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