varias superponer studio resumen lineas graficos graficas decreto corto capitulo scala pattern-matching type-erasure case-class unapply

scala - studio - superponer graficas en r



Scala: no se aplica la clase de caso frente a una implementación manual y el borrado de tipo (2)

No puedo dar una respuesta completa, pero puedo decirle que a pesar de que el compilador genera un método de no aplicación para las clases de caso, cuando el patrón coincide con una clase de caso, no usa ese método de no aplicación. Si prueba -Ybrowse:typer utilizando tanto la coincidencia de casos incorporada como su método de no aplicación, verá que se produce un árbol de sintaxis muy diferente (para la match ) según cuál se use. También puede navegar por las fases posteriores y ver que la diferencia permanece.

¿Por qué Scala no usa la aplicación incorporada? No estoy seguro, aunque puede ser por la razón que mencionas. Y no tengo ni idea de cómo unapply por tu propia unapply . Pero esta es la razón por la que Scala parece evitar mágicamente el problema.

Después de experimentar, aparentemente esta versión de no unapply funciona, aunque estoy un poco confundido acerca de por qué:

def unapply[A,B](value: BlackOrWhite[A,B]): Option[B] = value match { case w: White[_,_] => Some(w.right) case _ => None }

La dificultad con su unapply es que, de alguna manera, el compilador debe estar convencido de que si una White[A,B] BlackOrWhite[C,D] extiende una BlackOrWhite[C,D] entonces B es la misma que la D , que aparentemente el compilador es capaz de resolver en este Versión pero no en la tuya. No estoy seguro de por qué.

Estoy tratando de entender lo que Scala hace con las Clases de Casos que los hace de alguna manera inmunes a las advertencias de borrado de tipos.

Digamos que tenemos la siguiente estructura de clase simple. Es básicamente un Either

abstract class BlackOrWhite[A, B] case class Black[A,B]( val left: A ) extends BlackOrWhite[A,B] case class White[A,B]( val right: B ) extends BlackOrWhite[A,B]

Y estás tratando de usarlo así:

object Main extends App { def echo[A,B] ( input: BlackOrWhite[A,B] ) = input match { case Black(left) => println( "Black: " + left ) case White(right) => println( "White: " + right ) } echo( Black[String, Int]( "String!" ) ) echo( White[String, Int]( 1234 ) ) }

Todo se compila y se ejecuta sin problemas. Sin embargo, cuando intento implementar el método de no unapply yo mismo, el compilador lanza una advertencia. Utilicé la siguiente estructura de clase con la misma clase Main anterior:

abstract class BlackOrWhite[A, B] case class Black[A,B]( val left: A ) extends BlackOrWhite[A,B] object White { def apply[A,B]( right: B ): White[A,B] = new White[A,B](right) def unapply[B]( value: White[_,B] ): Option[B] = Some( value.right ) } class White[A,B]( val right: B ) extends BlackOrWhite[A,B]

Al compilar eso con el indicador -unchecked emite la siguiente advertencia:

[info] Compiling 1 Scala source to target/scala-2.9.1.final/classes... [warn] src/main/scala/Test.scala:41: non variable type-argument B in type pattern main.scala.White[_, B] is unchecked since it is eliminated by erasure [warn] case White(right) => println( "White: " + right ) [warn] ^ [warn] one warning found [info] Running main.scala.Main

Ahora, entiendo el borrado de tipos y he tratado de sortear la advertencia con Manifests (hasta ahora sin ningún resultado), pero ¿cuál es la diferencia entre las dos implementaciones? ¿Las clases de casos están haciendo algo que necesito agregar? ¿Se puede sortear esto con Manifests ?

Incluso intenté ejecutar la implementación de clase de caso a través del compilador de scala con el -Xprint:typer activado, pero el método de no aplicación se parece bastante a lo que esperaba:

case <synthetic> def unapply[A >: Nothing <: Any, B >: Nothing <: Any](x$0: $iw.$iw.White[A,B]): Option[B] = if (x$0.==(null)) scala.this.None else scala.Some.apply[B](x$0.right);

Gracias por adelantado


No puedo darle la respuesta a la diferencia entre la coincidencia de clase de caso y la no aplicación. Sin embargo, en su libro (Odersky, Spoon, Venners) "Programación en Scala" 2nd chptr 26.6 "Extractores versus clases de casos" escriben:

"ellas (clases de casos) generalmente llevan a coincidencias de patrones más eficientes que los extractores, porque el compilador de Scala puede optimizar los patrones sobre las clases de casos mucho mejor que los patrones sobre los extractores. Esto se debe a que los mecanismos de las clases de casos son fijos, mientras que un método de no aplicación o no aplicación en un extractor podría hacer casi cualquier cosa. Tercero, si sus clases de caso se heredan de una clase base sellada, el compilador de Scala verificará nuestra concordancia de patrones en busca de exhaustividad y se quejará si alguna combinación de valores posibles no está cubierta por un patrón. Los controles están disponibles para los extractores ".

Lo que me dice que los dos son más diferentes de lo que uno esperaría a primera vista, sin embargo, sin ser específicos sobre cuáles son las diferencias exactas.