Reputation: 1285
Okay, so it's easy to create a reference to an array...
my @a;
my $b=\@a;
#can now reference the same list of scalars from either @$b or @a
But how can I do this in reverse? For instance:
my $a=[1..4];
my @b;
#some magic happens here and now @b is an alias for @$a
@b=(6..10);
print "@$a\n"; #should print "6 7 8 9 10"
I assume this would happen through typeglobs, but those just elude me. Ideas?
Also it would be nice to do the same for hashes as well as arrays.
EDIT: This seems to work, but it's a tad kludgy as it just copies the anon array elements to the "alias" and then re-points itself to the array:
my @b=@$a;
$a=\@b;
Any better ideas?
Upvotes: 5
Views: 2568
Reputation: 386461
Three ways:
Refaliasing.
5.22 added an experimental feature that does exactly what you want.
use experimental qw( refaliasing );
\my @B = $A;
5.26 added a second experimental feature that allows the following:
use experimental qw( refaliasing declared_refs );
my \@B = $A;
Note that, being an experimental features, these features are subject to change and removal at any time.
Glob aliasing
Perl calls "type glob", or "glob" for short, its symbol table entry data structure. It is possible to set the entries in this data structure to a reference to name that reference.
local our @B;
*B = $A; # Sets the array slot of "B", @B.
Note that we have to use a package variables, so the variable is globally visible.
alias my @B = @$A;
Upvotes: 9
Reputation: 3272
All variables in a perl programs are stored in namespaces. There are two types of namespaces:
Typeglobs are used to define a record (a variable, an array etc.) of Symbol tables, but not Lexical scopes. So, when you use this part of code:
my @b;
*b = $a;
you will get it:
Name "main::b" used only once:
This says us that the record main::b is not defined in a Symbol tables by us, but we can do it with a modifier "our". Therefore when you write so:
our @b;
*b = $a;
We can get an usefull result for us because *b is stored in a Symbol tables and we can use an operator * typeglob.
Upvotes: 6
Reputation: 1285
I think I got it...
my $a=[1..4];
our @b;
*b=$a;
print "@b\n";
@b=(6..10);
print "@$a\n";
prints:
1 2 3 4
6 7 8 9 10
"our" is still a bit of a mystery to me... I guess I have some reading to do...
Upvotes: 3
Reputation: 1384
$a and @a are not the same thing. $a, as you first assign it is a reference to an anonymous array. It doesn't have anything to do with @a, which is an array (not a reference).
$b = \@a # $b holds a reference to @a but not to $a.
$a, @a, %a are all different variables. So, if you have
my @a = (1,2,3,4);
And then you declare
my $a;
$a doesn't hold a reference to @a;
The variables are held in the symbol table by their type; scalar, hash, array, etc. That way you can have $a, @a, %a, &a ... and the don't conflict with one another.
The point is that
#some magic happens here and now @b is an alias for @$a
doesn't happen. It's still pointing the area in memory where @a is stored which is different than where $a is stored.
Upvotes: 0