此子句无法匹配,因为前一个子句始终匹配

时间:2016-04-13 18:05:00

标签: elixir

不确定我为什么会收到此编译器警告。我在这里做错了什么?

defmodule T do
    def get_length do
        with {:ok, file} <- File.read("<file>"),
             content <- String.downcase(file) do
                IO.puts content
             end
    end
end

警告:此子句无法匹配,因为第4行的前一个子句始终匹配

2 个答案:

答案 0 :(得分:6)

TLDR:with这里有点矫枉过正。

defmodule T do
  def get_length do
    {:ok, file} = File.read("<file>") 
    IO.puts String.downcase(file)
  end
end

此外,您收到了编译器警告,因为content会有效地匹配String.downcase/1提供的任何内容。

详细模式:

我不认为你理解with的意图。 with是通过描述你关心的快乐路径上的模式匹配来链接一些粗糙嵌套的案例的糖。

所以不要像这样写一些令人发指的东西......

defp serve(socket) do
  msg =
    case read_line(socket) do
      {:ok, data} ->
        case KVServer.Command.parse(data) do
          {:ok, command} ->
            KVServer.Command.run(command)
          {:error, _} = err ->
            err
        end
      {:error, _} = err ->
        err
    end

  write_line(socket, msg)
  serve(socket)
end

......你可以写下这个可爱的魔法:

defp serve(socket) do
  msg =
    with {:ok, data} <- read_line(socket),
         {:ok, command} <- KVServer.Command.parse(data),
         do: KVServer.Command.run(command)

  write_line(socket, msg)
  serve(socket)
end

因此,为了好玩,让我们根据您的文件示例构建一个可以使用with的情况。

想象一下,这里定义的函数具有相当复杂的失败案例

defmodule X do
  def extract_header(file) do
    # returns {:ok, file} or {:err, file} or whatever
  end

  def starts_with_emoji?(file) do
    # returns true or false
  end
end

您可以看到with如何派上用场:

defmodule T do
  def header_emoji_alert do
    with {:ok, file} <- File.read("<file>"),
         {:ok, header} <- X.extract_header(file),
         true  <- X.starts_with_emoji?(header), do: IO.puts("EMOJI!!!!")
  end
end

答案 1 :(得分:3)

你真的有意这样做吗?

defmodule T do
   def get_length do
     with {:ok, file} <- File.read("<file>") do
       content = String.downcase(file) #Assigning result of String.downcase  will _always_ work.
       IO.puts content
     end
   end
 end

老实说,有点难以推断代码的意图。我的意思是这也会做同样的事情(据我所知)

defmodule T do
   def get_length do
     {:ok, file} = File.read("<file>") 
     content = String.downcase(file)
     IO.puts content
   end
 end

我的意思是说我不确定使用with在哪里获得任何东西。

在Erlang和Elixir中,如果你从File.read获得除{:ok, file}元组以外的任何东西,那么你将得到错误。如果您无法读取该文件,那么还没有真正的恢复选项吗?