【问题标题】:Block does not recognise variable at first time块第一次无法识别变量
【发布时间】:2013-04-24 20:21:24
【问题描述】:
y = lambda { z }
z = 9

y.call
=> NameError: undefined local variable or method `z' for main:Object

y = lambda { z }
y.call
=> 9

我认为拥有一个块的想法是推迟块内代码的执行。你能解释一下吗?

【问题讨论】:

    标签: ruby lambda block


    【解决方案1】:

    lambda 创建所谓的lexical closure,这意味着它捕获对封闭环境的引用,并且可以使用在创建闭包时处于范围内的变量。

    y = lambda { z } # Woops! There's no variable named `z`!
    

    在创建闭包之后创建一个名为z的变量并不重要;闭包的想法是捕捉特定时刻的环境。

    理论上,您可能希望在创建该 lambda 时出现错误,因为可以对其进行分析并确定将取消引用尚未定义的变量。然而,Ruby 不是这样工作的。只有在评估代码时,您才会因为尝试访问未定义的变量而出错。

    当您在几行之后创建第二个闭包时,该闭包确实捕获了z 存在的环境:

    y = lambda { z } # This closure is broken and can't be fixed
    z = 9
    y = lambda { z } # This is a new closure, and `z` is accessible within it
    

    我认为有一个块的想法是推迟块内代码的执行。

    有点,但它与简单地从 lambda 复制和粘贴代码并在调用它时对其进行评估不同。 evaling 字符串会这样做:

    y = "z"
    z = 9
    eval(y)
    # => 9
    

    同样,闭包的想法是它捕获代码环境。

    【讨论】:

      【解决方案2】:

      在第一行中,当创建块时,根本没有z 可以被块“捕获”。当你第二次写y = lambda { z }时,有一个z

      该块拍摄周围变量的一种快照。在这种情况下,第一次不存在名为 z 的变量。

      【讨论】:

        【解决方案3】:

        当你定义一个 lambda 时,它会获得一个 闭包,其中包含对定义时范围内所有变量的引用。 lambda 始终可以访问它“关闭”的每个变量的当前值,但新定义的变量不会追溯添加到闭包中。所以当你这样做时:

        x = 5
        y = lambda { x + z }
        z = 7
        

        lambda y 可以访问 x 的值,但不能访问 z,因为在您定义 lambda 时只有 x 存在。但如果你这样做:

        x = 5
        z = 0
        y = lambda { x + z }
        
        z = 7
        y.call
        # => 12
        

        那么一切都会好起来的。

        【讨论】:

          【解决方案4】:

          undefined local variable or method 'z' for main:Object 在未创建局部变量时出现。仅由assignment 操作创建的局部变量。

          您的第一个y = lambda { z } 无法绑定z,因为z 是在此lambda 定义之后定义的。

          以下工作:

          y = lambda { z }
          y.call
          => 9
          

          正如您在第二个 lambda 定义之前定义的 z = 9

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-02-27
            • 1970-01-01
            • 1970-01-01
            • 2014-08-09
            • 2018-08-22
            • 2021-02-27
            • 2013-05-15
            • 2015-10-27
            相关资源
            最近更新 更多