为什么类型相等失败,但类型一致性在此宏中成功?

Mat*_*rts 6 macros scala scala-macros

我正在尝试确定在编译时传递给宏的参数的类型.它似乎在我使用<:<时起作用,但在我使用时不起作用=:=.我不知道为什么.谁能指出我正确的方向?我在下面列出了示例代码.

这个宏:

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) }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

由此代码调用:

object Test extends App {
  Macros.say("Hi")
  Macros.say(1)
  Macros.say(Blah)
}

case object Blah
Run Code Online (Sandbox Code Playgroud)

返回:

string: Hi
int: 1
any: Blah
Run Code Online (Sandbox Code Playgroud)

但是,如果我检查类型equality(=:=)而不是宏返回:

any: Hi
any: 1
any: Blah
Run Code Online (Sandbox Code Playgroud)

任何帮助将非常感激.

ghi*_*hik 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) }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • +1,打败了我.值得注意的是,`Int(1)`被称为_singleton type_,即一个只有值为'1`的类型,而`=:=`将按预期的方式使用非文字参数(例如`val i = 1; Macros.say(i)`). (5认同)