【问题标题】:How do functions work in Elixir?Elixir 中的函数是如何工作的?
【发布时间】:2017-09-09 11:54:18
【问题描述】:

在“Programming Elixir”一书中,Dave Thomas 展示了一个示例

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)

?

【问题讨论】:

    标签: function arguments elixir


    【解决方案1】:

    这是一个多子句匿名函数。 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]:“几乎”,因为当没有任何模式匹配时引发的错误在两种情况下会略有不同。

    【讨论】:

      【解决方案2】:

      这实际上只是模仿 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-21
        • 1970-01-01
        • 1970-01-01
        • 2021-03-30
        • 2020-07-18
        • 2015-11-08
        • 2017-05-21
        • 2011-04-24
        相关资源
        最近更新 更多