in reply to Re^2: Indirect variable name
in thread Indirect variable name

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.

Replies are listed 'Best First'.
Re^4: Indirect variable name
by LanX (Saint) on Nov 21, 2008 at 00:08 UTC
    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

      sorry I don't understand this argumentation, if you want to make a symderef on a lexical you can always use eval

      Not if a closure didn't include that variable:

      use strict; use warnings; my $sub = do { my $x = 4; my $y = 5; sub { my $a = shift; print 'Accessing $x: ', $x + $a, "\n"; print 'Accessing $y from eval: ', eval '$y + $a', "\n"; }; }; $sub->(2); __END__ Accessing $x: 6 Use of uninitialized value in addition (+) at (eval 1) line 1. Accessing $y from eval: 2

      Whoops. Perl knows at compile time which lexicals in outer scopes are needed for a closure, and only stores those.

      With the current current behaviour only eval can be used to detect that. That's OK because eval has the "evil, don't use" stigma on it.

      If symbolic deref would also look in lexicals, every deref might break this optimization.

      I hope it's a bit clearer now.

        Thanks, but

        > That's OK because eval has the "evil, don't use" stigma on it.

        Well which is perfectly the same with symderef, that's why it's not strict!

        When the code breaks, the compiler can't be blamed. No optimization would be hindered by that.

        Cheers Rolf

Re^4: Indirect variable name
by blazar (Canon) on Nov 20, 2008 at 20:59 UTC
    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.
      Hi blazar,

      I agree with you that these are two different variable systems, and the implementation of lexicals is only half way... mainly because a lot of actions on packagevars are not possible with lexicals.

      But personally I prefer halfway to nothing!

      > 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, ...

      please, could you give me a link explaining this magical unification? My fantasy fails to imagine lexicals as package-vars ... or what exactly do you mean with "lexical variables as package variables" ???

      OTH it shouldn't be that difficult to harmonize these two systems... eg. with something like a dynamic hash %PAD for the active block as equivalent to stashes like %main:: ! %PAD would replace the use of padwalker.

      Cheers LanX

        please, could you give me a link explaining this magical unification? My fantasy fails to imagine lexicals as package-vars ... or what exactly do you mean with "lexical variables as package variables" ???

        I personally believe that I may well be the least entitled person to give you any further piece of information. (For any incorrect, imprecise, misleading claim in this post I hope to stand corrected ASAP by the intervention of someone who's more knowledgeable than I am!) For one thing however, packages in Perl 6 are different beasts wrt to their Perl 5 equivalents: for example, typeglobs are gone forever... but IIRC there are more sound and relevant (for the sake of the issue we're discussing here) differences as well. I seem to remember having read, at some point, that lexical variables are nothing but package variables of a magic ::MY package corresponding to the current lexical block. Of course, if all this has not changed, it must be somewhere within Perl 6's docs.

        OTOH I also wonder how all this can mix with the fact that we can have lexically scoped packages too! (Declared with my, of course.) Again, if it's still true, then I would like both to see it backported to Perl 5, albeit, as I said, possibly only in terms of UI (well, if some more power could be given en passant that would be not so bad, don't you think so?) and to see how much of it can be backported there, from a consistency and orthogonality POV... (I'm the kind of guy interested in the "phylosophical POV" if it were not clear enough!)

        --
        If you can't understand the incipit, then please check the IPB Campaign.
Re^4: Indirect variable name
by FreakyGreenLeaky (Sexton) on Nov 20, 2008 at 16:29 UTC
    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
      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
      The last 2 aren't working because, in the second case, you are trying to call the flag method on the variable named Util::Stuff::aaa1; and, in the third case, you are referring to the variable named Util::Stuff::aaa1->flag (no method call is occurring). What you want to do is to call the flag method on the class Util::Stuff::aaa1 itself—no symbolic references are required.
      our $v = 'Util::Stuff::aaa1'; print $v->flag;
        In other words $$v->flag is not being dereferenced and the method called, as I incorrectly assumed.

        Thanks for all the help.
Re^4: Indirect variable name
by FreakyGreenLeaky (Sexton) on Nov 20, 2008 at 13:40 UTC
    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.
      probably because he explains later