Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
#######
#
# E-scripts on Erlang.
#
# Note 1: use the eev command (defined in eev.el) and the
# ee alias (in my .zshrc) to execute parts of this file.
# Executing this file as a whole makes no sense.
# An introduction to eev can be found here:
#
#   (find-eev-quick-intro)
#   http://angg.twu.net/eev-intros/find-eev-quick-intro.html
#
# Note 2: be VERY careful and make sure you understand what
# you're doing.
#
# Note 3: If you use a shell other than zsh things like |&
# and the for loops may not work.
#
# Note 4: I always run as root.
#
# Note 5: some parts are too old and don't work anymore. Some
# never worked.
#
# Note 6: the definitions for the find-xxxfile commands are on my
# .emacs.
#
# Note 7: if you see a strange command check my .zshrc -- it may
# be defined there as a function or an alias.
#
# Note 8: the sections without dates are always older than the
# sections with dates.
#
# This file is at <http://angg.twu.net/e/erlang.e>
#           or at <http://angg.twu.net/e/erlang.e.html>.
#        See also <http://angg.twu.net/emacs.html>,
#                 <http://angg.twu.net/.emacs[.html]>,
#                 <http://angg.twu.net/.zshrc[.html]>,
#                 <http://angg.twu.net/escripts.html>,
#             and <http://angg.twu.net/>.
#
#######




# «.debian»	(to "debian")


https://en.wikipedia.org/wiki/Erlang_(programming_language)
https://en.wikipedia.org/wiki/Elixir_(programming_language)

https://stackoverflow.com/questions/25322269/why-is-there-no-multi-line-commenting-support-in-erlang
https://stackoverflow.com/questions/30749094/multiline-comment-in-elixir






#####
#
# debian
# 2022dec15
#
#####

# «debian»  (to ".debian")
# (find-zsh "installeddebs | sort | grep erlang")
# (find-zsh "availabledebs | sort | grep erlang")
# (find-sh "grep-aptavail -P erlang")

# (find-status   "erlang")
# (find-vldifile "erlang.list")
# (find-udfile   "erlang/")
# (find-status   "erlang-base")
# (find-vldifile "erlang-base.list")
# (find-udfile   "erlang-base/")
# (find-status   "erlang-doc")
# (find-vldifile "erlang-doc.list")
# (find-udfile   "erlang-doc/")
# (find-status   "erlang-examples")
# (find-vldifile "erlang-examples.list")
# (find-udfile   "erlang-examples/")
# (find-status   "erlang-manpages")
# (find-vldifile "erlang-manpages.list")
# (find-udfile   "erlang-manpages/")
# (find-status   "erlang-src")
# (find-vldifile "erlang-src.list")
# (find-udfile   "erlang-src/")


* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
apti erlang erlang-manpages erlang-doc
apti erlang erlang-manpages erlang-src erlang-mode erlang-examples

erlang

# (find-status   "erlang-examples")
# (find-vldifile "erlang-examples.list")
# (find-udfile   "erlang-examples/")
# (find-fline "/usr/lib/erlang/lib/gs-1.5.11/examples/src/")
# (find-efunction 'erlang-shell-display)

# (find-status   "erlang-mode")
# (find-vldifile "erlang-mode.list")
# (find-udfile   "erlang-mode/")
# (find-fline "/usr/share/emacs/site-lisp/erlang/")
# (find-sitelispfile "erlang/erlang.el" "defun inferior-erlang")

(require 'erlang)
(require 'erlang-start)
(require 'erlang-unit)

# (find-status   "erlang-gs")
# (find-vldifile "erlang-gs.list")
# (find-udfile   "erlang-gs/")




http://learnyousomeerlang.com/starting-out-for-real


# (find-status   "erlang")
# (find-vldifile "erlang.list")
# (find-udfile   "erlang/")
# (find-status   "erlang-manpages")
# (find-vldifile "erlang-manpages.list")
# (find-udfile   "erlang-manpages/")

* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
erl


http://learnyousomeerlang.com
http://learnyousomeerlang.com/starting-out-for-real


* (eepitch-erl)
* (eepitch-kill)
* (eepitch-erl)
2 + 15.         % 17
49 * 100.       % 4900
1892 - 1472.    % 420
5 / 2.          % 2
5 div 2.        % 1
5 rem 2.        % 1
(50 * 100) - 4999.      % 1
-(50 * 100 - 4999).     % -1
-50 * (100 - 4999).     % 244950
2#101010.  % 42
8#0677.    % 447
16#AE.     % 174
One.                  % * 1: variable 'One' is unbound
One = 1.              % 1
Un = Uno = One = 1.   % 1
Two = One + One.      % 2
Two = 2.              % 2
Two = Two + 1.        % ** exception error: no match of right hand side value 3
two = 2.              % ** exception error: no match of right hand side value 2
47 = 45 + 2.          % 47
47 = 45 + 3.          % ** exception error: no match of right hand side value 48
_ = 14+3.       % 17
_.              % * 1: variable '_' is unbound

Unlike any other kind of variable, it won't ever store any value. Totally useless for now, but you'll know it exists when we need it.

Note: If you're testing in the shell and save the wrong value to a variable, it is possible to 'erase' that variable by using the function
f(Variable).. If you wish to clear all variable names, do f()..

These functions are there only to help you when testing and only work in the shell. When writing real programs, we won't be able to
destroy values that way. Being able to do it only in the shell makes sense if you acknowledge Erlang being usable in industrial scenarios:
it is wholly possible to have a shell being active for years without interruption... Let's bet that the variable X would be used more than
once in that time period.

* (eepitch-erl)
* (eepitch-kill)
* (eepitch-erl)
atom.                     % atom
atoms_rule.               % atoms_rule
atoms_rule@erlang.        % atoms_rule@erlang
'Atoms can be cheated!'.  % 'Atoms can be cheated!'
a.tom.                    % 'a.tom'
atom = 'atom'.            % atom
true and false.         % false
false or true.          % true
true xor false.         % true
not false.              % true
not (true and true).    % false
5 =:= 5.             % true
1 =:= 0.             % false
1 =/= 0.             % true
5 =:= 5.0.           % false
5 == 5.0.            % true
5 /= 5.0.            % false
1 < 2.          % true
1 < 1.          % false
1 >= 1.         % true
1 =< 1.         % true
5 + llama.      % ** exception error: bad argument in an arithmetic expression
5 =:= true.          % false
0 == false.          % false
1 < false.           % true
X = 10, Y = 4.          % 4
Point = {X,Y}.          % {10,4}
Point = {4,5}.          % {4,5}
{X,Y} = Point.          % {4,5}
X.                      % 4
{X,_} = Point.          % {4,5}
{_,_} = {4,5}.          % {4,5}
{_,_} = {4,5,6}.        % ** exception error: no match of right hand side value {4,5,6}
Temperature = 23.213.                    % 23.213
PreciseTemperature = {celsius, 23.213}.  % {celsius,23.213}
{kelvin, T} = PreciseTemperature.        % ** exception error: no match of right hand side value {celsius,23.213}
{point, {X,Y}}.                           % {point,{4,5}}
[1, 2, 3, {numbers,[4,5,6]}, 5.34, atom].  % [1,2,3,{numbers,[4,5,6]},5.34,atom]
[97, 98, 99].                              % "abc"
[97,98,99,4,5,6].                          % [97,98,99,4,5,6]
[233].                                     % "é"
[1,2,3] ++ [4,5].          % [1,2,3,4,5]
[1,2,3,4,5] -- [1,2,3].    % [4,5]
[2,4,2] -- [2,4].          % [2]
[2,4,2] -- [2,4,2].        % []
[1,2,3] -- [1,2] -- [3].          % [3]
[1,2,3] -- [1,2] -- [2].          % [2,3]
hd([1,2,3,4]).            % 1
tl([1,2,3,4]).            % [2,3,4]
List = [2,3,4].            % [2,3,4]
NewList = [1|List].        % [1,2,3,4]
[Head|Tail] = NewList.      % [1,2,3,4]
Head.                       % 1
Tail.                       % [2,3,4]
[NewHead|NewTail] = Tail.   % [2,3,4]
NewHead.                    % 2
[1 | []].                % [1]
[2 | [1 | []]].          % [2,1]
[3 | [2 | [1 | []] ] ].  % [3,2,1]
[2*N || N <- [1,2,3,4]].          % [2,4,6,8]
[X || X <- [1,2,3,4,5,6,7,8,9,10], X rem 2 =:= 0].          % [2,4,6,8,10]
RestaurantMenu = [{steak, 5.99}, {beer, 3.99}, {poutine, 3.50}, {kitten, 20.99}, {water, 0.00}].  % [{steak,5.99}, {beer,3.99}, {poutine,3.5}, {kitten,20.99}, {water,0.0}]
[{Item, Price*1.07} || {Item, Price} <- RestaurantMenu, Price >= 3, Price =< 10].          % [{steak,6.409300000000001},{beer,4.2693},{poutine,3.745}]

Of course, the decimals aren't rounded in a readable manner, but you get the point. The recipe for list comprehensions in Erlang is
therefore NewList = [Expression || Pattern <- List, Condition1, Condition2, ... ConditionN]. The part Pattern <- List is named a Generator
expression. You can have more than one!

5> [X+Y || X <- [1,2], Y <- [2,3]].
[3,4,4,5]

This runs the operations 1+2, 1+3, 2+2, 2+3. So if you want to make the list comprehension recipe more generic, you get: NewList =
[Expression || GeneratorExp1, GeneratorExp2, ..., GeneratorExpN, Condition1, Condition2, ... ConditionN]. Note that the generator
expressions coupled with pattern matching also act as a filter:

6> Weather = [{toronto, rain}, {montreal, storms}, {london, fog},   
6>            {paris, sun}, {boston, fog}, {vancouver, snow}].
[{toronto,rain},
 {montreal,storms},
 {london,fog},
 {paris,sun},
 {boston,fog},
 {vancouver,snow}]
7> FoggyPlaces = [X || {X, fog} <- Weather].
[london,boston]

If an element of the list 'Weather' doesn't match the {X, fog} pattern, it's simply ignored in the list comprehension whereas the =
operator would have thrown an exception.

There is one more basic data type left for us to see for now. It is a surprising feature that makes interpreting binary data easy as pie.

Speedometer with values in binary  

Bit Syntax!

Most languages have support for manipulating data such as numbers, atoms, tuples, lists, records and/or structs, etc. Most of them also
only have very raw facilities to manipulate binary data. Erlang goes out of its way to provide useful abstractions when dealing with
binary values with pattern matching taken to the next level. It makes dealing with raw binary data fun and easy (no, really), which was
necessary for the telecom applications it was created to help with. Bit manipulation has a unique syntax and idioms that may look kind of
weird at first, but if you know how bits and bytes generally work, this should make sense to you. You may want to skip the rest of this
chapter otherwise.

Bit syntax encloses binary data between << and >>, splits it in readable segments, and each segment is separated by a comma. A segment is
a sequence of bits of a binary (not necessarily on a byte boundary, although this is the default behaviour). Say we want to store an
orange pixel of true color (24 bits). If you've ever checked colors in Photoshop or in a CSS style sheet for the web, you know the
hexadecimal notation has the format #RRGGBB. A tint of orange is #F09A29 in that notation, which could be expanded in Erlang to:

1> Color = 16#F09A29.
15768105
2> Pixel = <<Color:24>>.
<<240,154,41>>

This basically says "Put the binary values of #F09A29 on 24 bits of space (Red on 8 bits, Green on 8 bits and Blue also on 8 bits) in the
variable Pixel." The value can later be taken to be written to a file. This doesn't look like much, but once written to a file, what you'd
get by opening it in a text editor would be a bunch of unreadable characters. When you read back from the file, Erlang would interpret the
binary into the nice <<240,151,41>> format again!

What's more interesting is the ability to pattern match with binaries to unpack content:

3> Pixels = <<213,45,132,64,76,32,76,0,0,234,32,15>>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
4> <<Pix1,Pix2,Pix3,Pix4>> = Pixels.
** exception error: no match of right hand side value <<213,45,132,64,76,32,76,
                                                        0,0,234,32,15>>
5> <<Pix1:24, Pix2:24, Pix3:24, Pix4:24>> = Pixels.
<<213,45,132,64,76,32,76,0,0,234,32,15>>

What we did on command 3 is declare what would be precisely 4 pixels of RGB colors in binary.
On expression 4, we tried to unpack 4 values from the binary content. It throws an exception, because we have more than 4 segments, we in
fact have 12! So what we do is tell Erlang that each variable on the left side will hold 24 bits of data. That's what Var:24 means. We can
then take the first pixel and unpack it further into single color values:

6> <<R:8, G:8, B:8>> = <<Pix1:24>>.
<<213,45,132>>
7> R.
213

"Yeah that's dandy. What if I only wanted the first color from the start though? will I have to unpack all these values all the time?"
Hah! Doubt not! Erlang introduces more syntactic sugar and pattern matching to help you around:

8> <<R:8, Rest/binary>> = Pixels.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
9> R.
213

Nice, huh? That's because Erlang accepts more than one way to describe a binary segment. Those are all valid:

        Value
        Value:Size
        Value/TypeSpecifierList
        Value:Size/TypeSpecifierList

where Size is always in bits and TypeSpecifierList represents one or more of the following:

Type
    Possible values: integer | float | binary | bytes | bitstring | bits | utf8 | utf16 | utf32
    This represents the kind of binary data used. Note that 'bytes' is shorthand for 'binary' and 'bits' is shorthand for 'bitstring'.
    When no type is specified, Erlang assumes an 'integer' type.
Signedness
    Possible values: signed | unsigned
    Only matters for matching when the type is integer. The default is 'unsigned'.
Endianness
    Possible values: big | little | native
    Endianness only matters when the Type is either integer, utf16, utf32, or float. This has to do with how the system reads binary data.
    As an example, the BMP image header format holds the size of its file as an integer stored on 4 bytes. For a file that has a size of
    72 bytes, a little-endian system would represent this as <<72,0,0,0>> and a big-endian one as <<0,0,0,72>>. One will be read as '72'
    while the other will be read as '1207959552', so make sure you use the right endianness. There is also the option to use 'native',
    which will choose at run-time if the CPU uses little-endianness or big-endianness natively. By default, endianness is set to 'big'.
Unit
    written unit:Integer
    This is the size of each segment, in bits. The allowed range is 1..256 and is set by default to 1 for integers, floats and bit strings
    and to 8 for binary. The utf8, utf16 and utf32 types require no unit to be defined. The multiplication of Size by Unit is equal to the
    number of bits the segment will take and must be evenly divisible by 8. The unit size is usually used to ensure byte-alignment.

The TypeSpecifierList is built by separating attributes by a '-'.

Some examples may help digest the definitions:

10> <<X1/unsigned>> =  <<-44>>.
<<"Ô">>
11> X1.
212
12> <<X2/signed>> =  <<-44>>.  
<<"Ô">>
13> X2.
-44
14> <<X2/integer-signed-little>> =  <<-44>>.
<<"Ô">>
15> X2.
-44
16> <<N:8/unit:1>> = <<72>>.
<<"H">>
17> N.
72
18> <<N/integer>> = <<72>>.
<<"H">>
19> <<Y:4/little-unit:8>> = <<72,0,0,0>>.      
<<72,0,0,0>>
20> Y.
72

You can see there are more than one way to read, store and interpret binary data. This is a bit confusing, but still much simpler than
using the usual tools given by most languages.

The standard binary operations (shifting bits to left and right, binary 'and', 'or', 'xor', or 'not') also exist in Erlang. Just use the
functions bsl (Bit Shift Left), bsr (Bit Shift Right), band, bor, bxor, and bnot.

2#00100 = 2#00010 bsl 1.
2#00001 = 2#00010 bsr 1.
2#10101 = 2#10001 bor 2#00101.

With that kind of notation and the bit syntax in general, parsing and pattern matching binary data is a piece of cake. One could parse TCP
segments with code like this:

<<SourcePort:16, DestinationPort:16,
  AckNumber:32,
  DataOffset:4, _Reserved:4, Flags:8, WindowSize:16,
  CheckSum: 16, UrgentPointer:16,
  Payload/binary>> = SomeBinary.

The same logic can then be applied to anything binary: video encoding, images, other protocol implementations, etc.

Don't drink too much Kool-Aid:
Erlang is slow compared to languages like C or C++. Unless you are a patient person, it would be a bad idea to do stuff like converting
videos or images with it, even though the binary syntax makes it extremely interesting as I hinted above. Erlang is just not that great at
heavy number crunching.

Take note, however, that Erlang is still mighty fast for applications that do not require number crunching: reacting to events, message
passing (with the help of atoms being extremely light), etc. It can deal with events in matters of milliseconds and as such is a great
candidate for soft-real-time applications.

A stri

There's a whole other aspect to binary notation: bit strings. Binary strings are bolted on top of the language the same way they are with
lists, but they're much more efficient in terms of space. This is because normal lists are linked lists (1 'node' per letter) while bit
strings are more like C arrays. Bit strings use the syntax <<"this is a bit string!">>. The downside of bit strings compared to lists is a
loss in simplicity when it comes to pattern matching and manipulation. Consequently, people tend to use bit strings when storing text that
won't be manipulated too much or when space efficiency is a real issue. We'll see strings and bit strings more in depth in chapter 9. For
the time being, that's all we need to know.

Note: Even though bit strings are pretty light, you should avoid using them to tag values. It could be tempting to use string literals to
say {<<"temperature">>,50}, but always use atoms when doing that. Previously in this chapter, atoms were said to be taking only 4 or 8
bytes in space, no matter how long they are. By using them, you'll have basically no overhead when copying data from function to function
or sending it to another Erlang node on another server.
Conversely, do not use atoms to replace strings because they are lighter. Strings can be manipulated (splitting, regular expressions, etc)
while atoms can only be compared and nothing else.

Binary Comprehensions

Binary comprehensions are to bit syntax what list comprehensions are to lists: a way to make code short and concise. They are relatively
new in the Erlang world as they were there in previous revisions of Erlang, but required a module implementing them to use a special
compile flag in order to work. Since the R13B revisions (those used here), they've become standard and can be used anywhere, including the
shell:

1> [ X || <<X>> <= <<1,2,3,4,5>>, X rem 2 == 0].     
[2,4]

The only change in syntax from regular list comprehensions is the <- which became <= and using binaries (<<>>) instead of lists ([]).
Earlier in this chapter we've seen an example where there was a binary value of many pixels on which we used pattern matching to grab the
RGB values of each pixel. It was alright, but on larger structures, it would become possibly harder to read and maintain. The same
exercise can be done with a one-line binary comprehension, which is much cleaner:

2> Pixels = <<213,45,132,64,76,32,76,0,0,234,32,15>>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>
3> RGB = [ {R,G,B} || <<R:8,G:8,B:8>> <= Pixels ].
[{213,45,132},{64,76,32},{76,0,0},{234,32,15}]

Changing <- to <= let us use a binary stream as a generator. The complete binary comprehension basically changed binary data to integers
inside tuples. Another binary comprehension syntax exists to let you do the exact opposite:

4> << <<R:8, G:8, B:8>> ||  {R,G,B} <- RGB >>.
<<213,45,132,64,76,32,76,0,0,234,32,15>>

Be careful, as the elements of the resulting binary require a clearly defined size if the generator returned binaries:

5> << <<Bin>> || Bin <- [<<3,7,5,4,7>>] >>.
** exception error: bad argument
6> << <<Bin/binary>> || Bin <- [<<3,7,5,4,7>>] >>.  
<<3,7,5,4,7>>





http://www.eonblast.com/blog/optimizing-erlualib-calls/

http://www.infoq.com/presentations/Building-Highly-Available-Systems-in-Erlang

https://www.erlang.org/doc/getting_started/conc_prog.html#message-passing


https://en.wikipedia.org/wiki/Elixir_(programming_language)
https://news.ycombinator.com/item?id=38903276 The Erlang Ecosystem [video] (youtube.com)
https://blog.stenmans.org/theBeamBook/ The Erlang Runtime System
https://news.ycombinator.com/item?id=39342392 The Erlang Runtime System (stenmans.org)
https://jlouisramblings.blogspot.com/2010/12/response-to-erlang-overhyped-or.html





#  Local Variables:
#  coding:               utf-8-unix
#  End: