Muutettu viimeksi 23.2.2016 / Sivu luotu 9.3.2010 / [oppikirjan esimerkit] / [Scala]
Sivun sisältöä:
$ scala Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_72). Type in expressions to have them evaluated. Type :help for more information. scala> 1 + 2 res0: Int = 3 scala> res0 * 3 res1: Int = 9Tulkki siis laittaa nuo arvot itse nimeämiinsä systeemivakioihin res0, res1, res2, ...
scala> println("Hello, world!") Hello, world!Metodikutsut ja muut algoritminpalaset suoritetaan sellaisinaan.
scala> val msg = "Hello, world!" msg: java.lang.String = Hello, world! scala> val msg2: java.lang.String = "Hello again, world!" msg2: java.lang.String = Hello again, world!Toki tyypin saa määritelläkin kuten yllä: val msg2: java.lang.String = ...
scala> println(msg) Hello, world!Nimetyt vakiot siis ovat vakioita:
scala> msg = "Goodbye cruel world!" <console>:5: error: reassignment to val msg = "Goodbye cruel world!" ^Muuttujat määritellään var-ilmauksella:
scala> var muu = 666 muu: Int = 666 scala> println(muu) 666 scala> muu = 14 muu: Int = 14 scala> println(muu) 14Rakenteen jäädessä kesken tulkki antaa uuden rivin:
scala> val multiLine = | "This is the next line." multiLine: java.lang.String = This is the next line.Tyypillisesti näin käy funktion määrittelyssä:
scala> def max(x: Int, y: Int): Int = { | if (x > y) x | else y | } max: (x: Int, y: Int)IntJos funktion runko muodostuu yhdestä lauseesta, aaltosulkeet saa jättää pois:
scala> def max2(x: Int, y: Int) = if (x > y) x else y max2: (x: Int, y: Int)Int scala> max(3, 5) res5: Int = 5Näiden kahden funktion tyyppi siis on (Int,Int)—>Int.
Huom: Funktion arvon tyyppi ilmaistaan otsikossa, ellei kääntäjä osaa sitä päätellä. Ja palautettavan arvon ilmaisemiseen riittää algoritmin suorituspolun viimeinen ilmaus, mitään returneja ei tarvita. Toisaalta return-lause on myös käytettävissä, jos halutaan algoritmiin useita erillisiä lopetuskohtia. Tätä ei kuitenkaan Scala-maailmassa pidetä tyylikkäänä eikä suotavana!
Huom: Koska "kaikella on arvo" ja arvo on lause-/lausekejonon viimeinen arvo, seuraavanlainen sivuvaikutuksilla pelleilykin on mahdollista:
scala> val x = {println("böö"); 78} böö x: Int = 78
Huom: Funktion muodollisten parametrien tyyppi annetaan aina!
"Void-metodin" tyyppi on Unit:
scala> def greet() = println("Hello, world!") greet: ()UnitParametrittoman funktion kutsussa tyhjä parametrilista ei ole tarpeen:
scala> greet Hello, world! scala> greet() Hello, world! scala> sys exit // tai toki myös sys.exit tai sys.exit() $
Huom: Ilman yhtäsuuruusmerkkiä funktion tyyppi on Unit:
scala> def f(a:Int, b:Int) {a-b} f: (a: Int, b: Int)Unit scala> def f(a:Int, b:Int) = {a-b} f: (a: Int, b: Int)Int
Huom: Kutsussa voi nimetä, mitkä muodolliset parametrit saavat arvokseen todelliset parametrit:
scala> def f(a:Int, b:Int) = {a-b} f: (a: Int, b: Int)Int scala> f(1,2) res3: Int = -1 scala> f(b=1, a=2) res4: Int = 1
// Say hello to the first argument println("Hello, "+ args(0) +"!")Huom: Taulukon indeksit Scalassa kirjoitetaan kaarisulkeisiin!
Tuttua ja turvallista:
var i = 0 while (i < args.length) { println(args(i)) i += 1 }Ja iffitkin peliin:
var i = 0 while (i < args.length) { if (i != 0) print(" ") print(args(i)) i += 1 } println()Huom: Scalassa ei ole operaatioita ++i ja i++. Ja hyvä niin! Ehtojen ympärillä on Javan tapaan oltava kaarisulkeet.
Skaalautuvalla Scalalla tuommoinen perinneohjelmointi toki onnistuu, ohjelmointi, jossa peräkkäin suoritettavin operaatioin muutetaan ja tutkitaan muuttujien arvoja eli ohjelman tilaa (state).
Mutta Scalalla hommia voi hoidella korkeammallakin abstraktiotasolla. Komentoriviparametrit voi tulostaa vaikka näin:
args.foreach(arg => println(arg))Näyttää siistiltä, mutta mitä tässä oikeastaan sanotaan?
args.foreach((arg: String) => println(arg))
(x: Int, y: Int) => x + yEikö alakin näyttää kahden muuttujan funktiolta, joka kuvaa argumenttinsa argumenttien summalle?
args.foreach(println)Tässä foreach-metodi saa parametrikseen ns. osittain sovelletun funktion, println-funktion ilman parametria. Metodi foreach osaa sitten itse soveltaa tätä jokaiselle args-taulukon alkiolle. Tästä lisää myöhemmin.
args foreach printlnkoska foreach-metodikutsua voi käyttää myös infix-operaattorina.
for (arg <- args) println(arg)
Esimerkki: Laaditaan funktio, joka saa parametrina kaksi kokonaislukua ja funktion, joka kuvaa kaksi lukua kolmanneksi. Laadittava funktio soveltaa saamaansa funktiota parametrilukuihin:
def koristele(x: Int, y: Int, arvo: (Int, Int) => Int) = println("**** " + arvo(x, y) + " ****")Ja näin kätevästi sitä sitten voi käyttää:
koristele(5, 9, (x: Int, y: Int) => x + y) // **** 14 **** koristele(5, 9, (x: Int, y: Int) => x * y) // **** 45 **** def erotus(a: Int, b: Int) = a-b koristele(5, 9, erotus) // **** -4 ****Kuten näkyy, todellisena funktioparametrina voidaan antaa funktioliteraalien lisäksi myös nimettyjä funktioita!