2014-01-05 56 views
3

鉴于宏的Option[T],我试图找到封闭式T,从而给出类似斯卡拉宏:找到选项的封闭式

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

def innerTypeImpl[T: c.WeakTypeTag](c: Context): c.Expr[String] = { 
    import c.universe._ 

    val tpe = weakTypeOf[T] 
    val innerType = tpe.typeSymbol.asType.typeParams.head.name.decoded 
    c.Expr[String] { q" {$innerType} " } 
} 

def innerType[T] = macro innerTypeImpl[T] 

通话innerType[Option[Int]]将返回"Int"(而现在它是返回"A",其对应于的Option定义中使用的类型的参数)

T可以不是Option(该计划是使用tpe.typeSymbol.name.decoded == "Option",以确定是否TOption),所以我不能够把任何边界上T

回答

4

我想你想是这样的:

val innerType = weakTypeOf[T] match { 
    case r: TypeRef => r.args.head 
    case _ => c.abort(c.enclosingPosition, "call this method with known type parameter only.") 
} 

注意WeakTypeTag可能不是一个TypeRef

该方法将在None.type上失败。为了使它在工作的亚型(如None.type),你应该使用的方法baseType这样的:

val innerType = weakTypeOf[T].baseType(typeOf[Option[_]].typeSymbol) match { 
    case TypeRef(_, _, targ :: Nil) => targ 
    case NoType => c.abort(...) 
} 
+1

一定要调用'baseType'之前,模式匹配。如果有可能声明Option的无参数子类,模式匹配将虚假地崩溃。 –

+0

@EugeneBurmako:你可以添加细节到你的答案。我无法尽可能好地创建一个关于scala宏的答案。 – senia

+0

非常感谢您的阐述!我已经删除了我的答案,因为你的更友好。 –