Reputation: 15
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
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
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