为什么我会用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返回StringString■不要到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)) 
+0

对不起,我错过了“&”前'm.to_proc'到PROC转换成块,并仍然没有工作。 – Leantraxxx