2011-08-10 13 views
6

Według specyfikacji Scala, ekstraktor zbudowany według klas przypadek jest następujący (specyfikacja scala §5.3.2):Różnica między domowym wyciąg i case class ściągacza

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

Ze względów wykonawczych, chcę być w stanie naśladować zachowanie tego ekstraktora w klasie nieobjętej przypadkiem. Jednak moja implementacja nie powiela tego samego zachowania.

Oto przykład różnicy mam:

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 
} 

Mam następujące ostrzeżenie:

<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) 

Wskazówka ostrzeżenie pojawia się tylko w przypadku D w przypadku klasy nie obudowa textractor. Czy masz pojęcie o przyczynie ostrzeżenia/o tym, co powinienem zrobić, aby uniknąć tego ostrzeżenia?

Uwaga: Jeśli chcesz przetestować go w REPL, najprostszym sposobem jest:

  1. Aby aktywować niesprawdzony ostrzeżenie

    scala>: moc

    scala> settings.unchecked .value = true

  2. Aby skopiować powyższy kod w trybie wklejania:

    scala>: pasta

    [copy/paste]

    [Ctrl + D]

Edit: Jak wspomniano Antoras powinno być błąd kompilatora, może wersja scala może być użyteczny: scala 2.9.0.1 (po szybkim teście, wciąż w scala 2.9.1RC2)

Odpowiedz

2

To wydaje się być błąd kompilatora. Przeanalizowałem dane wyjściowe kompilatora AST (z fsc -Xprint:typer <name_of_file>.scala). Interpretuje on obie wartości jako takie:

... 
    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) 
    }; 
... 

Podpis metody dla obu metod nie jest identyczny.

Ponadto kod działa poprawnie (zgodnie z oczekiwaniami z powodu identycznych metod):

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

Czy uważasz, że mamy wystarczająco dużo materiału, aby otworzyć bilet? – Nicolas

+0

Tak, myślę, że to wystarczy. Pojawiło się ostrzeżenie, ale mimo to działa poprawnie. Ponadto wygenerowany kod działa również dobrze i jest identyczny. – sschaef