Credence.Pattern.PreferRegexMatch
(credence v0.7.0)
Copy Markdown
Rewrites a case over Regex.run/2 that only tests whether the regex
matched — never the captured groups — into the idiomatic boolean form built
on Regex.match?/2.
Bad
case Regex.run(~r/ab{3,}/, string) do
[_ | _] -> "Found a match!"
_ -> "Not matched!"
endGood
if Regex.match?(~r/ab{3,}/, string) do
"Found a match!"
else
"Not matched!"
endScope (the safe core)
Regex.run(re, str) (default :capture) returns nil on no match and a
non-empty list (the whole match is always element 0) on a match. So the
pattern [_ | _] matches exactly the "matched" case and nil/_ the
"no match" case — which is precisely what Regex.match?/2 decides. The fix
fires only when ALL of these hold:
- The scrutinee is
Regex.run(re, str)with exactly two arguments. - There are exactly two clauses, neither guarded.
One clause pattern is
[_ | _](wildcard head and tail — binds nothing).- The other clause pattern is
nilor_.
converting to anWhen the other clause is the catch-all _, the `[__]` clause comes first (otherwise _shadows it and the `[__]` body is dead code — ifwould change the result). When the other clause isnilthe two patterns are disjoint, so either order is safe.
The [_ | _] body becomes the do branch and the nil/_ body the else
branch, regardless of source order.
Does NOT fire (deliberately dropped — not provably behaviour-preserving)
Regex.run/3with options.capture: :none(and:all_but_firstwith no subpatterns) returns[]on a match, which[_ | _]does not match — the two forms disagree, so any 3-argument call is skipped.A bound head (
[match | _]) — the body reads the capture, whichRegex.match?/2does not provide.- More than two clauses, or specific-capture patterns (
["x"],[_, a, b],[]) — these inspect the captures, not mere existence. - A single clause, or a second clause that does not cover
nil— the original raisesCaseClauseErroron a no-match where anifwould not. - A named catch-all (
other ->) — its body may read the boundnil. - Guarded clauses.