4

What is the difference between a named and anonymous function?

How is hello = &("Hello, #{&1}") an anonymous function?

Onorio Catenacci
  • 14,928
  • 14
  • 81
  • 132
user1354934
  • 8,139
  • 15
  • 50
  • 80

3 Answers3

5

The main difference is one of scope. What do you have access to in the function body.

Named functions in Elixir are grouped into modules, and their scope is limited to the arguments given to them.

An anonymous function can be defined anywhere, and have access to whatever is visible in their immediate surrounding. The jargon is that they are "closures", that they "close over" surrounding scope.

Let's look at an example:

c = 10

anon = fn(a, b) -> a + b + c end
anon.(1, 2) # => 13, because c is available in the anonymous function

# The module below will fail to compile, because c isn't available
defmodule MyModule do
  def named(a, b), do: a + b + c
end

You can create an anonymous functions from a named function with the & capture operator, and it will have access to your current scope. This is common, as many functions expect other functions as arguments. Browse through the docs for Enum, and you'll see plenty of examples.

You'll notice I called the anonymous anon function like this: anon.(1, 2), instead of anon(1, 2). It makes the difference between the two kinds of functions more explicit in your code.

José gave a good answer to a related question.

Community
  • 1
  • 1
Martin Svalin
  • 2,227
  • 1
  • 17
  • 23
  • 1
    This will likely cause more confusion than help, but I find the whole "named" function vs anonymous function thing misleading. There's really only closures and expressions. Module are ways of defining complex expressions at compile time, closures are a way to define complex expressions at run time. – Fred the Magic Wonder Dog Nov 21 '16 at 23:55
  • This explanation is the one that makes the most sense to me and really cements for me the difference between the two. However, one part I don't quite get is your comment about how named functions that have been captured into anonymous functions "will have access to your current scope". Are you saying that named functions that have been captured into anonymous functions will still have access to the scope in which it was defined (i.e. within the module it was defined in)? – wmock Feb 28 '18 at 01:59
3

A named function needs to be defined inside a module. An anonymous function doesn't have that restriction.

On your example, &("Hello, #{&1}") is the anonymous function part. It is using the capture operator &, so this function is just a shorter way of writing fn (x) -> "Hello, #{x}" end. The &1 is a placeholder for the function parameter. You can assign that anonymous function to a variable (hello in this case). To access the function via the variable you use hello.("Derek"). Don't forget the dot!

Remember that Function is also a type in Elixir and functions are first-class citizen, that's why you can assign it to a variable and make functions return other functions.

1

The function itself has no name, it is bound to a variable, but you could place it inline anywhere a function is expected like:

Enum.map([1,2,3],  &("Hello, #{&1}") )

No name. Anonymous.

greg
  • 102
  • 3