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

hi monks,

i'm trying to use a hash which has been stored within another hash.
can anyone tell me what im doing wrong in the following piece of code?
#!/usr/bin/perl use strict; use warnings; my %blah1 = (); $blah1{condition} = ""; $blah1{terms} = [ "foobar" ]; my %blah2 = (); $blah2{condition} = "AND"; $blah2{terms} = [ "foo", "OR bar" ]; my %tests = (); $tests{1} = %blah1; $tests{2} = %blah2; print "Results from a straight hash:\n"; &makef(%blah2); print "Results from a hash within a hash:\n"; &makef(%{$tests{2}}); sub makef { my (%farticle) = @_; foreach my $blah (@{$farticle{terms}}) { print "$blah\n"; } } exit;

Replies are listed 'Best First'.
Re: hash with a hash
by almut (Canon) on Jun 04, 2007 at 09:02 UTC

    You probably want

    $tests{2} = \%blah2;

    (i.e., you need to assign a hashref when you're in scalar context...  Otherwise, you get the number of used/allocated buckets of the hash — which is why you see the error 'Can't use string ("2/8") as a HASH ref while "strict refs" in use...')

      Yeah,
      $tests{2} = \%blah2;
      is the same as
      $tests{2} = { condition => "AND", terms => [ "foo", "bar" ], };
      One thing that you should note is that when explicitly defining hashes and arrays, one can use "()"'s.
      my @array = ( 1, 2, 3 ); my %hash = ( A => 1, B => 2, C => 3, );
      However, anonymous arrays are defined with "[]"'s
      my $array_ref = [ 1, 2, 3 ]; my @array = @{$array_ref}; # becomes an explicit array
      and anonymous hashes are defined with "{}"'s.
      my $hash_ref = { A => 1, B => 2, C => 3, }; my %hash = %{$hash_ref}; # becomes an explicit hash
Re: hash with a hash
by andreas1234567 (Vicar) on Jun 04, 2007 at 09:32 UTC
    Use Data::Dumper to inspect your datastructure. It probably is not what you think:
    $ perl use strict; use warnings; my %blah1 = (); $blah1{condition} = ""; $blah1{terms} = [ "foobar" ]; my %blah2 = (); $blah2{condition} = "AND"; $blah2{terms} = [ "foo", "OR bar" ]; my %tests = (); $tests{1} = %blah1; $tests{2} = %blah2; use Data::Dumper; print Dumper(\%tests); __END__ $VAR1 = { '1' => '2/8', '2' => '2/8' };
    ++ for using strict and warnings. Read Perl Data Structures Cookbook for more on hashes of hashes.
    --
    print map{chr}unpack(q{A3}x24,q{074117115116032097110111116104101114032080101114108032104097099107101114})
Re: hash with a hash
by nferraz (Monk) on Jun 04, 2007 at 10:02 UTC
    You can't store a hash inside of a hash, or an array inside of an array. But you can store references. Please read the perl data structures cookbook.
Re: hash with a hash
by 13warrior (Acolyte) on Jun 04, 2007 at 10:53 UTC
    If you want to use a hash with another hash then you got to use references.

    $tests{2} = %blah2; You should use ref like $test{2} = \%blah2;

    Please go through references do use complex data structures.
Re: hash with a hash
by Anonymous Monk on Jun 04, 2007 at 18:43 UTC
    Hashes can only store scalar variables. If you want to have a hash of hashes or hash of lists of hashes, etc. you need to use references. You can do something like this: my %foo = ( one => 'apple', two => 'orange' ); my %bar = ( foo => \%foo ); when you do \%foo you take a reference to %foo hash, and the reference is a scalar, which can be stored in a hash. in your case lines: $tests{1} = %blah1; $tests{2} = %blah2; do not do what you want, you need to re-write them like so: $tests{1} = \%blah1; $tests{2} = \%blah2; Here's a little test prog, try it: #!/usr/bin/perl -w use strict; use Data::Dumper; my %foo = ( one => 'apple', two => 'orange' ); my %bar = ( foo => \%foo ); # wrong $bar{1} = %foo; print Dumper(\%bar);
Re: hash with a hash
by TGI (Parson) on Jun 04, 2007 at 23:18 UTC

    I've said it before, and I'll say it again, don't use the ampersand (&) sigil on your subroutine calls. It can have some nasty unintended consequences.

    See perlsub for more details.


    TGI says moo