Tied Variables, AUTOLOAD and DESTROY

35.1 tie

Tie methods: scalars (TIESCALAR FETCH STORE), arrays (TIEARRAY FETCH STORE FETCHSIZE ...), hashes (TIEHASH FETCH STORE EXISTS DELETE CLEAR FIRSTKEY NEXTKEY), handles (TIEHANDLE PRINT READLINE ...).

Real uses: Tie::File (an array view of a file's lines), DB_File (a hash on disk), Tie::IxHash (ordered hash), Tie::RefHash.

package UpperCaseHash;
use v5.36;
require Tie::Hash;
our @ISA = ('Tie::StdHash');                          # inherit default behavior
sub STORE($self, $key, $value) { $self->{uc $key} = $value }
sub FETCH($self, $key)         { $self->{uc $key} }

package main;
tie my %h, 'UpperCaseHash';
$h{name} = 'Ana';
say $h{NAME};                                        # Ana
say join ',', keys %h;                               # NAME

35.2 AUTOLOAD

package Dynamic;
use v5.36;
our $AUTOLOAD;
sub new($class, %f) { bless {%f}, $class }
sub AUTOLOAD {
    my $self = shift;
    (my $name = $AUTOLOAD) =~ s/.*:://;                  # strip the package name
    return if $name eq 'DESTROY';                        # don't autoload DESTROY
    die "No method $name" unless exists $self->{$name};
    no strict 'refs';
    *{$AUTOLOAD} = sub { $_[0]{$name} };                 # install it so later calls are fast
    goto &$AUTOLOAD;
}
sub can($self, $m) { $self->SUPER::can($m) // (ref $self && exists $self->{$m} ? sub { $_[0]{$m} } : undef) }
package main;
say Dynamic->new(color => 'red')->color;                 # red

35.3 DESTROY and Resource Management

package TempFile;
sub new { my ($class, $path) = @_; open my $fh, '>', $path or die; bless { path => $path, fh => $fh }, $class }
sub DESTROY {
    my $self = shift;
    return if ${^GLOBAL_PHASE} eq 'DESTRUCT';            # avoid problems during global destruction
    close $self->{fh};
    unlink $self->{path};
}
# Perl's reference counting makes destruction deterministic: the object is destroyed when its last reference goes away.
# Guard pattern (CPAN Scope::Guard / Guard): run cleanup at scope exit; or use the core `defer` feature.