Consider following code using implicit class. I would like to use extension instead, but I run into several issues:
type IXY = (Int, Int)
implicit class IXYOps(private val xy: IXY) extends AnyVal {
inline def x: Int = xy._1
inline def y: Int = xy._2
def +(that: IXY): IXY = (xy._1 + that._1, xy._2 + that._2)
def -(that: IXY): IXY = (xy._1 - that._1, xy._2 - that._2)
def *(that: IXY): IXY = (xy._1 * that._1, xy._2 * that._2)
def /(that: IXY): IXY = (xy._1 / that._1, xy._2 / that._2)
def *(x: Int): IXY = (xy._1 * x, xy._2 * x)
def /(x: Int): IXY = (xy._1 / x, xy._2 / x)
def unary_- : IXY = (-xy._1, -xy._2)
def min(that: IXY): IXY = (x min that.x, y min that.y)
def max(that: IXY): IXY = (x max that.x, y max that.y)
def manhattanSize: Int = math.abs(x) + math.abs(y)
def manhattanDistance(that: IXY): Int = (this - that).manhattanSize
def dot(that: IXY): Int = x * that.x + y * that.y
def size2: Double = xy.dot(xy)
def size: Double = math.sqrt(xy.dot(xy))
def dist(that: IXY): Double = (this - that).size
inline def map[X](f: Int => X): (X, X) = (f(xy._1), f(xy._2))
def abs: IXY = map(math.abs)
def toSeq: Seq[Int] = Seq(xy._1, xy._2)
}
implicit class DoubleTupleOps(private val xy: (Double, Double)) extends AnyVal {
inline def x: Double = xy._1
inline def y: Double = xy._2
def +(that: (Double, Double)): (Double, Double) =
(xy._1 + that._1, xy._2 + that._2)
def -(that: (Double, Double)): (Double, Double) =
(xy._1 - that._1, xy._2 - that._2)
def *(that: (Double, Double)): (Double, Double) =
(xy._1 * that._1, xy._2 * that._2)
def /(that: (Double, Double)): (Double, Double) =
(xy._1 / that._1, xy._2 / that._2)
def *(x: Double): (Double, Double) = (xy._1 * x, xy._2 * x)
def /(x: Double): (Double, Double) = (xy._1 / x, xy._2 / x)
def min(that: (Double, Double)): (Double, Double) =
(x min that.x, y min that.y)
def max(that: (Double, Double)): (Double, Double) =
(x max that.x, y max that.y)
def size2: Double = xy._1 * xy._1 + xy._2 * xy._2
inline def map[X](f: Double => X): (X, X) = (f(xy._1), f(xy._2))
def abs: (Double, Double) = map(math.abs)
def toSeq: Seq[Double] = Seq(xy._1, xy._2)
}
val doubles = (0.0, 1.0) - (1.0, 0.0)
val ints = (0, 1).manhattanDistance((1, 0))
When I convert IXYOps
to extension, I get error:
value manhattanSize is not a member of (IXY) => IXY.
An extension method was tried, but could not be fully constructed:
manhattanSize(
{
def $anonfun(that: IXY): IXY = this.-(that)(that)
closure($anonfun)
}
)
See Scastie - An interactive playground for Scala.
When I remove the size and manhattanSize methods and try to convert both IXYOps and DoubleTupleOps, i get errors like this:
Double definition:
def +(xy: IXY)(that: IXY): IXY in object XX at line 8 and
def +(xy: (Double, Double))(that: (Double, Double)): (Double, Double) in object XX at line 33
have the same type after erasure.
See Scastie - An interactive playground for Scala.
How can I work around this?