Home Navigation

Friday 29 April 2022

Erlang start nodes and rebar3 package

Create rebar3 app:

Create:  $rebar3 new release <app name>
Compile$rebar3 compile
Run$rebar3 shell
Update dependency$rebar3 update
Packagerebar3 as prod release
Run the package:  $
/<app name>/bin/<app name> foreground
Publishing to hex: $ rebar3 hex publish -r  <test_repo>
refhttps://rebar3.readme.io/docs/commands


Start a node in Erlang:


Creating node
:
    $erl -name server@192.168.0.149 -setcookie mathcluster
    $erl -name client@192.168.0.90 -setcookie mathcluster
Test the connection:
    >net_adm:ping('server@192.168.0.149').
List the nodes: >nodes().

Thursday 7 April 2022

Erlang cheatsheet

Erlang

Erlang is a programming language used to build massively scalable soft real-time systems with requirements on high availability. Some of its uses are in telecoms, banking, e-commerce, computer telephony and instant messaging. Erlang's runtime system has built-in support for concurrency, distribution and fault tolerance.


Installing erlang:

https://www.erlang-solutions.com/downloads/

https://tecadmin.net/install-erlang-on-centos/


Erlang basic syntax:
Compiling and running:
Start erlang shell just typing in the command line erl
Compile: >c(module_name).
Running: >module_name:function().

String concat:

> “earl” ++ “ang”. 
> string:concat(“erl” , “ang”).

 

Lists:

1> Insert = [2,4,5,6].
     [2,4,5,6]
2> Full = [1, Insert, 16,32].
     [1,[2,4,5,6],16,32]
3> Neat = lists:flatten(Full).
    [1,2,4,5,6,16,32]

Combine/merge:
> A = [1,3,5].
[1,3,5]
> B = [2,4,6].
[2,4,6]
> C = A ++ B.
[1,3,5,2,4,6]
> D = lists:append(A,B).
[1,3,5,2,4,6] 


Split by head and tail:
> [Head | Tail] = [1,2,4].
> Head.
1
> Tail.
[2,4]

Adding to a list:

> Y=[1,2 | [3]].
[1,2,3]
> Z=[1,2 | 3].
[1,2|3]

zip/unzip mixing list and tuples:

> List1=[1,2,4,8,16].
[1,2,4,8,16]
> List2=[a,b,c,d,e].
[a,b,c,d,e]
> TupleList=lists:zip(List1,List2).
[{1,a},{2,b},{4,c},{8,d},{16,e}]
> SeparateLists=lists:unzip(TupleList).
{[1,2,4,8,16],[a,b,c,d,e]}

Keystone/ key replace:

> Initial=[{1,tiger}, {3,bear}, {5,lion}].
[{1,tiger},{3,bear},{5,lion}]
> Second=lists:keystore(7,1,Initial,{7,panther}).
[{1,tiger},{3,bear},{5,lion},{7,panther}]
> Third=lists:keystore(7,1,Second,{7,leopard}).
[{1,tiger},{3,bear},{5,lion},{7,leopard}]
>Fourth=lists:keyreplace(6,1,Third,{6,chipmunk}).
 [{1,tiger},{3,bear},{5,lion},{7,leopard}]
> Animal5=lists:keyfind(5,1,Third).
{5,lion}
> Animal6=lists:keyfind(6,1,Third).
False

Higher-order functions, functions that accept other functions as arguments

lists:forach

1> Print = fun(Value) -> io:format("~p~n",[Value]) end.

#Fun<erl_eval.44.65746770>

2> List = [1,2,3,4,5,6].

[1,2,3,4,5,6]

3> lists:foreach(Print, List).

1

2

3

4

5

6

Ok


lists:map

> Square = fun(Value)->Value*Value end.

#Fun<erl_eval.44.65746770>

> lists:map(Square, List).

[1,4,9,16,25,36]

 

OR

> [Square(Value) || Value <- List].

> [Value * Value || Value <- List].

> List2 = [10 | List].                           

[10,1,2,3,4,5,6]

In list difference between | and || are, | concat and || map operation.

 

Filter:

> LessThanFive = fun(Value)-> (Value<5) and (Value>=0) end. 

#Fun<erl_eval.44.65746770>

> lists:filter(LessThanFive,List).                         

[1,2,3,4]

> [Value || Value <- List, Value<5, Value>=0].

[1,2,3,4]


> Weather = [{toronto, rain}, {montreal, storms}, {london, fog},  

> {paris, sun}, {boston, fog}, {vancouver, snow}].              

[{toronto,rain},

 {montreal,storms},

 {london,fog},

 {paris,sun},

 {boston,fog},

 {vancouver,snow}]

> 

> FoggyPlaces = [X || {X, fog} <- Weather].

[london,boston]


Maps:

ModuleSyntax
maps:new/1#{}
maps:put/3Map#{Key => Val}
maps:update/3Map#{Key := Val}
maps:get/2Map#{Key}
maps:find/2#{Key := Val} = Map


>Pets = #{"dog" => "al", "fish" => "dory"}.
>Pets#{"cat" => "tiger"}.
   #{"cat" => "tiger","dog" => "al","fish" => "dory"}
> Pets#{"dog":="Pok"}.
  #{"dog" => "Pok","fish" => "dory"}
> maps:get("dog", Pets).
"al"
> #{"fish" := CatName, "dog" := DogName} = Pets.
#{"dog" => "al","fish" => "dory"}

Process:

Sending message to a process using !

> self() ! test1.

test1 message will be waiting in the mail box

You can retrieve by receive block

> receive X -> X end.

 

Spawning a process:

> Pid=spawn(bounce,report,[]).

> Pid ! “Hello World”.

 

receive XXX -> XXX end.

exit(whereis(registered pid), kill).

flush().

erlang:process_info(self(), messages)

spawn(?ModuleName, <Function name> , <argument>)


Registrering a process:

register(<name to be registered> ,<Process id>).

whereis/1 to find the process

unregister/1. To unregister a process


Parent = ?current_span_ctx,

io:format("Parent: ~p~n",[Parent]),

Span2Ctx = Parent#span_ctx{trace_id=TraceId},

?set_current_span(Span2Ctx),


Record:

Records let you create data structures that use names to connect with data rather than order

For example

-record(planemo, {name, gravity, diameter, distance_from_sun}).

-record(tower, {location, height=20, planemo=earth, name}).


The command rr (for read records) lets you bring this into the shell:

 

1> rr("records.hrl").

[planemo,tower]

 

> Tower1=#tower{location="NYC", height=241, name="Woolworth Building"}.

 

Accessing value from a record

> Tower1#tower.planemo.

 

Pattern matching to extract value:

 

#tower{location=L5, height=H5} = Tower1.

 

Update record value:

 

Tower1a=Tower1#tower{height=512}.


ETS:

Erlang Term Storage (ETS) is a simple but powerful in-memory collection store.

 

Creating and Populating a Table

PlanemoTable=ets:new(planemos, [named_table, {keypos, #planemo.name}]),

ets:info(PlanemoTable).

 

To see what’s in the table

 

ets:tab2list(<record name eg, planemos>).

Lookup: ets:lookup(planemos,eris).

 

11> Result=hd(ets:lookup(planemos,eris)).

#planemo{name = eris,gravity = 0.8,diameter = 2400,

         distance_from_sun = 10210.0}

12> Result#planemo.gravity.

 

Overwriting Values

ets:insert(planemos, #planemo{ name=mercury,

 gravity=3.9, diameter=4878, distance_from_sun=57.9 }).

true

  

ets:fun2ms 

ets:match

ets:select

ets:delete

ets:first

ets:next

ets:last


Mnesia:

mnesia:create_schema([node()]).

mnesia:start().

mnesia:table_info/2


mnesia:transaction(fun() -> mnesia:read(planemo,neptune) end).

mnesia:first

mnesia:next

 

(If you want to change where Mnesia stores data, you can start Erlang with some extra options: erl -mnesia dir " path ". The path will be the location Mnesia keeps any disk-based storage.)

Apart from the setup, the key thing to note is that all of the writes are contained in a fun that is then passed to mnesia:transaction to be executed as a transaction. Mnesia will restart the transaction if there is other activity blocking it, so the code may get executed repeatedly before the transaction happens. Because of this, do not include any calls that create side effects to the function you’ll be passing to mnesia:transaction, and don’t try to catch exceptions on Mnesia functions within a transaction. If your function calls mnesia:abort/1 (probably because some condition for executing it wasn’t met), the transaction will be rolled back, returning a tuple beginning with aborted instead of atomic.


Query list:

 

mnesia:transaction(

  fun() ->

    qlc:e(

      qlc:q( [X || X <- mnesia:table(planemo)] )

    )

  end

) 

mnesia:transaction(

  fun() ->

    qlc:e(

      qlc:q( [{X#planemo.name, X#planemo.gravity} ||

               X <- mnesia:table(planemo),

               X#planemo.gravity < 9.8] )

    )

  end

)

mnesia:transaction(

  fun() ->

    qlc:e(

      qlc:q( [X || X <- mnesia:table(planemo),

                   X#planemo.gravity < 9.8] )

    )

  end

)


OTP

OTP is set of Erlang libraries and design principles providing middle-ware to develop these systems. It includes its own distributed database, applications to interface towards other languages, debugging and release handling tools.

 

OTP Gen server:

  • Generic server specific behaviour
  • Supports server like component 
  • business logic lives in app specific callback module

OTP formalizes those activities, and a few more, into a set of behaviors (or behaviours—this was originally created with British spelling). The most common behaviors are gen_server (generic server) and supervisor, though gen_fsm (finite state machine) and gen_event are also available. The application behavior lets you package your OTP code into a single runnable (and updatable) system.

 

OTP Building blocks:

  • process spawning
  • sending and receiving messages
  • process linking and monitoring

Application Behavior

  • application provides an entry point for an OTP-compliant app
  • Allows multiple Erlang components to be combined into a system
  • Erlang apps can declare their dependencies on other apps

Async Events

  • send_event: asynchronously send event into gen_fsm process
  • calls Module:StateName/2,where StateName is a function named for the current state
  • send_all_state_event: asynchronously send event into gen _fm process calls Module handle_event, allows handling event regardless of current state. current state name is passed into handle_event

Sync Events

  • sync _send_event: synchronously send event into gen_fsm process calls Module:StateName/3,where StateName is a function named for the current state
  • sync_send_all_state_event: synchronously send event into gen_fm process
  • calls Module:handle_sync_event,allows handling event regardless of current state. current state name is passed into handle_sync_event

{ok, Pid} = drop_sup:start_link().

1> c(drop_app).

{ok,drop_app}

2> code:add_path("ebin/").

true

3> application:load(drop).

ok

4> application:loaded_applications().

[{kernel,"ERTS  CXC 138 10","2.15.2"},

 {drop,"Dropping objects from towers","0.0.1"},

 {stdlib,"ERTS  CXC 138 10","1.18.2"}]

5> application:start(drop).

ok

6> gen_server:call(drop, 60).

{ok,34.292856398964496}


REBAR3 

Rebar3 is an Erlang tool that makes it easy to create, develop, and release Erlang libraries, applications, and systems in a repeatable manner. If you are from java programming, it is like maven. Hex is the repository to publish erlang library and searching, downloading library.

For installing rebar3 

https://github.com/erlang/rebar3

https://rebar3.readme.io/docs/getting-started

 

PATH=$PATH:$HOME/bin

export PATH=$PATH:~/.cache/rebar3/bin

 

Compile with rebar3: $rebar3 compile

Running with rebar3: $rebar3 shell

Publishing to hex: $ rebar3 hex publish -r test_repo


Erlang commands:

q()

Quits the shell and the Erlang runtime.

c(file)

Compiles the specified Erlang file.

b()

Displays all variable bindings.

f()

Clears all variable bindings.

f(X)

Clears specified variable binding.

h()

Prints the history list of commands.

e(N)

Repeats the command on line N.

v(N)

The return value of line N.

catch_exception(boolean)

Sets how strict the shell will be in passing errors.

rd(Name, Definition)

Defines a record type Name with contents specified by Definition.

rr(File)

Defines record types based on the contents of File.

rf()

Clears all record definitions. Can also clear specific definitions.

rl()

Lists all current record definitions.

pwd()

Gets the present working directory.

ls()

Lists files at the current location.


RESOURCES:

Dockerizing:

Git 2.0 installation:

Install java 11: yum -y install  java-11-openjdk java-11-openjdk-devel