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 在函数内和函数外生成是这种差异的原因。