2014-01-24 3 views
1

2.10.3 용 Scala API 문서에서는 "refiy를 사용하여 주어진 스칼라 표현식을 나타내는 추상 구문 트리를 생성 할 수 있습니다."라고 말합니다. 따라서, 내가 할 수있는 : Predef.intWrapper(1).to(3))가 (작업의 편리 확장 된 표현을 실시하기) :Scala reify가 문서에 따라 작동하지 않는 이유는 무엇입니까?

scala> val uni = scala.reflect.runtime.universe 
uni: scala.reflect.api.JavaUniverse = [email protected] 

scala> uni reify { 1 to 3 } 
res2: uni.Expr[scala.collection.immutable.Range.Inclusive] = Expr[scala.collection.immutable.Range.Inclusive](Predef.intWrapper(1).to(3)) 

을 위의 예에서, 나는 내가 무엇을 찾고 얻을.

그러나 1 + 3을 구체화하려고 할 때 원하는 작업을 수행 할 표현이 없습니다.

scala> uni reify { 1 + 3 } 
res5: uni.Expr[Int(4)] = Expr[Int(4)](4) 

이 예상되는 동작입니까? +은 기본 연산이며 따라서 정규화되지 않았습니까?

스칼라 문서

는 더욱 유용한 표현이 가능하다는 것을 의미한다 구체화의 예를 보여줍니다 (있는 경우) 내가 1 + 3에 대한 적절한 확장 된 표현을 검사 할 수 있습니다 내가 어떻게 검색 할 수있는 방법

reify{ 2 + 4 } // Apply(Select(Literal(Constant(2)), newTermName("$plus")), List(Literal(Constant(4)))) 

(바로 위의) 표현식에 대한 자세한 표현은 무엇입니까?

편집 : 이제 스칼라 문서의 표현은 showRaw으로 생성됩니다. 그러나 위 예제의 2 + 4에 대한 원시 표현을 여전히 재현 할 수 없습니다.

답변

5

유진 Burmako 의해 this answer 참조 :

매크로 및 유형 검사

reify가 상수

폴드 (매크로 이전 매크로 팽창 타입 체크된다 인수한다는 의미에서) 유형 검사로 배선되고 매크로를 사용하여 구현되었습니다.

당신은 다음과 같이 상수 폴딩을 방지해야한다 : 당신의 해결 방법을 사용하기 위해

{ 
    val i = 1 
    showRaw{ reify{i + 2}.tree } 
} 
// Apply(Select(Ident(newTermName("i")), newTermName("$plus")), List(Literal(Constant(2)))) 
+0

, 나는 내가 reifying하고 코드를 변경해야합니다. 항상 쉬운 것은 아닙니다. 다른 방법이 없습니까? –

+0

또한 {reef {2 + 4} // Apply (Select (리터럴 (상수 (2)), newTermName ("$ 플러스"), List (리터럴 (4)))))'? –

+0

@AndrewMcKinlay : 컴파일 타임에'2 + 4'가'6'으로 접혀 런타임에 상수'6' 만 남을 것입니다. 나는 지속적인 폴딩을 막을 다른 방법을 모른다. 어떤 종류의 DSL을 개발하고 있다면'math "1 + 2"'와 같은 문자열 보간법을 사용할 수 있습니다. – senia