NAME
Switch::Perlish::Smatch - the 'smart' behind the matching in S::P
VERSION
1.0.1 - Updated and cleaned up documentation.
SYNOPSIS
use Switch::Perlish::Smatch 'smatch';
print 'yep'
if smatch $foo => \@bar;
DESCRIPTION
Given two values compare them in an intelligent fashion (i.e smart match) regardless of type. This is done by discerning the types of the values and delegating to the associated subroutine, or croak
ing if one isn't available.
Glossary
- comparators
-
When talking about the subroutine that compares the two values in the document below it will referred to as a comparator
- comparator category
-
A comparator category holds all the comparators for a given type.
- comparator notation
-
Some handy notation for referring to specific comparators is
FOO<=>BAR
, whereFOO
is the topic andBAR
is the match (i.e the first and second arguments, respectively).
METHODS
- match( $topic, $match )
-
Try to smart match the
$topic
against$match
by delegating to the appopriate comparator. It returns the result of the match per the comparator, but it can always be assumed that a successful match will evaluate to true and an unsuccessful one false. This can also be exported assmatch
. - register( %hash )
-
The expected
%hash
looks like this:topic => $t_type, match => $m_type, compare => $sub,
So
$sub
will be the registered comparator when the topic type is$t_type
and the matching value is of type$m_type
e.gmy $foo = 'a string'; my $bar = [qw/ an array /]; smatch $foo, $bar;
In this case the
$t_type
isVALUE
and the$m_type
isARRAY
. If one were to override the default comparator forVALUE<=>ARRAY
usingregister()
then it would be done like this:Switch::Perlish::Smatch->register( topic => 'VALUE', match => 'ARRAY', compare => sub { my($t, $m) = @_; return grep /$t/, @$m; }, );
If you run the code above you should get a warning noting that there is an existing comparator for that type combination. To suppress this and any other warnings from this module just add
no warnings 'Switch::Perlish::Smatch'
.This method is aimed at adding comparators for objects so they can be used seamlessly in
switch
calls. So instead of defaulting to the existingOBJECT
comparators a user-defined comparator would be used, with more desirable results. For more information see "Creating a new comparator" below.If your comparator is reversible, i.e the arguments can be reversed and the result will be the same, then you can pass in the
reversible
argument e.gSwitch::Perlish::Smatch->register( topic => 'My::Obj', match => 'ARRAY', compare => sub { my($t, $m) = @_; return $t->cmp( $m ); }, reversible => 1, );
So both the
My::Obj<=>VALUE
andVALUE<=>My::Obj
comparators will be setup, whereVALUE<=>My::Obj
will behave exactly the same asMy::Obj<=>VALUE
. - register_package( $package, $category[, $prefix, $reversible] );
-
Given the package name in
$package
, register all subroutines beginning with$prefix
(by default an underscore:_
) to the comparator category in$category
. This is how the standard comparator functions are registered. An empty$prefix
is disallowed asregister_package()
must be able to know which subroutines to register. If$reversible
is passed in and it evaluates to true then all comparators for this package will be reversible. - is_registered( $t_type[, $m_type] )
-
If one argument is provided, check if there is a comparator category for
$t_type
. If two arguments are provided then check if the comparator for$t_type<=>$m_type
has been registered. - dispatch( $t_type, $m_type[, $topic, $match] )
-
Dispatch to the comparator for
$t_type
and$m_type
, passing along$topic
and$match
(defaulting to$Switch::Perlish::TOPIC
and$Switch::Perlish::MATCH
, respectively).
Helper subroutines
- value_cmp($t, $m)
-
Given two simple values try to compare them in the most natural way i.e try to compare 2 numbers as numbers, 2 strings as strings and any other combination do a regexp match.
FURTHER INFO
Creating a new comparator
If we have a CGI object and want smart match it to something then we need to create a new comparator. This can be implemented in whatever way seems most appropriate, so for the sake of this module we will be testing for the existence of a simple value in param()
e.g
sub cgi_comparator {
my($cgi, $val) = @_;
return defined( $cgi->param($val) );
}
Now that we have our comparator for CGI<=>VALUE
(the above subroutine) and we know what we're comparing (a CGI object and a simple value) we can register it like this:
use Switch::Perlish::Smatch 'smatch';
Switch::Perlish::Smatch->register(
topic => 'CGI',
match => 'VALUE',
compare => \&cgi_comparator,
);
So we can now compare simple values with CGI objects e.g
my $q = CGI->new;
my $check = $ARGV[0];
printf "%s $check in params!\n",
smatch($q, $check) ? 'found' : 'not found';
The default types
There are currently 8 default types, all of which have a complete set of comparators implemented. These 8 types are:
- VALUE
-
This type covers simple values which are just strings or numbers.
- UNDEF
-
This covers any
undef
s. - SCALAR
-
This covers all
SCALAR
references. - ARRAY
-
Covers arrays.
- HASH
-
Covers hashes.
- CODE
-
Covers coderefs i.e subroutines.
- OBJECT
-
Covers any objects that don't have specific comparators.
- Regexp
-
Covers
Regexp
objects.
How comparators compare
For info on how each comparator works see. Switch::Perlish::Smatch::Comparators.
TODO
Add more helper subroutines for common operations default, and make them easier to access.
Move into own module if people find it sufficiently useful.
Add object functionality perhaps (but who wants that?).
Maybe add inheritable comparators.
Set __ANON__ to comparator name for debugging purposes.
Add support for
GLOB
(and possiblyIO
) types.Store the smatch result somewhere.
Allow for choice of which comparators are reversible in
register_package()
.
SEE. ALSO
EXPORT_OK
smatch
(an alias to match
)
value_cmp
AUTHOR
Dan Brook <mr.daniel.brook@gmail.com>
COPYRIGHT
Copyright (c) 2006, Dan Brook. All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.