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ä

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 perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 5

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

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet

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ä

Ohjelmoinnin peruskurssi Y1

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Ohjelmoinnin perusteet Y Python

Tutoriaaliläsnäoloista

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Luento 5. Timo Savola. 28. huhtikuuta 2006

JavaScript alkeet Esimerkkikoodeja moniste 2 ( Metropolia)

Java kahdessa tunnissa. Jyry Suvilehto

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

M. Merikanto 2012 XML. Merkkauskieli, osa 2

Ohjelmoinnin jatkokurssi, kurssikoe

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

Olio-ohjelmointi Javalla

Ohjelmoinnin perusteet Y Python

11/20: Konepelti auki

Javan perusteita. Janne Käki

Ohjelmoinnin perusteet Y Python

A TIETORAKENTEET JA ALGORITMIT

Ohjelmoinnin peruskurssien laaja oppimäärä

ITKP102 Ohjelmointi 1 (6 op)

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Makrojen mystinen maailma lyhyt oppimäärä

Ohjelmoinnin perusteet Y Python

Scheme-kesäkurssi luento 4

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

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

1. Olio-ohjelmointi 1.1

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Hohde Consulting 2004

7/20: Paketti kasassa ensimmäistä kertaa

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Tietueet. Tietueiden määrittely

JWT 2016 luento 11. to klo Aulikki Hyrskykari. PinniB Aulikki Hyrskykari

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

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

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Kerta 2. Kerta 2 Kerta 3 Kerta 4 Kerta Toteuta Pythonilla seuraava ohjelma:

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

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Javascript 2: Ohjelmointikielen ominaisuudet. Jaana Holvikivi Metropolia

1. Omat operaatiot 1.1

TIE Principles of Programming Languages CEYLON

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

9. Periytyminen Javassa 9.1

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

AJAX-konsepti AJAX. Asynkronisuus. Nykyisten web-ohjelmien ongelmia. Asynchronous JavaScript And XML

Ohjelmoinnin peruskurssi Y1

JReleaser Yksikkötestaus ja JUnit. Mikko Mäkelä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Transkriptio:

Ohjelmoinnin peruskurssien laaja oppimäärä Luento 13: Scheme-tulkki Pythonilla, datan serialisointi, keväästä Riku Saikkonen 11. 12. 2012

Sisältö 1 Scheme-tulkki Pythonilla 2 Datan serialisointi 3 Suunnitelmia kevään kursseista

Tulkin tekeminen muilla kielillä kuin Schemellä edellä tehtiin Scheme-tulkkia Schemellä entä jos tekisi kielen x tulkin kielellä y (esim. Scheme Pythonilla)? melkein aina pitää tehdä itse lausekkeiden esitysmuoto tulkissa ja esikäsittelyvaihe, joka lukee ohjelman merkkijonona ja jäsentää (parse) sen tähän omaan esitysmuotoon (edellä Schemen sulkulausekkeet ja read tekivät nämä) sen sijaan varsinaisen tulkin perusrakenne on yleensä sama jos kieli y ei tue mutta x:n pitää tukea: häntärekursiota eval-funktio pitää muuttaa silmukaksi poikkeuksia kutsupino pitää itse tallettaa tulkin sisälle sen sijaan, että se kutsuisi itseään rekursiivisesti automaattista muistinhallintaa oma roskankeruualgoritmi jne. muille vastaaville rakenteellisille ominaisuuksille seuraavaksi esimerkkinä osa Scheme-tulkista Pythonilla

Scheme-lausekkeiden esitysmuoto Pythonissa on suoraviivaista esittää Scheme-lauseke (define fact (lambda (n) (if (= n 0) 1 (* n (fact (- n 1)))))) sulkulauseketta vastaavana Python-listana: ['define', 'fact', ['lambda', ['n'], ['if', ['=', 'n', 0], 1, ['*', 'n', ['fact', ['-', 'n', 1]]]]]] tulkki siis voisi tallettaa lausekkeensa tässä muodossa muoto toimii millä tahansa sulkulausekkeilla joten esim. quote ja makrot toimisivat myös tosin oikeastaan pitäisi vielä mm. erottaa symbolit ja merkkijonot toisistaan sekä tukea mm. #t:tä ja Schemen erikoisia numerotyyppejä ja keksiä esitysmuoto pareille, jotka eivät pääty tyhjään listaan

Tulkki tälle esitysmuodolle Osa tulkin evalin koodista def tagged_list(exp, tag): return instanceof(exp, list) and exp[0] == tag def istrue(val): return val!= False def seval(exp, env): if... elif tagged_list(exp, 'if'): if istrue(seval(exp[1], env)): return seval(exp[2], env) else: return seval(exp[3], env) else: # proseduurikutsu proc = seval(exp[0], env) args = [seval(e, env) for e in exp[1:]] return sapply(proc, args) eli SICP-kirjan tulkin voisi kääntää suoraviivaisesti Pythoniksi tämä tulkin rakenne toimisi, mutta se ei ole tyypillinen tapa tehdä tulkkeja olio-ohjelmointikielellä

Lausekkeet olioina tyypillisempi tapa tehdä tulkkeja on esittää lauseke oliona, joka kuvaa sen ulointa osaa ja sisältää viittauksia alilausekkeisiin esim. if-lauseketta vastaisi luokka If, jonka kentissä olisi tallessa ehtoa, then- ja else-haaraa vastaavat lausekkeet eli tulkin abstrakti syntaksi olisi näitä luokkia tällaiselle lausekeoliolle tarvitaan: konstruktori, joka ottaa alilausekkeet talteen eval-metodi, joka suorittaa lausekkeen ja palauttaa sen arvon, kutsuen alilausekkeiden eval-metodeja (lisäksi oliossa voisi olla metodeja lausekkeen tulostamiseen, sen käyttämien muuttujien luettelemiseen optimointeja varten, jne.) lausekkeen suorittaminen vaatii pääsyä muuttujien arvoihin joten evalille annetaan argumentiksi ympäristö tulkki voi siis suorittaa minkä tahansa lausekkeen kutsumalla sen eval-metodia

Lausekkeet olioina: esimerkki Scheme-lauseke (define fact (lambda (n) (if (= n 0) 1 (* n (fact (- n 1)))))) voidaan esittää Pythonilla olioina esimerkiksi näin: Define('fact', Lambda(['n'], [If(Call(Var('='), Var('n'), SelfEval(0)), SelfEval(1), Call(Var('*'), Var('n'), Call(Var('fact'), Call(Var('-'), Var('n'), SelfEval(1)))))])) em. Python-koodi on siis sisäkkäisiä kutsuja eri lausekeluokkien konstruktoreihin kukin konstruktori ottaa argumentiksi lausekeluokkien osat, esim. Lambda ottaa parametrilistan ['n'] ja proseduurin koodin (lista lausekeolioita, tässä vain yksi If) SelfEval(1) tarvitaan, jotta myös sille voisi kutsua eval-metodia

Lausekkeet olioina: lausekeluokan toteutus tässä esimerkkinä If:n toteutus; muut ovat samankaltaisia Osa tulkin koodista (koko If) class Expr(object): # po. abstrakti luokka def eval(self, env): raise NotImplementedError schemeeval.py class If(Expr): def init (self, condition_expr, then_expr, else_expr): self.condition_expr = condition_expr self.then_expr = then_expr self.else_expr = else_expr def eval(self, env): if self.istrue(self.condition_expr.eval(env)): return self.then_expr.eval(env) else: return self.else_expr.eval(env) def istrue(self, val): return (val!= False)

Ympäristöt mitä muuta tulkkiin tarvitaan kuin kaikkien eri lauseketyyppien toteutus? 1 ympäristöt (eli paikka, jossa muuttujat ovat tallessa) 2 proseduurit ja niiden kutsuminen (eli SICP-tulkin apply) 3 muut arvot, joita ei ole samanlaisina alla olevassa kielessä (jos sellaisia on; tässä esim. Schemen symbolit) 4 ehkä käyttöliittymä (riippuen tulkin käyttötarkoituksesta) ympäristöissä voi käyttää Pythonin valmiita tietorakenteita: esim. kehys on dict muuttujannimistä arvoihin, ja ympäristö on lista näitä kehyksiä paikallisia muuttujia tehdessä (proseduurikutsussa) voi tehdä uuden ympäristöolion, jossa on yksi kehys lisää

Proseduurien toteutus: lausekkeet Lambda-lauseke ja proseduurikutsulauseke class Lambda(Expr): def init (self, params, body): self.params = params self.body = body def eval(self, env): return Procedure(self.params, self.body, env) schemeeval.py class Call(Expr): def init (self, procexpr, *argexprs): self.procexpr = procexpr self.argexprs = argexprs def eval(self, env): proc = self.procexpr.eval(env) argvals = [expr.eval(env) for expr in self.argexprs] return proc.apply(argvals) koodi on samaa kuin SICPin tulkissa (paitsi siirrettynä luokkiin): proseduurikutsussa esim. (fact (+ 1 2)) kutsutaan evalia kaikille lausekkeen osille ja applyä saadulle proseduurioliolle

Proseduurien toteutus: proseduurioliot Proseduurioliot (omat proseduurit ja primitiivit) class Callable(object): # po. abstrakti luokka def apply(self, argvalues): raise NotImplementedError schemeeval.py class Procedure(Callable): def init (self, params, body, env): self.params = params self.body = body self.env = env def apply(self, argvalues): # uusi ympäristö, jossa on uusi kehys ja sen jälkeen env applyenv = self.env.extended(self.params, argvalues) r = None for expr in self.body: r = expr.eval(applyenv) return r class Primitive(Callable): def init (self, python_func): self.python_func = python_func def apply(self, argvalues): return apply(self.python_func, argvalues) # Pythonin apply

Entä jonkin muun kielen tulkki? esimerkkikoodissa schemeeval.py on toimiva tulkki, jossa on useimmat SICP-kirjan tulkin ominaisuudet mikä muuttuisi, jos tehtäisiin tulkki muulle kuin Schemelle? suurin osa lausekeolioista olisi samoja (lähes kaikille kielille yhteisiä) paljon monimutkaisempi jäsennin kielen syntaksille Definen sijaan monessa kielessä olisi erilliset lausekkeet proseduurien ja muiden muuttujien määrittelyyn (eikä Lambdaa) muitakin tapoja tehdä paikallisia muuttujia kuin proseduurikutsu (esim. oma lauseketyyppi joka vastaisi Schemen letiä) silmukkarakenteita operaattorit ja vastaavat voisivat olla Call-lausekkeita, paitsi jos primitiiviä ei haluta hakea nimen perusteella ympäristöstä isommassa ohjelmointikielessä voisi olla myös oliot, moduulijärjestelmä, poikkeukset, staattiset tyypit, jne. eli lähinnä lisää ominaisuuksia samaan runkoon (ja jäsennin) poikkeus: runko muuttuisi jonkin verran, jos pitäisi pitää itse yllä kutsupinoa (esim. poikkeusten tekemistä varten)

Sisältö 1 Scheme-tulkki Pythonilla 2 Datan serialisointi 3 Suunnitelmia kevään kursseista

Yleisiä tapoja datan siirtoon useimmat ohjelmat tallettavat ja lataavat dataa tiedostoista tai esim. verkon yli toiselta ohjelmalta esim. lautapeli voisi tallentaa pelin (eli laudan sisällön) tai verkkopelinä toimiessaan lähettää sen toiselle pelaajalle myös tulkin lausekkeet ovat tällaista dataa miten tällainen data kannattaa esittää? itse keksityllä binääri- tai tekstitiedostolla? jollain puolivalmiilla formaatilla kuten XML:nä? jonkin muun ohjelman ennestään käyttämällä formaatilla? omia binääriformaatteja on helppo tuottaa joistain ohjelmointikielistä (muistin sisältö levylle), mutta vaikea käsitellä muilla kielillä tai eri versioilla seuraavilla kalvoilla on muutama yleinen puolivalmis formaatti

Datan serialisointi serialisointi (serialization, marshalling) tarkoittaa ohjelmassa olevan datan muuttamista merkkijonoksi ja takaisin erityisesti ohjelmointikielen tietorakenteiden automaattista tallentamista ja lataamista Schemessä read ja write toteuttavat Scheme-datan serialisoinnin mm. Pythonissa ja Javassa on valmiit kirjastot olioiden serialisointiin kielen omaan (binääri)formaattiin, jota on tarkoitus käsitellä vain näillä kirjastoilla itsellään joten se ei toimi kunnolla kielten välillä eikä tiedostoformaattia usein voi luotettavasti dokumentoida kaikkea ei voi serialisoida (esim. useimmiten funktioita) käytännössä serialisointi tehdään usein kuitenkin osittain käsin esimerkiksi jotta ohjelman eri versiot toimisivat ristiin, vaikka olioiden rakenne muuttuu tai jotta ylimääräistä esim. väliaikaista dataa ei menisi talteen

Sulkulausekkeet Esimerkki datasta sulkulausekkeina (osm ((version "0.6") (generator "CGImap 0.0.2")) (bounds 60.1711000 24.8552600 60.1760400 24.8672200) (way 26026161 (user "alv") (uid 4660) (visible #t) (version 2) (changeset 139696) (timestamp "2008-08-08T08:00:57Z") (nodes 284132199 284132200 286097549) (tags ("highway" "footway") ("surface" "unpaved")))) Schemen read- ja write-primitiivit käyttävät Scheme-koodin näköistä sulkulauseke-esitysmuotoa esitysmuoto on nimeltään S-expression (symbolic expression) sitä on kohtalaisen helppo kirjoittaa ja lukea automaattisesti ilmankin ohjelmointikielen tukea

JSON (JavaScript Object Notation) Esimerkki datasta JSON-muodossa { "osm": { "version": "0.6", "generator": "CGImap 0.0.2" }, "bounds": { "minlat": 60.1711000, "minlon": 24.8552600, "maxlat": 60.1760400, "maxlon": 24.8672200 }, "ways": [ { "id": 26026161, "user": "alv", "uid": 4660, "visible": true, "version": 2, "changeset": 139696, "timestamp": "2008-08-08T08:00:57Z", "nodes": [ { "ref": 284132199 }, { "ref": 284132200 }, { "ref": 286097549 } ], "tags": [ { "k": "highway", "v": "footway" }, { "k": "surface", "v": "unpaved" } ] } ] } JSON-formaatti on tehty JavaScript-kielen pohjalta periaatteessa se on koodia (olion ja/tai taulukon alustus), jonka voisi suoraan antaa JavaScript-tulkille käytännössä sitä useimmiten luetaan kirjaston avulla käytetään varsinkin webbisovelluksissa selaimessa pyörivän JavaScript-koodin ja palvelimen väliseen tiedonsiirtoon

XML Esimerkki XML-datasta (pala OpenStreetMap-dataa) <?xml version="1.0" encoding="utf-8"?> <osm version="0.6" generator="cgimap 0.0.2"> <bounds minlat="60.1711000" minlon="24.8552600" maxlat="60.1760400" maxlon="24.8672200"/> <way id="26026161" user="alv" uid="4660" visible="true" version="2" changeset="139696" timestamp="2008-08-08t08:00:57z"> <nd ref="284132199"/> <nd ref="284132200"/> <nd ref="286097549"/> <tag k="highway" v="footway"/> <tag k="surface" v="unpaved"/> </way> </osm> XML-esitysmuotoon kuuluu yleensä skeema (schema), joka määrittelee, mitä alikohtia missäkin saa olla ja valmiita työkaluja, jotka tarkistavat skeemanmukaisuuden, editoivat XML:ää, hakevat XML:stä osia tietyillä hakuehdoilla, konvertoivat XML:ää muunlaisiin formaatteihin, jne. XML:n käsittelyyn on kirjastoja useimmissa ohjelmointikielissä

Itse tehdyt formaatit hyvin usein ohjelmissa käytetään edellä lueteltujen formaattien sijaan omia itse suunniteltuja formaatteja etuja: joustavampia ja tilanteeseen sopivampia, joskus yksinkertaisempia ymmärtää, usein helpompia kirjoittaa käsin haittoja: itse tehty jäsennin ei yleensä ole yhtä monipuolinen; omaa formaattia käsitteleviä muita työkaluja ei ole valmiina etu ja haitta: ei tarvitse käyttää valmiita kirjastoja se, että jokin data esitetään sulkulausekkeina, JSONina tai XML:nä ei useinkaan kerro vielä kovin paljon pitää vielä määritellä, miten niitä käytetään nämä valmiit formaatit helpottavat suunnittelua, mutta eivät tee sitä ohjelmoijan puolesta usein näiden valmiiden formaattien sisälle (esim. tiettyihin merkkijonoihin) määritellään vielä itse jokin oma formaatti

Mitä Pythonista löytyy? Pythonin pickle-paketti serialisoi Python-olioita automaattisesti formaatti on Pythonille sisäinen: ei ole tarkoitus käsitellä muuten kuin pickle:llä Pythonin repr-funktio tuottaa tekstimuotoisen esityksen argumentistaan (esim. "['abc', 3, [1, 2, 3]]") kuten Schemen write, paitsi että repr:n tulostetta ei ole tarkoitus lukea takaisin Pythoniin Pythonille on kirjastot mm. XML:n ja JSONin käsittelyyn pitääkö kirjastolta saaduille olioille tehdä vielä itse jotain? yleensä ne pitää käydä läpi ja tarkistaa, varsinkin jos data tulee ohjelman tai sen käyttäjän ulkopuolelta kirjastot siis auttavat mutta eivät korvaa kokonaan esim. datatiedoston tai verkkopaketin lukevaa funktiota samoin kielen oma serialisointi (esim. pickle)

Sisältö 1 Scheme-tulkki Pythonilla 2 Datan serialisointi 3 Suunnitelmia kevään kursseista