Scala 懒惰的人做什么?
我注意到Scala提供了Scala 懒惰的人做什么?,scala,lazy-evaluation,Scala,Lazy Evaluation,我注意到Scala提供了惰性VAL。但我不明白他们在做什么 scala> val x = 15 x: Int = 15 scala> lazy val y = 13 y: Int = <lazy> scala> x res0: Int = 15 scala> y res1: Int = 13 scala>valx=15 x:Int=15 scala>延迟值y=13 y:Int= scala>x res0:Int=15 scala>y res1:Int=
惰性VAL
。但我不明白他们在做什么
scala> val x = 15
x: Int = 15
scala> lazy val y = 13
y: Int = <lazy>
scala> x
res0: Int = 15
scala> y
res1: Int = 13
scala>valx=15
x:Int=15
scala>延迟值y=13
y:Int=
scala>x
res0:Int=15
scala>y
res1:Int=13
显示
y
是一个lazy val
,但它与正常的val
有何不同?它们之间的区别是,定义时执行val
,而第一次访问时执行lazy val
scala> val x = { println("x"); 15 }
x
x: Int = 15
scala> lazy val y = { println("y"); 13 }
y: Int = <lazy>
scala> x
res2: Int = 15
scala> y
y
res3: Int = 13
scala> y
res4: Int = 13
这里,当值x
和y
从未使用时,只会x
不必要地浪费资源。如果我们假设y
没有副作用,并且我们不知道它被访问的频率(从来没有,一次,数千次),那么将它声明为def
是没有用的,因为我们不想多次执行它
如果您想知道如何实现
惰性val
,请参见此。它们之间的区别是,定义时执行val
,而第一次访问时执行惰性val
scala> val x = { println("x"); 15 }
x
x: Int = 15
scala> lazy val y = { println("y"); 13 }
y: Int = <lazy>
scala> x
res2: Int = 15
scala> y
y
res3: Int = 13
scala> y
res4: Int = 13
这里,当值x
和y
从未使用时,只会x
不必要地浪费资源。如果我们假设y
没有副作用,并且我们不知道它被访问的频率(从来没有,一次,数千次),那么将它声明为def
是没有用的,因为我们不想多次执行它
如果您想知道如何实现
惰性VAL
,请参见此。此功能不仅有助于延迟昂贵的计算,而且对于构造相互依赖或循环结构也很有用。例如,这会导致堆栈溢出:
trait Foo { val foo: Foo }
case class Fee extends Foo { val foo = Faa() }
case class Faa extends Foo { val foo = Fee() }
println(Fee().foo)
//StackOverflowException
但是对于懒惰的VAL,它工作得很好
trait Foo { val foo: Foo }
case class Fee extends Foo { lazy val foo = Faa() }
case class Faa extends Foo { lazy val foo = Fee() }
println(Fee().foo)
//Faa()
此功能不仅有助于延迟昂贵的计算,而且有助于构造相互依赖或循环结构。例如,这会导致堆栈溢出:
trait Foo { val foo: Foo }
case class Fee extends Foo { val foo = Faa() }
case class Faa extends Foo { val foo = Fee() }
println(Fee().foo)
//StackOverflowException
但是对于懒惰的VAL,它工作得很好
trait Foo { val foo: Foo }
case class Fee extends Foo { lazy val foo = Faa() }
case class Faa extends Foo { lazy val foo = Fee() }
println(Fee().foo)
//Faa()
另外,
lazy
在没有循环依赖关系的情况下也很有用,如下代码所示:
abstract class X {
val x: String
println ("x is "+x.length)
}
object Y extends X { val x = "Hello" }
Y
访问Y
现在将抛出空指针异常,因为x
尚未初始化。
但是,以下方法可以很好地工作:
abstract class X {
val x: String
println ("x is "+x.length)
}
object Y extends X { lazy val x = "Hello" }
Y
编辑:以下内容也适用:
object Y extends { val x = "Hello" } with X
这被称为“早期初始值设定项”。有关更多详细信息,请参阅 还有
lazy
在没有循环依赖关系的情况下很有用,如下代码所示:
abstract class X {
val x: String
println ("x is "+x.length)
}
object Y extends X { val x = "Hello" }
Y
访问Y
现在将抛出空指针异常,因为x
尚未初始化。
但是,以下方法可以很好地工作:
abstract class X {
val x: String
println ("x is "+x.length)
}
object Y extends X { lazy val x = "Hello" }
Y
编辑:以下内容也适用:
object Y extends { val x = "Hello" } with X
这被称为“早期初始值设定项”。有关更多详细信息,请参阅 惰性val最容易理解为“(无arg)def” 与def一样,延迟val在被调用之前不会被计算。但结果会被保存,以便后续调用返回保存的值。记忆结果会占用数据结构中的空间,就像val一样 正如其他人所提到的,延迟val的用例是推迟昂贵的计算,直到需要它们时再存储它们的结果,并解决值之间的某些循环依赖关系 事实上,惰性VAL或多或少是作为已记忆的DEF实现的。您可以在此处阅读有关其实施的详细信息:
惰性val最容易理解为“(无arg)def” 与def一样,延迟val在被调用之前不会被计算。但结果会被保存,以便后续调用返回保存的值。记忆结果会占用数据结构中的空间,就像val一样 正如其他人所提到的,延迟val的用例是推迟昂贵的计算,直到需要它们时再存储它们的结果,并解决值之间的某些循环依赖关系 事实上,惰性VAL或多或少是作为已记忆的DEF实现的。您可以在此处阅读有关其实施的详细信息:
我知道答案已经给出,但我写了一个简单的例子,让像我这样的初学者更容易理解:
var x = { println("x"); 15 }
lazy val y = { println("y"); x + 1 }
println("-----")
x = 17
println("y is: " + y)
上述代码的输出为:
x
-----
y
y is: 18
可以看出,x在初始化时打印,但y在以相同方式初始化时不打印(我在这里故意将x作为var,以解释y何时初始化)。接下来,当调用y时,它将被初始化,最后一个“x”的值也将被考虑在内,而不是旧的值
希望这能有所帮助。我知道答案已经给出,但我写了一个简单的例子,以便于像我这样的初学者理解:
var x = { println("x"); 15 }
lazy val y = { println("y"); x + 1 }
println("-----")
x = 17
println("y is: " + y)
scala> lazy val lazyEight = {
| println("I am lazy !")
| 8
| }
lazyEight: Int = <lazy>
scala> lazyEight
I am lazy !
res1: Int = 8
上述代码的输出为:
x
-----
y
y is: 18
可以看出,x在初始化时打印,但y在以相同方式初始化时不打印(我在这里故意将x作为var,以解释y何时初始化)。接下来,当调用y时,它将被初始化,最后一个“x”的值也将被考虑在内,而不是旧的值
希望这有帮助。scala>lazy val lazyweight={
scala> lazy val lazyEight = {
| println("I am lazy !")
| 8
| }
lazyEight: Int = <lazy>
scala> lazyEight
I am lazy !
res1: Int = 8
|println(“我很懒!”)
| 8
| }
懒散的人:Int=
斯卡拉>懒汉
我很懒!
res1:Int=8
- 所有VAL都在对象构造期间初始化
- 使用lazy关键字将初始化延迟到第一次使用
- 注意:延迟VAL不是最终版本,因此可能会显示性能缺陷
scala>lazy val lazyweight={
|println(“我很懒!”)
| 8
| }
懒散的人:Int=
斯卡拉>懒汉
我很懒!
res1:Int=8
- 所有VAL都在对象构造期间初始化
- 使用lazy关键字将初始化延迟到第一次使用
- 注意:延迟VAL不是最终版本,因此可能会显示性能缺陷
//编译器说这是