Reasons NOT to use short-circuit evaluation: Because it will behave differently and produce different results if your functions, property Gets or operator methods have side-effects. And this may conflict with: A) Language Standards, B) previous versions of your language, or C) the default assumptions of your languages typical users. These are the reasons that VB has for not short-circuiting Because you may want the complier to have the freedom you reorder and prune expressions, operators and sub-expressions as it sees fit, rather than in the order that the user typed them in.
These are the reasons that SQL has for not short-circuiting (or at least not in the way that most developers coming to SQL think it would). Thus SQL (and some other languages) may short-circuit, but only if it decides to and not necessarily in the order that you implicitly specified I am assuming here that you are asking about "automatic, implicit order-specific short-circuiting", which is what most developers expect from C,C++,C#,Java, etc. Both VB and SQL have ways to explicitly force order-specific short-circuiting. However, usually when people ask this question it's a DWIM* question, that is they mean "why doesn't it Do What I Want?
", as in, automatically short-circuit in the order that I wrote it DWIM = "Do What I Meant.
Reasons NOT to use short-circuit evaluation: Because it will behave differently and produce different results if your functions, property Gets or operator methods have side-effects. And this may conflict with: A) Language Standards, B) previous versions of your language, or C) the default assumptions of your languages typical users. These are the reasons that VB has for not short-circuiting.
Because you may want the complier to have the freedom you reorder and prune expressions, operators and sub-expressions as it sees fit, rather than in the order that the user typed them in. These are the reasons that SQL has for not short-circuiting (or at least not in the way that most developers coming to SQL think it would). Thus SQL (and some other languages) may short-circuit, but only if it decides to and not necessarily in the order that you implicitly specified.
I am assuming here that you are asking about "automatic, implicit order-specific short-circuiting", which is what most developers expect from C,C++,C#,Java, etc. Both VB and SQL have ways to explicitly force order-specific short-circuiting. However, usually when people ask this question it's a DWIM* question, that is they mean "why doesn't it Do What I Want?", as in, automatically short-circuit in the order that I wrote it. *- DWIM = "Do What I Meant.
1: VB was the first programming language I learned (besides web-based stuff) and because it didn't have short-circuiting, I had to learn what it was the hard way when I learned C. – Carson Myers Sep 18 '09 at 17:47 1 +1. Although I suppose on point 2, the compiler could be allowed to short-circuit either part of the expression depending on its preferences - it doesn't have to do it in the order the user typed them in.
– MarkJ Sep 18 '09 at 17:54 +1 for mentioning SQL. – Daniel Pryden Sep 18 '09 at 17:54 2 @MarkJ: No, it cannot. Think of the Java expression (thing == null || thing.getField() == 1).
– Dirk Sep 18 '09 at 17:56 2 (cont’d) Saying that VB doesn’t “have impliciy implicit or default short-circuiting†is like saying that C# doesn’t have it and in either case, it’s just plain wrong. If you use And in a conditional statement in VB you are committing a semantical mistake just as if you were using & in a conditional statement in C#, and the compiler will issue an error accordingly. So Kibbee is wrong as well: VB doesn’t give you the choice in that matter either (unless you were referring to Option Strict).
There’s a clear semantical distinction between logical operations and bit operations. – Konrad Rudolph Sep 18 '09 at 20:39.
One benefit I can think of is that some operations might have side-effects that you might expect to happen. Example: if (true || someBooleanFunctionWithSideEffect()) { ... } But that's typically frowned upon.
This is similar to superjoe30's answer (increment y each time). The argument against this is to run someBooleanFunctionWithSideEffect() and assign the result so you can later test it. Doing so is much clearer and easier to read and understand what is happening – shufler Sep 18 '09 at 17:41 2 Yes, which is why I say that my example is frowned upon.
– Ben S Sep 18 '09 at 17:42 1 unless you want someBooleanFunctionWithSideEffect() to only perform its side effect if the first operation was false. – Carson Myers Sep 18 '09 at 17:45 1 @Carson Myers: Then you should probably have another if block demonstrating that logic. – Ben S Sep 18 '09 at 17:46.
Look at my example at On SQL Server boolean operator short-circuit which shows why a certain access path in SQL is more efficient if boolean short circuit is not used. My blog example it shows how actually relying on boolean short-circuit can break your code if you assume short-circuit in SQL, but if you read the reasoning why is SQL evaluating the right hand side first, you'll see that is correct and this result in a much improved access path.
Ada does not have it by default. In order to get short-circut you have to use "and then" or "or else" instead of "and" or "or". I believe the issue was that there are some circumstances where it actually slows things down.
If the second condition is quick to calculate and the first condition is almost always true for "and" or false for "or", then the extra check-branch instruction is kind of a waste. However, I understand that with modern processors with branch predictors, this isn't so much the case. I've heard objections that it can lead to unexpected behavior of the code in the case where the second test has side effects.
IMHO it is only "unexpected" if you don't know your language very well, but some will argue this. In case you are interested in what actual language designers have to say about this issue, here's an excerpt from the Ada 83 (original language) Rationale: The operands of a boolean expression such as A and B can be evaluated in any order. Depending on the complexity of the term B, it may be more efficient (on some but not all machines) to evaluate B only when the term A has the value TRUE.
This however is an optimization decision taken by the compiler and it would be incorrect to assume that this optimization is always done. In other situations we may want to express a conjunction of conditions where each condition should be evaluated (has meaning) only if the previous condition is satisfied. Both of these things may be done with short-circuit control forms ... In Algol 60 one can achieve the effect of short-circuit evaluation only by use of conditional expressions, since complete evaluation is performed otherwise.
This often leads to constructs that are tedious to follow... Several languages do not define how boolean conditions are to be evaluated. As a consequence programs based on short-circuit evaluation will not be portable. This clearly illustrates the need to separate boolean operators from short-circuit control forms.
1 VB uses the same concept, except that VB has AndAlso, and OrElse if you want short circuiting. – Kibbee Sep 18 '09 at 19:04 @Kibbee: Sorry but you are mistaken. You are confusing bit operations with logical operations and are probably using Option Strict Off which allows more lax type checking.
Nonetheless, there’s a clean semantical distinction between the two operations and the bit operations were never meant for conditionals in VB. NET (if they were, they would still work with Option Strict On which they don’t). – Konrad Rudolph Sep 18 '09 at 20:41 @Konrad - I'm sure you know the And and Or operators in VB.NET were left as is for legacy purposes from older versions of VB.
But they can still be used for conditional statements (albeit 99% of the time the short-circuiting logical operators are preferred). But your statement about Option Strict is incorrect. All Option Strict On does is prevent implicit conversion.
As long as you're not doing that then the bitwise And and Or operators will indeed work for conditional statements. – Steve Wortham Sep 18 '09 at 22:05 I don't know about VB, but in languages I do know a bitwise and is a very different animal than a boolean and. For example, in C '2 && 1' is true, while '2 & 1' is false (none of the same bits are set in the two operands).
– T.E.D. Sep 18 '09 at 13:43 @Konrad, you can still use And or Or with Option Strict On. The very first line of the And Operator in the VB Language Reference is: "Performs a logical conjunction on two Boolean expressions, or a bitwise conjunction on two numeric expressions" It's an overload, and And is fine as long as you use booleans on either side and not numerics. – Richard Gadsden Sep 18 '09 at 15:31.
Bill has alluded to a valid reason not to use short-circuiting but to spell it in more detail: highly parallel architectures sometimes have problem with branching control paths. Take NVIDIA’s CUDA architecture for example. The graphics chips use an SIMT architecture which means that the same code is executed on many parallel threads.
However, this only works if all threads take the same conditional branch every time. If different threads take different code paths, evaluation is serialized – which means that the advantage of parallelization is lost, because some of the threads have to wait while others execute the alternative code branch. Short-circuiting actually involves branching the code so short-circuit operations may be harmful on SIMT architectures like CUDA.
€“ But like Bill said, that’s a hardware consideration. As far as languages go, I’d answer your question with a resounding no: preventing short-circuiting does not make sense.
I'd say 99 times out of 100 I would prefer the short-circuiting operators for performance. But there are two big reasons I've found where I won't use them. (By the way, my examples are in C where && and || are short-circuiting and & and | are not.) 1.
) When you want to call two or more functions in an if statement regardless of the value returned by the first. If (isABC() || isXYZ()) // short-circuiting logical operator //do stuff; In that case isXYZ() is only called if isABC() returns false. But you may want isXYZ() to be called no matter what.
So instead you do this: if (isABC() | isXYZ()) // non-short-circuiting bitwise operator //do stuff; 2. ) When you're performing boolean math with integers. MyNumber = I && 8; // short-circuiting logical operator is not necessarily the same as: myNumber = I & 8; // non-short-circuiting bitwise operator In this situation you can actually get different results because the short-circuiting operator won't necessarily evaluate the entire expression.
And that makes it basically useless for boolean math. So in this case I'd use the non-short-circuiting (bitwise) operators instead. Like I was hinting at, these two scenarios really are rare for me.
But you can see there are real programming reasons for both types of operators. And luckily most of the popular languages today have both. Even VB.
NET has the AndAlso and OrElse short-circuiting operators. If a language today doesn't have both I'd say it's behind the times and really limits the programmer.
2 If you want to evaluate the second expression, make it explicit! Do not use arcane code like the above, it’s extremely hard to read and thus prone to misunderstanding. Likewise for Boolean math.
– Konrad Rudolph Sep 18 '09 at 18:24 I see what you're getting at now. I wrote it the way I did to make it easier to illustrate the difference. – Steve Wortham Sep 18 '09 at 18:57 Heh, that's funny.
I've known C since the mid 80's, and it had never occurred to me to use the bitwise operators to get the effect of a non-short circuit boolean check. It's kinda dangerous, as the bitwise and won't work the way you want if the two values are non-zero but happen to have different bits set. Still, its an interesting hack.
The only safe way to do it in C is to save both calculations into temporaries and check those with the boolean operator. – T.E.D. Sep 18 '09 at 19:35 1 While "if (abc() | xyz())" is usually the same as "if (abc() || xyz())" except for the evaluation of xyz(), remember that "if (abc() & xyz())" is NOT the same as "if (abc() && xyz())" - consider what happens if abc() returns 1 and xyz() returns 2. That's why I'd strongly advise not writing a boolean with "|"; it means you're likely to do it with "&".
– David Thornley Sep 18 '09 at 19:41 @David - I was imagining that abc() and xyz() would both return boolean values. Your point is well taken though. It's what I was trying to illustrate in #2 (the whole boolean math thing).
– Steve Wortham Sep 18 '09 at 22:25.
If you wanted the right hand side to be evaluated: if( x 10 ) printf("do something\n"); Perhaps you wanted y to be incremented whether or not x.
I don't see a boolean expression in that code – Carson Myers Sep 18 '09 at 17:48 @Carson - The condition is in the pipe (|) which is designed as a bitwise 'or' operator with no short-circuiting. It's usually used for things like boolean math but it can be used in conditional statements as well. The circumstances in which you'd want to do this are rare, but you do at least have the option.
– Steve Wortham Sep 18 '09 at 22:19.
The Ada programming language supported both boolean operators that did not short circuit (AND, OR), to allow a compiler to optimize and possibly parallelize the constructs, and operators with explicit request for short circuit (AND THEN, OR ELSE) when that's what the programmer desires. The downside to such a dual-pronged approach is to make the language a bit more complex (1000 design decisions taken in the same "let's do both! " vein will make a programming language a LOT more complex overall;-).
1 -1 for talking about Ada in the past sense. The old gal's not dead yet – Pete Kirkham Sep 18 '09 at 17:47 True. However Ada generally errs on the side of simplicity and leaving decisions up to the compiler, so it had some room to spare in this direction.
The language has fewer keywords than C++, and its entire BNF syntax fits on about 6 pages. A lot of that is to support things that C++ doesn't have, like specifically layout the exact location and offset of every record field, or specify threading and synchronization. If you were to stick to a C or C++-like subset of the language, it is actually much simpler than either.
– T.E.D. Sep 18 '09 at 17:58.
Not that I think this is what's going on in any language now, but it would be rather interesting to feed both sides of an operation to different threads. Most operands could be pre-determined not to interfere with each other, so they would be good candidates for handing off to different CPUs. This kins of thing matters on highly parallel CPUs that tend to evaluate multiple branches and choose one.It's a bit of a stretch but you asked "Why would a language"... not "Why does a language".
Even if the language doesn't do it in multiple threads a program compiled to machine code might benefit from not having short circuit. This is because processors pipeline the operations they are doing and if they know then need to evaluate both sides it can pipeline the whole thing without having to account for rollback. However, if there is short circuit evaluation then it adds another branch in the code that either stops the pipeline or the processor has to account for rollback.
– tster Sep 18 '09 at 18:43.
The language Lustre does not use short-circuit evaluation. In if-then-elses, both then and else branches are evaluated at each tick, and one is considered the result of the conditional depending on the evaluation of the condition. The reason is that this language, and other synchronous dataflow languages, have a concise syntax to speak of the past.
Each branch needs to be computed so that the past of each is available if it becomes necessary in future cycles. The language is supposed to be functional, so that wouldn't matter, but you may call C functions from it (and perhaps notice they are called more often than you thought). In Lustre, writing the equivalent of if (y 0) then 100/y else 100 is a typical beginner mistake.
The division by zero is not avoided, because the expression 100/y is evaluated even on cycles when y=0.
1 Interesting language. How would you avoid dividing by 0 then? – Bill Sep 18 '09 at 18:19 Probably the old-fashioned way: Nested ifs.
– T.E.D. Sep 18 '09 at 19:19 @Bill The '/' is in fact a call to the division of C. One way to avoid the division by zero is to replace it by a call to a "safe" division function that tests for zero. The recommended way would be to use "sampling" to create a ("slower") stream that contains only the non-zero values of y.
A better link for Lustre than the Wikipedia page that I gave is www-verimag.imag. Fr/PEOPLE/Pascal. Raymond/edu/eng/lustre-a.
Pdf – Complicated see bio Sep 18 '09 at 19:25 Wouldn't it make sense to allow the short-circuiting operators in cases like this, and have the compiler use sampling? And how do you write a safe division function? – David Thornley Sep 18 '09 at 19:49.
Because short-circuiting can change the behavior of an application IE: if(!SomeMethodThatChangesState() ||! SomeOtherMethodThatChangesState()).
1 And using short circuiting will help to get rid of these type of statements. – Cem Kalyoncu Sep 18 '09 at 17:41.
As a stretch: If you wanted a language to be super secure (at the cost of awesomeness), you would remove short circuit eval. When something 'secure' takes a variable amount of time to happen, a Timing Attack could be used to mess with it. Short circuit eval results in things taking different times to execute, hence poking the hole for the attack.In this case, not even allowing short circuit eval would hopefully help write more secure algorithms (wrt timing attacks anyway).
I'd say it's valid for readability issues; if someone takes advantage of short circuit evaluation in a not fully obvious way, it can be hard for a maintainer to look at the same code and understand the logic. If memory serves, erlang provides two constructs, standard and/or, then andalso/orelse . This clarifies intend that 'yes, I know this is short circuiting, and you should too', where as at other points the intent needs to be derived from code.As an example, say a maintainer comes across these lines: if(user.inDatabase() || user.
InsertInDatabase()) user.DoCoolStuff(); It takes a few seconds to recognize that the intent is "if the user isn't in the Database, insert him/her/it; if that works do cool stuff". As others have pointed out, this is really only relevant when doing things with side effects.
You can write obscure code with any constructs. Trust me on this. – David Thornley Sep 18 '09 at 19:44 I don't doubt it, but the point of the language is to try and make it ever so slightly more difficult to be unclear.
– CoderTao Sep 18 '09 at 19:59 Well... most languages at least. INTERCAL is still a special case. – CoderTao Sep 18 '09 at 20:29.
I don't know about any performance issues, but one possible argumentation to avoid it (or at least excessive use of it) is that it may confuse other developers.
There are already great responses about the side-effect issue, but I didn't see anything about the performance aspect of the question. If you do not allow short-circuit evaluation, the performance issue is that both sides must be evaluated even though it will not change the outcome. This is usually a non-issue, but may become relevant under one of these two circumstances: The code is in an inner loop that is called very frequently There is a high cost associated with evaluating the expressions (perhaps IO or an expensive computation).
1 You must have missed my answer then. In fact, there are some circumstances where it could be faster to not use short-circuit. That is why Ada gives you both forms.
– T.E.D. Sep 18 '09 at 19:23 Sorry there were a lot of answers already :-) – Eric J. Sep 18 '09 at 19:52.
The short-circuit evaluation automatically provides conditional evaluation of a part of the expression. The main advantage is that it simplifies the expression. The performance could be improved but you could also observe a penalty for very simple expressions.
Another consequence is that side effects of the evaluation of the expression could be affected. In general, relying on side-effect is not a good practice, but in some specific context, it could be the preferred solution.
VB6 doesn't use short-circuit evaluation, I don't know if newer versions do, but I doubt it. I believe this is just because older versions didn't either, and because most of the people who used VB6 wouldn't expect that to happen, and it would lead to confusion. This is just one of the things that made it extremely hard for me to get out of being a noob VB programmer who wrote spaghetti code, and get on with my journey to be a real programmer.
Yes, newer versions definitely do use short-circuiting (AndAlso, OrElse, which is good VB parlance). VB1–6 was just handicapped that way. – Konrad Rudolph Sep 18 '09 at 18:18 so it's like Ada in that it has an extra, short-circuiting keyword?
I'll have to remember that in case I start using VB again – Carson Myers Sep 19 '09 at 7:51.
A language not use short - circuit evaluation would a language not use short-circuit evaluation because (without quotes):.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.