40 votes

Quand @uncheckedVariance est-il nécessaire dans Scala, et pourquoi est-il utilisé dans GenericTraversableTemplate?

@uncheckedVariance peuvent être utilisés pour combler le fossé entre la Scala de déclaration du site de la variance d'annotations et de Java est invariant génériques.

scala> import java.util.Comparator    
import java.util.Comparator

scala> trait Foo[T] extends Comparator[T]
defined trait Foo

scala> trait Foo[-T] extends Comparator[T]     
<console>:5: error: contravariant type T occurs in invariant position in type [-T]java.lang.Object with java.util.Comparator[T] of trait Foo
       trait Foo[-T] extends Comparator[T]
             ^

scala> import annotation.unchecked._    
import annotation.unchecked._

scala> trait Foo[-T] extends Comparator[T @uncheckedVariance]    
defined trait Foo

Ceci dit que java.util.Comparateur est naturellement contre-variante, qui est le paramètre de type T s'affiche dans les paramètres, et jamais dans un type de retour.

Cela pose la question: pourquoi est-il aussi utilisé dans le Scala collections de la bibliothèque, qui ne s'étend à partir d'interfaces Java?

trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance]

Quelles sont les utilisations valides pour cette annotation?

30voto

Adriaan Moors Points 1765

Le problème est que GenericTraversableTemplate est utilisé deux fois: une fois pour mutable collections (d'où son paramètre de type doit être invariante), et une fois pour l'immuable collections (où la covariance est toujours roi).

GenericTraversableTemplate de typechecks en supposant que ce soit la covariance ou d'invariance pour l'Un paramètre de type. Cependant, lorsque nous héritons dans une mutable trait, nous devons choisir d'invariance. A l'inverse, nous aimerions covariance dans un immuable sous-classe.

Puisque nous ne pouvons pas abstraite et la variance d'annotation (encore ;-)) dans GenericTraversableTemplate, de sorte que nous pourrions avoir instancié à l'un des deux en fonction de la sous-classe, nous devons recourir à la coulée (@uncheckVariance est essentiellement une sorte de fonte). Pour plus de lecture, je vous recommande de ma thèse (désolé ;-)) ou de notre récente bitrot papier

8voto

Adriaan Moors Points 1765

Dans ma thèse, j'ai décrire un calcul, Scalina, qui a des limites & de la variance des annotations en tant que partie de la nature de la langue (une version antérieure est également disponible ainsi qu'un atelier de papier). La pertinence de cette discussion est la prochaine étape que je veux prendre dans le développement de ce calcul: construire une autre couche sur le dessus, de sorte que vous pouvez abstraite, plus de limites (facile) et de la variance des annotations (me fait tourner la tête). En fait, vous ne devriez pas simplement ajouter 1 couche supplémentaire là-bas, mais plutôt de généraliser votre polymorphisme des constructions afin qu'ils travaillent à tous les niveaux, et faire de votre "attributs" (limites, la variance des annotations, nécessaire implicite arguments,...) dans des types avec des types spéciaux, qui sont tous soumis à l'abstraction.

Les "attributs sont des types" l'idée est expliqué bien par Edsko de Vries dans le contexte de l'unicité types.

L'Unicité De Frappe Simplifié, Edsko de Vries, Rinus Plasmeijer, et David Abrahamson. Dans l'Olaf Chitil, Zoltán Horváth et Viktória Zsók (Eds.): ILM 2007, LNCS 5083, pp. 201-218, 2008.

Résumé: Nous présentons une singularité de type système qui est plus simple que les deux Nettoyer le caractère unique du système et la le système que nous avons proposé précédemment. La nouvelle type de système est simple à mettre en œuvre et les ajouter à l'existant les compilateurs, et peut facilement être étendu avec des fonctionnalités avancées comme la hausse de la rang types et impredicativity. Nous décrire la mise en œuvre Morrow, expérimental de la fonctionnelle de la langue avec ces deux caractéristiques. Enfin, nous prouver la solidité de la base type système à l'égard de la appel par nécessité lambda calcul.

5voto

retronym Points 35066

J'ai trouvé une autre fois où @uncheckedVariance est utilisé - la méthode synthétique qui renvoie la valeur par défaut pour un paramètre de type abstrait:

 M:\>scala -Xprint:typer -e "class C { def p[T >: Null](t: T = null) = t }"
[[syntax trees at end of typer]]// Scala source: (virtual file)
package <empty> {
  final object Main extends java.lang.Object with ScalaObject {
    def this(): object Main = {
      Main.super.this();
      ()
    };
    def main(argv: Array[String]): Unit = {
      val args: Array[String] = argv;
      {
        final class $anon extends scala.AnyRef {
          def this(): anonymous class $anon = {
            $anon.super.this();
            ()
          };
          class C extends java.lang.Object with ScalaObject {
            <synthetic> def p$default$1[T >: Null <: Any]: Null @scala.annotation.unchecked.uncheckedVariance = null;
            def this(): this.C = {
              C.super.this();
              ()
            };
            def p[T >: Null <: Any](t: T = null): T = t
          }
        };
        {
          new $anon();
          ()
        }
      }
    }
  }
 

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