in reply to Re^7: next unless condition
in thread next unless condition

I'm curious, though... Could you name a couple of languages in which the order of operations is not guaranteed? I don't think I've ever seen one myself and I have a hard time imagining the practical use of having an indeterminate order of operations.

Besides FORTRAN, which hippo mentioned, C also doesn't guarantee order of evaluation

Update: Apparently, logical or (and, presumably logical and) does have its evaluation order specific in the C11 standard. (pointed out by Athanasius)

Not all programming languages allow the use of if or unless as statement modifiers, nor the use of else in that fashion. If using or for flow control is bad practice because it's not reliable in other languages, then surely the use of statement modifiers is just as bad.

There's a difference between "not reliable" and "not supported".

Proper evaluation of or doesn't require a particular order for evaluating its operands to get the correct result. This is because or is transitive. The compiler is free to evaluate the operands as is convenient. It could even turn the operand expressions into tasks that a multi-threaded CPU could execute in parallel.

Update: Correction: The proper term is "commutative", not "transitive". (thanks, Athanasius)

Statement modifiers are not transitive. They intrinsically require a particular order of evaluation. if, as a statement modifier, requires right-to-left evaluation of its operands to produce a correct result. An else modifier would require left-to-right evaluation. The compiler doesn't get to choose which order is more convenient.

While, in Perl, the intent of something or die; is reasonably clear, something or something_else; is not as clear. While it being in void context might imply intent, it could just as easily be a mistake.

something else something_else; would be unambiguous in its intent.

As a native speaker of English, I find "open or die" to be a vastly clearer statement of intent than "open else die".

The computer is not. And I would say that the "die" part of "or die" is what gives that its clarity. And while common use of English encourages left-to-right evaluation, "something_else or something" is a fully valid, English interpretation of "something or something_else".

Replies are listed 'Best First'.
Re^9: next unless condition
by Athanasius (Archbishop) on Apr 06, 2016 at 07:57 UTC

    Hello RonW,

    I’m sorry, but you’re wrong about C:

    C also doesn't guarantee order of evaluation
    ...
    Proper evaluation of or doesn't require a particular order for evaluating its operands to get the correct result. This is because or is transitive.

    To take the last part first: logical or can’t be transitive, because transitivity applies only to those operators which are also relations, and logical or is not a relation. But suppose it were; and let propositions p, q, r have values false, true, false, respectively. Then p OR q is true, because false OR true is true; and q OR r is also true, because true OR false is true; so, by transitivity, p OR r should also be true. But it isn’t, because false OR false is false.

    Now to the important issue. The C standard does guarantee the order of evaluation for logical OR (||):

    Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of the first and second operands. If the first operand compares unequal to 0, the second operand is not evaluated.1

    To the best of my knowledge, this has always been an important feature of C. This is true for logical AND (&&) as well as logical OR. For example, when dealing with pointers it is often necessary to test whether the pointer is null before attempting a dereference:

    int *p; ... if (p && *p > 10) ...

    If the order of evaluation of logical AND (&&) were not guaranteed by the C standard (as it is2), the *p operation could be performed on a null pointer before the pointer is checked, causing the program to segfault. This possibility is explicitly excluded by the standard.

    1The C11 Standard, document WG14 N1570 (working paper, 2011-04-12), downloaded from here. The behaviour of the logical OR operator is specified in section 6.5.14, paragraph 4.
    2Ibid, section 6.5.13, paragraph 4.

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Quirks and programming. The topic reminded me of an old C book flush with anecdotal wisdom and insight (though old by now: it predates C99). The following note is preserved there:

      From decvax!harpo!npoiv!alice!research!dmr
      Date: Fri Oct 22 01:04:10 1982
      Subject: Operator precedence
      Newsgroups: net.lang.c
      
      The priorities of && || vs. == etc. came about in the following way.
      
      Early C had no separate operators for & and && or | and ||. (Got that?) Instead it used the notion (inherited from B and BCPL) of "truth-value context": where a Boolean value was expected, after "if" and "while" and so forth, the & and | operators were interpreted as && and || are now; in ordinary expressions, the bitwise interpretations were used. It worked out pretty well, but was hard to explain. (There was the notion of "top-level operators" in a truth-value context.)
      
      The precedence of & and | were as they are now. Primarily at the urging of Alan Snyder, the && and || operators were added. This successfully separated the concepts of bitwise operations and short-circuit Boolean evaluation. However, I had cold feet about the precedence problems. For example, there were lots of programs with things like
      
      	if (a==b & c==d) ...
      
      In retrospect it would have been better to go ahead and change the precedence of & to higher than ==, but it seemed safer just to split & and && without moving & past an existing operator. (After all, we had several hundred kilobytes of source code, and maybe 3 installations....)
      
      Dennis Ritchie 
      

      So, yes, the short-circuiting behavior was part of C from very beginning, even before logical && || were introduced. (And the explanation why bitwise operators have the wrong precedence in C and most other C-like languages.)

        Wow. So Perl wasn't the first to introduce "context"!

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,