2015-06-14 16 views
2
的可迭代

让我们考虑下面的定义以整数的嵌套可迭代结构中添加了所有元素:阵列阵列作为Iterables

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(如列表)一起工作。我怎样才能避免这个错误?它的基本原理是什么?猜测这与Java本身的数组本身有关,但在这种情况下不知道具体细节。

谢谢

+1

应该接受'可迭代[可迭代[INT]]'而不是方法?因为这为我编译。 –

+0

你说得对。我错误地复制了代码。现在它已被纠正。谢谢。错误依然存在。 – pepeStck

回答

3

它不工作,因为Scala需要使用2隐式转换成一排,从Array[Array[Int]]Iterable[Iterable[Int]],它(目的地)不这样做。

你可以指定外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

Two implicit conversions exist in scala.Predef that are frequently applied to arrays: a conversion to mutable.ArrayOps and a conversion to mutable.WrappedArray (a subtype of scala.collection.Seq). Both types make available many of the standard operations found in the Scala collections API. The conversion to ArrayOps is temporary, as all operations defined on ArrayOps return an Array, while the conversion to WrappedArray is permanent as all operations return a WrappedArray.

The conversion to ArrayOps takes priority over the conversion to WrappedArray.

+0

谢谢。直接进行2次隐式转换会出现什么问题? – pepeStck

+1

@ppgllrd:我找不到任何官方原因,但我的猜测是,它会大大增加可能的转换次数,并且不值得。再加上(简单的)隐式转换已经使得很难理解一段代码,我真的不想尝试和理解'嵌套'隐式转换。 – Marth

+0

再次感谢。这些数组与其他Scala数据结构的不规则性是我不太喜欢这种伟大的编程语言的事情之一。支付使用强调JVM的高效阵列的价格。 – pepeStck

-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] ... 

正如你可以看到Array不涉及Iterable[A]特质。

您可以通过实例调用toIterable解决这个问题:

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

非常感谢加文,但是让我感兴趣的是,如果我删除嵌套,阵列可以用作Iterables。例如,'def add2(xs:Iterable [Int])= xs.sum'可以通过'add2(Array(1,2,3))'正常工作。 – pepeStck