You are on page 1of 31

TEMA IMPLEMENTACION DE LENGUAJES FUNCIONALES.

Leccines

Clasificacin de los Lenguajes Funcionales

Segn el mtodo de evaluacin Evaluacin estricta (eaguer) Evaluacin diferida (lazy, perezosa) Segn la asignacin Lenguajes funcionales puros o sin asignacin Lenguajes funcionales con asignacin Mquina abstracta para un lenguaje con evaluacin eager (directa) FAM mquina basada en mbitos Mquina abstracta para un lenguaje con evaluacin lazy (diferida) G-Machine mquina basada en grafos y combinadores.

Implementacin de la Evaluacin Estricta


Un lenguaje funcional con evaluacin estricta se parece mucho a un lenguaje imperativo por Las operaciones se realizan en el orden que indica el programador La evaluacin estricta es compatible con la asignacin Idea de implementacin Modificar la mquina abstracta para lenguajes imperativos para que pueda ejecutar lenguajes funcionales con evaluacin estricta. Problemas a resolver con las modificaciones Implementacin ptima de la recursividad en cola. Funciones locales validas fuera de su entorno de definicin Clausuras (cdigo funcin+mbito) Acceso a mbitos de funciones inactivas

Recursividad en Cola: Importacia

Problema de los lenguajes funcionales puros Un lenguaje funcional puro no tiene asignacin. Por lo tanto, los cambios de estado solo se pueden realizar creando nuevas variables, o sea, realizando llamadas a funciones. Un programa que interaccione con el mundo real ha de cambiar su estado para representar el nuevo estado del mundo. Si para cada llamada a funcin se utiliza espacio de pila, el resultado es que el programa llenar la pila. Solucin: Optimizacin de la recursividad en cola La interaccin se implementa en un lenguaje imperativo con un bucle que procesa los eventos que vienen del mundo. En un lenguaje funcional se implementa con una funcin que procesa un evento y que al final se llama recursivamente para procesar en siguiente evento (recursividad en cola). Objetivo: Conseguir que la ltima llamada que realiza una funcin no consuma pila.

ltima llamada en un lenguaje imperativo 5

Recursividad en Cola: void f(a,b) { Problema


int c,d,e; ... g(c,d) }

Estado de la pila justo antes de llamar a g ( parametros de g en la pila)

Pila anterior b a PC f ED c d e d c

Bloque de activacin de f

Parmetros de g

Contenido de la pila que necesita la llamada a g. El bloque de activacin de f se puede eliminar ya que lo ltimo que se hace es llamar a g. Problema: despus del bloque de activacin de f se encuentran los parmetros de g

Pila anterior d c PC f

Usar dos pilas 6

Recursividad en Cola: Pila de contexto con los bloques de activacin un pila de Solucin parmetros.
De esta forma se evita que los parmetros impidan la eliminacin del bloque de activacin antes de la ltima llamada Los parmetros se han de copiar de la pila de argumentos al bloque de activacin o mbito de la funcin

Pila de Contexto

EP
CSP

AP Pila de Argumentos

Llamada a una Funcin (Ambito en la Pila)

Cdigo Llamada
Calcular los argumentos y ponerlos en la pila de argumentos Llamar a la funcin

Cdigo Funcin
Guardar EP en la pila Copiar argumentos de la pila de argumentos a la pila de contexto Inicializar espacio de variables Cuerpo de la funcin Poner el valor de retorno en un registro

Eliminar de la pila variables y argumentos


Recuperar EP retornar

Ejemplo de Secuencia de Llamada

Fun f(x,y)=>{ Var A; x+y; } Llamada f(10,20) Cdigo llamada


PushArg 10 PushArg 20 Call f

Cdigo funcin
PushCon EP EP=SP PopArg VR PushCon VR PopArg VR

PushCon VR
PushCon NIL Cuerpo funcin SP=EP PopCon EP Ret

Aplicacin de la Recursividad en Cola

Funcin que realiza una llamada

Fun f(x)={ g(10,20); }


Cdigo sin optimizar

PushArg 10 PushArg 20 Call g

SP=EP
PopCon EP Ret
Eliminar bloque de activacin de f antes de llamar

PushArg 10 PushArg 20 SP=EP PopCon EP Call g

Ret
Cdigo optimizado

PushArg 10 PushArg 20 SP=EP PopCon EP Jmp g

10

Definiciones Anidadas y Clausuras

En los lenguajes funcionales son bsicas las siguientes caractersticas


Definicin anidada de funciones
Esta implica el uso de display

Poder tratar cualquier funcin como un valor (apuntadores a funciones)


Para que una funcin local a otra pueda referenciarse desde donde queramos hay que asociarle su mbito de definicin. Esta asociacin la realizan las clausuras A travs de una clausura es posible acceder a un mbito de una funcin despus de que esta haya acabado su ejecucin

Funciones lambda o annimas


Son necesarias para facilitar la escritura de llamadas a funciones de orden superior, pero no obligan a modificar la mquina abstracta una vez consideradas las caractersticas anteriores
Son funciones definidas localmente Son funciones tratadas como un valor

Una clausura es

11
Fun f(x)={

Apuntador a la entrada del cdigo de la funcin Ambito de la funcin donde se creo

Display o valor de EP cuando se creo la clausura

Implementacin de Clausuras

Var y; Fun g(a,b)= { Var z; ... } g }

Bloque de activacin de f Clausura de g PC EP x y EP Entrada g EP def Clausura

Bloque de activacin de g PC EP EP f a b z

EP

Display

12 La funcin f retorna la clausura de g y al llamar a esta clausura Solucin:

Ambitos en el Heap

se puede acceder a las variables de f. Por lo tanto, no se puede eliminar el mbito de f al finalizar su ejecucin
Guardar el mbito de f en el heap para que no se elimine al salir de f Los mbitos en el heap existirn hasta que no se pueda acceder a ellos

Pila anterior PC EP SP

nulo x y Env

EP

Contenido de la pila al llamar a f con el mbito en el heap

Nodo con el mbito de f en el heap

13

Llamada a una Funcin con el mbito en el Heap

Cdigo Llamada
Calcular los argumentos y ponerlos en la pila de argumentos Llamar a la funcin

Cdigo Funcin
Guardar EP en la pila Crear nodo de mbito en el heap e inicializarlo EP apunta al nodo de mbito Copiar argumentos de la pila de argumentos al mbito Cuerpo de la funcin Poner el valor de retorno en un registro Recuperar EP de la pila de contexto retornar

14

mbito Ambito en la pilaen la Pila y en el


Pila deHeap contexto PC EP Display Argumentos Variables CSP

EP

Ambito en el Heap

Heap nulo EP

Pila de contexto PC EP

Display CSP Argumentos Variables Env

15

Llamada a una Clausura

Cdigo Llamada
Calcular los argumentos y ponerlos en la pila de argumentos Clo=Clausura Llamar a la funcin

Cdigo Funcin
Guardar EP en la pila de contexto Crear el Display a partir del EP de Clo Copiar argumentos de la pila de argumentos a la pila de contexto Inicializar espacio de variables en la pila de contexto Cuerpo de la funcin

Poner el valor de retorno en un registro


Recuperar EP de la pila de contexto retornar

16

Implementacin de un Interprete de LISP Basado en Precompilacin


Organizacin de la memoria
EP: apuntador al mbito activo CSP: apuntador a la cabeza de la pila de contexto ASP: apuntador a la cabeza de la pila de argumentos PC: contador de programa

Pila de Contexto

EP CSP

AP
Pila de Argumentos Heap PC

17

Pila de Contexto y Pila de Argumentos

En la pila de contexto se guarda


PC de retorno Bloques de mbito (bloques de activacin de las funciones)

En la pila de argumentos se guarda


Los argumentos de las funciones El valor de retorno Los resultados intermedios de la evaluacin de expresiones

En el Heap se guarda
Nodos de listas, smbolos, paquetes, etc. Cdigo de las funciones (puede estar en un segmento de memoria aparte si no puede variar) Clausuras Bloques de mbito accesibles desde fuera de la funcin que los ha creado

18

Llamada a una Funcin LISP

Cdigo de llamada
Poner los argumentos en la pila de argumentos Nargs=Nmero de argumentos Call funcion

Cdigo de la funcin
Verificar del nmero de argumentos (NArgs) Guardar EP en la pila de contexto Crear el mbito (EP apunta hacia el)
Copiar el Display de la clausura de la funcin

Leer los argumentos y ponerlos en el mbito Ejecutar el cuerpo de la funcin (deja el valor de retorno en la pila de argumentos Eliminar el mbito Recuperar EP de la pila de contexto retornar

19

Llamada a Funcin Simple

Poner Arg.

Crear mbito

Funcin: (defun f (x y) (list x y)) Llamada: (f 10 20)

Sacar Arg

Ejecutar cuerpo

Salir

PC de ret PC de ret PC de ret PC de ret EP EP EP X X=10 X=10 Y Y=20 Y=20 20 10 20 10

(10 20)

(10 20)

20

Llamada a Funcin con Display

Funcin:

Poner Arg.

Crear (labels ((gSacara x))) Ejecutar (a) (+ Arg mbito(list x (g y)))) cuerpo
Llamada: (f 10 20)

(defun f (x y)

Salir

PC de ret PC de ret EP EP X=10 X=10 Y=20 Y=20 PC de ret PC de ret EP(ED) Disp:EP f a

PC de ret EP X=10 Y=20 PC de ret EP(ED) Disp:EP f a=20

PC de ret PC de ret EP EP X=10 X=10 Y=20 Y=20 PC de ret EP(ED) Disp:EP f a=20

20 10

20 10

10

30 10

30 10

21

Clausuras

Una clausura un cdigo de una funcin junto clausura de g es mbito en quede F de ejecutarcon mbito se ha el apuntador al la funcin. X=10 Ejemplo: clausura de g: Y=20

Cdigo de G

Donde ha de estar el mbito de f:


Si solo se llama a g desde dentro de f, el mbito de f puede estar en la pila Si es posible llamar a g desde fuera de f, el mbito de f ha de estar en el HEAP.

22

Ejempo de Clausuras en el HEAP

Funcin que retorna dos funciones ligadas por una variable local

(defun varEscondida (n) (list (lambda (x) (+ x n)) (lambda (x) (setq n x))

)
) (setq a (varEscondida 10)) (#<Closure: #ffd8b044> #<Closure: #ffd8b020>) (funcall (first a) 5) 15 (funcall (second a) 30) 30 (funcall (first a) 5) 35

23

Listas Por Comprensin

La notacin de conjuntos por comprensin es


Compacta

{x 2 | x [1..100 ], x mod 5 0}

Fcil de entender Muy expresiva

Por ejemplo
Expresa el conjunto de los cuadrados de los nmeros pertenecientes al intervalo [1,100] divisibles por 5.

Por lo anterior se ha implementado en los lenguajes de programacin funcionales Hope, Miranda, Haskell, etc., pero se cambia el conjunto por lista. Notacin: [expresin | generadores y guardas]
Generador: variable <- lista o intervalo

Guarda: condicin

Ejemplo: [x**2

| x<-1..100,

x%5==0]

24

Generadores y Guardas

[expresin | generadores y guardas] Generadores variable <- lista o intervalo


Declara la variable La variable se instanciar con todos los elementos de la lista

Guardas condicin
Si la condicin se cumple se evaluar la expresin y se guardar en la lista resultante

Ejemplos

var l=[1,2,3,9,1] var l2=[6,4,2,19] [(x,y) | x<-l; y<-l2, x>y]

Resultado:
[(3,2),(9,6),(9,4),(9,2)]

25

Quick Sort con Listas por Comprensin

Fun Sort(l:List)=> { if (l==[]) [] else Sort([x | x<-l.Tail, x<l.Head)]) ++ [l.Head] ++

Sort([x | x<-l.Tail, x>=l.Head])


}

Fun Sort(l:List)=> { if (l==[]) [] else { Var menores=[]; for (e<-l.Tail) if (e<l.Head) menores=e::menores; Var mayores=[]; for (e<-l.Tail) if (e>=l.Head) mayores=e::mayores; Sort(menores)++[l.head]++Sort(mayores) } }

26

Qsort Funcional e Imperativo

Quicksort in Haskell

qsort []

= []

qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x

where

elts_lt_x

= [y | y <- xs, y < x]

elts_greq_x = [y | y <- xs, y >= x]

Quicksort in C

void qsort( int a[], int lo, int hi )

int h, l, p, t;

if (lo < hi) {

l = lo;

h = hi;

p = a[hi];

do {

while ((l < h) && (a[l] <= p))

l = l+1;

while ((h > l) && (a[h] >= p))

h = h-1;

if (l < h) {

t = a[l];

a[l] = a[h];

a[h] = t;

} while (l < h);

t = a[l];

a[l] = a[hi];

a[hi] = t;

qsort( a, lo, l-1 );

qsort( a, l+1, hi );

27

Listas por Comprensin en LISP (I)

(defmacro listcomp (Exp &rest Conds) (let ((SymList (gensym "LIST")) (SymP (gensym "P"))) `(let* ((,SymLIST (cons nil nil)) (,SymP ,SymLIST)) ,(ListComp2 Exp Conds SymP) (cdr ,SymLIST) )

)
) (defun ListComp2 (E Q L) (cond ((null Q) `(progn (setf (cdr ,L) (cons ,E nil)) (setq ,L (cdr ,L))) ) ((and (consp (car Q)) (eq (caar Q) 'in)) `(dolist (,(cadar Q) ,(caddar Q)) ,(ListComp2 E (cdr Q) L) ) ) (T `(when ,(car Q) ,(ListComp2 E (cdr Q) L))) ) )

28

Listas por Comprensin en LISP (II)

Ejemplo
(setq l (1 10 5 2 9)) (ListComp (* x x) (in x l) (> x 3)) Resultado: (100 25 81) Cdigo generado:

(LET* ((LIST5 (CONS NIL NIL)) (P6 LIST5)) (DOLIST (X L) (WHEN (> X 3) (PROGN (SETF (CDR P6) (CONS (* X X) NIL)) (SETQ P6 (CDR P6))))) (CDR LIST5))
Cdigo optimizado:

(LET* ((LIST5 (CONS NIL NIL)) (P6 LIST5)) (DOLIST (X L) (WHEN (> X 3) (SETF (CDR P6) (CONS (* X X) NIL)) (SETQ P6 (CDR P6)))) (CDR LIST5))

29

Listas por Comprensin en CoSeL

Fun ListComp(Exp,Conds)=> { Var SList=symbol("Lista"), SP=symbol("Posicion"); Fun ListComp2(Conds)=> { if (Conds==[]) << { *<SymP> = [<Exp>]; <SP> = &<SP>->Tail; } >> else if (ApplyFunP(Conds.Head,`\<-,2)) { // Generador Var sl=symbol("ListaGenerador"), sv=Conds.Head.Arg(0); Var srepetir=symbol("Repetir"); << { Var <sl> = <Conds.Head.Arg(1)>; Label <sRepetir>; if (<sl> != []) { Var <sv> = <sl>.Head; <ListComp2(Conds.Tail)>; <sl> = <sl>.Tail; goto <sRepetir>; } } >> } else { // Condicin << if (<Conds.Head>) <ListComp2(Conds.Tail)> >> } } << { Var <SList> = [], <SP> = &<SList>; <ListComp2(Conds)>; <SList> } >> }

30

Ejemplo

ListComp(`x,[`(x<-li),`(x>10)]) { Var Lista=[]; Var Posicion=&Lista; {

Var ListaGenerador=li;
Label Repetir; if (ListaGenerador!=[]) { Var x=ListaGenerador.Head; if (x>10) { &Posicion=[x]; Posicion=&Posicion->Tail; } ListaGenerador=ListaGenerador.Tail; GoTo Repetir } } Lista }

31

Pattern Maching

You might also like