INF2810: Funksjonell Programmering Strømmer Stephan Oepen & Erik Velldal Universitetet i Oslo 12. april 2013
Tema 2 Forrige uke Litt mer i dybden om køer Eksperiment: live-programmering Tabeller som hierarkiske lister Grunnleggende om parallelitet
Tema 2 Forrige uke Litt mer i dybden om køer Eksperiment: live-programmering Tabeller som hierarkiske lister Grunnleggende om parallelitet I dag Repetisjon: parallelitet Noe helt nytt: strømmer Litt mer live-programmering
(Assosiative) Tabeller 3 Også assosiative tabeller kan implementeres med cons-celler i bunnen. Lime sammen nøkkel, verdi -par som cons; så samle de som en liste. Noen operasjoner kan forenkles ved å sette én ekstra cons-celle foran. En slik headed list kan også bruke allerførste car som typemerkelapp.
En todimensjonal assosiativ tabell 4
Veldig kort om parallelitet (1/3) 5
Veldig kort om parallelitet (2/3) 6 Suppose that John, Luke, and Mark share a joint bank account that initially contains $100. Concurrently, John deposits $10, Luke withdraws $20, and Mark withdraws half the money in the account. John (set! balance (+ balance 10)) Luke (set! balance (- balance 20)) Mark (set! balance (- balance (/ balance 2)))
Veldig kort om parallelitet (2/3) 6 Suppose that John, Luke, and Mark share a joint bank account that initially contains $100. Concurrently, John deposits $10, Luke withdraws $20, and Mark withdraws half the money in the account. John (set! balance (+ balance 10)) Luke (set! balance (- balance 20)) Mark (set! balance (- balance (/ balance 2))) Hvor mange mulige sluttsaldoer, hvis hvert set!-uttrykk var atomært? Hvor mange muligheter uten hvilke som helst antakelser om rekkefølge? Hva er kritiske punkter med tanke på parallelitet og tidsdimensjonen?
Veldig kort om parallelitet (2/3) 6 Suppose that John, Luke, and Mark share a joint bank account that initially contains $100. Concurrently, John deposits $10, Luke withdraws $20, and Mark withdraws half the money in the account. John (set! balance (+ balance 10)) Luke (set! balance (- balance 20)) Mark (set! balance (- balance (/ balance 2))) Hvor mange mulige sluttsaldoer, hvis hvert set!-uttrykk var atomært? Hvor mange muligheter uten hvilke som helst antakelser om rekkefølge? Hva er kritiske punkter med tanke på parallelitet og tidsdimensjonen?
Veldig kort om parallelitet (3/3) 7 For å synkronisere rundt bruk av felles ressurser brukes semaphores; (aka mutex or lock) som ble først diskutert av Edsger Dijkstra (1965).
Veldig kort om parallelitet (3/3) 7 For å synkronisere rundt bruk av felles ressurser brukes semaphores; (aka mutex or lock) som ble først diskutert av Edsger Dijkstra (1965). Før kritisk avsnitt, få tak i semaphoren (acquire); Ved utgang fra kritisk avsnitt, slippe (release).
Veldig kort om parallelitet (3/3) 7 For å synkronisere rundt bruk av felles ressurser brukes semaphores; (aka mutex or lock) som ble først diskutert av Edsger Dijkstra (1965). Før kritisk avsnitt, få tak i semaphoren (acquire); Ved utgang fra kritisk avsnitt, slippe (release). Prosesser blokkeres under venting på semaphoren.
Veldig kort om parallelitet (3/3) 7 For å synkronisere rundt bruk av felles ressurser brukes semaphores; (aka mutex or lock) som ble først diskutert av Edsger Dijkstra (1965). Før kritisk avsnitt, få tak i semaphoren (acquire); Ved utgang fra kritisk avsnitt, slippe (release). Prosesser blokkeres under venting på semaphoren. (define (make-account) (let ((balance 0) (mutex (make-mutex))) (define (withdraw amount) (mutex acquire) (set! balance (- balance amount))) (mutex release) ))
Veldig kort om parallelitet (3/3) 7 For å synkronisere rundt bruk av felles ressurser brukes semaphores; (aka mutex or lock) som ble først diskutert av Edsger Dijkstra (1965). Før kritisk avsnitt, få tak i semaphoren (acquire); Ved utgang fra kritisk avsnitt, slippe (release). Prosesser blokkeres under venting på semaphoren. (define (make-account) (let ((balance 0) (mutex (make-mutex))) (define (withdraw amount) (mutex acquire) (set! balance (- balance amount))) (mutex release) )) Hver konto (som ressurs) har sin egen semaphore.
Tilbake til sekvenser som konvensjonell grensesnitt 8 (define (mystery low high) (define (recurse count sum) (cond ((> count high) sum) ((prime? count) (recurse (+ count 1) (+ count sum))) (else (recurse (+ count 1) sum)))) (recurse low 0))
Tilbake til sekvenser som konvensjonell grensesnitt 8 (define (mystery low high) (define (recurse count sum) (cond ((> count high) sum) ((prime? count) (recurse (+ count 1) (+ count sum))) (else (recurse (+ count 1) sum)))) (recurse low 0))? (mystery 1 5) Hva er formålet med mystery, og hva returnerer eksempelkallingen?
Tilbake til sekvenser som konvensjonell grensesnitt 8 (define (mystery low high) (define (recurse count sum) (cond ((> count high) sum) ((prime? count) (recurse (+ count 1) (+ count sum))) (else (recurse (+ count 1) sum)))) (recurse low 0))? (mystery 1 5) Hva er formålet med mystery, og hva returnerer eksempelkallingen? Ved bruk av høyreordensprosedyrer kan problemet løses elegantere : (define (sum-primes low high) (accumulate + 0 (filter prime? (interval low high))))
Tilbake til sekvenser som konvensjonell grensesnitt 8 (define (mystery low high) (define (recurse count sum) (cond ((> count high) sum) ((prime? count) (recurse (+ count 1) (+ count sum))) (else (recurse (+ count 1) sum)))) (recurse low 0))? (mystery 1 5) Hva er formålet med mystery, og hva returnerer eksempelkallingen? Ved bruk av høyreordensprosedyrer kan problemet løses elegantere : (define (sum-primes low high) (accumulate + 0 (filter prime? (interval low high)))) Kan vi finne noen relevante forskjell i tids- eller plasskompleksitet?
Begrensninger med sekvenser som konvensjonell grensesnitt 9 Satt på spissen, kan teknikken bli svært (og unødvendig) ueffisient:? (car (cdr (filter prime? (interval 100 100000)))) 103
Begrensninger med sekvenser som konvensjonell grensesnitt 9 Satt på spissen, kan teknikken bli svært (og unødvendig) ueffisient:? (car (cdr (filter prime? (interval 100 100000)))) 103 Det beregnes en lang sekvens, så én til, men bare fire elementer brukes. Helst ta vare på den elegante strukturen men bare beregne etter behov.
Begrensninger med sekvenser som konvensjonell grensesnitt 9 Satt på spissen, kan teknikken bli svært (og unødvendig) ueffisient:? (car (cdr (filter prime? (interval 100 100000)))) 103 Det beregnes en lang sekvens, så én til, men bare fire elementer brukes. Helst ta vare på den elegante strukturen men bare beregne etter behov. Utsatt evaluering (delayed evaluation) og strømmer gir oss begge deler. En strøm (stream) skal ha kontrakt som ligner på vanlige lister: (stream-car (cons-stream x y)) x (stream-cdr (cons-stream x y)) y
Begrensninger med sekvenser som konvensjonell grensesnitt 9 Satt på spissen, kan teknikken bli svært (og unødvendig) ueffisient:? (car (cdr (filter prime? (interval 100 100000)))) 103 Det beregnes en lang sekvens, så én til, men bare fire elementer brukes. Helst ta vare på den elegante strukturen men bare beregne etter behov. Utsatt evaluering (delayed evaluation) og strømmer gir oss begge deler. En strøm (stream) skal ha kontrakt som ligner på vanlige lister: (stream-car (cons-stream x y)) x (stream-cdr (cons-stream x y)) y Men elementene (untatt det første) blir først evaluert når de brukes.
Begrensninger med sekvenser som konvensjonell grensesnitt 9 Satt på spissen, kan teknikken bli svært (og unødvendig) ueffisient:? (car (cdr (filter prime? (interval 100 100000)))) 103 Det beregnes en lang sekvens, så én til, men bare fire elementer brukes. Helst ta vare på den elegante strukturen men bare beregne etter behov. Utsatt evaluering (delayed evaluation) og strømmer gir oss begge deler. En strøm (stream) skal ha kontrakt som ligner på vanlige lister: (stream-car (cons-stream x y)) x (stream-cdr (cons-stream x y)) y Men elementene (untatt det første) blir først evaluert når de brukes. Også tom strøm the-empty-stream og stream-null?-predikatet. For øyeblikket skal vi bare late som om disse var innebygget i Scheme.
Høyreordensprosedyrer for strømmer 10 Etter at grensesnittet er lik lister, kan filter, et al. lett adapteres: (define (stream-interval low high) (if (> low high) the-empty-stream (cons-stream low (stream-interval (+ low 1) high)))) (define (stream-filter predicate stream) (cond ((stream-null? stream) the-empty-stream) ((predicate (stream-car stream)) (cons-stream (stream-car stream) (stream-filter predicate (stream-cdr stream)))) (else (stream-filter predicate (stream-cdr stream)))))
Høyreordensprosedyrer for strømmer 10 Etter at grensesnittet er lik lister, kan filter, et al. lett adapteres: (define (stream-interval low high) (if (> low high) the-empty-stream (cons-stream low (stream-interval (+ low 1) high)))) (define (stream-filter predicate stream) (cond ((stream-null? stream) the-empty-stream) ((predicate (stream-car stream)) (cons-stream (stream-car stream) (stream-filter predicate (stream-cdr stream)))) (else (stream-filter predicate (stream-cdr stream))))) Nå litt live-programmering.
Høyreordensprosedyrer for strømmer 10 Etter at grensesnittet er lik lister, kan filter, et al. lett adapteres: (define (stream-interval low high) (if (> low high) the-empty-stream (cons-stream low (stream-interval (+ low 1) high)))) (define (stream-filter predicate stream) (cond ((stream-null? stream) the-empty-stream) ((predicate (stream-car stream)) (cons-stream (stream-car stream) (stream-filter predicate (stream-cdr stream)))) (else (stream-filter predicate (stream-cdr stream))))) Nå litt live-programmering. En strøm utsetter evalueringen av sin cdr inntill den blir etterspurt. Da styrer etterspørselen beregningsrekkefølge (computing on demand).
Uendelige strømmer 11 (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1))))
Uendelige strømmer 11 (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1))
Uendelige strømmer 11 (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1)) En strøm kan definere en uendelig sekvens uten å faktisk beregne den. Dette kan kombineres med andre strøm-prosedyrer og strømmer, f.eks. (define primes (stream-filter prime? integers))? (stream-ref primes 3)
Uendelige strømmer 11 (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1)) En strøm kan definere en uendelig sekvens uten å faktisk beregne den. Dette kan kombineres med andre strøm-prosedyrer og strømmer, f.eks. (define primes (stream-filter prime? integers))? (stream-ref primes 3) 7
Uendelige strømmer 11 (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1)) En strøm kan definere en uendelig sekvens uten å faktisk beregne den. Dette kan kombineres med andre strøm-prosedyrer og strømmer, f.eks. (define primes (stream-filter prime? integers))? (stream-ref primes 3) 7 (define (add-streams stream1 stream2) (stream-map + stream1 stream2))
Uendelige strømmer 11 (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1)) En strøm kan definere en uendelig sekvens uten å faktisk beregne den. Dette kan kombineres med andre strøm-prosedyrer og strømmer, f.eks. (define primes (stream-filter prime? integers))? (stream-ref primes 3) 7 (define (add-streams stream1 stream2) (stream-map + stream1 stream2)) (define ones (cons-stream 1 ones))
Uendelige strømmer 11 (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1)) En strøm kan definere en uendelig sekvens uten å faktisk beregne den. Dette kan kombineres med andre strøm-prosedyrer og strømmer, f.eks. (define primes (stream-filter prime? integers))? (stream-ref primes 3) 7 (define (add-streams stream1 stream2) (stream-map + stream1 stream2)) (define ones (cons-stream 1 ones))
Uendelige strømmer 11 (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1)) En strøm kan definere en uendelig sekvens uten å faktisk beregne den. Dette kan kombineres med andre strøm-prosedyrer og strømmer, f.eks. (define primes (stream-filter prime? integers))? (stream-ref primes 3) 7 (define (add-streams stream1 stream2) (stream-map + stream1 stream2)) (define ones (cons-stream 1 ones)) (define integers (cons-stream 1 (add-streams ones integers)))
Previously on Twin Peaks: Fibonaccitall 12 For å illustrere nok en annen type rekursiv prosess skal vi se på en prosedyre for å beregne tall i den såkalte Fibonacci-rekken: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,... Bortsett fra de to første er hvert tall gitt som summen av de to foregående. 0 hvis n = 0 fib(n) = 1 hvis n = 1 fib(n 1) + fib(n 2) ellers
Previously on Twin Peaks: Fibonaccitall 12 For å illustrere nok en annen type rekursiv prosess skal vi se på en prosedyre for å beregne tall i den såkalte Fibonacci-rekken: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,... Bortsett fra de to første er hvert tall gitt som summen av de to foregående. 0 hvis n = 0 fib(n) = 1 hvis n = 1 fib(n 1) + fib(n 2) ellers? (define (fib n) (cond ((= n 0) 0) ((= n 1) 1) (else (+ (fib (- n 1)) (fib (- n 2))))))
Previously on Twin Peaks: Fibonaccitall 12 For å illustrere nok en annen type rekursiv prosess skal vi se på en prosedyre for å beregne tall i den såkalte Fibonacci-rekken: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,... Bortsett fra de to første er hvert tall gitt som summen av de to foregående. 0 hvis n = 0 fib(n) = 1 hvis n = 1 fib(n 1) + fib(n 2) ellers? (define (fib n) (cond ((= n 0) 0) ((= n 1) 1) (else (+ (fib (- n 1)) (fib (- n 2))))))? (fib 5) 5? (fib 6) 8? (fib 7) 13? (fib 8) 21? (fib 9) 34
Previously on Twin Peaks: Fibonaccitall 12 For å illustrere nok en annen type rekursiv prosess skal vi se på en prosedyre for å beregne tall i den såkalte Fibonacci-rekken: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,... Bortsett fra de to første er hvert tall gitt som summen av de to foregående. Litt mer liveprogrammering 0 hvis n = 0 fib(n) = 1 hvis n = 1 fib(n 1) + fib(n 2) ellers? (define (fib n) (cond ((= n 0) 0) ((= n 1) 1) (else (+ (fib (- n 1)) (fib (- n 2))))))? (fib 5) 5? (fib 6) 8? (fib 7) 13? (fib 8) 21? (fib 9) 34
Fibonacci-rekken som en uendelig strøm 13 Kjenner man til de to siste verdiene, kan neste verdi enkelt beregnes. Igjen, en rekursiv prosedyre som strøm-generator, med to argumenter. Prosedyreargumente tar vare på relevant historie: f (n 2) og f (n 1). (define (fib n) (define (generator x y) (cons-stream x (generator y (+ x y)))) (stream-ref (generator 0 1) n))? (fib 10) 55
Fibonacci-rekken som en uendelig strøm 13 Kjenner man til de to siste verdiene, kan neste verdi enkelt beregnes. Igjen, en rekursiv prosedyre som strøm-generator, med to argumenter. Prosedyreargumente tar vare på relevant historie: f (n 2) og f (n 1). (define (fib n) (define (generator x y) (cons-stream x (generator y (+ x y)))) (stream-ref (generator 0 1) n))? (fib 10) 55 Kan selvfølgelig også skrives som en ekvivalent prosedyre uten strøm. Men den har ikke like godt samsvar med den matematiske definisjonen.
Nok en strøm: Sielen til Eratosthenes 14 Også primtallene danner en uendelig sekvens: 2, 3, 5, 7, 11, 13, 17, 19,... Altså en strøm der ingen element er delbart på tidligere elementer. Kan modelleres som lag på lag av strømmer: hvert lag filtrerer videre: (define (sieve stream) (cons-stream (stream-car stream) (sieve (stream-filter (lambda (x) (not (divisible? x (stream-car stream)))) (stream-cdr stream))))) (define primes (sieve (integers-starting-from 2)))
Nok en strøm: Sielen til Eratosthenes Også primtallene danner en uendelig sekvens: 2, 3, 5, 7, 11, 13, 17, 19,... Altså en strøm der ingen element er delbart på tidligere elementer. Kan modelleres som lag på lag av strømmer: hvert lag filtrerer videre: (define (sieve stream) (cons-stream (stream-car stream) (sieve (stream-filter (lambda (x) (not (divisible? x (stream-car stream)))) (stream-cdr stream))))) (define primes (sieve (integers-starting-from 2)))? (stream-ref primes 3) 7 14