Using Eval for Efficiency
Here are some examples where run-time evaluation can greatly speed up execution.
A Fast Multipattern grep
Consider a grep-like Perl script that can search for any number of patterns and print out only those lines that match all the given patterns (the order of the patterns being unimportant). You might structure the code like this:
while ($s = <>) { $all_matched = 1; # start by assuming all patterns match $s foreach $pat (@patterns) { if ($s !~ /$pat/) { $all_matched = 0; # No, our assumption was wrong last; } } print $s if $all_matched; }
The problem with this code is that the regular expression
(/$pat/
) is compiled afresh for every line and for
every pattern. That is, if you have, say, 10,000 lines in the text to
be searched, and three patterns to search for,
a.*b
, [0-9]
, and
[^def]
, the patterns will be compiled 30,000
times. The /o
flag, which tells Perl to compile
the regular expression, cannot be used here because
$pat
can vary as the program executes.
The fastest approach would be to hardcode the patterns as shown next. Unfortunately, it is also the least reusable approach.
while ($s = <> ) { if ( ($s =~ /a.*b/) && ($s =~ /[0-9]$/) && ($s =~ /[^def]/)) { print $s; } }
The good news is that it is possible to get this level of efficiency
without losing generality. The idea is to hand-craft the
“hard-wired” code above at run-time and then to
eval
it.
The strings constituting the code to be generated are shown in bold in Example 5.2.
Example 5-2. Compiling ...
Get Advanced Perl Programming now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.