Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Order of evaluation

0 views
Skip to first unread message

Mark Jason Dominus

unread,
Aug 30, 2003, 1:15:42 PM8/30/03
to perl5-...@perl.org
Is this:

@s = qw(a b);
$z = shift(@s) . shift(@s);
print $z;

guaranteed to print "ab"?

I asked this on comp.lang.perl.misc, but nobody seemed to know
anything. I thought I remembered that Larry had made a pronouncement
about this kind of thing, or that it had been discussed here before,
but I couldn't remember if that was true, or, if it was, what the
outcome was.

Mark-Jason Dominus m...@plover.com

Dan Kogai

unread,
Aug 30, 2003, 3:57:22 PM8/30/03
to Mark Jason Dominus, perl5-...@perl.org
On Sunday, Aug 31, 2003, at 02:15 Asia/Tokyo, Mark Jason Dominus wrote:
> Is this:
>
> @s = qw(a b);
> $z = shift(@s) . shift(@s);
> print $z;
>
> guaranteed to print "ab"?

I think so, so long as associativity and precedence order of perl stays
the same:

perldoc perlop
> left terms and list operators (leftward)
> [snip]
> left + - .

So your example must evaluate as:

$z = shift(@s);
$z .= shift(@s);

And my perls all print "ab" when your code is fed to them.

@signature = qw(dan kogai);
$signature = shift(@author) . shift(@author);
print $signature;

Rafael Garcia-Suarez

unread,
Aug 30, 2003, 4:10:29 PM8/30/03
to Dan Kogai, perl5-...@perl.org
Dan Kogai wrote:
> On Sunday, Aug 31, 2003, at 02:15 Asia/Tokyo, Mark Jason Dominus wrote:
> > Is this:
> >
> > @s = qw(a b);
> > $z = shift(@s) . shift(@s);
> > print $z;
> >
> > guaranteed to print "ab"?
>
> I think so, so long as associativity and precedence order of perl stays
> the same:

IIRC the same mistake was made on c.l.p.misc : neither associativity
nor precedence are related to evaluation order.

The summarizer's urge is to post a link to the relevant thread :

http://groups.google.com/groups?selm=bhok6j%2470f%241%40plover.com

--

Dan Kogai

unread,
Aug 30, 2003, 11:59:09 PM8/30/03
to Rafael Garcia-Suarez, perl5-...@perl.org
On Sunday, Aug 31, 2003, at 05:10 Asia/Tokyo, Rafael Garcia-Suarez
wrote:

> IIRC the same mistake was made on c.l.p.misc : neither associativity
> nor precedence are related to evaluation order.

Aagh, that's right. For (1+2)*(3+4), we may evaluate 1+2 first, 3+4
first, or even both at the same time (with multiprocessing). For such
(very likely most) cases you can safely evaluate both terms in parallel.

> The summarizer's urge is to post a link to the relevant thread :
>
> http://groups.google.com/groups?selm=bhok6j%2470f%241%40plover.com

I've read it and found Benjamin's example interesting.

$x{foo} ||= keys %x; # %x is (foo => 1) in current perl
$y{foo} = keys %y; # %x is (foo => 0) in current perl

I also googled 'perl "order of evaluation"' and the found that similar
discussion was already done here at perl5-porters.

http://www.perl.com/lpt/a/2000/12/p5pdigest/THISWEEK-20001217.html

It appears back then the order of evaluation remains undefined so I
reckon it is still undefined as of perl 5.8.

In the discussion above t Nicholas Clark points that keeping the order
undefined allows for flexibility in the implementation and I kind of
agrees with his point; Since multiprocessing is already a reality, we
should allow future perl to allow terms to be evaluated in parallel.

Hmm.... But does that mean that mjb's example may print 'aa' when
shift(@a) is evaluated simultaneously?

@me = qw(dan kogai); $me = shift(@me) . shift(@me); print $me;

Rafael Garcia-Suarez

unread,
Aug 31, 2003, 5:40:45 AM8/31/03
to Dan Kogai, perl5-...@perl.org
Dan Kogai wrote:
> Hmm.... But does that mean that mjb's example may print 'aa' when
> shift(@a) is evaluated simultaneously?

No, because that would be incorrect. shift() modifies its argument :
that means that it should have the conceptual equivalent of an exclusive
lock on it, and thus two shift()s on a same array will be executed
sequentially.

Dan Kogai

unread,
Aug 31, 2003, 6:36:51 AM8/31/03
to Rafael Garcia-Suarez, perl5-...@perl.org
On Sunday, Aug 31, 2003, at 18:40 Asia/Tokyo, Rafael Garcia-Suarez
wrote:

> Dan Kogai wrote:
>> Hmm.... But does that mean that mjb's example may print 'aa' when
>> shift(@a) is evaluated simultaneously?
>
> No, because that would be incorrect. shift() modifies its argument :

IF we CORRECTLY implement the future perl. Should we make a test suite
for future perls to come ? But what should we do on that test suite?

$a = shift(@a) . shift(@a); ok( $a ne 'aa' and scalar(@a) == 0 );

Is the code like this good enough?

> that means that it should have the conceptual equivalent of an
> exclusive
> lock on it, and thus two shift()s on a same array will be executed
> sequentially.

Exclusive lock is not good enough because for exclusive lock to work,
either shift() must be evaluated before the other but we make no such
guarantee; they MAY be evaluated REALLY AT THE SAME TIME. So the
serialization must occur at opcode generation level, not execution
level.

If we want future optimizer to allow parallel evaluation, it should try
to do so when and only when it is safe to do so. Frankly, I am not
sure if we can make our compiler that smart. Simply looking at an
expression and see if the same variable does not appear twice is not
good enough because we have reference now.

@a = (a b); $ra = \@a; $a = shift(@a) . shift(@$ra);

Can we safely optimize the code above?

Rafael Garcia-Suarez

unread,
Sep 1, 2003, 3:40:04 AM9/1/03
to Mark Jason Dominus, perl5-...@perl.org
Mark Jason Dominus wrote:
> Is this:
>
> @s = qw(a b);
> $z = shift(@s) . shift(@s);
> print $z;
>
> guaranteed to print "ab"?

While thinking about this, I remarked that I wrote
several times something like

sub foo($$) {
my ($x, $y) = (shift, shift);
...
}

to copy the @_ elements.

-- there's an instance of this statement in Test::LongString
for example. The implicit assumption is that C<,> guarantees
evaluation order. Like the comma operator in C IIRC.

(On the other hand the Test::LongString function that uses
this idiom is symmetric in its argument order.)

Elizabeth Mattijsen

unread,
Sep 1, 2003, 3:59:29 AM9/1/03
to Rafael Garcia-Suarez, Mark Jason Dominus, perl5-...@perl.org
At 09:40 +0200 9/1/03, Rafael Garcia-Suarez wrote:
>Mark Jason Dominus wrote:
> > Is this:
> > @s = qw(a b);
>> $z = shift(@s) . shift(@s);
> > print $z;
> > guaranteed to print "ab"?
>While thinking about this, I remarked that I wrote
>several times something like

I was watching this discussion and was wondering whether this idiom
is in danger:

sub accessor { shift->handler( 'accessor',@_ ) }

I don't think it is, but what do you guys think?


Liz

Rafael Garcia-Suarez

unread,
Sep 1, 2003, 4:04:17 AM9/1/03
to Elizabeth Mattijsen, m...@plover.com, perl5-...@perl.org
Elizabeth Mattijsen wrote:
> I was watching this discussion and was wondering whether this idiom
> is in danger:
>
> sub accessor { shift->handler( 'accessor',@_ ) }
>
> I don't think it is, but what do you guys think?

I don't think any idiom is in danger, but obviously
the lhs of -> should be evaluated first to perform method
dispatch. More or less.

Elizabeth Mattijsen

unread,
Sep 1, 2003, 4:23:58 AM9/1/03
to Rafael Garcia-Suarez, m...@plover.com, perl5-...@perl.org

Indeed. It's the "more or less" that I'm worried about ;-)


Liz

Mark Overmeer

unread,
Sep 1, 2003, 4:32:08 AM9/1/03
to Rafael Garcia-Suarez, Elizabeth Mattijsen, m...@plover.com, perl5-...@perl.org
* Rafael Garcia-Suarez (raphel.gar...@hexaflux.com) [030901 10:09]:

The above is dangerous, but works for all versions of Perl, as far
as I know. However,
sub accessor { shift->handler( 'accessor', shift ) }
does not always produce the same result.

As stated by someone before, precedence and associativity only
determine how to read the expression. Simply said: they allow you
to write Perl in stead of LISP; you may leave out some parenthesis.

However... there are exceptions. In some languages, some operators do
enforce order. For instance the && in C and Perl, but not AND in Pascal.
When you write A && B, it is guarenteed that A is evaluated before B.

In the C language, the comma does not define the order of evaluation,
which is cause of many conversion problems. In Perl, the comma is
strictly evaluated from left to right in scalar context (explicitly
described perlop).

In LIST context, the comma is not an operator at all, but an expression
separator like ';' And therefore, the comma is not in for re-ordering
in an argument list.

That's my opinion on the docs. Results may vary.
--
MarkOv

------------------------------------------------------------------------
drs Mark A.C.J. Overmeer MARKOV Solutions
Ma...@Overmeer.net solu...@overmeer.net
http://Mark.Overmeer.net http://solutions.overmeer.net

Benjamin Goldberg

unread,
Aug 31, 2003, 7:50:12 PM8/31/03
to Mark Jason Dominus, p5p

The order of evaluation is dependent on how perl turns a tree of ops
into a sequence of ops to be evaluated one at a time.

Perl starts with a tree:

[Windows 95] C:\WINDOWS>perl -MO=Concise -e "shift(@a) . shift(@b)"
a <@> leave[t1] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 5 -e:1) v ->3
9 <2> concat[t5] vK/2 ->a
5 <1> shift sK/1 ->6
4 <1> rv2av[t2] lKRM/1 ->5
3 <> gv s ->4
8 <1> shift sK/1 ->9
7 <1> rv2av[t4] lKRM/1 ->8
6 <> gv s ->7
-e syntax OK

(Without those numbers at the front of each line, innitially.)

Then, it turns that tree into a linear sequence of operations, to
perform one at a time (that's what those numbers represent).

Remember, perl5 is stack based, so the ops have to be done in the right
order, so that the ops using their results in turn get those arguments
in the right order.

The "gv" op gets a glob, and pushes it onto the stack.

Then "rv2av" pops a glob from the stack, fetches it's array slot, and
pushes the array onto the stack.

Then, "shift" pops an array from the stack, shifts off the first value,
and pushes the result onto the stack.

After we've done that twice, there are two strings on the stack.

Then, "concat" pops two items from the stack, concatenates them
together, then pushes the result onto the stack.

If shift(@b) had been evaluated before the first shift(@a), the two
strings would be on the stack in opposite order.

Now, obviously any change which makes shift(@s).shift(@s) produce "ba"
instead of "ab" needs to *not* change the apparent behavior of
shift(@a).shift(@b).

Thus, if the right side of "." were evaluated before the left side of
".", then the "concat" operator would need to be changed so that it
treats its two inputs (the top two items on the stack) in the opposite
order.

We could indeed do this (and of course change how the tree is linearized
to make the ops run in sequence), but it would be pointless... I can't
think of any way that such a change could be to anyone's advantage.

Thus, while order of evaluation isn't set in stone, it's *quite*
unlikely to change. At least, not as long as we retain the current
stack based design.

In ponie, on the other hand, it would be quite possible for the second
argument to concat to be evaluated before the first, since the results
of those shift() operations will be going into registers, not onto the
stack; this gives us the freedom to move around their order of
evaluation without changing anything else, not even the order that the
concat operator takes it's args (just switch around the order of the
arguments/registers which are passed to it).

Of course, since it would be non-backwards-compatible to have ponie
evaluate things in a different order than the current perl5, that's
rather unlikely.

--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}

Benjamin Goldberg

unread,
Sep 1, 2003, 8:23:05 PM9/1/03
to Mark Jason Dominus, p5p

The order of evaluation is dependent on how perl turns a tree of ops

);{push(@b,$a),(X-Mozilla-Status: 0009--$|;print "$@[$a%6

Smylers

unread,
Sep 8, 2003, 6:02:36 PM9/8/03
to Mark Jason Dominus, perl5-...@perl.org
On Aug 30 Mark Jason Dominus wrote:

> Is this:
>
> @s = qw(a b);
> $z = shift(@s) . shift(@s);
> print $z;
>
> guaranteed to print "ab"?
>

> ... I thought I remembered that Larry had made a pronouncement about
> this kind of thing,

Larry has pronounced that its undefinedness was a mistake in Perl 5 that
will be rectified in Perl 6:

http://groups.google.com/groups?threadm=20030301172639.GA29036%40wall.org

Smylers

Rafael Garcia-Suarez

unread,
Sep 8, 2003, 7:05:08 PM9/8/03
to Smylers, Mark Jason Dominus, perl5-...@perl.org

Cool.
We definitively need a p5p<->p6l bridge...

David Nicol

unread,
Sep 9, 2003, 1:30:31 AM9/9/03
to Smylers, Mark Jason Dominus, Perl 5 Porters

Is the statement correct? Is the example too complex?


diff -u old/pod/perlop.pod new/pod/perlop.pod
--- old/pod/perlop.pod Mon Sep 8 21:15:06 2003
+++ new/pod/perlop.pod Mon Sep 8 22:01:38 2003
@@ -404,6 +404,17 @@

Using "or" for assignment is unlikely to do what you want; see below.

+=head2 Evaluation order
+
+All evaluated operands are evaluated left to right as
+they appear, regardless of associative grouping.
+
+ @_ = qw(g f e d c b a);
+ print join(",",
+ shift().shift(), shift(),
+ sort shift().shift(), shift().shift()); # prints "gf,e,ba,dc"
+
+
=head2 Range Operators

Binary ".." is the range operator, which is really two different


Abigail

unread,
Sep 9, 2003, 2:48:06 AM9/9/03
to david nicol, Perl 5 Porters
On Tue, Sep 09, 2003 at 12:30:31AM -0500, david nicol wrote:
>
> Is the statement correct? Is the example too complex?

Not until there are regression tests to test this. And until there
is commitment not to change the order of evaluation.

> diff -u old/pod/perlop.pod new/pod/perlop.pod
> --- old/pod/perlop.pod Mon Sep 8 21:15:06 2003
> +++ new/pod/perlop.pod Mon Sep 8 22:01:38 2003
> @@ -404,6 +404,17 @@
>
> Using "or" for assignment is unlikely to do what you want; see below.
>
> +=head2 Evaluation order
> +
> +All evaluated operands are evaluated left to right as
> +they appear, regardless of associative grouping.
> +
> + @_ = qw(g f e d c b a);
> + print join(",",
> + shift().shift(), shift(),
> + sort shift().shift(), shift().shift()); # prints "gf,e,ba,dc"
> +
> +


Abigail

Enache Adrian

unread,
Sep 9, 2003, 2:04:33 PM9/9/03
to david nicol, Smylers, Mark Jason Dominus, Perl 5 Porters
On Tue, Sep 09, 2003 a.d., david nicol wrote:
> +All evaluated operands are evaluated left to right as
> +they appear, regardless of associative grouping.

This is not true.

$ perl -le '$a{shift()} = shift; print %a' 1 2
21

Regards,
Adi

David Nicol

unread,
Sep 10, 2003, 4:13:46 PM9/10/03
to Enache Adrian, Smylers, Mark Jason Dominus, Perl 5 Porters

+they appear, regardless of associative grouping. Assignment
+operations may be considered to be two separate expressions,
+with the right hand side evaluated first.


What else?

--
David Nicol / kernel 2.6.0 is pretty whippy


Yitzchak Scott-Thoennes

unread,
Sep 10, 2003, 6:21:47 PM9/10/03
to david nicol, Perl 5 Porters

The short-circuting assignment operators are an exception to the
exception.

Enache Adrian

unread,
Sep 10, 2003, 11:11:13 PM9/10/03
to david nicol, Smylers, Mark Jason Dominus, Perl 5 Porters
On Wed, Sep 10, 2003 a.d., david nicol wrote:
> > $ perl -le '$a{shift()} = shift; print %a' 1 2
> > 21
[...]

> +All evaluated operands are evaluated left to right as
> +they appear, regardless of associative grouping. Assignment
> +operations may be considered to be two separate expressions,
> +with the right hand side evaluated first.
[...]
> What else?

This :-)

$ perl -le 'sub a { print "a" } sub b { print "b" } (a)[b]'
b
a

Regards,
Adi

Alex Gough

unread,
Sep 10, 2003, 6:32:17 PM9/10/03
to Yitzchak Scott-Thoennes, david nicol, Perl 5 Porters
#### [Wed, Sep 10, 2003 at 03:21:47PM -0700: Yitzchak Scott-Thoennes]

> > +All evaluated operands are evaluated left to right as
> > +they appear, regardless of associative grouping. Assignment
> > +operations may be considered to be two separate expressions,
> > +with the right hand side evaluated first.
> >
> >
> > What else?
>
> The short-circuting assignment operators are an exception to the
> exception.

It occurs to me that exceptions don't prove rules, rather they do the
opposite.

Perhaps, for the time being, it's better to leave Perl to do what it
does, and let the future sort itself out by itself.

Alex Gough
--
"Life," said Marvin dolefully, "loathe
it or ignore it, you can't like it."

David Nicol

unread,
Sep 12, 2003, 11:45:09 PM9/12/03
to Enache Adrian, Smylers, Mark Jason Dominus, Perl 5 Porters
On Wed, 2003-09-10 at 22:11, Enache Adrian wrote:

> > What else?
>
> This :-)
>
> $ perl -le 'sub a { print "a" } sub b { print "b" } (a)[b]'
> b
> a
>
> Regards,
> Adi

so we're up to, in general left-to-right, except the RHS is always
before of the LVALUE, except for self-assignment, when the LVALUE
is part of the RHS and does not get reevaluated.

Also the index of an array is evaluated before a dynamic
array expression, as Adi points out. Curiously this does not
occur with hashes, only arrays.

perl -le 'sub a { print "a" } sub b { print "b" } @{[4 => a]}[b()]'
b
a

perl -le 'sub a { print "a" } sub b { print "b" } ${{4 => a}}{b()}'
a
b

More specificly, only array slices

perl -le 'sub a { print "a" } sub b { print "b" } ${[4 => a]}[b()]'
a
b

Hash slices evaluate the slice target first too
perl -le 'sub a { print "a" } sub b { print "b" } @{{4 => a}}{b()}'
b
a


so

(a)[b] # a slice, b first
[a]->[b] # not a slice, a first

Wow.

Is there any sense to this? The lookup of a sliced container is
not skipped when the key expression returns a null list:
perl -le 'sub a { print "a" } sub b { print "b";() } (a)[b()]'
b
a

was
that an optimization that was planned but never realized? It would
break some very odd code that considers fetching null slices out of
tied containers significant, it would also break designs that rely
on autovivification in such cases.

Mark Jason Dominus

unread,
Sep 13, 2003, 2:54:01 AM9/13/03
to perl5-...@perl.org

> Wow.
>
> Is there any sense to this?

It sounds like the answer to my question was 'no'. Thanks a lot!

0 new messages