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ä

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ä, kevät

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

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ä

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Ohjelmoinnin peruskurssien laaja oppimäärä

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

Ohjelmoinnin perusteet Y Python

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmointikielet ja -paradigmat 5op. Markus Norrena

Hieman linkkejä: lyhyt ohje komentoriviohjelmointiin.

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

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

Scheme-kesäkurssi luento 1

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 6

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

Scheme-kesäkurssi luento 4

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Ohjelmoinnin perusteet Y Python

Tutoriaaliläsnäoloista

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Hakemistojen sisällöt säilötään linkitetyille listalle.

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Pakkaukset ja määreet

Ohjelmoinnin peruskurssi Y1

Unix-perusteet. Unix/Linux-käyttöjärjestelmä ja sen ominaisuudet

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

Java kahdessa tunnissa. Jyry Suvilehto

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

SEPA REFAKTOROINTI Antti Ahvenlampi, 57408L Erik Hakala, 57509T

Common Lisp Object System

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

Korpusten käsittely clt131, P Luento 5

Luento 4 Aliohjelmien toteutus

Vertailulauseet. Ehtolausekkeet. Vertailulauseet. Vertailulauseet. if-lauseke. if-lauseke. Javan perusteet 2004

Kieliteknologian ATK-ympäristö Neljäs luento

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

Ohjelmoinnin perusteet Y Python

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

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

Ohjelmoinnin perusteet Y Python

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

Ohjelmoinnin perusteet Y Python

- Komposiittityypit - Object (Mukaanlukien funktiot) - Array. - Erikoisdatatyypit - null - undefined

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

11/20: Konepelti auki

PERL. TIE Principles of Programming Languages. Ryhmä 4: Joonas Lång & Jasmin Laitamäki

Rajapinta (interface)

Ohjelmoinnin peruskurssi Y1

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

TIE Ohjelmistojen suunnittelu. Luento 8..9: moniperintä

Taas laskin. TIES341 Funktio ohjelmointi 2 Kevät 2006

Olio-ohjelmointi Javalla

Perintä (inheritance)

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

linux: Ympäristömuuttujat

Linkitetystä listasta perittyä omaa listaa käytetään muun muassa viestiin liittyvien vastausten säilömiseen.

Ohjelmoinnin perusteet Y Python

Kieliteknologian ATK-ympäristö Viides luento

Ohjelmoinnin perusteet Y Python

Transkriptio:

Ohjelmoinnin peruskurssien laaja oppimäärä Luento 9: Miten oliot toteutetaan, skriptausta Riku Saikkonen (osa kalvoista on suoraan ei-laajan kurssin luennoista) 18. 3. 2013

Sisältö 1 Oliot Scheme-tulkkiin 2

Tee se itse: oliokieli lisätään SICP-kirjan metasirkulaariseen Scheme-tulkkiin yksinkertainen oliojärjestelmä tavoitteen saada selville: millaista uutta syntaksia olioihin tarvitaan? kuinka paljon koodia olioiden toteuttaminen vaatii? miten oliot käytännössä toimivat (esim. miten metodikutsu toteutetaan)? järjestelmä tukee: luokkia: kenttiä ja metodeita perintää ja dynaamista metodinvalintaa (ei moniperintää) oliot rakennetaan Schemen päälle eli olioita voi käyttää sekaisin muun koodin kanssa kaikkea ei tehdä niin hienosti kuin voisi (mm. ei proseduurien sisäisiä luokkia) kalvoissa vain osa toteutuksesta (mm. syntaksin ja tietorakenteiden käsittelyssä on melko paljon yksinkertaisia yksityiskohtia)

Oliojärjestelmämme syntaksi Koodiesimerkki tässä tulkattavasta koodista (define-class point object (define-field x 0) (define-field y 0) (define-method (dist point) (define (square x) (* x x)) (sqrt (+ (square (- (this get-x) (point get-x))) (square (- (this get-x) (point get-x)))))) (define-method (print) (display "Point at ") (display (this get-x)) (display ", ") (display (this get-y)) (newline))) point.scm (define-class colored-point point (define-field color 'black) (define-method (print) (display "Colored point at ") (display (this get-x)) (display ", ") (display (this get-y)) (display " colored ") (display (this get-color)) (newline))) (define p1 (new point 5 8)) (p1 set-x! 5) (p1 set-y! 8) (define p2 (new colored-point 2 3 "blue")) (p2 set-x! 2) (p2 set-y! 3) (p2 set-color! "blue") (p1 print) (p2 print) (p1 dist p2) (p2 dist p1)

Kertaus: Mitä oliosta on tallessa muistissa? ajon aikana luokat ja metodit ovat jo tiedossa: ne on luotu käännösaikana tai luokkia määritellessä sen sijaan kenttien arvot ovat jokaiselle oliolle yksilöllisiä ajon aikana jokaisesta oliosta on tallessa: kenttien arvot viittaus luokan tiedot (mm. metodit) sisältävään tietorakenteeseen mikä sitten on metodi? proseduuri, joka saa implisiittisenä argumenttina olion, jonka kautta metodia kutsuttiin (Javassa tästä tulee this; Pythonin self näkyy eksplisiittisesti metodin määritelmässä, muttei näy kutsussa) metodista on siis (esim. Javassa) muistissa vain koodi vrt. proseduuri Scheme-tulkissa: koodi ja määrittely-ympäristö (sisäkkäisten luokkien tukemiseen voisi tarvita myös määrittely-ympäristöä)

Olioiden toteutus 1/6 Muutokset tulkkiin: tulkin tietorakenteita (define (make-method body parameters environment) (list 'method body parameters environment)) (define (method-body method) (cadr method)) ; jne. m-eval-object (define (make-class name parent method-alist field-names field-value-exps) (list 'class name parent method-alist field-names field-value-exps)) (define (class-name class) (cadr class)) ; jne. (define (make-object class field-values) (cons 'object (cons class field-values))) (define (object? val) (tagged-list? val 'object)) (define (object-class object) (cadr object)) (define (object-field-value-get object field-index) (list-ref (cddr object) field-index)) (define (object-field-value-set! object field-index value) (set-car! (list-tail (cddr object) field-index) value)) metodissa on koodi, argumentit ja (globaali) ympäristö luokassa on isäluokka, metodit, kentät, kenttien alkuarvolausekkeet oliossa on tallessa viittaus luokkaan ja kenttien arvot

Olioiden toteutus 2/6 Muutokset tulkkiin: globaali luokkalista m-eval-object (define (make-initial-class-list) (list (list 'object (make-class 'object #f '() '() '())))) (define the-class-list (make-initial-class-list)) (define (find-class class-name) (let ((result (assq class-name the-class-list))) (if result (cadr result) (error "Unknown class name -- FIND-CLASS" class-name)))) (define (add-to-class-list! class-name class) (set! the-class-list (cons (list class-name class) the-class-list))) pidetään luokkien tietoja globaalissa listassa, josta find-class hakee luokan nimellä tämän vuoksi emme tue sisäkkäisiä luokkamäärittelyjä (ja metodiin talletettu ympäristö on aina globaali ympäristö, jos define-classia esiintyy vain tulkin päätasolla) globaalin listan sijaan luokat voisi periaatteessa myös yhdistää jollain tavalla ympäristöihin

Olioiden toteutus 3/6 Muutokset tulkkiin: uusi eval m-eval-object (define (eval exp env) (cond... ((define-class? exp) (eval-class-definition exp env)) ((new? exp) (eval-new (new-class-name exp) (list-of-values (new-arguments exp) env) env)) ((application? exp) (let ((evaled-op (eval (car exp) env))) (if (object? evaled-op) ; onko tämä metodikutsu? (apply-method evaled-op (cadr exp) ; metodin nimi (list-of-values (cddr exp) env)) (apply evaled-op (list-of-values (cdr exp) env)))))... )) evaliin tulee kolme uutta haaraa: 1 luokan määritteleminen (define-classin sisältä käsitellään samalla kenttiä ja metodeja määrittelevät lausekeet) 2 uuden olion tekeminen eli new 3 metodin kutsuminen (erilainen kuin proseduurikutsu)

Olioiden toteutus 4/6 Muutokset tulkkiin: uuden luokan luonti (osin) m-eval-object (define (eval-class-definition exp env) (let* ((new-class-name (class-definition-name exp)) (parent (find-class (class-definition-parent-name exp))) (field-names (map car (class-definition-fields exp))) (field-value-exps (map cadr (class-definition-fields exp))) (all-field-names (append (class-field-names parent) field-names)) (all-field-value-exps (append (class-field-value-exps parent) field-value-exps)) (user-methods (class-definition-make-method-alist exp env)) (get-set-methods (make-get-set-methods (length (class-field-names parent)) field-names env)) (the-new-class (make-class new-class-name parent (append user-methods get-set-methods) all-field-names all-field-value-exps))) (add-to-class-list! new-class-name the-new-class))) tämä lähinnä hakee define-class-lausekkeesta isäluokan, kentät ja metodit ja antaa ne lopulta make-class:lle make-get-set-methods tekee kentille get- ja set-metodit

Olioiden toteutus 5/6 Muutokset tulkkiin: uuden olion tekeminen m-eval-object (define (eval-new class-name constructor-arguments env) (let* ((class (find-class class-name)) (field-values (list-of-values (class-field-value-exps class) env)) (obj (make-object class field-values))) ;; käyttäjän määrittelemää konstruktoria pitäisi kutsua tässä ;; (ei vielä toteutettu) obj)) yksittäisessä oliossa on tallessa tieto sen luokasta (eli viittaus class-tietorakenteeseen) sekä kaikkien kenttien arvot yllä list-of-values suorittaa define-field:llä määritellyt lausekkeet, joista tulevat kenttien oletusarvot (toinen tapa olisi suorittaa ne vain kerran luokkaa määritellessä)

Olioiden toteutus 6/6 Muutokset tulkkiin: metodikutsu m-eval-object (define (apply-method object method-name arguments) (let ((method (find-method object method-name))) (eval-sequence (method-body method) (extend-environment (cons 'this (method-parameters method)) (cons object arguments) (method-environment method))))) (define (find-method object method-name) (define (find-in-class class) (assq method-name (class-method-alist class))) (define (find-in-parents class) (and class (or (find-in-class class) (find-in-parents (class-parent class))))) (let ((result (find-in-parents (object-class object)))) (if result (cadr result) (error "Unknown method name -- FIND-METHOD" method-name)))) kuten proseduurin kutsu, mutta ylimääräinen argumentti this metodia haetaan ensin olion luokasta ja sitten sen isistä

Mihin pääsimme? yksinkertaisten olioiden toteuttaminen oli melko helppoa enimmäkseen uuden syntaksin ja luokkatietorakenteen käsittelyä tosin koodia tuli yhteensä aika paljon järjestelmämme muistuttaa Javan ja Pythonin oliojärjestelmiä yksinkertaistettuna jotta se järjestelmä olisi kokonainen, siihen pitäisi lisätä ainakin omat konstruktorit ja super (harjoitustehtävinä) muuta mahdollista lisättävää: moniperintä (tässä voisi kokeilla eri toteutusvaihtoehtoja) abstraktit luokat luokkamuuttujat reektio (tapa nähdä kielen sisältä esim. mitä metodeita oliolla on) instanceof/isinstance, final yms. yksittäisiä ominaisuuksia Java-tyyliset näkyvyydet (vähän työläämpää)

Mitä voisi tehdä toisin? 1/2 automaattisia get- ja set-metodeja ei välttämättä tarvitsisi tehdä (Javassa ja C++:ssa ei ole) mutta silloin tarvittaisiin syntaksi kenttien käsittelyyn nyt niihin pääsee käsiksi vain näillä metodeilla metodien (ja proseduurien) argumenteilla voisi olla staattiset tyypit, ainakin silloin kun ne ovat olioita nyt olioargumentiksi kelpaa mikä tahansa olio, jolla on oikean nimiset metodit (ei siis välttämättä tietyn olion aliluokka) tätä tapaa kutsutaan duck typing:ksi, ja se on mm. Pythonissa, Rubyssä ja osin Common Lispissä vaihtoehto on ns. nimipohjainen tyyppijärjestelmä (nominal type system), kuten esim. Javassa ja C++:ssa tässä vaihtoehtoisessa tavassa voisi tukea myös useampaa samannimistä metodia, joilla on eri argumentit esimerkki: aiemmassa esimerkkikoodissa Point-olioksi kelpaa joko a) mikä tahansa olio jolla on mm. pprint-niminen metodi, tai b) vain Point-luokan aliluokan olio

Mitä voisi tehdä toisin? 2/2 metodien ei tarvitsisi kuulua yksittäisiin luokkiin: metodi on kuten proseduuri, jonka ensimmäinen argumentti (this/self) on erityisasemassa (ja jota kutsutaan olion kautta) mutta metodien sijaan (tai lisäksi) voisi olla vain funktioita, joiden kaikki argumentit ovat samanarvoisia C++ kutsuu tällaisia friend-funktioiksi, Common Lisp geneerisiksi funktioiksi periaatteessa luokka-käsitettä ei tarvittaisi, jos olioista voisi tehdä muutettuja kopioita esim. Javascriptissä luokan sijaan tehdään prototyyppiolio, josta varsinaiset oliot kopioidaan olioiden syntaksikin voisi tietysti olla eri...

Sisältö 1 Oliot Scheme-tulkkiin 2

Mikä on skripti? skriptien tyypillisiä piirteitä: lyhyt ohjelma (jopa vain 1 rivi, harvoin yli 500) nopeasti tehty (minuuteista tunteihin) usein vain tekijän itsensä käyttöön tarkoitettu joskus kertakäyttöinen tai vain muutaman kerran käytettävä skripteillä tyypillisimmillään: käsitellään tekstimuotoista dataa esim. muodosta toiseen käytetään muita ohjelmia apuna: skripti käynnistää usein aliohjelmia (harvemmin käyttää vastaavia kirjastoja) tehdään yksittäinen korjaus tiettyyn tilanteeseen esimerkkejä: laajan tehtävistä: MP3-tehtävä, karttatehtävä, kuvaajatehtävä korjataan tiedostojen nimiä tai oikeuksia luetaan tekstitiedosto(i)sta tiettyjä kohtia ja tehdään niistä tiedoista esim. koostetaulukko käynnistetään jokin ohjelma ja alustetaan tilanne sopivaksi sitä varten (esim. /usr/bin/firefox on usein skripti)

Unix shell-skriptit (sh) shell-skriptit ovat Unixin tavallisen komentotulkin kielellä tehtyjä pieniä ohjelmia komentotulkkikieliä on useita, mutta skriptit tehdään lähinnä ns. Bourne/POSIX sh:lla (josta esim. bash on laajennus) käytetään eniten (Unix-)ylläpidossa ja mm. Linux-levitysten käynnistysskripteissä hyvää: sama kieli kuin interaktiivisessa komentotulkissa; helppo ajaa ja yhdistellä komentoja (eli muita ohjelmia); valmiina kaikissa Unixeissa puutteita: ei tietorakenteita; syntaksi menee vaikeaksi monimutkaisissa asioissa (aliohjelmien vuoksi useita syntakseja sisäkkäin); turvattomien merkkijonojen käsittelyssä pitää olla tarkkana; monta toteutusta, vain tietyt ominaisuudet toimivat kaikissa; toimii parhaiten Unixissa esimerkkejä: /usr/bin/firefox, /etc/init.d/x11-common ohje esim. http://tldp.org/ldp/abs/html/

Perl Perl-skriptikielen syntaksi muistuttaa mm. shell-skriptejä ja C:tä yhtenäisempi kieli kuin shell-skriptit (voi tehdä paljon enemmän kielen sisällä ilman apuohjelmia) paljon valmiita kirjastoja (kuten Pythonissakin) monipuolinen myös ohjelmointikielenä (esim. moduulit, oliot, ensimmäisen luokan funktiot, leksikaalinen ja dynaaminen sidonta, jne.), joskin välillä erikoinen erityisen hyvä säännöllisten lausekkeiden käsittelyssä (ja siis skripteissä, jotka käyttävät niitä paljon) puutteita esim: sisäkkäiset tietorakenteet hankalia käyttää, skriptikielenä ei tarkoitettu isoihin ohjelmiin usein shell-skripteistä siirrytään Perliin tai Pythoniin, kun komentotulkki ei enää riitä vanha skriptikieli AWK on vähän Perlin kaltainen, mutta yksinkertaisempi (käytetään yhdessä shell-skriptien kanssa) esimerkkejä: /usr/bin/shasum, gnome-terminal.wrapper ohje: esim. manuaalisivu man perlintro

Skriptaus Pythonilla Python toimii myös skriptikielenä ohjelman ja skriptin välillä ei ole tarkkaa rajaa Python ja Perl ovat skriptikielinä melko samankaltaisia eroja: Pythonissa on mm. parempi tuki tietorakenteille, Perlissä tiivimpää syntaksia mm. säännöllisiin lausekkeisiin ja aliohjelmien käynnistämiseen skriptaukseen sopivia kirjastoja löytyy molemmille paljon Python lienee parhaimmillaan skripteissä, jotka käsittelevät (suurta määrää, varsinkin sisäkkäistä) dataa jos skriptin pitää vain käynnistää muutama komento, shell-skripti tai Perl ovat yleisempiä ratkaisuja (mutta Pythonkin toimii) Python-skriptiä on ehkä muita kahta helpompi laajentaa oikeammaksi ohjelmaksi esim. lisätä graanen käyttöliittymä (tehdään joskus Perlissäkin) Python-skripti tuntuu pysyvän todennäköisemmin helppolukuisena hyvin pienissä skripteissä Python vaatinee vähän enemmän koodia sillä lyhennysmerkintöjä on vähemmän ja esim. yksi rivi ei riitä

Esimerkki Python-skriptistä: koneen yleisimmät prosessit Osa ps -ef -komennon tulostetta UID PID PPID C STIME TTY TIME CMD root 12502 576 0 Aug 29? 0:22 screen irssi root 17117 1612 0 Jul 07? 0:00 /usr/lib/ssh/sshd root 12077 1612 0 16:57:57? 0:00 /usr/lib/ssh/sshd Python-skripti import sys cmds = dict() hdr = sys.stdin.readline() ind = hdr.rfind(" CMD")+1 for l in sys.stdin: cmd = l[ind:].partition(" ")[0].strip() if cmd in cmds: cmds[cmd] += 1 else: cmds[cmd] = 1 Ajoesimerkki 500x ssh-agent 418x /bin/tcsh 416x screen 308x irssi 307x /usr/lib/ssh/ssh 123x -tcsh 96x ssh 65x /c/bin/zsh 40x pine 17x /c/bin/bash scmds = sorted(cmds.items(), key=lambda x: x[1], reverse=true) for c,v in scmds[:10]: print str(v)+"x "+c