my %validation_for = ( foo => qr/^\d+$/, # foo must be an integer bar => \&validate, }: sub attr { my ( $self, $attr ) = splice @_, 0, 2; croak "No such attribute $attr" unless exists $validation_for{$attr}; return $self->{$attr} unless @_; # set the value my $validation = $validation_for{$attr}; my $new_val = shift; if ('Regexp' eq ref $validation) { croak "$new_val doesn't match $validation" if $new_val !~ $validation; } else { $self->$validation($new_val); # we'll assume it throws an error } $self->{$attr} = $new_val; return $self; }