Funktionaalinen ohjelmointi

Liittynyt
02.11.2016
Viestejä
4
Laitetaanpas pystyyn ketju funktionaaliselle ohjelmoinnille yleisesti kielestä riippumatta. Funktionaalisella tyylillähän voi periaatteessa ohjelmoida miltei millä kielellä tahansa, mutta minua on jo pitkään kiehtonut Haskell, joka on puhtaasti funktionaalinen kieli.

JavaScriptillä olen käyttänyt Underscore.js -kirjastoa. Niitä on paljon muitakin, mutten ole niistä niin perillä.

Joitain funktionaalisen ohjelmoinnin erityispiirteitä
  • Muuttumattomuus, "muuttujat" ovat muuttumattomia, eivätkä näin ollen muutu.
  • Funktioilla ei ole sivuvaikutuksia, eli funktio tuottaa ajasta ja paikasta riippumattomasti aina saman arvon kutsuttaessa sitä samoilla parametrien arvoilla. Funktiot eivät siis riipu ulkomaailmasta vaan ovat puhtaita. Esimerkiksi tällaisia tilanteita tulisi välttää (python-esimerkki):
Koodi:
# Funktion arvo riippuu ulkopuolisesta muuttujasta x
x = 4
def funktio(y):
    return x + y
  • Funktiot ovat ensimmäisen luokan kansalaisia, eli funktiot voivat palauttaa funktioita ja ottaa parametreinaan vastaan funktioita. Hyvänä esimerkkinä map-funktio.
Koodi:
-- lista, joka käsittää luvut 1-20
lista :: [Int]
lista = [1..20]

{-
  uusi lista, joka muodostetaan antamalla map-funktiolle funktio,
  (tässä tapauksessa anonyymi sellainen), jota sovelletaan listan
  jokaiseen elementtiin
-}
uusi_lista :: [Int]
uusi_lista = map (\x -> x * 2) lista
  • Laiska suoritus, lasketaan vain se mitä tarvitaan, silloin kun sitä tarvitaan. Tämä mahdollistaa äärettömät tietorakenteet.
Koodi:
-- 1:stä alkava äärettömän pitkä lista
lista :: [Int]
lista = [1..]

Tässä käytin Haskell-esimerkkejä, mutta kuten sanottua, funktionaalista tyyliä voi soveltaa myös muissa ohjelmointikielissä. Ainakin minulle on tavaksi tullut välttää sivuvaikutuksia aina kun mahdollista. Näin koodista tulee selkeämpää, yksinkertaisempaa ja sitä kautta myös turvallisempaa. Virheet on myös helpompi löytää ja testattavuus on helpompaa kun funktioilla ei ole sivuvaikutuksia.
 
Itselläni on toistaiseksi hyvin vähän kokemusta funktionaalisesta ohjelmoinnista, mutta olen tällä hetkellä tutustumassa Elm:iin.

Kyseessä on funktionaalinen kieli, joka kääntyy JavaScriptiksi. Se on erityisesti frontend-kehitykseen tarkoitettu kieli, jossa yhdistyy piirteitä mm. Reactista ja Reduxista. Funktion määrittely näyttää Elmissä tältä:

Koodi:
add : Int -> Int -> Int
add x y =
  x + y

Alussa tyyppien määrittely: ottaa parametriksi kaksi kokonaislukua ja palauttaa kokonaisluvun. Kuten Haskell, myös Elmissä on ns. "currying" (ei hajua suomennoksesta), jossa moniparametrinen funktio voidaan muuntaa yksiparametriseksi vaiheittain. Siksi tuossa tyyppimäärittelyssä ei erityisesti erotella parametrejä ja lopputulosta (joka on tuo listan viimeinen). Sulkeita ei parametrien yhteydessä käytetä ja sisennyksellä on väliä.

Erityispiirteinä kielessä on mm. staattinen tyypitys, modulaarisuus, nopea virtuaalinen DOM, ei ajonaikaisia virheitä ja todella selkeät kääntäjän virheilmoitukset. Elm noudattaa Model->View->Update -arkkitehtuuria.

Tässä eräs benchmark:


everyone.png


Tuota käytetään jo tuotannossa, joten kieli on siinä mielessä tarpeeksi kypsä. Aika näyttää, kuinka yleinen siitä tulee, mutta varsin lupaavalta vaikuttaa tällä hetkellä. Ainoat isommat haasteet tulevat silloin kun pitäisi käpistellä suoraan DOMia esim. joidenkin eventien yhteydessä. Tällöin on täysin sallittua käyttää Elmin rinnalla JS:ää tarpeen vaatiessa, jos homma ei ratkea suoraan Elmin puolella.

Pitäisi tutustua myös Haskelliin, josta löytyy materiaalia vaikka kuinka. Elmistä alkaa hissukseen löytyä enemmän oppaita, mutta ei ehkä vielä tarpeeksi kattavia.
 
Viimeksi muokattu:
Hieno ohjelmointisuuntaus on kyseessä näin lyhyesti sanottuna. Toisaalta välillä ärsyttää joidenkin periaatteiden tinkimättömyys. Lähinnä muuttujien/arvojen muuttumattomuus ja funktioiden puhtaus ovat häirinneet. Enimmäkseen ne vaikuttavat oikein hyödyllisiltä, mutta välillä tulee vastaan tilanteita, joissa tuntuisi pääsevän selvästi helpommalla, jos näistä periaatteista pääsisi vähän joustamaan. Ehkä kokemuksen avulla niihin oppii keksimään paremmat ratkaisut, mutta tähän asti on ollut tällaisia yksittäisiä vaikeampia tilanteita.
 
Tulee tehtyä funktionaalista ohjelmointia lähes aina niin paljon kuin vain pystyy. Kun sitä oppii lukemaan ja ymmärtämään niin koodin selkeys paranee 100-kertaisesti, testattavuus paranee, turvallisuus/vakaus paranee ja mikä parasta koodirivit vähenevät huomattavasti proseduraaliseen/OO-sotkuun verrattuna.

Päätoimiseksi työkseni teen iOS kehitystä ja Swift onneksi on erittäin joustava multiparadigmakieli joten vaikka iOS plätformina sinänsä on hyvin OO-pohjainen, sen päälle voi rakentaa erittäin paljon funktionaalista toiminnallisuutta. Suosittelisin ehdottomasti kaikille frontend ja application-levelillä koodaaville tyypeille tutustumaan myös FRP-ohjelmointiin (Functional Reactive Programming) eli tuttavallisemmin Rx-ohjelmointiin ja miksei myös muillekkin. Yksi hemmetin mehukas feature on esim asynkronisten eventtien funktionaalinen putkittaminen.

Pure functional kielissä on se ongelma ettei niillä tehdä kovin paljoa vielä käytännön hommia, mutta suosittelisin kaikkia aloittamaan sellaisella ja kokeilemaan erilaisten softien tekoa. Sitten kun homma alkaa olla hallussa ja aidosti ymmärtää mistä on kyse on opit helppo kantaa multiparadigm-kieliin ja käytännön maailmaan. Itse aloittelisin Clojurella ja F#:lla.
 
Funktionaalinen ohjelmointi kiinnostaa kyllä, Elmiä on tullut kokeiltua ja Haskellia on mukava opetella. Aikaan en ole saanut mitään kauhean isoa, mutta matopelin tein Haskellilla - se löytyy täältä: orouvinen/hssnake. Kyseessä ncurses-pohjainen viritys.

Ajattelin seuraavaksi alkaa väsäillä jotakin pikkupeliä Haskell + SDL2-kombolla, joskin aikaa vapaa-ajan koodailuun on tällä hetkellä erittäin rajatusti, joten en odota saavani oikeasti mitään aikaiseksi lähiaikoina. Mutta hauduttelen ideaa ja alan koodata heti kun tulee hyvä hetki.
 
Viimeksi muokattu:
Sitten kun homma alkaa olla hallussa ja aidosti ymmärtää mistä on kyse on opit helppo kantaa multiparadigm-kieliin ja käytännön maailmaan. Itse aloittelisin Clojurella ja F#:lla.
Yksi hyvä lisä tuohon listaan on Scala jolle erilaisia kirjastoja löyty paljon, koodiesimerkkejä on paljon ja SBT build toolina toimii ihan hyvin, kunnes rakentaa jokun tuotantokokonaisuuden usean aliprojektiin. Sitten saa SBTn kanssa hieman hieroa. Scala kääntää JVM ajettavaa koodia, eli käytännössä rullaa sitten millä tahansa käyttiksellä.

Jos joku päätyy Scalaa kokeilemaan ja haluaa opiskella FPiS -kirja (FPiS) on melko hyvä, jonka harjoitustehtäviin löytyy netistä myös vastaukset jos ei saa ratkaistua itse tai jos haluaa nähdä muita ratkaisuja.

Tosin jos tarkoitus on oppia oikein puristi FP koodailua niin sitten työkaluksi Haskell tai vastaava joka estää asioita joita edellä mainitut sallii.
 
[...] Swift onneksi on erittäin joustava multiparadigmakieli [...] Sitten kun homma alkaa olla hallussa ja aidosti ymmärtää mistä on kyse on opit helppo kantaa multiparadigm-kieliin ja käytännön maailmaan. Itse aloittelisin Clojurella ja F#:lla.
Täältä myös ääni multiparadigma-koodille! Tai pikemminkin, oikea työkalu kuhunkin ongelmaan. Puhdas funktionaalinen ohjelmointi ei tee koodista mielestäni yhtään luettavampaa/testattavampaa, jos tilan hallinta on erityisen monimutkainen (esim. GUI).

Itse lähden yleensä rakentamaan koodia proseduraalisella lähestymistavalla, ja yleensä vasta refaktoroinnin yhteydessä vaihdan koodipalasia tarpeen mukaan joko funktionaaliseen tai olio-ohjelmoinnin tyyliin. Koodaan pääosin Pythonilla, joten tyylin vaihtaminen on myös hyvin helppoa (etenkin, kun nykyään Pythonissa voi antaa myös type-hintejä). Usein julkiset "api"-metodit ovat mahdollisimman funktionaalisia, mutta privaatit funktiot sisältävät vähän mitä sattuu.

Multiparadigma-ohjelmoinnista oli myös ihan kiva luento EuroPythonissa.
 
Täältä myös ääni multiparadigma-koodille! Tai pikemminkin, oikea työkalu kuhunkin ongelmaan. Puhdas funktionaalinen ohjelmointi ei tee koodista mielestäni yhtään luettavampaa/testattavampaa, jos tilan hallinta on erityisen monimutkainen (esim. GUI).

Itse lähden yleensä rakentamaan koodia proseduraalisella lähestymistavalla, ja yleensä vasta refaktoroinnin yhteydessä vaihdan koodipalasia tarpeen mukaan joko funktionaaliseen tai olio-ohjelmoinnin tyyliin. Koodaan pääosin Pythonilla, joten tyylin vaihtaminen on myös hyvin helppoa (etenkin, kun nykyään Pythonissa voi antaa myös type-hintejä). Usein julkiset "api"-metodit ovat mahdollisimman funktionaalisia, mutta privaatit funktiot sisältävät vähän mitä sattuu.

Multiparadigma-ohjelmoinnista oli myös ihan kiva luento EuroPythonissa.

Tuo monimutkaisen tilan hallinta riippuu myös kielestä. Jos tialle voi ja suunnittelee vahvasti tyypitetyn data objectin ja toimet UI:lla ovat aina actioniin sidottu functio ja mahdollinen input data + nykyinen tila, niin functio voi aina palauttaa uuden tilan. Vaan en kyllä lähtisi mitään FP puristi harjoitusta GUI:lla kokeilemaan vain huvikseni. Ja toki mielellään vaatii sitten kielen/työkalun joka voi jo kääntöaikana validoida, että jokaisen data objectin input/output onnistuu kaikilla suorituspoluilla.

Tämmöinen härveli rakenneltu duunissa Scalalla. Eos onnistuuko type hinteillä, on aika pitkä aika meikän python koodailuista jos nyt jotain yksinkertaisia scriptejä ei lasketa.

Ja ei.. en ole FP puristi vaihdan kieltä ja paradigmaa tarpeen ja järjen mukaan.
 
Pitäisi tutustua myös Haskelliin, josta löytyy materiaalia vaikka kuinka. Elmistä alkaa hissukseen löytyä enemmän oppaita, mutta ei ehkä vielä tarpeeksi kattavia.

Ja nyt alkoi (vasta) se tutustuminen :D Tässä on hyvä ilmainen verkkokurssi Haskellin ja funktionaalisen ohjelmoinnin perusteiden opiskeluun. Kurssista saa myös noppia, jos niitä tarvitsee:


Lähdetään aivan perusteista ja rakennetaan yksinkertaisten funktioiden kautta osaamista. Kurssista on ilmestynyt juuri 2-osan Preview, eli syventävää kontenttia on tullut lisää. Sinänsä Haskellin syntaksi ja perusteet oli helppo omaksua kun oli jo ennestään kokemusta Elmistä.
 
Funktionaalisten kielten opiskelusta on ainakin se hyöty, että myös muiden paradigmojen koodista tulee parempaa.

Immutability on hankala hanskata alkuun, mutta sillä on isoja etuja. Se poistaa ison joukon kokonaisia bugityyppejä ja mm. helpottaa rinnakkaistamista merkittävästi. Jokainen rinnakkaissoftaa koodannut tietää, minkälaista helvettiä se pahimmillaan saattaa olla deadlockeineen ja race conditioneineen.
 

Statistiikka

Viestiketjuista
261 574
Viestejä
4 540 708
Jäsenet
74 825
Uusin jäsen
Pete52

Hinta.fi

Back
Ylös Bottom