Нужно запоминающееся объяснение прока и лямбды - PullRequest
13 голосов
/ 28 апреля 2011

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

Может кто-нибудь объяснить мне это так, чтобы оно было ясным и запоминающимся?

Ответы [ 6 ]

8 голосов
/ 28 апреля 2011

Отредактировано: после прочтения других хороших ответов здесь я предлагаю следующую дистилляцию, которая может спасти вас от перечитывания:

(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  

Эйнштейн сказал: «... упростите все каквозможно, но не проще ".Если бы у него было переполнение стека, он бы указал вам здесь:

В чем разница между процедурой и лямбда?

или здесь:

В чем разница между процедурой и лямбдой в Ruby?

hth -

Перри

4 голосов
/ 28 апреля 2011

Я думаю о них так: лямбда ведет себя больше как функция, а процесс или блок ведут себя больше как структура управления.

Я думаю, что лучший способ понять, почему они существуют и в чем разница, - это понять, как они используются. Возьмите этот код, например:

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 в лямбда-выражении. Лямбды являются функциями и возвращаются из себя, тогда как Procs возвращаются из включающего метода.

Итак, Procs и блоки возвращаются из метода, используя их (как в цикле), а лямбды (как методы) возвращаются из себя.

2 голосов
/ 28 апреля 2011

Proc с ведут себя как блоки.Лямбды ведут себя как методы.

Т.е. return внутри Proc ведет себя как return внутри блока, а привязка аргумента для Proc s работает так же, как привязка аргумента для блоков.return внутри лямбды работает как return внутри метода, а привязка аргумента для лямбды работает так же, как привязка аргумента для методов.

Обратите внимание, однако, что лямбда Procs, то есть они являются экземплярами класса Proc.Разница между ними заключается в том, является ли Proc#lambda? true или false.

Также обратите внимание, что в более старых версиях Ruby Kernel#proc создавал лямбду, а не a Proc, который был совершенно запутанным.Это было исправлено в современных версиях Ruby, где Kernel#proc теперь эквивалентно Proc.new и, таким образом, создает Proc.

Kernel#lambda, а синтаксис лямбда-выражения (->(x, y) { x + y }) всегда создаетлямбда, Proc.new всегда создает Proc, а Kernel#proc зависит от версии Ruby.

1 голос
/ 28 апреля 2011

В Proc:

  • Оператор return возвращается из вызывающего контекста - например, из метода или контекста, вызывающего Proc, а не только из Proc.block.
  • Не выдает исключение для неверного числа переданных аргументов

В лямбде:

  • Оператор возврата возвращает управлениевызывающий контекст - вне блока, но не вне метода.
  • Он выдает исключение, если задано неправильное количество аргументов, точно так же, как метод.
0 голосов
/ 29 апреля 2011

Как говорит Йорг Миттаг, Procs ведет себя как блоки, а лямбды ведут себя как методы.

Я запоминаю это как "proc", рифмуется с "block".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...