Can you use a Regular Expression inside a case
in Elixir?
So something along the lines of this:
case some_string do
"string" -> # do something
~r/string[\d]+/ -> # do something
_ -> # do something
end
Can you use a Regular Expression inside a case
in Elixir?
So something along the lines of this:
case some_string do
"string" -> # do something
~r/string[\d]+/ -> # do something
_ -> # do something
end
With case
it is not possible, but you can use cond
:
cond do
some_string == "string" -> # do something
String.match?(some_string, ~r/string[\d]+/) -> # do something
true -> # do something
end
The reason is that there is no way to hook into the pattern matching by calling special functions for specific values. I guess you got the idea from Ruby, which implements this by defining the special operator ===
. This will be implicitly called by Ruby's case statement and for a regex it will match the given value.
As Patrick said in his answer, there is nothing built-in for this, and cond
is probably your best option.
But to add another option and to show off the flexibility of Elixir: Since case
is just a macro in Elixir, you could implement your own macro like regex_case
to do this.
You should keep in mind that this might make the code harder to understand for new people on the project, but if you do a lot of regex matching, maybe the trade-off could make sense. You be the judge.
I implemented this a while ago, just to see that it was possible:
defmodule RegexCase do
defmacro regex_case(string, do: lines) do
new_lines = Enum.map lines, fn ({:->, context, [[regex], result]}) ->
condition = quote do: String.match?(unquote(string), unquote(regex))
{:->, context, [[condition], result]}
end
# Base case if nothing matches; "cond" complains otherwise.
base_case = quote do: (true -> nil)
new_lines = new_lines ++ base_case
quote do
cond do
unquote(new_lines)
end
end
end
end
defmodule Run do
import RegexCase
def run do
regex_case "hello" do
~r/x/ -> IO.puts("matches x")
~r/e/ -> IO.puts("matches e")
~r/y/ -> IO.puts("matches y")
end
end
end
Run.run