[Chapter 9] Tie
Author: Sriram Srinivasan
Date: 1999-07-02T01:34:50Z

#

| Chapter 9 |

# 9. Tie

Contents:
Tying Scalars
Tying Arrays
Tying Hashes
Tying Filehandles
Example: Monitoring Variables
Comparisons with Other Languages

Give me a wild tie brother,
One with a cosmic urge,
A tie that will swear and rip and tear,
When it sees my old blue serge.

- Stoddard King, The Ties That Bind

Normally, when you read or update a scalar, array, hash, or filehandle, Perl performs the appropriate operation on the corresponding internal data structure. Alternatively, you can use the `tie` keyword to bind the value (or variable) to a user-defined object, so that when you read from or write to that variable, Perl simply calls a specific method of the object it is tied to. In other words, while it provides the implementation for a "normal" variable, Perl expects a user-defined module to do so for a tied variable. Once a variable is tied, even accesses from the C API of the Perl library are delegated to the corresponding tied object.

This approach may seem like syntactic sugar, but as you'll see from the examples in this chapter, it is the syntax that gives it its power: an ordinary variable can be made to invoke a user-defined function whenever a variable is manipulated, without the user's code changing or being necessarily aware of the subterfuge. The most common use of this technique is to tie a hash variable to a module that can manipulate DBM files, which are typically disk-based hash tables (they can also be BTrees). This technique allows you to make a hash value persistent and is capable of storing much more information than can fit into available memory, while giving the impression that you are manipulating an ordinary associative array.

In the following pages, we will study how `tie` works with the various data types, and look at a few useful examples of this feature.

## 9.1 Tying Scalars

At the most basic level, there are only four things you can do with a scalar. You can create it, get or set its value, and destroy it (by ending the scope or `undef`'ing it). `tie` allows you to supply a subroutine to be called back for each of these operations.

The syntax of `tie` is as follows:

    tie variable, classname, list;

The first parameter should be one of the four supported types described above. The second parameter is the name of a user-defined class. You are expected to have invoked `use` `classname` or `require` `classname` before calling `tie`.

When this statement is executed, Perl checks the type of the variable (the first parameter). It then calls the method ``classname`->TIESCALAR(`list`)`, or `TIEARRAY`, `TIEHASH`, or `TIEHANDLE`, depending on whether the tied variable is a scalar, array, hash, or filehandle. It is a run-time error if this method is not present in the class. `TIESCALAR()` is expected to return an object, which is then internally associated with (or tied to) the given variable. Now, when you read and write to the variable, Perl internally calls ``object`->FETCH()` and ``object`->STORE(`new value`)`, respectively. Finally, when the tied variable goes out of scope, Perl calls ``object`->DESTROY()`. Simple, isn't it?

The names `FETCH`, `STORE`, and `TIESCALAR` are similar to `AUTOLOAD` and `DESTROY` in that they have a special significance for Perl only under appropriate circumstances. That is, a module can have a method called `FETCH`, which can be used normally like any other user-defined subroutine. But if you use `tie`, this method assumes a special meaning.

Perl does not care about the exact data structure used for the object (whether you used a hash or ObjectTemplate). Table 9.1 shows a variable "`$temperature`" tied to an automatic temperature control system, which is represented by a Perl module called AC.pm.[1] An attempt to read `$temperature`'s value is translated to a call to the temperature sensor, and an attempt to set its value translates to a command to the heating system to do what is needed.

> [1] Air conditioning, not alternating current!

Table 9.1: Flow of Control in a Tie Scalar Operation
When you say: | Perl translates it to the method call: | The method looks like this:
--- | --- | ---
    tie $temperature,
        'AC';
    $obj = AC->TIESCALAR()
Perl now "ties" `$temperature` and `$obj` |
    package AC;
    sub TIESCALAR {
      ...
      $ac = bless {...},
            $pkg;
      return $ac;
    }
    $x = $temperature;
    $x = $obj->FETCH();
    sub FETCH {
      $ac->get_temp();
    }
    $temperature = 20;
    $obj->STORE(20);
    sub STORE {
     ($obj, $t) = @_;
     $ac->set_temp($t);
    }
    untie $temperature;
    #or
    undef $temperature;
or when `$temperature` goes out of scope |
    $obj->DESTROY()
    sub DESTROY {
    }

As you can see, the AC module is an ordinary class with a constructor and three object methods (whose names happen to be special). Perl interacts with this module behind the scenes, providing the user with a much simpler interaction model. You can get the tied object as the return value of `tie` or invoke the `tied` function to get to it at any other time. Therefore the statement

    $temperature = 20;

is identical to

    (tied $temperature)->STORE(20);

The `untie` function restores the original value of the variable and also calls the object's `DESTROY` method.

Perl does not constrain the object's module in any way other than to expect it to provide the methods we saw earlier. It can store whatever data it wants, can have other methods, and is perfectly usable even in a non-tie context.

### 9.1.1 Example: Stopwatch

Let us look at a simple example of a stopwatch using a tied scalar. When you store any value into it, it notes the current time (that is, it ignores the value). When you retrieve a value from it, it returns the amount of time elapsed since the last time a store was attempted on it. This is how it is used:

    use Stopwatch;
    tie $s, 'Stopwatch';

    # $s is scalar transparently tied to a Stopwatch object.
    $s = 0;             # Writing to it forces a reset
    sleep(10);          # Sleep 10 seconds
    print "$s\n";       # Should print 10

The example might sometimes print 9 because of `sleep`'s resolution.

Example 9.1 shows how Stopwatch is implemented.

#### Example 9.1: Stopwatch Implemented Using tie

    package Stopwatch;

    sub TIESCALAR {
       my ($pkg) = @_;
       my $obj = time();  # $obj stores the time at last reset.
       return (bless \$obj, $pkg);
    }

    sub FETCH {
       my ($r_obj) = @_;
       # Return the time elapsed since it was last reset
       return (time() - $$r_obj);
    }

    sub STORE {
       my ($r_obj, $val) = @_;
       # Ignore the value. Any write to it is seen as a reset
       return ($$r_obj = time());
    }

    1;

`TIESCALAR` notes the current time and returns a reference to a blessed scalar (with the current time in it). As was mentioned earlier, you are under no obligation to provide a blessed scalar reference; Perl does not care whether the object is a scalar or an array or a complex data structure. The only requirement is that it be blessed into a module that supports the `FETCH` and `STORE` methods. In this case, `FETCH` computes the interval between the current time (as reported by `time`) and the last reset time.

Incidentally, the time calculations in this module work at the granularity of only a second. If you want a finer granularity, you can use the Time::HiRes module available from CPAN, which gives microsecond resolution on Unix systems (gives access to the usleep and ualarm system calls). On Microsoft Windows systems, you can use the `Win32::Timer` call for millisecond-level timing.

#### 9.1.1.1 tie works with anonymous values

The first argument to `tie` must boil down to a scalar, array, hash, or filehandle value ; it does not have to be a variable. The following code shows two valid examples of scalar ties:

    $r = \$s;
    tie $$r, 'Stopwatch';  # Indirect tie to $s

    @foo = (1, 2);
    tie $foo[1], 'Stopwatch';

As you can see, this facility works with the underlying values and is not associated with a variable name (unlike the trace facility in TCL).

8.4 Resources |  | 9.2 Tying Arrays