Skip to content

Commit cf454cd

Browse files
authored
Add Regex.import/1 (#14910)
1 parent f12ff1d commit cf454cd

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

lib/elixir/lib/regex.ex

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ defmodule Regex do
102102
(the previous `r` option is deprecated in favor of `U`)
103103
104104
* `:export` (E) (since Elixir 1.19.3) - uses an exported pattern
105-
which can be shared across nodes or through config, at the cost of a runtime
106-
overhead every time to re-import it every time it is executed.
105+
which can be shared across nodes or passed through config, at the cost of a runtime
106+
overhead to re-import it every time it is executed.
107107
This modifier only has an effect starting on Erlang/OTP 28, and it is ignored
108108
on older versions (i.e. `~r/foo/E == ~r/foo/`). This is because patterns cannot
109109
and do not need to be exported in order to be shared in these versions.
@@ -275,6 +275,35 @@ defmodule Regex do
275275
regex
276276
end
277277

278+
@doc """
279+
Imports a `regex` that has been exported, otherwise returns the `regex` unchanged.
280+
281+
This means it will lose the ability to be sent across nodes or passed through config,
282+
but will be faster since it won't need to be imported on the fly every time it is executed.
283+
284+
Exported regexes only exist on OTP 28, so this has no effect on older versions.
285+
286+
## Examples
287+
288+
Regex.import(~r/foo/E)
289+
~r/foo/
290+
291+
Regex.import(~r/foo/)
292+
~r/foo/
293+
294+
"""
295+
@doc since: "1.20.0"
296+
@spec import(t) :: t
297+
def import(%Regex{re_pattern: re_pattern} = regex) do
298+
case re_pattern do
299+
{:re_exported_pattern, _, _, _, _} ->
300+
%{regex | re_pattern: :re.import(re_pattern), opts: regex.opts -- [:export]}
301+
302+
_ ->
303+
regex
304+
end
305+
end
306+
278307
@doc """
279308
Returns the version of the underlying Regex engine.
280309
"""

lib/elixir/test/elixir/regex_test.exs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,18 @@ defmodule RegexTest do
132132
end
133133
end
134134

135+
test "import/1" do
136+
# no-op for non-exported regexes
137+
regex = ~r/foo/
138+
assert Regex.import(regex) == regex
139+
140+
imported = Regex.import(~r/foo/E)
141+
142+
assert imported.opts == []
143+
assert "foo" =~ imported
144+
assert {:re_pattern, _, _, _, _} = imported.re_pattern
145+
end
146+
135147
test "opts/1" do
136148
assert Regex.opts(Regex.compile!("foo", "i")) == [:caseless]
137149
assert Regex.opts(Regex.compile!("foo", [:ucp])) == [:ucp]

0 commit comments

Comments
 (0)