Thursday, April 25, 2019

Scala Match Expressions

- Expressions are matched against a pattern
- Difference to the switch statement of C or Java
   - No fall through to the next alternative
   - Match expressions return a value
- MatchError is thrown if no pattern matches

expr match {
  case pattern1 => result1
  case pattern2 => result2
}

Match pattern 
case pattern => result

- case declares a match pattern
- If pattern matches, result will be evaluated and returned

Pattern 1

Wildcard Pattern

 _ is used as a wildcard to match everything

scala> def whatTimeIsIt(any: Any): String = any match {
     | case _ => s"any is no time"
     | }
whatTimeIsIt: (any: Any)String

scala> whatTimeIsIt(20)
res18: String = any is no time


Variable Pattern

scala> def whatTimeIsIt(any: Any): String = any match {
     | case any => s"$any is no time"
     | }
whatTimeIsIt: (any: Any)String

scala> whatTimeIsIt("winter")
res21: String = winter is no time


Typed Pattern

- Use a type annotation to match only certain annotations
- Typed pattern needs to be composed with the wildcard and variable pattern

scala> def whatTimeIsIt( any:Any ): String = any match {
     | case time: Time => s"Time is ${Time.hours}:{Time.minutes}"
     | case _ => s"$any is no time"
     | }

scala> whatTimeIsIt(Time(9,30))

Constant Pattern

- Use a stable identifier to match something constant

scala> def whatTimeIsIt( any:Any ): String = any match {
     | case "12:00" =>  "High Noon"
     | case _ => s"$any is no time"
     | }

scala> whatTimeIsIt("12:00")
res23: String = High Noon

scala> whatTimeIsIt("10:00")
res24: String = 10:00 is no time

Pattern 2

Tuple Pattern 

- Use tuple syntax to match and decompose tuples
- Tuple pattern is composed with other patterns like the constant pattern or variable pattern

def whatTimeIsIt( any:Any ): String = any match {
   case (x, "12:00") => s"From $x to noon"
   case _ => s"$any is no time"
}

scala> whatTimeIsIt("5")
res27: String = 5 is no time

scala> whatTimeIsIt("5","12:00")
res28: String = From 5 to noon


Constructor Pattern

- Use constructor syntax to match and decompose case classes
- The constructor pattern is  composed with other patterns
- We can build deeply nested structures

def whatTimeIsIt( any:Any ) = any match {
   case Time(12,0) => "High Noon"
   case Time(12,m) => s"It is $m past 12"
   case _ => s"$any is no time"

>whatTimeIsIt(Time(12,15))
>It is 15 minutes past 12


Sequence Pattern

Use sequence constructors or append or prepend operators to match and decompose sequences

scala> def matchSeq[A]( seq: Seq[A] ): String = seq match {
     | case Seq(1,2,3) => "1 to 3"
     | case x +: Nil => s"Only element is $x"
     | case _+:x => s"Last element is $x"
     | case Nil => "Empty sequence"
     | }
matchSeq: [A](seq: Seq[A])String

scala> matchSeq(1 to 3)
res29: String = 1 to 3

scala> matchSeq(Vector(1))
res30: String = Only element is 1

scala> matchSeq(Array(1,2,3,4))
res31: String = Last element is WrappedArray(2, 3, 4)


Pattern Alternatives

- Use | symbol to combine various pattern alternatives

def whatTimeIsIt( any:Any ): String = any match {
   case  "00:00" | "12:00" => s"Midnight or high noon"
   case _ => s"$any is no time"
}

Pattern Binders

- Use @ to bind various pattern alternatives

def whatTimeIsIt(any:Any) : String = any match {
  case time @ Time (_,0) => s"time with 0 minutes"
  case time @ Time (_,m) => s"time with $m minutes"
  case _ => s"$any is no time"
}  

Pattern Guards

- Composing patterns gives more control over matching
- If that's not enough, use the if keyword to define pattern guard

def isAfternoon(any:Any) : String = any match {
  case Time(h,m) if h>=12  => s"Yes, it is $(h-12): $m pm"
  case Time(h,m) => s"No, it is $h:$m am"
  case _ => s"$any is no time"
}  


No comments:

Post a Comment