Created
September 2, 2008 07:19
-
-
Save arunthampi/8388 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
% 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