Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: Why is the execution order of subexpressions undefined? (why not?)

by tye (Sage)
on Apr 12, 2005 at 04:25 UTC ( [id://446837]=note: print w/replies, xml ) Need Help??


in reply to Why is the execution order of subexpressions undefined?

Why should it be strictly defined? Why tie your hands so thoroughly?

There really isn't some one compelling argument on either side.

There are advantages to defining the order of things and advantages to leaving the order of things unspecified. Your question really boils down to "Why don't we define the order of everything?". And I think it doesn't take much contemplation to realize that the middle ground is the place to be.

Perl goes futher than C in defining the order of some things. There is advantage in knowning that ( foo(), bar() )[-1] will call foo() before it calls bar(). It allows you to express some complex instructions in concise ways (which is a very Perlish thing to allow).

A similar expression in C might call the functions in either order, depending on the implementation. There is good reason for this. C runs on systems were the low-level calling conventions specified that you pushed the first argument first (and where C wanted to use the same conventions to ease interoperability with the non-C routines on such systems) but C also runs on systems that take good advantage of pushing the first argument last (which allows you to pass in extra arguments with little impact). Overspecifying such things could mean slower code on some system (having to compute the values in one order and then push them onto the stack in the reverse order) that was also more complicated and more likely to be buggy.

To go all the way in one direction would require writing up all of the details of exactly how order is determined and require a lot of work to figure out all of the bugs in this specification and the implementation. It just isn't worth the small gain of being able to define exactly how things happen even if you write something that most people won't have a good feel for exactly in what order it should be evaluated.

Leaving some things unspecified gives you the freedom to re-implement things in a way that makes more sense, is more efficient, or to just not have to sweat so dang much when making a trivial change because it might have some subtle effect of the order of evaluation of some convoluted expression that noone should have to bother to figure out exactly what order it should be evaluated in.

You define what it makes sense to nail down and give warning that the rest may or may not change because the work hasn't been done to define exactly how it must stay the same and there may be a real benefit to changing it some day (like the real benefit of recently making the order of hash keys vary between runs of the same Perl script).

A major goal of Perl 6 is to support code optimization. If you over-specify the order of evaluation, then you lose the ability to perform some optimizations. You can't move opcodes around to take advantage of efficient ways of combining certain things.

The reason that sometimes the fact that some orders are not defined is so pointedly noted is that people have a tendency to assume that once they figure out X, that X will always be true. You can see it happening with the expression you posted. Some people have already convinced themselves that they know exactly what order things are done and why and even say things like "It must be this way to allow ..." and then they go and write code that breaks if things aren't exactly the way they think they must be (I'm not saying that ikegami writes such code, just that ikegami has demonstrated the first step or two along that path to doom).

And that scenario is worse than having the order exactly specified, because you have different groups tying peoples' hands in different ways for no benefit. So it is important to at least occasionally beat people up and remind them that some things are not defined and if they depend on them being one particular way, the fact that it works for them now doesn't mean it will always work.

- tye        

  • Comment on Re: Why is the execution order of subexpressions undefined? (why not?)
  • Download Code

Replies are listed 'Best First'.
Re^2: Why is the execution order of subexpressions undefined? (why not?)
by BrowserUk (Patriarch) on Apr 12, 2005 at 05:24 UTC
    Why tie your hands so thoroughly?

    I don't think it would tie my hands (where I am the Perl 6 programmer? Indeed, I think that it would free me from having to consider whether I am writing an expression that could have dependancy issues--which is the basic reason for my asking if it would be possible and if so, what penalties it would carry.

    It may tie the hands of the Perl 6 compiler/interpreter writer to some degree, but I think that this is much less than you are implying. I've been playing around with some expression parsing code and I've reached the conclusion that the only time that execution order could be varied in a way that might be an optimisation is when dealing with native integer manipulations. There are occasionally some small gains to be had by reordering operations on integers and uints that allow you to avoid performing intermediate stores by retaining them in a register across higher level sub-expression boundaries.

    But not only are these rare, you cannot generate these occasions directly from your Perl code--as far as I can see. All Perl level manipulations involve PMCs, which are effectively objects and all operations will (again, as far as I can see) be effected through method calls. The order of execution of the Perl level subexpressions will be a chain of load a VM register, index through the vtable, call the methods, move onto the next subexpression. There is no scope for optimations across those boundaries that I can see.

    There is potentially scope for optimisation across method call boundaries once the code has been JITed, but that would require a very clever machine-code level optimiser capable of performing out-of-order execution analysis, and would obviously need to be specific to the processor upon which it runs. Do you envisage Parrot providing that level of optimiser?

    If I am right, and it's not possible to optimise across perl-level subexpression boundaries--which would mean that there would be no point in moving (Parrot-level) opcodes around--then defining an execution order could be beneficial by removing another level on uncertainty from the Perl code. And noone would have to beat anyone up for writing code that different implementations might choose to execute differently on some whim.

    I'm also not at all sure that the task of specifying the execution order is that onerous either. There are, as far as I can tell, actually not that many situations where the execution order isn't aready well-defined by context and other influences, but I'm not very sure of my ground here. Is there a document that identifies when the execution or is not well-defined?

    So, in answer to your question:

    Why should it be strictly defined?

    Because it would save me guessing when the were not, and anything that removes uncertainty is a good thing--I think. But I am not sure, hence my question.


    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?
Re^2: Why is the execution order of subexpressions undefined? (why not?)
by ikegami (Patriarch) on Jul 14, 2006 at 17:46 UTC
    Some people have already convinced themselves that they know exactly what order things are done and why and even say things like "It must be this way to allow ..."

    I don't know how I could have convinced myself I "know exactly what order things are done and why" when I specifically mentioned I didn't know whether execution order is defined in this circumstance.

    "It" in "It must be this way to allow ..." refers to passing by reference, not execution order. There is no way of allowing $_[0] = ... to edit the caller's variable without passing the variable in by reference (by definition). Perl5 doesn't currently have a mechanism to specify whether a variable should be passed by value or by reference (or maybe it does and it wasn't used here), so everything must be passed by reference to allow $_[0] = ... to edit the caller's variable.

    My post only explains why ++$i affected the $i, nothing more.

      Sure it does. func( $pass_by_reference, "$pass_by_value" ). You can do that to strings, booleans, and numbers easily. Use Storable::dclone() if you want to pass in an object or data structure as a value.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        The new value is still passed by reference, but all of this is besides the point. As I said, such mechanisms weren't used.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://446837]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2024-04-18 01:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found