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