Alex学Ruby[eval && binding]

本文详细解析了Ruby语言中eval和binding的功能与使用方法。通过多个示例代码展示了如何利用eval执行字符串作为Ruby代码,以及如何通过binding捕获当前作用域的环境。深入探讨了eval与binding在不同上下文中的交互方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看Ruby参考里面对eval和binding的解释:

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

    把字符串expr当作Ruby程序来运行并返回其结果。若给第二参数传递Proc对象或Binding对象的话,将在生成该对象的环境中对字符串进行计算。请参考binding。

    def foo
      a = 1
      binding
    end

    eval("p a", foo)  # => 1


    若指定了fname 和 lineno的话,将假定字符串位于fname文件lineno行,并且进行编译。这时可以显示栈跟踪(stack trace)等信息。


binding

    生成并返回Binding对象。该对象包含变量、方法等的环境信息,它通常用作Eval的第二参数。

由上面信息不难理解。 eval可以把字符串当作Ruby程序来运行并返回其结果,同时也可以指定该字符串运行的环境, 只需要加第二个参数就行了,把binding的环境传过去。

太cool了。

例子:
ruby 1.8.7 (2008-06-20 patchlevel 22) [i686-darwin9.2.1]

irb(main):001:0> def foo
irb(main):002:1>   x = 1
irb(main):003:1>   binding
irb(main):004:1> end
=> nil

irb(main):005:0> save_binding = foo
=> #<Binding:0x8988c>

irb(main):006:0> p eval("x", save_binding)
1

irb(main):007:0> x = 2

irb(main):008:0> p eval("x", save_binding)
1

irb(main):009:0> p eval("x = 5 ", save_binding)
5

irb(main):010:0> p eval("x", save_binding)
5


上例中,eval的第一个参数放在第二个参数所形成的环境里被执行,同时第一个参数影响着第二个参数的闭包环境。



irb(main):011:0> def foo(my_binding)
irb(main):012:1>   eval("x", my_binding)
irb(main):013:1> end

irb(main):014:0> def bar
irb(main):015:1>   x = 100
irb(main):016:1>   foo(binding)
irb(main):017:1> end

irb(main):018:0> p bar
100

irb(main):019:0> def foo(my_binding)
irb(main):020:1>   x = 200
irb(main):021:1>   eval("x", my_binding)
irb(main):022:1> end

irb(main):023:0> p bar
100


上例中x的值已经和bar方法里的x绑定好了,任凭你foo方法如何改变都是无用的。

irb(main):024:0> x = 100
=> 100

irb(main):025:0> block_var = lambda{ x }
=> #<Proc:0x00044f98@(irb):25>
irb(main):026:0> def foo(blk)
irb(main):027:1>   blk.call
irb(main):028:1> end

irb(main):029:0> p foo(block_var)
100

上例中,lambda对象已经和x = 100 形成了一个闭包。

你call他的时候当然是得到100.

InBlock.gifclass  << Object
InBlock.gif  def xxx(name,klass)
InBlock.gif    define_method( name ) { eval "@#{name} ||= #{klass}.new" }
InBlock.gif  end
InBlock.gifend


InBlock.gifclass << Object
InBlock.gif   def attr_init(name, klass)
InBlock.gif     eval "define_method(name) { @#{name} ||= #{klass}.new }"
InBlock.gif   end
InBlock.gif end


这两种写法的区别是:第二种写法只需要调用一次eval方法,而不是在每次进行方法定义时都去重新调用eval。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值