Mike said:
In <
[email protected]>
That's cool. But I'm curious, why did you design prefix_pattern
to make also the first letter optional? My naive implementation
of prefix_pattern would have treated the first letter specially:
sub my_prefix_pattern {
my ($first, $rest) = split //, shift, 2;
$first . ($rest ? '(?:' . my_prefix_pattern($rest) . ')?' : '');
}
That's a possibility, though I tend to avoid recursion when it doesn't
have a clear advantage. Maybe it has, I haven't tried to rewrite it.
However, there's a general design principle that says a subroutine
should do one thing right, no more, no less. As a corollary, in a
well-written program every subroutine does almost nothing.
This
makes as sub easy to describe and to remember what it does, and it
makes it well suited as a building block, even if the expected usage
changes later.
When writing a sub to do X, there is often a temptation to say, I'll
never want X without Y in this program, so let's put Y in there, too.
It looks economical. However, I have often (and too often painfully)
reversed that kind of decision, so I tend to keep dealing with special
cases out of subroutines.
Taken a step further, I might even pull split( //, ...) out of the sub
and relegate it to the caller. Let the user provide a list of arbitrary
strings (which will be single characters in the actual calls).
sub prefix_pattern {
my $pat = ''
$pat = "(?:$_$pat)?" for reverse @_;
$pat;
}
(The sub name needs some thought now.)
After all, in the rare instances in which one wanted to treat even
the first letter as optional, one could still easily define $re as
How do you know they will always be rare? The empty string *is* a
legitimate prefix, after all. I often find, when I refine an ad-hoc
solution to a more systematic approach, the limiting and special cases
are dealt with quite differently than anticipated. Then it's good when
they aren't hard-soldered into the basic routines.
my $re = '(?:' . my_prefix_pattern($word) . ')?';
Yes, but you are fixing a result to fit the general case because it is
too special. It is better to fix the general result to fit the special
case.
All that said, in the concrete example the issue is minor. If you
*know* you'll never want the empty prefix to match, go ahead and
write a sub to that specification. I just took occasion to apply
the more general principle.
Anno