L'une des nouvelles fonctionnalités de Scala 2.8 sont les limites de contexte. Qu'est-ce qu'un contexte lié et où est-il utile?
Bien sûr, j'ai cherché en premier (et trouvé par exemple ceci ) mais je n'ai pas trouvé d'informations vraiment claires et détaillées.
scala
scala-2.8
context-bound
Jesper
la source
la source
Réponses:
Avez-vous trouvé cet article ? Il couvre la nouvelle fonctionnalité liée au contexte, dans le contexte des améliorations des tableaux.
En général, un paramètre de type avec un contexte lié est de la forme
[T: Bound]
; il est développé en paramètre de type simpleT
avec un paramètre implicite de typeBound[T]
.Considérons la méthode
tabulate
qui forme un tableau à partir des résultats de l'application d'une fonction f donnée sur une plage de nombres de 0 jusqu'à une longueur donnée. Jusqu'à Scala 2.7, le tableau pouvait être écrit comme suit:Dans Scala 2.8, cela n'est plus possible, car les informations d'exécution sont nécessaires pour créer la bonne représentation de
Array[T]
. Il faut fournir ces informations en passant aClassManifest[T]
dans la méthode en tant que paramètre implicite:En tant que forme abrégée, un contexte lié peut être utilisé sur le paramètre type à la
T
place, donnant:la source
La réponse de Robert couvre les détails techniques des limites de contexte. Je vais vous donner mon interprétation de leur signification.
Dans Scala, un View Bound (
A <% B
) capture le concept de «peut être vu comme» (alors qu'une borne supérieure<:
capture le concept de «est un»). Un contexte lié (A : C
) dit «a un» sur un type. Vous pouvez lire les exemples sur les manifestes comme "T
a unManifest
". L'exemple auquel vous avez lié aboutOrdered
vsOrdering
illustre la différence. Une méthodedit que le paramètre peut être vu comme un
Ordered
. Comparer avecqui dit que le paramètre a un associé
Ordering
.En termes d'utilisation, il a fallu un certain temps pour que les conventions soient établies, mais les limites de contexte sont préférées aux limites de vue (les limites de vue sont maintenant obsolètes ). Une suggestion est qu'un contexte lié est préféré lorsque vous devez transférer une définition implicite d'une portée à une autre sans avoir besoin de s'y référer directement (c'est certainement le cas pour le
ClassManifest
utilisé pour créer un tableau).Une autre façon de penser aux limites de vue et aux limites de contexte est que la première transfère les conversions implicites de la portée de l'appelant. Le second transfère les objets implicites de la portée de l'appelant.
la source
has a
plus de sens pour moi](Ceci est une note entre parenthèses. Lisez et comprenez d'abord les autres réponses.)
Les limites de contexte généralisent en fait les limites de vue.
Donc, étant donné ce code exprimé avec un View Bound:
Cela pourrait également être exprimé avec un Contexte Bound, à l'aide d'un alias de type représentant des fonctions de type
F
en typeT
.Un contexte lié doit être utilisé avec un constructeur de type de type
* => *
. Cependant, le constructeur de typeFunction1
est du genre(*, *) => *
. L'utilisation de l'alias de type applique partiellement le second paramètre de type avec le typeString
, ce qui donne un constructeur de type du type correct à utiliser en tant que contexte lié.Il existe une proposition pour vous permettre d'exprimer directement des types partiellement appliqués dans Scala, sans utiliser l'alias de type à l'intérieur d'un trait. Vous pourriez alors écrire:
la source
From
de type du typeTo[String]
. Nous ne fournissons pas d'argument de type àFrom
, donc nous nous référons au constructeur de type, pas à un type. Ce constructeur de type est du bon type pour être utilisé en tant que contexte lié -* -> *
. Cela limite le paramètre de typeT
en exigeant un paramètre implicite de typeTo[String]#From[T]
. Développez les alias de type, et voila, il vous resteFunction1[String, T]
.Ceci est une autre note entre parenthèses.
Comme Ben l'a souligné , un contexte lié représente une contrainte "has-a" entre un paramètre de type et une classe de type. En d'autres termes, cela représente une contrainte qu'une valeur implicite d'une classe de type particulière existe.
Lors de l'utilisation d'un contexte lié, il faut souvent faire apparaître cette valeur implicite. Par exemple, étant donné la contrainte
T : Ordering
, on aura souvent besoin de l'instance deOrdering[T]
qui satisfait la contrainte. Comme démontré ici , il est possible d'accéder à la valeur implicite en utilisant laimplicitly
méthode ou une méthode légèrement plus utilecontext
:ou
la source