ruby-on-rails - 为什么 class_eval 以不同的方式评估字符串和块?
问题描述
我是 ruby 新手,今天我发现class_eval
for string 和 block 有一些不同的行为。例如
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
中,然后在类 A 上调用这个 class_eval。因此,当计算表达式时Module.nesting
- 它需要生成它的嵌套级别 - 发现它自己在 aA
中,而后者又在 a 中被计算C
。
在第二种情况下,您传递一个类似于 proc 对象的块。效果可媲美
class C
p = Proc.new { print Module.nesting }
do_something(p)
end
Proc 代表一个闭包,即上下文是创建 Proc 的上下文。很明显,这里的嵌套只是 C,如果你在里面计算 p,这不会改变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 指的是x
内部的局部值g
,尽管f
有一个同名的局部变量。因此,此处打印g 。同样,在您的示例中再现了块定义点的嵌套。
推荐阅读
- javascript - 使用 JavaScript 进行 JSON 转换
- python - 如何在 CPython 中将错误消息作为字符串获取
- mongodb - 将 MongoDB 从 2.6 升级到 4.2.6
- corda - 如何在 TokenSDK 中使用 addIssueTokens Utility 方法
- ruby-on-rails - Money-rails 显示金额为数千
- c++ - 当我在 Ubuntu 终端上发送 SIGTERM (Ctrl + C) 时,为什么我的 C++ 代码没有终止?
- javascript - 在 keyup 函数中使用通配符
- nginx - 获取 Web 服务的 kerberos/Windows AD 登录工作的问题
- google-apps-script - 将特定数据从工作表复制到工作表
- javascript - 如何在 Node.js 中使用 Jimp 调整图像大小以进行上传而不刷新