tags:

views:

121

answers:

2

I know it is possible to use a variable as a variable name for package variables in Perl. I would like to use the contents of a variable as a module name. For instance:

package Foo;
our @names =("blah1", "blah2");
1;

And in another file I want to be able be able to set the contents of a scalar to "foo" and then access the names array in Foo through that scalar.

my $packageName = "Foo";

Essentially I want to do something along the lines of:

@{$packageName}::names; #This obviously doesn't work.

I know I can use

my $names = eval '$'. $packageName . "::names" 

But only if Foo::names is a scalar. Is there another way to do this without the eval statement?

+3  A: 

Strict checking is preventing you from using a variable (or literal string) as part of a name, but this can be disabled locally:

my @values;
{
    no strict 'refs';
    @values = @{"Mypackage"}::var;
}
Ether
Essentially what I'm doing is globbing a directory for *.pm and then for each file I find I require $filename. Once those modules are loaded I then need to access the @names variable defined inside each package. I don't know the package's name until runtime, all I have is a variable which will contain the name of the package.
mjn12
I'm not have a problem loading packages from a variable name - I've got that part down. Its accessing the variables within those packages. This answer would have definitely save me a lot of googling an hour ago though :)
mjn12
@mjn: oops sorry, I'm editing my answer now to make the real issue more prominent :)
Ether
+6  A: 

To get at package variables in package $package, you can use symbolic references:

no strict 'refs';
my $package = 'Foo';

# grab @Foo::names
my @names = @{ $package . '::names' }

A better way, which avoids symbolic references, is to expose a method within Foo that will return the array. This works because the method invocation operator (->) can take a string as the invocant.

package Foo;

our @names = ( ... );
sub get_names { 
    return @names;
}

package main;
use strict;

my $package = 'Foo';
my @names = $package->get_names;
friedo
No parens on get_names?
Paul Nathan
I think I like the alternative method you described, long as I can define get_names in Foo's base class (we'll call it Bar to be original) that way I can just define @names in every class which inherits from Bar. I'm using Moose objects if that makes any difference.
mjn12
@Paul, parens are not required on method calls if there are no arguments. Some people prefer to always include an empty `()` for consistency, but I generally leave them out if I can.
friedo
@friedo: Gotcha. I prefer the consistency personally.
Paul Nathan
You can consistentially leave off parens, too. That's consistent. :)
brian d foy