Hash key types and equality of hash keys


T

Tim McDaniel

I tried "man perldata", but I didn't notice anything applicable.

I've always used only strings as hash keys -- I've just assumed
without any evidence that they're the only things that work.
But it occurred to me to wonder what else could be used as keys.
(Any scalar value can be used as hash *data*, I think.)
I was expecting errors from

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#! /usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
my %hash = ();
my $i = 23;
$hash{\$i} = 'narf';
$hash{sub { print 'blort' }} = 'hurple';
my $f = sub { print 'bazinga' };
$hash{$f} = 'poit';
$hash{qr/acc/} = 'zing';
$hash{undef} = 'WTF?';
print $hash{\$i}, "\n";
print $hash{sub { print 'blort' }}, "\n";
print $hash{$f}, "\n";
print $hash{qr/acc/}, "\n";
print $hash{undef}, "\n";
print Data::Dumper->Dump([\%hash], [qw[hash]]), "\n";
exit 0;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

but I was astonished that most of it worked:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

$ perl ~/local/test/027.pl ; perl -v
narf
Use of uninitialized value in print at
/home/tmcdaniel/local/test/027.pl line 14.

poit
zing
WTF?
$hash = {
'SCALAR(0x116ede20)' => 'narf',
'undef' => 'WTF?',
'CODE(0x116f4200)' => 'poit',
'CODE(0x116ede80)' => 'hurple',
'(?-xism:acc)' => 'zing'
};

This is perl, v5.8.8 built for x86_64-linux-thread-multi
....

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

So I'm thinking that, in Perl, hash keys can also be any scalar.
Is that documented anywhere?

That then leads to the question: what counts as "equal" in the context
of looking up a hash value?

- sub { print 'blort' } is considered a different key from a later
lexical use of sub { print 'blort' }.

- But qr/acc/ matches a later lexical use of qr/acc/.

- The same reference to the same item is equal to itself, which is not
surprising. That is, evaluate the reference in one place, store it
in a variable, and use that variable's value. (E.g., $f = sub {...}
and use $f.)

- A reference to the same scalar (\$i) is consistent, even though I
didn't assign \$i to a variable. This too is unsurprising. This
probably works with a reference to any variable.

- "undef" is identical, and without a warning.

I'm sure I'm overlooking some other scalar value types. And I cannot
try every value even of the types I know about -- qr/acc/ is simple
enough that Perl knows it's identical to another instance, but for all
I know, if there's a certain more complicated expression or some
certain modifier, Perl doesn't understand equality (much like sub{}).

So is there documentation for what keys are considered equal?

I don't think there's an operator to check for that equality
(other than "sub hashequal { my ($a, $b) = @_; my %t = ($a, 1); return exists $t{$b}; }")
 
Ad

Advertisements

R

Rainer Weikusat

I tried "man perldata", but I didn't notice anything applicable.

I've always used only strings as hash keys -- I've just assumed
without any evidence that they're the only things that work.
But it occurred to me to wonder what else could be used as keys.
[...]

$hash = {
'SCALAR(0x116ede20)' => 'narf',
'undef' => 'WTF?',
'CODE(0x116f4200)' => 'poit',
'CODE(0x116ede80)' => 'hurple',
'(?-xism:acc)' => 'zing'
};
[...]

So I'm thinking that, in Perl, hash keys can also be any scalar.
Is that documented anywhere?

It is documented:

Hashes are unordered collections of scalar values indexed by
their associated string key.
[perldata(1)]

This means that if you use something which is not a string as hash
key, that something is stringified and the resulting string becomes
the actual key.
 
Ad

Advertisements

T

Tim McDaniel

[email protected] (Tim McDaniel) said:
I tried "man perldata", but I didn't notice anything applicable.

I've always used only strings as hash keys -- I've just assumed
without any evidence that they're the only things that work.
But it occurred to me to wonder what else could be used as keys.
[...]

$hash = {
'SCALAR(0x116ede20)' => 'narf',
'undef' => 'WTF?',
'CODE(0x116f4200)' => 'poit',
'CODE(0x116ede80)' => 'hurple',
'(?-xism:acc)' => 'zing'
};
[...]

So I'm thinking that, in Perl, hash keys can also be any scalar.
Is that documented anywhere?

It is documented:

Hashes are unordered collections of scalar values indexed by
their associated string key.
[perldata(1)]

This means that if you use something which is not a string as hash
key, that something is stringified and the resulting string becomes
the actual key.

*light dawns over Marblehead* Why, lookie at all those *QUOTATION MARKS*
in the key positions in the Data::Dumper->Dump output, as opposed to
what it outputs when given a real reference!

Thank you. I blush.

I just realized that
$hash{undef} = 'WTF?';
was wrong: "undef" is interpreted as a string, of course.
$hash{undef()} = 'WTF?';
gives a warning "Use of uninitialized value in hash element" and
the key is a null string.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top