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; # NAME35.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; # red35.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.