如何在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