What is the idiomatic way to pattern match sequence comprehensions?
Well, you can pattern-match any sequence:
case Seq(a, b, rest @ _ *) =>
For example:
scala> def mtch(s: Seq[Int]) = s match {
| case Seq(a, b, rest @ _ *) => println("Found " + a + " and " + b)
| case _ => println("Bah")
| }
mtch: (s: Seq[Int])Unit
Then this will match any sequence with more than (or equal to) 2 elements
scala> mtch(List(1, 2, 3, 4))
Found 1 and 2
scala> mtch(Seq(1, 2, 3))
Found 1 and 2
scala> mtch(Vector(1, 2))
Found 1 and 2
scala> mtch(Vector(1))
Bah
letmaik
All original source snippets I post on stackoverflow are dedicated to the public domain. Do with them as you see fit.
Updated on June 05, 2022Comments
-
letmaik almost 2 years
val x = for(i <- 1 to 3) yield i x match { case 1 :: rest => ... // compile error }
constructor cannot be instantiated to expected type; found : collection.immutable.::[B] required: scala.collection.immutable.IndexedSeq[Int]
This is the same problem as MatchError when match receives an IndexedSeq but not a LinearSeq.
The question is, how to do it right? Adding
.toList
everywhere doesn't seem right. And creating an own extractor which handles everySeq
(as described in the answer of the other question) would lead to a mess if everybody would do it...I guess the question is, why can't I influence what the return type of sequence comprehensions is, or: why isn't such a generalized
Seq
extractor part of the standard library? -
letmaik almost 12 yearsI get scala.MatchError: Vector(1, 2, 3) (of class scala.collection.immutable.Vector) with that. Isn't it possible to only match case classes like that?
-
oxbow_lakes almost 12 yearsIt's possible to match anything with an extractor - in this case, anything with an
unapplySeq
method. -
letmaik almost 12 yearsSomewhere I read that instead of using
List
in method signatures it's better to useSeq
if that also describes the problem. So if I have Seq everywhere, should I then always use Seq(..) pattern matching as the idiomatic way? Because with Seq I probably shouldn't match on List or :: anyway. Or wait for 2.10 and use +: everywhere? -
oxbow_lakes almost 12 yearsWell, 2.10 is several months away. I would usually use
List
myself, unless I am converting some huge data structure, in which case pattern-matching might not be the best bet anyway. If you are just testing for emptiness, you can always useheadOption
-
letmaik almost 12 yearsWhat I actually do now is matching
Seq()
for empty seqs,Seq(a,b)
for fixed numbers of elements anda +: rest
for head tail matching. I actually copied the relevant extractors into my project and created package objects with+:
and:+
for each package so that I don't have to import anything and can just delete those once 2.10 comes out.