Почему равенство типов терпит неудачу, а соответствие типов в этом макросе оказывается успешным?

Я пытаюсь определить тип параметра, передаваемого в макрос во время компиляции. Кажется, работает, когда я использую <:< но не когда я использую =:=, Я не уверен почему. Может кто-то указать мне верное направление? Я включил пример кода ниже.

Этот макрос:

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) }
    }
  }
}
Другие вопросы по тегам