Scala中def和val之间的区别

时间:2018-03-07 04:41:59

标签: scala

循环定义如下:

 def loop : Boolean = loop

当x定义为:def x = loop时,控制台中会显示“x:Boolean”。

当x定义为:val x = loop时,它会进入无限循环

我知道def正在使用call-name,而val正在使用call by-value。尽管上面定义的关于循环的这一点并不十分清楚。

2 个答案:

答案 0 :(得分:4)

def并未评估作业的右侧。就像

def f(x : Int) = x + 2

没有(在这种情况下逻辑上不能)评估任何事情的f,只需定义函数f,意思是def loop : Boolean = loop和{{} 1}}评估任何东西。您只是定义了要在其他位置执行的函数。

def x = loop确实需要评估作业的右侧。所以val尝试在右侧执行表达式。但是,尝试评估val x = loop永远不会终止,因为loop是一个无限循环。

答案 1 :(得分:4)

在这种情况下,按姓名调用或按值调用的区别似乎不太有用,因为您的xloop都不会接受任何参数。

但是valdef有两种不同的方式。

第一个区别是:渴望与懒惰。

  • val
  • val的右侧被懒惰地评估,只要 <{1}}已访问

例如:

def

将打印:

def

因为def x = { println("x is evaluated"); 42 } val y = { println("y is evaluated"); 42 } x 会立即被评估,而y is evaluated x is evaluated 只会在我们调用它时进行评估。

另一个区别是计算结果是否被缓存:

  • y的值评估,然后缓存
  • x的值每次评估我们称之为函数

这就是为什么

val

将输出:

def

也就是说,def dice = { new scala.util.Random().nextInt(6) + 1 } val once = { new scala.util.Random().nextInt(6) + 1 } println(dice + " <-> " + once) println(dice + " <-> " + once) println(dice + " <-> " + once) println(dice + " <-> " + once) 是一个或多或少有用的随机数生成器,它生成值5 <-> 6 4 <-> 6 6 <-> 6 5 <-> 6 ,而dice是一个相当无用的随机值,一旦被修复就会被修复创建

现在,你可以想到一个2x2表在一个维度上具有eager-vs-lazy,而在另一个维度中则是cached-vs-not-cached:

  • 1-6 急切已缓存
  • once lazy 已缓存(因此已记住val s)
  • lazy val 懒惰未缓存
  • 实际上没有急切未缓存,因为计算某些内容然后立即将其丢弃并不是很有用。也许有一个非常接近的异常:程序的入口点,因为即使defdef,它总是被调用,所以从某种意义上说它们都是类似的 - 渴望和未加工的。

在您的代码中,def main本质上是非终止的尾递归版本

def

但由于loopdef loop: Boolean = { while (true) {}; true } ,因此是懒惰的,因此在定义时不会评估右侧。

如果您现在定义

loop

仍然没有发生任何事情,因为def也是懒惰的,所以再次没有评估右侧。

但是如果你定义

def x = loop

然后xval x = loop ,因此其右侧会被急切地评估。在定义的右侧,有一个x的调用。现在访问val,因为它是loop,它现在评估它的主体,并进入无限循环。