in reply to Re: Will "$_[0]=shift" always resolve shift first?
in thread Will "$_[0]=shift" always resolve shift first?

I was going to say Perl always evaluates operands in left to right order, but it's not the case.

It does, unless precedence or associativity gets in your way. Your example demonstrates this quite well:

var() = foo() + bar() * baz(); 6 1 2 3 7 5 4 Precedence tightest: * + loosest: =

So the arguments are evaluated left-to-right on the LHS of the =, then the sub expressions in order of their precedence, then the RHS. (perltrap documents that the RHS is evaluated first, btw).

Update: the more I think about this, the less sure I am. So try not rely too much on it ;-)

In short, you might be able to rely on the order in which operands are evaluated, but I consider it a bad practice

Fully agreed.

Second update

Ok, the operands are evaluated left-to-right, the operators according to their precedence/associativity.

The assignment operator is an exception (on which we rely quite often).

Replies are listed 'Best First'.
Re^3: Will "$_[0]=shift" always resolve shift first?
by ikegami (Patriarch) on Sep 08, 2008 at 22:14 UTC

    It does, unless precedence or associativity gets in your way. Your example demonstrates this quite well:

    Not at all. My example shows that precedence has no effect on the operatoroperand evaluation order.

    And since associativity breaks ties in precedence, how could it possibly have any effect on the operatoroperand evaluation order if precedence doesn't.

    Updated (18:55 EDT): I keep typing "operator" when I try to type "operand"! argh!

      Sorry, but not entirely true. If you remove precedence, then things get evaluated in a different order:
      foo() + bar() + baz() 1 2 3 4 5
      The following script proves this:
      #! /usr/bin/perl use strict; package Foo; use overload '+' => sub { my ($self, $other) = @_; print "Evaluating $self + $other\n"; return Foo->new($$self + $$other); }, '0+' => sub {my $self = shift; $$self}, '""' => sub {my $self = shift; $$self}; sub new { my $class = shift; my $obj = \shift; print "Creating $$obj\n"; bless $obj, $class; } package main; Foo->new(1) + Foo->new(2) + Foo->new(4); __END__ Creating 1 Creating 2 Evaluating 1 + 2 Creating 3 Creating 4 Evaluating 3 + 4 Creating 7
      That said, it looks like Perl likes to evaluate binary operations by evaluating the left hand side, then the right hand side, then performing the operation. (As you found, = is an exception.) With that order, the fundamental operands will generally go left to right. The order of the intermediate operations can generally be predicted fairly easily from perlop.

      That said there are some points of precedence that are officially not documented. But that's because it is easier to say it is not documented than it is to explain why

      my $foo = 0; print ++$foo + $foo++;
      prints 3. (At least with Perl 5.8.)

      The reason is that you evaluate the pre-increment that turns $foo into 1 then return $foo. You copy the existing value into a temp, then increment $foo again. You then add $foo (now 2) to its old value (1) to get 3. While there is no need to change this, anyone who depends on it deserves the worst of what they might get at some future date.

        my $foo = 0; print ++$foo + $foo++; prints 3

        Treating + as a function is the best way I've found to explain it.

        do { local @_; alias $_[0] = ++$foo; # aliases to $foo alias $_[1] = $foo++; # aliases to anon 1 &sum # 2+1 }

        Sorry, but not entirely true. If you remove precedence, then things get evaluated in a different order:

        eh? The operands are evaluated in the same order as before (foo then bar then baz). I've said all along precedence wasn't relevant to operand evaluation order, so what is "not entirely true"?

      My example shows that precedence has no effect on the operator evaluation order.

      Not quite true. * is evaluated before +. (Which makes a difference for overloaded operators)

      And since associativity breaks ties in precedence, how could it possibly have any effect on the operator evaluation order if precedence doesn't.
      You're right here. After reading betterworld's comment I thought that the right associativity of the = operator was the key, but it isn't. It seems to be just a special case for =.
        Sorry for the confusion. I said "operator" where I meant "operand" earlier. I keep mistyping it. I corrected myself in time elsewhere, but missed that one. It's now fixed, so you may want to reread it.