Donnerstag, 24. Mai 2012


Artikel

September 2010 | Artikel

Advanced Scala

(Link zum Artikel: http://www.entwickler.de/jaxenter//003353)

Implicit Parameters und Type Classes

Text: Heiko Seeberger
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
Im letzten Teil dieser Serie haben wir Implicit Conversions kennen gelernt. Heute werden wir unseren Blick zunächst auf ein verwandtes Thema richten, auf Implicit Parameters. Anschließend werden wir Type Classes vorstellen, ein derzeit sehr angesagtes Anwendungsbeispiel für die Implicits.
Teil 1   Teil 2   

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:

  1. scala> val add = (x: Int) => (y: Int) => x + y
  2. add: (Int) => (Int) => Int = <function1>
  3. scala> add(1)(2)
  4. 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:

  1. scala> val addOne = add(1)
  2. addOne: (Int) => Int = <function1>
  3. scala> addOne(2)
  4. 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.

  1. scala> def add(x: Int)(implicit y: Int) = x + y
  2. add: (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:

  1. scala> add(2)
  2. <console>:7: error: could not find implicit value for parameter y: Int
  3. add(2)
  4. ^

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:

  1. scala> implicit val defaultInt = 1
  2. defaultInt: Int = 1
  3. scala> add(2)
  4. 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.

Teil 1   Teil 2   

andere Artikel dieser Serie

Kommentare

Gravatar steve 17.09.2010
um 15:59 Uhr
"[...] fortschrittliches Sprachkonstrukt unter die Lupe nehmen: Currying [...]"

Das "fortschrittlich" würde ich - ehrlich gesagt - entweder in Anführungszeichen packen oder ganz entfernen...
#zitieren