Scala Extractor
An extractor is an object that extracts the parameters used to construct an object from the object passed to it.
The Scala standard library includes some predefined extractors, which we will briefly explore.
A Scala extractor is an object with an unapply method. The unapply method is essentially the reverse operation of the apply method: unapply accepts an object and then extracts values from it, values that are typically used to construct the object.
The following example demonstrates an extractor object for email addresses:
Example
object Test {
def main(args: Array[String]) {
println("Apply method: " + apply("Zara", "gmail.com"));
println("Unapply method: " + unapply("[email protected]"));
println("Unapply method: " + unapply("Zara Ali"));
}
// Factory method (optional)
def apply(user: String, domain: String) = {
user + "@" + domain
}
// Extractor method (required)
def unapply(str: String): Option[(String, String)] = {
val parts = str split "@"
if (parts.length == 2) {
Some(parts(0), parts(1))
} else {
None
}
}
}
Running the above code, the output will be:
$ scalac Test.scala
$ scala Test
Apply method: [email protected]
Unapply method: Some((Zara,gmail.com))
Unapply method: None
The above object defines two methods: apply and unapply. With the apply method, we can create objects without using the new operator. So you can construct a string "[email protected]" with the statement Test("Zara", "gmail.com").
The unapply method is the reverse operation of the apply method: unapply accepts an object and then extracts values from it, values that are typically used to construct the object. In the example, we use the Unapply method to extract the username and the email address suffix from the object.
In the example, the unapply method returns None when the input string is not an email address. The code demonstration is as follows:
unapply("[email protected]") equals Some("Zara", "gmail.com")
unapply("Zara Ali") equals None
Extractor Usage with Pattern Matching
When we instantiate a class, we can include zero or more parameters, and the compiler will call the apply method during instantiation. We can define the apply method in both classes and objects.
As we mentioned earlier, unapply is used to extract the values we are looking for, and it is the opposite operation of apply. When we use a match statement in an extractor object, unapply is automatically executed, as shown below:
Example
object Test {
def main(args: Array[String]) {
val x = Test(5)
println(x)
x match {
case Test(num) => println(x + " is " + num + " times two!")
//unapply is called
case _ => println("Cannot calculate")
}
}
def apply(x: Int) = x*2
def unapply(z: Int): Option[Int] = if (z%2==0) Some(z/2) else None
}
Running the above code, the output will be:
$ scalac Test.scala
$ scala Test
10
10 is 5 times two!