Thursday, April 28, 2011

Do all programming languages have boolean short-circuit evaluation?

In the PHP code

if(a() && b())

when the first argument is false, b() will not be evaluated.

Similarly, in

if (a() || b())

when the first argument is 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';
}
?>
From stackoverflow
  • 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.

    Greg D : Likewise, the shortcircuiting `Or` is `OrElse`. Which I like. It's VB's "Do it my way, OrElse!"
  • You might find it helpful to refer to the language specifications.

    It has been true of all the languages in the C lineage that I have used. Neliac, C, C++, Java.

    This article discusses the idea

  • 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.

    R. Bemrose : Don't forget the VB.NET OrElse operator, too!
    Patrick McDonald : Fair point, thanks :)
    Dan Diplo : Are there any languages that evaluate from right to left, I wonder?
    dmckee : @Dan Diplo: One of the unix shells does that for some arithmetical operations. There is a SO question on the matter...
    Martin Beckett : 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()
    dmckee : It is csh. Here we go: http://stackoverflow.com/questions/1010049/in-csh-why-does-4-3-1-0
    Gamecat : In Delphi this is optional, default on.
  • It's called short-circuit evaluation and most languages do this. In some languages there exists operators that don't do this.

  • 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 ^^ )

    Gertjan : 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).
  • 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.

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

    Imagist : Ugh. |, & etc aren't really related operators.
    Joachim Sauer : @Imagist: how so? "|" and "&" can be both the bitwise operators and the logical non-shortcut operators, depending on the context.
  • 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.

    R. Bemrose : Java has the same non-short-circuited operators.
    David Thornley : 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 ||.
  • 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.

    troelskn : Not lisp. Well, not unless `or` is defined as a macro.
    Jeff Hornby : Really? I did Lisp over 20 years ago in university so you'll have to excuse my memory.
    David Thornley : 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.
  • 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.

  • 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>
    
  • 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.

    Patrick McDonald : This might explain why VB operates differently, as it does not make a distinction between bitwise and logical operators.
    Pavel Minaev : `&` and `|` are not binary operators when applied to `bool`s in C#. They are boolean, just not short-circuited.
  • In Delphi it's a compiler option.

    Alex Feinman : Oh dear god. So you can have completely unpredictable bugs based on what option someone else passes the compiler when they built your code?
    anon : 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.
    Julian de Wit : Yes, it seemed pretty risky to mee too so I never touched it.. :S
  • 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.

  • 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.

    David Thornley : Ick. I bet that causes a lot of bugs.
    mipadi : 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.
  • 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.

0 comments:

Post a Comment