Last active
August 29, 2015 14:19
-
-
Save caligin/28c4f664b7f773d46461 to your computer and use it in GitHub Desktop.
Erlang - Fibonacci with processes example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-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