I am implementing some filters to use while loading data, and I would like these filters to be customisable, so that you can do the following:

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
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:

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

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.