2012-09-29 18 views
6

Poznaję koncepcję manifestów Scala i mam podstawową wiedzę na temat jej wykorzystania w niektórych prostych przypadkach. Co mnie zastanawia, dla których jest OptNanifest i ? Nigdy nie widziałem, żeby był używany. Czy ktoś może podać przykład, gdzie są one potrzebne/przydatne?Do czego służą OptManifest i NoManifest firmy Scala?

(widzę, że Scala 2,10 zastępuje pojęcie Manifest sz TypeTags ale do 2.10 jest ostateczna musimy użyć Manifest s.)

Odpowiedz

6

Załóżmy, że mamy następujące klasy przypadek i rodzaj Alias:

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

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

Możemy teraz (niezbyt skutecznie) zrobić listę rzeczy typu F:

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

I możemy przekształcić tablicy:

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

Tak wyraźnie kompilator jest w stanie znaleźć manifeście musi jako niejawny argument do metody toArray na List. Ale jeśli poprosić o zwykły stary Manifest dla F otrzymujemy błąd:

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] 

więc jest oczywiste, że kompilator ma problemy z wykorzystaniem manifesty do reprezentowania wieloznaczny w naszym typu alias.

Powodem, dla którego toArray działa, jest oczekiwanie, że ClassManifest, a nie tylko Manifest. I faktycznie możemy uzyskać ClassManifest dla F bez żadnych problemów, właśnie dlatego, że ClassManifest używa do reprezentowania swoich argumentów typu - w przeciwieństwie do Manifest, których argumenty typu są po prostu inne rzeczy typu Manifest.

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

To <?> jest reprezentacją ciąg NoManifest. Odgrywa on tutaj rolę None, umożliwiając kompilatorowi przedstawienie informacji o klasie o typie F (który jest wszystkim, czego potrzebujemy do stworzenia tablicy, na szczęście), nie mówiąc nic o argumentach typu z F poza "nie, mogę" t modelu, który ".

Powiązane problemy