Scala Extractors | Extractors vs Case Classes

1. Objective

In this Scala tutorial, we learned what are Extractors in Scala. Moreover, we will discuss Scala Extractors example. Also, we will discuss unapplySeq and apply the method in Scala extractors. Along with this, we will see how can we use Extractors in pattern matching in Scala. At last, we will learn variable argument Scala Extractors.

So, let’s start Scala extractors.

Scala Extractors

Scala Extractors | Extractors vs Case Classes

2. What are Scala Extractors?

A Scala extractor is an object in Scala that defines a method unapply() and optionally a method apply(). One use-case of the apply() method is that Scala invokes it on an instance when we instantiate a class with parentheses with a list of parameters zero or more. While an extractor has other members too, these are what we will discuss here.

An apply() method lets us build values and an unapply() method helps us take them apart. Let’s take an example.

Read Scala Method Overriding

3. An Example of Extractors in Scala

In the following example, we define a method apply() to turn (“Ayushi”,”Sharma”) into “Ayushi Sharma”. unapply() turns this class into an extractor and works to return two strings here from “Ayushi Sharma”- the fname and the lname. Where it observes a string other than a name(because there’s no space), it returns None. That is why we make it return an Option.

scala> //Optional injection
scala> def apply(fname:String,lname:String)={
    | fname+" "+lname
    | }
apply: (fname: String, lname: String)String
scala> //Mandatory extraction
scala> def unapply(str:String):Option[(String,String)]={
    | val parts=str split " "
    | if(parts.length==2){
    | Some(parts(0),parts(1))
    | }else{
    | None
    | }
    | }
unapply: (str: String)Option[(String, String)]
scala> apply("Ayushi","Sharma")
res4: String = Ayushi Sharma
scala> unapply("Ayushi Sharma")
res5: Option[(String, String)] = Some((Ayushi,Sharma))
scala> unapply("AyushiSharma")
res6: Option[(String, String)] = None

4. Using Scala Extractors for Pattern Matching

Where can we make use of this? One such application is pattern-matching. Before you continue, you should read up on Pattern Matching in Scala.

Let’s explore 14 Types Scala Pattern Matching

We can compare Scala extractor objects using a match statement. Here, Scala executes the unapply() method.

Let’s take an example.

object Demo{
def main(args: Array[String]){
val y=Demo(3)
//Apply invoked
println(“y: “+y)
y match{
case Demo(num)=>println(y+” is twice bigger than “+num)
//Unapply invoked
case _=>println(“Sorry”)
}
}
def apply(y:Int)=y*2
def unapply(y:Int):Option[Int]=if(y%2==0) Some(y/2) else None
}

This gives us the following output:
y: 6
6 is twice bigger than 3

5. Variable Argument Extractors in Scala

What happens when we want a Scala extractor that returns a variable number of element values? Let’s try taking a domain apart. A domain may be made of more than two sub-patterns. We can then express such patterns:

domain match{
case Domain("ro","versuri")=>println("versuri.ro")
case Domain("com", "sun", "java") => println("java.sun.com")
case Domain("net", _*) => println("a .net domain")

Let’s explore Scala Regex | Scala Regular Expressions
Here, we arrange the domains such that we expand them top-down- from the top-level domain to the subdomains. _* is a wildcard pattern that let us match any remaining elements in a sequence.
To carry out extraction with vararg matching, we can use the method unapplySeq(). This is the Scala extractor object for the same:

scala> object Domain{
    | //Optional injection
    | def apply(parts:String*):String=
    | parts.reverse.mkString(".")
    |
    | //Mandatory extraction
    | def unapplySeq(whole:String):Option[Seq[String]]=
    | Some(whole.split("\\.").reverse)
    | }
defined object Domain

In this object, the unapplySeq() method splits the string using periods to get an array of substrings. This is an array with all elements reversed and wrapped in a Some.

Scala Quiz

6. Scala Extractors vs Case Classes

We have seen about case classes in Case Classes and Objects in Scala. They let us model immutable values. But they represent concrete representation of data. So, the class name in a constructor pattern pertains to the concrete representation type for the selector object.

a. Representation Independence

One property of Scala extractors is representation independence. They enable patterns without any relation to the data type for the selected object. This is important in open systems of large size as they let us change implementation type without changing clients. This is where extractors win over case classes in Scala.

However, in some places, case classes have their own advantages over extractors in Scala. It is easier to define them and set them up. They also need less code. Other than that, the compiler patterns over case classes better than it does so over extractors. This makes for more efficient pattern matches for case classes. Finally, there are no exhaustiveness checks for Scala extractors.

Concluding, use a case class when writing for a closed application for conciseness, speed, and static checking. Use extractors when you want to expose a type to unknown clients.

So, this was all about Scala Extractors. Hope you like our explanation.

7. Conclusion

Hence, in this Scala Extractors tutorial, we discussed Extractors in Scala. Where it helps us break an object. Moreover, we saw Scala Extractors examples and extractors vs case class. Also, we learned how to use extractors for pattern matching. Is this information helpful to you? Tell us your thoughts in the comments.
See also –
Scala Method Overloading with Example
For reference

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.