http://qs1969.pair.com?node_id=543989

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

Hi Monks,

The perl program below should print 3 identical lines,

#! /usr/perl -l sub f1 { my ($f) = @_; my @z = ("$f"); for my $d (@z) {return $d} } sub f2 { my ($f) = @_; for my $d ("$f") {return $d} } sub f3 { for my $d (@_) {return $d} } print map {f1($_)} qw(x y z); print map {f2($_)} qw(x y z); print map {f3($_)} qw(x y z);
Output:
xyz zzz xyz
why does it happen. I run this program in unix ksh.

"Keep pouring your ideas"

2006-10-07 Unapproved by planetscape once evidence of habitual plagiarism uncovered.

Replies are listed 'Best First'.
Re: "map" sometimes uses only the last mapped value
by Ovid (Cardinal) on Apr 18, 2006 at 07:51 UTC

    Ugh. What a mess. It appears that when values are stringified, map sometimes returns the last mapped value. Oops. Someone has reported this on P5P and and a potential culprit has been identified. I expect it will be fixed soon.

    Interestingly, it appears that this bug may have cropped up in 5.005 and never been noticed until now. Oops.

    Cheers,
    Ovid

    New address of my CGI Course.

Re: "map" sometimes uses only the last mapped value
by bobf (Monsignor) on Apr 18, 2006 at 04:06 UTC

    I get different results depending on whether or not $f is quoted in the for list:

    sub f2a { my ($f) = @_; for my $d ("$f") {return $d} } sub f2b { my ($f) = @_; for my $d ($f) {return $d} } print map {f2a($_)} qw(x y z); # zzz print map {f2b($_)} qw(x y z); # xyz

    I also ran it through B::Deparse, but gained no insight.

Re: "map" sometimes uses only the last mapped value
by Tanktalus (Canon) on Apr 18, 2006 at 03:42 UTC

    It doesn't do that when I run it in the debugger, but does do that when I run straight through. Thus, I highly suspect a bug in the perl interpreter/runtime.

    That said, I'm not really sure what you're trying to get at with your three versions of functions - they look incredibly wierd.

Re: "map" sometimes uses only the last mapped value
by turo (Friar) on Apr 18, 2006 at 13:57 UTC

    Seems to be a problem with references ...

    The map operator receives all the elements of the array (x, y, z) and passes all of them correctly to the function f2:

    #! /usr/perl -l sub f1 { my ($f) = @_; my @z = ("$f"); for my $d (@z) {return $d} } sub f2 { my ($f) = @_; print "\n*$f*\n" for my $d ("$f") {return $d} } sub f3 { for my $d (@_) {return $d} } print map {f1($_)} qw(x y z); print map {f2($_)} qw(x y z); print map {f3($_)} qw(x y z);
    Extrange, is like the function f2, only has been collecting the ref of the $d variable, and when print is going to print the array, it prints the value of the same reference; that is the last 'z' (what's about the scopes!!! arrg)

    I have solved the problem using a intermediate variable:

    #! /usr/perl -l sub f1 { my ($f) = @_; my @z = ("$f"); for my $d (@z) {return $d} } sub f2 { my ($f) = @_; for my $d ("$f") {my $a=$d; return $a} } sub f3 { for my $d (@_) {return $d} } print map {f1($_)} qw(x y z); print map {f2($_)} qw(x y z); print map {f3($_)} qw(x y z);

    cheers

    perl -Te 'print map { chr((ord)-((10,20,2,7)[$i++])) } split //,"turo"'
Re: "map" sometimes uses only the last mapped value
by Anonymous Monk on Apr 18, 2006 at 12:55 UTC
    It seems to have to do with returning a temp from inside a for loop. It's not just stringify, here:
    print map sub{return $_ for 0+shift}->($_), 1, 2, 3; # 333 print map sub{return $_ for shift}->($_), 1, 2, 3; # 123 print map sub{return 0+shift}->($_), 1, 2, 3; # 123 print map sub{return 0+$_ for shift}->($_), 1, 2, 3; # 123
    Only the first of these cases messes up, funny
      That was my post, forgot to log in. Sorry :-)
Re: "map" sometimes uses only the last mapped value = PLAGIARISM
by liverpole (Monsignor) on Oct 06, 2006 at 13:46 UTC
    This question was first posted at this site.

    Other than the change from "6 identical lines" to "3 identical lines" and the removal of newlines, the OP is a verbatim, blatant plagiarism of this original post:

    [Please enter your report here] The perl program below should print 6 identical lines, but one of them is different, which appears to be a very serious bug, perhaps in the optimization of "map". It appears to not be Solaris-specific. I also see this on Linux perl 5.6.1. $ perl <<'EOF' sub f1 { my ($f) = @_; my @z = ("$f"); for my $d (@z) {return $d} } sub f2 { my ($f) = @_; for my $d ("$f") {return $d} } sub f3 { for my $d (@_) {return $d} } print map {f1($_)} qw(x y z); print "\n"; print map {f2($_)} qw(x y z); print "\n"; print map {f3($_)} qw(x y z); print "\n"; for my $a (qw(x y z)) { print f1($a) } print "\n"; for my $a (qw(x y z)) { print f2($a) } print "\n"; for my $a (qw(x y z)) { print f3($a) } print "\n"; EOF xyz zzz xyz xyz xyz xyz

    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
      Well said ++ Liverpole

      Postings of that sort to gain xp are not in the spirit of perlmonks.
Re: "map" sometimes uses only the last mapped value
by ambrus (Abbot) on Apr 18, 2006 at 20:25 UTC

    I really don't understand how this could happen. turo's answer has reminded me to Aliasing bites, but I can't see how that could happen here, as the statement my ($f) = @_ copies the string passed.