2016-07-25 9 views
0

シンプルなタイプのビルダーをscalaでコーディングしたいと思います。とにかく、タイプビルダーそれは魅力のように自己作品。 typebuilderの抽象クラスをチェックしたいと思います。抽象型をチェックする際に奇妙なマクロの振る舞いがありますか?

ランタイムではそのための問題はありません。

if (classSymbol.isAbstract) throw new IllegalArgumentException("Provided class is abstract") 

私はTypeTag属性を持つメソッドをタグ付けするので、Scalaはコンパイル時間を消去しないでください。

def createInstance[T: TypeTag]: T 

とにかくこれは動作しています。私はこの方法を好むわけではないので、ユーザーは抽象クラスを入力してそれを作成することができます。私は実行時に引数の例外をチェックしたくありません。

コンパイル時間の間、正しいタイプをチェックするのは本当にクールだと思いました。「クラスでなければなりません」私はこのマクロを使用Evertime、私はアボートメッセージを取得

object ClassCheckMacro { 

    def checkClass[T](x: T): T = macro checkClassImpl[T] 

    def checkClassImpl[T: c.WeakTypeTag](c: blackbox.Context)(x: c.Tree) = { 
    import c.universe._ 
    val symbol = weakTypeOf[T].typeSymbol 
    if (symbol.isAbstract) { 
     c.abort(c.enclosingPosition, s"${symbol.fullName} must be a class") 
    } else { 
     c.Expr(q"($x)") 
    } 
    } 
} 

: これはマクロ関数の完全なコードです。 クラスか抽象タイプかは関係ありません。 使用法:

val typeInfo = typeOf[T] 
    val classSymbol = typeInfo.typeSymbol.asClass 
    ClassCheckMacro.checkClass(classSymbol) 

は、この "奇妙な" 行動のための任意のヒントがありますか?

+0

あなたは '' checkClass(新しいC)を意図していましたか? –

+0

うん、何かある。 'new C'の場合は、typeSymbolを入れなければなりません。ジェネリック型の新しいインスタンスを作成できないからです; –

+0

あなたはそれを呼び出す方法を誤解していると思います。 'class C'が与えられた場合、' checkClass [C](null) 'を試してみてください。 –

答えて

0

xは単なる値です。 Windowsの10に作業ノートPCをアップグレードの途中で

$ scalam -language:_ 
Welcome to Scala 2.12.0-M5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92). 
Type in expressions for evaluation. Or try :help. 

scala> import reflect.macros._ 
import reflect.macros._ 

scala> def checkClassImpl[T: c.WeakTypeTag](c: blackbox.Context)(x: c.Tree) = { 
    |  import c.universe._ 
    |  val symbol = weakTypeOf[T].typeSymbol 
    |  if (symbol.isAbstract) { 
    |   c.abort(c.enclosingPosition, s"${symbol.fullName} must be a class") 
    |  } else { 
    |   c.Expr(q"($x)") 
    |  } 
    | } 
checkClassImpl: [T](c: scala.reflect.macros.blackbox.Context)(x: c.Tree)(implicit evidence$1: c.WeakTypeTag[T])c.Expr[T] 

scala> def checkClass[T](x: T): T = macro checkClassImpl[T] 
defined term macro checkClass: [T](x: T)T 

scala> class C 
defined class C 

scala> checkClass[C](null) 
res0: C = null 

scala> abstract class K 
defined class K 

scala> checkClass[K](null) 
<console>:17: error: K must be a class 
     checkClass[K](null) 
        ^

...

+0

うん、パラメータは静かな無用です。以前はパラメータなしで試してみましたが、マクロ実装でこれが正しいクラスを取得するために必要と思っていました。私はこのプロジェクトをスカラー "2.12.0-M5"にアップデートしましたが、同じ問題が再び発生しました。とにかくあなたの答えをどうもありがとう... :) –