views:

625

answers:

2

I want to be able to implicitly convert Tuples of numbers (Ints and double) into a vector object.

Assuming a Vector class with a + method

case class Vector(x: Double, y:Double){
  def + (v:Vector)= new Vector(x+v.x,y+v.y)
}

My goal is to have the following code work.

val vec = (1,2)+(.5,.3) // vec == Vector(1.5,2.3)

I can get it to work for Int with the following

implicit def int2vec(t:Tuple2[Int,Int])=new Vector(t._1,t._2)
val vec = (1,2)+(3,4) // vec == Vector(4.0,6.0)

But it fails when I add the convertion for double

implicit def int2vec(t:Tuple2[Int,Int])=new Vector(t._1,t._2)
implicit def double2vec(t:Tuple2[Double,Double])=new Vector(t._1,t._2)
val a = (1,2)
val b = (.5,.3)
val c = (1,1)+b // vec = Vector(1.5,1.3)
val d = (1,2)+(.3,.5) // compile error: wrong number of arguments
val e = (1,2)+((.3,.5)) // compile error: type mismatch

Trying just double per Andri's sugestion

implicit def double2vec(t:Tuple2[Double,Double])=new Vector(t._1,t._2)
val a = (.5,.3)
val b = (1,1)+a // type mismatch found:(Double,Double) required:String

What do I need to do to get this to work?

A: 

These implicit conversions are ambiguous and thus Scala won't use either of them. This is the reason why the last lines won't evaluate.

One way to fix this would leave the int2vec out completely, although this means all integers would be first implicitly converted into Doubles.

andri
Thank you. I'm obviously an idiot as I still can't get it to work.
ScalaNoob
+6  A: 

Scala's syntax is flexible, but it's not infinitely flexible. In particular, the confluence of tuples, parameters, and implicits makes this a really dangerous area in the library design space. As you've noticed, things are likely to break, not work well, and give cryptic error messages. I'd suggest you avoid it if you can.

In particular, I suggest you make the following definition:

val V = Vector

And then all your examples work as you'd expect, without any implicits, magic, or cryptic error messages, and at the cost of only one character per Vector.

val a = V(1,2)+V(.5,.3)
val b = V(1,2)+V(3,4)
val c = V(1,2)
val d = V(.5,.3)
val e = V(1,1)+b
val f = V(1,2)+V(.3,.5)
val g = V(.5,.3)
val h = V(1,1)+a

It's not exactly the syntax you want, but trust me, it'll save you pain and headaches in the long-run.

Jorge Ortiz