嵌套函数定义

use*_*563 1 elixir

我只是在通过 Programming Elixir 和 implpementing Split 工作。

我的代码如下 -

defmodule MyEnum do
    def split(l, n) do
        def split_helper([], pre, _n), do: {pre, []}
        def split_helper(l, pre, 0), do: {pre, l}
        def split_helper([h|t], pre, n), do: split_helper(t, [h|pre], n-1)
        split_helper(l, [], n)
    end
end
Run Code Online (Sandbox Code Playgroud)

我收到错误 - 无法在函数/宏中调用 def/2

我的意思是我不能嵌套命名函数。由于您不能编写递归匿名函数并且没有letrec,我想知道如何在嵌套函数递归的地方嵌套函数。这是我在球拍中构建代码的方式,因为我永远不需要在其他任何地方使用 split_helper。

Ale*_*kin 5

Elixir 中的函数不能嵌套。时期。

实现这一点的惯用方法是使用一个名为do_split/3.

defmodule MyEnum do
  def split(l, n), do: do_split(l, [], n)

  defp do_split([], pre, _n), do: {pre, []}
  defp do_split(l, pre, 0), do: {pre, l}
  defp do_split([h|t], pre, n), do: do_split(t, [h|pre], n-1)
end
Run Code Online (Sandbox Code Playgroud)

解决这个问题的另一种方法是简单地使用几个子句split/3

defmodule MyEnum do
  def split(l, acc \\ [], n) # default values

  def split([], pre, _n), do: {pre, []}
  def split(l, pre, 0), do: {pre, l}
  def split([h|t], pre, n), do: split(t, [h|pre], n-1)
end
Run Code Online (Sandbox Code Playgroud)

最不优雅但仍然有效的方法是创建匿名函数并通过.

defmodule MyEnum do
  def split(l, n) do
    split_helper = fn
      [], pre, _, _ -> {pre, []}
      l, pre, 0, _ ->  {pre, l}
      [h|t], pre, n, split_helper ->
        split_helper.(t, [h|pre], n-1, split_helper)
    end
    split_helper.(l, [], n, split_helper)
  end
end
Run Code Online (Sandbox Code Playgroud)