http://qs321.pair.com?node_id=149343

Fool on the Hill has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I would really like to be able to get a variable name from a reference so that I could do things like this:
#!/usr/bin/perl -w use strict; my %hash1=("A"=>1); my %hash2=("B"=>2); foreach my $hashref (\%hash1,\%hash2) { print "$hashref:",ref($hashref),":",(join ",",sort keys %{$hashref}) +,"\n";
Output
HASH(0x2002a3d0):HASH:A HASH(0x2002a418):HASH:B
But I would really like to display the name of the hash that is referenced like this:
hash1:A hash2:B
Cheers.

Replies are listed 'Best First'.
Re: Getting a variable name from a reference
by MZSanford (Curate) on Mar 05, 2002 at 13:46 UTC
    Let me start by saying, this should never be done. never. Ok, that aside, i thought of a way that might work.
         You could loop through the %main:: hash, and compare the values of each name-spaces hash variable. Something like this (untested code and idea):
    %hash1 = ('A' => 1); $href = \%hash1; foreach my $name (keys %main::) { if ($href eq \%{"main::$name"}) { print "Hash ref is for %",$name,"\n"; } }

    Please note, i do not condone this behavior.
    from the frivolous to the serious

      Note that variables declared with my are not in any symbol table. So this won't work for the code used in the original question.

              - tye (but my friends call me "Tye")
      I agree that it's probably not a good thing to do but, If you don't find it in the package, ie.. it's a lexical, you could try PadWalker.

      -Lee

      "To be civilized is to deny one's nature."
Re: Getting a variable name from a reference
by strat (Canon) on Mar 05, 2002 at 12:47 UTC
    I think, this is not possible, because if you put a reference to a hash, the name of the hash is not saved, just it's adress.

    Probably, you could save the name of the hash in the hash before referencing it.

    Best regards,
    perl -le "s==*F=e=>y~\*martinF~stronat~=>s~[^\w]~~g=>chop,print"

      You're right - it can't be done without saving the name of the name of the variable and some additional jiggery pokery. At least it can't be done with a hard reference like this. The reason it can't be done is because a hard reference is just and address - so the "thingie" that the address points to might have no varable name, such as an anonymous hash:

      $hashref = {'Anonymous' => 'Hash'}; #hash has no varable #name - just reference

      Additionally, a varable might have more than one name, if it has aliases.

      Back in Perl 4 (which I've never used) there were no hard refs, so you had to use variable - name - plus eval tricks to do reference type stuff. This might do what you want it to (warning - untested code):

      #usr/bin/perl -w use strict; my %hash1 = ('A' => 1); my $hashname1 = 'hash1'; my %hash2 = ('B' => 2); my $hashname2 = 'hash2'; eval qq (print qq(Hashname: $$hashname1 Values:); print join ",",sort +keys %{$hasname1})" ); eval qq (print qq(Hashname: $$hashname1 Values:); print join ",",sort +keys %{$hasname1}) );

      But these kinds of eval tricks I'm not used to - and you probably shouldn't use them anyway. Also, you can't print out a memory address here, unless you add in a pair of hard refs.

      Cheers,
      Erik
Re: Getting a variable name from a reference
by Sweeper (Pilgrim) on Mar 05, 2002 at 21:57 UTC
    Do not confuse variables and values. References apply to values, so you can reference anonymous arrays, anonymous hashes and anonymous subroutines. In these cases your request cannot be fulfilled.

    On the other hand, with typeglob assignment, several variables can be associated to a single value. In this case, you would have several variable names for the single value your reference points to.

    Further, you can reference an element of an array

    $r_array_elem = \$array[1]
    instead of the usual
    $r_array = \@array
    which references the whole array. In this case, what would your name-retrieving operation yield?

    Note this code was taken verbatim from page 20 of Advanced Perl Programming (Sriram Srinivasan, O'Reilly). The first chapter deals with references, and is very interesting. The only glitch is that it does not warn sufficiently about the banana skins you get with symbolic variables. Nevertheless, this is a good book.

      Hello,

      Thanks for the clarification. I am going to borrow a colleagues Advanced Perl Programming and read some more (I foolishly thought I understood references).

      I still think it would be nice (but maybe impossible?) to find out what refers to a particular piece of data/value. I understand that there is a reference count that means that even if a lexical goes out of scope if it has been referenced and the reference is still in scope then the value will be preserved.

      After reading your reply and Programming Perl again, I now see that the reference is basically a one way link between reference and the value (referent). The diagram 8.1 (from Programming Perl) is particularly useful. It seems like this is one case where symbolic references are the ones to use. (It has been hammered into me that soft references are bad.....)

      Many Thanks for everybodys help.

Re: Getting a variable name from a reference
by koolade (Pilgrim) on Mar 05, 2002 at 18:18 UTC

    You can use symbolic references:

    our %hash1 = ("A"=>1); our %hash2 = ("B"=>2); foreach my $hashref ('hash1', 'hash2') { no strict 'refs'; print "$hashref:",(join ",",sort keys %{$hashref}),"\n"; }

    Note that it won't work on variables declared with my(). From perlref:

    Only package variables (globals, even if localized) are visible to symbolic references. Lexical variables (declared with my()) aren't in a symbol table, and thus are invisible to this mechanism.