in reply to Re: print behavior
in thread print behavior

With due respect to ikegami and all other monks, I strongly disagree with ikegami for the following reasons.

  1. How will you explain the peculiar behavior I have explained in my post Re: print behavior when we have more than one $x++ in same print statement ? ( the table is appended below for reference.

    Print orderO/P in Perl
    $x0
    $x,$x++10
    $x,$x,$x++110
    $x,$x++,$x++201
    $x,$x++,$x++,$x++3012
    $x,$x++,$x++,$x++,$x++40123
    $x,$x++,$x++,$x++,$x++,$x++501234

  2. How we have the similar behaviour with "C" where printf("%d%d",x,x++) which will also print 10?
  3. you said "print will see the change in $x caused by ++ (which must be evaluated before print is called)." Then why
    my $x =0; print $x++; #prints 0 print $x++; #prints 1
    works properly? Why in this case $x++ is NOT incrementing $x before print is called?
  4. Given $x=0, @_ is ($x, $anon) which evaluates to (1, 0). --- Can you explain how the @_ is evaluated to ( 1, 0 ) ?
  5. arguments are passed by reference --- if its passed by reference, how will you explain this behaviour for all function calls? including user-defined-functions? (see comments in my post Re: print behavior)

If you keep the explanation I posted at Re: print behavior in mind, there is NO harm in modifying a variable in a parameter list expression when the variable appears elsewhere in that parameter list. Isn't it a nice obfuscation.

Replies are listed 'Best First'.
Re^3: print behavior
by ikegami (Patriarch) on Jul 10, 2007 at 16:42 UTC

    That's a lot of questions! Here goes...

    Answer to Question 1

    I'll do two examples, $x,$x,$x++:

    { local @_; alias $_[0] = $x; alias $_[1] = $x; alias $_[2] = $x++; &print; # @_ = ($x, $x, $anon) = (1, 1, 0) }

    $x,$x++,$x++:

    { local @_; alias $_[0] = $x; alias $_[1] = $x++; alias $_[2] = $x++; &print; # @_ = ($x, $anon1, $anon2) = (2, 1, 0) }

    $x,$x++,$x++, on a system that does the alias statments in a different order:

    { local @_; alias $_[2] = $x++; alias $_[1] = $x++; alias $_[0] = $x; &print; # @_ = ($x, $anon1, $anon2) = (2, 0, 1) }

    Answer to Question 2

    Your compiler probably does something like:

    load x inc push load x push call printf

    C doesn't guarantee the order either.

    Answer to Question 3

    The return value of $x++ is not $x. It's a new variable that contains the old value of $x. $x is incremented before the print call, but you are aren't printing $x. Check perlop.

    Answer to Question 4

    # $x | anon returned | $_[0] | $_[1] # | by $x++ | | # ------+-----------------+---------+--------- my $x = 0; # 0 | -- | -- | -- { # 0 | -- | -- | -- local @_; # 0 | -- | undef | undef alias $_[0] = $x; # 0 | -- | 0 | undef alias $_[1] = $x++; # 1 | 0 | 1 | 0 &print; }

    or in even more detail

    # $x | anon returned | $_[0] | $_[1] # | by $x++ | | # ------+-----------------+---------+--------- my $x = 0; # 0 | -- | -- | -- { # 0 | -- | -- | -- local @_; # 0 | -- | undef | undef alias $_[0] = $x; # 0 | -- | 0 | undef my $anon = $x++; # 1 | 0 | 1 | undef alias $_[1] = $anon; # 1 | 0 | 1 | 0 &print; }

    Answer to Question 5

    Guess what the following prints:

    perl -le"$x=3; sub { $_[1]++; $_[2]++; print @_ }->($x+0, ++$x, $x++, +$x+0, $x);"

    On my system, it prints 36556.

    my $x = 3; # $anon0 | $x | $anon2 | $anon3 | $x { # $_[0] | $_[1] | $_[2] | $_[3] | $_[4] local @_; # --------+-------+--------+--------+------- # $x+0 my $anon0 = $x+0; alias $_[0] = $anon0; # 3 | -- | -- | -- | -- # ++$x $x=$x+1; # 3 | -- | -- | -- | -- alias $_[1] = $x; # 3 | 4 | -- | -- | -- # $x++ my $anon2 = $x; alias $_[2] = $anon2; # 3 | 4 | 4 | -- | -- $x=$x+1; # 3 | 5 | 4 | -- | -- # $x+0 my $anon3 = $x+0; alias $_[3] = $anon3; # 3 | 5 | 4 | 5 | -- # $x alias $_[4] = $x; # 3 | 5 | 4 | 5 | 5 &anon_sub; # $_[1]++; # 3 | 6 | 4 | 5 | 6 # $_[2]++; # 3 | 6 | 5 | 5 | 6 # print @_; }

    Notice how $x and $x+0 are different.
    Notice how $_[1]++ affects more than one argument.
    Notice how $_[1]++ affects $x and ++$x.
    Notice how $_[1]++ doesn't affect $x+0 and $x++.