INF2810: Funksjonell Programmering

Like dokumenter
INF2810: Funksjonell Programmering. Muterbare data

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

INF2810: Funksjonell Programmering. Trær og mengder

INF2810: Funksjonell Programmering

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

INF2810: Funksjonell Programmering

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

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

INF2810: Funksjonell Programmering

Høyere-ordens prosedyrer

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

INF2810: Funksjonell Programmering. En metasirkulær evaluator

INF2810: Funksjonell Programmering. En metasirkulær evaluator

INF2810: Funksjonell Programmering. Eksamensforberedelser

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme

INF2810: Funksjonell Programmering. Kommentarer til prøveeksamen

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme

INF2810: Funksjonell Programmering. Strømmer og utsatt evaluering

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

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

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

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

INF2810: Funksjonell Programmering. Strømmer

INF2810: Funksjonell Programmering. Oppsummering og eksamensforberedelser

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

INF2810: Funksjonell Programmering. Huffman-koding

INF2810: Funksjonell Programmering. Huffman-koding

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

INF2810: Funksjonell Programmering. Muterbare data

INF2810: Funksjonell Programmering. Huffman-koding

UNIVERSITETET I OSLO

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

INF2810: Funksjonell Programmering. Huffman-koding

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

INF2810: Funksjonell Programmering. Mer om strømmer

INF2810: Funksjonell Programmering. Huffman-koding

Innlevering 2b i INF2810, vår 2017

Innlevering 2a i INF2810, vår 2017

INF2810: Funksjonell programmering: Introduksjon

INF2810: Funksjonell Programmering. Huffman-koding

INF2810: Funksjonell Programmering. Eksamensforberedelser

INF2810: Funksjonell programmering: Introduksjon

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

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

INF2810: Funksjonell Programmering. Lister og høyereordens prosedyrer

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

UNIVERSITETET I OSLO

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)

Informasjonsteori og entropi

INF2220: Forelesning 2. Balanserte søketrær Rød-svarte trær (kapittel12.2) B-trær (kapittel 4.7)

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

INF2220: Forelesning 2

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

INF2220: Forelesning 1. Praktisk informasjon Analyse av algoritmer (kapittel 2) (Binær)trær (kapittel )

Informasjonsteori og entropi

Memoisering, utsatt evaluering og strømmer

INF2220: Forelesning 2

Transkript:

INF2810: Funksjonell Programmering Omgivelsesmodeller og destruktive listeoperasjoner Stephan Oepen & Erik Velldal Universitetet i Oslo 15. mars 2013

Tema 2 Forrige uke Representasjon av mengder Sorterte lister og binære trær Lokal tilstand og assignment Prosedyrebasert objektorientering I dag The whole truth: omgivelser Destruktive listeoperasjoner Data-identitet vs. -ekvivalens

Representasjon av mengder: Binærtrær 3 Enda mer effektivt: {1, 3, 5, 7, 9, 11} som binærtre med ordnede noder. Hver node lagrer et element en venstre-gren med mindre elementer en høyre-gren med større elementer Ved søk etter et gitt element x: Hvis x er mindre enn node-oppslaget, søk til venstre. Hvis x er større, søk til høyre. Kan halvere søkerommet i hvert trinn: Logaritmisk vekst; O(log n). Må være litt obs på å holde treet (noenlunde) balansert.

Trær som lister og mengdeoperasjoner for binærtrær 4 To abstraksjonsbarrier (abstrakte datatyper) som bygger på hverandre: (define (make-tree entry left right) (list entry left right)) (define (tree-entry tree) (car tree)) (define (tree-left-branch tree) (cadr tree)) (define (tree-right-branch tree) (caddr tree)) (define (element-of-set? x set) (cond ((null? set) #f) ((= x (tree-entry set)) #t) ((< x (tree-entry set)) (element-of-set? x (tree-left-branch set))) ((> x (entry set)) (element-of-set? x (tree-right-branch set)))))

Tid og tilstand 5 Så langt ren funskjonell programmering: prosedyrer som funksjonelle (dvs. matematiske) transformasjoner av data; statisk over tid. Semantikken til et uttrykk er uavhengig av hvor og når det brukes. Gir stor grad av gjennomsiktighet (referential transparency). Fra kapittel 3 i SICP tar vi høyde for at uttrykk (og objekter ) kan inngå i en omgivelse som forandrer seg over tid. Sentrale konsepter: tilstand (state) og tilordning (assignment). Gir oss en form for (prosedyre-basert) objekt-orientering. Viktig teknikk for å organisere programmer: vi kan opprette objekter i programmene våre som tilsvarer entiteter i verden vi ønsker å modellere. Atferden avhenger av egenskaper som kan forandre seg over tid.

For eksempel: bankkonto 6 (define (make-withdraw initial) (let ((balance initial)) (lambda (amount) (cond ((>= balance amount) (set! balance (- balance amount)) balance) (else "Insufficient funds")))))? (make-withdraw 100) #<procedure>? (define w1 (make-withdraw 100))? (define w2 (make-withdraw 200))? (w1 50) 50? (w2 50) 150 Vi representerer kontoobjekter som prosedyrer. make-withdraw: En prosedyre for å generere nye konto-objekter. Returnerer en anonym prosedyre som innkapsler sin egen saldo-variabel: w1 og w2 er distinkte objekter, med distinkte lokale tilstandsvariabler. innkapsling kalles gjerne for closure utenfor SICP.

Destruktive operasjoner 7 I kapittel 3 i SICP tok vi et stort skritt: Med set! bryter vi med ren funksjonell programmering og introduserer elementer fra imperativ programmering: Verditilordning og tilstandsendring som modifiserer objekter. Kalles i noen sammenhenger fra et funksjonelt perspektiv for destruktive operasjoner. Når vi endrer tilstanden til et objekt destruerer vi det siden det ikke lenger representerer samme verdi. Til nå har vi kunnet tenke på variabler som navn på verdier. Fra nå må vi tenke på variabler som steder man kan lagre verdier. Bankkonto er en muterbar objekt, med både identitet og tilstand.

Prosedyre-basert objektorientering og message passing 8 (define (make-account) (let ((current 0)) (define (deposit amount) (set! current (+ current amount))) (define (withdraw amount) (deposit (- amount))) (define (balance) current) (define (dispatch message) (cond ((eq? message deposit) deposit) ((eq? message withdraw) withdraw) ((eq? message balance) balance))) dispatch))? (define erik (make-account))? (define oe (make-account))? ((oe deposit) 100)? ((oe balance)) 100? ((erik balance)) 0 Hvorfor kan vi ikke uten videre forenkle til f.eks. (oe deposit 100)?

På sidespor: dotted pairs vs. lister 9 Hvordan Scheme viser cons-celler:? (cons 1 2) (1. 2)? (cons 1 (cons 2 ())) (1 2)? (cons (list 1 2) 3) ((1 2). 3) I bunnen er (1 2 3) en cons-kjede (1. (2. (3. ()))); Er cdr-verdien et par sløyfer Scheme punktum og parentes:. (.? (1. (2. (3. ()))) (1 2 3) Dermed kan vi skrive prosedyrer som tar et variabel antall argumenter: (define (map fn. lists)...)

Polyadiske prosedyrer 10 (define (n-ary-append. lists) (define (recurse lists) (if (null? lists) () (append (car lists) (recurse (cdr lists))))) (recurse lists))? (n-ary-append (1 2) (3 4) (5 6)) (1 2 3 4 5 6) Men hvorfor trengs det egentlig den indre rekursive prosedyren? (define (n-ary-append. lists) (if (null? lists) () (append (car lists) (n-ary-append (cdr lists))))) Hva er verdien til lists-parameteret i første og andre oppkalling?

På en annen sidespor: identitet vs. ekvivalens 11? (define foo foo)? (define bar foo)? (eq? foo bar) #t? (eq? foo bar) #f? (define baz (1 2 3))? (eq? baz (1 2 3)) #f? (equal? baz (1 2 3)) #t? (equal? baz (1 (2) 3)) #f eq? tester identitet, som i Scheme tolkes som samme sted (i minne). equal? tester strukturell ekvivalens mellom (muligens nøstete) par; equal? kan lett implementeres som en polymorf rekursiv prosedyre.? (define mee baz)? (eq? mee baz) #t Flere (kalle)navn kan brukes for én og det samme objektet aliasing.

Hvordan teste for ekvivalens? (define (equal foo bar) (cond ((and (number? foo) (number? bar)) (= foo bar)) ((and (pair? foo) (pair? bar)) (and (equal (car foo) (car bar)) (equal (cdr foo) (cdr bar)))) (else (eq? foo bar)))) Men hva med identitet vs. ekvivalens mellom to prosedyrer?? (define erik (make-account))? (define oe (make-account))? (define liv oe)? (eq? erik oe) #f? (equal? erik oe) #f? (eq? liv oe) #t? ((oe withdraw) 100)? (eq? liv oe) #t 12

En gang i tid: substitusjonsmodellen 13 Prosedyrer evalueres på samme måte som beskrevet og praktisert tidligere. Først evalueres uttrykkene i argumentposisjon, deretter anvendes funksjonen. Vi kan tenke oss at funksjonsuttrykk skrives om på følgende måte: Hele uttrykket erstattes av prosedyrekroppen i definisjonen. Argumentnavnene i definisjonen erstattes av verdiene til uttrykkene i argumentposisjon. Dette kalles substitusjonsmodellen. Eksempel (define square (lambda (x) (* x x))) (square (+ 2 1)) (square 3) (* 3 3) 9

Substitusjonsmodellen passer ikke med muterbar data 14 (define (make-withdraw balance) (lambda (amount) (set! balance (- balance amount)) balance)) Vi må ta hensyn til at første argumentet til set! er spesielt; men ellers kan vi jo bare prøve å bruke den samme oppskriften: ((make-withdraw 25) 20) ((lambda (amount) (set! balance (- 25 amount)) 25) 20) (set! balance (- 25 20)) 25 (set! balance 5) 25 Den lokale variablen balance brukes tre ganger i prosedyrekroppen. Substitueres 2. og 3. bruk av balance samtidig blir resultatet feil.

Omgivelsesmodellen kan forklare alt 15 En omgivelse (environment) er en samling av rammer (frames); Hver ramme inneholder bindinger (bindings), dvs. navn, verdi -par; I tilleg har hver ramme en peker til sin omsluttende omgivelse; Prosedyreobjekter er par: prosedyrekoden koblet til en omgivelse.

Noen kommentarer til omgivelsesmodellen 16 SICP bruker ramme og omgivelse om hverandre noen steder. Evaluering av uttrykk kan nå defineres i forhold til en omgivelse. define og set! brukes for å etablere eller endre bindinger. Prosedyreoppkalling (og dermed også let) etablerer nye rammer. Rammer nøstes innenfor hverandre og danner så omsluttende rammer. Når et symbol evalueres finnes den nærmeste omsluttende bindingen. Nøstete bindinger for samme navnet overskygger (shadow) hverandre.

Repetisjon: omgivelsesmodellen og let? (define foo 42)? (let ((x foo) (y 1)) (list x y)) (42 1)? (let ((x foo) (y foo)) (list x y)) (42 42)? (let ((x foo) (y x)) (list x y)) error: x undefined? (let ((foo 7) (y foo)) (list foo y)) (7 42)? (let ((foo 7)) (let ((y foo)) (list foo y))) (7 7)? (let* ((foo 7) (y foo)) (list foo y)) (7 7) 17

Tilbake til innkapsling (1/3) 18 Innkapsling kan nå avmystifiseres på grunnlag av omgivelsesmodellen: (define (make-withdraw balance) (lambda (amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient Funds"))) (define w1 (make-withdraw 100)) Kroppen til make-withdraw returnerer et prosedyreobjekt (dvs. par); Oppkallingen av make-withdraw etablerer en ny ramme, som så blir omgivelsen til den anonyme prosedyren som lambda returnerer.

Tilbake til innkapsling (2/3) 19 Innkapsling: balance er kun tilgjengelig i omgivelsen E1, ikke globalt.

Tilbake til innkapsling (3/3) 20 Oppkalling av prosedyreobjektet w1 etablerer nok en ny ramme; som nøstes innenfor omgivelsen til w1 (med innkapsulert balance)