数组数组作为Iterables的Iterable

时间:2015-06-14 23:56:43

标签: arrays scala iterable

让我们考虑以下定义来添加Ints的嵌套Iterable结构中的所有元素:

def add(xss : Iterable[Iterable[Int]]) : Int = xss.map(_.sum).sum

但是,评估以下表达式会产生类型错误:

   scala> add(Array(Array(1,2,3)))
   <console>:9: error: type mismatch;
   found   : Array[Array[Int]]
   required: Iterable[Iterable[Int]]
                add(Array(Array(1,2,3)))
                         ^

该功能与其他Iterables(如Lists)一样正常工作。我该如何避免这个错误?它的理由是什么?猜猜这与使用Java本机的Arrays有关,但在这种情况下不知道具体细节。

由于

2 个答案:

答案 0 :(得分:4)

它不起作用,因为Scala需要连续使用2个隐式转换才能从Array[Array[Int]]转到Iterable[Iterable[Int]],而它(故意)不会这样做。< / p>

您可以指定外部Array的类型:

scala> add(Array[Iterable[Int]](Array(1,2,3)))
res4: Int = 6

或将其元素转换为Iterable[Int](从而绕过隐式转换):

scala> add(Array(Array(1,2,3)).map(_.toIterable))
res5: Int = 6

问题来自于Scala的Array[T]只是Java T[]的代表。使Array[T]的行为与通常的Scala集合相似的是Predef中的隐式转换。

来自Array's documentation

  

scala.Predef 中经常存在两个隐式转换   应用于数组:转换为 mutable.ArrayOps   并转换为 mutable.WrappedArray scala.collection.Seq 的子类型)。两种类型都提供了许多标准   Scala集合API中的操作。转换为    ArrayOps 是临时的,因为 ArrayOps 上定义的所有操作都返回   数组,而转换为 WrappedArray 是永久性的,因为所有   操作返回 WrappedArray

     

转换为 ArrayOps 优先于转换为    WrappedArray

答案 1 :(得分:-1)

你的直觉是正确的。请参阅Array类型签名:

final class Array[T] extends java.io.Serializable with java.lang.Cloneable

Seq类型签名形成鲜明对比:

trait Seq[+A] extends Iterable[A] with collection.Seq[A] ...

正如您所看到的,ArrayIterable[A]特征无关。

您可以通过在实例上调用toIterable来解决此问题:

scala> add(Array(Array(1,2,3).toIterable).toIterable)
res1: Int = 6