6

我试图确定在编译时传递给宏的参数类型。它似乎在我使用时有效,<:<但在我使用时无效=:=。我不确定为什么。谁能指出我正确的方向?我在下面包含了示例代码。

这个宏:

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

任何帮助将非常感激。

4

1 回答 1

7

那是因为 type of"Hi"不只是String,它是更具体的 type - String("Hi"),这意味着这个类型包含它代表具体字符串文字的信息。

文字也会出现同样的情况1——它的类型是Int(1),而不仅仅是Int

您可以使用widen方法 onType去除有关常量值的信息:

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) }
    }
  }
}
于 2013-05-30T22:10:45.803 回答