Chris Chris - 1 month ago 6
Perl Question

How do I alias a long package name without affecting the main package?

If I have a really long package name, I can alias that package by making an entry in the symbol table:

BEGIN {
# Make "Alias" be an alias for "Some::Really::Long::Package";
*Alias:: = \*Some::Really::Long::Package::;
# Equivalent to:
# *main::Alias:: = \*Some::Really::Long::Package::;
}


This is what something like
Package::Alias
does for you internally. However, this stinks because it mucks with the
main
package. How can I make the alias only affect the current package, and be able to use just the alias within the package? I tried changing the alias definition to

*Short::Alias:: = \*Some::Really::Long::Package::;


But then I have to use
Short::Alias->myMethod()
instead of just
Alias->myMethod()
.

use strict;
use warnings;

package Some::Really::Long::Package;

sub myMethod {
print "myMethod\n";
}

package Short;

BEGIN {
# Make "Alias" be an alias for "Some::Really::Long::Package";
*Short::Alias:: = \*Some::Really::Long::Package::;
}

# I want this to work
Alias->myMethod();

package main;

# I want this to not work
Alias->myMethod();





Bonus points if both
Alias->myMethod()
and
Alias::myMethod()
work in the
Short
package, and not in
main
.

Answer

Since you don't want to modify the symbol table of main, you could create a "package-local" alias with

package Short;

use constant Alias => 'Some::Really::Long::Package'; # create alias
Alias->myMethod(); # correctly calls myMethod() of package Some::Really::Long::Package

or alternatively

package Short;

sub Alias { Some::Really::Long::Package:: } # create alias
Alias->myMethod(); # correctly calls myMethod() of package Some::Really::Long::Package

Both examples should work as intended. Consequently, any attempt to call Alias->myMethod() from package main will obviously fail with

Can't locate object method "myMethod" via package "Alias" (perhaps you forgot to load "Alias"?)

because the symbol table %main:: or %:: has no such entry called Alias::.


Due to the fact that you have several package calls in one file, you can also create $alias to reference Some::Really::Long::Package. Then you can limit the scope of $alias to the package Short to make it inaccessible from other places:

package Short;
{
   my $alias = Some::Really::Long::Package::; # create alias
   $alias->myMethod(); # correctly calls myMethod() of package Some::Really::Long::Package
}

I will update this answer in case I'm able to come up with more ideas.