功能如何在Elixir中起作用?

时间:2017-09-09 11:54:18

标签: function arguments elixir

在书"编程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)

2 个答案:

答案 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