288 votes

Quelles sont les limites de contexte et vue Scala ?

D’une manière simple, quelles sont les limites de la vue et de contexte et quelle est la différence entre eux ?

Quelques exemples faciles à suivre serait trop génial !

504voto

Daniel C. Sobral Points 159554

Je pensais que c'était déjà demandé, mais, dans l'affirmative, la question n'est pas apparente dans la "relative" de la barre. Donc, ici, il est:

Qu'est ce qu'une Vue?

Une vue lié est un mécanisme mis en Scala pour permettre l'utilisation d'un certain type A comme si elle était un type B. La syntaxe typique est ceci:

def f[A <% B](a: A) = a.bMethod

En d'autres termes, A devrait avoir une conversion implicite en B disponible, de sorte que l'on peut appeler B méthodes sur un objet de type A. L'utilisation la plus courante de vue des limites dans la bibliothèque standard (avant Scala 2.8.0, de toute façon), c'est avec Ordered, comme ceci:

def f[A <% Ordered[A]](a: A, b: A) = if (a < b) a else b

Parce que l'on peut convertir A en Ordered[A], et parce qu' Ordered[A] définit la méthode d' <(other: A): Boolean, je peux utiliser l'expression a < b.

S'il vous plaît être conscient que vue les limites sont obsolètes, vous devriez les éviter.

Qu'est ce qu'un Contexte Lié?

Contexte limites ont été introduites dans Scala 2.8.0, et sont généralement utilisés avec la soi-disant classe de type de modèle, un modèle de code qui émule la fonctionnalité fournie par Haskell type de classes, mais d'une manière plus détaillée.

Alors qu'une vue lié peut être utilisé avec les types simples (par exemple, A <% String), un contexte lié nécessite un type paramétré, comme Ordered[A] - dessus, mais à la différence de String.

Un contexte lié décrit implicite de valeur, au lieu d'afficher lié implicite de conversion. Il est utilisé pour déclarer que pour certains type A, il y a une valeur implicite de type B[A] disponible. La syntaxe ressemble à ceci:

def f[A : B](a: A) = g(a) // where g requires an implicit value of type B[A]

C'est plus de confusion que de la vue liés car il n'est pas immédiatement clair comment l'utiliser. L'exemple le plus connu de l'utilisation de Scala est ceci:

def f[A : ClassManifest](n: Int) = new Array[A](n)

Un Array d'initialisation sur un paramétrée type nécessite une ClassManifest à être disponible, pour des arcanes des raisons liées à type d'effacement et de la non-effacement de la nature de tableaux.

Un autre exemple courant dans la bibliothèque est un peu plus complexe:

def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b)

Ici, implicitly est utilisé pour retrive la valeur implicite que nous voulons, l'une de type Ordering[A], ce qui classe définit la méthode d' compare(a: A, b: A): Int.

Nous allons voir une autre façon de le faire ci-dessous.

Comment Afficher les Limites et le Contexte des Limites mises en œuvre?

Il ne devrait pas être surprenant que les deux limites et le contexte des limites sont mises en œuvre avec les paramètres implicites, compte tenu de leur définition. En fait, la syntaxe, j'ai montré sont syntaxique des sucres pour ce qui se passe vraiment. Voir ci-dessous comment ils de-sucre:

def f[A <% B](a: A) = a.bMethod
def f[A](a: A)(implicit ev: A => B) = a.bMethod

def g[A : B](a: A) = h(a)
def g[A](a: A)(implicit ev: B[A]) = h(a)

Alors, naturellement, on peut écrire dans leur syntaxe complète, ce qui est particulièrement utile pour le contexte de limites:

def f[A](a: A, b: A)(implicit ord: Ordering[A]) = ord.compare(a, b)

Ce sont des vues de Limites?

Afficher les limites sont utilisées principalement pour profiter de la pimp my bibliothèque de modèle, à travers laquelle on "ajoute" des méthodes à une classe existante, dans le cas où vous voulez retourner le type d'original, d'une certaine manière. Si vous n'avez pas besoin de retourner ce type de toute façon, vous n'avez pas besoin d'une vue lié.

L'exemple classique de vue lié d'utilisation est de manutention Ordered. Notez que Int n'est Ordered, par exemple, si il y a une conversion implicite. L'exemple donné précédemment besoins de vue lié, car il renvoie la non-conversion de type:

def f[A <% Ordered[A]](a: A, b: A): A = if (a < b) a else b

Cet exemple ne fonctionnera pas sans afficher de limites. Cependant, si je devais revenir un autre type, alors je n'ai pas besoin d'une vue plus lié:

def f[A](a: Ordered[A], b: A): Boolean = a < b

La conversion (si nécessaire) arrive avant que je passe le paramètre f, alors f n'a pas besoin de le savoir.

En plus d' Ordered, l'utilisation la plus courante de la bibliothèque est de manutention String et Array, qui sont des classes Java, comme s'ils étaient Scala collections. Par exemple:

def f[CC <% Traversable[_]](a: CC, b: CC): CC = if (a.size < b.size) a else b

Si l'on essayait de le faire sans afficher de limites, le type de retour d'une String serait un WrappedString (Scala 2.8), et de même pour Array.

La même chose se produit même si le type n'est utilisé que comme un paramètre de type de le type de retour:

def f[A <% Ordered[A]](xs: A*): Seq[A] = xs.toSeq.sorted

Quels sont le Contexte des Limites?

Contexte limites sont principalement utilisés dans ce qui est devenu connu comme typeclass modèle, car une référence à Haskell type de classes. Fondamentalement, ce modèle met en œuvre une alternative à l'héritage en faisant des fonctionnalités disponibles par l'intermédiaire d'une sorte d'implicite de l'adaptateur.

L'exemple classique est celui de la Scala 2.8 de l' Ordering, qui a remplacé Ordered tout au long de Scala, à la bibliothèque. L'utilisation est:

def f[A : Ordering](a: A, b: A) = if (implicitly[Ordering[A]].lt(a, b)) a else b

Si vous aurez généralement voir qui écrit comme ceci:

def f[A](a: A, b: A)(implicit ord: Ordering[A]) = {
    import ord.mkOrderingOps
    if (a < b) a else b
}

Qui de tirer avantage de certaines conversions implicites à l'intérieur d' Ordering qui permettent à l'opérateur traditionnel de style. Un autre exemple dans Scala 2.8 est l' Numeric:

def f[A : Numeric](a: A, b: A) = implicitly[Numeric[A]].plus(a, b)

Un exemple plus complexe est la nouvelle collection de l'utilisation de CanBuildFrom, mais il y a déjà une très longue réponse à ce sujet, donc je vais éviter de le faire ici. Et, comme mentionné avant, il y a l' ClassManifest d'utilisation, ce qui est nécessaire pour initialiser de nouveaux tableaux sans types de béton.

Le contexte lié à la typeclass modèle est beaucoup plus susceptibles d'être utilisés par vos propres classes, car ils permettent la séparation des préoccupations, alors que vue les limites peuvent être évités dans votre propre code par une bonne conception (il est principalement utilisé pour obtenir autour de quelqu'un d'autre de design).

Bien qu'il ait été possible pendant un certain temps, l'utilisation du contexte de limites a réellement pris son envol en 2010, et se trouve maintenant à un certain degré dans la plupart de la Scala, à la plus importante des bibliothèques et des structures. L'exemple le plus extrême de son utilisation, cependant, est le Scalaz de la bibliothèque, qui apporte beaucoup de la puissance de Haskell à la Scala. Je vous recommande la lecture sur typeclass modèles pour obtenir plus de connaître tous les moyens dont il peut être utilisé.

MODIFIER

La question de l'intérêt:

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X