#!/usr/bin/perl -w
use strict;
my $aref = [1, 2, 3];
my @a = @$aref; # this line
$a[1] = 99;
print "aref = @$aref\n";
print "a = @a\n";
produces output:
aref = 1 2 3
a = 1 99 3
The output shows that @a
and @$aref
do not refer to the same array.
The marked line is where my problem lies. The value of scalar $aref
is a reference to an anonymous array. In the marked line I was hoping to be able to make the array variable @a
refer to that array, but what happens is that the anonymous array is copied and @a
refers to a copy of the anonymous array. The assignment and print statements show this.
I understand that when you assign to an array the right hand side of the assignment is a list context, so the @$aref
is coerced to a list of its elements. Is there a way to give the name @a
to the array referred to by $aref
?
You create an anonymous array by using square brackets like this: $arrayref = [ 'one', 'two', 'three' ]; There exists an array that has no name but is available via the $arrayref reference, which is just like any other array reference in all other respects.
Perl anonymous references These types of references are called anonymous references. The rules of creating anonymous references are as follows: To get an array reference, use square brackets [] instead of parentheses. To get a hash reference, use curly brackets {} instead of parentheses.
An anonymous hash is simply a hash without a name. Both named and anonymous hashes have references, and \%hash is no more a direct reference than { foo => "bar" } . You imply that the latter is an indirect reference. – Borodin.
A list is an ordered collection of scalars. An array is a variable that contains a list. In Perl, the two terms are often used as if they're interchangeable. But, to be accurate, the list is the data, and the array is the variable.
I wonder why would you want to do this? I presume it's a performance issue, but the usual solution is to pass your data around by reference. It is just as easy to write $aref->[1]
as $a[1]
You could alias your reference in the package symbol table by assigning to the typeglob, but the alias must be a package variable
use strict;
use warnings;
my $aref = [1, 2, 3];
our @a;
*a = $aref;
$a[1] = 99;
print "aref = @$aref\n";
print "a = @a\n";
aref = 1 99 3
a = 1 99 3
There are a number of modules that offer a nice syntax and allow you to alias lexical variables
Here's a version that uses Lexical::Alias
which has the advantage of aliasing lexical variables, and could be more robust than assigning to typeglobs. Data::Alias
works in a very similar way. The output is identical to the above
use strict;
use warnings;
use Lexical::Alias qw/ alias_r /;
my $aref = [1, 2, 3];
alias_r $aref, \my @a;
$a[1] = 99;
print "aref = @$aref\n";
print "a = @a\n";
an alternative way is to use alias
instead of alias_r
with
alias @$aref, my @a;
our @array; local *array = $aref;
Pros: Built-in feature since 5.6.
Cons: Ugly. Uses a global variable, so the variable is seen by called subs.
use Data::Alias qw( alias );
alias my @array = @$aref;
Pros: Clean.
Cons: This module gets broken by just about every Perl release (though it gets fixed quickly if not before the actual release).
use feature qw( refaliasing );
no warnings qw( experimental::refaliasing );
\my @array = $aref;
Pros: Built-in feature.
Cons: Requires Perl 5.22+, and even then, the feature is experimental.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With