在上一堂课中,我们共同探索了一个非常正规有条理的表达式求值模式——“转换模型”的表达式求值。我们发现有多种方式去实现表达式的求值,我们并一起探讨了call by name和call by value这两种求值策略。在这堂课里,我们进一步探讨两种求值策略的不同,特别是在两种求值策略影响最终值的方面,会做深入的学习和探讨。
如果看看上节课中咱们比较的call by name 和 call by value以及他们如何影响到最终值,我们就会发现,在最后的那个例子中,call-by-name 和 call-by-value 两种策略在得到最终值之前最终都转化成了拥有相同值的表达式。但是,如果函数返回不被保障会是怎样呢?如果函数不返回呢?在上一节课中的练习中,我们发现确实有些例子在有限的步骤中没有得到一个值,因此,我们有一个非常重要理论:
1、如果call-by-value以表达式e 为终结(意思是不是loop),那么,call-by-name也将会以表达式e结尾
2、其他反向都是不正确的。
因此call-by-name的最终值不能说明call-by-value的最终值,下面,我们来看一个例子:
“找到一个以call-by-name下不以call-by-value的最终值?”
好的,让我们来找一下例子。 我们首先定义一个函数:
def first(x:Int, y:Int) = x
然后考虑一下表达式 first(1, loop)
以call-by-name的方式:first(1, loop) ==> 1
以call-by-value的方式:first(1, loop) ==> loop
在Scala中,通常情况下用的是call-by-value。
但是如果有一个函数的参数加了“=>” 来写,说明它用的是call-by-name。
例如:
def constOne(x:Int, y:=> Int) = 1
让我们来追踪一下 constOne(1+2, loop) 和 constOne(loop, 1+2)
constOne(1+2, loop) ==> constOne(3, loop) ==> 1
constOne(loop, 1+2) ==> constOne(loop, 1+2) (循环下去)
视频地址:https://www.coursera.org/learn/progfun1/lecture/eervR/lecture-1-3-evaluation-strategies-and-termination