Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala pattern matching on sequences other than Lists

I have the following code which recursively operates on each element within a List

def doMatch(list: List[Int]): Unit = list match {   case last :: Nil  => println("Final element.")   case head :: tail => println("Recursing..."); doMatch(tail) } 

Now, ignoring that this functionality is available through filter() and foreach(), this works just fine. However, if I try to change it to accept any Seq[Int], I run into problems:

  • Seq doesn't have ::, but it does have +:, which as I understand is basically the same thing. If I try to match on head +: tail however, the compiler complains 'error: not found: value +:'
  • Nil is specific to List, and I'm not sure what to replace it with. I'm going to try Seq() if I ever get past the previous problem

Here is how I think the code should look, except it doesn't work:

def doMatch(seq: Seq[Int]): Unit = seq match {   case last +: Seq() => println("Final element.")   case head +: tail  => println("Recursing..."); doMatch(tail) } 

Edit: So many good answers! I'm accepting agilesteel's answer as his was the first that noted that :: isn't an operator in my example, but a case class and hence the difference.

like image 251
Zecrates Avatar asked Jul 24 '11 14:07

Zecrates


People also ask

How do you match a pattern in Scala?

A pattern match includes a sequence of alternatives, each starting with the keyword case. Each alternative includes a pattern and one or more expressions, which will be evaluated if the pattern matches. An arrow symbol => separates the pattern from the expressions.

Does Scala have pattern matching?

Notes. Scala's pattern matching statement is most useful for matching on algebraic types expressed via case classes. Scala also allows the definition of patterns independently of case classes, using unapply methods in extractor objects.

What is the use of Scala pattern matching?

Pattern matching is a way of checking the given sequence of tokens for the presence of the specific pattern. It is the most widely used feature in Scala. It is a technique for checking a value against a pattern. It is similar to the switch statement of Java and C.

Which method of case class allows using objects in pattern matching?

Case classes are Scala's way to allow pattern matching on objects without requiring a large amount of boilerplate. In the common case, all you need to do is add a single case keyword to each class that you want to be pattern matchable.


1 Answers

As of the ides of March 2012, this works in 2.10+:

  def doMatch(seq: Seq[Int]): Unit = seq match {     case last +: Seq() => println("Final element.")     case head +: tail  => println("Recursing..."); doMatch(tail)   }                                               //> doMatch: (seq: Seq[Int])Unit    doMatch(List(1, 2))                             //> Recursing...                                                   //| Final element. 

More generally, two different head/tail and init/last decomposition objects mirroring append/prepend were added for Seq in SeqExtractors:

List(1, 2) match { case init :+ last => last } //> res0: Int = 2                                               List(1, 2) match { case head +: tail => tail } //> res1: List[Int] = List(2)                                                Vector(1, 2) match { case init :+ last => last } //> res2: Int = 2                                               Vector(1, 2) match { case head +: tail => tail } //> res3: scala.collection.immutable.Vector[Int] = Vector(2) 
like image 83
yakshaver Avatar answered Sep 17 '22 17:09

yakshaver