Pattern matching. The if expression The else part of an if expression is optional if ( condition )...
-
Upload
rhoda-hopkins -
Category
Documents
-
view
218 -
download
0
Transcript of Pattern matching. The if expression The else part of an if expression is optional if ( condition )...
![Page 1: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/1.jpg)
Pattern matching
![Page 2: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/2.jpg)
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
![Page 3: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/3.jpg)
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
![Page 4: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/4.jpg)
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.toStringres1: String = abc
scala> val y = if (true) 123y: AnyVal = 123
scala> y.toInt<console>:9: error: value toInt is not a member of AnyVal y.toInt ^
scala> y.toString.toIntres3: Int = 123
4
![Page 5: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/5.jpg)
The match expression
The match expression is more general than if The syntax is: expression match { case value1 => result1
case value2 => result2
. . . case valueN => resultN
} 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
![Page 6: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/6.jpg)
Example match expressions Boolean-expression match {
case true => expression1
case false => expression2
}is equivalent toif (Boolean-expression) expression1 else expression2
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, 2nd ed., p. 275
6
![Page 7: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/7.jpg)
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 = 5n: 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
![Page 8: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/8.jpg)
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
![Page 9: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/9.jpg)
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 case9
![Page 10: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/10.jpg)
Pattern matching in assignments
scala> val Vector(x, y) = Vector(101, 102)x: Int = 101y: Int = 102
scala> val Vector(a, b, c, _*) = Vector(11, 22, 33, 44)a: Int = 11b: Int = 22c: Int = 33
scala> var List(p, q, r) = List("one", "two", "three")p: String = oneq: String = twor: String = three
10
![Page 11: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/11.jpg)
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
![Page 12: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/12.jpg)
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") | } | }<console>: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") ^<console>: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") ^<console>: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
![Page 13: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/13.jpg)
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) = tx: Int = 1y: String = abcz: 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
![Page 14: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/14.jpg)
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._2res3: String = Queen of Spades
14
![Page 15: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/15.jpg)
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
![Page 16: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/16.jpg)
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
![Page 17: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/17.jpg)
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
![Page 18: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/18.jpg)
match with guards scala> def describe(x: Int) = x match {
| case n if n < 0 => 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
![Page 19: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/19.jpg)
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) <- students) { | if (score >= 70) println(s"$name did well.") | else println(s"$name did poorly.") | }Mary did well.John did poorly.Bill did well.
19
![Page 20: Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.](https://reader035.fdocuments.us/reader035/viewer/2022081811/56649ea15503460f94ba53c4/html5/thumbnails/20.jpg)
The End