6

コンパイル時にマクロに渡されるパラメーターの型を判別しようとしています。を使用すると機能するようです<:<が、使用すると機能しません=:=。理由はわかりません。誰かが私を正しい方向に向けることができますか? 以下にサンプルコードを含めました。

このマクロ:

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

object Macros {
  def say(param: Any): Unit = macro impl

  def impl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = {
    if (param.actualType.<:<(c.universe.typeOf[String])) {
      c.universe.reify { printf("string: %s\n", param.splice) }
    } else if (param.actualType.<:<(c.universe.typeOf[Int])) {
      c.universe.reify { printf("int: %d\n", param.splice) }
    } else {
      c.universe.reify { printf("any: %s\n", param.splice) }
    }
  }
}

このコードで呼び出されます:

object Test extends App {
  Macros.say("Hi")
  Macros.say(1)
  Macros.say(Blah)
}

case object Blah

戻り値:

string: Hi
int: 1
any: Blah

しかし、代わりに型の等価性 ( =:=) をチェックすると、マクロは次のように返します。

any: Hi
any: 1
any: Blah

どんな助けでも大歓迎です。

4

1 に答える 1

7

これは、 type of"Hi"が単なるStringではなく、より具体的な type -String("Hi")であるためです。つまり、この型には具体的な文字列リテラルを表す情報が含まれています。

リテラルでも同じ状況が発生します。1型はInt(1)だけではなく ですInt

widenメソッド onを使用しTypeて、定数値に関する情報を取り除くことができます。

object Macros {
  def say(param: Any): Unit = macro impl

  def impl(c: Context)(param: c.Expr[Any]): c.Expr[Unit] = {
    if (param.actualType.widen.=:=(c.universe.typeOf[String])) {
      c.universe.reify { printf("string: %s\n", param.splice) }
    } else if (param.actualType.widen.=:=(c.universe.typeOf[Int])) {
      c.universe.reify { printf("int: %d\n", param.splice) }
    } else {
      c.universe.reify { printf("any: %s\n", param.splice) }
    }
  }
}
于 2013-05-30T22:10:45.803 に答える