44

In the PHP code

if(a() && b())

when the first operand evaluates to false, b() will not be evaluated.

Similarly, in

if (a() || b())

when the first operand evaluates to true, b() will not be evaluated..

Is this true for all languages, like Java, C#, etc?

This is the test code we used.

<?php
function a(){
echo 'a';
return false;
}

function b(){
echo 'b';
return true;
}


if(a() && b()){
echo 'c';
}
?>
Kim Stacks
  • 10,202
  • 35
  • 151
  • 282
  • 3
    Does anybody know how SQL server and Oracle are handling their OR/AND operators? Becuase I frequently use: (@var IS NULL OR @var = table.col). I hope that he stops after the @var IS NULL, because I think this is faster since the comparison to table.col is not executed (this will even save more time when using this in combination with a LIKE operator). – Gertjan Aug 05 '09 at 11:31
  • 3
    I would be very surprised if Oracle's (or any) optimizer were ot overlook anything as simple as this. In fact, the optimizer is free to change the order of the conditions if it thinks it will get better result. So (@var like 'xxx' or @var = 3) will probably short circuit, but not in the order written. – Lucky Aug 05 '09 at 12:37
  • 1
    I don't think anyone has mentioned it here, but be aware that side effects can occur because of short circuit evaluation. – Kinze Aug 05 '09 at 14:05
  • In some functional, `if` is just a function that calls other functions (called thunks as fair I remember - from a Coursera' programming course). `(if (< a b) (print "foo") (print "baz"))` - `if` will just call `(print "foo")` or `(print "baz")`. In a Factor you would write something like: `[ "foo" print ] [ "baz" print ] if`. You just need a programming language with ability to create and pass function as an argument to a another function. – Darek Nędza Jul 26 '15 at 23:43
  • *All* of them? Not the one I just made up in my head, which happens to be identical to C except that it doesn't have short-circuit evaluation. – user253751 Dec 09 '15 at 01:03

17 Answers17

72

This is called short-circuit evaluation.

It is generally true for languages derived from C (C, C++, Java, C#) but not true for all languages.

For example, VB6 does not do this, nor was it done in early versions of VB.NET. VB8 (in Visual studio 2005) introduced the AndAlso and OrElse operators for this purpose.

Also, from comments, it seems that csh performs short-circuit evaluation from right to left, to make matters even more confusing.

It should also be pointed out that short-circuit evaluation (or lack of) has its dangers to be aware of. For example, if the second operand is a function that has any side effects, then the code may not perform exactly as the programmer intended.

Patrick McDonald
  • 64,141
  • 14
  • 108
  • 120
20

It's not true for VB6.

In VB.net you have to use "AndAlso" instead of "And" if you want it to skip evaluating the second expression.

Alex Warren
  • 7,187
  • 2
  • 31
  • 30
13

Is this true for ALL languages, like JAVA, C#, etc?

In C# this is only true for the short-circuiting operators '||' and '&&'; if you just use '|' or '&' it will evaluate both sides every time.

James McMahon
  • 48,506
  • 64
  • 207
  • 283
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 4
    Java has the same non-short-circuited operators. – Powerlord Aug 05 '09 at 14:04
  • 5
    Same as C and C++. They don't do quite the same thing, though. In C, 2 && 1 evaluates to 1 (the equivalent of true), while 2 & 1 does a bitwise and and evaluates to 0. This won't be as noticeable with languages that require boolean operands for && and ||. – David Thornley Aug 05 '09 at 14:29
  • 4
    As David said, | and & aren't boolean operators, so shortcircuiting doesn't make sense with them-- unless there was some way to do bit-level shortcircuiting. – rmmh Mar 04 '13 at 19:31
  • @rmmh that depends quite a bit on how you state your definitions. They are operators that can operate on booleans and, when doing so, return booleans. Certainly at that level they are boolean operators. If you are talking implementation: they basically all use the same bitwise operations (which incidentally can be exploited for some fun edge-case examples). That leaves, when used in this context, the only distinction being: do they short-circuit or not. – Marc Gravell Mar 04 '13 at 20:59
  • This is very misleading as `|` and `&` do not do the same thing that `||` and `&&` do in languages like C, C++, C#, JavaScript, and probably Java (however I can't confirm that last one). – Benji Altman Jan 21 '20 at 20:54
12

It's called short-circuit evaluation and most languages do this. In some languages there exists operators that don't do this.

waxwing
  • 18,547
  • 8
  • 66
  • 82
8

The original version of Pascal did not, which caused lots of grief. Modern Pascals, such as Delphi work the same way as C et al.

7

Ada has special short-circuited forms of conditionals:

and then
or else

used like this:

if p.next /= null and then p.next.name = 'foo'
if x = 0 or else 1/x = y

In some ways it's kind of nice because you can deduce that the programmer knew the expression needed to be short-circuited and that the conditional is not working by accident.

Mark Harrison
  • 297,451
  • 125
  • 333
  • 465
5

It is true for languages that are "children" of the C : PHP, Java, C++, C#, ... or in the same "inspiration", like Perl.

But it is not true for VB (at least before .NET, which introduced new keywords for that).
(And that's really disturbing the first you work with VB ^^ )

John Topley
  • 113,588
  • 46
  • 195
  • 237
Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
  • 2
    It is also disturbing when you are going from C# to VB.NET. This is especially annoying when using stuff like: If(myVar ISNOT Nothing And myVar.Count > 0). The AND needs to be an ANDALSO. Most cases you won't encounter issues, but when myVar is nothing/null you might get confused. I needed to use .NET Reflector to find out that I needed to use AndAlso (google for "VB.NET And" did not give the wanted results). – Gertjan Aug 05 '09 at 11:28
4

Microsoft VBScript (often used in conjunction with 'Classic' ASP) had no short-circuit evaluation for boolean operators, instead it uses bitwise evaluation. Which is one of the many reasons it is possibly the worst language ever!

"What's going on is that VBScript is not logical. VBScript is bitwise. All the so-called logical operators work on numbers, not on Boolean values! Not, And, Or, XOr, Eqv and Imp all convert their arguments to four-byte integers, do the logical operation on each pair of bits in the integers, and return the result. If True is -1 and False is 0 then everything works out, because -1 has all its bits turned on and 0 has all its bits turned off. But if other numbers get in there, all bets are off".

Taken from this blog. by Eric Lippert.

Dan Diplo
  • 25,076
  • 4
  • 67
  • 89
  • same to VB: [*... Prior to VB.NET, the VB language only had the `And` and `Or` operators. They were essentially bitwise operators, which means that they took their two operands and performed an AND or OR operation on each bit position to produce the resulting bit...*](https://blogs.msdn.microsoft.com/vbfaq/2004/04/20/why-did-visual-basic-net-introduce-andalso-and-orelse/) – phuclv Apr 14 '18 at 13:34
3

In Delphi it's a compiler option.

Julian de Wit
  • 3,084
  • 2
  • 29
  • 29
  • 11
    Oh dear god. So you can have completely unpredictable bugs based on what option someone else passes the compiler when they built your code? – Alex Feinman Aug 05 '09 at 13:16
  • 2
    This tends to be true of all compilers which must deal with languages that have changed over time, as Pascal and C have. In practice, no-one ever uses this particular Delphi option. –  Aug 05 '09 at 19:48
  • Yes, it seemed pretty risky to mee too so I never touched it.. :S – Julian de Wit Aug 06 '09 at 17:38
3

In standard FORTRAN or Fortran, the operands of a boolean expression can be evaluated in any order. Incomplete evaluation is permitted, but implementation defined.

This allows optimisation of boolean expressions that would not be permitted if strict Left-To-Right ordering was enforced. Expressions which require strict ordering must be decomposed into seperate conditionals, or implementation-dependent assumptions can be made.

Since decomposition is used to enforce ordering, it follows that seperate IF statements can not always be optimised into a single expression. However, short-circuit evaluation is explicit with decomposition, and this is never worse than languages which enforce strict left-to-right ordering to allow lazy evaluation.

Languages wich are derived from FORTRAN (Fortran, BASIC, VBn), and languages which were designed to achieve FORTRAN-like efficiency (Pascal, Ada) initially followed the FORTRAN example of allowing out-of-order evaluation.

david
  • 2,435
  • 1
  • 21
  • 33
2

This is true for Java as well but the operators |, & etc will evaluate both sides.

willcodejavaforfood
  • 43,223
  • 17
  • 81
  • 111
  • 3
    Ugh. |, & etc aren't really related operators. – Imagist Aug 05 '09 at 14:10
  • 2
    @Imagist: how so? "|" and "&" can be both the bitwise operators and the logical non-shortcut operators, depending on the context. – Joachim Sauer Aug 05 '09 at 14:20
  • @JoachimSauer in what context would the bitwise operators & and | be "logical non-shortcut operators"? Are you referring specifically to the case where both operands are boolean/Boolean? – jarmod Aug 27 '18 at 20:37
  • @jamod: exactly. Basically when they are used the same way `&&` and `||` are used. See [JLS 15.22.2](https://docs.oracle.com/javase/specs/jls/se10/html/jls-15.html#jls-15.22.2). – Joachim Sauer Aug 27 '18 at 20:47
  • @JoachimSauer The spec doesn't seem to explicitly require the compiler to short-circuit in that case. It does for the regular boolean operators, for example && "evaluates its right-hand operand only if the value of its left-hand operand is true". In fact, the spec states "The conditional-and operator && is like & (§15.22.2), *but* evaluates its right-hand operand only if the value of its left-hand operand is true." – jarmod Aug 27 '18 at 21:02
2

This is called short-circuit evaluation and it is common for all of the languages that I have ever worked in (C, C++, C#, Java, Smalltalk, Javascript, Lisp) except for VB, VB.NET and Fortran.

It's actually a pretty useful feature. Without short-circuiting you wouldn't be able to do this:

if (a != null && a.isBlank())

Without short-circuiting you would have to have nested if statements because the second part would throw an error if a was null.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Jeff Hornby
  • 12,948
  • 4
  • 40
  • 61
  • 1
    Not lisp. Well, not unless `or` is defined as a macro. – troelskn Aug 05 '09 at 11:45
  • Really? I did Lisp over 20 years ago in university so you'll have to excuse my memory. – Jeff Hornby Aug 05 '09 at 13:41
  • 2
    OR is a macro in Common Lisp, I believe. I don't think it's a special form (like IF), and it certainly does short-circuit. I don't know if there are any Lisp versions that don't short-circuit, but I haven't seen one. – David Thornley Aug 05 '09 at 14:31
  • or is a short-circuiting macro in Clojure too. Coupled with the fact that nils are treated as "false", it allows for the nice little idiom: (or (function-that-might-return-nil) some-default-value) – mikera Nov 19 '11 at 09:03
2

Most languages (all that I've seen) use short circuit evaluation on CONDITIONAL operators such as && and ||. They will stop evaluating as soon as one of the conditions has satisfied the requirement. (The first false on &&. The first true on ||)

All BINARY operators such as & and |, are processed. (Original)

All BITWISE operators such as & and |, are processed. (Edit: 5/10/17)

Brad Bruce
  • 7,638
  • 3
  • 39
  • 60
  • This might explain why VB operates differently, as it does not make a distinction between bitwise and logical operators. – Patrick McDonald Aug 05 '09 at 14:22
  • 1
    `&` and `|` are not binary operators when applied to `bool`s in C#. They are boolean, just not short-circuited. – Pavel Minaev Aug 07 '09 at 00:38
  • 1
    Old content is old, but in the name of pedantry: all of these operators are "binary", as in operate on two operands. `||`/`&&` are boolean conditional, and `|`/`&` are bitwise. – Dan Lugg May 09 '17 at 22:09
2

In Erlang, the and and or operators do not do short-circuit evaluation; you have to use orelse and andalso operators if you want short-circuiting behavior.

mipadi
  • 398,885
  • 90
  • 523
  • 479
1

Coldfusion will natively do short-circut evaluation. I am sure all CF developers have written:

<cfif isdefined("somevariable") and somevariable eq something>
//do logic
</cfif>
andrewWinn
  • 1,786
  • 2
  • 14
  • 28
1

MATLAB is one language that distinguishes between "standard" logical operators and short-circuit operators:

  • & (AND operator) and | (OR operator) can operate on arrays in an element-wise fashion.
  • && and || are short-circuit versions for which the second operand is evaluated only when the result is not fully determined by the first operand. These can only operate on scalars, not arrays.
gnovice
  • 125,304
  • 15
  • 256
  • 359
0

Other answers have given good examples of languages with and without short circuit evaluation so I won't repeat them.

Just one interesting point to add: Lisps such as Clojure have boolean short circuit evaluation, but in addition you can quite trivially define any operator you like with short circuit evaluation through the use of macros.

Example of a short-circuiting "nand" operation in Clojure:

(defmacro nand 
  ([x] 
    `(not ~x))
  ([x & xs] 
    `(let [nand# (not ~x)]
       (if nand# 
         true               ; short circuit if we can prove the nand is true
         (nand ~@xs)))))    ; continue with the other expressions otherwise

(nand true true)
=> false

(nand false (println "Expression with a side effect!"))
=> true
mikera
  • 105,238
  • 25
  • 256
  • 415