Pattern Matching Basics

FILE : PatternMatching1Demo

At first pattern matching in scala looks like simple switch. You can create a variable and trigger an action according to its value

someValue match {
      case 1 => println("matched 1")
      case other => println(s"matched $other")
 }

The real power of this mechanism is shown when we use case classes - then we can easily decompose those values to handle properly each case.

case class SimpleCaseClass(innerValue:String)


simpleExample match {
      case SimpleCaseClass(innerValue) => println(s"inner value is : $innerValue")
      case _ => println("can not extract inner value")
}

This mechanism becomes more useful in case of complex case classes which contains other case classes

case class ComplexCaseClass(value:String, innerCaseClass:SimpleCaseClass)

val complex=ComplexCaseClass("complex",SimpleCaseClass("simple"))

complex match {
  case ComplexCaseClass(name,SimpleCaseClass(inner)) =>
     println(s"complex case class has : name=$name , with inner value=$inner")
}

Information Hiding

At first it seems that we are breaking encapsulation with pattern matching. First of all _case classes have different _philosophy than standard classes which we could see in java. We don't want to protect access to mutable data because... there is no mutable data at all!

But what if we want to have some private state for performance reason or something like that? Then we can create custom deconstructors - more on this mechanism in next workshops.

Patterns everywhere

You don't need match...case syntax to use convenience of Pattern Matching in the code.

You can use it during assignment :

val ComplexCaseClass(extractedName,SimpleCaseClass(extractedInner)) = complex

val tuple:(Int,String) = (1,"aaa")

val (key,value) = tuple

Guards

This simple concept allows you to add conditions to given case pattern

  anotherValue match {
      case s:String if s.length < 3 => println(s" very short string $s")
      case s:String  => println(s" long string $s")
      case i:Int if i > 0 => println("positive integer $i")
      case i:Int if i < 0 => println("negative integer $i")
      case i:Int  => println("this must be zero : $i")
      case other => println(s"neither String nor Integer : $other")

Performance

If you are matching primitives then generated bytecode may use standard java switch bytecode

To give a hint from compiler if this is doable you need to use @switch annotation

import scala.annotation.switch

    (i: @switch) match {
      case 9 => println("9")
        //uncomment to check warning
//      case SimpleCaseClass(value) => println(s"value from simple case class = $value")
      case _ => println("other")
}

Exercises

FILE: PatternMatching1Exercises

Exercise1 Finish implementation of simple calculator which matches on two case classes Multiply _or _Add and then performs proper mathematical operation.

Exercise2 You need to properly identify type of passed variable

Exercise3

Here you need to pattern match on complex case classes representing expressions

results matching ""

    No results matching ""