使用ruby_parser和Ruby2Ruby宝石,我正在编写代码来跟踪已评估的条件以及它们的结果和参数。为了保持尽可能简单,我有时会重写AST。当然,如果我确定结果与原始结果完全相同,我只能这样做。
我是否正确断言以下三个Ruby片段在功能上是等效的,假设三个点被有效的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
答案 0 :(得分:2)
如果var
是幂等的,则这三个片段是等效的,即多次评估var
具有与评估一次相同的副作用。
所以,如果var
确实是一个变量,那么你是安全的,但请记住它可以是一个任意的表达式,包括发送给副作用方法的消息(如puts
)。 / p>
E.g。
case puts('Hello')
when 1
when 2
与
相同if 1 === puts('Hello')
elsif 2 === puts('Hello')
因为在后一种情况下,“Hello”将打印两次。
更好的翻译可能是:
__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
答案 1 :(得分:0)
是的,三个Ruby代码段在功能上是等价的。
更新:
在Ruby中,case语句的时间是隐含的===。所以,这3个(修剪过的)基本相同:
case var when foo
,if 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 === b
=&gt;是的,b === A
=&gt;假。 (b.instance_of? A
=&gt; false,b.instance_of? B
=&gt; true)
== :
在Object级别,==
仅在obj和other是同一个对象时才返回true。
b == b
=&gt;是的,B.new == B.new
=&gt;假
对于类Object,===
实际上与调用==
相同。
Fixnum === 1
=&gt;是的,1 === Fixnum
=&gt;假
eql?:
如果两个具有相同的值,则eql?
方法返回true。
1 == 1.0
=&gt;是的,1.eql? == 1.0
=&gt;假