(Revisiting) Smart match in p5
by Roy Johnson (Monsignor) on Apr 04, 2005 at 20:03 UTC
|
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
Caution: Contents may have been coded under pressure.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Smart match in p5
by Juerd (Abbot) on Mar 14, 2005 at 07:52 UTC
|
xmath++
I'll start working on SmartMatch.pm when I have the time, which should be this week.
| [reply] [Watch: Dir/Any] |
Re: Smart match in p5
by demerphq (Chancellor) on Mar 14, 2005 at 09:35 UTC
|
Wouldnt it be better if your patch was against blead and not maint and that you submit it to p5p for review?
| [reply] [Watch: Dir/Any] |
|
Wouldnt it be better if your patch was against blead and not maint and that you submit it to p5p for review?
Perhaps. However, I'd like to have a more complete implementation (i.e. one with SmartMatch.pm itself) before sending things over to p5p. I want to avoid discussion of practical problems that simply aren't there, and the only way to do that is to prove it can work before suggesting its inclusion. The advance work usually consumes less time than the discussion avoided by it. Also, I don't care much for the final implementation, and see what we're doing now as a proof of concept (that can very well be implemented without much change, if people like it).
I haven't needed switch/case or given/when myself. But many, many people would prefer it over if/elsif/else structures.
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] [d/l] |
|
|
|
| [reply] [Watch: Dir/Any] |
|
|
|
|
|
|
|
| [reply] [Watch: Dir/Any] |
|
A reply falls below the community's threshold of quality. You may see it by logging in.
|
Re: Smart match in p5
by halley (Prior) on Mar 14, 2005 at 13:52 UTC
|
I read Juerd's request. I read the summary of smart matching you linked. I'd like to think I'm not dense, but I don't get what this operator is supposed to do, or why it's better than the various operators that exist?
Maybe it's because I watched The Fifth Element this weekend, but I read the ~~ as that annoying 'bzzzZZz!' noise which the superstar personality did whenever he wanted other people to divine his vague intentions and to get lost.
I know Perl is supposed to have lots of DWIM, but another programmer should be able to understand WIM too.
-- [ e d @ h a l l e y . c c ]
| [reply] [Watch: Dir/Any] [d/l] |
|
Blatent-plug: As brian d foy commented in his review, Perl 6 Now: The Core Ideas Illustrated with Perl 5 has a whole chapter on Switch and smart matching. Sadly it came out before xmath's amazing hack, but there are a few examples in there where smart matching saves a lot of typing and makes code a lot more clear. (Thankfully, there are 22 other chapters - as cool as smart matching is, vector operations and coroutines are much cooler, IMO). So go fork over your cash right a away - I worked harder for your cash than you did ;)
-scott
| [reply] [Watch: Dir/Any] |
|
I don't get what this operator is supposed to do, or why it's better than the various operators that exist?
It's one operator to compare anything to anything. It's eq, ==, grep, exists, all in one. That's useful if you want to pass a condition to be applied to a general function. Normally, you'd supply a coderef, but now, you can just supply any value it can be smart matched to. And the great thing is, that you can still pass that coderef.
The "when" operator implicitly smart-matches against $_.
given ($address) {
when (@whitelist) { $score -= 30 }
when (@blacklist) { $score += 50 }
when (/example\.com$/) { $score = 0 }
default { ... }
}
The smart match operator, in this example invisible because it's used by when internally, avoids a lot of typing. Compare the alternative:
for my $a ($address) {
if (grep $_ eq $a, @whitelist) { $score -= 30; last; }
if (grep $_ eq $a, @blacklist) { $score += 50; last; }
if ($a =~ /example\.com$/) { $score = 0; last; }
...
}
Smart match replaces grep and =~ here. But it can also replace eq and == and exists, making it a great tool for making code easier to read, especially when implied with given/when.
PS The default block { } around ... isn't needed, but it's good documentation. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
I know that idiom plays a large part of understanding a language, but I feel like neither of those examples are particularly self-documenting or literate.
Saying "Given X, when A, B, C, do T" does not roll off the tongue. It doesn't express any particular relationship between X and the list. It doesn't help me understand what the when operator does. Are we iterating? Triggering? You said "smart matching," but uh, that still leaves my uninitiated brain lost. Also, "when" connotates time or passive reaction to me, not compliance or active processing.
"Given X, if it matches any of A, B, C, do T" is a step up. Going from a complicated concept of "does whatever you want" to a more specific concept of "performs this particular comparison" is a shift toward self-documentary or literate programming.
As you can see, I am very dubious of the value of Perl6, and this sort of divergence from pragmatic programming to ethereal ivory-tower philosophizing just doesn't get me any closer to enjoying the changes in the language. The language should express generic problem-solving succinctly, but not so tersely it cannot be understood concretely.
-- [ e d @ h a l l e y . c c ]
| [reply] [Watch: Dir/Any] [d/l] |
|