Issue #19932 has been updated by jeremyevans0 (Jeremy Evans).
I don't think the documentation could be made significantly clearer, though
potentially it could benefit from an additional example. It's expected that the `o`
modifier works the way it does, and does not generate a new regexp with each call to the
`poc` method in your example.
There isn't a modifier that operates like `o`, but generates a new regexp for each
call to `poc`, but not a new regexp per iteration inside `poc`. Doing so would be hard to
reason about, because the `o` modifier changes how the code is compiled. What if the code
was changed to?:
```ruby
poc = lambda do |regexp|
hs = [
'azerty',
'azertyui',
'azertyuiop'
]
out = []
hs.each do |h|
out << h if /#{regexp}/o.match?('azerty')
end
out
end
```
Should that still generate a new regexp per call to `poc`? Remember that `lambda` is not a
keyword, it is a normal method call, so you can redefine it to use `define_method`, or to
be the same as `Array#each`.
For your example, for what you want, you should create a literal regexp without `o`
modifier before the loop, set that to a local variable, and use that local variable inside
the loop.
----------------------------------------
Bug #19932: Regexp o modifier freeze interpolation between method calls
https://bugs.ruby-lang.org/issues/19932#change-104958
* Author: noraj-acceis (Alexandre ZANNI)
* Status: Closed
* Priority: Normal
* ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
Taken the following PoC:
```ruby
def poc(regexp)
hs = [
'azerty',
'azertyui',
'azertyuiop'
]
out = []
hs.each do |h|
out << h if /#{regexp}/.match?('azerty')
end
out
end
p poc('az')
p poc('wxc')
```
I have the following output:
```ruby
["azerty", "azertyui", "azertyuiop"]
[]
```
Now because the regexp never change inside the method once set I could add the `o`
modifier so that `#{}` interpolation is computed only once.
So the PoC becomes:
```ruby
def poc(regexp)
hs = [
'azerty',
'azertyui',
'azertyuiop'
]
out = []
hs.each do |h|
out << h if /#{regexp}/o.match?('azerty')
end
out
end
p poc('az')
p poc('wxc')
```
Output:
```
["azerty", "azertyui", "azertyuiop"]
["azerty", "azertyui", "azertyuiop"]
```
So each future call to the method will be equals to the result of the first call because
the regexp is "frozen".
I was expecting the regexp to be "frozen" only for the current call in an effort
of performance but instead it's "frozen" for future calls too.
Another example of usage of `o` modifier here:
https://learnbyexample.github.io/Ruby_Regexp/modifiers.html#o-modifier
So is that a side effect or is that the expected behavior?
--
https://bugs.ruby-lang.org/