Modifying $_ in "map", with an array containing a gap...

Discussion in 'Perl Misc' started by Raymundo, May 17, 2007.

  1. Raymundo

    Raymundo Guest

    Hello,

    I'm sorry I'm not good at English. :)


    foreach and map functions show the same result when an array has no
    gap.

    @array = (1, 2, 3, 4);
    foreach (@array) {
    $_ *= 10
    }
    # now, $array = (10, 20, 30, 40)

    @array = (1, 2, 3, 4);
    map { $_ *= 10 } @array;
    # now, $array = (10, 20, 30, 40)


    However, if an array contains a gap...

    1 $array1[0] = 0;
    2 $array1[9] = 9; # now $array1 = (0, undef,
    undef, ... , 9);
    3 print "@array1", "\n"; # 0 "" "" ... "" 9
    4 foreach (@array1) {
    5 $_ *= 10 # $array1 = (0, 0, 0, ... , 90)
    6 }
    7 print "@array1", "\n"; # 0 0 0 ... 0 90
    8
    9
    10 $array2[0] = 0;
    11 $array2[9] = 9;
    12 print "@array2", "\n"; # 0 "" "" ... "" 9
    13 map { $_ *= 10 } @array2; # ERROR!!!!!!
    14 print "@array2", "\n";

    line 1-7 work well, but using map, line 13 reports an error:

    Modification of a read-only value attempted at t2.pl line 13.


    Before line 13, line 12 prints the intervening elements, treating
    undef as null string. Then why does line 13 make such error? Is it a
    bug? or...?
    Raymundo, May 17, 2007
    #1
    1. Advertising

  2. On 16 May 2007 23:42:07 -0700, Raymundo <> wrote:

    >Subject: Modifying $_ in "map", with an array containing a gap...

    ^^^^^^^^^^^^^^^^^^^^^
    ^^^^^^^^^^^^^^^^^^^^^

    DON'T! That's not what map() is for.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, May 17, 2007
    #2
    1. Advertising

  3. Raymundo

    Mirco Wahab Guest

    Raymundo wrote:
    > foreach and map functions show the same result when
    > an array has no gap.


    There are some misunderstanding from your side ;)

    > 1: $array1[0] = 0;
    > 2: $array1[9] = 9; # now $array1 = (0, undef, undef, ... , 9);
    > 3: print "@array1", "\n"; # 0 "" "" ... "" 9


    Warning: "Use of uninitialized value in join or string at line 3."

    > 4 foreach (@array1) {
    > 5 $_ *= 10 # $array1 = (0, 0, 0, ... , 90)
    > 6 }


    Warning: "Use of uninitialized value in multiplication (*) at line 5."

    > 7 print "@array1", "\n"; # 0 0 0 ... 0 90
    > 8


    No more warnings on #7, because the for *did* convert undef to numeric 0

    > 10 $array2[0] = 0;
    > 11 $array2[9] = 9;
    > 12 print "@array2", "\n"; # 0 "" "" ... "" 9


    Warning: Use of uninitialized value in join or string at line 12.

    > 13 map { $_ *= 10 } @array2; # ERROR!!!!!!


    Error: "Modification of a read-only value attempted at line 13."

    Do you understand, what this error means? $_ can't be written
    to ($_ = $_ * 10) in a map.

    > Before line 13, line 12 prints the intervening elements, treating
    > undef as null string. Then why does line 13 make such error? Is it a
    > bug? or...?


    No. The map operator is intended to convert one list, element by element,
    into a new list, leaving the old list as it is. The 'correct' usage of
    map would be, in your case:

    13: my @array3 = map { $_ * 10 } @array2;
    14: print "@array3", "\n";


    Regards

    Mirco
    Mirco Wahab, May 17, 2007
    #3
  4. On Thu, 17 May 2007 10:22:39 +0200, Michele Dondi wrote:

    > On 16 May 2007 23:42:07 -0700, Raymundo <> wrote:
    >
    >>Subject: Modifying $_ in "map", with an array containing a gap...

    > ^^^^^^^^^^^^^^^^^^^^^
    > ^^^^^^^^^^^^^^^^^^^^^
    >
    > DON'T! That's not what map() is for.
    >


    From perldoc -f map:

    Note that $_ is an alias to the list value, so it can be used
    to modify the elements of the LIST. While this is useful and
    supported, it can cause bizarre results if the elements of LIST
    are not variables. Using a regular "foreach" loop for this
    purpose would be clearer in most cases.

    So modifying $_ is supported, but as undef is not a variable we get
    bizarre results.

    This is clearly one of those cases where it isn't a bug, it's a
    feature. :)
    Martijn Lievaart, May 17, 2007
    #4
  5. On Thu, 17 May 2007 14:20:01 +0200, Martijn Lievaart
    <> wrote:

    >This is clearly one of those cases where it isn't a bug, it's a
    >feature. :)


    I didn't want to imply it were a bug, in fact I didn't write so.
    Indeed I know it is supported and in very rare situations may also be
    useful. But generally you use map() to *map* a list to another list,
    which its main use.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, May 17, 2007
    #5
  6. Raymundo

    Guest

    Raymundo <> wrote:
    > Hello,
    >
    > I'm sorry I'm not good at English. :)
    >
    > foreach and map functions show the same result when an array has no
    > gap.
    >
    > @array = (1, 2, 3, 4);
    > foreach (@array) {
    > $_ *= 10
    > }
    > # now, $array = (10, 20, 30, 40)
    >
    > @array = (1, 2, 3, 4);
    > map { $_ *= 10 } @array;
    > # now, $array = (10, 20, 30, 40)
    >
    > However, if an array contains a gap...
    >
    > 1 $array1[0] = 0;
    > 2 $array1[9] = 9; # now $array1 = (0, undef,
    > undef, ... , 9);
    > 3 print "@array1", "\n"; # 0 "" "" ... "" 9
    > 4 foreach (@array1) {
    > 5 $_ *= 10 # $array1 = (0, 0, 0, ... , 90)
    > 6 }
    > 7 print "@array1", "\n"; # 0 0 0 ... 0 90
    > 8
    > 9
    > 10 $array2[0] = 0;
    > 11 $array2[9] = 9;
    > 12 print "@array2", "\n"; # 0 "" "" ... "" 9
    > 13 map { $_ *= 10 } @array2; # ERROR!!!!!!
    > 14 print "@array2", "\n";
    >
    > line 1-7 work well, but using map, line 13 reports an error:
    >
    > Modification of a read-only value attempted at t2.pl line 13.
    >
    > Before line 13, line 12 prints the intervening elements, treating
    > undef as null string. Then why does line 13 make such error? Is it a
    > bug? or...?


    I don't know about a bug, but at least a mal-feature, I would say.
    There is a special kind of fly-weight undef used in sparse arrays.
    It should get promoted to the other kind of undef automatically when
    needed. Apparently being aliased through map or grep inhibits this
    automatic promotion, while being aliased through foreach doesn't inhibit
    it.


    This also gives the error:

    perl -le 'my @x; $x[5]=5; $_*=10 foreach grep 1, @x; print "@x"'


    removing the "grep 1," also removes the error.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , May 17, 2007
    #6
  7. On 17 May 2007 15:36:20 GMT, wrote:

    >needed. Apparently being aliased through map or grep inhibits this
    >automatic promotion, while being aliased through foreach doesn't inhibit
    >it.


    Thank you. While I still repeat my initial reply to the OP, the issue
    was subtler than I had understood.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, May 17, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. chlori

    Gap in IE, no gap in FF

    chlori, Jan 19, 2006, in forum: HTML
    Replies:
    1
    Views:
    449
    kchayka
    Jan 19, 2006
  2. JW
    Replies:
    1
    Views:
    444
    David Jeske
    Jul 12, 2003
  3. J W
    Replies:
    0
    Views:
    389
  4. Raymundo
    Replies:
    7
    Views:
    117
    Raymundo
    May 17, 2007
  5. nmvega
    Replies:
    1
    Views:
    164
Loading...

Share This Page