在 Elixir 中传递和使用命名函数?

Posted

技术标签:

【中文标题】在 Elixir 中传递和使用命名函数?【英文标题】:Pass and consume a named function in Elixir? 【发布时间】:2017-08-25 05:09:26 【问题描述】:

以下 Elixir 代码不正确,但传达了(我认为)想要的结果:

defmodule Question do
  def dbl(n), do: n * 2
  def trp(n), do: n * 3

  def consumer(xs, f) do
    Enum.filter(xs, f.(x) > 5)
  end
end

Question.consumer([1, 2, 3], dbl) # [3]
Question.consumer([1, 2, 3], trp) # [2, 3]

应该如何编写consumer 方法以正确使用dbltrp?那你怎么称呼它?

谢谢!

编辑:

请提出相关问题。您将如何在 Elixir 中编写和调用以下 Scala 代码:

def dbl(n: Int): Int = n * 2
def trp(n: Int): Int = n * 3

def consume(xs: List[Int], f: (Int) => Int): List[Int] =
  xs.filter(x => f(x) > 5)

consume(List(1, 2, 3), dbl) # List(3)
consume(List(1, 2, 3), trp) # List(2, 3)

(谢谢)* 2

【问题讨论】:

【参考方案1】:

与 Scala 的 x => f(x) > 5 等效的 Elixir 是 fn x -> f.(x) > 5 end。这就是你使用它的方式:

defmodule Question do
  def dbl(n), do: n * 2
  def trp(n), do: n * 3

  def consumer(list, f) do
    Enum.filter(list, fn x -> f.(x) > 5 end)
  end
end

然后您可以使用以下方式调用它:

Question.consumer([1, 2, 3], &Question.dbl/1)   # => [3]
Question.consumer([1, 2, 3], &Question.trp/1)   # => [2, 3]

补充说明:

您也可以使用简写 &(f.(&1) > 5) 代替完整功能 注意&/1 - 您需要传递对命名模块方法的完整引用。 See the Elixir guide on the Function captures.

另一方面,如果您将 dbltrp 函数设为匿名,则可以直接将它们作为参数传递:

dbl = fn n -> n * 2 end
trp = fn n -> n * 3 end

Question.consumer([1, 2, 3], dbl)   # => [3]
Question.consumer([1, 2, 3], trp)   # => [2, 3]

供参考,阅读:Why are there two kinds of functions in Elixir?

【讨论】:

感谢您的回答。请你看看编辑。我不知道如何将Enum.filter 与传入函数一起使用。 Enum.filter(xs, f > 5) 似乎不起作用? 我只想使用提供的函数过滤集合 - 没有映射 - 所以 [2] 和 [2, 3] 的 scala 输出就是我所追求的。 太棒了。感谢您的快速帮助 - 正是我想要的!

以上是关于在 Elixir 中传递和使用命名函数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 elixir 中定义命名函数有两种方式?

Elixir/Erlang 中的命名函数是不是有等效于 __MODULE__ 的方法?

Elixir重命名并包装Erlang模块?

如何检查 ETS Erlang/Elixir 中是不是存在命名表

在 elixir 中命名嵌套伞应用程序

如何将输入传递到用户定义函数中的命名列表