Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: Pattern matching Seq[Nothing]

Tags:

scala

I am trying to match the case where a Seq contains Nothing.

models.Tasks.myTasks(idUser.toInt) match {
  case tasks => tasks.map {
    task => /* code here */
  }
  case _ => "" //matches Seq(models.Tasks)
}

How is Seq[Nothing] represented in pattern matching ?

like image 737
Andrew Avatar asked Oct 25 '12 11:10

Andrew


2 Answers

Matching against an empty sequence looks like this:

val x: Seq[Nothing] = Vector()

x match { 
  case Seq() => println("empty sequence") 
}

EDIT: Note that this is more general than case Nil since Nil is a subclass only of List, not Seq in general. Strangely, the compiler is ok with matching against Nil if the type is explicitly annotated as Seq, but it will complain if the type is any non-List subclass of Seq. Thus you can do this:

(Vector(): Seq[Int]) match { case Nil => "match" case _ => "no" }

but not this (fails with compile-time error):

Vector() match { case Nil => "match" case _ => "no" }
like image 118
dhg Avatar answered Nov 11 '22 09:11

dhg


Assuming I understand what you mean correctly, a sequence that contains nothing is empty, which is Nil:

case Nil => //do thing for empty seq

This works even though you're dealing with Seqs, not Lists:

scala> Seq()
res0: Seq[Nothing] = List()

scala> Seq() == Nil
res1: Boolean = true

Some more REPL output to show that this works absolutely fine with other subclasses of Seq:

scala> Nil
res3: scala.collection.immutable.Nil.type = List()

scala> val x: Seq[Int] = Vector()
x: Seq[Int] = Vector()

scala> x == Nil
res4: Boolean = true

scala> x match { case Nil => "it's nil" }
res5: java.lang.String = it's nil

scala> val x: Seq[Int] = Vector(1)
x: Seq[Int] = Vector(1)

scala> x match { case Nil => "it's nil"; case _ => "it's not nil" }
res6: java.lang.String = it's not nil

As can be seen from the above output, Nil is a type all of it's own. This question has some interesting things to say on the matter.

But @dhg is correct that if you manually create a specific subtype such as vector, the match does not work:

scala> val x = Vector()
x: scala.collection.immutable.Vector[Nothing] = Vector()

scala> x match { case Nil => "yes"} 
<console>:9: error: pattern type is incompatible with expected type;
 found   : object Nil
 required: scala.collection.immutable.Vector[Nothing]
              x match { case Nil => "yes"} 

Having said that, I don't know why you would need to force your objects to be a referred to as a specific concrete subclass very often.

like image 27
Russell Avatar answered Nov 11 '22 10:11

Russell