深入理解 ruby 中的 eval 与 binding

2017-09-05 19:19:09来源:CSDN作者:antony1776人点击

分享
eval(expr[, binding[, fname[, lineno=1]]])

eval 可以把字符串当做代码来执行,并返回结果;第二个参数如果是 Proc 对象或 Binding 对象,将在生成该对象的环境中对字符串进行解析执行。

示例 1 main 环境

irb(main):001:0> var = "hello ruby"=> "hello ruby"irb(main):002:0> eval("p var")"hello ruby"=> "hello ruby"

此处待执行的字符串 “p var”的运行环境为 main;就好像是直接执行了一条 p var 语句。

当前作用域中,var 为 “hello ruby”。

示例 2 foo 环境

irb(main):006:0> def fooirb(main):007:1> var = "hello foo"irb(main):008:1> eval("p var")irb(main):009:1> end=> nilirb(main):010:0> foo"hello foo"

eval 在函数 foo 中执行,因此 eval 的执行环境也变为 foo,var 的值不再是 “hello ruby”而变为“hello foo”。

示例3 binding

binding 会生成并返回 Binding 对象,该对象包含变量、方法等环境信息,可以作为eval的第二个参数,来执行 eval 的执行环境。

代码的运行是不可能脱离环境的,如果不指定,就默认为当前环境,也就是调用 eval 的地方;如果想要灵活的指定运行环境,就需要使用binding了。

irb(main):011:0> binding=> #<Binding:0x007fd391c545b0>irb(main):012:0> binding=> #<Binding:0x007fd391c492a0>irb(main):013:0> binding=> #<Binding:0x007fd391c3c438>

当调用 binding 时,会返回一个 Binding 对象,每次返回的对象都不同,这个一定要注意。如果想要保存执行环境,多次运行eval的话,一定要使用同一个 Binding 对象。

irb(main):014:0> def bindirb(main):015:1> x = 1irb(main):016:1> bindingirb(main):017:1> end=> nilirb(main):018:0> p eval("x=5", bind)5=> 5irb(main):019:0> p eval("x", bind)1=> 1

上例中,每次调用 bind 函数都会返回一个赞新的 Binding 对象,因此执行环境中的 x 始终都是 1。

irb(main):020:0> fix = bind=> #<Binding:0x007fd391beb010>irb(main):021:0> p eval("x = 5", fix)5=> 5irb(main):022:0> p eval("x", fix)5=> 5

这次,将 bind 返回的 Binding 对象保存,执行的 eval 语句会处在相同的执行环境中,变更的内容会被保存。

实例4 binding Proc

def test_bind(x,y,&p)p “x:#{x},y:#{y}”p p.call x,yreturn bindingendp1 = Proc.new(){|x,y| x+y}p2 = Proc.new(){|x,y| x*y}b1 = test_bind(3,5,&p1)=>x:3,y:5=>8=><Binding:0xxxxxxxxx…>b2 = test_bind(3,5,&p2)=>x:3,y:5=>15=><Binding:-xxxxxxxxx>eval(‘p.call x,y’,b1)=>8eval(‘p.call x,y’,b2)=>15

Binding不仅可以保存环境作用域中的变量和self,还能保存作用域中的 block 对象。

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台