代码之家  ›  专栏  ›  技术社区  ›  Eric Duminil

从另一个lambda调用lambda。为什么顺序很重要?

  •  4
  • Eric Duminil  · 技术社区  · 6 年前

    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 second 通过方法或常量lambda修复 命名错误 question 但在我的例子中,两个lambda都是在 main .

    你能解释一下吗?

    2 回复  |  直到 6 年前
        1
  •  4
  •   Marek Küthe    6 年前
    first  = -> { defined? second }
    second = -> { 'Ok' }
    p first.call
    

    结果nil=>变量“second”未在lambda“first”中定义。

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

    结果主=>这意味着它使用main的当前绑定,因此定义了变量“second” 只有 binding .

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

    结果“Ok”。这就是为什么当我请求绑定的变量“second”的内容时,代码也会打印“Ok”。

    变量“second”未在lambda“first”中定义。变量“second”仅在 . 因此,“local\u variables”的输出也返回“second”,因为信息是从绑定中检索的。

        2
  •  4
  •   3limin4t0r    6 年前

    在你失败的例子中

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

    second first lambda变量不作为 Binding 对于 第一 .

    然而,简单地定义 第二 在创建 第一

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

    这个 Proc::new 文件说明如下:

    Proc 对象,绑定到当前上下文。 过程::新建 可以 只能在带有附加块的方法中调用而没有块, 在这种情况下,该块将转换为 过程 对象。

    结合 文档。请记住,绑定在创建时绑定到lambda/proc(而不是在调用时):

    Binding 在某个位置封装执行上下文 并保留此上下文以备将来使用。 self ,可能还有迭代器块 Kernel#binding ,并提供给 Kernel#set_trace_func

    我希望这能把事情弄清楚一点。