我正在尝试确定在编译时传递给宏的参数的类型。它似乎在我使用<:<
时有用,但在我使用=:=
时则无效。我不知道为什么。谁能指出我正确的方向?我在下面列出了示例代码。
这个宏:
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
非常感谢任何帮助。
答案 0 :(得分:7)
这是因为"Hi"
的类型不仅仅是String
,而是更具体的类型 - String("Hi")
,这意味着此类型包含表示具体字符串文字的信息。
文字1
也会出现同样的情况 - 它的类型为Int(1)
,而不只是Int
。
您可以在widen
上使用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) }
}
}
}