<< ruby implementation index single process erlang implementation >>
the obvious choice for this kind of distributed algorithm is erlang there are lots of tutes online but here's my quick intro
all examples done in erlang shell erl
bash> erl
variables start with a capital and are immutable
erl> X = 2. X is unbound, assigns it value 2 erl> X = 3. ERROR! since X is already bound erl> X = 2. X is bound, and has value 2 so equality holds erl> Y = 3. Y is unbound, assigns it value 3 erl> X = Y-1. X is value 2, Y-1 is value 2, so equality holds
(note: values in erl shell can be unbound with f(orget) function)
erl> X = 2. erl> f(). erl> X = 3. no error
there are various types of variables
standard numerics; ints & floats
erl> A = 2. erl> B = 3.5.
atoms; symbolic constants that start with a lowercase
erl> C = shutdown_command.
tuples; short lists used for building structs
erl> D = {min_max,3,10}.
lists; variables sized array with lots of helper functions
erl> E = [1,2,3]. erl> length(E). 3 erl> E ++ [4]. [1,2,3,4]
functions; are first class objects
erl> G = fun(X) -> X * 2 end. erl> G(5). 10
pattern matching
binding of variables is through pattern matching
erl> f(). erl> X = 2. simplest pattern match there is erl> {min_max,Min,Max} = {min_max,3,10}. erl> Min. 3 erl> Max. 10
special variable 'underscore' used for matching values we don't care about
erl> f(). erl> {min_max,Min,5} = {min_max,4,6}. FAIL, no match. 5 != 6 erl> {min_max,Min,_} = {min_max,4,6}. erl> Min. 3
some special list matching with 'pipe' list splitter
erl> [Head|Tail] = [1,2,3]. erl> Head. 1 erl> Tail. [2,3]
most looping code implemented in function programming style, ie recursively using pattern matching a different version of the overloaded sum function is called
sum([]) -> 0; sum([H|T]) -> H + sum(T).
executed as
sum([1,2,3]) = 1 + sum([2,3]) = 1 + ( 2 + sum([3]) ) = 1 + ( 2 + ( 3 + sum([]) ) ) = 1 + ( 2 + ( 3 + ( 0 ) ) ) = 6
actually compiled though to use an accumulator thus can use last call optimisation to avoid recursive stackoverflow (ie can then be implement as loop using jump operation).
sum(L) -> sum(L,0); sum([],Acc) -> Acc; sum([H|T],Acc) -> sum(T, Acc+H).
executed as
sum([1,2,3]) = sum([1,2,3],0) = sum([2,3],0+1) = sum([3],1) = sum([3],1+2) = sum([3],3) = sum([],3+3) = sum([],6) = 6
concurrency support
erlangs main strength is it's concurrency support any function call can be run asynchronously using the spawn command
main() -> say_word_n_times('hello',4), say_word_n_times('goodbye',4).results in
hello hello hello hello goodbye goodbye goodbye goodbye
main() -> spawn(fun() -> say_word_n_times('hello',4) end), spawn(fun() -> say_word_n_times('goodbye',4) end).results in something like
hello goodbye hello hello goodbye goodbye hello goodbye
spawn creates a new erlang 'process'. each process has it's own context and runs on one of N erlang managed system threads. processes are extremely lightweight and very cheap to create/destroy; it's quite feasible to have thousands of running processes
processes can only communicate through messaging. a process can be sent a message with the ! operator. messages are queued in a mailbox and handling with the receive operator.
main() -> P = spawn(fun() -> message_loop() end), P ! hello, P ! hello, P ! goodbye, P ! hello. message_loop() -> receive hello -> io:format("i got a hello\n"), message_loop(); goodbye -> io:format("bye bye!\n") end.results in
i got a hello i got a hello bye bye!main process spawns a process that enters the message loop main process then sends 4 messages to spawned process spawned process receives a 'hello', writes some output and reenter message loop spawned process receives a 'hello', writes some output and reenter message loop spawned process receives a 'shutdown', writes some output but doesnt reenter message loop final hello message unprocessed
the real power comes from fact processes can be spawned just as easily on another erlang vm
P = spawn(AnotherNode, fun() -> message_loop() end),no other change to the code is required.
<< ruby implementation index single process erlang implementation >>
nov 2008