Sunteți pe pagina 1din 9

17.03.

2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

Paradigme de Programare
laboratoare13:scheme-evaluare

ntrzierea evalurii n Scheme


Responsabil: Alex Popa [mailto:alex.calc2008@gmail.com] Data publicrii: 17.03.2013 Data ultimei modificri: 17.03.2013

Obiective
Scopul acestui laborator nelegerea diverselor forme de evaluare, i stpnirea controlului evalurii n Scheme. Aspectele urmrite sunt: evaluarea aplicativ evaluarea lenesa promisiuni

Evaluare aplicativ vs. evaluare lene


Fie urmatoarea aplicaie, scris n calcul Lambda:
( x . y . ( x+y )12 )

Evident, in urma aplicrii funciei de mai sus, expresia se va evalua la 3 . Ce se ntmpl ns dac parametrii funciei noastre reprezint alte aplicaii de funcii?
( x . y . ( x+y )1( z . ( z+2 )3 ) )

Intuitiv, expresia de mai sus va aduna 1cu 5 , unde 5este rezultatul evalurii expresiei ( z . ( z+2 )3 ) . n cadrul acestui raionament, am presupus c parametrii sunt evaluai naintea aplicrii funciei asupra acestora. Vom vedea, n cele ce urmeaz, c evaluarea se poate realiza i in alt ordine.

Evaluare aplicativ
Evaluarea aplicativa (eager evaluation) este cea n care fiecare expresie este evaluat imediat. n exemplul de mai sus, evaluarea aplicativ va decurge astfel:
( x . y . ( x+y )1( z . ( z+2 )3 ) ) ( x . y . ( x+y )15 ) 6

Observaii: parametrii funciei sunt evaluai naintea aplicrii funciei asupra acestora. Afirmm c transferul parametrilor se face prin valoare . toate limbajele imperative folosesc un astfel de mecanism de evaluare S c h e m efolosete evaluare aplicativa

Evaluare lene
elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare 1/9

17.03.2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

Spre deosebire de evaluarea aplicativ, evaluarea lene va ntarzia evaluarea unei expresii, pn cnd aceasta este folosit efectiv. Exemplu:
( x . y . ( x+y )1( z . ( z+2 )3 ) ) ( 1+( z . ( z+2 )3 ) ) ( 1+5 ) 6

Observatii: aplicatia funciei anonime, de parametru z , este trimis ca parametru, i nu se evalueaz nainte ca acest lucru sa devin necesar. Afirmm c transferul parametrilor se face prin nume . H a s k e l lfoloseste evaluare lene Exist avantaje i dezavantaje ale evalurii lenee . O situaie n care evaluarea lene se poate dovedi util, este urmtoarea: Fie urmtoarea funcie F i x :
F i x= f . ( f( F i xf ) ) F i xprimete ca parametru o

funcie f , care este aplicat asupra parametrului ( F i xf ) . S considerm funcia constant (care

ntoarce mereu valoarea b ):


c t= x . b

S aplicm F i xasupra funciei constante c t , folosind evaluarea aplicativ:


( F i xc t ) ( f . ( f( F i xf ) )c t ) ( c t( F i xc t ) ) ( c t( f . ( f( F i xf ) )c t ) ) ( c t( c t( F i xc t ) ) ) ( c t( c t( f . ( f( F i xf ) )c t ) ) ) ( c t( c t( c t( F i xc t ) ) ) ) . . .

Cum evaluarea este aplicativ, parametrul trimis lui c t , mai precis ( F i xc t ) , va fi evaluat, n mod recursiv, la infinit. Sa ncercm aceeai aplicare, folosind de data aceasta evaluarea lene:
( F i xc t ) ( f . ( f( F i xf ) )c t ) ( c t( F i xc t ) ) ( x . b( F i xc t ) ) b

Observm c evaluarea lene a lui ( F i xc t )se termin, i ntoarce valoarea b . Terminarea este posibil datorit faptului c evaluarea expresiei ( F i xc t ) , trimis ca parametru lui c t , este ntrziat, pn cnd va fi nevoie de ea (n acest caz, niciodat). Construcii precum F i xpot prea ezoterice i nefolositoare. n realitate ns, ele au aplicabilitate. F i xeste un combinator de punct fix (generator de funcii recursive).

Evaluarea n Scheme
Fie urmtorul cod:
( +1( +23 ) )

Codul de mai sus este o rescriere din calcul Lamba in Scheme a exemplului introductiv. Reamintim c evaluarea n Scheme este aplicativ, astfel c, n exemplul de mai sus, etapele parcurse sunt urmtoarele:
elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare 2/9

17.03.2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

( +23 ) : al doilea parametru al funciei + , va produce 5 ( +15 )va produce 6

Cu toate acestea, putem ntrzia evaluarea unei expresii in Scheme, n dou moduri: inchideri nulare (fara parametri): ( l a m b d a( )( ) ) promisiuni: d e l a y /f o r c e

Evaluare lene folosind nchideri


Fie urmatorul exemplu:
( d e f i n es u m ( l a m b d a( xy ) ( l a m b d a( ) ( +xy ) ) ) ) ( s u m12 )

Observai c ( s u m12 )nu evalueaz suma parametriilor, ci ntoarce o funcie . Mai precis, avem de-a face cu o nchidere funcional (functie care i salveaz contextul). Pentru a fora evaluarea este suficient s aplicam rezultatul ntors de ( s u m12 ) asupra a zero parametri, astfel:
( ( s u m12 ) );s ev ae v a l u al a3

Evaluare lene cu promisiuni


Fie definiia convenional a sumei ntre dou numere:
( d e f i n es u m ( l a m b d a( xy ) ( +xy ) ) )

Putem ntrzia evaluarea lui s u m , astfel:


( d e l a y( s u m12 ) );v aa f i s a# < p r o m i s e >

Pentru a scrie o funcie cu evaluare lene, asemntoare celei scrise cu ( l a m b d a( ) ) , putem proceda astfel:
( d e f i n es u m ( l a m b d a( xy ) ( d e l a y( +xy ) ) ) ) ( s u m12 );v aa f i s a# < p r o m i s e >

Pentru a fora evaluarea, putem folosi f o r c e :


( f o r c e( s u m12 ) );v aa f i a3

Fluxuri - aplicaii ale evalurii lenee


Folosind evaluarea lene, putem construi obiecte infinite , sau fluxuri (streams). Exemplu de stream: irul numerelor naturale: ( 0 123n) . Un astfel de obiect poate fi reprezentat ca o pereche , unde: primul element reprezint numarul curent al doilea element reprezinta o funcie fr parametri (generator), care, apelat, va ntoarce urmtoarea pereche din stream (restul fluxului) Exemplu:
elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare 3/9

17.03.2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

;p r i m av a l o a r eaf l u x u l u in u m e r e l o rn a t u r a l e ( 0.g e n e r a t o r _ p e n t r u _ u r m a t o r u l _ n u m a r _ d i n _ f l u x ) . . . ;v a l o a r e akaf l u x u l u in u m e r e l o rn a t u r a l e ( k.g e n e r a t o r _ p e n t r u _ u r m a t o r u l _ n u m a r _ d i n _ f l u x )

irul constant de 1
Implementare folosind nchideri S considerm un alt obiect infinit, i anume irul:
a ( n )=1 ,n > = 0

Primele 5elemente ale acestui ir sunt:


( 11111 )

Sa scriem un generator pentru acest ir:


( d e f i n em a k e _ o n e s ( l a m b d a( ) ( c o n s1( l a m b d a( )( m a k e _ o n e s ) ) ) ) )

Conform explicaiilor anterioare, observm faptul c un element al irului este format dintr-o pereche, unde: primul element reprezint valoarea curent al doilea element reprezint o funcie care genereaz elementul urmtor observai construcia ( l a m b d a( )( m a k e _ o n e s ) ) . Evaluarea lui m a k e _ o n e seste NTRZIAT cu ajutorul unei funcii nulare. Folosind generatorul, s definim irul a ( n ) :
;g e n e r a t o r ( d e f i n em a k e _ o n e s ( l a m b d a( ) ( c o n s1( l a m b d a( )( m a k e _ o n e s ) ) ) ) ) ;s i r u ld en u m e r e1 ( d e f i n eo n e s _ s t r e a m( m a k e _ o n e s ) )

Evaluarea lui m a k e _ o n e sreprezint, in cazul nostru, obiectul infinit, mai precis sirul a ( n ) ; Sa scriem o functie care ntoarce primele nelemente din ir:
;e x t r a g e r e ap r i m e l o rne l e m e n t ed i n i r ( d e f i n et a k e ( l a m b d a( ns t r e a m ) ( i f( =n0 )' ( ) ( c o n s( c a rs t r e a m )( t a k e( -n1 )( ( c d rs t r e a m ) ) ) ) ) ) ) ;t e s t a r e ( t a k e5o n e s _ s t r e a m );v aa f i s a( 11111 )

Observaii: funcia t a k eprimete doi parametri: numrul de elemente de extras din ir irul efectiv, definit ca in exemplul anterior dac neste zero, ntoarcem lista vid (intuitiv, acesta este cazul de baza, deasupra caruia vom construi lista cu cele n elemente)
elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare 4/9

17.03.2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

altfel, construim, recursiv, lista, pornind de la primul element al stream-ului, i apelm recusiv t a k eavand parametrii n 1i restul fluxului: ( c d rs t r e a m ) ; observm c, ntrcut ( c d rs t r e a m )este o functie a crei evaluare este ntrziat, dorim s o evaluam efectiv; prin urmare, in apelul recursiv, se foreaza evaluarea acesteia: ( ( c d rs t r e a m )) Implementare folosind promisiuni S rescriem exemplul anterior folosind d e l a y /f o r c e :
; g e n e r a t o r ( d e f i n em a k e _ o n e s ( l a m b d a( ) ( c o n s1( d e l a y( m a k e _ o n e s ) ) ) ) ) ; s i r u ld ev a l o r i1 ( d e f i n eo n e s _ s t r e a m( m a k e _ o n e s ) ) ; e x t r a g e r e ap r i m e l o rne l e m e n t ed i ns i r ( d e f i n et a k e ( l a m b d a( ns t r e a m ) ( i f( z e r o ?n )' ( ) ( c o n s( c a rs t r e a m )( t a k e( -n1 )( f o r c e( c d rs t r e a m ) ) ) ) ) ) ) ;t e s t a r e ( t a k e4o n e s _ s t r e a m ) ;v aa f i s a( 11111 )

Observatii: funciile ( l a m b d a( )( e x p r ) )au fost nlocuite cu ( d e l a ye x p r ) 1 ) apelurile care forau evaluarea, de tip , au fost inlocuite cu ( f o r c ee v a l _ e x p r )

irul numerelor naturale


Fie urmtorul cod, care implementeaz irul numerelor naturale:
;e l e m e n td en o u t a t e ,p r e z e n t au n e if u n c t i is u c c e s o r ( d e f i n es u c c ( l a m b d a( n ) ( +n1 ) ) ) ;g e n e r a t o rp e n t r un u m e r en a t u r a l e ( d e f i n em a k e _ n a t u r a l s ( l a m b d a( k ) ( c o n sk( l a m b d a( )( m a k e _ n a t u r a l s( s u c ck ) ) ) ) ) ) ;f l u x u ln u m e r e l o rn a t u r a l e ( d e f i n en a t u r a l s _ s t r e a m( m a k e _ n a t u r a l s0 ) ) ;t e s t a r e ( t a k e4n a t u r a l s _ s t r e a m );v aa f i s a( 0123 )

Observaii: spre deosebire de abordarea anterioar, aici am definit o funcie s u c c , care, pentru un element noarecare, calculeaz succesorul acestuia. (Puteam introduce i n exemplul anterior funcia s u c c ; ea ar fi fost reprezentata de functia constanta 1, ntruct succesorul oricrui element din irul de 1, este mereu 1) generatorul din acest exemplu are, de data aceasta, un parametru, mai precis valoarea pentru care se construieste elementul din flux; din nou, un element din flux este format din perechea (valoare, funcie de generare a elementului urmator din flux ).

elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare

5/9

17.03.2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

irul lui Fibonacci


Sirul lui Fibonacci este:
F i b o=t 0t 1t 2t 3. . .t n. . . u n d e : t 0=0 t 1=1 t k=t ( k 2 )+t ( k 1 )p e n t r uk> =2

Exista o diferen esenial ntre acest ir, i irurile definite anterior, si anume faptul ca succesorul nu mai este calculat pe baza unei expresii care depinde de rangul su in sir (ex: n + 1la numere naturale), ci pe baza unor valori calculate anterior. S exploatm aceast diferen, facnd urmatoarea observaie:
F i b o =t 0t 1t 2t 3. . .t ( k 2 ). . .+ ( t a i lF i b o )=t 1t 2t 3t 4. . .t ( k 1 ). . . _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ F i b o =t 0t 1t 2t 3t 4t 5. . .t k. . .

Observam ca, adunand elemente din sirurile (fluxurile) F i b oi ( t a i lF i b o ) , obinem irul t 2t 3t k . Daca adaugam primele doua elemente, t 0si t 1la inceput, obtinem exact F i b o . Pentru a implementa expresia de mai sus, avem un singur obstacol de depasit, si anume trebuie s scriem o funcie care adun dou fluxuri. O implementare posibil este:
( d e f i n ea d d ( l a m b d a( s 1s 2 ) ( c o n s( +( c a rs 1 )( c a rs 2 ) ) ( d e l a y( a d d( f o r c e( c d rs 1 ) )( f o r c e( c d rs 2 ) ) ) ) ) ) )

Observatii:
a d dprimete doua fluxuri,

i ntoarce fluxul rezultat prin adunare: fluxul-adunare este o pereche (valoare, funcie de generare a elementului urmator); primul element al perechii este valoarea efectiva: ( +( c a rs 1 )( c a rs 2 ) ) al doilea element al perechii este o funcie care va genera urmtorul element din flux evaluarea recursiva a lui a d deste intrziat; n momentul cnd apelul recursiv a d dse va evalua, acesta foreaz evaluarea ( c d rs 1 )si ( c d rs 2 ) . S definim fluxul F i b ope baza adunrii de mai sus:
( d e f i n ef i b o _ s t r e a m ( c o n s0 ( d e l a y( c o n s1 ( d e l a y( a d df i b o _ s t r e a m( f o r c e( c d rf i b o _ s t r e a m ) ) ) ) ) ) ) )

Observatii: adaugm manual primele doua elemente din flux, i ntrziem evaluarea celui de-al doilea element al perechii folosim adunarea fluxurilor pentru definirea celorlalte elemente Codul final:
;f u n c t i aa d dp r i m e s t ed o u as i r u r i / f l u x u r i :s 1 ,s 2 ,s ii n t o a r c ef l u x u lr e z u l t a td i na d u n a r e as 1+s 2 ( d e f i n ea d d ( l a m b d a( s 1s 2 ) ( c o n s( +( c a rs 1 )( c a rs 2 ) ) ( d e l a y( a d d( f o r c e( c d rs 1 ) )( f o r c e( c d rs 2 ) ) ) ) ) ) ) ;g e n e r a t o r u lp e n t r ue l e m e n t ed i ns i r
elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare 6/9

17.03.2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

( ( d e f i n ef i b o _ s t r e a m ( c o n s0 ( d e l a y( c o n s1 ( d e l a y( a d df i b o _ s t r e a m( f o r c e( c d rf i b o _ s t r e a m ) ) ) ) ) ) ) ) ;t e s t a r e ( t a k e1 0f i b o _ s t r e a m );v ai n t o a r c e( 01123581 32 13 4 )

Fluxul numerelor prime


Eratostene a conceput un algoritm pentru determinarea unui ir de numere prime, care funcioneaz astfel: fie irul numerelor naturale, ncepand cu 2:
234567891 01 11 21 31 41 51 61 71 81 92 02 1. . . _

Parcurgem acest ir, i eliminm elementele care se divid cu 2:


23 _ 5 7 9 1 1 1 3 1 5 1 7 1 9 2 1. . .

Alegem urmatorul element din irul rmas, i eliminm toate elementele care se divid cu el:
23 _ 5 7 1 1 1 3 1 7 1 9 . . .

Pentru iruri finite, ne oprim cnd ptratul elementului curent depete numrul de elemente din ir.

Funcii auxiliare
;v e r i f i c a md a c axs ed i v i d ec uy ( d e f i n ed i v i d e s ? ( l a m b d a( xy ) ( z e r o ?( r e m a i n d e rxy ) ) ) ) ;d e f i n i t i i l ep e n t r uf l u x u ln u m e r e l o rn a t u r a l e ( d e f i n es u c c ( l a m b d a( n ) ( +n1 ) ) ) ( d e f i n em a k e _ n a t u r a l s ( l a m b d a( k ) ( c o n sk( d e l a y( m a k e _ n a t u r a l s( s u c ck ) ) ) ) ) ) ;d e f i n i mf l u x u ln u m e r e l o rn a t u r a l e ,i n c e p a n dd el a2 ( d e f i n en a t u r a l s _ f r o m _ 2( m a k e _ n a t u r a l s2 ) ) ;f u n c t i at a k e ( d e f i n et a k e ( l a m b d a( ns t r e a m ) ( i f( z e r o ?n )' ( ) ( c o n s( c a rs t r e a m )( t a k e( -n1 )( f o r c e( c d rs t r e a m ) ) ) ) ) ) )

Observaii: am preluat din exemplele anterioare definitia fluxului numerelor naturale, i l-am adaptat astfel inct s nceapa de la 2 am creat o funcie, d i v i d e s ? , care verific dac un numar se divide cu cellalt

Filtrarea elementelor
S scriem o funcie care filtreaz elementele unui flux:
elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare 7/9

17.03.2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

( d e f i n ef i l t e r ( l a m b d a( fs );p a r a m e t r i is u n tf u n c t i ad ef i l t r a r e ,s if l u x u l ( i f( f( c a rs ) ) ( c o n s( c a rs )( d e l a y( f i l t e rf( f o r c e( c d rs ) ) ) ) ) ( f i l t e rf( f o r c e( c d rs ) ) ) ) ) )

Observaii: funcia f i l t e rprimete urmtorii parametri: o funcie de testare, f : aceasta primeste ca parametru o valoare din flux (sir), i verifica dac aceasta satisface o proprietare oarecare (fva intoarce # tsau # f ) un flux oarecare f i l t e rintoarce un nou flux, care conine doar elementele din scare satisfac proprietatea testat de f Analizai modul de constructie a fluxului ntors: ca i n exemplele anterioare, se construiete o pereche (valoare, funcie de generare) de cte ori folosim restul fluxului, ( c d rs ) , form evaluarea.

Ciurul lui Eratostene


Fie urmatoarea functie, care construiete un flux, trecnd fiecare element din fluxul numerelor naturale (incepand cu 2):
( d e f i n es i e v e ( l a m b d a( s ) ( c o n s( c a rs ) ( d e l a y( s i e v e( f i l t e r( l a m b d a( x )( n o t( d i v i d e s ?x( c a rs ) ) ) ) ( f o r c e( c d rs ) ) ) ) ) ) ) )

Observaii: primul element al fluxului rezultat din cernere , este chiar primul element din fluxul trimis ca parametru (valoarea 2) restul fluxului ( c d rs )este filtrat recursiv de functia s i e v e f i l t e rprimeste ca parametru o functie anonima, care testeaza daca parametrul sau se divide cu primul element al fluxului observati si aici modul de constructie a rezultatului: pereche (valoare, functie de generare) observati, de asemenea, ( f o r c e( c d rs ) ) , care forteaza evaluarea lui ( c d rs )

Codul complet
primes.scm
;v e r i f i c a md a c axs ed i v i d ec uy ( d e f i n ed i v i d e s ? ( l a m b d a( xy ) ( z e r o ?( r e m a i n d e rxy ) ) ) ) ;d e f i n i t i i l ep e n t r uf l u x u ln u m e r e l o rn a t u r a l e ( d e f i n es u c c ( l a m b d a( n ) ( +n1 ) ) ) ( d e f i n em a k e _ n a t u r a l s ( l a m b d a( k ) ( c o n sk( d e l a y( m a k e _ n a t u r a l s( s u c ck ) ) ) ) ) ) ;d e f i n i mf l u x u ln u m e r e l o rn a t u r a l ei n c e p a n dd el a2 ( d e f i n en a t u r a l s _ f r o m _ 2( m a k e _ n a t u r a l s2 ) ) ;f u n c t i at a k e ( d e f i n et a k e ( l a m b d a( ns t r e a m )
elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare 8/9

17.03.2013

ntrzierea evalurii n Scheme [Paradigme de Programare]

( i f( z e r o ?n )' ( ) ( c o n s( c a rs t r e a m )( t a k e( -n1 )( f o r c e( c d rs t r e a m ) ) ) ) ) ) ) ;f u n c t i ec a r ep r i m e s t eu nf l u x ,s ii n t o a r c eu nf l u xf i l t r a t ,d u p af u n c t i af ( d e f i n ef i l t e r ( l a m b d a( fs );p a r a m e t r i is u n tf u n c t i ad ef i l t r a r e ,s if l u x u l ( i f( f( c a rs ) ) ( c o n s( c a rs )( d e l a y( f i l t e rf( f o r c e( c d rs ) ) ) ) ) ( f i l t e rf( f o r c e( c d rs ) ) ) ) ) ) ;f u n c t i ad ec e r n e r e( s i t a ) ( d e f i n es i e v e ( l a m b d a( s ) ( c o n s( c a rs ) ( d e l a y( s i e v e( f i l t e r ( l a m b d a( x )( n o t( d i v i d e s ?x( c a rs ) ) ) ) ( f o r c e( c d rs ) ) ) ) ) ) ) ) ;d e f i n i t i af l u x u l u i ( d e f i n ep r i m e s _ s t r e a m( s i e v en a t u r a l s _ f r o m _ 2 ) ) ;t e s t a r e ( t a k e1 0p r i m e s _ s t r e a m );v ai n t o a r c e( 23571 11 31 71 92 32 9 )

Resurse
Exerciii propuse

Referine
Wikipedia: Evaluation strategy [http://en.wikipedia.org/wiki/Evaluation_strategy]
1) eval_expr

laboratoare13/scheme-evaluare.txt Ultima modificare: 2013/03/17 18:32 de ctre Andru Gheorghiu

elf.cs.pub.ro/pp/laboratoare13/scheme-evaluare

9/9

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