Kurssin viimeisimmän version löydät täältä: O1: 2024
Luku 1.3: Lukuja, tekstiä, ääniä ja kuvia
Tästä sivusta:
Pääkysymyksiä: Miten saan käskettyä tietokonetta? Voitaisiinko jo oppia vähän sitä Scala-kieltä? Miten Scalalla lasketaan luvuilla? Entä tekstin käyttäminen ohjelmissa? Mikä on kätevä tapa kokeilla yksittäisiä käskyjä?
Mitä käsitellään? REPL-ympäristössä työskenteleminen. Scala-kielen
alkeita: kokonais- ja liukulukuja, aritmeettiset operaattorit,
merkkijonot, tulostuskäsky println
. Yksinkertaista äänen ja kuvien
tuottamista. Työkalujen käyttöönotto import
-käskyllä.
Mitä tehdään? Luetaan samalla itse harjoitellen.
Suuntaa antava työläysarvio:? Reilu tunti.
Pistearvo: A13.
Oheisprojektit: GoodStuff, jonka otit jo käyttöön edellisessä luvussa. (Lisäksi tässä ja useimmissa tulevissa luvuissa tarvitaan yleisprojektia O1Library.)
Muuta: Eräissä tämän luvun kohdissa on kaiuttimista tai kuulokkeista hyötyä. Aivan pakolliset ne eivät ole.
Missä mennään?
Nyt kun edelliset luvut ovat antaneet kokonaiskuvaa, lähdetään kehittämään konkreettisia ohjelmointitaitoja pienin askelin.
Lyhyen tähtäimen suunnitelma olkoon:
- Nyt käsillä olevasta luvusta 1.3 aina lukuun 1.6 asti opit käyttämään valikoituja yleishyödyllisiä tekniikoita ja ymmärtämään niihin liittyviä käsitteitä. Ohjelmoit antamalla yksittäisiä käskyjä tietokoneelle. Nämä perustekniikat ovat aluksi "irrallisia osia", ja niistä tehdään vain pieniä erillisharjoituksia, mutta pian näet, että niitä käytetään lähes kaikkien sovellusohjelmien toteutuksessa.
- Luvuissa 1.7 ja 1.8 opit luomaan itse uusia komentoja olemassa olevia yhdistelemällä.
- Luvusta 2.1 alkaen pureudumme siihen, miten sovellusohjelma voidaan koostaa palasista. Aiemmin opitut tekniikat tulevat tässä tarpeeseen.
Yksi ynnä yksi
Käytännöllisesti katsoen kaikissa ohjelmissa tarvitaan ainakin jonkin verran perusaritmetiikkaa: yhteen-, vähennys-, kerto- ja/tai jakolaskua. Vaikkapa edellisessä luvussa kohdattu GoodStuff-ohjelma tarvitsee jakolaskua määrittääkseen kokemusten hinta–laatu-suhteen, ja Pong-ohjelma laskee pallolle ja mailoille jatkuvasti uusia koordinaatteja pelin käydessä.
Scala-kieli, kuten muutkin ohjelmointikielet, tarjoaa välineitä luvuilla laskemiseen. Esimerkiksi seuraavalla Scala-kielen käskyllä voit ohjeistaa tietokonetta laskemaan, paljonko on yksi plus yksi:
1 + 1
Yksinkertaista. Mutta mihin tällainen käsky kirjoitetaan?
Yksi vaihtoehto olisi laatia ja tallentaa kokonainen ohjelma, jossa hyödyntäisimme käskyä jotenkin. On kuitenkin myös toinen ja usein kätevämpi tapa kokeilla Scala-kielen käskyjä yksitellen:
REPL
Valitsemalla valikosta Window ‣ Show View ‣ Scala Interpreter
(tai joissain ympäristöissä Window ‣ Show View ‣ Other... ‣
Scala Interpreter) saat Eclipseen esiin näkymän, josta käytetään usein nimeä REPL.
Kun kurssin Eclipse-asetustiedosto on käytössä, REPL-näkymän voi avata myös
yksinkertaisemmin painamalla Alt+F11
. Kokeile!
REPLin käynnistyessä Eclipse kysyy, mihin projektiin REPL-sessio liitetään. Valitse nyt GoodStuff-projekti. Esiin tulee suunnilleen tällainen näky:
Tämä näkymä sopii Scala-käskyjen vuorovaikutteiseen kokeilemiseen. REPL on lyhenne sanoista read–evaluate–print loop, jotka kertovat perusidean:
- read: Voit kirjoittaa REPLiin Scala-kielisen pätkän, jonka REPL vastaanottaa eli "lukee".
- evaluate: REPL suorittaa koodinpätkäsi heti sen vastaanotettuaan; esimerkiksi aritmeettisen laskutoimituksen tapauksessa se määrittää laskun tuloksen.
- print: Evaluoinnin tulokset tulostuvat näytölle. (Suomalaiselle voi tulla nykyään "tulostamisesta" mieleen lähinnä printterit, mutta ohjelmoinnin yhteydessä myös tekstin kirjoittamisesta näytölle puhutaan tulostamisena.)
- loop: Edellä mainittuja vaiheita voi toistaa vuorovaikutteisesti.
Kirjoita REPLin alareunan kehotteeseen vaikkapa juuri teksti 1 + 1
ja paina
Ctrl+Enter
. Tulos näyttää suurin piirtein tältä:
1 + 1res0: Int = 2
Tämä on Scala-REPLin tapa kertoa, että laskutoimituksen tulos on kaksi.
res0
tulee sanasta result ja tarkoittaa "tulos numero 0" eli ensimmäinen tällä
käyttökerralla tulostettu tulos. Tässä yhteydessä, kuten ohjelmoinnissa usein
muutenkin, numerointi alkaa nollasta eikä ykkösestä.
Int
puolestaan on Scala-kieltä ja tarkoittaa kokonaislukua. Kokonaisluku on englanniksi
integer; Scalassa, kuten ohjelmoinnissa usein muutenkin, monet ilmaisut pohjautuvat
englannin kielen sanoihin.
Voit pyytää lisää laskutuloksia REPLiltä. Tulokset tulostuvat edellisten perään numeroituina:
2 + 5res1: Int = 7 1 - 5res2: Int = -4 2 * 10res3: Int = 20 15 / 3res4: Int = 5
Kokeile vapaasti itse peruslaskutoimituksia REPLissä.
Käytännön vinkki
Voit "kelata" aiemmin saman käyttösession aikana antamiasi
syötteitä REPLissä painamalla näppäimistön ylä- ja alanuolia
Ctrl
-näppäimen ollessa pohjassa. Kokeile! Tästä on hyvin
usein hyötyä. (Mac-ympäristöissä Ctrl+Cmd
ja nuolet.)
REPL vs. kokonainen ohjelma
Edellisessä luvussa tarkastelimme GoodStuff-ohjelmaa, joka oli tallennettu tiedostoihin. GoodStuff-ohjelman pystyi näin ollen ajamaan halutessaan. Ohjelmakoodia kirjoitettiin ja ajettiin erikseen.
Huomaa, että REPL on luonteeltaan erilainen: sinne kirjoitetut yksittäiset käskyt eivät jää pysyvämmin talteen. REPLissä ei myöskään ole vastaavaa eroa koodin kirjoittamishetken ja ajohetken välillä: kukin käsky tulee suoritetuksi välittömästi.
Lausekkeista
Vaikka esimerkkimme ovat olleet äärimmäisen yksinkertaisia, jo niissä esiintyi useita ohjelmoinnin peruskäsitteitä, joiden ymmärtäminen on erinomaisen tärkeää. Keskeisin näistä on lauseke (expression).
Muodollista määritelmää emme tässä lausekkeen käsitteelle tarvitse, vaan riittää
ajatella, että ohjelmoinnissa lausekkeella tarkoitetaan sellaista ohjelmointikielen
ilmaisua, jolla on jokin arvo (value). Esimerkeissämme on esiintynyt aritmeettisia
lausekkeita; niiden arvo on kyseisen laskutoimituksen tulos. Vaikkapa 1 + 1
on lauseke,
jonka arvo on kokonaisluku kaksi.
Tässä vielä yksi REPL-esimerkki ja sen kautta selitettynä muutama tärkeä termi. (Muistutus: Korosta vihreäpohjaiseen selitystekstiin liittyvä kohta siirtämällä hiiren kursori selitystekstin päälle.)
50 * 30res5: Int = 1500
50
arvo on luku viisikymmentä.Int
on eräs Scala-kieleen määritellyistä tietotyypeistä.Yksittäinen literaalikin on mahdollista syöttää REPLiin, kuten alla. Evaluointi on tällöin mahdollisimman yksinkertaista: literaalilausekkeen arvoksi saadaan juuri se syötetty arvo.
123res6: Int = 123
Vielä tässä luvussa — ja kasvavassa määrin tulevissa — kohtaamme myös muita
tietotyyppejä kuin Int
, muunlaisia lausekkeita kuin literaaleja ja aritmeettisia
lausekkeita sekä muita operaattoreita kuin aritmeettisia.
Välilyönneistä
Välilyönnit operaattorien ympärillä eivät ole pakolliset eivätkä vaikuta Scala-koodin toimintaan. Ne kuitenkin selkiyttävät koodia (varsinkin kun sitä rupeaa olemaan enemmän), ja niiden käyttö kuuluu hyvään ohjelmointityyliin.
Jakolaskua
Vaikka moni asia Scala-aritmetiikassa onkin matematiikasta tuttu, eräs seikka voi yllättää. Kokeile erilaisia jakolaskuja, vaikkapa näin:
15 / 5res7: Int = 3 15 / 7res8: Int = 2 19 / 5res9: Int = 3
Mitä jos haluan pyöristää "oikein"?
Scalan tapa käsitellä kokonaislukuja on ohjelmointikielissä yleinen. On ehkä yllättävänkin usein kätevää, että se toimii juuri noin.
Muunlaisiin pyöristystarpeisiin löytyy kyllä ratkaisuja, joista lisää myöhemmin (esim. luvussa 5.2).
Suoritusjärjestys ja sulut
Operaattoreilla on suoritusjärjestys (operator precedence). Se on aritmeettisten laskutoimitusten osalta hyvin tuttu:
1 + 2 * 3res10: Int = 7 5 * 4 + 3 * 2 + 1res11: Int = 27
Ohjelmoija voi vaikuttaa suoritusjärjestykseen käyttämällä sulkuja luontevalla tavalla:
(1 + 2) * 3res12: Int = 9 5 * ((4 + 3) * 2 + 1)res13: Int = 75
Sulkuvaroitus
Olet saattanut koulumatematiikassa tottua käyttämään erilaisia suljetyyppejä, kun sulkeet ovat sisäkkäin. Olet esimerkiksi ehkä käyttänyt kaarisulkeita hakasulkeiden sisällä, kuitenkin niin, että molemmilla suljetyypeillä on sama merkitys laskujärjestyksen määräämisessä.
Scala-ohjelmakoodissa näin ei voi tehdä.
Laskettavien ryhmittely on yksi niistä asioista, johon kaarisulkeet Scala-ohjelmassa sopivat; esimerkiksi haka- ja aaltosulkeet eivät tähän kelpaa. Muunmuotoisilla sulkeilla on ihan toisia käyttötarkoituksia, joista lisää myöhemmin kurssilla.
Scala on tässä suhteessa tyypillinen ohjelmointikieli. Ohjelmoinnissa on tavanomaista, että erilaisilla sulkeilla on erilaisia merkityksiä.
Desimaaliluvut
Entäs desimaaliluvut sitten? Ne toimivat pitkälti niin kuin sopii odottaa. Huomaa käyttää desimaalierottimena epäsuomalaisittain pistettä:
4.5res14: Double = 4.5 2.12 * 3.2205res15: Double = 6.82746 4.0res16: Double = 4.0
Mikä ihmeen Double
?
Sana Double
on käytössä useassa eri ohjelmointikielessä.
Scalaankin se on napattu juuri siksi, että se on muista
kielistä Scalaan siirtyville ohjelmoijille tuttu.
Tietotyypin nimi on lyhennetty englannin ilmaisusta double
precision floating-point number eli "kaksinkertaisen tarkkuuden
liukuluku". Tämä on kuvaus Double
-tietotyypin toteutustekniikasta:
"desimaaliluvut" kuvataan tietokoneelle usein ns. liukulukuina,
Niistä kerrotaan hieman lisää tämän materiaalin luvussa 5.4.
Kuten yltä näkyy, "desimaalilukuja" kutsutaan Scalassa Double
iksi. Tämän kummallisen
nimen syyt ovat historialliset.
Double
-arvoilla myös jakolasku onnistuu tutumpaan tapaan. Kun lasketaan kahdella
Double
-tyyppisellä arvolla, on myös tulos Double
-tietotyyppiä.
999.0 / 1000.0res17: Double = 0.999
Lukutyyppien yhdistely
Double
- ja Int
-tyyppisiä arvoja voi yhdistellä.
29 / 10res18: Int = 2 29.0 / 10res19: Double = 2.9 29 / 10.0res20: Double = 2.9 30.0 / 10.0res21: Double = 3.0
Kun laskettavina on yksi kokonaisluku ja yksi desimaaliluku, tuloksena saadaan desimaaliluku. Näin siinäkin tapauksessa, että jakolasku menee tasan.
Entä jos tekee monimutkaisemman erityyppisiä arvoja sisältävän lausekkeen? Vaikkapa
(10 / 6) * (2.0 + 3) / 4
. Tällöin operaattorien suoritusjärjestys määrää, miten
kukin osalauseke evaluoidaan ja minkä tyyppinen arvo kussakin vaiheessa saadaan.
Osaatko päätellä, mikä mainitun lausekkeen arvo on?
Tarkista päättelysi paikkansa pitävyys tutustumalla tämän lausekkeen evaluointiin seuraavan vuorovaikutteisen animaation avulla:
Tietokoneen muistista ja kurssimateriaalin animaatioista
Tietokoneen muisti on bittivarasto, josta ohjelmat voivat varata tilaa erilaisiin tarkoituksiin. Kullakin muistin kohdalla on oma osoitteensa, eräänlainen järjestysnumero, joka identifioi kyseisen muistipaikan.
Muistin käytön täsmälliset yksityiskohdat "bittitasolla" eivät ole tällä kurssilla keskeisiä. Kuitenkin ohjelman muistinkäytön pääpiirteittäisestä osaamisesta on aloittelevallekin ohjelmoijalle kosolti hyötyä. Siksi käytämme äskeisen kaltaisia animoituja diagrammeja, jotka kuvaavat ohjelman suorituksen vaikutuksia muistin sisältöön. Diagrammin "alueet" vastaavat tietokoneen muistista tiettyihin tarkoituksiin varattuja osia.
Äskeinen ensimmäinen animaatioesimerkki on erittäin yksinkertainen, ja sen esittämä lauseke lienee hyvin ymmärrettävissä ilman animaatiotakin. Kuitenkin on hyvä jo tässä vaiheessa totutella tähän esitystapaan, sillä vastaavia animaatioita käytetään tässä materiaalissa jatkossa myös mutkikkaampien ilmiöiden havainnollistamiseen.
Merkkijonot
Lukujen lisäksi ohjelmissa tarvitaan toistuvasti tekstiä. Kokeillaan:
"Moi"res22: String = Moi "Täällähän kaikuu!"res23: String = Täällähän kaikuu!
Kuten REPL kertoo, tekstinpätkiä eli virallisemmin merkkijonoja (string eli
string of characters) kuvataan Scalassa tietotyypillä String
.
Merkkijonoliteraalilla tarkoitetaan ohjelmakoodiin sellaisenaan kirjoitettua
merkkijonoa (vrt. Int
- ja Double
-tyyppiset literaalit ylempänä). Se kirjoitetaan
lainausmerkkeihin.
(Yhden merkkijonoliteraalin kohtasitkin jo aiemmin, kun korjasit kirjoitusvirheen GoodStuff-ohjelmasta edellisessä luvussa.)
Jos unohdat lainausmerkit, saat mitä luultavimmin virheilmoituksen, koska silloin REPL yrittää tulkita kirjoittamaasi tekstiä Scala-käskyinä:
Moi<console>:8: error: not found: value Moi Moi ^
Tulostuskäsky
Näyttämällä kunkin evaluoidun lausekkeen arvon ja tyypin REPL on tarjonnut meille kätevän
palvelun. Mutta mitä jos haluaisimme tulostuvan jotain muuta kuin tuon tutun litanian
resX: Tyyppi = arvo
?
Voimme räätälöidä halutunlaisen tulosteen Scala-kielisellä tulostuskäskyllä.
Scalassa tulostaminen onnistuu println
-nimisellä käskyllä:
println("Terve!")Terve! println(123)123 println(-5.2)-5.2
Nämä käskyt ovat melko itseselitteisiä, mutta niissäkin kohtaamme tärkeitä Scala-kielen piirteitä, jotka ansaitsevat erillisen huomion.
println
tulee
englannin sanoista print line.println
-käskylle annetaan yksi parametrilauseke,
joka määrää, mitä tulostetaan.Parametriksi voi kirjoittaa myös literaalia monimutkaisemman lausekkeen. Seuraava
animaatio kuvaa tulostuskäskyn println("Ohjelmointi" + (100 - 99))
suorituksen vaiheet.
Suoritus eteni siis "sulkujen sisältä ulos". Jatkossa nähdään, miten tämä nyrkkisääntö pätee muissakin yhteyksissä: sulkujen sisään kirjoitetut parametrilausekkeet evaluoidaan ensin, ja näin saadut parametriarvot käytetään sitten käskyn suorituksessa.
Parametri vai argumentti?
Muissa ohjelmointia käsittelevissä teksteissä usein käytetään termiä argumentti (argument) tarkoittamaan joko sitä, mitä olemme kutsuneet parametrilausekkeeksi, tai sitä, mitä olemme kutsuneet parametriarvoksi, tai molempia.
Lisää merkkijonoista nuoteilla
Merkkijonoilla eli String
-tyyppisillä arvoilla kuvataan usein tekstiä, mutta voi niillä
kuvata muutakin. Vaikkapa musiikkia. Alla on tulostuskäsky, joka tulostaa Ukko Nooa
-hitin ensimmäiset tahdit. Nuotit on tässä esitetty yksinkertaisesti kirjaimina, jotka
vastaavat myös oheisen kuvan pianon koskettimia.
println("cccedddf")cccedddf
Sepä ei ollut kovin jännittävää. Nuotit olisi antoisampaa soittaa kuin tulostaa.
Otetaan avuksi toinen ilmaisu. Toisin kuin println
, joka kuuluu Scala-kielen
perustyökaluihin, nyt kokeiltava o1.play
on laadittu tämän kurssin tarpeisiin. Sen
avulla saamme vähän eloa muun muassa näihin tämän luvun pieniin merkkijonoesimerkkeihin.
(Soittokäsky on määritelty projektissa O1Library. Jos et noutanut projektia työtilaasi
edellisessä luvussa 1.2, niin tee se nyt ja käynnistä REPL uudelleen.)
Kokeile seuraavaa.
o1.play("cccedddf")
Tämä käsky ei tuota näkyvää tulostetta, vaan soittaa parametriksi saamaansa String
-arvoon
merkityt nuotit virtuaalisella pianolla. Olihan sinulla äänet päällä koneessasi?
Kokeile antaa myös muita merkkijonoja o1.play
-käskyn parametriksi. Voit kokeilla
esimerkiksi välilyöntejä, jotka o1.play
tulkitsee tauoiksi:
o1.play("cccdeee f ffe e")
Ja viivoja, jotka o1.play
tulkitsee pidempikestoisiksi nuoteiksi:
o1.play("cccdeee-f-ffe-e")
Ääni tällä kurssilla
Kurssilla on muutamia kohtia, joissa käytetään ääntä, kuten äsken. Tämä tietysti toimii vain, jos sinulla on äänentoistolaitteisto käytettävissäsi.
Jos opiskelet ihmisten keskellä, esimerkiksi Aallon tietokoneluokissa, varaa omat kuulokkeet mukaan.
Jos koira söi kuulokkeesi, niin voit käyttää println
-käskyä
o1.play
-käskyjen sijaan. Se kuiventaa näitä kohtia muttei
vaaranna kurssisuoritusta.
Emme edellytä kurssin opiskelijoilta musiikillista osaamista.
Merkkijonojen yhdisteleminen
Merkkijonoja voi yhdistellä toisiinsa plus-operaattorilla. Tällä operaattorilla, joka tarkoitti lukujen yhteydessä yhteenlaskua, on merkkijonojen yhteydessä toisenlainen merkitys:
"omena" + "kynä"res24: String = omenakynä "REPL with" + "out" + " a cause"res25: String = REPL without a cause
Huomaa, että lainausmerkkien sisällä välilyönneillä on väliä.
Sama operaattori toki toimii myös parametrilausekkeen osana:
println("Ukko Nooa, Ukko Nooa" + " oli kunnon mies.")Ukko Nooa, Ukko Nooa oli kunnon mies. o1.play("cccedddf" + "eeddc---")
Merkkijonon "kertominen"
Toinen tapa vaihtaa oktaavia
Mainitun väkäsmerkinnän lisäksi o1.play
mahdollistaa oktaavien
kirjaamisen numerolla yksittäisten äänien kohdalle. Käytössä on numerot
0–9, joista oletusoktaavi on numero 5. Nämä siis tekevät saman asian:
o1.play(">cd<<e")o1.play("c6d6e4")
Tämä ei ole varsinaisesti tärkeää, koska kyse on vain tästä kurssille laaditusta yksinkertaisesta soittopelistä, mutta tieto voi helpottaa omia äänileikkejä, jos haluat niitä tehdä.
Kuvia ja pakkauksia
GoodStuff-ohjelmassa näkyy irvinaaman kuva suosikkikokemuksen kohdalla. Pong-pelissä mailat näkyvät suorakaiteen kuvina ja pallo ympyrän kuvana. Ohjelmat käsittelevät kuvia.
Kuvia näkyviin
Ladataan kuva verkko-osoitteesta Scala-kielisellä käskyllä. Kokeile:
o1.Pic("https://en.wikipedia.org/static/images/project-logos/enwiki.png")res26: o1.gui.Pic = https://en.wikipedia.org/static/images/project-logos/enwiki.png
Pic
on kuvatietotyypin nimi ja
kirjoitetaan isolla samoin kuin vaikkapa String
tai Int
.o1
kertoo siitä, että nytkin käytämme tämän kurssin
tarpeisiin laadittua aputyökalustoa. Ei silti huolta: näitä
työkaluja käyttäessäsikin opit kyllä ohjelmoinnin yleisempiä
periaatteita, jotka toimivat kurssin ulkopuolellakin.Pic
-tyyppinen arvo, joka sisältää netistä
ladatun kuvan.Noin saimme erään kuvan ladattua tietokoneesi muistiin, mutta näkyviin se ei tullut. Yksi
helppo tapa laittaa kuva näkyviin on käsky o1.show
, joka toimii samankaltaisesti kuin
o1.play
äänille. Siitä on esimerkki alla. Muihinkin tapoihin törmäämme vielä.
o1.show(o1.Pic("https://en.wikipedia.org/static/images/project-logos/enwiki.png"))
Kuva piirtyy näkyviin erilliseen pikkuikkunaan näytön vasemman yläkulman tuntumaan.
Klikkaa kuvaa tai paina Esc
sulkeaksesi ikkunan.
Äskeisessä esimerkissä kuva ladattiin netistä. Kuvan voi ladata myös tiedostosta, joka on tallessa omalla koneella. Vaikkapa näin:
o1.show(o1.Pic("d:/jokin/kansio/koneellani/kuva.png"))
Toisaalta koko tiedostopolku ei välttämättä ole tarpeellinen. Jos tiedosto on sellaisen
projektin sisällä, joka on valittuna käsiteltäväksi, niin yksinkertaisempikin riittää.
Olettaen, että valitsit REPLin käynnistäessäsi GoodStuff-projektin, tämäkin toimii, koska
face.png
löytyy tuon projektin sisältä:
o1.show(o1.Pic("face.png"))
o1
ja muut pakkaukset
Osa kurssilla käyttämistämme välineistä on siis työkalupakkauksessa nimeltä o1
. Kun
näitä työkaluja käytetään, pitää Scala-ohjelmassa mainita, että käytetään juuri tuon
pakkauksen sisältöä.
Työkalujen jaottelu eri pakkauksiin on tarpeen muun muassa siksi, että isompiin ohjelmiin
voi helpostikin tulla keskenään samannimisiä osia esimerkiksi eri ohjelmoijien laatimina.
Esimerkiksi nimet play
tai show
voivat olla toisissa yhteyksissä muussa käytössä kuin
ne ovat o1
-kirjastossa.
Ongelma ratkeaa sijoittamalla keskenään samannimiset osat eri pakkauksiin, jolloin pakkauksen nimellä voi ilmaista, minkä pakkauksen sisällöstä on kyse. Haittapuolena on, että pakkauksen nimen toistuva kirjoittaminen on ärsyttävää ja voi vaikeuttaa koodin lukemista.
Haitta pienenee import
-käskyllä. Tutustutaan siihen ja palataan sitten kuvien pariin.
Kätevämpää työkalujen käyttöä: import
-käsky
Jos aiomme käyttää jotakin o1
-työkalupakin käskyä — vaikkapa o1.show
— toistuvasti,
voimme ilmoittaa ensin näin:
import o1.showimport o1.show
Tämä import
-käsky tarkoittaa suunnilleen: "Aina, kun jäljempänä sanotaan show
,
niin se tarkoittaa juuri o1
-nimisen työkalupakkauksen määrittelemää show
-käskyä."
import
-käsky ei ole lauseke eikä sillä ole varsinaista arvoa. REPL kuittaa käskyn
toistamalla sen.
import
-käskyn annettuamme voimme näyttää kuvia aavistuksen kätevämmin:
show(o1.Pic("https://en.wikipedia.org/static/images/project-logos/enwiki.png"))show(o1.Pic("face.png"))
show
-sanan edessä ei enää tarvita o1
-alkuliitettä.Pic
-sanan yhteydessä vielä tarvitaan. Jos olisimme
antaneet aluksi myös käskyn import o1.Pic
, niin nämäkin
voisi jättää pois.Voisimme kirjoittaa import
-käskyn kullekin tarvitsemallemme o1
-pakkauksen työkalulle
erikseen. Mutta jatkossa usein otamme koko o1
-pakkauksen työkaluston kätevästi käyttöön
kerralla:
import o1._import o1._
_
on Scalassa useita käyttöyhteydestä riippuvia
merkityksiä, mutta yleisesti ottaen se tarkoittaa suunnilleen
"mikä vain" tai "kaikki".Nyt voimme käyttää mitä vain pakkauksen o1
työkaluista lyhyin merkinnöin:
play("cdefg")show(Pic("https://en.wikipedia.org/static/images/project-logos/enwiki.png"))show(Pic("face.png"))
Vielä emme ole monta näppäimenpainallusta import
illa säästäneet, mutta se kyllä maksaa
itsensä takaisin, kun kohta käytämme runsaampaa työkaluvalikoimaa o1
-pakkauksesta.
Myöhemmissä luvuissa hyödynnämme import
-käskyä myös muiden kuin o1
-pakkauksen käyttöön.
Värillisiä kuvioita
Jo nähty Pong-peli on esimerkki ohjelmasta, jonka grafiikka perustuu tuttuihin geometrisiin kuvioihin. Työkalupakkimme tarjoaa välineitä tällaisten eriväristen kuvioiden määrittelemiseen helposti. Kokeillaan.
Aloitetaan väreistä. Kunhan käsky import o1._
on annettu, tyypillisiin perusväreihin voi
viitata yksinkertaisesti niiden englanninkielisillä nimillä:
Lisää värejä
Koko luettelo tarjolla olevista värinimistä löytyy O1Libraryn dokumentaatiosta.
Blueres27: o1.gui.Color = Blue Greenres28: o1.gui.Color = Green DarkGreenres29: o1.gui.Color = DarkGreen
Color
.Luodaan circle
-käskyllä sininen ympyrä:
circle(200, Blue)res30: o1.gui.Pic = circle-shape
Pic
.show
-käskylle voi välittää minkä vain Pic
-tyyppisen parametrin. Verkosta tai levyltä
ladatun kuvan sijaan kelpaa myös itse määritelty ympyrän kuva:
show(circle(200, Blue))
Kokeile myös muita värejä ja muotoja. Tässä esimerkiksi suorakaide, sen ystävä sekä tasakylkinen kolmio:
show(rectangle(200, 500, Green))show(rectangle(500, 200, Red))show(triangle(150, 200, PhthaloBlue))
REPListä vielä
Ehkä olet miettinyt, onko REPL vain opiskelijoiden tai aloittelijoiden työkalu osaavien ammattilaisten sijaan.
Ei ole.
Monet ammattilaisetkin käyttävät REPLiä erilaisiin kokeilu- ja testaustarkoituksiin. Sitä paitsi myös osaavat ammattilaiset ovat opiskelijoita perehtyessään uusiin ohjelmointikieliin ja muiden laatimiin ohjelmakomponentteihin.
REPLin kautta voi käyttää monimutkaisiakin ohjelmakomponentteja, myös sellaisia, jotka ovat osina tietyissä sovellusohjelmissa. Vaikka emme ole vielä paljon koodausta harjoitelleetkaan, voit jo helposti REPLin kautta koekäyttää valmiin ohjelman osaa. Kokeile seuraavaa, jos haluat.
GoodStuff-käyttöliittymä REPListä käsin
Edellisessä luvussa käynnistettiin GoodStuff-projektin käyttöliittymä Eclipsen valikon avulla. Voit myös avata GoodStuff-käyttöliittymäikkunan antamalla seuraavat Scala-komennot REPLissä:
import o1.goodstuff.gui.CategoryDisplayWindow
import o1.goodstuff.Category
val testWindow = new CategoryDisplayWindow(new Category("Hotel", "night"))
testWindow.visible = true
Lyhyesti selitettynä: näin määrätään tietokone luomaan uusi
kokemuskategoria hotelleille (jos haluat, voit korvata lainausmerkeissä
olevat sanat muillakin) sekä uusi käyttöliittymäikkuna, jossa tuon
kategorian kokemuksia voi kirjata. Apuna käytetään pakkauksista
o1.goodstuff
ja o1.goodstuff.gui
löytyviä määrittelyjä.
Kaikkien äskeisen esimerkin käskyjen täsmällisempi merkitys selviää kurssin parin ensimmäisen kierroksen aikana.
Yhteenvetoa
- Ohjelmoija voi muodostaa aritmeettisia lausekkeita yhdistelemällä
kokonaislukuja (
Int
), desimaalilukuja (Double
) ja aritmeettisia operaattoreita. - Lauseke on ilmaisu, jolle voidaan määrittää arvo. Lausekkeen arvon määrittämistä sanotaan evaluoimiseksi.
- Merkkijonotyyppiä
String
käyttäen voi muodostaa lausekkeita, joiden arvoina on tekstinpätkiä. println
-käskyllä voi itse määrittää tarkasti, mitä haluaa tulostettavan.import
-käsky on kätevä, kun halutaan käyttää jonkin pakkauksen sisältämää työkalustoa, esimerkiksi tämän kurssino1
-pakkausta.- Kurssin työkalupakki sisältää välineitä mm. merkkijonoina kuvatun
äänen soittamiseen (
play
) ja kuvien käsittelyyn (Pic
,show
,circle
,Red
jne.). - REPL on kätevä työkalu muun muassa uusien ohjelmointitekniikoiden kokeiluun ja opiskeluun.
- Kurssin ensimmäisten viikkojen aikana selviää, miten tässä luvussa käsiteltyjä perustietotyyppejä, lausekkeita ja operaatioita voi hyödyntää GoodStuffin tai muun sovelluksen toteutuksen osana.
- Lukuun liittyviä termejä sanastosivulla: REPL; lauseke, arvo, evaluoida, literaali; operaattori; tietotyyppi; merkkijono; tulostaa; parametrilauseke, parametriarvo.
Alla on kaavio, joka pyrkii selventämään eräitä tärkeimmistä kohdatuista käsitteistä ja eräitä näiden käsitteiden tärkeimmistä suhteista. Tulemme täydentämään tätä kaaviota kurssin parin ensimmäisen viikon aikana.
Opettele tämän luvun käsitteet!
Useat tässä luvussa ensimmäistä kertaa kohdatut termit ja käsitteet ovat erittäin keskeisiä. Eivät itseisarvoisesti vaan siksi, että pystyt niiden avulla jäsentämään ohjelmointiin liittyviä asioita. Termistön hallinta auttaa sekä tämän materiaalin lukemisessa että toisten ohjelmoijien (esim. assarien ja työparisi) kanssa viestimisessä. Kiinnitä erityistä huomiota yllä olevan kaavion käsitteisiin.
Silti vielä tärkeämpää on...
... että saat tuntumaa ohjelmoinnin käytäntöön. REPL-ympäristö sopii tähän hyvin. Älä epäröi kokeilla REPLissä omin päin erilaisia juttuja, myös muita kuin tässä materiaalissa ehdotettuja.
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!
Kierrokset 1–13 ja niihin liittyvät tehtävät ja viikkokoosteet on laatinut Juha Sorva.
Kierrokset 14–20 on laatinut Otto Seppälä. Ne eivät ole julki syksyllä, mutta julkaistaan ennen kuin määräajat lähestyvät.
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, Joonatan Honkamaa, Jaakko Kantojärvi, Niklas Kröger, Teemu Lehtinen, Strasdosky Otewa, Timi Seppälä, Teemu Sirkiä ja Aleksi Vartiainen.
Lukujen alkuja koristavat kuvat ja muut vastaavat kuvituskuvat on piirtänyt Christina Lassheikki.
Yksityiskohtaiset animaatiot Scala-ohjelmien suorituksen vaiheista ovat suunnitelleet Juha Sorva ja Teemu Sirkiä. Niiden teknisen toteutuksen ovat tehneet Teemu Sirkiä ja Riku Autio käyttäen Teemun toteuttamia Jsvee- ja Kelmu-työkaluja.
Muut diagrammit ja materiaaliin upotetut vuorovaikutteiset esitykset on laatinut Juha Sorva.
O1Library-ohjelmakirjaston ovat kehittäneet Aleksi Lukkarinen ja Juha Sorva. Useat sen keskeisistä osista tukeutuvat Aleksin SMCL-kirjastoon.
Opetustapa, jossa 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+ on luotu Aallon LeTech-tutkimusryhmässä pitkälti opiskelijavoimin. Pääkehittäjänä toimii tällä hetkellä Jaakko Kantojärvi, jonka lisäksi järjestelmää kehittävät useat tietotekniikan ja informaatioverkostojen opiskelijat.
Kurssin tämänhetkinen henkilökunta on kerrottu luvussa 1.1.
Joidenkin lukujen lopuissa on lukukohtaisia lisäyksiä tähän tekijäluetteloon.
*
.