package Tie::Constrained;
####
use Errno qw/EINVAL EDOM ERANGE/;
sub TIESCALAR {
my $class = shift;
my $self = { test => defined $_[0]? $_[0]: \&validate };
$self->{test}($_[1]) or invalid(EINVAL) if defined $_[1];
$self->{val} = $_[1];
bless $self, $class;
}
sub STORE {
my ($self, $try) = @_;
$self->{test}($try) or invalid(EINVAL);
$self->{val} = $try;
}
sub FETCH {
$_[0]->{val};
}
sub DESTROY {}
sub validate { 1 }
sub invalid {
$! = shift;
die sprintf("Constraint violation: %s by %s::%s in %s line %s.\n",
$!,
map { qq($_) } (caller 1)[0,3,1,2] );
}
1;
__DATA__
##
##
Usage:
use Tie::Constrained;
tie my $var, Tie::Constrained => \&mytest, $initval;
Both arguments are optional, but the default validator
function always says yes. mytest() should be designed
to return true for valid data and false for data to reject.