Currying
Um Implicit Parameters zu verstehen, müssen wir zunächst ein anderes fortschrittliches Sprachkonstrukt unter die Lupe nehmen: Currying. Damit bezeichnet man die Möglichkeit, dass Methoden und Funktionen mehrere Parameterlisten haben können, wie im folgenden Beispiel der Addition zweier Int-Werte demonstriert:
scala> val add = (x: Int) => (y: Int) => x + yadd: (Int) => (Int) => Int = <function1>scala> add(1)(2)res0: Int = 3
Die Funktion add hat je eine Parameterliste für jeden Summanden und muss auch dementsprechend aufgerufen werden. Natürlich funktioniert das auch mit drei oder mehr Parameterlisten und ebenso mit mehreren Parametern pro Liste.
Mit Blick auf die Definition bzw. den Typ können wir die Funktion add auch anders auffassen, und zwar als eine Funktion mit einem Parameter, die als Ergebnis eine weitere Funktion mit einem Parameter hat. Diese Sichtweise führt nun direkt zum größten Nutzen der “gewürzten” Schreibweise. Wir können beim Aufruf die rechte Parameterliste weglassen und erhalten dadurch eine neue Funktion:
scala> val addOne = add(1)addOne: (Int) => Int = <function1>scala> addOne(2)res1: Int = 3
Implicit Values
Es gäbe noch vieles über das in funktionalen Sprachen beheimatete Currying zu sagen, aber wir wollen uns nun einem speziellen Scala-Feature zuwenden. Wenn wir eine Methode mit mehreren Parameterlisten schreiben, können wir die letzte als implicit kennzeichnen.
scala> def add(x: Int)(implicit y: Int) = x + yadd: (x: Int)(implicit y: Int)Int
Diese Methode können wir zunächst “ganz normal” aufrufen, indem wir beide Parameterlisten verwenden. Aber wir können auch die letzte einfach weglassen und der Compiler wird sie für uns implizit füllen:
scala> add(2)<console>:7: error: could not find implicit value for parameter y: Intadd(2)^
Nun, so einfach geht es doch nicht, denn der Compiler verwendet natürlich keine zufälligen Werte. Hier kommen jetzt die Implicit Values ins Spiel: Wir definieren einfach einen passenden Wert, also einen Int-Wert, mit dem Schlüsselwort implicit, und schon kompiliert unser kleines Beispiel:
scala> implicit val defaultInt = 1defaultInt: Int = 1scala> add(2)res1: Int = 3
Ähnlich wie für Implicit Conversions gelten auch für Implicit Values strenge Regeln. Insbesondere gilt, dass ein Implicit Value im Scope sein muss, sonst wird sich der Compiler beschweren.




