in reply to Re^30: Why is the execution order of subexpressions undefined? (magic ruts)
in thread Why is the execution order of subexpressions undefined?

In code with undefined EO, we still have some defined order. They're called "sequence points". And that is anywhere you see ";", ",", "(...)", "||", "&&", "or", "and". So, if I want to define an order, I can use temporary variables:

my $var = do { my $temp1 = func1($a); my $temp2 = func2(++$a); $temp1 + $temp2; };
Here is a single statement with multiple sequence points. I know that func1 will be passed the original $a value. I know that $a will be incremented prior to entering func2 (the parens become a sequence point), and that func2 will get that incremented value. And that $var will be the sum of the return values from the two functions. If func1 has side effects that affect func2, then I know that func1 will finish prior to caling func2, and those side effects will occur.

Compare with:

my $var = func1($a) + func2($a + 1);
The compiler is free to do this in any order it pleases. Even parallel. Side effects from func1 will not be guaranteed to occur prior to executing func2. Thus, with undefined EO, the programmer is asserting that there are no such side effects. If the compiler wants to run func1 and func2 in separate threads and combine their return value, that's fine by the programmer. The programmer has a degree of freedom here to choose one of the two methods depending on whether there are side effects or not.

With defined EO, the programmer has no freedom. There is no way to express the idea that "these may be parallelised." That's because defined EO defines, well, an Execution Order. That something completes prior to something else. And that is the definition of serial. The closest that we get to allowing a programmer to do this in parallel is:

my $var = do { my ($temp1, $temp2); my $thr1 = threads->new(sub { $temp1 = func1($a) })->start; my $thr2 = threads->new(sub { $temp2 = func2($a+1) })->start; $thr1->join; $thr2->join; $temp1 + $temp2 };
Now, if the argument for EO is that this convoluted syntax would require programmers to really think hard before doing anything with threading, I could buy that a bit more. If perl (5 or 6) ever started auto-threading functions, I'm sure a lot of code would break. However, I would prefer undefined EO, and simpler syntax:
AUTOTHREADSUBEXPRS { $var = func1($a) + func2($a+1); }
Or something like that. Or a pragma of some sort:
use threadedsubexprs; my $var = func1($a) + func2($a+1);
These only work when the EO remains undefined and make zero sense when EO is defined.

Summary - I think I showed exactly how undefined EO still allows a programmer to convey requirements for execution ordering to the compiler. I've gone further - I've shown how EO definition merely changes how much work it is to either define execution order, or to get a pseudo-random execution order (via threads). Please stop making claims to the contrary. Thanks.

Replies are listed 'Best First'.
Re^32: Why is the execution order of subexpressions undefined? (magic ruts)
by Anonymous Monk on Apr 18, 2005 at 08:49 UTC
    Parenthesis are strictly for the parser. Parenthesis do not create lists, and they do not create sequence points. Parenthesis define precedence. In:
    (f(a) + g(b)) * h(c)
    the run-time is free to calculate g(b), h(c), f(a) in that order.

    IMO, it should even be free to not calculate f(a) or g(b) if it finds h(c) to be 0. But that's just me.

      What if f(a) or g(b) returns Inf?
        Then, IMO, the expression should still return 0.

      What if f(), g() and h() get their values from arrays (or external sources) in lockstep? Ie. each call returns the next value from it's respective source.

      The compiler arbitrarially opts to not call some of those functions when one of them returns 0, all subsequent calculations are wrong because the sequences are no longer in step. Is 0 a second class number?

      So now the only way to avoid the compiler subverting what the programmer know he needs is for the programmer to play hostage to the compiler and code:

      my $temp1 = f(a); my $temp2 = g(b); my $temp3 = h(c); my $result = ($temp1 + $temp2) * $temp3;

      You call that an optimisation? That is so ludicrous as to be laughable, except it is where thing stand right now--and, on the basis of majority opinion in this thread, the way it is likely to be in the future. No that is laughable!


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco.
      Rule 1 has a caveat! -- Who broke the cabal?
        So now the only way to avoid the compiler subverting what the programmer know he needs is for the programmer to play hostage to the compiler and code
        Well, either that or avoid side-effects in your functions. Is that really so much to ask? You do realize you should try to minimize the use of side-effects in general, right? Just like you should limit your use of global variables and gotos?
        Replace + with ||, and * with &&.

        Still ludicrous?

A reply falls below the community's threshold of quality. You may see it by logging in.