This is one of the features that Ruby cribbed directly from Perl. The Ruby documentation seems really bad, in particular “interpolation mode” is grievously misleading.
Perl’s documentation is far more clear about the consequences:
o Compile pattern only once.
[…]
PATTERN may contain variables, which will be
interpolated every time the pattern search is
evaluated, except for when the delimiter is a
single quote. […] Perl will not recompile the
pattern unless an interpolated variable that
it contains changes. You can force Perl to skip
the test and never recompile by adding a /o
(which stands for "once") after the trailing
delimiter. Once upon a time, Perl would recompile
regular expressions unnecessarily, and this
modifier was useful to tell it not to do so,
in the interests of speed. But now, the only
reasons to use /o are one of:
[reasons]
The bottom line is that using /o is almost
never a good idea.
In the days before Perl automatically memoized the compilation of regexes with interpolation, even back in the 1990s, it said,
However, mentioning /o constitutes a promise
that you won't change the variables in the
pattern. If you change them, Perl won't even
notice.
PATTERN may contain references to scalar
variables, which will be interpolated
(and the pattern recompiled) every time the
pattern search is evaluated. […] If you want
such a pattern to be compiled only once, add
an “o” after the trailing delimiter. This
avoids expensive run-time recompilations, and
is useful when the value you are interpolating
won't change over the life of the script.
riffraff · 1h ago
Unsurprisingly, `END {}` is also inherited from perl, tho I think it originally comes from awk.
In the spirit of "what's old is new again," PowerShell also has the same idea, and is done per Function with "begin", "process", "end", and "clean" stanzas that allow setup, teardown, for-each-item, and "finally" behavior: https://learn.microsoft.com/en-us/powershell/module/microsof...
cbsmith · 1h ago
As an old Perl programmer, I knew immediately what the /o would do. ;-)
Amorymeltzer · 12m ago
I've always loved the recent[1] summary from `perlre`:
>o - pretend to optimize your code, but actually introduce bugs
This is the same problem people have with closures, where it's unclear to the user whether the argument is captured by name or by value.
layer8 · 22m ago
This isn't the same problem, because this is about whether the regex is instantiated each time the code around the regex is executed, or only the first time and cached for subsequent executions. The same could in theory happen with closures, but I haven't ever seen programming-language semantics where, for example, a function containing the definition of a closure that depends on an argument of that outer function, would use the argument value of the first invocation of the function for all subsequent invocations of the function.
For example, when you have
fn f x = (y -> x + y)
then a sequence of invocations of f
f 1 3
f 2 6
will yield 4 and 8 respectively, but never will the second invocation yield 7 due to reusing the value of x from the first invocation. However, that is precisely what happens in the article's regex example, because the equivalent is for the closure value (y -> x + y) to be cached between invocations, so that the x retains the value of the first invocation of f — regardless of whether x is a reference by name or by value.
zer00eyz · 43m ago
Im sorry but the classics never go out of style:
"Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems."
jodrellblank · 2m ago
The second problem being how to deal with all the extra time they just freed up?
stavros · 11m ago
Yeah but it's kind of tired when it's being used every time someone makes a mistake with regex. I've used them extensively in my career and never once regretted it.
Perl’s documentation is far more clear about the consequences:
(https://perldoc.perl.org/perlop#Regexp-Quote-Like-Operators)
In the days before Perl automatically memoized the compilation of regexes with interpolation, even back in the 1990s, it said, Perl 4’s documentation is briefer. It says,(https://github.com/Perl/perl5/blob/perl-4.0.00/perl.man#L272...)
In the spirit of "what's old is new again," PowerShell also has the same idea, and is done per Function with "begin", "process", "end", and "clean" stanzas that allow setup, teardown, for-each-item, and "finally" behavior: https://learn.microsoft.com/en-us/powershell/module/microsof...
>o - pretend to optimize your code, but actually introduce bugs
1: I still think of it as a relatively new change, but it's from 2013: <https://github.com/Perl/perl5/commit/7cf040c1f649790a4040aec...>
For example, when you have
then a sequence of invocations of f will yield 4 and 8 respectively, but never will the second invocation yield 7 due to reusing the value of x from the first invocation. However, that is precisely what happens in the article's regex example, because the equivalent is for the closure value (y -> x + y) to be cached between invocations, so that the x retains the value of the first invocation of f — regardless of whether x is a reference by name or by value."Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems."