Part of I. A Diurnal Cipher of Raku.
We have looked upon the singular Scalar, the fluid
List, and the collapsing Slip. Today, our
descent brings us to the architecture of memory that binds names to
destinies: the Associative Realm, governed by the % sigil.
In lesser languages, a dictionary or map is a fragile construct. In
Raku, the % container is a permanent anchor for pairs, establishing a
cosmic link between a unique string identifier (the key) and the value
trapped within its slot.
The Rite of Construction: The Fat Arrow
To populate the associative vessel, we utilize the =>
operator—colloquially termed the fat arrow. This rune serves a dual
purpose: it constructs a literal Pair object, and automatically treats
the left-hand identifier as a string, sparing your sanity from
unnecessary quotation marks.
my %coven =
neophyte => "Thomas",
adept => "Alhazred",
master => "Waite";
say %coven; # {adept => Alhazred, master => Waite, neophyte => Thomas}
{adept => Alhazred, master => Waite, neophyte => Thomas}
Notice that upon outputting the container, the order of the entities has
shifted. The % vessel holds no loyalty to the sequence of creation; it
organizes its contents according to its own inscrutable internal hashing
algorithms.
Extracting Truth: Two Paths into the Crypt
When you wish to peer inside the % container and pull a specific value
back into reality, you have two primary methods at your disposal.
1. The Runic Braces {}
The most direct method relies on curly braces. Inside these braces, you pass a normal expression or string.
my $rank = "adept";
say %coven{$rank}; # Alhazred
say %coven{"master"}; # Waite
Alhazred
Waite
2. The Angled Quotes <>
For moments when you wish to summon a key directly by its literal name without typing quotes, the angled brackets provide a cleaner shortcut. Raku automatically assumes whatever you write inside them is a literal string.
say %coven<neophyte>; # Thomas
Thomas
The Trap of the Unseen Void: If you attempt to access a key that has not been bound to a value, Raku will not crash or cry out in agony. Instead, it quietly returns a quiet, harmless
Anytype object (an uninitialized state), allowing you to safely test for an entity’s existence.
Checking for Existence vs. Truth
Because an unbound key returns an uninitialized value, checking if a key
exists requires precise magic. If a key maps to 0 or "" (the empty
string), a simple boolean check will falsely claim the slot is empty.
To determine if a key is genuinely bound within the hash—regardless of
its value—we invoke the .exists method:
my %ritual-counts = banishing => 0, summoning => 5;
# The naive approach fails us
if %ritual-counts<banishing> {
say "This will not print, as 0 evaluates to false!";
}
# The true method reveals the bond
if %ritual-counts<banishing>:exists {
say "The banishing ritual exists within the records!";
}
The banishing ritual exists within the records!
The trailing :exists adverb forces the container to reveal whether the
key has a home in the table, piercing through the illusion of boolean
falseness.
The Threshold Crossed
The % hash completes the trinity of primary containers. Armed with
$, @, and %, you now possess the complete vocabulary required to
hold, index, and map any data structures plucked from the void. In our
next transmission, we shall step away from containers entirely and
investigate the dark machinery that acts upon them: the system of
Operators and Precedence.