Tied scalars#

A tied scalar is the smallest tie interface and the best place to learn the shape of all the others. You define a constructor and two accessor methods; from then on, every read of the variable calls one of them and every write calls the other.

The class needs four methods, two of them optional:

  • TIESCALAR - the constructor, called once by tie.

  • FETCH - called on every read of the variable.

  • STORE - called on every write to the variable.

  • DESTROY - called when the tied variable goes away (optional).

The full signature list is on the tie reference page. This chapter shows what each method does by building one.

A complete class#

A counter that clamps writes so the value never drops below zero:

use v5.36;

package Counter {
    sub TIESCALAR {
        my ($class, $start) = @_;
        my $n = $start // 0;
        return bless \$n, $class;
    }
    sub FETCH { my $self = shift; return $$self }
    sub STORE {
        my ($self, $value) = @_;
        $$self = $value < 0 ? 0 : $value;   # never go below zero
    }
    sub DESTROY { }
}

tie my $hits, 'Counter', 10;
say $hits;            # 10
$hits = 25;
say $hits;            # 25
$hits = -7;
say $hits;            # 0

The object behind the scalar can be anything blessed - here a reference to a plain number. The LIST after the class name in the tie call (10) is passed straight to TIESCALAR.

The method contract#

TIESCALAR classname, LIST

The constructor. It receives the class name and whatever extra arguments were passed to tie. It must return a blessed reference; that reference becomes the tied object and the return value of the tie call. A common shortcut is a blessed scalar ref holding the value, as above, but a blessed hash ref is just as valid when the class needs more state.

FETCH this

Called every time the variable is read. It takes only the object. Whatever it returns is what the reader sees. FETCH is where a computed scalar earns its keep: it can recompute, look something up, or log the access and return a stored value.

STORE this, value

Called every time the variable is assigned. It receives the object and the single new value. Its return value is ignored - the assignment expression’s value comes from a subsequent FETCH, not from STORE. This is where validation, clamping, or write-through to a backing store lives.

DESTROY this

Called when the tied variable is destroyed (scope exit, or the last reference dropping). Define it only when the class holds a resource that needs releasing - an open handle, a lock. A counter has nothing to clean up, so its DESTROY is empty or omitted entirely.

Call timing#

  • Reading in any context calls FETCH. say $hits, $x = $hits + 1, and "$hits" each trigger one FETCH.

  • Assignment calls STORE with the right-hand value. $hits = 25 calls STORE($obj, 25).

  • Compound assignment reads then writes: $hits += 5 calls FETCH, adds 5, then STORE. So does $hits++.

  • The value of an assignment expression comes from FETCH, not STORE’s return. After my $r = ($hits = -7), $r is 0 because the clamp ran in STORE and the expression’s value was fetched back.

Minimum viable class#

The smallest useful tied scalar defines exactly TIESCALAR, FETCH, and STORE. Omit DESTROY unless you allocate something. A class with only TIESCALAR and FETCH produces a read-only scalar: it ties fine, but the first assignment dies with Can't locate object method "STORE".

The easy way: inherit from Tie::StdScalar#

Tie::StdScalar (shipped inside Tie::Scalar) implements TIESCALAR, FETCH, STORE, and DESTROY over a blessed scalar ref. Inherit from it and override only the hook you want to change:

package Uppercase {
    use Tie::Scalar;
    our @ISA = ('Tie::StdScalar');
    sub STORE { my ($self, $v) = @_; $$self = uc $v }
}

tie my $shout, 'Uppercase';
$shout = 'hello';
say $shout;          # HELLO

STORE upper-cases on the way in; FETCH and the constructor come from the base class unchanged.

Tie::Scalar itself is the abstract base - it defines FETCH and STORE that croak, so subclassing it directly means supplying your own TIESCALAR. Reach for Tie::StdScalar when you want a working constructor for free; reach for Tie::Scalar only when you intend to write every method anyway and want the interface documented by inheritance.

See also#

  • tie - the built-in, with the full per-type method menu

  • tied - recover the object backing the variable to call class-specific methods on it

  • untie - dissolve the binding

  • Tied hashes - the next step up: a constructor plus an iteration protocol

  • Tie::Scalar - the base-class module; Tie::StdScalar is the concrete version you usually want