Re: A better understanding of array and hash references
by jeffa (Bishop) on Dec 01, 2005 at 17:18 UTC
|
Actually, the reason why your non-working examples "do not work" is simply because that @$hr{a} is ambigious: does it mean that $hr is an array reference or does it mean that the key 'a' from the hash reference $hr contains an array reference. If the case is the latter, you really should be using syntax like so:
@{$hr->{a}} = [qw(foo bar baz)];
@{$ar->[0]} = [0 .. 9];
Data::Dumper and References quick reference are your friends. :)
Update: thanks for the typo correction, ikegami.
| [reply] [d/l] |
Re: A better understanding of array and hash references
by Fletch (Bishop) on Dec 01, 2005 at 17:20 UTC
|
Yeah, works for me as well. Perhaps your confusion is with %$hr{a} which would be trying to dereference a hashref contained in the hash %hr in the value associated with the key "a".
use Data::Dumper qw( Dumper );
$hash_a->{a} = "hello" ;
@$hash_b{a} = "hello" ;
$arr_a->[0] = "hello" ;
@$arr_b[0] = "hello" ;
print "hash_a ", Dumper( $hash_a ), "\n";
print "hash_b ", Dumper( $hash_b ), "\n";
print "arr_a ", Dumper( $arr_a ), "\n";
print "arr_b ", Dumper( $arr_b ), "\n";
__END__
hash_a $VAR1 = {
'a' => 'hello'
};
hash_b $VAR1 = {
'a' => 'hello'
};
arr_a $VAR1 = [
'hello'
];
arr_b $VAR1 = [
'hello'
];
| [reply] [d/l] [select] |
Re: A better understanding of array and hash references
by ikegami (Patriarch) on Dec 01, 2005 at 17:16 UTC
|
Contrary to what you say, both
@$hr{a} = "hello"; # Hash slice. Equiv to @h[0].
and
@$ar[0] = "hello"; # Array slice. Equiv to @a[0].
work for me, as they should.
ActivePerl v5.6.1 Win2k
ActivePerl v5.8.0 WinXP
perl v5.8.0 FreeBSD
It's true that %$hr{a} doesn't work, but why should it? It would be equivalent to %h{a} which is not valid Perl.
Of course, I don't know what you're using slices with just one element. The following work just as great:
$$hr{a} = "hello"; # Same as $hr->{a}. Equiv to $h{a}.
and
$$ar[0] = "hello"; # Same as $ar->[0]. Equiv to $a[0].
Update: Added to the node.
| [reply] [d/l] [select] |
Re: A better understanding of array and hash references
by wfsp (Abbot) on Dec 01, 2005 at 17:53 UTC
|
I also highly recommend using Data::Dumper as mentioned above.
What I find helpful is to use the longhand:
push @{$hr->{a}}, 'hello';
print "${$hr->{a}}[0]\n";
I find that this give my eye a better chance to see that some derefencing is going on (I'm old!).
Hang on in there! :-)
| [reply] [d/l] |
Re: A better understanding of array and hash references
by jeanluca (Deacon) on Dec 01, 2005 at 18:23 UTC
|
Wow, and I thought I saw the light some time ago, but I realize now my dear monks, that it should have been something else.
I get the feeling its time for me to study slices, I always thought they were not so important, but to get the whole picture I guess it is important!
Thanks a lot Luca | [reply] |
Re: A better understanding of array and hash references
by Errto (Vicar) on Dec 04, 2005 at 03:53 UTC
|
One thing that hasn't been mentioned yet in this thread is that in your example, you are only looking at one value at a time: either the hash key 'a' or the array index 0. If this is true in your real code as well, then you don't need to be using slices. In fact I would say you should not use slices for a couple of reasons:
- Someone who has to maintain the code later will be confused as to why you're using them when unneeded
- There's a slight performance penalty (I think)
- When you assign to a slice instead of a single element, the right side is in list context, which can matter
To see what I mean by that last one, try this code:
my $hashref = {}; # initializer not needed, but helps clarity
$hashref->{a} = localtime; # can also be written $$hashref{a}
print "$hashref->{a}\n";
@$hashref{a} = localtime; # this is a slice because of the @
print "$hashref->{a}\n";
The second assignment evaluates localtime in list context, but because the slice on the left side only has one element, only the first value in the returned list gets stored there, which happens to be the number of seconds.
My preference is to be as explicit as possible so I write $hashref->{a} for single elements and @{$hashref}{'a','b'} for slices. | [reply] [d/l] [select] |
Re: A better understanding of array and hash references
by jeanluca (Deacon) on Dec 01, 2005 at 17:25 UTC
|
sorry typo,
@$hr{a} = ....
should be %$hr{a} = ....
| [reply] [d/l] [select] |
|
|
No, you have it backwards. The hash equivalent of
@$ar[0] (or @$ar[0, 1, 2])
is
@$hr{a} (or @$hr{'a', 'b', 'c'})
%$hr{a} is nonsense. Read about slices in perldata
By the way, you shouldn't use slices for single elements.
@$ar[0] and @$hr{a}
should be
$$ar[0] and $$hr{a}
Remember: When using an index on a hash or an array, the sigil is of the type returned/assigned. Slices return/accept a list, so @ is used. When refering to a single element, $ is used. % is never used when an index is specified.
Update: Here's a table which should help:
|
| Direct
| Using References
|
| Syntax 1*
| Syntax 2
|
| array
| element
| $a[0]
| ${$ar}[0]
| $ar->[0]
|
| slice
| @a[0,1,2]
| @{$ar}[0,1,2]
|
|
| unindexed
| @a
| @{$ar}
|
|
| hash
| element
| $h{'a'}
| ${$hr}{'a'}
| $hr->{'a'}
|
| slice
| @h{'a','b','c'}
| @{$hr}{'a','b','c'}
|
|
| unindexed
| %h
| %{$hr}
|
|
* – The curly brackets around $ar and $hr are optional.
| [reply] [d/l] [select] |
|
|
Very nice table/overview!!!
| [reply] |