2012-04-19 3 views
1

ruby_parser 및 Ruby2Ruby 젬을 사용하여 어떤 조건이 평가되었는지와 그 결과와 매개 변수가 무엇인지 추적하는 코드를 작성합니다. 가능한 한 간단하게 유지하기 위해 때때로 AST를 약간 재 작성합니다. 물론 결과가 원래와 정확히 동일하면 확신 할 수 있습니다.Ruby에서 if 문과 case 문 형식의 동일성

트리플 점이 유효한 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

이 세 조각은 var IFF 멱등 등가 인, 즉 var 여러번 한번 평가와 같은 부작용을 평가했다.

따라서 var이 실제로 변수 인 경우 안전하지만 부작용 메서드 (예 : puts)로 보내는 메시지를 포함하여 임의의식이 될 수 있습니다.

예.

case puts('Hello') 
when 1 
when 2 

때문에 후자의 경우

if 1 === puts('Hello') 
elsif 2 === puts('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 
+0

좋은 지적. 코드에는 이미 부작용이있는 인수에 대해 작동하지 않는다는 엄격한 경고가 포함되어 있습니다 (여기에서 설명한 것과 비슷한 이유로). 그러나 여기에도 적용된다는 것을 아직 알지 못했습니다. 그에 따라 문서를 수정했습니다. – Confusion

0

네 개의 루비 스 니펫은 기능이 동일합니다.

업데이트 : 루비에서

은 case 문의 === 암시되는 경우. 그래서 (손질)이 3 본질적으로 동일합니다

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

내가 여기 documentation 몇 번 인용된다.

===, ==eql?은 클래스 개체에 대해 다른 결과를 생성합니다. 이러한 클래스는 String과 같은 다른 클래스에서 재정의됩니다. foo는 바는 String 있다면 , 당신은 그러나, 그들은 우리의 정규 과목 다를 foo == var 또는 foo.eql? var

와 삼중 등호 === 주장을 대체 할 수있다.

=== : 인수가 클래스 (또는 서브 클래스)의 인스턴스의 경우는 Class === (또는 Class.===)의 경우 는 작업이 true를 돌려줍니다. 경우 : => 사실

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

A === b, b === A => false입니다. (b.instance_of? A => false를 b.instance_of? B => TRUE)

== : 개체 수준에서 , == 만 반환 OBJ 경우는 true, 그리고 다른 하나는 같은 객체. b == b => 사실 , Object 클래스 B.new == B.new => 거짓

, === 효과적으로 ==를 호출 한 것과 같은 상태가된다. Fixnum === 1 => true, 1 === Fixnum => false

eql? : 두 값이 같은 경우 eql? 메서드는 true를 반환합니다. 1 == 1.0 => 진정한 1.eql? == 1.0 => 거짓

+1

교체'==='에 의해'=='또는'EQL'다른 결과를 제공하는이 조각으로 이어질 것?. 클래스 A를 사용해보십시오. 종료; 클래스 B Confusion

+0

나는 내 대답에 더 많은 내용을 넣지 않았다는 것을 유감스럽게 생각한다. 상속 된 클래스 및 객체에 대해이 작업을 수행하고 있다는 것을 알지 못했습니다. 위의 3 개 발췌문의 기능을 평가할 때 정수와 문자열을 사용했습니다. 네, 맞습니다,'===','=='및'eql? '은 클래스 객체에 대해 다른 결과를 생성합니다. 이것들은'String'과 같은 다른 클래스에서 무효화됩니다 (이것은 제가 대답을 기반으로합니다). 솔직히 말해서, 내가 처음에 숙고해야했던 모든 시나리오를 반영하기 위해 내 대답을 업데이트했습니다. 죄송합니다 다시 – prasvin