1

使用 ruby​​_parser 和 Ruby2Ruby gems,我正在编写代码来跟踪已评估的条件以及它们的结果和参数是什么。为了使这尽可能简单,我有时会稍微重写 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
4

2 回答 2

2

如果是幂等的,这三个片段是等价var的,即var多次评估与评估一次具有相同的副作用。

因此,如果var真的是一个变量,那么您是安全的,但请记住,它可以是任意表达式,包括发送到副作用方法(如puts)的消息。

例如

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
于 2012-04-19T12:58:35.877 回答
0

是的,这三个 Ruby 片段在功能上是等价的。

更新 :

在 Ruby 中,case 语句的 when 是一个隐含的 ===。因此,这 3 个(修剪过的)本质上是相同的:

case var when foo, if foo === var&case when foo === var

我将在这里多次引用文档。

=====eql?为类对象产生不同的结果。这些在其他类中被覆盖,例如String. 如果 foo 和 bar 是String,你可以用or替换三等号===断言 foo == varfoo.eql? var

但是,它们对于我们的普通课程有所不同。

=== :在 (or ) 的情况下,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?如果两者具有相同的值,则该方法返回 true。 1 == 1.0=> 真,1.eql? == 1.0=> 假

于 2012-04-19T09:51:11.977 回答