Joe K
Joe K

Reputation: 18424

Scala type-safety vs overhead (type vs class)

I have a graph, where each vertex has both an ID (which never changes) and a label (which changes frequently). Both are represented by longs.

Currently, I define the following types:

type VertexId = Long
type VertexLabel = Long

However, I discovered a bug today where I was passing in a VertexLabel to a function that expected a VertexId. This seems like the type of thing the scala compiler should be able to prevent.

I considered doing this instead:

case class VertexId(id: Long)
case class VertexLabel(label: Long)

But then there's extra overhead of "boxing" and "unboxing" and some extra memory usage.

Is there anyway to get the best of both worlds? Define both types as Longs in such a way that the compiler will prevent you from using one as the other?

Upvotes: 3

Views: 117

Answers (2)

Michael Zajac
Michael Zajac

Reputation: 55569

Type aliases are really just for code clarity. When you declare type VertexId = Long, you're saying that VertexId is equivalent to Long. Then transitively, VertexId is equivalent to VertexLabel. They are still both Long underneath, and that is how the compiler will see them once de-aliased.

So no, I don't think you can completely get the best of both worlds here, because you're requirement is that VertexId and VertexLabel must be different types. A simple type alias cannot do that.

@Lee's answer is correct in that you can use value classes to create different types, (most of the time) without actually instantiating the types at runtime. But note the caveats in the link.

Upvotes: 3

Lee
Lee

Reputation: 144136

Yes, you can use value classes:

case class VertexId(val id: Long) extends AnyVal
case class VertexLabel(val label: Long) extends AnyVal

see http://docs.scala-lang.org/overviews/core/value-classes.html

Upvotes: 9

Related Questions