Upload
others
View
9
Download
0
Embed Size (px)
Citation preview
INF2810: Funksjonell programmering
INF2810: Funksjonell Programmering
Køer, tabeller, og (litt om) parallelitet
Stephan Oepen & Erik Velldal
Universitetet i Oslo
5. april 2013
Tema
Siste gangI Kort om underveisevaluering
I Destruktive listeoperasjoner
I Implementasjon av køer
I Den store INF2810-påskequizzen
I dagI Litt mer i dybden om køer
I Eksperiment: live-programmering
I Tabeller som hierarkiske lister
I Grunnleggende om parallelitet
2
Repetisjon: Spørsmål 1 (omgivelser)
(a) Hvor mange nye omgivelser oppstår under evaluering av dette uttrykket?
(b) Hva er resultatet av evalueringen?
(define foo 41)
(let ((foo (+ foo 1)))((lambda (foo)
(* foo 2))foo))
(a) let, +, oppkalling av anonym prosedyre, *: 4 (2 poeng).
(b) (* (+ 41 1) 2) ≡ 84 (1 poeng).
3
Vi gratulerer!
I Ganske eksamensrelevante spørsmål; vinnerlaget med 12 av 20 poeng.4
Destruktive listeoperasjoner
I Når tilordningen til symbol kan endres, hva med komplekse objekter?
I Med set-car! og set-cdr! kan tilordninger innenfor et par endres.
? (define foo ’(0 2 2))? (set-car! foo 1)? foo → (1 2 2)? (set-car! (cddr foo) 3)? foo → (1 2 3)
I Så langt brukte vi cons-celler som ‘lim’ for komplekse datastrukturer.
I Kan nå definere mutators i tillegg til constructor, selectors, og predicate.
I Det kan være hensiktsmessig for å minimere bruk av minne (plass).
5
Destruktiv Listekonkatenasjon
(define (append! front tail)(if (null? (cdr front))
(set-cdr! front tail)(append! (cdr front) tail)))
? (define foo ’(1 2))? (define bar ’(3 4))? (append! foo bar)
? foo → (1 2 3 4)
I Vår prosedyre append! er destruktiv siden (verdien til) foo endres.
Ennå mer aliasing? (append! foo bar)
? foo → (1 2 . #0=(3 4 . #0#))
6
Litt mer trening på destruktive listeoperasjoner
(define (foo bar)(if (null? bar)
’()(cons (car bar) (foo (cdr bar)))))
? (define baz ’((a b) c))? (define fee (foo baz))? (equal? baz fee) → #t? (eq? baz fee)→ #f
? (set-cdr! baz ’(d))? baz → ((a b) d)? fee → ((a b) c)
? (set-car! (car baz) ’b)? baz → ((b b) d)? fee → ((b b) c)
7
Køer (implementert på grunnlag av lister)I En kø (queue) er en rettferdig datastruktur: first in, first out (FIFO).
I Kan implementeres som liste, sammen med ‘først’- og ‘sist’-pekere.
I Nye objekter legges til på slutten; objekter kan kun fjernes fra fronten.
I Kunne vi klart oss med bare en liste (én cons per elementet i køen)?8
Køer som abstrakt datatype
I make-queue ingen parametre; returnerer en tom kø.
I queue-empty? ett parameter; tester for tomhet.
I queue-insert! setter første parameteret inn i andre parameteret.
I queue-extract! ett parameter; tar ut og returnerer første objektet.
Nå skal vi prøve oss pålive-programmering.
9
(Assosiative) TabellerI Også assosiative tabeller kan implementeres med cons-celler i bunnen.
I Lime sammen 〈nøkkel, verdi〉-par som cons; så samle de som en liste.
I Noen operasjoner kan forenkles ved å sette én ekstra cons-celle foran.
I En slik headed list kan også bruke allerførste car som typemerkelapp.
10
Endimensionale tabeller som lister
(define (make-table)(list ’*table*))
(define (assoc key records)(cond ((null? records) #f)
((equal? key (caar records)) (car records))(else (assoc key (cdr records)))))
(define (lookup key table)(let ((record (assoc key (cdr table))))
(and record (cdr record))))
(define (insert! key value table)(let ((record (assoc key (cdr table))))
(if record(set-cdr! record value)(set-cdr! table (cons (cons key value) (cdr table))))))
I 〈nøkkel, verdi〉-lister heter assoc-lister og støttes i Scheme (og Lisp).11
Noen refleksjoner rundt tabeller
I I denne (naïve) implementasjonen, hvilken tidskompleksitet har detI å slå opp verdien til en nøkkel?I å legge inn et 〈nøkkel, verdi〉-par?
I Kompleksiteten kan forbedres hvis nøklene sorteres → binære trær.
I Vi husker at cons-celler kunne implementeres som prosedyreobjekter;
I dette kan utvides til destruktive operasjoner (set-car! og set-cdr!).
I Med mange elementer kan det lønne seg å bruke en hashtabell isteden.
I Common Lisp har hashtabeller som innebygd datatype, enn ikke R5RS.
I Men Scheme har støtte for fast dimensionerte felt (vector eller array).
I Multidimensjonale tabeller kan realiseres ved å nøste assoc-tabeller.
12
En todimensjonal tabell
13
Veldig kort om parallelitet (1/4)
I Med set! introduserte vi elementer fra imperativ programmering:
I Verditilordning og tilstandsendring som modifiserer objekter.
I Bankkonto er en muterbar objekt, med tidsavhengig tilstand.
I I ren funskjonell programmering derimot var ting statisk over tid:
I Semantikken til et uttrykk var uavhengig av hvor og når det brukes.
I Derfor kan (rent) funksjonelle programmer uten videre paralleliseres.
I Med tidsavhengig tilstand trengs det mekanismer for synkronisering.
I Problem: destruktive prosedyrer som ‘deler’ på noen felles ressurser.
14
Veldig kort om parallelitet (2/4)
15
Veldig kort om parallelitet (3/4)
Suppose that Peter, Paul, and Mary share a jointbank account that initially contains $100.
Concurrently, Peter deposits $10, Paul withdraws $20,and Mary withdraws half the money in the account.
Peter (set! balance (+ balance 10))Paul (set! balance (- balance 20))Mary (set! balance (- balance (/ balance 2)))
I Hvor mange mulige sluttsaldoer, hvis hvert set!-uttrykk var atomært?
I Hvor mange muligheter uten hvilke som helst antakelser om rekkefølge?
I Hva er ‘kritiske punkter’ med tanke på parallelitet og tidsdimensjonen?
16
Veldig kort om parallelitet (4/4)
I For å synkronisere rundt bruk av felles ressurserbrukes semaphores; (aka mutex or lock) som bleførst diskutert av Edsger Dijkstra (1965).
I Før kritisk avsnitt, få tak i semaphoren (acquire);
I Ved utgang fra kritisk avsnitt, slippe (release).
I Prosesser blokkeres under venting på semaphoren.
(define (make-account)(let ((balance 0)
(mutex (make-mutex)))(define (deposit amount)
(mutex ’acquire)(set! current (+ current amount)))(mutex ’release)
· · · ))
17