4

I'd like to define some implicit methods for arrays of doubles to make my code cleaner. Ideally, they would look like this:

type Vec = Array[Double]

implicit def enrichVec(v: Vec) = new {
  def /(x: Double) = v map (_/x)
  def *(u: Vec) = (v zip u) map {case (x,y) => x*y} sum
  def normalize = v / math.sqrt(v * v)
}

However the normalize function doesn't work as written because Scala won't apply implicit methods recursively. Specifically, I get an error Note: implicit method enrichVec is not applicable here because it comes after the application point and it lacks an explicit result type. I could avoid this by explicitly writing out the code for normalize, but that would be ugly. Is there a nicer solution?

davidsd
  • 771
  • 4
  • 18

2 Answers2

6

The anonymous class inhibits the recursive function definitions. You need to define the "RichVec" as a class and then separately define the implicit conversion.

type Vec = Array[Double]
implicit def enrichVec(v: Vec) = RichVec( v )
case class RichVec( v: Vec ) {
  def /(x: Double) = v map (_/x)
  def *(u: Vec) = (v zip u) map {case (x,y) => x*y} sum
  def normalize = v / math.sqrt( v * v )
}
Neil Essy
  • 3,607
  • 1
  • 19
  • 23
0

This works:

type Vec = Array[Double]
abstract class RichVec(v: Vec) {
  def /(x: Double): Vec
  def *(u: Vec): Double
  def normalize: Vec
}
implicit def enrichVec(v: Vec): RichVec = new RichVec( v ) {
  def /(x: Double) = v map (_/x)
  def *(u: Vec) = (v zip u) map {case (x,y) => x*y} sum
  def normalize = v / math.sqrt(v * v)
}

But there are other ways to do it. What is most important is that you specify the return type for the implicit.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681