2013-05-08 2 views
4

"type"키워드로 정의 된 유형을 사용하는 매크로를 사용하고 싶습니다. 그것을 어떻게 참조 할 수 있습니까? 내가 예제에서 컴파일러 오류를 표시 한유형 프로그래밍을 스칼라 매크로와 결합하는 방법

import scala.reflect.macros.Context 
import scala.language.experimental.macros 

trait Demo6 { 
    type T 

    def add(param: Any): T = macro Demo6.addImpl[T] 

    def fullAdd(param: Any, toStringBasedOnAST: String): T = { 
    doesSomeThing_and_returnsSomething_OfTypeT 
    } 
    def doesSomeThing_and_returnsSomething_OfTypeT: T //just to allow compilation 
} 

object Demo6 { 
    def addImpl[T: c.WeakTypeTag](c: Context)(param: c.Expr[Any]): c.Expr[T] = { 
    import c.universe._ 
    reify { (c.Expr[Demo6](c.prefix.tree)).splice.fullAdd(param.splice, 
             c.literal(show(param.tree)).splice) } 
    //  ^- type mismatch; found : org.autotdd.scalamacros.Demo6#T 
    //       required: T 
    } 
} 

내 시작 코드입니다. 그것은 무슨 일이 일어나고 있는지 꽤 명확 : 키워드에 의해 정의 된 타입 T가하지 내가 전달하고있는 T 형과 동일 내가 해봤

아직에 많은 문서가 아닌 . scala-macros. http://docs.scala-lang.org/overviews/macros/overview.html의 섹션은 지금까지 나에게 도움이되었지만 예제에서는 클래스 수준과 메서드 수준을 일반적으로 사용합니다. Expecty와 macrocosm에 대한 코드를 찾아 보았습니다.이 코드는 문서에서 언급 된 프로젝트이지만 이런 코드는 찾을 수 없습니다.

+0

'T'에 type 태그를 사용해야합니까? 그렇지 않다면,'addImpl'을 위해서'T' 매개 변수조차 필요하지 않습니다. 당신은'Typed'와'TypeName ("T")'를 사용할 수 있어야합니다. –

답변

4

귀하의 코드는 거의 정확, 단지 Expr의 형식 매개 변수를 변경 : 당신이 반환해야

val expr = reify { ... } 
c.Expr[T](expr.tree) 

reify없이 :

c.Expr[T](Apply(Select(c.prefix.tree, newTermName("fullAdd")), 
       List(param.tree, Literal(Constant(show(param.tree)))))) 

reify이 같은 작성하지만 잘못된 유형의 매개 변수.

showRaw 사용의 경우 this answer을 참조하십시오. 이 경우

:

scala> import reflect.runtime.universe._ 
import reflect.runtime.universe._ 

scala> { 
    | object Demo { def fullAdd(param1: Any, param2: String): String = "result" } 
    | showRaw{ reify { Demo.fullAdd("param1", "param2") } } 
    | } 
res0: String = Expr(Apply(Select(Ident(newTermName("Demo")), newTermName("fullAdd")), List(Literal(Constant("param1")), Literal(Constant("param2"))))) 

show(param.tree)param.treec.prefix.treeIdent(newTermName("Demo")), Literal(Constant("param1"))"param2"를 교체하고 당신이 당신의 결과를 얻을 수 있습니다.

+1

감사합니다. 정말 잘했습니다. 나는 당신이 그 일을 어떻게했는지 이해하는 데 어려움을 겪고 있습니다. 여기에서 나를 도울 코드를 제안 해 주시겠습니까? –

+0

@StaveEscura : 답변을 업데이트했습니다. – senia

+0

정말 좋은 링크입니다. 나는 그것을 읽는 데 몇 시간을 보내는 것을 볼 수있다. :) –