隐式宏默认隐式值怎么样?

问题描述

我什至不知道怎么问这个问题。

我有一个宏,它为类型IsEnum[T]创建T的实例。

我正在对此进行测试,并希望确保未密封的类型或通常不满足枚举要求的类型没有找到隐式。

所以我创建了这种测试方法

    def enumOf[T](implicit isEnum:IsEnum[T] = null) = isEnum

然后确保enumOf[NotAnEnum] == null

但是,它在编译时失败。

一件事是宏错误。另一件事是宏仅不适用给定情况。创建宏时如何区分?

编辑:我使用过c.abortc.error,它们都给我相同的结果。

解决方法

听起来好像您没有将宏实现类型的类IsEnum放入白盒。通常,隐式宏应该是白盒。

import scala.language.experimental.macros
import scala.reflect.macros.whitebox

trait IsEnum[T]
object IsEnum {
  implicit def mkIsEnum[T]: IsEnum[T] = macro mkIsEnumImpl[T]
  def mkIsEnumImpl[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
    import c.universe._
    val typ = weakTypeOf[T]
    val classSymbol = typ.typeSymbol.asClass
    if (!classSymbol.isTrait || !classSymbol.isSealed) c.abort(c.enclosingPosition,s"$typ must be sealed trait")
    val symbols = classSymbol.knownDirectSubclasses
    symbols.collectFirst {
      case symbol if !symbol.isModuleClass || !symbol.asClass.isCaseClass =>
        c.abort(c.enclosingPosition,s"${symbol.asClass.toType} must be case object")
    }
    q"new IsEnum[$typ] {}"
  }
}

def enumOf[T](implicit isEnum: IsEnum[T] = null) = isEnum

用法:

sealed trait A
object A {
  case object B extends A
  case object C extends A
  case class D() extends A
}
enumOf[A] //null

sealed trait A
object A {
  case object B extends A
  case object C extends A
  class D extends A
}
enumOf[A] //null

sealed trait A
object A {
  case object B extends A
  object C extends A
}
enumOf[A] //null

trait A
object A {
  case object B extends A
  case object C extends A
}
enumOf[A] //null

sealed trait A
object A {
  case object B extends A
  case object C extends A
}
enumOf[A] //App$$anon$1@47f37ef1

宏的运行时是主代码的编译时间。如果黑盒宏(甚至是隐式黑盒宏)抛出异常,则在编译主代码期间它将是编译错误。如果白盒隐式宏抛出异常,则在编译主代码期间,该隐式宏将被静静地从候选者中删除。

https://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...