Elixir案例中的正则表达式

时间:2016-01-07 07:14:17

标签: regex elixir

你可以在Elixir的case内使用正则表达式吗?

就像这样:

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

2 个答案:

答案 0 :(得分:36)

使用case是不可能的,但您可以使用cond

cond do
  some_string == "string"                     -> # do something
  String.match?(some_string, ~r/string[\d]+/) -> # do something
  true                                        -> # do something
end

原因是没有办法通过调用特定值的特殊函数来挂钩模式匹配。我猜你从Ruby那里得到了这个想法,它通过定义特殊运算符===来实现这一点。这将由Ruby的case语句隐式调用,对于正则表达式,它将匹配给定的值。

答案 1 :(得分:23)

帕特里克在回答中说,没有任何内置的内容,cond可能是你最好的选择。

但要添加其他选项并展示Elixir的灵活性:由于case只是Elixir中的一个宏,因此您可以实现自己的宏regex_case来执行此操作。

你应该记住,这可能会使代码更难理解项目中的新人,但如果你做了很多正则表达式匹配,也许权衡可能是有意义的。你是法官。

我前一段时间implemented this,只是为了看到它是可能的:

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