Accesses to tied hash tables are fully supported, unlike arrays. The tie-hash facility allows you to trap operations on the entire hash table (%h = ()), accesses to individual elements, and queries (exists, defined, each, keys, and values). Table 9.3 shows how these actions are mapped to method invocations on the tied object.
When you say: | Perl translates it to: |
---|---|
tie %h, 'Foo', 'a' => 1 | $obj = Foo->TIEHASH('a',1); |
$h{a} | $obj->FETCH ('a') |
$h{a} = 1 | $obj->STORE ('a', 1) |
delete $h{a} | $obj->DELETE('a') |
exists $h{a} | $obj->EXISTS('a') |
keys (%h),values(%h) each (%h) | $lk = $obj->FIRSTKEY (); do { $val = $obj->FETCH{$lk}; } while ($lk = $obj->NEXTKEY($lk)); |
%h = () | $obj->CLEAR() |
%h = (a=> 1) | $obj->CLEAR() $obj->STORE('a',1) |
untie %h | $obj->DESTROY() |
FIRSTKEY and NEXTKEY are expected to return the next key in the sequence. This suffices if keys is invoked by the calling code; but if values or each is called, it calls FETCH for each key.
The most common (and natural-looking) use of tie is as a frontend for DBM files, which, as we mentioned earlier, are disk-based hash tables. Perl comes enabled with various flavors of DBM support. The following example uses the SDBM module, which comes with the standard Perl distribution:
use Fcntl; use SDBM_File; tie (%h, 'SDBM_File', 'foo.dbm', O_RDWR|O_CREAT, 0640) || die $!; # Open dbm file $h{a} = 10; # Write to file transparently while (($k, $v) = each %h) { # Iterate over all keys in file print "$k,$v\n" } untie %h; # Flush and close the dbm file
Perl old-timers may recognize the similarity to the dbm_open function. tie just happens to be a more general facility.
Tied hashes have the same problem outlined in the last section: You cannot store references unless you explicitly serialize the structures referred to into one stream (from which you can recreate the data structure later). The MLDBM module, which we will explore further in Chapter 10, attempts to tie multilevel hashes to a DBM file.
Two other modules in the standard Perl distribution use tie internally. Config makes all information known to the build environment (that is, to configure) as a hash (%Config) in the caller's namespace, like this:
use Config; while (($k, $v) = each %Config) { print "$k => $v \n"; }
Env is another standard library that uses tie to make environment variables appear as ordinary variables. We saw a non-tie variant of Env in the section "Importing Symbols" in Chapter 6, Modules.