Почему равенство типов терпит неудачу, но соответствие типов успешно выполняется в этом макросе?
Я пытаюсь определить тип параметра, переданного в макрос во время компиляции. Кажется, это работает, когда я использую <:< но не тогда, когда я использую =:=. Не знаю почему. Кто-нибудь может указать мне правильное направление? Я включил пример кода ниже.
этот макрос:
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: %sn", param.splice) }
} else if (param.actualType.<:<(c.universe.typeOf[Int])) {
c.universe.reify { printf("int: %dn", param.splice) }
} else {
c.universe.reify { printf("any: %sn", 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
любая помощь была бы очень признательна.
1 ответов
это потому, что типа "Hi" не только String, это более конкретный тип - String("Hi"), что означает, что этот тип содержит информацию о том, что он представляет конкретный строковый литерал.
та же ситуация происходит с literal - это 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) }
}
}
}