Funktionaalinen ohjelmointi
|
|
- Kari Saaristo
- 8 vuotta sitten
- Katselukertoja:
Transkriptio
1 Funktionaalinen ohjelmointi Aiemmin on käsitelty nykyohjelmoinnin suosituimpia ohjelmointiparadigmoja: imperatiivista ohjelmointia ja olio-ohjelmointia. Tässä osassa perehdytään funktionaaliseen ohjelmointiin vaihtoehtona imperatiiviselle ohjelmoinnille; pääasiallisena lähteenä toimii Sebestan ([Seb]) luku 15. Maarit Harsu käsittelee vastaavia asioita teoksensa [Har] luvussa 13. Myöhemmin tarkastellaan logiikkaohjelmointia; näitä molempia kutsutaan joskus yhteisesti deklaratiiviseksi ohjelmoinniksi. Joissakin lähteissä deklaratiivinen ohjelmointi tarkoittaa pelkästään logiikkaohjelmointia (ks. esim [Seb] kappale 16.1). Vielä nykyäänkin yleisimpien, imperatiivisten ohjelmointikielten suunnittelu perustuu vallitsevan tietokonearkkitehtuurin eli von Neumannin arkkitehtuurin varaan. Tällaisten kielten tunnusomaisia piirteitä ovat fyysisiin muistipaikkoihin sidottujen muuttujien käyttö, sijoituslause ja iteratiivisen toiston tehokas soveltaminen. Tällöin ohjelmoinnin olennaisimmaksi piirteeksi muodostuu algoritmien ja tietorakenteiden suunnittelu ratkaisemaan ohjelmointiongelma. Funktionaalisen ohjelmoinnin perusidea on luopua komennoista ja suorittaa kaikki tarvittavat operaatiot lausekkeita käyttämällä, erityisesti funktioita toistuvasti soveltamalla. Funktionaalinen ohjelmointi pohjautuu vahvasti laskennan teoriaan. Samaan aikaan (vuonna 1936) Alan Turingin määritellessä Turingin koneen, jota käytetään tietojenkäsittelyn teoriassa tietokoneen abstraktina mallina, loi Stephen Kleene rekursiivisten funktioiden teorian. Voidaan osoittaa, että Turingin koneen ja Kleenen mallin laskennallinen voima on täsmälleen sama (ks. esimerkiksi [Dav], ss ). Funktionaalinen ohjelmointi perustuu matemaattisten funktioiden ja korkeamman asteen funktioiden (higher order functions) soveltamiseen. Matemaattinen funktio on kuvaus funktion määrittelyjoukolta funktion arvojoukolle. Kuvaus voidaan määritellä luettelemalla funktion arvot tai jonkin lausekkeen avulla, esimerkiksi määrittelemällä funktio f reaalilukujen joukolta reaalilukujen joukolle kaavalla f(x) = 3x-1. Korkeamman asteen funktioita kutsutaan myös funktionaalisiksi muodoiksi (functional forms) ja ne
2 voivat ottaa parametreikseen funktioita sekä myös palauttaa funktioita paluuarvonaan. Matemaattinen funktio eroaa imperatiivisen ohjelmoinnin funktiosta pääasiassa siinä, että matemaattisella funktiolla ei voi olla sivuvaikutuksia; sen ainoa toimenpide on palauttaa parametrejaan vastaava arvo, joka on aina samoilla parametrien arvoilla sama. Funktiot ovat funktionaalisen ohjelmoinnin peruselementtejä samaan tapaan kuin muuttujat imperatiivisessa ohjelmoinnissa. Tyypillinen funktionaalinen muoto on esimerkiksi funktioiden yhdistäminen (kompositio): Funktioiden f ja g yhdistetyllä funktiolla h = f g tarkoitetaan funktiota, joka saadaan, kun argumenttiin sovelletaan ensin funktiota g ja sitten tulokseen funktiota f, ts. h(x) = f(g(x)). Esimerkiksi, jos f(x) = x2 ja g(x) = 2x+1, h(x) = f g(x) = f(g(x)) = f(2x+1) = (2x+1)2 = 4x2 + 4x +1. Konstruktioksi kutsutaan funktionaalista muotoa, joka saadaan soveltamalla annetun funktiolistan jokaista funktiota yhteen argumenttiin: tuloksena on siis arvojen lista, jossa on yhtä monta alkioita kuin funktioita oli listassa. Yleensä konstruktio merkitään kirjoittamalla funktiot hakasulkeisiin, esimerkiksi funktioiden f(x) = 3x-1 ja g(x) = x 4 +2 tapauksessa [f,g](3) tuottaa tulokseksi listan (8,83). Yksittäistä funktiota voidaan myös soveltaa argumenttilistan kaikkiin arvoihin, tätä merkitään yleisesti symbolilla α. Esimerkiksi, jos f(x) = x/3, on operaation α(f,(1,2,3)) tuloksena (1/3,2/3,1). Funktionaalisen ohjelmoinnin perusta, matemaattisten funktioiden mallintaminen, johtaa tyystin erilaiseen ohjelmointityyliin kuin imperatiivisissa kielissä. Näissä kielissä lausekkeet evaluoidaan ja tulos sijoitetaan muistipaikkaan, (puhtaasti) funktionaalisissa kielissä ei käytetä muuttujia tai sijoituslauseita. Tällöin ohjelmoija ei voi käyttää imperatiivisesta ohjelmoinnista tuttuja tekniikoita, kuten iteratiivista toistoa: toisto on tehtävä rekursion avulla, on siis sovellettava funktiota toistuvasti lausekkeeseen. Ohjelmien koodista muodostuu funktioiden määrittelyjä; nämä koostuvat funktiokutsuista ja kutsujärjestystä ohjaavista ehtolauseista. Itse ohjelman toiminta koostuu funktiokutsuista. Funktionaalisen kielen funktio, kuten matemaattinenkin,
3 palauttaa samoilla parametreilla aina saman arvon. Tätä kutsutaan viittauksen läpinäkyvyydeksi (referential transparency). Puhtaan funktionaalisen kielen semantiikka on näistä syistä huomattavasti yksinkertaisempi kuin imperatiivisten kielten tai imperatiivisia piirteitä sisältävien funktionaalisten kielten. Funktionaalisessa kielessä on valmiiksi määriteltynä joukko primitiivisiä funktioita, joukko korkeamman asteen funktioita, joiden avulla ohjelmoija voi muodostaa uusia funktioita entisistä, funktion soveltamisoperaatio sekä rakenteita datan esittämiseksi. Yleensä primitiivisten funktioiden joukko pyritään pitämään pienenä. Vaikka funktionaalisia kieliä voidaankin kääntää, ne ovat usein tulkattavia. 1. LISP- ja Scheme-kielet Aluksi kuvataan funktionaalista ohjelmointia pääasiassa ensimmäiseksi syntyneen ja vieläkin yleisimmän funktionaalisen ohjelmointikielen, LISPin ja sen erään murteen, Schemen, avulla. John McCarthy esitteli LISPin jo vuonna 1958 MIT:n tekoälyprojektin yhteydessä. McCarthy halusi luoda kielen, jolla olisi vahva matemaattinen pohja; hän oli sitä mieltä, että rekursiivisten funktioiden teoria soveltui perustaksi paremmin kuin Turingin koneeseen perustuvat mallit, jotka olivat silloin suositumpia. Erityisesti kielen tulisi tarjota mahdollisuus listojen käsittelyyn ja soveltaa funktion käsitettä mahdollisimman laajasti; lisäksi kieleen olisi sisällytettävä korkeamman kertaluvun funktiot. Ensimmäinen LISP -tulkki syntyi puolittain vahingossa. Kun McCarthy kehitti julkaisussaan LISPin yleisfunktion eval, joka laskee minkä tahansa LISP-funktion arvon, kaksi hänen projektissaan työskennellyttä henkilöä huomasi, että implementoituna tätä funktiota voidaan käyttää LISP-tulkkina. Pian funktio kirjoitettiinkin ja ensimmäinen LISP-tulkki syntyi. Kohta tämän jälkeen kirjoitettiin myös kääntäjä, joka toteutettiin LISP-kielellä. Tämä on tiettävästi ensimmäinen kerta, kun kielen kääntäjä kirjoitetaan samalla kielellä. LISPistä on kehittynyt monia murteita, joista COMMON LISP ja Scheme
4 lienevät yleisimmin käytössä. Tässä esityksessä keskitytään Sebestaa ([Seb], kappaleet 15.4 ja 15.5) mukaillen Schemen ominaisuuksiin. 1.1 LISP LISPin symbolit koostuvat kirjaimista, numeroista ja eräistä sallituista erikoismerkeistä. Symbolien ohella käsitellään myös lukuja, jotka eivät ole symboleja, koska ne aina edustavat ainoastaan numeerista arvoaan. Symboleilla T ja NIL on erikoismerkitys: ensimmäinen on totuusarvo tosi ja toinen epätosi. Loogisissa lausekkeissa NIL on epätosi ja mikä tahansa siitä poikkeava arvo katsotaan todeksi. Symboleita ja lukuja kutsutaan atomeiksi (atoms); LISPin perustietotyypit ovat atomit ja listat (lists). LISPin lista on järjestetty joukko, jonka alkiot ovat atomeja tai toisia listoja. Listan rajoittimina toimivat kaarisulut ja alkioiden erottimina sanavälit. Lista voi olla myös tyhjä, jolloin se merkitään ( ) tai NIL. Atomeja ja listoja kutsutaan yhteisnimellä symboliset lausekkeet tai s-lausekkeet (s-expression). Listan ensimmäinen alkio on sen pää (head) ja kaikki loput sen häntä (tail). Myös funktiot kirjoitetaan LISPissä listamuodossa (funktio parametri1 parametri2...) Funktion nimi kirjoitetaan aina ensin, esimerkiksi operaatio 2+3 kirjoitetaan LISPissä (+ 2 3). Kaikki lausekkeet on kirjoitettava sulkujen sisään; sulkulausekkeet voivat limittyä määräämättömän pitkälle. (Jotkut ovatkin pilkallisesti väittäneet, että LISP on lyhenne sanoista "Lots of Idiotic Silly Parenthesis"). LISP sisältää joitakin ennalta määriteltyjä funktioita aritmetiikkaa ja listojen käsittelyä varten. Kun lauseke annetaan LISP -tulkille, se yrittää selvittää lausekkeen arvon laskemalla uloimman funktion kutsun argumenttien arvot vasemmalta oikealle. Joskus on tarpeen kuitenkin käsitellä lauseketta sellaisenaan, jolloin sen arvoa ei haluta laskettavan. Esimerkiksi voidaan haluta tarkastella lauseketta (- 5 4) listana eikä laskutoimituksena 5-4. Tällöin laskenta voidaan estää merkitsemällä se lainaukseksi kirjoittamalla lainausmerkki ' (tai sana QUOTE) lausekkeen eteen.
5 1.2 Scheme Scheme on 1970-luvun puolivälissä MIT:ssä syntynyt LISPin murre. Kieli on pieni, yksinkertainen, käyttää staattista näkyvyysalueen määräytymistä ja käsittelee funktioita ensimmäisen kertaluokan olioina (ts. funktioihin voidaan soveltaa samoja operaatioita kuin kielen muihinkin entiteetteihin). Schemen syntaksi ja semantiikka on yksinkertainen, minkä vuoksi sitä on käytetty funktionaalisen ohjelmoinnin opetuksessa. Tässä esitettävät ohjelmaesimerkit ovat pienin muutoksin myös kelvollista LISP-koodia. Schemeen on toteutettu primitiivifunktiot aritmeettisia perusoperaatioita varten. Schemessä kirjoitetaan aritmeettiset operaatiot aina prefix-notaatiolla, ts. operaattori ensin ja sitten operandit, esimerkiksi laskutoimitus 1/6 + 2/3 kirjoitetaan (+ (/ 1 6) (/2 3)) ja tuloksena saadaan 5/6 (huomaa, että tulos saadaan murtolukuna). Kielessä on myös laaja joukko funktioita numeerista laskentaa varten, esimerkiksi modulo, sin ja sqrt jakojäännöksen, sinin ja neliöjuuren laskemiseksi. Jotta ohjelmoija voisi kirjoittaa toimivia ohjelmia, kielen on annettava mahdollisuus määritellä omia funktioita. Schemessä (kuten myös LISPissä) käytetään ns. lambdalausekkeita funktioiden määrittelyyn. Idea perustuu Alonso Churchin kehittämään lambda-kalkyyliin (lambda calculus), joka tarjoaa yksinkertaisen formalismin funktioiden määrittelyyn ja niillä laskemiseen. Churchin esitysmuoto argumenttinsa neliöivälle funktiolle on λx.x 2
6 Schemessä vastaava kirjoitetaan (lambda (x) (* x x)) Tässä symboli lambda ilmaisee kyseessä olevan funktion määritelmän. Luonnollisesti muodollisia parametreja voi olla useita; parametrien listaa kutsutaan lambda-listaksi. Yleinen laskenta esitetään lambda-lauseen rungossa (yllä olevassa esimerkissä (* x x) ). Runko voi olla mikä tahansa Scheme-tulkin laskettavissa oleva muoto. Lambda-lause on abstrakti mekanismi funktion määrittelyä ja laskentaa varten; sen avulla saadaan täsmällinen kuvaus funktiosta, sen parametreista ja laskennasta. Tällainen lause on nimetön funktio, joka katoaa bittitaivaaseen heti kun muoto on laskettu. Näin ollen kielessä pitää vielä olla jokin mekanismi, jolla funktioon voidaan sitoa tunniste, jotta funktiota voidaan kutsua ohjelmassa. Uusien funktioiden määrittely tapahtuu funktiolla define (LISPissä vastaava funktio on defun), esimerkiksi ylläolevan esimerkin funktio voidaan määritellä (define (nelio x) (* x x) ) jolloin sitä voidaan ohjelmassa kutsua nimellä: (nelio 9) ja lauseke palauttaa arvon 81. Funktion laskenta noudattaa seuraavaa järjestystä: 1. Evaluoidaan todellisten parametrien arvot 2. Sidotaan muodolliset parametrit näihin arvoihin 3. Lasketaan lambda-lauseen runko, jonka tuloksena saatu arvo palautetaan lambda-kutsun arvona. Funktiota ei siis evaluoida ennen kuin sen parametrit on täysin evaluoitu. Tällaisen kielen sanotaan noudattavan tiukkaa semantiikkaa (strict semantics). Mikäli tällaista vaatimusta ei kielessä ole, sanotaan että kielessä on käytössä joustava semantiikka
7 (non-strict semantics). Funktiota define voidaan käyttää myös nimen sitomiseksi johonkin lausekkeeseen, esimerkiksi (define pii 3.14) Seuraavaksi käsitellään Schemen kontrollirakenteita eli laskennan ohjausta. Imperatiivisissa ohjelmointikielissä tarvitaan erilaisia kontrollirakenteita (haarautumisia ja toistoja) laskennan ohjausta varten. Myös funktionaalisissa kielissä on laskentaa ohjattava jonkinlaisilla rakenteilla. Schemen kontrollirakenteet muistuttavat ulkoisesti funktiokutsuja. Ohjausrakenteet esitetään sulkulausekkeina, joissa ensimmäinen termi on ohjausrakenteen nimi ja seuraavat termit ikään kuin funktion argumentteja, joihin rakennetta sovelletaan. Rakenteen laskennan tuloksena on jokin arvo kuten funktioillakin. Tässä tarkastellaan joitakin tapoja haaroittaa laskentaa. Toisto toteutetaan funktionaalisessa ohjelmoinnissa yleensä rekursion avulla, vaikka joihinkin funktionaalisiin kieliin onkin toteutettu iteratiivisia kontrollirakenteita. Predikaatiksi sanotaan funktiota, joka palauttaa totuusarvon (#t tai #f). Ehtolauseita kontrolloidaan yleensä predikaattien avulla. Kahden vaihtoehdon tapauksessa on yleensä kätevintä käyttää if -lausetta, jonka muoto on (if ehto tosi_lauseke epätosi_lauseke) Muodon arvoksi tulee lausekkeen tosi_lauseke arvo, mikäli ehto on tosi ja muussa tapauksessa lausekkeen epätosi_lauseke arvo. Esimerkiksi (if (= 1 1) 4 5) saa arvon 4 ja (if (= 1 2) 4 5)
8 Lauseen avulla voitaisiin määritellä esimerkiksi kertomafunktio seuraavasti: (define (kertoma n) (if (<= n 1) 1 (* n (kertoma (- n 1))))) Huomaa, että määrittely on rekursiivinen: kun funktion parametri n on suurempi kuin 1, kutsutaan funktiota parametrilla (n-1). Kun n on korkeintaan 1, palautetaan arvo 1. Monivalinta voidaan Schemessä saada aikaan cond-lauseeella, joka haarauttaa laskentaa predikaattien määrittelemien ehtojen nojalla. Lauseen muoto on seuraava: (cond (p1 a1) (p2 a2) (pn an) (else a)) missä predikaatit pi ja arvolausekkeet ai voivat olla mielivaltaisia lausekkeita. Lauseen arvo määräytyy seuraavasti: Predikaattiosia lasketaan järjestyksessä, kunnes kohdataan ensimmäinen, jonka looginen arvo on tosi, ts. #t. Tätä predikaattia vastaavan arvolausekkeen arvo palautetaan lauseen arvona. Ellei mikään predikaateista ole tosi, lauseen arvo on else-osan arvo. Ellei else-osaa ole ja kaikki ehdot ovat epätosia, lauseen arvo on määräämätön. Esimerkiksi Fibonaccin luvut laskeva funktio (fibo(0)=0, fibo(1)=1, ja fibo(n) = fibo(n-1)+fibo(n-2)) voidaan määritellä cond-lauseen avulla seuraavasti: (define (fibo n) (cond ((= n 0) 0) ((= n 1) 1) (else (+ (fibo (- n 1)) (fibo (- n 2)))))) Edellä olevasta funktiosta näkyy myös, miten LISP-tyyppisissä kielissä sulkuja kertyy usein lauseiden loppuun. Symboleilla ja listoilla operoiminen ovat tyypillisiä LISP-pohjaisten kielten sovelluskohteita. Esitellään vielä Schemen listankäsittelyominaisuuksia. Schemen
9 perustietotyypit ovat, kuten LISPinkin, atomit ja listat; listojen perusominaisuudet ovat myös samat kuin LISPissä. Listojen konstruoimista, purkamista ja tutkimista varten Schemeen on toteutettu seuraavat primitiivifunktiot: car, cdr, cons, ja list. Näistä car ja cdr ovat listan purkufunktioita; car palauttaa argumenttina saadun listan pään ja cdr listan hännän. Funktion car paluuarvo on toisin sanoen s-lauseke ja funktion cdr lista. Näin ollen (car '(a b c d) ) palauttaa s-lausekkeen a ja (cdr '(a b c d) ) palauttaa listan (b c d) Yhden alkion listaan sovellettuna cdr palauttaa tyhjän listan. Huomaa, että listat on annettava lainauksina (lainausmerkki listan edessä), jotta tulkki ei yritä evaluoida listojen alkioita lausekkeina. Samannimisiä funktioita käytetään myös LISP-kielessä; funktioiden omalaatuiset nimet ovat peräisin historian kätköistä: Nimet ovat lyhennyksiä IBM -tietokoneen tiettyjen rekisterien nimistä (CAR = Contents of Address Register ja CDR = Contents of Decrement Register). John McCarthy käytti näitä rekistereitä listan pään ja hännän tallettamiseen. Funktio cons muodostaa uuden listan argumenttina saatuina päästä ja hännästä. Funktion ensimmäinen argumentti on siten s-lauseke ja toinen lista, jonka alkuun funktio lisää ensimmäisen lausekkeen. Paluuarvo on aina lista. Esimerkiksi (cons 'C '(A B))
10 palauttaa listan (C A B). Sen sijaan funktio list muodostaa listan parametreistansa, esimerkiksi (list 'C '(A B) 'D) palauttaa listan (C (A B) D). Kuten aiemmin todettiin, predikaatiksi sanotaan funktiota, joka palauttaa totuusarvon (#t tai #f). Funktiot eq?, null? ja list? ovat Schemen listojen käsittelyn alkeispredikaatit. Funktio list? palauttaa tiedon, onko sen argumentti lista vai ei, esimerkiksi (list? 'a) palauttaa arvon #f ja (list? '(a b)) arvon #t. Predikaatti eq? vertaa argumenttina saamaansa kahta symbolia ja palauttaa arvon #t mikäli ne ovat identtisiä. Muussa tapauksessa palautetaan #f. Funktio eq? rajoittaa argumenttinsa symboleiksi - funktio ei testaa olioiden yhtäläisyyttä loogisesti vaan ovatko oliot esitetty fyysisesti samoilla rakenteilla. Yleensä funktiota voidaan soveltaa myös lukuihin ja listoihin, mutta tulokset saattavat olla yllättäviä, koska esimerkiksi listat saattavat olla ulkoisesti samanlaisia mutta kuitenkin koostua fyysisesti eri listasoluista, esimerkiksi (eq? '(a b) '(a b)) palauttaa arvon #f. Sen sijaan (eq? 'a 'a) palauttaa arvon #t. Predikaatti null? kertoo, onko parametrilista tyhjä vai ei. Schemeen on toteutettu alkeisfunktioita käyttämällä useita varusfunktioita listojen käsittelyyn. Seuraavaksi esitetään kaksi esimerkkiä listoja käsittelevästä Scheme-ohjelmoinnista.
11 Esimerkki 1. Kirjoita funktio, joka päättelee, onko parametrina saatu alkio toisena parametrina saadun listan alkio. Paluuarvo on #t tai #f sen mukaan esiintyykö alkio listassa vai ei. Listan syvärakennetta ei tarvitse tarkastaa, ts. ei tutkita, esiintyykö alkio jossakin listan alilistassa. Ratkaisu. Ongelma voidaan ratkaista yksinkertaisella rekursiolla. Mikäli parametrina saatu lista on tyhjä, voidaan palauttaa arvo #f. Ellei lista ole tyhjä, voidaan tarkastelu jakaa kahteen osaan: tutkitaan, onko parametrina saatu alkio listan ensimmäinen jäsen (eli listan pää), jolloin paluuarvo on #t. Ellei näin ole, tutkitaan sisältyykö alkio listan häntään. Näin saadaan kirjoitettua rekursiivinen ratkaisufunktio: (define (onko_jasen x lista) (cond ((null? lista) #f) ((eq? (car lista) x) #t) (else (onko_jasen x (cdr lista))) )) Esimerkki 2. Kirjoita funktio litista, joka litistää parametrina saadun listan, ts. poistaa kaikki muut paitsi uloimmat sulut. Apuna voi käyttää Schemen varusfunktiota append, joka yhdistää parametreinaan saadut kaksi listaa. Ratkaisu. Ratkaisuideana on litistää listan pää ja häntä sekä yhdistää näin saadut listat. Täten ratkaisufunktio toteutetaan luonnollisimmin rinnakkaisella rekursiolla, jossa funktiota itseään kutsutaan kaksi kertaa. Erikoistapauksina pitää käsitellä tyhjä lista (palautetaan tyhjä lista) ja atomi (palautetaan atomista muodostettu lista): Ratkaisufunktio on seuraava: (define (litista lista) (cond ((null? lista) '() ) ((not (list? lista)) (cons lista '())) (else (append (litista (car lista)) (litista (cdr lista)))))) Ensimmäinen ehtolause siis vertaa listaa tyhjään listaan ja palauttaa tällöin tyhjän listan. Toinen lause tutkii, onko parametri atomi (ts. ei ole lista) ja muodostaa tässä tapauksessa atomin sisältävän listan. Mikäli kumpikaan näistä ehdoista ei ole voimassa, litistetään listan pää ja häntä ja yhdistetään tulokset.
12 2. Haskell Seuraavaksi käsiteltävä Haskell on puhtaasti funktionaalisista kielistä todennäköisesti nykyään yleisin. Nimensä kieli on saanut Haskell Brooks Curryn mukaan; Curryn tulokset matemaattisen logiikan alalla toimivat teoreettisena pohjana funktionaaliselle ohjelmoinnille. Haskellin syntaksi muistuttaa varhaisemman funktionaalisen ML-kielen syntaksia, mutta monilta osin se poikkeaa ML-kielestä merkittävästi. Yhteisiä piirteitä ovat vahva tyypitys, joka mahdollistaa staattisen tyypin tarkistuksen sekä moduulirakenne. Haskellin toteutuksia on vapaasti saatavissa, ks. esimerkiksi (Haskellin kotisivu). Haskell on siis puhdas funktionaalinen kieli eikä sisällä lainkaan imperatiivisia piirteitä. Erityisesti kielessä ei ole muuttujia eikä sijoituslauseita. Haskell noudattaa joustavaa semantiikkaa, mikä mahdollistaa ns. laiskan evaluoinnin, jota. käytetään joissakin funktionaalisissa kielissä lausekkeiden arvojen määräämisessä erotuksena kaikissa imperatiivisissa ja monissa funktionaalisissakin kielissä käytettävästä innokkaasta evaluoinnista (eager evaluation). Innokkaassa evaluoinnissa funktion ja lausekkeen arvo lasketaan välittömästi sen parametrien kulloisillakin arvoilla. Laiskassa evaluoinnissa sen sijaan lausekkeen arvo evaluoidaan vasta kun sitä tarvitaan ja evaluointi tapahtuu ainoastaan kerran. Tämä mahdollistaa näennäisesti äärettömien rakenteiden kirjoittamisen. Haskellissa funktio voidaan määritellä pelkästään sen nimellä (ilman erillistä avainsanaa) käyttäen hahmontunnistusta seuraavasti. Määrittelyssä voidaan käyttää rekursiota. Alla määritellään kertoman laskeva funktio fact 0 = 1 fact n = n * fact(n-1) Funktiota voidaan kutsua ohjelmassa tulostamaan luvun 9 kertoma esimerkiksi seuraavasti
13 main = do print(fact 9) Funktion määrittelyssä voidaan käyttää myös ehtolauseita: kertoma(n) = if n == 0 then 1 else n*kertoma(n-1) määrittelee myös kertomafunktion. Funktio voidaan myös määritellä käyttäen eräänlaista monivalintarakennetta. Seuraava funktio laskee rekursiivisesti Fibonaccin lukuja, joista esitettiin esimerkki myös Schemen yhteydessä fibo n n == 0 = 0 n == 1 = 1 n > 1 = fibo(n-1)+fibo(n-2) Perehdytään vielä Haskellin listojenkäsittelyn ominaisuuksiin. Listat esitetään hakasulkujen sisällä alkiot pilkulla toisistaan erotettuna, esimerkiksi suunnat = [ pohjoinen, ete1ä, itä, länsi ] listojen yhdistämisoperaattori on ++ ja kahta pistettä voidaan käyttää esittämään aritmeettista jonoa listassa, esimerkiksi operaation [1, 4, 5] ++ [2, 6, 8] tuloksena on lista [1,4,5,2,6,8] ja operaation [1, 4..16] tuloksena on lista [1,4,7,10,13,16]. Kaksoispistettä (:) voidaan käyttää merkitsemään osaa listasta operaation, joten listan pituuden palauttava funktio voitaisiin kirjoittaa rekursiivisesti hahmontunnistusta käyttäen Haskellissa seuraavalla tavalla len [] = 0 len(x:xs) = 1 + len(xs)
14 Jos siis parametri lista on tyhjä, palautetaan arvo nolla. Muuten jaetaan lista päähän ja häntään ja palautetaan 1+hännän pituus. Haskellissa voidaan käyttää ns. listakehitelmiä (list comprehension) listojen määrittelyyn. Listakehitelmän muoto on seuraava [runko määreet]. Esimerkiksi [n*n n <- [1..20]] tuottaisi listan jossa on lukujen 1,2,, 20 neliöt. Lista olisi siis [1,4,9,16,,400]. Laiskan laskennan avulla voidaan muodostaa myös periaatteessa äärettömiä tietorakenteita. Esimerkiksi lista, joka sisältää kaikkien parillisten kokonaislukujen neliöt voitaisiin määritellä seuraavasti: parilliset = [2, 4..] neliot = [n*n n <- parilliset] Luonnollisestikaan tietokoneessa ei voi generoida todellisuudessa ääretöntä listaa. Haskellissa lukujen neliöitä generoidaan aina listaa käytettäessä siihen saakka kuin lukuja tarvitaan. Näin esimerkiksi ohjelma main = do print(144 `elem` neliot) voidaan suorittaa ja se tulostaa arvon True, koska luku 144 on listassa (funktio `elem` tutkii onko alkio listassa). Sen sijaan main = do print(121 `elem` neliot) jäisi generoimaan listaa ikuisesti, koska 121 ei ole parillisen luvun neliö. Näin ollen tällaista listaa käsitellessä tulisi kirjoittaa itse funktio tarkistamaan onko alkio listassa. Sellainenhan on helppo tehdä, koska luvut ovat listassa suuruusjärjestyksessä. Laiskaa evaluointia voidaan hyödyntää monin tavoin, mutta voimakkaana ja joustavana
15 työkaluna se myös vaatii resursseja ja saattaa johtaa koodin hitaampaan suorittamiseen. 3. Muita funktionaalisia kieliä Aiemmin käsiteltiin LISPiä ja Schemeä; nykyisistä LISPin murteista yleisin on ehkä kuitenkin COMMON LISP, joka syntyi luvun alkupuolella yhdistämään siihen asti kehittyneiden LISP-versioiden piirteitä. Täten COMMON LISP, päinvastoin kuin Scheme, sisältää varsin laajan kirjon piirteitä, myös imperatiivisia ominaisuuksia. COMMON LISP sallii sekä staattisen että dynaamisen määräytymisen, kun Scheme käyttää pelkästään staattista näkyvyysalueen määräytymistä. ML (MetaLanguage) on myös tunnettuja funktionaalisia kieliä, joka sisältää imperatiivisia piirteitä. Syntaksiltaan ML muistuttaa enemmän Pascalia kuin LISPin murteita. Lisäksi ML:ssä voidaan esitellä muuttujan tyyppejä, muuttujia ei kuitenkaan tarvitse esitellä vaan tyypit määräytyvät myös implisiittisesti. Kieli on vahvasti tyypitetty - jokaisen muuttujan ja lausekkeen tyyppi voidaan määrittää jo käännösaikana. Jotkut funktionaalisen ohjelmoinnin kannattajat vastustavat tätä menettelyä, mutta sillä saavutetaan myös monia etuja, esimerkiksi luotettavuus ja tehokkuus lisääntyvät. ML sisältää myös sijoituslauseen, joskin sen toiminta poikkeaa imperatiivisten kielten sijoituslauseesta. Kieli ei salli automaattisia tyyppimuunnoksia, operandien tyyppien on sovittava operaatioihin. ML:n moduuliominaisuutta voidaan käyttää abstraktien tietotyyppien toteuttamiseen; kieleen on myös toteutettu valmiita tietorakenteita. Microsoftin.NET-perheeseen kuuluu myös funktionaalinen kieli, F#. Kielen pohjautuu perustaltaan O Caml-kieleen, joka puolestaan on ML- ja Haskell-kielien jälkeläinen. F# ei ole puhtaasti funktionaalinen kieli, vaan se sisältää imperatiivisia piirteitä ja tukee olio-ohjelmointia. F#-kielessä voidaan määritellä jonoja (sequences) ja listoja (lists), jotka eroavat toisistaan siten, että jonot muodostetaan laiskasti ja listat innokkaasti. Jonot voivat siis olla äärettömiä, kun taas listat muodostetaan aina muistiin kokonaisuudessaan. Kielen funktiot muistuttavat Haskellin funktioita.
16 4. Imperatiivisten ja funktionaalisten kielten vertailua Funktionaalisten kielten syntaksi on yleensä hyvin yksinkertainen imperatiivisiin kieliin verrattuna, esimerkiksi LISP-kielen listarakennetta käytetään sekä ohjelman että tietorakenteiden esittämiseen. Funktionaalisten kielten semantiikkakin on yksinkertaisempaa, esimerkiksi funktioilla ei ole sivuvaikutuksia, rekursiivisten toistorakenteiden semantiikka on helpommin kuvattavissa jne. On epäselvää, onko funktionaalisilla kielillä ohjelmoiminen tuottavampaa vai tuottamattomampaa kuin imperatiivisilla kielillä. Erityisesti funktionaalisten kielten kannattajat väittävät, että niillä laaditut ohjelmat ovat huomattavasti pienempiä kuin imperatiivisten kielten ohjelmat. Tästä seuraisi tuottavuuden kasvu. Tosiasiassa sovelluskohde lienee olennainen seikka, joka vaikuttaa sovelluksen kokoon. Mikäli sovellus sopii funktionaaliseen paradigmaan, väite saattaa päteä. Joissakin tapauksissa funktionaalisesti laadittu ohjelma voi olla imperatiivista ohjelmaa laajempi (ks. [Seb], kappale 15.11). Funktionaalisten ohjelmien väitetään olevan suoritusajaltaan heikompia kuin imperatiivisten ohjelmien. Mikäli funktionaalista ohjelmaa tulkataan, se on luonnollisesti verrattain hidas. Lähes kaikille funktionaalisille kielille on kuitenkin kehitetty kääntäjät. Tämä tietenkin tasoittaa asetelmia. Funktionaaliset ohjelmat sisältävät usein ominaisuuksia, jotka ovat omiaan hidastamaan ohjelman suoritusta. Esimerkiksi laiska evaluointi on tällainen ominaisuus. Lisäksi imperatiiviset on nimenomaan suunniteltu ohjelmointiin nykytietokoneiden von Neumann-ympäristössä. On arvioitu, että funktionaalisena ohjelma kuluttaisi keskimäärin kaksinkertaisen ajan imperatiiviseen versioon verrattuna. Useimmissa ohjelmissa tämä ei ole kovin merkittävä ero. Luettavuus on ainakin funktionaalisiin kieliin tottuneelle yleisesti funktionaalisten kielten puolella. Monesti funktionaalinen ohjelmakoodi on varsin helposti tulkittavissa jopa käytettyä ohjelmointikieltä tuntemattomalle. Imperatiivinen koodi on muuttujien
17 esittelyjen ja monimutkaisten kontrollirakenteiden vuoksi vaikeaselkoisempaa. Samion rinnakkaisuus on funktionaalisessa ohjelmoinnissa helpompaa funktioiden sivuvaikutusten puuttumisen takia. Näin arvioituna on vaikea päättää, miksi funktionaalisten kielten suosio on niin paljon vaatimattomampi kuin imperatiivisten kielten. Ehkä merkittävin seikka on, että suurin osa ohjelmoijista oppii ohjelmoinnin alkeet imperatiivisella kielellä. Tällöin funktionaalinen ohjelmointityyli saattaa vaikuttaa vieraalta ja vaikeaselkoiselta. Kuitenkin moniin perustaltaan imperatiivisiin kieliin on viime aikoina toteutettu funktionaalisen ohjelmoinnin ominaisuuksia. Esimerkiksi anonyymit lambda-funktiot kuuluvat nykyisin C++-, C#- ja Java-kieliin, joissa niistä käytetään yleensä nimeä lambdalausekkeet (lambda expressions). Kaupallisen ohjelmistotuotannon ulkopuolella funktionaalista ohjelmointia on sovellettu laajasti tekoälysovellusten ohjelmointiin. Tämä on edelleenkin yksi funktionaalisten kielten pääsovellusalueita; erityisesti kielet sopivat symboliseen laskentaan ja listojen käsittelyyn. Funktionaalisilla kielillä on toteutettu muun muassa matematiikkaohjelmia, luonnollista kieltä käsitteleviä ohjelmia sekä puheen ja kuvan mallinnusohjelmia. Muillakin alueilla on sovellettu funktionaalisia kieliä, esimerkiksi tekstieditori EMACS on kirjoitettu LISPillä. Myös oliotietokantojen käsittelyohjelmia sekä CAD -ohjelmia on toteutettu funktionaalisilla kielillä. Haskellilla on kirjoitettu pelejäkin. Akateemisessa maailmassa funktionaalisia kieliä on sovellettu laajasti erilaisissa tutkimusprojekteissa. Lisäksi ainakin Schemeä on käytetty funktionaalisen ohjelmoinnin opetuskielenä ja joissakin issa ohjelmoinnin ensimmäisenä opetuskielenäkin.
18 Lähteet [Dav] Davis, M. Tietokoneen esihistoria Leibnizista Turingiin, Art House, 2003 [Har] Harsu, Maarit. Ohjelmointikielet, Periaatteet, käsitteet, valintaperusteet, Talentum [Seb] Sebesta, Robert W. Concepts of Programming Languages 10th edition, Pearson 2013.
815338A Ohjelmointikielten periaatteet
815338A Ohjelmointikielten periaatteet 2015-2016 VI Funktionaalinen ohjelmointi Sisältö 1. Johdanto ja peruskäsitteitä 2. LISP- ja Scheme-kielet 3. Haskell 4. IO funktionaalisissa kielissä 5. Muita funktionaalisia
LisätiedotFunktionaalinen ohjelmointi
Funktionaalinen ohjelmointi Aiemmin on käsitelty nykyohjelmoinnin suosituimpia ohjelmointiparadigmoja: imperatiivista ohjelmointia ja olio-ohjelmointia. Tässä osassa perehdytään funktionaaliseen ohjelmointiin
Lisätiedot815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset
815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 6 Vastaukset Harjoituksen aiheena on funktionaalinen ohjelmointi Scheme- ja Haskell-kielillä. Voit suorittaa ohjelmat osoitteessa https://ideone.com/
Lisätiedot815338A Ohjelmointikielten periaatteet 2014-2015. Harjoitus 7 Vastaukset
815338A Ohjelmointikielten periaatteet 2014-2015. Harjoitus 7 Vastaukset Harjoituksen aiheena on funktionaalinen ohjelmointi Scheme- ja Haskell-kielillä. Voit suorittaa ohjelmat osoitteessa https://ideone.com/
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Keskeneräinen luento 3: Listat (mm. SICP 22.2.3) Riku Saikkonen 31. 10. 2011 Sisältö 1 Linkitetyt listat 2 Linkitetyt listat (SICP 2.1.1, 2.2.1) funktionaalinen
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 2: SICP kohdat 22.2.3 Riku Saikkonen 2. 11. 2010 Sisältö 1 Linkitetyt listat 2 Listaoperaatioita 3 Listarakenteet 4 Gambit-C:n Scheme-debuggeri Linkitetyt
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 8: Pienen ohjelmointikielen tulkki (ohjelmoitava laskin) (mm. SICP 4-4.1.5 osin) Riku Saikkonen 15. 11. 2012 Sisältö 1 Nelilaskintulkki, globaalit muuttujat
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 6: Rajoite-esimerkki, funktionaalista ohjelmointia (mm. SICP 3.3.5, 3.5) Riku Saikkonen 8. 11. 2012 Sisältö 1 SICP 3.3.5 esimerkki: rajoitteiden vyörytysjärjestelmä
LisätiedotAlkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)
Alkuarvot ja tyyppimuunnokset (1/5) Aiemmin olemme jo antaneet muuttujille alkuarvoja, esimerkiksi: int luku = 123; Alkuarvon on oltava muuttujan tietotyypin mukainen, esimerkiksi int-muuttujilla kokonaisluku,
LisätiedotTietorakenteet ja algoritmit - syksy 2015 1
Tietorakenteet ja algoritmit - syksy 2015 1 Tietorakenteet ja algoritmit - syksy 2015 2 Tietorakenteet ja algoritmit Johdanto Ari Korhonen Tietorakenteet ja algoritmit - syksy 2015 1. JOHDANTO 1.1 Määritelmiä
LisätiedotELM GROUP 04. Teemu Laakso Henrik Talarmo
ELM GROUP 04 Teemu Laakso Henrik Talarmo 23. marraskuuta 2017 Sisältö 1 Johdanto 1 2 Ominaisuuksia 2 2.1 Muuttujat ja tietorakenteet...................... 2 2.2 Funktiot................................
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 4: Symbolit, derivojaesimerkki, kierroksen 1 ratkaisut (mm. SICP 2.32.3.2) Riku Saikkonen 1. 11. 2011 Sisältö 1 Symbolit ja sulkulausekkeet 2 Lisää Schemestä:
LisätiedotTietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari Korhonen
Tietorakenteet ja algoritmit Johdanto Lauri Malmi / Ari 1 1. JOHDANTO 1.1 Määritelmiä 1.2 Tietorakenteen ja algoritmin valinta 1.3 Algoritmit ja tiedon määrä 1.4 Tietorakenteet ja toiminnot 1.5 Esimerkki:
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 7: Funktionaalista ohjelmointia (mm. SICP 3.5) Riku Saikkonen 13. 11. 2012 Sisältö 1 Laiskaa laskentaa: delay ja force 2 Funktionaalinen I/O 3 Funktionaalista
LisätiedotPERL. TIE Principles of Programming Languages. Ryhmä 4: Joonas Lång & Jasmin Laitamäki
PERL TIE-20306 Principles of Programming Languages Ryhmä 4: Joonas Lång & Jasmin Laitamäki 1. Johdanto Perl on ohjelmointikielten perhe, johon kuuluu Perl 5 ja Perl 6. Kielet ovat kuitenkin erilliset ohjelmointikielet
LisätiedotAlgebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005
Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005 Tällä luennolla Algebralliset tietotyypit Hahmonsovitus (pattern matching) Primitiivirekursio Esimerkkinä binäärinen hakupuu Muistattehan...
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 5: Sijoituslause, SICP-oliot, tietorakenteen muuttaminen (mm. SICP 33.1.3, 3.33.3.2) Riku Saikkonen 6. 11. 2012 Sisältö 1 Muuttujan arvon muuttaminen:
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 11: Tulkin muokkaaminen, sisäiset määrittelyt, makrot (mm. SICP 3.2.4, 4-4.1.6) Riku Saikkonen 29. 11. 2012 Sisältö 1 Kirjan tulkin muokkaaminen 2 Yksityiskohta:
LisätiedotEhto- ja toistolauseet
Ehto- ja toistolauseet 1 Ehto- ja toistolauseet Uutena asiana opetellaan ohjelmointilauseet / rakenteet, jotka mahdollistavat: Päätösten tekemisen ohjelman suorituksen aikana (esim. kyllä/ei) Samoja lauseiden
Lisätiedot815338A Ohjelmointikielten periaatteet 2014-2015
815338A Ohjelmointikielten periaatteet 2014-2015 X Skriptiohjelmointi Sisältö 1. Johdanto 2. Skriptikielten yleispiirteitä 3. Python 815338A Ohjelmointikielten periaatteet, Skriptiohjelmointi 2 X.1 Johdanto
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 4: SICP kohta 3.3.5 ja funktionaalista ohjelmointia Riku Saikkonen 15. 11. 2010 Sisältö 1 Ensimmäisen kierroksen tehtävistä 2 SICP 3.3.5: rajoitteiden
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 3: Funktionaalinen listankäsittely ja listankäsittelyoperaatiot (mm. SICP 22.2.3) Riku Saikkonen 31. 10. 2011 Sisältö 1 Linkitetyt listat 2 Listarakenteet
Lisätiedot811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2016-2017 4. Joukot, relaatiot ja funktiot Osa 3: Funktiot 4.3 Funktiot Olkoot A ja B joukkoja. Funktio joukosta A joukkoon B on sääntö, joka liittää yksikäsitteisesti määrätyn
LisätiedotAlgoritmit 1. Luento 3 Ti Timo Männikkö
Algoritmit 1 Luento 3 Ti 17.1.2017 Timo Männikkö Luento 3 Algoritmin analysointi Rekursio Lomituslajittelu Aikavaativuus Tietorakenteet Pino Algoritmit 1 Kevät 2017 Luento 3 Ti 17.1.2017 2/27 Algoritmien
Lisätiedottään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla
2.5. YDIN-HASKELL 19 tään painetussa ja käsin kirjoitetussa materiaalissa usein pienillä kreikkalaisilla kirjaimilla. Jos Γ ja ovat tyyppilausekkeita, niin Γ on tyyppilauseke. Nuoli kirjoitetaan koneella
LisätiedotITKP102 Ohjelmointi 1 (6 op)
ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 7. huhtikuuta 2017 Vastaa kaikkiin tehtäviin. Tee jokainen tehtävä erilliselle konseptiarkille. Kirjoittamasi luokat, funktiot ja aliohjelmat
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 5: Sijoituslause, SICP-oliot, todistamisesta (mm. SICP 33.1.3, 3.33.3.2) Riku Saikkonen 7. 11. 2011 Sisältö 1 Muuttujan arvon muuttaminen: set! 2 SICP-oliot
LisätiedotOsoitin ja viittaus C++:ssa
Osoitin ja viittaus C++:ssa Osoitin yksinkertaiseen tietotyyppiin Osoitin on muuttuja, joka sisältää jonkin toisen samantyyppisen muuttujan osoitteen. Ohessa on esimerkkiohjelma, jossa määritellään kokonaislukumuuttuja
LisätiedotTIEA341 Funktio-ohjelmointi 1, kevät 2008
TIEA34 Funktio-ohjelmointi, kevät 2008 Luento 3 Antti-Juhani Kaijanaho Jyväskylän yliopisto Tietotekniikan laitos 2. tammikuuta 2008 Ydin-Haskell: Syntaksi Lausekkeita (e) ovat: nimettömät funktiot: \x
LisätiedotSe mistä tilasta aloitetaan, merkitään tyhjästä tulevalla nuolella. Yllä olevassa esimerkissä aloitustila on A.
Tehtävä. Tämä tehtävä on aineistotehtävä, jossa esitetään ensin tehtävän teoria. Sen jälkeen esitetään neljä kysymystä, joissa tätä teoriaa pitää soveltaa. Mitään aikaisempaa tehtävän aihepiirin tuntemusta
LisätiedotOhjelmoinnin perusteet Y Python
Ohjelmoinnin perusteet Y Python T-106.1208 2.3.2009 T-106.1208 Ohjelmoinnin perusteet Y 2.3.2009 1 / 28 Puhelinluettelo, koodi def lue_puhelinnumerot(): print "Anna lisattavat nimet ja numerot." print
LisätiedotPythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python
Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python 8. marraskuuta 2010 Ohjelmointi Perusteet Peruskäsitteitä Olio-ohjelmointi Pythonin alkeet Esittely Esimerkkejä Muuttujat
LisätiedotOhjelmointikieli TIE Principles of Programming Languages Syksy 2017 Ryhmä 19
Ohjelmointikieli TIE-20306 Principles of Programming Languages Syksy 2017 Ryhmä 19 Juho Kärnä Ville Mäntysaari 1. Johdanto D on yleiskäyttöinen, strukturoitu, staattisesti tyypitetty, käännettävä ohjelmointikieli
LisätiedotOhjelmoinnin peruskurssi Y1
Ohjelmoinnin peruskurssi Y1 CSE-A1111 30.9.2015 CSE-A1111 Ohjelmoinnin peruskurssi Y1 30.9.2015 1 / 27 Mahdollisuus antaa luentopalautetta Goblinissa vasemmassa reunassa olevassa valikossa on valinta Luentopalaute.
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 3: SICP kohdat 2.22.3, 33.1 ja 3.33.3.2 Riku Saikkonen 8. 11. 2010 Sisältö 1 Lisää listoista 2 Symbolit ja sulkulausekkeet 3 Derivoijaesimerkki 4 Muuttujan
LisätiedotLisää pysähtymisaiheisia ongelmia
Lisää pysähtymisaiheisia ongelmia Lause: Pysähtymättömyysongelma H missä H = { w111x w validi koodi, M w ei pysähdy syötteellä x } ei ole rekursiivisesti lueteltava. Todistus: Pysähtymisongelman komplementti
Lisätiedot13. Loogiset operaatiot 13.1
13. Loogiset operaatiot 13.1 Sisällys Loogiset operaatiot AND, OR, XOR ja NOT. Operaatioiden ehdollisuus. Bittioperaatiot. Loogiset operaatiot ohjausrakenteissa. Loogiset operaatiot ja laskentajärjestys.
LisätiedotTIE Principles of Programming Languages. Seminaariesityksen essee. Ryhmä 18: Heidi Vulli, Joni Heikkilä
TIE-20306 Principles of Programming Languages Seminaariesityksen essee Ryhmä 18: Heidi Vulli, Joni Heikkilä SISÄLLYSLUETTELO 1. Johdanto... 1 2. Ohjelmointikielen perusperiaatteet... 1 2.1 Paradigmat...
Lisätiedot811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2016-2017 1. Algoritmeista 1.1 Algoritmin käsite Algoritmi keskeinen laskennassa Määrittelee prosessin, joka suorittaa annetun tehtävän Esimerkiksi Nimien järjestäminen aakkosjärjestykseen
LisätiedotMatematiikan tukikurssi, kurssikerta 1
Matematiikan tukikurssi, kurssikerta 1 1 Joukko-oppia Matematiikassa joukko on mikä tahansa kokoelma objekteja. Esimerkiksi joukkoa A, jonka jäseniä ovat numerot 1, 2 ja 5 merkitään A = {1, 2, 5}. Joukon
Lisätiedot811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2018-2019 1. Algoritmeista 1.1 Algoritmin käsite Algoritmi keskeinen laskennassa Määrittelee prosessin, joka suorittaa annetun tehtävän Esimerkiksi Nimien järjestäminen aakkosjärjestykseen
Lisätiedot815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset
815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 2 vastaukset Harjoituksen aiheena on BNF-merkinnän käyttö ja yhteys rekursiivisesti etenevään jäsentäjään. Tehtävä 1. Mitkä ilmaukset seuraava
LisätiedotMatematiikan johdantokurssi, syksy 2016 Harjoitus 11, ratkaisuista
Matematiikan johdantokurssi, syksy 06 Harjoitus, ratkaisuista. Valitse seuraaville säännöille mahdollisimman laajat lähtöjoukot ja sopivat maalijoukot niin, että syntyy kahden muuttujan funktiot (ks. monisteen
LisätiedotProlog kielenä Periaatteet Yhteenveto. Prolog. Toni ja Laura Fadjukoff. 9. joulukuuta 2010
kielenä 9. joulukuuta 2010 Historia kielenä Historia Sovelluksia kehitettiin vuonna 1972 Kehittäjinä ranskalaiset Pääkehittäjä Alain Colmerauer Philippe Roussel programmation en logique Robert Kowalski
LisätiedotChomskyn hierarkia. tyyppi 0 on juuri esitelty (ja esitellään kohta lisää) tyypit 2 ja 3 kurssilla Ohjelmoinnin ja laskennan perusmallit
Chomskyn hierarkia Noam Chomskyn vuonna 1956 esittämä luokittelu kieliopeille niiden ilmaisuvoiman mukaan tyyppi kieli kielioppi tunnistaminen 0 rekurs. lueteltava rajoittamaton Turingin kone 1 kontekstinen
LisätiedotFunktionaalinen ohjelmointi
hyväksymispäivä arvosana arvostelija Funktionaalinen ohjelmointi Eeva Terkki Helsinki 10.12.2012 HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos HELSINGIN YLIOPISTO HELSINGFORS UNIVERSITET UNIVERSITY
LisätiedotPerinteiset tietokoneohjelmat alkavat pääohjelmasta, c:ssä main(), jossa edetään rivi riviltä ja käsky käskyltä.
TIETOKONEOHJELMIEN RAKENNE Perinteiset tietokoneohjelmat alkavat pääohjelmasta, c:ssä main(), jossa edetään rivi riviltä ja käsky käskyltä. Teollisuusautomaation ohjelmiin on lainattu runsaasti perinteisen
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 6: Funktionaalista ohjelmointia: todistamisesta, virrat ja I/O, hahmonsovitus (mm. SICP 3.5) Riku Saikkonen 8. 11. 2011 Sisältö 1 Vähän funktionaalisten
LisätiedotOhjelmoinnin perusteet Y Python
Ohjelmoinnin perusteet Y Python T-106.1208 1.4.2009 T-106.1208 Ohjelmoinnin perusteet Y 1.4.2009 1 / 56 Tentti Ensimmäinen tenttimahdollisuus on pe 8.5. klo 13:00 17:00 päärakennuksessa. Tämän jälkeen
LisätiedotTutoriaaliläsnäoloista
Tutoriaaliläsnäoloista Tutoriaaliläsnäolokierroksella voi nyt täyttää anomuksen läsnäolon merkitsemisestä Esim. tagi ei toiminut, korvavaltimon leikkaus, yms. Hyväksyn näitä omaa harkintaa käyttäen Tarkoitus
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 8: Tulkki: proseduurit, abstrakti syntaksi, quote ja cond (mm. SICP 44.1.5 osin) Riku Saikkonen 15. 11. 2011 Sisältö 1 Argumentittomat proseduurit ja käyttöliittymä
Lisätiedot815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset
815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 3 vastaukset Harjoituksen aiheena ovat imperatiivisten kielten muuttujiin liittyvät kysymykset. Tehtävä 1. Määritä muuttujien max_num, lista,
LisätiedotAS-0.1103 C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin
AS-0.1103 C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin Raimo Nikkilä Aalto-yliopiston sähkötekniikan korkeakoulu - Automaation tietotekniikan tutkimusryhmä 17. tammikuuta 2013
LisätiedotKoka. Ryhmä 11. Juuso Tapaninen, Akseli Karvinen. 1. Taustoja 2. Kielen filosofia ja paradigmat 3. Kielen syntaksia ja vertailua JavaScriptiin Lähteet
Koka Ryhmä 11 Juuso Tapaninen, Akseli Karvinen 1. Taustoja 2. Kielen filosofia ja paradigmat 3. Kielen syntaksia ja vertailua JavaScriptiin Lähteet 1 1. Taustoja Koka on Daan Leijenin ja Microsoft:n kehittämä
LisätiedotClojure, funktionaalinen Lisp murre
Clojure, funktionaalinen Lisp murre Principles of Programming Languages, S2015 Jukka Pekka Venttola & Pietari Heino Taustaa Clojuren pohjana on käytetty Lisp ohjelmointikieltä, jonka historia ulottuu 1950
LisätiedotConcurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo
Concurrency - Rinnakkaisuus Group: 9 Joni Laine Juho Vähätalo Sisällysluettelo 1. Johdanto... 3 2. C++ thread... 4 3. Python multiprocessing... 6 4. Java ExecutorService... 8 5. Yhteenveto... 9 6. Lähteet...
Lisätiedot811120P Diskreetit rakenteet
811120P Diskreetit rakenteet 2016-2017 ari.vesanen (at) oulu.fi 5. Rekursio ja induktio Rekursio tarkoittaa jonkin asian määrittelyä itseensä viittaamalla Tietojenkäsittelyssä algoritmin määrittely niin,
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 10: Tulkin muokkaus, makrot, ohjelmia muokkaavat ohjelmat (mm. SICP 3.2.4, 4-4.1.6) Riku Saikkonen 22. 11. 2011 Sisältö 1 Kirjan tulkin muokkaaminen 2
LisätiedotOhjelmoinnin perusteet Y Python
Ohjelmoinnin perusteet Y Python T-106.1208 9.2.2009 T-106.1208 Ohjelmoinnin perusteet Y 9.2.2009 1 / 35 Listat Esimerkki: halutaan kirjoittaa ohjelma, joka lukee käyttäjältä 30 lämpötilaa. Kun lämpötilat
Lisätiedot1. Olio-ohjelmointi 1.1
1. Olio-ohjelmointi 1.1 Sisällys Olio-ohjelmointi on eräs ohjelmointiparadigma. Olio-ohjelmoinnin muotoja. Ohjelmiston analyysi ja suunnittelu. Olioparadigman etuja ja kritiikkiä. 1.2 Ohjelmointiparadigmoja
LisätiedotITKP102 Ohjelmointi 1 (6 op)
ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 22. huhtikuuta 2016 Vastaa kaikkiin tehtäviin. Tee jokainen tehtävä erilliselle konseptiarkille! Kirjoittamasi luokat, funktiot ja aliohjelmat
Lisätiedotja λ 2 = 2x 1r 0 x 2 + 2x 1r 0 x 2
Johdatus diskreettiin matematiikkaan Harjoitus 4, 7.10.2015 1. Olkoot c 0, c 1 R siten, että polynomilla r 2 c 1 r c 0 on kaksinkertainen juuri. Määritä rekursioyhtälön x n+2 = c 1 x n+1 + c 0 x n, n N,
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Esittelyluento 2: Scheme-ohjelmointikieli ja mihin se on hyvä Riku Saikkonen 5. 10. 2010 Sisältö 1 Scheme-kielen pikaesittely 2 Kurssin käyttämästä kielestä 3
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 1: Rekursiivinen ajattelutapa, Scheme-kielen perusteita (mm. SICP 11.2.4) Riku Saikkonen 16. 10. 2012 Sisältö 1 Kurssijärjestelyitä 2 Perusteita Scheme-kielestä,
LisätiedotOhjelmoinnin perusteet Y Python
Ohjelmoinnin perusteet Y Python T-106.1208 11.2.2009 T-106.1208 Ohjelmoinnin perusteet Y 11.2.2009 1 / 33 Kertausta: listat Tyhjä uusi lista luodaan kirjoittamalla esimerkiksi lampotilat = [] (jolloin
Lisätiedot815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset
815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 4 vastaukset Harjoituksen aiheena ovat imperatiivisten kielten lauseisiin, lausekkeisiin ja aliohjelmiin liittyvät kysymykset. Tehtävä 1. Mitä
LisätiedotTIEA241 Automaatit ja kieliopit, kesä Antti-Juhani Kaijanaho. 26. kesäkuuta 2013
ja ja TIEA241 Automaatit ja kieliopit, kesä 2012 Antti-Juhani Kaijanaho TIETOTEKNIIKAN LAITOS 26. kesäkuuta 2013 Sisällys ja ja on yksi vanhimmista tavoista yrittää mallittaa mekaanista laskentaa. Kurt
Lisätiedot3. Muuttujat ja operaatiot 3.1
3. Muuttujat ja operaatiot 3.1 Sisällys Imperatiivinen laskenta. Muuttujat. Nimi ja arvo. Muuttujan nimeäminen. Muuttujan tyyppi. Operaattorit. Operandit. Arvon sijoitus muuttujaan. Aritmeettiset operaattorit.
Lisätiedot13. Loogiset operaatiot 13.1
13. Loogiset operaatiot 13.1 Sisällys Loogiset operaatiot AND, OR, XOR ja NOT. Operaatioiden ehdollisuus. Bittioperaatiot. Loogiset operaatiot ohjausrakenteissa. Loogiset operaatiot ja laskentajärjestys.
LisätiedotTietueet. Tietueiden määrittely
Tietueet Tietueiden määrittely Tietue on tietorakenne, joka kokoaa yhteen eri tyyppistä tietoa yhdeksi asiakokonaisuudeksi. Tähän kokonaisuuteen voidaan viitata yhteisellä nimellä. Auttaa ohjelmoijaa järjestelemään
LisätiedotRekursiolause. Laskennan teorian opintopiiri. Sebastian Björkqvist. 23. helmikuuta Tiivistelmä
Rekursiolause Laskennan teorian opintopiiri Sebastian Björkqvist 23. helmikuuta 2014 Tiivistelmä Työssä käydään läpi itsereplikoituvien ohjelmien toimintaa sekä esitetään ja todistetaan rekursiolause,
LisätiedotTähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python
Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python 31. tammikuuta 2009 Ohjelmointi Perusteet Pythonin alkeet Esittely Esimerkkejä Muuttujat Peruskäsitteitä Käsittely
LisätiedotJava-kielen perusteet
Java-kielen perusteet Tunnus, varattu sana, kommentti Muuttuja, alkeistietotyyppi, merkkijono, Vakio Tiedon merkkipohjainen tulostaminen Ohjelmointi (ict1tx006) Tunnus (5.3) Javan tunnus Java-kirjain Java-numero
LisätiedotJohdatus matematiikkaan
Johdatus matematiikkaan Luento 7 Mikko Salo 11.9.2017 Sisältö 1. Funktioista 2. Joukkojen mahtavuus Funktioista Lukiomatematiikassa on käsitelty reaalimuuttujan funktioita (polynomi / trigonometriset /
LisätiedotPython-ohjelmointi Harjoitus 2
Python-ohjelmointi Harjoitus 2 TAVOITTEET Kerrataan tulostuskomento ja lukumuotoisen muuttujan muuttaminen merkkijonoksi. Opitaan jakojäännös eli modulus, vertailuoperaattorit, ehtorakenne jos, input-komento
LisätiedotHarjoitus 1 -- Ratkaisut
Kun teet harjoitustyöselostuksia Mathematicalla, voit luoda selkkariin otsikon (ja mahdollisia alaotsikoita...) määräämällä soluille erilaisia tyylejä. Uuden solun tyyli määrätään painamalla ALT ja jokin
LisätiedotT Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 7 (opetusmoniste, kappaleet )
T-79144 Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 7 (opetusmoniste, kappaleet 11-22) 26 29102004 1 Ilmaise seuraavat lauseet predikaattilogiikalla: a) Jokin porteista on viallinen
LisätiedotTietotyypit ja operaattorit
Tietotyypit ja operaattorit Luennossa tarkastellaan yksinkertaisten tietotyyppien int, double ja char muunnoksia tyypistä toiseen sekä esitellään uusia operaatioita. Numeeriset tietotyypit ja muunnos Merkkitieto
LisätiedotLuku 3. Listankäsittelyä. 3.1 Listat
Luku 3 Listankäsittelyä Funktio-ohjelmoinnin tärkein yksittäinen tietorakenne on lista. Listankäsittely on paitsi käytännöllisesti oleellinen aihe, se myös valaisee funktio-ohjelmoinnin ideaa. 3.1 Listat
LisätiedotMatematiikan tukikurssi
Matematiikan tukikurssi Kurssikerta 1 1 Matemaattisesta päättelystä Matemaattisen analyysin kurssin (kuten minkä tahansa matematiikan kurssin) seuraamista helpottaa huomattavasti, jos opiskelija ymmärtää
LisätiedotHaskell ohjelmointikielen tyyppijärjestelmä
Haskell ohjelmointikielen tyyppijärjestelmä Sakari Jokinen Helsinki 19. huhtikuuta 2004 Ohjelmointikielten perusteet - seminaarityö HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos 1 Johdanto 1 Tyyppien
Lisätiedotetunimi, sukunimi ja opiskelijanumero ja näillä
Sisällys 1. Algoritmi Algoritmin määritelmä. Aiheen pariin johdatteleva esimerkki. ja operaatiot (sijoitus, aritmetiikka ja vertailu). Algoritmista ohjelmaksi. 1.1 1.2 Algoritmin määritelmä Ohjelmointi
LisätiedotLuku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti
Luku 6 Dynaaminen ohjelmointi Dynaamisessa ohjelmoinnissa on ideana jakaa ongelman ratkaisu pienempiin osaongelmiin, jotka voidaan ratkaista toisistaan riippumattomasti. Jokaisen osaongelman ratkaisu tallennetaan
LisätiedotITKP102 Ohjelmointi 1 (6 op)
ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 12. huhtikuuta 2019 Tee kukin tehtävä omalle konseptiarkille. Noudata ohjelmointitehtävissä kurssin koodauskäytänteitä. Yksi A4-kokoinen lunttilappu
LisätiedotITKP102 Ohjelmointi 1 (6 op)
ITKP102 Ohjelmointi 1 (6 op) Tentaattori: Antti-Jussi Lakanen 20. huhtikuuta 2018 Vastaa kaikkiin tehtäviin. Tee kukin tehtävä omalle konseptiarkille. Noudata ohjelmointitehtävissä kurssin koodauskäytänteitä.
LisätiedotMS-A010{3,4} (ELEC*) Differentiaali- ja integraalilaskenta 1 Luento 3: Jatkuvuus
MS-A010{3,4} (ELEC*) Differentiaali- ja integraalilaskenta 1 Luento 3: Jatkuvuus Pekka Alestalo, Jarmo Malinen Aalto-yliopisto, Matematiikan ja systeemianalyysin laitos 19.9.2016 Pekka Alestalo, Jarmo
LisätiedotJava-kielen perusteet
Java-kielen perusteet Tunnus, varattu sana, kommentti Muuttuja, alkeistietotyyppi, merkkijono, literaalivakio, nimetty vakio Tiedon merkkipohjainen tulostaminen 1 Tunnus Java tunnus Java-kirjain Java-numero
LisätiedotTIES542 kevät 2009 Tyyppijärjestelmän laajennoksia
TIES542 kevät 2009 Tyyppijärjestelmän laajennoksia Antti-Juhani Kaijanaho 16. helmikuuta 2009 Tyypitetyt ohjelmointikielet sisältävät paljon muitakin konstruktioita kuin yksinkertaisesti tyypitetyn lambda-kielen,
Lisätiedot8. Kieliopit ja kielet
8. Kieliopit ja kielet Suomen kielen sanoja voidaan yhdistellä monella eri tavalla. Kielioppi määrää sen, milloin sanojen yhdistely antaa oikein muodostetun lauseen. "Mies räpyttää siipiään" on kieliopillisesti
LisätiedotZeon PDF Driver Trial
Matlab-harjoitus 2: Kuvaajien piirto, skriptit ja funktiot. Matlabohjelmoinnin perusteita Numeerinen integrointi trapezoidaalimenetelmällä voidaan tehdä komennolla trapz. Esimerkki: Vaimenevan eksponentiaalin
LisätiedotVaihtoehtoinen tapa määritellä funktioita f : N R on
Rekursio Funktio f : N R määritellään yleensä antamalla lauseke funktion arvolle f (n). Vaihtoehtoinen tapa määritellä funktioita f : N R on käyttää rekursiota: 1 (Alkuarvot) Ilmoitetaan funktion arvot
LisätiedotOhjelmoinnin perusteet Y Python
Ohjelmoinnin perusteet Y Python T-106.1208 10.2.2010 T-106.1208 Ohjelmoinnin perusteet Y 10.2.2010 1 / 43 Kertausta: listat Tyhjä uusi lista luodaan kirjoittamalla esimerkiksi lampotilat = [] (jolloin
LisätiedotSisällys. 3. Muuttujat ja operaatiot. Muuttujat ja operaatiot. Muuttujat. Operaatiot. Imperatiivinen laskenta. Muuttujat. Esimerkkejä: Operaattorit.
3. Muuttujat ja operaatiot Sisällys Imperatiivinen laskenta. Muuttujat. Nimi ja arvo. Muuttujan nimeäminen. Muuttujan tyyppi.. Operandit. Arvon sijoitus muuttujaan. Aritmeettiset operaattorit. Arvojen
LisätiedotJava-kielen perusteita
Java-kielen perusteita valintalauseet 1 Johdantoa kontrollirakenteisiin Tähän saakka ohjelmissa on ollut vain peräkkäisyyttä eli lauseet on suoritettu peräkkäin yksi kerrallaan Tarvitsemme myös valintaa
Lisätiedot815338A Ohjelmointikielten periaatteet
815338A Ohjelmointikielten periaatteet 2015-2016 VII Logiikkaohjelmointi Sisältö 1. Johdanto 2. Predikaattilogiikan käsitteistöä 3. Prolog 815338A Ohjelmointikielten periaatteet, Logiikkaohjelmointi 2
LisätiedotKoottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.
2. Ohjausrakenteet Ohjausrakenteiden avulla ohjataan ohjelman suoritusta. peräkkäisyys valinta toisto Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet
LisätiedotRekursio. Funktio f : N R määritellään yleensä antamalla lauseke funktion arvolle f (n). Vaihtoehtoinen tapa määritellä funktioita f : N R on
Rekursio Funktio f : N R määritellään yleensä antamalla lauseke funktion arvolle f (n). Vaihtoehtoinen tapa määritellä funktioita f : N R on käyttää rekursiota: Rekursio Funktio f : N R määritellään yleensä
LisätiedotTIE PRINCIPLES OF PROGRAMMING LANGUAGES Eiffel-ohjelmointikieli
TIE-20306 PRINCIPLES OF PROGRAMMING LANGUAGES Eiffel-ohjelmointikieli Seminaariesitelmä ryhmä 24 Markku Ahokas Jani Kuitti i SISÄLLYSLUETTELO 1. YLEISTÄ EIFFELISTÄ... 1 1.1 Historia ja tausta... 1 1.2
LisätiedotJohdatus Ohjelmointiin
Johdatus Ohjelmointiin Syksy 2006 Viikko 2 13.9. - 14.9. Tällä viikolla käsiteltävät asiat Peruskäsitteitä Kiintoarvot Tiedon tulostus Yksinkertaiset laskutoimitukset Muuttujat Tiedon syöttäminen Hyvin
LisätiedotOhjelmoinnin peruskurssien laaja oppimäärä
Ohjelmoinnin peruskurssien laaja oppimäärä Luento 9: Makrot ja dynaaminen sidonta Riku Saikkonen 7. 12. 2010 Sisältö 1 Makrot 2 Pieni esimerkki abstraktion tekemisestä 3 Dynaaminen sidonta Mikä on makro?
Lisätiedot