Erlang & Elixir DISCUSSION

Why does Elixir need a dot to call an anonymous function, as in add.(1, 2), but not a named one?

Started by sabari Elixir anonymous functionsnamed functionscapture operatorfunction arityclosures
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Why does Elixir need a dot to call an anonymous function, as in add.(1, 2), but not a named one?

sabari Erlang & Elixir Forum
#1

In Elixir I can define def add(a, b), do: a + b inside a module and call it as Math.add(1, 2). If I write add = fn a, b -> a + b end, I must call it as add.(1, 2); plain add(1, 2) gives an undefined function error. And to pass the named one to Enum.map I need &Math.add/2.

Why are there two kinds of function with different call syntax, and what are the practical differences between them?

Community replies 5

Re: Why does Elixir need a dot to call an anonymous function, as in add.(1, 2), but not a named one?

#2

Named functions and variables live in separate namespaces. A named function is identified by module, name and arity (Math.add/2) and exists only inside a module. An anonymous function is a value, stored in a variable like any other term. Since a variable add and a function add/2 can both exist in the same scope, the syntax has to say which you mean: add(1, 2) always calls the named function, and add.(1, 2) calls whatever function value the variable holds.

Erlang has the same split but needs no dot, because its variables start with a capital letter: Add = fun(A, B) -> A + B end, Add(1, 2) cannot be confused with the function add/2.

Re: Why does Elixir need a dot to call an anonymous function, as in add.(1, 2), but not a named one?

#3

The capture operator converts between the two worlds. &Math.add/2 produces a function value that refers to the named function, so Enum.reduce([1, 2, 3], 0, &Math.add/2) returns 6. The same operator is a shorthand for small anonymous functions, with &1, &2 standing for the arguments: Enum.map([1, 2, 3], &(&1 * 2)) gives [2, 4, 6] and is the same as fn x -> x * 2 end.

Arity is part of a function's identity. add/2 and add/3 are unrelated functions, which is why the capture must state the arity.

Re: Why does Elixir need a dot to call an anonymous function, as in add.(1, 2), but not a named one?

#4

The main practical difference is that anonymous functions are closures. They capture the variables that are in scope where they are created: factor = 3; scale = fn x -> x * factor end; scale.(5) returns 15, and it keeps returning 15 even if factor is rebound afterwards, because the closure holds the value, not the name.

A named function captures nothing. The body of a def cannot see variables defined around it in the module, so everything it needs must arrive as an argument or come from a module attribute.

Re: Why does Elixir need a dot to call an anonymous function, as in add.(1, 2), but not a named one?

#5

Other differences: named functions can have several arities, default arguments, documentation and defp for private visibility. Anonymous functions can have multiple clauses with pattern matching and guards, but all clauses must take the same number of arguments, and they have no name with which to call themselves recursively.

Errors differ too: calling a function value with the wrong number of arguments raises BadArityError, whereas calling a named function that does not exist with that arity raises UndefinedFunctionError.

Re: Why does Elixir need a dot to call an anonymous function, as in add.(1, 2), but not a named one?

#6

A guideline for choosing: use fn for short, local behaviour passed to Enum, Task and similar APIs, and named functions for everything else. When a function value is going to be stored for a long time, put in process state, or sent to another node, prefer a capture of a public function, &Mod.fun/1, or a {module, function, args} tuple. An anonymous function is tied to the particular version of the module that created it, while a remote capture is resolved by name and keeps working after the module is recompiled or upgraded.

TEP COMMUNITY