Recipe 5.2 Testing for the Presence of a Key in a Hash

5.2.1 Problem

You need to know whether a hash has a particular key, regardless of whatever value may be associated with that key.

5.2.2 Solution

Use the exists function.

```# does %HASH have a value for \$KEY ?
if (exists(\$HASH{\$KEY})) {
# it exists
} else {
# it doesn't
}```

5.2.3 Discussion

This code uses exists to check whether a key is in the %food_color hash:

```# %food_color per the introduction
foreach \$name ("Banana", "Martini") {
if (exists \$food_color{\$name}) {
print "\$name is a food.\n";
} else {
print "\$name is a drink.\n";
}
}

Banana is a food.
Martini is a drink.```

The exists function tests whether a key is in the hash. It doesn't test whether the value corresponding to that key is defined, nor whether the value is true or false. We may be splitting hairs, but problems caused by confusing existence, definedness, and truth can multiply like rabbits. Take this code:

```%age = ( );
\$age{"Toddler"}  = 3;
\$age{"Unborn"}   = 0;
\$age{"Phantasm"} = undef;

foreach \$thing ("Toddler", "Unborn", "Phantasm", "Relic") {
print "\$thing: ";
print "Exists "  if exists  \$age{\$thing};
print "Defined " if defined \$age{\$thing};
print "True "    if         \$age{\$thing};
print "\n";
}

Toddler: Exists Defined True
Unborn: Exists Defined
Phantasm: Exists
Relic: ```

\$age{"Toddler"} passes the existence, definedness, and truth tests. It exists because we gave "Toddler" a value in the hash; it's defined because that value isn't undef; and it's true because the value isn't one of Perl's false values.

\$age{"Unborn"} passes only the existence and definedness tests. It exists because we gave "Unborn" a value in the hash, and it's defined because that value isn't undef. It isn't true, however, because 0 is one of Perl's false values.

\$age{"Phantasm"} passes only the existence test. It exists because we gave "Phantasm" a value in the hash. But because that value was undef, it doesn't pass the definedness test. Because undef is also one of Perl's false values, it doesn't pass the truth test either.

\$age{"Relic"} passes none of the tests. We didn't put a value for "Relic" into the hash, so the existence test fails. Because we didn't put a value in, \$age{"Relic"} is undef whenever we try to access it. We know from "Phantasm" that undef fails the definedness and truth tests.

Sometimes it's useful to store undef in a hash. This indicates "I've seen this key, but it didn't have a meaningful value associated with it." Take, for instance, a program to look up file sizes given a list of files as input. This version tries to skip files we've seen before, but it doesn't skip zero-length files, and it doesn't skip files that we've seen before but don't exist.

```%size = ( );
while (<>) {
chomp;
next if \$size{\$_};              # WRONG attempt to skip
\$size{\$_} = -s \$_;
}```

If we change the incorrect line to call exists, we also skip files that couldn't be statted, instead of repeatedly trying (and failing) to look them up:

`next if exists \$size{\$_};`

The exists and defined functions in perlfunc(1) and Chapter 29 of Programming Perl; the discussion of truth in the "Scalar Values" section of perldata(1), and the "Boolean Context" section of Chapter 2 of Programming Perl

 Chapter 1. Strings
 Chapter 2. Numbers
 Chapter 3. Dates and Times
 Chapter 4. Arrays
 Chapter 6. Pattern Matching
 Chapter 7. File Access
 Chapter 8. File Contents
 Chapter 9. Directories
 Chapter 10. Subroutines
 Chapter 11. References and Records
 Chapter 12. Packages, Libraries, and Modules
 Chapter 13. Classes, Objects, and Ties
 Chapter 14. Database Access
 Chapter 15. Interactivity
 Chapter 16. Process Management and Communication
 Chapter 17. Sockets
 Chapter 18. Internet Services
 Chapter 19. CGI Programming
 Chapter 20. Web Automation
 Chapter 21. mod_perl
 Chapter 22. XML