Scala value class, use cases
Asked Answered
G

3

8

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???

Greasepaint answered 20/11, 2016 at 13:24 Comment(2)
calling this.i + that.i does not seems that much slower than i + i How did you determine this? Did you microbenchmark that code?Middelburg
Besides of the fact the call is faster (which will be most likely inlined by the JIT compiler anyway), value classes avoid object instantiation, therefore reducing Garbage Collection load.Purnell
I
12

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

Imogene answered 20/11, 2016 at 14:25 Comment(1)
Thanks for your help.Greasepaint
B
11

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.

Bankhead answered 20/11, 2016 at 14:22 Comment(1)
what a great explanation! thank you for your detail. performance cost of not using value class seems obviousGreasepaint
E
1

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

Enneagon answered 20/11, 2016 at 13:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.