Я пробовал читать о procs и лямбда, но я должен продолжать перечитывать определение.
Может кто-нибудь объяснить это мне таким образом, что это понятно и запоминаемо?
Я пробовал читать о procs и лямбда, но я должен продолжать перечитывать определение.
Может кто-нибудь объяснить это мне таким образом, что это понятно и запоминаемо?
Несколько ресурсов:
Также есть целая глава в Read Ruby 1.9 book
Отредактировано: после прочтения других хороших ответов здесь я предлагаю следующую дистилляцию, которая может спасти вас от повторного чтения:
(l)ambda -
(L)ocal return
(L)ooks at the arguments
(p)roc -
(P)ops you out of the method when it returns.
(P)ermits different arguments
Эйнштейн сказал: "... делайте все как можно проще, но не проще". Если бы у него было переполнение стека, он бы указал вам здесь:
В чем отличия между proc и лямбдой?
или здесь:
В чем разница между proc и лямбдой в Ruby?
hth -
Перри
То, как я думаю о них, состоит в том, что лямбда ведет себя скорее как функция, а Proc или block ведет себя скорее как структура управления.
Я думаю, что лучший способ понять, почему эти два существуют и какова разница, - это понять, как каждый используется. Возьмите этот код, например:
def find (elem)
@array.each { |item| return item if item == elem }
return false
end
Для всех, знакомых с Ruby, очевидно, что здесь происходит, но спросите себя, с чего вы возвращаетесь, когда вызывается return
. То, что вы ожидаете, и что происходит, заключается в том, что сам метод возвращается. Несмотря на то, что мы находимся внутри блока кода, это возвращает метод, а не только блок. Так ведет себя Proc, и это позволяет нам использовать цикл .each
и возвращать его, как и в эквивалентном цикле for
.
С другой стороны, лямбда - это как функции. Если вы вернетесь из лямбда, он выходит только из лямбды.
def find (elem)
l = lambda { |item| return item if item == elem }
@array.each(&l)
return false
end
Здесь метод всегда будет возвращать false из-за того, что окончательная строка не обходится вызовом return
в лямбда. Lambdas являются функциями и возвращаются от себя, тогда как Procs возвращаются из прилагаемого метода.
Итак, Procs и блоки и возвращаются из метода, использующего их (например, цикл будет), в то время как lambdas (например, методы) возвращаются от себя.
Proc
ведут себя как блоки. Lambdas ведут себя как методы.
т.е. return
внутри a Proc
ведет себя как return
внутри блока, а привязка аргументов для Proc
работает так же, как привязка аргументов для блоков. return
внутри lambda работает как return
внутри метода и привязка аргумента для lambdas работает так же, как привязка аргумента для методов.
Обратите внимание, что lambdas Proc
s, то есть они являются экземплярами класса Proc
. Разница между ними заключается в том, является ли Proc#lambda?
true
или false
.
Обратите также внимание на то, что в старых версиях Ruby Kernel#proc
создан лямбда, а не Proc
, что было совершенно запутанно. Это было исправлено в современных версиях Ruby, где Kernel#proc
теперь эквивалентно Proc.new
и, таким образом, создает Proc
.
Kernel#lambda
и синтаксис лямбда-литерала (->(x, y) { x + y }
) всегда создают лямбда, Proc.new
всегда создает Proc
и Kernel#proc
в зависимости от версии Ruby.
В Proc:
В лямбда:
Как и Jorg W Mittag, Procs ведут себя как блоки, а lambdas ведут себя как методы.
То, как я запоминаю, это "proc", рифмуется с "блоком".