How do I make a class generic for all Numeric Types?

Arne picture Arne · Jan 20, 2011 · Viewed 12.2k times · Source

I am trying to create a Vector class that is generic for all numeric types. my original attempt was to write a class for all Types like this:

class Vector3f(val x:Float, val y:Float, val z:Float)

since scala supports the specialised annotation I could use this to generate me these classes for all numeric types

class Vector3[A <: What?](val x:A,val y:A, val z:A)

but everything I found as a super type for numbers was AnyVal, but AnyVal does not support + - * /. So what is the right way to do this, but without sacrificing the performance of unboxed number types?

Answer

Daniel C. Sobral picture Daniel C. Sobral · Jan 21, 2011

You can't. Not right now. Maybe when, and if, Numeric gets specialized.

Say you get the simplest parameterized class possible:

class Vector3[@specialized T](val x: T, val y: T, val z: T)(implicit num: Numeric[T]) {
    def +(other: Vector3[T]) = new Vector3(num.plus(x, other.x), num.plus(y, other.y), num.plus(z, other.z))
}

The method + will compile into something roughly like this:

override <specialized> def +$mcD$sp(other: Vector3): Vector3 = new Vector3$mcD$sp(
  scala.Double.unbox(
    Vector3$mcD$sp.this.Vector3$$num.plus(
      scala.Double.box(Vector3$mcD$sp.this.x()), 
      scala.Double.box(other.x$mcD$sp()))),
  scala.Double.unbox(
    Vector3$mcD$sp.this.Vector3$$num.plus(
      scala.Double.box(Vector3$mcD$sp.this.y()),
      scala.Double.box(other.y$mcD$sp()))),
  scala.Double.unbox(
    Vector3$mcD$sp.this.Vector3$$num.plus(
      scala.Double.box(Vector3$mcD$sp.this.z()), 
      scala.Double.box(other.z$mcD$sp()))), 
  Vector3$mcD$sp.this.Vector3$$num);

That's scalac -optimize -Xprint:jvm output. Now there are even subclasses for each specialized type, so that you can initialize a Vector3 without boxing, but as long as Numeric is not specialized, you can't go further.

Well... you can write your own Numeric and specialize that, but, at that point, I'm not sure what you are gaining by making the class parameterized in first place.