Ruby binding 对象可以携带一个块?

cichol · 2015年03月01日 · 2220 次阅读
require 'erb'

temp ="<%= yield %>"

erb = ERB.new(temp)

def get_binding
  binding
end

p erb.result(get_binding{1})  #=> "1"

b = get_binding{1}
p erb.result(b)  #=> "1"

p b.class  #=> Binding

p erb.result(binding{1})  #=> no block given (yield) (LocalJumpError)

Kernel.binding方法不接受参数,ERB#result接受一个binding对象,这里get_binding方法接受了一个块,但是当这个方法返回的时候,那个块应该就被弃置了啊。

获得 b 可以知道 b 确实是一个 Binding 对象,然而直接传入 erb.result 却可以起到块的作用,b 这个对象看起来携带了一个块。

而且 erb.result(binding{1}) 在语法的角度看和 get_binding 应该没有区别,但是却报错了,其中肯定有一些特殊的机制在工作。

disasm 一下代码的话发现二者对 binding 的调用是不同的,一个是 send,一个是 send_simple,说明这个语句可能有两种不同的实现方式。然后就再没办法获得更多线索了。

更新

stackoverflow 上的回答是在函数内产生的 binding,包括当时所有的上下文,也包含了传入的块,yield 便可以此访问函数调用时的 block,用“携带”一词可能不太合适,虽然表现上是这样。binding 在函数内和函数外生成是这种差异的原因。

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号