15

どのようにProc#==評価されますか?RDocによると:

prc==other_proc→trueまたはfalse

prcがother_procと同じオブジェクトである場合、または両方が同じ本体を持つprocである場合、trueを返します。

しかし、何が「同じ体」を持っていると見なされるのかは明らかではありません。1つの条件は、アリティが同じでなければならないということのようです。

->{} == ->{} # => 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

体はどの程度評価されていますか?

4

2 に答える 2

9

これはRuby2.0で変更されたため、を比較しようとしないでくださいProc。それら==がまったく同じオブジェクトでない限り、それらはありません。

議論はここで見つけることができます。

本当に2つのブロックのコードを比較する必要があり、MRIRubyVM::InstructionSequence.disassemble(block)を使用している場合は、 Ruby2.0で遊んでみてくださいRubyVM::InstructionSequence.of(block)

于 2013-01-23T19:53:43.027 に答える
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;
}

最初のifブランチは非常に単純です-2つのprocが同じオブジェクトであると比較してください。2つ目は、もう少し注意が必要です。両方のprocが同じenvval、iseq(proc実装)のサイズ、ローカル変数のサイズを持っていることを確認し、両方の実装が同一であることを比較します。つまり、procの同等性は、procの結果ではなく、構文レベルでチェックされます。

https://gist.github.com/4611935を見てみましょう。 ローカル変数の数が同じで、操作のシーケンスが同じであるため、最初のサンプルは問題なく機能します。ローカル変数に123を割り当てます。操作シーケンスが異なるため、2番目のサンプルは同じではないものとして扱われます。123を異なる変数に割り当てます。

しかし、はい、procの比較はかなり紛らわしく、私が推測するruby2.0から削除されました。これで、procはそのIDによって通常のオブジェクトとして比較されます。

于 2013-01-23T19:58:02.733 に答える