Подтвердить что ты не робот

Регулярные выражения в случае эликсира

Можно ли использовать регулярное выражение внутри case в Elixir?

Итак, что-то вроде этого:

case some_string do
  "string"        -> # do something
  ~r/string[\d]+/ -> # do something
  _               -> # do something
end
4b9b3361

Ответ 1

С 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, а для регулярного выражения оно будет соответствовать заданному значению.

Ответ 2

Как сказал Патрик в своем ответе, для этого нет ничего встроенного, и 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