Home / Alt manpages / perltie(1)

  • perltie(1)
  • User command
  • linux

Use Perl tie Safely: Turn Variable Access into Class Methods

A tied Perl variable looks ordinary, but every read or assignment can secretly run a class method. This guide builds a working tied scalar to make that mechanism concrete. The example is self-contained, changes no system files and needs no elevated privileges. Allow about 15 minutes if you are reading the mechanism as you go, or five minutes if you only need a small test.

Before you start

You need Perl and a shell. This guide follows the installed perltie(1) manual from Perl v5.38.2. Check your interpreter before relying on version-specific details:

perl -v

The manual describes tie for scalars, arrays, hashes and filehandles. Start with a scalar: it has a small method surface and makes it obvious when Perl is calling into the class. A tied variable is still executable behaviour, not passive data, so only tie a variable to code you trust.

Checkpoint: the class contract

A scalar class normally supplies TIESCALAR, FETCH and STORE. Perl calls the constructor during tie, FETCH when the variable is read, and STORE when it is assigned. The method names are uppercase because they are implicit callbacks. UNTIE and DESTROY are optional lifecycle hooks.

The constructor receives the class name first, followed by the extra arguments from the tie statement, and it should return a blessed reference. That reference is the class's private state, and the return value of tie gives you a second way to reach it.

1. Create a harmless tied scalar

Save this as /tmp/perltie-example.pl. It keeps an integer in memory and counts reads. There is no file, network connection or process operation to clean up:

use strict;
use warnings;

{
    package Counter;

    sub TIESCALAR {
        my ($class, $initial) = @_;
        return bless { value => $initial // 0, reads => 0 }, $class;
    }

    sub FETCH {
        my ($self) = @_;
        $self->{reads}++;
        return $self->{value};
    }

    sub STORE {
        my ($self, $value) = @_;
        $self->{value} = $value;
    }

    sub reads {
        return $_[0]->{reads};
    }

    sub UNTIE {
        my ($self, $extra_references) = @_;
        print "untied with $extra_references extra references\n"
            if $extra_references;
    }
}

my $number;
my $object = tie $number, Counter => 10;
print "start=$number\n";
$number = $number + 5;
print "after=$number reads=", $object->reads, "\n";
untie $number;
undef $object;

2. Run it and inspect the callbacks

Run the script as your ordinary user:

perl /tmp/perltie-example.pl

Expected output is:

start=10
after=15 reads=3
untied with 1 extra references

The first interpolation reads the tied scalar once. The addition reads it again, then the assignment invokes STORE. The final interpolation reads it a third time. The constructor's object is stored in $object, so UNTIE reports one extra reference when the variable is untied.

3. Remove the extra reference before cleanup

The extra reference is a common distraction when a tied class owns a buffered file, database handle or other resource. Calling untie removes the variable's tie, but it does not necessarily destroy an object you are still holding. For a class whose cleanup lives in DESTROY, that can leave work delayed until a later scope exit.

Change the end of the example to release the object first:

undef $object;
untie $number;

Run it again:

perl /tmp/perltie-example.pl

There should be no UNTIE warning line this time, because the callback receives no extra reference. In real code, follow the class's documented lifecycle: some classes use UNTIE for cleanup, others keep it in DESTROY.

When a tied scalar is the right tool

Tie earns its keep when an interface should look like a scalar but its storage or side effects belong behind a class boundary. A read can fetch from another system, and an assignment can validate or persist a new value. That convenience has a cost: ordinary-looking expressions can run arbitrary class code, and repeated reads can call FETCH repeatedly, so never assume that reading a tied value once is free or side-effect-free.

For an array, the matching constructor is TIEARRAY, with methods such as FETCH, STORE, FETCHSIZE and STORESIZE. A hash uses TIEHASH plus methods such as FETCH, STORE, FIRSTKEY and NEXTKEY. A filehandle uses TIEHANDLE and callbacks such as PRINT or READLINE. Choose the narrowest interface that matches your data; do not tie a bigger surface just to avoid writing one explicit method call.

Common failure points

  • The module is not loaded. tie does not load a package for you. Put use Your::Module; in the script, or define the package there as this example does.
  • The constructor returns nothing. A failed constructor makes the tie fail. Check its inputs and report the error in a way the caller can handle.
  • STORE returns the assigned value. The assignment result comes through a later FETCH; the manual says not to rely on a return value from STORE.
  • Cleanup appears late. Look for references returned by tie or tied. Release them before untie when the class expects destruction at that point.
  • A tied hash is unexpectedly slow. Iteration invokes FIRSTKEY and NEXTKEY, so counting entries through iteration can be expensive for a large backing store.

Done means

  • perl -v identified the interpreter you are using.
  • The tied scalar printed start=10 and after=15.
  • You can identify which reads invoke FETCH and which assignment invokes STORE.
  • You understand why an object retained after tie can delay destruction.
  • Your class is trusted, its callbacks are narrow, and its cleanup path is deliberate.