Function capturing
Throughout this tutorial, we have been using the notation name/arity
to refer to functions. It happens that this notation can actually be used to retrieve a named function as a function type. Start iex
, running the math.exs
file defined above:
$ iex math.exs
iex> Math.zero?(0)
true
iex> fun = &Math.zero?/1
&Math.zero?/1
iex> is_function(fun)
true
iex> fun.(0)
true
Local or imported functions, like is_function/1
, can be captured without the module:
iex> &is_function/1
&:erlang.is_function/1
iex> (&is_function/1).(fun)
true
Note the capture syntax can also be used as a shortcut for creating functions:
iex> fun = &(&1 + 1)
#Function<6.71889879/1 in :erl_eval.expr/5>
iex> fun.(1)
2
The &1
represents the first argument passed into the function. &(&1+1)
above is exactly the same as fn x -> x + 1 end
. The syntax above is useful for short function definitions.
If you want to capture a function from a module, you can do &Module.function()
:
iex> fun = &List.flatten(&1, &2)
&List.flatten/2
iex> fun.([1, [[2], 3]], [4, 5])
[1, 2, 3, 4, 5]
&List.flatten(&1, &2)
is the same as writing fn(list, tail) -> List.flatten(list, tail) end
which in this case is equivalent to &List.flatten/2
. You can read more about the capture operator &
in the Kernel.SpecialForms
documentation.