Tout ce que je sais sur TypeTags, c'est qu'ils ont en quelque sorte remplacé les manifestes. Les informations sur Internet sont rares et ne me donnent pas une bonne idée du sujet.
Je serais donc heureux si quelqu'un partageait un lien vers des documents utiles sur TypeTags, y compris des exemples et des cas d'utilisation populaires. Les réponses et explications détaillées sont également les bienvenues.
scala
types
scala-2.10
reification
Sergey Weiss
la source
la source
Réponses:
A
TypeTag
résout le problème de l'effacement des types de Scala au moment de l'exécution (effacement de type). Si nous voulons fairenous recevrons des avertissements:
Pour résoudre ce problème, des manifestes ont été introduits dans Scala. Mais ils ont le problème de ne pas pouvoir représenter beaucoup de types utiles, comme les types dépendants du chemin:
Ainsi, ils sont remplacés par TypeTags , qui sont à la fois beaucoup plus simples à utiliser et bien intégrés dans la nouvelle API Reflection. Avec eux, nous pouvons résoudre le problème ci-dessus à propos des types dépendants du chemin avec élégance:
Ils sont également faciles à utiliser pour vérifier les paramètres de type:
À ce stade, il est extrêmement important de comprendre l'utilisation de
=:=
(égalité de type) et<:<
(relation de sous-type) pour les vérifications d'égalité. N'utilisez jamais==
ou!=
, sauf si vous savez absolument ce que vous faites:Ce dernier vérifie l'égalité structurelle, ce qui n'est souvent pas ce qui devrait être fait car il ne se soucie pas de choses telles que les préfixes (comme dans l'exemple).
A
TypeTag
est entièrement généré par le compilateur, ce qui signifie que le compilateur crée et remplit unTypeTag
quand on appelle une méthode qui attend un telTypeTag
. Il existe trois formes différentes de balises:ClassTag
substitutsClassManifest
alors queTypeTag
c'est plus ou moins le remplacement deManifest
.Le premier permet de travailler pleinement avec des tableaux génériques:
ClassTag
fournit uniquement les informations nécessaires pour créer des types lors de l'exécution (dont le type est effacé):Comme on peut le voir ci-dessus, ils ne se soucient pas de l'effacement des types, donc si l'on veut que les types "complets"
TypeTag
soient utilisés:Comme on peut le voir, la méthode
tpe
desTypeTag
résultats dans un fullType
, qui est la même que nous obtenons quandtypeOf
est appelée. Bien sûr, il est possible d'utiliser les deux,ClassTag
etTypeTag
:La question restante est maintenant quel est le sens de
WeakTypeTag
? En bref,TypeTag
représente un type concret (cela signifie qu'il n'autorise que les types entièrement instanciés) alors qu'ilWeakTypeTag
ne permet que n'importe quel type. La plupart du temps, on ne se soucie pas de savoir quoi (quels moyensTypeTag
doivent être utilisés), mais par exemple, lorsque des macros sont utilisées qui devraient fonctionner avec des types génériques, elles sont nécessaires:Si l'on remplace
WeakTypeTag
parTypeTag
une erreur est levée:Pour une explication plus détaillée des différences entre
TypeTag
etWeakTypeTag
voir cette question: Macros Scala: "ne peut pas créer TypeTag à partir d'un type T ayant des paramètres de type non résolus"Le site officiel de documentation de Scala contient également un guide pour Reflection .
la source
==
pour les types représente l'égalité structurelle, pas l'égalité de référence.=:=
prendre en compte les équivalences de type (même celles qui ne sont pas évidentes comme les équivalences de préfixes provenant de différents miroirs), 2) Les deuxTypeTag
etAbsTypeTag
sont basés sur des miroirs. La différence est queTypeTag
seuls les types entièrement instanciés sont autorisés (c'est-à-dire sans aucun paramètre de type ou référence à des membres de type abstrait), 3) Une explication détaillée est ici: stackoverflow.com/questions/12093752Int
et types génériques tels queList[Int]
), en laissant de côté les types Scala tels que les raffinements, les types dépendants du chemin, les existentiels, les types annotés. Les manifestes sont également un boulon, ils ne peuvent donc pas utiliser les vastes connaissances que le compilateur possède pour, par exemple, calculer une linéarisation d'un type, savoir si un type en sousTypes.scala
(7kloc de code qui sait comment les types sont pris en charge pour fonctionner ensemble),Symbols.scala
(3kloc de code qui sait comment fonctionnent les tables de symboles), etc.ClassTag
est un remplacement exact pourClassManifest
, alors qu'ilTypeTag
est plus ou moins un substitutManifest
. Plus ou moins, car: 1) les balises de type ne portent pas d'effacement, 2) les manifestes sont un gros hack, et nous avons renoncé à émuler son comportement avec des balises de type. # 1 peut être corrigé en utilisant à la fois les limites de contexte ClassTag et TypeTag lorsque vous avez besoin à la fois d'effacements et de types, et l'un ne se soucie généralement pas de # 2, car il devient possible de jeter tous les hacks et d'utiliser l'API de réflexion à part entière au lieu.