call by name vs. call by value
假设现在需要在Scala实现一个断言函数,我们该怎么做呢?可能第一反应是下面的代码:
> val assertionEnabled = true
>
> def myAssert(predicate: Boolean) =
> if (assertionEnabled && !predicate)
> throw new AssertionError
简单来说,就是我们期望传入一个bool值,然后检查它,比如:myAssert(5 > 3)。看起来很完美,至少一眼看下去简单得无法挑剔。但是,有一个重大问题是:无论断言是否被打开,predicate都会被计算一次。如果写成myAssert(foo(x,y)),则foo(x,y)会被执行一次 -- 虽然接下来因为&&是个短路操作符,myAssert()并不检查该函数的执行结果。这叫call-by-value[1],就是说参数传递给函数之前会先计算出其结果。
Scala除了支持C家族中的call-by-value外还支持call-by-name,代码改动很简单:
-- def myAssert(predicate: Boolean) =
++ def myAssert(predicate: => Boolean) =
我这样,predicate将会在myAssert中求值,而非传入时求值。C程序员会认为 "x = 1"是个赋值语句,而对习惯于FP思维的程序员来说,他们可能倾向另一种解释:x只是个name(label),但它绑定了一个类型为整型的数值1(或者x是个返回整数1的函数)。
参考:
[1] Evaluation Strategy,http://en.wikipedia.org/wiki/Evaluation_strategy
标签: scala
0 Comments:
发表评论
<< Home