scala def/val/lazy val区别以及call-by-name和call-by-value

Posted TXFSheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala def/val/lazy val区别以及call-by-name和call-by-value相关的知识,希望对你有一定的参考价值。

scala 学习

参考链接:https://blog.csdn.net/qq_29343201/article/details/56281777

scala def/val/lazy val区别以及call-by-name和call-by-value

关于def/val/lazy val

def

def类似于每一次重新赋值,如果是用def定义函数,则是每一次重新获得一个函数

val

获得一次,并立即执行(严格执行)

lazy val

惰性执行,也就是赋值(绑定)的时候先不会执行,等到需要的时候再执行

实验

scala> def f = {println("hello"); 1.0}
f: Double

scala> f
hello
res3: Double = 1.0

scala> f
hello
res4: Double = 1.0

scala> f
hello
res5: Double = 1.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

这里使用的是def,则每一次获取一个新的,也就是每一次我使用f的时候,都会获得一个{ println(“hello”); 1.0},其值为1,但是中间过程会打印出hello,这是在赋值(绑定)的时候才会打印出来的,而使用def,则会每一次都打印出来

scala> val f = { println("hello"); 1.0}
hello
f: Double = 1.0

scala> f
res6: Double = 1.0

scala> f
res7: Double = 1.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这里使用val,则只有一次绑定,所以后面不再打印出hello

scala> lazy val f = { println("hello"); 1.0}
f: Double = <lazy>

scala> f
hello
res8: Double = 1.0

scala> f
res9: Double = 1.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

这里使用的是lazy val,即为延迟执行的,可以看到在进行绑定的时候并没有打印出hello,也看不到其值,是因为现在还没有使用这个值,只是定义了这个值,在第二次进行使用的时候则会类似于val,第一次会打印出hello,之后就不再打印出了

call-by-name和call-by-value

scala的函数参数有两种情况,一种为by-value一种为by-name

call-by-value

默认情况的函数调用的参数为call-by-value, 
比如:

def callByValue(x: Int) = {
  println("x1=" + x)
  println("x2=" + x)
}
  • 1
  • 2
  • 3
  • 4

这种情况是默认的,也是显然的,就是call by value,翻译为按值传递,就是把具体的值传入x

call-by-name

按名传递,即将参数的“名字”传入,在不使用到的时候不提出他的值,类似于一种延迟执行 
比如:

def callByName(x: =>Int) = {
  println("x1=" + x)
  println("x2=" + x)
}
  • 1
  • 2
  • 3
  • 4

这样的写法就是call-by-name

区别

假设有一个函数,为func():

def func() = {
//这个函数有副作用,除了返回值还会打印出hello
  println("hello")
  1
}
  • 1
  • 2
  • 3
  • 4
  • 5

分别调用之前的两个函数:

callByValue(func())
这种情况,func会先执行,也就会先打印出hello一次,然后将返回的直接传入作为参数
callByName(func())
这种情况,func不会先执行,而是会整个代入(按名字传入)这个函数,在使用到的时候,也就是两次打印出x的时候再调用,这样就会出现两次hello了
  • 1
  • 2
  • 3
  • 4

总结

def 和 val的关系其实就是call-by-name和call-by-value的关系,def对应的是by-name,val对应的是by-value

 

以上是关于scala def/val/lazy val区别以及call-by-name和call-by-value的主要内容,如果未能解决你的问题,请参考以下文章

在Scala 中 val 与 var 的区别(言简意赅 小白易懂 实例代码)

Scala 编程语言:b/w 的区别是啥:1) Var 不可变映射、Val 可变映射和 Var 可变映射? [复制]

Scala面试题总结

Scala面试题汇总

Scala 中 val 可变与 var 不可变

Scala函数和方法的区别浅析