1. Johdanto. 2. Ominaisuudet Tietotyypit ja tyypitys

Samankaltaiset tiedostot
Erlang. Miika Heinonen ja Lassi Uosukainen (Group 92) TIE Principles of Programming Languages Seminaariessee. Yleistä

ELM GROUP 04. Teemu Laakso Henrik Talarmo

Ohjelmoinnin perusteet Y Python

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Ohjelmoinnin peruskurssien laaja oppimäärä

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

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

Harjoitustyö: virtuaalikone

TIE PRINCIPLES OF PROGRAMMING LANGUAGES Eiffel-ohjelmointikieli

Ohjelmoinnin peruskurssien laaja oppimäärä

Clojure, funktionaalinen Lisp murre

Tieto- ja tallennusrakenteet

TIE Principles of Programming Languages CEYLON

Luku 3. Listankäsittelyä. 3.1 Listat

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

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

Algoritmit 1. Luento 3 Ti Timo Männikkö

11/20: Konepelti auki

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Java-kielen perusteet

Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen

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

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

Ohjelmointikieli TIE Principles of Programming Languages Syksy 2017 Ryhmä 19

Ohjelmoinnin perusteet Y Python

12. Näppäimistöltä lukeminen 12.1

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

Prolog kielenä Periaatteet Yhteenveto. Prolog. Toni ja Laura Fadjukoff. 9. joulukuuta 2010

Tietorakenteet ja algoritmit - syksy

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Mathematica Sekalaista asiaa

Jakso 4 Aliohjelmien toteutus

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

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

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

ITKP102 Ohjelmointi 1 (6 op)

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

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

Luento 4 Aliohjelmien toteutus

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

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

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

7. Oliot ja viitteet 7.1

A TIETORAKENTEET JA ALGORITMIT

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

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

Rakenteiset tietotyypit Moniulotteiset taulukot

815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Ohjelmoinnin perusteet Y Python

Tyyppejä ja vähän muutakin. TIEA341 Funktio ohjelmointi 1 Syksy 2005

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

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

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

1 Tavoitteet. 2 Periaatteet ja ominaisuudet. 2.1 Tyyppipäättely

ITKP102 Ohjelmointi 1 (6 op)

15. Ohjelmoinnin tekniikkaa 15.1

Principles of Programming Languages: Erlang

Ohjelmoinnin perusteet Y Python

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

815338A Ohjelmointikielten periaatteet Harjoitus 7 Vastaukset

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

Ohjelmoinnin perusteet Y Python

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

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

Jakso 4 Aliohjelmien toteutus

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

Ohjelmoinnin peruskurssien laaja oppimäärä

Java-kielen perusteet

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

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

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

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

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

Ohjelmoinnin perusteet Y Python

LOAD R1, =2 Sijoitetaan rekisteriin R1 arvo 2. LOAD R1, 100

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Lisää pysähtymisaiheisia ongelmia

815338A Ohjelmointikielten periaatteet

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely

ITKP102 Ohjelmointi 1 (6 op)

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

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Solidity älysopimus ohjelmointi. Sopimus suuntautunut ohjelmointi

815338A Ohjelmointikielten periaatteet

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Osoitin ja viittaus C++:ssa

Ohjelmoinnin peruskurssien laaja oppimäärä

Jatkeet. TIES341 Funktio ohjelmointi 2 Kevät 2006

Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö. Muistin käyttö C-ohjelmassa

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

Kielioppia: toisin kuin Javassa

Harjoitus 3 (viikko 39)

Java kahdessa tunnissa. Jyry Suvilehto

Transkriptio:

Erlang

1. Johdanto Erlang on funktionaalinen ja rinnakkainen ohjelmointikieli. Se kehitettiin alun perin 1980- luvulla Ericssonilla puhelinvaihteiden ohjelmistoja varten ja se on suunniteltu niiden vaatimuksia, kuten hajauttamista, virhesietoisuutta ja saavutettavuutta silmällä pitäen. Vuodesta 1998 lähtien se on ollut avoimen lähdekoodin projekti. Vaikka Erlang onkin yleiskäyttöinen kieli, monista sen ominaisuuksista paistaa läpi, se että se on oikeasti suunniteltu varsin tarkkaan määriteltyä tarkoitusta varten, eikä välttämättä oikeasti sovellu moniin muihin asioihin. Ensimmäiset toteutukset Erlangista tehtiin Prologilla mutta sen osoittauduttua liian hitaaksi vaihdettiin toteutuskieleksi C. 2. Ominaisuudet 2.1. Tietotyypit ja tyypitys Erlang on dynaamisesti ja vahvasti tyypitetty kieli. Dynaamisen tyypityksen vuoksi muuttujien tyyppejä ei tarvitse ilmoittaa erikseen. Esimerkiksi hahmontunnistus hyväksyy useimmissa tapauksissa kaikenlaisia tietotyyppejä ja niiden yhdistelmiä ja tunnistaa ne automaattisesti. Erlang on kuitenkin myös vahvasti tyypitetty, eli se ei suorita implisiittisiä tyyppimuunnoksia, ja jotkut operaatiot, kuten yhteenlasku esimerkiksi numeron ja atomin välillä, johtavat virheeseen. Eksplisiittiset tyyppimuunnokset ovat kuitenkin sallittuja. 2.1.1. Perustietotyypit Erlang tukee sekä kokonaislukuja että liukulukuja, eikä tee eroa niiden välille. Niitä voi laskea yhteen, ja kertoa ja jakaa vapaasti. Kokonaislukuja käsitellään siis käytännössä liukulukuina aritmeettisissa operaatioissa. Kokonaislukujen väliselle jakolaskulle ja modulo-operaattorille on omat avainsanansa, div ja rem. Erlangista löytyy myös boolean-tietotyyppi. Epätavallisempi Erlangista löytyvä tietotyyppi on atomi (atom). Atomit ovat vakioita, joiden nimi on myös niiden arvo. Atomi foo on foo eikä sille voi tehdä mitään operaatioita. Tämä saattaa vaikuttaa hyödyttömältä ja epäintuitiiviselta, mutta atomeita voi käyttää vakioina ja enumeraation kaltaisina arvoina. Niitä kannattaa käyttää myös tilanteissa, joissa dataan tavallisesti liitettäisiin jokin merkkijono kertomaan mitä data tarkoittaa, esimerkiksi {50, kg }. Tietoliikennetaustansa vuoksi Erlangissa on laaja tuki erilaisille bittioperaatioille ja -asetuksille, kuten sille, onko eniten merkitsevä bitti ensimmäinen vai viimeinen. Tyypillisten loogisten ja shift-operaatioiden lisäksi myös hahmontunnistus (pattern matching) toimii binääridatalle; esimerkiksi <<A:16, B:8>> = <<255,0,170,>> tuottaa lopputuloksen A = <<255,0>> ja B = 170. Kukin listattu arvo on yksi tavu ja muuttujien perässä olevat numerot tarkoittavat haluttujen bittien määrää. Myös listaoperaatiot ovat kaikki käytettävissä binääridatalle.

Merkkijonoille Erlangissa ei ole omaa tietotyyppiä vaan niitä käsitellään listoina. Tuki merkkijonoihin liittyville operaatioille ei siten ole myöskään kovin hyvä. 2.1.2. Tietorakenteet Erlang tarjoaa kaksi perustietorakennetta: listan ja tuplen. Kumpikin voi sisältää mitä tahansa tietotyyppejä, mutta tuple on vakiomittainen ja listan pituus voi muuttua. Listat toimivat hyvin samalla tavalla kuin esimerkiksi Haskellissa. Listan ensimmäisen alkion käsittely ja alkion lisääminen listan alkuun ovat kevyitä operaatioita, ja listan lopun käsittely on hitaampaa. Listojen käsittelyyn on tarjolla paljon erilaisia hahmontunnistusmalleja, joilla voi luoda uusia listoja tyhjästä tai toisen listan perusteella. Toisin kuin monissa muissa kielissä, tuplen alkioita ei voi käsitellä first- ja second-operaattoreilla tai vastaavilla mekanismeilla, vaan ne täytyy sijoittaa muuttujiin hahmontunnistuksen avulla. Esimerkiksi käskyn {X, Y} = {1, 2} lopputuloksena X = 1 ja Y = 2, mikäli X ja Y olivat alustamattomia muuttujia. Record-tyyppi sallii structin kaltaisten rakenteiden luonnin, joiden atribuutteja voi käsitellä suoraan määritellyn nimen kautta. Käytännössä record-tyypin perustana on kuitenkin vain joukko sisäkkäisiä tupleja, ja tuplejen avulla saakin aikaan samanlaisen toiminnallisuuden. Record ei ole structiin tai luokkaan verrattava tietotyyppi, joten sen käsittely on monella tapaa kömpelömpää kuin esimerkiksi C-structin. Muista tietorakenteista löytyy useita hieman erilaisia versioita, koska suunnittelustrategiana on ollut, että ei ole vain yhtä universaalisti parasta tapaa toteuttaa tietynlainen tietorakenne. Dictionaryn kaltaisia tietotyppejä on neljä: Pienille tietomäärille on olemassa proplist ja järjestetty orddict, ja suuremmille tietomäärille dict ja gb_tree (general balanced tree). Myös joukoille on erilaisia toteutuksia, joista jokaisella on omat hyvät ja huonot puolensa. Esimerkiksi sets-moduuli tarjoaa tehokkaammat lukuoperaatiot ja gb_sets taas nopeammat kirjoitusoperaatiot. Erlangissa on myös sisäänrakennettuna muite tietorakentaita, kuten suunnattu graafi. O(1)-ajassa toimivia taulukoita Erlangissa ei kuitenkaan ole. 2.1.3. Muistinhallinta Erlangissa muistinhallinta on automatisoitu. Ohjelmoijan ei tarvitse varata tai vapauttaa muistia itse, vaan se on Erlangin virtuaalikoneen vastuulla. Erlang käyttää myös roskienkeruuta. Erlangissa kullakin prosessilla on oma keko ja pino, jotka kasvavat toisiaan kohti. Kun ne kohtaavat, roskienkeruu aktivoituu ja vapauttaa muistia. Jos roskien kerääjä ei pysty vapauttamaan tarpeeksi muistia, kekoa kasvatetaan. Roskienkeruu ei kuitenkaan poista muistista atomeita, ja siksi niitä ei kannata luoda dynaamisesti tai muutenkaan kovin montaa.

2.2. Funktionaalisuus Erlang on funktionaalinen kieli, ja funktioita voi siinä käyttää kuten muitakin arvoja, esimerkiksi parametrina tai paluuarvona. Kieli ei salli arvojen mutatoimista eikä siinä myöskään ole minkäänlaisia silmukkarakenteita, vaan kaikki silmukat on toteutettava rekursiolla. Erlang ei kuitenkaan ole puhdas funktionaalinen kieli kuten esimerkiksi Haskell. Erlang sallii viitteiden läpinäkyvyyden rikkomisen tarvittaessa, eli funktio saa palauttaa samoilla parametreilla erilaisia tuloksia. Esimerkiksi päivämäärän palauttava funktio saa palauttaa joka päivä eri päivämäärän. Erlang ei myöskään tue curry-muunnoksia eli useamman muuttujan funktion muuntamista ketjuksi yhden muuttujan funktioita. Tämän vuoksi osittainen soveltaminen (partial application) ei ole mahdollista Erlangissa, eli funktiolle ei voi antaa vain osaa parametreista tuottaen uuden funktion, vaan funktion kaikki parametrit on aina täytettävä kerralla. 2.3. Rinnakkaisuus Vahva tuki rinnakkaisuudelle on keskeinen Erlangin ominaisuus. Rinnakkaisuuden toteuttamiseen käytetään prosesseja. Erlangin prosessit eivät vastaa käyttöjärjestelmän prosesseja, eivätkä edes säikeitä, vaan ne ovat Erlang-virtuaalikoneen toteuttamia vielä kevyempiä suoritusyksiköitä. Prosesseista on haluttu mahdollisimman kevyitä, jotta niiden käynnistäminen ja poistaminen olisi mahdollisimman nopeaa, koska prosesseja täytyy pystyä ajamaan jopa tuhansia kerrallaan. Erlangin prosessit eivät jaa muistia keskenään vaan ne kommunikoivat viestinvälityksellä. Prosessin käynnistäminen palauttaa prosessitunnisteen, jota käyttämällä prosessille voi lähettää viestejä. Prosessilla voi olla myös nimi, jota voi käyttää viestien lähettämiseen. Prosessin suoritettavaksi annettu funktio määrittelee, kuinka se reagoi viesteihin. Kullakin prosessilla on oma postilaatikko, johon viestit saapuvat, ja josta prosessi lukee niitä sitä mukaa kun ehtii. 2.3.1. OTP Koska rinnakkaisuus on Erlangissa niin tärkeää, on sen ympärille kehittynyt useita kirjastojaratkaisuja, jotka helpottavat prosessien hallintaa. Yksi näistä on OTP (Open Telecom Platform). Koska ohjelmissa käytettävät prosessit ovat yleensä rakenteeltaan hyvin samankaltaisia, on nämä samankaltaiset osuudet prosessien luonti ja tuhoaminen, viestien lähetys ja vastaanottaminen toteutettu OTP:n puolella, jolloin toteuttajan vastuulle jää vain ohjelmalle spesifi toiminta. Yksi OTP:n useimmin käytetyistä abstraktioista on palvelin (gen_server), joka tarjoaa perustan prosessin käynnistykselle sekä synkroniselle ja asynkroniselle viestinnälle. Mielenkiintoisena yksityiskohtana gen_server tarjoaa myös mahdollisuuden päivittää prosessin koodia ajonaikaisesti ilman, että prosessin tilaan liittyvää dataa menetetään.

Muita oleellisia abstraktioita ovat gen_fsm, joka tarjoaa äärellisen tilakoneen ominaisuudet ja gen_event, joka tarjoaa laajemman tuen tapahtumien käsittelylle. 2.4. Virheenkäsittely Erlangin yleinen filosofia virheidenkäsittelyssä on Antaa kaatua, koska tieto kaatuneesta prosessista on mahdollista välittää toiselle prosessille, joka käynnistää kaatuneen prosessin uudelleen. Tätä pidetään yksinkertaisempana kuin kaatumisen estämisen yrittämistä kaikin keinoin. Yksittäisen prosessin sisällä Erlang käyttää virheidenkäsittelyyn poikkeuksia. Poikkeuksia on kolmea tyyppiä, virheet (error), poistumiset (exit) ja heitot (throw). Virheet lopettavat prosessin suorituksen. Niitä käytetään, kun törmätään tilanteeseen, jota kutsuva koodi ei osaa käsitellä ja on järkevämpää antaa prosessin kaatua. Poistumiset ja virheet ovat lähes samanlaisia mutta poistumisia käytetään yleensä, kun halutaan välittää tieto prosessin kaatumisesta toisille prosesseille. Poistuminen ei esimerkiksi palauta pinovedosta (stack trace) toisin kuin virhe, koska pinovedoksen lähettäminen toiselle prosessille on yleensä tarpeetonta. Heittoja käytetään ilmoittamaan virheistä, jotka voidaan käsitellä kaatamatta prosessia. Heittojen avulla voidaan palata nopeasti rekursiosta ylimmälle tasolle, jolloin virheen voi käsitellä erillinen funktio ja rekursiivisen funktion ei tarvitse välittää siitä. Poikkeukset voidaan ottaa kiinni try-catch-rakenteella. Kaikki poikkeustyypit voidaan ottaa kiinni, vaikka niiden varsinainen tarkoitus olisikin erilainen, kuten edellisessä kappaleessa on kuvattu. Try-catch-rakenteessa try- ja of-avainsanojen väliin kirjoitetun lausekkeen paluuarvo käsitellään of- ja catch- avainsanojen välissä määritetyllä tavalla ja poikkeukset käsitellään catch- ja end-avainsanojen välissä määritetyllä tavalla. Try-catch-rakenteessa käytetään hahmontunnistusta päättämään millä tavalla minkäkin tyyppinen paluuarvo tai poikkeus käsitellään. Virhetilanteista kommunikoimiseen prosessien välillä Erlang käyttää linkkejä (link), järjestelmäprosesseja (system process) ja monitoreja (monitor). Linkeillä voidaan yhdistää prosesseja niin, että kun yksi prosessi kaatuu myös siihen linkitetyt prosessit kaatuvat. Tämä voi olla hyödyllistä tilanteessa, jossa yhden prosessin häviäminen tekisi laskennan jatkamisen mahdottomaksi. Järjestelmäprosessit vastaanottavat tiedon siitä, että prosessi on kaatunut, jotta prosessi voidaan käynnistää uudelleen. Monitorit muistuttavat linkkejä mutta monitoreilla joitakin lisäominaisuuksia. Monitorit ovat pinottavia, eli yhtä prosessia varten voi olla monta monitoria mutta ne voi poistaa yksi kerrallaan. Monitorit ovat myös yksisuuntaisia, joten monitoroitava prosessi ei tiedä monitorista mitään.

3. Käyttökokemus Tutustuaksemme kieleen toteutimme rinnakkaisuutta hyväksi käyttävän matriisikertolaskimen. Rinnakkaisuutta käytettiin niin että prosessi, joka suorittaa kertolaskufunktion luo uuden prosessin jokaista tulomatriisin riviä varten eli jokainen rivi lasketaan omassa prosessissaan. Luodut prosessit lähettävät tuloksensa takaisin alkuperäiselle prosessille, joka yhdistää ne tulomatriisiksi. Meillä oli jonkin verran kokemusta funktionaalisesta ohjelmoinnista ja rinnakkaisuudesta jo ennakkoon, joten ohjelmaa ei ollut kohtuuttoman vaikeaa toteuttaa. Funktionaalisena kielenä Erlang ei tunnu yhtä sujuvalta kuin vaikkapa Haskell tai F#, koska siinä ei ole operaatioita funktioiden yhdistämistä varten, joten joissain kohdissa oli pakollista turvautua imperatiiviseen tyyliin, kun kahta peräkkäistä funktioita ei voinut yhdistää yhdeksi. Toisaalta Erlangin prosessimalli ja viestinvälitys tuntui luontevalta ja helpolta, koska keskinäisistä riippuvuuksista ei tarvitse jaetun muistin puuttumisen vuoksi välittää. Näin matriisikertolaskuoperaatio oli helppo jakaa prosessien kesken suoritettavaksi. Vaikeinta oli keksiä, kuinka tulokset kerätään takaisin yhteen, mutta siihenkin löytyi kelvollinen ratkaisu.