Scala`view`:`force`不是`Seq`的成员

时间:2016-11-09 22:57:08

标签: scala collections scala-collections

似乎应用mapfilter会以某种方式将view转换为Seqdocumentation包含以下示例:

> (v.view map (_ + 1) map (_ * 2)).force
res12: Seq[Int] = Vector(4, 6, 8, 10, 12, 14, 16, 18, 20, 22)  

但如果我做类似的事情,我会收到错误:

> val a = Array(1,2,3)
> s.view.map(_ + 1).map(_ + 1).force
<console>:67: error: value force is not a member of Seq[Int]

如果我map超过Array view多次,SeqView成为Seq

> a.view.map(_+1)
res212: scala.collection.SeqView[Int,Array[Int]] = SeqViewM(...)
> a.view.map(_+1).map(_+1)
res211: Seq[Int] = SeqViewMM(...)

我怀疑这种行为可能与Array是一个可变集合有关,因为我无法使用ListVector复制此行为。不过,我可以filter Array view多次{。}}。

1 个答案:

答案 0 :(得分:3)

专业提示:在REPL中调试含义时,来自reify的{​​{1}}是您的朋友。

reflect

按照设计,scala> import reflect.runtime.universe.reify scala> import collection.mutable._ // To clean up reified exprs scala> reify(a.view.map(_ + 1).map(_ * 2)) Expr[Seq[Int]](Predef.intArrayOps($read.a).view.map(((x$1) => x$1.$plus(1)))(IndexedSeqView.arrCanBuildFrom).map(((x$2) => x$2.$times(2)))(Seq.canBuildFrom)) 不会生成另一个IndexedSeqView.arrCanBuildFrom,而是一个普通的IndexedSeqView。但是,从那时起,你会期望SeqView仍然如此。为了实现这一点,传递给第二个SeqView的{​​{1}}应该是CBF,但出于某种原因,我们从map获得了SeqView.canBuildFrom。现在我们知道了这个问题,让我们手动传递Seq并解析错误。

SeqView.canBuildFrom

好的,所以这不是隐式解决方案或编译器或其他任何内容的错误;它是错误的库,因为编译器能够给我们一个很好的理由在这里失败。

scala> a.view.map(_ + 1).map(_ * 2)(collection.SeqView.canBuildFrom) <console>:??: error: polymorphic expression cannot be instantiated to expected type; found : [A]scala.collection.generic.CanBuildFrom[collection.SeqView.Coll,A,scala.collection.SeqView[A,Seq[_]]] (which expands to) [A]scala.collection.generic.CanBuildFrom[scala.collection.TraversableView[_, _ <: Traversable[_]],A,scala.collection.SeqView[A,Seq[_]]] required: scala.collection.generic.CanBuildFrom[scala.collection.SeqView[Int,Array[Int]],Int,?] a.view.map(_ + 1).map(_ * 2)(collection.SeqView.canBuildFrom) ^ 要求scalacCBF的第二个类型参数为Int或其中的超类型,并且由于我们提供的参数需要任何A,我们就是好。第三个是未知的,所以它也可以是任何东西,也是好的。因此,问题出在第一位。

scala> implicitly[collection.SeqView[Int, _] <:< collection.TraversableView[_, _]]
<function1>

这将问题缩小到Array[Int] <: Traversable[_]。它就是。 Array不是Traversable,因此他们在此处失败,并被Seq CBF强制成为Seq

要解决此问题,SeqView需要arrCanBuildFrom IndexedSeqView。这是库中的一个错误。这与Array可变的无关;这真的是因为Array并不是一个真正的集合(它没有实现Traversable)而且必须被强迫进行。