This will never work in that definition as you can not wildcard any subsequence except tail in result of unapplySeq
.
But let me suggest a workaround.
Lets define this helper:
object Span {
class Spanner[T](pred: T => Boolean) {
def unapply(seq: Seq[T]) = for {
idx <- Some(seq.indexWhere(pred)) if idx >= 0
(start, elem +: end) = seq.splitAt(idx)
} yield (start, end)
}
def apply[T](pred: T => Boolean) = new Spanner(pred)
}
This allows us to define more interesting matchers like this function:
def splitter[T](from:T, to:T): PartialFunction[Seq[T], Seq[Seq[T]]] = {
val From = Span[T](_ == from)
val To = Span[T](_ == to)
{
case From(prefix, To(middle, postfix)) => Seq(prefix, middle, postfix)
}
}
So if we specialize it to:
val mySplitter = splitter("from", "to").lift
We could get appropriate results:
mySplitter(Seq("1", "2", "to", "3", "4", "from", "5", "6")) // None
mySplitter(Seq("1", "2", "from", "3", "4", "to", "5", "6")) // Some(List(List(1, 2), List(3, 4), List(5, 6)))
Lets try to clarify how compiler understands your syntax, lets define
def splitter2(from: AnyRef, to: AnyRef): PartialFunction[Seq[_], AnyRef] = {
case beginColl :+ `from` +: someElement +: `to` +: tail => (beginColl, someElement, tail)
}
val mySplitter2 = splitter2("from", "to").lift
So if we try to match
mySplitter2(Seq("1", "2", "from", "3", "4 ", "to", "5", "6"))
We'll surely get None
But if we try
mySplitter2(Seq("1", "2", Seq("from", "3", "to", "4", "5")))
Suddenly we getting Some(...)
So compiler just understood your expression as _match element as
beginColl :+ __last
then match __last
as
`from` +: someElement +: `to` +: tail
Which is basically verify this is non-empty Seq
last element of which is
another Seq
that consists of at least three elements, first and third of these are from
and to