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 bytie.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, LISTThe 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 thetiecall. 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 thisCalled every time the variable is read. It takes only the object. Whatever it returns is what the reader sees.
FETCHis where a computed scalar earns its keep: it can recompute, look something up, or log the access and return a stored value.STORE this, valueCalled 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 fromSTORE. This is where validation, clamping, or write-through to a backing store lives.DESTROY thisCalled 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
DESTROYis empty or omitted entirely.
Call timing#
Reading in any context calls
FETCH.say $hits,$x = $hits + 1, and"$hits"each trigger oneFETCH.Assignment calls
STOREwith the right-hand value.$hits = 25callsSTORE($obj, 25).Compound assignment reads then writes:
$hits += 5callsFETCH, adds 5, thenSTORE. So does$hits++.The value of an assignment expression comes from
FETCH, notSTORE’s return. Aftermy $r = ($hits = -7),$ris0because the clamp ran inSTOREand 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 menutied- recover the object backing the variable to call class-specific methods on ituntie- dissolve the bindingTied hashes - the next step up: a constructor plus an iteration protocol
Tie::Scalar- the base-class module;Tie::StdScalaris the concrete version you usually want