何时在 Scala 中使用惰性值?

2022-09-04 06:42:19

为什么 Scala 引入了惰性参数。它不应该由JVM(对用户不可见)如何初始化值来管理吗?在现实世界的用例中,值得将控制权交给开发人员并将值定义为懒惰?


答案 1

按名称参数:主要动机之一是支持 dsls。它们允许你在API中有一个非常好的语法,几乎感觉它们被内置到语言中。例如,您可以非常轻松地定义自己的自定义 -loop:repeat

def repeat(body: =>Unit)(until: =>Boolean): Unit = {
  body
  if (until) {} else repeat(body)(until)
}

然后使用它,就好像它是语言的一部分一样。

var i = 0
repeat {
  println(i)
  i += 1
} (i < 3)

或者,您也可以类似地生成一个如下的新线程:,或者您可以像这样对您的 s 进行自动资源管理:。spawn { println("on the new thread!") }FileInputStreamwithFile("/home/john/.bashrc") { println(_.contents) }

懒惰的价值观 - 这里的动机是:

  1. 懒惰的数据结构,如Stream在函数式语言中很受欢迎,可用于实现高效的数据结构a-la Okasaki的函数队列。
  2. 以避免分配或初始化一些昂贵的资源,如果它们从未在某些对象中使用,例如文件句柄或数据库连接。
  3. 正确的顺序初始化对象字段,对于由许多 mixin 组成的对象。
  4. 当有许多线程共享一个值时,实现正确的“仅初始化一次”语义(请参阅此处的介绍)。
  5. 为嵌套的单例对象提供转换方案:

class A { object B }

变成类似的东西:

class A {
  class A$B$
  lazy val B = new A$B$
}

答案 2

一种常见的情况是,当类的编写者不知道是否将使用成本高昂的初始化时。在这种情况下,将按需初始化 。valval

另一种情况是有机地控制初始化的排序。通常,在初始化特定对象之前很久就创建了对象,因为其他类尚未初始化。在这种情况下,懒惰为这种测序自然发生提供了一种方便的方式,而无需作者提出对复杂的多阶段初始化进行排序的总体规划。val


推荐