• ベストアンサー

Procの==はほとんど常にfalseを返す?

Procの==はほとんど常にfalseを返す? Proc#==は同じインスタンスであるか、それぞれのインスタンスの内容がまったく同じ場合にtrueを返すことを期待していたのですが..なぜ以下のようなことが起きるのでしょうか? >> Proc.new{}==Proc.new{} => true >> a = 1 => 1 >> Proc.new{a}==Proc.new{a} => false 私の想像の及ばないところで何か起きているような気がしています。ご教授下さい。

  • Ruby
  • 回答数4
  • ありがとう数17

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

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だと少し違う結果になりました。)

yu090jp
質問者

お礼

おお、ありがとうございます。 1.9だと期待した動きですね。元々はクローンかコピーの時に==が成立するような仕様だったんですね。私が先に挙げたのは最新のバージョンのリファレンスだったかもしれません。

その他の回答 (3)

  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.4

#2です。 >以下の二つのソースを見ると違うものなのでProcで再定義されているのではないでしょうか? なるほど。わたしは、http://www.ruby-lang.org/ja/documentation/ を見てました。リファレンスの記述不足ということですね。

yu090jp
質問者

お礼

ああ、なるほど。 そうでしたね。リファレンスがちょっと足りなかったですね。ありがとうございました。

  • notnot
  • ベストアンサー率47% (4848/10261)
回答No.2

リファレンスを見ると、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しても同じオブジェクトになるようですね。当然等しい。

yu090jp
質問者

お礼

ありがとうございます。 >リファレンスを見ると、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)
回答No.1

オブジェクトの生成過程で、Proc.new{}は無意味なので、自動的に生成しない最適化を図るのでしょう。したがって、Proc.new{}は両方ともnullオブジェクトとして返されて、一致するのでしょう。 また、Proc.new{a}は役には立たないインスタンスですが、一応インスタンス化はなされて、それぞれ別の記憶場所を確保するので、二つのインスタンスは別のものと答えているのでしょう。

yu090jp
質問者

お礼

Proc.new{}自体はProcのインスタンスを返すので http://apidock.com/ruby/Proc/== にある条件すべてでfalseにならないようになっていたりはしませんか? また同ページによると、オブジェクトが同じ場合とブロックの内容が同じ場合にtrueを返す様です。

関連するQ&A

  • equals("A") ?false : true

    質問します。 次の内容のjavaプログラムを見かけました。 if (args[0].equals("A") ? false : true) { この「? false : true」の意味がわかる方、教えてもらえますか? よろしくお願いします。

    • ベストアンサー
    • Java
  • WEBrick の mount_proc について

    WEBrick の mount_proc について WEBrick の mount_proc がうまく動かず困っています。 以下のようなプログラムを書いたのですが、"Hello,World!!"ではなく、dummy/index.htmlの内容が表示されてしまいます。p "hello"も実行されないのでmount_procがそもそもうまくいっていないようです。どうすれば解決できるでしょうか。よろしくお願いします。 ****** #! ruby -Ks # -*- coding: Windows-31J -*- require 'webrick' config = { :Port => 3000, :DocumentRoot => '.', } server = WEBrick::HTTPServer.new(config) server.mount_proc("./dummy") do |req, res| res.body = "Hello, World!!" p "hello" end trap(:INT) do server.shutdown end server.start

    • ベストアンサー
    • Ruby
  • FALSEの行を削除したい

    office365 データベースから抽出したデータでフラグがFALSEの行を削除したい。 行数は2万行くらいある状態。 データの状態は A列に親となる番号のコード B列に順番と品番が結合されたコード C列にフラグのコード で、具体的なデータのイメージは下記状態 A列   B列  C列 A0001 1code1 TRUE A0001 2code1 TRUE A0001 2code1 FALSE A0001 3code1 TRUE A0001 4code1 A0001 5code1 TRUE A0001 6code1 TRUE A0001 7code1 TRUE A0001 8code1 TRUE A0001 9code1 TRUE A0001 10code1 TRUE A0001 11code1 TRUE A0001 12code1 TRUE A0002 1code2 TRUE A0002 2code2 TRUE A0002 3code2 TRUE A0002 4code2 TRUE A0002 5code2 TRUE A0002 6code2 TRUE A0002 7code2 TRUE A0002 8code2 TRUE A0003 1code3 TRUE A0003 2code3 TRUE A0003 3code3 TRUE A0003 3code3 FALSE この状態でC列がFALSEとなっている行を削除したい。 C列がNULLの行はそのまま残す。 これを実現するマクロを下記の様にしました。 C列NULLのセルをいったんTRUEに置換、 sub macro1() Dim LASTROW1 As Long 'シートのmax行数 LASTROW1 = Worksheets("sheet1").Cells(Rows.count, 1).End(xlUp).Row Range("C2: C" & LASTROW1).Select Selection.Replace What:="", Replacement:="TRUE", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula end sub C列で並び替えてTRUEの行を別シート(work)へコピー sub macro2() ThisWorkbook.Worksheets("sheet1").Select Dim t As Long t = 2 Dim LASTROW As Long LASTROW = Worksheets("sheet1").Cells(Rows.count, 1).End(xlUp).Row Range("A:C").Select Selection.AutoFilter ActiveSheet.Range(Cells(1, 1), Cells(LASTROW, 3)).AutoFilter Field:=3, Criteria1:="TRUE" Rows(t & ":" & LASTROW).Select Selection.Copy Sheets("work").Select Range("A1").Select ActiveSheet.Paste end sub 実行結果 A0001 1code1 TRUE A0001 2code1 TRUE A0001 3code1 TRUE A0001 4code1 A0001 5code1 TRUE A0001 6code1 TRUE A0001 7code1 TRUE A0001 8code1 TRUE A0001 9code1 TRUE A0001 10code1 TRUE A0001 11code1 TRUE A0001 12code1 TRUE A0002 1code2 TRUE A0002 2code2 TRUE A0002 3code2 TRUE A0002 4code2 TRUE A0002 5code2 TRUE A0002 6code2 TRUE A0002 7code2 TRUE A0002 8code2 TRUE A0003 1code3 TRUE A0003 2code3 TRUE A0003 3code3 TRUE となる様にしたいのです。 いちおうmacro1とmacro2の内容で目的は達成されているのですが、 もっとすっきりするマクロがあれば教えていただきたく。

  • VLOOKUPのTRUEとFALSEの意味は

    Excel2010を使っています。VLOOKUP関数を使うときに、検索掛ける値と掛けられる値が一致しなくてもいい時は、例えば=VLOOKUP(A8,E8:G30,3,TRUE)などと書きます。完全に一致する検索の場合は、TRUEではなくFALSEを入れます。  このTRUE(真)とFALSE(偽)の意味は何でしょうか。どう解釈すると覚えやすい(説明しやすい)でしょうか。

  • VLOOKUP関数のFALSEって?

    VLOOKUP関数をよく使うのですが、ふと最後の引数のFALSEって何を意味しているのかが気になりました。いつも無意識にFALSEを使っていましたが、TRUEはどのような場合に使う必要が生じるのでしょうか? 本をみると「検索の型」を選択するようですが、よく意味がわかりません。具体的にどういうことなのでしょうか?

  • VLOOKUP関数のFALSEって?

    VLOOKUP関数をよく使うのですが、ふと最後の引数のFALSEって何を意味しているのかが気になりました。いつも無意識にFALSEを使っていましたが、TRUEはどのような場合に使う必要が生じるのでしょうか? 本をみると「検索の型」を選択するようですが、よく意味がわかりません。具体的にどういうことなのでしょうか?

  • VLOOKUP関数 「ある」ならTrue、「ない」ならFalseを返したい

    現在、図のように、 「B列の値がA列にあるならその値をC列に返す」と言うようにしています。 しかし、返す値を検索値ではなく True、もしくはFalseで返すにはどうすればいいでしょうか? IF関数を使うのですか? ご教授よろしくお願い致します。

  • ifの条件式 !について

    以下処理があります。 1.宣言、初期化 var A = new Array(); A[1] = A[2] = A[3] = false; 2.条件判断 if(!A[1] && !A[2] && !A[3]){ A[1] = $A[2] = A[3] = true; }else{ 処理 } } 質問:宣言⇒ifに処理が流れた時、条件式の内容は ・A[1]の否定⇒A1は、falseが格納されているので、否定でtrue。 ・A[2]の否定⇒A1は、falseが格納されているので、否定でtrue。 ・A[3]の否定⇒A1は、falseが格納されているので、否定でtrue。 よって、 if(true && true && true){ A[1] = $A[2] = A[3] = true; } で結果、配列の1~3は、全てfalseから、trueに変更されるという考えで間違っていないでしょうか? よろしくお願いします。

  • 「True or False 謎」の質問について

    まず、この質問内容は、別の方が質問された事柄に関しての質問です。私が気付いた時には、既に締め切られていて、それでも私の頭の中では解決していないので、新しく質問をさせて下さい。 以下で、元々の質問のページがご覧になれます。 http://okwave.jp/qa2670564.html もし、この様な質問の仕方が、OKWave の規則に反するものでしたら、OKWave さん、削除して下さい。 質問の内容は、質問者さんにとって、 >>"He is still working at the company as busily as before." >>True or False: He is not busier than before. の答えはどうしても True だとしかとれないのだが、どうして False という答えが出て来るのか、というような内容でした。 アメリカ在住17年の私も、アメリカ人の夫も答えは即答で TRUE でした。(彼に言わせれば、falseが間違いだそうです)ですが、上記のページで質問にお答えになっていらっしゃる方の答えは全て、False でした。内容を読ませて頂いたのですが、なおさら頭がこんがらがってしまったと言うか...本当にfalseが正しいのでしょうか。 分かりやすく説明を頂けると、大変有り難いです。どうぞよろしくお願い致します。

  • IEでnavigator.javaEnabled()にfalseを返させる方法

    IE6を使っています。 navigator.javaEnabled()はどういう場合にfalseを返すのだろうと思ってテストしていたのですが、Java関連の設定をいじってみても常にtrueが返ってきます。 変更した設定は、インターネットオプションのセキュリティ>レベルのカスタマイズの、 ・MicrosoftVM>Javaの許可:Javaを無効にする ・スクリプト>Javaアプレットのスクリプト:無効にする の2つです。 これで確かにアプレットは起動しないのですが、navigator.javaEnabled()を実行するとtrueが返ってくるのです。 navigator.javaEnabled()にfalseを返させるためには、どのようにすればよいのでしょうか? よろしくお願いします。

専門家に質問してみよう