隐式宏.默认隐式值.如何? [英] Implicit macro. Default implicit value. How?

查看:98
本文介绍了隐式宏.默认隐式值.如何?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I don't even know how to ask the question.

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

I have a macro that creates an instance of IsEnum[T] for a type T.

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

I'm doing testing for it, and want to make sure that the implicit is not found for types that are not sealed, or that, in general, don't meet the requirements of an enum.

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

So I created this method for testing

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

然后确保enumOf[NotAnEnum] == null

但是,它在编译时失败.

But instead, it fails at compile time.

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

One thing is the macro erroring. Another thing is the macro just not applying for a given case. How to make that distinction when creating macros?

我用过c.abortc.error,它们都给我相同的结果.

I've used c.abort and c.error, both giving me the same results.

推荐答案

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

Sounds like you didn't make your macro materializing type class IsEnum whitebox. Normally implicit macros should be whitebox.

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

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

Runtime of macros is compile time of main code. If a blackbox macro (even implicit blackbox macro) throws an exception then it will be a compile error during compilation of main code. If a whitebox implicit macro throws an exception then during compilation of main code the implicit will be silently removed from candidates.

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

这篇关于隐式宏.默认隐式值.如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆