Do all programming languages have boolean short-circuit evaluation?
Asked Answered
D

17

45

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';
}
?>
Dmz answered 5/8, 2009 at 11:16 Comment(5)
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).Jordans
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.Coacervate
I don't think anyone has mentioned it here, but be aware that side effects can occur because of short circuit evaluation.Curettage
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.Amphetamine
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.Enchase
N
74

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.

Nunnery answered 5/8, 2009 at 11:19 Comment(7)
Don't forget the VB.NET OrElse operator, too!Interstate
Are there any languages that evaluate from right to left, I wonder?Verne
@Dan Diplo: One of the unix shells does that for some arithmetical operations. There is a SO question on the matter...Landing
Dan - C/C++ compilers are free to reorder the arguments in the if statement, so you can't be sure only a() would be called - it might be only b()Phono
It is csh. Here we go: https://mcmap.net/q/183380/-in-csh-why-does-4-3-1-0Landing
In Delphi this is optional, default on.Amidst
VB: "Honey, do this AndAlso this AndAlso this OrElse!"Unsuspected
N
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.

Nonresident answered 5/8, 2009 at 11:18 Comment(2)
Likewise, the shortcircuiting Or is OrElse. Which I like. It's VB's "Do it my way, OrElse!"Brainwork
But remember: VBScript does not support this.Longcloth
L
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.

Lifelong answered 5/8, 2009 at 11:24 Comment(5)
Java has the same non-short-circuited operators.Interstate
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 ||.Aboveboard
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.Clemmer
@Clemmer 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.Lifelong
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).Mungovan
R
12

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

Regionalism answered 5/8, 2009 at 11:19 Comment(0)
R
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.

Rhodonite answered 5/8, 2009 at 11:21 Comment(0)
W
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.

Weakness answered 5/8, 2009 at 11:30 Comment(0)
O
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 ^^ )

Oxime answered 5/8, 2009 at 11:20 Comment(1)
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).Jordans
G
4

In Delphi it's a compiler option.

Gladwin answered 5/8, 2009 at 12:53 Comment(3)
Oh dear god. So you can have completely unpredictable bugs based on what option someone else passes the compiler when they built your code?Aphoristic
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.Rhodonite
Yes, it seemed pretty risky to mee too so I never touched it.. :SGladwin
V
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.

Verne answered 5/8, 2009 at 12:59 Comment(2)
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...Pimbley
On processors like the 8086 family, there is no such thing as "a logical operation on each pair of bits". Bit wise operation is done on words, and single-pair operations are done by masking or shifting. Nor is there any "conversion" from Boolean to Integer. The 8086 family was designed to support Pascal and c conventions, but not so far as to implement native inefficient bit operations to map to c. There have been processors with native Boolean types, and processors with native single-bit operations, but VBScript and related languages were designed to be more modern.Knothole
K
4

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.

Knothole answered 17/3, 2015 at 11:24 Comment(0)
P
2

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

Phyl answered 5/8, 2009 at 11:22 Comment(5)
Ugh. |, & etc aren't really related operators.Valladares
@Imagist: how so? "|" and "&" can be both the bitwise operators and the logical non-shortcut operators, depending on the context.Tonsillitis
@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?Travers
@jamod: exactly. Basically when they are used the same way && and || are used. See JLS 15.22.2.Tonsillitis
@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."Travers
E
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.

Estaminet answered 5/8, 2009 at 11:30 Comment(4)
Not lisp. Well, not unless or is defined as a macro.Allista
Really? I did Lisp over 20 years ago in university so you'll have to excuse my memory.Estaminet
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.Aboveboard
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)Denizen
A
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)

Alongshore answered 5/8, 2009 at 12:1 Comment(3)
This might explain why VB operates differently, as it does not make a distinction between bitwise and logical operators.Nunnery
& and | are not binary operators when applied to bools in C#. They are boolean, just not short-circuited.Crowe
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.Timetable
M
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.

Mycenaean answered 5/8, 2009 at 13:59 Comment(2)
Ick. I bet that causes a lot of bugs.Aboveboard
It was kind of a "gotcha" until I got used to it. Code like A > 1 and math:sqrt(A) can cause problems if you don't realize the behavior.Mycenaean
C
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>
Coagulase answered 5/8, 2009 at 11:33 Comment(0)
X
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.
Xenophon answered 5/8, 2009 at 14:22 Comment(0)
D
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
Denizen answered 19/11, 2011 at 8:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.