2013-01-23 141 views
15

Proc#==如何評估? RDoc說:如何評估「Proc#==」?

中國== other_proc→真或假

返回true如果中國是相同的對象other_proc,或者如果它們與同一機構既特效。

但是目前還不清楚什麼算作「擁有同一個身體」。其中一種情況似乎是這樣一種情況必須是相同的:

->{} == ->{} # => true 
->{} == ->x{} # => false 
->x{} == ->x{} # => true 
->x{} == ->y{} # => true 
->x{} == ->y,z{} # => false 

但還有更多。至於說的RDoc,身體事項:

->{nil} == ->{nil} # => true 
->{nil} == ->{false} # => false 
->{false} == ->{false} # => true 

但在同一時間,它看起來像PROC沒有充分評估:

->{} == ->{nil} # => false 
->{false} == ->{1 == 2} # => false 

的就是身體評估什麼程度?

+1

我想象中的代碼必須是相同的,而不是其評估的結果。 –

+1

我在想分析的源代碼樹必須是相同的,但是......' - > {nil} == - > {nil; nil}#=> true'或者,也許第一個零被剝離源樹,因爲它沒有效果或意義? –

+1

另外:'a,b = - > {}, - > {}; a == b#=> true',但是'a = - > {} [newline] b = - > {}; a == b#=> false'。注意換行符必須是換行符;如果你使用分號,'a'等於'b'。 WTF的確如此。 –

回答

9

這有changed in Ruby 2.0,所以你不應該試圖比較Proc s。除非它們完全相同,否則它們不會是==

討論可以是found here

如果你真的需要比較兩個塊的代碼,並且正在使用MRI,那麼你可以使用RubyVM::InstructionSequence.disassemble(block),甚至在Ruby 2.0 RubyVM::InstructionSequence.of(block)中更好。

+1

比較塊的反彙編是一個有趣的技術。它顯然有侷限性 - proc必須共享一個行號(如果需要,你可以用eval僞造),並且proc綁定中變量的值不被考慮。但是我能夠創建一個考慮到塊參數的方法緩存。偉大的提示。 – rcrogers

+1

另外,Proc#to_source可能會在某個時候實現:http://bugs.ruby-lang.org/issues/2080 – rcrogers

4

要回答這個問題,讓我們看看PROC比較代碼

static VALUE 
proc_eq(VALUE self, VALUE other) 
{ 
    if (self == other) { 
     return Qtrue; 
    } 
    else { 
     if (rb_obj_is_proc(other)) { 
      rb_proc_t *p1, *p2; 
      GetProcPtr(self, p1); 
      GetProcPtr(other, p2); 
      if (p1->envval == p2->envval && 
       p1->block.iseq->iseq_size == p2->block.iseq->iseq_size && 
       p1->block.iseq->local_size == p2->block.iseq->local_size && 
       MEMCMP(p1->block.iseq->iseq, p2->block.iseq->iseq, VALUE, 
        p1->block.iseq->iseq_size) == 0) { 
       return Qtrue; 
      } 
     } 
    } 
    return Qfalse; 
} 

首先,如果分支是很簡單 - 比較兩份特效是同一個對象。 第二個有點棘手。它檢查兩個proc具有相同的envval,iseq(proc實現)的大小,局部變量大小,並比較兩個實現是否相同。這意味着在語法級別檢查proc相等性,而不是在proc結果上進行檢查。

讓我們拿https://gist.github.com/4611935 第一個示例工作得很好,因爲局部變量的數量是相同的,並且操作的順序是相同的。將123分配給局部變量。第二個樣本由於操作順序不同而被視爲不相同 - 您將123分配給不同的變量。

但是,是的,proc比較是相當混亂,並已被刪除形式紅寶石2.0我猜。現在通過它的id將procs作爲常規對象進行比較。