use Loop::Watch; my $x = 2; ensure { $x > 0 } watching($x), doing { # all your code centered around $x here }; #### package Tie::Scalar::Watch; use Carp; use strict; # rich man's Exporter ;) # this just puts 'watch()' in the caller's namespace sub import { my $pkg = caller; no strict 'refs'; *{ $pkg . "::watch" } = \&watch; } sub TIESCALAR { my ($class, $val, $rule) = @_; my $self = bless [ undef, $rule ], $class; $self->STORE($val); return $self; } sub FETCH { $_[0][0] } sub STORE { my ($self, $val) = @_; return $self->[0] = $val if $self->[1]->($val); croak "Value $val is out of bounds"; } sub watch (&$) { tie $_[1], __PACKAGE__, $_[1], $_[0]; } 1; #### use Tie::Scalar::Watch; # imports 'watch' my $x = 10; watch { $_[0] > 5 } $x; # $x is now transparently tied! # and you thought tying was transparent already! while (1) { print "$x\n"; $x--; } #### sub STORE { my ($self, $val) = @_; $self->[0] = $val; $self->[1]->() ? return $val : croak "Value $val is out of bounds"; }