Presentation is loading. Please wait.

Presentation is loading. Please wait.

Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.

Similar presentations


Presentation on theme: "Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates."— Presentation transcript:

1 Pattern matching

2 The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates to true, the value of the if-expression is expression1, else it is expression2 if ( condition ) expression1 If the condition evaluates to true, the value of the if-expression is expression1, else it is “unit” Regardless of the type of expression1, the type of the result is Any Scala determines the type of everything before the program runs, and at that time it doesn’t know whether the condition will be true When you use an if without an else, typically you don’t care what the value of the if-expression will be 2

3 Unit -returning expressions In Scala, the “statements” are really expressions But a lot of expressions return Unit, () for (without yield ) while assignments val and var print and println methods Some expressions (can) return more meaningful values if, especially with else Without else, if you don’t get Unit, you get a value of type Any for with yield The match method Arithmetic, logical, or string expressions Your own methods 3

4 Dealing with Any Any usually means that Scala doesn’t know the type Scala determines types at compile time; if the type depends on what happens at run time, Scala can’t know exactly scala> val x = if (true) "abc" x: Any = abc scala> x.toString res1: String = abc scala> val y = if (true) 123 y: AnyVal = 123 scala> y.toInt :9: error: value toInt is not a member of AnyVal y.toInt ^ scala> y.toString.toInt res3: Int = 123 4

5 The match expression The match expression is more general than if The syntax is: expression match { case value 1 => result 1 case value 2 => result 2... case value N => result N } The expression is evaluated, then compared with each value in order When a value is found that matches the expression, the corresponding result is computed, and that is the value of the match expression 5

6 Example match expressions Boolean-expression match { case true => expression 1 case false => expression 2 } is equivalent to if ( Boolean-expression ) expression 1 else expression 2 def describe(x: Any): String = x match { case 5 => "five" case true => "truth" case "hello" => "hi!" case Nil => "The empty list" case _ => "something else" // _ will match anything } This example taken from Programming in Scala, 2 nd ed., p. 275 6

7 match with variables You can use case variable => The match will succeed, and the variable will get the value of the expression being matched scala> val n = 5 n: Int = 5 scala> n match { | case 1 => 10 | case x => 10 * x | } res6: Int = 50 In the above, x gets, as a val, the value of the expression n You don’t explicitly say val x, just say x The scope of x is just the case in which it occurs; you cannot use it after the match expression 7

8 match with sequences You can match a sequence (List, Vector, Array,…) scala> val nums = List(10, 20, 30, 40) nums: List[Int] = List(10, 20, 30, 40) scala> nums match { | case List(a, b, c, d) => println(s"a is $a, d is $d") | } a is 10, d is 40 You can use underscore as a wild card, meaning “match and forget” scala> nums match { | case List(_, b, _, _) => println(s"b is $b") | } b is 20 Unlike an ordinary variable, _ can match something different each time 8

9 The extended wildcard, _* _* will match all remaining elements (zero or more of them) scala> def take3(v: Vector[Int]) = v match { | case Vector(a, b, c, _*) => | println("No problem!") | Vector(a, b, c) | case _ => | println("I can't take three!") | v :+ 99 | } take3: (v: Vector[Int])scala.collection.immutable.Vector[Int] scala> take3(Vector(11, 22, 33, 44, 55, 66)) No problem! res26: scala.collection.immutable.Vector[Int] = Vector(11, 22, 33) scala> take3(Vector(11, 22)) I can't take three! res27: scala.collection.immutable.Vector[Int] = Vector(11, 22, 99) Braces, { }, are not needed to have multiple expressions in a case 9

10 Pattern matching in assignments scala> val Vector(x, y) = Vector(101, 102) x: Int = 101 y: Int = 102 scala> val Vector(a, b, c, _*) = Vector(11, 22, 33, 44) a: Int = 11 b: Int = 22 c: Int = 33 scala> var List(p, q, r) = List("one", "two", "three") p: String = one q: String = two r: String = three 10

11 match with types scala> def printType(x: Any) = x match { | case d: Double => println(s"$d is a Double") | case i: Int => println(s"$i is an Int") | case s: String => println(s"$s is a String") | case other => println(s"I don't know what $other is!") | } printType: (x: Any)Unit scala> printType(5.3) 5.3 is a Double scala> printType("abc") abc is a String scala> printType('a') I don't know what a is! 11

12 No match with generic types scala> def printType(x: List[Any]) { | x match { | case n: List[Int] => println("These are Ints") | case n: List[String] => println("These are Strings") | } | } :13: warning: non-variable type argument Int in type pattern List[Int] is unchecked since it is eliminated by erasure case n: List[Int] => println("These are Ints") ^ :14: warning: non-variable type argument String in type pattern List[String] is unchecked since it is eliminated by erasure case n: List[String] => println("These are Strings") ^ :14: warning: unreachable code case n: List[String] => println("These are Strings") ^ printType: (x: List[Any])Unit scala> printType(List("a")) These are Ints 12

13 Tuples A tuple is a sequence of values enclosed in parentheses The values may be of different types scala> val t = (1, "abc", 5.3) t: (Int, String, Double) = (1,abc,5.3) Notice how the type is expressed: (Int, String, Double) Tuples may be assigned to tuples scala> val (x, y, z) = t x: Int = 1 y: String = abc z: Double = 5.3 Components of a tuple are accessed with._1,._2,._3, etc. scala> println(s"t._1 is ${t._1} and t._3 is ${t._3}") t._1 is 1 and t._3 is 5.3 13

14 Pattern matching on tuples scala> val card = (12, "Spades") card: (Int, String) = (12,Spades) scala> ( card match { | case (1, _) => "Ace of " | case (11, _) => "Jack of " | case(12, _) => "Queen of " | case(13, _) => "King of " | } ) + card._2 res3: String = Queen of Spades 14

15 Option Just as a Vector can hold zero or more items, an Option can hold zero or one item If it holds zero items, its value is None If it holds item, its value is Some( item ) Option is perfect when you don’t know whether or not you are going to have a value Typical uses: Searching for something in a Vector or a List Trying to solve a problem that may not have a solution (or at least, not one you can find) You can match on Some( variable ) or None 15

16 Using Option in a search method scala> val names = List("Bob", "Alice", "Charles", "Dawn") names: List[String] = List(Bob, Alice, Charles, Dawn) scala> def find(name: String, names: List[String]): Option[Int] = { | var result: Option[Int] = None | for (i <- 0 until names.length if result == None) { | if (name == names(i)) result = Some(i) | } | result | } find: (name: String, names: List[String])Option[Int] scala> find("Alice", names) res4: Option[Int] = Some(1) scala> find("dawn", names) res5: Option[Int] = None 16

17 Pattern matching with Option scala> find("Charles", names) match { | case Some(x) => println(s"Found at location $x") | case None => println("Nobody here by that name!") | } Found at location 2 As mentioned before, you can do pattern matching in assignments scala> val Some(loc) = find("Charles", names) loc: Int = 2 …But it’s dangerous, and not recommended scala> val Some(loc2) = find("Inigo", names) scala.MatchError: None (of class scala.None$) 17

18 match with guards scala> def describe(x: Int) = x match { | case n if n s"$n is negative" | case n if n == 0 => "That's a zero" | case n if n % 2 == 0 => s"$n is an even number" | case n if n % 2 != 0 => s"$n is an odd number" | case _ => "How did I get here?" | } describe: (x: Int)String scala> describe(3) res34: String = 3 is an odd number scala> describe(-3) res35: String = -3 is negative 18

19 patterns in for expressions scala> val students = List(("Mary", 95), ("John", 46), ("Bill", 75)) students: List[(String, Int)] = List((Mary,95), (John,46), (Bill,75)) scala> for ((name, score) = 70) println(s"$name did well.") | else println(s"$name did poorly.") | } Mary did well. John did poorly. Bill did well. 19

20 The End


Download ppt "Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates."

Similar presentations


Ads by Google