Scala Tutorial
Basics
Control Statements
OOP Concepts
Parameterized - Type
Exceptions
Scala Annotation
Methods
String
Scala Packages
Scala Trait
Collections
Scala Options
Miscellaneous Topics
In Scala, extractors are objects that have an unapply
or unapplySeq
method, which allows them to define custom patterns that can be used in pattern matching. These methods make it possible to reverse the construction sequence of objects, essentially letting you "de-structure" objects.
The most common use of extractors is with case classes, which automatically provide an unapply
method. But you can also define custom extractors for your own classes or even built-in types.
Here's a breakdown of how you can use extractors with pattern matching:
Scala's case classes automatically generate an unapply
method for you:
case class Person(name: String, age: Int) val alice = Person("Alice", 25) alice match { case Person(n, a) => println(s"$n is $a years old") }
Let's say you have an object that represents an email address, and you'd like to extract the user and domain parts:
object Email { // The apply method is not necessary for extraction, but it helps in construction. def apply(user: String, domain: String) = user + "@" + domain def unapply(email: String): Option[(String, String)] = { val parts = email.split("@") if (parts.length == 2) Some(parts(0), parts(1)) else None } } val email = Email("john", "example.com") email match { case Email(user, domain) => println(s"User: $user, Domain: $domain") }
unapplySeq
If you're not sure about the number of elements you're going to extract, you can use unapplySeq
:
object Words { def unapplySeq(str: String): Option[Seq[String]] = { Some(str.split(" ")) } } val sentence = "Hello World from Scala" sentence match { case Words(first, second, _*) => println(s"First word: $first, Second word: $second") }
In this example, the extractor Words
will split the string into words, and you can match the first few words (or more) in your pattern.
apply
method, but it's common to define both apply
and unapply
for symmetry (constructing and de-constructing).unapply
method signals whether the matching has succeeded or not. For single-element matching, Option[T]
is used. For multiple elements, Option[(T1, T2, ...)]
is used.Extractors provide a powerful mechanism to augment pattern matching capabilities in Scala, making the language even more expressive.
How to use extractors in Scala pattern matching:
unapply
or unapplySeq
methods, allowing pattern matching on complex data structures.// Extractor example object Even { def unapply(x: Int): Option[Int] = if (x % 2 == 0) Some(x) else None } val value = 42 value match { case Even(evenValue) => println(s"$value is even") case _ => println(s"$value is odd") }
Custom extractors in Scala for pattern matching:
unapply
method.// Custom extractor object Name { def unapply(fullName: String): Option[(String, String)] = { val parts = fullName.split(" ") if (parts.length == 2) Some((parts(0), parts(1))) else None } } val fullName = "John Doe" fullName match { case Name(firstName, lastName) => println(s"First: $firstName, Last: $lastName") case _ => println("Invalid name format") }
Case classes and extractors in Scala:
unapply
methods) for pattern matching based on their constructor parameters.// Case class and extractor case class Person(name: String, age: Int) val person = Person("Alice", 25) person match { case Person(name, age) => println(s"Name: $name, Age: $age") case _ => println("Invalid person") }
Extractor objects in Scala pattern matching:
unapply
method, providing a convenient way to organize and reuse extractors.// Extractor object object Even { def unapply(x: Int): Option[Int] = if (x % 2 == 0) Some(x) else None } val value = 42 value match { case Even(evenValue) => println(s"$value is even") case _ => println(s"$value is odd") }
Pattern matching with unapply method in Scala:
unapply
method is a fundamental part of extractors, enabling pattern matching on custom data types.// Pattern matching with unapply object Even { def unapply(x: Int): Option[Int] = if (x % 2 == 0) Some(x) else None } val value = 42 value match { case Even(evenValue) => println(s"$value is even") case _ => println(s"$value is odd") }
Scala extractor patterns for collections:
// Extractor pattern for collections object NonEmptyList { def unapply[A](list: List[A]): Option[List[A]] = if (list.nonEmpty) Some(list) else None } val myList = List(1, 2, 3) myList match { case NonEmptyList(elements) => println(s"Non-empty list: $elements") case _ => println("Empty list") }