Sunteți pe pagina 1din 5

Paradigme de Programare

Laborator 2 - Structuri de date ı̂n Scheme

by Mihai Maruseac

May 20, 2010

Des, i lista este structura de date ı̂ntâlnită ı̂n Scheme, putem defini s, i altele ba-
zându-ne pe anumite extensii s, i funct, ii ale limbajului. Vom vedea ı̂ntr-un laborator
ulterior că vom putea defini inclusiv date infinite dar cu o reprezentare finită.

Select, ii ı̂n liste


Pe lângă funct, iile cunoscute din laboratorul trecut (cdr, car, cons, list, append),
Scheme furnizează un set de definit, ii auxiliare pentru a reduce numărul de paran-
teze dintr-o expresie.
Astfel, vom avea funct, iile c{a,d}+r (de exemplu cadaar) reprezentând scurtă-
turi pentru aplicarea ı̂nlănt, uită a funct, iilor car s, i cdr. Astfel, (cadaar l) se va
reduce la (car (cdr (car (car l)))). Mai pe larg, apelulurile următoare sunt
echivalente (returnând 20).

(cadaar ’(((1 20 3 4) (1 2 3 4)) (((a b c)))))


(car (cdr (car (car ’(((1 20 3 4) (1 2 3 4)) (((a b c))))))))

Trecerea de la un format la altul e simplă: literele interioare din forma conden-


sată (caaar) sugerează ce funct, ie trebuie folosită ı̂n forma extinsă (car sau cdr).
Tipul de date folosit se deduce foarte us, or.
Aceste funct, ii sunt utile când dorim să accesăm un element situat mai ı̂n spatele
listei (cadddr va ı̂ntoarce al 4-lea element) sau dintr-un tip de date mai avansat.
Des, i utile, aceste construct, ii nu sunt infinite. Lungimea maximă a unui s, ir este
de 6 caractere, ceea ce va duce la maxim 4 litere de a s, i d ı̂n nume, deci 4 nivele
de indirectare.
Abstractizare for
Des, i ı̂n Scheme nu există construct, ia for, putem efectua anumite operat, ii pe liste
ce s-ar face ı̂n C cu o asemenea instruct, iune. Pentru aceasta, va trebui să declarăm
faptul că vrem să folosim o extensie a limbajului:

(require srfi/1)

Această declarat, ie poate fi dată oriunde ı̂n fis, ierul sursă cu except, ia spat, iului
ocupat de alte definit, ii s, i ne va permite să folosim următoarele funct, ii:
I funct, ia map ce va realiza transformarea tuturor elementelor dintr-o listă pe
baza unei funct, ii - argument
I funct, ia filter ce va obt, ine o nouă listă din lista dată ca argument pe baza
unui predicat - argument, elementele rămase fiind cele ce respectă predicatul.
I funct, iile take s, i drop ce vor păstra doar o port, iune a listei (fie primele
elemente, fie toate elementele cu except, ia primelor).
I funct, ia fold construies, te o singură valoare pe baza elementelor din listă s, i
a unei funct, ii de combinare, pornind de la un element init, ial. De exemplu,
funct, ia fold din exemplul de mai jos va returna suma elementelor listei - re-
alizată prin combinarea elementelor listei utilizând funct, ia anonimă ce reali-
zează suma a două numere, ı̂ntreaga operat, ie pornind de la valoarea init, ială
0.
Astfel, următoarele exemple vor returna #t.

(equal? ’(3 4 5 6) (map (lambda (x) (+ x 1)) ’(2 3 4 5)))


(equal? ’(3 4 5 6) (filter (lambda (x) (>= x 3)) ’(2 3 4 5 6)))
(equal? ’(3 4 5 6) (take ’(3 4 5 6 7 8 9) 4))
(equal? ’(3 4 5 6) (drop ’(’a ’a ’a ’a 3 4 5 6) 4))
(= 21 (fold (lambda (x y) (+ x y)) 0 ’(1 2 3 4 5 6)))

S-a observat că peste 90% din buclele for sunt folosite pentru a filtra anumite
valori (filter) sau pentru a calcula ceva pe baza acestor valori: o listă cu aceeas, i
structură dar alte elemente (map) sau o altă valoare (fold). Restul cazurilor pot
fi restructurate pentru a se folosi de aceste abstractizări.

Structuri de liste
Utilizând funct, iile anterioare, putem defini aproximativ orice tip de date utilizând
doar liste.
De exemplu, o matrice ar putea fi privită ca o listă de liste. Exemplul următor
realizează suma elementelor unei matrici.

2
(require srfi/1)

(define sum-matrix
(lambda (m) (sum-line (map sum-line m))))

(define sum-line
(lambda (l) (fold (lambda (x y) (+ x y)) 0 l)))

(define matrix
’((1 2 3 4)
(2 3 4 1)
(3 4 1 2)
(4 1 2 3)))

Identic, putem defini un arbore multi-căi prin legături de tip fiu stâng - frate
drept. Astfel, pentru un nod vom ret, ine valoarea lui, primul fiu s, i fratele lui drept.
De exemplu, următoarea listă cu liste imbricate va cont, ine reprezentarea arborelui
următor:

(1 (2 (3 () (4 () (5 () ()))) (6 () ())) ())

Pentru arbore s-au figurat legăturile ı̂ntre frat, i s, i ı̂ntre părint, i s, i fiul stâng.

1
|
2---6
|
3---4---5

Utilizând funct, iile descrise anterior se pot realiza operat, ii pe acest arbore.
De regulă, cel care-s, i defines, te structurile de date este programatorul. De foarte
multe ori, o regândire a problemei poate duce la simplificarea structurii de date.
De exemplu, dacă avem o tablă de s, ah s, i trebuie să punem câte o singură piesă pe
fiecare coloană nu are rost să ret, inem ı̂ntreaga matrice a tablei ca listă de liste.

Tipul pereche cu punct. Operatori inline


Pe lângă liste, Scheme mai are un tip de date numit pereche cu punct. El se
creează oricând se face cons la un tip de date care nu este vid sau produs de un
alt cons.
În prezent, există doar câteva funct, ii ce folosesc acest tip de date.

3
Putem folosi operatorii binari ı̂ntre argumentele lor utilizând o notat, ie cu două
puncte. Expresia (1 . < . 2) (atent, ie la spat, ii!) se va evalua la #t. Des, i dificil
de tastat, această notat, ie poate duce uneori la o lizibilitate mai mare a codului.

Tipuri de date definite ca funct, ii.


Introducere ı̂n Lambda0
Des, i putem reprezenta aproape orice cu liste, din considerente de lizibilitate,
eficient, ă s, i complexitate putem folosi s, i un alt model: vom trata orice tip de
date ca fiind o funct, ie ı̂n formă curry. Urmărit, i exemplul următor ce va demonstra
construct, ia tipurilor booleene:

(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))))

Rulat, i următoarele exemple ı̂n Scheme:

(no true)
(no false)
(no (and false))
(no ((and false) true))
((or ((and false) true)) true)

Aparent, Scheme s, tie să compare două funct, ii (problemă nedecidabilă). Ce se


compară sunt de fapt locat, iile de memorie ı̂n care se află definit, iile S-expresiilor ce
definesc funct, iile.
Urmărind acest exemplu, putem construi orice tip de date plecând de la specifi-
carea constructorilor, operatorilor s, i axiomelor lui. Mai multe detalii ı̂n laboratorul
următor.

4
Exercit, ii
1. Având o listă, accesat, i elementul de pe pozit, ia 8 utilizând cât mai put, ine
paranteze.

2. Definit, i o matrice de 5x5 s, i accesat, i elementul din centrul matricii utilizând


cât mai put, ine paranteze.

3. Determinat, i numărul de inversiuni dintr-o permutare.

4. Calculat, i suma elementelor dintr-un arbore.

5. * Pornind de la următoarea descriere a tipului Pair s, i de la implementarea


valorilor true s, i false implementat, i operatorii fst s, i snd pentru Pair.
(define pair
(lambda (x)
(lambda (y)
(lambda (z) ((z x) y)))))

6. * Găsit, i numerele ı̂ntregi al căror pătrat este de forma 1_2_3_4_5_6_7_8_9_0


unde _ reprezintă orice cifră.

7. *** Realizat, i transpusa unei matrici.

S-ar putea să vă placă și