juanamari
juanamari

Reputation: 15

How can I redefine an operator as a function?

I've been thinking about a way to stop repeating myself when I create new code for a class, for instance, I need to sum all the values within a case class when the same class appears.

An example might better explain what I'm currently doing:

case class A(a: Double, b: Double) {
    def +(that: A): A {
        A(a + that.a, b + that.b)
    }
    def *(that: A): A {
        A(a * that.a, b * that.b)
    }
}

which allows me to do:

val a = A(1, 2)
val b = A(3, 4)
val c = a + b

where c = A(4, 6), right?

Well, what if I want to generalize the operation? For instance, let me give you an example of something that does not work but that I believe portrays my intention perfectly.

case class A(a: Double, b: Double) {
    def operation(op: (x: Double, y: Double) => Double)(that: => A) = {
        A(op(a, that.a), op(b, that.b))
    }
}

Now, I know that doesn't work because I probably got some extremely important concepts mixed up which I haven't pinpointed yet, but I came up with this idea thinking of this possibility:

val a = A(1, 2)
val b = B(3, 4)
val + = (x: Double, y: Double) => (x + y)
val res = a + b

I know that this can be done in different ways which will achieve the same result, but is there a way to portray generic operations like this?

Upvotes: 1

Views: 86

Answers (2)

jwvh
jwvh

Reputation: 51271

Not exactly sure what you're after, but maybe this comes close.

case class A(a: Double, b: Double) {
  def @@(that:A): ((Double, Double) => Double) => A =
    op => A(op(a, that.a), op(b, that.b))
}

Usage:

val a = A(7, 2)
val b = A(3, 4)

(a @@ b)(_+_)      // res0: A = A(10.0,6.0)
(a @@ b)(_*_)      // res1: A = A(21.0,8.0)
(a @@ b)(Math.min) // res2: A = A(3.0,2.0)

Upvotes: 2

TeWu
TeWu

Reputation: 6526

You can do this like that:

case class A(a: Double, b: Double) {
  def + = operation(_ + _) _
  def * = operation(_ * _) _

  private def operation(op: (Double, Double) => Double)(that: => A) =
    A(op(a, that.a), op(b, that.b))
}

Upvotes: 2

Related Questions