2017-11-17 140 views
0

我這樣做的,它的工作原理:爲什麼我會用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

回答

0

在第二個片段中,您打電話給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

相關問題