Почему равенство типов терпит неудачу, но соответствие типов успешно выполняется в этом макросе?
Я пытаюсь определить тип параметра, переданного в макрос во время компиляции. Кажется, это работает, когда я использую <:<
но не тогда, когда я использую =:=
. Не знаю почему. Кто-нибудь может указать мне правильное направление? Я включил пример кода ниже.
этот макрос:
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) }
}
}
}