Hashes
🗂️ Hashes
🏷️ The % Sigil
=> (the "fat comma") is functionally identical to a plain comma — it's used here purely for readability, visually pairing each key with its value. As a bonus, a bareword immediately to its left is automatically quoted, so Ada => 28 works exactly like "Ada" => 28.
Accessing a single value uses curly braces and, once again, the $ sigil — not %:
This is the exact same rule from Chapter 3's $fruits[0], just with curly braces instead of square brackets: %ages is the whole hash, $ages{"Ada"} is one scalar value pulled out of it.
🛠️ Common Hash Operations
if ($ages{"Bob"}) and if (exists $ages{"Bob"}) are genuinely different questions. If $ages{"Bob"} is 0 (a valid age for a newborn, technically) or undef, the first check is false even though the key is really there — exists answers "is this key present at all," independent of whatever value it happens to hold.
🔁 Iterating Hashes
foreach ... keys %hash is the standard, idiomatic way to iterate — loop over the keys, look up each value as needed. Perl also has an each function (while (my ($name, $age) = each %ages) { ... }) that returns key/value pairs one at a time, but it has real gotchas if the hash is modified mid-loop — keys-based iteration is the safer, more common idiom in real code.
Unlike Python 3.7+ dictionaries (which guarantee insertion order), Perl hashes have no guaranteed order at all — keys %ages can return the keys in a different order between runs, or even between two calls in the same run in older Perl versions. If a specific, predictable order matters, sort explicitly: foreach my $name (sort keys %ages).
🔧 A Worked Example — Word Frequency Count
$counts{$word}++ works even the very first time a given word is seen — an unset hash value auto-vivifies to undef, which ++ treats as 0 before incrementing, so no separate "does this key exist yet?" check is needed first.
Hashes: Perl vs. Python
Perl hashes and Python dicts serve the identical role — a Python developer will recognize the concept instantly. The differences are the same two threads running through this whole course: the sigil switches from % to $ the moment you access one value ($hash{key}, vs. Python's uniform my_dict[key]), and — genuinely worth remembering — Perl hashes have never guaranteed any particular order, where Python's dicts have guaranteed insertion order since 3.7.
% vs $
%hash is the whole hash; $hash{key} is one scalar value.
exists vs truthiness
exists $hash{key} checks presence, independent of the value itself.
keys / values
Return arrays — unordered by default, sort explicitly when order matters.
Auto-vivification
$hash{key}++ works even on a key that's never been set yet.
💻 Coding Challenges
Challenge 1: Build and Query a Hash
Declare a hash mapping 3 countries to their capital cities. Print one capital by looking it up directly, then print "Found" or "Not found" for a country that isn't in the hash, using exists.
Challenge 2: Sorted Iteration
Given a hash of 4 people mapped to their ages, print each "Name: Age" pair sorted alphabetically by name, using sort keys.
Challenge 3: exists vs Truthiness
Given my %inventory = ("apples" => 5, "bananas" => 0);, show that if ($inventory{"bananas"}) and if (exists $inventory{"bananas"}) behave differently, and explain why in one sentence.
🎯 What's Next
Next chapter: Control Flow & Operators — if/unless, while/until, for/foreach, and Perl's postfix conditionals.