Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

(Revisiting) Smart match in p5

by Roy Johnson (Monsignor)
on Apr 04, 2005 at 20:03 UTC ( #444780=note: print w/replies, xml ) Need Help??


in reply to Smart match in p5

As an alternative to having hacked syntax, I've written up this little package that does the most useful (in my view) smart matches in a case-ish sort of call.
#!perl =pod =head1 NAME smatch - smart matching switch construct =head1 SYNOPSIS smatch $val => [ 1, sub { print "number 1" } ], [ 'a', sub { print 'string a' } ], [ [1,10], sub { print 'number in range' } ], # strings work, to +o [ @array, 42, sub { print 'number in list' } ], [ qr/\w+/, sub { print 'pattern' } ], [ \%hash, sub { print 'entry in hash' } ], [ \&sub, sub { print 'arg to sub' } ], [ (), sub { print 'default' } ] ;
Code and comments follow
=head1 NOTES C<smatch> aliases $_ to $val and evaluates its subsequent arguments in that context. Each subsequent argument should be an arrayref, whose last element is a coderef. The coderef will be executed if any other element yields a true value after being evaluated according to this table: Input ($in) is Example Operation =============== ============= ================================= Regex qr/foo|bar/ /$in/ Number 3.14 $_ == $in coderef sub { /foo/ } $in->($_) range specifier [100,1000] $in->[0] <= $_ and $_ <= $in->[1] (arrayref) hashref \%hash $in->{$_} any other scalar 'a string' $_ eq $in =cut use strict; use warnings; package Smatch; use Regexp::Common; sub in_range { my ($n, $lo, $hi) = @_; if ($n =~ /^RE{num}{real}$/ and $lo =~ /^$RE{num}{real}$/ and $hi =~ /^$RE{num}{real}$/) { $lo <= $hi or warnings::warnif(misc => 'Invalid range $lo .. $ +hi'); return ($lo <= $n and $n <= $hi); } else { $lo le $hi or warnings::warnif(misc => 'Invalid range $lo .. $ +hi'); return ($lo le $n and $n le $hi); } } sub smatch { local *_ = \$_[0]; CASES: for my $caselist (@_[1..$#_] ) { my $coderef = pop @$caselist; if (@$caselist) { for my $case (@$caselist) { if (my $reftype = ref $case) { $coderef->(), last CASES if ($reftype eq 'Regexp' and m{$case}) or ($reftype eq 'ARRAY' and in_range($_, @$case)) o +r ($reftype eq 'HASH' and $case->{$_}) or ($reftype eq 'CODE' and $case->($_)) or $case eq $_ ; } else { $coderef->(), last CASES if ($case =~ /^$RE{num}{real}$/ and /^$RE{num}{real +}/ and $case == $_) or $case eq $_ ; } } } else { $coderef->(); last; } } } package main; my @vals = (1, 10, 'foo1', 'bar', 'leftover'); for my $val (@vals) { no warnings 'exiting'; Smatch::smatch $val => [ 1, sub { print "$_ is 1\n" } ], [ [10, 20], sub { print "$_ hit me\n"; next } ], [ 'foo1', sub { print "$_ matched foo1\n"; next} ], [ { foo1=>1 }, sub { print "$_ found in hash\n" } ], [ qr/1/, sub { print "$_ got me, too?\n" } ], [ sub { s/bar/baz/ }, sub { print "$_ satisfied code\n" } ], [ (), sub { print "$_ fell to the default\n" } ] ; print "Done smatching $val\n"; }
Note that coderefs can alter the loop variables (bar gets changed to baz in my example. Also note that use of "next" triggers fallthrough (much like Switch.pm, on which this is based) but you'll want to turn off exiting warnings as I have done here.

Caution: Contents may have been coded under pressure.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://444780]
help
Chatterbox?
[Mr. Muskrat]: (considered) Re^3: Please help with Regexp::Common needs to be reparented to Re^2: Please help with Regexp::Common
[Mr. Muskrat]: Is it just me or does that timeout issue seems to be happening more often lately?
[Corion]: Mr. Muskrat: I'm not sure if it really happens more often, but I don't exactly know either
[LanX]: yep
[LanX]: more often for some weeks now
[Corion]: I think I'll have to manually (as god) intervene with that node, as the simple reparenting didn't seem to fix the parent/child relationship of the nodes
[Corion]: I think I have an idea but I'll have to open a ticket with Pair.com on that - hopefully I get to that on the weekend
LanX imagines a burning thorn bush
[Mr. Muskrat]: Thank you!
[Mr. Muskrat]: Oh that is odd. I got the message that it was reparented but yeah, it didn't actually do it. lol

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (11)
As of 2017-01-19 16:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you watch meteor showers?




    Results (170 votes). Check out past polls.