- ベストアンサー
Procの==はほとんど常にfalseを返す?
Procの==はほとんど常にfalseを返す? Proc#==は同じインスタンスであるか、それぞれのインスタンスの内容がまったく同じ場合にtrueを返すことを期待していたのですが..なぜ以下のようなことが起きるのでしょうか? >> Proc.new{}==Proc.new{} => true >> a = 1 => 1 >> Proc.new{a}==Proc.new{a} => false 私の想像の及ばないところで何か起きているような気がしています。ご教授下さい。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
1.8と1.9でも大分挙動が違いますね。 p Proc.new{} == Proc.new{} #=>[1.8]true,[1.9]true p1 = Proc.new{} p2 = Proc.new{} p p1 == p2 #=>[1.8]true,[1.9]true a = 1 p Proc.new{a} == Proc.new{a} #=>[1.8]false,[1.9]true p Proc.new{|x| x} == Proc.new{|x| x} #=>[1.8]false,[1.9]true p1 = Proc.new{|x|x} p2 = Proc.new{|x|x} p p1 == p2 #=>[1.8]false,[1.9]true p Proc.new{|x| x} == Proc.new{|x| x*x} #=>[1.8]false,[1.9]false p1= Proc.new{|x| x} p p1== p1.dup #=>[1.8]true,[1.9]true p (p1=Proc.new{|x|x})==(p2=Proc.new{|x|x})#=>[1.8]false,[1.9]true p p1 == p2 #=>[1.8]false,[1.9]true 「Procの==が成立するのは、比較対象がクローンかコピーになっている場合。 Proc.new{}==Proc.new{}等は例外的にtrueを返す」とあります。 (引用元:「プログラミング言語 Ruby」 David Flanagan、まつもとゆきひろ共著) 1.8では上記の通りでしたが、1.9ではProc内のコードが一緒であればtrueを返しました。 1.9だと期待通りですかね? 1.8と1.9で変更があったのかもしれません。 (irbだと少し違う結果になりました。)
その他の回答 (3)
- notnot
- ベストアンサー率47% (4900/10359)
#2です。 >以下の二つのソースを見ると違うものなのでProcで再定義されているのではないでしょうか? なるほど。わたしは、http://www.ruby-lang.org/ja/documentation/ を見てました。リファレンスの記述不足ということですね。
お礼
ああ、なるほど。 そうでしたね。リファレンスがちょっと足りなかったですね。ありがとうございました。
- notnot
- ベストアンサー率47% (4900/10359)
リファレンスを見ると、Proc#== は再定義されてないので、Object#== と同じ、つまり Object#equal? と同じく同じオブジェクトの時だけ等しいはずです。 a=Proc.new{} b=Proc.new{} p a.object_id p b.object_id をみると、違うオブジェクトなので、Proc.new{}==Proc.new{} はfalseになるのが正しい挙動のように思います。 解答になってなくてすみません。 一方、 def foo(&p) a=Proc.new(&p) b=Proc.new(&p) p a.object_id p b.object_id end foo{123} とかを見ると、同じブロックを与えた場合は、何度Proc.newしても同じオブジェクトになるようですね。当然等しい。
お礼
ありがとうございます。 >リファレンスを見ると、Proc#== は再定義されてないので、Object#== と同じ、つまり Object#equal? と同じく同じオブジェクトの時だけ等しいはずです。 以下の二つのソースを見ると違うものなのでProcで再定義されているのではないでしょうか? http://apidock.com/ruby/Object/== http://apidock.com/ruby/Proc/== ブロックの内容を比べている条件(if (data->body != data2->body) return Qfalse;)以外でfalseが返されている様に思えます。
- seastar3
- ベストアンサー率69% (99/142)
オブジェクトの生成過程で、Proc.new{}は無意味なので、自動的に生成しない最適化を図るのでしょう。したがって、Proc.new{}は両方ともnullオブジェクトとして返されて、一致するのでしょう。 また、Proc.new{a}は役には立たないインスタンスですが、一応インスタンス化はなされて、それぞれ別の記憶場所を確保するので、二つのインスタンスは別のものと答えているのでしょう。
お礼
Proc.new{}自体はProcのインスタンスを返すので http://apidock.com/ruby/Proc/== にある条件すべてでfalseにならないようになっていたりはしませんか? また同ページによると、オブジェクトが同じ場合とブロックの内容が同じ場合にtrueを返す様です。
お礼
おお、ありがとうございます。 1.9だと期待した動きですね。元々はクローンかコピーの時に==が成立するような仕様だったんですね。私が先に挙げたのは最新のバージョンのリファレンスだったかもしれません。