Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: Indirect variable name

by moritz (Cardinal)
on Nov 20, 2008 at 12:57 UTC ( [id://724857]=note: print w/replies, xml ) Need Help??


in reply to Indirect variable name

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.

Replies are listed 'Best First'.
Re^2: Indirect variable name
by FreakyGreenLeaky (Sexton) on Nov 20, 2008 at 13:01 UTC
    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.
Re^2: Indirect variable name
by FreakyGreenLeaky (Sexton) on Nov 20, 2008 at 13:23 UTC
    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.

        Hi Moritz

        > 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 I don't understand this argumentation, if you want to make a symderef on a lexical you can always use eval. The optimization shouldn't be bothered about this possibility.

        our $x=666; #develish { my $x='et voila'; my $y="x"; print eval "\$$y"; # prints "et voila" }
        If ever it fails because of optimization, it's in the responsibility of the hacker, like eval is.

        so why shouldn't there be a symderef for lexicals, that actually does an eval???

        the reason why perl 5 can't do this out of the box, is IMHO most probably that lexicals were too new to consider all use-cases...

        Cheers LanX

        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:

        I personally believe, speaking of philosophical arguments, that having what that basically boils down to two independent variable systems is particularly annoying especially because they're in fact so similar to each other, thus adding to confusion rather than diminishing it! A posteriori, if say lexical variables looked all that different from package ones, then one would not even think of asking herself why something e.g. "works when variables are declared with our but not with my."

        OTOH not only do I cherish the way Perl 6 solves the issue by implementing lexical variables as package variables thus unifying the two systems into one, "just" by means of a special, magic (and then some people still whine that Perl 6 is not magic enough any more...) package, but I... well, personally believe to even be annoying myself for having said so many times how much I would love this feature to be backported to Perl 5. Of course, if it ever were, I don't expect so in terms of an actual implementation, which would be too big a of dream but as a sort of convenient UI to modules like PadWalker & C.

        --
        If you can't understand the incipit, then please check the IPB Campaign.
        Using symbolic references for plain variables works as expected. However, I'm stuck on how to reference 'flag' below.

        Origional code:
        package Util::Stuff::aaa1; sub flag { 10 } #### use Util::Stuff; print Util::Stuff::aaa1->flag; # yields 10 ... our $v = 'Util::Stuff::aaa1'; print $$v->flag; # yields undef error ... our $v = 'Util::Stuff::aaa1->flag'; print "$$v\n"; # yields nothing

        If it wasn't for the need to find a clean way to glue two separate projects together, I wouldn't bother with this. However, it's an interesting issue and I'm keen to learn something different.

        Thanks!
        Henry
        Thanks for the detailed explanation.

        The Camel Book also doesn't go into details about why. It just mentions it in passing (almost as if the author was saying "don't ask me why.":)

        Cheers.
      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". ; )

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://724857]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (6)
As of 2024-04-23 19:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found