Luku 1.5: Kokoelmia ja viittauksia

../_images/person01.png

Johdanto: kokoelmat ja alkiot

Valtaosa tietokoneohjelmista käsittelee lukuisia "tiedonjyväsiä", joista muodostuu luetteloja tai muita kokonaisuuksia. Ohjelmasta riippuen voi olla tarpeen pitää kirjaa vaikkapa useista mittaustuloksista, käyttäjän kirjaamista hotellikokemuksista, käyttäjän kavereista tai kurssille ilmoittautuneista opiskelijoista.

Tällaiseen tarkoitukseen käytetään alkiokokoelmia tai lyhyemmin sanoen vain kokoelmia (collection). Yksi kokoelma voi sisältää esimerkiksi kaikki käyttäjän kaverit tai sarjan mittaustuloksia. Yksittäistä kokoelman sisältämää tietoa sanotaan alkioksi (element); alkio voi siis olla esimerkiksi yksi mittaustulos, kokemus, kaveri tai opiskelija.

Koska tarve kokoelmille on yleinen, ohjelmointikieliin on määritelty valmiita kokoelmatyyppejä, joita ohjelmoija voi hyödyntää. Scala-kieli tarjoaa runsaan valikoiman kokoelmatyyppejä, joista käytämme nyt aluksi yhtä.

Puskurin luominen

Eräs Scala-kieleen määritelty kokoelmatyyppi on puskuri (buffer). Puskuri on kokoelma, jonka alkioilla on määrätty järjestys. Puskuriin voi lisätä uusia alkioita, ja vanhoja alkioita voi poistaa tai korvata uusilla. Voit ajatella, että puskuri on eräänlainen tietokoneen muistiin tallennettu luettelo.

Luodaan kokeeksi puskuri, jossa on alkioina neljä merkkijonoa:

Buffer("eka", "toka", "kolmas", "vielä neljäskin")res0: scala.collection.mutable.Buffer[String] = ArrayBuffer(eka, toka, kolmas, vielä neljäskin)

Puskuria luodeessa kirjataan sulkeiden sisään parametreiksi puskuriin tallennettavat alkiot. Tässä alkiot ovat mielivaltaisesti valittuja merkkijonoja. Parametrilausekkeet erotellaan toisistaan pilkuilla.

REPL raportoi, että tuloksen tyyppi on Buffer[String]. Hakasulkeisiin merkitään Scalassa tyyppiparametri (type parameter), joka on lisätarkennus siitä, mistä tietotyypistä on kyse. Esimerkiksi tässä tyyppiparametri on String: ei ole luotu mitä tahansa puskuria vaan nimenomaan merkkijonoja sisältävä puskuri. Puheessa tietotyypin Buffer[String] voi lausua vaikkapa "String-puskuri", "merkkijonopuskuri" tai "buffer of string".

REPLiin tulostuu kuvaus luodusta puskurista alkioineen. Kuten näkyy, puskuri sisältää merkkijonot juuri siinä järjestyksessä, missä ne annettin luomiskäskylle parametreiksi.

REPL vielä mainitsee, että tarkemmin sanoen tuli luotua ArrayBuffer eli eräällä tietyllä tekniikalla (taulukoilla; array) toteutettu puskuri. Scalassa puskurit ovat oletusarvoisesti juuri ArrayBuffereita. Tästä ei toistaiseksi tarvitse välittää sen enempää.

Alla on kaksi lisäesimerkkiä: kaksialkioinen merkkijonopuskuri sekä viisialkioinen Double-lukuja sisältävä puskuri.

Buffer("ABC", "XYZ")res1: scala.collection.mutable.Buffer[String] = ArrayBuffer(ABC, XYZ)
Buffer(2.40, 3.11, 4.56, 10.29, 8.11)res2: scala.collection.mutable.Buffer[Double] = ArrayBuffer(2.4, 3.11, 4.56, 10.29, 8.11)

Huomaa puskurien erilaiset tyyppiparametrit, jotka määrittyvät automaattisesti alkioiden mukaan.

Sivuhuomio oppimateriaalista: REPL raportoi puskurin tyypin perinjuurisesti kirjaten mukaan pakkauksen nimen, esim. scala.collection.mutable.Buffer[Double]. Kurssimateriaalin tulevissa esimerkeissä on lukemisen helpottamiseksi yksinkertaistettu REPL-näkymää tuollaisista kohdista; esimerkiksi koko tuon rimpsun sijaan lukee vain Buffer[Double].

Puskurin indeksit ja niiden käyttö

Alla olevat esimerkit käyttävät seuraavaa esimerkkipuskuria ja siihen viittaavaa lukuja-nimistä muuttujaa.

val lukuja = Buffer(12, 2, 4, 7, 4, 4, 10, 3)lukuja: Buffer[Int] = ArrayBuffer(12, 2, 4, 7, 4, 4, 10, 3)

Muuttuja on tarpeen, jotta pääsemme kokoelmaan käsiksi sen luomiskäskyn jälkeen, kuten alla näet.

Puskurin alkion tutkiminen

Kukin puskurin alkio on tallennettu tietylle järjestysnumerolle eli indeksille (index). Moni puskureiden käyttötapa perustuu juuri indekseihin.

Tietylle indeksille tallennetun arvon voi katsoa tähän tapaan: ilmoitetaan, mistä puskurista katsotaan, ja perään sulkeissa haluttu indeksi.

lukuja(0)res3: Int = 12

Indeksit alkavat nollasta! Tässä siis katsottiin puskurin ensimmäinen alkio.

Vastaavaa ilmaisua voi käyttää lausekkeena vaikkapa muuttujaan sijoituksessa. Tässä puskurin neljäs alkio (eli indeksin 3 alkio) sijoitetaan muuttujaan neljasLuku:

val neljasLuku = lukuja(3)neljasLuku: Int = 7

Puskuritehtäviä

Seuraavien pikkukysymysten avulla voit harjoitella puskureihin liittyvien peruskäskyjen ymmärtämistä. Päättele annettujen koodinpätkien toiminta. Kokeile myös itse REPLissä ohjelmoiden.

Tutki seuraavia käskyjä. Mitä ne tekevät puskurilla?

val testi = Buffer(4, 10, 3, 10, 15, -2)
println(testi(4))

Kirjoita tähän tulostuskäskyn tulostama luku:

Tutki seuraavia käskyjä. Mitä ne tekevät puskurilla?

val testi = Buffer(4, 10, 3, 10, 15, -2)
val poimittu = testi(0)
val summa = poimittu + testi(3)

Kirjoita tähän summa-muuttujaan sijoitettu lukuarvo:

Tutki seuraavia käskyjä. Mitä ne tekevät puskurilla?

val testi = Buffer(4, 10, 3, 10, 15, -2)
val indeksi = 1
println(testi(indeksi) + testi(indeksi + 1))

Kirjoita tähän tulostuskäskyn tulostama luku:

Oletetaan, että on olemassa puskuri ja testiluvut-muuttuja, jotka on luotu näin:

val testiluvut = Buffer(10.5, 10.3, 9.8, 7.9, 10.2, 9.7)

Kirjoita tähän Scala-kielinen käsky, joka poimii puskurista viidennen alkion (eli sen alkion, joka esimerkissämme on 10.2) ja tulostaa sen. (Siis vain sen luvun omalle rivilleen eikä muuta.)

Puskurin sisältöä voi vaihtaa

Puskuriin sijoittaminen

Puskurin sisältämän alkion voi vaihtaa toiseen kirjoittamalla indeksin sulkeisiin ja perään yhtäsuuruusmerkin ja halutun uuden arvon. Tässä esimerkissä puskurin neljäs alkio vaihdetaan luvuksi 1.

lukuja(3) = 1

Tällä käskyllä itsellään ei ole kiinnostavaa arvoa. Käsky vain komentaa tietokonetta muuttamaan puskurin sisältöä eikä varsinaisesti tuota mitään tulosta. Niinpä REPLkin pysyy vaiti. Kuitenkin kun pyydämme raportin lukuja-muuttujan arvosta, näemme, että tietokoneen muistin sisältö on muuttunut neljännen alkion kohdalla:

lukujares4: Buffer[Int] = ArrayBuffer(12, 2, 4, 1, 4, 4, 10, 3)

Muutos vaikutti vain puskuriin. Se ei vaikuttanut muuttujaan, johon aiemmin tallensimme vanhan arvon:

neljasLukures5: Int = 7

Alkion lisääminen puskuriin

Operaattorilla += voi lisätä uuden alkion puskurin loppuun. Puskurin koko siis kasvaa.

lukuja += 11res6: Buffer[Int] = ArrayBuffer(12, 2, 4, 1, 4, 4, 10, 3, 11)

Puskurin käyttö muistuttaa kovasti muuttujien käyttöä, kuitenkin sillä lisäyksellä, että tarvitaan indeksejä kohdistamaan käskyt tiettyyn kohtaan puskuria. Voitkin ajatella, että puskuri on ikään kuin numeroitu luettelo var-muuttujia.

Siitä puheen ollen: Huomaa, että puskuria käytettiin äskeisessä esimerkissä val-muuttujan avulla. val ei estä muuttamasta puskurin sisältöä; se ei ole puskurin ominaisuus lainkaan. Kun lukuja on val, niin tuota muuttujaa ei voi myöhemmin asettaa viittaamaan johonkin toiseen puskuriin. Silti sen puskurin sisältö, johon lukuja viittaa, voi muuttua.

Tyhjä puskuri

Monesti on hyödyllistä luoda puskuri, jossa ei vielä ole lainkaan alkioita. Esimerkiksi GoodStuff-ohjelmassa ei aluksi ole lainkaan kirjattuja kokemuksia, mutta niitä voi vähitellen lisätä sinne.

Tyhjän puskurin luomiseen liittyy yksi uusi asia. Se ei nimittäin kunnolla onnistu ihan vain näin:

val toimiikohan = Buffer()toimiikohan: Buffer[Nothing] = ArrayBuffer()

Tällä käskyllä saa kylläkin luotua tyhjän puskurin, mutta tyhjäksi se jääkin. Tietokone ei tiedä, mitä aiot puskuriin tallentaa, ja Scala-työkalusto asettaa puskurin tietotyypiksi Buffer[Nothing]. Tällaisesta puskurista on harvoin iloa, koska sinne ei voi lisätä mitään.

Voit kuitenkin kertoa, minkä tyyppisen puskurin haluat luoda. Luodaan kokeeksi tyhjä puskuri, johon voi myöhemmin lisätä merkkijonoja. Tyyppiparametri, joka on tässä tapauksessa String, kirjoitetaan hakasulkeisiin aiemmista REPL-tulosteista jo tuttuun tapaan:

val sanat = Buffer[String]()sanat: Buffer[String] = ArrayBuffer()

Näin luotuun tyhjään puskuriin voi lisätä merkkijonoja:

sanat += "kissa"res7: Buffer[String] = ArrayBuffer(kissa)

Itse asiassa tyyppiparametrin saa kirjata puskurinluontikäskyihin silloinkin, kun se ei välttämätöntä olekaan. Tämäkin toimii:

val lukuja = Buffer[Int](2, -1, 10)lukuja: Buffer[Int] = ArrayBuffer(2, -1, 10)

[Int]-tyyppiparametrin voi tästä jättää poiskin. Alkiot määräytyvät lausekkeista 2, -1 ja 10, ja Scala-työkalut osaavat tästä päätellä, että halutaan luoda juuri Buffer[Int].

Lisää puskuritehtäviä

Seuraavien pikkukysymysten avulla voit harjoitella puskureihin liittyvien peruskäskyjen ymmärtämistä. Päättele annettujen koodinpätkien toiminta. Kokeile myös itse REPLissä ohjelmoiden.

Minkälaiseksi seuraavat alkionlisäyskäskyt muokkaavat puskurin?

val sanoja = Buffer[String]()
val sana = "alkioita"
sanoja += "me"
sanoja += "olem" + sanoja(0)
sanoja += sana
println(sanoja(0) + " " + sanoja(1) + " " + sanoja(2))

Kirjoita tähän tulostuskäskyn tulostama teksti:

Tutki seuraavia käskyjä. Mitä ne tekevät puskurille?

val testi = Buffer(4, 10, 3, 10, 15, -2)
var indeksi = 0
testi(indeksi) = 0
indeksi = indeksi + 1
testi(indeksi) = 0
indeksi = indeksi + 1
testi(indeksi) = 0
indeksi = indeksi + 1
testi(indeksi) = 0

(Jos kokeilet REPLissä, syötä käskyt yksitellen.)

Mikä on näiden käskyjen suorittamisen jälkeen puskurin alkioiden summa?

Oletetaan, että seuraavat koodirivit on juuri suoritettu.

val testiluvut = Buffer(10.5, 10.3, 9.8, 7.9, 10.2, 9.7)
val lukumaara = 6
val tyhja = Buffer[Double]()

Alla on muutama yritys poimia yksittäinen alkio. Mitkä kaikki niistä aiheuttavat virheilmoituksen (ja miksi)?

Oletetaan, että on luotu puskuri ja siihen viittaava muuttuja nimeltä testiluvut täsmälleen kuten edellisessä kohdassa. Kirjoita tähän Scala-kielinen käsky, joka lisää puskurin viimeiseksi (eli seitsemänneksi) alkioksi luvun 9.9.

Viittaukset

Luvussa 1.4 sanottiin, että muuttujalla on vain yksi arvo. Eikö meillä nyt kuitenkin ole yhdessä puskurimuuttujassa useita arvoja?

Tavallaan, mutta ei oikeasti.

Samalla kun kohta tarkastelemme tätä kysymystä, kohtaat viittauksen (reference) käsitteen. Tällä käsitteellä on myös laajempi merkitys ohjelmoinnin kannalta, kuten myöhemmin osoittautuu.

Huomasitko, että nimi kokeilu on muuttujan nimi, ei puskurin? (Puskurilla ei ole nimeä.) Tämä osoittautuu tärkeäksi aivan kohta.

Viittauksilla on konkreettinen merkitys ohjelmakoodin toiminnassa. Tarkastellaan toista animaatiota:

Viittaustehtävä

Käy seuraava koodi läpi ajatuksella ja vastaa kysymyksiin. Jos tehtävä tuntuu vaikealta, se voi helpottua, jos piirrät kuvan puskureista, muuttujista ja viittauksista. Voit myös syöttää koodin REPLiin. Jos jää epäselvää, kertaa puskuri- ja viittausasiaa yltä tai kysy neuvoa.

var henkilo = Buffer("Cai-Göran")
var toinen = Buffer("Cai-Göran")
var presidentti = toinen

Montako puskuria tämä koodi luo?

Montako johonkin puskuriin osoittavaa muuttujaa tämä koodi luo?

Suoritetaan lisäksi nämä rivit:

presidentti += "Alexander"
toinen += "Stubb"

Montako puskuria nyt on olemassa?

Montako alkiota on nyt siinä puskurissa, johon muuttuja presidentti viittaa?

Montako alkiota on nyt siinä puskurissa, johon muuttuja toinen viittaa?

Sitten suoritetaan tämäkin rivi:

toinen = Buffer("Suzanne", "Innes-Stubb")

Montako alkiota on nyt siinä puskurissa, johon muuttuja presidentti viittaa?

Montako alkiota on nyt siinä puskurissa, johon muuttuja toinen viittaa?

Ja lopuksi vielä:

toinen = henkilo
henkilo = Buffer("Milo & Nala")

Moniko muuttujista viittaa nyt sellaiseen puskuriin, jossa on nimet "Suzanne" ja "Innes-Stubb"?

Moniko muuttujista viittaa nyt sellaiseen puskuriin, jossa on vain nimi "Cai-Göran" eikä muuta?

Tämän luvun merkityksestä ja viittauksista

Puskureilla ja muilla kokoelmatyypeillä voi tehdä valtavasti erilaisia asioita, mistä tässä luvussa vain raapaistiin pintaa. Näet runsaasti esimerkkejä kokoelmista tulevissa luvuissa; kuten jo edellä vihjattiin, esimerkiksi GoodStuff-ohjelmassa kokemuskategorian sisältämät päiväkirjamerkinnät kootaan puskuriin. Kokoelmien alkioina tulemme käyttämään muunkinlaisia arvoja kuin vain yksittäisiä lukuja ja merkkijonoja.

Tässä vaiheessa oleellisinta on tietää, miten puskureita luodaan ja miten niiden yksittäisiä arvoja tutkitaan ja vaihdetaan. Sekä se, että puskureita käsitellään viittausten kautta.

Viittauksen käsitettä tarvitaan jatkossa toistuvasti. Viittausten avulla käsitellään ohjelmissa myös monia muita asioita kuin puskureita.

Viittausasian oppimista voi sekoittaa se, että ohjelmoinnista puhuttaessa usein "oikaistaan" hieman. Harvemmin sanotaan tai kirjoitetaan esimerkiksi, että "lukuja-muuttujassa on viittaus puskuriin" vaan epätarkemmin: "lukuja-muuttujassa on puskuri". Saatetaan myös puhua "lukuja-puskurista", vaikka varsinaisestihan muuttujassa on vain viittaus, ja lukuja on muuttujan eikä puskurin nimi. (Kuten näit, yhteen puskuriin voi viitata useilla erinimisillä muuttujilla.) Sanamuotojen yksinkertaistaminen on luonnollista ja kätevää, eikä sitä tarvitse välttää, mutta se täytyy ymmärtää.

Psst! Itse asiassa...

... jos tarkkoja ollaan, niin myös monien Scala-kielen perustietotyyppien arvot — esimerkiksi String-tyyppiset arvot — ovat "viittausten päässä" kuten puskuritkin. Tätä ei ole aiemmin mainittu, ja kurssimateriaalin animaatiotkaan eivät ole piirtäneet viittauksia tiettyjen perustyyppisten arvojen yhteyteen. Alla on kuitenkin esimerkkianimaatio, joka on "totuudenmukaisempi" (yksityiskohtaisempi) kuin aiemmat merkkijonoja käsitelleet animaatiot, mutta vähän epäselvempi:

Yleensä on kätevämpää ajatella yksinkertaistetusti niin, että esimerkiksi itse merkkijono "kissa" on tallennettuna muuttujaan (kuten aiemmissa animaatioissa), eikä niin, että muuttuja pitää sisällään viittauksen toiseen paikkaan, josta löytyvät merkkijonon merkit (kuten tuossa äskeisessä animaatiossa). Yksinkertaistettua tapaa käytetään paitsi aiemmissa myös tulevissa animaatioissa.

Tämä yksinkertaistus on esimerkiksi String-arvojen yhteydessä "turvallinen" eikä johda virheellisiin päättelyihin, koska — toisin kuin puskuri — merkkijonoarvo ei koskaan sisäisesti muutu. Merkkijonon voi kylläkin yhdistää toiseen merkkijonoon, jolloin syntyy uusi merkkijono kuten äskeisessä esimerkissämme. Lisää aiheesta mm. luvuissa 5.2 ja 11.2.

Lisähuomio muilla kielillä ohjelmoineille

Usein kysyttyä: onko näin muka Pythonissa, Javassa tms.?

Joillakin kurssilaisista on aiempaa kokemusta muista ohjelmointikielistä, kuten Pythonista. Ja osa heistä miettii tässä kohden kurssia seuraavaan tapaan:

Puskurien viittaus tuotti hieman hämmennystä, sillä vastaavaa ei ole minulle ainakaan Pythonissa tullut vastaan aikaisemmin.

Se, että monta muuttujaa voi osoittaa viittauksilla samaan puskuriin ei ole minulle ollenkaan intuitiivista. Jos ymmärsin oikein, kun tuollaista puskuria muokkaa, se vaikuttaa useaan muuttujaan. Se tuntuu hämmentävältä, varsinkin kun minulla on jo taustaa Pythonista, enkä ole siellä kohdannut vastaavaa.

Tämä aihe oli tosi kiinnostava. Tällainen ei ollut Javasta ollenkaan tuttua.

Tää viittausasia saa huomaamaan, miten Scala eroaa Pythonista.

Kuitenkin itse asiassa alkiokokoelmiin (ja muihinkin rakenteisiin) viittaaminen toimii Python-kielessä juuri samoin kuin Scalassakin. Tämän luvun esittelemä viittauksen käsite on merkityksellinen myös Python-ohjelmissa — ja Javassa ja monessa muussa kielessä.

Tässä esimerkki Pythonin REPListä:

>>> ekat_luvut = [123, 456, 789](Python-REPL ei kommentoi.)
>>> tokat_luvut = ekat_luvut(Python-REPL ei kommentoi.)
>>> ekat_luvut.append(1111)(Python-REPL ei kommentoi.)
>>> tokat_luvut.append(2222)(Python-REPL ei kommentoi.)
>>> ekat_luvut[123, 456, 789, 1111, 2222]
>>> tokat_luvut[123, 456, 789, 1111, 2222]

Koodi luo kokoelman, johon viittaa kaksi muuttujaa ja jossa on alkioina aluksi kolme kokonaislukua.

append-käsky lisää kokoelmaan alkion. Tehdäänpä tuo kumman tahansa muuttujan kautta...

... kokoelmia on tässä vain yksi, ja muutos näkyy kumman vain muuttujan arvoa tutkimalla.

Nuo Python-muuttujatkin siis säilyttävät viittauksia kokoelmiin samaan tapaan kuin Scala-muuttujat aiemmin tässä luvussa.

Maailmalla on valitettavasti paljonkin kursseja ja verkkotutoriaaleja, jotka yksinkertaistavat liiaksi, eivät selitä esimerkiksi tuota ja jättävät opiskelijoille virheellisiä vaikutelmia.

Yhteenvetoa

  • Ohjelmoija voi varastoida useita "tiedonjyväsiä" — alkioita — yhteen kokoelmaan.

  • Eräs kokoelmatyyppi on puskuri.

    • Puskurin alkioilla on järjestysnumerot eli indeksit.

    • Puskurin alkioita voi vaihtaa toisiin, ja puskuriin voi lisätä uusia alkioita.

    • Puskuri on siis tavallaan joukko yhteen liitettyjä var-muuttujia.

  • Puskureita käsitellään viittausten kautta. Muuttujaan tallennetaan viittaus, joka kertoo missä päin tietokoneen muistia itse puskuri on.

    • Usea muuttuja voi viitata samaan puskuriin.

    • Puskurin muuttaminen minkä tahansa siihen viittaavan muuttujan kautta "näkyy" kaikkien siihen viittaavien muuttujien kautta.

  • Viittauksia käytetään samaan tapaan myös muunlaisten tietojen kuin alkiokokoelmien käsittelyyn, kuten jatkossa nähdään.

  • Lukuun liittyviä termejä sanastosivulla: viittaus; (alkio)kokoelma, puskuri, alkio, indeksi; tyyppiparametri; pakkaus.

Päivitetty käsitekaavio:

Palaute

Huomaathan, että tämä on henkilökohtainen osio! Vaikka olisit tehnyt lukuun liittyvät tehtävät parin kanssa, täytä palautelomake itse.

Tekijät

Tämän oppimateriaalin kehitystyössä on käytetty apuna tuhansilta opiskelijoilta kerättyä palautetta. Kiitos!

Materiaalin luvut tehtävineen ja viikkokoosteineen on laatinut Juha Sorva.

Liitesivut (sanasto, Scala-kooste, usein kysytyt kysymykset jne.) on kirjoittanut Juha Sorva sikäli kuin sivulla ei ole toisin mainittu.

Tehtävien automaattisen arvioinnin ovat toteuttaneet: (aakkosjärjestyksessä) Riku Autio, Nikolas Drosdek, Kaisa Ek, Joonatan Honkamaa, Antti Immonen, Jaakko Kantojärvi, Onni Komulainen, Niklas Kröger, Kalle Laitinen, Teemu Lehtinen, Mikael Lenander, Ilona Ma, Jaakko Nakaza, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä, Joel Toppinen, Anna Valldeoriola Cardó ja Aleksi Vartiainen.

Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat on piirtänyt Christina Lassheikki.

Yksityiskohtaiset animaatiot Scala-ohjelmien suorituksen vaiheista suunnittelivat Juha Sorva ja Teemu Sirkiä. Teemu Sirkiä ja Riku Autio toteuttivat ne apunaan Teemun aiemmin rakentamat työkalut Jsvee ja Kelmu.

Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset laati Juha Sorva.

O1Library-ohjelmakirjaston ovat kehittäneet Aleksi Lukkarinen, Juha Sorva ja Jaakko Nakaza. Useat sen keskeisistä osista tukeutuvat Aleksin SMCL-kirjastoon.

Tapa, jolla käytämme O1Libraryn työkaluja (kuten Pic) yksinkertaiseen graafiseen ohjelmointiin, on saanut vaikutteita tekijöiden Flatt, Felleisen, Findler ja Krishnamurthi oppikirjasta How to Design Programs sekä Stephen Blochin oppikirjasta Picturing Programs.

Oppimisalusta A+ luotiin alun perin Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Nykyään tätä avoimen lähdekoodin projektia kehittää Tietotekniikan laitoksen opetusteknologiatiimi ja tarjoaa palveluna laitoksen IT-tuki; sitä ovat kehittäneet kymmenet Aallon opiskelijat ja muut.

A+ Courses -lisäosa, joka tukee A+:aa ja O1-kurssia IntelliJ-ohjelmointiympäristössä, on toinen avoin projekti. Sen suunnitteluun ja toteutukseen on osallistunut useita opiskelijoita yhteistyössä O1-kurssin opettajien kanssa.

Kurssin tämänhetkinen henkilökunta löytyy luvusta 1.1.

Joidenkin lukujen lopuissa on lukukohtaisia lisäyksiä tähän tekijäluetteloon.

a drop of ink
Palautusta lähetetään...