These filters will be called repeatedly, so I'd like to optimise (prematurely?) for speed. Also, Module also needs to be subclassable. So what I'm doing at the moment is this:my $c = Module->new( { filterX => XXXX } ); where XXXX could be: - a hash ref --> checks for exists $hashref->{$va +lue} - a regex --> checks if the regex matches - an array ref of regexes --> checks if any regex matches - a coderef --> the code is called
At object intialisation, it:
Then I can use the filter with $self->{$filter}->($self,$value);
Advantage: Speed - All I have to do is to call the coderef with the values and we're done. All the up front work is done at initialisation.
Disadvantages: The "subclassability" is fixed as soon as the object is instantiated, which is not a standard OO approach. I would guess that this would rarely be a problem.
The actual code is below (I have removed a few filter specific checks from this code) :
my %callbacks = ( CODE => \&_init_code_callback, HASH => \&_init_hash_callback, ARRAY => \&_init_array_callback, ); #=================================== sub _init_callback { #=================================== my ( $self, $callback, $filter ) = @_; # If nothing set, use default or subclassed version unless ($filter) { $self->{$callback} = $self->can($callback); return; } # If not in callbacks, then assume it is a single regex $filter = [$filter] unless exists $callbacks{ref $filter}; return $callbacks{ref $filter}->($filter); } #=================================== sub _init_code_callback { #=================================== return $_[0] }; #=================================== sub _init_hash_callback { #=================================== my $filter = shift; return sub { my $self = shift; my $param = shift; return exists $filter->{$param}; }; } #=================================== sub _init_array_callback { #=================================== my $filter = shift; foreach my $value (@$filter) { $value ||= ''; die "'$value' is not a regular expression" unless ref $value eq 'Regexp'; } return sub { my $self = shift; my $value = shift; foreach my $regex (@$filter) { return 1 if $value =~ m/$regex/; } return 0; }; }
Is my approach a reasonable one, or is it likely to cause confusion to other developers? Should I just bite the bullet and use (essentially) the same code that is in _init_callback in the default filters?
thanks
Clint
In reply to Implementing filters as callbacks / hashrefs / regexes by clinton
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |