首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala中的`def` vs `val` vs ` `lazy val`求值

Scala中的`def` vs `val` vs ` `lazy val`求值
EN

Stack Overflow用户
提问于 2012-02-26 08:36:34
回答 8查看 23.5K关注 0票数 71

我的理解对吗?

每次获得

  • def时都会对其求值,一旦获得accessed
  • lazy val,就会对其求值。一旦进入执行作用域,就会对accessed
  • val进行求值-
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2012-02-26 08:45:06

是的,但对于第三个语句,我会说“当该语句被执行时”,因为,例如:

代码语言:javascript
复制
def foo() {
    new {
        val a: Any = sys.error("b is " + b)
        val b: Any = sys.error("a is " + a)
    }
}

这就给了"b is null"b不会被计算,它的错误也不会抛出。但一旦控制进入块,它就在作用域内。

票数 50
EN

Stack Overflow用户

发布于 2012-02-26 11:00:44

是的,但是有一个很好的技巧:如果你有一个懒惰的值,在第一次求值时它会得到一个异常,下一次你试图访问它时,它会尝试重新求值。

下面是一个例子:

代码语言:javascript
复制
scala> import io.Source
import io.Source

scala> class Test {
     | lazy val foo = Source.fromFile("./bar.txt").getLines
     | }
defined class Test

scala> val baz = new Test
baz: Test = Test@ea5d87

//right now there is no bar.txt

scala> baz.foo
java.io.FileNotFoundException: ./bar.txt (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:137)
...

// now I've created empty file named bar.txt
// class instance is the same

scala> baz.foo
res2: Iterator[String] = empty iterator
票数 93
EN

Stack Overflow用户

发布于 2016-01-03 18:19:14

我想通过我在REPL.I中执行的例子来解释这些差异,我相信这个简单的例子更容易掌握,并解释了概念上的差异。

在这里,我创建了一个val result1、一个lazy val result2和一个def result3,它们都有一个类型字符串。

A)。val

代码语言:javascript
复制
scala> val result1 = {println("hello val"); "returns val"}
hello val
result1: String = returns val

在这里,因为已经计算了result1的值,所以执行了println。因此,现在result1将始终引用它的值,即“return val”。

代码语言:javascript
复制
scala> result1
res0: String = returns val

现在,您可以看到result1现在引用了它的值。注意,这里不执行println语句,因为在第一次执行时已经计算了result1的值。因此,从现在开始,result1将始终返回相同的值,并且再也不会执行println语句,因为已经执行了获取result1的值的计算。

B)。惰性val

代码语言:javascript
复制
scala> lazy val result2 = {println("hello lazy val"); "returns lazy val"}
result2: String = <lazy>

正如我们在这里看到的,println语句没有在这里执行,也没有计算值。这就是懒惰的本质。

现在,当我第一次引用result2时,将执行println语句,并计算和赋值。

代码语言:javascript
复制
scala> result2
hello lazy val
res1: String = returns lazy val

现在,当我再次引用result2时,这一次,我们将只看到它持有的值,并且不会执行println语句。从现在开始,result2将简单地表现为val,并始终返回其缓存值。

代码语言:javascript
复制
scala> result2
res2: String = returns lazy val

C)。定义

在def的情况下,每次调用result3时都必须计算结果。这也是我们在scala中将方法定义为def的主要原因,因为每次在程序中调用方法时,方法都必须计算并返回一个值。

代码语言:javascript
复制
scala> def result3 = {println("hello def"); "returns def"}
result3: String

scala> result3
hello def
res3: String = returns def

scala> result3
hello def
res4: String = returns def
票数 41
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9449474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档