Skip to content

Commit 50343c1

Browse files
committed
Rewrote extractors section of tour
1 parent 1a5aabb commit 50343c1

File tree

1 file changed

+15
-17
lines changed

1 file changed

+15
-17
lines changed

tutorials/tour/_posts/2017-02-13-extractor-objects.md

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,25 @@ next-page: sequence-comprehensions
1111
previous-page: regular-expression-patterns
1212
---
1313

14-
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-
16-
```tut
17-
object Twice {
18-
def apply(x: Int): Int = x * 2
19-
def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
20-
}
21-
22-
object TwiceTest extends App {
23-
val x = Twice(21)
24-
x match { case Twice(n) => Console.println(n) } // prints 21
25-
}
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.
2615
```
16+
import scala.util.Random
2717
28-
There are two syntactic conventions at work here:
18+
object CustomerID{
2919
30-
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`
20+
def apply(name: String) = s"$name--${Random.nextLong}"
3121
32-
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)`.
22+
def unapply(customerID: String): Option[String] = {
23+
val name = customerID.split("--")(0)
24+
if (!name.isEmpty) Some(name) else None
25+
}
26+
}
27+
28+
val customer1ID = CustomerID("Sukyoung") // Sukyoung-23098234908
29+
val CustomerID(name) = customer1ID
30+
println(name) // Sukyoung
31+
```
32+
The `apply` method creates a `CustomerID` string from a `name`. The `unapply` does the inverse to get the `name` back. Although `CustomerID` doesn't take any parameters, when we call `CustomerID("Sukyoung")`, this is shorthand syntax for calling `CustomerID.apply("Sukyoung")`. When we call `val CustomerID(name) = customer1ID`, this is shorthand for `val name = CustomerID.unapply(name)`.
3333

3434
The return type of an `unapply` should be chosen as follows:
3535

@@ -38,5 +38,3 @@ The return type of an `unapply` should be chosen as follows:
3838
* If you want to return several sub-values `T1,...,Tn`, group them in an optional tuple `Option[(T1,...,Tn)]`.
3939

4040
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).

0 commit comments

Comments
 (0)