Jay Savage wrote:
> On 10/20/06, Rob Dixon <[EMAIL PROTECTED]> wrote:
>> Paul Johnson wrote:
>> >
>> > On Fri, Oct 20, 2006 at 10:56:09AM +0200, Dr.Ruud wrote:
>> >
>> >> Norbert Preining schreef:
>>  >>>
>> >>> Dr.Ruud:
>>  >>>>
>> >>>> $ perl -wle '
>> >>>>   $a = 3;
>> >>>>   $b = 0 + (++$a) + ($a++);
>> >>>>   print "b=$b\n";
>> >>>> '
>> >>>> b=8
>> >>>> :)
>> >>> Nup, this is not the solution:
>> >> Solution?
>> >>
>> >> It showed that there is a bug. I already reported it.
>> >
>> > And I already replied ENOTABUG as promised ;-)
>>
>> It's clear what the language should be doing in this situation and it
>> isn't doing it, so it's broken. It's only not a bug in the sense that it's
>> documented to be broken.
>>
>> Rob
>>
>
> How is it clear what the language should be doing? Repeat after me:
> addition is a commutative.

Addition is a commutative.

> The order of addition by definition does not matter, and any attempt to make
> it matter should absolutely return an undefined behavior. Why should Perl
> guarantee that it will read the operands of '+' from left to right? As far as
> I'm concerned, the Perl/C people have this one right. Given
>
>    $x = 3;
>    $y = ++$x + $x++;
>
> It seems to me that the flow (remembering that addition is
> commutative) could be optimized to
>
>    $y = $x++;     # $y = 3, postincrement, $x=4
>    $y += ++$x;     # preincrement, $x = 5, $y = 9
>
> That makes perfect sense to me. The optimizer sees that it needs an
> unincremented $x, inlines the '3', and then gets on witth the
> increments. Because, let me say it again, addition is commutative.

A lot of the rest of your argument breaks down here Jay, because 3 + 5 == 8, not
9. And whichever increment operator is executed first the result should be
either 3 + 5 or 4 + 4, but instead Perl provides 9, as if both were preincrement
operators.

I admit that the documentation is silent on which side of the addition operator
is evaluated first, but it is implied strongly - see later. And the fact that
addition is commutative is also irrelevant, as both arguments must be evaluated
before the addition is applied whether it is an addition or, say, a subtraction,
which is non-commutative.

> If you want to perform addition where the order of execution does
> matter, it's up to you to ensure the order.
>
>    $y = (0 + ++$x) + $x++; # gets 8
>    $y = (++$x + 0) + $x++; # gets 8
>    $y = ++$x + (0 + $x++); # gets 9
>    $y = ++$x + ($x++ + 0); # gets 9
>
> for instance, seem to yield the expected results. I'd still try to split the
> increments into separate statements if possible, though, because I don't think
> that behavior is guaranteed.

Now /here/ the behaviour /is/ guaranteed, even without the parentheses. perlop
says:

    *Operator associativity* defines what happens if a sequence of the same
    operators is used one after another: whether the evaluator will evaluate
    the left operations first or the right. For example, in "8 - 4 - 2",
    subtraction is left associative so Perl evaluates the expression left to
    right. "8 - 4" is evaluated first making the expression "4 - 2 == 2" and
    not "8 - 2 == 6".

and addition is also left-associative to Perl, so

  $y = 0 + ++$x + $x++

unambiguously means

  $y = (0 + ++$x) + $x++;

and (here is what I meant above by the order being strongly implied) it would
very perverse of Perl to do it this way round but to evaluate the right-hand
half of

  ++$x + $x++

before the left. (And anyway, as I've said already, the answer still isn't 9!)

> The current optimizer seems to perform the variable substitution when the
> parens are evaluated, but I don't see why that couldn't break at some point;
> it's still non-commutative and therefore undefined.

In this case the evaluator is substituting /operator/ values, not variables.
It's helpful to think of operators as just functions with a different syntax,
and if I write the equivalent:

sub ppx { $_[0] += 1; return $_[0]; }
sub xpp { my $t = $_[0]; $_[0] += 1; return $t; }

my $a = 3;
my $b = ppx($a) + xpp($a);
print $b, "\n";

then I get my '8' as I expected (even if you reverse the operands of the
addition). The built-in operators should behave the same way, or at least bleat
at you and say that they're not going to.

> Perl is good about DWIM, but don't expect it to read your mind and figure out
> which mathematical properties you'd like to suspend today. If you want to
> re-write the rules of logic to suit your fancy, it's up to you to
> rewirte the optimizer to suit your fancy, too.

No mathematical property suspension or logic rule rewriting required. 3+5 == 5+3 == 4+4 == 8, not 9

> At least that's my $.02.
>
> I'd also recommend against using the reserved variables $a and $b in
> examples.

Thay can be tricky things, but to be honest I'm inclined to think that the magic
sort variables should be something other than $a and $b, or at least they should
be implicitly localized inside a sort block. But that's another thing...

> That in itself should be a warning that the problem is with the implementor,
> not the implementation.

Not sure what you mean. Presumably that it's the Perl programmer's fault and not
the Perl implementors'? I don't see how $a and $b have anything to do with that,
and I think using them is absolutely fine as long as they're in a program that's
short enough for it to be blatantly obvious that there are no calls to sort(),
which this one was. But then I also think that using $& is also fine as long as
your program runs fast enough for you, so maybe it's just me :)

By the way, for further thought you might like to consider the simpler

my $a;
my $b = ($a = 1) + ($a = 2);

which clears away any confusion over order of evaluation.

Cheers,

Rob


--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to