scala - 在 Scala 中自动初始化对象

标签 scala annotations scala-macros

如果您运行这个简单的代码,您将看到以下内容:

object A {
  println("from A")
  var x = 0
}

object B {
  println("from B")
  A.x = 1
}

object Test extends App {
  println(A.x)
}

// Result:
// from A
// 0

你可以猜到,scala 会延迟初始化对象。对象 B 未初始化,并且未按预期工作。我的问题是:什么 技巧我可以用来初始化对象 B 而不访问它吗?我可以使用的第一个技巧是使用某些特征扩展对象并使用反射来初始化扩展特定特征的对象。我认为更优雅的方法是使用宏注释来注释对象:
@init
object B {
  println("from B")
  A.x = 1
}

class init extends StaticAnnotation {
  def macroTransform(annottees: Any*) = macro init.impl
}

object init {
  def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    // what should i do here ?
  }
}

但我有点困惑。如何从宏 impl 中的带注释的对象调用方法(为了初始化)方法 ?

最佳答案

我找到了解决方案:

用法:

object A {
  println("from A")
  var x = 0
}

@init
object B {
  println("from B")
  A.x = 1
}

@init
object C {
  println("from C")
  A.x = 2
}

object Test extends App {
  init()
  println(A.x)
}

输出:
from B
from A
from C
2

宏实现:
class init extends StaticAnnotation {
  def macroTransform(annottees: Any*) = macro init.impl
}

object init {
  private val objFullNames = new mutable.MutableList[String]()

  def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    annottees.map(_.tree).toList match {
      case (obj: ModuleDef) :: Nil =>
        objFullNames += c.typecheck(obj).symbol.fullName
      case _ =>
        c.error(c.enclosingPosition, "@init annotation supports only objects")
    }

    annottees.head
  }

  def apply() = macro runImpl

  def runImpl(c: whitebox.Context)(): c.Expr[Any] = {
    import c.universe._
    val expr = objFullNames.map(name => q"${c.parse(name)}.##").toList
    val res = q"{..$expr}"
    c.Expr(res)
  }
}

关于scala - 在 Scala 中自动初始化对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31777514/

相关文章:

scala - 是否可以在 Intellij IDEA Scala 插件中知道应用了哪种隐式转换?

scala - Akka - 是否有可能在 Actor 的主管中收到有关它失败的消息?

scala - 尝试使用 MMLSpark 的 scala LIME 库解释模型时出现异常

java - @Override 注释在 Java 中如何工作?

Java EJB 在运行时修改计划属性值

scala - 需要宏 : found: singleton type with underlying type A, 的奇怪类型不匹配:A

scala - 在 Scala 宏中,如何从 WeakTypeTag 中检索完整类型信息?

exception - 并发程序中具有不可变 Map 的 Scala 错误?

python - 在 Python 中键入没有赋值的提示

scala - 测试 c.universe.Type 是否可分配给宏中的另一种类型