Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is a match word omitted in Scala?

Tags:

scala

In Scala, you can do

list.filter { item =>
    item match {
      case Some(foo) => foo.bar > 0
    }
}

But you can also do the quicker way by omitting match:

list.filter {
  case Some(foo) => foo.bar > 0
}

How is this supported in Scala? Is this new in 2.9? I have been looking for it, and I can figure out what makes this possible. Is it just part of the Scala compiler?

like image 816
Amir Raminfar Avatar asked Aug 23 '11 21:08

Amir Raminfar


2 Answers

Edit: parts of this answer are wrong; please refer to huynhjl's answer.


If you omit the match, you signal the compiler that you are defining a partial function. A partial function is a function that is not defined for every input value. For instance, your filter function is only defined for values of type Some[A] (for your custom type A).

PartialFunctions throw a MatchError when you try to apply them where they are not defined. Therefore, you should make sure, when you pass a PartialFunction where a regular Function is defined, that your partial function will never be called with an unhanded argument. Such a mechanism is very useful e.g. for unpacking tuples in a collection:

val tupleSeq: Seq[(Int, Int)] = // ...
val sums = tupleSeq.map { case (i1, i2) => i1 + i2 }

APIs which ask for a partial function, like the collect filter-like operation on collections, usually call isDefinedAt before applying the partial function. There, it is safe (and often wanted) to have a partial function that is not defined for every input value.

So you see that although the syntax is close to that of a match, it is actually quite a different thing we're dealing with.

like image 92
Jean-Philippe Pellet Avatar answered Oct 09 '22 22:10

Jean-Philippe Pellet


The language specification addresses that in section 8.5. The relevant portions:

An anonymous function can be defined by a sequence of cases

{ case p1 => b1 ... case pn => bn }

If the expected type is scala.Functionk[S1, ..., Sk, R] , the expression is taken to be equivalent to the anonymous function:

(x1 : S1, ..., xk : Sk) => (x1, ..., xk) match {
  case p1 => b1 ... case pn => bn
}

If the expected type is scala.PartialFunction[S, R], the expression is taken to be equivalent to the following instance creation expression:

new scala.PartialFunction[S, T ] {
  def apply(x: S): T = x match {
    case p1 => b1 ... case pn => bn
  }
  def isDefinedAt(x: S): Boolean = {
    case p1 => true ... case pn => true
    case _ => false
  }
}  

So typing the expression as PartialFunction or a Function influences how the expression is compiled.

Also trait PartialFunction [-A, +B] extends (A) ⇒ B so a partial function PartialFunction[A,B] is also a Function[A,B].

like image 35
huynhjl Avatar answered Oct 09 '22 23:10

huynhjl