可以从另一个lambda调用lambda:
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]
我只为golfing purposes使用lambda,所以我不确定范围是怎么回事。用方法或常量lambda替换second
可修复NameError
。似乎与此question有关,但就我而言,两个lambda都在main
中定义。
你能解释一下吗?
答案 0 :(得分:4)
创建lambda / proc时,其内容不会执行,但是在创建时,lambda / proc本身会绑定到当前作用域中的一组局部变量。
在您失败的示例中
first = -> { second.call } second = -> { 'Ok' } puts first.call
由于在创建second
lambda之前未定义first
,因此变量不会作为first
的{{3}}的一部分传递。
但是,只需在创建second
之前定义first
就可以解决此问题。
second = nil
first = -> { second.call }
second = -> { 'Ok' }
puts first.call
# OK
#=> nil
Binding文档说:
创建一个绑定到当前上下文的新
Proc
对象。Proc::new
可能 仅在具有附加块的方法中不带块地调用, 在这种情况下,该块将转换为Proc
对象。
将以上内容与Proc::new
文档结合在一起。请记住,绑定是在创建时绑定到lambda / proc的(不是在调用时):
类
Binding
的对象在某些地方封装了执行上下文 代码中的特定位置,并保留此上下文以供将来使用。 变量,方法,self
的值,以及可能的迭代器块 在此上下文中可以访问的所有内容都将保留。绑定对象 可以使用Kernel#binding
创建,并可供Kernel#set_trace_func
的回调。
我希望这可以使事情变得简单
答案 1 :(得分:4)
first = -> { defined? second }
second = -> { 'Ok' }
p first.call
results nil =>在lambda“ first”中未定义变量“ second”。
first = -> { binding.receiver }
second = -> { 'Ok' }
p first.call
result main =>这意味着它使用main的当前绑定,因此在binding中仅仅定义了变量“ second”。
first = -> { binding.local_variable_get(:second).call }
second = -> { 'Ok' }
p first.call
结果为“确定”。这就是为什么当我要求绑定变量“ second”的内容时,代码还会显示“ Ok”的原因。
摘要:在lambda“ first”中未定义变量“ second”。变量“ second”仅在binding中定义。因此,“ local_variables”的输出也返回“ second”,因为该信息是从绑定中检索的。
我自己也学到了一些东西。希望我能为您服务!