Eine der neuen Funktionen von Scala 2.8 sind Kontextgrenzen. Was ist ein Kontext gebunden und wo ist er nützlich?
Natürlich habe ich zuerst gesucht (und zum Beispiel dies gefunden ), aber ich konnte keine wirklich klaren und detaillierten Informationen finden.
scala
scala-2.8
context-bound
Jesper
quelle
quelle
Antworten:
Haben Sie diesen Artikel gefunden ? Es behandelt die neue kontextgebundene Funktion im Kontext von Array-Verbesserungen.
Im Allgemeinen hat ein Typparameter mit einer Kontextbindung die Form
[T: Bound]
; Es wirdT
zusammen mit einem impliziten Parameter vom Typ zu einem einfachen Typparameter erweitertBound[T]
.Betrachten Sie die Methode,
tabulate
die aus den Ergebnissen der Anwendung einer bestimmten Funktion f auf einen Zahlenbereich von 0 bis zu einer bestimmten Länge ein Array bildet. Bis zu Scala 2.7 kann die Tabelle wie folgt geschrieben werden:In Scala 2.8 ist dies nicht mehr möglich, da Laufzeitinformationen erforderlich sind, um die richtige Darstellung von zu erstellen
Array[T]
. Diese Informationen müssen bereitgestellt werden, indem einClassManifest[T]
als impliziter Parameter an die Methode übergeben wird:Als Kurzform kann stattdessen eine Kontextbindung für den Typparameter
T
verwendet werden, die Folgendes ergibt:quelle
Roberts Antwort behandelt die technischen Details von Context Bounds. Ich werde Ihnen meine Interpretation ihrer Bedeutung geben.
In Scala
A <% B
erfasst a View Bound ( ) das Konzept von 'kann als' gesehen werden (während eine Obergrenze<:
das Konzept von 'is a' erfasst). Ein Kontext gebunden (A : C
) sagt 'hat ein' über einen Typ. Sie können die Beispiele zu Manifesten als "T
hat einManifest
" lesen . Das Beispiel, das Sie mit aboutOrdered
vs verknüpft haben,Ordering
zeigt den Unterschied. Eine Methodesagt, dass der Parameter als ein gesehen werden kann
Ordered
. Vergleichen mitwas besagt, dass dem Parameter eine zugeordnet ist
Ordering
.In Bezug auf die Verwendung hat es eine Weile gedauert, bis Konventionen festgelegt wurden, aber Kontextgrenzen werden gegenüber Ansichtsgrenzen bevorzugt ( Ansichtsgrenzen sind jetzt veraltet ). Ein Vorschlag ist, dass eine Kontextbindung bevorzugt wird, wenn Sie eine implizite Definition von einem Bereich in einen anderen übertragen müssen, ohne direkt darauf verweisen zu müssen (dies ist sicherlich der Fall, wenn
ClassManifest
ein Array erstellt wird).Eine andere Art, über Sicht- und Kontextgrenzen nachzudenken, besteht darin, dass beim ersten Mal implizite Konvertierungen aus dem Bereich des Anrufers übertragen werden. Der zweite überträgt implizite Objekte aus dem Bereich des Aufrufers.
quelle
has a
für mich mehr Sinn](Dies ist eine Anmerkung in Klammern. Lesen und verstehen Sie zuerst die anderen Antworten.)
Kontextgrenzen verallgemeinern tatsächlich Ansichtsgrenzen.
Angesichts dieses Codes, der mit einer Ansichtsgrenze ausgedrückt wird:
Dies kann auch mit Hilfe eines Typalias ausgedrückt werden, der Funktionen von Typ
F
zu Typ darstelltT
.Eine Kontextbindung muss mit einem Typkonstruktor verwendet werden
* => *
. Der TypkonstruktorFunction1
ist jedoch von Art(*, *) => *
. Die Verwendung des Typalias wendet teilweise den zweiten Typparameter auf den Typ anString
, wodurch ein Typkonstruktor der richtigen Art zur Verwendung als Kontextbindung erhalten wird.Es gibt einen Vorschlag, mit dem Sie teilweise angewendete Typen in Scala direkt ausdrücken können, ohne den Typalias innerhalb eines Merkmals zu verwenden. Sie könnten dann schreiben:
quelle
From
des TypsTo[String]
. Wir geben kein Typargument anFrom
, daher verweisen wir auf den Typkonstruktor, nicht auf einen Typ. Dieser Typkonstruktor ist von der richtigen Art, um als kontextgebunden - verwendet zu werden* -> *
. Dies begrenzt den Typparameter,T
indem ein impliziter Parameter vom Typ erforderlich wirdTo[String]#From[T]
. Erweitern Sie die Typ-Aliase und voila, die Ihnen verbleibenFunction1[String, T]
.Dies ist eine weitere Anmerkung in Klammern.
Wie Ben hervorhob, stellt eine Kontextbindung eine "has-a" -Einschränkung zwischen einem Typparameter und einer Typklasse dar. Anders ausgedrückt, es stellt eine Einschränkung dar, dass ein impliziter Wert einer bestimmten Typklasse vorhanden ist.
Wenn man einen Kontext verwendet, muss man diesen impliziten Wert oft auftauchen lassen. In Anbetracht der Einschränkung
T : Ordering
wird beispielsweise häufig die Instanz benötigtOrdering[T]
, die die Einschränkung erfüllt. Wie hier gezeigt , ist es möglich, mit derimplicitly
Methode oder einer etwas hilfreicherencontext
Methode auf den impliziten Wert zuzugreifen :oder
quelle