Tuesday, November 17, 2009

Reading Notes #2: Passing functions as arguments to higher order functions

Does Erlang allow you to pass functions (not "funs" or anonymous functions) as arguments to higher order functions? I was under the impression that it doesn't. To find out I tweeted a question about the same. After looking at the answers I decided to rephrase the question with the help of a concrete example. Here it goes:

Step 1: Define a function add_one in a module named test.

Step 2: Start the erlang shell and try to use this function.

As you can see I have tried three different combinations. Line #3 shows a call to the higher order function lists:map passing in the qualified name of the add_one function as first argument. The shell throws an error.

In Line #4 I wrap test:add_one inside a fun and it works.

In Line #5 I replicate the code of add_one inside an anonymous fun and everything works fine.

Contrast this with say, Python.

Definition:

Usage:

Now I'll repeat the question: Does Erlang allow you to pass functions (not "funs" or anonymous functions) as arguments to higher order functions? Or am I missing something?

Please share your thoughts in the comments.

Update #1:
Got an answer. There is a way to do it. It still involves using the fun keyword.
Update #2:
Got another answer which does *not* use fun. The syntax is just a little different. Thanks to Justin Sheehy.

2 comments:

Anonymous said...

$ erl
1> AddN = fun(N) -> fun(X) -> X + N end end.
#Fun<erl_eval.6.13229925>
2> Ten = AddN(10).
#Fun<erl_eval.6.13229925
3> Ten(5).
15

Robert Virding said...

I would avoid using the second method, {test,add_one} as this is a very old, now deprecated, hack from way back before we had funs. The only way to pass a function is by a fun. (fun add_one/1 actually expands to fun(X) -> add_one(X) end internally)