Когда использовать лямбду, когда использовать Proc.new? - PullRequest
328 голосов
/ 03 августа 2008

В Ruby 1.8 есть небольшие различия между proc / lambda с одной стороны и Proc.new с другой.

  • Что это за различия?
  • Можете ли вы дать рекомендации, как решить, какой из них выбрать?
  • В Ruby 1.9, proc и lambda разные. В чем дело?

Ответы [ 14 ]

3 голосов
/ 28 апреля 2015

Я немного опоздал, но есть одна замечательная, но малоизвестная вещь о Proc.new, которая вообще не упоминается в комментариях. По документации :

Proc::new может быть вызван без блока только внутри метода с прикрепленным блоком, и в этом случае этот блок преобразуется в объект Proc.

Тем не менее, Proc.new позволяет связать методы получения:

def m1
  yield 'Finally!' if block_given?
end

def m2
  m1 &Proc.new
end

m2 { |e| puts e } 
#⇒ Finally!
3 голосов
/ 07 сентября 2008

Чтобы уточнить ответ аккордеонного парня:

Обратите внимание, что Proc.new создает процесс, передавая блок. Я считаю, что lambda {...} анализируется как своего рода литерал, а не как вызов метода, который передает блок. return извлечение из блока, присоединенного к вызову метода, будет возвращено из метода, а не из блока, и случай Proc.new является примером этого при воспроизведении.

(Это 1,8. Я не знаю, как это переводится в 1,9.)

1 голос
/ 15 ноября 2018

Стоит подчеркнуть, что return в процедуре возвращается из лексически заключенного метода, то есть метода, в котором был создан процесс , , а не метода, который вызвал процедуру. Это является следствием свойства замыкания процедур. Поэтому следующий код ничего не выводит:

def foo
  proc = Proc.new{return}
  foobar(proc)
  puts 'foo'
end

def foobar(proc)
  proc.call
  puts 'foobar'
end

foo

Хотя процедура выполняется в foobar, она была создана в foo, поэтому return выходит foo, а не только foobar. Как Чарльз Колдуэлл писал выше, у этого есть GOTO чувство к этому. На мой взгляд, return подходит для блока, который выполняется в его лексическом контексте, но гораздо менее интуитивно понятен при использовании в процедуре, выполняемой в другом контексте.

1 голос
/ 11 августа 2008

Разница в поведении с return является ИМХО наиболее важной разницей между 2. Я также предпочитаю лямбду, потому что она меньше печатает, чем Proc.new: -)

...