This solution depends on two factors, how many times does the code run and how much do the length of the strings vary? If the answers are "a lot" and "not much" then here's a faster solution:
{
my @cache; # a cache of substring-finding subs
sub substrings {
my $string = shift;
my $length = length $string;
# use cached sub if we have one
return $cache[$length]->($string)
if exists $cache[$length];
# create sub to find substrings for this length
my $sub = 'sub { $_ = shift; return (';
foreach my $length (1..length($string)) {
foreach my $offset (0..length($string)-$length) {
$sub .= "substr(\$_,$offset,$length),";
}
}
$sub .= ")};";
$cache[$length] = eval $sub;
# and use it
return $cache[$length]->($string);
}
}
Using Benchmark.pm and a test case against random words from /usr/dict/words I found this to be 300% faster over 100,000 iterations. Not bad, but I bet we could do better!
-sam
PS: Has anyone noticed that <code> doesn't deal with hard tabs right? Copy-and-paste from Emacs is unpleasant.