2014-01-05 55 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

非常感謝您的闡述!我已經刪除了我的答案,因爲你的更友好。 –