choroba has asked for the wisdom of the Perl Monks concerning the following question:

yasserhussain1110 asked an interesting question in the CB. What would you expect the following code to return? Why aren't the three values the same?
#!/usr/bin/perl -l sub mychomp { chomp $_[0] } my $x = "a\n"; my $y = "b\n"; our $z = "c\n"; $x = chomp $x; $y = mychomp($y); $z = chomp $z; print "($x,$y,$z).";

Adding use strict doesn't change the result.

لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Replies are listed 'Best First'.
Re: Assigning the result of a chomp to the chomped var itself.
by Discipulus (Canon) on Nov 26, 2014 at 09:22 UTC
    while my old 5.8.8 returns (1,1,1) newer strawberry one returns all 0,1,1
    general>check_perl_distro c:/scripts/ideone-choroba.pl ----------------------------------------······· | (0,1,1). --------------------------------------------------------------------- +--······· [OK] C:\ulisse\strawberry\perl\bin\perl.exe ----------------------------------------······· | (0,1,1). --------------------------------------------------------------------- +--······· [OK] C:\ulisse\straw5.20-32b\perl\bin\perl.exe ----------------------------------------······· | (0,1,1). --------------------------------------------------------------------- +--······· [OK] C:\ulisse\straw64\perl\bin\perl.exe
    UPDATE: docs say also It returns the total number of characters removed from all its arguments. but i see another thing:
    perl -e "$a=qq(AA\n\n);$res = chomp $a; print qq(>$a< removed $res\n)" >AA < removed 1 ## maybe it means another thing: perl -e "$a=qq(AA\n\n);$b=qq(BB\n\n);$res = chomp ($a,$b); print qq(>$ +a< removed $res\n>$b< removed $res )" >AA < removed 2 >BB < removed 2
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      chomp ... It returns the total number of characters removed from all its arguments. It's often used to remove the newline from the end of an input record when you're worried that the final record may be missing its newline. When in paragraph mode ("$/ = """), it removes all trailing newlines from the string. When in slurp mode ("$/ = undef") or fixed-length record mode ($/ is a reference to an integer or the like; see perlvar) chomp() won't remove anything.

      So ...

      perl -e '$/ = "" ; $a = qq(AA\n\n); $b = qq(BB\n\n); $res = chomp ($a, +$b); print qq(>$a< removed $res\n>$b< removed $res\n)' >AA< removed 4 >BB< removed 4

      UPDATE: docs say also It returns the total number of characters removed from all its arguments. but i see another thing:

      What is that?

      $ perl -MData::Dump -e " $g=$f=qq{a\n}; dd( chomp( $f, $g ) ) ; dd( $ +f, $g )" 2 ("a", "a")
        removes any trailing string that corresponds to the current value of $/
        Maybe this is problem due to my poor english but with 'any' i supposed to be 'all accurences' not the last one.
        $ perl -MData::Dumper -e ' $g=$f=qq{a\n}; print Dumper( chomp( $f, $g + ) ) ; print Dumper( $f, $g )' $VAR1 = 2; $VAR1 = 'a'; $VAR2 = 'a'; $perl -MData::Dumper -e ' $g=$f=qq{a\n\n}; print Dumper( chomp( $f, $ +g ) ) ; print Dumper( $f, $g )' $VAR1 = 2; $VAR1 = 'a '; $VAR2 = 'a ';
        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Assigning the result of a chomp to the chomped var itself.
by dave_the_m (Monsignor) on Nov 26, 2014 at 15:03 UTC
    It appears to be fixed in perl-5.21.6: i.e. 5.21.5 outputs 0,1,1 while 5.21.6 outputs 1,1,1.

    Dave.

      Oh, thanks for the info. Probably mentioned in the delta:
      Assignment to a lexical scalar is often optimised away (as mentioned under "Performance Enhancements"). Various bugs related to this optimisation have been fixed. Certain operators on the right-hand side would sometimes fail to assign the value at all or assign the wrong value, or would call STORE twice or not at all on tied variables. The operators affected were $foo++, $foo--, and -$foo under use integer, chomp, chr and setpgrp.
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Just felt is should share my findings.

      When i ran the code in Perl version 5.16.1 developed by activestate i got the following results.

      $x = 0   $y = 1  $z = 0
Re: Assigning the result of a chomp to the chomped var itself.
by Anonymous Monk on Nov 26, 2014 at 11:36 UTC
Re: Assigning the result of a chomp to the chomped var itself.
by ikegami (Patriarch) on Nov 26, 2014 at 14:29 UTC

    Generally speaking, you should avoid reading and modifying a variable in the same expression. You run into tricky and undefined areas.

    For many operators, operand evaluation order is undefined. While it's not explicitly defined for the assignment operators, the fact that local $x = $x; is guaranteed to work strongly implies that the RHS side of that operator is evaluated before its LHS.

    As such, there's a strong implication that the observed behaviour is a bug.

    Update: LHS being evaluated first wouldn't cause $x to get cleared.

Re: Assigning the result of a chomp to the chomped var itself.
by Laurent_R (Canon) on Nov 26, 2014 at 18:44 UTC
    I have a behavior that is even more difficult to understand (running Perl 5.14.4).

    Running the test directly under the Perl debugger:

    DB<1> $x = "a\n"; DB<2> $x = chomp $x; DB<3> print $x 1
    And running the same at the command line:
    $ perl -E 'my $x = "a\n"; $x = chomp $x; say $x' 0
    So I get 1 under the debugger et 0 at the command line. Isn't it strange?

    And, BTW, using another variable solves the issue:

    $ perl -E 'my $x = "a\n"; my $y = chomp $x; say $y;' 1
    This leads me to believe that doing this:
    $x = chomp $x;
    might well be undefined behavior (and should most probably be avoided), just as:
    $c = ++$c;
    is undefined both in C and in Perl. (And different C compilers actually give different results on the code above, I have tried it once in the past.)

      Interesting...

      $ perl -wMstrict -e 'my $x = "a\n"; $x = chomp $x; print "<$x>\n"' <0> $ perl -wMstrict -e 'our $x = "a\n"; $x = chomp $x; print "<$x>\n"' <1> $ perl -wMstrict -MO=Terse -e 'our $x; $x = chomp $x;' LISTOP (0x8aa33b8) leave [1] OP (0x8aa3694) enter COP (0x8aa33dc) nextstate UNOP (0x8aa3414) null [15] SVOP (0x8aa3434) gvsv GV (0x8a9e5c0) *x COP (0x8aa36b8) nextstate BINOP (0x8aa36f0) sassign UNOP (0x8aa3714) schomp [2] UNOP (0x8aa3750) null [149] UNOP (0x8aa3774) null [15] SVOP (0x8aa3794) gvsv GV (0x8a9e5c0) *x UNOP (0x8aa3368) null [15] SVOP (0x8aa3398) gvsv GV (0x8a9e5c0) *x $ perl -wMstrict -MO=Terse -e 'my $x; $x = chomp $x;' LISTOP (0x92913d8) leave [1] OP (0x9291754) enter COP (0x92913fc) nextstate OP (0x9291434) padsv [1] COP (0x929171c) nextstate UNOP (0x9291778) schomp [1] UNOP (0x9291368) null [149] OP (0x92913a0) padsv [1]