Short-circuit evaluation
最早是在php中接触到的这种求值,后来在学习Lisp中又一次接触到了,于是想写一篇文章记录一下,并分享一下,这个被我忽略的可能可以说是细节的点吧
Short-circuit evaluation, minimal evaluation, or McCarthy evaluation (after John McCarthy) is the semantics of some Boolean operators in some programming languages in which the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND function evaluates to false, the overall value must be false; and when the first argument of the OR function
evaluates to true, the overall value must be true.
概况来说就是在求布尔表达式的时候程序并不会执行全部的Expression
比如AND或者OR操作时如果后面第一个Expression为True,那么之后的Expression就不会再求值了。
int denom = 0;
if (denom != 0 && num / denom)
{
... // ensures that calculating num/denom never results in divide-by-zero error
}
int a = 0;
if (a != 0 && myfunc(b))
{
do_something();
}
在这个例子中&&后的myfunc(b)将永远不会执行,因为a!=0永远是FALSE。
利用短路求值有2个有用的技巧
bool is_first_char_valid_alpha_unsafe(const char *p)
{
return isalpha(p[0]); // SEGFAULT highly possible with p == NULL
}
bool is_first_char_valid_alpha(const char *p)
{
return p != NULL && isalpha(p[0]); // 1) no unneeded isalpha() execution with p == NULL, 2) no SEGFAULT risk
}
这个例子避免了空指针
(defparameter *is-it-even* nil)
(or (oddp 5)
(setf *is-it-even* t))
利用短路求值,用OR实现了条件判断
尽管有上面说的优点,但是可能会带来没有意识到的问题,比如:
if (expressionA && myfunc(b)) {
do_something();
}
当expressionA为True时无论do_something()是否执行,myfunc(b)都会执行,例如分配系统资源的操作。
相反,expressionA为False时myfunc(b)永远不会执行
并不是所有语言和所有操作符支持的
Java支持非短路求值也支持短路求值
常见的语言 | 支持的操作符 |
---|---|
C, Obejective-C, C++, C# | &&, | |, ? |
Java, MATLAB, R, Swift | &&, | | |
JavaScript, GO, Haskel | &&, | | |
Lisp, Lua, Scheme | and, or |
PHP | &&, and, | |, or |
Python | and, or |
Visual Basic | 不支持 |