localizing lexical aggregates

P

Paul Lalli

Greetings.

I recently found out entirely by accident that it is possible to
localize members of a hash or array which have been declared lexical.
In other words, the following "works" just fine:

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

my @n = (1..10);
print "N: @n\n";

{
local $n[5] = 'foo bar';
print "N: @n\n";
}

print "N: @n\n";

__END__

N: 1 2 3 4 5 6 7 8 9 10
N: 1 2 3 4 5 foo bar 7 8 9 10
N: 1 2 3 4 5 6 7 8 9 10

I discovered this when I wanted to temporarily change an attribute of a
database handler reference in a large chunk of code. After compiling
and running, I suddenly realized "Wait, that shouldn't work.". I was
shocked to find that it did.

My shock stems from the long-held (apparently wrong) belief that only
package variables can be localized. And indeed, it seems that is
partially true - an entire lexical variable cannot be localized, only
members of lexical aggregates:

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

my @n = (1..10);
print "N: @n\n";
{
local @n = (11..20)
print "N: @n\n";
}
print "N: @n\n";

__END__

Can't localize lexical variable @n at ./lex.pl line 8.

Reading up on local in perlsub, I find that my findings do match what
the docs say, but that the docs are rather vague on the topic as a
whole. They say that local may only localize Package Variables, but in
a later paragraph, may also localize "certain l-values", such as parts
of hashes and arrays.

All of this boils down to a single question: If members of lexical
hashes and arrays can be localized, is there any particular *reason*
for the inability to localize entire lexical variables?

Thanks for your input,
Paul Lalli
 
A

Ala Qumsieh

Paul said:
I recently found out entirely by accident that it is possible to
localize members of a hash or array which have been declared lexical.
Interesting.

All of this boils down to a single question: If members of lexical
hashes and arrays can be localized, is there any particular *reason*
for the inability to localize entire lexical variables?

Well, other people might have better insight, but my gut feeling is the
following. Since lexical variables do not live in the stash, the
inability to localize them is deliberate. They were designed to be that
way, or else we wouldn't have local/my/our. The fact that you can
localized members of a lexical hash or array is simply a side-effect of
the way the members are stored, and I would consider it a "bug".

My two cents,
--Ala
 
P

Paul Lalli

Ala said:
The fact that you can
localized members of a lexical hash or array is simply a side-effect of
the way the members are stored, and I would consider it a "bug".

I would too, except that it seems as though there's some
features/modules that depend upon it. For example, the DBI
documentation very specifically says that the recommended way of
turning off PrintError within a subroutine likely to cause errors is
local $dbh->{PrintError} = 0;

If that "bug" were fixed, things like this would break rather
spectacularly.

Paul Lalli
 
B

Brian McCauley

Paul said:
All of this boils down to a single question: If members of lexical
hashes and arrays can be localized, is there any particular *reason*
for the inability to localize entire lexical variables?

No, it's largely a historical mistake. When lexical variables were
introduced it was decided to disallow local() to "help" programmers by
informing them that they should (99% of the time) be using my() to
redeclare a lexical in an inner scope rather than localizing. It has
been suggested a number of times that this has out-lived it's
usefullness. It is, I suspect, unlikely this will ever be changed in
Perl5. In Perl6 it has been.
 
P

Paul Lalli

Brian said:
No, it's largely a historical mistake. When lexical variables were
introduced it was decided to disallow local() to "help" programmers by
informing them that they should (99% of the time) be using my() to
redeclare a lexical in an inner scope rather than localizing. It has
been suggested a number of times that this has out-lived it's
usefullness. It is, I suspect, unlikely this will ever be changed in
Perl5. In Perl6 it has been.

Interesting. Thanks for the information!

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top