Undefined local variable or method after eval, if not previously declared
In 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
So the question is, why is variable 'b' going to be an 'undefined local variable or method', but variable 'a' is 4?
source to share
When you call a eval
lambda, you create a new scope for the code you are executing.
It will be like creating and executing a new lambda. If you declare a
before and then use a named variable a
in your lambda, you must use it. But if you don't declare b
before the lambda eval
will create its own variable and delete it at the end.
source to share
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__}"
follow the code above, you will see that the outer binding and the inner binding use different IDs. but share the same a. when we run eval, ruby will copy the external binding, so it will use the same a; but b is defined in the internal binding, when eval is executed the internal binding is lost and hence b. In fact, the block area is the same as this one.
source to share