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