Scala中的清单是什么?您什么时候需要它?

Scala中的清单是什么?您什么时候需要它?,scala,manifest,Scala,Manifest,自Scala2.7.2以来,有一种称为Manifest的东西,它是Java类型擦除的一种变通方法。但是Manifest究竟是如何工作的,以及为什么/何时需要使用它 豪尔赫·奥尔蒂斯(Jorge Ortiz)的博客文章解释了其中的一些内容,但没有解释如何与其他人一起使用 另外,什么是ClassManifest,与Manifest有什么区别 我有一些代码(一个更大的程序的一部分,在这里不容易包含它)有一些关于类型擦除的警告;我怀疑我可以通过使用清单来解决这些问题,但我不确定具体如何解决。这不是一个完

自Scala2.7.2以来,有一种称为
Manifest
的东西,它是Java类型擦除的一种变通方法。但是
Manifest
究竟是如何工作的,以及为什么/何时需要使用它

豪尔赫·奥尔蒂斯(Jorge Ortiz)的博客文章解释了其中的一些内容,但没有解释如何与其他人一起使用

另外,什么是
ClassManifest
,与
Manifest
有什么区别


我有一些代码(一个更大的程序的一部分,在这里不容易包含它)有一些关于类型擦除的警告;我怀疑我可以通过使用清单来解决这些问题,但我不确定具体如何解决。

这不是一个完整的答案,但是关于
Manifest
ClassManifest
之间的区别,您可以在以下列表中找到一个示例:

剩下的唯一问题是如何实现通用数组创建。与Java不同,Scala允许创建新的
Array[T]
实例,其中
T
是一个类型参数。考虑到Java中不存在统一的数组表示,如何实现这一点

唯一的方法是需要额外的运行时信息来描述类型
T
。Scala 2.8为此提供了一种新机制,称为清单。
Manifest[T]
类型的对象提供了有关
T
类型的完整信息
清单
值通常以隐式参数传递;编译器知道如何为静态已知类型
T
构造它们

还存在一个名为
ClassManifest
弱形式,它可以通过只知道类型的顶级类来构造,而不必知道它的所有参数类型

创建数组需要这种类型的运行时信息

例如:

需要通过将
ClassManifest[T]
传递到 方法作为隐式参数:

在对类型(如
Int
、或
String
、或
List[T]
)调用tablate时,Scala编译器可以创建一个类清单,作为隐式参数传递到tablate


编译器知道的关于类型的信息比JVM运行时容易表示的要多。清单是编译器在运行时向代码发送关于丢失的类型信息的跨维度消息的一种方式

这与盗贼如何在化石记录和人类“垃圾”DNA中留下编码信息相似。由于光速和引力共振场的限制,它们无法直接通信。但是,如果你知道如何调到他们的信号中去,你可以以你无法想象的方式从中受益,比如决定午餐吃什么或者玩哪个乐透号码

在不知道更多细节的情况下,清单是否有助于您看到的错误还不清楚

清单的一个常见用途是让代码根据集合的静态类型表现出不同的行为。例如,如果您想将列表[字符串]与其他类型的列表区别对待,该怎么办

 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
def foo[T](x:List[T])(隐式m:Manifest[T])={

if(mManifest旨在具体化在JVM(不支持泛型)上运行时删除类型的泛型类型但是,它们有一些严重的问题:它们过于简单化,无法完全支持Scala的类型系统。因此,它们在Scala 2.10中被弃用,并被替换为
TypeTag
s(基本上是Scala编译器本身用来表示类型的,因此完全支持Scala类型)。有关差异的详细信息,请参阅:

换句话说 你什么时候需要它


在2013-01-04年之前,.

让我们在
scala
源(
manifest.scala
)中也勾选
manifest
),我们看到:

关于以下示例代码:

def foo[A](somelist: List[A])(implicit m: Manifest[A]): String = {
  if (m <:< manifest[String]) {
    "its a string"
  } else {
    "its not a string"
  }
}

您正在检查您在函数中定义的当前
隐式m
是否为
清单[String]
类型,并且由于
清单
清单[T]
类型的函数,它将搜索特定的
清单[String]
,它会发现是否存在这种隐式的差异。

邮件列表中已经讨论了清单/类清单的差异,另请参见:它还没有被弃用(但会被弃用),因为Scala反射在2013-01-04之前的2.10中仍然是实验性的,或者如果您正在使用依赖它的API。
 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
  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.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"
  }
}
if (m <:< manifest[String]) {