http://www.perlmonks.org?node_id=724856

FreakyGreenLeaky has asked for the wisdom of the Perl Monks concerning the following question:

Greets,

Following on from the great explanation by LanX here Re: Accessing list of package names in a module, I'm now trying to figure out how to dereference a variable who's name has been previously extracted from a module.

Simply put, given the following variable and it's contents (where Util::Stuff:aaa1 comes from a loaded module):
my $var = 'Util::Stuff::aaa1'
I wish to get at the 'flag' value which is defined in Util::Stuff:aaa1 as:
package Util::Stuff::aaa1; sub flag { 10 } ...
Something akin to:
print $"$var" # oogly, I know :-)
ie, "interpolate" the variable to get the actual name before dereferencing.

Possible?
Normal usage of Util::Stuff::aaa1 would be
print Util::Stuff::aaa1->flag ...
Apologies if I haven't explained myself clearly.

Thanks
Henry

Replies are listed 'Best First'.
Re: Indirect variable name
by moritz (Cardinal) on Nov 20, 2008 at 12:57 UTC
    It's called "symbolic reference" in perl, and works like this:
    $ perl -wle ' our $x = 34; my $name = "x"; print $$name' 34

    If you have use strict; in effect, you need no strict 'refs' in the scope where you do the symbolic deref.

    Update: Please be aware that most of the time symbolic references are a very bad idea, and hashes can be used to a very similar effect. Actually symbol tables are hashes, but they are specially used by the perl interpreter/compiler.

      moritz, thou art the Father Pope of All Perlorian Monks

      Thanks!
      A reply falls below the community's threshold of quality. You may see it by logging in.
      Interesting that this doesn't work if you declare $x with my (instead of our). Any idea why that is?
        my variables are stored in the lexical pad (which is a hidden data structure associated with every block), while our variables are globals that are stored in the symbol table, for which our installs a lexically scoped alias.

        Symbolic deferences only look in the symbol table, not in the lexical pad. A reason for that is that lexical variables can be removed from an outer pad when taking a closure, and allowing symbolic differentiation would defeat that optimization.

        (Sorry if that explanation was very technical and relies on internals; if you don't understand it, read it as "it's much more efficient to implement that way")

        Update: if you are more interested in philosophical arguments, there's a fundamental asymmetry between lexicals and entries in the symbol table: lexicals always have names that are identifiers, whereas symbol table entries can have arbitrary names:

        $ perl -lwe '*4 = sub { print "yes" }; 4->()' yes

        So under some circumstance it might be better not to mix up the lookup of those two.

        to make it a bit less technical, the lexical variables are much younger in perl history than the package variables, dating back to perl 4 3 2 1 or older.

        Lexicals are by definition private to the lexical block, marked by { curlies }. You can rely on that they will be destroyed after leaving the block! This "hiddeness" is a quality (!) package-vars do not have. (*)

        (Note: The biggest possible block is the containing file, and you could prolong the lifetime by returning references - thats also a matter of garbage collection and closures and ... getting to far)

        Package variables OTH have the quality to be as global as possible, if you know the packagename you can access them from everywhere in the program, any file.

        So lexicals can't be in the stash associated to a package!!! If you want to inspect them you need to hack with moduls like padwalker.

        Saying that lexicals are "much younger", explains some inconsequences / inorthogonalities of perls syntax.

        e.g. you can (without extra non-core moduls) only alias a packagevar $a directly with globs * eg *a=$b but not lexical vars ...

        ... which leads to the problem that you end using hashrefs and arrayrefs as returnvalues

        ... which as a consequence complicate the sourcecode cluttered with dereferencing syntax

        my ($arr_ref)=func(); push @{ $arr_ref->[1][2] }, "elem"; # hate this @{}

        ... sigh!!! O Perl 6! Where art thou!!!

        Cheers LanX

        UPDATES:

        (*) neither Python AFAIK

        MENMONIC: because packagevars are as global as possible they are ours, meanwhile lexicals belong privately to the block/sub, they are "my-ne". ; )

Re: Indirect variable name
by GrandFather (Saint) on Nov 20, 2008 at 20:45 UTC

    Having read through the replies to date, it seems to me that there is some XY stuff going on here - you are seeking to solve a problem (X) that is what you perceive to be the solution to your real problem (Y). You will likely get a much better result if you tell us about the bigger (Y) problem.

    If you find yourself "needing" symbolic references then most likely you have overlooked a better solution. Symbolic references are almost never the Right Answer™.


    Perl reduces RSI - it saves typing