Tied hashes#

A tied hash is the richest of the tie types, because a hash does more than read and write single elements - it iterates, it reports its size, it tests for key existence, and it clears. Each of those is a separate hook. Hashes were the first Perl data type to be tied (the original use case was binding %hash to an on-disk DBM file), and the interface still reflects that heritage.

The full method menu is on the tie reference page. This chapter builds one class and explains each hook, with attention to the part that trips people up: the iteration protocol.

A complete class#

A hash whose keys are case-insensitive - $h{Name} and $h{NAME} address the same slot:

use v5.36;

package CaseInsensitive {
    sub TIEHASH  { my $class = shift; return bless {}, $class }
    sub STORE    { my ($self, $key, $val) = @_; $self->{lc $key} = $val }
    sub FETCH    { my ($self, $key) = @_; return $self->{lc $key} }
    sub EXISTS   { my ($self, $key) = @_; return exists $self->{lc $key} }
    sub DELETE   { my ($self, $key) = @_; return delete $self->{lc $key} }
    sub CLEAR    { my $self = shift; %$self = () }
    sub FIRSTKEY { my $self = shift; my $reset = keys %$self; return each %$self }
    sub NEXTKEY  { my $self = shift; return each %$self }
    sub SCALAR   { my $self = shift; return scalar %$self }
}

tie my %h, 'CaseInsensitive';
$h{Name}  = 'Ada';
$h{EMAIL} = 'ada@example.org';

say $h{name};                          # Ada
say $h{email};                         # ada@example.org
say exists $h{NAME} ? 'yes' : 'no';    # yes
say scalar %h ? 'nonempty' : 'empty';  # nonempty

for my $k (sort keys %h) {
    say "$k => $h{$k}";
}
# email => ada@example.org
# name => Ada

The object is a blessed hash ref used as the real storage; the hooks lower-case the key before touching it. Notice that iteration returns the stored (lower-cased) keys, which is exactly what a case-insensitive hash should do.

The method contract#

TIEHASH classname, LIST

The constructor. Returns a blessed reference - usually but not necessarily a hash ref - that becomes the tied object.

FETCH this, key / STORE this, key, value

Single-element read and write, the same pair as for scalars but with a key argument. STORE’s return value is ignored.

EXISTS this, key / DELETE this, key

Back the exists and delete built-ins. DELETE’s return value becomes delete’s return value; to match a plain hash, return what FETCH would have returned for that key before removing it.

CLEAR this

Triggered when the whole hash is emptied, typically by assigning the empty list (%h = ()). Remove everything.

FIRSTKEY this / NEXTKEY this, lastkey

The iteration protocol - see below. Together they drive keys, values, and each.

SCALAR this

Called when the hash is evaluated in scalar or boolean context (scalar %h, if (%h), and since 5.28 keys %h in boolean context). Return a value that is true when the hash is non-empty and false when empty.

DESTROY this and UNTIE this

Optional cleanup hooks, identical in role to the scalar case. UNTIE is covered under the untie gotcha below.

The iteration protocol#

This is the part of the hash interface that has no analogue in the scalar one, and the part that most often goes wrong.

When a keys, values, or each iteration begins, the runtime calls FIRSTKEY to get the first key, then NEXTKEY repeatedly, passing the previously returned key each time, until a method returns the empty list or undef. Both are always called in scalar context and should return just a key; the runtime calls FETCH itself to get each value.

Two rules keep iteration correct:

  • FIRSTKEY must reset any internal iterator. When the backing store is a real hash, evaluate keys %$self in void or scalar context first - that resets Perl’s per-hash each cursor - then call each. The throwaway my $reset = keys %$self in the example does exactly this. Skip it and a fresh keys %h may resume from wherever the last iteration stopped.

  • Signal the end with the empty list. When the backing store is not a real hash and has no each of its own, return the empty list (or undef) once you have handed out the last key.

Why SCALAR is worth defining#

Without a SCALAR method, the runtime guesses at the hash’s truth in boolean context, and the guess can be wrong - notably, it may report a hash as non-empty right after you have emptied it by repeated DELETE. If if (%tied_hash) matters to your callers, define SCALAR and return the real answer, as the example does with scalar %$self.

Call timing#

  • $h{k} reads → FETCH; $h{k} = $vSTORE.

  • exists $h{k}EXISTS; delete $h{k}DELETE.

  • %h = ()CLEAR; %h = (a => 1)CLEAR then STORE.

  • keys %h / values %h / each %hFIRSTKEY once, then NEXTKEY per step. keys and values in list context call FETCH for each key as well.

  • scalar %h, if (%h)SCALAR (if defined).

  • A hash slice @h{qw(a b)} calls FETCH once per key; there is no slice hook.

Minimum viable class#

A read/write tied hash needs at least TIEHASH, FETCH, and STORE. If callers will ever iterate it, add FIRSTKEY and NEXTKEY - without them, keys and each see an empty hash. Add EXISTS and DELETE if callers use those built-ins; without them, exists/delete die at the point of use. SCALAR and CLEAR round out correctness for boolean tests and bulk emptying.

The easy way: inherit from Tie::StdHash#

Tie::StdHash (shipped inside Tie::Hash) implements the entire menu over a blessed hash ref. Inherit from it and override only the hooks that should behave differently:

package LoudHash {
    use Tie::Hash;
    our @ISA = ('Tie::StdHash');
    sub STORE { my ($self, $k, $v) = @_; $self->{$k} = uc $v }
}

tie my %loud, 'LoudHash';
$loud{greeting} = 'hi';
say $loud{greeting};                # HI

Only STORE changes; FETCH, EXISTS, the iteration protocol, and the constructor all come from the base class. Tie::Hash (the parent) is the abstract version that supplies a default TIEHASH and new but leaves the access methods for you to write; Tie::StdHash is the concrete one you usually want.

See also#

  • tie - the built-in and the full hash method menu

  • tied - reach the backing object for class-specific methods

  • each - the iterator that FIRSTKEY / NEXTKEY implement; its own page documents the end-of-iteration contract

  • exists and delete - the built-ins behind EXISTS and DELETE

  • Tied scalars - the simpler interface this one builds on

  • Tie::Hash - the base-class module; Tie::StdHash is the concrete version