The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Match::Smart - best-guess matching of two scalars

SYNOPSIS

   use Match::Smart qw/ smart_match /;

   if (smart_match( $user, qr/^dan/ )) {
      print "You might be a dan\n";
   }

   if (smart_match( $amount, sub { $_[0] < 10} )) {
      print "$amount is less than 10\n";
   }

DESCRIPTION

Match::Smart provides a easy means of testing whether two scalars match. A best guess on how they should be compared is made, based on the types of the two scalars.

The means of matching is based heavily on the Apocalypse 4, Perl 6 document by Larry Wall.

EXPORT

Nothing is exported by default. The smart_match() subroutine can be exported if desired.

FUNCTIONS

smart_match($val1, $val2)

Attempts to do the right thing in matching the two given values. Returns true if the two values match, false otherwise.

If both values are references, referring to the same thing, they are assumed to match.

The table below describes how the comparisons are performed. Those described using grep only do so for conciseness. The implementation uses for loops to allow short-circuiting as soon as a match is determined.

The order in which the values are passed to smart_match() only affects the return value when comparing two CODE references. Therefore, the table below only shows half of the necessary comparisons (those missing can be inferred).

Those noted as '-' are not currently defined and will result in fatal run-time exceptions.

   $val1    $val2    true if ...
   =====    =====    ===========

   ARRAY    ARRAY    any in @{$val1} smart_match any in @{$val2}
   ARRAY    CODE     $val2->(@{$val1})
   ARRAY    HASH     grep { $val2->{$_} } @{$val1}
   ARRAY    NUMBER   $val1->[$val2]
   ARRAY    OBJECT   grep { smart_match($_, $val2)    } @{$val1}
   ARRAY    REF      grep { smart_match($_, ${$val2}) } @{$val1}
   ARRAY    REGEXP   grep { smart_match($_, $val2)    } @{$val1}
   ARRAY    SCALAR   grep { smart_match($_, ${$val2}) } @{$val1}
   ARRAY    STRING   grep { smart_match($_, $val2)    } @{$val1}
   ARRAY    UNDEF    grep { smart_match($_, $val2)    } @{$val1}

   CODE     CODE     $val1->(&{$val2})
   CODE     HASH     $val1->(%{$val2})
   CODE     NUMBER   $val1->($val2)
   CODE     OBJECT   $val1->($val2)
   CODE     REF      smart_match($val1, ${$val2})
   CODE     REGEXP   $val1->($val2)
   CODE     SCALAR   smart_match($val1, ${$val2})
   CODE     STRING   $val1->($val2)
   CODE     UNDEF    $val1->($val2)

   HASH     HASH     grep { exists $val1->{$_} } keys %{$val2}
   HASH     NUMBER   $val1->{$val2}
   HASH     OBJECT   -
   HASH     REF      smart_match($val1, ${$val2})
   HASH     REGEXP   grep { $_ =~ $val2 } keys %{$val1}
   HASH     SCALAR   smart_match($val1, ${$val2})
   HASH     STRING   $val1->{$val2}
   HASH     UNDEF    -

   NUMBER   NUMBER   $val1 == $val2
   NUMBER   OBJECT   -
   NUMBER   REF      smart_match($val1, ${$val2})
   NUMBER   REGEXP   $val1 =~ $val2
   NUMBER   SCALAR   smart_match($val1, ${$val2})
   NUMBER   STRING   $val1 == $val2
   NUMBER   UNDEF    ** ALWAYS FALSE **

   OBJECT   OBJECT   $val1 == $val2
   OBJECT   REF      smart_match($val1, ${$val2})
   OBJECT   REGEXP   -
   OBJECT   SCALAR   smart_match($val1, ${$val2})
   OBJECT   STRING   $val1->can($val2) && $val1->$val2
   OBJECT   UNDEF    ** ALWAYS FALSE **

   REF      REF      smart_match(${$val1}, ${$val2})
   REF      REGEXP   smart_match(${$val1}, $val2)
   REF      SCALAR   smart_match(${$val1}, ${$val2})
   REF      STRING   smart_match(${$val1}, $val2)
   REF      UNDEF    smart_match(${$val1}, $val2)

   REGEXP   REGEXP   $val1 eq $val2
   REGEXP   SCALAR   smart_match($val1, ${$val2})
   REGEXP   STRING   $val2 =~ $val1
   REGEXP   UNDEF    ** ALWAYS FALSE **

   SCALAR   SCALAR   smart_match(${$val1}, ${$val2})
   SCALAR   STRING   smart_match(${$val1}, $val2)
   SCALAR   UNDEF    smart_match(${$val1}, $val2)

   STRING   STRING   $val1 eq $val2
   STRING   UNDEF    ** ALWAYS FALSE **

   UNDEF    UNDEF    ** ALWAYS TRUE **

TO DO

- handle GLOB and LVALUE ref types
- provide a means of registering comparisons for specific Object types (call Class->smart_match() method to get class to fill in requirements)
- allow the comparison methods to be overridden

SEE ALSO

Apocalypse 4: http://www.perl.com/pub/a/2002/01/15/apo4.html?page=2

AUTHOR

Daniel B. Boorstein, <danboo@cpan.org>

COPYRIGHT AND LICENSE

Copyright 2004 by Daniel B. Boorstein

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.