宏奇怪的动作(想要一个更好的标题) [英] Macro strange action (wanting a better title)
问题描述
我做一个枚举宏,它结束了具有奇怪的行为.
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>本身也是宏(其实现调用
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屋!