Reputation: 25133
The DOC explains perl operator precedence and associativity. I am interesting at ->
and *
operators. Both have left
associativity.
I have next example and it seems that ->
has right associativity. Not left as documentation states:
my @args;
sub call { print "call\n"; shift @args }
sub test { print "test\n"; 1 }
sub t4 { print "t4\n"; 4 }
@args=( \&test, 2, 3 );
call()->( @args, t4 );
sub m1 { print "m1\n"; 2 }
sub m2 { print "m2\n"; 4 }
m1()*(@args, m2);
The output is:
t4
call
test
m1
m2
Because ->
has left associativity I expect next output:
call
t4
test
m1
m2
What did I miss? Why t4
is called before call
?
Upvotes: 1
Views: 171
Reputation: 385819
You are asking about operand evaluation order (the order in which operands are evaluated), not operator associativity (the order in which operators of the same operator precedence are evaluated).
The operand evaluation order is undefined (or at least undocumented) for many operators, including ->
. You will find it consistent, but one shouldn't rely on that.
You can use statement breaks to force the desired order:
my $sub = call();
$sub->( @args, t4 );
This would also work:
$_->( @args, t4 ) for call();
Associativity is the order in which operators of the same precedence are evaluated.
For example, *
and /
have the same precedence, so associativity determines that
3 / 4 * 5 * 6
is equivalent to
( ( 3 / 4 ) * 5 ) * 6 = 22.5
and not
3 / ( 4 * ( 5 * 6 ) ) = 0.025
As you can see, associativity can have a direct effect on the outcome of the expression.
Operand evaluation order is the order in which operands are evaluated.
For example, operand evaluation order determines whether 1+2
is evaluated before 3+4
, or vice-versa in
( 1 + 2 ) * ( 3 + 4 )
Unless evaluating the operand has a side-effect (e.g. changing a variable or printing to the screen), then operand evaluation order has no effect on the outcome of the expression. As such, some languages leave it undefined to allow for optimization.
In Perl, it's undefined (or at least undocumented) for many operators. It's only documented for the following:
,
and =>
): left to rightand
, or
, &&
, ||
and //
): left, then maybe right[1]? :
): left, then either second or third[1]=
): right, then left[2]=~
and !~
): left, then right[3]my $x = $x;
.Upvotes: 4
Reputation: 46187
Associativity describes the order that multiple operators of equal precedence are handled. It has nothing to do with whether the left arguments or the right arguments are processed first. ->
being left associative means that a->b->c
is processed as (a->b)->c
, not as a->(b->c)
.
Upvotes: 2
Reputation:
Associativity is a rule that tells you how to parse an expression where the same operator appears twice, or more than one operator with the same precedence level appears. For example, associativity determines that:
foo()->bar()->baz()
is equivalent to
(foo()->bar())->baz() # left associative
and not
foo()->(bar()->baz()) # right associative
Since your code only hase one ->
operator in it, the associativity of that operator is irrelevant.
You seem to be looking for a rule about the order of evaluation of operands to the ->
operator. As far as I know, there is no guaranteed order of evaluation for most operators in perl (much like C). If the order matters, you should split the expression into multiple statements with an explicit temporary variable:
my $tmp = call();
$tmp->( @args, t4 );
Upvotes: 3