This is well-documented in the perldoc entries for defined
and exists
. Here's a quick summary:
defined $hash{key}
tells you whether or not the value for the given key is defined (i.e. not undef
). Use it to distinguish between undefined values and values that are false in a boolean context such as 0
and ''
.
exists $hash{key}
tells you whether or not %hash
contains the given key. Use it to distinguish between undefined values and non-existent ones.
This is easiest to see with an example. Given this hash:
my %hash = (a => 1, b => 0, c => undef);
Here are the results for retrieval, defined-ness, and existence:
# key value defined exists
a 1 1 1
b 0 1 1
c undef 0 1
d undef 0 0
In practice, people often write just if ($hash{key}) {...}
because (in many common cases) only true values are meaningful/possible. If false values are valid you must add defined()
to the test. exists()
is used much less often. The most common case is probably when using a hash as a set. e.g.
my %set = map { $_ => undef } 'a' .. 'z';
Using undef
for set values has a few advantages:
- It more accurately represents the intent (only the keys are meaningful, not the values).
- All
undef
values share a single allocation (which saves memory).
exists()
tests are slightly faster (because Perl doesn't have to retrieve the value, only determine that there is one).
It also has the disadvantage that you have to use exists()
to check for set membership, which requires more typing and will do the wrong thing if you forget it.
Another place where exists
is useful is to probe locked hashes before attempting to retrieve a value (which would trigger an exception).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…