使用视图时匹配错误

Lui*_*hys 6 scala view pattern-matching

List(1,2,3,4).sliding(2).map({ case List(a, b) => a < b }).forall(identity)
Run Code Online (Sandbox Code Playgroud)

编译并返回true(尽管警告说匹配并非详尽无遗).

List(1,2,3,4).view
   .sliding(2).map({ case List(a: Int, b: Int) => a < b }).forall(identity)
Run Code Online (Sandbox Code Playgroud)

编译(只要我们包括类型注解ab),但抛出一个MatchError:

scala.MatchError: SeqViewC(...) (of class scala.collection.SeqViewLike$$anon$1)
        at $anonfun$1.apply(<console>:12)
        at $anonfun$1.apply(<console>:12)
        at scala.collection.Iterator$$anon$19.next(Iterator.scala:335)
        at scala.collection.Iterator$class.forall(Iterator.scala:663)
        at scala.collection.Iterator$$anon$19.forall(Iterator.scala:333)
Run Code Online (Sandbox Code Playgroud)

为什么?

huy*_*hjl 7

有趣的是,列表提取器List.unapplySeq无法提取SeqViewLike对象,这就是为什么会出现匹配错误.但另一方面Seq可以.你可以这样看:

scala> val seqView = List(1,2).view.sliding(2).next
seqView: scala.collection.SeqView[Int,List[Int]] = SeqViewC(...)

scala> val List(a, b, _*) = seqView

scala.MatchError: SeqViewC(...) 

scala> val Seq(a, b, _*) = seqView
a: Int = 1
b: Int = 2
Run Code Online (Sandbox Code Playgroud)

所以修复你的第二行将是:

List(1,2,3,4).view.sliding(2).map({ case Seq(a, b) => a < b }).forall(identity)
// res: Boolean = true
Run Code Online (Sandbox Code Playgroud)

所以问题是List(1,2,3,4).view返回一个SeqView.

注意,sliding已经返回一个Iterator,所以List(1,2,3,4).sliding(2)是懒惰的意思.可能view没有必要.


Mal*_*lio 6

好吧,一个列表的视图不是一个列表,它是一个SeqView,它是一个Seq.以下是正确的事情:

List(1,2,3,4).view
   .sliding(2).map({ case Seq(a: Int, b: Int) => a < b }).forall(identity)
Run Code Online (Sandbox Code Playgroud)