Talk:Short-circuit evaluation

Latest comment: 29 days ago by Matma Rex in topic Ruby

Article title edit

Can anyone motivate (with a reference) the term "minimal evaluation"? I've only seen this concept referred to as short-circuit evaluation (in compiler literature). Wouter Lievens 14:33, 19 May 2006 (UTC)Reply

Problems edit

Added a brief segue into problems that short-circuit evaluation may cause (not executing the second part of a conditional if that conditional is supposed to do something.), since every programming book I've ever seen mentions this at least briefly. Sloverlord 15:00, 25 October 2006 (UTC)Reply

It is not true that a evaluates to false. a evaluates to 0. The logical operators in C recognize zero and nonzero, not true and false. If you wish to use Boolean terminology, it would be better to give code examples in a language that actually has a bool type. Penry 22:38, 9 January 2007 (UTC)Reply

...and evaluate to 1 and 0. (which are sometimes considered as true and false) ca1 (talk) 00:36, 12 May 2008 (UTC)Reply

Inaccuracy? edit

Quote:

In others (C, Ada), both short-circuit and standard boolean operators are available.

What standard boolean operator is available in C? I didn't know C has boolean operators at all, just logical ones (difference being that a logical operator evaluates something to be logical true or false and a boolean operator evaluates to a typed true or false statement). I suppose you could write the first example as (assuming a and myfunc are both int and long has more bits):

   if ((long)a + (long)myfunc(b)) {
       do_something();
   }

This would cause a and myfunc to be evaluated and then convert to a larger type so the results can't overflow and get back to 0 so the addition acts like an &&, but I hardly think that anyone would consider + a boolean operator. --216.37.197.174 14:42, 8 March 2007 (UTC)Reply

You're not kidding. The implication that an Ada 'and' is equivalent to a C '&' is brutally misleading. 209.139.199.1 (talk) 17:49, 29 January 2008 (UTC)

Well, of course C has loose typing, and doesn't have a separate boolean type (neither does Lisp), but it uses integer 0 as False and integer 1 as True (in all integer types), though it also accepts all non-0 integers as True in conditionals. These are the values returned by the relational operators as well as by && and ||. On the other hand, though & and | function as boolean AND and OR for the standard True and False values, they also function as bit-wise AND and OR for other values. With that convention, "&" is the boolean AND and "|" is the boolean OR. "&&" is the short-circuit AND and "||" the short-circuit OR. Interestingly, 3 && 5 => 1 (not 5, as it would in Lisp), 3 || 5 => 1 (not 3, as it would in Lisp), and 0 || 5 => 1 (not 5, as it would in Lisp). So I think it is perfectly sensible to say that C and Lisp have boolean short-circuit operators, even though they aren't as clear-cut as in more strictly typed languages. --Macrakis 16:19, 8 March 2007 (UTC)Reply

An explicit native bool type was added in C99, it is called _Bool, and a header <stdbool.h> that defines bool as a macro that expands to _Bool --.oisyn 10:14, 31 August 2007 (UTC)Reply

better example edit

 if(0!=b && a/b) {
     printf("divided by %d",b);
 }
  • i always thought this is the one of best examples for such thing. for such example shows something you should avoid anyway.
    • strlen(0) is valid last time i checked ;) - even though it depends on library :)
  • another one, can be seen in linux kernel. in same spirit is this one.
 int finished_with_condition_2=1; // set to zero if loop finished with condition 2
 do {
    if(some_condition_1())
          break;
 } while(some_condition_2() || (finished_with_condition_2=0));
  • unix shell uses && and || for evaluate if first was ok, evaluate if first was not ok, respectively.

ca1 (talk) 00:34, 12 May 2008 (UTC)Reply

This code demonstrates that bit-wise operators (such as |) in C do not short-circuit while logical ones (like ||) do.
:for( int i = 1 ; i <= 100 ; i++ )
:{
:  (
:    ( i%3==0 && printf( "Fizz" ) ) |
:    ( i%5==0 && printf( "Buzz" ) ) |
:    ( i%7==0 && printf( "Zazz" ) )
:  ) ||
:  printf( "%d" , i ) ;
:  putchar( '\n' ) ;
:}
:
Jiri Programagor (talk) 09:57, 15 July 2022 (UTC)Reply

Confused boolean operators with binary operators edit

Neither the statement

In others (C, Ada), both short-circuit and standard boolean operators are available.

nor the table "Support in common programming languages" is correct, or at least very misleading. But the way I understood the table, it seems to state that & and | are boolean operators in C, which isn't true. They compute and/or per bit. (3&7)==3 for example, and (3&4)==0. I don't consider that a boolean operator. The same holds for C++ and Python, and probably a lot of other languages in that list. I am not sure how to correct it though, because I don't know most of the other languages well enough. —Preceding unsigned comment added by 91.14.105.106 (talk) 09:35, 8 August 2009 (UTC)Reply

That column lists how to perform non-short-circuit AND and OR of two boolean operands. It's irrelevant that some of those operators may have other meanings for other types like integers. --76.91.63.71 (talk) 09:52, 8 August 2009 (UTC)Reply
But that's very misleading. In C intergers are commonly used for boolean values. And it's even more misleading for languages like python, where the value is not Boolean but "Last value" in the table, because & and | won't work as boolean operators on arbitrary values. I think one could at least note explicitly that this only works for boolean types. --91.14.105.106 (talk) 12:52, 8 August 2009 (UTC)Reply
I agree: using bitwise operators as logical operators is so unacceptable in most of these languages, especially the "last value" languages, that there shouldn't even be any question about whether they should be permitted in the table. Using bitwise operators as if they were logical operators is error-prone and likely to give surprising results at times. If the use of bitwise operators as logical operators is to be mentioned at all, we should mention it in its own section instead of lumping them in with logical operators. For these reasons, I have removed the bitwise operators from the table. - furrykef (Talk at me) 03:18, 27 February 2010
I originally cleaned out C and C++ from the table. As for Java, however, &, |, and ^ are boolean logical operators. In fact, && and || are described in terms of & and |: "The && operator is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true". Thus, Java is an example of a language with short-circuiting, and non-short-circuiting boolean operators. I reinstated the operators for Java. decltype (talk) 13:45, 27 February 2010 (UTC)Reply
Same for C#: "The operation x && y corresponds to the operation x & y, except that y is evaluated only if x is not false." decltype (talk) 13:49, 27 February 2010 (UTC)Reply
C's type system uses integers as the representation of Booleans, with the canonical representations being 0 for False and 1 for True. On those canonical values (the ones that are returned by the relational operators), & and | function as the AND and OR operators. Of course, they also function as bitwise AND and OR on integer values. The if statement and expression (?:), in addition to the canonical Booleans, also allow integers, with 0 interpreted as False and non-0 interpreted as True. For those values, & does not correctly implement AND (2 & 1 => 0, though T & T should be T) -- though && does. Which is all problematic and error-prone in various ways, but Wikipedia is not about passing judgement on language designs, but on recording reality as it is.
The reality, then, is that C simply doesn't have a distinct Boolean data type, but does have a standard representation of booleans, namely 0=False and 1=True. For this standard representation, & and | are the Boolean operators. --macrakis (talk) 22:17, 27 February 2010 (UTC)Reply
Perhaps, but I think this is largely irrelevant. For one thing, a C program can do enum { false, true = -1 }; and this will still always behave exactly as intended as long as the programmer never compares directly against true (which one should never do anyway). For another thing, if we were to add the bitwise operators back into the table, we would have to add an explicit explanation that the operators work only when the values are 0 and 1 -- a restriction that never applies to the logical operators. Considering that using & and | as logical operators often flies in the face of good programming practice in the first place, I see no reason to bother. - furrykef (Talk at me) 09:33, 3 March 2010 (UTC)Reply
Agree, keep them out for C and C++. Unlike in Java and C#, & and | are not logical operators in those languages, and were never intended to be. decltype (talk) 10:00, 3 March 2010 (UTC)Reply
You are discussing C as though it were a modern, strictly-typed language, which it is not. Though you could define a true/false enum, that is simply not what C does. It does not have a boolean data type; it has integers which are interpreted as booleans by various operations. I believe & and | should go in the table as boolean operators, with a footnote explaining that they work only on the canonical representations of True and False. --macrakis (talk) 03:42, 4 March 2010 (UTC)Reply

(Unindenting...) And you are discussing & and | as if they were logical operators, which they are not. Logical boolean operators in C don't need to operate on any "canonical representations of True and False"; they just operate on zero and non-zero. Bitwise operators have different semantics, different purposes, and different typical uses. They're apples and oranges, and lumping bitwise operators in with logical operators will 1) cause confusion and 2) appear to promote bad programming practice. - furrykef (Talk at me) 01:03, 5 March 2010 (UTC)Reply

The whole design of C "promotes bad programming practices" -- it is an old, low-level language, but we are not here to judge whether its design is good or bad, nor to promote good programming practices, just to describe the feature. I'll have to go back to K&R and see how they describe it, though of course that isn't definitive in itself.... --macrakis (talk) 04:19, 5 March 2010 (UTC)Reply
Perhaps, but in any case, the idea of putting bitwise operators in a table that is otherwise full of logical operators reminds me of that Cookie Monster song: "One of these things is not like the other things, one of these things, it doesn't belong..." After all, every other operator in the table is a logical operator, all of the other operator pairs have consistent semantics between them, etc. There are just too many ways in which the bitwise operators stick out like a sore thumb. - furrykef (Talk at me)
The bitwise operators are also the logical operators in C -- just think of it as a form of polymorphism/overloading operating through punning. That is, the same operators (& and |) apply both to the Boolean type and to the fixed-length bitstring type, which both happen to be represented in C as integers. With Boolean arguments, & and | return a Boolean result. With fixed-length bitstring operators, & and | return a bitstring result. And it "just happens" than Booleans, fixed-length bitstrings, and integers are all the same implementation type....
A footnote suffices to explain this. --macrakis (talk) 17:20, 6 March 2010 (UTC)Reply
That's getting close to entering the area of original research. And still doesn't explain the (1 & 2) vs. (1 && 2) discrepancy. decltype (talk) 17:27, 6 March 2010 (UTC)Reply
Not at all original research; on the contrary, it is original research to claim the opposite. C clearly does not have a separate Boolean type -- I think we all agree on that. If we are going to say it has Boolean operators at all, we must define them as those which take Boolean values as arguments and return Boolean values as results. What are Boolean values? The values produced by the standard relational operators like <, ==, etc. which are 0 and -1, and not 1 and 2.
The fact that & and | are extended/overloaded to operate on other values as well is a quirk of C semantics, no question, but it doesn't mean that & and | aren't Boolean operators.
Compare the situation in languages where "+" is overloaded to mean both arithmetic addition and string concatenation. The fact that 3+"a" yields a string doesn't mean that "+" isn't an arithmetic operator; it just means that it's also a string operator. --macrakis (talk) 19:50, 6 March 2010 (UTC)Reply
C does have a boolean data type, _Bool. & and |, however, are bitwise operators that take integers, such as 1 or 2, as arguments. It just so happens that for the values 0 and 1 the results are the same as for && and ||. That doesn't change the fact that their semantics are different. It is not uncommon to use values other than the ones produced by relational operators (0 and 1, not 0 and -1), as arguments to the logical operators. decltype (talk) 20:12, 6 March 2010 (UTC)Reply
This is the main part I take issue with: "If we are going to say it has Boolean operators at all, we must define them as those which take Boolean values as arguments and return Boolean values as results." I would say (again) that Boolean values in C are zero and non-zero, not zero and one. Yes, operators like == and && are explicitly defined to return only zero and one, but they gotta return something, and 1 is as good a non-zero value as any. The bitwise operators are the only operators in the entire language where "any non-zero value is true" doesn't hold. "One of these things is not like the other things..."
Also, I don't think type punning even enters the picture. I doubt K&R or even the ANSI standard committee ever intended & and | to function as logical operators; that they could be used that way is just coincidence. It's also worth noting that C++ does have both an explicit boolean type and operator overloading, and the operators still do not behave as expected; 3 & true returns true. Surely if the ANSI C++ committee wanted it to behave like a logical operator, it would return false.
To summarize: the bitwise operators are different in semantics, they're different in purpose, they're different in common usage, and they're only similar when you make contrivances for them that you don't need to make for other operators -- contrivances that the standard never requires you to make for true logical boolean operations. That's four arguments against (well, three if you count the last as a variation of the first), and so far I've only seen one real argument in favor. I think the case for inclusion in the table is looking pretty thin. - furrykef (Talk at me) 19:26, 7 March 2010 (UTC)Reply

I came here to see if anybody else mentioned what I thought was a mistake for C. I understand the argument for putting none there, but I'd like to see a footnote next to it. — Preceding unsigned comment added by 173.19.237.184 (talk) 01:46, 10 May 2015 (UTC)Reply

Poorly written edit

This entire article needs to be cleaned up. The summary, main content, and examples all seem to be written by a computer science professor trying to justify his education. This fairly simple topic should be easy to understand by someone with a basic knowledge of programming but I fear this article is a lot harder to understand than it needs to be. —Preceding unsigned comment added by 99.29.171.122 (talk) 17:21, 25 January 2010 (UTC)Reply

Is a warning about operator precedence needed? edit

Is a reminder about short-circuit not obviating operator precedence needed? A colleague of mine recently asserted that (in C++):

But parens shouldn't matter in this case since it is evaluated from left to right with short circuit. A && B || C should give the same as A && ( B || C ). A must be true to proceed. If you proceed, A is thrown away and now only B || C exist to be evaluated.

He then cited this Wikipedia page as evidence. Actually, in the first case A and B have to both be false for C to be evaluated, while in the 2nd case, If A is false, neither B or C will be evaluated. I cited Stroustrup "The C++ Programming Language (3rd Edition)" page #121, but he had to write a little truth-table program to convince himself. Dag in va (talk) 15:03, 11 May 2010 (UTC)Reply

(A && B) || C is certainly not equivalent to A && (B || C), but I don't see what this has to do with short-circuit evaluation. After all, they are different with non-short-circuit evaluation as well.
I re-read the article to see if there is some easy-to-misinterpret wording like "evaluated from left to right", but I couldn't see any. Can you point to the particular wording in the article that your colleague misinterpreted? Perhaps we can reword it to be clearer. --macrakis (talk) 17:05, 11 May 2010 (UTC)Reply
The colleague has back-pedalled now - says he didn't read it that closely, just assumed it backed his position! (Good ol' "ass-u-me' strikes again!) Dag in va (talk) 14:46, 12 May 2010 (UTC)Reply

Incorrectness w.r.t. Fortran edit

The Fortran language standard(s) (see e.g. section 6.6.1 of the FORTRAN77 or section 7.1.8.1 of the Fortran2003 standard) explicitely allow a 'processor' to perform short circuit evaluation. However, it is not required to happen. I am currently not sure, how to best represent this in the language overview table. Maybe with an entry of none in eager operators and .and., .or. in short-circuit operators combined with a footnote as for Pascal? InfoBroker2020 (talk) 11:16, 12 May 2010 (UTC)Reply

cleanup edit

* ALGOL68 (WTF?) paragraph removed
- irrelevant to the subject other than mentioning ALGOL - either rewrite it back in better fashion or keep it dead
* minor editorial (weasels, cits etc)
* ToC cleanup
* unneeded example removed
* code example simplified

cheers, and be bold, ppl. Vaxquis (talk) 19:07, 2 July 2010 (UTC)Reply

Ruby edit

The "&" in ruby is greedy --

irb(main):423:0> (1 == 2) & (Math::log(-1) < 2)
NoMethodError: undefined method `<' for (0.0+3.14159265358979i):Complex
from (irb):423
from /opt/local/bin/irb1.9:12:in `<main>'

Exactly. It doesn't short-circuit. That's why it is listed under the Eager operators column in the table. --71.141.138.20 (talk) 05:55, 14 July 2010 (UTC)Reply

It is still wrong edit

What is listed under Eager operators are `and`/`or`. This is not correct. They do short-circuiting, too:

   def t ; puts "TRUE"  ; true  ; end
   def f ; puts "FALSE" ; false ; end
   puts "and:"
   f and t
   puts "or:"
   t or f
   puts "&&:"
   f && t
   puts "||:"
   t || f

The difference between `and`/`or` and `&&`/`||` is the precedence behaviour.

   [
     %w(or and),     # same precedence
     %w(|| &&),      # && has higher precedence
   ].each { |o,a|
     [true,false].each { |a1|
       [true,false].each { |a2|
         [true,false].each { |a3|
           r0 = "(#{a1} #{o}  #{a2}) #{a} #{a3} "
           r1 = " #{a1} #{o}  #{a2}  #{a} #{a3} "
           r2 = " #{a1} #{o} (#{a2}  #{a} #{a3})"
           e0 = eval r0
           e1 = eval r1
           e2 = eval r2
           next if e0 == e2
           puts "#{r0}   #=>  #{e0}"
           puts "#{r1}   #=>  #{e1}"
           puts "#{r2}   #=>  #{e2}"
           puts
         }
       }
     }
     puts
   }

Yet, the bitwise operators `&`/`|` don't short-circuit.

Bertram Scharpf — Preceding unsigned comment added by 77.186.148.237 (talkcontribs) 17:50, 2 April 2024 (UTC)Reply

Indeed that was incorrect. I corrected it with a reference to [1]. Matma Rex talk 18:29, 2 April 2024 (UTC)Reply

Additional operators in Java and C# that short circuit edit

Java - the '?' operator definitely short-circuits C# - the '?' operator probably short-circuits and the '??' (Null Coalescing) operator definitely does

Should the row in the table for "C#, Java, MATLAB R" be split up? — Preceding unsigned comment added by 198.178.8.81 (talk) 21:23, 10 August 2012 (UTC)Reply

The MATLAB-entry might be worth a footnote, as the eager operator "&" behaves like a short-circuit operator when used in a statement following "if" or "while"; this is noted in the "Tips" Section of the documentation (https://de.mathworks.com/help/matlab/ref/and.html#bu46s7m-4). So it is not guaranteed to be "eager" in all cases. ChristophE (talk) 13:51, 21 September 2021 (UTC)Reply

Select/Case in VB edit

Could someone please explain how Select/Case in VB is related to short-circuit evaluation? As far as I can tell, it has nothing to do with it. --Macrakis (talk) 15:13, 18 December 2012 (UTC)Reply

Ternary operators edit

Shouldn't the table mention ternary operators like ?: in PHP? --217.110.53.72 (talk) 10:12, 6 July 2013 (UTC)Reply

Efficiency edit

This paragraph is peculiar:

If both expressions used as conditions are simple boolean variables, it can be faster to evaluate both conditions used in boolean operation at once, as it always requires one calculation cycle, versus one or two cycles used in short-circuit evaluation (depending on the value of the first). The difference in computing efficiency between these two cases depends heavily on compiler and optimizing scheme used. With proper optimizing, they will execute at the same speed, as they will get compiled to identical machine code.

If both expressions are simple boolean variables, then eager and lazy evaluation are semantically identical, so of course a decent compiler will generate the same code for them. In any case, this is an utterly trivial matter. I will remove this paragraph. --Macrakis (talk) 21:17, 4 October 2016 (UTC)Reply

Merge from Elvis operator edit

The following discussion is closed. Please do not modify it. Subsequent comments should be made in a new section. A summary of the conclusions reached follows.
No consensus to merge. Matma Rex talk 21:47, 1 November 2022 (UTC)Reply

In some languages, the Elvis operator ?: is a notation for a short-circuit or with last-value semantics. I see no reason to have a separate article for it -- and I see value in integrating it into the comparison table in this article. --Macrakis (talk) 20:19, 17 November 2020 (UTC)Reply

Merge See reasoning above. --Macrakis (talk) 20:19, 17 November 2020 (UTC)Reply
Because the Elvis operator has this meaning in some but not all languages, I oppose the merge as these are distinct topics best covered separately. Klbrain (talk) 17:02, 27 December 2021 (UTC)Reply
So what? Different languages have different operator sets and different syntax for them. Would you also want to see separate articles on or else, &&, etc.? --Macrakis (talk) 17:18, 5 February 2022 (UTC)Reply
Support. There is no single reason to keep an artical per every operator which evaluates to a similar result. I'm also going to propose to merge Null coalescing operator into this artcle because it's basically the same binary operation. AXONOV (talk) 11:12, 6 February 2022 (UTC)Reply
No — Short-circuit evaluation covers a principle whereas the Elvis and Null coalescing operators are specific operators. All three deserve an article — GhostInTheMachine talk to me 10:06, 11 February 2022 (UTC)Reply
So you think that the particular form of syntactic sugar used is worth an article? Should we also have separate articles for the conditional in Pascal "if ... then ...", Lisp "(cond (...) ...)", Scheme "(if ... ...)", C "if (...) ...", and Python "if ...: // ..."?
For that matter, the present article has a whole section on the varying operators used to represent short-circuit evaluation. What's so special about the Elvis syntax? --Macrakis (talk) 17:30, 28 March 2022 (UTC)Reply
Oppose merge, since it's going to be less helpful for a reader if we try to shove all the information from the elvis operator article in here (and I do think that information should be kept in Wikipedia), but I think it's fine to include the Elvis operator in the comparison table where appropriate. Dingolover6969 (talk) 09:15, 23 August 2022 (UTC)Reply
The discussion above is closed. Please do not modify it. Subsequent comments should be made on the appropriate discussion page. No further edits should be made to this discussion.

Additional bash operators edit

Bash has two additional operators that act like boolean ones[2]:

declare out=${foo:-$bar} # out = foo || bar 
declare out=${foo:+$bar} # out = foo  ? bar : ''
            ${out:=$foo} # out = out || foo
            ${foo:?$bar} # if foo is nullish, print $bar value as an error message

The first one is basically a null coalescing operator. I propose to add all of them. Any objections? AXONOV (talk) 10:53, 6 February 2022 (UTC)Reply

Merge from Null coalescing operator edit

The following discussion is closed. Please do not modify it. Subsequent comments should be made in a new section. A summary of the conclusions reached follows.
To not merge given that these are distinct topics best covered separately. Klbrain (talk) 00:09, 24 August 2022 (UTC)Reply

The same as above discussion about Elvis operator. I propose we merge Null coalescing operator and leave redirections in place as there are basically no differences sshort circuit evaluation. Objections? --AXONOV (talk) 11:21, 6 February 2022 (UTC)Reply

Survey
Support as nom per reasons of WP:REDUNDANT. We don't need multiple articles covering the same topic. --AXONOV (talk) 11:21, 6 February 2022 (UTC)Reply
No — Short-circuit evaluation covers a principle whereas the Elvis and Null coalescing operators are specific operators. All three deserve an article — GhostInTheMachine talk to me 10:06, 11 February 2022 (UTC)Reply
No as per GhostInTheMachine's response, they deserve separate articles rather than a discombobulation of multiple topics in a single article. DevSpenpai::talk 16:35, 28 March 2022 (UTC)Reply
Oppose as per my opposition to the other merge, but also because the NCO is specifically, like, a short-circuit OR for nulls. That's the basic difference. I think that difference is enough. After all, XOR is just OR, but, like, not both, and it gets its own article. Ternary operator is basically just an if statement that evaluates to something, and it gets its own article. Plenty of languages have both sc-|| and nco, and the distinction is very important if they have both boolean/falsy types and nulls. I believe it's useful to the reader if we're able to cover them both in-depth, cross-linking as appropriate. Dingolover6969 (talk) 09:22, 23 August 2022 (UTC)Reply
The discussion above is closed. Please do not modify it. Subsequent comments should be made on the appropriate discussion page. No further edits should be made to this discussion.