Switch::Perlish::Smatch - the 'smart' behind the matching in S::P
1.0.1 - Updated and cleaned up documentation.
use Switch::Perlish::Smatch 'smatch'; print 'yep' if smatch $foo => \@bar;
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 croaking if one isn't available.
croak
When talking about the subroutine that compares the two values in the document below it will referred to as a comparator
A comparator category holds all the comparators for a given type.
Some handy notation for referring to specific comparators is FOO<=>BAR, where FOO is the topic and BAR is the match (i.e the first and second arguments, respectively).
FOO<=>BAR
FOO
BAR
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 as smatch.
$topic
$match
smatch
The expected %hash looks like this:
%hash
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.g
$sub
$t_type
$m_type
my $foo = 'a string'; my $bar = [qw/ an array /]; smatch $foo, $bar;
In this case the $t_type is VALUE and the $m_type is ARRAY. If one were to override the default comparator for VALUE<=>ARRAY using register() then it would be done like this:
VALUE
ARRAY
VALUE<=>ARRAY
register()
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'.
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 existing OBJECT comparators a user-defined comparator would be used, with more desirable results. For more information see "Creating a new comparator" below.
switch
OBJECT
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.g
reversible
Switch::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 and VALUE<=>My::Obj comparators will be setup, where VALUE<=>My::Obj will behave exactly the same as My::Obj<=>VALUE.
My::Obj<=>VALUE
VALUE<=>My::Obj
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 as register_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.
$package
$prefix
_
$category
register_package()
$reversible
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.
$t_type<=>$m_type
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).
$Switch::Perlish::TOPIC
$Switch::Perlish::MATCH
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.
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
param()
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:
CGI<=>VALUE
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';
There are currently 8 default types, all of which have a complete set of comparators implemented. These 8 types are:
This type covers simple values which are just strings or numbers.
This covers any undefs.
undef
This covers all SCALAR references.
SCALAR
Covers arrays.
Covers hashes.
Covers coderefs i.e subroutines.
Covers any objects that don't have specific comparators.
Covers Regexp objects.
Regexp
For info on how each comparator works see. Switch::Perlish::Smatch::Comparators.
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 possibly IO) types.
GLOB
IO
Store the smatch result somewhere.
Allow for choice of which comparators are reversible in register_package().
Match::Smart
Data::Compare
Switch::Perlish
smatch (an alias to match)
match
value_cmp
Dan Brook <mr.daniel.brook@gmail.com>
<mr.daniel.brook@gmail.com>
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.
To install Switch::Perlish, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Switch::Perlish
CPAN shell
perl -MCPAN -e shell install Switch::Perlish
For more information on module installation, please visit the detailed CPAN module installation guide.