如何在Elixir中使用“with”关键字和它是什么?

在elixir 1.2中,他们已经包含了关键字“with”,但是这并不完全清楚它的用途。

我将如何以及在何种情况下使用它?

在1.2版之前的Elixir版本中,当使用pipe道中的函数时,要么使用monad库,要么嵌套case语句(可以使用私有函数重构,但仍然是冗长的)。 与/ 1允许以不同的方式来解决这个问题。

以下是原始提案的一个例子:

case File.read(path) do {:ok, binary} -> case :beam_lib.chunks(binary, :abstract_code) do {:ok, data} -> {:ok, wrap(data)} error -> error end error -> error end 

下面是使用函数重构的相同的东西:

 path |> File.read() |> read_chunks() |> wrap() defp read_chunks({:ok, binary}) do {:ok, :beam_lib.chunks(binary, :abstract_code)} end defp read_chunks(error), do: error defp wrap({:ok, data}) do {:ok, wrap(data)} end defp wrap(error), do: error 

和相同的代码使用:

 with {:ok, binary} <- File.read(path), {:ok, data} <- :beam_lib.chunks(binary, :abstract_code), do: {:ok, wrap(data)} 

这是有效的,因为如果值与左边的模式匹配with将只保持链接。 如果不是那么链将被中止,并返回第一个不匹配的结果。 例如,如果文件不存在,则File.read(path)将返回{:error, :enoent} – 这不匹配{:ok, binary}所以with/1调用将返回{:error, :enoent}.

值得注意的是,可以使用任何模式,不只是{:ok, foo}{:error, reason} (尽pipe这是一个非常常见的用例)。

您也可以链接“裸露的表情”,正如文档所述:

 with {:ok, binary} <- File.read(path), header = parse_header(binary), {:ok, data} <- :beam_lib.chunks(header, :abstract_code), do: {:ok, wrap(data)} 

variablesheader只能在with语句中使用。 更多信息在https://gist.github.com/josevalim/8130b19eb62706e1ab37