This articleneeds additional citations forverification. Please helpimprove this article byadding citations to reliable sources. Unsourced material may be challenged and removed. Find sources: "Short-circuit evaluation" – news ·newspapers ·books ·scholar ·JSTOR(August 2013) (Learn how and when to remove this message) |
| Evaluation strategies |
|---|
Short-circuit evaluation,minimal evaluation, orMcCarthy evaluation (afterJohn McCarthy) is the semantics of someBoolean operators in someprogramming 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 theAND function evaluates tofalse, the overall value must befalse; and when the first argument of theOR function evaluates totrue, the overall value must betrue.
In programming languages withlazy evaluation (Lisp,Perl,Haskell), the usualBoolean operators short-circuit. In others (Ada,Java,Delphi), both short-circuit and standard Boolean operators are available. For some Boolean operations, likeexclusive or (XOR), it is impossible to short-circuit, because both operands are always needed to determine a result.
Short-circuit operators are, in effect,control structures rather than simple arithmetic operators, as they are notstrict. Inimperative language terms (notablyC andC++), where side effects are important, short-circuit operators introduce asequence point: they completely evaluate the first argument, including anyside effects, before (optionally) processing the second argument.ALGOL 68 usedproceduring to achieveuser-defined short-circuit operators and procedures.
The use of short-circuit operators has been criticized as problematic:
The conditional connectives — "cand" and "cor" for short — are ... less innocent than they might seem at first sight. For instance,cor does not distribute overcand: compare
- (Acand B)cor Cwith (Acor C)cand (Bcor C);
in the case ¬A ∧ C , the second expression requires B to be defined, the first one does not. Because the conditional connectives thus complicate the formal reasoning about programs, they are better avoided.
In any programming language that implements short-circuit evaluation, the expressionx andy is equivalent to theconditional expressionifx theny elsex, and the expressionx ory is equivalent toifx thenx elsey. In either case,x is only evaluated once.
The generalized definition above accommodates loosely typed languages that have more than the twotruth-valuesTrue andFalse, where short-circuit operators may return the last evaluated subexpression. This is called "last value" in the table below. For a strictly-typed language, the expression is simplified toifx theny elsefalse andifx thentrue elsey respectively for the Boolean case.
AlthoughAND takesprecedence overOR in many languages, this is not a universal property of short-circuit evaluation. An example of the two operators taking the same precedence and beingleft-associative with each other isPOSIX shell's command-list syntax.[2]: §2.9.3
The following simple left-to-right evaluator enforces a precedence ofAND overOR by acontinue:
function short-circuit-eval (operators,values)letresult := Truefor each (op,val) in (operators,values):ifop = "AND" &&result = Falsecontinueelse ifop = "OR" &&result = Truereturnresultelseresult :=valreturnresult
Short-circuit logic, with or without side-effects, have been formalized based onHoare's conditional. A result is that non-short-circuiting operators can be defined out of short-circuit logic to have the same sequence of evaluation.[3]
& and| arebitwise operators that occur in many programming languages. The major difference is that bitwise operations operate on the individual bits of a binary numeral, whereas conditional operators operate on logical operations. Additionally, expressions either side of a bitwise operator are always evaluated. In some languages, includingJava andC#, they can be used on Boolean operands to force both sides to be evaluated.
if(expression1||expression2||expression3)
If expression 1 is true, expressions 2 and 3 are not checked.
if(expression1|expression2|expression3)
This checks expressions 2 and 3, even if expression 1 is true.
Short-circuit operators can thus reduce run times by avoiding unnecessary calculations. They can also avoid null exceptions when expression 1 checks whether an object is valid.
The following table is restricted to common programming languages and the basic Boolean operators forlogical conjunctionAND andlogical disjunctionOR.Bitwise operators are shown only for languages that allow them to be used as eager Boolean operators and have the same return type.
Note that there are more short-circuit operators, for example theternary conditional operator, which iscond? e1: e2 (C,C++,Java,PHP),if condthen e1else e2 (ALGOL,Haskell,Kotlin,Rust),e1if condelse e2 (Python). Please take a look atternary conditional operator#Usage.
| Language | Eager operators | Short-circuit operators | Result type |
|---|---|---|---|
| Ada | and,or | and then,or else | Boolean |
| ALGOL 68 | and, &, ∧ ; or, ∨ | andf , orf(both user defined) | Boolean |
| APL | ∧,∨ | :AndIf,:OrIf | Boolean |
| awk | none | &&,|| | Boolean |
| C,Objective-C | &,|[a] | &&,||[5] | int |
| C++[b] | none | &&,||[6] | Boolean |
| C# | &,| | &&,|| | Boolean |
| D[c] | &,| | &&,|| | Boolean |
| Eiffel | and,or | and then,or else | Boolean |
| Erlang | and,or | andalso,orelse | Boolean |
| Fortran[d] | .and.,.or. | .and.,.or. | Boolean |
| Go,Haskell,OCaml[e] | none | &&,|| | Boolean |
| Java,R,Swift | &,| | &&,||[f] | Boolean |
| JavaScript | none | &&,|| | Last value |
| Julia | none | &&,|| | Last value |
| Kotlin | and,or | &&,|| | Boolean |
| Lisp,Lua[e],Scheme | none | and,or | Last value |
| MATLAB[g] | &,| | &,|,&&,|| | Boolean |
| MUMPS (M) | &,! | none | Numeric |
| Modula-2 | none | AND,OR | Boolean |
| Pascal | and,or[h][i] | and_then,or_else[i] | Boolean |
| Perl | &,| | &&,and,||,or | Last value |
| PHP | none | &&,and,||,or | Boolean |
| POSIX shell,Bash | none | &&,|| | Numeric (exit code) |
| PowerShell Scripting Language | none | -and,-or | Boolean |
| Python | &,| | and,or | Last value |
| Ruby | &,| | &&,and,||,or[9] | Last value |
| Rust | &,| | &&,||[10] | Boolean |
| Smalltalk | &,| | and:,or:[j] | Boolean |
| Standard ML | Unknown | andalso,orelse | Boolean |
| Visual Basic .NET | And,Or | AndAlso,OrElse | Boolean |
| Visual Basic,Visual Basic for Applications (VBA) | And,Or | none | Numeric |
bool or take only the values0 or1.[4]&& and|| are eager and can return any type.static if andstatic assert. Expressions in static initializers or manifest constants use eager evaluation.&,| (OCamlland,lor) are restricted to integers and cannot be used with Booleans.?…: are sometimes referred to as "conditional operators".[7]& behaves like a short-circuit operator when used in a statement followingif orwhile.[8]and: is a block (e.g.,falseand: [Transcriptshow:'Wont see me']).Usual example, using aC-based language:
intdenom=0;if(denom!=0&&num/denom){...// ensures that calculating num/denom never results in divide-by-zero error}
Consider the following example:
inta=0;if(a!=0&&myfunc(b)){doSomething();}
In this example, short-circuit evaluation guarantees thatmyfunc(b) is never called. This is becausea != 0 evaluates tofalse. This feature permits two useful programming constructs.
Both are illustrated in the following C snippet where minimal evaluation prevents both null pointer dereference and excess memory fetches:
boolisFirstCharValidAlphaUnsafe(constchar*p){returnisalpha(p[0]);// SEGFAULT highly possible with p == NULL}boolisFirstCharValidAlpha(constchar*p){returnp!=NULL&&isalpha(p[0]);// 1) no unneeded isalpha() execution with p == NULL, 2) no SEGFAULT risk}
Since minimal evaluation is part of an operator's semantic definition and not an optionaloptimization, a number of coding idioms rely on it as a succinct conditional construct. Examples include:
Perl idioms:
some_conditionordie;# Abort execution if some_condition is falsesome_conditionanddie;# Abort execution if some_condition is true
POSIX shell idioms:[11]
modprobe-qsome_module&&echo"some_module installed"||echo"some_module not installed"
This idiom presumes thatecho cannot fail.
Despite these benefits, minimal evaluation may cause problems for programmers who do not realize (or forget) it is happening. For example, in the code
if(expressionA&&myFunc(b)){doSomething();}
ifmyFunc(b) is supposed to perform some required operation regardless of whetherdoSomething() is executed, such as allocating system resources, andexpressionA evaluates as false, thenmyFunc(b) will not execute, which could cause problems. Some programming languages, such asJava, have two operators, one that employs minimal evaluation and one that does not, to avoid this problem.
Problems with unperformed side effect statements can be easily solved with proper programming style, i.e., not using side effects in Boolean statements, as using values with side effects in evaluations tends to generally make the code opaque and error-prone.[12]
Short-circuiting can lead to errors inbranch prediction on moderncentral processing units (CPUs), and dramatically reduce performance. A notable example is highly optimized ray with axis aligned box intersection code inray tracing.[clarification needed] Some compilers can detect such cases and emit faster code, but programming language semantics may constrain such optimizations.[citation needed]
An example of a compiler unable to optimize for such a case isJava'sHotspot virtual machine (VM) as of 2012.[13]