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 croaking 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, where FOO is the topic and BAR 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 as smatch.

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.g

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:

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 existing OBJECT 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.g

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.

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

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 undefs.

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 possibly IO) types.

  • Store the smatch result somewhere.

  • Allow for choice of which comparators are reversible in register_package().

SEE. ALSO

Match::Smart

Data::Compare

Switch::Perlish

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.