Можно ли использовать регулярное выражение внутри case
в Elixir?
Итак, что-то вроде этого:
case some_string do
"string" -> # do something
~r/string[\d]+/ -> # do something
_ -> # do something
end
Можно ли использовать регулярное выражение внутри case
в Elixir?
Итак, что-то вроде этого:
case some_string do
"string" -> # do something
~r/string[\d]+/ -> # do something
_ -> # do something
end
С case
это невозможно, но вы можете использовать cond
:
cond do
some_string == "string" -> # do something
String.match?(some_string, ~r/string[\d]+/) -> # do something
true -> # do something
end
Причина в том, что нет способа подключиться к сопоставлению шаблонов, вызывая специальные функции для определенных значений. Думаю, у вас есть идея от Ruby, которая реализует это, определяя специальный оператор ===
. Это будет неявно вызвано оператором case Ruby, а для регулярного выражения оно будет соответствовать заданному значению.
Как сказал Патрик в своем ответе, для этого нет ничего встроенного, и cond
, вероятно, ваш лучший вариант.
Но добавить еще один вариант и продемонстрировать гибкость Elixir: Поскольку case
- это просто макрос в Elixir, вы можете реализовать свой собственный макрос, например regex_case
, чтобы сделать это.
Вы должны помнить, что это может сделать код более сложным для понимания для новых людей в проекте, но если вы выполняете много регулярных выражений, возможно, компромисс может иметь смысл. Вы будете судьей.
I реализовал это некоторое время назад, просто чтобы увидеть, что это возможно:
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