SEMINAARI ESSEE: DYLAN. TIE Principles of Programming Languages

Samankaltaiset tiedostot
TIE PRINCIPLES OF PROGRAMMING LANGUAGES Eiffel-ohjelmointikieli

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Ohjelmointikieli TIE Principles of Programming Languages Syksy 2017 Ryhmä 19

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

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

TIE Principles of Programming Languages CEYLON

Common Lisp Object System

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

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

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

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

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

7. Oliot ja viitteet 7.1

Ohjelmoinnin peruskurssien laaja oppimäärä

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

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

Dart. Ryhmä 38. Ville Tahvanainen. Juha Häkli

Objective-C. Ryhmä 35: Ilpo Kärki Aleksi Pälä

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

815338A Ohjelmointikielten periaatteet

Tutoriaaliläsnäoloista

15. Ohjelmoinnin tekniikkaa 15.1

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

Sisällys. 15. Lohkot. Lohkot. Lohkot

11/20: Konepelti auki

9. Periytyminen Javassa 9.1

Solidity älysopimus ohjelmointi. Sopimus suuntautunut ohjelmointi

Sisällys. 16. Lohkot. Lohkot. Lohkot

Haskell ohjelmointikielen tyyppijärjestelmä

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

12. Monimuotoisuus 12.1

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

15. Ohjelmoinnin tekniikkaa 15.1

Ohjelmoinnin peruskurssien laaja oppimäärä

Rajapinta (interface)

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

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

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

Ohjelmoinnin peruskurssien laaja oppimäärä

UML -mallinnus TILAKAAVIO

Luento 5. Timo Savola. 28. huhtikuuta 2006

Ohjelmoinnin perusteet Y Python

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

1. Olio-ohjelmointi 1.1

12. Monimuotoisuus 12.1

7/20: Paketti kasassa ensimmäistä kertaa

Ohjelmoinnin perusteet Y Python

Tie Principles of Programming Languages Seminar Essay. Lua. Group 23 Miikka Koskinen Joose Sainio

Ohjelmoinnin perusteet Y Python

Osoitin ja viittaus C++:ssa

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

5/20: Algoritmirakenteita III

Tietueet. Tietueiden määrittely

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

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

Ohjelmoinnin perusteet Y Python

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

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

PRINCIPLES OF PROGRAMMING LANGUAGES - DEBUGGER

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

Loppukurssin järjestelyt

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

Scheme-kesäkurssi luento 5

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

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

14. Poikkeukset 14.1

Harjoitustyö: virtuaalikone

9. Periytyminen Javassa 9.1

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

14. Poikkeukset 14.1

4. Luokan testaus ja käyttö olion kautta 4.1

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Groovy. Niko Jäntti Jesper Haapalinna Group 31

4.2. ALIOHJELMAT 71. Tulosvälitteisyys (call by result) Tulosvälitteinen parametri kopioidaan lopuksi

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Loppukurssin järjestelyt C:n edistyneet piirteet

TIES542 kevät 2009 Tyyppijärjestelmän laajennoksia

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

4. Lausekielinen ohjelmointi 4.1

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

Tyyppiluokat II konstruktoriluokat, funktionaaliset riippuvuudet. TIES341 Funktio-ohjelmointi 2 Kevät 2006

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. IX Suunnittelumallit Proxy, Factory Method, Prototype ja Singleton

8. Näppäimistöltä lukeminen 8.1

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

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

Imperatiivisten ohjelmien organisointiparadigmojen. historia

Imperatiivisten ohjelmien organisointiparadigmojen historia

Soveltuvuustutkimus Lifebelt-ohjelman ideologian käytettävyydestä olioorientoituneeseen

TAMPEREEN TEKNILLINEN YLIOPISTO

Ohjelmoinnin peruskurssien laaja oppimäärä

1. Omat operaatiot 1.1

Java kahdessa tunnissa. Jyry Suvilehto

Ohjelmoinnin peruskurssien laaja oppimäärä

Javan perusteita. Janne Käki

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

Transkriptio:

SEMINAARI ESSEE: DYLAN TIE-20306 Principles of Programming Languages Tiivistelmä Tässä esseessä käydään läpi Dylan ohjelmointikielen perus piirteet ja ominaisuudet. Alussa myös lyhyt historia kielen synnystä ja sen kehitysvaiheista. Mukana myös koodi esimerkkejä muun muassa mergesortista toteutettuna Dylanilla. Jaakko Laitinen & Shayan Shajarian Ryhmä 27

1 Johdanto Dylan nimi tulee englannin sanoista dynamic ja language, eli dynaaminen kieli, mikä kuvastaa jo hyvin kielen luonnetta ja myös sen tavoitteita ja tarkoitusta. Dylan sai alkunsa 1990-luvulla Applen sisäisenä projektina. Alun perin Dylanin oli tarkoitus tulla käyttöön Applen omaan kehitystyöhön, mutta Dylanin kehitys ei edennyt tarpeeksi nopeasti ja lopulta projekti hylättiin Applen osalta. Dylanin kehitystä jatkoi kuitenkin Applen ulkopuoliset tahot ja Dylanin kehitys keskittyi pääasiassa Windows alustalle. Lopputuloksena Dylan siirtyi avoimen lähdekoodin projektiksi, joka tunnetaan nykyään Open Dylanina. Dylan kääntäjästä on unix alustalle suunnattu versio nimeltä Gwydion Dylan, joka tosin vain luo C-koodia Dylanin lähdekoodista. Dylan on saanut vaikutteita muun muassa Lispistä(CLOS) ja Shcemasta. Alun perin Dylanin syntaksi suunniteltiin olemaan Lispin kaltainen prefix-syntaksi. Tämän prefix-syntaksin pelättiin kuitenkin olevan liian vieras kohderyhmälle, joten lopulta Dylanin kehittäjät päätyivät tutumpaan C:n kaltaiseen infix-syntaksiin. Luvussa 2 käydään läpi Dylanin ominaisuuksia kurssilla mietittyjen aiheiden näkökulmasta. Luku 3 taas esittelee muita kielen mielenkiintoisia ominaisuuksia. Lopuksi vielä lyhyt yhteenveto, käytetyt lähteet ja koodiesimerkit. 2 Pääpiirteet Dylanin pääasiallinen pyrkimys on ollut luoda kieli, joka toisaalta abstrahoi turhan laitteistoläheisyyden pois tarjoten nopean tavan rakentaa prototyyppejä, mutta mahdollistaen prototyyppien jatkojalostuksen ohjelmiksi, joidenka suoritus olisi verrattavissa laitteistoläheisemmin kehitettyihin vastaaviin ohjelmiin. Tämä kehityskaari näkyy esimerkki koodissa (Koodi 3 ja Koodi 2), jossa on esitelty kaksi kielen hyväksymää syntaktista ääripäätä yksityiskohtien suhteen. Kun esimerkiksi muuttujien ja parametrien tyypit on eksplisiittisesti ilmoitettu, kääntäjän pitäisi pystyä generoimaan tehokkaampaa koodia kuin, jos tyypit jätetään auki. 2.1 Paradigmat Dylan on yhdistelmä funktionaalista- ja olio-paradigmaa. Kaikki Dylanissa ovat olioita ja niitä voidaan käsitellä saman arvoisesti. Vaikka Dylanissa ohjelman rakenne voi muistuttaa imperatiivisen kielen rakennetta (kuten C) peräkkäin suoritettavien lausekkeiden takia, on se kuitenkin suurelta osin funktionaalinen kieli. Funktioita käsitellään kuten mitä tahansa muuta luokkaa ja yleensä keskitytään prosessoimaan annettua sisääntuloa sen muuttamisen sijaan. Dylanin olio-luonne tarjoaa kuitenkin myös niin sanotut mutable-luokat joiden tilaa voi muuttaa vasten funktionaalisuuden periaatetta. Dylan tarjoaa kaikki yleisimmät olio-ohjelmoinnin ominaisuudet kuten käyttäjän määrittämät luokat, (moni- )periyttämisen ja polymorfismin; ainakin omalla tavallaan. Sen sijaan, että luokalle määritettäisiin suoraan metodeja, luokka määrittelyssä spesifioidaan ainoastaan luokan tilamuuttujat. Näille luokan muuttujille luodaan automaattisesti myös funktiot arvojen asettamiseen ja palauttamiseen. Dylan käyttää niin sanottua multiple dispatch mekanismia hoitamaan tiettyyn luokkaan liittyvät funktiot ja niiden kutsumisen. Tästä tarkemmin luvussa 3.1. 2.2 Tyyppi järjestelmä Dylanissa pääasiassa käytetyt tyypit ovat luokat (classes), singletonit (singletons), unionit (unions) ja rajatut (limited). Kaikki oliot ovat siis esiintymiä jostain näistä. Singletonit tekevät ikään kuin oliosta itsestään luokan/tyypin. Tämä tarkoittaa esimerkiksi funktiokutsun parametrissa, että funktiota pitää kutsua tietyllä 1

oliolla, johon singleton-tyyppi perustuu. Union kokoaa useamman luokan/tyypin yhdeksi tyypiksi ja parametrina se siis hyväksyy minkä tahansa olion, joka kuuluu unionin luokkiin/tyyppeihin. Rajatut tyypit taas ottavat jonkin luokan ja muodostaa sille ali-tyypin, jolla on myös muita rajoitteita. Esimerkiksi <integer>luokasta voi määrittää version, jonka arvo alue on rajattu tietylle välille. Koko tyyppi hierarkian huipulla on <object>-luokka ja kaikki Dylanissa on joko tämän esiintymä ("olio") tai alityyppi tästä (edellä mainitut tyypit). Luokkien yhteydessä periyttäminen määrittelee luokka hierarkian ja aliluokka suhteet. 2.3 Muuttujat ja parametrit Dylanissa kaikki ovat olioita, jopa numeeriset vakiot eli numerot. Näin ollen kaikki muuttujat ja parametrit ovat vain viitteitä tiettyyn olioon ja muuttujat vain sidotaan tiettyyn olioon. Dylanissa "="-merkki sitoo muuttujaan olion muuttujan määrittelyn yhteydessä, mutta pitää käyttää ":="-merkkiä kun muuttuja halutaan sitoa uuteen olioon. Dylanissa siis kaikki muuttuja ja funktiot käsitellään niin sanotusti sidontoina (bindings). Tämä tuo muun muassa vertailuun eri tasoja. Kun kahta oliota vertaillaan "="-merkillä, testataan yleensä, onko viitatut oliot samaa luokkaa ja onko niillä sama rakenne (käyttäjä voi määritellä oman funktion "="-operaattorille, kun sitä käytetään tiettyjen luokkien kanssa). Kun taas vertaillaan "=="-merkillä, testataan viittaavatko muuttujat samaan olioon. Funktiolle voidaan antaa C/C++:n jne. tyyliin (pakollisia) parametreja, jotka on annettava tietyssä järjestyksessä. Tämän lisäksi avainsanalla #key voidaan määrittää vapaaehtoisia avain-parametreja, jotka annetaan pakollisten parametrien jälkeen ensiksi antamalla avain-parametrin nimi ja sitten arvo (järjestyksellä ei väliä). Avain-parametreille annetaan oletus arvo (tai false). Dylanissa on myös mahdollista antaa parametrilistoja avain sanalla #rest. Tämä järjestää loput parametrit listaksi. Monipuolisen funktio parametri järjestelmän lisäksi funktiot voivat palauttaa useamman kuin yhden arvon kerrallaan. 2.4 Dynaaminen muistinhallinta Dylanissa käytetään automaattista roskien keruuta eli eksplisiittistä muistin varausta ja vapautusta ei tarvita. Tämä voi aiheuttaa pientä hidastumista manuaaliseen muistin hallintaan verrattuna, mutta roskien keruulla voidaan välttää yleisimpiä muistinhallintaan liittyviä virheitä. Hyvin toteutettu kääntäjä voi myös päätellä milloin olio luodaan vain pinoon, jolloin sen vapauttaminen on helppoa. 2.5 Enkapsulointi Enkapsulointi menetelmistä luokat ovatkin jo mainittu edellä, mutta niiden lisäksi Dylan tarjoaa niin sanotut moduulit (modules) ja kirjastot (libraries) hallitsemaan ohjelman rakennetta. Yksinkertainen moduuli/kirjasto esimerkki on esitetty dokumentin lopussa (Koodi 1). Moduuli määrittää, mitä muita moduuleita käytetään (moduulin ympäristössä) ja se myös määrittää, mitkä sidonnat paljastetaan (export) eli mitkä luokat/muuttujat/funktiot ovat käytettävissä moduuleissa, jotka käyttävät määriteltävää moduulia. Kirjastot taas määrittelevät, mitä muita kirjastoja tullaan käyttämään. Kirjastot vastaavasti taas paljastavat moduulit, joita kyseiset kirjastot haluavat tarjota muille. Näitä yhdistämällä käyttäjällä on hyvin hienojakoinen tapa hallita, mitä rajapintoja mikin kirjasto paljastaa. 3 Muita ominaisuuksia Tässä luvussa esitellään vielä muita Dylanin ominaisuuksia, joita ei aikaisemmissa luvuissa tullut esille. Dylanista löytyy melko paljon erilaisia ominaisuuksia, joten tässä käydään läpi vain pintapuolisesti mielenkiintoisimpia ominaisuuksia. 2

3.1 Multiple dispatch ja geneeriset funktiot Dylanissa funktiot tukevat niin sanottuja multimetodeja (multimethods/multiple dispatch). Tämä tarkoittaa, että funktiokutsun yhteydessä kutsuttava funktio valitaan jokaisen parametrin tyypin/luokan perusteella. Prosessi menee korkealla tasolla niin, että aluksi jokaista parametria kohden etsitään kaikki funktion versiot, jotka sopivat kyseiseen parametriin eli funktiot, joiden parametrin luokkaan kyseinen parametrin luokka on ali-luokkana. Löydetyt funktiot järjestetään niiden spesifiyden mukaan. Spesifiys tässä tarkoittaa luokkaa, joka on perintä hierarkiassa mahdollisimman lähellä parametrina annetun olion varsinaista luokkaa. Lopuksi valitaan mahdollisimman spesifi funktio, joka löytyy kaikkien parametrien listasta. Luokkien funktiot voidaankin määrittää vain kirjoittamalla funktio, joka ottaa kyseisen luokan olion parametrina. Tämä mahdollistaa niin sanottujen geneeristen funktioiden määrittelyn. Geneerinen funktio ei vastaa mitään varsinaista toteutusta, mutta ohjelmoija voi määritellä samalla nimellä metodeja, joilla on jokin varsinainen toteutus ja parametreilla luokka, joille funktio halutaan määritellä. Parametrien luokka määrittää varsinaisesti kutsutun funktio yllä esitetyn mukaisesti. Periyttämisen yhteydessä periytetty luokka voi hyödyntää ylä-luokan funktioita, mutta se voi myös laajentaa tai määrittää uudestaan kyseiset funktiot. Laajentaminen onnistuu kutsumalla next-method()-funktiota, joka kutsuu seuraavaksi spesifeintä funktiota (yleensä siis ylä-luokan vastaavaa funktiota). 3.2 Poikkeuskäsittely ja lohkot Dylanissa tarjotaan poikkeuskäsittelyyn hieman muista kielistä poikkeava mekanismi. Dylan tarjoaa niin sanotun signaloinnin (signaling). Koodiin voi lisätä signal-kutsun, jolla voidaan käsitellä poikkeukselliset tilanteet. Toisin kuin esimerkiksi C/C++:ssa, signalointi ei keskeytä ohjelman suoritusta vaan se on kuin funktiokutsu ja se etsii viimeisimmän käsittely-funktion (handle-funktion), joka sitten suoritetaan. Käsittely funktio asetetaan 'let handler <error-class> = error-handler-func'-komennolla. Käsittely funktio voidaan siis asettaa missä vain ennen signalointia ja sitä kutsutaan sitten signaloidussa kohdassa. Kuten muutkin funktiot, myös signalointi-kutsu voi palauttaa jonkin arvon poikkeuksesta palautumiseksi. Edellä mainitulla mekanismilla ei kuitenkaan ole mahdollista poiketa ohjelman normaalista suorituksesta. Ohjelman normaalin suorituksen muuttamiseksi Dylanissa on niin sanotut lohkot (blocks)(katso Koodi 2 ja Koodi 3), jotka muistuttavat esimerkiksi C/C++:n goto-lausetta tai break-lausetta. Lohkot voivat palauttaa arvoja ja ne määritetään 'block(block_id)...end'-rakenteella. Nyt kutsumalla block_id(ret_val)-funktiota keskeytyy normaali suoritus ja kyseisestä lohkosta poistutaan. Lohkoihin voi myös määrittää vapaaehtoiset afterwards- ja cleanup-osiot. Afterwards-osio suoritetaan vain normaalin suorituksen jälkeen. Cleanup-osio suoritetaan aina lohkon jälkeen (vaikka olisi poistuttu kesken). Lohkoihin voidaan lisäksi vielä yhdistää signalointi, jolloin saadaan C++:n try-catch-lohkon kaltainen rakenne lisäämällä exception-osio. 4 Yhteenveto Imperatiivisia/olio kieliä käyttäneelle Dylan voi aluksi vaikuttaa melko tutulta, mutta se silti sisältää vahvan funktionaalisen pohjan. Dylan tarjoaa paljon ominaisuuksia, joita käytetyimmissä kielissä harvemmin tapaa. Jää tosin ohjelmoijan vastuulle hyödyntää niitä. Toisaalta ominaisuuksien moninaisuus voi hankaloittaa kielen omaksumista, joten ohjelmoija voi helposti tukeutua vanhoihin tapoihinsa, vaikka Dylan tarjoaisikin paremman tavan saavuttaa sama asia. 3

5 Lähteet Dylan Hackers, "An Introduction to Dylan", saatavilla: http://opendylan.org/documentation/intro-dylan/index.html Open Dylan -> History, saatavilla: http://opendylan.org/history/index.html Neal Feinberg et al., "Dylan Programming", saatavilla: http://opendylan.org/books/dpg/index.html Andrew Shalit, "The Dylan Reference Manual", saatavilla: http://opendylan.org/books/drm/title Wikipedia, "History of the Dylan programming language", saatavilla: https://en.wikipedia.org/wiki/history_of_the_dylan_programming_language define library sort-lib use dylan; use mergesort-lib; use quicksort-lib; use bucketsort-lib; define library mergesort-lib use dylan; export mergesort; define module mergesort use dylan; export mergesort!, mergesort; Koodi 1: Esimerkki kuvitteellisesta sort-kirjastosta. 4

define method mergesort! ( lst ) block( skip ) if ( ~lst size(lst)==1 ) skip(); local method split-lst () values( copy-sequence (lst, end: size(lst)/2), copy-sequence (lst, start: size(lst)/2 + 1) ) let (l1,l2) = split-lst(lst); mergesort!(l1); mergesort!(l2); for (i from 0 to size(lst)-1) let (a,b) = values(head(l1),head(l2)); if ( ~b ( a & (a < b)) ) lst[i]:= a; l1:=tail(l1); else lst[i]:=b; l2:=tail(l2); Koodi 3: Esimerkki toteutus mergesortista. (Toimivuutta ei testattu käännösympäristön pystytyksessä ilmenneiden ongelmien takia) define method mergesort! ( lst :: <collection> ) => () block( skip ) if ( ~lst size(lst)==1 ) skip(); end if; local method split-lst () => (lst1 :: <collection>, lst2 :: <collection>) let (lst1,lst2) = values( copy-sequence (lst, end: size(lst)/2), copy-sequence (lst, start: size(lst)/2 + 1)) end method split-lst; let (l1,l2) = split-lst(lst); mergesort!(l1); mergesort!(l2); for (i from 0 to size(lst)-1) let (a,b) = values(head(l1),head(l2)); if ( ~b ( a & (a < b)) ) lst[i]:= a; l1:=tail(l1); else lst[i]:=b; l2:=tail(l2); end if; end for; end block; end method mergesort!; Koodi 2: Mergesort lisätyillä yksityiskohdilla. 5