Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Modifying $_ in "map", with an array containing a gap...

Reply
Thread Tools

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

 
 
Raymundo
Guest
Posts: n/a
 
      05-17-2007
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...?

 
Reply With Quote
 
 
 
 
ron.hartikka@gmail.com
Guest
Posts: n/a
 
      05-17-2007

$array2[0] = 0;
$array2[9] = 9;
print "@array2", "\n"; # 0 "" "" ... "" 9
map { defined $_ ? $_ *= 10 : 0 } @array2;
print "@array2", "\n"; # 0 "" "" ... "" 90

 
Reply With Quote
 
 
 
 
Mirco Wahab
Guest
Posts: n/a
 
      05-17-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> $array2[0] = 0;
> $array2[9] = 9;
> print "@array2", "\n"; # 0 "" "" ... "" 9
> map { defined $_ ? $_ *= 10 : 0 } @array2;


map { $_ *= 10 if defined } @array2;

will do in the context.

> print "@array2", "\n"; # 0 "" "" ... "" 90


I think it's generally a bad practice to
emphasize such solutions which are clearly
of bad style and will lead to dozens of
warnings under 'use warnings'.

Regards

Mirco
 
Reply With Quote
 
Mirco Wahab
Guest
Posts: n/a
 
      05-17-2007
Glenn Jackman wrote:
> At 2007-05-17 11:02AM, "(E-Mail Removed)" wrote:
>>
>> $array2[0] = 0;
>> $array2[9] = 9;
>> print "@array2", "\n"; # 0 "" "" ... "" 9
>> map { defined $_ ? $_ *= 10 : 0 } @array2;
>> print "@array2", "\n"; # 0 "" "" ... "" 90

>
> Of course, @array2 no longer contains undefined values at this point:
> it contains zeroes instead.


Wrong guess

Of course will @array2 keep the undefs.

Regards

Mirco
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      05-17-2007
On May 17, 8:40 am, Raymundo <(E-Mail Removed)> wrote:

> I'm sorry I'm not good at English.


Good enough.

> 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...?


Yes it's a bug.

The subtly is the difference between elements of an array that are
undef and ones that are non-existent.

See "perldoc -f exsts".

If I say..

my @array2;
$array2[0] = 0;
$array2[9] = 9;

...then elements 1..8 of @array are not just undef but non-existent.

In for() there is special magic to allow you to have a reference to a
non-existent element of an array without it becoming autovivified.

In map() there's evidently no such magic. In the LIST argument in
map() any non-existent elements are replaced by the "one true undef"
aka PL_sv_undef. (The one you get a reference to by saying \undef).

IMNSHO this needs to be explained in "perldoc -f map" or changed.

Note: if you think what map() does is odd then consider what happens
if you pass a gappy array to a subroutine! Here gap in the argument
leave gaps in @_ but modifying the missing element in @_ gives no
error but does not modify the missing element in the original array.

sub inc {
for my $i ( 0.. $#_ ) {
$_[$i]++;
}
}

my @array;
$array[1]=666;

inc @array;

print join ',' => @array; # ,667

 
Reply With Quote
 
Mirco Wahab
Guest
Posts: n/a
 
      05-17-2007
Brian McCauley wrote:
> The subtly is the difference between elements of an array that are
> undef and ones that are non-existent.


Very interesting, I wasn't even aware of it.

Lets see:
my @array;
$array[0] = 0;
$array[9] = 9;

then elements 1..8 will be(Devel:eek)
"NULL" SV's with Refcnt of 1

SV = NULL(0x0) at 0x182d528
REFCNT = 1
FLAGS = ()


in 'for', these NULL SV's are replaced dynamically
by something strange:

SV = PVLV(0x18b3164) at 0x182d510
REFCNT = 2
FLAGS = (GMG,SMG)
IV = 0
NV = 0
PV = 0
MAGIC = 0x18e3474
MG_VIRTUAL = &PL_vtbl_defelem
MG_TYPE = PERL_MAGIC_defelem(y)
TYPE = y
TARGOFF = 1
TARGLEN = -1
TARG = 0x1b8d8e4
SV = PVAV(0x22b4c4) at 0x1b8d8e4
REFCNT = 3
FLAGS = (PADBUSY,PADMY)
IV = 0
NV = 0
ARRAY = 0x20093bc
FILL = 9
MAX = 11
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = IV(0x1823db at 0x1ffca94
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 0
Elt No. 1
Elt No. 2
Elt No. 3


==> Dump $_ for @array


in 'map', the same NULL SV's will keep NULL
and get Refcounts of -2^31 plus the READONLY flag:

SV = NULL(0x0) at 0x224b30
REFCNT = 2147479514
FLAGS = (READONLY)

==> map Dump($_), @array


Very interesting. Thanks for
giving some infos on the topic.

Regards

Mirco

 
Reply With Quote
 
Mirco Wahab
Guest
Posts: n/a
 
      05-17-2007
Brian McCauley wrote:
> Note: if you think what map() does is odd then consider what happens
> if you pass a gappy array to a subroutine! Here gap in the argument
> leave gaps in @_ but modifying the missing element in @_ gives no
> error but does not modify the missing element in the original array.
>
> sub inc {
> for my $i ( 0.. $#_ ) {
> $_[$i]++;
> }
> }


More funny, *in* the sub, the NULL SV
*is* autovivicated, but *after* the sub,
the vivicated SV* isn't propagated back
to the original array (Devel:eek 'Dump'):

sub inc {
$_[1]++;
Dump($_[1]);
}

SV = IV(0x191f83c) at 0x1ffcc08
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 1

- - - - - - - - - - -

inc @array;
Dump($array[1]);

SV = NULL(0x0) at 0x1b93ea8
REFCNT = 1
FLAGS = ()

Rergards

Mirco
 
Reply With Quote
 
Raymundo
Guest
Posts: n/a
 
      05-17-2007
On 5월18일, 오전2시28분, Brian McCauley <(E-Mail Removed)> wrote:
> On May 17, 8:40 am, Raymundo <(E-Mail Removed)> wrote:
>
> > I'm sorry I'm not good at English.

>
> Good enough.
>
>
>
>
>
> > 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...?

>
> Yes it's a bug.
>
> The subtly is the difference between elements of an array that are
> undef and ones that are non-existent.
>
> See "perldoc -f exsts".
>
> If I say..
>
> my @array2;
> $array2[0] = 0;
> $array2[9] = 9;
>
> ..then elements 1..8 of @array are not just undef but non-existent.
>
> In for() there is special magic to allow you to have a reference to a
> non-existent element of an array without it becoming autovivified.
>
> In map() there's evidently no such magic. In the LIST argument in
> map() any non-existent elements are replaced by the "one true undef"
> aka PL_sv_undef. (The one you get a reference to by saying \undef).
>
> IMNSHO this needs to be explained in "perldoc -f map" or changed.
>
> Note: if you think what map() does is odd then consider what happens
> if you pass a gappy array to a subroutine! Here gap in the argument
> leave gaps in @_ but modifying the missing element in @_ gives no
> error but does not modify the missing element in the original array.
>
> sub inc {
> for my $i ( 0.. $#_ ) {
> $_[$i]++;
> }
>
> }
>
> my @array;
> $array[1]=666;
>
> inc @array;
>
> print join ',' => @array; # ,667- 따온 텍스트 숨기기 -
>
> - 따온 텍스트 보기 -


Thank you, McCauley. Now I understand (I hope I do the situation.

And I thank everyone who replied in this thread. I forgot to say in my
first post but... yes, I know that the main purpose of map() is making
a new list rather than modifying a existing array. However I thought
it had to be supported (as perldoc -f map says) and I had no idea why
for() and map() operate differently.

Raymundo at South Korea

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Address of a specific element: an Array containing Array References... nmvega Perl Misc 1 10-30-2008 09:52 PM
Modifying $_ in "map", with an array containing a gap... Raymundo Perl Misc 6 05-17-2007 05:34 PM
Newbie problem with modifying array correctly Marco Guiseppe Ruby 2 02-08-2007 09:31 PM
Re: Passing pointer to array from C to Python..and modifying same array in python? J W Python 0 07-14-2003 02:59 PM
Passing pointer to array from C to Python..and modifying same array in python? JW Python 1 07-12-2003 10:45 PM



Advertisments