Erik Bennett
Erik Bennett

Reputation: 1099

how to create perl aliases? typeglobs?

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

Answers (1)

melpomene
melpomene

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

Related Questions