Scala编译器不会计算方法,它只会确定其参数和返回类型。Scala 编译器评估赋值。
我基于对以下陈述的评估来构建这些陈述:
//create a function which accepts two int parameters and returns their sum
def f(a: Int, b: Int) = a + b //> f: (a: Int, b: Int)Int
//create a function which returns the sum of 1+2
def fh = f(1, 2) //> fh: => Int
//The use of val forces the function 'f' to be evaluated :
val vh = f(1, 2) //> vh : Int = 3
让我们看一下以下控制台输出:
scala> def f(a:Int, b:Int) = {
| println("f called...")
| a+b
| }
f: (a: Int, b: Int)Int
scala> f(1,2)
f called...
res4: Int = 3
我稍微修改了函数定义。现在当我们调用 f
时,它将打印出f called...
scala> def fh = f(1,2)
fh: Int
scala> fh
f called...
res5: Int = 3
当您键入fh
并按 输入 键, fh
,即执行f(1,2)
。您可以看到f called...
打印在控制台上。每当评估fh
时,屏幕上都会出现f called...
。
scala> val vh = f(1,2)
f called...
vh: Int = 3
scala> vh
res6: Int = 3
当您键入 vh
时,它不会打印出消息。有什么区别? fh
只是f(1,2)
的别名,它将在评估fh
时调用f
。另一方面,vh
只是一个用 f(1,2)
的结果初始化的值。
简而言之:
- 每次访问
def
时都会对其进行评估 -
val
仅在第一次遇到时进行评估 - 还有第三种类型的声明,
lazy val
,仅在第一次使用时进行评估 - 如果它没有抛出异常,否则将重新计算
最后一点并不广为人知,因为大多数人认为无论例外情况如何,lazy val
第一次才进行评估。以下示例对此进行了演示:
scala> var n = 1
n: Int = 1
scala> lazy val x = if (n == 1) sys.error("Not Ready") else 42
x: Int = <lazy>
scala> x
java.lang.RuntimeException: Not Ready
...
scala> n = 0
n: Int = 0
scala> x
res1: Int = 42
scala> n = 1
n: Int = 1
scala> x
res2: Int = 42