Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

surprising backwards evaluation order

by fizbin (Chaplain)
on Mar 17, 2006 at 20:03 UTC ( #537549=perlquestion: print w/replies, xml ) Need Help??

fizbin has asked for the wisdom of the Perl Monks concerning the following question:

So in the process of getting enlightened about a syntax misunderstanding, I ran across this oddity:

First, look at this code and ask yourself what you think it should produce:

sub ctx { print "$_[0] "; \&ctx; } ctx(1)->(2,ctx(3),ctx(4))->(5,ctx(6))->(7,ctx(8)); print "\n";

No peaking; take a guess first

That code produces

8 6 3 4 1 2 5 7

Now, I'm pretty sure we all agree that 7 has to be last, and obviously 2 must be printed later than both 3 and 4, and also 5 must be printed later than 6, but what about the rest?

It appears that this order is the logical result of perl evaluating &{func }(args ) by evaluating args first, (left to right), and then evaluating func.

This strikes me as an odd choice - it goes against the left-to-right evaluation order that perl follows elsewhere. (well, except for if and other control constructs at the end of a statement) Do any monks familiar with language implementation in general have any insight into why things are done that way?

Note that an interesting consequence of this is that the following both die with the message "TWO":

perl -e '&{die("ONE")}(die("TWO"))' perl -e 'die("ONE")->(die("TWO"))'
@/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/; map{y/X_/\n /;print}map{pop@$_}@/for@/

Replies are listed 'Best First'.
Re: surprising backwards evaluation order
by diotalevi (Canon) on Mar 17, 2006 at 20:21 UTC

    It's undefined whether perl evaluates ->( ... ) before or after func. It has to have evaluated both prior to calling func with the arguments but before that it's completely up in the air about which happens first. One thing to note, the comma operator has explicit order of operation. It evaluates the argument to tit's left, then evaluates the one on the right.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      Officially undefined, as in you have a reference that says that, or as in it's not specified anywhere?
      @/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/; map{y/X_/\n /;print}map{pop@$_}@/for@/
Re: surprising backwards evaluation order
by ikegami (Patriarch) on Mar 17, 2006 at 23:10 UTC
    This strikes me as an odd choice

    In a stack machine, it's easier to calculate last what you will need first. The arguments are only needed once the function is called, so it's convenient to calculate the address of the function last.

    It's not purely a Perl oddity. Visual Studio .NET 2003's C++ compiler does things in the same order with respect to function pointer vs function argument order:

    #include <stdio.h> typedef void (*fp)(int); void f(int) { printf("f()\n"); } fp a() { printf("a()\n"); return &f; } int b() { printf("b()\n"); return 0; } int main() { ((fp)(a()))(b()); // (a())->(b()) return 0; }


    b() a() m()
      Consider also that in an MMD implementation, it's a requirement that the call destination be calculated on the basis of the run-time types of the arguments. Even for a single dispatch system like Perl 5, you have to at least figure out what the object is before you find out where you're going to call.

      Also, some of the bias is just coming from seeing the verb out in front. A speaker of a language such as Japanese might not have that bias, since the verb comes after the object there. Even in English, you have to reserve judgement on the meaning of a verb until you've seen the object. You don't know what "screw the X" means until you know whether X is a light bulb or a Californian.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://537549]
Approved by xdg
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (2)
As of 2022-08-18 00:56 GMT
Find Nodes?
    Voting Booth?

    No recent polls found