How to pass a function of arity 2 as an argument in Elixir for Enum.map?

Sasha Fonseca picture Sasha Fonseca · Nov 13, 2015 · Viewed 7.5k times · Source

Let's say I have something like:

    Enum.map(list, fn(x) -> String.duplicate("a", someValue * x) end)

But instead, I'd like to pass the String.duplicate/2 function as an argument in order to simplify my code:

Enum.map(list, &String.duplicate/2)

I know you can do it for arity 1 functions:

Enum.map(list, &String.downcase/1)

Thanks!

Answer

Gazler picture Gazler · Nov 13, 2015

You can't pass a function to Enum.map with an arity of 2 as Enum.map calls your function with each element in the list as an argument. If you use another function like Enum.reduce then it expects a function with an arity of 2.

This is an example of the String.downcase/1 function being called with each item in the list:

Enum.map(["FOO", "BAR", "BAZ"], fn(x) -> String.downcase(x) end)
# String.downcase("FOO")
# String.downcase("BAR")
# String.downcase("BAZ")

In your example with duplicate, you are trying to call String.duplicate/2 with a single argument (the string "FOO").

You can use the capture syntax to create a function (this is a shorthand way of defining the function you provided):

Enum.map([1,2,3], &String.duplicate("a", &1))

You can also define a named function in your module that only requires one argument, for example:

Enum.map([1, 2, 3], &duplicate_foo/1)

def duplicate_foo(times), do: String.duplicate("a", times)