为什么我会用to_proc而不是用Proc.new调用instance_eval的错误?
问题描述:
我这样做的,它的工作原理:为什么我会用to_proc而不是用Proc.new调用instance_eval的错误?
class B
def value
"X"
end
end
class A
def initialize(context)
@context = context
end
def m
Proc.new do
value
end
end
def execute
@context.instance_eval(&m)
end
end
A.new(B.new).execute #=> "X"
但调用是不工作...
class B
def value
"X"
end
end
class A
def initialize(context)
@context = context
end
def m
value
end
def execute
@context.instance_eval(&m.to_proc)
end
end
A.new(B.new).execute #=> NameError: undefined local variable or method `value' for #<A:0x007fae2ab02040 @context=#<B:0x007fae2ab02108>>
我想知道为什么这两个例子是不同的,如何使它与to_proc
答
在第二个片段中,您打电话给m
,返回调用的结果,这是未定义的。 (甚至如果如果不知何故神奇地调用B#value
,然后B#value
返回String
和String
■不要到to_proc
回应,所以你会得到一个NoMethodError
那里。)在第一个片段,你叫m
,它返回一个Proc
。
它看起来像你试图通过方法m
本身而不是调用它的结果。在Ruby中,方法不是对象,所以你不能只抓住它们并传递它们(即使方法是对象,那么m
仍然是调用m
的语法,而不是用于引用它)。你必须先问一下Ruby的反射API为方法的反射代理,使用Object#method
方法,该方法返回一个代表该方法的Method
对象:
@context.instance_eval(&method(:m).to_proc)
注意,调用to_proc
是完全多余的,在这里,因为&
无论如何,如果参数已不是Proc
,将会调用to_proc
。 (您可能已经看到过类似foo.map(&:bar)
之前,调用Symbol#to_proc
)
@context.instance_eval(&method(:m))
对不起,我错过了“&”前'm.to_proc'到PROC转换成块,并仍然没有工作。 – Leantraxxx