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

I'm trying to create a class that implements a tree. An object can have zero or more references to other objects of the same type. I'm trying to put the child objects in an @Array. Since this is an object I’ll have to put this in an anonymous hash, but I'm not getting the syntax right. How do I put an array in the anonymous hash? Maybe someone can help! Here is an example of how the code looks like.
package TreeNode; use strict; sub new { my $caller = shift; my $class = ref($caller) || $caller; #the instance data is stored in an anonymous hash my $self = { TreeNodes => '@' # Array of TreeNodes }; bless ($self, $class); return $self; } sub AddNode { my $self = shift; # Create a new instance of TreeNode my $newNode = TreeNode->new(); # Add new instance to Array of TreeNodes push( @{$self->{TreeNodes}}, $newNode ); # This goes wrong! } 1; # so the require or use succeeds

Replies are listed 'Best First'.
Re: array stored in anonymous hash
by revdiablo (Prior) on Mar 02, 2004 at 21:31 UTC

    As matija rightly points out, you'd want to initialize your TreeNodes hash value to an actual arrayref (which would be easy to create with the anonymous arrayref constructor []).

    Update: here's an example if you want to go the explicit route:

    my %hash = ( TreeNodes => [] ); push @{ $hash{TreeNodes} }, 1, 2; use Data::Dumper; print Dumper \%hash;

    You do not even have to initialize the key, however. You can simply push into a previously non-existent key, and it will automatically be created and populated with an array reference. This is known as autovivification, and is made for situations like this.

    Quick example:

    my %hash; push @{ $hash{TreeNodes} }, 1, 2; use Data::Dumper; print Dumper \%hash;

    Update: please see perlreftut and perlref for more information about references. (Re-reading your original question leads me to believe you might still be struggling with this topic. Hopefully I haven't assumed too much, but it's a common problem, so the docs might help.)

Re: array stored in anonymous hash
by matija (Priest) on Mar 02, 2004 at 21:21 UTC
    The part of the push looks OK to me. I think your problem is in the part where you initialize the TreeNodes hash. Perhaps if you initialized it to [] instead of to '@'?
Re: array stored in anonymous hash
by Stevie-O (Friar) on Mar 03, 2004 at 00:32 UTC
    Something you said stood out at me: "Since this is an object, I'll have to put it into an anonymous hash". Unless you:
    1. need to store some metadata other than the child nodes, or
    2. want to overload @{},
    it's perfectly acceptable to make your object out of an array. In fact, I've made an object out of a scalar (which itself was a reference to an array) to overload @{} ;)
    package TreeNode; use strict; # new TreeNode() # new TreeNode( list of nodes ) sub new { my $caller = shift; my $class = ref($caller) || $caller; my $self = []; bless ($self, $class); $self->AddNode(@_) if @_; return $self; } # $obj->AddNode() # Creates a new TreeNode object, adds it to the tree, a +nd returns said object. # $obj->AddNode(another node[, still another node, ...]) # Adds one or more existing TreeNode objects to the tre +e. sub AddNode { my $self = shift; @_ = $self->new unless @_; push @$self, @_; $_[0]; # return the first object added (so that AddNode() w +ith no args returns the new node) } 1; # so the require or use succeeds
    --Stevie-O
    $"=$,,$_=q>|\p4<6 8p<M/_|<('=> .q>.<4-KI<l|2$<6%s!<qn#F<>;$, .=pack'N*',"@{[unpack'C*',$_] }"for split/</;$_=$,,y[A-Z a-z] {}cd;print lc