Scala extractor is an object which has a method called unapply as one of its members. The unapply method matches a value and take it apart. The extractor also defines apply method for building values.
Consider an example of extracting first name and last name that uses space as separator.
firstName.scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
object firstName { def main(args: Array[String]) { println("Apply method : " + apply("Steve", "Smith")); println("Unapply method : " + unapply("Steve Smith")); println("Unapply method : " + unapply("Rob")); } def apply(fname: String, lname: String) = { fname + " " + lname } def unapply(s: String): Option[(String, String)] = { val pts = s split " " if (pts.length == 2) { Some(pts(0), pts(1)) } else { None } } } |
The object firstName defines two methods apply and unapply. The apply method turns into an object that accepts the arguments specified within the parenthesis and builds the value as specified in the method. The first and last name combined together with a space in between is returned.
The unapply method returns firstname object into an extractor and breaks the arguments as specified in the method. The unapply methods accepts a String argument and splits the String with space as separator and returns the option type over pair of strings. The result is a pair of strings if the first name and last name is passed as an argument else returns none.
Below image shows the output produced by above scala program.
Scala Extractor Pattern Matching
If the instance of the class contains a list of zero or more parameters, compiler calls apply method on that instance. The apply method can be defined for both objects and classes.
Consider an example as shown below;
patternmatch.scala
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
case class Student(name: String, address: Seq[Address]) case class Address(city: String, state: String) object City { def unapply(s: Student): Option[Seq[String]] = Some( for (c <- s.address) yield c.state) } class StringSeqContains(value: String) { def unapply(in: Seq[String]): Boolean = in contains value } object PatternMatch { def main(args: Array[String]) { val stud = List(Student("Harris", List(Address("LosAngeles", "California"))), Student("Reena", List(Address("Houston", "Texas"))), Student("Rob", List(Address("Dallas", "Texas"))), Student("Chris", List(Address("Jacksonville", "Florida")))) val Texas = new StringSeqContains("Texas") val students = stud collect { case student @ City(Texas()) => student.name } println(students) } } |
In the above example we are defining two classes Student and Address. Student class contains name and address and address contains city and state.
In the object City we are defining an unapply method which fetches the state from the address list. In the PatternMatch object we are creating objects of Student and address and we are fetching the names of the students who stay in texas city which is the pattern to be matched.
Below image shows the output produced when above class is executed.
That’s all for Scala Extractors and pattern matching, we will look into file operations in scala in next post.