2013-04-03 1 views
2

일부 클래스 이름을 기반으로 매크로를 사용하여 잘 유형화 된 인스턴스를 만들 수 있기를 원합니다. 예를 들어 나는 그렇게 같은 Long 인스턴스를 만들 수 있도록하려면 :매크로를 사용하여 컴파일 할 때 잘 형식화 된 인스턴스 생성

def fromName[T](typeName: String) = macro FromNameMacro.impl[T] 

// will typecheck ok 
fromName("scala.Long") ==== 0L 
// will not typecheck ok 
fromName("scala.Long") ==== "" 

구현 될 법한 :

import scala.reflect.macros.Context 

object FromNameMacro { 
    def impl[T: c.WeakTypeTag](c : Context)(klassName: c.Expr[String]): c.Expr[T] = { 
    import c.{universe => u}; import u._ 
    val name = klassName.tree match { case Literal(Constant(n)) => n.toString } 

    // of course this doesn't work... 
    reify(this.getClass.getClassLoader.loadClass(name).newInstance.asInstanceOf[T]) 
    } 
} 

내 질문

은 다음과 같습니다

  • 내가 무엇을 할 매개 변수에 따라 유형이 달라 지므로 매크로가 올바른 유형의 객체를 반환하도록해야합니까?

  • Scala 2.10을 사용하는 것이 가능합니까? 매크로 반환 올바른 유형의 결과를 갖는

+0

, 2.10.x에서 매우 간단합니다 매크로 천국에서만 가능합니다. http://docs.scala-lang.org/overviews/macros/inference.html – Eric

+0

Miles의 답변과 함께 http://stackoverflow.com/questions/13669974/static-return을 참조하십시오. -type-of-scala-macros –

답변

1

그것은 내가 원하는 무엇처럼 보인다

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

object fromName { 
    def apply(tpe: String): Any = macro fromNameImpl 

    def fromNameImpl(c: Context)(tpe: c.Expr[String]): c.Expr[Any] = { 
    import c.universe._ 

    c.Expr(tpe.tree match { 
     case Literal(Constant("scala.Long")) => Literal(Constant(0L)) 
     case Literal(Constant("java.lang.String")) => Literal(Constant("")) 
     case _ => Literal(Constant(())) 
    }) 
    } 
} 

샘플 REPL 세션,

scala> fromName("scala.Long") 
res0: Long = 0 

scala> fromName("java.lang.String") 
res1: String = "" 
+0

T 매크로의 반환 유형이'c.Expr [Any]'(다른 SOF 질문에 대한 포인터 인 Eugene에게 감사합니다. 어제 읽었지만 요점을 놓쳤습니다.)라고 추가하면 그의 작품은 정상적으로 작동합니다. 놀랄 만한... – Eric

관련 문제