Elixir - 通过传递函数参数

Elixir - passing function parameter through

假设我有一个函数,它有点冗长并且每次都使用相同的参数调用,在该模块的任何其他函数可以在其回调中调用之前,这个函数也需要做很多设置。

SomeMod.called_a_lot(‘xx’, fn(y) ->
  SomeMod.needs_called_a_lot_to_be_called_first(‘do_stuff’)
end)

我想我可以这样包装它:

defp easier_to_call(func) do
  SomeMod.called_a_lot(‘xx’, fn(y) -> func(y) end
end

然后像这样使用它:

easier_to_call(fn(y) ->
  SomeMod.needs_called_a_lot_to_be_called_first(‘do_stuff’)
end)

实际上如何在 Elixir 中做到这一点?

Dogbert 的评论是正确的。但是因为你不修改参数,你可以直接传递函数而不用匿名函数包装它:

defp easier_to_call(func) do
  SomeMod.called_a_lot(‘xx’, func)
end

您的语法对于调用匿名函数来说有点偏离。您将需要使用

func.(y)

而不是

func(y)

因为它是一个匿名函数。

有关简短示例,请参阅 Elixir Crash Course

我不太明白你到底在问什么,但我觉得 capture operator (&) 就是你要找的东西。

一个示例用法是:

easier_func = &SomeMod.called_a_lot(‘xx’, &1)

easier_func.(fn(_y) ->
  SomeMod.needs_called_a_lot_to_be_called_first(‘do_stuff’)
end)

其中 &1 是匿名函数中的第一个参数。

如果你需要一个多重匿名函数,那么你可以这样做:

easy_reduce = &Enum.reduce(&1, 0, &2)

easy_reduce.([1,2,3,4], fn(x, acc) -> acc + x end) # => 10

另外一种方法:可以用宏来实现,先调用要调用的函数,再调用块:

defmodule Test do
  defmacro with_prepended(arg, do: block) do
    quote do
      IO.inspect(unquote(arg), label: "In function")
      prepended(unquote(arg))
      unquote(block)
    end
  end
end

defmodule Tester do
  require Test

  defp prepended(arg), do: IO.inspect(arg, label: "In prepended")

  def fun(arg) do
    Test.with_prepended(arg) do
      IO.puts "Actual code"
    end
  end
end

Tester.fun(42)

#⇒ In function: 42
#⇒ In prepended: 42
#⇒ Actual code