Listen Print

Changing Hash Behaviour with tie

by Dave Cross
September 04, 2001

Introduction

In my experience, hashes are just about the most useful built-in datatype that Perl has. They are useful for so many things - from simple lookup tables to complex data structures. And, of course, most Perl Objects have a blessed hash as their underlying implementation.

The fact that they have so many uses must mean the Larry and the Perl5 Porters must have got the functionality of hashes pretty much right when designing them - it's simple, instinctive and effective. But have you ever come across a situation where you wanted to change the way that hashes worked? Perhaps you wanted hashes that only had a fixed set of keys. Faced with this requirement, it's tempting to move away from the hash interface completely and use an object. The downside to this decision is that you lose the easy-to-understand hash interface. But using tied variables it is possible to create an object and still use it like a hash.

Tied Objects

Tied objects are, in my opinion, an underused feature of Perl. The details (together with some very good examples) are in perltie and there are some extended examples in the ``Tied variables'' chapter of Programming Perl. Despite all of this great documentation, most people seem to believe that tieing is only used to tie a hash to a DBM file. The truth is that any type of Perl data structure can be tied to just about anything. It's simply a case of writing an object that includes certain pre-defined methods. If you want to create a tied object that emulates a standard Perl object most of the time, then it's even easier, as the Perl distribution contains modules that define objects that mimic the behavior of that standard data types. For example, there is a class called Tie::StdHash (in the file Tie::Hash) that mimics the behavior of a real hash. To alter that behavior we simply have to subclass Tie::StdHash and override the methods that we're interested in.

Related Reading

Programming Perl, 3rd Edition

Programming Perl, 3rd Edition
By Larry Wall, Tom Christiansen, Jon Orwant

Using Tied Objects

In your Perl program, you make use of a tied object by calling the tie function. tie takes two mandatory parameters: the variable that you are tieing and the name of the class to tie it to, followed by any number of optional paramters. For example, if we had written the hash with fixed keys discussed earlier (which we will do soon), we could use the class in our program like this:


  use Tie::Hash::FixedKey;

  my %person;

  my @keys = qw(forename surname date_of_birth gender);

  tie %person, 'Tie::Hash::FixedWidth', @keys;

After running this code, %person can still be used like a hash, but its behavior will have been changed. Any attempt to assign a value to a key outside the list that we used in the call to tie will fail in some way that we get to specify when we write the module.

If for some reason we wanted to get to the underlying object that is tied to the hash, then we can use the tied function. For example,


  my $obj = tied(%person);

will give us back the Tie::Hash::FixedKeys object that is tied to our %person hash. This is sometimes used to extend the functionality in ways that aren't available through the standard hash interface. In our fixed keys example, we might want the user to be able to extend or reduce the list of valid keys. There is no way to do this in the standard hash interface so we would need to add new methods called, say, add_keys and del_keys, which can be called like this:


  tied(%person)->add_keys('weight', 'height');

When you have finished with the tied object and want to return it to being an ordinary hash, you can use the untie function. For example,


  untie %person;

returns %person to being an ordinary hash.

To tie an object to a Perl hash, your object needs to define the following set of methods. Notice that they are all named in upper case. This is the standard for function names that Perl is going to call for you.

TIEHASH
This is the constructor function. It is called when the user calls the tie function. It is passed the name of the class and the list of parameters that were passed to tie. It should return a reference to the new tied object.
FETCH
This is the method that is called when the user accesses a value from the hash. The method is passed a reference to the tied object and the key that the user is trying to access. It should return the value associated with the given key (or undef if the key isn't found).
STORE
This method is called when the user tries to store a value against a key in the tied hash. It is passed a reference to the object, together with the key and value pair.
DELETE
This method is called when the user calls the delete function to remove one of the key/value pairs in the tied hash. It is passed a reference to the tied object and the key that the user wishes to remove. The return value becomes the return value from the delete call. To emulate the 'real' delete function, this should be the value that was stored in the hash before it was deleted.
CLEAR
This method is called when the user clears the whole hash (usually by asigning an empty list to the hash). It is passed a reference to the tied object.
EXISTS
This method is called when the user calls the exists function to see whether a given key exists in the hash. It is passed a reference to the tied object and the key to search for. It should return a true value if the key is found and false otherwise.
FIRSTKEY
This method is called when one of the hash iterator functions (each or keys) is called for the first time. It is passed a reference to the tied object and should return the first key in the hash.
NEXTKEY
This method is called when one of the iterator functions is called. It is passed a reference to the tied object and the name of the last key that was processed. It should return the name of the next key or undef if there are no more keys.
UNTIE
This method is called when the untie function is called. It is passed a reference to the tied object.
DESTROY
This method is called when the tied variable goes out of scope. It is passed a reference to the tied object.

As you can see, there are a large number of methods to implement, but in the next section we'll see how you can get away with only implementing some of them.

Pages: 1, 2, 3

Next Pagearrow





Contact Us | Advertise with Us | Privacy Policy | Press Center | Jobs | Submissions Guidelines

Copyright © 2000-2008 O’Reilly Media, Inc. All Rights Reserved. | (707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on the O'Reilly Network are the property of their respective owners.

For problems or assistance with this site, email