NAME
Sub::Approx - Perl module for calling subroutines by approximate names!
SYNOPSIS
use Sub::Approx;
sub a {
# blah...
}
&aa; # executes &a if &aa doesn't exist.
use Sub::Approx (match => 'text_metaphone');
use Sub::Approx (match => 'string_approx');
use Sub::Approx (match => 'text_soundex');
use Sub::Approx (match => \&my_matcher);
use Sub::Approx (match => \&my_matcher, choose => \&my_chooser);
DESCRIPTION
This is _really_ stupid. This module allows you to call subroutines by _approximate_ names. Why you would ever want to do this is a complete mystery to me. It was written as an experiment to see how well I understood typeglobs and AUTOLOADing.
To use it, simply include the line:
use Sub::Approx;
somewhere in your program. Then each time you call a subroutine that doesn't exist in the the current package Perl will search for a subroutine with approximately the same name. The meaning of 'approximately the same' is configurable. The default is to find subroutines with the same Soundex value (as defined by Text::Soundex) as the missing subroutine. There are two other built-in matching styles using Text::MetaPhone and String::Approx. To use either of these use:
use Sub::Approx (match => 'text_metaphone');
or
use Sub::Approx (match => 'string_approx');
when using Sub::Approx.
You can also use your own subroutine to do the matching. Your subroutine should expect to receive the name of the missing subroutine followed by a list containing all valid subroutine names and should return a list of all matching subroutines. For example:
sub my_matcher {
my $sub_wanted = shift;
my @subs = @_;
return @subs;
}
This example isn't particularly useful as it says that all subroutine names are an equally good match. To use this match subroutine in place of the standard ones, give Sub::Approx a reference to the subroutine like this:
use Sub::Approx (match => \&my_matcher);
Having retrieved a list of matches, we need to select one of them to run. The default behaviour is to pick one at random, but again you can configure this behaviour by writing a subroutine. This subroutine will be passed a list of matching subroutine names and should return the name of the subroutine to run. For example:
sub my_chooser {
return shift;
}
which will return the first subroutine name in the list. To make Sub::Approx use this subroutine in place of the standard one, give Sub::Approx a reference to the subroutine like this:
use Sub::Approx (choose => \&my_chooser);
You can, of course, define both a matcher and a chooser like this:
use Sub::Approx (match => \&my_matcher, choose => \&my_chooser);
or use you own chooser in conjunction with a standard matcher like this:
use Sub::Approx (match => 'text_metaphone',
choose => \&my_chooser);
CAVEAT
I can't stress too strongly that this will make your code completely unmaintainable and you really shouldn't use this module unless you're doing something very stupid.
ACKNOWLEDGEMENTS
This idea came to me whilst sitting in Mark-Jason Dominus' "Tricks of the Wizards" tutorial. In order to protect his reputation I should probably point out that just as the idea was forming in my head he clearly said that this kind of thing was a very bad idea.
Leon Brocard is clearly as mad as me as he pointed out some important bugs and helped massively with the 'fuzzy-configurability'.
Matt Freake helped by pointing out that Perl generally does what you mean, not what you think it should do.
AUTHOR
Dave Cross <dave@dave.org.uk>
With lots of help from Leon Brocard <leon@astray.com>
SEE ALSO
perl(1).