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

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

I am trying to figure out if it is possible for a hash value to reference a key value in the same hash. As a much simplified example, suppose I have the following:

use strict; my %hash = ( name => "foo", code => sub{ print "name: ", "foo", "\n"; }, ); $hash{code}->(); _____ name: foo

"foo" is the value of the name key and is also in the code subroutine. Is it possible to have a hash refer to itself with something like

use strict; my %hash = ( name => "foo", code => sub{ print "name: ", $hash{name}, "\n"; }, ); $hash{code}->();

Obviously this syntax does not work, but is there a way to do this?

Replies are listed 'Best First'.
Re: hash reference to itself
by dave_the_m (Monsignor) on Aug 02, 2016 at 17:41 UTC
    Note that a self-referential hash will leak. This code consumes several Gb after running for a few seconds:
    while (1) { my %h; $h{a} = \%h; }

    You may need to use weaken() from Scalar::Util

    Dave.

      Good to know. Thanks!

Re: hash reference to itself
by Anonymous Monk on Aug 02, 2016 at 17:09 UTC

    Declare the hash before assignment.

    my %hash; %hash = ...

      When my forehead hit the desk, I woke up several people sleeping around me. I don't expect this kind of mental flatulence until Fridays. Thanks! Just what I needed.

        Note that this approach will leak memory unless you do the following when you're done with the hash:
        %hash = ();
Re: hash reference to itself
by VinsWorldcom (Prior) on Aug 02, 2016 at 17:11 UTC

    Perl can do object-oriented code.

    #!perl use strict; use warnings; package MyPkg; sub name { return 'foo'; } sub print { print "name: " . name(); } package main; print MyPkg->name() . "\n"; MyPkg->print();

    UPDATE: Actually *not* OO as YourMother points out below.

      There is no object here, just class calls which might as well be package calls.

      print MyPkg::name(), $/; MyPkg::print();

        You're right. Is this better?

        #!perl use strict; use warnings; package MyPkg; sub new { my ($self, $name) = @_; my %hash = ( name => $name ); return bless \%hash; } sub print { my $self = shift; print "name: " . $self->{name}; } package main; my $obj = MyPkg->new('foo'); $obj->print();

      I think if I had the time to do it, OO may have been a better way to do it. But for now, I will have to stick with the huge hashes I have. Thanks.

Re: hash reference to itself
by talexb (Chancellor) on Aug 02, 2016 at 17:05 UTC

    What problem are you trying to solve here?

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

      I have a rather large hash that has a somewhat similar structure. There are many keys containing subs that use another key to print messages. I wanted to bring those keys up a level ( the name key was inside the code sub) and another piece of code wanted to see the name value. Hence I wanted to bring the name up where it was visible to others. Anonymous Monk hit the nail on the head.