Tutaj jest dużo zamieszania, ponieważ istnieją terminy z wieloma definicjami i wieloma różnymi rzeczami, które łączą się ze sobą po prostu dlatego, że zwykle występują razem.
Po pierwsze, mamy "blok". To tylko leksykalny fragment kodu, który tworzy jednostkę - na przykład ciało pętli. Jeśli język rzeczywiście ma zasięg blokowy, wówczas można zdefiniować zmienne, które istnieją tylko w tym fragmencie kodu.
Po drugie, mamy kod wywoływalny jako typ wartości. W językach funkcjonalnych są to wartości funkcyjne - czasami nazywane "funkcjami", "funkcjami anonimowymi" (ponieważ funkcja znajduje się w wartości, a nie jej nazwa jest przypisana, nie trzeba nazwy, aby je wywoływać), lub " lambdas "(od operatora użytego do stworzenia ich w Kościele Lambda Rachunek). Można je nazywać "zamknięciami", ale nie są one automatycznie prawdziwymi zamknięciami; aby się zakwalifikować, muszą hermetyzować ("zamknąć") zakres leksykalny otaczający ich tworzenie - to znaczy zmienne zdefiniowane poza zakresem samej funkcji, ale w zakresie jej definicji są nadal dostępne za każdym razem, gdy funkcja jest wywoływana, nawet jeśli punkt wywołania jest po tym, jak zmienna odniesienia w przeciwnym razie wykroczyłaby poza zakres i została poddana recyklingowi.
Można jednak wywoływać wartości kodu, które nie są pełnymi funkcjami. Smalltalk nazywa te "zamknięcia bloków", a Ruby nazywa je "procami". Ale większość Rubyistów nazywa je po prostu "blokami", ponieważ są one poprawioną wersją tego, co zostało utworzone przez składnię {
... lubTo, co odróżnia je od lambdów (lub "zamknięć funkcji"), to to, że nie wprowadzają nowego poziomu podprogramu. Jeśli kod w treści zamknięcia bloku wywołuje return
, zwraca on z zewnętrznej funkcji/metody, w której istnieje zamknięcie bloku, a nie tylko sam blok.
Takie zachowanie ma kluczowe znaczenie dla zachowania tego, co R.D. Tennent nazwał "zasadą korespondencji", która mówi, że powinieneś być w stanie zamienić dowolny kod na wbudowaną funkcję zawierającą ten kod w ciele i natychmiast zadzwonić. Na przykład, w JavaScripcie, można zastąpić to:
x = 2;
z tym:
(function(){x = 2;})();
mój przykład nie jest bardzo ciekawe, ale zdolność do tego rodzaju transformacji, nie wpływając na zachowanie tego Program odgrywa kluczową rolę w refakturach funkcjonalnych. Problem polega na tym, że zaraz po tym, jak masz wbudowane oświadczenia return
, zasada już nie istnieje.
To dlatego Ruby ma zarówno procsy, jak i lambdy - odwieczne źródło zamieszania dla początkujących. Zarówno procsy, jak i lambdy są obiektami klasy Proc
, ale zachowują się inaczej, jak wskazano powyżej: a return
po prostu wraca z ciała lambda, ale powraca z metody otaczającej proc. (Również, gdy nie pasuję do rozróżnienia, które tutaj rysuję, lambdas sprawdza się i narzeka, jeśli zostanie wywołany z niewłaściwą liczbą argumentów.) Możesz powiedzieć, jaki masz typ, dzwoniąc pod numer .lambda?
.
Obecnie Javascript ma tylko funkcje zamknięcia, chociaż na stole jest propozycja wprowadzenia bloków zamkniętych dla języka.
Nie jestem pewien, czy mają precyzyjne definicje, na przykład zamknięcia dodane przez Apple do gcc nazywane są "blokami" – cobbal
Jeśli mówisz o [] - dostali się do Celu C z Smalltalk, gdzie są wkompilowane w instancję myląco nazwaną "BlockClosure". – daf
Nie mówi o Objective-C, mówi o rozszerzeniach Apple'a na C. W OSX 10.6 Snow Leopard, Appel wprowadził nową bibliotekę współbieżności zwaną Grand Central Dispatch. Jest to biblioteka oparta na zadaniach, podobna do biblioteki Task Parallel Library firmy Microsoft. Podstawową ideą GCD jest przekazanie bloku kodu do biblioteki, a biblioteka decyduje, kiedy i na jakim rdzeniu ma zostać wykonany. Zwykle robiłbyś to za pomocą wskaźników funkcji, ale Apple uznał to za zbyt brzydkie i rozszerzyło C o zasadniczo wyrażenia lambda, które nazywają blokami. –