Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understand how to use apply and unapply

Tags:

scala

I'm trying to get a better understanding of the correct usage of apply and unapply methods.

Considering an object that we want to serialize and deserialize, is this a correct usage (i.e. the Scala way) of using apply and unapply?

case class Foo object Foo {     apply(json: JValue): Foo = json.extract[Foo]     unapply(f: Foo): JValue = //process to json } 
like image 351
igx Avatar asked Aug 27 '13 14:08

igx


People also ask

What is apply and Unapply method?

An extractor object is an object with an unapply method. Whereas the 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. This is most often used in pattern matching and partial functions.

What is use of Unapply method in Scala?

In Scala, every object that has an unapply() method is called an extractor object. The unapply() method is the basis of pattern matching in Scala because this method helps us to extract data values compacted in objects.

What is pattern matching in Scala?

Pattern matching is a mechanism for checking a value against a pattern. A successful match can also deconstruct a value into its constituent parts. It is a more powerful version of the switch statement in Java and it can likewise be used in place of a series of if/else statements.


1 Answers

Firstly, apply and unapply are not necessarily opposites of each other. Indeed, if you define one on a class/object, you don't have to define the other.

apply

apply is probably the easier to explain. Essentially, when you treat your object like a function, apply is the method that is called, so, Scala turns:

obj(a, b, c) to obj.apply(a, b, c).

unapply

unapply is a bit more complicated. It is used in Scala's pattern matching mechanism and its most common use I've seen is in Extractor Objects.

For example, here's a toy extractor object:

object Foo {   def unapply(x : Int) : Option[String] =      if(x == 0) Some("Hello, World") else None } 

So now, if you use this is in a pattern match like so:

myInt match {     case Foo(str) => println(str) } 

Let's suppose myInt = 0. Then what happens? In this case Foo.unapply(0) gets called, and as you can see, will return Some("Hello, World"). The contents of the Option will get assigned to str so in the end, the above pattern match will print out "Hello, world".

But what if myInt = 1? Then Foo.unapply(1) returns None so the corresponding expression for that pattern does not get called.

In the case of assignments, like val Foo(str) = x this is syntactic sugar for:

val str : String = Foo.unapply(x) match {   case Some(s) => s   case None    => throw new scala.MatchError(x) } 
like image 64
amnn Avatar answered Oct 09 '22 07:10

amnn