List Comprehensions

07/05/2009

Another way to work with lists is called “List Comprehensions”, this is quite immediate, we have a list

List = [1,2,3].

and we want to iterate over every item in the list … we can do:

[Item * 2 || Item <- List].

This way we are asking a list as result of execution (using []). We are asking that every Item in List (the code after ||) must be used in the code before || (Item * 2).

So we asked a thing like:

lists:map(fun(Item) -> 2*Item end, List).

without having to define a fun! useful 🙂

Advertisements

Funs

06/05/2009

Funs are called ‘anonymous functions’, let’s try to define one:

Sum = fun(X, Y) -> X+Y end.

This funs simply sums X and Y.

In erlang there are (and is possible to define) functions that accept a fun as parameter, this kind of functions are called “higher-order functions”.

Let’s define a list with our wishes:

ThingsIDesire = [iphone, mouse, keyboard].

Now we can define a fun that remove iphone from the list (we have already a phone and we can’t spend more for this kind of things!):

GoAwayIphone = fun(Devices) -> lists:delete(iphone, Devices) end.

Note: doing lists:delete we are using a function available in erlang’s standard lib, you can see more of it -> http://erlang.org/doc/apps/stdlib/index.html

Now if we execute:

GoAwayIphone(ThingsIDesire).

we will obtain:

[mouse,keyboard]

To use a fun inside another function is really simple, in the standard lib there is a function called lists:member(item, list) that returns true if <item> is in the <list>.
If we try:

lists:member(iphone, ThingsIDesire).

it returns true (because iphone is in ThingsIDesire), but if I pass GoAwayIphone(ThingsIDesire) as second argument like:

lists:member(iphone, GoAwayIphone(ThingsIDesire)).

I got false!

Is also possible for a function to return a fun, for example we can do:

DevicesToBlock = [iphone].
CheckPresenceOfBlockedDevices = fun(Devices) -> (fun(Device) -> lists:member(Device, Devices) end) end.

We defined fun(Devices) that returns fun(Device), now let’s define the function that actually check an item:

CheckIfThisIsABlockedDevice = CheckPresenceOfBlockedDevices(DevicesToBlock).

so

CheckIfThisIsABlockedDevice(iphone). returns true and
CheckIfThisIsABlockedDevice(mouse). returns false

The argument passed to CheckIfThisIsABlockedDevice is passed to fun(Device) that checks if the passed item is in the DevicesToBlock list.

By now it sounds quite confusing … but I can imagine some benefit of it!

Modules

06/05/2009

All the functions will be stored in modules, and they must be compiled before the code can be run.
When you write a module its extension will be .erl but when it will be compiled it changes in .beam

ThingsToBuy = [ {iphone, 100},
{mac, 1500},
{mouse, 20},
{keyboard, 30}].

This is the list of items we want to buy, how much money will we spend to buy all these items? Let’s create a module to calculate it!

-module(cost).
-export([total/1]).

total([{_, Money}|T]) -> Money + total(T);
total([]) -> 0.

(save this code in cost.erl)

Now in shell you have to compile your module writing:

c(cost).

Now you can calculate the sum of all these items doing:

cost:total(ThingsToBuy).

f().

06/05/2009

When you are working with erlang shell you will use much variables and sometimes the fact you can’t change a value force you to choose funny names.

There is a way to flush all variables in erlang shell, this way every variable will be unbound and you can re-utilize its name 🙂

Simply do f(). in the shell and all variables will be flushed 🙂

Strings

06/05/2009

You can define a String using “,

Name = “Simone”.

Note: You have to use double quotes, not single ones!

A string in Erlang is just a List of integer that represent characters that compose the string you defined.
If we try to do:

[Head | RemainingString] = Name.

We will get Head -> 83 (the ‘S’) and RemainingString -> “imone”.

How to know that 83 means ‘S’? You can get $<letter>. to see the value, for example:

$S. -> 83 (so we know that 83 means ‘S’)

So using this thing we can compose a list of integer (representing letters) and create a string like:

[$S, $i, $m, $o, $n, $e]. -> “Simone”

Note: these values are related to Latin-1 (ISO-8859-1) character codes!

List are (as name implies) a list of things (mixed type) defined using [] separating items with ,
For example:

[simone, marco, 2+3, {language, erlang}].

returns:

[simone,marco,5,{language,erlang}]

The “head of the list” is the first item in the list (‘simone’ in our example), when you remove the head from a list the remaining part is called “tail of the list” ([marco,5,{language,erlang}] in our example). So a simple schema for a list is [head|tail].

A list:

Devices = [iphone, mac, arduino].

Another list created using an existing one:

ToBuy = [mouse, keyboard | Devices].

Now let’s try to pull out the head of the list using the matching operator ‘=’!

[FirstThingToBuy | OtherThingsToBuy] = ToBuy.

Now I have:

FirstThingToBuy -> mouse (the ex head of the list)

and:

OtherThingsToBuy -> [keyboard,iphone,mac,arduino] (the tail of the list)

Now we need to buy another item (the second), so:

[SecondThingToBuy | OtherThingsToBuy1] = OtherThingsToBuy.

Now I have:

SecondThingToBuy -> keyboard (the new ex hed of the list)

and:

OtherThingsToBuy1 -> [iphone,mac,arduino] (the new tail of the list)

Note: I had to use OtherThingsToBuy1 instead of OtherThingsToBuy because OtherThingsToBuy had already a value and we know that we can’t change it! (I don’t still like it …)

One thing I had clear about erlang (see my first post) is that in erlang a variable gets a value and never change it, it looks a bit different in reality.

When you execute something like X = 5. Erlang read ‘=’ as a matching operator, “X must be equal to 5”, so to become true the phrase it sets X the value of 5.

So … if you have a tuple like:

Person = {person, simone, 26}.

you can make something like:

{person, Name, Age} = Person.

In that way you will have Name with ‘simone’ as value and Age with ’26’. Good!

Another try:

Person = {person,
{name, simone},
{age, 26},
{location, italy}}.

To get the name you have to:

{_,{_,Who},_,_} = Person.

‘_’ is called anonymous variable and it represents variables not interesting for us. Notice that the structure of the first operand is the same of the Person, it simply has many ‘_’ where there is non interesting data.

Another example:

Desk = {desk,
{material, plastic},
{height, 50}}.

I can get material and height values simply doing:

{_, {_, Material}, {_, Height}} = Desk.

Now I’ll have two variables (Material and Height) with values ‘plastic’ and ’50’. Good 🙂