Pattern matching is another functional programming concept introduced in Scala. To start with, Scala pattern matching looks similar to switch case in Java. The example in the following listing, showing the similarity between Scala and Java, takes an integer and prints its ordinal number.
- Listing 2.2 An ordinal class written in Java
- public class Ordinal {
- public static void main(String[] args) {
- ordinal(Integer.parseInt(args[0]));
- }
- public static void ordinal(int number) {
- switch(number) {
- case 1: System.out.println("1st"); break;
- case 2: System.out.println("2nd"); break;
- case 3: System.out.println("3rd"); break;
- case 4: System.out.println("4th"); break;
- case 5: System.out.println("5th"); break;
- case 6: System.out.println("6th"); break;
- case 7: System.out.println("7th"); break;
- case 8: System.out.println("8th"); break;
- case 9: System.out.println("9th"); break;
- case 10: System.out.println("10th"); break;
- default : System.out.println("Cannot do beyond 10");
- }
- }
- }
- Listing 2.3 An ordinal class in Scala
- ordinal(args(0).toInt)
- def ordinal(number:Int) = number match {
- case 1 => println("1st")
- case 2 => println("2nd")
- case 3 => println("3rd")
- case 4 => println("4th")
- case 5 => println("5th")
- case 6 => println("6th")
- case 7 => println("7th")
- case 8 => println("8th")
- case 9 => println("9th")
- case 10 => println("10th")
- case _ => println("Cannot do beyond 10")
- }
The wildcard case is optional and works like a safe fallback option. If you remove it, and none of the existing cases match, you get a match error:
This is great because it tells you that you’re missing a case clause, unlike in Java, where if you remove the default and none of the existing cases match, it ignores it without providing any sort of feedback.
The similarity between Java and Scala pattern matching ends here because Scala takes pattern matching to the next level. In Java you can only use a switch statement with primitives and enums, but in Scala you can pattern match strings and complex values, types, variables, constants, and constructors. More pattern-matching concepts are in the next chapter, particularly constructor matching, but look at an example of a type match. The following example defines a method that takes an input and checks the type of the given object:
- def printType(obj: AnyRef) = obj match {
- case s: String => println("This is string")
- case l: List[_] => println("This is List")
- case a: Array[_] => println("This is an array")
- case d: java.util.Date => println("This is a date")
- }
Scala also allows the infix operation pattern, in which you can specify an infix operator in your pattern. In the infix style, operators are written between the operands—for example, 2 + 2. In the following example, you’re extracting the first and the second elements from the List:
Here you’re matching 1 to f, 2 to s, and 3 and 4 to the rest of the variables. Think of it
as what it will take to create a List of 1, 2 ,3, and 4 from the expression f :: s :: rest, and then this will make more sense. Sometimes you need to have a guard clause along with the case statement to have more flexibility during pattern matching. In the following example you’re determining the range in which the given number belongs:
- def rangeMatcher(num:Int) = num match {
- case within10 if within10 <= 10 => println("with in 0 to 10")
- case within100 if within100 <= 100 => println("with in 11 to 100")
- case beyond100 if beyond100 < Integer.MAX_VALUE => println("beyond 100")
- }
- Listing 2.4 Ordinal2.scala reimplemented
- val suffixes = List("th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th")
- println(ordinal(args(0).toInt))
- def ordinal(number:Int) = number match {
- case tenTo20 if 10 to 20 contains tenTo20 => number + "th"
- case rest => rest + suffixes(number % 10)
- }
沒有留言:
張貼留言