2012-09-29 18 views
6

Estoy aprendiendo el concepto de manifiestos de Scala y tengo un conocimiento básico de cómo usarlo en algunos casos simples. Lo que me desconcierta es ¿qué es OptNanifest y NoManifest? Nunca he visto y luego usado. ¿Alguien puede dar un ejemplo de dónde son necesarios/útiles?¿Para qué es el OptManifest y NoManifest de Scala?

(veo que Scala 2.10 reemplaza el concepto de Manifest s con TypeTags pero hasta 2.10 es definitiva tenemos que utilizar Manifest s.)

Respuesta

6

Supongamos que tenemos la siguiente clase de caso y tipo de alias:

scala> case class Foo[A](a: A) 
defined class Foo 

scala> type F = Foo[_] 
defined type alias F 

ahora podemos (no muy útil) hacer una lista de cosas del tipo F:

scala> val foos: List[F] = List(Foo(1), Foo("a"), Foo('a)) 
foos: List[F] = List(Foo(1), Foo(a), Foo('a)) 

Y podemos convertir esto en una matriz:

scala> foos.toArray 
res0: Array[F] = Array(Foo(1), Foo(a), Foo('a)) 

Así que está claro que el compilador es capaz de encontrar el manifiesto que necesita como un argumento implícito al método toArray en List. Pero si nos preguntamos por un viejo y simple Manifest para F, obtenemos un error:

scala> manifest[F] 
<console>:11: error: overloaded method value classType with alternatives: 
    (prefix: scala.reflect.Manifest[_],clazz: Class[_],args: scala.reflect.Manifest[_]*)scala.reflect.Manifest[F] <and> 
    (clazz: Class[F],arg1: scala.reflect.Manifest[_],args: scala.reflect.Manifest[_]*)scala.reflect.Manifest[F] <and> 
    (clazz: Class[_])scala.reflect.Manifest[F] 
cannot be applied to (java.lang.Class[Foo[_$1]], scala.reflect.Manifest[_$1]) 
       manifest[F] 

Así que está claro que el compilador está teniendo problemas para usar los manifiestos para representar el comodín en nuestra typeAlias.

El motivo toArray funciona es que espera un ClassManifest, no solo un Manifest. Y de hecho podemos obtener un ClassManifest para F sin problemas, precisamente porque ClassManifest usa OptManifest para representar su tipo argumentos-a diferencia de Manifest, cuyos tipos de argumentos son solo otras cosas del tipo Manifest.

scala> classManifest[F] 
res2: ClassManifest[F] = Foo[<?>] 

Eso <?> es la representación de cadena de NoManifest. Juega el rol de None aquí, permitiendo que el compilador represente la información de clase sobre el tipo F (que es todo lo que necesitamos para crear una matriz, afortunadamente), sin decir nada sobre los argumentos de tipo de F más allá de "no, puedo" t modelo eso ".

Cuestiones relacionadas