Ohjelmoinnin peruskurssien laaja oppimäärä

Samankaltaiset tiedostot
Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 3

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 5

Scheme-kesäkurssi luento 4

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 1

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 2

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

Ohjelmoinnin peruskurssien laaja oppimäärä

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Hohde Consulting 2004

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 6

815338A Ohjelmointikielten periaatteet

Makrojen mystinen maailma lyhyt oppimäärä

Se mistä tilasta aloitetaan, merkitään tyhjästä tulevalla nuolella. Yllä olevassa esimerkissä aloitustila on A.

Luento 5. Timo Savola. 28. huhtikuuta 2006

Ohjelmoinnin perusteet Y Python

C++11 lambdat: [](){} Matti Rintala

Ohjelmointikieli TIE Principles of Programming Languages Syksy 2017 Ryhmä 19

Ohjelmointiharjoituksia Arduino-ympäristössä

Ohjelmointi 1 C#, kevät 2013, 2. tentti

Luento 4 Aliohjelmien toteutus

7/20: Paketti kasassa ensimmäistä kertaa

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Jakso 4 Aliohjelmien toteutus

ICS-C2000 Tietojenkäsittelyteoria Kevät 2016

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

Ohjelmoinnin peruskurssi Y1

A TIETORAKENTEET JA ALGORITMIT

Geneeriset tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

Ohjelmoinnin peruskurssien laaja oppimäärä, kevät

Taas laskin. TIES341 Funktio ohjelmointi 2 Kevät 2006

tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla

Luento 4 Aliohjelmien toteutus

Algoritmit 1. Demot Timo Männikkö

11/20: Konepelti auki

1.3Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Ohjelmoinnin peruskurssien laaja oppimäärä

Olio-ohjelmointi Syntaksikokoelma

List-luokan soveltamista. Listaan lisääminen Listan läpikäynti Listasta etsiminen Listan sisällön muuttaminen Listasta poistaminen Listan kopioiminen

13. Loogiset operaatiot 13.1

TIEP114 Tietokoneen rakenne ja arkkitehtuuri, 3 op. Assembly ja konekieli

Tietorakenteet ja algoritmit - syksy

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Tieto ja sen osoite (3) Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI) Osoitinmuuttujat. Tieto ja sen osoite (5)

Luento 4 Aliohjelmien toteutus

Funktionaalinen ohjelmointi

DATA-vaiheen ohjelmoijan yleissivistys helposti unohtuvia asioita

linux: Ympäristömuuttujat

Jakso 3 Konekielinen ohjelmointi (TTK-91, KOKSI)

5.5 Jäsenninkombinaattoreista

13. Loogiset operaatiot 13.1

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

Tehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003

Algoritmit 1. Luento 4 Ke Timo Männikkö

C++11 Syntaksi. Jari-Pekka Voutilainen Jari-Pekka Voutilainen: C++11 Syntaksi

Ohjelmoinnin perusteet Y Python

Jakso 4 Aliohjelmien toteutus

Jakso 4 Aliohjelmien toteutus

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 5: Python

Ehto- ja toistolauseet

Jakso 4 Aliohjelmien toteutus. Tyypit Parametrit Aktivointitietue (AT) AT-pino Rekursio

SIMULINK S-funktiot. SIMULINK S-funktiot

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Sisältö. 2. Taulukot. Yleistä. Yleistä

Racket ohjelmointia osa 2. Tiina Partanen Lielahden koulu 2014

Tietorakenteet ja algoritmit

Transkriptio:

Ohjelmoinnin peruskurssien laaja oppimäärä Luento 8: Tulkki: proseduurit, abstrakti syntaksi, quote ja cond (mm. SICP 44.1.5 osin) Riku Saikkonen 15. 11. 2011

Sisältö 1 Argumentittomat proseduurit ja käyttöliittymä 2 Abstrakti syntaksi ja env-argumentti 3 Lisäabstraktio evaliin 4 quote ja cond

Lisätään argumentittomat proseduurit ja begin 1/2 lisätään tulkkiimme proseduurit (taas Schemen näköisellä syntaksilla), mutta ei mietitä paikallisia muuttujia vielä tällä tulkilla voi teoriassa jo laskea mitä tahansa (sillä tulkattava kieli on Turing-täydellinen, jos numeroarvoilla ei ole ylärajaa), mutta pelkillä globaaleilla muuttujilla koodi on BASIC-mäistä... Testiajoja (koodi seuraavalla kalvolla) nelilaskin6.scm (eval '(define fact-iter ; vrt. factorial SICP 3.1.3:n lopussa (lambda () ; argumenttilistaa ei vielä käytetä mihinkään (if (> c n) p (begin (set! p (* c p)) (set! c (+ c 1)) (fact-iter)))))) (eval '(define p 1)) (eval '(define c 1)) (eval '(define n 5)) (eval '(fact-iter)) 120

Lisätään argumentittomat proseduurit ja begin 2/2 Muutokset edelliseen koodiin (tämä riittää!) nelilaskin6.scm (define (eval-sequence exps) ; suorittaa exps-lausekkeet järjestyksessä (cond ((null? (cdr exps)) ; onko viimeinen lauseke? (eval (car exps))) (else (eval (car exps)) (eval-sequence (cdr exps))))) (define (eval exp) (cond... ((and (pair? exp) (eq? (car exp) 'lambda)) (list 'procedure (cddr exp))) ; proseduurin ''arvo'' ((and (pair? exp) (eq? (car exp) 'begin)) (eval-sequence (cdr exp))) ((pair? exp) (let ((proc (eval (car exp)))) (if (and (pair? proc) (eq? (car proc) 'procedure)) (eval-sequence (cadr proc)) (proc (eval (cadr exp)) (eval (caddr exp))))))... ))

Lisätään vielä käyttöliittymä (SICP 4.1.4) jotta tulkkimme näyttäisi tulkilta, lisätään siihen vielä käyttöliittymä eli silmukka, joka lukee lausekkeen, suorittaa sen, ja kertoo laskennan tuloksen eli paluuarvon Schemessä (Lispissä) tällainen on nimeltään readevalprint loop tämä on helppoa, koska Schemessä on read-primitiivi Lisäyksiä edelliseen koodiin nelilaskin7.scm (define input-prompt ";;; Eval input:") (define output-prompt ";;; Eval value:") (define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (eval input))) (announce-output output-prompt) (display output))) (driver-loop)) (define (prompt-for-input string) (newline) (newline) (display string) (newline)) (define (announce-output string) (newline) (display string) (newline))

Sisältö 1 Argumentittomat proseduurit ja käyttöliittymä 2 Abstrakti syntaksi ja env-argumentti 3 Lisäabstraktio evaliin 4 quote ja cond

Mitä seuraavaksi? tehdään seuraavaksi edellisen luennon tulkkiin abstraktiot tulkattavan kielen syntaksin käsittelylle, jotta syntaksia olisi periaatteessa helppo muuttaa samalla koodi muuttuu lähemmäs SICP-kirjan tulkin koodia... pidetään tulkin toiminta muuten täsmälleen samana, mutta lisätään tässä samalla tuki: else-haarattomalle if:lle (palauttaa false) primitiiveille, joilla on enemmän tai vähemmän kuin kaksi argumenttia (define (f)...)-syntaksille: kuten Schemessä, se on sama kuin (define f (lambda ()...)) luovutaan myös globaaleista muuttujista variable-names ja variable-values ja kuljetetaan niitä tulkkiproseduurien uudessa argumentissa env toistaiseksi env osoittaa koko ajan samaan tietorakenteeseen (tätä muokataan myöhemmin paikallisten muuttujien tukemiseksi)

Entinen eval Koko eval ennen tätä muutosta nelilaskin7.scm (define (eval exp) (cond ((number? exp) exp) ((symbol? exp) (lookup-variable-value exp)) ((and (pair? exp) (eq? (car exp) 'set!)) (set-variable-value! (cadr exp) (eval (caddr exp)))) ((and (pair? exp) (eq? (car exp) 'define)) (define-variable! (cadr exp) (eval (caddr exp)))) ((and (pair? exp) (eq? (car exp) 'if)) (if (true? (eval (cadr exp))) (eval (caddr exp)) (eval (cadddr exp)))) ((and (pair? exp) (eq? (car exp) 'lambda)) (list 'procedure (cddr exp))) ((and (pair? exp) (eq? (car exp) 'begin)) (eval-sequence (cdr exp))) ((pair? exp) (let ((proc (eval (car exp)))) (if (and (pair? proc) (eq? (car proc) 'procedure)) (eval-sequence (cadr proc)) (proc (eval (cadr exp)) (eval (caddr exp)))))) (else (error "Invalid expression -- EVAL" exp))))

Uusi eval Koko eval tämän muutoksen jälkeen nelilaskin8.scm (define (eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env)) ((assignment? exp) (set-variable-value! (assignment-variable exp) (eval (assignment-value exp) env) env)) ((definition? exp) (define-variable! (definition-variable exp) (eval (definition-value exp) env) env)) ((if? exp) (if (true? (eval (if-predicate exp) env)) (eval (if-consequent exp) env) (eval (if-alternative exp) env))) ((lambda? exp) (make-procedure (lambda-body exp))) ((begin? exp) (eval-sequence (begin-actions exp) env)) ((application? exp) (let ((proc (eval (operator exp) env))) (if (compound-procedure? proc) (eval-sequence (procedure-body proc) env) (apply proc (map (lambda (exp) (eval exp env)) (operands exp)))))) (else (error "Unknown expression type -- EVAL" exp))))

Syntaksiabstraktioita 1/3 (SICP 4.1.2) Evalin apuproseduureja (samoja kuin kirjassa) nelilaskin8.scm (define (self-evaluating? exp) (cond ((number? exp) true) ((string? exp) true) (else false))) (define (variable? exp) (symbol? exp)) (define (tagged-list? exp tag) (if (pair? exp) (eq? (car exp) tag) false)) (define (assignment? exp) (tagged-list? exp 'set!)) (define (assignment-variable exp) (cadr exp)) (define (assignment-value exp) (caddr exp)) (define (definition? exp) (tagged-list? exp 'define)) (define (definition-variable exp) (if (symbol? (cadr exp)) (cadr exp) ; esim. (define a 3) a (caadr exp))) ; esim. (define (f) 5) f (define (definition-value exp) (if (symbol? (cadr exp)) (caddr exp) (make-lambda (cdadr exp) (cddr exp))))

Syntaksiabstraktioita 2/3 (SICP 4.1.1, 4.1.2) Evalin apuproseduureja (samoja kuin kirjassa) nelilaskin8.scm (define (true? x) (not (eq? x false))) (define (if? exp) (tagged-list? exp 'if)) (define (if-predicate exp) (cadr exp)) (define (if-consequent exp) (caddr exp)) (define (if-alternative exp) (if (not (null? (cdddr exp))) ; onko else-haaraa? (cadddr exp) 'false)) ; 'false on tulkattavan kielen koodia! (define (begin? exp) (tagged-list? exp 'begin)) (define (begin-actions exp) (cdr exp)) (define (last-exp? seq) (null? (cdr seq))) (define (first-exp seq) (car seq)) (define (rest-exps seq) (cdr seq)) (define (eval-sequence exps env) (cond ((last-exp? exps) (eval (first-exp exps) env)) (else (eval (first-exp exps) env) (eval-sequence (rest-exps exps) env)))) (define (application? exp) (pair? exp)) (define (operator exp) (car exp)) (define (operands exp) (cdr exp))

Syntaksiabstraktioita 3/3 (SICP 4.1.2, 4.1.3) Evalin apuproseduureja (eri kuin kirjassa) nelilaskin8.scm ;; Tulkattavan kielen lambda-lauseke (define (lambda? exp) (tagged-list? exp 'lambda)) (define (lambda-body exp) (cddr exp)) (define (make-lambda parameters body) (cons 'lambda (cons parameters body))) ;; Tulkin muistiin talletettu proseduuriolio (define (compound-procedure? p) (tagged-list? p 'procedure)) (define (procedure-body p) (cadr p)) (define (make-procedure body) (list 'procedure body)) nämä ovat vielä erilaisia kuin kirjassa, koska argumentteja ja paikallisia muuttujia ei tueta niitä varten make-procedure:n pitäisi liittää proseduuriin paikallisten muuttujien arvot eli nk. ympäristö

Primitiivit ja globaalit muuttujat 1/2 siirrytään siis globaaleista muuttujista variable-names ja variable-values tietorakenteeseen env env on vielä erilainen kuin kirjassa (ei paikallisia muuttujia) toistaiseksi env-argumentti on siis koko ajan sama siirretään samalla primitiivit takaisin omaan listaansa mutta nyt ne kopioidaan sieltä env-rakenteeseen (koodi alla) Primitiivit ja uuden ympäristön alustus nelilaskin8.scm (define primitive-procedures (list (list '+ +) (list '- -) (list '* *) (list '/ /) (list '< <) (list '= =) (list '> >))) (define (primitive-procedure-names) (map car primitive-procedures)) (define (primitive-procedure-objects) (map cadr primitive-procedures)) (define (setup-environment) ; tekee uuden env-rakenteen eli ympäristön (let ((initial-env (cons (primitive-procedure-names) (primitive-procedure-objects)))) (define-variable! 'true true initial-env) (define-variable! 'false false initial-env) initial-env))

Primitiivit ja globaalit muuttujat 2/2 Muuttujan haku ja muuttaminen env:stä (define (define-variable! var val env) (set-car! env (cons var (car env))) (set-cdr! env (cons val (cdr env)))) nelilaskin8.scm (define (lookup-variable-value var env) (define (scan names values) (cond ((null? names) (error "Variable not found -- LOOKUP-VARIABLE-VALUE" var)) ((eq? (car names) var) (car values)) (else (scan (cdr names) (cdr values))))) (scan (car env) (cdr env))) (define (set-variable-value! var val env) (define (scan names values) (cond ((null? names) (error "Variable not found -- SET-VARIABLE-VALUE!" var)) ((eq? (car names) var) (set-car! values val)) (else (scan (cdr names) (cdr values))))) (scan (car env) (cdr env)))

Tulkin käyttöliittymä Käyttöliittymän koodi (melkein sama kuin ennen) nelilaskin8.scm (define input-prompt ";;; Eval input:") (define output-prompt ";;; Eval value:") ;; kirjan driver-loop käyttää tätä globaalia muuttujaa (define the-global-environment (setup-environment)) (define (driver-loop) (prompt-for-input input-prompt) (let ((input (read))) (let ((output (eval input the-global-environment))) (announce-output output-prompt) (display output))) (driver-loop)) (define (prompt-for-input string) (newline) (newline) (display string) (newline)) (define (announce-output string) (newline) (display string) (newline))

Entä nyt? edellisillä kalvoilla oli koko uuden tulkin koodi koodi on nyt muuten sama kuin SICP-kirjan kohtien 4.14.1.6 tulkki, mutta: 1 eval-proseduuri on vielä hieman vähemmän abstrakti 2 primitiiviproseduuri tulkissa on suoraan Scheme-proseduuri (kirjassa (list 'primitive Scheme-proseduuri )) 3 evalista puuttuu tuki quote:lle ja cond:lle 4 paikalliset muuttujat puuttuvat (joten muutamat niitä käsittelevät kohdat, mm. lambda, toimivat eri tavalla ja env on aina sama) 5 käyttöliittymäkoodi tulostaa proseduurit eri tavalla tehdään kohdat 13 seuraavaksi ja 45 seuraavalla luennolla

Sisältö 1 Argumentittomat proseduurit ja käyttöliittymä 2 Abstrakti syntaksi ja env-argumentti 3 Lisäabstraktio evaliin 4 quote ja cond

Vielä abstraktimpi eval 1/3 (SICP 4.1.1) Koko eval ja siitä irrotettu apply nelilaskin9.scm (define (eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env)) ((assignment? exp) (eval-assignment exp env)) ((definition? exp) (eval-definition exp env)) ((if? exp) (eval-if exp env)) ((lambda? exp) (make-procedure (lambda-body exp))) ((begin? exp) (eval-sequence (begin-actions exp) env)) ((application? exp) (apply (eval (operator exp) env) ; ei Schemen apply! (list-of-values (operands exp) env) env)) (else (error "Unknown expression type -- EVAL" exp)))) (define apply-in-underlying-scheme apply) ; Schemen apply talteen (define (apply procedure arguments env) ; uusi määritelmä applylle (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) env)) (else (error "Unknown procedure type -- APPLY" procedure))))

Vielä abstraktimpi eval 2/3 (SICP 4.1.1) Uusia evalin apuproseduureja (define (eval-assignment exp env) (set-variable-value! (assignment-variable exp) (eval (assignment-value exp) env) env) 'ok) (define (eval-definition exp env) (define-variable! (definition-variable exp) (eval (definition-value exp) env) env) 'ok) (define (eval-if exp env) (if (true? (eval (if-predicate exp) env)) (eval (if-consequent exp) env) (eval (if-alternative exp) env))) nelilaskin9.scm sama koodi oli aiemmin evalin sisällä, paitsi uusi paluuarvo 'ok

Vielä abstraktimpi eval 3/3 (SICP 4.1.1, 4.1.2) Uusia applyyn liittyviä apuproseduureja nelilaskin9.scm (define (no-operands? ops) (null? ops)) (define (first-operand ops) (car ops)) (define (rest-operands ops) (cdr ops)) ;; sama kuin (map (lambda (exp) (eval exp env)) exps) (define (list-of-values exps env) (if (no-operands? exps) '() (cons (eval (first-operand exps) env) (list-of-values (rest-operands exps) env)))) ;; uusi primitiivien esitysmuoto (define (primitive-procedure? proc) (tagged-list? proc 'primitive)) (define (primitive-implementation proc) (cadr proc)) (define (apply-primitive-procedure proc args) (apply-in-underlying-scheme (primitive-implementation proc) args)) (define (primitive-procedure-names) (map car primitive-procedures)) (define (primitive-procedure-objects) (map (lambda (proc) (list 'primitive (cadr proc))) primitive-procedures))

Miksi tämä abstraktio? nyt on tehty puutelistan kohdat 1 ja 2 (abstraktimpi eval ja uusi primiitiivien esitysmuoto) miksi teimme näin paljon abstraktioita? kaikki lausekkeen rakenteeseen liittyvä on nyt abstrahoitu koskematta evaliin ja applyyn voisi vaihtaa tulkattavan kielen syntaksia tai lausekkeiden esitysmuotoa tulkissa (nyt listarakenne, voisi olla esim. taulukko) myös suuri osa lausekkeiden käsittelystä on abstrahoitu: esim. define-lauseketta voisi käsitellä eri lailla vain muuttamalla eval-definitionia tulkin perusta on eval ja apply eli lausekkeen tulkitseminen ja proseduurin kutsu

Sisältö 1 Argumentittomat proseduurit ja käyttöliittymä 2 Abstrakti syntaksi ja env-argumentti 3 Lisäabstraktio evaliin 4 quote ja cond

Puutelistan kohta 3 lisätään vielä tuki quote:lle ja cond:lle quotessa (eli ':ssä) osa tulkattavan ohjelman koodista päätyy suoritettavassa ohjelmassa näkyväksi tietorakenteeksi tästä syystä perus-schemessä ei periaatteessa saa muuttaa quotella tehtyä listaa: toteutus saa viitata suoraan listarakenteena talletettuun koodiin toteutetaan cond muuttamalla se sisäkkäisiksi if-lausekkeiksi tämä menetelmä on nimeltään syntaksimuunnos (syntax transformation, program transformation), ja condin sanotaan olevan johdettu lauseke (derived expression) riittää määritellä uusi syntaksi olemassaolevien avulla: toteutukseen ei tarvitse lisätä muuta tukea condille kuin muunnosproseduuri joissain kielissä myös ohjelmoija itse voi tehdä syntaksimuunnoksia makroilla kielen toteutusta muokkaamatta lisätään vielä muutama primitiivi: cons, car, cdr, null?, display ja newline

Lisätään quote (SICP 4.1.2) quote on helppo lisätä: sen toteutus palauttaa palan koodista esim. '(a b) eli (quote (a b)) palauttaa osoittimen siihen koodin pariin, jossa a on car read muuntaa ' x :n (quote x )-listaksi periaatteessa tässä voisi myös tehdä listarakenteesta kopion samalla saadaan symbolit tulkattavaan kieleen (mutta ilman esim. eq?-primitiiviä niillä ei voi tehdä kovin paljon) quoten lisääminen nelilaskin10.scm (define (quoted? exp) (tagged-list? exp 'quote)) (define (text-of-quotation exp) (cadr exp)) (define (eval exp env) (cond... ((quoted? exp) (text-of-quotation exp))... ))

Syntaksimuunnos cond->if (SICP 4.1.2) mikä tahansa cond-lauseke voidaan muuttaa jonoksi if-lausekkeita koodista tulee hieman pidempää, mutta samalla tavalla toimivaa (samat ehdot pitäisi käydä läpi jos cond toteutettaisiin suoraan) muunnosta tehdessä ei tarvitse tietää muun tulkin toiminnasta vain osata muokata tulkattavia lausekkeita Esimerkki muunnoksesta (cond ((> x 0) x) ((= x 0) (display 'zero) 0) (else (- x))) muuttuu muotoon (if (> x 0) x (if (= x 0) (begin (display 'zero) 0) (- x)))

Toteutus cond->if:lle 1/2 (SICP 4.1.2) jotta muunnoksen voisi tehdä säilyttäen syntaksiabstraktiot (eikä suoraan listarakennetta tuottamalla), tarvitaan apuproseduurit if- ja begin-lausekkeiden tekemiseen evalissa vain evaluoidaan syntaksimuunnoksen lopputulos Apuproseduureja ja eval-lisäys (define (make-if predicate consequent alternative) (list 'if predicate consequent alternative)) nelilaskin10.scm (define (make-begin seq) (cons 'begin seq)) (define (sequence->exp seq) ; ''optimoitu'' make-begin (cond ((null? seq) seq) ((last-exp? seq) (first-exp seq)) (else (make-begin seq)))) (define (eval exp env) (cond... ((cond? exp) (eval (cond->if exp) env))... ))

Toteutus cond->if:lle 2/2 (SICP 4.1.2) Itse cond->if-muunnos (define (cond? exp) (tagged-list? exp 'cond)) (define (cond-clauses exp) (cdr exp)) (define (cond-else-clause? clause) (eq? (cond-predicate clause) 'else)) (define (cond-predicate clause) (car clause)) (define (cond-actions clause) (cdr clause)) nelilaskin10.scm (define (cond->if exp) (expand-clauses (cond-clauses exp))) (define (expand-clauses clauses) (if (null? clauses) 'false ; tulkattavaa koodia, joka suoritetaan kun else:ä ei ole (let ((first (car clauses)) (rest (cdr clauses))) (if (cond-else-clause? first) (if (null? rest) (sequence->exp (cond-actions first)) (error "ELSE clause isn't last -- COND->IF" clauses)) (make-if (cond-predicate first) (sequence->exp (cond-actions first)) (expand-clauses rest))))))

Primitiivien lisääminen ja ajoesimerkki Uusia primitiivejä (tämä muutos riittää) nelilaskin10.scm (define primitive-procedures (list (list 'car car) (list 'cdr cdr) (list 'cons cons) (list 'null? null?) (list '+ +) (list '- -) (list '* *) (list '/ /) (list '< <) (list '= =) (list '> >) (list 'display display) (list 'newline newline))) Tämän tulkin ajoesimerkki (define (fact-iter) ;;; Eval input: (cond ((> c n) p) (fact-iter) (else fact-iter: c = 1 (display "fact-iter: c = ") fact-iter: c = 2 (display c) fact-iter: c = 3 (newline) fact-iter: c = 4 (set! p (* c p)) fact-iter: c = 5 (set! c (+ c 1)) (fact-iter))))) ;;; Eval value: (define p 1) 120 (define c 1) (define n 5) nelilaskin10.scm