Tại sao Python và Ruby không phân biệt giữa khai báo và gán giá trị cho các biến?


8

Hai trong số các ngôn ngữ kịch bản được gõ động phổ biến nhất, Python và Ruby, không tạo ra sự khác biệt trong cú pháp giữa khai báo một biến và gán giá trị cho nó.

Đó là trong cả hai ngôn ngữ, khai báo một biến nvà gán giá trị cho nó sẽ giống như vậy:

n = 10

Và việc gán một giá trị mới cho biến sau này sẽ trông giống nhau.

Điều này tạo ra hai vấn đề lớn:

  1. Một lỗi đánh máy trong tên của một biến khi thay đổi giá trị của nó sẽ tạo ra một biến mới và gây ra lỗi.

  2. Nó làm cho ý định của mã ít rõ ràng hơn. Khó biết nơi một biến được khai báo và sử dụng đầu tiên, có thể làm cho mã khó hiểu hơn.

Điều tôi không hiểu là tại sao những ngôn ngữ này không có vartừ khóa để sử dụng khi khai báo, để phân biệt giữa khai báo và chuyển nhượng. Điều này không làm cho ngôn ngữ trở nên kém năng động hơn và tôi không thấy nhược điểm nào.

Lợi thế của việc không phải xác định rõ ràng một biến là gì?



@Akash Điều đó dường như không liên quan đến câu hỏi, nó vẫn có giá trị như nhau nếu chạy qua s/variable/name/g.

Câu trả lời:


4

Là người dùng chứ không phải (người thiết kế) của Python, có ba lý do khiến tôi hài lòng với quyết định này:

Chủ yếu, nó đọc tốt hơn. Tất nhiên tôi phải có ý thức quyết định giới thiệu một biến mới khi viết , nhưng mã được đọc thường xuyên hơn nhiều so với nó được viết. Rất nhiều mã đơn giản theo nghĩa là điều khiển luồng và lồng không ảnh hưởng đến ý nghĩa và sự tồn tại của các biến. Khi tôi đọc

it = Snark()
message = "A letter, not signed"
if random.random() > 0.5:
    hunt(it)
    message += " (by the Knave)"
return [it, message]

sau đó tôi thường không thực sự quan tâm (nếu có) đề cập đến cái tên đầu tiên giới thiệu nó, tôi chỉ quan tâm rằng nó ở đó và những gì xảy ra với nó.

Lưu ý rằng một phần đáng kể của mã giả sử dụng cùng một quy ước (không khai báo, giới thiệu ngầm thông qua gán) và Python thường được mô tả là mã giả thực thi, chỉ nửa đùa nửa thật. Bốn ký tự bổ sung cho mỗi biến cục bộ, đối với đôi mắt hư hỏng của tôi, cảm thấy như sự lộn xộn đáng kể trong bối cảnh của Python, đặc biệt là khi nó không cảm thấy như nó thêm bất kỳ giá trị nào (xem bên dưới); điều này sẽ được giảm bớt bởi một :=nhà điều hành như trong Go.

Thứ hai, tôi chưa gặp phải một lỗi đánh máy (do tính năng cụ thể này) mà cũng không hiển thị theo cách rõ ràng khác. Có thể tôi sẽ thay đổi suy nghĩ của mình trong một vài năm nữa khi tôi gặp phải một số lỗi thuộc loại này, nhưng cho đến nay, đó là cách, trong danh sách những điều gây ra lỗi. Có rất nhiều câu hỏi về UnboundLocalErrorvà thật khó để giải thích cho người mới bắt đầu, nhưng tần suất và mức độ phổ biến của những câu hỏi đó, so với các vấn đề khác (tham số mặc định có thể thay đổi, ngữ nghĩa tham chiếu, biến so với biến đối tượng) cho thấy đây là một vấn đề hiếm gặp.

Cuối cùng, ý định ... xin lỗi nhưng tôi thực sự không thể hiểu điều này. Khi đọc và viết Python, nó luôn hoàn toàn rõ ràng: Những gì bạn gán cho mục đích là cục bộ, trừ khi được tuyên bố rõ ràng và rõ ràng khác. Không có câu hỏi về nó. Hơn nữa, vì (ít nhất là trong Python) một biến là cục bộ cho toàn bộ hàm hoặc hoàn toàn không , nên bạn không thể có mã phức tạp sử dụng biến cục bộ trong một nhánh và biến toàn cục trong một nhánh khác. Bạn thấy một cái tên được gán cho? Bạn ngay lập tức biết nó luôn luôn là địa phương ngay từ đầu. Chà, trừ khi mã bị phá vỡ theo một cách rất đặc biệt (và sẽ ném sự sợ hãi UnboundLocalErrortrong thời gian chạy, khi vào những trường hợp đó).


Dưới đây là một ví dụ về lỗi trong PHP do thiếu khai báo, từ một trường hợp thực tế: $a = [1, 2, 3]; foreach ($a as $k => &$v) $v++; foreach ($a as $k => $v) echo "$k => $v\n";
Alexander Gelbukh

@AlexanderGelbukh Tôi không biết rõ về PHP để xác định nguyên nhân, bạn có phiền giải thích không?

Xin vui lòng xem đây là câu trả lời của tôi . Như bạn thấy, thật bất ngờ đối với khá nhiều người, bao gồm cả tôi, vì vậy tôi đã phải thử nghiệm rất nhiều. Bây giờ hãy tưởng tượng có bao nhiêu chương trình không chính xác ngoài kia do một lỗi như vậy.
Alexander Gelbukh

1
@AlexanderGelbukh Lưu ý rằng lỗi bạn mô tả là do sự tương tác của một số tính năng PHP (chủ yếu là tài liệu tham khảo) và IIUC không thể xảy ra theo cách đó trong các ngôn ngữ khác thiếu khai báo. Đối với việc viết / gỡ lỗi: Lưu ý rằng hầu hết các chiến lược gỡ lỗi (từ công nghệ thấp "nhìn chằm chằm vào nó cho đến khi rõ ràng" đến các trình gỡ lỗi du hành thời gian ưa thích) bao gồm một đoạn đáng kể về việc đọc mã được gỡ lỗi.

1
Hoàn toàn đồng ý: khả năng đọc là vô cùng quan trọng. Bạn đồng ý rằng việc ngăn chặn lỗi là quan trọng. Bạn không đồng ý với tuyên bố đó giúp ngăn ngừa lỗi. Tôi không đồng ý với tuyên bố đó làm tổn thương khả năng đọc. Có lẽ chúng ta có thể đồng ý không đồng ý :-)
Alexander Gelbukh

-3

Không phải việc xác định một biến cũng giống như gán cho nó - đó là các biến không được xác định. Nó được gọi là Nhập động .

Bạn không thể có một ngôn ngữ kiểu động cho phép bạn xác định một biến, bởi vì đó là những gì gõ động .

Quyết định làm điều này thay đổi hoàn toàn bản chất của trình phân tích cú pháp và dẫn đến một loại ngôn ngữ hoàn toàn khác. Sự khác biệt chính đối với người dùng cuối thường là, khi xác định hàm, các tham số của bạn hóa ra là bất kỳ loại nào ("gõ vịt"), cả hai đều là một phước lành, vì nó làm cho mã của bạn đơn giản hơn nhiều và một lời nguyền, trong đó nó cho phép vô số cách mới mà mã của bạn có thể thất bại.

Tôi không phải là chuyên gia biên dịch nhưng tôi nghĩ cũng đúng là Dynamic Typing có ý nghĩa chính đối với hương vị của OOP mà bạn có trong ngôn ngữ.


3
Bạn đang có lỗi. JavaScript trong chế độ nghiêm ngặt yêu cầu bạn sử dụng các biến trước khi sử dụng chúng. Đó là, tuy nhiên, tự động gõ. Một không có gì để làm với các khác. Gõ động có nghĩa là biến của bạn có thể giữ một giá trị thuộc bất kỳ loại nào. Nó không liên quan gì đến việc bạn có phải xác định nó hay không. Tương tự, một ngôn ngữ gõ tĩnh với suy luận kiểu sẽ cho phép sử dụng các biến mà không cần xác định chúng. Hai điều này là trực giao.
back2dos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.