Scala阵列与矢量

Lui*_*hys 9 arrays scala vector

Scala newb ......我很困惑

object myApp extends App {
  println("Echo" + (args mkString " "))
}
Run Code Online (Sandbox Code Playgroud)

"args"是类型Array [String],但在scaladoc中,Array没有这样的方法.mkString是Vector的一种方法,但我没有看到两者之间的任何继承链接.那么为什么我们可以在args上使用mkString方法呢?

Kev*_*vin 17

我不是scala专家(远非它!)但我认为答案是隐式转换(请参阅scala.Predef参考资料)和WrappedArray.scala.

特别是,Predef具有以下隐式转换:

implicit def genericWrapArray [T] (xs: Array[T]): WrappedArray[T] 
Run Code Online (Sandbox Code Playgroud)

而WrappedArray有一个mkString方法.当scala在Array上找不到mkString方法时,它会查找到类型的隐式转换.

http://www.scala-lang.org/api/current/scala/Predef $ .html

http://www.scala-lang.org/api/current/scala/collection/mutable/WrappedArray.html

  • 谢谢,我没有隐含的转换头.WrappedArray和Vector都从他们共享的T​​raversableOnce特征中获取mkString方法.如果scaladoc在类的定义中告诉你什么是隐式defs,那么可能会有用吗? (2认同)

huy*_*hjl 12

扩展了Kevin的答案,并解释了为什么scaladoc不可能告诉你隐含的转换存在的原因:只有当你的代码不能编译时,隐式转换才会发挥作用.

您可以将其视为编译期间激活的类型错误的错误恢复机制.在这种情况下,Array[String]没有mkString方法.此代码无法编译,因为该方法不存在Array[T].但在放弃之前,编译器会在范围内寻找隐式转换.

它会Predef在范围内带来一些隐式转换,并且会在此处应用.

找出适用的隐式转换可以通过使用-Xprint:typer标志进行编译来完成.在这种情况下,它将打印:

$ scalac -d classes -Xprint:typer A.scala
[[syntax trees at end of typer]]// Scala source: A.scala
package <empty> {
  final object myApp extends java.lang.Object with App with ScalaObject {
    def this(): object myApp = {
      myApp.super.this();
      ()
    };
    scala.this.Predef.println("Echo ".+(scala.this.Predef.refArrayOps[String](myApp.this.args).mkString(" ")))
  }
}
Run Code Online (Sandbox Code Playgroud)

所以你可以看到Predef.refArrayOps实际上是使用的隐式转换.它将您的数组转换为ArrayOps[String]具有mkString方法的数组.

因此,考虑到这一点,你就会明白为什么scaladoc对于Array不能告诉你隐式转换可以申请什么.它可能是任何东西.事实上,它完全基于没有这种方法的事实.只有编译器才会知道基于代码发现的隐式内容.

您甚至可以定义自己的隐式转换:

object myApp extends App {
  implicit def myImplicit(arr:Array[String]) = new {
    def mkString(s:String) = arr.length + s
  }
  println("Echo " + (args mkString(" ")))
}
Run Code Online (Sandbox Code Playgroud)

这将产生以下影响:

$ scala -cp classes myApp a b c
Echo 3
Run Code Online (Sandbox Code Playgroud)

显然scaladoc无法证明这一点.请注意,Eclipse Scala插件可以mkString通过按F3(最终进入TraversableOnce)来实现.