为什么 class_eval 以不同的方式评估字符串和块?
Why class_eval evaluates the string and block differently?
我是 ruby 的新手,今天我发现 class_eval
对于字符串和块有一些不同的行为。例如
class A
end
class C
A.class_eval("print Module.nesting") # [A, C]
A.class_eval{print Module.nesting} # [C]
end
如您所见,在字符串 Module.nesting
的情况下打印 [A,C],而在块的情况下它仅打印 C.
能告诉我这是什么原因吗?
在第一种情况下,您将一个字符串填充到 class_eval
中,然后在 class A 上调用此 class_eval。因此,当计算表达式时,Module.nesting
- 需要生成其嵌套级别 - 发现自己位于 A
内,而后者又在 C
.
内求值
在第二种情况下,你传递了一个类似于proc对象的块。效果堪比有一个
class C
p = Proc.new { print Module.nesting }
do_something(p)
end
Proc 表示一个 闭包,即上下文是创建 Proc 的上下文。很明显,这里的 nesting 只是 C,如果你在 do_something
.
中计算 p,这不会改变
这是一件好事。想象一下以下情况:
def f(p)
x = 'f'
p.call
end
def g
x = 'g'
p = Proc.new { puts x }
f(p)
end
因为 p 的绑定发生在方法 g 内部,块中引用的 x 引用 g
内部的局部值 x
,尽管 f
有一个局部变量一样的名字。因此,g 被打印在这里。以同样的方式,在你的例子中复制了块定义点的嵌套。
我是 ruby 的新手,今天我发现 class_eval
对于字符串和块有一些不同的行为。例如
class A
end
class C
A.class_eval("print Module.nesting") # [A, C]
A.class_eval{print Module.nesting} # [C]
end
如您所见,在字符串 Module.nesting
的情况下打印 [A,C],而在块的情况下它仅打印 C.
能告诉我这是什么原因吗?
在第一种情况下,您将一个字符串填充到 class_eval
中,然后在 class A 上调用此 class_eval。因此,当计算表达式时,Module.nesting
- 需要生成其嵌套级别 - 发现自己位于 A
内,而后者又在 C
.
在第二种情况下,你传递了一个类似于proc对象的块。效果堪比有一个
class C
p = Proc.new { print Module.nesting }
do_something(p)
end
Proc 表示一个 闭包,即上下文是创建 Proc 的上下文。很明显,这里的 nesting 只是 C,如果你在 do_something
.
这是一件好事。想象一下以下情况:
def f(p)
x = 'f'
p.call
end
def g
x = 'g'
p = Proc.new { puts x }
f(p)
end
因为 p 的绑定发生在方法 g 内部,块中引用的 x 引用 g
内部的局部值 x
,尽管 f
有一个局部变量一样的名字。因此,g 被打印在这里。以同样的方式,在你的例子中复制了块定义点的嵌套。