pattern match returns a different result for ArrayBuffer and Seq

感情迁移 提交于 2019-12-12 19:04:30

问题


In the sample below, there is a function seqResult that pattern matches against a Seq. Another function that accepts variable arguments calls seqResult and passes in an ArrayBuffer. This causes the pattern match result to be different when called with a Seq or with an ArrayBuffer.

With a Seq the matcher hits case head :: rest => ..., with an ArrayBuffer the matcher hits case Seq(one, two) => ....

Is this a bug? Is there anyway to safeguard against this?

If it's not a bug, what is a safe way to match a list of 1 or more entries that would work for Seq(a,b) and ArrayBuffer(a,b)?

def seqResult(arr:Seq[String]) = arr match {
  case Nil =>  "Nil"
  case head :: Nil => "head :: Nil"
  case head :: rest => "head :: rest"
  case Seq(one, two) => "one, two"
  case _ => "other"
}

def varArgResult(args:String*) = seqResult(args)

val ab = varArgResult("one", "two")
val se = seqResult(Seq("one", "two"))

println(ab) //=> "one, two"
println(se) //=> "head :: rest"

回答1:


:: is an extractor object for Lists. Since lists are the default implementation of Seq, this is what you're seeing when you use Seq(a, b, ...).

The extractor for Seqs is +:.




回答2:


args: String* is actually Array

Seq() constructor uses builder based on ListBuffer so as the result we have List data type.

object Seq extends SeqFactory[Seq] {
  def newBuilder[A]: Builder[A, Seq[A]] = new mutable.ListBuffer
}

...

println(Seq("one", "two"))

List(one, two)

head::rest is syntax sugar for List matching and can be represented as List(head, rest) which is match se in your case.



来源:https://stackoverflow.com/questions/35727584/pattern-match-returns-a-different-result-for-arraybuffer-and-seq

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!