Fun = fun() -> {programming, erlang, elixir} end.

home

Laziness

13 Jun 2014

I like lazy data structures, so I was curious about how they could be implemented in Erlang. Actually, I have found that is quite easy. In order to understand how they work only a little understanding of functional programming is needed.

Let’s see a basic example.

-module(lazy).
-export([generator/1, next_val/1, val/1]).


generator([H|T]) ->
    {H, fun() -> generator(T) end};
generator([]) ->
    end_of_list.

next_val({_Value, FunctionNext}) ->
    FunctionNext().

val({Value, _FunctionNext}) ->
    Value.

Let’s see it in action.

$ erl
Erlang/OTP 17 [RELEASE CANDIDATE 2] [erts-6.0] [source] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V6.0  (abort with ^G)
1> c(lazy).
{ok,lazy}
2> Gen1 = lazy:generator([1, 2, 3]).
{1,#Fun<lazy.0.84850269>}
3> lazy:val(Gen1).
1
4> Gen2 = lazy:next_val(Gen1).
{2,#Fun<lazy.0.84850269>}
5> Gen3 = lazy:next_val(Gen2).
{3,#Fun<lazy.0.84850269>}
6> lazy:next_val(Gen3).
end_of_list
7>

Basically, the clue is to keep the state as a tuple with its first term being the current value and the second one a function which encloses the next execution of the generator for the tail. The potential for the next execution is retained in this clousure.

Another example with infinite values.

-module(lazy2).
-export([generator/1, next_val/1, val/1]).


generator(Val) ->
    {Val, fun() -> generator(Val + 1) end}.

next_val({_Value, FunctionNext}) ->
    FunctionNext().

val({Value, _FunctionNext}) ->
    Value.

And its execution.

$ erl
Erlang/OTP 17 [RELEASE CANDIDATE 2] [erts-6.0] [source] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V6.0  (abort with ^G)
1> c(lazy2).
{ok,lazy2}
2> Gen1 = lazy2:generator(0).
{0,#Fun<lazy2.0.2666151>}
3> lazy2:val(Gen1).
0
4> Gen2 = lazy2:next_val(Gen1).
{1,#Fun<lazy2.0.2666151>}
5> Gen3 = lazy2:next_val(Gen2).
{2,#Fun<lazy2.0.2666151>}
6> Gen4 = lazy2:next_val(Gen3).
{3,#Fun<lazy2.0.2666151>}
7>

As its title denotes this post has been quite short.

Have fun.