2011-08-10 3 views
6

Selon la spécification scala, l'extracteur construit par les classes de cas est la suivante (spécification scala §5.3.2):Différence entre le domicile fait extracteur et classe cas extracteur

def unapply[tps](x: c[tps]) = 
    if (x eq null) scala.None 
    else scala.Some(x.xs11, ..., x.xs1k) 

Pour des raisons de mise en œuvre, je veux être capable d'imiter le comportement de cet extracteur sur une classe non-cas. Cependant, mon implémentation ne parvient pas à reproduire le même comportement.

Voici un exemple de la différence que j'ai:

trait A 

sealed trait B[X <: A]{ val x: X } 

case class C[X <: A](x: X) extends B[X] 

class D[X <: A](val x: X) extends B[X] 

object D { 
    def unapply[X <: A](d: D[X]): Option[X] = 
    if (d eq None) None 
    else Some(d.x) 
} 

def ext[X <: A](b: B[X]) = b match { 
    case C(x) => Some(x) 
    case D(x) => Some(x) 
    case _ => None 
} 

je l'avertissement suivant:

<console>:37: warning: non variable type-argument X in type pattern D[X] is unchecked since it is eliminated by erasure 
    case D(x) => Some(x) 

Notez l'avertissement ne se produit que dans le D cas, pas dans le cas de la classe cas de textractor. Avez-vous une idée de la cause de l'avertissement/de ce que je devrais faire pour éviter cet avertissement?

Note: Si vous voulez tester dans REPL, le plus simple est:

  1. Pour activer avertissement décochée

    scala>: Puissance

    scala> settings.unchecked .value = true

  2. Pour copier le code ci-dessus en mode collage:

    scala>: coller

    [copier/coller]

    [Ctrl + D]

Edit: Comme Antoras mentionné, il devrait être un bug du compilateur, peut-être la version scala pourrait être utile: scala 2.9.0.1 (après un test rapide, toujours là dans la version 2.9.1RC2)

Répondre

2

Cela semble être un bug du compilateur. J'ai analysé la sortie du compilateur AST (avec fsc -Xprint:typer <name_of_file>.scala). Il interprète les deux comme étant les mêmes:

... 
    final <synthetic> object C extends java.lang.Object with ScalaObject with Serializable { 
     def this(): object test.Test.C = { 
     C.super.this(); 
     () 
     }; 
     final override def toString(): java.lang.String = "C"; 
     case <synthetic> def unapply[X >: Nothing <: test.Test.A](x$0: test.Test.C[X]): Option[X] = if (x$0.==(null)) 
     scala.this.None 
     else 
     scala.Some.apply[X](x$0.x); 
     case <synthetic> def apply[X >: Nothing <: test.Test.A](x: X): test.Test.C[X] = new test.Test.C[X](x); 
     protected def readResolve(): java.lang.Object = Test.this.C 
    }; 
... 
    final object D extends java.lang.Object with ScalaObject { 
     def this(): object test.Test.D = { 
     D.super.this(); 
     () 
     }; 
     def unapply[X >: Nothing <: test.Test.A](d: test.Test.D[X]): Option[X] = if (d.eq(null)) 
     scala.None 
     else 
     scala.Some.apply[X](d.x) 
    }; 
... 

La signature de méthode des deux méthodes non appliquées est identique.

De plus, le code fonctionne bien (comme prévu en raison de méthodes identiques):

trait A { 
    def m = "hello" 
} 

class AA extends A 

sealed trait B[X <: A]{ val x: X } 

case class C[X <: A](x: X) extends B[X] 

class D[X <: A](val x: X) extends B[X] 

object D { 
    def apply[X <: A](x: X) = new D(x) 
    def unapply[X <: A](d: D[X]): Option[X] = 
    if (d eq null) None 
    else Some(d.x) 
} 

def ext[X <: A](b: B[X]) = b match { 
    case C(x) => Some("c:"+x.m) 
    case D(x) => Some("d:"+x.m) 
    case _ => None 
} 
println(ext(C[AA](new AA()))) 
println(ext(D[AA](new AA()))) 
+0

Pensez-vous que nous avons assez de matériel pour ouvrir un billet? – Nicolas

+0

Oui, je pense que c'est assez. Il y a un avertissement mais néanmoins le code fonctionne bien. En outre, le code généré fonctionne également bien et est identique. – sschaef

Questions connexes