Erlang for Python programmers: Part I

by on September 9, 2007

Let’s skim over data types in Erlang today. Check previous tutorial for introduction.

Numbers

In Erlang there are two types of numeric literals: integers and floats.
In Python there are four of them: plain integers(usually called just integers), long integers, floating point numbers, and imaginary numbers.

In addition to conventional notation Erlang has its own specific notations:
1) \$char
Gives ASCII value of char
2) base#value
Produces integer. Base is in range [2,36]

```1> \$A.
65
2> 2#111.
7
3> 16#1A.
26
4> 5.
5
5> 2.55.
2.55000```

In Python we can define octinteger and hexinteger correspondingly with:

```>>> 017, 0x1A
(15, 26)```

To produce integer from different bases in Python we may use built-in int([x[, radix]]), where radix is in range [2,36]:

```>>> int("111", 2), int("1A", 16)
(7, 26)```

Atom

An atom is a literal or a constant with name. Atoms should start with small letter or it should be enclosed in single quote(‘) if it contains other characters than alphanumeric characters, _, or @.
Atoms can not have values like variables, they are simply names (constant with name).

```1> erlang.
erlang
2> 'hello world'.
'hello world'
3> 'Erlang'.
'Erlang'```

In Python there are also atoms in form of identifiers or literals, but no correspondence with Erlang’s constant with name type of atom.

More examples with atoms to come when we get acquainted with other data types
and parts of Erlang.

Binary

From a reference manual:
“A binary is used to store an area of untyped memory.
Binaries are expressed using the bit syntax.”

This data type allows to store large raw chunks of memory in an efficient way, much more space-efficient than in lists or tuples.

Binaries are written in double less-than and greater-than brackets and printed in that form as well.
They can be constructed from set of constants or string literal:

```1> <<1,2,3>>.
<<1,2,3>>
2> <<"erlang">>.
<<"erlang">>```

Or from bound variables:

```3> A = 1, B = 2, C = 3.
3
4> Bin = <<A, B, C>>.
<<1,2,3>>```

Remember pattern matching ?
Binary (Bin for short) can also be used for matching:

```5> <<X, Y, Z>> = Bin.
<<1,2,3>>
6> X.
1
7> Y.
2
8> Z.
3```

There is more than that, namely bit syntax which allows to pack/unpack sequences of bits in Bin. Actually bit syntax is an extension to pattern matching.
Let’s pack three variables into 16 bit memory area in a variable Mem, then unpack it to another three variables using bit syntax:

```1> X = 2.
2
2> Y = 40.
40
3> Z = 30.
30
4> Mem = <<X:3, Y:7, Z:6>>.
<<74,30>>
5> <<X1:3, Y1:7, Z1:6>> = Mem.
<<74,30>>
6> X1.
2
7> Y1.
40
8> Z1.
30```

In foregoing output you see that after packing shell prints packed three variables as <<74,30>> which is 16 bits.

In Python 2.5 there is no built-in data type to support binary data, but in Python 3000 binary data is represented by a separate mutable “bytes” data type.

Fun

Fun is an anonymous function, ie without name.

In Python this is infamous lambda, which had many debates whether it should remain in language or not. Personally i like lambda and glad it survived and will continue its life in Python 3000.

But Ok, back to Erlang’s Fun. Here how we can define it in shell:

```1> Double = fun(X) -> X * 2 end.
#Fun<erl_eval.6.56006484>
2> Double(4).
8```

In contrast to Python Erlang’s Fun can contain statements and is “more advanced” in general:

```1> Print_val = fun(X) -> io:format("X = ~p~n", [X]), X*2 end.
#Fun<erl_eval.6.56006484>
2> Print_val(3).
X = 3
6```
```>>> print_val = lambda x: print 'x = %d' % x; x*2
File "<stdin>", line 1
print_val = lambda x: print 'x = %d' % x; x*2
^
SyntaxError: invalid syntax
>>> print_val = lambda x: x*2
>>> print_val(3)
6```

More advanced examples of Fun like Funs with several different clauses i’ll show when discussing in details functions in Erlang in upcoming tutorials.

Tuple

It’s a compound data type with fixed number of terms (Term is a piece of data of any data type). Number of elements in tuple is called size of tuple.
Syntax of tuples is:

```1> Tuple = {ruslan, 28}.
{ruslan,28}
2> Info = {data, Tuple}.
{data,{ruslan,28}}```

In Python tuples are defined with or without enclosing parentheses:

```>>> tup = "ruslan", 28
>>> tup
('ruslan', 28)
>>> info = ('data', tup)
>>> info
('data', ('ruslan', 28))```

To get number of elements in tuple.

Erlang:

```3> size(Info).
2```

Python:

```>>> len(info)
2```

List

List is a compound data type with variable number of terms. Number of elements in a list is called length of the list.

List is declared in square brackets like in Python.

```1> List = [1, 2, 3, "erlang"].
[1,2,3,"erlang"]```

Now Erlang specific part, which may be familiar to you if you know a bit Lisp and its CAR/CDR stuff:
List is either an empty list [] or may be represented as head (first element – CAR in Lisp) and tail (remainder of list – CDR in Lisp) which is also a list and often you can see it in form like [H|T].
This representation is recursive:
[]
]
[b | ]]
[a | [b | ]]]
are all lists actually.

Let’s define list in shell:

```1> List = [a, 1, {b, 2}].
[a,1,{b,2}]```

and unpack it with pattern matching to head and tail:

```2> [H|T] = List.
[a,1,{b,2}]
3> H.
a
4> T.
[1,{b,2}]```

As you see T(tail) above is also a list.

We can also construct list using head and tail syntax:

```5> List2 = .
```

Working with Erlang you’ll see/use this syntax quite often.

To get number of elements in list.

Erlang:

```6> length(List2).
3```

Python:

```>>> len([1, 2, 3, "python"])
4```

String

In Python string type is immutable sequence of characters. In Python there is no separate character type, a character is represented by a string of one item. String literals are written in single or double quotes:

```>>> 'xyz', "xyz"
('xyz', 'xyz')```

In Erlang strings are enclosed in double quotes, but unlike Python string is not separate data type actually. String “erlang” is just shorthand for list [\$e, \$r, \$l, \$a, \$n, \$g].

Adjacent string literals are concatenated at compile time:

```1> "hello" ", world" " in " "erlang".
"hello, world in erlang"```

In Python behaviour with adjacent strings is the same:

```>>> 'hello' ', world' ' in ' 'python'
'hello, world in python'```

Boolean

Again unlike Python Erlang has no built-in Boolean type, but it uses atoms true and false to denote Boolean values:

```1> 1 < 2.
true
2> true or false.
true```

In Python Boolean is separate data type:

```>>> type(True), type(False)
(<type 'bool'>, <type 'bool'>)
>>> 1 < 2
True
>>> True or False
True```

Record

Record is a data structure to hold fixed number of elements and it provides method to associate a name with particular element in tuple. It resembles structure in C. Record is not true data type, it is “tuple in disguise”(TM).
It’s syntax is:
-record(Name, {key1=Default1, key2, …}).

But in shell we can not use -record syntax and we do not yet know about modules where it can be defined, so we’ll use ‘rd’ shell command to define record:

```1> rd(info, {name="ruslan", age=28, height, weight}).
info```

Now let’s create instance of record:

```2> X = #info{}.
#info{name = "ruslan",age = 28,height = undefined,weight = undefined}
3> X.
#info{name = "ruslan",age = 28,height = undefined,weight = undefined}```

As you see height and weight got “undefined” value.

To extract fields of record we use pattern matching:

```4> #info{name=Name, age=Age} = X.
#info{name = "ruslan",age = 28,height = undefined,weight = undefined}
5> Name.
"ruslan"
6> Age.
28```

We can also access field of record with “dot syntax”:

```7> X#info.name.
"ruslan"```

Erlang has more data types like Pid, Port identifier, Reference which will be described later in more advanced topics.There is no direct correspondence to Python’s built-in data types like dictionaries and sets, but Erlang has modules which provide the same semantics.

That’s it for today.

If you enjoyed this post why not subscribe via email or my RSS feed and get the latest updates immediately. You can also follow me on GitHub or Twitter.

{ 7 comments… read them below or add one }

Ian Bicking September 11, 2007 at 6:27 PM

Isn’t an Atom really most like a string in Python (since strings are immutable)? Similar to a symbol in other languages (:sym in Ruby, #sym in Smalltalk, ‘sym in Scheme, etc) — Python just manages to conflate strings with symbols due to the immutability of strings. “Constant with name” I guess could be used to describe Atoms, but it’s awfully confusing to me.

Reply

Ruslan Spivak September 11, 2007 at 7:33 PM

“Isnâ€™t an Atom really most like a string in Python (since strings are immutable)?”

Not exactly, though visually there may be similarity when Atom in Erlang is represented with single quotes (‘) and this could bring confusion to Python programmer as it looks like string in Python, ie:
‘hello world’ in Erlang –> atom
‘hello world’ in Python –> string

I should note though that i meet more often Atoms represented in form of
“constant with name” like in:
1> T = {erlang, 10, “hello”}.
{erlang,10,”hello”}
2> {Atom, 10, “hello”} = {erlang, 10, “hello”}.
{erlang,10,”hello”}
3> Atom.
erlang

Atom is a separate data type in Erlang, but not in Python. In Python’s Reference manual Atoms are defined as “the most basic elements of expressions”, which is a different beast, obviously, than in Erlang.

In next tutorials i’ll give some examples which i hope will shed more light on place and behavior of atoms in Erlang.

Reply

Joe April 19, 2008 at 8:11 PM

Was there a syntax change in 5.6.2? This isn’t quite working for me:

\$ erl
Erlang (BEAM) emulator version 5.6.2 [source][/source] [async-threads:0] [kernel-poll:false]

Eshell V5.6.2 (abort with ^G)
1> Print_val = fun(X) -> io:format(.X = ~p~n., [X]), X*2 end.
* 1: syntax error before: X

Reply

Ruslan Spivak April 19, 2008 at 9:49 PM

I think it could be related to copy/paste error in your code.
In io:format there should be double quotes around X = ~p~n, i.e
io:format(“X = ~p~n”, [X])

Reply

Andrew B. April 22, 2010 at 2:26 AM
demokrito February 25, 2011 at 5:16 PM

Hello! Your tutorial is amazing and very unusual. I’m so lucky to be Pythoneer and study Erlang right now.

By the way, in Python 3 ‘bytes’ datatype is not mutable, ‘bytearray’ is.

Reply

Ruslan Spivak February 25, 2011 at 8:05 PM

Hey demokrito,

Thanks for pointing out ‘bytes’. Time passes so fast – now even Python 2.6 has a bytearray data type.

P.S. It’s great that you’ve started to learn Erlang – I hope you’ll like it.

Reply

{ 1 trackback }

Previous post: