val和def的區別
在scala中,可以用val和def前綴來定義變量,例如:
val x = 1
def y = “foo”
這兩者的區別在于:
- val定義值時,會做call-by-value操作,
- def則會做call-by-name操作。
例如:
// 這是一個死循環
def loop: Boolean = loop
// 用val定義時會做call-by-value,以下語句會block住
val x = loop
// 用def定義時,是做的call-by-name。故以下語句暫時不會執行,在用到y的時候才做evaluation
def y = loop
陷到loop里時,用ctrl+c發中斷信號終止。
函數定義中的call-by-name和call-by-value
首先思考一個問題,如何在不使用”||”和“&&”的情況下,實現如下兩個函數and和or:
and(x, y) == x && y
or(x, y) == x || y
對于and,可以用如下方式定義:
def and(x: Boolean, y: Boolean) =
if (x) y else false
// 測試
and(true, true) // => true
and(false, true) // => false
但是,這種定義在遇上循環的時候會有問題,例如
and(false, loop)
上述語句會陷入循環,因為在我們的定義中,對于x和y參數的引用都是call-by-value的。要指定參數為call-by-name,只需要把函數定義改為如下形式即可:
def and(x: Boolean, y: => Boolean) =
if (x) y else false
// 測試
and(false, loop) // => false
注意我們在定義參數y的時候,使用的=>
符號。