Что такое манифест в Scala и когда он вам нужен?
С Scala 2.7.2 есть что-то под названием Manifest который является обходным путем для стирания типа Java. Но как это Manifest работа именно и почему / когда вам нужно использовать его?
в блоге Манифесты: Овеществленные Типы Хорхе Ортис объясняет некоторые из них, но это не объясняет, как использовать его вместе с контексте границ.
кроме того, что такое ClassManifest какая разница с Manifest?
у меня есть некоторый код (часть более крупной программы, не может легко включить его здесь), который имеет некоторые предупреждения в отношении стирания типа; Я подозреваю, что могу решить их с помощью манифестов, но я не уверен точно, как это сделать.
4 ответов:
компилятор знает больше информации о типах, чем может легко представить среда выполнения JVM. Манифест-это способ для компилятора отправить межмерное сообщение в код во время выполнения о потерянной информации о типе.
неясно, будет ли Манифест полезен для ошибок, которые вы видите, не зная более подробно.
def foo[T](x: List[T])(implicit m: Manifest[T]) = { if (m <:< manifest[String]) println("Hey, this list is full of strings") else println("Non-stringy list") } foo(List("one", "two")) // Hey, this list is full of strings foo(List(1, 2)) // Non-stringy list foo(List("one", 2)) // Non-stringy listрешение на основе отражения для этого, вероятно, будет включать проверку каждого элемента списка.
контекстная привязка кажется наиболее подходящей для использования классов типов в scala и хорошо объясняется здесь Debasish Ghosh: http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html
границы контекста также могут просто сделать сигнатуры метода более читаемыми. Например, эта функция может быть переписана используя контекстные границы, например:
def foo[T: Manifest](x: List[T]) = { if (manifest[T] <:< manifest[String]) println("Hey, this list is full of strings") else println("Non-stringy list") }
не полный ответ, но относительно разницы между
ManifestиClassManifest, вы можете найти пример в Scala 2.8Arrayстатьи:единственный оставшийся вопрос - как реализовать создание универсального массива. В отличие от Java, Scala позволяет создавать экземпляр new
Array[T]здесьTпараметр типа. Как это может быть реализовано, учитывая тот факт, что в Java не существует единого представления массива?единственный способ сделать это-потребовать дополнительную информацию о времени выполнения, которая описывает тип
T. В Scala 2.8 имеет новый механизм для этого, который называется Манифест. Объект типаManifest[T]предоставляет полную информацию о типеT.Manifestзначения обычно передаются в неявных параметрах; и компилятор знает, как построить их для статически известных типовT.есть еще слабее форма имени
ClassManifestкоторый может быть построен из знания только класса верхнего уровня типа, не обязательно зная все его типы аргументов.
Именно этот тип информации о времени выполнения требуется для создания массива.пример:
нужно предоставить эту информацию, передав
ClassManifest[T]в метод как неявный параметр:def tabulate[T](len:Int, f:Int=>T)(implicit m:ClassManifest[T]) = { val xs = new Array[T](len) for (i <- 0 until len) xs(i) = f(i) xs }как a сокращенная форма, контекст bound1 может быть использован для параметра типа
Tвместо(см. так вопрос для иллюстрации)
, давая:
def tabulate[T: ClassManifest](len:Int, f:Int=>T) = { val xs = new Array[T](len) for (i <- 0 until len) xs(i) = f(i) xs }при вызове tabulate на тип, такой как
IntилиStringилиList[T], компилятор Scala может создать манифест класса для передачи в качестве неявного аргумента для табуляции.
Манифест был предназначен для овеществления универсальных типов, которые стираются для запуска на JVM (который не поддерживает универсальные типы). Однако у них были некоторые серьезные проблемы: они были слишком упрощены и не могли полностью поддерживать систему типов Scala. Они были такими устаревший в Scala 2.10, и заменяются
TypeTags (которые по существу являются тем, что сам компилятор Scala использует для представления типов и поэтому полностью поддерживает типы Scala). Для получения более подробной информации о разнице, смотрите:
- Scala: что такое тег типа и как его использовать?
- как новые теги типов Scala улучшают (устаревшие) манифесты?
другими словами
когда вам это нужно?
до 2013-01-04, когда Scala 2.10 был выпущен.
давайте также chck out
manifestнаscalaисточники (Manifest.scala), мы видим:Manifest.scala: def manifest[T](implicit m: Manifest[T]) = mИтак, что касается следующего примера кода:
def foo[A](somelist: List[A])(implicit m: Manifest[A]): String = { if (m <:< manifest[String]) { "its a string" } else { "its not a string" } }мы видим, что
manifestfunctionпоиск неявногоm: Manifest[T]что соответствуетtype parameterвы предоставляете в нашем примере кода это былоmanifest[String]. Поэтому, когда вы называете что-то вроде:if (m <:< manifest[String]) {вы проверяете, если ток
implicit mкоторый вы определили в своей функции имеет типmanifest[String]и как тоmanifestявляется функцией типаmanifest[T]он будет искать конкретныйmanifest[String]и он найдет, если есть такой неявный.
Comments