5

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?

mswanberg
  • 1,285
  • 8
  • 20

4 Answers4

9

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;
    
ikegami
  • 367,544
  • 15
  • 269
  • 518
6

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.

kingsfoil
  • 3,795
  • 7
  • 32
  • 56
edem
  • 3,222
  • 3
  • 19
  • 45
3

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

mswanberg
  • 1,285
  • 8
  • 20
  • This might be helpful: http://stackoverflow.com/questions/4623556/symbol-table-deleting-entries-question – creaktive Dec 28 '12 at 14:52
0

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

jmcneirney
  • 1,374
  • 8
  • 23
  • I fear you have missed the point of my question entirely. I know that $a and @a are different things. That's not the point. I know how to take a reference to an array and store it in a scalar, as in $b=\@a. My questions is in making the declaration in the reverse order... I want to place @a on top of the same memory location as @$b so that I can access that array in that memory location from both methods. Obviously, @a=@$b won't do it as that COPIES the array elements. \@a=$b doesn't work either... "Can't modify reference constructor in scalar assignment..." as the error states. – mswanberg Dec 28 '12 at 14:30
  • FYI, my "some magic happens here" isn't a reference to something Perl does... it's a reference to "tell me what commands/code to put here to make the following happen" – mswanberg Dec 28 '12 at 14:35
  • Ok. You need to make that clear in your question then. I can't know that based on what you wrote. – jmcneirney Dec 28 '12 at 14:39
  • 1
    Apologies... seems perfectly clear when you look at the code and the desired output. – mswanberg Dec 28 '12 at 14:44