代码之家  ›  专栏  ›  技术社区  ›  Jesper

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

  •  126
  • Jesper  · 技术社区  · 14 年前

    自从Scala 2.7.2以来 Manifest 准确地工作,为什么/什么时候需要使用它?

    博客帖子 Manifests: Reified Types 作者Jorge Ortiz解释了其中的一些,但没有解释如何与 context bounds .

    ClassManifest ,有什么区别 显示

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

    4 回复  |  直到 7 年前
        1
  •  201
  •   Mitch Blevins    14 年前

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

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

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

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

     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")
      }
    
        2
  •  26
  •   Community Egal    7 年前

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

    换句话说

    你什么时候需要它?

    when Scala 2.10 was released .

        3
  •  25
  •   Community Egal    7 年前

    不是一个完整的答案,但是关于 Manifest ClassManifest ,您可以在 Scala 2.8 Array paper

    剩下的唯一问题是如何实现泛型数组创建。与Java不同,Scala允许创建新的实例 Array[T] 哪里 T 是类型参数。既然Java中不存在统一的数组表示,那么如何实现这一点呢?

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

    还有一个 较弱的形式 命名 它可以通过只知道类型的顶级类来构造,而不必知道它的所有参数类型 .
    创建数组需要这种类型的运行时信息。

    例子:

    我们需要通过传递 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 
    } 
    

    作为一种简写形式,可以在type参数上使用context bound1 相反,

    SO question for illustration )

    ,给出:

    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 
    } 
    

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

        4
  •  1
  •   Tomer Ben David    8 年前

    我们也走吧 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"
      }
    }
    

    我们可以看到 显示 function 搜索隐式 m: Manifest[T] 满足 type parameter 您在我们的示例代码中提供了 manifest[String]

    if (m <:< manifest[String]) {
    

    您正在检查当前 implicit m 在函数中定义的类型 清单[String] 作为 显示 是类型的函数 manifest[T] 它会搜索一个特定的 清单[String]