How can I delay variable interpolation in a regex to the point of use?
perl, regex
Solution
I think if you wrap each regular expression in anonymous sub, you can do this sort of deferral:
my ($var1, $var2, $var3);
my @search_regexes=(
sub { return qr/foo $var1/ },
sub { return qr/foo bar $var2/ },
sub { return qr/foo bar baz $var3/ },
);
Then when you are going to evaluate them you just 'call' the anonymous sub:
($var1, $var2, $var3) = qw(thunk this code);
if( $_ =~ $search_regexes[0]->() ) {
# Do something
}
I know in Scheme this is called thunking I am not sure if it has a name in Perl. You can do something similar in Ruby with Proc objects
Problem
For example, let's imagine that I have a set of variables and an array of regexes that interpolate those variables: ``` my ($var1, $var2, $var3); my @search_regexes=( qr/foo $var1/, qr/foo bar $var2/, qr/foo bar baz $var3/, ); ``` The above code will give us warnings telling us that `$var1`, `$var2` and `$var3` are not defined at the point of regex compilation for the regexes in `$search_regexes`. However, I want to delay variable interpolation in those regexes until the point they are actually used (or later (re)compiled once the variables have values): ``` # Later on we assign a value to $var1 and search for the first regex in $_ ... $var1='Hello'; if (/$search_regexes[0]/) { # Do something ... } ``` How would I go about restructuring the construct in the initial code sample to allow for this? As a bonus, I would like to compile each regex after a value is assigned to the respective variable(s) appearing in that regex in the same way that the `qr//` operator is doing now (but too early). If you can show how to further extend the solution to allow for this, I would greatly appreciate it. Update: I have settled on a variant of Hunter's approach, because using it I don't take a performance hit and there are minimal changes to my existing code. Other answers also taught me quite a bit about alternative solutions to this problem and their performance implications when very many lines need to be matched. My code now resembles the following: ``` my ($var1, $var2, $var3); my @search_regexes=( sub {qr/foo $var1/}, sub {qr/foo bar $var2/}, sub {qr/foo bar baz $var3/}, ); ... ($var1,$var2,$var3)=qw(Hello there Mr); my $search_regex=$search_regexes[$based_on_something]->(); while (<>) { if (/$search_regex/) { # Do something ... # and sometimes change $search_regex to be another from the array } } ``` This gets me what I was looking for with minimal changes to my code (i.e., just the addition of subs to the array up top) and no performance hit per regex usage.