【问题标题】:Can I check whether a lazy val has been evaluated in Scala?我可以检查是否在 Scala 中评估了惰性 val 吗?
【发布时间】:2011-04-16 07:34:21
【问题描述】:

例如,在toString 方法中,我想提供有关类的惰性val 成员是否已评估的信息,如果是,则打印其值。这可能吗?

【问题讨论】:

  • 我害怕这样的回答“没有 API,但你可以使用 Java 反射以某种方式手动测试它……”
  • 有。每个懒惰的 member (不同于局部变量)都有一个带有时髦名称的支持字段,它实际上保存了该值,我认为另一个来确定“如果评估”。虽然不确定确切的细节/命名规则。听起来像是一个“有趣”的要求。
  • 与“懒惰的成员”打交道总是有问题
  • github.com/scala/scala/blob/master/src/compiler/scala/tools/nsc/… 是完成这项工作的代码。因此,您对skirhiro4chawon 的anwser 的评论是正确的:您需要知道惰性值的顺序才能正确检查位图的值。
  • 当然,它总是可以通过编译器插件来完成。

标签: scala lazy-evaluation


【解决方案1】:

据我所知,你不能。但是您可以提供帮助:

  class A {
    var isMemberSet = false
    lazy val member = { isMemberSet = true; 8 }
  }

  val a = new A
  a.isMemberSet // false
  a.member // 8
  a.isMemberSet // true

当然,可见性和访问修饰符必须进行调整。

【讨论】:

  • +1 不错,但它复制了编译器生成的“运行时”所做的工作,我试图直接访问它。
【解决方案2】:

如果您想直接访问编译器生成的字段,请尝试以下代码。

import java.lang.reflect._

class A {
  lazy val member = 42
  def isEvaluated = 
    (1 & getClass.getField("bitmap$0").get(this).asInstanceOf[Int]) == 1
}

val a = new A
println(a.isEvaluated) // => true
println(a.member)
println(a.isEvaluated) // => false

【讨论】:

  • ……而且,有趣的是,测试第二个惰性 val 的神奇常数不是 2 而是 4 :-) 重新排序成员并观察它分解……谁知道呢,改变类层次结构,并且由于父母中惰性 val 数量的变化而中断?
  • 它既美味又令人厌恶,为此,你应该受到表扬或责备。
【解决方案3】:

我还发现检查惰性值是否确实在某些棘手的情况下进行了评估很有用。
这是一个你可以使用的通用类:

class ExtraLazy[T](notYetEvaluatedValue: => T) {
  var isSet = false;
  lazy val value: T = {
    Logger("lazy value being evaluated");
    isSet = true;
    notYetEvaluatedValue;
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 2014-02-08
    相关资源
    最近更新 更多