Question

I am just starting my seemingly steep learning curve with Scala and can't quite grasp how "case" works in partial functions exactly.

I looked at the definition of PartialFunction itself, and there I see a sample like the following:

val isEven: PartialFunction[Int, String] = { 
   case x if x % 2 == 0 => x+" is even" 
}

The part where I am getting stuck is case x if x%2 -- how does Scala know what's what here? What is a formal definition of this "case" statement/keyword?

I think one reason for my confusion is because in Lift I see things like the following(in Actor classes):

override def messageHandler = {
   case SomeKindOfUserMessageClass(id1, param1) => ....
   case AnotherKindOfUserMessageClass(id2) => ....
}

I sort of understand intuitively what's going on here, but I can't assemble some kind of unified definition of how "case" should be used. Even more puzzling to me is how Scala compiler untangles all that.

Was it helpful?

Solution

The thing you're asking about is called pattern matching. A pattern match block can be used with the match keyword, or it can be used to define either a function or a partial function, depending on the context.

Your second example uses extractors. Scala's evaluation of m match { case A(x) => } involves calling A.unapply(m). The companion object of a case class is an extractor (using case classes is more common than actually writing an unapply method).

The Scala Language Specification is a tough read, but sometimes it's worth trying to take a look at, especially if you're looking for formalism. Chapter 8 is about pattern matching. Section 8.4 introduces the idea of using if in a case clause like in your first example.

OTHER TIPS

Under section "Case sequences as partial functions" in page http://www.artima.com/pins1ed/case-classes-and-pattern-matching.html, I came across the following sentences, which I think may be also a good answer to "how 'case' should be used" as well.

A sequence of cases (i.e., alternatives) in curly braces can be used anywhere a function literal can be used. Essentially, a case sequence is a function literal, only more general. Instead of having a single entry point and list of parameters, a case sequence has multiple entry points, each with their own list of parameters. Each case is an entry point to the function, and the parameters are specified with the pattern. The body of each entry point is the right-hand side of the case.

Think of case like matching some condition or to be more specific some pattern. There are various ways in which you can specify a pattern.

case SomeKindOfUserMessageClass(id1, param1) : This says that the value should be of type SomeKindOfUserMessageClass and if yes then destruct the values to the id1 and param1. So it is like a condition with pattern match.

case x if x % 2 == 0: This says the condition is that the value should be divisible by 2 and if yes then bind the value to x OR you can say, bind the value to x and check if it is divisible by 2.

Think of it like a switch statement in other languages.

In PHP, you'd use the word case before each option. In ruby, you'd use the word "when"... and similar in other languages.

It runs top-to-bottom and runs the code for the first pattern that matches. You can match based on value, type, constructor, etc... and it only runs one code block... and checks top to bottom.

It can be in the syntax...

val x = List(1,2,3,4)
x match {
  case Nil => Nil
  case x => x map someFunction
}

or you can use pattern matching in lambda expressions as well.

Check out the course functional programming pinrciples in scala on coursera.org. If you took that, you'd have a good heads tart in scala.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top