问题
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 List
s. Since lists are the default implementation of Seq
, this is what you're seeing when you use Seq(a, b, ...)
.
The extractor for Seq
s 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