You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In Scala, patterns can be defined independently of case classes. To this end, a method named unapply is defined to yield a so-called extractor. An extractor can be thought of as a special method that reverses the effect of applying a particular object on some inputs. Its purpose is to 'extract' the inputs that were present before the 'apply' operation. For instance, the following code defines an extractor [object](singleton-objects.html) Twice.
15
-
14
+
An extractor object is an object with an `unapply` method. Whereas the a `apply` method is like a constructor which takes arguments and creates an object, the `unapply` takes an object and tries to give back the arguments.
The pattern `case Twice(n)` will cause an invocation of `Twice.unapply`, which is used to match any even number; the return value of the `unapply` signals whether the argument has matched or not, and any sub-values that can be used for further matching. Here, the sub-value is `z/2`
The `apply` method is not necessary for pattern matching. It is only used to mimick a constructor. `val x = Twice(21)` expands to `val x = Twice.apply(21)`.
28
+
val customer1ID = CustomerID("Sukyoung") // Sukyoung-23098234908
29
+
val CustomerID(name) = customer1ID
30
+
println(name) // prints Sukyoung
31
+
```
32
+
The `apply` method creates a `CustomerID` string from a `name`. The `unapply` does the inverse to get the `name` back. When we call `CustomerID("Sukyoung")`, this is shorthand syntax for calling `CustomerID.apply("Sukyoung")`. When we call `val CustomerID(name) = customer1ID`, this is equivalent to `val name = CustomerID.unapply(customer1ID)`. This is used in pattern matching like so:
33
+
```tut
34
+
val customer2ID = CustomerID("Nico")
35
+
val customer2Name = customer2ID match {
36
+
case CustomerID(name) => name
37
+
}
38
+
```
39
+
In fact, if we tried to unapply an invalid `CustomerID`, we would get a `scala.MatchError`:
40
+
```tut:fail
41
+
val CustomerID(name2) = "--asdfasdfasdf"
42
+
name2.isEmpty
43
+
```
33
44
34
45
The return type of an `unapply` should be chosen as follows:
35
46
36
47
* If it is just a test, return a `Boolean`. For instance `case even()`
37
48
* If it returns a single sub-value of type T, return an `Option[T]`
38
49
* If you want to return several sub-values `T1,...,Tn`, group them in an optional tuple `Option[(T1,...,Tn)]`.
39
50
40
-
Sometimes, the number of sub-values is fixed and we would like to return a sequence. For this reason, you can also define patterns through `unapplySeq`. The last sub-value type `Tn` has to be `Seq[S]`. This mechanism is used for instance in pattern `case List(x1, ..., xn)`.
41
-
42
-
Extractors can make code more maintainable. For details, read the paper ["Matching Objects with Patterns"](https://infoscience.epfl.ch/record/98468/files/MatchingObjectsWithPatterns-TR.pdf) (see section 4) by Emir, Odersky and Williams (January 2007).
51
+
Sometimes, the number of sub-values is fixed and we would like to return a sequence. For this reason, you can also define patterns through `unapplySeq` which returns `Option[Seq[T]]` This mechanism is used for instance in pattern `case List(x1, ..., xn)`.
0 commit comments