Блок в Ruby по сравнению с Smalltalk

Что блокирует Ruby? Он похож на Smalltalk, но вы не можете отправлять ему сообщения.

Например, в smalltalk:

[:x | x + 3] value: 3

возвращает 6. Но в ruby:

{|x| x + 3}.call 3

вызовет SyntaxError.

Ну, вы можете передавать сообщения в лямбда в ruby, хотя:

irb(main):025:0> ->(x){x+3}.call 3
=> 6

Итак, в Ruby блок не является блоком, но лямбда - это блок? Это правда? Я имею в виду, существуют ли какие-либо различия между рубинским лямбда и блоком smalltalk? Если это так, то каков блок ruby?

Обновление:

Из комментария и ответа ниже, вместе с некоторыми поисковыми системами, я думаю, я имеют больше понимания блока Ruby. В Ruby обычно часть кода оценивает значение, и каждое значение является объектом. Но блок не оценивает значение. Так что это не объект. Вместо этого он может действовать как часть объекта. Например, в {| x | x + 3} может действовать как часть объекта proc {| x | x + 3}.

Но это меня смутило. В smalltalk почти каждое выражение можно разделить на объекты (привязка к переменным - это исключения). Кажется, в Ruby есть больше исключений.

Ответ 1

Сначала и самое главное, что блок Ruby не является: объектом. Это синтаксическая конструкция, а также, очевидно, имеет эквивалентную реализацию, но она не является объектом и, следовательно, не может получать сообщения. Что делает ваш пример

{|x| x + 3}.call 3

безграмотно. Lambdas, procs - это объекты, которые обертывают блок, и имеют метод call, который выполняет блок.

Таким образом, блок - это просто фрагмент кода, который может быть передан методу, вне списка аргументов - не более, не меньше. Если вы передадите его в конструктор Proc.new, например, он обернет его и предоставит вам объект, с которым вы можете обращаться:

Proc.new {|x| x + 3}.call 3

Ответ 2

Точность:

Я бы даже сказал, что в smalltalk даже привязка составлена ​​с помощью объекта. Подумайте о MethodContext. То, что вы на самом деле делаете, - это сохранить объект в MethodContext. Так

a := Object new

Можно переписать в:

thisContext at: 1 put: Object new.

Но, очевидно, вы не напишете это так, так как вам нужно знать, что это переменная temps.

Ответ 3

Блок в Smalltalk является анонимным объектом. Синтаксически он разделяется парой [... ].

При оценке он вернет последнее выражение, оцениваемое внутри себя, и в его протоколе есть много методов.

Вот комментарии класса для блоков от Smalltalk (в данном случае Dolphin Smalltalk 6.03 Community Edition)

"Блоки инкапсулируют последовательность операторов, которые будут выполняться позднее. Блоки могут захватывать (или" закрывать ") состояние времени выполнения, такое как значения временных переменных, из охватывающей лексической области в точке, где они находятся созданный. Когда оценивается, блок выполняется так, как если бы в лексической области, в которой он был определен, за исключением того, что блоки могут иметь аргументы, которые связаны во время оценки. Блоки могут передаваться как аргументы с сообщениями другим объектам и оцениваться этими объектами когда это уместно, и, таким образом, образуют очень мощный и универсальный механизм" подключаемости ", который является основной функцией, которая обеспечивает большую часть мощности Smalltalk".

В отличие от этого блок в Ruby представляет собой просто строку параметров. Он синтаксически разделен парой {... }, но у нее нет собственных методов.