Skip to content

Instantly share code, notes, and snippets.

@caligin
Last active August 29, 2015 14:19
Show Gist options
  • Save caligin/28c4f664b7f773d46461 to your computer and use it in GitHub Desktop.
Save caligin/28c4f664b7f773d46461 to your computer and use it in GitHub Desktop.
Erlang - Fibonacci with processes example
-module(fib_proc).
-export([fib/2]).
-export([start/0]).
-export([start_link/0]).
%% start will be executed in the calling process,
%% creating a new one where the function init/0,
%% that represents the entry point of the "fibonacci
%% service" will be run. Returns the Pid of the newly
%% created process.
start() ->
spawn(fun init/0).
%% init is the starting point of the newly created process,
%% will start the process recursion with some initial state
init() ->
loop({1, #{ 0 => 1, 1 => 1}}).
%% this is not really a loop (no loops in erl!) but rather
%% the "main infinite-spinning recursion" of this process
%%
%% this will wait for a message that asks for a computation,
%% then if it knows the answer
loop(State) ->
receive
{fib, Num, From} when is_number(Num) andalso is_pid(From) ->
NewState = {_, ComputedMappings} = compute_if_missing(Num, State),
Result = maps:get(Num, ComputedMappings),
From ! {fib, Num, Result},
loop(NewState);
_ -> loop(State)
end.
%% Updates the state with a corecursion up to the requested number
%% if needed, then it returns the state
compute_if_missing(Requested, {HighestComputed, ComputedMappings}) when Requested > HighestComputed ->
Prev = maps:get(HighestComputed, ComputedMappings),
PrevPrev = maps:get(HighestComputed - 1, ComputedMappings),
NewState = {HighestComputed + 1, maps:put(HighestComputed + 1, Prev + PrevPrev, ComputedMappings)},
compute_if_missing(Requested, NewState);
compute_if_missing(_Requested, State) ->
State.
%% calculating a fib number from the initial process translates
%% to a request sent to the fib process (which Pid we need to know),
%% that will eventually reply asynchronously.
fib(Number, Pid) when is_number(Number) andalso
Number >= 0 andalso
is_pid(Pid) ->
Pid ! {fib, Number, self()},
receive
{fib, Number, Result} -> Result
after
5000 -> {error, timeout}
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment