宏奇怪的动作(想要一个更好的标题) [英] Macro strange action (wanting a better title)

查看:84
本文介绍了宏奇怪的动作(想要一个更好的标题)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做一个枚举宏,它结束了具有奇怪的行为.

I've made an enum macro, which ended up having a strange behavior.

这是主要执行:

object Enum {
  def values[A]: Seq[A] = macro Impl.values[A]

  class Impl(val c: Context) {
    import c.universe._

    def values[A: c.WeakTypeTag]: c.Expr[A] = {
      val elemType = weakTypeOf[A]
      val elemSymbol = elemType.typeSymbol.asSealedClass
      val elemSymbols = elemSymbol.knownDirectSubclasses.toList
      val elemIdents = elemSymbols.map(s => Ident(s.asCaseClass.asModuleClass.module))
      val elemSeqSymbol = weakTypeOf[Seq[A]].typeSymbol
      c.Expr(Apply(Ident(elemSeqSymbol.companion), elemIdents))
    }

    implicit class SymbolOp(s: Symbol) {
      def asSealedClass = s.asClass.ensuring(_.isSealed, s"$s is not sealed")
      def asCaseClass = s.asClass.ensuring(_.isCaseClass, s"$s is not a case class")
      def asModuleClass = s.asClass.ensuring(_.isModuleClass, s"$s is not an object")
    }
  }
}

和这是测试:

object EnumTest extends App {
  sealed trait Foo
  case object Moo extends Foo
  case object Noo extends Foo

  val values = Enum.values[Foo]
  println(values)

  println(Enum.values[Foo])

  println({
    val v = Enum.values[Foo]
    v
  })
}

控制台应打印出三个相同的输出,但是:

The console should print out three same outputs, but:

List()
List(Moo, Noo)
List(Moo, Noo)

这会发生什么?你如何处理?点击 我将不胜感激,如果你可以在你的SBT测试: https://github.com/ryo0ka/enum

Wny does this happen? How do you deal with this?
I would appreciate if you can test it in your SBT: https://github.com/ryo0ka/enum

谢谢!

推荐答案

这的确是一个奇怪的现象,但是这是很难Scalac在这里做的工作:问题是,你使用嵌套对象.请考虑以下内容:

This is indeed a strange behavior, but it is hard for Scalac to do a good job here: The problem is that you use nested objects. Consider the following:

object EnumTest extends App {
  sealed trait Foo
  case object Moo extends Foo
  case object Noo extends Foo

  println(Enum.values[Foo])

  case object Bar extends Foo
}

此打印.如果我们移动语句之前,它打印如我们期望的那样.

This prints List(Moo, Noo). If we move Bar before the println statement, it prints List(Moo, Noo, Bar) as we would expect.

如果将密封的层次结构移出对象,则一切正常.

If we move the sealed hierarchy out of the object, everything works fine.

因此,似乎在定义案例类的位置进行宏化可能不是一个明智的主意.你可以把<4>本身也是宏(其实现调用右<6>).这大概会的工作.

Therefore, it seems it is probably not a smart idea to have the macro reify at the location where you define your case classes. You could make values itself a macro (whose implementation simply calls Impl.values with the right WeakTypeTag). That would probably work.

这篇关于宏奇怪的动作(想要一个更好的标题)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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