R-ohjelmointi.org

Tilastotieteellistä ohjelmointia R-kielellä

Ovatko sanat anagrammeja – kokemuksia funktion kehittämisestä ryhmätyönä

Kokeilimme kolmeen pekkaan, mitä hyötyä voisi olla esimerkiksi R-funktioiden kehittämisestä ryhmätyönä. Valitsimme testiin yksinkertaisen esimerkin: toteutettavan funktion piti testata, ovatko sille syötteenä annetut merkkijonot keskenään anagrammeja.

Anagrammeja ovat kaikki ne merkkijonot, jotka ovat permutaatioita samasta merkkijonosta, ja lisäksi muodostavat jonkin ymmärrettävän sanan. Siten esimerkiksi merkkijonot, jotka ovat eri mittaisia tai koostuvat eri kirjaimista eivät voi olla anagrammeja.

Kaikki osallistujat toteuttivat ensin yksinään yhden version funktiosta, ja sitten vaihdoimme funktioiden koodeja keskenämme. Lopetimme kun kukaan ei enää viitsinyt jatkaa pidempään. Lopulliseksi versioksi jäi viimeisenä toteutettu.

Kokeilun aikana henkilöiden välillä tapahtui luonnollisesti ajatusten vaihtoa, mikä näkyi myös toteutettujen funktioiden muutoksina. En ole aiemmin tehnyt ihan samanlaista harjoitusta, ja koodin kehittyminen ripein harppauksin yllätti ainakin minut.

Kaavioksi koostettuna funktion kehittyminen on kuvattu alla olevassa kuvassa. Voit tarvittaessa klikata kuvan suuremmaksi. Koodiblokkien oikeassa yläreunassa oleva numero kertoo versionumeron, ja eri väriset nuolet kertovateri tekijöiden välisistä interaktioista.

anagrammi3

Minä (tekijä 1) ja tekijä kaksi vaihdoimme ensin keskenämme koodeja. Nähtyäni tekijän 2 koodin, tajusin ettei sanojen aakkostoa ole pakko päätellä etukäteen, vaan sen voi päätellä ns. lennossa. Tällä välin tekijä 3 oli laatinut oman ensimmäisen versionsa, ja nähtyään tekijän 1 jo hieman parannellun version, hän tajusi, ettei sanaa ole pakko pilkkoa erillisiksi kirjaimiksi silmukalla, vaan sen voi tehdä vektoroidulla funktiolla strplit().

Tämän jälkeen tekijä 3 jäi vielä pohtimaan omaa toteutustaan, ja sai sen lyhennettyä paljon lyhyemmäksi. Kun taas tekijä 1 sai nähtäväkseen tekijän 3 viimeisimmän funktioversion, hän tajusi ettei kirjaimista tarvitse välttämättä edes laskea lukumääriä, vaan järjestettyjen vektorien vertaaminen ajaa saman asian: jos kaikki kirjaimet ovat järjestetyissä vektoreissa samoilla kohdin, ovat merkkijonot anagrammeja.

Kohdaksi 6 merkitty versio jäi tämän harjoituksen viimeisimmäksi funktion muodoksi. Se on tosin aavistuksen vajavainen, ja tulostaa vain loogisen arvon (TRUE/FALSE), kun muut kertovat suomeksi, ovatko merkkijonot anagrammeja. Niinpä funktion 6 voisi vielä kirjoittaa muotoon, jossa kuitenkin ns. one-liner -muoto säilyy:

f<-function(a, b) {
   return(ifelse(identical(sort(strsplit(tolower(a),"")[[1]]), sort(strsplit(tolower(b),"")[[1]])), "Ovat anagrammeja.", "Eivät ole anagrammeja."))
}

Mitä opimme harjoituksesta? Olen jo aiemmin mm. pitämilläni kursseilla havainnut, että ihmiset koodaavat hyvin eri tavoin. Eri ihmiset voivat ratkaista saman ongelman varsin erilaisilla tavoilla. Osittain kyseessä voi olla osaamisero tai aiemman ohjelmointikokemuksen tuottama oppimistulos, mikä esimerkiksi tässä harjoituksessa näkyi siinä, käyttikö merkkijonon pilkkomiseen merkeiksi silmukkaa vai valmista funktiota. R:ssähän mieluusti käytetään vektoroituja funktioita, vaikka jotkin muut kielet käyttävät samassa tarkoituksessa silmukkaa. Vielä suuremmalta osin on nähdäkseni kuitenkin kyse eroista koodaamistavoissa ja kenties ajatusmalleissakin.

Esimerkiksi havaitsin itse koodaavani hyvin tiiviisti, mikä haittaa luettavuutta. Huomaan toivovani, että osaisin koodata (tai oikeastaan tulisin koodanneeksi) kuten yllä olevassa esimerkissä tekijä 2, sillä siitä on helppo seurata miten koodi ja toiminnallisuus etenee. Peräkkäisiä komentoja on huomattavasti helpompi seurata kuin sisäkkäisiä komentoja ja niihin liittyviä sulkeita. Sellaisenaan tekijän 2 koodaustapa on kuin selkosuomea; sitä on niin helppo lukea, ettei tarvitse suuresti pohtia vaiheita tajutakseen, mitä koodissa tapahtuu. Tekijä 3:n koodi taas on kuin tekijöiden 1 ja 2 välimuoto.

Tästä on kuitenkin sen verran otettava opikseen, että niissä tapauksissa, joissa joudun jatkossa hallinnoimaan useiden tekijöiden koodikirjastoja tai vähintäänkin kontribuutioita kirjastoihin, lienee syytä ottaa käyttöön jonkinlainen vakiotyyli. Tyylien noudattaminen on itse asiassa muutenkin suositeltavaa, mutta tämä harjoitus osoitti itselleni, että niille todellakin on tarvetta. Käytännön vinkkejä tyyleistä on mm. StackOverflow:ssa ja StackExchanges:ssa.

Tyylejä on käytössä esimerkiksi Googlella ja Hadley Wickhamilla. Lisäksi paketti formatR mahdollistaa jo kirjoitetun koodin automaattisen muotoilun. Niinikään RStudio IDE:n Code-valikon funktio Reformat Code muotoilee koodin automaattisesti mm. välilyöntien ja rivinvaihtojen osalta tyylin mukaiseksi.