表达式求值策略(Evaluation Strategy)
Scala中所有的运算都是基于表达式的。
- Call By Value - 对函数实参求值,且仅求值一次;函数调用之前对所有表达式进行求值
- Call By Name - 函数实参每次在函数体内被用到时都会求值;函数形参类型以“=>”开头
进行函数设计和调用的过程中,要理解两者之间的差异,明白执行过程和期望的结果。
Scala通常使用“Call By Value”。
示例1:
object test { def test1(x: Int, y: Int): Int = x * x //> test1: (x: Int, y: Int)Int
def test2(x: => Int, y: => Int): Int = x * x //> test2: (x: => Int, y: => Int)Int test1(3 + 4, 8) //> res0: Int = 49
test2(3 + 4, 8) //> res1: Int = 49 test1(7, 2 * 4) //> res2: Int = 49
test2(7, 2 * 4) //> res3: Int = 49 }
过程解释:
test1(3 + 4, 8) 的过程:test1(3+4, 8) -->test1(7. 8) -->7*7 -->49
test2(3 + 4, 8) 的过程:test2(3+4, 8) -->(3+4)*(3+4) -->7*(3+4) -->7*7 -->49
test1(7, 2 * 4) 的过程:test1(7, 8) -->7*7 -->49
test2(7, 2 * 4)) 的过程:7*7 -->49
示例2:
object test { def bar(x: Int, y: => Int) = 1 //> bar: (x: Int, y: => Int)Int
def loop(): Int = loop //> loop: ()Int
bar(1, loop) //> res4: Int = 1
//bar(loop, 1) }
bar(1, loop) :
loop的返回值值传给call by name变量y,但y在函数体内没有被应用,loop没有运行和求值
bar(loop, 1) :
loop的返回值传给call by value的变量x,函数调用之前对所有表达式进行求值,由于loop是一个死循环,无法退出函数体,一直无法得到loop的返回值,从而导致此时不能正常调用bar函数