Programmeringsmetodik DV1 Programkonstruktion 1. Moment 9 Om högre ordningens funktioner. PK1&PM1 HT-06 moment 9 Sida 1 Uppdaterad

Relevanta dokument
Programkonstruktion och datastrukturer. Moment 9 Om högre ordningens funktioner. PKD 2010/11 moment 9 Sida 1 Uppdaterad

Programkonstruktion och datastrukturer. Moment 9 Om högre ordningens funktioner. PKD 2011/12 moment 9 Sida 1 Uppdaterad

Programmeringsmetodik DV1 Programkonstruktion 1. Moment 8 Om abstrakta datatyper och binära sökträd

Tabeller. Programkonstruktion. Moment 8 Om abstrakta datatyper och binära sökträd. Implementering av tabellen. Operationer på tabellen

Tabeller. Programkonstruktion. Moment 8 Om abstrakta datatyper och binära sökträd. Specifikationer för tabellfunktionerna. Operationer på tabellen

Programkonstruktion. Tentamen,

Programkonstruktion. Tentamen,

Programmeringsmetodik DV1 Programkonstruktion 1. Moment 4 Om rekursion. PK1&PM1 HT-06 moment 4 Sida 1 Uppdaterad

Programkonstruktion och datastrukturer. Moment 5 Om generella datastrukturer och träd. PKD 2011/12 moment 5 Sida 1 Uppdaterad

Omtentamen (del 1, 6 högskolepoäng) i Programkonstruktion och datastrukturer (1DL201)

Programkonstruktion och datastrukturer. Moment 6 Om generella datastrukturer och träd. PKD 2012/13 moment 6 Sida 1 Uppdaterad

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson 2

Dagens föreläsning Programmering i Lisp Fö 5

Två fall: q Tom sekvens: () q Sekvens av element: (a b c) ; (sum-rec '(2 4 6)) = 12. q Första elementet uppfyller vissa villkor: (2 a b c)

Programkonstruktion. Tentamen,

F6: Högre ordningens funktioner. Mönster för rekursion (1) Mönster för rekursion (1b) Mönster för rekursion (2) Högre Ordningens Funktioner

Programmeringsmetodik DV1, Programkonstruktion del 1 Tentamen,

Programmering II (ID1019) :00-17:00

DD1361 Programmeringsparadigm. Carina Edlund

Programkonstruktion och Datastrukturer

Tentamen (del 2) (4 högskolepoäng) i Programkonstruktion och datastrukturer (1DL201)

LÖSNINGSFÖRSLAG TENTAMEN PROGRAMMERING I ETT FUNKTIONELLT SPRÅK ML, 5P

Tillämpad Programmering (ID1218) :00-13:00

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 14-18

Övningsuppgifter #11, Programkonstruktion och datastrukturer

Summera godtyckligt antal tal. Programkonstruktion. Moment 4 Om rekursion. Fullständigt resonemang för summeringen. Analys av summeringsproblemet

SI-möte #10, Programkonstruktion och Datastrukturer

Föreläsning 9 Innehåll

Hitta k största bland n element. Föreläsning 13 Innehåll. Histogramproblemet

Introduktion till formella metoder Programmeringsmetodik 1. Inledning

Former av rekursion. Programkonstruktion. Moment 5 Mera om rekursion. Fakultetsfunktionen. Största gemensamma delare (repris!

"Referentiell transparens"

Tentamen i. TDDC67 Funktionell programmering och Lisp

Föreläsning 5 i programmeringsparadigm.

Sätt att skriva ut binärträd

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 14-18

Symboliska konstanter const

Programmering II (ID1019) :00-12:00

TDIU01 - Programmering i C++, grundkurs

Några inbyggda funktioner (med resultat!) Introduktion till programmering D0009E. Föreläsning 4: Villkor och rekursion. Modulus-operatorn.

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

Föreläsning 6: Introduktion av listor

Introduktion till programmering SMD180. Föreläsning 4: Villkor och rekursion

Imperativ programmering. Imperativ programmering konstruktioner i Lisp. Datastrukturer (kap ) arraystruktur poststruktur

Föreläsning 3-4 Innehåll

Föreläsning 14 Innehåll

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

Namn: (Ifylles av student) Personnummer: (Ifylles av student) Tentamensdatum: Tid: Hjälpmedel: Inga hjälpmedel

Rekursiva algoritmer sortering sökning mönstermatchning

Sökning och sortering. Sökning och sortering - definitioner. Sökning i oordnad lista. Sökning med vaktpost i oordnad lista

Korsordlösare Sara Hedbrandh Strömberg Programkonstruktion VT 10 Inlämninsguppgift

Föreläsningsanteckningar, Introduktion till datavetenskap HT S4 Datastrukturer. Tobias Wrigstad

n Detta för att kunna koncentrera oss på n Tal: number? n Symboler: symbol? n Strängar: string? n Tecken: char? n Boolskt: boolean?

Tentamen 1 (6 högskolepoäng) i Programkonstruktion och datastrukturer (1DL201)

Sökning och sortering

Föreläsning 8 Datastrukturer (DAT037)

Inlämningsuppgift MiniPlotter

Abstrakta datatyper. Primitiva vektorer. Deklarera en vektor

Programmering för Språkteknologer II. Innehåll. Associativa datastrukturer. Associativa datastrukturer. Binär sökning.

Föreläsning 4 Datastrukturer (DAT037)

Föreläsning Datastrukturer (DAT037)

Tommy Färnqvist, IDA, Linköpings universitet

Programmering II (ID1019) :00-12:00

DD1361 Programmeringsparadigm. Formella Språk & Syntaxanalys. Per Austrin

TDDC74 Programmering, abstraktion och modellering. Tentamen

Arrayer (vektorer) Murach s: kap Elektronikcentrum i Svängsta AB

Programmeringsmetodik DV1 Programkonstruktion 1. Moment 2 Introduktion till funktioner och programutveckling

Klassen BST som definierar binära sökträd med tal som nycklar och enda data. Varje nyckel är unik dvs förekommer endast en

Föreläsning Datastrukturer (DAT036)

TENTAMEN: Algoritmer och datastrukturer. Läs detta! Uppgifterna är inte avsiktligt ordnade efter svårighetsgrad.

Föreläsning 13. Träd

Pascal... Pascal. Pascal... Pascal...

Tentamen Datastrukturer D DAT 035/INN960 (med mycket kortfattade lösningsförslag)

1 Texthantering. 1.1 Typen char. Exempel, skriv ut alfabetet

TDDC74 Programmering, abstraktion och modellering DUGGA 2

Pascal. reserverade ord fördefinierade funktioner och procedurer egendefinierade funktioner, procedurer och objekt

Föreläsning 8 i kursen Ma III, #IX1305, HT 07. (Fjärde föreläsningen av Bo Åhlander)

Umeå universitet Programspråk, 7.5hp

Pythons standardbibliotek

Introduktion C-programmering

Föreläsning 13. Rekursion

Exempeltenta GruDat 2002/2003

TDDC74 Programmering: Abstraktion och modellering Tentamen, lördag 27 augusti 2016, kl 8 12

GRUNDER I VHDL. Innehåll. Komponentmodell Kodmodell Entity Architecture Identifierare och objekt Operationer för jämförelse

Repetition C-programmering

Sökning och sortering

TDIU01 - Programmering i C++, grundkurs

Lösningar Datastrukturer TDA

Introduktion till programmering D0009E. Föreläsning 9: Tupler och dictionaries

6 Rekursion. 6.1 Rekursionens fyra principer. 6.2 Några vanliga användningsområden för rekursion. Problem löses genom:

Föreläsning 8 Datastrukturer (DAT037)

Typsystem. Typsystem... Typsystem... Typsystem... 2 *

Idag: Par och listor. Scheme. DA2001 (Föreläsning 6) Datalogi 1 Hösten / 29

Idag: Par och listor. Symboler. Symboler används för att uttrycka icke-numeriska data såsom namn, adress, bilregisternummer, boktitel, osv.

Programkonstruktion och. Datastrukturer

Typsystem. DA2001 (Föreläsning 23) Datalogi 1 Hösten / 19

Föreläsning 9 Innehåll

Lägg uppgifterna i ordning. Skriv uppgiftsnummer och din kod överst i högra hörnet på alla papper.

Programmering A. Johan Eliasson

public boolean containskey(string key) { return search(key, head)!= null; }

Transkript:

Programmeringsmetodik DV1 Programkonstruktion 1 Moment 9 Om högre ordningens funktioner PK1&PM1 HT-06 moment 9 Sida 1 Uppdaterad 2006-09-06

Anonyma funktioner igen En funktion som inte är namngiven kallas för en anonym funktion. formellt argument fn x => x+1 funktionskropp När man anropar funktionen så beräknas funktionskroppen som om x bytts ut mot argumentet i anropet. x är bunden i funktionen. x är en godtycklig identifierare. Funktionens typ bestäms av typen hos det formella argumentet och funktionskroppen. Funktionen ovan har typen int -> int. (fn x => x+1)(4*2) - > (fn x => x+1) 8 - > 8+1 - > 9 PK1&PM1 HT-06 moment 9 Sida 2 Uppdaterad 2006-09-06

Funktioner är första klassens objekt i ML Kom ihåg att funktioner kan behandlas som datastrukturer i ML. Funktioner kan vara argument till andra funktioner Värdet av en funktion kan också vara en funktion Funktioner kan förekomma som delar av datastrukturer (t.ex. element i listor). PK1&PM1 HT-06 moment 9 Sida 3 Uppdaterad 2006-09-06

Funktioner kan vara argument fun dotwice(f,x) = f(f x); fun square x = x*x; dotwice(square,3) - > square(square 3) - > square(3*3) - > square 9 - > 9*9 - > 81 dotwice(fn x=>x+1,3) - > (fn x=>x+1)((fn x=>x+1) 3) - > (fn x=>x+1)(3+1) - > (fn x=>x+1) 4 - > 4+1 - > 5 Vilken är typen av dotwice? ('a->'a)*'a->'a. En första ordningens funktion har argument som inte är funktioner. En högre ordningens funktion har något funktionsargument. PK1&PM1 HT-06 moment 9 Sida 4 Uppdaterad 2006-09-06

mergesort igen 7 1 5 7 3 2 12 8 split 7 5 3 12 1 7 2 8 mergesort mergesort 3 5 7 12 1 2 7 8 merge 1 2 3 5 7 7 8 12 Varför var inte mergesort polymorf? PK1&PM1 HT-06 moment 9 Sida 5 Uppdaterad 2006-09-06

Original-merge 3 5 7 12 1 2 7 8 merge 1 2 3 5 7 7 8 12 (* merge(l1,l2) Type: int list*int list -> int list Pre: l1 och l2 är sorterade i stigande ordning. Post: En lista med alla element i l1 och l2 i stigande ordning. Ex.: merge([3,5,7,12],[1,2,7,8]) = [1,2,3,5,7,7,8,12] *) (* Variant: (length l1)+(length l2) *) fun merge([],l2) = l2 merge(l1,[]) = l1 merge(l1,l2) = if hd l1 < hd l2 then hd l1 :: merge(tl l1, l2) else hd l2 :: merge(l1,tl l2) PK1&PM1 HT-06 moment 9 Sida 6 Uppdaterad 2006-09-06

Polymorf merge (* merge(less,l1,l2) Type: ('a*'a->bool)*'a list*'a list -> 'a list Pre: l1 och l2 är sorterade i stigande ordning enligt relationen less. Post: En lista med alla element i l1 och l2 i stigande ordning enligt relationen less. Ex.: merge(op <,[3,5,7,12],[1,2,7,8]) = [1,2,3,5,7,7,8,12] *) (* Variant: (length l1)+(length l2) *) fun merge(_,[],l2) = l2 merge(_,l1,[]) = l1 merge(less,l1,l2) = if less(hd l1,hd l2) then hd l1 :: merge(less,tl l1,l2) else hd l2 :: merge(less,l1,tl l2); PK1&PM1 HT-06 moment 9 Sida 7 Uppdaterad 2006-09-06

Notationen op Funktioner som är infixa operatorer kan inte direkt vara argument: - merge(<,[3,5,7,12],[1,2,7,8]);! Toplevel input:! merge(<,[3,5,7,12],[1,2,7,8]);! ^! Ill-formed infix expression ML förväntar sig argument före och efter <. Lösning: skriv op före <. op stänger av den speciella syntaktiska betydelsen hos <. - merge(op <,[3,5,7,12],[1,2,7,8]); > val it = [1, 2, 3, 5, 7, 7, 8, 12] : int list Varning: foo(op *) gör inte vad man tror. Åtgärd: foo(op * ) blank Varför? PK1&PM1 HT-06 moment 9 Sida 8 Uppdaterad 2006-09-06

Polymorf mergesort (* mergesort(less,l) Type: ('a*'a->bool)*'a list -> 'a list Pre: (ingen) Post: En lista med alla element i l i stigande ordning enligt relationen less. Ex.: mergesort(op <,[7,1,5,7,3,2,12,8]) = [1,2,3,5,7,7,8,12] *) (* Variant: length l *) fun mergesort(_,[]) = [] mergesort(_,[x]) = [x] mergesort(less,l) = let val (l1,l2) = split l in merge(less,mergesort(less,l1), mergesort(less,l2)) end; PK1&PM1 HT-06 moment 9 Sida 9 Uppdaterad 2006-09-06

Mer komplicerade relationer Sortera en lista av namn uttryckta som efternamn-förnamn-par: val namnlista = [("Bergkvist","Erik"),("Andersson","Arne"), ("Björklund","Henrik"),("Eriksson","Lars-Henrik"), ("Andersson","Petra"),("Berg","Stina")]; När kommer ett namn före ett annat? Efternamnet skall jämföras först! fun lessname((e1:string,f1:string),(e2,f2)) = e1 < e2 orelse e1 = e2 andalso f1 < f2; Varför behövs typdeklarationerna (:string)? mergesort(lessname,namnlista) = [("Andersson","Arne"),("Andersson","Petra"), ("Berg","Stina"),("Bergkvist","Erik"), ("Björklund","Henrik"),("Eriksson","Lars-Henrik")] PK1&PM1 HT-06 moment 9 Sida 10 Uppdaterad 2006-09-06

Värdet av en funktion kan vara en funktion fun selectopr s = case s of "plus" => op + "minus" => op - "sumto" => sumrange "mean" => fn (x,y) => (x+y) div 2 (sumrange(i,n) summerar heltalen från i till n.) selectopr "plus" - > op + selectopr "mean" - > fn (x,y) => (x+y) div 2 (selectopr "plus") (4,6) - > (op +)(4,6) - > 10 (selectopr "sumto") (4,6) - > sumrange(4,6) - > 15 Vilken är typen av selectopr? string->(int*int->int). -> är högerassociativ så vi kan utelämna parenteserna och skriva: string -> int*int -> int. PK1&PM1 HT-06 moment 9 Sida 11 Uppdaterad 2006-09-06

Diverse om användning av funktionsvärden Funktionsapplikation i ML är vänsterassociativ. Ett uttryck som (f x) y kan lika gärna skrivas f x y. ML kan inte skriva ut funktionsvärden. Funktionsvärden ersätts med symbolen fn. - selectopr "plus"; > val it = fn : int * int -> int PK1&PM1 HT-06 moment 9 Sida 12 Uppdaterad 2006-09-06

Syntaxträd igen Strukturen hos en formel kan beskrivas med ett syntaxträd. 3+2*x-1 : + 1 datatype expr = Const of int Var of string Plus of expr*expr Minus of expr*expr Times of expr*expr Div of expr*expr; Minus(Plus(Const 3,Times(Const 2,Var "x")), Const 1) PK1&PM1 HT-06 moment 9 Sida 13 Uppdaterad 2006-09-06 3 2 * x

exception UnDefVar of string; Beräkning av uttryck igen (* eval(expr,var,value) TYPE: expr*string*int->int PRE: var är den enda variabel som förekommer i expr. Ingen division med 0 förekommer i expr. POST: Värdet av expr uträknat. Ex: eval(minus(plus(const 3,Times(Const 2,Var "x")),const 1), "x",4) = 10 *) (* VARIANT: Storleken hos expr. *) fun eval(const c,_,_) = c eval(var v,var,value) = if v = var then value else raise UnDefVar v eval(plus(e1,e2),var,value) = eval(e1,var,value) + eval(e2,var,value) eval(minus(e1,e2),var,value) = eval(e1,var,value) - eval(e2,var,value) eval(times(e1,e2),var,value) = eval(e1,var,value) * eval(e2,var,value) eval(div(e1,e2),var,value) = eval(e1,var,value) div eval(e2,var,value); PK1&PM1 HT-06 moment 9 Sida 14 Uppdaterad 2006-09-06

Lite annorlunda syntaxträd Operatorn lagras i ett fält i varje nod. 3+2*x-1 : + 1 datatype expr = Const of int Var of string Op of string*expr*expr; Op("minus",Op("plus",Const 3, Op("times",Const 2,Var "x")), Const 1) 3 2 * x PK1&PM1 HT-06 moment 9 Sida 15 Uppdaterad 2006-09-06

exception UnDefVar of string; Beräkning av uttryck (* eval(expr,var,value) TYPE: expr*string*int->int PRE: var är den enda variabel som förekommer i expr. Ingen division med 0 förekommer i expr. Bara operatorer som är kända av selectopr förekommer i expr. POST: Värdet av expr uträknat. EX: eval(op("minus",op("plus",const 3, Op("times",Const 2,Var "x")), Const 1), "x",4) = 10 *) (* VARIANT: Storleken hos expr *) fun eval(const c,_,_) = c eval(var v,var,value) = if v = var then value else raise UnDefVar v eval(op(opr,e1,e2),var,value) = selectopr opr (eval(e1,var,value),eval(e2,var,value)); PK1&PM1 HT-06 moment 9 Sida 16 Uppdaterad 2006-09-06

Datatypen order Ibland behöver man kunna jämföra två objekt både för storlek och likhet. Det finns en fördefinierad datatyp order för att beskriva resultatet av jämförelsen: datatype order = LESS GREATER EQUAL; Flera inbyggda funktioner har värde av typ order: Int.compare, String.compare, Real.compare,... Int.compare(3,3) = EQUAL String.compare("Aha","Ahaaaa!") = LESS Real.compare(46.4,32.0) = GREATER Speciellt för abstrakta datatyper kan det vara praktiskt att ha en order-värd jämförelsefunktion. PK1&PM1 HT-06 moment 9 Sida 17 Uppdaterad 2006-09-06

Exempel på order-värd jämförelse Givet två rationella tal representerade som (p1,q1) och (p2,q2) så gäller att (p1,q1) är mindre än (p2,q2) omm p1*q2<p2*q1. fun rationalcompare((p1,q1),(p2,q2)) = case p1*q2-p2*q1 of 0 => EQUAL d => if d < 0 then LESS else GREATER; rationalcompare((7,14),(6,9)) > case 7*9-14*6 of 0 => EQUAL d => if... > case ~21 of 0 => EQUAL d => if... > if ~21 < 0 then LESS else GREATER > if true then LESS else GREATER > LESS PK1&PM1 HT-06 moment 9 Sida 18 Uppdaterad 2006-09-06

Binära sökträd igen 4 2 7 1 6 9 Kom ihåg att funktionerna för sökning i binära sökträd inte utan vidare kan vara polymorfa eftersom man måste använda storleksjämförelse vid sökning i träden. PK1&PM1 HT-06 moment 9 Sida 19 Uppdaterad 2006-09-06

Deklaration av polymorfa binära sökträd abstype ('a,'b) table = Empty of ('a*'a->order) Bintree of ('a*'a->order)*'a*'b* ('a,'b) table*('a,'b) table (* dokumentation *) with fun empty compare = Empty compare; fun update...; fun lookup...; fun remove...; fun tolist...; end; Den nödvändiga jämförelsefunktionen lagras i trädet när en tom tabell skapas. (OBS att empty nu är en funktion.) Nyckeltypen ('a) behöver nu inte vara en likhetstyp. Varför? PK1&PM1 HT-06 moment 9 Sida 20 Uppdaterad 2006-09-06

Funktionen lookup (* lookup(key,table) TYPE: 'a*('a*'b) table -> 'b option PRE: (ingen) POST: SOME v om key finns i table och v är motsvarande värde. NONE annars. *) (* VARIANT: Största djupet hos ett löv i table *) fun lookup(key,empty _) = NONE lookup(key,bintree(compare,key',value, left,right)) = case compare(key,key') of EQUAL => SOME value LESS => lookup(key,left) GREATER => lookup(key,right); PK1&PM1 HT-06 moment 9 Sida 21 Uppdaterad 2006-09-06

Funktionen update (* update(key,value,table) TYPE: 'a*'b*('a*'b) table -> ('a*'b) table POST: Tabellen table uppdaterad med värdet value för nyckeln key *) (* VARIANT: största djupet av ett löv i table *) fun update(key,value,empty compare) = Bintree(compare,key,value, Empty compare,empty compare) update(key,value, Bintree(compare,key',value', left,right)) = case compare(key,key') of EQUAL => Bintree(compare,key,value,left,right) LESS => Bintree(compare,key',value', update(key,value,left),right) GREATER => Bintree(compare,key',value', left,update(key,value,left)); PK1&PM1 HT-06 moment 9 Sida 22 Uppdaterad 2006-09-06

Användning av polymorfa sökträd val tabell = update("lars-henrik",1057, update("roland", 7606, empty String.compare)); Tabellen innehåller information om Lars-Henrik och Roland. lookup("lars-henrik",tabell) = SOME 1057 lookup("roland",tabell) = SOME 7606 lookup("kalle",tabell) = NONE PK1&PM1 HT-06 moment 9 Sida 23 Uppdaterad 2006-09-06

Mönster vid listrekursion fun squarelist [] = [] squarelist (first::rest) = square first::squarelist rest; fun neglist [] = [] neglist (first::rest) = ~first::neglist rest; Dessa funktioner har samma struktur de skiljer sig bara i funktionsnamnen och de rödmarkerade delarna. Man kan skriva en högre ordningens funktion mapl som fångar strukturen och som har ett funktionsargument för olikheten: fun mapl(f,[]) = [] mapl(f,first::rest) = f first::mapl(f,rest); fun squarelist l = mapl(square,l); fun neglist l = mapl(~,l); PK1&PM1 HT-06 moment 9 Sida 24 Uppdaterad 2006-09-06

Mönster vid listrekursion (forts.) fun mapl(f,[]) = [] mapl(f,first::rest) = f first::mapl(f,rest); fun squarelist l = mapl(square,l); squarelist [1,~2,4] - > mapl(square,[1,~2,4]) - > square 1::mapl(square,[~2,4]) - > 1*1::mapl(square,[~2,4]) - > 1::mapl(square,[~2,4]) - > 1::square ~2::mapl(square,[4]) - > 1:: ~2* ~2::mapl(square,[4]) - > 1::4::mapl(square,[4]) - > 1::4::square 4::mapl(square,[]) - > 1::4::4*4::mapl(square,[]) - > 1::4::16::mapl(square,[]) - > 1::4::16::[] = [1,4,16] PK1&PM1 HT-06 moment 9 Sida 25 Uppdaterad 2006-09-06

Stuvade funktioner fun plus(x,y) = x+y; (plus: int*int->int) fun plus' x = fn y => x+y; (plus': int->int->int) plus(4,6) > 4+6 > 10 plus' 4 6 > (fn y => 4+y)6 > 4+6 > 10 plus' är en stuvad (curried efter H.B. Curry) form av plus. plus' tar ett argument i taget. Funktionen som är värdet av plus' minns bindningen av x. val add1 = plus' 1; (add1 nu bunden till fn y => 1+y) add1 3 > (fn y => 1+y)3 > 1+3 > 4 fun har en speciell form för att definiera stuvade funktioner: fun plus' x y = x+y; är samma definition av plus' som den ovan. PK1&PM1 HT-06 moment 9 Sida 26 Uppdaterad 2006-09-06

Beräkning av funktioner En stuvad form av mapl finns inbyggd i ML under namnet map. mapl(f,l) = map f l fun squarelist l = map square l; map kan också användas för att beräkna funktionen squarelist: val squarelist = map square; PK1&PM1 HT-06 moment 9 Sida 27 Uppdaterad 2006-09-06

Mer komplicerade programmönster fun length [] = 0 length (first::rest) = 1+length rest; fun addlist [] = 0 addlist (first::rest) = first+addlist rest; fun append([],x) = x append(first::rest,x) = first::append(rest,x); Gemensamt för dessa: En operation utförs på första elementet av listan och resultatet av det rekursiva anropet (blått) Det finns ett bestämt värde ( startvärde ) vid basfallet (rött). (Not: även 1+ är principiellt en operation på första elementet i listan och resultatet av det rekursiva anropet även om det är en operation som inte utnyttar värdet av det första listelementet.) PK1&PM1 HT-06 moment 9 Sida 28 Uppdaterad 2006-09-06

Funktionen foldr Den inbyggda funktionen foldr utför mer generell rekursion över listor än map. foldr kan utläsas som fold from right. (* foldr f e l TYPE: ('a*'b->'b)->'b->'a list->'b PRE: (ingen) POST: f(x1,f(x2,...f(xn,e)...)) om l=[x1,x2,...,xn] *) (* VARIANT: längden av l *) fun foldr f e [] = e foldr f e (first::rest) = f(first,foldr f e rest); PK1&PM1 HT-06 moment 9 Sida 29 Uppdaterad 2006-09-06

Beräkning av funktioner med foldr fun foldr f e [] = e foldr f e (first::rest) = f(first,foldr f e rest); Vad är värdet av foldr (op +) 0? f binds till (op +) och e binds till 0. Resultatet blir alltså en funktion som är definierad som: fun foo [] = 0 foo (first::rest) = (op +)(first,foo rest);...vilket (utom syntaxen) är den rekursiva definitionen av addlist. (Den beräknade funktionen är anonym jag har kallat den för foo.) addlist kan alltså definieras som: val addlist = foldr (op +) 0; eller kanske lite tydligare fun addlist l = foldr (op +) 0 l; PK1&PM1 HT-06 moment 9 Sida 30 Uppdaterad 2006-09-06

Användning av foldr Exempel på användning av foldr: fun length l = foldr (fn (x,y) => 1+y) 0 l; fun addlist l = foldr (op +) 0 l; fun append(x,y) = foldr (op ::) y x; fun smallest (first::rest) = foldr Int.min first rest; fun split l = foldr (fn (first,(x,y)) => (first::y,x)) ([],[]) l; map kan definieras med hjälp av foldr: fun map f l = foldr (fn (x,y) => f x::y) [] l; PK1&PM1 HT-06 moment 9 Sida 31 Uppdaterad 2006-09-06

Funktionen foldl Det finns också en inbyggd funktion för iteration (svansrekursion) över listor: (* foldl f e l TYPE: ('a*'b->'b)->'b->'a list->'b POST: f(xn,...f(x2,f(x1,e))...) om l=[x1,x2,...,xn] *) (* VARIANT: längden av l *) fun foldl f e l = let fun foldlaux([],ack) = ack foldlaux(first::rest,ack) = foldlaux(rest,f(first,ack)) in foldlaux(l,e) end; Exempel: fun rev l = foldl (op ::) [] l; PK1&PM1 HT-06 moment 9 Sida 32 Uppdaterad 2006-09-06

Funktionen filter List.filter kan användas för att välja ut vissa delar av en lista. T.ex. List.filter (fn x => x>0) [1,~2,4,0] = [1,4] (* filter p l TYPE: ('a -> bool) -> 'a list -> 'a list POST: En lista av de element i l som gör p sann *) (* VARIANT: längden av l *) fun filter p [] = [] filter p (first::rest) = if p first then first::filter p rest else filter p rest; filter kan även definieras med hjälp av foldr: fun filter p l = foldr (fn (x,y) => if p x then x::y else y) [] l PK1&PM1 HT-06 moment 9 Sida 33 Uppdaterad 2006-09-06

Högre ordningens funktioner för vektorer I biblioteket Vector finns varianter av funktionerna map, foldr och foldl som arbetar på vektorer i stället för listor. Exempel: Summera heltal i en vektor (svansrekursivt): (* sumvector a TYPE: int vector -> int POST: Summan av elementen i a *) fun sumvector a = Vector.foldl (op +) 0 a; Exempel: Bilda en lista av elementen i en vektor: (* tolist a TYPE: 'a vector -> 'a list POST: En lista av elementen i vektorn a. *) fun tolist a = Vector.foldr (op ::) [] a; - tolist #[18,12,~5,12,10]; > val it = [18, 12, ~5, 12, 10] : int list PK1&PM1 HT-06 moment 9 Sida 34 Uppdaterad 2006-09-06