What’s the difference between exists and defined?

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:

  1. It more accurately represents the intent (only the keys are meaningful, not the values).
  2. All undef values share a single allocation (which saves memory).
  3. 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).

Leave a Comment