何时在Scala中使用延迟值?

Łuk*_*ski 10 java jvm scala

为什么Scala引入了惰性参数.它不应该由JVM管理(对于用户是不可见的)如何初始化值?什么是真实世界的用例,值得将控件交给开发人员并将值定义为惰性?

Ed *_*aub 9

一种常见的情况是,类的编写者不知道是否将使用昂贵的初始化val.在这种情况下,val按需初始化.

另一种情况是有机地控制初始化的排序.通常,在特定val初始化之前很久就会创建一个对象,因为其他类尚未初始化.在这种情况下,懒惰提供了一种方便的方法,可以自然地进行这种测序,而无需作者提出一个对复杂的多相初始化进行排序的主计划.


axe*_*l22 9

名字参数:主要动机之一是支持dsls.它们允许您在API中使用非常好的语法,几乎感觉它们就像是内置于语言中一样.例如,您可以非常轻松地定义自己的custom repeat-loop:

def repeat(body: =>Unit)(until: =>Boolean): Unit = {
  body
  if (until) {} else repeat(body)(until)
}
Run Code Online (Sandbox Code Playgroud)

然后使用它就好像它是语言的一部分.

var i = 0
repeat {
  println(i)
  i += 1
} (i < 3)
Run Code Online (Sandbox Code Playgroud)

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

lazy -动机这里有:

  1. 懒惰的数据结构,如Streams,在函数式语言中很流行,可用于实现高效的数据结构a-la Okasaki的功能队列.
  2. 如果它们从未在某些对象中使​​用过,例如文件句柄或数据库连接,则避免分配或初始化一些昂贵的资源.
  3. 对于由许多mixins组成的对象,以正确的顺序初始化对象字段.
  4. 当有许多线程共享一个值时,实现正确的"只初始化一次"语义(参见这里的介绍).
  5. 有嵌套单例对象的翻译方案:

class A { object B }

变成这样的东西:

class A {
  class A$B$
  lazy val B = new A$B$
}
Run Code Online (Sandbox Code Playgroud)


om-*_*nom 5

TLDR:因为它会吓跑用户并且由于性能原因

当今大多数语言都渴望。其中一些不是,他们称为懒惰。尽管可以通过惰性评估以美观而简洁的方式表达许多编程问题,但我认为绝对惰性不是一个好主意。从主观的角度来看,程序员习惯于以一种热切的方式思考(特别是那些来自命令式领域的人),如此幼稚的用Haskell编写的程序可能会使您感到困惑。只为每个可能的菜只提供叉子并不如在叉子和汤匙之间进行选择那样好,尽管scala支持语言级别的惰性评估,但默认情况下它渴望模型。原因(除了Martin和其他语言设计师的个人选择)是Java和Scala之间的互操作-用一种语言组合这两个世界将是一场噩梦。此外,在Scala设计之时,JVM尚不支持或多或少地支持此类功能。只有在Java 7中引入了方法句柄(才两年,而scala已经存在了十年),才使高性能的惰性val成为可能。