Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Creating an alias to an existing hash (from a hash reference)

5 views
Skip to first unread message

jl_...@hotmail.com

unread,
Dec 17, 2009, 5:52:16 PM12/17/09
to
Hi,

Recently I was reviewing someone's Perl code and I saw that his
code used a few global variables that were set and accessed by several
functions. Since I am not a fan of global variables, I edited the
code to get rid of all but one of them.

(For the record, his code used "strict" and "warnings".)

The remaining global variable was a hash. I proceded to edit the
code so that the functions took a hash reference as an input
argument. So previously, the code looked something like:

my %hash;

{
f1();
f2();
f3();
f4();
}

sub f1 { ... }
sub f2 { ... }
sub f3 { ... }
sub f4 { ... }

(This is a simplification.)

I changed those lines to something like:

sub f1 { ... }
sub f2 { ... }
sub f3 { ... }
sub f4 { ... }

{
my %hash;

f1(\%hash);
f2(\%hash);
f3(\%hash);
f4(\%hash);
}

In the function definitions themselves, I added code to read in the
input arguments, like this:

sub f
{
my ($hashRef) = @_;
.
.
.
}

However, all the functions still referred to %hash (which at this
point was no longer visible to the functions). So I figured I had to
change all instances of "$hash{...}" to "$hashRef->{...}".

But then I thought: Could there be another way that doesn't
involve changing all those instances in each function? I'd like to do
something similar to what C++ allows with references:

int cat = 5;
int & dog = cat;
// Now every change made to dog will be
// reflected in cat, and vice-versa.

The idea of creating a new variable named %hash came to mind:

sub f
{
my ($hashRef) = @_;
my %hash = %$hashRef;
.
.
.
}

but that would create a completely new copy of the original %hash
(using extra memory), and any changes made to the copy would have to
be copied back to the original be returning from the function, like
this:

%$hashRef = %hash;

I thought of using typeglobs, like this:

local *hash = $hashRef;

which would allow %hash to be used as if it were a real hash, all the
while reading and writing from the hash that $hashRef points to.

However, since his code had "use strict;" in effect, "perl -c"
responded with:

Variable "%hash" is not imported at ...

So I declared %hash the line before with "my", like this:

my %hash;
local *hash = $hashRef;

That didn't work; although it compiled just fine, %hash was empty.
So then I changed it to be declared with "our" instead of "my", like
this:

our %hash;
local *hash = $hashRef;

and that worked. From then on in that function, every instance of
%hash pointed back to the passed-in %hash (that was passed in as a
reference).

However, I'm a little concerned with the usage of "our". That has
the effect of creating a package variable named %hash (separate from
the lexical), which can be accessed from anywhere in the package. Is
this a good idea to do?

In other words, if I need to create an alias for a variable, is it
a good idea to do something like this:

our %dog;
local *dog = \%ENV;
# Now %dog and %ENV are the same:
# any changes made to %dog will
# affect %ENV, and vice-versa.

or is there a better way to do this?

...or should I just bite the bullet and change all the instances of
%hash in the functions to hash references?

Any thoughts, advice, and ideas are welcome.

-- Jean-Luc

P.S. Incidentally, the generated Perl code that find2perl creates
uses this typeglob approach to create aliases named $name, $dir, and
$prune.

Ben Morrow

unread,
Dec 17, 2009, 6:52:44 PM12/17/09
to

Quoth "jl_...@hotmail.com" <jl_...@hotmail.com>:

>
> Recently I was reviewing someone's Perl code and I saw that his
> code used a few global variables that were set and accessed by several
> functions. Since I am not a fan of global variables, I edited the
> code to get rid of all but one of them.

Good work :).

> The remaining global variable was a hash. I proceded to edit the
> code so that the functions took a hash reference as an input
> argument. So previously, the code looked something like:

<snip>


>
> In the function definitions themselves, I added code to read in the
> input arguments, like this:
>
> sub f
> {
> my ($hashRef) = @_;
> .
> .
> .
> }
>
> However, all the functions still referred to %hash (which at this
> point was no longer visible to the functions). So I figured I had to
> change all instances of "$hash{...}" to "$hashRef->{...}".
>
> But then I thought: Could there be another way that doesn't
> involve changing all those instances in each function? I'd like to do
> something similar to what C++ allows with references:

use Data::Alias;

sub f {
my ($hashRef) = @_;

alias my %hash = %$hashref;
...;
}

I'm rather fond of D::A, for exactly this reason.

<snip>


> I thought of using typeglobs, like this:
>
> local *hash = $hashRef;
>
> which would allow %hash to be used as if it were a real hash, all the
> while reading and writing from the hash that $hashRef points to.
>
> However, since his code had "use strict;" in effect, "perl -c"
> responded with:
>
> Variable "%hash" is not imported at ...
>
> So I declared %hash the line before with "my", like this:
>
> my %hash;
> local *hash = $hashRef;
>
> That didn't work; although it compiled just fine, %hash was empty.

Typeglobs always refer to package globals. Lexicals don't live in
typeglobs, so you need a module like Data::Alias to do the aliasing
magic for you.

> So then I changed it to be declared with "our" instead of "my", like
> this:
>
> our %hash;
> local *hash = $hashRef;
>
> and that worked. From then on in that function, every instance of
> %hash pointed back to the passed-in %hash (that was passed in as a
> reference).
>
> However, I'm a little concerned with the usage of "our". That has
> the effect of creating a package variable named %hash (separate from
> the lexical), which can be accessed from anywhere in the package. Is
> this a good idea to do?

Absolutely not. This variable is now *more* global than the file-scoped
'my %hash' you started with. In particular, if you have an 'our %hash'
in another sub, it will refer to the *same* variable.

A rule of thumb is that 'our' variables, like named subs, should always
appear at file scope, not inside a function.

> ...or should I just bite the bullet and change all the instances of
> %hash in the functions to hash references?

Some might consider D::A obscure. If you think you need to please such
people, you will have to do the find-and-replace. (With a decent editor
it shouldn't be difficult.)

> P.S. Incidentally, the generated Perl code that find2perl creates
> uses this typeglob approach to create aliases named $name, $dir, and
> $prune.

Yes. find2perl is *very* old, and predates the invention of 'my'.
Playing fancy tricks with typeglobs was entirely standard in Perl 4, as
there was often no alternative.

Ben

Ruben Safir

unread,
Dec 17, 2009, 9:54:53 PM12/17/09
to

It would probably be better to just use an object.


Oh.. - why do you say that?

C.DeRykus

unread,
Dec 18, 2009, 8:56:19 AM12/18/09
to
On Dec 17, 2:52 pm, "jl_p...@hotmail.com" <jl_p...@hotmail.com> wrote:
> ...

>    However, since his code had "use strict;" in effect, "perl -c"
> responded with:
>
> Variable "%hash" is not imported at ...
>
> So I declared %hash the line before with "my", like this:
>
>    my %hash;
>    local *hash = $hashRef;
>
>    That didn't work; although it compiled just fine, %hash was empty.
> So then I changed it to be declared with "our" instead of "my", like
> this:
>
>    our %hash;
>    local *hash = $hashRef;
>
> and that worked.  From then on in that function, every instance of
> %hash pointed back to the passed-in %hash (that was passed in as a
> reference).

I was glad to hear about Data::Alias which's the way to go.
However, 'no strict', used sparingly, may make sense in some
cases too, particularly as an 'our' alternative:

{ no strict; local *hash = $hashRef; $hash{...} = ...; }

--
Charles DeRykus

jl_...@hotmail.com

unread,
Dec 18, 2009, 11:32:38 AM12/18/09
to
On Dec 18, 6:56 am, "C.DeRykus" <dery...@gmail.com> wrote:
> On Dec 17, 2:52 pm, "jl_p...@hotmail.com" <jl_p...@hotmail.com> > I was glad to hear about Data::Alias which's the way to go.

> However, 'no strict', used sparingly, may make sense in some
> cases too, particularly as an 'our' alternative:
>
> { no strict; local *hash = $hashRef; $hash{...} = ...; }


Actually, I'm pretty sure that, when "no strict" is in effect, all
non-declared variables are automatically treated as package variables
(that is, as if they were declared with "our").

So it's not really an alternative to "our"; instead, that's all
you'd be using (unless, of course, you explicitly use "my").

(I tested it out with the following example:

1. I started the Perl interpreter with: perl -wde 1

2. Then I typed:

use strict; { no strict; *blah = \%ENV; }

3. Then I was able to reference %ENV through %blah outside
of the scope %blah was fist used in, like this:

print $blah{PATH};

So disabling "strict" doesn't avoid the hazards of using "our",
unfortunately.)

And I agree with you that Data::Alias is definitely the way to go.
I just wish it was a standard module so it could be used without
having to install it explicitly.

-- Jean-Luc

jl_...@hotmail.com

unread,
Dec 18, 2009, 2:15:27 PM12/18/09
to
On Dec 17, 4:52 pm, Ben Morrow <b...@morrow.me.uk> wrote:
>     use Data::Alias;
>
>     sub f {
>         my ($hashRef) = @_;
>         alias my %hash = %$hashref;
>         ...;
>     }

Thanks, Ben, yet again! I just installed Data::Alias from CPAN,
and it works great.

It would be nice if it were a standard module, so I could freely
use it on code that is supposed to run on plain Perl installations
(where I have no control over which Perl modules are installed).

If I find myself in such a situation in the future (which I'm sure
will happen), I'll probably just resort to search-and-replacing
instances of "$hash{" to "$hashRef->{".

But if I'm in a situation where I'm free to use CPAN modules, I'll
probably be making good use of Data::Alias.

Thanks again, Ben.

-- Jean-Luc

jl_...@hotmail.com

unread,
Dec 18, 2009, 2:35:20 PM12/18/09
to
> On Thu, 17 Dec 2009 14:52:16 -0800, jl_p...@hotmail.com wrote:
> > The idea of creating a new variable named %hash came to mind:
>
> > sub f
> > {
> >    my ($hashRef) = @_;
> >    my %hash = %$hashRef;
> >    .
> >    .
> >    .
> > }
>
> > but that would create a completely new copy of the original
> > %hash (using extra memory),


On Dec 17, 7:54 pm, Ruben Safir <ru...@mrbrklyn.com> wrote:
> Oh.. - why do you say that?


Because when you make a copy of a hash, a completely separate copy
is made. Consider this code:

my %hash = %ENV;

or even:

my $hashRef = \%ENV;
my %hash = %$hashRef;

With either approach, %hash is now equivalent to %ENV, but only
temporarily, since it is a completely separate hash. If you add a new
entry to %hash, like this:

$hash{apple} = 'banana';

that same entry won't exist in %ENV. Likewise, if %ENV is modified
(for whatever reason), that modification won't carry over to %hash.

I hope this clarifies things, Ruben.

-- Jean-Luc

C.DeRykus

unread,
Dec 18, 2009, 2:55:59 PM12/18/09
to
On Dec 18, 8:32 am, "jl_p...@hotmail.com" <jl_p...@hotmail.com> wrote:
> On Dec 18, 6:56 am, "C.DeRykus" <dery...@gmail.com> wrote:
>
> > On Dec 17, 2:52 pm, "jl_p...@hotmail.com" <jl_p...@hotmail.com> > I was glad to hear about Data::Alias which's the way to go.
> > However, 'no strict', used sparingly, may make sense in some
> > cases too, particularly as an 'our' alternative:
>
> > { no strict; local *hash = $hashRef; $hash{...} = ...; }
>
>    Actually, I'm pretty sure that, when "no strict" is in effect, all
> non-declared variables are automatically treated as package variables
> (that is, as if they were declared with "our").
>

No, ordinary package variables and those declared with
'our' are scoped differently. And 'our' can be clobbered
in a multi-package global way that ordinary package
variables won't be:

perl -Mstrict -wle "package main; our $x=1;
package Foo; our $x=2;
package main; print $x"
2

vs.

perl -Mstrict -wle "package main; use vars '$x';$x=1;
package Foo; use vars '$x';$x=2;
package main; print $x"
1


>
>    So it's not really an alternative to "our"; instead, that's all
> you'd be using (unless, of course, you explicitly use "my").
>
>    (I tested it out with the following example:
>
> 1. I started the Perl interpreter with:  perl -wde 1
>
> 2. Then I typed:
>
>       use strict; { no strict; *blah = \%ENV; }
>
> 3. Then I was able to reference %ENV through %blah outside
>    of the scope %blah was fist used in, like this:
>
>       print $blah{PATH};
>
>    So disabling "strict" doesn't avoid the hazards of using "our",
> unfortunately.)
>

Hm, you didn't declare 'blah' or localize inside the
{no strict;...} so that won't compile outside of the
debugger:

perl -Mstrict -le "{no strict; *blah = \%ENV;}
print $blah{PATH}"
Variable "%blah" is not imported ...
Global symbol "%blah" requires explicit package name...


But with those corrections, the first print below
works as expected and the final print outside the
{no strict;...} draws an uninitialized warning:


perl -Mstrict -wle "use vars '%blah';
{no strict; local *blah = \%ENV; print $blah{PATH};}
print $blah{PATH}"

--
Charles DeRykus

Xho Jingleheimerschmidt

unread,
Dec 18, 2009, 3:09:53 PM12/18/09
to
jl_...@hotmail.com wrote:

> If I find myself in such a situation in the future (which I'm sure
> will happen), I'll probably just resort to search-and-replacing
> instances of "$hash{" to "$hashRef->{".

Don't forget about replacing "@hash{" with "@{$hashRef}{", and "keys
%hash" with "keys %$hashRef", etc.

Xho

jl_...@hotmail.com

unread,
Dec 18, 2009, 3:57:47 PM12/18/09
to
On Dec 18, 12:55 pm, "C.DeRykus" <dery...@gmail.com> wrote:
> the first print below
> works  as expected and the final print outside the
> {no strict;...} draws an uninitialized warning:
>
> perl -Mstrict -wle "use vars '%blah';
>       {no strict; local *blah = \%ENV; print $blah{PATH};}
>       print $blah{PATH}"


True, but the uninitialized warning happened because you used the
"local" keyword. If you remove that, then the second print() line
will have access to %ENV via %blah.

So you might think that using "local" prevents code in outside
scopes from accessing %ENV through %blah. But that's not true. The
"local" keyword temporarily changes the value of %blah, but it changes
it everywhere in the package, not just in its scope.

Consider this code:

perl -Mstrict -wle "{no strict; local *blah = \%ENV; f() }
sub f { our %blah; print $blah{PATH} }

Even though the code inside f() is in a completely different scope
that the code that calls f(), the code inside f() still has access to
%blah as the calling code sees it (and therefore has access to modify
%ENV through it).

Sure, declaring *blah as "local" in f() would prevent that from
happening, but since you can't always guarantee that all code will
"local"ize all its typeglobs, declaring one typeglob as "local" won't
necessarily stop all code (outside the intended scope) from accessing
what %blah references. (It'll stop some code, but not all code.)

Cheers,

-- Jean-Luc

jl_...@hotmail.com

unread,
Dec 18, 2009, 5:31:22 PM12/18/09
to
> jl_p...@hotmail.com wrote:
> >    If I find myself in such a situation in the future (which I'm sure
> > will happen), I'll probably just resort to search-and-replacing
> > instances of "$hash{" to "$hashRef->{".

On Dec 18, 1:09 pm, Xho Jingleheimerschmidt <xhos...@gmail.com>
replied:


> Don't forget about replacing "@hash{" with "@{$hashRef}{", and "keys
> %hash" with "keys %$hashRef", etc.


Very true. Yet another reason Data::Alias is so nice.

-- Jean-Luc

jl_...@hotmail.com

unread,
Dec 18, 2009, 5:46:19 PM12/18/09
to
On Dec 18, 12:55 pm, "C.DeRykus" <dery...@gmail.com> wrote:
> No, ordinary package variables and those declared with
> 'our' are scoped differently. And 'our' can be clobbered
> in a multi-package global way that ordinary package
> variables won't be:
>
>   perl -Mstrict -wle "package main; our $x=1;
>                       package Foo;  our $x=2;
>                       package main; print $x"
>   2
>
> vs.
>
>   perl -Mstrict -wle "package main; use vars '$x';$x=1;
>                       package Foo;  use vars '$x';$x=2;
>                       package main; print $x"
>   1


Interesting. I did not know that.

"perldoc -f our" helped me understand a little more.

Of course, if your scopes don't cross package boundaries, then this
isn't an issue to worry about. But if they do, then this is good to
know.

-- Jean-Luc

C.DeRykus

unread,
Dec 18, 2009, 6:59:01 PM12/18/09
to
On Dec 18, 12:57 pm, "jl_p...@hotmail.com" <jl_p...@hotmail.com>
wrote:

> On Dec 18, 12:55 pm, "C.DeRykus" <dery...@gmail.com> wrote:
>
> > the first print below
> > works  as expected and the final print outside the
> > {no strict;...} draws an uninitialized warning:
>
> > perl -Mstrict -wle "use vars '%blah';
> >       {no strict; local *blah = \%ENV; print $blah{PATH};}
> >       print $blah{PATH}"
>
>    True, but the uninitialized warning happened because you used the
> "local" keyword.  If you remove that, then the second print() line
> will have access to %ENV via %blah.

True but it can be a good idea in general to
insulate a variable with 'local' to avoid
avoid clobbering any potential existing values.
I thought you had control of that part of the
code...

>
>    So you might think that using "local" prevents code in outside
> scopes from accessing %ENV through %blah.  But that's not true.  The
> "local" keyword temporarily changes the value of %blah, but it changes
> it everywhere in the package, not just in its scope.
>
>    Consider this code:
>
>    perl -Mstrict -wle "{no strict; local *blah = \%ENV; f() }
>                        sub f { our %blah; print $blah{PATH} }
>
> Even though the code inside f() is in a completely different scope
> that the code that calls f(), the code inside f() still has access to
> %blah as the calling code sees it (and therefore has access to modify
> %ENV through it).
>
>    Sure, declaring *blah as "local" in f() would prevent that from
> happening, but since you can't always guarantee that all code will
> "local"ize all its typeglobs, declaring one typeglob as "local" won't
> necessarily stop all code (outside the intended scope) from accessing
> what %blah references.  (It'll stop some code, but not all code.)
>

That's expected because 'local's dynamic scoping
propagates the localized variable into any called
subroutine in the localized scope. For instance:

{ local $foo='bar'; f(); }

"The f() or any sub called within f() all the way
down the call stack will see $foo with its local
value 'bar'.

So, used correctly, 'local' does limit what's seen.
There's quite a bit of confusion about the gory
details of 'local' however. And details in perlsub
and perlfaq7 are skimpy..

--
Charles DeRykus

Ben Morrow

unread,
Dec 21, 2009, 2:05:37 PM12/21/09
to

Quoth "C.DeRykus" <der...@gmail.com>:

>
> So, used correctly, 'local' does limit what's seen.
> There's quite a bit of confusion about the gory
> details of 'local' however. And details in perlsub
> and perlfaq7 are skimpy..

What about local's behaviour is unclear to you?

Ben

C.DeRykus

unread,
Dec 21, 2009, 6:57:29 PM12/21/09
to
On Dec 21, 11:05 am, Ben Morrow <b...@morrow.me.uk> wrote:
> Quoth "C.DeRykus" <dery...@gmail.com>:

Plenty :) but I just intending to say that there's
more to 'local' than a quick peek at the docs might
show. There're some caveats/subtleties to 'local'.
as well as the need for understanding 'my vs. local',
and 'lexical vs. dynamic' scoping issues, etc.. Even
the word 'local' is a bit of a mis-nomer. Lots of
good info in perlsub but close, careful look(s) are
needed. Fun for young and old alike...

I can't find it now but there was a lengthy thread I just
saw yesterday (and now can't find) that dealt with what
appeared to be buggy behavior of local. I think Abigail
demo'ed a short code example to make the case for a bug.
Others, arguably more correct, countered the "bug' was
just a 'feature' due to the way 'local' was implemented.

--
Charles DeRykus

Tad McClellan

unread,
Dec 21, 2009, 8:38:48 PM12/21/09
to
C.DeRykus <der...@gmail.com> wrote:

[ snip: local() is hard to understand ]

> Even
> the word 'local' is a bit of a mis-nomer.


Mainly because of the way we humans "complete" it.

If we think "local variable" when we see local(), then confusion ensues,
as local isn't about variables.

We should instead think "local value" when we see local(), then there
is a better chance of understanding its action.

What is local about "local $foo" is not the variable $foo (which is,
in fact, a *global* variable).

What is local about "local $foo" is the _value_ associated with $foo.


Larry Wall was asked "if you could change one thing about Perl,
what would it be?".

He answered "I would not have named local() local"

(but I've heard him asked that question 3 times, and he
gave 3 different answers)


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"

Ben Morrow

unread,
Dec 21, 2009, 9:13:05 PM12/21/09
to

Quoth Tad McClellan <ta...@seesig.invalid>:

> C.DeRykus <der...@gmail.com> wrote:
>
> [ snip: local() is hard to understand ]
>
> > Even
> > the word 'local' is a bit of a mis-nomer.
>
>
> Mainly because of the way we humans "complete" it.
>
> If we think "local variable" when we see local(), then confusion ensues,
> as local isn't about variables.
>
> We should instead think "local value" when we see local(), then there
> is a better chance of understanding its action.
>
> What is local about "local $foo" is not the variable $foo (which is,
> in fact, a *global* variable).
>
> What is local about "local $foo" is the _value_ associated with $foo.

In Perl 6 local is (or was; I lose track) renamed to 'temp', which is a
much better name.

'local' is also a common builtin in Unix shells, with the same dynamic
scoping properties as Perl's local.

Ben

C.DeRykus

unread,
Dec 21, 2009, 11:13:53 PM12/21/09
to
On Dec 21, 3:57 pm, "C.DeRykus" <dery...@gmail.com> wrote:
> ...
> I can't find it now but there was a lengthy thread I just
> saw yesterday (and now can't find)  that dealt with what
> appeared to be buggy behavior of local. I think Abigail
> demo'ed a short code example to make the case for a bug.
> Others, arguably more correct, countered the "bug' was
> just a 'feature' due to the way 'local' was implemented.
>

Still can't find the thread but I think
the code was kinda/sorta like:

use strict;
use warnings;
use vars qw/$foo $bar/;
$foo = 3;
$bar = \$foo;
{
local $foo = 4;
print $$bar; # 3 not 4!
}


--
Charles DeRykus

Ben Morrow

unread,
Dec 22, 2009, 12:26:39 AM12/22/09
to

Quoth "C.DeRykus" <der...@gmail.com>:

>
> Still can't find the thread but I think
> the code was kinda/sorta like:
>
> use strict;
> use warnings;
> use vars qw/$foo $bar/;
> $foo = 3;
> $bar = \$foo;
> {
> local $foo = 4;
> print $$bar; # 3 not 4!
> }

Yes. This is where Tad's explanation of 'local' as 'local value' falls
down: like all good explanations, it only contains as much truth as it
needs to. In the interest of those reading the archives, I should
probably say

IF YOU ARE the least bit confused about the difference between 'local'
and 'my', DO NOT READ ANY FURTHER.

The usual distinction between 'variable' and 'value' is incomplete. In
Perl 5, as in most languages with true references, there are actually
three levels: 'name', 'container' and 'value'. The 'name' is an entry in
the symbol table (for globals) or the lexical pad (for lexicals) and
points to a 'container'; the 'container' holds a 'value', which can be
changed without changing the identity of the container.

When you take a reference to something, you are creating a 'value' that
points to a 'container': this is why it is possible to return references
to variables which have gone out of scope, since it is only the name
which has vanished. The container will be garbage-collected in due
course.

'local' takes the name you pass it, records which container it points to
to be restored at the end of the scope, and creates a new container for
the name to point to until then. (This is why 'local' variables start
out empty.) When you say

$bar = \$foo;

above, you are putting a reference to the *current* container for $foo
into $bar; this reference is now completely divorced from the name
'$foo' and is unaffected by 'local' pointing that name somewhere else.

Note that this is only true of Perl 5-style hard refs: Perl 4-style
symrefs point to a name (after all, they're only strings) so

no strict;
$foo = 3;
$bar = "foo";
{
local $foo = 4;
say $$bar;
}

will see the localized value for $foo, as you might have expected.

(I should probably point out that this explanation is also incomplete
:). In particular, it doesn't cover cases like

local $foo{bar};
local $$foo;
)

Ben

Marc Girod

unread,
Dec 22, 2009, 3:52:04 AM12/22/09
to
On Dec 22, 5:26 am, Ben Morrow <b...@morrow.me.uk> wrote:

> there are actually
> three levels: 'name', 'container' and 'value'.

Excellent discussion, which could be generalized
to a critique of the concept of 'high-level'.

High-level means: 'simpler on the surface'.
Low-level means: 'simpler at depth'.

Weren't you explaining a high-level concept
by the means of its (simpler) low-level
implementation?

Marc

Ben Morrow

unread,
Dec 22, 2009, 8:14:37 AM12/22/09
to

Quoth Marc Girod <marc....@gmail.com>:

I suppose. I find it impossible to understand any of the more complex
questions of variable lifetime (what happens when a lexical is captured
by a closure, for instance) without keeping the name/container/value
distinction straight. (Though I do call them 'SVs', of course :).)

Ben

C.DeRykus

unread,
Dec 22, 2009, 3:12:42 PM12/22/09
to
On Dec 21, 9:26 pm, Ben Morrow <b...@morrow.me.uk> wrote:
> Quoth "C.DeRykus" <dery...@gmail.com>:
>
>
>
> 'local' takes the name you pass it, records which container it points to
> to be restored at the end of the scope, and creates a new container for
> the name to point to until then. (This is why 'local' variables start
> out empty.) When you say
>
>     $bar = \$foo;
>
> above, you are putting a reference to the *current* container for $foo
> into $bar; this reference is now completely divorced from the name
> '$foo' and is unaffected by 'local' pointing that name somewhere else.

Thanks, great explanation.

And addresses confirm that the localized address
is now 'somewhere else':

perl -wle "no strict; $foo='foobar'; $bar=\$foo; print \$foo;
{ local $foo = 'foobar1'; print \$foo; }"
SCALAR(0x16808e4)
SCALAR(0x2b7b14)

>
> Note that this is only true of Perl 5-style hard refs: Perl 4-style
> symrefs point to a name (after all, they're only strings) so
>
>     no strict;
>     $foo = 3;
>     $bar = "foo";
>     {
>         local $foo = 4;
>         say $$bar;
>     }
>
> will see the localized value for $foo, as you might have expected.

Good 'ole slow, straightforward symrefs ;)

>
> (I should probably point out that this explanation is also incomplete
> :). In particular, it doesn't cover cases like
>
>     local $foo{bar};
>     local $$foo;
> )
>

--
Charles DeRykus

0 new messages