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

Re^2: Indirect variable name

by FreakyGreenLeaky (Sexton)
on Nov 20, 2008 at 13:23 UTC ( [id://724867]=note: print w/replies, xml ) Need Help??


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

Interesting that this doesn't work if you declare $x with my (instead of our). Any idea why that is?

Replies are listed 'Best First'.
Re^3: Indirect variable name
by moritz (Cardinal) on Nov 20, 2008 at 13:30 UTC
    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

        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.

      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

      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;
      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
Lexicals vs package vars
by LanX (Saint) on Nov 20, 2008 at 14:08 UTC
    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://724867]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2024-04-23 18:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found