mswanberg
mswanberg

Reputation: 1285

typeglob aliases

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

Answers (4)

ikegami
ikegami

Reputation: 386461

Three ways:

  1. 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.

  2. 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.

  3. Data::Alias

    alias my @B = @$A;
    

Upvotes: 9

edem
edem

Reputation: 3272

All variables in a perl programs are stored in namespaces. There are two types of namespaces:

  1. Symbol tables. It is a global hash which stores record of global variables.
  2. Lexical scopes. It is anonymous temporary memory which is stored, not a PARTICULAR symbol table but it is attached to a block of your program. They store variables which we can see only in that program block.

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

mswanberg
mswanberg

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

jmcneirney
jmcneirney

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

Related Questions