Erlang (programming language)/Tutorials: Difference between revisions

From Citizendium
Jump to navigation Jump to search
imported>Eric Evers
imported>Eric Evers
No edit summary
 
(99 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{subpages}}
=Erlang Language Programming Tutorials=
=Erlang Language Programming Tutorials=
==History==
The erlang language was first written in prolog by Joe Armstrong. Ref:audio interview with Joe Armstrong from (http://www.se-radio.net). Joe is a known fan of prolog and borrowed much syntax from prolog in the design of erlang. This first prolog version of erlang was slow and motivated the creation of a virtual machine. Later an emulator called the BEAM(Bogdans's Erlang Abstract Machine, [http://www.erlang.se/publications/icfp97.ps.gz]) was written in C and is about 200,000 lines of code. The language name erlang was most likey used because it is also a (unit of phone connection); because of its original use in the phone company Ericsson.


==Overview==
==Overview==
==Simple Types==
==Advanced Types==
==Examples==
===Hello World (serial)===


====Code Example====
Erlang is a language created to do parallel programming with only message passing. Pure message passing makes MIMD ([[Parallel_computation]]) programming almost easy once you get friendy with it. No memory is shared.
 
Erlang is a concurency oriented language and the primary programming building block is a process.
-module(hello).
In erlang, processes are allowed to fail and are simply restarted.
-export([start/0]).
   
   
start() ->
Erlang has a purely functional core. A functional language is one that is based on [[Lambda_calculus]]. In lambda calculus variables have single assignment and behave like mathematical functions and functions are stateless. The advantages of referential transparency(single assignment) are many. Single assignment makes debugging easier(Joe Armstrong http://www.se-radio.net). Statelessness makes hot code swapping easy in erlang(Joe Armstrong). Referential transparency makes editing and code transformation easier(via find and replace). Functional languages have the advantage that syntax and semantics are unified. This unification makes it easier for code to modify itself safely, which facilitates meta-programming. Added benefits of functional programming include the ability to prove things like the correctness and equivalence between programs
    io:format("Hello, world!\n").
(see Functional Programming [http://en.citizendium.org/wiki/Functional_programming])


====Analysis of the example====
Print functions and message passing are side effects and are not part of the purely functional core of erlang.
One of the main ideas in erlang is to make as much of a program purely functional as possible and isolate the
functions that include side effects to improve stability. The theory is that the purely functional part is naturally well behaved.


The [[Hello World]] program (see above) appears in many programming languages books and articles as a cursory introduction into a language's [[syntax]]. The first hello world program was introduced in the book ''The C Programming Language''<ref name="K&R"/>.
Erlang has been around for 20 years and has a large library of functions available, especially for networking and the web.


<code>-module(hello)</code> tells the [[compiler]] to create a new module(library) called hello. The code tells us the file name for this code: hello.erl.
==Basic Erlang==


<code>-export([start/0]). </code> exports a function named start with 0 arguments to the world outside of this module called hello.
:[[/Command Line|Get to know the Command Line]]
:[[/Quick_tips|Quick tips]]
:[[/Terms|Terms]]
:[[/Pattern Matching|Pattern Matching]]
:[[/Expressions|Expressions]]
:[[/Functions|Functions]]
:[[/guards|Guards]]
:[[/Modules|Modules]]
:[[/Errors|Errors]] - working with exceptions
:[[/Processes|Processes and Messages]]
:[[/Trap_exit|Trapping Exit Signals]]
:[[/Timeouts|Timeouts]]
:[[/Macros|Macros]]
:[[/Techniques of Recursion|Techniques of Recursion]]
:[[/List Comprehensions|List Comprehensions]]
:[[/List Comments/]]


<code> start() -> </code> tells the compiler that there is a [[function]] named start() with no arguments.  
==Syntax==
Functions are defined by the domain of the arguments and the number of arguemnts. A function ends with a period. A function over a particular domain(set of inputs) is separated by a semicolon. The arrow shows how a particular function of a particular value or variable maps to an output.


<code>io:format("Hello, world!\n").</code> will make the program output <code>Hello, world!</code> and a new line (<code>\n</code>) on the screen.
fact(0) -> 1;
fact(N) when is_integer(N) ->  
    fact(N-1)*N.


===Hello World (parallel)===
:[[Erlang_programming_language/Tutorials/Advanced_syntax|Advanced Syntax]]


====Parallel Hello World====
==Simple Types==
<pre>
-module(tree_hello).                                                  % 1
-export([start/0, speak/1]).                                          % 2
                                                                      % 3
start() ->                                                            % 4
Pid1 = spawn( tree_hello, speak,[ 1 ]),                        % 5
Pid2 = spawn( tree_hello, speak,[ 2 ]),                        % 6
        Pid1 ! {hello, world},                                        % 7
        Pid2 ! {hello, world},                                        % 8
done.                                                          % 9
                                                                      % 10
speak(N) ->                                                            % 11
        receive                                       % 12
{hello, world} ->                               % 13
                      io:format("Hello, world! ~w \n", [N])          % 14
end.                                                          % 15


Basic types in erlang include:
*atom - alice
*integer - 3
*float - 3.1415
*pid - a process id number <0.42.0>
*list - [ things in square brackets ]
*tuple - { things in curly braces }


==========================================================================           
==Advanced Types==
*binary - a binary data block, <<42>>
*function - a function, F = fun(X) -> X*X end.
*port - a path for data to flow to the outside world
*reference - a unique id over all processes
*record - the standard erlang data structure


output
==Modules==
--------------------
tree_hello:start().
hello world! 1
hello world! 2
done
</pre>
====Analysis of the example====
Here is a simple hello world in the parallel spirit of erlang. The program, par_hello, will create 3 processes, one manager process called "start( )" and 2 worker processes called speak(1) and speak(2) in a tree like relationship. Start( ) creates speak(1) and speak(2), then start( ) sends a message to each worker. The message is {hello, world}. Each worker process responds by printing out "hello world". All three are running simultaneously when line 7 starts.


Lines 1 to 4: see serial "hello world".
===Adding/Replacing Modules===
Line 5 spawns a process called speak giving it one argument with the value 1.
Erlang is picky about updating or replacing modules of the same name.
  Line 5 also creates a variable Pid1 and gives it the processes id number of speak(1).
You should completely remove the old module code from the directory tree,
Line 6 spawns a process called speak giving it one argument with the value 2.
not just rename the containing directory.
  Line 6 also creates a variable Pid2 and gives it the process id number of speak(2).
Line 7 uses the Pid1(process id number of speak(1) to send a message to speak(1).
Line 8 uses the Pid2(process id number of speak(2) to send a message to speak(2).
Line 9 "done" is an arbitrary atom that finishes the function start( ).
Line 10 is a call to print formated text from the input/output(io) module(library).
Line 11 starts the function speak(N).
Line 12 starts to listen for a message.
Line 13 lists the message that is received
Line 14 shows what happens when the message in 13 is received.
  Line 14 prints out "hello world 1" if N is one or "hello world 2" if N is 2


Note: bang, ! in erlang means "send the following message".
===Popular Modules===
:[[Erlang_programming_language/Tutorials/Math|math]]
:[[Erlang_programming_language/Tutorials/gb_sets|gb_sets]]
:[[Erlang_programming_language/Tutorials/Lists|lists]]
:[[Erlang_programming_language/Tutorials/regexp|regexp: Regular Expressions]]


===Prime Sieve (parallel with linda type coordination)===
===Nonstandard Modules===
:[[Erlang_programming_language/Tutorials/eunit|Eunit]] Unit Testing Module


How many processes can this program use?
==Object Oriented Programming with erlang==
This program creates as many sieves as the square root of the
numbers in the matrix. If we are looking for the primes below
100 then there are ~10 parallel sieve processes.
Actually, most of the seive processes are halted and only
(the number of prime numbers under the square root of Max)
processes are left at the end. This allows an easy parallelism
of 10 for 100 and 100 for 10000 with little modification.


====Prime Sieve Program (parallel)====
Behaviours
:[[Erlang_programming_language/Tutorials/behaviours|Behaviours]]


    -module(primes).
Nonstandard OOP with erlang
:[[Erlang_programming_language/Tutorials/erlangOOP|Objects with erlang]]


    % This is a simple linda tuplespace. Here we use it to find primes numbers.
==Functional Programming with erlang==
    % This tuple-space can not have duplicate tuples, but with a prime sieve it does
    %  not matter.


    -compile(export_all).
:[[Erlang_programming_language/Tutorials/Folding|Fun with folding]]
:[[Erlang_programming_language/Tutorials/Iterator|Iterator]]
:[[Erlang_programming_language/Tutorials/Simplify|Simplify Numeric Types]] (auto-demotion of numerical types)


    start() -> start(100). % defualt value for max is 100
==Example programs==
    start(Max) ->
   
        io:format("  Loading ~w numbers into matrix (+N) \n ", [ Max ] ),
:[[Erlang_programming_language/Tutorials/Hello|Hello World (Serial)]]
        Lid = spawn_link( primes, linda, [Max, [], [] ]),
:[[Erlang_programming_language/Tutorials/Tree_Hello|Hello World (parallel) ]]
        Sqrt = round(math:sqrt(Max)+0.5), 
:[[Erlang_programming_language/Tutorials/Linda_Sieve|Prime Sieve with Linda]]
        io:format(" Sqrt(~w) + 1 = ~w \n " , [Max,Sqrt] ), 
:[[Erlang_programming_language/Tutorials/Agents|Autonomous Agents in Erlang]] -- def: [[Autonomous Agent]].
        io:format(" Tuple space is started ~n ",[]), 
        io:format(" ~w sieves are spawning (+PN) ~n ", [Sqrt] ),
        io:format(" Non prime sieves are being halted (-PN) ~n ", [] ),
        % load numbers into tuplespace
        % and spawn seive process
        spawn( primes, put_it, [Max, Max, Lid] ).


    start_sieves(Lid) ->
==OTP==
        Lid ! {self(), get, all, pids}, 
Design of OTP programs
        receive
:[[Erlang_programming_language/Tutorials/otp_design|otp_design]]
            {lindagram, pids, Pids} -> done
OTP Behaviours
        end,
  client-server
        start_sieve_loop(Pids).
  event-handler
  :[[Erlang_programming_language/Tutorials/gen_server|gen_server]]
  hot-standby
  keep-me-alive
  supervision-tree
  upgrade-handler
  worker-supervisor


    start_sieve_loop([]) -> done;
    start_sieve_loop([Pid|Pids]) ->
        receive
        after 100 -> done
        end,
        Pid ! {start},
        start_sieve_loop(Pids).


    spawn_sieves( _Max, Sqrt, _Lid, Sqrt ) -> done; 
==Databases==
    spawn_sieves( Max, Inc, Lid, Sqrt ) ->
        T = 1000,
        Pid = spawn( primes, sieve, [ Max, Inc+Inc, Inc, Lid, T ]),
        Name = list_to_atom("P" ++ integer_to_list(Inc)),
        Lid ! {put, pid, Name},
        register( Name, Pid),
        io:format(" +~s ", [atom_to_list(Name)]),
        spawn_sieves( Max, Inc+1, Lid, Sqrt ).


    put_it(Max, N, Lid) when N =< 1 ->
:[[Erlang_programming_language/Tutorials/ETS|ETS programming]]
        Sqrt = round(math:sqrt(Max)+0.5),
:[[Erlang_programming_language/Tutorials/DETS|DETS programming]]
        spawn_sieves( Max, 2, Lid, Sqrt ); 
:[[Erlang_programming_language/Tutorials/Mnesia|Mnesia database]]


    put_it(Max, N,Lid) when N > 1 ->
==Advanced Erlang==
        receive
:[[Erlang_programming_language/Tutorials/Yecc|Making parsers with yecc]]
        after 0 ->
:[[Erlang_programming_language/Tutorials/Evaluation|Evaluation]]
            Lid ! {put, N, N},
            if
                N rem 1000 == 0 ->
                    io:format(" +~w ", [N]);
                true -> done
            end,
            put_it(Max, N-1,Lid)
        end.


    % the 2 sieve starts last and has the most to do so it finishes last
==Glossary of Erlang Terms==
    sieve(Max, N, 2, Lid, _T) when N > Max ->
  Call:     a Synchronous message between processes
        io:format("final sieve ~w done, ~n", [2] ),
  Cast:     an Asynchronous message between processes
        Lid ! {dump,output};
   Reference: an data type that provides a unique mark of identification
 
            you can generate an id with the command:
    sieve(Max, N, Inc, _Lid, _T) when N > Max ->   
            erlang:make_ref()
        io:format("sieve ~w done ", [Inc] );
 
    sieve(Max, N, Inc, Lid, T) when N =< Max -> 
        receive
        after
            T -> NT = 0 
        end,
        receive
            {lindagram,Number} when Number =/= undefined ->
                clearing_the_queue;
            {exit} -> exit(normal)
        after
            1 -> done
        end,
 
        % remove multiple of number from tuple-space
        Lid ! {self(), get, N},
        Some_time = (N rem 1000)==0,
        if Some_time -> io:format("."); true -> done end,
 
        % remove (multiple of Inc) from sieve-process space
        Name = list_to_atom("P" ++ integer_to_list(N)),
        Exists = lists:member( Name, registered()),
        if
            Exists ->
                Name ! {exit},
                io:format(" -~s ", [atom_to_list(Name)] );
            true -> done
        end,
        sieve(Max, N+Inc, Inc, Lid, NT).        % next multiple
       
    %% linda is a simple tutple space
    %%    if it receives no messages for 2 whole seconds it dumps its contents
    %%    as output and halts
 
    linda(Max, Keys, Pids) ->
        receive
        {put, pid, Pid} ->
            linda(Max, Keys, Pids++[Pid]);
        {put, Name, Value} ->
            put( Name, Value),
            linda(Max, Keys++[Name], Pids);
        {From, get, Name} ->
            From ! {lindagram, get( Name)},
            erase( Name ),                          % get is a desructive read 
            linda(Max, Keys--[Name],Pids);
        {From, get, all, pids} ->
            From ! {lindagram, pids, Pids},
            linda(Max, Keys, Pids );
        {From, get, pid, Pid} ->
            L1 = length( Pids ),
            L2 = length( Pids -- [Pid]),
            if
                L1 > L2 ->  % if it exists
                    From ! {lindagram, pid, Pid};
                true ->
                    From ! {lindagram, pid, undefined}
            end,
            linda(Max, Keys, Pids );
        {dump,output} ->
            io:format(" ~w final primes remain: ~w ~n ", [length(Keys),  lists:sort(Keys) ])
        after (100*Max) -> % if there is not tuple action after some time then print the results
            io:format(" ~w primes remain: ~w ~n ", [length(Keys),  lists:sort(Keys) ])
        end.
 
====Sample Output for Prime Sieve ====
c(primes).
primes:start(1000).
  Loading 1000 numbers into matrix (+N)
  Sqrt(1000) + 1 = 32
  Tuple space is started
  32 sieves are spawning (+PN)
  Non prime sieves are being halted (-PN)
   +1000 <0.46.0>
+P2  +P3  +P4  +P5  +P6  +P7  +P8  +P9  +P10 
+P11  +P12  +P13  +P14  +P15  +P16 
+P17  +P18  +P19  +P20  +P21  +P22  +P23  +P24 
+P25  +P26  +P27  +P28  +P29  +P30 
+P31  -P8  -P6  -P4  -P9  -P12  -P10  -P15 
-P15  -P18  -P14  -P21  -P21  -P22 
-P26  -P20  -P24  -P25  -P27  -P28  -P30  -P30  -P16
sieve 31 done sieve 29 done
sieve 19 done sieve 23 done sieve 11 done
sieve 13 done sieve 17 done sieve 7 done
.sieve 5 done sieve 3 done .final sieve 2 done,
168 final primes remain:  
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,
71,73,79,83,89,97,
101,103,107,109,113,127,131,137,139,149,151,157,163,
167,173,179,181,191,193,197,199,
211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,
307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,
401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,
499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,
601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,
701,709,719,727,733,739,743,751,757,761,769,773,787,797,
809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,
907,911,919,929,937,941,947,953,967,971,977,983,991,997]
 
===Autonomous Agents===
 
See definition of [[Autonomous Agent]].
 
====Dynamic timeout based initiative switching====
 
=====Explanation of the code in jungle.erl=====
 
Here we have a simple chat-bot agent called person/4. We create two instances of it called Tarzan and Jane. They talk to each other. Each has a timeout. The timeout is the lenght of time one will wait before they intiate conversation. The initial timeout of Jane is set to 10 seconds. The initial timeout of Tarzan is set to 8 seconds. Because of the initial values, Tarzan will speak first and Jane will respond. Both timeouts start over but keep the same values. Again, Tarzan speaks first and Jane responds. Now things get interesting. The agent can tell if the conversation is repeating. If the conversation repeats then special messages are sent to cause a swap in the relative levels of timeout. Now Tarzan waits longer than Jane and Jane has a chance to speak first. Now, Jane speaks first twice. Then they swap initiative again. Since the processes are autonomous, we need to stop them with a quit program called jungle:quit().
 
=====Example program listing: jungle.erl=====
                                                         
-module( jungle ).
-compile(export_all).
   
%% This program shows how chat-bot agents can exchange initiative(lead) while in conversation.
%%  Start with start().
%%  End with quit().
 
start() ->
    register( tarzan, spawn( jungle, person, [ tarzan,  8000, "", jane ]  ) ),
    register( jane, spawn( jungle, person,  [ jane,  10000, "", tarzan ] ) ),
    "Dialog will start in 5ish seconds, stop program with jungle:quit().".
                                                                                         
quit() ->
    jane ! exit,
    tarzan ! exit.
    
    
%% Args for person/4
==Projects using erlang==
%%  Name:  name of agent being created/called
*CouchDB - a scalable database for Apache
%%  T:    timeout to continue conversation
*Wings3D - a 3-D editor
%%  Last:  Last thing said
%%  Other: name of other agent in conversation
 
person( Name, T, Last, Other ) ->
    receive
        "hi" ->
            respond( Name, Other, "hi there \n " ),
            person( Name, T, "", Other );
        "slower" ->
            show( Name, "i was told to wait more " ++ integer_to_list(round(T*2/1000))),
            person( Name, T*2, "", Other );
        "faster" ->
            NT = round( T/2 ),
            show( Name, "I was told to wait less " ++ integer_to_list(round(NT/1000))),
            person( Name, NT, "", Other );
        exit ->
            exit(normal);
        _AnyWord ->
            otherwise_empty_the_queue,
            person( Name, T, Last, Other )
    after T ->
        respond( Name, Other, "hi"),
        case Last of
            "hi" ->
            self() ! "slower",
            sleep( 2000),                  % give the other time to print
            Other ! "faster",
            person( Name, T, "", Other );
        _AnyWord ->
            person( Name, T, "hi", Other )
        end
    end.
                                                                                              %
respond( Name, Other, String ) ->
    show( Name, String ),
    Other ! String.
                                                                                              %
show( Name, String ) ->
    sleep(1000),
    io:format( " ~s -- ~s \n ", [ Name, String ] ).
                                                                                              %
sleep(T) ->
    receive
    after T ->
        done
    end.
% ===========================================================>%


====Sample output from: jungle.erl====
==References==
 
Sample output:
 
  18> c(jungle).
  {ok,jungle}
 
  19> jungle:start().
  jane_and_tarzan_will_start_in_5_seconds
 
  tarzan -- hi
  jane -- hi there
 
  tarzan -- hi
  jane -- hi there
 
  jane -- I was told to wait less: 5
  tarzan -- I was told to wait more: 16
 
  jane -- hi
  tarzan -- hi there
 
  jane -- hi
  tarzan -- hi there
 
  tarzan -- I was told to wait less: 8
  jane -- I was told to wait more: 10
 
  tarzan -- hi
  jane -- hi there
 
  tarzan -- hi
  jane -- hi there
 
  jane -- I was told to wait less: 5
  tarzan -- I was told to wait more: 16
 
  jane -- hi
  tarzan -- hi there
 
20> jungle:quit().
exit


==References==
[http://www.erlang.org/doc/man/| 1 - Erlang Man Pages at Erlang,org]

Latest revision as of 14:28, 24 August 2009

This article is developing and not approved.
Main Article
Discussion
Related Articles  [?]
Bibliography  [?]
External Links  [?]
Citable Version  [?]
Tutorials [?]
 
Tutorials relating to the topic of Erlang (programming language).

Erlang Language Programming Tutorials

History

The erlang language was first written in prolog by Joe Armstrong. Ref:audio interview with Joe Armstrong from (http://www.se-radio.net). Joe is a known fan of prolog and borrowed much syntax from prolog in the design of erlang. This first prolog version of erlang was slow and motivated the creation of a virtual machine. Later an emulator called the BEAM(Bogdans's Erlang Abstract Machine, [1]) was written in C and is about 200,000 lines of code. The language name erlang was most likey used because it is also a (unit of phone connection); because of its original use in the phone company Ericsson.

Overview

Erlang is a language created to do parallel programming with only message passing. Pure message passing makes MIMD (Parallel_computation) programming almost easy once you get friendy with it. No memory is shared. Erlang is a concurency oriented language and the primary programming building block is a process. In erlang, processes are allowed to fail and are simply restarted.

Erlang has a purely functional core. A functional language is one that is based on Lambda_calculus. In lambda calculus variables have single assignment and behave like mathematical functions and functions are stateless. The advantages of referential transparency(single assignment) are many. Single assignment makes debugging easier(Joe Armstrong http://www.se-radio.net). Statelessness makes hot code swapping easy in erlang(Joe Armstrong). Referential transparency makes editing and code transformation easier(via find and replace). Functional languages have the advantage that syntax and semantics are unified. This unification makes it easier for code to modify itself safely, which facilitates meta-programming. Added benefits of functional programming include the ability to prove things like the correctness and equivalence between programs (see Functional Programming [2])

Print functions and message passing are side effects and are not part of the purely functional core of erlang. One of the main ideas in erlang is to make as much of a program purely functional as possible and isolate the functions that include side effects to improve stability. The theory is that the purely functional part is naturally well behaved.

Erlang has been around for 20 years and has a large library of functions available, especially for networking and the web.

Basic Erlang

Get to know the Command Line
Quick tips
Terms
Pattern Matching
Expressions
Functions
Guards
Modules
Errors - working with exceptions
Processes and Messages
Trapping Exit Signals
Timeouts
Macros
Techniques of Recursion
List Comprehensions
List Comments

Syntax

Functions are defined by the domain of the arguments and the number of arguemnts. A function ends with a period. A function over a particular domain(set of inputs) is separated by a semicolon. The arrow shows how a particular function of a particular value or variable maps to an output.

fact(0) -> 1;
fact(N) when is_integer(N) -> 
    fact(N-1)*N.
Advanced Syntax

Simple Types

Basic types in erlang include:

  • atom - alice
  • integer - 3
  • float - 3.1415
  • pid - a process id number <0.42.0>
  • list - [ things in square brackets ]
  • tuple - { things in curly braces }

Advanced Types

  • binary - a binary data block, <<42>>
  • function - a function, F = fun(X) -> X*X end.
  • port - a path for data to flow to the outside world
  • reference - a unique id over all processes
  • record - the standard erlang data structure

Modules

Adding/Replacing Modules

Erlang is picky about updating or replacing modules of the same name. You should completely remove the old module code from the directory tree, not just rename the containing directory.

Popular Modules

math
gb_sets
lists
regexp: Regular Expressions

Nonstandard Modules

Eunit Unit Testing Module

Object Oriented Programming with erlang

Behaviours

Behaviours

Nonstandard OOP with erlang

Objects with erlang

Functional Programming with erlang

Fun with folding
Iterator
Simplify Numeric Types (auto-demotion of numerical types)

Example programs

Hello World (Serial)
Hello World (parallel)
Prime Sieve with Linda
Autonomous Agents in Erlang -- def: Autonomous Agent.

OTP

Design of OTP programs

otp_design

OTP Behaviours

 client-server 
 event-handler 
 :gen_server 
 hot-standby 
 keep-me-alive 
 supervision-tree 
 upgrade-handler 
 worker-supervisor 


Databases

ETS programming
DETS programming
Mnesia database

Advanced Erlang

Making parsers with yecc
Evaluation

Glossary of Erlang Terms

 Call:      a Synchronous message between processes
 Cast:      an Asynchronous message between processes
 Reference: an data type that provides a unique mark of identification
            you can generate an id with the command:
            erlang:make_ref()
 

Projects using erlang

  • CouchDB - a scalable database for Apache
  • Wings3D - a 3-D editor

References

1 - Erlang Man Pages at Erlang,org