High Order Function Inputs

Why do I need to specify the ampersand & arity in higher order functions?

E.g.

Enum.map [0,1,2] &Maths.double/1

I suspect the runtime could be smart enough to figure this out - perhaps not - just wondering…

2 Likes

The ampersand (&) is there to tell Elixir ‘I want to pass a function instead of calling it’. This is necessary because it is possible to call functions (and macros) without supplying brackets. ( rem(2,3) is the same as rem 2, 3. Many perceived ‘keywords’ in Elixir are actually normal functions or macros under the hood.

The & can be used to pass functions with two different kinds of syntaxes:

  1. Part of the parameters are filled in, part of them are numbered &1, &2, etc. An example: [1,:foo,"bar"] |> Enum.map(&is_integer(&1)).
  2. The version where you supply the arity, such as &Enum.reverse/2

The reason the second version exists is twofold:

  • By using a slash with the arity, it is clear that Elixir should not expect parameter-insertion as is used in the first form.
  • By passing the arity, it is very explicit which function is meant. This is useful because functions with the same name but with different arities are completely unconnected in Elixir (for instance, one of them can be public and the other private).

I am not sure if there is another reason for passing the arity beyond these two.

And “The runtime could be smart enough to figure this out” is true, but these kind of checks come at the cost of reduced performance.

4 Likes

And. IMO. reduced readability.

2 Likes

While I think you’re right, something doesn’t feel quite right, perhaps it’s just me : )

To be clear, in the BEAM a function consists of a name and an arity. foo/1 is a completely different function than foo/2.

2 Likes