19
INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 Stephan Oepen & Erik Velldal Universitetet i Oslo 03. mai 2013

INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

  • Upload
    others

  • View
    22

  • Download
    0

Embed Size (px)

Citation preview

Page 1: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

INF2810: Funksjonell programmering

INF2810: Funksjonell Programmering

En metasirkulær evaluator, del 2

Stephan Oepen & Erik Velldal

Universitetet i Oslo

03. mai 2013

Page 2: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Tema

Forrige ukeI SICP 4.1.I Structure and interpretation ofcomputer programs

I “Metacircular evaluator”I Scheme-evaluator skrevet i SchemeI Omgivelsesmodellen

I dagI Vi skal se litt mer på koden fra 4.1 og alternativ syntaks.I SICP 4.2 og alternativ semantikk; lazy evaluation.

2

Page 3: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

En parentes:

I Mye av denne forelesningen vil som sist være basert på at vi sammengår igjennom kode i evaluator.scm med kjøringseksempler.

I http://www.uio.no/studier/emner/matnat/ifi/INF2810/v13/

undervisningsmateriale/evaluator.scm

3

Page 4: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

En evaluator for Scheme, i Scheme

I Evaluator (interpreter) –et program som tolker og utføreret program.

I Metasirkulær evaluator –en evaluator skrevet i sammespråket som den skal evaluere.

MotivasjonI Gjør omgivelsesmodellen eksplisitt gjennom en konkret implementasjon.I Bedre forståelse for hvordan ulike uttrykk evalueres.I Lar oss eksperimentere med alternativ syntaks og alternativ semantikk.I Viser hvordan program er data.

4

Page 5: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Program = data

I Evaluatoren vår er en prosedyre som tar kode som argument.

I Men for evaluatoren er koden bare symbolske data som vi kanmanipulere på vanlig måte.

I Grunnen til at vi kaller den metasirkulære evaluatoren vår mc-eval erat Scheme selv allerede gir oss direkte tilgang til den underliggendeevaluatoren sin via den innebygde eval:

? (let* ((args ’(1 2 3))(proc ’+)(exp (cons proc args)))

(display exp) (newline)(eval exp (interaction-environment)))

; (+ 1 2 3)→ 6

5

Page 6: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Delene i den metasirkulære evaluatoren

I Datastrukturer for å representere omgivelser og prosedyreobjekter.

I Predikater og aksessorer som definerer syntaksen til uttrykk i språket.I mc-eval og mc-apply

I Med spesialiserte varianter for evaluering av special forms.I Definerer semantikken.

I Mekanisme for å kalle primitive / innebygde prosedyrer.

I REPL

6

Page 7: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Gjensidig rekursjon

Kjernen i evaluatorenI eval; tar et uttrykk og en omgivelse, evaluerer del-uttrykkene rekursivt,og kaller apply med en prosedyre og argumenter.

I apply; tar en prosedyre og argumenter, og kaller eval med nye uttrykkog en ny omgivelse.

7

Page 8: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

To typer evaluering

I Eager evaluation

I Eller applicative-order evaluation/ strict evaluation.

I Argumentene evalueres før enprosedyre anvendes.

(Sussman)

I Lazy evaluation

I Eller normal-order evaluation /non-strict evaluation.

I Evaluering av argumenteneutsettes til vi faktisk trengerverdiene deres.

(Abelson) 8

Page 9: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Evalueringsstrategier: eager vs. lazy

I Eager evaluation er standardstrategien i Scheme.

I Kalles også call-by-value.

I Men i visse tilfeller brukes lazy evaluation:

I Ved special-forms, som if, and og or.

? (define (foo) (foo))

? (if (= 0 1) (foo) ’bar) → bar

9

Page 10: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Evalueringsstrategier: eager vs. lazy

? (define (foo) (foo))

? (define (proc-if test then-do else-do)(if test then-do else-do))

? (proc-if (= 0 1) (foo) ’bar) → ??

I Kallet på proc-if vil her gi en uendelig løkke under eager evaluation.

I Men fungerer fint under lazy evaluation.

I Lazy evaluation gjør det også mulig å jobbe med uendeligedatastrukturer, som strømmer.

10

Page 11: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Lazy evaluation

I I noen varianter av normal-order evaluation re-evalueres uttrykkene hvergang de brukes (call-by-name).

I Men lazy evaluation inkluderer gjerne også memoisering:I Argument-uttrykk evalueres kun når de trengs og maksimalt én gang.I Ved evaluering lagres verdien for mulig gjenbruk senere.I Call-by-need

I Vi skal gjøre Scheme-evaluatoren vår lazy.I I stedet for å evaluere argumentene før et prosedyrekall pakker vi sammenuttrykkene og kall-omgivelsen slik at de kan evalueres senere.

I Vi trenger altså en måte å “fryse” uttrykk på.I (Gjelder kun ikke-primitive prosedyrer.)

11

Page 12: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Thunks

(define (delay-it exp env)(list ’thunk exp env))

(define (thunk? obj)(tagged-list? obj ’thunk))

(define (thunk-exp thunk)(cadr thunk))

(define (thunk-env thunk)(caddr thunk))

(define (evaluated-thunk? obj)(tagged-list? obj ’evaluated-thunk))

(define (thunk-value evaluated-thunk)(cadr evaluated-thunk))

I Representerer uttrykk som thunks.I Liste av taggen ’thunk, selveuttrykket, og omgivelsen.

I Thunk som allerede har blittevaluert (og verdien memoisert):

I Taggen ’evaluated-thunk

I og verdien til uttrykket.I Trenger ikke huske omgivelsen.

12

Page 13: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Thunks

(define (force-it obj)(cond ((thunk? obj)

(let ((result (actual-value ; evaluer uttrykket.(thunk-exp obj)(thunk-env obj))))

(set-car! obj ’evaluated-thunk)(set-car! (cdr obj) result) ; erstatter uttrykk med verdi.(set-cdr! (cdr obj) ’()) ; glem omgivelsen.result))

((evaluated-thunk? obj) ; memoisert?(thunk-value obj))

(else obj))) ; ikke en thunk.

(define (actual-value exp env)(force-it (mc-eval exp env)))

; gjensidig rekursjon: actual-value kaller force-it igjen; i tilfelle mc-eval returnerer en ny thunk.

13

Page 14: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Lazy Scheme

I Med thunks har vi nå en måte å “fryse” uttrykk på.

I Så må dette plugges inn i eval / apply.I Generelt kan vi si at uttrykk kun trenger å evalueres dersom de er

I argumentene til primitive prosedyrer,I predikatet vi skal teste i en kontrollstruktur, ellerI operatoren vi skal til å anvende i et prosedyrekall.

14

Page 15: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

mc-eval

(define (mc-eval exp env)(cond ((self-evaluating? exp) exp)

((variable? exp) (lookup-variable-value exp env))((special-form? exp) (eval-special-form exp env))((application? exp)(apply (actual-value (operator exp) env)

(operands exp) ;; selve uttrykkene, ikke verdieneenv))))

15

Page 16: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

mc-apply

(define (apply proc args env)(cond ((primitive-procedure? proc)

(apply-primitive-procedureproc (list-of-arg-values args env))) ; henter faktiske verdier

((compound-procedure? proc)(eval-sequence(procedure-body proc)(extend-environment(procedure-parameters proc)(list-of-delayed-args args env) ; lager thunks(procedure-environment proc))))))

(define (list-of-arg-values exps env)(if (no-operands? exps) ’()

(cons (actual-value (first-operand exps) env)(list-of-arg-values (rest-operands exps) env))))

(define (list-of-delayed-args exps env)(if (no-operands? exps) ’()

(cons (delay-it (first-operand exps) env)(list-of-delayed-args (rest-operands exps) env))))

16

Page 17: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

NB

I Vanskelig å forutsi rekkefølgen på operasjoner.

I Lazy evaluation i kombinasjon med prosedyrer som har side-effekter kandermed være forvirrende.

I Forventet effekt kan utebli fordi et uttrykk ikke har blitt evaluert ennå.

I Et av få språk med lazy evaluation som standardstrategi er Haskell.

I Et mere rent funksjonelt språk.

17

Page 18: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Strømmer som late lister

I Tidligere har vi implementert strømmer som “utsatte” lister:I Brukte special forms delay og cons-stream.I Trenger ikke lenger skille mellom strømmer og lister:I La cons bruke lazy evaluation.I I så fall må vi enten la evaluatoren støtte ikke-strikte primitiver ellerimplementere cons som en ikke-primitiv.

I Som vi har sett tidligere kan par f.eks representeres som prosedyrer:

(define (cons x y)(lambda (m) (m x y)))

(define (car z)(z (lambda (p q) p)))

(define (cdr z)(z (lambda (p q) q)))

18

Page 19: INF2810: Funksjonell Programmering€¦ · INF2810: Funksjonell programmering INF2810: Funksjonell Programmering En metasirkulær evaluator, del 2 StephanOepen&ErikVelldal Universitetet

Neste gang

I Om tre uker: 24/5

I Eksamensforberedelser

I Oppsummeringλ19