scope of MY in FOREACH with global array

B

Bill

I've been programming perl for a while now and I can't believe something so
simple is confusing me. Take a look at the following code:

-------------------------
#!/usr/bin/perl -w

# global array definition
my @array = ("a","b","c");

sub print_array {
foreach my $element (@array) {
$element .= "9";
print $element . "\n";
}
}

for ($i = 0; $i < 3; $i++) {
&print_array();
}
------------------------

The output is as follows:

a9
b9
c9
a99
b99
c99
a999
b999
c999

What I expected was:

a9
b9
c9
a9
b9
c9
a9
b9
c9

I thought that "my" would make a copy of each array element whose scope was
limited to the subroutine in which it was defined. But it seems that
modifying the elements locally is modifying them in the global array as
well. What am I missing here?

-Bill
 
J

Jürgen Exner

Bill said:
-------------------------
#!/usr/bin/perl -w

# global array definition
my @array = ("a","b","c");

sub print_array {
foreach my $element (@array) {
$element .= "9";
print $element . "\n";
}
}

for ($i = 0; $i < 3; $i++) {
&print_array();
}
------------------------ [...]
I thought that "my" would make a copy of each array element whose
scope was limited to the subroutine in which it was defined. But it
seems that modifying the elements locally is modifying them in the
global array as well. What am I missing here?

Simple. The loop variable ($element in this case, $_ by default) is an
_alias_ of the array element, not a copy. That means, when you write
$element .= "9" this has the same effect as using $array[$CURRENTINDEX] .=
"9". Otherwise it would be impossible to use such a loop to alter the array
elements. And because @array is global those changes stick.

Now, the scoping rule for my effect $element. That means, if there were a
global variable $element, then that global variable would have been
protected from undesired changes by the "my $element".

In short: the "my" localizes the variable $element, but not the variable
@array.

jue
 
B

Brian McCauley

Bill said:
foreach my $element (@array) {
I thought that "my" would make a copy of each array element

No, the for-loop interator variable is an _alias_ not a _copy_ of an
element in the list over which you are iterating. Changes made to the
loop iterator variable $elmenet are, therefore, changes to acual
elements of @array.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
P

Paul Lalli

I've been programming perl for a while now and I can't believe something so
simple is confusing me. Take a look at the following code:

-------------------------
#!/usr/bin/perl -w

# global array definition
my @array = ("a","b","c");

sub print_array {
foreach my $element (@array) {
$element .= "9";
print $element . "\n";
}
}

for ($i = 0; $i < 3; $i++) {
&print_array();
}
------------------------

I thought that "my" would make a copy of each array element whose scope was
limited to the subroutine in which it was defined. But it seems that
modifying the elements locally is modifying them in the global array as
well. What am I missing here?

You're missing the difference between a value in memory and the name that
refers to it. The 'symbol' (for lack of a better term here) called
$element is is scoped to only within the foreach loop. However, that
symbol represents an alias to the values in @array. Because it's an
alias, not a copy, you are directly modifying @array. If you were to try
to access $element outside the foreach loop, it would have no value.

In short, the 'name' $element is what's scoped, not the memory location it
represents.

Paul Lalli
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,159
Messages
2,570,879
Members
47,414
Latest member
GayleWedel

Latest Threads

Top