erlang secuencial - ucmgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · lo que...

67
Erlang Secuencial Francisco Javier L´ opez Fraguas April 13, 2015

Upload: others

Post on 25-Apr-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Erlang Secuencial

Francisco Javier Lopez Fraguas

April 13, 2015

Page 2: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Parte I - Erlang secuencial

Joe Armstrong – Programming Erlang

You can’t run until you can walk. Erlang programs are made

up from lots of small sequential programs running at the same

time. Before we can write concurrent code, we need to be able

to write sequential code.

Page 3: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Erlang: primer contacto

Computos ≡ evaluacion de expresiones

En la shell de Erlang (interprete de comandos)

Lanzamos computos ; Evaluamos expresiones

Algunas expresiones pueden ser vistas como comandos, e.g:

> c(programa ): compilar un programa> cd(directorio ): cambiar de directorio> i(): informacion sobre procesos> help(): ayuda de la shell. . .

Page 4: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +
Page 5: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Algunas cosas sobre la Erlang shell

La shell ejecuta (como un proceso Erlang) un bucle eval-print

No olvidar el punto al final de las expresiones a evaluar!>1+2.

(si no se pone, se queda esperandolo y parece que el sistemase ha colgado)

Toda expresion (incluso las que ejecutan ’comandos’) devuelveun valor, salvo que la evaluacion no termine o genere un error.

Algunas soluciones cuando la shell se queda colgada

Crtl+C (Unix), Crtl+Break (Windows)Mejor, Crtl+G

Puede haber varias shells abiertas en la misma sesion

Page 6: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Terminos y expresiones Erlang

Enteros

>20+30.

50

>33 div 5.

6

>33 rem 5.

3

Precision arbitraria> 111111111 * 2222222222* 333333333.

82304526576131687341563786

Podemos usar otras bases distintas de 10>16#11

17

>16#ba

186

Erlang tiene tipado dinamico> 1+true.

** exception error ...

Page 7: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Terminos y expresiones Erlang

Reales en coma flotante

> 20+30.1.

50.1

> 33/5.

6.6

> math:pow(2,100).

1.2676506002282294e30

> trunc(math:pow(2,100)).

1267650600228229401496703205376

Page 8: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Terminos y expresiones Erlang

Atomos

Representan valores constantes

Formados por: caracteres alfanumericos, , @

lunes rojo ok rojo claro paco@ucm

O bien por caracteres cualesquiera encerrados entre ’.’hola hola’ ’[email protected]’ ’1+2’

Un atomo se evalua a el mismo.

Page 9: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Terminos y expresiones Erlang

Expresiones booleanas

true , false son dos atomos mas, pero con unainterpretacion especial: son valores booleanos y con ellos sepueden formar expresiones booleanas.

Expresiones booleanas:not e e1 and e2 e1 or e2 e1 xor e2donde ei son expresiones que se evaluan a un valor booleano.

> not true.

false

> (5>3) or (1<0).

true

> (5>3) and (1<0).

false

> (5>3) or (1<1/0).

** exception

Page 10: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Expresiones booleanas cortocircuitadas

e1 andalso e2 e1 orelse e2

No siguen el regimen de evaluacion impaciente:se evalua e1 y solo si hace falta se evalua e2.

> (5>3) orelse (1<0).

true

> (5>3) andalso (1<0).

false

> (5>3) orelse (1<1/0).

true

Page 11: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

BIFs (Built In Functions) para reconocimiento de tipos

> is integer(3).

true

> is integer(3.0).

false

> is float(3).

false

> is float(3.0).

true

> is number(3).

true

> is number(3.0).

true

> is number(1+1.2).

true

> is atom(ok).

true

> is boolean(1>0).

true

Otras BIFs de ese estilo:is tuple is list is function is pid is record . . .

Page 12: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Variables

Formados por: caracteres alfanumericos, , @, empezandopor una mayuscula o por

X X1 X 1 Hola

Lo que nunca encontraremos: X=X+1

No hay variables asignables a un valor que va cambiando+ no hay estado mutable

Las variables aparecen para representar parametros formalesen las definiciones de funciones.

Tambien aparecen en expresiones de ajuste de patrones(pattern matching), en las que una variable puede quedarligada a un valor que ya no puede cambiar.+ variables de asignacion unica .

Page 13: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Expresiones de ajuste de patrones: e1 = e2

No son un test de igualdad (para eso tenemos e1 =:= e2 oe1 =:= e2)

El valor de e1 = e2 es:

El valor de e2 si e1 y e2 se evaluan al mismo valorEl valor de e2 si e1 es una variable no ligada X, que quedaentonces ligada al valor de e2

Este la situacion interesanteMas adelante veremos mas posibilidades para ligaduras devariables por ajuste de patrones

Un error en otros casos (valores no coincidentes, variables noligadas en e2, . . . )

Page 14: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Expresiones de ajuste de patrones: e1 = e2

> 1+1=2+0.

2

> +1=2+2.

error: no match

> X=2+2.

2

> X.

4

> Y.

error: Y unbound

> Y=1+X.

5

> Y.

5

> Y=X.

error: no match

> Y=Y+1.

error: no match

> f(Y).

ok

> X=Y.

error: Y unbound

> Y=X.

4

Page 15: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Expresiones secuencia: e1, e2, . . . , en

Para evaluarla se evaluan (en ese orden) e1, e2, . . . ,en, pero elvalor devuelto es el valor de en.

Tiene sentido usarlas cuando la evaluacion de e1,. . . producealgun efecto lateral.

> 1,2,3.

3.

> R=3.5,math:pi()*R*R.

38.484510006.

> R=3.5,math:pi()*R*R.

38.484510006.

> io:format("abc\n"),timer:sleep(1000),X=2*3,X+4.abc

10

Page 16: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Tuplas

Agrupacion de datos de tamano fijo

Sintaxis: {} Tupla vacıa{e1,e2,...,en} Tupla de n elementos

{1,3} {paco,56} dos tuplas de tamano 2

{persona, {nombre,’Paco’},{apellidos,{’Lopez’,’Fraguas’}},{edad,56}

}Una tupla de tamano 4 formada por otras tuplas

Page 17: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Ajuste de patrones con tuplas

> P = {punto,3,4}.{punto,3,4}

> {punto,X,Y} = P.

{punto,3,4}

> D = math:sqrt(X*X+Y*Y).

5.0

> {Tag,A,A} = {punto,3,3} , {Tag,A}.{punto,3}

> { ,B, } = P , B.

3

> {1,2} =:= {2,1}.false

Page 18: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Algunas BIFs sobre tuplas

> tuple size({punto,3,4}).3

> tuple size({}).0

> element(2,{punto,3,4}).3

> setelement(2,{punto,3,4},10).{punto,10,4}

Muchas BIFs devuelven tuplas como resultado

> time().

{19,22,40}> date().

{2014,10,6}

Page 19: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Listas

Secuencia de datos de tamano arbitrario

Sintaxis: [] Lista vacıa[e1,e2,...,en] Lista de n elementos• e1 es la cabeza de la lista• [e2,...,en] es el resto de la lista

> [1+2,true or false,{ok,3}][3,true,{ok,3}]

+ los elementos pueden ser de tipos distintos

Page 20: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Algunas BIFs (y funciones de librerıas) sobre listas

> hd([1,a,3]).

1

> tl([1,a,3]).

[a,3]

> tl([3]).

[]

> hd([]).

error: bad argument

> length([1,2,3]).

3

> ([1,2,3]++[4,5]).

[1,2,3,4,5]

> ([1,2,3,1]--[3,1,4]).

[2,1]

> lists:reverse([a,b,c])

[c,b,a]

> lists:nth(2,[a,b,c])

[b]

> lists:append([[1,2,3],[4,5],[a,b]]).

[1,2,3,4,5,a,b]

Page 21: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

La constructora de listas [ | ]

[h|t] ; lista de cabeza h y resto t

[a,b,c] es lo mismo que [a|[b|[c|[]]]]

[a,b,c] ≡ [a|[b|[c|[]]]] ≡ [a|[b,c]] ≡ [a,b|[c]] ≡[a,b|[c|[]]] ≡ [a,b,c|[]]

La notacion [h|t] sera esencial para expresar el ajuste depatrones al definir funciones sobre listas.

Page 22: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Ajuste de patrones con listas

> X = [1,2,3].

[1,2,3]

> Y = [a|X].

[a,1,2,3]

> [A,B,2,C] = Y,{A,B+C}.{a,4}

> [U|V] = Y , {U,V}.{a,[1,2,3]}

Page 23: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Strings

No hay strings propiamente dichos, son listas de enteros(listas de codigos Unicode)

Pero tenemos un azucar sintactico: ”caracteres”> "Hola".

"Hola"

> "Hola"++",amigo".

"Hola,amigo"

> hd("Hola").

72

> tl("Hola").

"ola"

> [1|"Hola"].

[1,72,111,108,97]

> [72,111,108,97].

"Hola"

> [A,B|C] = "Hola",{A,B,C}.{72,111,"la"}

Page 24: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Convesiones entre tipos

> atom to list(hello).

"hello"

> list to atom("hello").

hello

> integer to list(77).

"77"

> list to integer("77").

77

> tuple to list({a,b,c}).[a,b,c]

> list to tuple([a,b,c]).

{a,b,c}> ...

Page 25: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Modulos y funciones

Modulos

Unidades basicas de codigo

Ficheros con extension .erl

Al compilarlos generan .beam

Constan de directivas y definiciones de funciones

Se pueden compilar desde el SO o desde la shell.

Page 26: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

factorial.erl

-module(factorial).

-export([fac/1]). % /1 indica aridad 1

fac(0) -> 1; % Primera clausula de fac

fac(N) -> N * fac(N-1). % Segunda

> c(factorial).

ok,factorial

> fac(7).

** exception error: undefined shell command fac/1

> factorial:fac(7).

5040

Page 27: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

El orden de las clausulas es importante

-module(factorial).

-export([fac/1]).

fac(N) -> N * fac(N-1); % mal asunto ...

fac(0) -> 1.

factorial.erl con recursion de cola (last call optimization)

-module(factorial).

-export([fac/1]).

fac(0) -> 1;

fac(N) -> N * fac(N-1). % No hay LCO

facc(0,Acc) -> Acc;

facc(N,Acc) -> facc(N-1,N*Acc). % Hay LCO

Page 28: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Programas con tuplas: paso de parametros por ajuste de patrones

-module(medidas).

-export([area/1,perimetro/1]).

area({cuadrado,L}) -> L*L;

area({rectangulo,X,Y}) -> X*Y;

area({circulo,R}) -> math:pi()*R*R.

perimetro({cuadrado,L}) -> 4*L;

perimetro({rectangulo,X,Y}) -> 2*X+2*Y;

perimetro({circulo,R}) -> 2*math:pi()*R.

% Aqui el orden de las clausulas no importa

Page 29: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Programas con listas: ajuste de patrones, recursion

-module(listas).

-compile(export_all).

% length(Xs)= longitud de la lista Xs

length([]) -> 0;

length([X|Xs]) -> 1+length(Xs).

% O bien, con LCO

length1(Xs) -> length1(Xs,0).

length1([],N) -> N;

length1([X|Xs],N) -> length1(Xs,N+1).

Page 30: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

% append(Xs,Ys) = concatenacion de Xs e Ys

append([],Ys) -> Ys;

append([X|Xs],Ys) -> [X|append(Xs,Ys)].

% hd(Xs) = cabeza de Xs ; tl(Xs) = resto de Xs

hd([X|_]) -> X.

tl([_|Xs]) -> Xs.

% nth(N,Xs) = elemento N-simo de Xs, numerando desde 1

nth(1,[X|_]) -> X;

nth(N,[_|Xs]) -> nth(N-1,Xs).

length/1,tl/1,append/2,nth/2 recorren la lista (costelineal)

length/1,hd/1,tl/1 son BIF, append/2,nth/2 estan enlists

append(X,Y) se escribe mejor como X++Y

Page 31: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Patrones con variables repetidas: expresan igualdad

% member(X,Xs) = true si X es elemento de Xs; false e.o.c.

member(X,[]) -> false;

member(X,[X|_]) -> true;

member(X,[_|Ys]) -> member(X,Ys).

% seq(N,M) = [N,N+1,...,M]

seq(N,N) -> [N];

seq(N,M) -> [N|seq(N+1,M)]

member/2 es BIF, seq/2 en lists

Page 32: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

¿Cual es la complejidad de esta funcion?

% revese(Xs) = la inversa de la lista Xs

reverse([]) -> []

reverse([X|Xs]) -> reverse(Xs)++[X]

Page 33: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Mejor sera esto. . .

reverse(Xs) -> reverse(Xs,[]).

reverse([],RevAcc) -> RevAcc;

reverse([X|Xs],RevAcc) -> reverse(Xs,[X|RevAcc]).

La funcion lists:reverse/1 esta eficientementeimplementada

Recomendaciones generales para programas que computanlistas como resultado:

Muy preferible computar [X|e] en lugar de e++[X]

Si por hacerlo ası sale el resultado al reves, usarlists:reverse/1

Page 34: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Otras formas de poner condiciones a los argumentos: guardas when

Recordemosfac(0) -> 1;

fac(N) -> N * fac(N-1).

Podemos poner una condicion en la segunda clausulafact(0) -> 1;

fact(N) when N > 0 -> N*fact(N-1).

Aquı sı podemos cambiar el orden de las clausulasfact(N) when N > 0 -> N*fact(N-1).

fact(0) -> 1;

Tambien podemos poner el caso 0 con una guardafact(N) when N > 0 -> N*fact(N-1);

fact(N) when N==0 -> 1.

Page 35: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Otras formas de poner condiciones: expresiones if

facif(N) ->

if N == 0 -> 1;

true -> N*facif(N-1)

end.

Igual preferimos esto otrofacif1(N) ->

if N == 0 -> 1;

N > 0 -> N*facif1(N-1)

end.

O incluso estofacif1(N) ->

if N == 0 -> 1;

N > 0 -> N*facif1(N-1);

true -> no_definido

end.

Page 36: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Otros ejemplos: member/2

% member(X,Xs) = true si X es elemento de Xs; false e.o.c.

Con patronesmember(X,[]) -> false;

member(X,[X|_]) -> true;

member(X,[_|Ys]) -> member(X,Ys).

Con (alguna) guardamember(X,[]) -> false;

member(X,[Y|_]) when X=:=Y -> true;

member(X,[_|Ys]) -> member(X,Ys).

Con ifmember(X,[]) -> false;

member(X,[Y|Ys]) ->

if X=:=Y -> true;

true -> member(X,Ys)

end.

Page 37: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Otras formas de poner condiciones: expresiones case

member(X,[]) -> false;

member(X,[Y|Ys]) ->

case X=:=Y of

true -> true;

false -> member(X,Ys)

end.

Tambien valdrıamember(X,[]) -> false;

member(X,[Y|Ys]) ->

case X=:=Y of

true -> true;

_ -> member(X,Ys)

end.

Page 38: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Expresiones secuencia en el cuerpo de una clasula

sols(A,B,C) = lista de soluciones de Ax2 +Bx+ C = 0sols(A,B,C) ->

D= B*B-4*A*C, % calculamos D como valor intermedio

if D < 0 -> [];

D == 0 -> [-B/2*A];

D > 0 -> [(-B + math:sqrt(D))/(2*A),

(-B - math:sqrt(D))/(2*A)]

end.

Page 39: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Formato general de una definicion de funcion f/n

f(Pat11,...,Pat1n) [when Guardas1] -> expr1;

. . . . . . . . .f(Patk1,...,Patkn) [when Guardask] -> exprk.

Donde

expri puede ser una expresion secuencia

Guardas ::= Guarda1;...;Guardam ; es como orelse

Guarda ::= GExpr1,...,GExprl , es como andalso

GExpr es una expresion booleana formada por algunas BIFs, como==,>,...,is atom,is list,...,pero no funciones de usuario.

Page 40: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Y esto se ejecuta ası: para evaluar f(e1,...,en). . .

Se evaluan e1,...,en, para obtener t1,...,tnAhora, para evaluar f(t1,...,tn)

Se prueban las cabezas de las causulas en su orden hastaencontrar una aplicable a f(t1,...,tn). Si esta es la i, seevalua expri.La cabeza f(Pati1,...,Patin) when Guardasi es aplicablea f(t1,...,tn) si:

Los argumentos t1,...,tn ajustan con los patronesPati1,...,PatinLa guarda Guardasi se evalua a true (recuerda, interpretando; como orelse y , como andalso).

Si ninguna clausula resulta aplicable, se produce un error.

Page 41: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Funciones de orden superior (HO functions)

Un lema famoso de la programacion funcional

Las funciones son ciudadanos de primera clase

Una funcion puede ser argumento o resultado de otra

Funciones de orden superior (HO functions)

Funciones con algun argumento (o el resultado) de tipofuncional.

Favorecen la abstraccion, concision y reutilizacion de codigo.

Funciones de primer orden: las ”normales”, que no son de OS

Page 42: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Funciones de orden superior

Un par de funciones de primer orden...

% inc_list(Xs): suma uno a todos los elementos de Xs

inc(X) -> 1+X.

inc_list([]) -> [];

inc_list([X|Xs]) -> [inc(X)|inc_list(Xs)].

% cabezas(Xss): cabezas de los elementos de Xss

cabezas([]) -> [];

cabezas([X|Xs]) -> [hd(X)|cabezas(Xs)].

Se repite la misma estructura:aplicar una funcion f a todos los elementos de la lista

Page 43: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Funciones de orden superior

Abstraccion de OS: map

% map(F,Xs) = resultado de aplicar F a cada elemento de Xs

% map(F,[X1,...,Xn]) = [F(X1),...,F(Xn)]

-module(ho).

map(F,[]) -> [];

map(F,[X|Xs]) -> [F(X)|map(F,Xs)].

> ho:map(fun erlang:hd/1,[[1,2,3],[2],[7,6,4]]).

[1,2,7]

> ho:map(fun ho:inc/1,[1,3,5])

[2,4,6]

Page 44: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Funciones de orden superior

Recordemos: un par de funciones de primer orden...

inc(X) -> 1+X.

inc_list([]) -> [];

inc_list([X|Xs]) -> [inc(X)|inc_list(Xs)].

cabezas([]) -> [];

cabezas([X|Xs]) -> [hd(X)|cabezas(Xs)].

Pero es mejor usando map/2

inc_list(Xs) -> map(fun ho:inc/1,Xs).

cabezas(Xss) -> map(fun erlang:hd/1,Xss).

Page 45: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Funciones de orden superior

Funciones anonimas (λ-abstracciones)

inc(X) -> 1+X.

> inc(3).

4

' > Inc=fun(X) -> 1+X end.

> Inc(3).

4

fun(X) -> 1+X end. ; funcion anonima

Podemos usarlas en map/2

inc_list(Xs) -> map(fun(X) -> 1+X end,Xs).

% hace innecesaria inc/1

cabezas(Xss) -> map(fun(X) -> hd(X) end,Xss).

% alternativa a fun erlang:hd/1

Page 46: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Otros ejemplos de funciones anonimas

fun(X,Y) -> math:sqrt(X*X+Y*Y) end

fun ({milla,X}) -> {km,X*1.609344};({km,X}) -> {milla,X/1.609344}

end

fun(Xs) -> (fun(X) -> lists:member(X,Xs) end) end

Page 47: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Otros ejemplos de funciones de HO: ¿que hacen?

filter(F,[]) -> [];

filter(F,[X|Xs]) ->

case F(X) of

true -> [X|filter(F,Xs)];

false -> filter(F,Xs)

end.

for(I,J,F) when I<=J -> [F(I)|for(I+1,J,F)];

for(I,J,F) when I>J -> [].

Page 48: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Listas intensionales (List comprehensions)

Notacion inspirada en las Matematicas: conjuntos por comprension

{x2 | x ∈ {1, . . . , 5}} {1, 4, 9, 16, 25}

{x+ 1 | x ∈ {1, . . . , 10}, x2 acaba en 9} {4, 8}

En programacion funcional: map, filter

map(fun(X) -> X*X end,[1,2,3,4,5])

map(fun(X) -> X+1,filter(fun(X)->X*X rem 10 =:= 9 end,seq(1,10)))

O tambien podemos usar notacion de listas intensionales

[X*X || X <- [1,2,3,4,5]]

[X+1 || X <- seq(1,10), X*X rem 10 =:= 9]

Page 49: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Mas ejemplos

[Y || Y <- seq(1,24), 24 rem Y =:= 0] [1,2,3,4,6,8,12,24]

divisores(X) -> [Y || Y <- seq(1,X), X rem Y =:= 0]

es primo(X) -> [Y || Y <- seq(2,X-1), X rem Y =:= 0] =:= []

[{X,Y,X and Y} || X <- [true,false], Y <- [true,false]]

[{Y,X} || X <- [true,false], Y <- [true,false] ,X and Y =:= X or Y]

Page 50: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Morfologıa de las listas intensionales

[ X+1 || X <- seq(1,10) , X*X rem 10 =:= 9]

expresion principal

[X+1 || X <- seq(1,10) , X*X rem 10 =:= 9]

generador

[X+1 || X <- seq(1,10) , X*X rem 10 =:= 9 ] filtro

En general, una lista intensional es: [e || c1,...,cn]

e es una expresionc1 es un generadorCada ci con i > 1 es un generador o un filtroUn generador es de la forma p <- l

l es una expresion cuyo valor es una listap es un patron

Un filtro es una expresion booleana

Page 51: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Generadores

Puede haber varios generadores seguidos[{X,Y} || X <- [1,2] , Y <- [a,b,c]]

[{1,a},{1,b},{1,c},{2,a},{2,b},{2,c}]El orden de los generadores influye[{X,Y} || Y <- [a,b,c] , X <- [1,2]]

[{1,a},{2,a},{1,b},{2,b},{1,c},{2,c}]Generadores multiples actuan al modo de bucles anidados

Un generador p <-l con p no variable tiene un efecto filtropor el ajuste de patrones[X+Y || {{X,Y},a} <- [{{2,1},a},{{1,3},b},{{2,4},a}]][3,6]

Filtros

Puede haber varios filtros seguidosCada filtro actua sobre el resultado de los generadores y filtrosanteriores

Page 52: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Un ejemplo: quicksort

qsort([]) -> [];

qsort([X|Xs]) -> qsort([U || U <- Xs, U < X])

++ [X] ++

qsort([U || U <- Xs, U > X]).

Page 53: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Ternas pitagoricas: (x, y, z) tales que x2 + y2 = z2

-- ternasP(N) = ternas pitagoricas con numeros =< N

ternasP(N)= [{X,Y,Z}|| X <- lists:seq(1,N),

Y <- lists:seq(1,N),

Z <- lists:seq(1,N),

Z*Z == X*X+Y*Y]

% Mejor, para evitar repeticiones

ternasP’(N)= [{X,Y,Z}|| Z <- lists:seq(1,N),

X <- lists:seq(1,Z-1),

Y <- lists:seq(1,X-1),

Z*Z == X*X+Y*Y]

Page 54: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Map, filter, append y listas intensionales

map(F,Xs) = [F(X) || X <- Xs]

filter(P,Xs) = [X || X <- Xs , P(X)]

append(Xss) = [X || Xs <- Xss , X <- Xs]

Recıprocamente toda lista intensional puede expresarse enterminos de map, filter y append.

+ Las listas intensionales son azucar sintactico

Page 55: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Manejo de errores y excepciones

Dos posibilidades en la evaluacion de una expresion

La evaluacion tiene exito y devuelve un valor > 1+2.

3

La evaluacion produce un error > 1+true.

exception error

Se genera o eleva una excepcion (raise an exception)Las excepciones rompen el flujo normal de evaluacionLas excepciones las puede generar:

el sistemael programador

Page 56: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Tipos de errores producidos por el sistema

Function Clause Errors

Case Clause Errors

If Clause Errors

Bad Match Errors

Bad Argument Errors

Undefined Function Errors

Bad Arithmetic Errors

Bad Function Errors

Bad Arity Errors

System Limit Errors

Page 57: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Captura de excepciones

Expresiones try. . . catch: version simple

try e

catch

error:PatronError -> e’

end

> try 1/0 catch error: -> ’Division por cero’.

’Division por cero’

> try 1/2 catch error: -> ’Division por cero’.

0.5

> try 1/0 catch error: -> 0.

0

> try 1/2 catch error:E -> E.

badarith

Page 58: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Captura de excepciones

Expresiones try. . . catch: forma general

try e of

Patron1 [when Guarda1 ] -> e1;

Patron2 [when Guarda2 ] -> e2;

...

catch

exceptionType1 :PatronError1 -> e1’

exceptionType2 :PatronError2 -> e2’

...

end

Page 59: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Tipos de excepciones

error: es el mas habitual.

Las produce el sistema como run-time errorsSe pueden producir mediante la BIF error(Why )

exit: mas ligada a procesos

Se pueden producir mediante la BIF exit(Why )

throw:

Se pueden producir mediante la BIF throw(Why )

Page 60: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Records: tuplas con nombre para las componentes

Personas, representadas como tupas

{Nombre,Apellido1,Apellido2,Edad,Tipo Documento, Num Documento,

Ciudad, Provincia }

{’Francisco’,’Lopez’,’Fraguas’,56,dni, 51334962,

Madrid, Madrid}

Page 61: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Records: tuplas con nombre para las componentes

Ejemplo: personas, representadas como records

. Definicion de la estructura de record para representar personas

> rd(persona, { nombre,ap1,ap2,

edad,tipo doc = dni,num doc,

ciudad = ’Madrid’,provincia=’Madrid’}).

. Creacion de un record persona concreto

> Yo = #persona{ nombre=’Francisco’,ap1=’Lopez’,

ciudad=’Getafe’,edad=56,

num doc=51344962}.

Page 62: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

rd/2 se usa en la shell para definir records

En programas hay que usar una directiva-record(Name,{...})Se suelen recolectar definiciones de records en ficheros *.hrl

Los ficheros *.hrl se cargan en otros mediante-include(file ).

Los ficheros *.hrl se cargan la shell mediante> rr(file ).

Page 63: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Acceso a componentes de records

Acceso a una componente concreta:> Yo#persona.edad.

56

O mediante pattern matching de records:> #persona{edad=E,ciudad=C} = Yo.

#persona{...}

> E.

56

> C.

’Getafe’

Creacion de un record por actualizacion de otro

> Yo1 = Yo#persona{ap2=’Fraguas’}.#persona{...}

> Yo#persona.ap2.

undefined

> Yo1#persona.ap2.

’Fraguas’

> Yo1#persona.edad.

56

Page 64: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Los records se muestran con apariencia de records

4> Yo.

#persona{nombre=’Francisco’,ap1=’Lopez’,ap2=undefined,edad=56,tipo doc=dni,

num doc=51334962,ciudad=’Getafe’,provincia=’Madrid}

Pero es azucar sintactico: son realmente tuplas

4> io:write(Yo).

{persona,’Francisco’,’Lopez’,undefined,56,dni,51334962,’Getafe’,’Madrid}ok

Tuplas: manejo de componentes por posicion

Records: manejo de componentes por nombre

Todo el procesado de los records es en tiempo de compilacion

Page 65: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

misrecords.hrl

-record(persona,{nombre,ap1,ap2,edad,tipo_doc=dni,num_doc,

ciudad=’Madrid’,provincia=’Madrid’}).

personas.erl

-module(personas).

-include("misrecords.hrl").

nombre_largo(Per) ->

{Per#persona.nombre,

Per#persona.ap1,

Per#persona.ap2}.

% Mejor con ajuste de patrones de record

nombre_largo1(#persona{nombre=N,ap1=Ap1,ap2=Ap2}) ->

{N,Ap1,Ap2}.

% Peor, usando tuplas

nombre_largo2(Per) ->

{element(2,Per),element(3,Per),element(4,Per)}.

Page 66: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +

Macros: expansiones en tiempo de compilacion

-define(Constante,Valor ).

-define(Func(V1,...,Vn) -> Valor ).

Ejemplos

-define(ESCALA,1000).

-define(Doble(X) -> 2*X).

Una macro MACRO se usa como ?MACRO

-module(mapas).

-define(ESCALA,1000).

escala(X) -> X/?ESCALA.

Las macros se suelen recolectar en ficheros *.hrl

Existen macros condicionales: ver libro o manual

Existen macros predefinidas: ?MODULE,?FILE,?LINE

Page 67: Erlang Secuencial - UCMgpd.sip.ucm.es/jaime/pda/erlang_secuencial.pdf · 2015-04-14 · Lo que nunca encontraremos: X=X+1 No hay variables asignables a un valor que va cambiando +