在书"编程Elixir"戴夫托马斯展示了一个例子
handle_open = fn
{:ok, file} -> "Read data: #{IO.read(file, :line)}"
{_, error} -> "Error: #{:file.format_error(error)}"
end
handle_open.(File.open("code/intro/hello.exs"))
handle_open.(File.open("nonexistent"))
我无法理解为什么第二次调用函数会进入第二次流程。 也是为什么我们不将参数传递给func:
handle_open = fn(file)
答案 0 :(得分:3)
这是一个多子句匿名函数。 handle_open
有2个子句,一个用于匹配模式{:ok, file}
的参数,另一个用{_, error}
匹配。执行与参数匹配的第一个模式。给定的代码几乎是 [1] ,相当于以下内容:
handle_open = fn arg ->
case arg do
{:ok, file} -> ...
{_, error} -> ...
end
end
因此,如果文件存在,File.open
将返回{:ok, file}
,并且将执行第一个子句。如果它没有,将返回{:error, error}
,它将匹配第二个子句并执行它。
[1]:"几乎"因为在两种情况下,没有任何模式匹配时引发的错误会略有不同。功能
答案 1 :(得分:0)
这实际上只是模仿Elixir的模式匹配行为。
就像您可以在模块功能上进行模式匹配一样。
defmodule MyModule do
def read_file(path) do
File.open(path) |> handle_file()
end
defp handle_file({:ok, file}) do
// File there..
end
defp handle_file({_, error}) do
// Could not open file.. because of `error`
end
end
就像书中的例子一样,我会尝试在case子句中打开文件并将结果委托给相应的函数:
defmodule FileReader do
def read_file(path) do
case File.open(path) do
{:ok, file} -> handle_file(file)
{_, error} -> handle_error(error)
end
end
defp handle_file(file) do
// File there..
end
defp handle_error(error) do
//
end
end