views:

121

answers:

5

I have an array of references to anonymous hashes. From the reference to that array, $allDirArray, I want to access the value corresponding to the key 'dir'. Currently I am getting the error:

Can't use string ("HASH(0x100878050)") as a HASH ref while "strict refs" 
in use at nameOfProgram.pl line 148.

My code:

my $tempDir = ${$allDirArray}[$i]{'dir'};
+3  A: 
 $allDirArray->[$i]->{dir}

See perldoc perlreftut.

Now, I think Dan has the right diagnosis of your problem. So, the FAQ What's wrong with always quoting "$vars"? might be helpful.

Sinan Ünür
If you don't like arrows so much, note that `$allDirArray->[$i]{dir}` works, too.
Telemachus
@Telemachus I want my arrows!
Sinan Ünür
@Sinan: Actually, I've noted your preference for them. I omit them myself, but I don't really feel very strongly about it. The "you" in my comment was really the general "whoever stops by someday and reads this" kind of you. But you (the specific and the general you) knew that. :)
Telemachus
I remove all superfluous arrows, but it's a stylistic preference like using quotes when accessing all-alpha hash keys.
Ether
@Ether: wait - you omit the arrows, but keep the quotes? See, now, that's just wrong.
Telemachus
@Telemachus I don't think @Ether said he/she keeps (or does not keep) the quotation marks.
Sinan Ünür
A: 
$$allDirArray[$i]->{'dir'}
SquareCog
ew, there's no need for `$$`.
Ether
You get more money if you write $$ in your program rather than $.
Kinopiko
`$$allDirArray` is the same as `${$allDirArray}`, the `{}` are optional (but often recommended, if only for readability). I'd prefer `$allDirArray->[$i]{dir}`, personally.
Dan
I personally find `${$foo}` less readable than `$$foo` :-). Agreed that `$foo->[$i]` is about the cleanest you are going to get though. Thanks for the tip, SO!
SquareCog
Explicitly dereferencing like that removes ambiguity. Otherwise constructs like `$$foo[1]` become more likely to mislead you in 6 months when you're not sure if you meant `${$foo}[1]`, or '${$foo[1]}'.Uglier, I'll grant you ;)
Dan
+2  A: 

I couldn't really see what the problem was with the code you quoted, so I wrote a short test script and passed it through Perl.

#! perl
use warnings;
use strict;

my $allDirArray = [{dir => "b"},{c => "d"}];
my $i = 0;
my $tempDir = ${$allDirArray}[$i]{'dir'};
print "$tempDir\n";

As written above, using Perl 5.10 on Cygwin, the program ran as followed:

$ perl allarraydir.pl
b

No error message was printed. See http://codepad.org/pH4eyMlt

Edit

After including telemachus's suggestion, I added the following code to the end of the above program,

# The following addition was included re telemachus's comment
my @allDirArray2 = ({dir => "b"},{c => "d"});
$tempDir = ${$allDirArray2}[$i]{'dir'};
print "$tempDir\n";

ran it again and got the following error message:

$ perl allarraydir.pl
Global symbol "$allDirArray2" requires explicit package name at 
allarraydir.pl line 10.
Execution of allarraydir.pl aborted due to compilation errors.

(this should really be a comment on your question rather than an answer, but the code is too long.)

Kinopiko
@telemachus: if so that error message makes even less sense.
Kinopiko
@Kinopiko: yeah, I reread the post and realized I was confused.
Telemachus
Originally, the OP stated *From the reference of that array (`$allDirArray`)* meaning he is working with a reference to an array of hashrefs. Anyway, I think @Kinopiko's observation is on the money. +1
Sinan Ünür
@Sinan: Yup. When I first looked up, I paid attention only to the first sentence, "I have an array of references to anonymous hashes."
Telemachus
+5  A: 

The error message suggests you're actually trying to use the string "HASH(0x100878050)" as a hashref. So I suspect you've somehow managed to stringify your hashes (ie, you used them as strings, and Perl turned them into strings for you). One way this can happen is if you assign a hashref to a hash key (hash keys can only be strings), or by quoting variables in an assignment like this $array[0] = "$hashref".

So inside ${$allDirArray}[$i] is a string containing "HASH(0x100878050)", literally that, in a string. Not a hash.

Best bet to confirm this is probably to dump the data structure. You can do this with Data::Dumper:

use Data::Dumper;
print Dumper($allDirArray);
Dan
+1 for Data::Dumper. Soooooo useful.
Daren Schwenke
A: 

Somehow you managed to make your anonymous hash into a string.

Here is a short example that causes that error.

use strict;
use warnings;

my $allDirArray = [ ''.{ 'dir' => 'somedir' } ];

my $tempdir = ${$allDirArray}[0]{'dir'};
# or
my $tempdir = $allDirArray->[0]{'dir'};
Can't use string ("HASH(0x8555168)") as a HASH ref while "strict refs" in use at nameOfProgram.pl line 8.
Brad Gilbert