in reply to Precompiling qr/.../o question

The purpose of the o modifier was to speed up dynamically built regexps. The downside is that it creates hard to find bugs since any change to the regexp gets ignored. qr// was introduced as an alternative to the o modifier. There isn't any reason to use the o modifier any more.

If all you want to do is avoid having $re compiled for every @b element, you don't need the o modifier:

my $re=qr/...$xxx..../; @a = grep { /$re/ } @b

There are checks in place to avoid recompiling a regexp is the interpolated variables haven't changed, so the following also does what you want:

@a = grep { /...$xxx.../ } @b

If you want the o behaviour:

my $re; ... { $re ||= qr/.../; ... }

If you want a cache:

my %re_cache; ... { my $re = $re_cache{$key} ||= qr/.../; ... }

Replies are listed 'Best First'.
Re^2: Precompiling qr/.../o question
by ikegami (Patriarch) on Apr 08, 2008 at 04:43 UTC

    Just to add a bit, a common performance pitfall is

    @regexps = qw( foo bar baz ); @strings = qw( abc def ghi ); for $string (@strings) { for $regexp (@regexps) { $string =~ /$regexp/ } }

    Each regexp is compiled for each element in @strings.

    >perl -Mre=debug -e"@regexps = qw( foo bar baz ); @strings = qw( abc d +ef ghi ); for $string (@strings) { for $regexp (@regexps) { $string = +~ /$regexp/ } }" 2>&1 | find "Compiling" Compiling REx `foo' Compiling REx `bar' Compiling REx `baz' Compiling REx `foo' Compiling REx `bar' Compiling REx `baz' Compiling REx `foo' Compiling REx `bar' Compiling REx `baz'

    Solution 1: Put the regexp loop on the outside:

    @regexps = qw( foo bar baz ); @strings = qw( abc def ghi ); for $regexp (@regexps) { # All I did was reverse for $string (@strings) { # these two lines. $string =~ /$regexp/ } }
    >perl -Mre=debug -e"@regexps = qw( foo bar baz ); @strings = qw( abc d +ef ghi ); for $regexp (@regexps) { for $string (@strings) { $string = +~ /$regexp/ } }" 2>&1 | find "Compiling" Compiling REx `foo' Compiling REx `bar' Compiling REx `baz'

    Solution 2: Precompile the regexps:

    @regexps = map qr/$_/, qw( foo bar baz ); # All I did was add the qr +//. @strings = qw( abc def ghi ); for $string (@strings) { for $regexp (@regexps) { $string =~ /$regexp/ } }
    >perl -Mre=debug -e"@regexps = map qr/$_/, qw( foo bar baz ); @strings + = qw( abc def ghi ); for $string (@strings) { for $regexp (@regexps) + { $string =~ /$regexp/ } }" 2>&1 | find "Compiling" Compiling REx `foo' Compiling REx `bar' Compiling REx `baz'