Почему в функции с двумя лямбдами при использовании с .call оценивается только последняя лямбда? (рубиновые хлопья)

В следующем коде я читал о замыканиях, но задавался вопросом, что произойдет, если в функции будет более одного объекта proc. Поэтому, когда функция была вызвана, была вызвана только последняя лямбда. Я проверил это ниже. (интерактивно: http://labs.codecademy.com/BAZX#:workspace)

def n_times(thing)
  lambda {|n| puts "first called"; thing * n}  
  lambda {|n| puts "second called"; thing - n}
end

test = n_times(2)
puts test.call(3)

Почему первая лямбда пропущена?

puts n_times(3).call(2) => second called 1

Моресо, почему следующее недействительно? Редактировать: удалено, глупая ошибка. Спасибо ниже :)


person Senjai    schedule 12.05.2013    source источник
comment
Трудно отвечать на такие вопросы, не понимая, почему вы считаете, что должна быть вызвана первая лямбда, или почему вы считаете, что второй пример должен быть допустимым. Например, что вы ожидали от второго примера? Что, по-вашему, это означало, когда вы обвязывали его трубами?   -  person Joshua Cheek    schedule 12.05.2013
comment
Причина, по которой я проверил это, заключается в том, что .call на самом деле не принимает параметры, кроме передачи аргументов в блок. Но я не знаю, что lambda .call выбирает для выполнения. Я хотел проверить, выполнил ли он оба блока, поэтому я использовал инструкции put, чтобы увидеть, был ли хотя бы выполнен код первого, но это не так. Я не понимаю, почему.   -  person Senjai    schedule 12.05.2013


Ответы (1)


Лямбда — это замыкание, то есть код внутри нее не запускается до тех пор, пока не будет вызвана лямбда. Вы создаете первую лямбду, но ни один код в блоке не выполняется, пока вы не выполните lambda.call.

Возвращается последняя лямбда, так она и называется. Вот небольшой график выполнения:

test = n_times(2)
puts test.call(3)
  1. n_times вызвано (2 передано)
  2. лямбда 1 создана в объеме n_times
  3. лямбда 2 создана "
  4. лямбда 2 неявно возвращается (последнее значение), сохраняется в test
  5. test.call(5) - вызывается 2-я лямбда с переданным 5
  6. печатается "второй вызов" и возвращается -1

Больше не актуально:

lambda {|t| puts |t|}

должно быть

lambda {|t| puts t}
person AJcodez    schedule 12.05.2013
comment
Я так подумал, вот почему я вставил оператор puts в первую лямбду, даже если он не возвращался, он все равно должен был вывести на консоль нет? - person Senjai; 12.05.2013