# Erlang for Python programmers: Part IV

by on October 2, 2007

Previous parts: Intro, Part I, Part II and Part III

### Funs – sequel

Continuing previous post about functions let’s remember about Fun. I already mentioned it in Part I and promised to show its advanced forms. So, here we go.

Fun with one clause:

```1> Double = fun(X) -> X * 2 end.
#Fun<erl_eval.6.56006484>
2> Double(2).
4```

But Fun actually has the same function declaration syntax as regular function, except that it has no name in declaration, so we can have this:

```3> Big = fun (X) when X > 100 -> true;
3>           (X) -> false
3>       end.
#Fun<erl_eval.6.56006484>
4> lists:filter(Big, [20, 30, 120, 130]).
[120,130]```

As you see our Fun has two clauses separated by semicolon(;) and first clause has also guard, ie syntax is the same as in regular function declaration.

There are also following fun expressions that can be used:

1. fun FunctionName/Arity (FunctionName should point to local function defined in the same module with our fun)
2. fun Module:FunctionName/Arity (FunctionName should be exported from module Module)

fun FunctionName/Arity is just syntactic sugar for fun (X1, ..Xn) -> FunctionName(X1, .., Xn) end.

Let’s take a look on foregoing in action and create mymath.erl

```-module(mymath).
-export([test1/0,
test2/0,
test3/0,
double/1]).

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

test2() -> lists:map(fun double_local/1, [1, 2, 3]).

test3() -> lists:map(fun mymath:double/1, [1, 2, 3]).

%% helper function, not exported
double_local(X) ->
X * 2.

%% helper function, exported
double(X) ->
X * 2.```

Compile and test it (I’m compiling as usual in Emacs with C-c C-k):

```1> c("/home/alienoid/dev/erlang/mymath", [{outdir, "/home/alienoid/dev/erlang/"}]).
{ok,mymath}
2> mymath:test1().
[2,4,6]
3> mymath:test2().
[2,4,6]
4> mymath:test3().
[2,4,6]```

Also tuple of type {Module, FunctionName} is interpreted as a fun Module:FunctionName/Arity which you already saw. This usage is deprecated, but to be complete here is an example:

```5> Append = {lists, append}.
{lists,append}
6> Append([1, 2], [3, 4, 5]).
[1,2,3,4,5]```

As you already noted Fun in Erlang is “richer” than lambda in Python.

### Built-in functions, BIFs

Both Erlang and Python provide built-in functions that are always available and do not require explicit usage of module name to use them.

Python:

In Python shell you can inspect in addition contents of __builtins__ module if you need:

```>>> import pprint
>>> pprint.pprint(dir(__builtins__))
['ArithmeticError',
'AssertionError',
...
'type',
'unichr',
'unicode',
'vars',
'xrange',
'zip']```

Erlang:
Most of the built-in functions belong to module erlang and they are auto-imported.
To get list of all BIFs with description read man erlang.
In Eshell you can get list of functions that belong to erlang module with m(Module). command:

```1> m(erlang).
Module erlang compiled: No compile time info available
Compiler options:  []
Exports:
'!'/2                         list_to_existing_atom/1
'\$erase'/1                    list_to_float/1
'\$erase'/0                    list_to_integer/2
'\$get'/1                      list_to_integer/1
'\$get'/0                      list_to_pid/1
'\$get_keys'/1                 list_to_tuple/1
'+'/1                         localtime/0
'+'/2                         localtime_to_universaltime/1
'++'/2                        localtime_to_universaltime/2
...
ok```

Take into account though that not all functions in above list that you’ll see are auto-imported and may require usage of module: prefix. Again, for more information read man erlang (either in command line with erl -man erlang or if you use Emacs take a look at Erlang man pages in Emacs)

### Macros

Python does not have them, Erlang does. In Erlang they are not as powerful as in Common Lisp, but more like in C.

They are defined in following form:

```-define(Const, Replacement).
-define(Func(Var1,...,VarN), Replacement).```

Whenever erlang preprocessor encounters expression of form ?MacroName it expands corresponding macro.
Define utils.erl:

```-module(utils).
-export([foo/0]).
-define(TIMEOUT, 100).
-define(FUNCMACRO(X, Y), {X, x, Y, y}).

foo() ->
io:format("TIMEOUT = ~p~n", [?TIMEOUT]),
?FUNCMACRO(3, 7).```

Compile and run:

```1> utils:foo().
TIMEOUT = 100
{3,x,7,y}```

There are also some predefined macros:

`?MODULE`
The name of the current module.
`?MODULE_STRING`.
The name of the current module as a string.
`?FILE`.
The file name of the current module.
`?LINE`.
The current line number.
`?MACHINE`.
The machine name, `'BEAM'`.

Having ?MODULE we can rewrite earlier example with Fun as:

```-module(mymath).
-export([test1/0,
test2/0,
test3/0,
double/1]).

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

test2() -> lists:map(fun double_local/1, [1, 2, 3]).

%% test3() -> lists:map(fun mymath:double/1, [1, 2, 3]).
test3() -> lists:map(fun ?MODULE:double/1, [1, 2, 3]).

%% helper function, not exported
double_local(X) ->
X * 2.

%% helper function, exported
double(X) ->
X * 2.```

And as usual compile and run to see that result is the same:

```1> c("/home/alienoid/dev/erlang/mymath", [{outdir, "/home/alienoid/dev/erlang/"}]).
{ok,mymath}
2>  mymath:test1().
[2,4,6]
3>  mymath:test2().
[2,4,6]
4>  mymath:test3().
[2,4,6]```

In addition there is also flow control in macros. Some of corresponding macro directives are:

• ifdef(Macro). – Evaluate the following lines only if Macro is defined.
• else. – It’s used after ifdef or ifndef
• endif. - Marks the end of ifdef or ifndef directive

Example in utils.erl:

```-module(utils).
-export([foo/0]).

-ifdef(debug).
-define(LOG(Msg), io:format("{~p:~p}: ~p~n", [?MODULE, ?LINE, Msg])).
-else.
-define(LOG(Msg), true).
-endif.

foo() ->
?LOG("Debug is enabled").```

To turn LOG macro on debug should be defined. This can be achieved from command line with erlc -Ddebug utils.erl or from Eshell using c/2 function:

```1> c(utils, {d, debug}).
{ok,utils}
2> utils:foo().
{utils:11}: "Debug is enabled"
ok```

To turn LOG macro off debug should be omitted:

```3> c(utils).
{ok,utils}
4> utils:foo().
true```

To be continued.

If you enjoyed this post why not subscribe via email or my RSS feed and get the latest updates immediately. You can also follow me on GitHub or Twitter.