Gaz*_*ler 70
在1.2之前的Elixir版本中,当在管道中使用函数时,您将不得不使用monad库或嵌套case语句(可以使用私有函数重构,但最终仍然是冗长的).with/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
Run Code Online (Sandbox Code Playgroud)
以下是使用函数重构的相同内容:
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
Run Code Online (Sandbox Code Playgroud)
使用相同的代码with:
with {:ok, binary} <- File.read(path),
{:ok, data} <- :beam_lib.chunks(binary, :abstract_code),
do: {:ok, wrap(data)}
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为with只有当值与左侧的模式匹配时才会保持链接.如果不是,则中止链并返回第一个不匹配的结果.例如,如果文件不存在则File.read(path)返回{:error, :enoent}- 这不匹配,{:ok, binary}因此with/1调用将返回{:error, :enoent}.
值得注意的是,与可以用任何方式来使用,而不仅仅是{:ok, foo}和{:error, reason}(虽然它是一个很常见的情况).
小智 17
您还可以链接"裸表达式",正如文档所说:
with {:ok, binary} <- File.read(path),
header = parse_header(binary),
{:ok, data} <- :beam_lib.chunks(header, :abstract_code),
do: {:ok, wrap(data)}
Run Code Online (Sandbox Code Playgroud)
该变量header仅在with语句中可用.更多信息,请访问https://gist.github.com/josevalim/8130b19eb62706e1ab37
| 归档时间: |
|
| 查看次数: |
8165 次 |
| 最近记录: |