1

ruby_parser と Ruby2Ruby の gem を使用して、どの条件が評価され、その結果とパラメーターがどのようなものであったかを追跡するコードを作成しています。これをできるだけ単純にするために、AST を少し書き直すことがあります。もちろん、結果がオリジナルとまったく同じように機能することが確実な場合にのみ、それを行うことができます。

次の 3 つの 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
4

2 に答える 2

2

これらの 3 つのスニペットはvar、冪等である場合は同等です。つまり、var複数回評価すると、1 回評価した場合と同じ副作用があります。

したがって、var本当に が変数である場合は安全ですが、副作用のあるメソッド ( などputs) に送信されるメッセージを含む、任意の式になる可能性があることに注意してください。

例えば

case puts('Hello')
when 1
when 2

と同じではありません

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

後者の場合、「Hello」が2 回出力されるためです。

より良い翻訳は次のようになります。

__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
于 2012-04-19T12:58:35.877 に答える
0

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

アップデート :

Ruby では、case ステートメントの when は暗黙の === です。したがって、これらの 3 つの (トリムされた) は本質的に同じです。

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

ここでドキュメントを数回引用します。

===、クラス オブジェクトに対して異なる結果を生成します==eql?これらは、 などの他のクラスでオーバーライドされStringます。foo と bar が の場合、トリプル イコールアサーションを orStringに置き換えることができます。===foo == varfoo.eql? var

ただし、通常のクラスでは異なります。

=== : Class ===(またはClass.===) の場合、引数がクラス (またはサブクラス) のインスタンスである場合、操作は true を返します。為に :

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

A === b=>真、b === A=>偽。( b.instance_of? A=> 偽、b.instance_of? B=> 真)

== : オブジェクト レベルで==は、obj と other が同じオブジェクトである場合にのみ true を返します。 b == b=>真、B.new == B.new=>偽

クラス Object の場合、===実質的に を呼び出すのと同じ==です。 Fixnum === 1=>真、1 === Fixnum=>偽

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

于 2012-04-19T09:51:11.977 に答える