2012-04-19 10 views
1

ruby​​_parserとRuby2Rubyの宝石を使って、私はどの条件が評価されたか、その結果とパラメータが何であったかを記録するコードを書いています。できるだけシンプルにするために、ASTを少し書き直すことがあります。もちろん、結果が元のものとまったく同じであることが確かであれば、私はそれを行うことができます。Rubyにおけるif文とcase文の等価性

三つ目のドットが有効なRuby式に置き換えられたと仮定して、以下の3つのRubyスニペットが同等であると主張して正しいですか?エッジケースを見落としていますか?

case var 
    when foo 
    something 
    when ... 
    another_thing 
    else 
    something_else 
end 

if foo === var 
    something 
elsif ... === var 
  another_thing 
else 
    something_else 
end 

case 
    when foo === var 
    something 
    when ... === var 
    another_thing 
    else 
    something_else 
end 

答えて

2

これらの3つの断片は、等価IFF varである、すなわちvar複数回の評価が一度評価と同様の副作用を有し、冪等です。

したがって、varが本当に変数であれば、安全ですが、副作用メソッド(putsなど)に送信するメッセージを含む任意の式を使用できます。

など。

case puts('Hello') 
when 1 
when 2 

なぜなら後者の場合には、 "こんにちは" は二回を印刷する

if 1 === puts('Hello') 
elsif 2 === puts('Hello') 

同じないあります。 `==`や `` EQLにより `===`交換

__randomly_generated_guaranteed_unique_local_variable_jhggfq45g345 = var 

if foo === __randomly_generated_guaranteed_unique_local_variable_jhggfq45g345 
    something 
elsif ... === __randomly_generated_guaranteed_unique_local_variable_jhggfq45g345 
  another_thing 
else 
    something_else 
end 

case 
    when foo === __randomly_generated_guaranteed_unique_local_variable_jhggfq45g345 
    something 
    when ... === __randomly_generated_guaranteed_unique_local_variable_jhggfq45g345 
    another_thing 
    else 
    something_else 
end 
+0

良い点。このコードには、副作用のある引数では機能しないという厳しい警告が既に含まれています(ここで概要を説明したのと同じ理由で)。ただし、ここでも同様です。それに応じてドキュメントを変更しました。 – Confusion

0

はい、3つのRubyスニペットは機能が同等です。

更新:Rubyで

ときcase文の暗黙的===です。したがって、これら3(トリミング)は基本的に同じである:

case var when fooif foo === var & case when foo === var

私はここdocumentation数回を引用するものとします。

===,==およびeql?は、クラスオブジェクトに対して異なる結果を生成します。これらは、Stringのような他のクラスでは上書きされます。 fooとbarがStringた場合は、しかし、彼らは私たちの通常の授業のために異なるfoo == varまたはfoo.eql? var

と三重の等号===アサーションを置き換えることができます。

===Class ===(又はClass.===)の場合 引数がクラス(またはそのサブクラス)のインスタンスである場合、動作はtrueを返します。以下の場合:=>真

class A 
end 
class B < A 
end 
b = B.new 

A === bb === A => falseを返します。 (b.instance_of? A => falseを、b.instance_of? B => TRUE)

==:オブジェクト・レベルで 、==戻り真OBJ他方が同じオブジェクトである場合にのみ。 b == b =>真 、ObjectクラスのB.new == B.new => falseを

===は効果的==を呼び出すのと同じです。 Fixnum === 1 => true、1 === Fixnum => false

eql?eql?メソッドは、2つの値が同じ場合はtrueを返します。 1 == 1.0 => trueを、1.eql? == 1.0 =>偽

+1

異なる結果を与えるこれらのスニペットにつながる:?

より良い翻訳のかもしれません。クラスAを試してください。終わり;クラスB Confusion

+0

申し訳ありませんが私は私の答えに詳細を入れませんでした。私はあなたが継承したクラスとオブジェクトのためにこれをやっていたことを知らなかった。上記の3つのスニペットの機能を評価するときには、私は単純に整数と文字列を持っていました。はい、あなたは正しいです、 '==='、 '=='、 'eql?'はクラスオブジェクトに対して異なる結果を生成します。これらは 'String'のような他のクラスでオーバーライドされています(私の答えに基づいています)。私はこれらのシナリオをすべて反映するように自分の答えを更新しました。正に、最初に熟考すべきだったはずです。再度申し訳ありません – prasvin