【发布时间】:2014-10-12 15:24:22
【问题描述】:
请考虑以下不同的方式来定义方法m:
-
方法一:
class C def m; yield; end end -
方法二:
class C def initialize (class << self; self; end).class_eval do define_method(:m){|&b| b.call } end end end -
方法三:
class C def initialize (class << self; self; end).class_eval do define_method(:m){puts block_given?; yield} end end end
然后我可以使用Object#send 调用m。
o = C.new
o.send(:m) {puts 'test'}
虽然使用方法 1 或方法 2 调用 m 可以正常工作,但方法 3 会出现此错误:
no block given (yield) (LocalJumpError)
我知道块不是一个对象,而只是方法调用语法的一部分,如果不写一些晦涩的东西,就不能将隐式块从一个函数传递到另一个函数:
def printer
yield
end
def proxy
printer &Proc.new
end
proxy { puts "&Proc.new probably creates Proc object from block"}
但是在这种情况下,为什么方法 1 有效?得到一个可以解释幕后发生的事情的答案真是太棒了。
【问题讨论】:
-
不清楚您所说的“静态定义 ...”、“使用显式块”或“第一种情况”是什么意思。我猜你可能会提到你的方法 1、方法 2 或方法 3,但不清楚是哪个。
-
@sawa 我认为代码片段会很清楚。您分别引用了方法一、方法二和方法一:)
-
你为什么用
send打电话给m?它看起来没有任何意义。 -
@sawa 这个代码是从上下文中派生的,它应该被这样调用,但在这种特殊情况下,它似乎并不重要。
-
如果您不知道,在方法 2 中,您可以在类上调用
class_eval,而不是在单例类上:self.class.class_eval do。
标签: ruby metaprogramming proc