3
votes

This question is about some syntax a partner came across today and though we understand how it works, we don't understand why is it allowed (what is its use?).

Look at this snippet:

fun() -> ok end().

Without the last pair of parentheses this will produce something like:

#Fun<erl_eval.20.82930912>

But with them, the function is evaluated producing:

ok

My question is, why is that syntax allowed in Erlang ? why would I want to create a function just to call it immediately instead of just writing out its contents? is there any practical use to it ?

The only thing we could think about was introducing local variables inside the fun's body (but that would look ugly and unclear to me).

Please note that this other syntax is not allowed in Erlang, even though it follows the same concept of the former:

fun() -> fun() -> ok end end()().  

(It would mean: a function A that returns a function B. And I'm evaluating A (thus producing B) and then evaluating B to get 'ok').

2
I don't know Erlang, but (I think) functions are first-class objects. That means that they can be arguments to functions, be assigned to variables, or even be return values themselves. It's super useful when you're doing something like sorting by a custom made function. See stackoverflow.com/questions/245192/what-are-first-class-objects - vroomfondel
About the last one, you might be wrong. At least my version of erlang works with this fun() -> fun() -> ok end() end(). I mean that the statement is correct. - ipinak
@rogaos Yes, they're 1st-class objects in Erlang. But then why is the second syntax not allowed? (the fun returning the fun). - Daniel
@ipinak Note how the 2 pairs of parentheses are placed at the end of the second end of my version. - Daniel
@DWilches I didn't really understood your reply. - ipinak

2 Answers

9
votes

The syntax you mentioned is a natural outcome of Erlang's being functional.

In Erlang, functions are values (stored as closures).

The value of fun() -> ok end is a function, which takes nothing and returns ok. When we put parentheses after it, we are calling that function. Another way to demonstrate this is:

 > F = fun() -> ok end.  
 #Fun<erl_eval.20.80484245>
 > F().                  
 ok

The functions in the second example of yours need to be grouped properly in order for the parser to make sense of them.

As for your question -- "why this syntax is allowed", I'd have to say it's a natural outcome of functions being values in Erlang. This ability enables the functional style of programming. Here is an example:

 > lists:map(fun(X) -> X * 2 end, [1,2,3]).
 [2,4,6]

The above code is in essence this:

 > [fun(X) -> X * 2 end(1), fun(X) -> X * 2 end(2), fun(X) -> X * 2 end(3)].
 [2,4,6]

A "natural outcome" is just a natural outcome, it really doesn't have to be of any practical use. So, you will probably never see code like (fun() -> fun() -> ok end end())(). being used:)

2
votes

You typically wont't have much use for the syntax fun() -> ok end (). But it can be useful to do something like (find_right_fun()) (), which is basically the same thing - an expression that evaluates to a function.

Note that the Erlang parser requires you to specify the precedence using () to sort out the meaning of ()(), i.e. your second example should be (fun() -> fun() -> ok end end()) ().