tags:

views:

55

answers:

4

This Script:

use strict;  

my %new;
my $test_ref = [24, 26, 55];
$new{$test_ref} = 10;

foreach my $key (keys %new){
    print $key->[0];
}

when i try to access this element, it gives an error like: "Can't use string ("ARRAY(0x...)") as an ARRAY ref" any ideas why?

+3  A: 

Because a hash key is always stringified, and a stringified value of an array REFERENCE (which $test_ref is) is exactly that: "ARRAY(0x...)". This is different from Java maps which can store arbitrary object as a key.

Therfore, your hash would have 1 ket-value pair, with the key being a string ""ARRAY(0x...)""

So, when you have your for loop, it loops over all the keys (all 1 of them), and then assigns the key value (a string "ARRAY(0x...)") to $key variable.

You then try to array-dereference that string - which of course can't be done since it is not an array reference - it is merely a string containing the string representation of what array reference used to be.

If you want to have "24, 26, 55" as 3 hash keys, you can do this:

my %new = map { $_ => 10 } @$test_ref;

If you actually want to store a list in a hash key, it's doable but not always (in your case of a list of integers, you can, but it's slow, clumzy and I can't imagine when you'd ever wish to.

# Trivial example:
my $test_ref = [24, 26, 55];
$new{ join(",",@$test_ref) } = 10;
foreach my $key (keys %new){
    my @list = split(/,/,$key);
    print $list[0];
}

This approach has some performance penalties, and can be optimized a bit (e.g. by memoizing the split results). But again, for pretty much ANY reason you might want to do this, there probably are better solutions.

DVK
A: 

I'm guessing (and I may be wrong) that you want to assign 24, 26 and 55 as the keys of %new.

If you want to do this, the following is what you're after:

use strict;

my %new;
my $test_ref = [24, 26, 55];

@new{@$test_ref} = (10) x @$test_ref;

print "$new{$_}\n" foreach keys %new;
Zaid
A: 

If you want to access the array reference $test_ref, then you want to use the array syntax (square brackets)

$test_ref->[0];

If you want to access the hash %new, then use the hash syntax (braces)

$new{$key}

What you are doing is using an array reference $test_ref as a key into a hash %new - what perl does is convert that array reference into a string to use at the key. It is the string and not the reference that is returned by keys.

You can't use references as keys and then get the reference back again (trivially).

Beano
+2  A: 

Hash keys are normally stringified, so they lose the ability to act as a reference.

The core module Tie::RefHash provides this capability:

use strict;
use warnings;
use Tie::RefHash;

tie my %new, 'Tie::RefHash';
my $test_ref = [24, 26, 55];
$new{$test_ref} = 10;

foreach my $key (keys %new){
    print $key->[0];
}

Good job using strict. But warnings is even more important.

ysth