Scala (8): Pattern Matching

Why do we need to know what is pattern matching? The main reason is that in object-oriented programming, program is organized to different layers of class. Pattern matching is going to solve the problem how to probe the layer from outside. You also can treat pattern matching as “switch-case” or “if-else”. But comparing with them, pattern matching is more flexible than them. 

Patterns

Constant Patterns

val times = 1
times match {
  case 1 => "one"
  case 2 => "two"
  case _ => "some other number" // wildcard can make sure to deal with others. 
}

Variable Patterns

times match {
  case i if i == 1 => "one"
  case i if i == 2 => "two"
  case _ => "some other number" // wildcard can be treated as special variable
}
def bigger(o: Any): Any = {
  o match {
    case i: Int if i < 0 => i - 1
    case i: Int => i + 1
    case d: Double if d < 0.0 => d - 0.1
    case d: Double => d + 0.1
    case text: String => text + "s"
  }
}

Constructor Patterns

Here we have to know what is case classes. It is easy to store and match class content by Case Classes. You don’t need to use new to create its instance.

case class Calculator(brand: String, model: String)
val temp = Calculator("hp", "20b")

Case classes are designed to be used in pattern matching.

def calcType(calc: Calculator) = calc match {
  case Calculator("hp", "20B") => "financial"
  case Calculator("hp", "48G") => "scientific"
  case Calculator("hp", "30B") => "business"
  case Calculator(ourBrand, ourModel) => "Calculator: %s %s is of unknown type".format(outBrand, ourModel)
} 
// the last can be written like this: 
// case Calculator(_, _) => "Calculator of unknown type" 
// OR case _ => "Calculator of unknown type" 
// OR case c@Calculator(_, _) => "Calculator: %s of unknown type".format(c)

case class

case class will add some methods for your constructor, including getter, toString, hashCode, equals, etc. The important thing for case is to help implement a companion object, which defines two methods, one is apply, the other is unapply.

Here we use an example to declare case class.

abstract class Expr

case class FibonacciExpr(n: Int) extends Expr {
  require(n >= 0)
}

case class SumExpr(a: Expr, b: Expr) extends Expr 

def value(in: Expr): Int = in match {
  case FibonacciExpr(0) => 0 
  case FibonacciExpr(1) => 1
  case FibonacciExpr(n) => value(SumExpr(FibonacciExpr(n - 1), FibonacciExpr(n - 2)))
  case SumExpr(a, b) => value(a) + value(b)
  case _ => 0
}

println(value(FibonacciExpr(3))) // output: 2

For

In Scala, for is not only to loop every element, which also do pattern matching. Here are some examples to help us understand the meaning.

>>for ((name, "female") <- Set("wang"->"male","zhang"->"female")) println(name)
// output: zhang
>>for ((k, v: Int) <- List(("A"->2), ("B"->"C"))) println(k)
// output: A

Example

Here is an example which uses pattern matching to finish fibonacci.

def fibonacci(in: Any): Int = in match {
  case 0 => 0
  case 1 => 1
  case n: Int => fibonacci(n - 1) + fibonacci(n - 2)
  case _ => 0
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s