Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala value class, use cases

I know value class in scala inline the operation at compiler time.

maybe like this

case class A(i: Int) extends AnyVal {
   def +(that: A) = A(this.i + that.i)
} 
A(1) + A(2) // After compile it equals to 1 + 2 

But It seems not a big deal to me.

It might enhance performance but,

calling this.i + that.i does not seems that much slower than i + i

Why we need value class in scala and any use cases???

like image 831
Wonpyo Park Avatar asked Nov 20 '16 13:11

Wonpyo Park


3 Answers

Why would you wrap a single value into an additional class?

One big use case is type safety. Let's say you have function that can multiply money, like so:

def multiply(factor: Int, amount: Int): Int = ???

The problem with this is that it would be very easy to confuse the two arguments and therefore call the function incorrectly. With values classes, you could create a Money type and re-write the function like so:

case class Money(amount: Int) extends AnyVal
def multiply(factor: Int, amount: Money): Money = ???

Now with your special Money type, the compiler will tell you if you try to pass arguments in the wrong order.

Were it not a value class, people may say that the added type safety is not worth the performance penalty in some cases. However with value classes, you have no runtime overhead (there are limitations though: http://docs.scala-lang.org/overviews/core/value-classes.html).

An alternative to achieve the same goal are unboxed (no runtime overhead) tagged types in scalaz: http://eed3si9n.com/learning-scalaz/Tagged+type.html

Note that for example haskell uses newtype for the same idea: https://wiki.haskell.org/Newtype

like image 197
rethab Avatar answered Oct 10 '22 23:10

rethab


Let's look at how Scala works with value classes (-print option).

case class A(i: Int) extends AnyVal {
   def +(that: A) = A(this.i + that.i)
} 
A(1) + A(2)

is translated to:

final def +$extension($this: Int, that: Int): Int = $this.+(that)
...
A.+$extension(1, 2)

As you can see Scala avoids working with class A and simply adds Int to Int returning Int. At the same time:

case class A(i: Int) {
   def +(that: A) = A(this.i + that.i)
} 
A(1) + A(2)

is translated to:

def +(that: A): A = new A(this.i().+(that.i()))
...
new A(1).+(new A(2))

So to compute 1 + 2 you need to instantiate class A three times.

like image 43
Victor Moroz Avatar answered Oct 10 '22 22:10

Victor Moroz


Value classes are a mechanism in Scala to avoid allocating runtime objects. This is accomplished through the definition of new AnyVal subclasses.

More about value classes is here Value Classes

like image 41
pamu Avatar answered Oct 10 '22 23:10

pamu