globals and while

M

Matija Papec

use strict;
my $x = 3;
print "$y\n" while my $y = $x--;

Why does perl want to use global $y; can someone point me to relevant rtfm?
:)
 
U

Uri Guttman

MP> use strict;
MP> my $x = 3;
MP> print "$y\n" while my $y = $x--;

MP> Why does perl want to use global $y; can someone point me to relevant rtfm?
same reason why you can't refer to a my $sub from inside the closure
assigned to it:

my $sub = sub { $sub->( blah ) }

$sub isn't declared yet so the $sub inside the closure refers to a
global (or earlier lexical) $sub. your code has the same problem,
refering to a lexical declared the same statement.

the main reason for this is so you can do stuff like:

my $foo ;

{
# this assigns the value of the current foo to the new lexical foo
# if your code worked, then this would not be possible.

my $foo = $foo ;

mung with $foo
}

# print untouched foo
print $foo ;

perldoc -f my refers you to the private variables section of perlsub
which does cover this point.

The declared variable is not introduced (is not visible)
until after the current statement. Thus,

my $x = $x;

can be used to initialize a new $x with the value of the old
$x, and the expression

my $x = 123 and $x == 123

is false unless the old $x happened to have the value "123".



uri
 
A

Ala Qumsieh

Uri Guttman said:
MP> use strict;
MP> my $x = 3;
MP> print "$y\n" while my $y = $x--;

MP> Why does perl want to use global $y; can someone point me to relevant rtfm?
same reason why you can't refer to a my $sub from inside the closure
assigned to it:

my $sub = sub { $sub->( blah ) }

$sub isn't declared yet so the $sub inside the closure refers to a
global (or earlier lexical) $sub. your code has the same problem,
refering to a lexical declared the same statement.

But I thought that the OP's code was symantically identical to the
following:

use strict;
my $x = 3;
while (my $y = $x--) {
print "$y\n";
}

and this is perfectly fine. Why the difference in behaviour then?

--Ala
 
U

Uri Guttman

MP> my $x = 3;
MP> print "$y\n" while my $y = $x--;

AQ> But I thought that the OP's code was symantically identical to the
AQ> following:

AQ> use strict;
AQ> my $x = 3;
AQ> while (my $y = $x--) {
AQ> print "$y\n";
AQ> }

AQ> and this is perfectly fine. Why the difference in behaviour then?

how are those the same? the OP's code was a single statement, yours is a
while with a block. in the former, my $y means $y is not visible until
the next statement. in your code $y is visible to the code in the block.

the code make look similar but there is a major different in the scope
of $y.

uri
 
A

Ala Qumsieh

Uri Guttman said:
MP> my $x = 3;
MP> print "$y\n" while my $y = $x--;

AQ> But I thought that the OP's code was symantically identical to the
AQ> following:

AQ> use strict;
AQ> my $x = 3;
AQ> while (my $y = $x--) {
AQ> print "$y\n";
AQ> }

AQ> and this is perfectly fine. Why the difference in behaviour then?

how are those the same? the OP's code was a single statement, yours is a
while with a block. in the former, my $y means $y is not visible until
the next statement. in your code $y is visible to the code in the block.

I never said they were the same, just that I thought they were semantically
(sic) identical. I guess I'm wrong, but I don't really understand why. You
say that in the OP's code, the $y is not visible until the next statement,
but that doesn't seem intuitive to me since the "body" of the while loop
(i.e the print statement) will not execute until after the condition
(setting my $y = $x--) has been tested, at which point $y has been defined
as a lexical variable. And since it's defined in the condition part of the
while loop, then it ought to be available in the body, just like my longer
version of the code. To me (and I have never designed a language, so please
excuse my ignorance), both versions of the code ought to behave the same way
(the OP's version has an "invisible block" if you will). But, I get the
feeling that this might break something.

Btw, is this related to the fact that in statements of the form "EXPR
foreach EXPR" you can only use $_ as your loop variable?

Now, I would immediately see why this is wrong:

do {
print "$y\n";
} while my $y = $x--;

since this will evaluate the body before the condition.

--Ala
 
U

Uri Guttman

AQ> I never said they were the same, just that I thought they were
AQ> semantically (sic) identical. I guess I'm wrong, but I don't
AQ> really understand why. You say that in the OP's code, the $y is
AQ> not visible until the next statement, but that doesn't seem
AQ> intuitive to me since the "body" of the while loop (i.e the print
AQ> statement) will not execute until after the condition (setting my
AQ> $y = $x--) has been tested, at which point $y has been defined as
AQ> a lexical variable. And since it's defined in the condition part
AQ> of the while loop, then it ought to be available in the body, just
AQ> like my longer version of the code. To me (and I have never
AQ> designed a language, so please excuse my ignorance), both versions
AQ> of the code ought to behave the same way (the OP's version has an
AQ> "invisible block" if you will). But, I get the feeling that this
AQ> might break something.

there is NO block in the single statement line. so my $y is not declared
yet and can't be refered to in the same statement. there is NO implicit
block as it is a single statement with a modifier.

in the blcok form, the my $y is visible to the BLOCK as it is not in the
same statement line as the declaration.

AQ> Btw, is this related to the fact that in statements of the form "EXPR
AQ> foreach EXPR" you can only use $_ as your loop variable?

larry never created a syntax that would support a named lexical
there. it could be for a similar reason.

uri
 
R

Roy Johnson

Ala Qumsieh said:
Btw, is this related to the fact that in statements of the form "EXPR
foreach EXPR" you can only use $_ as your loop variable?

Yes. The issue is that your declared variable doesn't exist until the
end of the declaration. Anything that happens in the same statement
cannot use that variable:
my $x = 3, print "$x\n";
will cause strict to give the same complaint.

Note that assigments are sort of a special case. You can use the
result of an assignment/declaration, e.g.,:
my $x = my $y = 3;
so you could do
my $y = abs(my $x = -3);
but not
my $x = 3, my $y = abs($x);

Even this is ok:
sub mod_arg { $_[0]++ }
my $y = mod_arg(my $x = -3);
print "$x and $y\n";
or even
my $y = (my $x = -3)++;

But you can't use an assignment/declaration as a loop variable.

You can do this little weirdo with nary a peep from strict (though
warnings gives you a heads-up):
print --$a,"\n" and sleep 1 while (my $a = 3);
Note that the $a in the print is $main::a and not the lexical $a in
the while. If you make it a block-form while, you are declaring $a on
every pass through the loop, so the printed value never changes.
 
R

Roy Johnson

Ala Qumsieh said:
Btw, is this related to the fact that in statements of the form "EXPR
foreach EXPR" you can only use $_ as your loop variable?

Actually, I should have said "no" to this. In general, loop variables
are localized global variables, so in theory, Perl could have allowed
you to specify loop variables for one-line loops (even if not "my"
variables). So fundamentally, it's a syntax issue that disallows named
loop vars for one-line loops.

On the other hand, if they were allowed, the scoping problem would
still be a problem.
 
M

Matija Papec

X-Ftn-To: Uri Guttman

Uri Guttman said:
$sub isn't declared yet so the $sub inside the closure refers to a
global (or earlier lexical) $sub. your code has the same problem,
refering to a lexical declared the same statement.

the main reason for this is so you can do stuff like:

my $foo ;

{
# this assigns the value of the current foo to the new lexical foo
# if your code worked, then this would not be possible.

my $foo = $foo ;

mung with $foo
}

# print untouched foo
print $foo ;

perldoc -f my refers you to the private variables section of perlsub
which does cover this point.

The declared variable is not introduced (is not visible)
until after the current statement. Thus,

my $x = $x;

can be used to initialize a new $x with the value of the old
$x, and the expression

my $x = 123 and $x == 123

Tnx, this was insightful; so only what matters is a statement which can't
define lexical and use it at the same time.
 

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
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top