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

Hi all,
Im trying to figure out if i can tie an anonymous hash. Here is the simpest example i could come up with:
my %hash = tie( ('a' => 1), 'IxHash' );
This results in the error:

Can't modify constant item in tie at tie_test.pl line XX, near "'IxHash')"

So im guessing that tie() must have a non-anonymous hash (or other data struct, depending on the tie). That makes sense, but i'd really like to do something like the following:

my %big_hash = ( 'part_1' => tie( %{...}, 'MyTie'), 'part_2' => tie( %{...}, 'MyTie'), ... );

I know that i could do something like:

tie my %part_1, 'IxHash'; # set values for %part_1 tie my %part_2, 'IxHash'; # set values for %part_2 # ... my %big_hash = ( 'part_1' => \%part_1, 'part_2' => \%part_2, ... );
But that isnt what i want to happen. Im almost certain that this cannot be done like i want, but i thought i'd ask.

Thanks

Replies are listed 'Best First'.
Re: Tieing anonymous hashes
by davido (Cardinal) on Jun 28, 2005 at 20:41 UTC

    Essentially, what appears within the tie function must have a sigil. That means that tie expects an actual hash, not a hashref. The {...} anonymous hash constructor returns a hashref, which doesn't work. For example:

    tie( %hash, 'Class' );

    ...is valid, but ...

    tie( { anon => 'hash' }, 'Class' );

    ...is not valid. However, you can tie the nested portions of nested datastructures like this:

    my $href = {}; tie( %{$href}, 'Class' );

    ...or even...

    my( %hash ) = ( 'this' => {}, 'that' => {} ); tie( %{$hash{'this'}}, 'Class' );

    Also note, definately it is not doing what you expect if you do this:

    my( %hash ) = tie( %otherhash, 'Class' );

    ...because tie doesn't return the tied hash, it returns the tied object's instance reference. Since you're assigning the object's reference to %hash, you'll stringify the object ref and turn it into a hash key in %hash with undef as the value. So don't do that. In other words, this does work:

    my $obj = tie( %hash, 'Class' ); $obj->DESTROY;

    Dave

      In other words, this does work:

      my $obj = tie( %hash, 'Class' ); $obj->DESTROY;

      It works except that you'd never, ever write code to call ->DESTROY because that's only ever called by perl when it is actually destroying something. ->DESTROY doesn't provoke a cleanup - its only something that happens during cleanup.

        You are correct, sir.
        I was demonstrating that the return value of tie is an object reference that could be treated as such. My choice of DESTROY in the example was to use a method I knew should exist regardless of the class to which the variable is tied, that is common in any old ordinary class, and that people familiar with OO would visually recognize as a method call. But you're absolutely right about letting Perl call DESTROY().


        Dave

Re: Tieing anonymous hashes
by ikegami (Patriarch) on Jun 28, 2005 at 20:35 UTC

    ('a' => 1) is a list, not a hash.
    %{{'a' => 1}} is an anonymous hash.

    tie(%{{'a' => 1}}, 'class');
    seems to work, but it was a simple test.

Re: Tieing anonymous hashes
by Arunbear (Prior) on Jun 28, 2005 at 22:04 UTC
    Maybe you don't need to tie an anonymous hash:
    use strict; use warnings; use Tie::IxHash; use Data::Dumper; my %big_hash = ( 'part_1' => tie_me_up(first => 1, second => 2, third => 3), 'part_2' => tie_me_up(foo => 1, bar => 2, baz => 3), 'part_3' => tie_me_up(oranges => 1, apples => 2, lemons => 3), ); print Dumper(\%big_hash); sub tie_me_up { tie my %temp, 'Tie::IxHash'; %temp = @_; return \%temp; }
    Output:
    $VAR1 = { 'part_2' => { 'foo' => '1', 'bar' => '2', 'baz' => '3' }, 'part_3' => { 'oranges' => '1', 'apples' => '2', 'lemons' => '3' }, 'part_1' => { 'first' => '1', 'second' => '2', 'third' => '3' } };
Re: Tieing anonymous hashes
by shemp (Deacon) on Jun 28, 2005 at 20:48 UTC
    Thanks guys!
    Yeah, this is going to get too complicated to be worth it. I'm going to store what i need in XML, which is what i should be doing anyway.

    Interesting note, trying things from earlier responses, i tried running this:

    use strict; use warnings; use Tie::IxHash; use Data::Dumper; { my $blah = tie( %{{ 'a' => 1 }}, 'Tie::IxHash'); print Dumper($blah); }
    And the resulting output was:
    $VAR1 = bless( [ {}, [], [], 0 ], 'Tie::IxHash' );
    Which is not what i expected, but oh well, im not using this anyway.