def multiplier(n)
lambda { |data| data.map { |x| x*n } }
end
doubler = multiplier(2)
puts doubler.([1,2,3])
eval("n=3", doubler)
#doubler.binding.eval("n=3")
#eval("n=3", doubler.binding)
puts doubler.([1,2,3])
书中说可以用 eval("n=3", doubler) 代替注释的行,我测试报错,求解,谢谢。:
test.rb:7:in eval': wrong argument type Proc (expected Binding) (TypeError)
from test.rb:7:in
首先,我估计 [双飞燕] 可能有中文版和英文版,我的是英文版的 PDF,这部分内容在英文版的 217 页,第 6.6.2 章节中,所以楼主最好以后留下章节信息,因为章节信息在任何版本中应该都是对应的。
其次在英文版中,这里的内容和注释内容是这样写的:
eval("n=3", doubler.binding) # Or doubler.binding.eval("n=3") in Ruby 1.9
也就是说,如果楼主用的 ruby 版本是 1.9 以上,那么就需要用注释中的第二种写法
~ $ irb
>> def multiplier(n)
>> lambda {|data| data.collect{|x| x*n } } end
=> nil
>> doubler = multiplier(2)
=> #<Proc:0x007fd3420d1b38@(irb):2 (lambda)>
>> puts doubler.call([1,2,3])
2
4
6
=> nil
>> doubler.binding.eval("n=3")
=> 3
>> puts doubler.call([1,2,3])
3
6
9
=> nil
#5 楼 @LinuxGit 我已经看过了,英文原版也有这一段,从测试来看,在 Ruby 1.9.3-p125 中已经不能这么用了。
As a shortcut, the eval method allows you to pass a Proc object directly instead of passing the Binding object of the Proc. So we could replace the eval invocation above with:
eval("n=3", doubler)
Bindings are not only a feature of closures. The Kernel.binding method returns a Binding object that represents the bindings in effect at whatever point you happen to call it.
#8 楼 @LinuxGit 刚刚测试了一下,以及检查了 API,如 #6 楼 @lgn21st 说的,1.9.2+ 不行用了,1.8.7 可以。
Ruby core API Proc 1.8.7 Proc 1.9.2 Proc 1.9.3
明显发现 1.9.2 及 1.9.3 少了无 binding 的例子。
提示很明显啊
/root/ruby/test.rb:284:in `eval': wrong argument type Proc (expected Binding) (TypeError)
我猜测主要是 1.9 针对 binding 对象已经提供了 eval 方法,根本没必要再通过之前的给 eval 提供第二参数的方式来运行了吧。再说了,原来那种所谓隐式转换,实在不是什么好的编程习惯,我发现 Ruby1.9 中大把这种似是而非 (容易引起混淆), 甚至之前当作好东西来卖弄的东西,都取缔了。