Paradigme de Programare

Laborator 3 - Lambda0 ˆ Scheme ın

by Mihai Maruseac May 20, 2010

Am ar˘tat ˆn laboratorul trecut cum putem implementa unele structuri de date ca a ı functii. Vom insista azi putin asupra acestui lucru si vom trece apoi la a studia , , , modul de transmitere a parametrilor ˆn Scheme. ı

Lambda0
Ne amintim din laboratorul trecut ca puteam reprezenta tipuri de date si structuri , ca functii ˆ form˘ curry cu mai multe argumente: ın a , (define false (lambda (x) (lambda (y) y))) (define true (lambda (x) (lambda (y) x))) (define no (lambda (b) ((b false) true))) (define and (lambda (x) (lambda (y) ((x y) false)))) (define or (lambda (x) (lambda (y) ((x true) y)))) Ne amintim c˘ true returna primul argument iar false pe al doilea si c˘ ne-am a a , folosit de acest lucru pentru a genera codul pentru celelalte operatii. , Pornind de la aceste definitii, vom extinde lumea tipurilor de date cu ˆ a trei ınc˘ , structuri:

tipul pereche - Pair. Avem nevoie de functii pentru a accesa primul si al , , doilea element: (define pair (lambda (x) (lambda (y) (lambda (z) ((z x) y))))) (define fst (lambda (p) (p true))) (define snd (lambda (p) (p false))) tipul list˘ - List. Tinˆnd cont c˘ o list˘ este de fapt o pereche cu cons si a a a a , , car implementarea este usoar˘: a , (define conss pair) (define carr fst) (define cdrr snd) (define nil (lambda (x) true)) (define null (lambda (l) (l (lambda (x) (lambda (y) false))))) Functia nil returneaz˘ lista vid˘ iar null este predicatul pentru a testa dac˘ a a a , o list˘ e vid˘. a a tipul num˘r natural - Number. Ne baz˘m pe tipul list˘ si pe reprezentarea a a a , multimii numerelor naturale ˆ baza 1 (aritmetica lui Peano) ın , (define (define (define (define n0 nil) succ (lambda (n) ((conss nil) n))) pred cdrr) zero nulll)

Evaluare aplicativ˘ a
Evaluarea cea mai des ˆ alnit˘ este cea aplicativ˘. O ˆ anlnim ˆ toate limbajele ıntˆ a a ıntˆ ın imperative si ˆ Scheme (si ˆ alte limbaje). Deoarece parametrii se evalueaz˘ ˆ a ına, ın , ın

2

intea aplic˘rii functiei asupra lor, orice functie va vedea doar valorile parametrilor. a , , Spunem c˘ transferul lor se face prin valoare. a Desi aceast˘ metod˘ are avantajul economisirii spatiului ocupat pe stiv˘ ˆ moa a a ın , , menul apel˘rii unei functii, are si anumite dezavantaje. Cel mai important este a , , faptul c˘ nu putem lucra cu structuri de date infinite, de exemplu, fluxul tuturor a numerelor naturale. Desi are o reprezentare finit˘, aceast˘ structur˘ infinit˘ nu a a a a , poate fi reprezentat˘ astfel. a

Evaluarea lenes˘ ,a
Putem obtine o asemenea reprezentare dac˘ argumentele nu ar fi evaluate la apel a , ci ˆ momentul ˆ care sunt necesare valorile lor. Este metoda de evaluare din ın ın Haskell. Putem avea evaluare lenesa si ˆ Scheme prin urm˘toarele metode: a , ˘ , ın functii cu 0 parametri , promisiuni

Functii cu 0 parametri ,
Deoarece functiile sunt valori ˆ programarea functional˘, le putem folosi oriunde ın a , , este nevoie de un parametru cu evaluare ˆ arziat˘. Tot ce trebuie s˘ facem este ıntˆ a a s˘-l ˆ a ınlocuim printr-o functie cu 0 argumente, la evaluarea c˘reia se va returna a , valoarea argumentului. Obtinem o ˆ ınchidere functional˘ ce ne va da argumentul a , , cerut doar cˆnd avem nevoie de el. a Fie urm˘torul exemplu: a (define sum (lambda (x y) (lambda () (+ x y)))) Se observ˘ c˘ nu se evalueaz˘ suma parametrilor transmisi ci se ˆ a a a ıntoarce o functie , , cu 0 argumente. Pentru a obtine rezultatul, vom evalua functia: , , (sum 1 2) ; va ıntoarce #<procedure>, e functie ^ , ((sum 1 2)) ; se va evalua la 3

3

Promisiuni
Folosirea metodei anterioare presupune definirea de noi functii pentru orice argu, ment a c˘rui evaluare vrem s-o ˆ arziem. Uneori, acest lucru este greu de realizat. a ıntˆ Din fericire, Scheme vine cu un mod propriu de a trata acest aspect: promisiunile. O promisiune este o garantie c˘ se va calcula o valoare dar numai atunci cˆnd a a , ea va fi necesar˘ si se va forta promisiunea. a , , De exemplu, dac˘ avem definitia conventional˘ pentru suma a dou˘ numere: a a a , , (define sum (lambda (x y) (+ x y))) putem obtine o promisiune prin ˆ arzierea evalu˘rii functiei utilizˆnd delay: ıntˆ a a , , (delay (sum 1 2)) Pentru a obtine valoarea promisiunii, vom folosi force: , (force (delay (sum 1 2)))

Fluxuri
Cea mai important˘ utilizare a evalu˘rii lenese o reprezint˘ posibilitatea definirii a a a , de fluxuri. De exemplu, sirul numerelor naturale reprezint˘ un flux. a , Putem reprezenta un flux ca o pereche (reprezentare finit˘!) unde: a primul element reprezint˘ valoarea curent˘ din flux a a al doilea element reprezint˘ o functie generator a , La apelarea functiei generator se va ˆ ıntoarce urm˘toarea pereche din flux. a , Fluxul (1,1,1...) poate fi definit astfel: utilizˆnd functii f˘r˘ argumente a aa , (define ones (lambda () (cons 1 (lambda () (ones))))) (define take (lambda (n stream) (if (= n 0) ’() (cons (car stream) (take (- n 1) ((cdr stream)) )))))

4

Observati faptul c˘ s-au folosit dou˘ rˆnduri de paranteze pe ultima linie a a a , util˘ din take - ((cdr stream)) - pentru a se obtine urm˘toarea pereche a a , prin evaluarea functiei cu 0 parametri. , utilizˆnd promisiuni a (define ones1 (cons 1 (delay ones1))) (define take1 (lambda (n stream) (if (= n 0) ’() (cons (car stream) (take1 (- n 1) (force (cdr stream)) ))))) Codul este ceva mai simplu desi este plin de delay si force , , Vom folosi fluxurile pentru a rezolva probleme complicate prin explorarea spatiului , solutiilor si construirea unui flux de posibile solutii. , , ,

Exercitii ,
1. Definiti numerele naturale reprezentˆnd num˘rul n ca o list˘ cu n elemente a a a , 1 (folositi lista existent˘ ˆ Scheme). Definiti adunarea, sc˘derea, ˆ a ın a ınmultirea , , , si ˆ ımmp˘rtirea cu rezultate numere naturale. a , , 2. Definim o fractie ca fiind o pereche de dou˘ numere naturale. Definiti a , , operatiile pe fractii: adunare, sc˘dere, ˆ a ınmultire si ˆ artire. Numerele na, , , , ımp˘ , turale vor fi reprezentate ca liste. 3. Construiti fluxul numerelor Fibonacci. , 4. Construiti fluxul numerelor prime. , 5. * Implementati operatiile urm˘toare pe un flux generic: a , , take, drop filter map split - primeste un predicat si ˆ a , , , ıntoarce o list˘ si un flux, lista contine , elementele dinaintea primului element ce satisface predicatul, fluxul contine restul elementelor din fluxul initial , , 6. *** Utilizˆnd un flux de numere naturale definiti operatiile pe numere mari: a , , adunare, sc˘dere, ˆ a ınmultire. ,

5

Sign up to vote on this title
UsefulNot useful