未声明的局部变量或方法之后的未定义的局部变量或方法

时间:2015-05-07 14:00:39

标签: ruby eval

在Ruby中

2.1.2 :068 >   a=1
 => 1
2.1.2 :069 > eval("a=4")
 => 4
2.1.2 :070 > a
 => 4
2.1.2 :071 > eval("b=4")
 => 4
2.1.2 :072 > b
NameError: undefined local variable or method `b' for main:Object

所以,问题是为什么变量'b'将是'未定义的局部变量或方法',但变量'a'等于4?

2 个答案:

答案 0 :(得分:1)

当您调用eval lambda时,您将为您执行的代码创建一个新范围。

这就像创建并执行一个新的lambda。如果您之前声明a然后在lambda中使用名为a的变量,则应使用相同的变量。但是如果你没有在lambda之前声明beval将创建自己的变量,并在最后删除它。

答案 1 :(得分:1)

 puts "outside binding #{binding.__id__}"
 a = 1
 puts "outside a #{a.__id__}"
 eval 'b="b"; puts "inside binding #{binding.__id__}"; puts "inside a #{binding.local_variable_get(:a).__id__}"; a="c"; puts "inside after a #{a.__id__}"'
 puts "outside after a #{a.__id__}"

运行上面的代码,你可以看到外部绑定和内部绑定使用不同的id。但是分享同样的。当我们运行eval时,ruby将复制外部绑定,因此它将使用相同的a;但是b是在内部绑定中定义的,当eval完成时,内部绑定会丢失,因此是b。实际上块范围与此相同。