Esittely latautuu. Ole hyvä ja odota

Esittely latautuu. Ole hyvä ja odota

Jatkeet TIES341 Funktio-ohjelmointi 2 Kevät 2006.

Samankaltaiset esitykset


Esitys aiheesta: "Jatkeet TIES341 Funktio-ohjelmointi 2 Kevät 2006."— Esityksen transkriptio:

1 Jatkeet TIES341 Funktio-ohjelmointi 2 Kevät 2006

2 Havainto: häntäkutsu (1) ● Funktiokutsun yleinen toimintaperiaate: – (koskee vain “täysiä kutsuja”, ts. jotka eivät palauta funktiota) – kutsuja kirjaa pinoon paluuosoitteen – kutsuja kirjaa pinoon parametrit – kutsuja hyppää kutsuttavaan – kutsuttava tekee työnsä – kutsuttava poistaa parametrit pinosta – kutsuttava laittaa pinoon paluuarvon – kutsuttava katsoo pinosta paluuosoitteen ja hyppää siihen

3 Havainto: häntäkutsu (2) ● Tapauksessa f x = g (x+1) – f:n kutsuja laittaa paluuosoitteen pinoon – f:n kutsuja laittaa argumentin pinoon – f:n kutsuja hyppää f:ään – f laittaa oman paluuosoitteensa pinoon – f laskee x+1 ja laittaa tuloksen pinoon – f hyppää g:hen –... g tekee mitä tekee, jättää pinoon f:n paluuosoitteen ja tuloksen... – f poistaa tuloksen pinosta – f poistaa paluuosoitteensa pinosta – f poistaa x:n pinosta – f palauttaa tuloksen pinoon – f hyppää kutsujansa paluuosoitteeseen

4 Havainto: Häntäkutsu (3) ● f tekee turhaa työtä! – f voisi korvata x:n x+1:llä ja hypätä suoraan g:hen – g palatessaan antaa f:n kutsujalle suoraan sen paluuarvon, minkä f olisi välittänyt ● tätä temppua sanotaan häntäkutsun poistoksi ● hyödyt: – rekursiivinen häntäkutsu (ns. häntärekursio) vaatii vain vakiomäärän pinoa, ei tavallisen rekursion vaatimaa lineaarista määrää – vähentää turhaa työtä ● haittana lähinnä debuggausinformaation häviäminen

5 Häntäkutsun määritelmä ● Kutsu on häntäkutsu, jos – kutsuva funktio ei tee mitään muuta kutsun päätyttyä kuin palaa omaan kutsujaansa ● olennaisesti – f... = g... ● g:n kutsu on häntäkutsu – f... = g (h...) ● g:n kutsu on häntäkutsu ● h:n kutsu ei ole häntäkutsu – f... = if... then g... else... ● g:n kutsu on häntäkutsu – jne ● Poistettu häntäkutsu on olennaisesti parametreja välittävä goto

6 Häntäkutsun tärkeys ● Jokainen oikea funktiokieli poistaa kaikki häntäkutsut ● Mahdollistaa monet funktio-ohjelmoinnin idiomit: – silmukoiden koodaaminen (häntä)rekursiona – äärellisten automaattien idiomi: ● kukin tila on funktio ● tilasiirtymä on häntäkutsu

7 Muunnos häntäkutsuksi, osa 1: akkumulaattoriparametri (1) ● Ykköskurssilla käytettiin välillä akkumulaattoriparametrin ideaa – Suht. yleiskäyttöinen malli, jolla funktiokutsun saa muutettua häntäkutsuksi f x | p x = r | otherwise = g x (f (h x)) ==> f x = f' r x where f' a x | p x = a | otherwise = f' (g x a) (h x)

8 Muunnos häntäkutsuksi, osa 1: akkumulaattoriparametri (2) length [] = 0 length (x:xs) = 1 + length xs ==> length xs = f 0 xs where f a [] = a f a (x:xs) = f (1 + a) xs map f [] = [] map f (x:xs) = f x : xs ==> map' f xs = g [] xs where g a [] = a g a (x:xs) = g (f x : a) xs

9 Muunnos häntäkutsuksi, osa 1: akkumulaattoriparametri (3) ● Tämä muunnos ei aina säilytä käyttäytymistä – x:t tulevat g:lle eri järjestyksessä – ei vaikutusta length-esimerkissä – map-esimerkissä tuloslista on käänteinen ● pitäisi oikeastaan laittaa reverse g:n kutsun ympärille ● huom! reverse saadaan id :: [a] -> [a] -funktiosta tällä muunnoksella :) ● Muunnos ei ole aina hyödyllinen – tilaa säästyy vain jos paluuarvon asymptoottinen tilavaativuus on sublineaarinen rekursion syvyyteen nähden – laiskan laskennan vallitessa muutos on joskus vahingollinen ● map toimii äärettömillä listoilla, map' ei

10 Muunnos häntäkutsuksi, osa 2: Jatkeenvälitys (1) ● jatkeenvälitys on englanniksi continuation-passing style, CPS g :: C -> B h :: A -> C f :: A -> B f x = g (h x) ==> g' :: C -> (B -> R) -> R h' :: A -> (C -> R) -> R f' :: A -> (B -> R) -> R f' x c = h' x $ \hx -> g' hx c

11 Muunnos häntäkutsuksi, osa 2: Jatkeenvälitys (2) ● Idea: – funktiolle annetaan parametrina “jatke”: ● funktio, joka, kun sitä kutsutaan, tekee sen, mitä alkuperäisen funktion “palattua” pitää tehdä – korvataan arvon palauttaminen funktiokutsulla ● “paluuarvo” annetaan tuolle funktiolle parametriksi ==> jokainen kutsu on häntäkutsu ● Ei ole optimointimuunnos kuten akku ● Käytetään erilaisissa kirjastoissa – mm. Haskellin I/O ennen monadiaikaa ● Jotkut (funktiokielten) kääntäjät perustuvat tähän – ks. Andrew Appel: Compiling with continuations, Cambridge University Press, 1992

12 Call/cc (1) ● Jotkin kääntäjät tekevät ensi töikseen koko ohjelmalle CPS- muunnoksen ● Tästä syntyi idea: annetaan tämä “implisiittinen” jatke ohjelmoijalle käyttöön ● call-with-current-continuation eli call/cc: – callCC :: ((a -> a) -> a) -> a – callCC (\c ->...) suorittaa “...”:n siten, että c:hen sidotaan funktio, jonka kutsuminen aiheuttaa goton callCC:n kutsujaan siten, että callCC näyttäisi palauttaneen c:lle annetun parametrin ● Ei löydy Haskellista – ei hyödyllinen laiskan laskennan kanssa ja sivuvaikutusten puuttuessa

13 Call/cc (2) ● call/cc on erittäin voimakas kontrollirakenne ● call/cc:llä voidaan toteuttaa – poikkeusjärjestelmä – korutiinit – ohjelmoijan sekoaminen – ym ym ym


Lataa ppt "Jatkeet TIES341 Funktio-ohjelmointi 2 Kevät 2006."

Samankaltaiset esitykset


Iklan oleh Google