Có rất nhiều sự nhầm lẫn xung quanh ở đây vì có các cụm từ có nhiều định nghĩa và nhiều thứ khác nhau bị bẻ khóa đơn giản vì chúng thường được tìm thấy cùng nhau.
Trước tiên, chúng tôi có "chặn". Đó chỉ là một đoạn mã từ vựng mà làm cho một đơn vị - cơ thể của một vòng lặp, ví dụ. Nếu ngôn ngữ thực sự có phạm vi chặn, thì các biến có thể được xác định chỉ tồn tại trong đoạn mã đó.
Thứ hai, chúng tôi có mã có thể gọi là loại giá trị. Trong các ngôn ngữ chức năng, đây là các giá trị hàm - đôi khi được gọi là "funs", "functions anonymous" (vì hàm được tìm thấy trong giá trị chứ không phải tên được gán cho nó; bạn không cần tên để gọi chúng) hoặc " lambdas "(từ nhà điều hành được sử dụng để tạo ra chúng trong Lambda Calculus của Giáo hội). Chúng có thể được gọi là "đóng cửa", nhưng chúng không tự động đóng cửa; để đủ điều kiện, chúng phải đóng gói ("đóng") phạm vi từ vựng xung quanh sự tạo của chúng - nghĩa là các biến được định nghĩa bên ngoài phạm vi của hàm đó nhưng trong phạm vi định nghĩa của nó vẫn có sẵn bất cứ khi nào hàm được gọi, thậm chí nếu điểm gọi là sau biến số được tham chiếu nếu không sẽ không còn phạm vi và đã được lưu trữ lại.
Mặc dù vậy, bạn có thể có các giá trị mã có thể gọi không phải là toàn bộ chức năng. Smalltalk gọi những "block closures", trong khi Ruby gọi chúng là "procs". Nhưng hầu hết người Ruby chỉ gọi họ là "chặn", bởi vì họ là phiên bản được chỉnh sửa của những gì được tạo bởi cú pháp {
... }
hoặc do
... end
. Điều gì làm cho chúng khác biệt với lambdas (hoặc "đóng cửa chức năng") là chúng không giới thiệu một cấp độ mới của chương trình con. Nếu mã trong phần đóng của một khối gọi là return
, nó trả về từ hàm/phương thức bên ngoài, việc đóng khối tồn tại bên trong, không chỉ chính khối đó.
Hành vi đó rất quan trọng để bảo tồn những gì mà Tennent gắn nhãn là "nguyên tắc tương ứng", tuyên bố rằng bạn có thể thay thế bất kỳ mã nào bằng hàm nội tuyến có chứa mã đó trong cơ thể và được gọi ngay lập tức. Ví dụ, trong Javascript, bạn có thể thay thế này:
x = 2;
với điều này:
(function(){x = 2;})();
Ví dụ của tôi không phải là rất thú vị, nhưng khả năng làm điều này loại chuyển đổi mà không ảnh hưởng đến hành vi của các chương trình đóng một vai trò quan trọng trong chức năng tái cấu trúc. Vấn đề là, ngay sau khi bạn đã nhúng câu lệnh return
, nguyên tắc không còn giữ.
Đây là lý do tại sao Ruby có cả procs và lambdas - một nguồn gây nhầm lẫn lâu năm cho người mới. Cả procs và lambdas đều là đối tượng của lớp Proc
, nhưng chúng hoạt động khác nhau, như được chỉ ra ở trên: một return
chỉ trả về từ phần thân của lambda, nhưng nó trả về từ phương thức xung quanh một proc. (Ngoài ra, trong khi không liên quan đến sự phân biệt tôi đang vẽ ở đây, lambdas kiểm tra tinh thần và phàn nàn nếu được gọi với số lượng sai đối số. Bạn có thể cho biết loại bạn có bằng cách gọi .lambda?
trên đối tượng.)
Javascript hiện tại chỉ có chức năng đóng cửa, mặc dù có một đề xuất trên bàn để giới thiệu các đóng cửa chặn cho ngôn ngữ.
Tôi không chắc là chúng có định nghĩa chính xác, ví dụ bao đóng của Apple được thêm vào gcc được gọi là "khối" – cobbal
Nếu bạn đang nói về [] - chúng đi vào Objective-C từ Smalltalk, nơi chúng được biên dịch thành một phiên bản có tên là 'BlockClosure'. – daf
Anh ấy không nói về Objective-C, anh ấy đang nói về các phần mở rộng của Apple đối với C. Trong OSX 10.6 Snow Leopard, Appel đã giới thiệu một thư viện đồng thời mới có tên là Grand Central Dispatch. Đó là một thư viện dựa trên nhiệm vụ tương tự như Thư viện song song nhiệm vụ của Microsoft. Ý tưởng cơ bản của GCD là bạn đưa một khối mã vào thư viện và thư viện sau đó quyết định khi nào và trên lõi nào để thực thi. Thông thường, bạn sẽ làm điều đó với các con trỏ hàm, nhưng Apple cho rằng quá xấu và chúng mở rộng C với các biểu thức lambda cơ bản, mà chúng gọi là các khối. –