Teil 2: Variablen

Die Schreibweise für Variablen unterscheidet sich grundlegend von der von Java. In den C-Nachfolgesprachen sieht eine Variablendeklaration meist so aus:

<type> <name> = [new] <type>

In Scala wird hingegen der Variablenname vor den Typ gesetzt:

var <name>: <type> = [new] <type>

Weiterhin wird die Deklaration durch das Schlüsselwort var eingeleitet und der Typ durch einen Doppelpunkt vom Variablennamen getrennt. Ein Beispiel:

scala> var name: String = "Hugo"
name: String = Hugo

scala> name
res1: String = Hugo

Scala besitzt ein äußerst tolles Feature namens „type inference“ oder auf Deutsch Typeninferenz. Dies erlaubt es dem Compiler zu erkennen was für ein Typ eine Variable annehmen wird, nachdem ihr ein Wert zugewiesen wurde. Dadurch besteht die Möglichkeit, den Typ bei der Deklaration der Variable einfach wegzulassen:

scala> var name = "Hugo"
name: java.lang.String = Hugo

Der Compiler erkennt selbstständig, dass ein Stringliteral vorliegt, welches an die Variable gebunden wird.

Die REPL bietet noch die Möglichkeit Rückgabewerte von Ausdrücken automatisch an Variablen zu binden:

scala> var name: String = "Hugo"
name: String = Hugo

scala> name
res1: String = Hugo

Die Variablen fangen stets mit „res“ an und werden von einem Zähler gefolgt.

Neben var gibt es auch noch val. Der Unterschied zwischen den beiden ist, dass var veränderlich ist und val nicht:

scala> var name = "Hugo"
name: java.lang.String = Hugo

scala> name = "Franz"
name: java.lang.String = Franz

scala> val name = "Hugo"
name: java.lang.String = Hugo

scala> name = "Franz"
<console>:8: error: reassignment to val
       name = "Franz"
            ^

In funktionalen Programmiersprachen werden unveränderliche Werte den Veränderlichen gegenüber bevorzugt. Dies wird dadurch begründet, dass ein Programm so wenig Nebeneffekte wie möglich vorweisen soll. Anstatt also den Inhalt einer Variablen zu ändern wird einfach eine neue angelegt:

scala> val name = "Hugo"
name: java.lang.String = Hugo

scala> val fullName = name+" Schmidt"
fullName: java.lang.String = Hugo Schmidt

Aus dokumentationstechnischer Sicht macht das auch mehr Sinn. Erst beherbergt eine Variable einen Wert und trägt einen Namen, der beschreibt was die Variable beinhaltet, aber dann beinhaltet sie etwas später womöglich was ganz anderes? Das ist unlogisch und durch die Vermeidung von veränderlichen Objekten umgeht man dieses Problem.
Um sich also der funktionalen Welt zuzuwenden (und wenn es nur ein ganz klein bisschen ist) empfiehlt es sich möglichst auf das Schlüsselwort var zu verzichten. Für den Anfang werdet ihr dies als unmöglich erachten (Schleifen ohne veränderliche Objekte?) aber ich versichere euch, nach der Lektüre dieses Tutorials werdet ihr die Welt mit ganz anderen Augen betrachten und sehen was für tollen Code man ohne veränderliche Objekte schreiben kann. 😉

Nun gibt es in Scala aber noch eine Variablen-Variante: den sogenannten lazy val. Der Unterschied zu einem val ist, dass ein lazy val nicht dann initialisiert wird wenn er deklariert wird, sondern dann wenn er zum ersten Mal benutzt wird.

scala> val x = { println("x"); 15 }
x
x: Int = 15

scala> lazy val y = { println("y"); 13 }
y: Int = <lazy>

scala> x
res2: Int = 15

scala> y
y
res3: Int = 13

scala> y
res4: Int = 13

In obigem Beispiel wird ein sogenannter Block an eine Variable gebunden. Ein Block steht immer in geschweiften Klammern, kann mehrere Anweisungen enthalten und wird im Zuge dieses Tutorials ausführlicher in einem späteren Kapitel besprochen. Der lazy val wird nur ein einziges Mal ausgeführt und dann nie wieder. Sie sind nützlich wenn Operationen lange dauern können, es aber nicht sicher ist ob sie überhaupt ausgeführt werden müssen.

scala> class X { val x = { Thread.sleep(2000); 15 } }
defined class X

scala> class Y { lazy val y = { Thread.sleep(2000); 13 } }
defined class Y

scala> new X
res5: X = X@262505b7 // we have to wait two seconds to the result

scala> new Y
res6: Y = Y@1555bd22 // this appears immediately

Hier sind unsere vals Member einer Klasse. Das bedeutet, dass sie ausgeführt werden sobald die Klasse instanziiert wird, was wir durch das lazy aber verhindern können.

Noch ein kleiner Tipp am Rande: Bei einer fehlerhaften Eingabe in der REPL ermöglicht die Eingabe von zwei Leerzeilen, dass das Kommando verworfen wird:

scala> val omg = {
     | 
     | 
You typed two blank lines.  Starting a new command.
Advertisements

3 comments so far

  1. prinzdezibel on

    Typo: s/ermöglicht die Eingabe von zwei Leerzeichen,/ermöglicht die Eingabe von zwei Leerzeilen,/

  2. Alexander on

    Das dritte Beispiel sollte wahrscheinlich „res“ verdeutlichen. Das gegebene Beispiel ist aber unverändert Copy&Pasted und ist mit dem ersten identisch.


Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: