Dwayne  XD
Dwayne XD

Reputation: 45

Functions as arguments -- What is happening here?

I am going through some Elixir koans and I'm a bit stumped on what is happening in these lines of code.

  def times_five_and_then(number, fun), do: fun.(number * 5)
  def square(number), do: number * number

  koan "You can pass functions around as arguments. Place an '&' before the name and state the arity" do
    assert times_five_and_then(2, &square/1) == ___
  end

For ___, the correct answer is 100. But I am not sure how or why, can anyone articulate what is happening?

Upvotes: 0

Views: 91

Answers (1)

Adam Millerchip
Adam Millerchip

Reputation: 23091

& is the function capture operator. &square/1 means "capture the function called square that has arity 1 (arity 1 in simple English: accepts a single argument)".

times_five_and_then(2, &square/1)

This means "call the times_five_and_then function with the number 2 and a capture of the fuction square (which has arity 1)".

A function stored in a variable is called an anonymous function (because it doesn't have a name, unlike functions defined with the def keyword). A named function can be captured as an anonymous function using the & capture operator, which is what happens in your example.

times_five_and_then/2 calls its parameters number and fun. The fun parameter is a variable that contains an anonymous function. The function could be any function, but in your example it happens to be a capture of the square/1 function. The syntax for calling an anonymous function is variable_name.(args). That's what's happening with fun.(number * 5) in this case. The function stored in fun is being called with the argument number * 5.

Let's look at the implementation of times_five_and_then/2:

def times_five_and_then(number, fun), do: fun.(number * 5)

This takes the fun argument, and calls the function it contains with the number argument, multiplied by 5. A breakdown of what happens:

  1. A function called square/1 is defined that squares its argument.
  2. The square function is captured as an anonymous function, and passed to the times_five_and_then/2 function as the second parameter.
  3. The times_five_and_then/2 function binds the captured function to the fun variable.
  4. The times_five_and_then/2 function multiplies its first argument, called number, by five.
  5. The times_five_and_then/2 function calls the anonymous function stored in fun (which is a capture of the square/2 function), with the result of the above multiplication.
  6. The result of the execution of the function in fun is returned.

Or in other words, 2 is multiplied by 5, then passed to a capture of the square/2 function, which squares it, to give 100.

Upvotes: 2

Related Questions