my

A

Awkish

Hello,
I'm a bit puzzled by the following behavior:

VARIANT 1:
===========
perl -e '
my $var=0;
sub fonc{
$var++;
printf "sub: $var\n";
}
$var=5;
my @arr=( 10,20,30 );
for $var (@arr){
printf "main: $var\n";
fonc();}
'

This gives:
main: 10
sub: 6
main: 20
sub: 7
main: 30
sub: 8


VARIANT 2:
===========
perl -e '
sub fonc{
$var++;
printf "$var\n";
}
$var=5;
my @arr=( 10,20,30 );
for $var (@arr){
printf "main: $var\n";
fonc();
}
'

This gives:
main: 10
11
main: 20
21
main: 30
31


Strange! What is the effect of "my"?
 
C

cperry

This is more of a scope issue I think
Since sub{} and my() were created at the same scope, my $var is
accessible within
 
J

John W. Krahn

Awkish said:
Hello,
I'm a bit puzzled by the following behavior:

VARIANT 1:
===========
perl -e '
my $var=0;
sub fonc{
$var++;
printf "sub: $var\n";
}
$var=5;
my @arr=( 10,20,30 );
for $var (@arr){
printf "main: $var\n";
fonc();}
'

This gives:
main: 10
sub: 6
main: 20
sub: 7
main: 30
sub: 8

perldoc perlsyn

[ snip ]

Foreach Loops

The "foreach" loop iterates over a normal list value and sets the
variable VAR to be each element of the list in turn. If the variable
is preceded with the keyword "my", then it is lexically scoped, and is
therefore visible only within the loop. Otherwise, the variable is
implicitly local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with "my", it uses
that variable instead of the global one, but it's still localized to
the loop. This implicit localisation occurs only in a "foreach" loop.



John
 
B

Ben Morrow

perldoc perlsyn

[ snip ]

Foreach Loops

The "foreach" loop iterates over a normal list value and sets the
variable VAR to be each element of the list in turn. If the variable
is preceded with the keyword "my", then it is lexically scoped, and is
therefore visible only within the loop. Otherwise, the variable is
implicitly local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with "my", it uses
that variable instead of the global one, but it's still localized to
the loop. This implicit localisation occurs only in a "foreach" loop.

This explanation doesn't seem quite right to me. AFAICS, there is only
one $var in the above, with a scope over both the sub and the for loop;
so if for simply local()ised that variable (I know you can't local()
lexicals; but the concept isn't stupid, and perhaps for can) I would
expect to get '10 11 12 13 14 15'. Instead, it seems as though if the
variable was previously declared a lexical, for creates a *new* lexical
over its own scope, exactly as though you had said C<for my $var () {}>.

Am I being stupid, or could the docs use a little revision?

Ben
 
P

Peter J. Holzer

perldoc perlsyn

[ snip ]

Foreach Loops

The "foreach" loop iterates over a normal list value and sets the
variable VAR to be each element of the list in turn. If the variable
is preceded with the keyword "my", then it is lexically scoped, and is
therefore visible only within the loop. Otherwise, the variable is
implicitly local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with "my", it uses
that variable instead of the global one, but it's still localized to
the loop. This implicit localisation occurs only in a "foreach" loop.

This explanation doesn't seem quite right to me. AFAICS, there is only
one $var in the above, with a scope over both the sub and the for loop;
so if for simply local()ised that variable (I know you can't local()
lexicals; but the concept isn't stupid, and perhaps for can) I would
expect to get '10 11 12 13 14 15'.

Why? If anything I'd expect '10 11 20 21 30 31'. I.e., $var is set to
each value in @arr in turn and then incremented in fonc. But that would
imply that the loop can change which version of $var fonc() sees and I
don't think that's possible with lexical variables
(I guess I should have a look at how that stuff is implemented one day).
Instead, it seems as though if the variable was previously declared a
lexical, for creates a *new* lexical over its own scope, exactly as
though you had said C<for my $var () {}>.

I think this is what is meant. I.e. "localized" is only used informally
here and means that the variable is visible only within the loop, not
that local() is called on it.

Am I being stupid, or could the docs use a little revision?

The latter I think. It's ambiguous in the best case.

Even if it is internally implemented differently, I think the effect
would be better described as:

therefore visible only within the loop. Otherwise, the variable is
implicitly local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with "my",
the loop variable is also lexically scoped to the loop, as if
it was preceded with the keyword "my".

hp
 
T

Tad McClellan

Ben Morrow said:
perldoc perlsyn

[ snip ]

Foreach Loops

The "foreach" loop iterates over a normal list value and sets the
variable VAR to be each element of the list in turn. If the variable
is preceded with the keyword "my", then it is lexically scoped, and is
therefore visible only within the loop. Otherwise, the variable is
implicitly local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with "my", it uses
that variable instead of the global one, but it's still localized to
the loop. This implicit localisation occurs only in a "foreach" loop.

This explanation doesn't seem quite right to me. AFAICS, there is only
one $var in the above, with a scope over both the sub and the for loop;
so if for simply local()ised that variable (I know you can't local()
lexicals; but the concept isn't stupid, and perhaps for can) I would
expect to get '10 11 12 13 14 15'. Instead, it seems as though if the
variable was previously declared a lexical, for creates a *new* lexical
over its own scope,


Adding some instrumentation seems to confirm a new lexical:

--------------------------------
#!/usr/bin/perl
use warnings;
use strict;

my $var=0;
my $identity = \$var;
print "file id=$identity\n";

sub fonc{
my $identity = \$var;
print "fonc id=$identity\n";
$var++;
printf "sub: $var\n";
}
$var=5;
my @arr=( 10,20,30 );
for $var (@arr){
my $identity = \$var;
print "for id=$identity\n";
printf "main: $var\n";
fonc();
}
--------------------------------

output:

file id=SCALAR(0x8167900)
for id=SCALAR(0x8166c28)
main: 10
fonc id=SCALAR(0x8167900)
sub: 6
for id=SCALAR(0x8166d48)
main: 20
fonc id=SCALAR(0x8167900)
sub: 7
for id=SCALAR(0x816787c)
main: 30
fonc id=SCALAR(0x8167900)
sub: 8

exactly as though you had said C<for my $var () {}>.


Adding "my" to the for gives the same output. It even has the same addresses.

Am I being stupid, or could the docs use a little revision?


No and yes, respectively.
 
B

Brian McCauley

Peter said:
Even if it is internally implemented differently, I think the effect
would be better described as:

therefore visible only within the loop. Otherwise, the variable is
implicitly local to the loop and regains its former value upon exiting
the loop. If the variable was previously declared with "my",
the loop variable is also lexically scoped to the loop, as if
it was preceded with the keyword "my".

Indded. On several occasions in the past I've gone one stage further
and suggested that when this implicit my() happens Perl should emit a
warning.
 

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

Forum statistics

Threads
474,202
Messages
2,571,055
Members
47,659
Latest member
salragu

Latest Threads

Top