Evaluación de expresiones de un lenguaje funcional La sintaxis de un lenguaje funcional básico Sintaxis Básica E E Es Es E E E E E E E atom (Es) E E , Es if E then E else E fi fun x E (E,E) let v = x in E let rec v = E in E prim E EE Azucar Sintáctico Al definir funciones: let foo = fun n Exp también podemos escribir let foo n = Exp Análogamente con let rec let rec foo = fun n Exp podría escribirse así let foo n = Exp Ejemplo let rec append = fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi in append((1,(2,(3,nil))),(4,nil)) Ejemplo let rec fact = fun n if (n=0) then 1 else n*fact(n-1) fi in fact(3)+fact(5) Ejemplo con azúcar sintáctico let rec append (x , y) = if null?(x) then y else (car(x), append(cdr(x),y)) fi in append((1,(2,(3,nil))),(4,nil)) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi append((1,(2,(3,nil))),(4,nil)) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (if null?(x) then y else (car(x), append(cdr(x),y)) fi ) ((1,(2,(3,nil))),(4,nil)) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi if null?((1,(2,(3,nil)))) then (4,nil) else (car((1,(2,(3,nil)))),append(cdr((1,(2,(3,nil)))), (4,nil)))) fi Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (car((1,(2,(3,nil)))), append(cdr((1,(2,(3,nil)))), (4,nil))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1, append(cdr((1,(2,(3,nil)))), (4,nil))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1, append( (2,(3,nil))), (4,nil))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1, fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi ( (2,(3,nil))), (4,nil))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1, if null?((2,(3,nil))) then (4,nil) else (car((2,(3,nil))), append(cdr((2,(3,nil))), (4,nil))) fi Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1, (car((2,(3,nil))), append(cdr((2,(3,nil))), (4,nil))) fi Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi in append((1,(2,(3,nil))),(4,nil)) (1,(2, append(cdr((2,(3,nil))), (4,nil))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, append( (3,nil), (4,nil)))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, (if null?(x) then y else (car(x), append(cdr(x),y)) fi (3,nil), (4,nil))) ) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, if null?((3,nil)) then (4,nil) else (car((3,nil), append(cdr((3,nil)), (4,nil))) fi)) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, (car((3,nil)), append(cdr((3,nil)), (4,nil))))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, (3, append(cdr((3,nil)), (4,nil))))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, (3, append(nil, (4,nil))))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, (3, if null?(x) then y else (car(x), append(cdr(x),y)) fi (nil, (4,nil))))) Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, (3, if null?(nil) then (4,nil) else (car(nil), append(cdr(nil), (4,nil))) fi Evaluación simple fun (x , y) if null?(x) then y else (car(x), append(cdr(x),y)) fi (1,(2, (3, (4,nil)))) Ejemplo • Let sumx = fun x -> fun y -> (x+y) in let sum5 = fun x -> ((sumx 5) x) in (sum5 6) (sum5 6) Ejemplo • Let sumx = fun x -> fun y -> (x+y) in let sum5 = fun x -> ((sumx 5) x) in (sum5 6) ((fun x -> ((sumx 5) x)) 6) Ejemplo • Let sumx = fun x -> fun y -> (x+y) in let sum5 = fun x -> ((sumx 5) x) in (sum5 6) ((sumx 5) 6) Ejemplo • Let sumx = fun x -> fun y -> (x+y) in let sum5 = fun x -> ((sumx 5) x) in (sum5 6) (( (fun x -> fun y -> (x+y) ) 5) 6) Ejemplo • Let sumx = fun x -> fun y -> (x+y) in let sum5 = fun x -> ((sumx 5) x) in (sum5 6) ( (fun y -> (5+y)) 6) Ejemplo • Let sumx = fun x -> fun y -> (x+y) in let sum5 = fun x -> ((sumx 5) x) in (sum5 6) (5+6) Ejemplo • Let sumx = fun x -> fun y -> (x+y) in let sum5 = fun x -> ((sumx 5) x) in (sum5 6) (11) Evaluación en un ambiente E e v El valor de e en el ambiente E es v E(x) =v (VAR) E x v Evaluación en un ambiente E e1 E E E E (e1 ... en) e1 E E v1 … true E en vn (v1 ... vn) e2 v2 if e1 then e2 else e3 fi e1 false E (n-tupla) e3 (cond1) v2 v3 if e1 then e2 else e3 fi (cond2) v3 Evaluación en un ambiente: Funciones de un argumento (Fun1) E E (fun x e) e1 <E’, (fun x e) > E (x:v2)::E’ e ( e1 e2 ) v <E, (fun x e) > v E e2 v2 (app1) Evaluación en un ambiente: Funciones de un argumento (Fun2) E E e1 <E’, (fun (x1, (x1:v1):: E ,xn) e) (fun (x1, ,xn) e) > ::(xn:vn)::E’ ( e1 e2 ) v e ,xn) e) > <E, (fun (x1, E e2 v1, ,vn v (app2) Evaluación en un ambiente: Funciones Primitivas E E e v ( prim e ) E E e1 v1 … (prim) prim v E prim(e1 ... en) en vn prim(v1 ... vn) (prim-n) Evaluación con Ambientes: Definiciones E e1 (x:v1)::E v1 E let x= e1 in e e v (let) v E’=(f:<E’,(fun xe1)>)::E E’ E e v let rec f x= e1 in e (letrec) v Referencias G. Cousineau & M. Mauny, The functional approach to programming, Cambridge University Press,1998 Otro enfoque Valor(exp, E) = v E exp v Se puede entonces hacer el cálculo simplemente haciendo reemplazos de iguales por iguales Evaluación en un ambiente Valor(x,E) = E(x) si x es variable (VAR) Valor(c,E) = E(x) si c es constante (CONST) Valor((v1 ... vn), E) =(valor(v1,E) ... Valor(vn,E)) (TUPLE) Valor( if exp1 then exp2 else exp3 fi) = if valor(exp1,E) then valor(Exp2,E) else (valor(Ep3,E) fi (COND) Valor (fun x e, E) clo( x, e, E) <FUN> Valor(let x = e1 in e2, E) = valor(e2, (x,valor(e1,E))::E) Valor(e1 e2) = ValorApp (valor(e1,E), valor(e2,E)) ValorApp(f,e) = IF f=clo(x,e2,E) THEN valor(e2, x:e::E) ELSE error FI Recursión Valor(let rec f = fun x body in exp, E) = valor(exp, E’) E’=(f:clo(x, body.E’)::E Un ejemplo let sumX = fun x fun y x + y in let sum5 = sumX 5 in sum5 2; Valor (let sumX = fun x fun y (x +y) in let sum5 = sumX 5 in sum5 2, ()) = se aplica la regla del LET Valor (let sum5 = sumX 5 in sum5 2, (sumX:valor(fun xfun y x+y,()))::()) = se aplica la regla de FUN para obtener su valor (ver ET) Valor (let sum5 = sumX 5 in sum5 2, (sumX:clo(x,fun y x +y,())::()) = se aplica la regla del LET Valor (sum5 2, (sum5:valor(sumX 5, Et))::Et)) = se aplica la regla de app Valor (sum5 2, (sum5:valorApp(valor(sumX,Et), valor( 5, Et))::Et)) Et =(sumX:clo(x,fun y x +y,())::() Valor (sum5 2, (sum5:valorApp(valor(sumX,Et), valor( 5, Et))::Et)) = la regla de var Valor (sum5 2, (sum5:valorApp(clo(x,fun y x+y,()), valor( 5, Et))::Et)) = la regla de const Valor (sum5 2, (sum5:valorApp(clo(x,fun y x+y,()), 5)::Et)) = valorApp Valor (sum5 2, (sum5:valor(fun y x+y, (x: 5 )::())::Et)) = regla de fun Valor (sum5 2, (sum5:clo( y,x+y, (x: 5 )::()))::Et)) = regla de app ValorApp (Valor (sum5, (sum5:clo( y,x+y, (x: 5 )::()))::Et)), Valor (2, (sum5:clo( y,x+y, (x: 5 )::()))::Et))) Et =(sumX:clo(x,fun y x +y,())::() ValorApp (Valor (sum5, (sum5:clo( y,x+y, (x: 5 )::()))::Et)), Valor (2, (sum5:clo( y,x+y, (x: 5 )::()))::Et))) = regla de VAR ValorApp (clo( y, x+y, (x: 5 )::()), Valor (2, (sum5:clo( y,x+y, (x: 5 )::()))::Et))) = regla de const ValorApp (clo( y,x+y, (x: 5 )::()), 2) = regla de valorApp Valor (x+y, (y: 2 ):(x: 5 )::()))) = regla de prim Valor (x, (y: 2 ):(x: 5 )::()))) + Valor (y, (y: 2 ):(x: 5 )::()))) = regla de var 5 + Valor (y, (y: 2 ):(x: 5 )::()))) = regla de var Et =(sumX:clo(x,fun y x +y,())::() 5 +2 Valor (let sumX = fun x fun y (x +y) in let twice fun f fun x f (f x) in (twice (sumX 3)) 4, ()) = valor (fun x fun y (x +y) , ()) = clo(x,fun y x +y,()) Valor (let twice fun f fun x f (f x) in (twice (sumX 3)) 4, (sumX: clo(x,fun y x +y),())::()) = valor (fun f fun x f( f x), Et) = clo(x,fun y x +y,Et) Valor ((twice (sumX 3)) 4, (twice: clo(f , fun x f (f x), Et))::Et) Et =(sumX:clo(x,fun y x +y,())::() Et =(sumX:clo(x,fun y x +y,())::() E =(twice:clo(f,fun x f (f x)),Et)::Et Valor ((twice (sumX 3)) 4, E) = es una aplicación de twice (sumX 3) sobre 4 ValorApp (Valor (twice (sumX 3), E ), Valor (4, E ) ) = es una aplicación de twice sobre (sumX 3) ValorApp (ValorApp (Valor( twice, E) , Valor((sumX 3), E)), Valor (4, E ) ) = el valor de twice está en el ambiente ValorApp (ValorApp (clo(f,fun x f (f x),Et) , Valor((sumX 3), E) ), Valor (4, E)) = Et =(sumX:clo(x,fun y x +y,())::() E =(twice:clo(f,fun x f (f x)),Et)::Et ValorApp (ValorApp (clo(f,fun x f (f x),Et) , Valor((sumX 3), E)), Valor (4, E ) ) = El valor de sumX 3 es una aplicación ValorApp (ValorApp (clo(f,fun x f (f x),Et) , ValorApp(Valor ( sumX , E), Valor ( 3, E))), Valor (4, E ) ) = El valor de sumX está en el ambiente ValorApp (ValorApp (clo(f,fun x f (f x),Et) , ValorApp(clo(x,fun y x +y,()), Valor ( 3, E))), Valor (4, E ) ) = El valor de 3 es 3 ValorApp (ValorApp (clo(f,fun x f (f x),Et) , ValorApp((clo(x,fun y x +y),()), 3)), Valor (4, E ) ) Et =(sumX:clo(x,fun y x +y,())::() E =(twice:clo(f,fun x f (f x)),Et)::Et ValorApp (ValorApp (clo(f,fun x f (f x),Et) , ValorApp((clo(x,fun y x +y),()), 3)), Valor (4, E ) ) = Ya se puede aplicar ValorApp (ValorApp (clo(f,fun x f (f x),Et) , Valor(fun y x +y, (x:3)::()), Valor (4, E ) ) = El valor de una función en un ambiente ValorApp (ValorApp (clo(f,fun x f (f x),Et) , clo (y, x +y, (x:3)::() )), Valor (4, E ) ) Et =(sumX:clo(x,fun y x +y,())::() E =(twice:clo(f,fun x f (f x)),Et)::Et E1 = (f:clo (y, x +y, (x:3)::()))::Et ValorApp (ValorApp (clo(f,fun x f (f x),Et) , clo (y, x +y, (x:3)::() )), Valor (4, E ) ) = ya se puede aplicar la regla de ValorApp ValorApp (Valor(fun x f (f x), (f:clo (y, x +y, (x:3)::() ))::Et), Valor (4, E ) ) = regla de FUN ValorApp (clo(x, f (f x), (f:clo (y, x +y, (x:3)::()))::Et ) Valor (4, E ) ) = Regla de const y definimos E1 ValorApp (clo(x, f (f x), E1),4 ) Et =(sumX:clo(x,fun y x +y,())::() E =(twice:clo(f,fun x f (f x)),Et)::Et E1 = (f:clo (y, x +y, (x:3)::()))::Et ValorApp (clo(x, f (f x), E1) ,4 ) = ya se puede aplicar la regla de ValorApp Valor( f (f x), (x:4)::E1 ) = Regla de App ValorApp(valor( f, (x:4)::E1) , valor ((f x), (x:4)::E1 )) = Regla de Var ValorApp(clo (y, x +y, (x:3)::() ), valor ((f x), (x:4)::E1 )) = Regla de App ValorApp(clo (y, x +y, (x:3)::() ) , valorApp (valor(f,(x:4)::E1 ), valor(x,(x:4)::E1 ))) = Et =(sumX:clo(x,fun y x +y,())::() E =(twice:clo(f,fun x f (f x)),Et)::Et E1 = (f:clo (y, x +y, (x:3)::()))::Et ValorApp(clo (y, x +y, (x:3)::() ) , valorApp (valor(f,(x:4)::E1 ), valor(x,(x:4)::E1 ))) = Regla de Var ValorApp(clo (y, x +y, (x:3)::() ) , valorApp (clo (y, x +y, (x:3)::() ) , valor(x,(x:4)::E1 ))) = Regla de Const ValorApp(clo (y, x +y, (x:3)::() ) , valorApp (clo (y, x +y, (x:3)::() ) , 4)) = Regla de ValorApp ValorApp(clo (y, x +y, (x:3)::() ) , valor (x +y, (y:4):: (x:3)::()) ) = Reglas de prim y luego regla de const y luego sumar ValorApp(clo (y, x +y, (x:3)::() ) , 7) Et =(sumX:clo(x,fun y x +y,())::() E =(twice:clo(f,fun x f (f x)),Et)::Et E1 = (f:clo (y, x +y, (x:3)::()))::Et ValorApp(clo (y, x +y, (x:3)::() ), 7) = Regla de valor App Valor(x+y, (y:7)::(x:3)::()) = Regla de prim de const y luego sumar 10 Valor(let rec fact = fun x if zero?(x) then 1 else times(x,fact(pred(x)) fi in fact 2 ()) = valor (fact 2, E) = valorApp (valor(fact ,E), valor(2,E)) = valorApp(clo( x,if zero?(x) then 1else times(x,fact pred(x),E),2) = valor(if zero?(x) then 1else times(x , fact pred(x)) fi,(2:x)::E) E=(fact:clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi,E))::() E=(fact:clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi,E))::() valor(if zero?(x) then 1else times(x,fact pred(x)) fi,(2:x)::E) = IF Valor(zero?(x), (2:x)::E) THEN valor(1, (2:x)::E) ELSE Valor(times(x, fact pred(x)),(2:x)::E) FI = IF zero?(Valor(x, (2:x)::E)) THEN valor(1, (2:x)::E) ELSE Valor(times(x, fact pred(x)),(2:x)::E) FI = IF zero?(2) THEN valor(1, (2:x)::E) ELSE Valor(times(x,fact pred(x)),(2:x)::E) FI = IF false THEN valor(1, (2:x)::E) ELSE Valor(times(x,fact pred(x)),(2:x)::E) FI = Valor(times(x,fact pred(x)),(2:x)::E) E=(fact:clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi,E))::() Valor(times(x,fact pred(x)),(2:x)::E) = Times(Valor(x, (2:x)::E), Valor(fact(pred(x)),(2:x)::E))) = Times(2, Valor(fact(pred(x)),(2:x)::E))) = Times(2, ValorApp(valor(fact, (2:x)::E), valor(pred(x),(2:x)::E))) = Times(2, ValorApp(clo( x,if zero?(x) then 1else times(x, fact pred(x)) fi,E), valor(pred(x),(2:x)::E))) = Times(2, ValorApp(clo( x,if zero?(x) then 1else times(x, fact pred(x)) fi,E), pred(valor(x,(2:x)::E)))) = Times(2, ValorApp(clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi, E), pred(2)) E=(fact:clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi,E))::() Times(2, ValorApp(clo( x,if zero?(x) then 1else times(x, fact pred(x)) fi,E), pred(2)) = Times(2, ValorApp(clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi,E), 1) = Times(2, Valor(if zero?(x) then 1else times(x,fact pred(x)) fi,(x:1)::E) = Times(2, IF valor(zero?(x), (x:1)::E) THEN valor(1, (x:1)::E) ELSE valor(times(x, fact pred(x)),(x:1)::E)) FI = Times(2, IF zero?(valor( x, (x:1)::E) ) THEN valor(1, (x:1)::E) ELSE valor(times(x,fact pred(x)),(x:1)::E)) FI = Times(2, IF zero?(1 ) THEN valor(1, (x:1)::E) ELSE valor(times(x, fact pred(x)),(x:1)::E)) FI = Times(2, IF false THEN valor(1, (x:1)::E) ELSE valor(times(x, fact pred(x)),(x:1)::E)) FI E=(fact:clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi,E))::() Times(2, IF false THEN valor(1, (x:1)::E) ELSE valor(times(x, fact pred(x)),(x:1)::E)) FI = Times(2, valor(times(x,fact(pred(x)),(x:1)::E)) = Times(2, Times(valor(x,(x:1)::E), valor(fact pred(x),(x:1)::E))) = Times(2, Times(1, valor(fact pred(x),(x:1)::E))) = Times(2, Times(1, valorApp(valor(fact,(x:1)::E),valor(pred(x),(x:1)::E)))) = Times(2, Times(1, valorApp(clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi , E), valor(pred(x),(x:1)::E)))) = Times(2, Times(1, valorApp(clo( x, if zero?(x) then 1else times(x,fact pred(x)) fi , E), pred(valor(x,(x:1)::E)))) E=(fact:clo( x,if zero?(x) then 1else times(x,fact pred(x)) fi,E))::() Times(2, Times(1, valorApp(clo( x, if zero?(x) then 1else times(x,fact pred(x)) fi , E), pred(valor(x,(x:1)::E)))) = Times(2, Times(1, valorApp(clo( x, if zero?(x) then 1else times(x,fact pred(x)) fi, E), pred(1))) = Times(2, Times(1, valorApp(clo( x, if zero?(x) then 1else times(x,fact pred(x)) fi , E), 0)) = Times(2, Times(1, valor(if zero?(x) then 1else times(x,fact pred(x)) fi,(x:0)::E))) = Times(2, Times(1, IF valor(zero?(x), (x:0)::E) THEN valor(1, (x:0)::E) ELSE valor(times(x,fact pred(x)),(x:0)::E) FI)) = Times(2, Times(1, IF zero?(valor(x, (x:0)::E) THEN valor(1, (x:0)::E) ELSE valor(times(x,fact pred(x),(x:0)::E) FI)) E=(fact:<E,clo( x,if zero?(x) then 1else times(x,fact(pred(x))>):: () Times(2, Times(1, IF zero?(valor(x, (x:0)::E) THEN valor(1, (x:0)::E) ELSE valor(times(x,fact pred(x),(x:0)::E) FI)) = Times(2, Times(1, IF zero?(0) THEN valor(1, (x:0)::E) ELSE valor(times(x,fact pred(x),(x:0)::E) FI)) = Times(2, Times(1, IF true THEN valor(1, (x:0)::E) ELSE valor(times(x,fact pred(x),(x:0)::E) FI)) = Times(2, Times(1, valor(1, (x:0)::E))) = Times(2, Times(1,1)) = Times(2, 1) = Times2