Reputation: 1099
Suppose I'm manipulating a hash that's in another package, and I want to create an alias to that variable? What's a clean way to do that? This sample code shows what I want to do, but it, and a dozen variations of it malfunction.
#!/usr/bin/perl
#use strict; # I want it to work with strict.
my $p = Person->new("Joe");
my $name;
*name = \*$p->{"name"}; # Latest broken attempt
printf("'%s' should eq '%s' because they both point to the same place.\n",
$name, $p->{"name"});
$name = "Sam";
printf("'%s' should eq '%s' because they both point to the same place.\n",
$name, $p->{"name"});
exit 0;
package Person;
sub new {
my $class = shift;
my $this = {};
bless $this, $class;
$this->{"name"} = shift;
return $this;
}
The functionality I want is to be able to manipulate $p->{"name"}
dozens of times without having to type $p->{"name"}
repeatedly. The real data structure is far more complex with a lot of nested hashes.
It's probably something easy. Thanks.
Upvotes: 1
Views: 1212
Reputation: 85837
The easiest way is to make a copy:
use strict;
use warnings;
my $p = { name => "Joe" };
my $name = $p->{name};
print "'$name' is '$p->{name}'\n";
This is what I'd use if I don't need to assign to $name
.
If you want to be able to write through $name
, the easiest way is to make it a reference:
use strict;
use warnings;
my $p = { name => "Joe" };
my $name = \$p->{name};
print "'$$name' is '$p->{name}'\n";
$$name = "Jill";
print "'$$name' is '$p->{name}'\n";
If you really want an alias, the easiest way is to abuse a for
loop:
use strict;
use warnings;
my $p = { name => "Joe" };
for my $name ($p->{name}) {
print "'$name' is '$p->{name}'\n";
$name = "Jill";
print "'$name' is '$p->{name}'\n";
}
If your perl is new enough (5.22+), you can also do aliasing through references:
use strict;
use warnings;
use feature 'refaliasing';
my $p = { name => "Joe" };
\my $name = \$p->{name};
print "'$name' is '$p->{name}'\n";
$name = "Jill";
print "'$name' is '$p->{name}'\n";
Finally, you can do aliasing to package variables by assigning to typeglobs, but that's not something I'd actually use here:
use strict;
use warnings;
my $p = { name => "Joe" };
*name = \$p->{name}; # sets *name{SCALAR} to point to $p->{name}
our $name; # declares $name so we can use it to refer to $main::name
print "'$name' is '$p->{name}'\n";
$name = "Jill";
print "'$name' is '$p->{name}'\n";
Upvotes: 6