根据Scaladoc,map
类中没有名为Array
的方法,但implicit def intArrayOps (xs: Array[Int]): ArrayOps[Int]
中定义了隐式函数scala.Predef
。因此,如果您愿意,可以在map
上应用Array(1,2,3,4)
。但我感到困惑的是,map
结果的类型为Array[Int]
,而不是ArrayOps[Int]
。这是我的测试:
scala> val array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)
scala> array.map(x => x)
res18: Array[Int] = Array(1, 2, 3, 4)
scala> res18.isInstanceOf[Array[Int]]
res19: Boolean = true
scala> res18.isInstanceOf[scala.collection.mutable.ArrayOps[Int]]
warning: there wre 1 unchecked warnings; re-run with -unchecked for details
res20: Boolean = false
答案 0 :(得分:11)
它确实返回了一个数组,按照预期方便,没有理由需要一个ArrayOps,它只是为数组提供额外的方法。该文档是错误的。
该例程实际上未在ArrayOps中实现。作为大多数收集方法,它继承自TraversableLike。你在doc中看到了两种map方法:
def map [B] (f: (T) ⇒ B): ArrayOps[B]
def map [B, That] (f: (T) ⇒ B)(implicit bf: CanBuildFrom[Array[T], B, That]): That
仅存在第二个(继承自TraversableLike)。它旨在允许在一个地方(可遍历的地方)实施地图,同时总是提供最好的行为。例如,String是Seq [Char]的一个,如果你用一个函数从一个字符映射到另一个字符,你得到一个String,但是如果你从集合映射到Int,结果不能是一个字符串,它只是一个Seq。文章fighting the bit rot with types中详细解释了这一点。
但是,这会产生一个非常复杂的签名,这不会反映使用该方法的简单性,并且在大多数情况下都会生成非常差的文档(通常您必须追逐隐式作用域中的CanBuildFrom才能工作)。这在this most famous scala question of stack overflow中讨论过。因此扩展了工具scaladoc,以便可以出现与预期用法相对应的更简单的条目。如果您查看引入例程的GenTraversableLike
source,您将在scaladoc for map中看到以下内容(以及许多方法中的类似内容)
@usecase def map[B](f: A => B): $Coll[B]
子类型添加在他们的文档@define Coll <className>
中,并且地图(以及其他)显示简化的签名,标记为[用例]。在ArrayOps
的{{3}}中,@define Coll ArrayOps
应该是Array
。
答案 1 :(得分:2)
您可以将REPL与-Xprint:typer选项一起使用,以查看正在发生的事情。以下是map方法的输出,重新格式化以便于阅读:
$ scala -Xprint:typer
scala> Array(1,2,3,4).map(x => x)
[[syntax trees at end of typer]]// Scala source: <console>
// some lines deleted
private[this] val res0: Array[Int] =
scala.this.Predef.intArrayOps(scala.Array.apply(1, 2, 3, 4))
.map[Int, Array[Int]]
(( (x: Int) => x ))
(scala.this.Array.canBuildFrom[Int](reflect.this.Manifest.Int));
这样简化包名称就是这样:
intArrayOps(Array(1,2,3,4)) // converts to ArrayOps
.map[Int, Array[Int]] // calls map with parameter lists below
((x:Int) => x) // pass identity function as fisrt param
(Array.canBuildFrom[Int]// pass builder for Array[Int] as second param
(Manifest.Int)) // pass class manifest for Int
ArrayOps
(第一行)。它返回ArrayOps[Int]
。ArrayOps.map[Int, Array[Int]]
方法。然后就像didierd解释的那样,map
的原始签名 - 而不是简化签名 - 表明推断的返回类型将是Array[Int]