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

I thought I posted this earlier, but since the search
turned up nil...
I have a hash made up of array refs mapping to array refs.
Why can't I access the key array data?
my %sample = ( [ 1, 2, 3, 4 ] => [ 5, 6, 7, 8 ] ); my $key; foreach $key (keys %samples) { my @a = @$key; my @b = @{$sample{ $key }}; print "key=@a\nvalue=@b\n"; }

Perl is not allowing me to dereference $key.
However, the value referred to is freely accessible.
I just don't understand what I'm doing wrong.

Rob

Replies are listed 'Best First'.
(jeffa) Re: Hash of refs to refs
by jeffa (Bishop) on Dec 01, 2001 at 00:42 UTC
    Um, you can't do that! Take a look at what %sample really is:
    'ARRAY(0xa01116c)' => [ 5, 6, 7, 8 ]
    If you are trying to create a hash slice, try this instead:
    my %hash; @hash{(1..4)} = (5..8);

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    F--F--F--F--F--F--F--F--
    (the triplet paradiddle)
    
Re: Hash of refs to refs
by lestrrat (Deacon) on Dec 01, 2001 at 00:46 UTC

    Update: after reading jeffa's reply... if you wanted a hash slice, then my answer is a bit off...

    That probably won't do what you thought it would... Try printing the contents of the has using Data::Dumper, and I think you will see:

    use Data::Dumper; my %sample = ( [ 1, 2, 3, 4 ] => [ 5, 6, 7, 8 ] ); print Dumper( \%sample ); ==output== $VAR1 = { 'ARRAY(0x13c864)' => [ 5, 6, 7, 8 ] };

    As you can see, hash keys are stringified. it does NOT hold the actual ref to an array...

    The reason why your foreach loop works is because when you call keys(), you get the string values which are used as the hash keys... but you can't dereference them because they are just strings representing the arrayref's location in memory ( I think that's wht those hex numbers mean )

    Anyway, the point is that in your code, $key is a string, not an arrayref. If you want to get to the array ref you have to do a bit more work

      I get it! Keys are stringified. That's why. Ahhhh...
      So, maybe what I could do is build an array of arrays:
      my @samples = ( [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ] ], [ [ 1, 3, 5, 7 ], [ 2, 4, 6, 8 ] ] ); my $sample; foreach $sample (@samples) { my @set = @$sample; my @in = @{$set[0]}; my @out = @{$set[1]}; print "in: @in out: @out\n"; }
      Or, if I really wanted to use the hashtable:
      my %samples = ( 'a' => [ [1, 2, 3, 4], [5, 6, 7, 8] ], 'b' => [ [1, 3, 5, 7], [2, 4, 6, 8] ] ); my $key; foreach $key (keys %samples) { my @set = @{$samples{$key}}; my @in = @{$set[0]}; my @out = @{$set[1]}; print "in: @in out: @out\n"; }

      The second method allows me to label my samples.
      How nice!

      Thanks again.

      Rob

        You got it!

        Welcome to the wonderful world of anonymous data structures, if you don't already know about it, Data::Dumper is a wonderful module (that comes with the standard distro) for debugging your stuctures to make sure that really have the composition you desire. Example:

        use Data::Dumper; print Dumper \%samples;
        Dumper will take a scalar, an array, a hash, references, and more - i find it best to give it references to hashes and arrays instead. Experiment and find out why!

        Also of interest to you might be Using stringified refs for unique IDs?.

        Last tip:

        # these 2 lines my $sample; foreach $sample (@samples) { # are usually better written as foreach my $sample (@samples) {
        The difference is that the $sample in the second snippet is local to the foreach block and goes out of scope when the foreach is finished. Since you aren't using $sample anywhere else it appears, i recommend you use this approach. But, if you do need $sample later in the code, use the first snippet.

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        F--F--F--F--F--F--F--F--
        (the triplet paradiddle)