Вызов лямбды из другой лямбды.Почему заказ имеет значение? - PullRequest
0 голосов
/ 30 сентября 2018

Можно вызвать лямбду из другой лямбды:

first   = -> { 'Ok' }
second  = -> { first.call }
puts second.call
# => 'Ok'

, но при обратном порядке:

first  = -> { second.call }
second = -> { 'Ok' }
puts first.call

код завершается ошибкой с NameError:

lambda_order.rb:1:in `block in <main>': undefined local variable or method `second' for main:Object (NameError)
Did you mean?  send
    from lambda_order.rb:3:in `<main>'

, хотя :second кажется локальной переменной внутри области действия first:

first  = -> { local_variables }
second = -> { 'Ok' }
p first.call
# => [:first, :second]

Я использую лямбды только для целей игры в гольф , поэтому я 'Я не уверен, что происходит с областью.Замена second методом или постоянной лямбда-кодом исправляет NameError.Кажется, это связано с вопросом , но в моем случае обе лямбды определены в main.

Не могли бы вы объяснить?

Ответы [ 2 ]

0 голосов
/ 01 октября 2018
first  = -> { defined? second }
second = -> { 'Ok' }
p first.call

results nil => Переменная «second» не определена в лямбда-выражении «first».

first  = -> { binding.receiver }
second = -> { 'Ok' }
p first.call

results main => Это означает, что она использует текущую привязку main и, таким образом,переменная "second" определена только в привязке .

first  = -> { binding.local_variable_get(:second).call }
second = -> { 'Ok' }
p first.call

в результатах "Ok".Вот почему код также выводит «Ok», когда я запрашиваю содержимое переменной «second» привязки.

Резюме: Переменная «second» не определена в лямбда-выражении"первый".Переменная «second» определяется только в привязке .Поэтому вывод «local_variables» также возвращает «second», потому что информация извлекается из привязки.

Я тоже кое-что узнал сам.Я надеюсь, что смогу вам помочь!

0 голосов
/ 01 октября 2018

Когда создается лямбда / proc, его содержимое не выполняется, однако при создании сама лямбда / proc привязывается к набору локальных переменных, находящихся в данный момент в области видимости.

В вашем ошибочном примере

first  = -> { second.call }
second = -> { 'Ok' }
puts first.call

Поскольку second не определено до создания first лямбды, переменная не передается как часть Binding для first.

Однако простое определение second до создания first решает эту проблему.

second = nil
first  = -> { second.call }
second = -> { 'Ok' }
puts first.call
# OK
#=> nil

В документации Proc::new говоритсяследующее:

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

Объедините вышеприведенное с Переплет Документация.Помня, что привязка привязана к lambda / proc при создании (не при вызове):

Объекты класса Binding инкапсулируют контекст выполнения в каком-то конкретном месте в коде и сохраняют этот контекстдля будущего использования.Переменные, методы, значение self и, возможно, блок итератора, к которому можно получить доступ в этом контексте, сохраняются.Связующие объекты могут быть созданы с помощью Kernel#binding и доступны для обратного вызова Kernel#set_trace_func.

Надеюсь, это немного прояснит ситуацию.

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