Ohjelmoinnin peruskurssien laaja oppimäärä

Samankaltaiset tiedostot
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 2

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ä

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 5

Scheme-kesäkurssi luento 3

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 1

815338A Ohjelmointikielten periaatteet

Olio-ohjelmointi Javalla

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Pino S on abstrakti tietotyyppi, jolla on ainakin perusmetodit:

Ohjelmoinnin peruskurssien laaja oppimäärä

Tutoriaaliläsnäoloista

Ohjelmoinnin perusteet Y Python

A TIETORAKENTEET JA ALGORITMIT

ITKP102 Ohjelmointi 1 (6 op)

TIETORAKENTEET JA ALGORITMIT

7/20: Paketti kasassa ensimmäistä kertaa

Ohjelmoinnin peruskurssien laaja oppimäärä

Java kahdessa tunnissa. Jyry Suvilehto

Ohjelmoinnin peruskurssien laaja oppimäärä

Abstraktit tietotyypit. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Rajapinta (interface)

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

Scheme-kesäkurssi luento 4

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

ITKP102 Ohjelmointi 1 (6 op)

Javan perusteita. Janne Käki

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

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Tieto- ja tallennusrakenteet

7. Oliot ja viitteet 7.1

18. Abstraktit tietotyypit 18.1

Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto

Mikä yhteyssuhde on?

Luento 4 Aliohjelmien toteutus

15. Ohjelmoinnin tekniikkaa 15.1

Ohjelmoinnin peruskurssien laaja oppimäärä

Imperatiivisen ohjelmoinnin peruskäsitteet. Meidän käyttämän pseudokielen lauseiden syntaksi

1. Olio-ohjelmointi 1.1

Listarakenne (ArrayList-luokka)

Luku 3. Listankäsittelyä. 3.1 Listat

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

15. Ohjelmoinnin tekniikkaa 15.1

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Metodien tekeminen Javalla

Ohjelmoinnin jatkokurssi, kurssikoe

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

Tämän vuoksi kannattaa ottaa käytännöksi aina kirjoittaa uuden funktion tyyppi näkyviin, ennen kuin alkaa sen määritemää kirjoittamaan.

Java-kielen perusteet

Kaksiloppuinen jono D on abstrakti tietotyyppi, jolla on ainakin seuraavat 4 perusmetodia... PushFront(x): lisää tietoalkion x jonon eteen

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

Ohjelmointi 2 / 2010 Välikoe / 26.3

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

Clojure, funktionaalinen Lisp murre

Sisältö. 22. Taulukot. Yleistä. Yleistä

Ohjelmoinnin peruskurssi Y1

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

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

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python

Ohjelmoinnin peruskurssi Y1

Sisällys. 15. Lohkot. Lohkot. Lohkot

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python

Lohkot. if (ehto1) { if (ehto2) { lause 1;... lause n; } } else { lause 1;... lause m; } 15.3

Jakso 4 Aliohjelmien toteutus

ITKP102 Ohjelmointi 1 (6 op)

Jakso 4 Aliohjelmien toteutus

811312A Tietorakenteet ja algoritmit II Perustietorakenteet

1. Mitä tehdään ensiksi?

Transkriptio:

Ohjelmoinnin peruskurssien laaja oppimäärä Luento 5: Sijoituslause, SICP-oliot, todistamisesta (mm. SICP 33.1.3, 3.33.3.2) Riku Saikkonen 7. 11. 2011

Sisältö 1 Muuttujan arvon muuttaminen: set! 2 SICP-oliot 3 Tietorakenteen muuttaminen: set-car! ja set-cdr! 4 Vähän funktionaalisten ohjelmien todistamisesta

Sijoituslause (SICP 3.1) (set! muuttuja lauseke ) laskee lausekkeen ja sijoittaa sen arvon muuttujan uudeksi arvoksi sama muuttuja kuin mihin pelkkä muuttujan nimi koodissa viittaa muut samaan arvoon osoittavat muuttujat eivät muutu Esimerkkejä (define x 1) (define y x) (set! x (+ x 1)) ; nyt x = 2, y = 1 (define (f z) (set! z (+ z 1)) x) (f x) ; palauttaa 2; edelleen x = 2, y = 1 (let ((x 5)) (set! y x) ; nyt y = 5 (set! x (+ x 1)) x) ; palauttaa 6, globaali x = 2, y = 5

Mikä on muuttuja? muuttuja on arvolle annettu nimi toinen tapa ajatella: muuttuja on osoitin arvoon (kaikki arvot, myös esim. kokonaisluvut, ovat periaatteessa tallessa jossain muistissa, ja muuttuja vain osoittaa johonkin niistä) mutta muuttuja ei ole arvon tallennuspaikka (define y x) (set! y (+ y 1)) ei muuta x:ää ei myöskään jos x osoittaa esim. listaan Esimerkkejä (define x (list 1 2)) (define y x) ; x = (1 2), y = (1 2) (set! y (cdr y)) ; x = (1 2), y = (2) (set! x (list 3 4)) ; x = (3 4), y = (2) (define (f l) (set! l (cdr l)) (car l)) (f x) ; palauttaa 4; edelleen x = (3 4), y = (2)

Sijoituslauseen haittoja (SICP 3.1.3) sijoituslauseella on sivuvaikutus: se muuttaa ohjelman tilaa eikä vain palauta arvoa samoin tulostuksella eli display:llä (ulospäin näkyvä tila muuttuu) (Schemen set!:llä on periaatteessa paluuarvo, mutta toteutus saa valita sen; käytännössä tulkki jättää sen useimmiten tulostamatta) sivuvaikutuksista seuraa mm: tarve sille, että suoritetaan useampi lauseke peräkkäin (Schemen begin tai cond, jonka seurausosassa on monta lauseketta) ohjelman toimintaa on vaikeampi mallintaa matemaattisesti: pitää käsitellä muuttujien vanhoja ja uusia arvoja ohjelmien laskujärjestys on usein tarkemmin määrätty (kääntäjällä on vähemmän mahdollisuuksia optimoida sitä) sijoituslauseen hyviä puolia: joitain algoritmeja on vaikea toteuttaa ilman sitä joskus se auttaa modulaarisuudessa: sillä voi piilottaa sisäistä tilaa sijoituslauseita käyttävä silmukka vastaa koneen todellista toimintaa suoremmin kuin esim. häntärekursio

Sisältö 1 Muuttujan arvon muuttaminen: set! 2 SICP-oliot 3 Tietorakenteen muuttaminen: set-car! ja set-cdr! 4 Vähän funktionaalisten ohjelmien todistamisesta

SICP-tyyliset oliot (SICP 3.1.1) Schemessä ei ole varsinaisia olioita, mutta samankaltaisen rakenteen voi tehdä palautetulla proseduurilla Luokka, jossa on kaksi metodia acct1.scm (define (make-account balance) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (define (dispatch m) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) (else (error "Unknown request -- MAKE-ACCOUNT" m)))) dispatch) ; make-account siis palauttaa dispatch-proseduurin (define acc (make-account 100)) ((acc 'withdraw) 50) 50 ((acc 'deposit) 40) 90 ; kutsu luo uuden olion

Muunnelma helpommalla metodikutsusyntaksilla Sama luokka kuin edellä (erilainen dispatch) acct2.scm (define (make-account balance) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (define (dispatch m. args) ; args = lista lopuista argumenteisa (cond ((eq? m 'withdraw) (apply withdraw args)) ((eq? m 'deposit) (apply deposit args)) (else (error "Unknown request -- MAKE-ACCOUNT" m)))) dispatch) (define acc (make-account 100)) (acc 'withdraw 50) 50 (acc 'deposit 40) 90

Vaihteleva määrä argumentteja Schemessä on pieni lisäominaisuus proseduurien argumentteja määriteltäessä: jos argumenttilista loppuu. x, proseduuria kutsuttaessa muuttujaan x tulee lista kaikista lopuista kutsussa annetuista argumenteista Pythonissa vastaava on *, esim. def f(a, b, *c): edellisen kalvon dispatch käytti tätä Esimerkki: osa argumenteista (define (f a b. c) c) ;; tai yhtä hyvin lambdalla: (define f (lambda (a b. c) c)) (f 1 2 3 4) (3 4) (f 1 2 3) (3) (f 1 2) () (f 1) virhe! Esimerkki: kaikki argumentit (define (g. x) x) ;; tai: (define g (lambda x ; ei siis (. x) x)) (g 1 2) (1 2) (g 1) (1) (g) ()

SICP-olioista olion tila on tallessa palautetussa dispatch-proseduurissa muuttujien näkyvyys: kentät ovat Java-termein private, metodit myös, paitsi että dispatch-proseduuri tekee niistä public:eja samaan ideaan voisi lisätä: enemmän paikallisia muuttujia eli kenttiä static-kenttiä eli konstruktoriproseduurin ulkopuolella määriteltyjä muuttujia (Javan static-metodi = globaali proseduuri) metodit voivat kutsua itseään ja toisiaan (dispatch vastaa this:iä/self:iä) dispatch-proseduurissa voisi tarjota useamman rajapinnan samoihin metodeihin edellä ollut ratkaisu ei ole täydellistä olio-ohjelmointia: mm. perintä puuttuu (tästä lisää myöhemmällä luennolla... )

Sisältö 1 Muuttujan arvon muuttaminen: set! 2 SICP-oliot 3 Tietorakenteen muuttaminen: set-car! ja set-cdr! 4 Vähän funktionaalisten ohjelmien todistamisesta

set-car! ja set-cdr! (SICP 3.3.1) parien (ja siis listojen) osia voi muuttaa set-car!:lla ja set-cdr!:llä vastaavasti merkkijonoja string-set!:llä, vektoreita vector-set!:llä jne. muutos näkyy kaikkialle, joka viittaa muutettuun pariin yksityiskohta: quotella (tai ':llä) tehtyä listaa ei saisi muuttaa: sellainen on vakiolista Esimerkkejä (define x (list 1 2)) (define y x) (define z (cdr x)) (set-car! x 3) ; nyt x = (3 2), y = (3 2), z = (2) (set-cdr! x (list 4)) ; nyt x = (3 4), y = (3 4), z = (2) (set-car! (cdr y) 5) ; nyt x = (3 5), y = (3 5), z = (2) (define (f a) (set-car! a (+ (car a) 1)) (car x)) (f x) ; palauttaa 4; nyt x = (4 5), y = (4 5), z = (2)

Entä set!? miksi tarvitaan set-car! vielä set!:n lisäksi? set! muuttaa vain sitä, mihin tietty muuttuja osoittaa sillä siis ei voi vaikuttaa esim. muihin samaan kohtaan osoittaviin muuttujiin set-car! ja set-cdr! sen sijaan muuttavat muistissa olevia arvoja (joihin jokin muuttuja tai tietorakenne saattaa osoittaa) tausta-ajatus: jaetaan muisti kahtia: 1) muuttujasidonnat (eli nimiosoitin -parit) ja 2) varsinaiset arvot; set! asettaa vain 1-muistia ja set-car!/set-cdr! vain 2-muistia mm. Common Lisp -kielessä set!:n vastineella voi muokata myös tietorakenteita Schemessä tätä ei ole, mutta se voisi olla esimerkiksi: (set! (car (cdr l)) 32) muuttaisi l:n toista alkiota mutta oikeastaan tällainen set! on vain lyhyempi syntaksi set-car!:lle ja set-cdr!:lle: ylläoleva on tavallisessa Schemessä (set-car! (cdr l) 32)

Esimerkki: First In First Out -jono queue.scm (SICP 3.3.2) (define (empty-queue? queue) (null? (front-ptr queue))) (define (make-queue) (cons '() '())) (define (front-queue queue) (if (empty-queue? queue) (error "FRONT called with an empty queue" queue) (car (front-ptr queue)))) (define (insert-queue! queue item) (let ((new-pair (cons item '()))) (cond ((empty-queue? queue) (set-front-ptr! queue new-pair) (set-rear-ptr! queue new-pair) queue) (else (set-cdr! (rear-ptr queue) new-pair) (set-rear-ptr! queue new-pair) queue)))) (define (delete-queue! queue) (cond ((empty-queue? queue) (error "DELETE! from empty queue" queue)) (else (set-front-ptr! queue (cdr (front-ptr queue))) queue))) (define (front-ptr queue) (car queue)) ; apufunktioita (define (rear-ptr queue) (cdr queue)) (define (set-front-ptr! queue item) (set-car! queue item)) (define (set-rear-ptr! queue item) (set-cdr! queue item)) Ajoesimerkki: (define q (make-queue)) (insert-queue! q 'a) (insert-queue! q 'b) (delete-queue! q) a

Funktiorajapinta vs. oliorajapinta edellisen kalvon esimerkin rajapinta koostui funktioista: (make-queue) (empty-queue? queue) (front-queue queue) (insert-queue! queue item) (delete-queue! queue) samankaltaisen rajapinnan voisi tehdä olioilla: (make-queue) q = new Queue (q 'empty?) q.is_empty() (q 'front) q.front() (q 'insert! item) q.insert(item) (q 'delete!) q.delete() muutamia näiden eroja: syntaksi: operaatio kohde argumentit (prex) vai kohde operaatio argumentit (inx) oliorajapinnassa globaaleja nimiä on vähemmän (ja metodien nimet voivat olla lyhyempiä) jos haluaa käsitellä esim. kolmea erilaista oliota, pitää valita keinotekoisesti yksi, johon metodin laittaa; funktiorajapinnassa tämä yksi kohde ei ole erityisasemassa voiko metodia käyttää funktioargumenttina?

Mikä on samaa? (SICP 3.3.1) jos tietorakennetta voi muuttaa, sillä on väliä, tehdäänkö siitä kopioita vai viitataanko samaan rakenteeseen mitä tarkoittaa, että x ja y ovat samat? Schemessä: (eq? x y): sama rakenne (sama muistiosoite); (equal? x y): sama tai samanlainen omia tietorakenteita tehdessä pitää yleensä ottaa tähän kantaa, mahdollisesti määritellä useampi yhtäsuuruus myös omia rajapintoja tehdessä kannattaa miettiä etukäteen: 1 muuttaako rajapinnan proseduuri f argumenttina saamaansa tietorakennetta? 2 saako joku muu proseduuri muuttaa f:lle antamaansa tietorakennetta myöhemmin (jos f tallettaa sen)? 3 saako f:n palauttamaa tietorakennetta muuttaa? jos tätä ei mieti kunnolla tai ole kerrottu kirjastorajapinnan dokumentaatiossa, päätyy helposti tekemään rakenteista kopioita varmuuden vuoksi

Sisältö 1 Muuttujan arvon muuttaminen: set! 2 SICP-oliot 3 Tietorakenteen muuttaminen: set-car! ja set-cdr! 4 Vähän funktionaalisten ohjelmien todistamisesta

Ohjelmien oikeaksi todistamisesta eräs funktionaalisuuden etu on, että ohjelmista on helpompi todistaa ominaisuuksia, jos ne ovat puhtaasti funktionaalisia lausekkeita voi muuttaa toisiksi matemaattisesti eli välittämättä ympäröivästä kontekstista tai ohjelman tilasta suoritushetkellä imperatiivisen koodin todistamisessa mietitään yleensä ohjelman tilaa tietyillä hetkillä todistus on usein ketju ohjelman välitiloja alkutilasta (argumentit) lopputilaan, joka toteuttaa todistettavan ehdon suoritusjärjestyksellä on siis koko ajan väliä silmukoille pitää keksiä invariantti: ehto joka on voimassa esim. jokaisen kierroksen alussa ja lopussa toinen funktionaalisuuden etu on, että koodi ja todistus voi olla abstraktimpaa: voidaan tehdä enemmän yleiskäyttöisiä apufunktioita ja todistaa ensin niiden ominaisuuksia

Funktionaalinen todistusesimerkki 1/2 Todistetaan: kaikille listoille l: (accumulate cons nil l) l (lista = nil:iin päättyvä jono pareja) Ensin accumulate:n määritelmä (define (accumulate op initial sequence) (if (null? sequence) initial (op (car sequence) (accumulate op initial (cdr sequence))))) Tai sanallinen määritelmä (jolloin toteutuksen ei tarvitse olla täsmälleen ylläoleva): 1 (accumulate op i '()) i 2 (accumulate op i (cons h t ) ( op h (accumulate op i t ))

Funktionaalinen todistusesimerkki 2/2 Todistetaan: kaikille listoille l: (accumulate cons nil l) l (lista = nil:iin päättyvä jono pareja) Todistus 1 Jos l = nil: (accumulate cons nil nil) nil (accumulate:n määritelmästä) 2 Jos l = pari (h,t) eli ((car l), (cdr l)): (accumulate cons nil (cons h t)) (cons h (accumulate cons nil t)) (taas määritelmästä, op = cons) Koska t on lyhyempi kuin (cons h t), tämä riittää induktioon.

Listankäsittelyproseduurien ominaisuuksia 1/2 tässä muutamia vastaavalla tavalla todistettavia ominaisuuksia (kaikki listat ovat nil:iin päättyviä ja argumenttifunktiot päättyviä ja sivuvaikutuksettomia) tarkoittaa, että lausekkeiden arvot ovat samoja suoritusaika tai laskujärjestys voi olla eri reverse:stä: (reverse (reverse l)) l lähinnä map:iin liittyviä: (map f (reverse l)) (reverse (map f l)) (map f (append l1 l2)) (append (map f l1) (map f l2)) (map (compose f g) l) (map (lambda (x) (f (g x))) l) (map f (map g l)) (filter p (map f l)) (map f (filter (lambda (x) (p (f x))) l))

Listankäsittelyproseduurien ominaisuuksia 2/2 foldeihin eli accumulateen liittyviä: (fold-right op i l) (fold-left op i l), jos op on assosiatiivinen ja kaikille x: (op x i) x ja (op i x) x (fold-right op i l) (fold-left (flip op) i (reverse l)), missä (define (flip f) (lambda (x y) (f y x))) alla olevat kaksi reverse:n toteutusta toimivat eli (rev-1 l) (rev-2 l) (reverse l) Kaksi toteutusta reverse:stä (define (rev-1 l) (if (null? l) l (append (rev-1 (cdr l)) (list (car l))))) (define (rev-2 l) (fold-left (flip cons) nil l))