Skip to content

Instantly share code, notes, and snippets.

@arunthampi
Created September 2, 2008 07:19
Show Gist options
  • Save arunthampi/8388 to your computer and use it in GitHub Desktop.
Save arunthampi/8388 to your computer and use it in GitHub Desktop.
% My attempt to document all the Erlang-isms that I come across
% mostly from the wonderful book by Joe Armstrong (which I highly recommend)
% Extracting values from tuples
Point = {point, 10, 45}.
{point, X, Y} = Point.
X. % Will return 10
Y. % Will return 45.
% Extracting elements from a list
ThingsToBuy = [{oranges, 4}, {newspaper, 1}].
[Buy1|ThingsToBuy1] = ThingsToBuy.
Buy1. % Is bound to {oranges, 4}
ThingsToBuy1. % Is bound to [{newspaper, 1}] Notice this is still a list
[A,B,C,|T] = [a,b,c,d,e,f] % A = a, B = b, C = c, T = [d,e,f]
% A Simple Erlang Module.
% Function area has two clauses. Final clause is terminated by a period.
% Clauses are separated by semicolon.
-module(geometry).
-export([area/1]).
area({rectangle, Width, Ht}) -> Width * Ht;
area({circle, R}) -> 3.14159 * R * R.
% Punctuation in Erlang
% Commas separate arguments in function calls, data constructors and patterns.
% Periods (followed by a whitespace) separate entire functions and expressions in the shell.
% Semicolons separate clauses.
% Funs are anonymous functions, Something like Procs or blocks in Ruby.
Z = fun(X) -> 2*X end.
Z(2). % Returns 4
% Functions that have funs as their arguments
Even = fun(X) -> (X rem 2) =:= 0 end.
lists:filter(Even, [1,2,3,4,5,6,7,8]). % Returns [2,4,6,8]
% To include Erlang modules use the import command. For example:
-import(lists, [map/2, sum/1]). % Can use map(Fun, ...) instead of lists:map(Fun, ...).
% List Comprehensions are expressions that create lists without having to use funs, maps or filters
% [F(X) || X <- L] ==> The list of F(X) where X is taken from list L
L = [1,2,3,4,5].
[2*X || X <- L]. % Returns [2,4,6,8,10]
% QuickSort using Erlang
qsort([]) -> [];
qsort([Pivot|T]) ->
qsort([X || X <- T, X < Pivot])
++ [Pivot] ++
qsort([X || X <- T, X >= Pivot]).
% A Guard Sequence is either a single guard or a series of guards, separated by a semicolon.
% The Guard Sequence G1; G2; ...; Gn is true if at least of one their guards evaluates to true
% The Guard Sequence G1, G2, ..., Gn is true if all their guards evaluate to true.
% Records are like tuples, but with names and fields so that they are more manageable.
% Field names must be atoms
-record(todo, {status=reminder,who=joe,text}).
% This creates a new record with status = reminder, who = joe and text = undefined
X=#todo{}.
% This creates a new record with status=urgent, who=joe and text = "Fix errata in book"
X1=#todo{status=urgent, text="Fix errata in book"}.
% This copies X1 to X2 but sets status=done
X2=X1#todo{status=done}.
% Extracting Fields from a record.
#todo{who=W, text=TXT} = X2.
W. % Returns joe
TXT. $ Returns "Fix Errata in book"
% To get one field
X2#todo.text % Returns "Fix Errata in book"
% Pattern Matching Records in Functions
clear_status(#todo{status=S, who=W} = R) ->
% Inside this function, S and W are bound to the field
% values in the record
% R is the entire record
R#todo{status=finished}.
% Case Primitive
filter(P, [H|T]) ->
case P(H) of
true -> [H|filter(P,T)];
false -> filter(P,T)
end;
filter(P, []) ->
[].
% BIFs are functions that are built into Erlang. They belong to the module erlang and are
% auto-imported into every module
tuple_to_list({12, cat, "hello"}). % Returns [12, cat, "hello"]
% apply method Erlang's equivalent of symbol_to_proc?
% Joe Armstrong's book warns that this should be used sparingly, as compiler optimizations
% cannot be used in such cases of metaprogramming.
apply(erlang, atom_to_list, [hello]) % Returns "hello"
% Macros are expanded by the Erlang preprocessor,
% when an expression of the form ?MacroName is encountered
% ?FILE expands to current filename, ?MODULE expands to current module name
% and ?LINE expands to current line number
-define(macro1(X,Y), {a,X,Y}).
% The function below evaluates to
% foo(A) ->
% {a, A+10, b}.
foo(A) ->
?macro1(A+10, b)
% Running an Erlang module outside the Erlang shell
-module(factorial).
-export([main/1]).
main([A]) ->
I = list_to_integer(atom_to_list(A)),
F = fac(I),
io:format("factorial ~w = ~w~n", [I, F]),
init:stop().
fac(0) -> 1;
fac(N) -> N * fac(N-1).
% To compile and run it
$ erlc factorial.erl
$ erl -noshell -s factorial main 25
% Concurrency Terminology
% The spawn function creates a new concurrent process that evaluates Fun
% The new process runs in parallel with the caller.
Pid = spawn(Fun).
% The ! function sends a message to process Pid. Message sending is asynchronous.
Pid ! Message
% Concurrent Programming Basics
-module(area_server_final).
-export([start/0, area/2]).
start() -> spawn(fun loop/0).
area(Pid, What) ->
rpc(Pid, What).
rpc(Pid, Request) ->
Pid ! {self(), Request},
receive
{Pid, Response} ->
Response
end.
loop() ->
receive
{From, {rectangle, Wd, Ht}} ->
From ! {self(), Wd * Ht},
loop();
{From, {circle, R}} ->
From ! {self(), 3.14159 * R * R},
loop();
{From, Other} ->
From ! {self(), {error, Other}},
loop()
end.
% To Actually start the server
Pid = area_server_final:start().
% Calculates area of a rectangle
area_server_final:area(Pid, {rectangle, 10, 8}).
% Calculates area of a circle
area_server_final:area(Pid, {circle, 4}).
% Receive message with a timeout - sets a maximum time that the process will wait to receive a message.
% If no matching message has arrived within Time milliseconds of entering the receive expression,
% the process will stop waiting for a message and evaluate Expressions.
% Function below suspends a process for T milliseconds
sleep(T) ->
receive
after T ->
true
end.
% Simple Timer
-module(stimer)
-export([start/2, cancel/1])
% start function spawns a function with a timeout value
% and an actual function to execute
start(Time, Fun) -> spawn(fun() -> timer(Time, Fun) end).
cancel(Pid) -> Pid ! cancel
% If the message received, is the atom cancel, then return immediately
% otherwise wait for Time milliseconds, after which execute Fun.
timer(Time, Fun) ->
receive
cancel ->
void
after Time ->
Fun()
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment