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

This isn't an appeal for help exactly, more an appeal for understanding.

I was struggling today with some code where the best structure, I thought, was a hash of arrays.

I read the fine manual, or rather the Perl CD Bookshelf. I know how to do it now, see below, but I found myself asking why, even when I knew how to do it.

Here's an example:

$, = ','; # I like to print out array items this way @my_array = ('Angel','Buffy','Cordelia'); # Now I have an array with three items. I want # to make it be a value in a hash. $my_hash{'my_key'} = [@my_array]; # Turns out to be the correct way to put an array into # a hash value. # But why? Why not # ($my_hash{'my_key'}) = @my_array; # for instance? That was my first thought, array context # on the left hand side comes from brackets -- or # $my_hash{'my_key'} = \@my_array; # is something else that occurred to me that didn't work. # Now I want to push something onto the end of the # array in the value: push (@{$my_hash{'my_key'}},'Darla'); # is the right way to do it, but first I tried just # a regular push, like: # push ($my_hash{'my_key'},'Darla'); # after all, Perl "knows" that value is an array, # but this doesn't work! It tells me "Type of # arg 1 to push must be array (not hash elem)"! # Now I want to get my array back out again, I have to # do this: print @{$my_hash{'my_key'}}; # in order to make it come out as an array and # not as "ARRAY(0x35fd724)". But why?

As you can tell, I'm very much self-taught, but what's obvious to me is that I've missed something about the syntax that led me up a few wrong paths. I had instincts which turned out to be wrong, and the correct syntax took me by surprise. I would never have guessed it.

Can anyone explain why, for instance square brackets on the right hand side mean "array context" in this case, not round brackets on the left hand side? And why an array comes out as "ARRAY(0x35fd724)" -- "I know it's an array, but I'm not giving it to you!" until I learnt the, to me quite baffling, syntax of "at-symbol, curly brackets, hash reference, close curly brackets"?

Thanks in advance.
--

($_='jjjuuusssttt annootthhrer pppeeerrrlll haaaccckkeer')=~y/a-z//s;print;

Replies are listed 'Best First'.
Re: My Struggles with Hash-of-Arrays Syntax
by shotgunefx (Parson) on Apr 19, 2002 at 09:25 UTC
    $my_hash{'my_key'} = [@my_array]; # Turns out to be the correct way to put an array into # a hash value.

    The brackets are creating an anonymous array, or rather it's creating an anonymous array with the values from @my_array and returning a reference to it.
    The reason \@my_array doesn't really work the way you want is that you would be repeatedly taking a ref to the SAME array over and over which is generally not what you want.

    All arrays and hashes can only hold scalar values so the only way to build more complex structures is with references. When you say a hash of arrays, we're really talking about a hash of array references. That's the reason you get "ARRAY(0x35fd724)" when you try and print out a ref to an array. It's not an array. It's a reference.

    Now why isn't perl smart enough to let you say the following?
    push ($HoA{key},@values)
    It has to do with parsing. What exactly is in $HoA{key} isn't known at compile time. It won't be determined til runtime and even then it could change at any given moment. Another parsing reason is context.

    For example:
    push (@vals, $HoA{key}, @list);

    What context do you want $HoA{key} to be used in? Perl couldn't possible figure that out. The syntax can be daunting at first, (especially on Hashes of Arrays of Hashes...) Hope this helps.

    -Lee

    "To be civilized is to deny one's nature."
Re: My Struggles with Hash-of-Arrays Syntax
by Hofmator (Curate) on Apr 19, 2002 at 09:11 UTC

    Try reading the perlreftut and perldsc. perllol and perlref could be interesting as well. If you have any further questions after that, feel free to ask here.

    -- Hofmator

      Also have a look at the excellent References quick reference for a handy shortcut, and a faster way to understand how it all sticks together. :)
      You have moved into a dark place.
      It is pitch black. You are likely to be eaten by a grue.
Re: My Struggles with Hash-of-Arrays Syntax
by Ryszard (Priest) on Apr 19, 2002 at 09:42 UTC
    I understand. I once also had trouble derefrencing complex data structures until someone smarter and wiser than I whispered "use Data::Dumper; good friend " in my ear.

    My life was then free of the toils of frustration.

    Come closer, put your ear to the monitor, use Data::Dumper I whisper.

Re: My Struggles with Hash-of-Arrays Syntax
by Cody Pendant (Prior) on Apr 20, 2002 at 00:08 UTC
    I'd just like to say thanks to everyone for their help.

    I did indeed read the references tute and the perldsc which were highly illuminating. Thank you. This is of course one of those things that you can't "read the manual" about, if you don't know which part of the manual to read.

    In other words, I now know what a reference is, and that a hash can't have an array in it after all, but the fact that it can have a reference to an array fixes all that. Plus some Perl 4/5 history which I didn't know. (that my hack solution, putting a comma-separated string in as the value, then split()ing it to get it back, was the only way to do it in the past).

    Anyway, thanks again.
    --

    ($_='jjjuuusssttt annootthhrer pppeeerrrlll haaaccckkeer')=~y/a-z//s;print;