SANKO-tapahtuma: Funktionaalinen ohjelmointi ja F#

This post is an exception from the English majority of my writings. I will be summarizing the Finnish .NET User Group’s event on F# and functional programming, and will do it in Finnish. In summary, a great event!

Neljäs SANKO-tapahtuma järjestettiin 9.6. ohjelmistoyhtiö Reaktorin tiloissa Helsingin keskustassa. Tuomas Hietanen ja Rami Karjalainen alustivat kertomalla kokemuksiaan funktionaalisesta ohjelmoinnista ja esittelemällä F#-kieltä. Kolmen tunnin tiukan esityksen jälkeen ilta jatkui ruokailulla ja saunomisella. Paikalla oli kokonaisuutena kolmisenkymmentä ihmistä.

imageTuomaksen ja Ramin esitykset voisi tiivistää seuraavasti: He näkivät funktionaalisuuden olennaisena positiivisena trendinä, ja kokivat F#:n erittäin vakavasti otettavana kielenä vähintäänkin liiketoimintalogiikan ja datan toteutukseen. He olivat pitkään tehneet yhdessä vakuutusalan hanketta, jossa F# oli keskeisessä roolissa.

Yleisössä oli vahvaa kiinnostusta aiheeseen, ja Tuomas saikin selittää funktioteoriaa ja muita periaatteita varsin pitkällisesti. Käyttökokemus F#:sta itsestään oli harvassa, mutta C#:lla funktionaalista ohjelmointia – siis LINQ:n tehokäyttöä – oli kyllä harrastanut monikin. Funktionaalisuutta harjoitellessa F# nousi C#:a suosituimmaksi mm. vahvemman tyyppi-inferenssin (tyyppien automaattinen päättely, jolloin koodissa tarvitaan vähemmän turhaa tyyppien toistelua ja generics-kulmasulkeita) ja interaktiivisuuden takia. Käytiinpä esitysten lomassa myös keskustelu, jossa pohdittiin testivetoisen kehittämisen (TDD) arvoa ja sitä, onko itseasiassa interaktiiviseen REPL-työkaluun pohjautuva interaktiivinen kehitysmalli tehokkaampi.

Tuomaksen esitys: kalvot ja esimerkkisovellus

Ramin matskut: kalvot ja koodi

SANKO-toimintaan voit tutustua Facebookissa ja LinkedInissä. F#:lle on myös oma käyttäjäryhmänsä.

Kiitos kaikille osallistujille ja esiintyjille – ja tietysti myös Reaktorille sponsoroinnista. Ja hei, Reaktorin läsnäolo .NET-kentällä tarkoittaa siis sitä, että Suomen parhaana työpaikkana monesti palkittu softatalo on nyt auki myös Microsoft-osaajille. Se on merkittävä asia, enkä sano tätä vain siksi, että sain hyvää ruokaa. :-)

June 26, 2011 · Jouni Heikniemi · 169 Comments
Tags: ,  Â· Posted in: General

169 Responses

  1. Vakuutusmies - January 23, 2012

    Tuomas,

    se voi etsiä nuppineulan kokoisessa projektissa, mutta ei "ison maailman" sovelluksessa. Eivät ne sorsat pyöri kaikkialla, vaan pitäisi pystyä käyttämään myös käännettyjä kikkareita. Varmuudella en sano mitään, mutta ihmettelen vaan mitenköhän toi inline mahtaa toimia jos annat minulle F#:lla toteutetun assemblyn C#:n käyttöön? Tai minkä kokoisen funktion uskallat inline:ta? Eikä se kuitenkaan ratkaise sitä, että joka tapauksessa pitää ymmärtää miksi vaikkapa 2.9 != ( 0.1 * 29.0 ) ja tyypitys on tehtävä desimaaliin jos haluaa koodin toimivan edes jotakuinkin järkevästi. Jos taas haluaa, että koodi suorituu (nuppineulan päätä isommissa jutuissa) pitää osata käyttää molempia. Esimerkiksi Javassa double on aivan sikana nopeampi kuin BigDecimal. Ei ole ympäristöä millä testata, mutta en näe mitään perusteita miksi näin ei olisi myös .NET:ssä. Ja syyhän löytyy taas ihan sieltä hardwaresta saakka.

  2. Vakuutusmies/Tietohallintomies - January 23, 2012

    Hyvät funktionalinistit ja muut,

    Se alkaa olla nyt Vakuutusmiehen sekä Tietohallintomiehen tarinat sitten tässä. Kiitos Jounille "varastamastani" levytilasta ;-)

    Mitä tästä kaikesta meuhkaamisesta sitten jäi käteen? No, minä opin hieman uutta sieltä sun täältä kun jouduin varmistelemaan sitä sun tätä, jotta en väitä mitään MUTU-periaatteella. Ja koska opettelin vähän myös F#:a, niin myös sellaista iisiä Scalaa osaan nyt lukea melko sujuvasti.

    Mitä mieltä sitten olen funktionaalisuudesta? Funktionaalisissa kielissä on toteutettuna muutamia ihan kivoja asioita, mutta juuri mikään niistä ei itse asiassa ole funktionaalisten kielten "yksityisomaisuutta". Esimerkiksi X10 (oliokieli) on paljon samoja asioita mitä funktionaalisissa kielissä, mutta myös muutamia sellaisia asioita joita voi olla hieman hankala muista kielistä löytää (esim. kielen suora tuki FPGA:lle ja GPU:lle, distributed parallelism, …). Näissä kielissä (F#, Scala) on kuitenkin yksi yhteinen tekijä: niillä ei ole riittävästi käyttäjiä eikä osaajia. Jos esimerkiksi luette tämän blogin läpi voitte itse tehdä johtopäätökset vaikkapa F#:n concurrency/parallelism asioiden osaamistasosta. Jos nyt puhun pelkästään Scalasta ja F#:sta, niin uskon että kumpikin näistä kielistä säilyy hengissä *vain ja ainoastaan* sen takia, että niistä pystyy käyttämään host-platformin oliokirjastoja. Ilman .NET-kirjastoja F# olisi nääntynyt jo laboratorio-olosuhteisiin. Sama koskee Scalaa. Nähtäväksi jää miten nämä kielet selviytyvät jatkosta. Ainakaan itse en olisi liian toiveikas. Kun esimerkiksi Java 8 läpsähtää saataville (mukana funktionaalisista kielistä pöllittyjä ominaisuuksia), veikkaan että näemme kohtalaisen jyrkän taantuman Scalalle. Osittain uusien piirteiden takia ja osittain vain sen takia, että Javasta tuli vihdoinkin taas uusi versio.

    Erittäin suurena miinuksena funktionaalisille kielille on myös se fakta, että nykyiset suunnittelumallit (joita en lähtisi kovasti kritisoimaan) perustuvat lähinnä vain ja ainoastaan olioihin. Ihmiset, minä mukaanlukien, nyt sattuvat ajattelemaan monista asioista oliomaisesti. Olen nähnyt miten oliosuunnittelulla ja oliokielellä toteutettuna homma toimii erinomaisen hyvin (tästä kokemusta sellaiset 20 vuotta). Toisaalta olen nyt myös viime aikoina nähnyt projekteja joissa propelipäät ovat tulleet kertomaan että agilea ja scrumia peliin vaan ja mitään suunnittelua ei tarvita. Ja juuri nämä projektit ovat epäonnistuneet ja laatu on ollut, anteeksi moderaattori, kauheaa paskaa. Vain IT-alan ihmiset ovat niin arrogantteja, että kuvittelevat että jotain järkevää voi tehdä ilman suunnittelua (vrt talon rakennus, auton rakennus, …). Tämä oli siis kannanottoni siihen suunnittelun tarpeeseen.

    No, joka tapauksessa minä vaihdan nyt varastomiehen univormun päälleni ja siirryn tietovarastoinnin ihmeelliseen MPP-maailmaan, eli taas ihan sellaista real life parallelismia.

    Onnea ja menestystä kaikille,

    Vakuutusmies/Tietohallintomies

  3. Tuomas - January 24, 2012

    F# ei ole ensisijaisesti tarkoitettu kevyeksi skriptikieleksi (kuten esim. Python), vaan dll-logiikka-kirjastojen rakennukseen.

    Menemättä tarkemmin CLR/IL-puolelle, niin yhteensopivuushuoli on turha. Vastaavasti C#:lla voi tehdä VB-yhteensopivia dll:iä. F# on (ML-pohjainen) OCaml-kieli .Net-ympäristöä varten.

    Oman kokemukseni mukaan "let" saa tyypin noin 80% tapauksista ilman lisäohjeita. Se on paremmin kuin esim. C#, jossa "var" ei voi olla Func, ja metodiparametrit pitää määritellä aina. Yleensä inline-koodia ei tarvitse kirjoittaa. Generic-tyypit merkitään pilkulla: 'a 'b 'c

    Uudet kielet tuovat hyvää painetta vanhojen kielten kehitykseen. Silti, kuten muukin softa, vanhat ohjelmointikielet kulkevat tiensä päähän aikanaan. Ei se C++ ole onnistunut nousemaan enää valtakieleksi, vaikka .NET-puolella siihen on saatu paljon uusia ominaisuuksia. On sille paikkansa, mutta käyttö on vähenemään päin.

    Omasta puolestani kiitos Vakuutusmiehelle käytetystä ajasta, linkeistä ja keskustelusta.

  4. Varastomies - February 10, 2012

    Ei oikein lennä toi funktionaalisuus vieläkään jos tuosta TIOBE:n listasta voi mitään päätellä …

    Object-Oriented Languages 57.6% +0.4%
    Procedural Languages 36.3% -1.0%
    Functional Languages 4.2% -0.1%
    Logical Languages 1.9% +0.7%

  5. C#-koodaaja - February 22, 2012

    TIOBE:n listalla OO-kielet (57%) pitävät sisällään mm. C# (8.7%).

    Nykyisellään C# (LINQ:ineen) on about kolmasosan funktionaalinen kieli. Siitä siirtyisi heti reilut 2,5% OO-kieliltä funktionaalisille.

    Ja mikäs Javascript sitten on? Tekijöidensä mukaan (Crockford) funktionaalinen. Mutta Javascript+Python>4.2, eli listan mukaan ei.

    Kategoriat eivät ole noin mustavalkoisia. Ehkä ne pitäisi jakaa uusiksi, ehkä lisätä Multi-paradigm Languages?

  6. Varastomies - February 27, 2012

    Entä miten pitäisi huomioida se, että suuri osa oliokielten ja osittain jopa funktionaalisten kielten ohjelmoijista ei kuitenkaan kirjoita ohjelmiaan oliomaisesti/funktionaalisesti vaan proseduraalisesti? Eli laitetaanko sitten sellaiset +50% proseduraalisille kielille heti samoin tein?

    Ja sitten Javascriptiin. Kuka sanoo, että Javascript on funktionaalinen? Jos vetoat Douglas "Cockford":iin, niin hänen kaikkia sanomisiaan en ottaisi ihan vakavasti. Hän ei myöskään ole Javascriptin isä, vaikka niin ilmeisesti oletit. Jos katsot vaikkapa http://www.crockford.com/javascript/private.html, niin hän esittelee siinä Javascript-patterneja, mutta ei muista kertoa, että osa niistä onkin eräänlaisia anti-patterneja (esim. juuri tuo privileged methods). Fakta on se, että toistaiseksi Javascriptistä ei ole täysveriseksi oliokieleksi (mm. koska tilan piilottaminen ei ole mahdollista järkevästi), eikä siitä myöskään ole kovin hyväksi funktionaaliseksi kieleksi. Sanon tämän kokemuksesta, en siitä että Douglas "Cockford" on sanonut niin. Oliokieleksi siitä voi tulevaisuudessa ehkä ollakin, mikäli tämä menee läpi http://wiki.ecmascript.org/doku.php?id=harmony:classes.

  7. Vakuutusmies - March 16, 2012

    Jäi vähän viime tinkaan tämä kun yllättäin Don'in maili oli mennyt roskapostin joukkoon ja löysin sen vasta nyt kun putsailin postilodjuani ;-)

    Tässä Don Symen vastaus esittämääni kissat ja hiiret haasteeseen, johon pyysin siis hänen mielipidettään ja mahdollista ratkaisua. Tai tarkemmin ottaen halusin hänen kertovan, että kyllä sitä mutable tilaa tarvitaan tässä ongelmassa.

    Kevätterveisin,

    Vakuutusmies

    Don Syme:

    "Hi Salminen,

    Its an interesting problem, and I think its great to challenge functional-think in this way.

    I can't write up an answer due to lack of time, and in any case it may well be I'd recommend the use of agents or mutable state – I'm no functional-fundamentalist :-) But I would encourage you to blog this and to ask this kind of question on stackoverflow or stackexchange – and ask for working code for the answer :-)

    Kind regards

    don
    "

    ja Vakuutusmiehen kysymys:

    On the other hand I'm also interested to know what functional programming is really good for and what it doesn't fit well. That’s why I joined discussion thread. However, these guys are just repeating the mantra about immutable objects, how shared state is root of all evil (which is partly true) and with functional programming is not needed at all (which I don't buy). I personally think this is crap, but I wanted to get a second opinion and decided to contact "trusted source", which in this case means you.

    First, I describe the challenge together with its restrictions. Here we go:

    The idea is to have self-playing game with a number of animals (rats and cats) in the maze. The maze contains rooms and each room can host only one animal at the time, except when rat is eated. If rat and predator enter the same room, predator eats the rat and rat must leave the game. Two predators cannot enter the same room and same applies to rats: they can't be in the same room, ever (including initialization). Each animal (i.e. instance of rat or cat) thinks a random period of time before moving to next room (just like in real world they have free will). This means that all animals can, but are not limited to, move randomly (north, nort-east, east,south-east,…) at the same time. If there's too much congestion (no free rooms after checking each point), the animal stays where it is.

    To me this implies that animals must be threads or similar behaviour must be implemented with the help of timers (which means threading again). The maze contains state which must be shared by all animals (threads): for example, available locations. I think it's a little bit hard to use immutable datasturecture as a maze (without locking), since other animals can move while switching the "current" maze state (thus loosing for example movement events). A little bit similar behaviour can be implemented without locking by using message passing, but I think it results in quite clumsy implementation.

    Any comments? I would really appreciate your response.

    BR, Pasi Salminen

  8. Vakuutusmies - March 16, 2012

    Tuosta vakuutusmiehen kysymyksestä puuttuu siis alusta hieman tekstiä johon korvasin tagin sisään (joka siis suodattui pois).

    * some ranting filtered out *

  9. Tuomas - March 26, 2012

    Moi,

    Lukoista vielä, kiinnittäisin huomiota: "agents or mutable state". Agents, message-passing ja mail-box-processor on samalle asialle monta eri nimeä, mutta se on tuotu tässä vaihtoehtona eksplisiittiselle tilalle. (Kuten aiemmin puhuttiin, niin siinä on näennäinen tila, yksi thread kontroloi sitä, mutta se on yksittäisen threadin sisäinen asia.)

    Koitin viikonloppuna ILSpyllä katsella mitä Mailboxprocessorin sisältä löytyy, ja .NET lock:eja sieltä en löytänyt (mikä ei takaa, ettei niitä jossain olisi). Siellä oli wait-retry-wait-retry-tyylinen jonotuskuvio.

    Sen sijaan Rx:ssä oli lockkeja.

  10. Tuomas - April 10, 2012

    Moi taas,

    Kävipäs tuuri, sillä eilen ilmestyi uusi video, jolla itse actor mallin isä vähän avaa ideologiaa actor(/message passing/mailbox/agents)-mallin takaa:

    http://channel9.msdn.com/Shows/Going+Deep/Hewitt-Meijer-and-Szyperski-The-Actor-Model-everything-you-wanted-to-know-but-were-afraid-to-ask

  11. Varastomies - April 24, 2012

    Moi,

    En katsonut tuota videota, mutta varmuudella voin sanoa, että myös message passing vaatii jonkun muistin synkronointimekanismin, eli joko lukon tai volatile muuttujan. En näe mitään syytä miksi se käyttäisi lukkoa, mutta volatile muuttujan siellä todennäköisesti on. Tämä perustuu siihen, että jopa Microsoft ei voi sille mitään miten prosessorit toimivat. Eli taas voi katella sitä muistimalliopusta tai MESI-protokolla. Molemmat linkit löytyvät ylempää. Muistuttaisin kuitenkin, että message passing mekanismi ei mahdollista kunnollista kissat ja hiiret pelin tekoa speksien mukaan.

    t. Varastomies

  12. Tuomas - May 5, 2012

    Yksittäisen prosessorin sijaan voidaan ajatella vaikka pilvi-arkkitehtuuria.

    Toimiihan esim. (hajautetut) versionhallintajärjestelmätkin niin, että synkronointi voidaan hoitaa paikallisesti, eikä jokaisen kehittäjän tarvitse lukita koko tilaa oman päivityksensä ajaksi. Merge-operaatiot tehdään aika-/eventhistorian pohjalta. Ajan ottaminen parametriksi ei ole kovin kummallinen temppu.

    Synkronointimekanismin ei tarvitse olla keskitetty, vaan se voi olla osittainen. Niin kauan kuin hiiret vain kuolevat pois, niin koko synkronointi voidaan vaikka laskea kokonaan jälikäteen. Sitten jos hiiret alkaisivat pariutua uusia hiiriä, niin tarvitaan jonkunlaista synkronointia ennen operaatiota, mutta tästä lisää Animal Planetilla.

  13. Varastomies - May 24, 2012

    Moi,

    No joo, joissain asioissa voi tietenkin aina fuskata, mutta esimerkiksi ydinohjusten ohjausjärjestelmän kanssa näkisin ihan oikean toimivuuden aika tärkeäksi. Tai voi toki olla, että joku jää tänne sitten vielä laskemaan niitä jälkikäteen. Sama pätee vaikkapa sairaalalaitteisiin; voi olla hieman myöhäistä peruuttaa tiettyjä väärin perustein tehtyjä operaatioita jos potilas on jo kuollut. Ei onnaa kun Schrödingeriltä. http://hikipedia.info/wiki/Schr%C3%B6dingerin_kissa

  14. Tuomas - June 6, 2012

    "Oikea toimivuus" riskeerataan aika monella muullakin tapaa kuin synkronoinnilla. Noin ylipäätään IT-toimittajien puitesopimukset ovat toimittajille edullisia ja sopimussakot ovat pieniä. Asiakkaat ne mokat maksavat, eivät toimittajat.

    Mutta mitä jälkikäteen laskemiseen tulee, niin se voidaan kyllä tehdä, kunhan homma mietitään oikein. (Ja säästetään servereiden hinnoissa aika huomattavasti.) Esim. Amazon ei voisi käsitellä varastoaan reaaliajassa. Tästä lisää viime vuoden techdays-esityksissä:
    http://video.fi.msn.com/watch/video/kolmikerrosarkkitehtuurin-evoluutio-cqrs-mikko-hytti-fujitsu-services/15db8zqmr
    http://video.fi.msn.com/watch/video/cqrs-kaytannossa-pasi-taive-cybercom/15dl3ey0i
    (Taas vaaditaan Silverlightia. Pasi T ja Mikko pitivät aiheesta myös SANKO-tapahtuman.)

    CQRS+EventSourcing on itse asiassa hyvin lähellä Agents-henkistä mallia ja funktionaalista reaktiivista ohjelmointia. Sanoisin jopa, että CQRS+EventSourcing on saatu, kun funktionaaliset ajatusmallit on sovellettu (oliopohjaisiin enterprise-)arkkitehtuurimalleihin.

  15. Varastomies - June 21, 2012

    Päivää taas,

    Ihan tiedotuksen omaisesti vaan kerron, että F# on tippunut Tioben listalla sijalle 50-100. Lieneekö F#-koodarit lomalla jo vai mistä on kyse?

    t. Tietohallintomies

  16. Satunnainen nettisurffari - October 20, 2015

    Usein näkee koodia jossa on yritä-ja-erehdy mallilla if-lauseista koottu iso puu. Pieni vauhdin haku jo suunnitteluvaiheessa vähän matemaattisemmasta lähestymistavasta tekisi hyvää ylläpidettävyydelle. For ja if ovat ehkä väärät alkiot rakentaa isoja ohjelmistoja, koska for ohjaa sivuvaikutuksiin ja if johtaa vahingossa vuotaviin koodipolkuihin.

    Oliojärjestelmien ongelmana on se, että pienistä palikoista ei tule itsenäisiä, koska ohjelmointiympäristö ei ohjaa toteuttajaa oikeanlaiseen kompositioon. Luokkien sisäinen tila vuotaa sivuvaikutuksina metodikutsujen kautta ulos. Jotta näin ei kävisi, vaaditaan kehittäjältä poikkeuksellisen suurta kurinalaisuutta, jota kaikilla kehittäjillä ei pidemmällä aikavälillä koodia ylläpidettäessä pysy. Tavallaan SOLID-periaatteita rikotaan niin perustavanlaatuisella tasolla, että sitä on edes vaikea huomata.

    Tiedon eheys voidaan varmistaa muutenkin kuin vain lukitsemalla koko maailma synkronoinnin ajaksi.

  17. Varastomies - December 21, 2017

    En tiedä mitä ihmettä edellisellä kommentilla oikein haettiin. Kuten Shrek jo aikanaan sanoi: varsinaista paskaa. Ja viimeinen kommentin rivi kyllä kertoo kaiken ymmärryksestä, joten ei tarvitse kommentoida enää tarkemmin.

  18. Lapioija - December 22, 2017

    "Oliojärjestelmien ongelmana on se, että pienistä palikoista ei tule itsenäisiä, koska ohjelmointiympäristö ei ohjaa toteuttajaa oikeanlaiseen kompositioon. "

    Mitä tarkoittaa "itsenäinen palikka"? Onko se koodinpätkä, jolla ei ole mitään riippuvuuksia? Miten "koosteisuus" pitäisi sitten toteuttaa – funtioilla jotka eivät riipu muista funktioista?

  19. Tikulla silmään sitä joka vanhoja muistelee? - May 4, 2018

    F# on näköjään tippunut jo näköjään listoilta niiden ohjelmointikielien joukosta, joille ilmoitetaan sijaluku. Käyttääköhän tätä kieltä enää ketään?

Leave a Reply