You are on page 1of 57

1.

Funkcionalno programiranje
1.1. Uvodni elementi o jezicima
Programski jezik :
- nain komunikacije ovek-raunar
- brojne podele po razliitim kriterijumima
- podela po stepenu razumljivosti za oveka
- jezici niskog nivoa
- jezici visokog nivoa
Jezici visokog nivoa : - iroko rasprostranjene kategorije
- proceduralni (kako se problem reava, najee korieni) Pascal,Modula,Fortran,...
- deklarativni ( opis ta se reava )
- logiki - Prolog,KLO,Mandola
- funkcionalni - LISP,Scheme,Iswim,Miranda,Haskell

1.2. Funkcionalni stil programiranja


- izraunavanje, tj. izvravanje programa je zasnovano na pojmu funkcije
( kod logikog stila programiranja zasnovano je na pojmu relacije)
- proces programiranja obuhvata dve aktivnosti:
1. definisanje funkcije - pridruivanje imenu funkcije izraza kojim se izraunava vrednost
2. poziv funkcije - primena funkcije na argumente
- izvravanje programa - izraunavanje vrednosti funkcije inicirano primenom jedne funkcije
na njene stvarne argumente
Primer: Program funkcionalnog stila
f(x)=x+1

g(x,y)=f(x)+2y
definicije funkcija
z(x)=g(x,2)-1

Za izvo|enje i aktiviranje programa treba pozvati funkciju (najoptiju) sa stvarnim argumentima


:

z(5)=g(5,2)-1=f(5)+2*2-1=5+1+2*2-1=9
Programi su :
- koncizni i jasni
- najee krai od proceduralnih ekvivalenata
- tee je napraviti greke - ako postoje lake ih je otkriti
- mogu se lako realizovati na paralelnim raunarima
- mogu je formalni dokaz korektnosti

1.2.1. Glavne karakteristike funkcionalnog stila programiranja


1. Nepostojanje eksplicitnog zadavanja redosleda izvravanja
- u proceduralnom stilu - program je spisak naredbi koje treba da se izvre u odre|enom
redosledu
- u funkcionalnom stilu - program definie izraz koji je reenje problema
Primer: n!
proceduralno
funkcionalno
rez := 1;
fakt(n)=if n=0 then 1
FOR i:=2 TO n DO
else n*fakt(n-1)
rez:=rez*i
1

END;
( strogo zadat redosled izraunavanja i izvravanja naredbi )

( matematika definicija)

2. Nepostojanje naredbi
-proceduralni stil je zasnovan na postojanju stanja programa na koje se u toku izvravanja
programa utie. Stanje je sadrano u tano odre|enim memorijskim lokacijama i na njega se utie
konstrukcijama programskog jezika, tj. naredbama dodeljivanja koje se izvravaju u tano odre|enom
redosledu.Nakon niza naredbi rezultat je u memorijskim lokacijama odakle se preuzima.
- funkcionalni stil - ne poznaje naredbe ve izraze. Izrazi su zapisi vrednosti tj. predstavljaju
vrednosti.
proceduralno
naredbe
uslovna naredba - odre|uje redosled
izvravanja
petlje
rezultat u memorijske lokacije

funkcionalno
izrazi
uslovni izraz - predstavlja vrednost
rekurzija
rezultat - vrednost nekog izraza

- ako je u programu potrebno definisati neko stanje i onda ga menjati u funkcionalnom stilu se
to postie prenoenjem stanja u sve izraze koji zavise od tog stanja (umesto da je stanje fiksirano na
odre|enim lokacijama).
Primer:
fakt(n) = f(n,1)
f(n,rez) = if n>0 then f(n-1,rez*n) else rez.
( eksplicitan prenos rezultata u naredni poziv funkcije )
3. Nepostojanje sporednih efekata
-isti izraz u istoj okolini uvek ima istu vrednost, tj. funkcija pozvana sa istim argumentima
uvek daje istu vrednost.
- osnovna osobina matematikog aspekta funkcije
- u programu se zbog sporednih efekata moe desiti da dva poziva iste funkcije daju razliit
rezultat f(x)f(x); najee zbog izmene vrednosti globalnih objekata programa ; uitavanja
vrednosti.
--VAR
a,x : INTEGER;
--PROCEDURE Isti(i:INTEGER):BOOLEAN;
BEGIN
a:=a+1;
RETURN i=a
END Isti;
--a:=0;x:=1;
IF Isti(x)=Isti(x) THEN
( nee biti jednako )
WriteString(jednako)
ELSE
WriteString(nije jednako )
END
--- ekvivalentnost spominjanja (referential transparency) - svi izrazi koji oznaavaju istu
vrednost se mogu zamenjivati jedni drugima.
2

Primer:
y=x^2+1 tada y+y <=> x^2+1+y <=> y+x^2+1 <=> x^2+1+x^2+1
Primer:
PROCEDURE Jedan(VAR x,y,z : INTEGER);
VAR
t: INTEGER;
BEGIN
t:=x; x:=y; y:=z; z:=t
END Jedan;
PROCEDURE Dva(VAR x,y,z : INTEGER);
VAR
t: INTEGER;
BEGIN
t:=y; y:=z; z:=x; x:=t
END Dva;
Moe se uiniti da ove procedure imaju isti efekat (pa da se mogu pozivati jedna umesto druge).
1) x=1, y=2, z=3
Jedan t=x=1
z=t=1
x=y=2
y=z=3
a

Dva

t=y=2
y=z=3
z=x=1
x=t=2

2) x=1, y=2, z=1


Jedan(a,b,a)

Dva(a,b,a)
x

t=x=1
x=y=2
y=z=1
z=t=1

t=y=2
y=z=1
z=x=1
x=t=2

( ovo z utie na vrednost x


jer su to iste veliine)
( kako su z i x iste promenjive to je pri
izlasku x=z=1 , y=2 , tj. a i b imaju
nepromenjene vrednosti )

( x i z e imati istu vrednost 2, a y=1, tj. a i b


su zamenili vrednosti )

4. Funkcije kao ravnopravni objekti


- fleksibilnost u rukovanju funkcijama
- ravnopravne sa svim drugim tipovima podataka
- funkcije kao argumenti
- funkcije kao deo strukture podataka
- funkcije kao vrednost drugih funkcija
- osobina uporediva sa funkcijama u matematici

f ( x) =

x3
x =
+ c = g( x)
3
2

i argument i rezultat funkcije

je

funkcija.
5. Nesteriktna semantika
- semantika jezika je striktna, ako je svaki izraz tog jezika striktan.
- izraz je striktan ako nema vrednost kad bar jedan od njegovih operanada nema vrednost.
3

- izraz je nestriktan kad ima vrednost ak i ako neki od njegovih operanada nema vrednost.
Ovo vai samo u principu , a od konkretnog izraza zavisi dali e i na osnovu koliko poznatih
argumenata biti izraunata njegova vrednost.
Posmatrajmo funkciju oblika :
map_f S = < fS1,fS2,...,fSn >
tj.

map_f S =

NIL , null S

f(car S):map_f (cdr S),

inae

Primer:
map_length<S1...Sn>=<lengthS1...lengthSn>
tj.
NIL , nullS
map_length S=
length(car S): map_length(cdr S) , inae
Da se svaki put ne bi ponavljala ista forma programa, moe se uvesti opti oblik koji bi mogao da
kreira sve sline funkcije.
Neka je opti oblik map funkcija koja za argumente ima eljenu funkciju koja se primenjuje na sve
argumente liste.
Da bi se realizovala funkcija length to se radi na sledei nain:
map(length) se primenjuje na S
(map(length))S

<=>

a po konvenciji o redosledu izvravanja funkcija

(map length)S
<=>

map length S .

Posmatrajmo ta je rezultat funkcije map:


Uzmimo map sin
Poto
sin: R-->R
map sin: R* -->R* ,

rezultat map sin je funkcija koja listu realnih vrednosti


preslikava u listu realnih vrednosti.
Stoga, poto map sin kao argument ima funkciju koja R-->R, a vraa funkciju koja preslikava
R* -->R* ona se zapisuje :
map (RR) R*R* .
T* =T0 U T1 U T 2U ... U Tn
Posmatrajmo sada map length :
length : T* N
map length : (T*)* N*
map : (T* N) (T*)* N*

, iz ovoga se zakljuuje da je tip map-a :

U optem sluaju oko f: D R map f vraa funkciju tipa


tj. map: (D R) D* R* D,R tip.
Semantika map-a
4

D* R* ,

map f S=<fS1 fS2 ... fSn>

tj.

map f nil = nil


map f ( x:S)= fx: map f S
Primer:
Neka je M matrica.
map( map square)<<m11...m1n > ... <m m1 ... m mn >> =
= <map square <m11...m1n > ... map square< square m m1 ... m mn >> =
= << square m11 ... square m1n> ... < square m m1 ... square m mn>>
Primetimo map_f je ime funkcije , map f je primena funkcije map na funkciju f.
map sin = map_sin
map length = map_length
...
Funkcije koje operiu sa funkcijama su funkcije vieg reda. Ovakve funkcije utiu na skraenje
procesa programiranja.
Moda je prirodniji zapis map funkcije na sledei nain:
nil , null S
map f=S
f( car S ): map f( cdr S )
u znaenju : map uzima S i preslikava ga u nil ako je S prazna lista , a inae primenjuje f na prvi
element liste i konstruie ga sa map primenom f na ostatak liste.
Primer:
U Scheme jeziku bi map funkcija bila definisana na sledei nain:
( define ( map f)
(lambda ( S )
( if ( null S) nil
( cons ( f (car S )) (( map f ) ( cdr S )))
)
)
)
poziv bi bio
(( map sin ) (interval 0 90 ))
------------------------------------------------------------------------------------------------------------------------Uopte za funkciju f definisanu nad D1 x D 2 , tj.
f : (D1 x D 2 )--> R
postoji ekvivalentna funkcija F definisana na prvom domenu, koja vraa funkciju definisanu nad
drugim domenom.
F : D1 --> ( D 2 -->R )
( carried verzija funkcije f ( unarna ) )
Neki funkcionalni jezici imaju samo unarne funkcije.
Postoje dva naina da se postigne efekat vie od jednog argumenta:
1) jedini argument je torka koja doputa kombinovanje nekoliko vrednosti u jednu
5

2) moe se koristiti Karijeva funkcija koja uzima prvi argument i vraa funkciju koja uzima
drugi argument itd.
Prvi nain nije dobar kad se programiraju funkcije prvog reda.
Ne Karijeva verzija map funkcije
map : (( D R ) x D* ) R*
funkcija

lista

rezultujua lista

ali , neto spreava da koristimo mapf kao funkciju.


fold

(A B B) (B (A* B ))
(A B B) B A* B

1) fold ( f,b,l ) = fold ( f,b,[l1 ... ln]) = f (l1, f(l2 , ... f(ln , b) ... )
2) fold ( f,b,nil) = b
fold (f,b,x:l ) = f(x,fold (f,b,l))
Primer:
fold ( +,0,[1,3,5] ) = fold ( +,0,1:(3:(5: nil )))
+ ( 1, fold(+, 0 , 3 :(5: nil))) +(1,+(3,fold(+,0,5: nil)))
+ (1,+(3,+(5,fold(+,0, nil))))
+ (1,+(3,+(5,0))) 9
--------------------------------------------------------------------------------------------------------------------------Striktna semantika
-prvo se izraunaju vrednosti svih operanada , pa se onda izraunava vrednost izraza.Tehnika prenosa
parametara koja podrava ovu semantiku je poziv po vrednosti (call by value).
Nestriktna semantika
-izraunavanje operanada , tj. argumenata , se odlae sve dok te vrednosti ne budu potrebne. Ta
strategija je poznata kao zadrano izraunavanje (lazy evoluation ),a prenos parametara je po potrebi (
call by need).
Znaaj nestriktne semantike
1) Osloba|anje brige o redosledu izraunavanja
x=0 v 1/x=10
U nestriktnoj semantici za x=0 izraz=T .
f a x where a=ged(b,c)
-programer ne mora da vodi rauna da li je a komplikovano za raunanje
i da li treba uvek da se rauna (vredno raunanje) , ve e se a raunati ako treba.
U striktnoj semantici bi se izraunavao i izraz 1/x to bi dovelo do greke.
primer:
f(x,y,z)= if x then y else z
2) Omoguava kreiranje beskonanih struktura (konceptualno)
a=(1.a) -beskonana lista
car(a) - u nestriktnoj semantici daje prvi element 1
- u striktnoj semantici pokuava prvo da formira beskonanu listu to je nemogue
3) Potencijalno efikasnije ( raunanje po potrebi )
primer: Iranska bajka
6

6) Statiko vezivanje
Funkcionalni programi su statiki ; vrednosti se veliinama vezuju u trenutku njihovog definisanja (tj.
statiki), a ne u toku izvravanja programa ( tj. dinamiki ) kao u proceduralnim jezicima. Nekada se u
funkcionalnom programu neki izrazi zamenjuju imenima zbog vee preglednosti.
Primer:
neka_je n=1 i
neka_je f(z)=z+n i
neka je n=2 u_izrazu f(3)
f(3) ?

-u statikom vezivanju f(z)=z+1 i naknadno n=2 , nema uticaja tj. f(3)=4


-u dinamikom vezivanju vrednosti se uzimaju u trenutku izraunavanja i poto je u tom
momentu n=2 to je f(z)=f(3)=z+2=3+2=5
Moe se desiti da za isti poziv funkcija vraa razliitu vrednost , to naruava princip ekvivalentnosti
pominjanja.
Rekurzivna definicija strukture podataka i redosled izraunavanja
Mac Lennan str. 316-323
Beskonane strukture-optost - jednom se definiu konceptualno , a kako e se koristiti zavisi od
konkretne primene.
Pogledajmo listu prirodnih brojeva :
Prir = < 0 1 2 3 ... >
Ako na nju primenimo funkciju naredni dobijamo
map[1+] Prir -<1 2 3 4 ... > - prirodni brojevi bez prvog elementa
cdr Prir = map [1+] Prir
Prirodni brojevi zadovoljavaju vezu
Prir = 0 : map [1+] Prir
(1*) -rekurzivna definicija strukture podataka
Da li je to mogue i kako?
Ako su dozvoljene definicije rekurzivnih struktura podataka, mnoge stvari postaju pogodnije.Onda se
mogu definisati beskonane liste rekurzivno.
Primer:
1) svi k =k: svi k
2) beskonana lista fibonaijevih brojeva F = 1:1 : map[+][ par ( F, cdr F )]
par(S,T)==<(S 1T 1)(S 2T 2) ... >
slino je i map definisan :

map F(x:S)=Fx:mapFS

( 2*)

Ovo nam pokazuje koliko su ovakve rekurzivne definicije mono oru|e u prog. jeziku. Me|utim, kako
vriti izraunavanja izraza u kojima figuriu ovakve strukture.
Pogledajmo jedan primer:
Dva naina izraunavanja jednog izraza koji sadri Prir.
1) Lenjo
car(cdr Prir)
tj. car(cdr (0: map [1+] Prir )) => car(map [1+] Prir )
( rauna car od izraza , taj izraz
rauna dok ne moe da uzme prvi i ostalo
zadrzava)
razvijajui to po (1*) i koristei (2*) =>
=> car( 1: map [1+] Prir)
7

ovo se zadrava

Primenjujui car dobijamo rezultat 1 . (To je lenjo izraunavanje, jer se izraz izraunava kada nema
drugog naina da se dobije njegova vrednost.)
2) Vredno
-zamenjujui Prir njihovom definicijom kad god je mogue, izraz e biti beskonaan.
car ( cdr Prir) = car ( cdr ( 0: map [1+] Prir))
= car ( cdr (0:1: map [1+] Prir))
-piemo ,
a stvarno se deava:
car ( cdr Prir) = cadr (0: map [1+] Prir)
Prir=0:map [1+] Prir
primeni se 1+ na prvi i na ostatak

= cadr (0:1: map [1+] ( cdr Prir))

po smislu map-a

= cadr (0:1:2: map[1+] ( cdr Prir))

Prir za sledei korak

.
.
.
--------------------------------------------------------------------------------------------------------------------------Lenjo izraunavanje izbegava beskonana izraunavanja.
Posmatrajmo drugi primer:
Po definiciji fac
if n=1 then 1 else n*fac (n-1)
fac (-1) -dovodi do beskonane petlje
Posmatrajmo:
cdr ( prefiks ( fac (-1), nil ))=
vredno: ako ponemo izraunavanje svih izraza , fac(-1) e otii u beskonanu petlju
lenjo: prefiksi cdr e se izraunavati pre fac , koji nije ni potreban
tj.
cdr( prefiks (fac(-1) , nil))=cdr < fac(-1) >=<>
Posmatrajmo trei primer:
(if y=0 ,1, x/y )
-moe se rei da se prvi argument rauna vredno , a druga dva argumenta lenjo
tj. raunaju se samo ako trebaju.
U ovom sluaju ako bi se sva 3 argumenta raunala vredno javilo bi se nemogue izraunavanje x/0.
Podela FP jezika sa stanovita lenjog izraunavanja

svi izrazi u jeziku se izraunavaju lenjo (implicitno)


samo parametri koji se prosle|uju funkciji se raunaju lenjo
eksplicitno se zadrava (delay) i forsira izraunavanje zadranog
izraza (force)
Primer: u LKL eksplicitno zadravanje i forsiranje
el. beskonane liste)
(letrec nthFirst
(nthFirst lambda(k,n)
(toke k(fr(quote 1)))
)
(toke lambda(k,x)
(if (eq k(0))
(nil)

(daje prvih n

nthFirst(k,n)=toke(k,fr(1))
where
toke(k,x)=if k=0 then nil
else
car(x):toke(k1,force(cdr(x)))
end
8

(cons (car x)(toke (sub k(1))(force(cdr x))))


/* je bio zadran,pa ga forsiraj

*/
)
(fr lambda(n)
(cons n(delay(fr(add n(1))))) /* zadran rep */
)
)
fr(n)=n:delay(fr(n+1))
Izraunavanja sa nepoznatim (primer lenjog izraunavanja):
- rezultat funkcije zavisi od vrednosti koje nisu poznate sve dok se
izracunavanje ne
kompletira
ReplByMax zamenjuje sve el. liste pozitivnih brojeva
maksimalnim brojem
1) dva puta prolazei kroz listu (vredno izraunavanje)
- na|e max
- zameni svaki el. sa max
ReplByMax(L)=map(f,L)

,gde je f(x)=fold(max,0,L)

2) jednim prolaskom kroz listu (lenjo izraunavanje)


ReplByMax : N* N*
ReplByMax(L)=Result
where (Result,max) = fold(f,(nil,0),L)
where f (x,(r,m)) = (max:r,if y>m then x else m);
car(ReplByMax([5,1,4])
(* moramo inicirati
izraunavanje jer je lenjo *)
= Result where (Result,max)=f(5,f(1,f(4,(nil,0))))
Result where (Result,max)=f(5,f(1,(max:nil,4)))
Result where (Result,max)=f(5,(max:(max:nil),4))
Result where (Result,max)=(max:(max:(max:nil)),5)
(* max je na kraju izraunavanja poznato a samim tim i
svaki el. liste je max tj. 5 *)

1.2.2. Podela jezika funkcionalnog stila


-

^FPJ - imaju osobine: - nepostojanje naredbi


- nepostojanje zadavanja redosleda
izvravanja
- nepostojanje sporednih efekata
- funkcije kao ravnopravni objekti
- statiko vezivanje
- FPJ - podravaju funkcionalni stil,ali ekvivalentnost spominjanja
ne vai za svaki mogui izraz.Za te FJ se esto kae da sadre
elemente imperativnog (proceduralnog) programiranja.
Podela ^FPJ u odnosu na neke bitne osobine funkcionalnog stila:
1) po striktnosti

F+s

- striktni ^FPJ

F+s F-s=
- nestriktni ^FPJ
9

F-s

2) lenjo izraunavanje - vrednost argumenta u pozivu funkcije se


izraunava najvie jedanput
potpuno lenjo izraunavanje - vrednost svakog argumenta
proizvoljnog izraza se rauna najvie jednom
Lenjo izraunavanje je est nain realizacije nestriktne
semantike.
- lenji ^FPJ (lazy)
- vredni ^FPJ (eager)
3) po tipiziranosti
- izraz je tipiziran (typed) ako je svakom identifikatoru koji
njemu uestvuje pridruen tip
- izraz je netipiziran (untyped) ako nije tipiziran
Netipizirani ^FPJ (F-T) su oni ^FPJ iji je bar jedan izraz
netipiziran.Tip podataka je pridruen vrednostima a uskla|enost
tipova se kontrolie dinamiki u toku izvravanja programa.
Tipizirani ^FPJ (F+T )su oni ^FPJ iji je svaki izraz
tipiziran.Tip podataka je pridruen identifikatorima a uskla|enost
tipova se kontrolie statiki u toku prevo|enja programa.
F+ T F-T=
4) Curry-jeve funkcije - nain definisanja funkcije ija je vrednost
funkcija
Funkcija f od n argumenata je definisana kao Curryjeva(curried) ako je rezultat njene primene na k<n argumenata
x1,...,xk nova funkcija f od n-k argumenata za koju vai
f xk+1...xn = f x1...xn
- ^FPJ bez Curry-jevih funkcija (F-c) - bar jedna korisnika
funkcija nije definisana kao Curry-jeva
- ^FPJ sa Curry-jevim funkcijama (F+c) - sve korisnike funkcije
su definisane kao Curry-jeve
F-c F+c =

2. Osnovni elementi -rauna u funkcionalnim


jezicima
Osnovni rad na -raunu uradio je Church 1932-33,1941. -raun
se treira kao prvi funkcionalni (ali ne i programski) jezik. Uticaj
-rauna na razvoj ranog LISP-a je minimalan,ali kasnije se sve vie
u njega ukljuuju i razra|uju ideje -rauna. -raun je sintaksa za
zapis termova i skup pravila za njihovu transformaciju. Pored niza
nedostataka (da bude opta matem. teorija) ostao je dobar model za
funkcije i izraunljivost.

2.1. ^isti netipizirani -raun


-izrazi:
xn.e

x - identifikator
x.e - apstrakcija
x1x2...xn.e
e1 e2 - aplikacija
(e)

10

x1.x2. ...

- po dogovoru aplikacija je levo asocijativna


e2) e3)
- slobodne promenljive u -izrazima (fV)
fV(x)={x}
fV(e1 e2)=fV(e1) fV(e2)
fV(x.e)=fV(e) {x}
- zamena izrazom
- zamena [e1/x]e2
identifikatora x u izrazu e2
1) [e/xi]xj = a) xj
b) e
2) [e1/x] (e2

e3)

e1

, i<>j
, i=j

(e1

e2 e3

) ((e1

svih slobodnih pojava

npr.

npr.
[y/x]x y
[y/x]z z

= ([e1/x]e2)([e1/x]e3)

,i=j
3) [e1/xi](xj.e2) = a) xj.e2
(xi nije slobodno)
,i<>j ,
b) xj.[e1/xi]e2
xjfV(e1)
,inae
c) xk.[e1/xi]([xk/xj]e2)
ki,kj,xkfV(e2) fv(e1)
(* mogui konflikt imena je izbegnut zamenom imena *)
Primer:
[y/x]((y.x)(x.x)x)
([y/x]x) (z.y)(x.x)y

e1
3a)

2
([y/x](y.x)) ([y/x](x.x))

e2

e3

3c)

1b)

z.[y/x]([z/y]x)

x.x

y
1a)
1b)

x
z.y

(* objanjenje:

3)

a) [y/x](x.x) = x.x
vezana
b) [z/y] x.xy

3c) [y/x] y.x

x.xz
(dovelo bi

do kolizije)
novo ime
z.y
*)
- -konverzije - pravilo za transformaciju izraza
1) -konverzija (preimenovanje)
xi.e xj.[xj/xi]e , xjfV(e)
2) -konverzija (primena)
(x.e1)e2 [e2/x]e1
11

3) -konverzija
(x.e)x
Primer:

, xfV(e)

(y.x.+xy)x kolizija,menja se smisao izraza y.x+xy


preimenovanje
(y.z+zy)x

z.+zy
- CHURCH-ROSSER-ove teoreme govore o redukovanju izraza,ali su - i
-konverzije mogue samo u stranu.
-redukcija
(x.e1)e2 [e2/x]e1
-redukcija
x.ex e
,xfV(e)
e1 * e2 oznaava da se e2 moe razviti iz e1 proizvoljnim
brojem(ukljuujui i 0) primena -redukcije,-redukcije i konverzije (* je refleksivno-tranzitivno zatvorenje ukljuujui i
-konverziju).
- -izraz je u normalnoj formi ako se ne moe dalje redukovati
korienjem - i -redukcija.
Neki -izrazi nemaju normalnu formu.
(x.(xx))(x.(xx)) (x.(xx))(x.(xx))

Primer:

e1

e2

Svaka nova -redukcija dovodi do istog izraza.


CHURCH-ROSSER TEOREMA 1 - postoji jedinstvena normalna forma.
Ako e0 * e1, tada e2 tako da e0 * e2 i e1 * e2.
Posledica: Nema -izraza koji se moe konvertovati u dve razliite
normalne forme (zanemarujui -konverziju).
Posledica: Redosled kojim se dolazi do NF nije vaan (naravno ,ako
NF postoji).
- Normalan redosled redukcije - sekvencijalna redukcija u kojoj kada
postoji vie od jednog reducibilnog izraza (redex),prvo se bira
krajnji levi spoljanji (nije sadran ni u jednom - najiri).
- Aplikativan redosled redukcije - sekvenc. redukcija u kojoj se
prvo bira krajnji levi najunutranjiji redex (ne sadri ni jedan najmanji).
CHURCH-ROSSER TEOREMA 2:
Ako e0 * e1 i e1 je NF,tada postoji normalna redukcija iz
- Aplikativna redukcija nije uvek odgovarajua.
Primer:
normalna redukcija
(x.y)((x.xx)(x.xx))
figurie u y
y
aplikativna redukcija
12

e0

e1.

, a poto x ne

(x.y)((x.xx)(x.xx))

, krajnja

leva najunutranjija
(x.y)((x.xx)(x.xx))
Rekurzija
TEOREMA FIKSNE TA^KE:
Svaki -izraz e ima fiksnu taku e tako da (e e) * e.
Dokaz:
,gde je Y paradoxical combinator ( daje
Neka je e=(Ye)
zau|ujue jednostavan dokaz )
Y=f.(x.f(xx))(x.f(xx))
e=(Ye)=(x.e(xx))(x.e(xx)) = e((x.e(xx))(x.e(xx))) =
e(Ye) = e e
Posledica : Svaka rekurzivna funkcija moe biti napisana rekurzivno.
Kako?
f = ...f...
f je rekurzivna
funkcija.
Znamo da je e = e e ,pa moemo pisati
f (f. ...f... ) f
tj. f. je
fiksna taka izraza f. ...f... po definiciji FT
Kada iskoristimo Y kombinator , dobijemo nerekurzivnu definiciju za
f.
f Y (f. ...f...)
Primer:
1)))
nerekurzivno :
1)))

fac = n.

if (n=0) then 1 else (n*fac(n-

fac Y (fac.n. if (n=0) then 1 else (n*fac(n-

U ovoj sposobnosti -izraza da simulira rekurziju je i snaga rauna.


POZNATA CHURCH TEOREMA:
Efektivno izraunljive funkcije iz pozitivnih celih u pozitivne cele
f : Z+ Z+ su samo one koje se mogu definisati u -raunu.
Primer: Kako se neke uobiajene stvari mogu predstaviti u -raunu.
Me|utim, tako neemo raditi, ve uvodimo proirenje -rauna:
- konstante (brojevi) , funkcije nad konstantama
- za svaku funkciju se uvodi -pravilo
Primer:

Uvodi se +,
xy.+xy

: +xy x+y

(* drugo + *)
- logike vrednosti T,F
- liste se predstavljaju kao specijalne strukture podataka
Logike konstante i operacije
Primer:

if P then Q else R
(COND PQR)
prevodi se u PQR sa pravilima TRUE xyx

FALSE xyy
u -raunu:
COND = p.q.r.pqr
13

TRUE = x.y.x
FALSE = x.y.y
Primer:
COND TRUE AB(p.q.r.pqr)(x.y.x)AB
(q.r.(x.y.x)qr)AB
(r.(x.y.x)Ar B
(x.y.x)AB
(y.A)B A
AND = x.y.x y FALSE
OR = x.y.(x TRUE)y
Liste u istom -raunu
-

NIL h t
CONS el slova
CONS = h.t.s.s ht
selektorske funkcije

h.t.h

h.t.t
(* definicijama TRUE i

FALSE *)
HD = L.L TRUE
TL = L.L FALSE
Tako primena HD i TL na CONS a b
daje odgovarajuu vrednost.
Primer:
HD(CONS a b ) = (c.c TRUE)((h.t.s.sht) a b)
((h.t.s.sht) a b) TRUE
(s.sab) TRUE
TRUE a b (h.t.h) a b (t.a) b a
isempty(IE) = TRUE , ako je lista NIL
IE(CONS a b) = IE((h.t.s.sht) a b) IE(s.sab)
poto ovo mora biti FALSE a,b ,jasno je da je IE oblika
GC(h.t.FALSE)
tj. NIL = x.TRUE
G uzima objekat (on je za 2 arg. uvek FALSE)
Redukovati:

IE =

IE ( TL ( CONS 1 NIL ) )

- Prirodni brojevi
Koristei liste definiemo prirodne brojeve:
- n kao lista od n el. proizvoljne vrednosti
- 0 praznoj listi
- EQ0 funkciji IE
- PRED funkciji TAIL
- SUCC =n.CONS any n
proizvoljni -izraz

Uvod u Miranda
1. Miranda - isto funkcionalni jezik
- program je skup jednaina (script)
- strogo je tipizirani jezik
- bazni tipovi :
brojevi,karakteri,istinitosne vrednosti
- bazne strukture - lista (el. istog
tipa)
14

- torka (tuple)
(el. razliitog tipa)
Primer: lista
1) radni_dani=[Pon,Ut,Sre,Cet,Pet]
dani=radni_dani ++ [Sub,Ned]
(append)
2) 0: [1,2,3] je [0,1,2,3] consiranje
#dani je 7 - duina liste
dani!0 je Pon - 0-ti el. liste
[1,2,3,4,5] [2,4] je [1,3,5]
3)biblioteke funkcije
product,sum
fac n = product[1..n]
res = sum [1,3..100]
Primer: torka
zaposleni=(Peric,True,False,39)

2. Jednaine sa straarima (Guarded equatons) i Blok Strukture


Jedna jednaina moe imati nekoliko razliitih desnih strana ,
koje se razlikuju po straarima (logiki izrazi)
Primer: NZD-najvei zajedniki delitelj
NZD a b = NZD (ab) b , a>b
= NZD a (ba)
= a ,
(* proveravaju se logiki izrazi *)

, a<b

args = des1 , test1


= des2 , test2
mogue uvo|enje lokalnih definicija*)
....................
= desn , otherwise

a=b

Primer:

(* u desi je

kvadjed a bc = error kompleksni koreni, delta<0


= [-b/(2*a)]

,delta=0
= [b/(2*a)+radix/(2*a),-b/(2*a)radix/(2*a)]

,delta>0
where
delta = b*b-4*a*c
radix = sqrt delta

vai za sve desne strane


- Pattern matching (prepoznavanje oblika) - analiza sluajeva ,
elegantnija od straara
- prepoznaje formalne parametre
sum[] = 0
reverse[] = []
sum (a:x) = a + sum x
reverse (a:x) = reverse x ++
[2]
- PM se moe kombinovati sa straarima
Primer: izbacivanje duplikata
na_dup x x ,#x<2
na_dup (a:a:x) = na_dup (a:x)
na_dup (a:b:x) = a: na_dup (b:x)
15

,a b

3. Currying i funkcije vieg reda


Miranda je jezik vieg reda .

f x y = (f x) y

Primer:
foldr op k [] = k
foldr op k (a:x) = op a (foldr op k x)
poetna vrednost a op operacija

,gde je k

Primer:
sum = foldr (+) 0
,
product = foldr (*) 1
4. Lenjo izraunavanje - vrednost izraza se ne izraunava sve dok
nije potrebno
- mogunost definisanja
beskonanih struktura podataka
one s = 1 : ones
fib = f 0 1
not s = [0..]
where f a b = a : f b (a+b)
add s = [1,3,..]
5. ZF (Zermelo-Frankel) izrazi
- opti prikaz operacija nad listama
[n*n n[1..100]]
generator
- opti oblik
[telo kvalifikatori]
1) var izraz
2) filter - logiki izraz koji odre|uje rang
(vrednost) promenljive
3) vie kvalifikatora je razdvojeno sa ;
Primer:
1) perm [] = [[]]
perm x = [a : y ax ; yperms(x[a])]
2) faktori n = [i i[1.. n div 2]; n mod i = 0]
6. Tipiziranost
Miranda je strogo tipiziran jezik - svaki izraz i podizraz ima tip,
koji se proverava u vreme prevo|enja i ako ne do|e do podudaranja,
javlja se greka.
1) osnovni tipovi : num,bool,char
2) za tip T ; [T] je lista iji su el. tipa T
[[1,2][2,3,4]] je tipa [[num]]
3) za tipove T1,...,Tn ; (T1,...,Tn) je torka
4) T1 i T2 tipovi ; T1T2 je funkcija koja ima arg. tipa T1 a
rezultat je tipa T2
Primer:
sum je tipa [num] num
Program moe da ukljui deklaracije tipa korienjem :: .
Primer:
sq::numnum
sq n = n*n
Ne mora se definisati tip, ali je dobro da postoji zbog
dokumentacije.
7) Polimorfizam - jedna funkcija moe raditi sa argumentima
razliitog tipa.
16

id x = x
*,**,...
id :: **

-bez obzira kog je tipa x


se koristi da oznai proizvoljne tipove.

Primer:
reverse :: [*][*]
fst(*,**)*

* - jedan proizvoljan

tip
snd(*,**)**

** - drugi proizvoljan tip

8) Korisniki definisani tipovi


Primer:
num stablo
tree ::= Hilt Node num tree tree

konstruktori tipa (uvek poinju


velikim slovom)
ime tipa def.tipa
- za analizu objekta korisnikog tipa koristi se pattern-matching
Primer:

kao u

mirror Hilt = Hilt


mirror (Node a xy) = Node a (mirror y)(mirror x)
(* daje stablo
ogledalu *)

- i ovi tipovi mogu biti polimorfni


ime* ::= Hilt Node * (tree *)(tree *)
Primer:
color ::= Crveno Oranz Zuto Zeleno Plavo Indigo
Ljubicasto
Standardni tipovi bi se mogli prikazati:
bool = True False
not ::= Zero Suc not
list * ::= Nil Cons * (list *)
Podela tipova:
1) algebarski tipovi - tipovi koji se definiu sa ::=
2) sinonimi - novo ime za postojei tip
primer:
string == [char]
3) apstraktni tipovi podataka

3.Osnovni elementi funkcionalnih programskih jezika


3.1.Osnovna struktura podataka
- s-izraz (simboliki izraz)
atom - simboliki
- numeriki
takasti izraz (S1.S2); S1 i S2 su izrazi.
lista (S1 S2 ...Sn); S1, ... ,Sn s-izrazi.
- formalno
s-izraz = atom lista
lista = ( sloen )
sloen = s-izraz takast s-izraz sloen
takast = s-izraz . s-izraz
17

- posebni simboliki atomi


NIL - prazna lista
T - logika vrednost tano
F - logika vrednost netano
- konvencije za ulanjanje . zapisa
1.) .( . . . )
2.) .NIL
Primer: ( 1. (2. NIL ) ) (1 2)

3.2 Primitivne funkcije


(QUOTE s-izraz) s-izraz
(CONS s-izraz1 s-izraz2) ( s-izraz1 . s-izraz2 )
- s-izraz2 - atom par_takasti zapis
- s-izraz2 - lista lista
( CAR ( s-izraz1 . s-izraz2 )) s-izraz1 - glava argumenta
( CDR ( s-izraz1 . s-izraz2 )) s-izraz2 - rep argumenta
( ADD num_atom num_atom) num_atom
Ostale aritmetike operacije slino.
( EQ atom atom ) logiki
Ostale rel. operacije slino.
- predikati
( NULL s-izraz ) log
- prazna lista
( ATOM s-izraz ) log
( NUMBER s-izraz ) log
- logike operacije
( DIS log log ) log
( CON log log ) log
( NOT log ) log
- uslovni izrazi
( IF log s-izrazT s-izrazF ) s-izrazL

s-izrazT ako je log = T


s-izrazF ako je log = F
(COND ( log1 s-izraz1 )
( log2 s-izraz2 )
...
s-izrazI I = 1,...,n za logI =T.
( log n s-izrazn )
)
- definicija i primena funkcije
- anonimna funkcija
def: ( LAMBDA argumenti telo ) arg . telo
lista
s-izraz
primena: ( (LAMBDA (x) (ADD x (1)) ) (2) ) 3
definicija funkcije
stvarni
argument
( f arg1 arg2 . . . argn )
- retko se funkcija primenjuje u ovom (anonimnom) obliku.
- imenovana funkcija - dodela imena funkciji.
f = larg.telo.
- LET i LETREC blokovi (izrazi)
18

- zamena izraza nekim imenom


LET izraz:
( LET s-izraz
( LET s-izraz
( ime1 . (s-izraz1))
( ime1 s-izraz1)
...
...
( imen . (s-izraz))
( imen s-izraz )
)
-->
s-izraz (ime1, . . . , imen)
)
Primer:

( LET (ADD Pi A1)


( Pi 3.14)
( A1 ADD (2) (4.12))
)

9.26

Primer: LET izraz kao samostalan program


(LET (a (2))
(a (LAMBDA (x) (ADD x (1))))
)
ili:
( LET a
(a . (LAMBDA (x)
(ADD X (1))))
)
LETREC izraz:
(LETREC s-izraz
( ime1 s-izraz1)
...
(imen
s-izrazn)

)
s-izraz (ime1 . . . imen)

ime1, ... ,imen mogu da figuriu i u


s-izraz1, . . . , s-izrazn.
definisanje rekurzivnih funkcija

Primer: ( LETREC fac


(fac LAMBDA (x)
(IF ( EQ x (0))
(1)
( MUL x ( fac ( SUB1 x )))
)
)
( SUB1 LAMBDA (x) ( SUB x (1)))
)
[ y / x ] ((y.x) (x.x) x)
e1
[ y / x ] ( y . x ) [ y / x ] ( x . x ) [y/x] x
e1 xi
xj e2 e1 xi
xj e2

4. SECD - maina
Prvi interpretator za izraunavanje vrednosti -izraza prvi je predloio Landin (1964). On se
sastojao od etiri steka S, E, C, D. Ovaj nain izraunavanja -izraza je opte prirode i omoguava
relativno jednostavan nain implementacije. Mada najstariji nain on se i danas koristi za
implementaciju funkcionalnih jezika, iako nije uvek i najefikasniji.
Javlja se u dva osnovna oblika:
19

- vredna maina - (data driven )


- lenja maina - (demand driven)
Proizvoljan -izraz je nekog od sledeih oblika:
izraz ::= id . izraz id izraz izraz ( izraz ) const.
const ::= atomi primitivne funkcije.
Izraunavanje nekog -izraza se prikazuje nizom stanja u SECD maini tj. nizom prelaska iz
jednog u drugo stanje poev od poetnog stanja kada je ulaz -izraz do zavrnog stanja kada je izlaz
vrednost -izraza.
SECD maina se sastoji od etiri steka:
- S je stek objekata koji uva vrednosti u toku izraunavanja izraza.
- E je okruenje u kom se izraunava izraz. To je obino asocijativna lista iji
su elementi parovi (id,vr).
- C je kontrolni stek, u kome se uva deo -izraza koji jo nije izraunat.
- D je dump, u kome se uva prethodno stanje stekova, koje je potrebno
rekonstruisati nakon povratka iz poziva neke funkcije.
Closure slui za reprezentaciju apstrakcije zajedno sa njihovim vezanim promenljivom. Ona
se zapisuje : [id, exp, env ] , gde je id ime vezane promenljive, exp je telo izraza i env je okruenje
koje povezuje vrednosti sa slobodnim promenljivima.
Funcije koje e se koristiti u funkciji za interpretaciju i simuliranje prelaska iz jednog u novo
stanje, su :
bv(x . E) = x ; body (x . E) = E
rotor( E1 E2) = E1 ; rand ( E1 E2) = E2

4.1. Funkcija promene stanja


promena : stanjei stanjei+1
Si Ei Ci Di Si+1 Ei+1 Ci+1 Di+1
Promena stanja uslovljena je tekuim stanjem u steku C.
1.) X = hd(C), - kontrolni string nije prazan.
a) X je identifikator.
( value_of (X,E) :: S , E , tl(C) , D )
( valueof (K,E) = K , za konstantu K u svim okruenjima ).
b) X je -apstrakcija : u tom sluaju se formira zatvorenje na vrhu steka S.
( [ bv(X) , body(X) , E] :: S , E, tl(C) , D )
c) X = FA - primena funkcije F na njene argumente A.
U vrednom izraunavanju izrazi F i A su prvo izraunati i onda se vrednos F primenjuje na
vrednost A . FA sa poetka kontrolnog steka se zamenjuju sa 3 elementa : A, F, @.
@ - kada se pojavi na poetku steka C, uslovljava primenu prvog elementa steka (S) na
elemente ispod njega.
Sledee stanje je :
( S , E , A :: ( F :: ( @ :: tl(C) ) ) , D )
d) X= @; Ako je oblik steka s:= f :: a :: S , tada :
(i) f je primitivna funkcija
( f (a) :: S , E , tl(C) , D ).
(ii) f je zatvorenje [ V , B , E ]
( ( ) , ( V , v ) :: E , B , ( S , E , tl (C) , D ) )
a
b
c
a - prazan stek za novo izraunavanje
20

b - okruenje E je dopunjeno vezom promenljivom V sa vrednou v


c - kada se zavri izraunavanje izraza iz B, mora se rekonstruisati stanje maine.
2.) C je prazan
a) D je prazan: Rezultat rada je prvi element steka S.
b) D nije prazan:
Ako je pri tom:
D = (S, E, C, D)
sledee stanje je:
( hd (S) :: S, E, C, D )
Primer:
twice = .x.(x)
posmatrajmo twice succ 0 tj. ( . x . (x) ) succ 0
S
()
()
0
0
succ, 0
[,x . (x), ( )], succ, 0
()
[x,(x),(= succ)]
[x,(x),(=succ)],0
()
()
()
0
succ,0
1
succ,1
2
2

E
C
()
((.x.(x)) succ 0)
()
0((.x.(x)) succ), @
()
((.x.(x))succ), @
()
succ, .x.(x),@,@
()
.x.(x),@,@
()
@@
( = succ)
x.(x)
( = succ)
()
()
@
( x=0, =succ)
((x))
( x=0, =succ)
x,,@
( x=0, =succ)
x,,@,,@
( x=0, =succ)
,@,,@
( x=0, =succ)
@,,@
( x=0, =succ)
,@
( x=0, =succ)
@
( x=0, =succ)
()
()
()

D
()
()
()
()
()
()
(0, ( ),@, ( ) )
(0, ( ),@, ( ) )
()
( ( ),( ),( ),( ) )
( ( ),( ),( ),( ) )
( ( ),( ),( ),( ) )
( ( ),( ),( ),( ) )
( ( ),( ),( ),( ) )
( ( ),( ),( ),( ) )
( ( ),( ),( ),( ) )
( ( ),( ),( ),( ) )
()

4.2. Specijalne primitivne funkcije u SECD maini


^ist netipizirani raun je kompletiran, ali se radi lakeg rada moe dopuniti jo nekim
primitivima.

4.2.1. Izraunavanje uslovnih izraza


Primer:
if a 0 then 1/a else a

- u aplikativnom nainu izraunavanja (vredno) uvek e se


izraunati sva tri izraza, bez obzira kakvo je a.

Tako|e:
fac(n) = if n = 0 then 1 else nfac(n-1),
else grana e se uvek izvravati na svaki rekurzivni poziv, uslovljavajui
beskonani niz poziva ( f(0) e prei u f(-1) . . .)
reenje1: transformisanje uslovnog izraza korienjem dummy funkcija. To je standardan
nain da se omogui normalan redosled izraunavanja. Ekvivalentan izraz je:
21

( if a 0 then dummy./1 a else dummy.a) any.


gde je any neki objeka
apstrakcija se ne moe izvriti dok
se ne primeni na neki argument. Kada se prosledi
ostaje neizvren ali kada je a 0 a=0
izvrava se apst. koja se mora primeniti na
neto a to je onda any.
primer:

deley e dum.e
force e e any

resenje 2: drugi nain je definisanje izraza novog tipa.


exp::= . . . cond exp exp exp

P - predikat

E - else grana
T - then grana
Ovaj izraz cond T E P na vrhu C steka se zamenjuje sa P, cond T E, @ .
X = cond T E
( tl(S), E , T :: tl( tl(C) ) , D ) if hd (S) = true
( tl(S), E , E :: tl( tl(C) ) , D ) if hd (S) = false

4.2.2 Izraunavanje izraza koji sadre rekurzivne funkcije


Rukovanje rekurzijom u vrednoj maini.
1) korienjem Y-kombinatora
2) korienjem oznaenih izraza ( lobetled expressions )
Rekurzivna funkija se moze prikazati:
1) Ako je (x) = t(,x) za neki izraz E moemo napisati:
= Y y.x.E(g,x) gde je Y =h.(x.h(xx)) (x.h(xx))
Primer: fac = Y .n. if (= n 2) then 2 dse*n( (pred n) )
Mi ipak ne moemo implementirati rekurzivne funkcije direktno korienjem fiksne take za
aplikativni redosled izvravanja jer se izvravanje nikad ne bi zavrilo zbog samo primene (xx). Stoga
se definise kombinator Y da se prevazi|e taj problem.
Y = h.( x . h(y.x xy)) (x . h(y. x xy))
zadrava izvravanje xx kao ldummy kod if a
( Y Y ) - neefikasna implementacija.
Korienje Y umesto Y uklanja eksplicitnu rekurziju, samoprimena se izvrava samo kada se
primenjuje na neki argument (onaj koji odgovara y). Ako primena funkcije koja odgovara ne ukljuuje
rekurzivni poziv, samoprimena se nee izvriti.
No bez obzira da li se koristi Y ili Y:
2) Proirenje fukcije stanja - ako je Y oznaeni izraz N,L, -apstrakcija L je povezana sa
imenom N i dodata u tekue okruenje.
Sledee stanje je :
( S , (N,L) :: E , L :: tl(C) , D )
,
N=l . . .

-apstrakcija
L
22

Naredne pojave ovog imena na vrhu kontrolnog steka ( u toku primene njegove l apstrakcije) e
usloviti da se njegova l-apstrakcija postavi na stek uz dodatak u okruenje.
Dodatak u fju promene stanja
x=@
i S = :: a :: S
dajui :
1)
( d ) (iii) = apstrakcija, gura se u C stek tako da naredna promena formira
zatvorenje u S. Novo stanje je :
(a : S , E , :: C , D )
Traeno ztvorenje se formira u dva koraka.
1) Kada se na vrhu C na|e labela <ime,izraz> ona se ubaci u okruenje, i izraz se ostavi na vrh C-a. Od njega se na vrhu S-a formira zatvorenje. Kada
se na vrhu C-a na|e ime rekurzivne fje ond se iz okruenja vadi njegova def. i stavlja na vrh S-a. Otuda dodatak 1d, kada se na vrh S-a na|e apstrakcija, onda se ona postavlja na C da bi se izvrila.
fac = (.x. if x=0 then 1 else x.fac(x-1))
2
< fac , x.x = 0 1 x.fac(x-1))
1uuuuuuuuuu2uuuuuuuuuuu3
L

5. SECD - maina u implementaciji FPJ


S - stek za smetanje me|u rezutata u vreme izvo|enja izraza.
E - okruenje - uva vrednosti vezane za promenljivu u vreme izraunavanja
C - kontrolna lista za smetanje programa
D - dump - pri pozivu nove fje, uva stnja registara
KOMANDE SECD MA[INE:
LD
LDC
LDF
AP
RTN
DUM
RAP
SEL
JOIN
CAR
CDR
CONS
EQ
ADD,SUM,MUL,DIV,REM
LEQ
STOP

punjenje
punjenje konstante
punjenje fje
primena fje
povratak
kreira fiktivnu eliju tj. formalno okruenje
rekurzivna primena
selekcija podliste (za dalje izvravanje)
uspostavljanje glavnog upravljanja
prvi element od elemenata na vrhu steka
ostatak od elemenata na vrhu steka
formira listu od 2 elementa sa vrha steka
proverava jednakost 2 elementa sa vrha steka
aritmetike operacije koje primenjuje na 2 elementa
sa vrha steka
prvi(S) <= drugi(S)
zaustavljanje izvravanje SECD programa na maini

ARITMETI^KE OPERACIJE I PORE\ENJE:


23

( a b . S ) e ( ADD . c ) d ( b + a . S ) e c d
( a b . S ) e ( SUB . c ) d ( b - a . S ) e c d
( a b . S ) e ( DIV . c ) d ( b DIV a . S ) e c d
( a b . S ) e ( REM . c ) d ( b MOD a . S ) e c d
( a b . S ) e ( EQ . c ) d ( b = a . S ) e c d
( a b . S ) e ( LEQ . c ) d ( b <= a . S ) e c d
Primer:

1-2*3=4

( EQ ( SUB (1 ) ( MUL (2 ) ( 3 ) ) ) ( 4 ) )
0
1
2 22
3 3 3 3 2 1 1 1 0
prevee se
( LDC 1 LDC 2 LDC 3 MUL SUB LDC 4 EQ )
Izvravanje:
(s)
e.
( 1 . S ) e ( LDC 2 LDC 3 MUL SUB LDC 4 EQ ) d
( 2 1 . S ) e ( LDC 3 MUL SUB LDC 4 EQ ) d
( 3 2 1 . S ) e ( MUL SUB LDC 4 EQ ) d
( 6 1 . S ) e ( SUB LDC 4 EQ ) d
( 1-6 . S ) e ( LDC 4 EQ ) d
( 4 -5 . S ) e ( EQ ) d
( F . S ) e NIL d
OPERACIJE SA LISTAMA:
( a b . S ) e ( CONS . c ) d ( ( a . b ) . S ) e c d
( a b . S ) e ( CAR . c ) d ( a . S ) e c d
( a b . S ) e ( CDR . c ) d ( b . S ) e c d
( a . S ) e ( ATOM . c ) d ( t . S ) e c d
t = T ako je a atom
t = F ako je a lista
POSTAVLJANJE VREDNOSTI:
Okruenje je lista listi u kojima se nalaze vrednosti koje figuriu u programu. Da bi se vrednost
iz okruenja prenela na vrh steka koristi se operacija maine LD. Ona ima argument koji je par (i,j)
indeksa: i odre|uje podlistu iz koje se uzima vrednost a j odre|uje koji element iz i-te podliste se uzima.
I podliste I elementi u njima se numeriu od 0,1,...
Primer:

0 1
0
( ( 3 17 ) ( ( AB ) ) )
0
1

(0.0)
(0.1)
(1.0)

3
17
(AB)

Bie potrebna fja koja daje n-ti element liste S:


index( n , S ) = if eq( n , 0 ) then car( S )
else index( n-1 , cdr ( S ))
tj. za i = ( b . n )
locate( i , e ) = index( n , index( b , e ) )
where b = car( i )
24

n = cdr( i )
IZVR[AVANJE OPERACIJE LD:
S e ( LD i . c ) d ( x . s ) e c d gde je x= locate ( i , e )
Primer:
s
NIL
( 7. )
(27)
(3)

e
((37)(20)
((37)(20)
((37)(20))
((37)(20))

c
( LD ( 0 . 1 ) LD( 1 . 0 ) ADD )
( LD ( 1 . 0 ) ADD)
(ADD)
NIL

d
d
d
d
d

USLOVNI IZRAZ:
Realizuje se pomou dve operacije:
SEL
JOIN

izabira koja e se podlista ( niz komandi ) izvravati u zavisnosti od


vrednosti koja s enalazi na vrhu steka
vraa upravljanje glavnoj listi

U optem sluaju je prevedena forma if izraza sledea:


( . . . SEL ( . . . JOIN ) ( . . . JOIN ) . . . )
C1
C0
Pravila:
( x . S ) e ( SEL C1 C0 . c ) d S e Cx ( c . d )
Cx = C1 za x = T
Cx = C1 za x = F
S
e ( JOIN ) ( c . d ) s e c d - vraa upravljanja u sauvanoj listi C.
Primer:

( LD ( 0.0) SEL ( LD ( 0 . 1 ) JOIN )


( LD ( 0 . 2 ) JOIN ) STOP )
ako je vrednost sa pozicije ( 0 . 0 ) T, onda je rezultat vrednost sa pozicije ( 0 . 1 ), a inae je vrednost
sa pozicije ( 0 . 2 ).
OPERACIJE ZA IZVR[AVANJE FJA:
- daleko sloenije, uestvuju u prevo|enju let blokova
- kada se korisnikova fja poziva ( primenjuje ) sa argumentima, vrednosti argumenata se smetaju
u okruenje kao podliste i u letu fje im se pristupa pomou komande LD. (Vrednosti argumenta su
prva podlista u okruenju)
- vrednost fje se predstavlja spojem (zatvorenje) ( -izraz, kopije konteksta) u kojem je formirana
fja. Ovaj par se formira pomou LDF komande:
S c ( LDF c . c ) d ( ( c . e ) . S ) e c d
c- kod koji odgovara fji
e - okruenje u kom se javlja , definie fja - statiko vezivanje
Primer ( 0 ) ( ( 3 7 ) ( A ) ) . ( LDF ( LD ( 1 . 1 ) RTN ) LD ( 0.1)) NIL
2 1uuu2uuu3
1uuuuuu2uuuuu3
2
S
e
c
d

( ( ( LD ( 1 . 1 ) RTN ) . ( ( 3 7 ) ( A) ) ) 0 ) ( ( 3 7) ( A ) ) ( LD ( 0 . 1 ) ) NIL
25

- kada se zatvorenje poziva i pimenjuje ( APP komanda) ono se nalazi na vrhu steka S ispred
stvarnih parametara.
APP
( ( c . e ) v . S ) e ( APP . c) d NIL ( v . e ) c ( S e c d )
v je stvarni parametar koji se javlja u 0-toj podlisti. Svarni parametri se javljaju u nultoj podlisti a
u prvoj podlisti se javljaju slobodne promenljive. U steku d se uva stanje registara koje treba obnoviti
nakon zavretka izvravanja fje.
Primer:
( ( ( LD( 1.1 ) LD( 0.0 ) ADD RTN ) . ( (3 7) ( A) ) ) ( 6 ) 0 ) ( ( 2 B ) ) ( ADD STOP ) d
1uuuuuuuuuuu2uuuuuuuuuuuuuuu3 1uu2uuu3 2 2 123 1uu2uuu3
c
e
v S
e
c

NIL ( ( 6 ) ) ( 3 7 ) ( A) ) ( LD( 1.1 ) LD( 0.0 ) ADD RTN ) ( ( 0 ) ( ( 2 B ) ) (STOP) . d)


13
13
7-globalno
6-stvarni parametar
RTN - vraa mainu u stanja koja se uvaju u d.
( x ) e ( RTN ) ( S e c d ) ( x . S ) e c d
Primer:

(13) ( ( 6 ) ( 37 ) ( A ) ( RTN ) ( ( 0 ) ( ( 2 B ) ) ( STOP ) . d )

( 130 ) ( ( 2 B ) ) ( STOP ) d

REKURZIVNE FJE ( operacije DUM I RAP)


Za ove operacije potrebno je uvesti pomonu fju zavrsi(x,y) koja zamenjuje car(x) sa y ( ali samo
u sluaju kada car(x) ima specijalnu vrednost -ne zavreno x = ( e)). Fja zavisi se koristi kod
realizacije rekurzivnih blokova ( letrec ) gde je potrebno izvriti izraunavanja lokalnih definicija u
kontekstu koji ukljuuje njihove sopstvene vrednosti. Taj problem se reava na sledei nain:
- formira se formalno okruenje sa nezavisnim lokalnim definicijama.
- izraunavaju se definicije; koristei to formalno okruenje.
- redom se zamenjuju nezavreni delovi okruenja izraunati definicijama.
Na ovaj nain u svako zatvorenje koje se formira pri izraunavanju definicije, ukljuuje se
formalno okruenje. Posle zamene nezavrenog dela ta zatvorenja postaju ciklina, svako od njih
sadri okruenje koje sadri samo zatvorenje kao vrednost.
DUM - formira fiktivno okruenje
s c (DUM.c) d s (.e) c d
RAP - odgovara komandi APP - koristi fju koja zamenjuje koje je ubaeno DUM komandom
( ( c . e ) v . S ) ( . e ) ( RAP . c ) d NIL zavrsi( e , v ) c ( S e c d )
2
123
U momentu primene RAO ovo je isto e = ( . e )

6.Prevo|enje LISP programa u jezik SECD maine

Svaki ispravni L izraz se prevodi u ekvivalentan niz naredbi SECD maine.


s e c d ! (x.s)e NIL d$ ; x je vrednost izraunavanja programa c u okruenju e
U prevo|enju emo koristiti oznaku | u smislu spajanja listi.
Primer:
26

s e c|c d ! (x.s) e c d
c=(LDC1)
c=(RTN) => c|c=(LDC1 RTN) tj.
se (LDC1 RTN) d ! (1.s) e (RTN) d
Ako su c1 i c2 liste za pravilne L izraze i ako su vrednosti njihovih izraunavanja x1 i x2 tada vai :
se c1|c2|cd!(x2 x1.s) e c d.
x|y|z!x|y|z= x|y|z
tj. x|y<-> append(x,y)
Pri analizi L izraza formira se lista promenjivih koje se javaljaju u izrazima i blokovima unutar
njih. Ta lista ima istu formu kao liste tj. okruenje u kom se vri izraunavanje ( to je lista listi)
kada se pojavi novi blok ili funkcija, promenjive iz njega (nje) se dodaju kao nova prva podlista u
listi imena.

Primer:
(letrec
(append (x y)
(let

! ((A)(x y) (append REV, DUP)


(A )))

(REV )
(DUP ))

0.0 1.0 1.1 2.0

2.1

2.2

Da bi se pri prevo|enju odredili parovi indeksa za poziciju imena koja se javlja u programu koriste
se pomonje funkcije.
location (x,n) - x - promenjiva
n - lista imena
position (x,a) - u listi atoma a, daje indeks (poziciju) atoma x
position (x,a)= if eq(x,car(a)) then
else 1+(position(x, cdr(0))
location(x,n) = if member (x, car(n)) then cons (0,position (x,car(n)))
else cons(car(z)+1,cdr(z))
where z=location (x,cdr(n))
(lista, pozicija u listi)

6.1 Prevo|enje

neka je e pravilan L izraz


n - lista imena
e * n je program koji se dobija prevo|enjem izraza e u odnosu na listu imena n
promenjiva i konstanta
x*n=(LD i), i=location (x,n)
(QUOTE S)*n= (LDC S)
Aritmetike operacije, operacije za rad sa listama
(ADD e1 e2)*n=e1*n|e2*n|(ADD)
e1 e2
kod za izraunavanje vrednosti izraza e1/e2
izraunava se e1 i stavlja na vrh steka S, zatim se izraunava e2 i stavlja na vrh, a onda se
primenjuje operacija ADD na prva 2 elementa steka i rezultat te operacije se stavlja na vrh steka S.
(OPER e1 e2)*n=e1*n|e2*n|(OPR)
OPER=SUB,MUL,DIV,REM,EQ,LEQ
27

(CAR e)*n=e*n|(CAR)
(CDR e)*n=e*n|(CDR)
(CONS e1 e2)*n=e2*n|e1*n|(CONS)
(ATOM e)*n=e*n|(ATOM)
Primer:
(ADD(CAR x)(1))*((xy))=(CAR x)*((xy))|(1)*((xy))|(ADD)=
x*((XY))|(CAR)|(LDC 1)|(ADD)
= (LD (0.0))|(CAR)|(LDC1)|(ADD)= (LD (0.0) CAR LDC 1 ADD)
uslovni izraz
Primer:
(IF e1 e2 e3)*n=e1*n|(SEL e2*n|(JOIN) e3*n | (JOIN))
argumenti od SLL
(ADD y(IF(EQ x y)x(i1)))*((xy))
=(LD(0.1)LD(0.0)LD(0.1)EQ SEL (LD(0.0) JOIN)
e1
(LDC 1 JOIN)ADD)
izraz
(LAMBDA (x1 xk)e)

-kako se mora prevoditi uzimajui u obzir i (x1 xk) to lista


imena ima oblik ((x1 xk).n)
- prom. iz n se pristupa tako da se prvi indeks u paru mora
poveati za jedan.

Program se formira kao rezultat izraza c=e*((x1 xk).n)


(LAMBDA (x1 xk) e) *n =(LDF e*((x1 xk).n)|(RTN))
Primer:
(LAMBDA (x) (ADD x y )* ((x y ))=
(LDF ( LD (0.0) LD (1.1) ADD RTN))
novo okruenje je ovde ((x).(x y ))
0.0 1.1
poziv funkcije (e e1 ek)
c c1 ck svakom izrazu e odgovarati lista tj. programski fragment
Programi tako treba da su ukomponovani, da bi se u vreme izvravanja u stek smestila lista vrednosti
izraunatih programima c1, , ck i zatvaranje izraunalo program c.
Lista vrednosti se moe dobiti programom:
(LCD NIL)|ck|(CONS)|ck-1|(CONS)||c1|(CONS)
na steku e se vrednosti javiti u ispravnom redosledu.
Ako se iz ci izrauna vi, tada na vrhu steka imamo listu vrednosti (v1 vk) tj. stvarnih argumenata
" program za poziv funkcije
(e e1 ek)*n=(LDC NIL) ek*n|(CONS)||e1*n|(CONS)|e*n|(ADD)
Primer:
poziv (AD1 (1)) se izraunava u kontekstu gde je AD1 jedinstvena promenjiva i njena vrednost se
dobija iz -izraza
(LAMBDA (x) (ADD x (1))) - pomou LDF formirano zatvorenje.
Zatvorenje koje predstavlja - izraz u trenutku izraunavanja je
=((LD(0.0) LDC 1 ADD RTN).NIL)
c program
e okruenje
28

Prevo|enje poziva daje:


(AD1 (1)*((AD1))
=(LDC NIL)|(LDC1)|(CONS)|(LD(0.0))|(AP)
=LDC NIL LDC 1 CONS LD (0.0) AP)
Izvrenje
S
(NIL.S)
(1 NIL.S)
((1).S)
((1).S)
NIL
(1)
(1 1)
(2)
(2.S)

(())
(())
(())
(())
(())
((1))
((1))
((1))
((1))
(())

(LDC NIL LDC 1 CONS LD (0.0) APP)


(LDC1 CONS LD (0.0) APP)
(CONS LD (0.0) APP)
(LD (0.0) APP)
(APP)
(LD (0.0) LDC1 ADD RTN)
(LDC1 ADD RTN)
(ADD RTN)
(RTN)
NIL

d
d
d
d
d
(S (()) NIL.d)
(S (()) NIL.d)
(S (()) NIL.d)
(S (()) NIL.d)
d

LET blok
(LET e (x1.e1)(xk.ek))((LAMBDA (x1xk)e)e1ek)
(LET e (x1.e1)(xk.ek))*n(LDC NIL)| ek*n|(CONS)||e1*n|(CONS)|
(LDF e*m |(RTN) AP)
m=((x1xk).n)
za izraunavanje e1, , ek nisu potrebna imena x1,,xk, tako da pri izraunavanju e1, , ek pozicije
za x1,,xk jo nisu uspostavljene. One se ustanovljavaju komandom APP
LETREC blok
slino kao LET ali
1) izrazi koji odre|uju vrednosti lokalnih promenjivih izraunavaju se u odnosu na dopunjenu listu
imena.
2) program za te izraze izraunava se u formalnom okruenju koje se formira komandom DUM.
Umesto komande APP koristi se RAP.
(LETREC e(x1.e1)(xk.ek))*n=
(DUM LDC NIL)|ek*m|(CONS)||e1*m|(CONS)|(LDF e*m |(RTN) RAP)
m=((x1xk).n)
Primer:
(LETREC (FAK (6))
(FAK LAMBDA (x)))
x1
e1

m=(FAK.n)
kod za telo funkcije FAK

(DUM LDC NIL LDF C CONS


poziv funkcije za FAK u donosu na m
LDF (LDC NIL LDC 6 CONS LD(0.0) AP RTN)RAP)
za primenu
(LDF C|(RTN))

za FAK u odnosu na m

(LDF (cod RTN))

fiktivno
okruenje
29

Izvo|enje
NIL
NIL
(NIL)
((c. )NIL)
(((c. )))
(((LDC NILRTN))
((c. )))
zatvorenje za izraz
definisan blokom

NIL

(DUMRAP)
(LDC NILRAP)
(LDF CRAP)
(CONSRAP)
(LDF(LDC NILRTN)RAP)
(RAP)

NIL
NIL
NIL
NIL
NIL
NIL

=(NK)

lista vrednosti definisanih u


bloku, u naem sluaju to je jedna
vrednost tj. zatvorenje koje
predstavlja funkciju FAK

Oba zatvorenja sadre fiktivno okruenje. Kada se izvri komanda RAP fiktivno okruenje se menja
tako da car te liste sadri listu definisanih vrednosti, pa se sledee stan
NIL (LDC NILRTN) (NIL NIL NIL.NIL)
koristi gde je zatvorenje = (((c. )).NIL) tj. je okruenje sa jedinstvenom pozicijom (0.0) gde se
uva vrednost (c. )
bilo -fiktivno okruenje
Stoga kada se u kontrolnoj listi javi komanda LD(0.0) za funkciju FAK e biti uvedeno
ispravno zatvorenje, a kada se izvrava rekurzivni poziv izRekurzivni
programapoziv
c, pomou
komande LD (1.0) to
je na vrh steka doveo
zatvorenje e se ponovo javiti, poto se (stvarno) javlja klistu
ao okruenje
tomzazatvorenju.
org., pa se ukod
FAC nalazi na
(1.0) poziciji.

Lenja
(DELAY e)*n=(LDE e*n|UPD)
FORCE e)*n=e*n|(APO)
recept (F(c.l)) - nije jo izraunat
(T x) - izraunat
L

S E (LDE c.c)d ! ([F(c.l)].S) lcd

([Tx.S)l(APO.c)d!(x.S) lcd

([F(c.l)].S)l(APO.c)d!NIL l c (([F(c.l)].S)lc.d
(x) l (UPD)(([F(c.l)].S)ec.d)!(x.S e c d

x [F(c.l)]![Tx]

30

Realizacija
S-izraz

cons
x

vred
x
x

atom

car

cdr

(A B C)
cons

cons

A
x

cons

B
x

NIL
x
x

C
x

(A.B)
cons

A
x

B
x

pr
(letrec l
(f -)
(g -))

cf, cg, ce - liste komandi za f, g, e


(DUM LDC NIL LDF cg CONS LDF cf CONS LDF ce RAD)

komanda DUM 1)

NIL

kada se f i g izvravaju poto su funkcije na vrhu s-a formiraju zatvaranja tj.

s
NIL
NIL

cf

cg
s:(cfcg.s)

Onda se na vrhu S postavi zatvaranje za ce i izvravan sa komanda RAP to uslovljava promenu


okruenja ija je prva komponenta formiranje okruenja tj.

l
NIL

31

cf

cg
ce se izraunava u
okruenju
gde
su
fiktivno cf i cg koji se
raunaju u istom tom
okruenju.
Okruenje
sadri
zatvorenje koje u sebi
sadri to isto okruenje
- ciklina struktura.

FOLD / UNFOLD
sum (nil)=0
sum (x:l)=x+sum(l)
double (nil)=nil
double (x:l)=(2*x):double(l)
g(l)=sum(double(l))
g(nil) =sum(double(nil))
= sum (nil)
=
g(x:l) = sum (double (x:l))
= sum ((2*x):double(l))
= (2*x)+sum(double(l))
= (2*x)+g(l)
dalje po lanku!

(instantiation)
(unfolding)
(unfolding)
(instant)
(unfolding)
(unfolding)
(folding)

Funk. Program je izraz koji ima jedinsvenu vrednost i nije bitan redosled kojim emo do njega
doi.
Sva komunikacija je kroz graf
Stanje izraunavanja ! graf

Model:
Proc Proc Proc
komunikacije
graf

zadaci

Kada novi proces


$ kozervativno: kad treba, +, AND,
$ spekulativno: unapred

+,AND,-, i kad je vrednost argument striktna. U kom sluaju obeleiti i vor primene i kombinator.
Zato? Ako obeleimo samo vorove
@
!

!
@

l
z

Ako je y rezultat on nee biti ra|en paralelno (ta


informacija je ostala u voru primene). Kada bi
to stajalo pored y sve bi bilo OK

32

@
IF

y
x

Obrnuto:
@
@
@

Ovde bi l moglo paralelno, ali nee sve dok IF


neto ne izrauna.

!z

!y

!IF
!x
Znai oba moraju biti oznaena:
!@
!F

Spekulativni ide pa ta stigne:


Opasno! Maina se zagui
ta ako ode u rekurziju?
Nema me|utim greke!
vitalni
Moemo podeliti
spekulativni
a njihovo stanje se moe menjati dinamiki
Mala granularnost - ne ii do lia nego nek jedan to uradi!
Blokiranje
Kad jedan pone ostali ne bi trebalo dok ovaj ne zavri i nestigne do WHNF.
Kada Razvija postavlja markere - ostali ne diraju
Ne treba blokirati WHNF
nikad nee biti promenjen
Kako je predstavljen Task?
pointerom na graf koji redukuje
ta sa blokiranim taskovima?
vratimo ga u pool (pa e ga opet startovati)
negde drugde, pa ga probudimo posle
u APP NODE moemo smestiti pointere na taskove koje treba probuditi,
Shared memory!
Stek lokalno (ili pointer reversal)
Interna reprezentacija:
brojevi, simboli, s-izrazi, primene
2x2 mogunosti
da: laki GL
1) Da li u elijama iste veliine
ne: vie memorije

33

"boxed": laka implementacija


2) Da li "boxed" ili "unboxed"
"unboxed": vie memorije
broj

cons

Dinamika dodela memorije?


Kontrola u naim rukama
Garbage collection:
Mark & Sweep (Scan)
Copying
Reference Counting
Procedure
dinamika memorija
neunitavanje prethodne strukture (kopiranje)
lenjo izraunavanje
funkcije (spoljanje promenjive)

34

symbol

istraivanje:
funkcionalnim
stilom reavanje
problema
("poznatih") i ta
nam donosi.

Funkcionalno
programiranje
Funkcionalni prog.
jezici

Konstrukcije jezika u
duhu funkcionalnog
programiranja (I/O)

Analize i optimizacije
sintaksna, semantika
zavisnost
striktnosti
"fold/unfold"
puteva
tipova
lambda raun

teorija
prevo|enje
optimizacije

teorijska podloga
(kombinatori, teorija
kategorija,...

Me|ujezik

SECD

Simulator

SK 6
spinless
tagless

stil, nain
programiranja koji
ima svoje principe i
zakonitosti
najpogodniji za
funkcionalno
programiranje

TIM
CAM

continuation
parallel

Prevodilac

Glasgow
London
Stirling
Birmingham
Chalmer (Se)
Yale
Wellington (NZ)

implementacija - strukture podataka


skupljanje otpadaka

Ko se jo u SRJ bavi time i ta mi radimo


[ta emoo priati: od sevga po malo, ali to manje iz knjige Peyton Jones-a: "The implementation
of functional programming languages".
Osnove funkcionalnog programiranja
Bitne karakteristike modernih funkcionalnih p.j.
raun - teorijska osnova veine f.p.j. i me|ujezika
Jednostavni me|ujezik zasnovan na -raunu
Izraunavanje -izraza SECD mainom - princip
Ma. jezik SECD maine, prevodilac me|ujezika, simulator.
Prevo|enje -izraza u kombinatore
proirenje do me|ujezika
Redukcija
"fold/unfold" transformacija
prevo|enje "pattern matching"-a u me|ujezik
prevo|enje ZF izraza u me|ujezik
35

struktura podataka za implementaciju


'heap' i 'garbage collector'
diskusija paralelne redukcije SK-grafa

Parser 1
( f g) x = f(gx)
parse = syntax lex read
read - uitava iz fajla u listu znakova.
Leksika analiza treba da prepozna brojeve, identifikatore i pojedinane znakove.
lex c:cs = lex cs | is WhiteSpace

= num_tok : lex rest_cs | digit c


where
num_tok = c: takewhile digit cs
rest_cs = dropwhile
digit cs
takewhile,dropwhile - ugradjeni
= var_tok : lex rest_cs
| letter c
where
var_tok = c: takewhile isIdChar cs
rest_cs = dropwhile
isIdChar cs
= [c] : lex cs
| otherwise
lex [] = [c]

Pretpostaviemo da je token lista znakova :Znai lex preslikava listu znakova


u listu listi znakova .
lex [1,2,3,a,b,c][ [1,2,3],[a,b,c] ]

Parser 2
isIdChar c = letter c || digit c || (c = )
is WhiteSpace = member " \ t \ n " c

Gramatika
pozdrav = pz osoba !
pz = Zdravo | Dovidjenja
osoba = id znak

Parser uzima listu listi (tokena) i vraa listu uredjenih parova.Prvi elemenat je ono to
je isparsirao , a drugi je ostatak.(Lista treba ako je to mogue isparsirati na vie naina).
plit uzima string i kao rezultat vraa parser koji prepoznaje taj string :
plit s [] = []
plit s (tok:toks) = [(s,toks)] | s=tok
= []
| otherwise
Primer :
plit Zdravo [ Zdravo, Pero, ! ] [(Zdravo,[Pero , !] )]

Parser 3
Slino (za identifikatore)
36

pVar (tok : toks) = [ (tok,toks)]


= []
pVar [] = []

| letter (hd tok)


| otherwise

pAlt uzima dva parsera i oba primenjuje na isti ulaz,a kao rezultat vraa sve mogue
rezultate (odgovara onome iz gramatike r = a | b)
pAlt p1 p2 toks = (p1 toks) ++ (p2 toks)
p ZiliD = (plit Zdravo ) pAlt (plit Dovidjenja )

pThen - sekvenca. Kombinuje dva parsera koji e dati trei koji radi sledee :
koristi prvo p1,pa p2 na ostatak ulazne liste. [ta je rezultat? Neka kombinacija
rezultata p1 i p2. Tu kombinaciju izraavamo funkcijom combine.
pThen combine p1 p2 toks =
= [(combine v1 v2,toks2) | (v1,toks1) p1 toks2,
(v2,toks2) p2 toks1]

combine - semantika akcija.


[ta treba da radimo kad prepoznamo ?

Parser 4
pPozdrav = pThen mkPair pZiliD pVar
where
mkPair a b = (a,b)
Primer
pPozdrav [ Zdravo, Pero, !] [((Zdravo,Pero), [!] )]

Finalna varijanta:
p = pThen keep pPozdrav (plit !)
where
keep a b = a
keep - odbacuje znak uzvika
pZeroOrMore p = (p OneorMore p) pAlt (pEmpty [])

(pEmpty uvek uspeva,vraa ono to dobije i nita ne uzima sa ulaza)

ZF izrazi
perms[] = [ [] ]
perms x = [a:y ax, yperms(x--[a])]
faktors n = [i i [1..n div2], n mod i = 0]
queens

[ [] ]

queens n
safe q b
checks q b i

= [ q:bq[0..7], bqueens (n1),safe q b ] n>0


= and [checks q b i | i [0..# b1 ]]
= q = (b!i) || abs(qb !i) = i+1
ide od nultog elementa

q- nema provere da li je u istoj koloni(zbog reprezentacije to nije mogue)

37

1 2 3 4
[3,1]

Nema backtracking-a !!
lenjo - ni jedno reenje se ne izraunava dok se ne zatrai.
ZF lenjo
fib = 1:1: [a+b (a,b)zip fib (tail fib)]
zip (x :xs) (y:ys) = (x,y) : zip xs ys
zip xs ys = []

Pamtimo samo efekat.


head(tail (tail(tail fib))) =
head (tail(tail (1:[a+b (a,b) zip fib (tail fib )])))=
head (tail [a+b (a,b)zip fib (tail fib)])=
(1,1) : zip
head (tail 2:[a+b (a,b) zip (tail fib) (tail (tail fib))] =
tail fib -- 1:2:[a+b) ]
tail fib - fib
= head [a+b (a,b) zip fib (tail fib)]=
= head 3:[a+b (a,b) zip fib" (tail fib" )] =
=3
fib" =2:3 [ .
]
fold f z [] = z
fold f z (x:xs) = f x (fold f z xs )
and = fold (&&) True
or = fold ( || ) False
sum = fold (+)
mul = fold () 1
reverse = fold postfix []
where postfix x | xs = xs ++ [x]
len = fold plus
where plus x n = 1+n
max = fold m
(prirodni)
where m x y = x,
x y
y,
otherwise

Vektor ( niz ) :
f : Index Value
Nula vektor f i =
Zbir dva vektora : vv Add f g = \ i ( f i ) + ( g i)
vvAdd f g i = ( f i ) + ( g i )
Negiranje :
v Neg f = \ i ( f i )
Primer f = \ i 1
g = \ i i+1
(vv Add f g 5) ili
(zbir = vv Add f g )
zbir 5
mm Add f g = \ i vv Add ( f i ) ( g i )
matrica : num num num
det matr n = matr 1 1
, n=1
altsum matr n 1
, otherwise
where

38

altsum matr

n k = 0, k>n
(matr 1 k ) ( minor matr n k ) (altsummatr n|k +1)
minor matr n j = det (det matr j )n1
det matr j = \ k l matr k+1 (if l> j then l else i+1 ))

taut f True , f = True


False , f = False
( taut ( f True )) &&
( taut ( f False )) , otherwise
fold f z [] = z
fold f z (x:xs) = f x (fold f z xs )
((( f x)y)z) = e

Elementi rauna
Lambda raun (nadalje raun) je nastao tridesetih godina ovog veka kao (jo) jedan od pokuaja da
se prona|e formalizam koji bi uspeno predstavio osnovu itave matematike .Ubrzo je postalo jasno da
raun nee moi ispuniti taj zadatak (kao ni mnogi drugi formalizmi i teorije pre i posle
njega).Poetkom ezdesetih godina se me|utim pokazalo da je raun dobra teorijska osnova za itavu
jednu klasu programskih jezika funkcionalne programske jezike.
Krajem pedesetih godina su se u programskom jeziku LISP pojavili neki termini iz rauna : na
primer lambda izraz za definisanje funkcije.LISP je me|utim bio autohtoni proizvod, koji je od
rauna iskoristio samo tehnologiju [McCartny,1978].Prvi jezik koji je zaista bio zasnovan na raunu
je bio ISWIM [Landin,1966]. Po reima Landin-a, ISWIM je predstavljao sintaksni eer (engl.
syntactic sugar) za raun jer je bez malo sintaksnog eera raun teko progutati.
Od ISWIM-a do dananjih dana, raun je ostao osnova najpoznatijih funkcionalnih
programskih jezika, ali se sintaksni eer stalno unapre|uje1.

1.1 termi
Pod raunom (engl.calculus) se podrazumeva:
skup termova i
skup pravila za konverziju (transformaciju) termova iz jednog oblika u drugi.
Termovi se grade od simbola iz unapred odre|enog skupa simbola na osnovu (sintaksnih) pravila za
gra|enje termova.
Primer. Jedan mogui raun je i sledei. Neka je skup simbola rauna :{(,),S}i neka se termi (na
primer: S-Termi) grade na sledei nain:
a) S je S-term,
b) ako su A i B S-termi, tada je i (AB) S-term,
c) S-termi se dobijaju samo primenom gornja dva pravila konano mnogo puta.
Neka u raunu postoji samo jedno pravilo konverzije:svaki pod-term oblika (((SA)B)C) se
transformie u term ((AB)(AC)),pri emu su A,B,C S-termi2.

Nisu svi funkcionalni programski jezici direktno zasnovani na raunu, ali su oni koji jesu najpoznatiji i najuticajniji.
Stoga e se ovaj tekst odnositi samo na implementaciju onih jezika koji jesu zasnovani na raunu.
2
S-term i opisano pravilo transformacije su ustvari deo kombinatorskog rauna koji ima tako|e veliki znaaj u
implementaciji funkcionalnih programskih jezika i koji e biti opisan u etvrtom poglavlju.

39

Normalnom formom rauna se naziva term na koji se ne moe primeniti nijedno pravilo
konverzije.Intuitivno,normalna forma se moe smatrati i rezultatom raunanja,odnosno vrednou
terma.
Za razliku od gornjeg primera , termi i pravila konverzije rauna su vrlo intuitivni.Intuitivno
tumaenje osobina rauna e u daljem tekstu biti navo|ena uz formalne definicije.
Definicija.Termi rauna ( termi, ponekad i izrazi) se grade od simbola iz skupa {,(,), .} i
unapred zadatog skupa identifikatora Id. Neka je za nae potrebe skup identifikatora Id sledei skup:
{a, b, , z}.
termi se grade na sledei nain:
a) x je term, ako x Id,
b) e1e2 je term, ako su e1 i e2 termi,
c) x.e je term, ako x Id i ako je e term,
d) (e) je term, ako je e term i
e) termi se dobijaju primenom gornjih pravila konaan broj puta.
term naveden u pravilu c) se esto naziva () apstrakcijom, dok se term naveden u pravilu b) esto
naziva primenom (ili apstrakcijom).
Intuitivno (u ta emo se uveriti u kasnijim primerima) apstrakcija odgovara definisanju
funkcije (u matematici ili programiranju) od jednog argumenta (x) sa telom e. Primena odgovara
primeni terma (funkcije) e1 na term e2.
Zbog jednostavnijeg zapisivanja termova, uvodimo dve konvencije:
termi oblika x1. x2. . xn.e se mogu zapisivati i kao x1x2 xn.e,
termi oblika ((e1e2)e3) se mogu zapisivati i kao e1e2e3 (tj. nadalje pretpostavljamo da je primena
levo-asocijativna)
raun je u stvari jedan od dva najpoznatija formalizma za opis rada sa funkcijama (definisanja
funkcija i njihove primene): drugi je predstavljanje funkcija kao skupova ure|enih parova. raun je
me|utim optiji: dozvoljava primenu funkcije na drugu funkciju i rekurzivne primene funkcija. Ni
jedno ni drugo nije mogue predstaviti uobiajenom predstavom funkcija kao skupom ure|enih parova
(zbog takozvanog Russel-ovog paradoksa).

1.2 Pravila konverzije


Da bismo opisali pravila konverzije termova, potrebno je uvesti pojam slobodnih identifikatora
(ponekad: slobodnih promenljivih) terma, a potom i zamene (supstitucije) svih slobodnih pojava
identifikatora, nekim drugim identifikatorom.
1.2.1 Slobodni identifikatori
Definicija. Identifikator x je slobodan u termu e, ako pripada skupu slobodnih identifikatora terma
e (u oznaci fv(e)).fv(e) je definisan na sledei nain:
a) fv(x)
= {x}
b) fv(e1e2)
= fv(e1) U fv(e2)
c) fv (x.e)
= fv(e) \ {x}
d) fv ( (x) )
= fv(e)

40

Intuitivna predstava slobodnih identifikatora je vrlo jednostavna: slobodni identifikatori su oni koji se
pojavljuju unutar tela apstrakcije, a ne pojavljuju se kao argumenti apstrakcije (tj. nisu
vezani lambdom). Pojam slobodnih identifikatora rauna je analogan pojmu globalnih
promenljivih funkcije nekog programskog jezika3.
Primer. U termu x.xz je identifikator z slobodan, dok identifikator x nije. U termu
xyz.abc identifikatori a, b i c su slobodni.
1.2.2 Pravila supstitucije
Supstitucija (zamena) svih slobodnih pojava identifikatora x termom e1 u izrazu e2 se oznaava
[e1/e2]e2 (ili: e1 stavljamo umesto svih slobodnih pojava identifikatora x u termu e2).

Supstitucija [e1/x]e2 je definisana na sledei nain:

a)
[e / x i ]x j = {

e , ako i=j
xj , ako i j

Primer. [y/x]x = y. Me|utim [y/x]z = z.


Intuitivno, ako je identifikator ije slobodne pojave elimo da zamenimo jednak izrazu u kojem elimo
da izvrimo zamenu, zamena se vri. Inae originalan izraz (identifikator) ostaje neizmenjen.
b) [e1/x](e2e3) = ([e1/x]e2) ([e1/x]e3)
Intuitivno, u sluaju aplikacije, supstitucija se vri u oba terma.
xj.e2, ako i=j
c) [e1/xi]( xj.e2) =
xj.[e1/xi]e2, ako ij i xjfv(e1)
xk.[e1/xj]([xk/xj]e2), inae,ki,kj,xkfv(e1) fv(e2)
Smisao pravila c) je da sprei konflikt identifikatora tokom supstitucije. Ne sme se dozvoliti da se neki
slobodni identifikator zameni sa identifikatorom koji je u termu vezan. Tako rezultujui term posle
supstitucije ne bi bio ekvivalentan poetnom termu ( bar po intuitivnom shvatanju apstrakcije).
Primer. U sluaju supstitucije [x/y]x.xy, rezultujui term bi bio (x.xx), ako bi se "sudaranje"
identifikatora dozvolilo. Po treem sluaju pravila c), medjutim, rezultujui term bi bio ( na
primer ) sledei : (z.zx) (posle preimenovanja identifikatora x u z).
Prva dva sluaja pravila c) ne zahtevaju preimenovanje identifikatora.
Primer. U sluaju supstitucije [x/y]x.x, rezultujui term je x.x (po prvom sluaju pravila c).
Supstitucija [z/y]x.x e dati rezultujui term x.xz (po drugom sluaju pravila c) ).
d) [e/ ](e) = ([e1/x]e)
Pravilo d) slui da se supstitucijom samo u|e ispod zagrada terma.
Primer. U sledeoj supstituciji su ilustrovana sva gore navedena pravila supstitucije.
[y/x]((y.x)( x.x)x) = (po dvostruko primenjenom pravilu b )
([y/x](y.x)) ([y/x](x.x)) ([y/x]x) = (po pravilu a )

Kao to je ve reeno, slobodne promenljive u rauna (odnosno funkcionalnih programskih jezika) mogu biti uzrok
neefikasnosti funkcionalnih programa.

41

[y/x]((y.x)( x.x)x) = (po dvostruko primenjenom pravilu b)


([y/x](y.x)) ([y/x](x.x)) ([y/x]x) = (po pravilu a)
([y/x](y.x)) ([y/x](x.x))y = ( po prvom sluaju pravila c)
([y/x](y.x) (x.x) y = (po treem sluaju pravila c)
(z.[y/x]([z/y]x)) (x.x) y = (po pravilu a)
(z.[y/x]x) (x.x) y = (po pravilu a)
(z.y) (x.x )y

1.2.3 Konverzije
Znajui pojmove slobodnih identifikatora i supstitucije , spremni smo da definiemo i pravila
transformacije termova, ime dovravamo definiciju rauna.
Definicija. Pravila za konverziju rauna su sledea :
- konverzija :
- konverzija :
- konverzija :

x.e
(x.e1 )e2
x.(ex)

y.[y/x]e, pri emu y fv(e)


[e2/x] e 1
e, ako x fv(e)

- konverzija se esto zove i preimenovanje (engl. renaming).-konverzija ima svoje intuitivno


opravdanje: ako identifikator x posmatramo kao formalni parametar, onda nije vano njegovo ime,
nego uloga "uvara mesta " za stvarni argument prilikom primene funkcije.
- konverzija (ili primena, aplikacija) odgovara intuitivnoj predstavi primene f-je na stvarni argument
(odnosno poziva f-je sa stvarnim argumentom ). Po (eta)-redukciji (i intuiciji), f-je (recimo u
matematici ili programskom jeziku) f i e su iste ako za svako x vai f(x)=e(x).
Pravila za konverziju terma vae u oba smera. Uobiajeno je da se primena konverzije s leva
udesno naziva redukcijom (jer se poetni term uproava), a da se primena konverzije s desna ulevo
naziva apstrakcijom (jer se term uoptava ). Izuzetak od ovog dogovora je - konverzija tokom koje se
term po svojoj sloenosti ne menja.
Usvajamo i sledee oznake:
ako se term e2 moe izvesti od terma e1 primenom 0 ili vie konverzija, - redukcija ili -redukcija. Slino, oznakom e1 e2 emo oznaavati ako se term e2 moe
izvesti od terma e1 primenom 0 ili vie - konverzija, - redukcija ili -redukcija i ako se term e1
moe izvesti od terma e2 primenom 0 ili vie - konverzija, - konverzija, ili -konverzija. Redukcija
termova e u daljem tekstu imati vei znaaj od apstrakcije.
Ukoliko se u termu nalazi vie od jednog reducibilnog (pod)terma (tj.(pod)terma koji se moe
redukovati), u principu se moe odabrati bilo koji od podtermova za redukciju. Me|utim mogue je i
tokom redukcije terma usvojiti i stalno primenjivati jednu strategiju.
Definicija. Redukcijom normalnog redosleda (ili normalnom redukcijom, engl. normal order
reduction ) se naziva strategija u kojoj se za redukovanje uvek bira najlevlji najspoljanjiji reducibilni
podterm (engl. leftmost outermost redex).
Redukcijom aplikativnog redosleda (ili aplikativnom redukcijom, engl. application-order
reduction) se naziva strategija u kojoj se za redukovanje uvek bira najlevlji najunutranjiji reducibilni
podterm (engl. leftmost innermost redex).
Definicija. Najlevljim podtermom terma se naziva podterm levo od koga se ne nalazi ni jedan
podterm. Najspoljanjijim podtermom se naziva podterm koji nije sadran ni u jednom
podtermu. Najunutranjijim podtermom se naziva podterm u kome nije sadran ni jedan
podterm.

42

Pri normalnoj redukciji se od svih najspoljanjijih reducibilnih podtermova za redukciju prvo bira
najlevlji. Pri aplikativnoj redukciji se od svih najunutranjijih reducibilnih podtermova za redukciju
prvo bira najlevlji.
Primer. U termu (x.y) (( x.x)z) je najunutranjiji podterm (x.x)z, dok je najspoljanjiji
reducibilni term itav polazni term. Normalnom redukcijom se term redukuje na sledei nain:
(x.y)(( x.x)z) y

(1)

dok se aplikativnom redukcijom term redukuje na sledei nain:


(x.y)(( x.x)z) y
1.3 Normalna forma
term koji se ne moe primeniti ni jedno pravilo redukcije se naziva normalnom formom. Kao to je
ve reeno, intuitivno normalnu formu moemo posmatrati kao "rezultat raunanja" raunom,
odnosno kao "vrednost" terma.
Primer. U prethodnom primeru je normalna forma terma (1) term y. Postoje me|utim i
termovi koji nemaju normalnu formu. Klasian primer je term (x.(xx))( x.(xx)), ija je
redukcija sledea :
(x.(xx))(x.xx)) (x.(xx))(x.(xx)) ...(x.(xx))(x.(xx))
Da bi raun bio korisna teorija sa perspektivom automatske (mainske) primene pravila redukovanja,
potrebno je odgovoriti na sledea pitanja:
Da li je normalna forma jedinstvena ?
Da li postoji rutinski nain da se bilo koji term redukuje do normalne forme (ukoliko normalna
forma postoji)?
Pozitivne odgovore na oba pitanja daju dve Church-Rosser-ove teoreme.

43

FAC fak.n.IF(=n 1 )1(*n (fak (- n 1)))


Y FAC2
Y FAC 2 -> FAC (YFAC)2
( fak. n.IF ( = n 1 ) 1 ( * n fak ( - n 1 )))(Y FAC)2
( n.IF ( - n 0 ) 1 ( * n (( Y FAC )( - n 1 )))2
IF ( = 2 0 ) 1 ( * n ((Y FAC)( - 2 1 ))
(* 2((Y FAC)1))
(* 2(FAC(Y FAC)1)
(* 2( FAC.n.IF( = n 1 ) 1 ( * n (FAC( - n 1 ))))(Y FAC) 1)
(* 2(n.IF( = n 1 ) 1 ( * n (FAC( - n 1 ))))-1)
(* 2)(IF( = 1 1 ) 1 ( * n (FAC( - n 1))))-1)
(* 2 1) 2
Kako predstaviti izraze ? Grafovima DAG (dok ne do|e rekurzija)
- konstante - vorovi grafa
- primena xy

- lambda apstrakcija x.y

- Curry-rana verzija

Primer: x.y.+x(*yy)

Implementacija lenjog izraunavanja


(x.AND x x) ( NOT TRUE)
- normal order reduction
AND (NOT TRUE) (NOT TRUE)

nije jo izraunato
Kako implementirati Normal Order Reduction ?
44

Kako spreiti viestruko izraunavanje ?


LazyEvalution - najvie jedan izraunava ( argument funkcije ) ?
- 1971 - predloio graf. redkukciju Wadsworth
- Zato ne pre ? - Neprimereno klasinim raunarskim arhitekturama
Bio CALL-BY-NEED

- Kopiranje

- Kako primitivne funkcije !

Ispostavlja se da je bitno voditi rauna o sledeim stvarima


- Ne kopirati nego premetati pointere !
- Rezultat redukovanja "prepisati" preko originalnog izraza
- Kopirati -apstrakcija (ostaviti original)

45

Koje izraunavanje :
- NOR
- Pointeri
- Zamena originalnog vora rezultatom
Problem : kopiranje je naporno, teko i sporo !
Konaan rezultat - NEEFIKASNOST
Od 1971-1976 (objavljeno 1979)
Kombinatori ( Schonfinjel, Carry & Fey's 1958 )
Kombinatori zatvornei lambda izrazi (bez slobodnoih promenljivih)
(x.x) = I identitet Ia a
(x.y.x) = K kancelerator Kab a
(x.y.z.xz(yz)) = S Sabc ac(bc)
Proizvoljan izraz se moe predstaviti odgovarajuom kombinacijom S i K kombinatora.
Ia = SKKa = Ka(Ka) = a
Kako transformisati izraz u SK i I kombinatore ?
C[x.x] I
C[x.c] c x Kc
C[x.AB] S(x.A)(x.B)
(x.AB)cA[xc]B[xc]
S(x.A)(x.B)c(x.A)c((x.B)c)
C[x]x , x je promenljiva ili konstanta
C[(x)] = (C[x]) C[x.y.E]=C[x.C[y.E]]
Prevodimo primer:
C[(x.+x1)]S[x.+x][x.1]S(S[x.+][x.x])[x.1] S(S(K+)I)(K1)
Nema lokalnih promenljivih!
Radi li ?
S(S(K+)I)(K1)5S(K+)I5((K1)5)K+5(I5)(K15) +(I5)(K15)+5(K15)+51
Optimizacija :
Zato. Iako nema parametara (pa ni potrebe za njihovim zamenjivanjem) SKI termovi su predugaki.
Uoavamo karakteristine pod termove :
(S(Kp)I)a (Kpa)(Ia)pa
1. (S(Kp)I) = p optimizacija
S(Kp)(Kq)a(Kpa)Kqa)pq
2. S(Kp)(Kq) = K(pq) optimizacija
C[x.y.+xy]=C[x.C[y.+xy]] = ....
S(S(KS)(S(S(KS)(S(KK)(K+)))(S(KK)I)))(KI)
46

3. (S(Kp)q) ( samo ako 1 i 2 nisu primenljivi ) =


(S(Kp)q)a (Kpa)(qa)p(qa)
Uvodimo novi ! (jer je a ostao zarobljen, pa ga ne moemo "skratiti")
Bpqa p(qa) - redukcija
S(Kp)q Bpq - optimizacija (kompozitor)
Isto samo ako 1 i 2 nisu primenljivi !
4. Sp(Kq)apa(Kq)paq
Sp(Kq) = Cpq - optimizacija (permutator)
Cpqapaq - redukcija
Optimizacije se mogu primeniti na kraju, ali je efikasnije primeniti ih to pre, da smanjimo "troak"
(memoriju,vreme). ^im se pojavi oblik Sab, probamo da ga optimizujemo :
Kako to radi ?
prethodni primer : S(S(K+)I)(K1)S+(K1)C+1
Redukcija: (C+1)5+516
Prevodjenje (x.y.+xy) uz optimizaciju.
([ta se oekuje kao rezultat ?)
[x.[y.+xy]]=[x.(S[y.+x][y.y] )]=[x.(S(S[y.+][y.x])[y.y])]=
S(K+)(Kx)
K(+x)
= [x.(S(K(+x))I)]=[x.+x]=S[x.+][x.x]=S(K+)I=+
1. Optimizacija uvodi "potpunu.lenjost", to znai da se ni jedno izraunavanje(a ne samo
izraunavanje argumenata).
Unapre|enje prevo|ena:
C[x.E] E ne sadrzi x-ova = KE
[x.AB] = S[x.A][x.B]=S(KA)(KB)=K(AB)
E moe biti konstanta, promenljiva ili aplikacija. Ako je aplikacija, tada....
Dalje: E ne sadri X-ove
C[x.Ex]=S[x.E][x.x]=S(KE)I=E
C[x.Ex]=S[x.E][x.X]=S(KE)[x.X]=BE[x.X]E
C[x.E]=KE, x nije u E
C[x.x]=I
C[x.Ex]=E
C[x.EX](xX)=BE[x.X]
C[x.XE](xX)=C[x.X]E
C[x.XY](xX,Y)=S[x.X][x.Y]
Potpuna lenjost 1-ve optimizacije.
Poredimo: S(Kp)(Kq)xKpx(Kqx)p(Kqx)pq - novo kreirano (sa optimizacijom je isto)

47

Jo jedna optimizacija
Cpp, ako je p komutativni operator
Uvedimo jo neke optimizacije:
XnXn-1.... X2 X1.pq =
[Xn.[Xn-1....[X2.[X1.pq]....]]=
[Xn.[Xn-1....[X2.p1q1]....]]= (velicina 3)
S[X2.Sp1][x X2q1]
S(BS p2)q2
(velicina "duzina" 5)
2 2
[X3.S(BSp )q ]
S[X3.S(BSp2)]q3
S(BS[X3.BSp2] )q3
S(BS(B(BS)p3)q3
(duzina 8)
.......
S(BS(B(BS)(B(B(BS))p4))))q4(12)
[ta se deava u stvari i kako to moemo popraviti
[x.Epq] = S(BE p1)q1
Prave se dva kombinatora,od kojih je jedan ugnjeden.
Uvodimo optimizaciju (Turner)
S(Bxy)z S'xyz
Tada bi postojalo jednostavnije prevo|enje
[x.Epq]=S'E p1q1
Pravilo redukcije :
S'abcx = S(Bab)cx = (Babx)(cx)=a(bx)(cx)
S' je kao i S,sa "extra" prvim argumentom.
Kad se S' optimizacija primeni, tada se promenljive x1..xn redom iz izraza p i q apstrakuju kao
Spq
S'S p2q2
S'(S'S) p3q3
S'(S'(S'S)) p4q4
Broj kombinatora sada linearno raste sa brojem apstrakovanih promenljivih.
Broj S' je "produenje" kombinatora S, pravimo i odgovarajua produenja za B i C.
B'abcxab(cx)
C'abcxa(bx)c
Sa optimizacionim pravilima:
B(ab)c B'abc
C(Bab)cC'abc
(kako se pokazuje korektnost gornjih pravila)
48

B' je iznena|enje, jer nita ne radi bitno !


Pokazuje se da B' ak "kvari" posao drugim optimizacijama jer unitava B kombinator :
C(B(ab)c)dC(B'abc)dC'(ab)cd
Sheevel (1986) uv odi B*
B*abcd a(b(cd))
sa optimizacionim pravilom
Ba(Bbc) B*abc
Jos me|utim nije jasno koji je i kada bolji.
I ove optimizacije se na prikazani nain mogu spustiti u originalni algoritam , na opisani nain.Ovde
navodimo algoritam Kennaway-a (1984):
(E,F,G ne sadre x,X,Y.Z sadre x proiren sa B*)
[x.x] = I
[x.E] = KE
* [x.(Ex)X] = SE[x.X]
* [x.(Ex)F] = SEF
[x.(EX)Y] = SE[x.X][x.Y]
[x.E(FX)] = B*EF[x.X]
[x.(EX)F] = CE[x.X]F
* [x.(Ex)] = E
[x.XY] = S[x.X][x.Y]
[x.EX] = BE[x.X]
[x.XE] = C[x.X]E

S[x.Ex]

Zato su pravila sa * prisutna?


da nisu:
[x.ExX] = SEI[x.X]a
= Ea([x.X])a
= (Ea)([x.X].a)

isto kao i:
SE[x.X]a = (Ea)[x.X]a

Moe i bez njih,ali se pravila za S,B* i C "gardiraju" uslovom x <> X ,pa se onda dobija isti
prevod,ali u dva cuga.Tu je kraj.Preveli smo.
Vraamo se na redukciju:
Podseamo: primena:

konstante:vorovi grafa

lambda apstrakcije nema : predstavljamo sada redukcije na grafovima koje smo


opisali
@ $
x $
I

49

@$
x $
@

@ $

@ $
novi!

@
@

z
y

@
s

z
@ $

@ $
novi!

@
@

z
y

@
B

@
x

z
@ $
@
@
C

@
z

@
C

@
x

Slino za S',B*,C'.
50

@ $
z
y

ugra|ena funkcija:
@ $

zbir
$

Rekurzija:
Umesto realizacije Y kombinatora lambda izrazom,uvodimo ga kao ugra|eni kombinator.
(kao opti nain realizacije rekurzije)
@
y

@
x

ili
@
y

@
x

@
y

Redukcija:
@
@
@
.
.
.

.
.
.
k

.
.
.

51

-Poevi od vrha steka, sledimo levu granu sve dok ne nai|emo na vor koji nije vor primene
("unwinding the spine"). Usput u stek stavljamo adrese vorova...Stek je tu zbog efikasnosti. Ako je
kombinator, primenimo odgovarajuu
-Ako je ugra|ena funkcija, rekurzivno pozvati evaluator za one argumente koje je potrebno izraunati.
Ponavljati "razvijanje"sve dok ima ta da se redukuje, odnosno sve dok ne do|emo u tzv. WHNF.
Zasad kaemo da su WHNF: konstante
primene funkcija bez dovoljno argumenata
(posle emo proiriti spisak)
-Rekurzivni poziv moe koristiti isti stek
indirection nodes:
-problem sa selekcijom
-"indirection nodes"
-bolje prvo redukovati,pa kopirati
Pa tako umesto R[kxy] = x
R[kxy] = R[x]
Kraj lambda rauna:
Kako prevodimo ostalo iz naeg jezika?
Podsetimo se:(lambda(x1...xn)e) "apstrahovanjem" promenjivih x1,...,xn iz izraza e -primitivne funkcije
u odgovarajue kombinatore
(add x y) -> add x y
(koji e se opet redukovati po unapred utvr|enim pravilima)
-(let blok)
(let e (x1.e1)...(xn.en))
-dve mogunosti:zameniti unutar e sve x1,...,xn sa e1,...,en pa onda prevesti e
-ili
let x1 = e1,...,xn = en in e
(lx1. ...lxn.e)e1...en
-letrec blok
(letrec e (x1.e1)...(xn.en))
Ako (letrec e (x1.e1)) tada
let(rec) x1=e1 in e = [x1.e](Y[x1.e1])
Ostali sluajevi se rade svo|enjem na opisani sluaj, tako to smetamo identifikatore i izraze u listu:
letrec (x1,...xn) = (e1,...en) in e
[<x1,...,xn>.e] (Y[<x1,...,xn>]<e1,...,en>)
Jo samo odgovor na pitanje: Kako apstrahovati listu identifikatora iz izraza? Uvo|enjem kombinatora
U:
Ufx -> f(hd x) (tail x)
i pravila prevo|enja:
[<x1,...,xn>.e] = U[x1.[<x2,...,xn>.e]]
[<>e] = Ke
Primer:
[<x,y>.+ xy] =
U[x.[<y>.+xy]] =
U[x.U[y.[<>.+xy]]] =
U[x.U[y.K+xy]]] =...
(a.b) -> CONS a b
i dodajemo u spisak WHNF jo i term CONS a b
-To e nam omoguiti da "rukujemo" beskonanim strukturama podataka
52

Pretpostavimo postojanje ovakvog izraza u me|ujeziku


case v of
kons1 x11...x1k -> e1
.
.
Svi sluajevi su ovde !
.
konsn xn1... xnk -> en
ija je vrednost izraz ei,ako je v tipa konsi, pri kome se imena xi1 ... xik unutar ei zamenjuju ...
primer:
case t of
Nil t -> nesto
Node x y z ->...x y z
f a [] y = []
f a (x:xs) [] = []
f a (x:xs)(y:ys) = ...a,x,xs,y,ys...
f = a.xx.yy.
case xx of
Nil ->Nil
CONS x xs -> case yy of
Nil ->Nil
CONS y ys ->...a x xs y ys...
f [] = []
f [x] = [x]
f(x:y:xs) = ...x,y,xs

f =xx.
case xx of
Nil ->Nil
CONS x' xs' ->case xs' of
Nil - > CONS x' Nil
CONS x xs ->...x',x,xs,xs'
-------------------------Funkcijom M (ali na primeru) za
f p11...p1n = e1
.
.
.
.
.
.
f pm1...pmn = em

[u1,...,un]
p11,...,p1n ; e1
pm1,...,pmn ; em
E

ui su nove promenjive, E je defaut izraz


------------------------demo f [] ys = A f ys
demo f (x:xs) [] = b f x xs
demo f (x:xs)(y:ys) = C f x xs y ys
53

Poinjemo
[u1,u2,u3] Unutra bi trebalo da stoje
prevodi !
demo = u1.u2.u3

f [] ys
; A f ys
f (x:xs) []
; B f x xs
f (x:xs) (y:ys) ; C f x xs y ys
panic

1.Variable rule
[u2,u3]
M []
ys
(x:xs) []
(x:xs) (y:ys)

; A u1 ys
; B u1 x xs
; C u1 x xs y ys

panic!
Nije bitno kako se promenjive zovu, bitno da su promenjive!
2. Constructor rule
Prearaniramo da su svi konstruktori istog tipa jedan do drugog.To smemo! Potom uvodimo case
case u2 of
Nil ->

[u3]
M ys ; A u1 ys
panic!
[u4,u5,u3]
M x,xs,[]
; B u1 x xs ;
x,xs,(y:ys)
; C u1 x xs y ys

CONS u4 u5 ->

panic!
.

3. Empty rule:
[]
M

; A u1 u3

-> a u1 u3

panic!
________________
M [] [] e

-> e

4. Mixture rule:
demo []
ys
xs
[]
(x:xs) (y:ys)
[ u1,u2]
M

[]

ys ; ... )

M [u1,u2]
54

xs [] ; ...
M [u1,u2]
(x:xs) (y:ys) : ...
panic!
Neki specijalni sluajevi:
[]
(x:(y:z))

-> ...
-> ...

[u1]
M [] ; ...
(x:(y:z)) ; ...
panic!
case u1 of
NIL -> M ...
[u2, u3]
cons u2 u3 -> M

X (y:z) -> ...


panic!
.
.
.
[u3]

M y:z -> ...


panic!
.
.
.
->

case u3 of
NIL -> M [] [] panic!
cons ... ->

Translacija ZF izraza
55

ZF izraz: [e|q] ; e je izraz, a q je sekvenca od 0 i vie kvalifikatora


Kvalifikator je generator
l lista
[e|v <- l ; Q']
ili "filter"
[e|B ; Q']
ili prazan
[e| ]
Primer:
[x y x| x <- [1..3] ; add x] -> [1, 9]
Objasniti (neformalno) kako radi.
Formalnije:
1. [e| v <- [] ; Q] -> []
2. [E| v <- [e':L';Q]] -> [E|Q] [E'/v] ++ [E| v <- L' ; Q]
3. [E| False;Q] -> []
4. [e| True;Q] -> [e|Q]
5. [e| ]
-> [e]
Pravila 1 i 2 definiu pravila za generatore, 3 i 4 za filtere i 5 za prolaznu listu.
Razvijeno pravilo 2 glasi:
[e| v <- [e1, ..., en];Q] -> [e|Q] [e1/v]++...++[e|Q] [en/v]
Primer:
[x * x | x <- [1, 2, 3] ; add x] ->
-> [1*1 | add 1]++[2*2 | add 2]++[3*3 | add 3] (1 i 2)
-> [1*1 | True]++[2*2 | False]++[3*3 | True] (add ...)
-> [1*1 | ]++[]++[3*3 | ] (3 i 4)
-> [1*1]++[]++[3*3] -> (5)
-> [1, 9]
Bilo je to vredno izraunavanje. Lenjo bi ilo ovako:
[x*x | x <- [1, 2, 3] ; add x]
-> [1*1 | add 1]++[x*x | x <- [2, 3] ; add x] (2)
-> [1*1 | ] ++
-||(4)
-> [1*1] ++
-||(5)
-> 1:
-||Kako prevesti u me|ujezik? - Slino. Uvodimo funkciju fMap.
fMap f [] = []
fMap f (x:xs) = (fx)++(fMap f xs)
^vraa listu kao rezultat !
fMap primenjuje f na svaki element liste xs (to nam daje liste kao rezultate) te ih potom sve apenduje.
56

Prevodimo:
a) C[ [e | v <-l ; Q] ] = fMap (v. C[ [e|Q] ] ) C[L]
b) C[ [e | B ; Q] ] = IF C[ B ] C[ [e | Q] ] NIL
c) C[ [e | ] ] = CONS C[e] NIL
Pravilo a) realizuje 1 i 2 pravilo ponaanja ZF izraza, pravilo 6, 3 i 4 pravilo ponaanja, a c 5. pravilo
ponasanja.
Da bismo bolje shvatili pravilo a), treba da se podsetimo da se [e/x]a , moe se realizovati kao (x.a)e.
Primer:
C[ [x*x| x<-[1, 2, 3] ; add x] ]
fMap (x . C[ [x*x | add x] ]) [1, 2, 3]
(a)
fMap( x . IF (add x) C[ [x*x | ] ] NIL ) [1, 2, 3] (b)
fMap( x . IF (add x) (CONS (mul x x) NIL) NIL) [1, 2, 3] (c)
______________________________________________________________________
Kad bi ovo poelo da se izvrava, ta bi se desilo?
[1]++[]++[9]
Moe dalje, ali odustajemo. Ostatak spada u transformacije programa.
Wadler, 1987,

57

You might also like