INF2810: Funksjonell Programmering. Utsatt evaluering og strømmer

Like dokumenter
INF2810: Funksjonell Programmering. Utsatt evaluering og strømmer

INF2810: Funksjonell Programmering. Utsatt evaluering og strømmer

INF2810: Funksjonell Programmering. Utsatt evaluering og strømmer

INF2810: Funksjonell Programmering. Mer om strømmer

INF2810: Funksjonell Programmering. Mer om strømmer

INF2810: Funksjonell Programmering. Strømmer og utsatt evaluering

INF2810: Funksjonell Programmering. Strømmer og utsatt evaluering

INF2810: Funksjonell Programmering. En metasirkulær evaluator, del 2

INF2810: Funksjonell Programmering. En metasirkulær evaluator, del 2

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

INF2810: Funksjonell Programmering. Kommentarer til prøveeksamen

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

INF2810: Funksjonell Programmering. Lokale variabler. Og trær.

INF2810: Funksjonell Programmering. Strømmer

INF2810: Funksjonell Programmering. Strømmer

INF2810: Funksjonell Programmering

INF2810: Funksjonell Programmering

INF2810: Funksjonell Programmering. Lokale variabler. Og trær.

INF2810: Funksjonell Programmering

INF2810: Funksjonell Programmering. Tilstand og verditilordning

INF2810: Funksjonell Programmering. Tilstand og verditilordning

INF2810: Funksjonell Programmering

INF2810: Funksjonell Programmering

INF2810: Funksjonell Programmering

INF2810: Funksjonell Programmering. Tilstand og verditilordning

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme

Rekursjon og lister. Stephan Oepen & Erik Velldal. 1. februar, Universitetet i Oslo

INF2810: Funksjonell Programmering. Eksamensforberedelser

INF2810: Funksjonell Programmering. Tilstand og verditilordning

INF2810: Funksjonell Programmering. En metasirkulær evaluator

INF2810: Funksjonell Programmering. Dataabstraksjon og Trerekursjon

INF2810: Funksjonell Programmering. En metasirkulær evaluator

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

INF2810: Funksjonell Programmering. Mer om verditilordning og muterbare data.

INF2810: Funksjonell Programmering. Mer om verditilordning og muterbare data.

INF2810: Funksjonell Programmering. Mer om verditilordning. Tabeller. Og strømmer.

INF2810: Funksjonell Programmering. Mer om verditilordning. Tabeller. Og strømmer.

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

INF2810: Funksjonell programmering: Mer om Scheme. Rekursjon og iterasjon.

Høyere-ordens prosedyrer

INF2810: Funksjonell Programmering. Muterbare data

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

INF2810: Funksjonell Programmering. Mengder og lokal tilstand

INF2810: Funksjonell Programmering. Trær og mengder

INF2810: Funksjonell Programmering. Køer, tabeller, og (litt om) parallelitet

INF2810: Funksjonell Programmering. Trær og mengder

INF2810: Funksjonell Programmering. Køer, tabeller, og (litt om) parallelitet

INF2810: Funksjonell Programmering. Mer om Scheme. Rekursjon og iterasjon.

INF2810: Funksjonell Programmering. Trær og mengder

Memoisering, utsatt evaluering og strømmer

Memoisering, utsatt evaluering og strømmer

INF2810: Funksjonell Programmering. Mer om Scheme. Rekursjon og iterasjon.

INF2810: Funksjonell Programmering. Mer om Scheme. Rekursjon og iterasjon.

Eksamen i SLI230, vår 2003.

Innlevering 2b i INF2810, vår 2017

Eksamen i HUMIT 2710, Funksjonell programmering, våren Ingen hjelpemidler er tillatt. <resten av forsiden> Side 1 av 7

INF2810: Funksjonell Programmering. Eksamensforberedelser

(define (naer-nok-kuberot? y x) (< (abs (- (kube y) x)) 0.001)) (define (naermere-kuberot y x) (/ (+ (* y 2) (/ x (kvadrat y))) 3))

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

Side 1. Oppgave 1. Prosedyrer 1.1. Prosedyrene f og g skal begge returnere prosedyrer. a. Skriv f slik at ((f a) b) returnerer summen av a og b.

Memoisering. I de følgende memoiseringeksemplene brukes tabeller, og vi tar derfor først en repetisjon av dette.

INF2810: Funksjonell programmering: Introduksjon

Appendiks A Kontinuasjoner

Vi skal se på lambda-uttrykk. Følgende er definerte og vil bli brukt gjennom oppgaven

UNIVERSITETET I OSLO

Gjennomgåelse av eksamensoppgaven i HUMIT2710 fra våren 2004

LISP PVV-kurs 25. oktober 2012

UNIVERSITETET I OSLO

Det er ikke tillatt med andre hjelpemidler enn de to sidene som er vedlagt oppgavesettet. Følgende funksjoner er definert og brukes i oppgaven:

Lisp 2: Lister og funksjoner

Moderne Funksjonell Programmering i Lisp

INF2810: Funksjonell Programmering. Muterbare data

INF2810: Funksjonell programmering: Introduksjon

Runtime-omgivelser Kap 7 - II

Kap.4 Funksjoner. Tre viktig ting ifm. funksjoner: parameter (input) oppskrift (body) for å beregne resultat (output)

Runtimesystemer - II. Parameteroverføring Call by value Call by reference Call by value-result Call by name INF 3110/ INF

Plan: Parameter-overføring Alias Typer (Ghezzi&Jazayeri kap.3 frem til 3.3.1) IN 211 Programmeringsspråk

INF2810: Funksjonell Programmering. Huffman-koding

INF2810: Funksjonell Programmering. Huffman-koding

Innlevering 2a i INF2810, vår 2017

INF2810: Funksjonell Programmering. Huffman-koding

INF2810: Funksjonell Programmering. Muterbare data

Haskell. Kjetil Ørbekk. Programvareverkstedet, 19. mars 2009

Repetisjon: Statiske språk uten rekursive metoder (C1 og C2) Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

INF2810: Funksjonell Programmering. Introduksjon

Par og Lister (først et par sider fra forrige uke) Par er byggestener for lister og trær og sammensatte datatyper.

INF2810: Funksjonell Programmering. Huffman-koding

TDT4165 PROGRAMMING LANGUAGES. Exercise 01 Introduksjon til Oz

2 Om statiske variable/konstanter og statiske metoder.

Oversikt. Introduksjon Kildekode Kompilering Hello world Hello world med argumenter. 1 C programmering. 2 Funksjoner. 3 Datatyper. 4 Pekere og arrays

Sideeekter og makroer i Lisp

Transkript:

INF2810: Funksjonell Programmering Utsatt evaluering og strømmer Stephan oepen Universitetet i Oslo 6. april 2017

Tema 2 Forrige gang Ny datastruktur, ny teknikk: Strømmer Utsatt evaluering I dag Uendelige sekvenser Mer om utsatt evaluering...... og strømmer Makroer: syntaktiske transformasjoner Tid og tilstand

Repetisjon: Utsatt evaluering 3 I stedet for å umiddelbart evaluere et uttrykk kan vi representere et løfte (promise) om at det kan evalueres senere dersom verdien trengs. Løftet kan representeres ved å pakke uttrykket inn i en anonym prosedyrekropp uten parametre, som så kan innfris ved å kalles. (delay exp) (lambda () exp) Slike innkapslinger (closures) kalles noen ganger thunks. Prosedyreobjektet har en peker til omgivelsen der det opprettes slik at vi kan finne verdiene til uttrykkets frie variabler ved evaluering.? (define p (let ((foo 42)) (delay (* foo 2))))? (force p) 84? (define p (let ((foo 42)) (lambda () (* foo 2))))? (p) 84

Repetisjon: Utsatt evaluering 4 Evalueringsstrategien i Scheme er i call-by-value / eager evaluation. Kan bruke teknikken over for å implementere en form for call-by-name. Risikerer å måtte evaluere samme uttrykk flere ganger. Kan optimeres med memoisering: call-by-need / lazy evaluation. (delay exp) (memoize (lambda () exp)) (delay som er innebygget i Scheme er memoisert.) Uttrykket evalueres kun én gang og verdien lagres for gjenbruk. Både utsatt evaluering og memoisering (og dermed strømmer) går dårlig sammen med side-effekter: bør brukes med funksjonell kode.

Å definere special forms 5 Vi har så langt beskrevet delay med -notasjon. Men hva om vi selv ønsker å implementere dette? For å definere våre egne special forms trengs det noe mer enn define. Makroer: Syntaktisk omskriving av Scheme-uttrykk. Lar oss transformere kode før den blir evaluert eller kompilert. Kode som genererer kode!

Syntaktisk omskriving med makroer 6 Et Scheme-uttrykk kan dekomponeres og omskrives før evaluering. (delay exp) (memoize (lambda () exp)) Dette kan implementeres ved define-syntax og syntax-rules: (define-syntax delay (syntax-rules () ((delay exp) (memoize (lambda () exp))))) syntax-rules definerer mønstre og ekspansjoner. Når Scheme ser et uttrykk som begynner med delay vil det nå skrives om ( ekspanderes ) til uttrykket på høyresiden før det evalueres.

Hygieniske makroer 7 (define-syntax identifier (syntax-rules ( keyword * ) ( pattern expansion )...)) identifier i operatorposisjon vil fra nå av ekspanderes som makro. pattern brukes for å bryte opp uttrykket og binde parameterne. expansion er oppskriften for å sette sammen bitene igjen. keyword kan deklarere syntaktiske nøkkelord (f.eks else i cond). Kalles for hygieniske makroer : Har garanti for at eksisterende bindinger ikke overskygges av variabler som introduseres i ekspansjonen (accidental capture).

Enkelt makroeksempel: when 8 Makroer lar oss gjøre ting vi ikke kan gjøre med vanlige prosedyrer. Kan utvide syntaksen til språket.? (define-syntax when (syntax-rules () ((when condition. body) (if condition (begin. body)))))? (when (> -2 100) (display "I was evaluated!\n") 42)? (when (> 3 1) (display "I was evaluated!\n") 42) I was evaluated! 42 Umulig å skrive when som vanlig prosedyre. (Prøv!)

Enkelt makroeksempel: when 9 En annen variant som viser bruk av syntaktiske keywords.? (define-syntax when (syntax-rules (do else) ((when condition do body1 else body2) (if condition body1 body2))))? (when (< 2 1) do (display "this") else (display "that")) that

Repetisjon: Strømmer via utsatt evaluering 10 Strømmer: en sentral datastruktur i funksjonell programmering. Kan tenke på dem som utsatte lister / lazy lists: En sekvensiell datastruktur der elementene realiseres ved behov. cons-stream utsetter evaluering av cdr-uttrykket. En special form som bruker delay på cdr-argumentet. stream-cdr tvinger evaluering.? (cons-stream (+ 1 2) (+ 3 4)) (3. #<promise>)? (stream-cdr (cons-stream (+ 1 2) (+ 3 4))) 7

Strømmer implementert via utsatt evaluering Kan implementre cons-stream med en makro: (define-syntax cons-stream (syntax-rules () ((cons-stream head tail) (cons head (delay tail))))) Resten av strømgrensesnittet kan defineres som vanlige prosedyrer: (define (stream-car stream) (car stream)) (define (stream-cdr stream) (force (cdr stream))) (define (stream-null? stream) (null? stream)) (define the-empty-stream '()) ;; en konstant 11

Hvor mange cons-celler genereres? 12 (define (stream-interval lo hi) (if (> lo hi) the-empty-stream (cons-stream lo (stream-interval (+ lo 1) hi))))? (stream-car (stream-cdr (stream-interval 1 1000))) (define (interval lo hi) (if (> lo hi) '() (cons lo (interval (+ lo 1) hi))))? (car (cdr (interval 1 1000)))

Strømmer og sekvensmanipulasjon 13? (reduce + 0 (filter prime? (interval 100 100000))) Mange beregninger kan formuleres som sekvensmanipulasjoner. En av hovedfordelene: modularitet. Komplekse operasjoner kan deles opp i flere mindre komponenter, med delvis prosesserte sekvenser som midlertidig resultat. Med lister må vi holde hele strukturen i minnet samtidig. Med strømmer kan vi jobbe på ett og ett element av gangen. Trenger ikke vente på at ett trinn er ferdig før neste begynner. Jf. pipeline av Un*x-kommandoer: $ cat big.data grep query sort more

Repetisjon: Uendelige strømmer 14 Vi har sett at en strøm er en sekvens som konstrueres mens den brukes. Kan dermed definere en uendelig sekvens, uten å faktisk beregne den. De naturlige tallene via en rekursiv strømgenerator:? (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1))))? (define nats (integers-starting-from 1)) Veldefinert pga utsatt evaluering. Hva mangler i forhold til rekursjonen vi har sett før? Hva ville skjedd om vi brukte cons? Kan kombineres med andre strømprosedyrer og strømmer, f.eks.? (define odds (stream-filter odd? nats))? (show-stream odds 5) 1 3 5 7 9...

Uendelige strømmer (forts.) Kan også definere uendelige strømmer direkte ved å la strømmen referere til seg selv rekursivt. (SICP: implisitt strømdefinisjon ) Veldefinert pga utsatt evaluering.? (define ones (cons-stream 1 ones))? (define ones (cons 1 ones)) ones: undefined; error? (define (add-streams stream1 stream2) (stream-map + stream1 stream2))? (define nats (cons-stream 1 (add-streams ones nats))) Definisjonen av nats her fungerer fordi akkurat nok av strømmen er konstruert til at vi kan bruke den rekursivt i add-streams: 2. element = 1. element + én 3. element = 2. element + én osv. 15

Repetisjon: Fibonaccitall 16 0 hvis n = 0 fib(n) = 1 hvis n = 1 fib(n 1) + fib(n 2) ellers Illustrerte trerekursive prosesser med en prosedyre for å beregne tall i Fibonacci-rekken: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144... Bortsett fra de to første er hvert tall summen av de to foregående.? (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 ;; = 5 + 8? (fib 8) 21 ;; = 8 + 13? (fib 9) 34 ;; = 13 + 21

Fibonaccitallene som en uendelig strøm 17 Kan bruke samme triks som for nats til å definere fibonaccirekken som en uendelig strøm fibs. Sørger for at akkurat nok av fibs finnes til at den kan brukes rekursivt:? (define fibs (cons-stream 0 (cons-stream 1 (add-stream fibs (stream-cdr fibs)))))? (show-stream fibs 20) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181.? (stream-ref fibs 9) 34 Antall addisjoner for det nte elementet i strømmen (SICP 3.57): Dersom delay er implementert med memoisering: Lineær. Uten: Eksponentiell.

Uendelige strømmer, fallgruver 18 Har sett at de fleste listeoperasjoner enkelt kan oversettes til strømmer. Og alle vanlige strømoperasjoner fungerer også for uendelige strømmer. Vi må likevel å ha tunga rett i munnen. Hva blir utfallet her:? (stream-null? (stream-filter odd? (stream-filter even? nats))) stream-null? vil aldri bli kalt: det yttereste kallet på stream-filter returnerer aldri.

Uendelige strømmer, fallgruver (forts.) 19 Kan du se noen problemer som kan oppstå med stream-append? (define (stream-append s1 s2) (if (stream-null? s1) s2 (cons-stream (stream-car s1) (stream-append (stream-cdr s1) s2)))) Hvis s1 er uendelig får vi aldri se elementer fra s2. Uendelige strømmer bør kombineres på andre måter, f.eks med; (define (stream-interleave s1 s2) (if (stream-null? s1) s2 (cons-stream (stream-car s1) (stream-interleave s2 (stream-cdr s1)))))

Strømmer og lister 20 Med lister så får vi levert dataene på en pall: alt på en gang. Med strømmer får vi dataene våre på et samlebånd: én av gangen. Lar oss jobbe med (konseptuelt) lange sekvenser uten å måtte holde hele strukturen i minnet samtidig. Avveining: plass vs tid. Strømmer mer komplekse: brukes når vi har uendelige eller veldig lange sekvenser som det ikke er praktisk eller mulig å lagre i minnet.

Strømmer, tid og tilstand 21 (define (input-stream) (cons-stream (read) (input-stream))) (define balances (cons-stream 100 (add-streams balances (input-stream))))? (show-stream balances 5)??? Funksjonell kode (minus set! i memoize). Likevel vil det for en bruker virke som at systemet som helhet her har tilstand, som forandrer seg over tid: Ser en oppdatert saldo for hvert innskudd på kontoen. Jf. de tidligere kontooperasjonene våre med (set! balance...)

Et anvendt eksempel: CMA 22 Cumulative Moving Average (CMA): Et løpende oppdatert gjennomsnitt for en strøm av tidsdata: x 1, x 2, x 3, x 4,.... Typisk eksempel: en investor vil vite snittpris for en aksje over tid. CMA er gjennomsnittet for alle dataene opp til nåværende tidspunkt: CMA i = x 1 + x 2 +... + x i i Kan oppdateres fortløpende etterhvert som mer data kommer inn: CMA i+1 = x i+1 + icma i i + 1 hvor CMA 0 = 0 (define (moving-average stream) (define (generate s prev i) (let ((new (/ (+ (stream-car s) (* i prev)) (+ i 1.0)))) (cons-stream new (generate (stream-cdr s) new (+ i 1))))) (generate stream 0 0))

Et anvendt eksempel: CMA (forts.) 23 (define (moving-average stream) (define (generate s prev i) (let ((new (/ (+ (stream-car s) (* i prev)) (+ i 1.0)))) (cons-stream new (generate (stream-cdr s) new (+ i 1))))) (generate stream 0 0))? (define avg-nats (moving-average nats))? (show-stream avg-nats 10) 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5...? (show-stream nats 10) 1 2 3 4 5 6 7 8 9 10... Strøm av løpende oppdaterte gjennomsnitt for saldo over tid:? (define avg-balance (moving-average balances))

Objekter, strømmer, tid og tilstand 24 To nye programmeringsstrategier i kap. 3: Objekter med lokal tilstand Organiserer programmet som distinkte objekter med egenskaper som kan forandre seg over tid. Modellen forsøkt inndelt på samme måte som vi oppfatter verden. Tilstand og endring i verden modellert med tilstandsvariabler og verditilordning. Simulert tid gitt ved evaluering. Strømmer Organiserer programmet som strømmer av informasjon som flyter mellom ulike komponenter. Deler opp og representerer tid eksplisitt: som distinkte punkter i en sekvens av hendelser. Simulert tid sammenfaller ikke nødvendigvis med evaluering.

Ny oblig 25 Oblig (3a) med prekode kommer trolig i morgen. Frist: 28. april. Hovedfokus: strømmer + språkmodeller. (3a)

Neste gang 26 Metalingvistisk abstraksjon Metasirkulær evaluator Enklere enn det høres ut! Vi ser på en evaluator for Scheme, skrevet i Scheme.