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ä

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ä

Scheme-kesäkurssi luento 4

Scheme-kesäkurssi luento 5

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 peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Scheme-kesäkurssi luento 2

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 1

ELM GROUP 04. Teemu Laakso Henrik Talarmo

AS C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin

Ohjelmoinnin peruskurssien laaja oppimäärä

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

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

Ohjelmoinnin perusteet Y Python

Luento 5. Timo Savola. 28. huhtikuuta 2006

11/20: Konepelti auki

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

C-ohjelmoinnin peruskurssi. Pasi Sarolahti

Tutoriaaliläsnäoloista

Scheme-kesäkurssi luento 6

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

Ruby. Tampere University of Technology Department of Pervasive Computing TIE Principles of Programming Languages

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

Makrojen mystinen maailma lyhyt oppimäärä

Ohjelmoinnin perusteet Y Python

Harjoitustyö: virtuaalikone

Ohjelmoinnin perusteet Y Python

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Tietorakenteet ja algoritmit - syksy

D-OHJELMOINTIKIELI. AA-kerho, 33. Antti Uusimäki. Arto Savolainen

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

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

Groovy. Niko Jäntti Jesper Haapalinna Group 31

815338A Ohjelmointikielten periaatteet

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

TIE PRINCIPLES OF PROGRAMMING LANGUAGES Eiffel-ohjelmointikieli

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

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

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

Groovy. Samuli Haverinen, Aki Hänninen. 19. marraskuuta 2015

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

Ohjelmoinnin peruskurssi Y1

BlueJ ohjelman pitäisi löytyä Development valikon alta mikroluokkien koneista. Muissa koneissa BlueJ voi löytyä esim. omana ikonina työpöydältä

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

2) Aliohjelma, jonka toiminta perustuu sivuvaikutuksiin: aliohjelma muuttaa parametrejaan tai globaaleja muuttujia, tulostaa jotakin jne.

815338A Ohjelmointikielten periaatteet

Hellä ensikosketus. Tomi Kiviniemi

Clojure, funktionaalinen Lisp murre

TIE Principles of Programming Languages. Seminaariesityksen essee. Ryhmä 18: Heidi Vulli, Joni Heikkilä

Ohjelmien analysointi. ER-kaaviot

Hohde Consulting 2004

Jatkeet. TIES341 Funktio ohjelmointi 2 Kevät 2006

Koka. Ryhmä 11. Juuso Tapaninen, Akseli Karvinen. 1. Taustoja 2. Kielen filosofia ja paradigmat 3. Kielen syntaksia ja vertailua JavaScriptiin Lähteet

GIS-automatisointi ja ohjelmointi/skriptaus. Harri Antikainen

ITKP102 Ohjelmointi 1 (6 op)

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Ohjelmoinnin perusteet Y Python

Ohjelmointikieli TIE Principles of Programming Languages Syksy 2017 Ryhmä 19

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

Proseduurit, funktiot ja herättimet - esimerkkeinä Oracle, SQL Server, MySQL ja OCELOT. Jouni Huotari S2008

SEMINAARI ESSEE: DYLAN. TIE Principles of Programming Languages

PROSEDUURIT, FUNKTIOT JA HERÄTTIMET - ESIMERKKEINÄ ORACLE, SQL SERVER, MYSQL JA OCELOT JOUNI HUOTARI K2009

Muistutus aikatauluista

Ohjelmointi 1 / syksy /20: IDE

Transkriptio:

Ohjelmoinnin peruskurssien laaja oppimäärä Luento 12: Ohjelmamuunnokset, dynaaminen sidonta, Lisp-kielistä Riku Saikkonen 4. 12. 2012

Sisältö 1 Ohjelmia muokkaavat ohjelmat 2 Dynaaminen sidonta 3 Lisp-kielistä ja DSL-kielistä

Ohjelmia muokkaavat ohjelmat kirjan tulkit suorittavat annettua Scheme- tms. ohjelmaa samaan tapaan voi myös muuttaa annettua ohjelmaa muunnosproseduuri ottaa ohjelman eli lausekkeen argumentiksi ja palauttaa muokatun version siitä jaetaan käsittely osiin lauseketyypin (set!, if jne.) mukaan samoin kuin tulkissa mutta lausekkeen suorittamisen sijaan palautetaan lauseke joko sellaisenaan tai muunnettuna alilausekkeet muunnetaan rekursiivisesti tai tutkia sitä: esimerkiksi tarkistaa osia koodin toiminnasta staattisesti eli suorittamatta sitä esim. Scheme-koodista voi tarkistaa, käytetäänkö siinä muuttujia, joita ei ole määritelty tai koodista voisi optimointeja varten etsiä muuttujia, joiden arvoja ei koskaan muuteta, tai sivuvaikutuksettomia proseduureja tai kääntää sen toiselle (yleensä matalamman tason) kielelle

Ohjelman muokkauksen käyttötarkoituksia mitä ohjelmaa muokkaamalla sitten voi tehdä? kääntää koodia yksinkertaisempaan muotoon, esim. poistaa cond-lausekkeet erilaisia optimointeja lisätä koodiin dynaamisia eli ajonaikaisia tarkistuksia muuttaa koodin toimintaa (esim. tehdä kaikkien tulostuskomentojen tilalla jotain muuta) lisätä toiminnallisuutta, esim. kerätä tietoja siitä, mitä koodia suoritetaan eniten kääntäjät tekevät usein tällaisia muunnoksia kääntämisen aikana varsinkin kääntäjissä tekniikka on nimeltään ohjelmamuunnos (program transformation)

Scheme-ohjelman muokkausproseduurin (eräs) runko Kopioi lausekkeen ja cond->if-muuntaa sen syntax-process.scm ;; käyttää kirjan tulkin apuproseduureja tagged-list? ja cond->if (define (process exp) (cond ((tagged-list? exp 'quote) exp) ((tagged-list? exp 'set!) (list 'set! (cadr exp) (process (caddr exp)))) ((tagged-list? exp 'define) (cons 'define (cons (cadr exp) (map process (cddr exp))))) ((tagged-list? exp 'if) (cons 'if (map process (cdr exp)))) ((tagged-list? exp 'lambda) (cons 'lambda (cons (cadr exp) (map process (cddr exp))))) ((tagged-list? exp 'begin) (cons 'begin (map process (cdr exp)))) ((tagged-list? exp 'cond) (process (cond->if exp))) ((tagged-list? exp 'let) (cons 'let (cons (map (lambda (clause) (list (car clause) (process (cadr clause)))) (cadr exp)) (map process (cddr exp))))) ((pair? exp) (map process exp)) (else exp)))

Muunnosesimerkki: tilastoja if:ien ehdoista Muutokset edelliseen punaisella syntax-process.scm (define predicate-id 0) (define (process exp) (cond... ((tagged-list? exp 'if) (set! predicate-id (+ predicate-id 1)) (cons 'if (cons (list 'predicate-stat predicate-id (process (cadr exp))) (map process (cddr exp)))))...)) lisää jokaisen if-lausekkeen ehtoon tilastointiproseduurin kutsun esim. (if (< x 0) a b) (if (predicate-stat 1 (< x 0)) a b) muunnettua koodia ajettaessa predicate-stat voisi esim. kerätä tilastoja siitä, kuinka usein mitäkin haaraa suoritetaan (define (predicate-stat n branch) (add-to-statistics! n branch) branch)

Sisältö 1 Ohjelmia muokkaavat ohjelmat 2 Dynaaminen sidonta 3 Lisp-kielistä ja DSL-kielistä

Mikä dynaaminen sidonta? Scheme ja kirjan tulkit, kuten useimmat ohjelmointikielet, ovat leksikaalisesti sidottuja (lexical/static scoping/binding) eli saatavilla olevat muuttujat näkee lauseketta ympäröivästä koodista (staattisesti tai leksikaalisesti) harvinaisempi vaihtoehto on dynaaminen sidonta: tietynnimisen muuttujan arvo on se arvo, joka tälle nimelle viimeksi ajon aikana asetettiin siis muuttujasidonta on dynaaminen eli ajon aikainen käytössä kokonaan lähinnä joissain vanhoissa kielissä, mm. Emacs Lisp, Logo ja APL vähän useammin dynaamista sidontaa käytetään osittain (tietynlaisille muuttujille tai tietyllä tavalla tehdylle koodille), mm. Perlissä, Common Lispissä ja monissa Scheme-toteutuksissa

Eräs tapa ymmärtää dynaamista sidontaa jos kaikki muuttujat ovat dynaamisesti sidottuja, kieli käyttäytyy kuten se toimisi näin: kaikki muuttujat ovat globaaleja muuttujia let-lauseke (tai vastaava) ottaa globaalin muuttujan arvon talteen, asettaa sille uuden arvon ja palauttaa talletetun arvon, kun let-lausekkeen suoritus loppuu samoin esimerkiksi proseduurikutsu asettaa argumenttimuuttujalle uuden arvon kutsun ajaksi ja palauttaa entisen arvon kutsun jälkeen todellisuudessa dynaaminen sidonta toteutetaan usein enemmän leksikaalista muistuttavalla tavalla (seuraava kalvo) dynaaminen sidonta on siis leksikaalista helpompi toteuttaa: ympäristö-tietorakenne voi olla yksinkertaisempi talletetun proseduurin ei tarvitse sisältää ympäristöä (joten proseduurista on tallessa pelkkä koodi eli ajon aikana ei tarvitse varata muistia sitä varten)

Dynaamisen sidonnan toteutus kirjan tulkkiin Muutokset tulkkiin dynaamista sidontaa varten m-eval-dynamic.scm (define (eval exp env) ; envistä voisi nyt tehdä globaalin muuttujan (cond... ; sen sijaan että sitä kuljettaa mukana evalissa ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) ; envin voisi nyt jättää tästä pois... ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env) env))... )) (define (apply procedure arguments env) (cond... ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments env))) ; oli (procedure-environment...)... ))

Esimerkki dynaamisesta sidonnasta Pieni koodiesimerkki (define (f a) (define (add x) (+ x a)) (let ((a 5)) (* a (add 2)))) tavallisella Schemellä eli leksikaalisella sidonnalla (f 3) 25 dynaamisella sidonnalla (f 3) 35 Hyödyllisempi (osittainen) esimerkki show-list.scm (define sl-columns 5) ; näin monta arvoa samalle riville (define sl-column-width 8) ; varataan tilaa näin monta merkkiä/arvo (define (show-list l) ; tulostaa listan l alkiot em. asetusten mukaan...) (define (show-data)... (show-list foo)...) (define (display-report) ; tulostaa tietoja kapeaan ikkunaan... (show-data)...) (define (print-report) ; tulostaa samoja tietoja leveälle paperille... (let ((sl-columns 10)) (show-data))...)

Makrot ovat dynaamisesti sidottuja! jos Lisp- tai C-makrosta laventuvassa koodissa on muuttujannimiä, joita ei ole siinä määritelty, ne käyttäytyvät kuin sidonta olisi dynaamista esim. jos makro lavenee koodiksi, joka käyttää muuttujaa x, tämä x viittaa siihen muuttujaan, joka makron käyttöpaikassa on vrt. jos proseduurin koodissa käyttää muuttujaa x, se haetaan leksikaalisen sidonnan mukaan proseduurin määritelmää eikä kutsua ympäröivästä koodista Schemen omat hygieeniset makrot (define-syntax) ovat kuitenkin leksikaalisesti sidottuja myös poikkeuksien käsittelijät ovat dynaamisesti sidottuja esim. Pythonissa poikkeuksen käsittelijä valitaan niistä try-lauseista, joiden sisällä ollaan poikkeuksen aiheuttavaa koodia suoritettaessa ei siis niistä, jotka ovat staattisesti koodin ympärillä

Dynaaminen sidonta Schemessä: parametrit Schemen with-output-to-file vaihtaa sen tiedoston, johon mm. display kirjoittaa: (define (myprint) (display "The answer is: ") (display 42) (newline)) (myprint) (with-output-to-file "foo.txt" myprint) eli nykyinen tiedosto on kuin dynaamisesti sidottu muuttuja, jota display käyttää monessa Scheme-toteutuksessa tällaiset asetukset on abstrahoitu parametreiksi: ne ovat dynaamisesti sidottuja muuttujia, joilla voi muokata primitiivien toimintaa niiden arvoja voi asettaa letiä muistuttavalla lauseella, esim. (parameterize ((radix 2))...) ohjelmoija voi tehdä myös uusia parametreja ja käyttää niitä itse joissain Schemeissä ja Lispeissä myös tavallisen (esim. globaalin) muuttujan arvon voi vaihtaa hetkeksi fluid-let-rakenteella, esim. (fluid-let ((x 2))...)

Sisältö 1 Ohjelmia muokkaavat ohjelmat 2 Dynaaminen sidonta 3 Lisp-kielistä ja DSL-kielistä

Muista Lisp-kielistä kuin Scheme Lisp-kielet ovat keskenään melko samankaltaisia; yhteisiä piirteitä: sulkusyntaksi (poikkeus: Dylan-kielessä tavallinen syntaksi) monia asioita voi itse määritellä uudelleen (esim. primitiivit) koodin käsittely on helppoa, esim. makroilla tai read:lla monet rakenteista, esim. let ja cond Schemeen verrattuna muut Lispit: eivät yritä olla minimaalisia (eivätkä ole niin siistejä kielinä) ovat yleensä vähemmän funktionaalisia käyttävät silmukoita häntärekursion sijaan käyttävät enemmän makroja ja erikoisia kontrollirakenteita yleensä muuttujilla ja funktioilla on omat nimiavaruudet (ja Schemeen verrattuna ylimääräistä syntaksia niiden käsittelyyn) Common Lisp yhdisti oman aikansa Lispejä yhdeksi isoksi kieleksi (noin 198186) nykyään yleisimmät Lispit lienevät Scheme, Common Lisp ja ohjelmien sisäiset Lispit esim. Emacsissa ja Autocadissa

Esimerkkejä Common Lisp -koodista muutama Common Lispin rakenne: declare: kertoo muuttujien tyypeistä yms. kääntäjälle (eli koodissa voi antaa vinkkejä optimointia varten) tapa dokumentoida proseduurit koodin sisällä (docstring) on lainattu Lispistä suoraan mm. Pythoniin funktioilla voi olla monta paluuarvoa (myös Schemessä) Common Lispin oliojärjestelmä CLOS on monipuolinen ja melko erilainen kuin muissa kielissä (opettavaisella tavalla erilainen?) loop: hyvin monipuolinen silmukkarakenne ( yhdistelmä silmukoista ja list comprehensionista) tagbody ja prog: yhdistelmiä Schemen letistä ja gotosta koodiesimerkkejä Maxima-matematiikkaohjelmistosta: src/factor.lisp src/plot.lisp (selaile esim. näitä jos haluat nähdä miltä Common Lisp näyttää)

DSL-kielistä DSL-kieli (domain specic language) on tiettyyn sovellusalueeseen tehty ohjelmointikieli usein se on periaatteessa yleiskäyttöinen ohjelmointikieli seuraavassa esimerkkinä DSL-kielestä Emacs-tekstieditorin oma Lispin murre se tehtiin Emacsin kongurointiin ja laajentamiseen (muuten pitäisi esim. muuttaa Emacsin C-koodia ja kääntää se uudelleen) kielessä on valmiina paljon tekstieditoriin liittyvää toiminnallisuutta monissa muissakin ohjelmissa on sisällä jonkin kielen tulkki nykyään se on usein tavallinen (skripti)kieli, johon on valmiiksi ladattu ohjelmaan liittyviä funktioita, makroja tms. esim. Python, Lua, Perl, Scheme tai Javascript usein sillä voi laajentaa ohjelmaa vain tietystä kohdasta (esim. Gnomen Hearts-korttipeliin voi tehdä tekoälyjä Pythonilla) yksinkertaisempi variaatio on ohjelmaa varten tehty kieli esim. konguraatiotiedostoille, jossa on jotain ohjelmointikielen ominaisuuksia mutta ei välttämättä esim. silmukoita tai funktioita

Emacsin Lisp-koodista Emacs Lisp on melko iso kieli (yleensä DSL on paljon pienempi) monet Emacsin lisätoiminnot on tehty sillä iso valmis kirjasto erityisesti tekstieditoriin liittyvistä asioista myös mm. oma GUI-kirjasto koodia on paljon: noin 1,2 miljoonaa koodiriviä (GNU Emacs 22.2) hyvin Lisp-mäistä koodia (paljon vanhoja muista Lispeistä lainattuja ohjelmointitapoja) koodi ei ole kovin monimutkaista, abstraktiot yksinkertaisia yleensä hyvin dokumentoitua (docstring-ominaisuudella) kielessä ei ole näkyvyyksiä, ja monia sisäisiäkin funktioita voi käyttää suoraan editorista ja käytetään muualta laajennettavuuden kannalta vähän haurasta: rakenteellisissa muutoksissa pitäisi muuttaa paljon koodia

Muutamia Emacs Lispin kontrollirakenteita (save-excursion koodia ): tallentaa kursorin yms. paikan ja palauttaa sen koodin suorituksen jälkeen imperatiivisempi rakenne olisi tallettaa vanhat arvot paikalliseen muuttujaan ja asettaa ne takaisin lopuksi (with-current-buffer puskuri koodia ) ajaa koodin niin, että sen ajaksi nykyinen editoitava puskuri vaihdetaan annetuksi muitakin with--alkuisia funktioita tai makroja on paljon myös Schemessä on esim. with-output-to-file defadvice: tapa lisätä olemassaolevan funktion alkuun ja/tai loppuun koodia pienissä paloissa, joita voi myöhemmin yksitellen kytkeä päälle ja pois

Emacs Lisp -koodiesimerkkejä katso vaikka näitä jos haluat nähdä Emacs Lisp -koodia: lisp/paren.el (260 riviä): show-paren-mode: yksi suoraviivainen funktio ja asetuksia lisp/calendar/cal-mayan.el (380 riviä): monta pientä funktiota, jotka käyttävät calendarin kirjastoa lisp/xml.el (900 riviä): yksinkertainen recursive descent -tyyppinen XML-jäsennin lisp/font-lock.el (2 300 riviä): sekavahkoa Lispiä, säännöllisten lausekkeiden käyttöä lisp/progmodes/gud.el (3 400 riviä): enimmäkseen tukea erilaisille debuggereille; lähettää tekstikomentoja aliprosessille tai sano Emacsissa C-h k ja joku käyttämäsi näppäinyhdistelmä: ohjetekstin ensimmäinen linkki on lähdekoodiin