Scala: I can overload operators again!
Overloading operators is a neat feature that languages like C++ have, where the programmer can redefine a limited set of algorithmic operators. Why would you want to do this? This could come in handy if you’re defining a new object (a complex number, say) and you want to be able to specify what happens when you add two complex numbers together.
I say it’s a neat feature because it has limited functionality. The programmer may only redefine algorithmic operators (+,-,*,/,…). Some would even argue that operator overloading makes code almost impossible to maintain. (By “some”, I mean Sun Microsystems, now Oracle). It is primarily for this reason that there is no operator overloading in Java.
So I was very surprised to learn that Scala supports operator overloading. It not only allows you to redefine operators, but also define completely new operators. Let’s give it a whirl. Let’s construct a Matrix class.
class Matrix(var a: Array[Array[Float]]) {
var m = a.length // rows
var n = a(0).length // cols
def +=(b: Matrix) {
for (i <- 0 until m)
for (j <- 0 until n)
a(i)(j) += b.get(i,j)
}
def get(i: Int, j: Int): Float = {
return a(i)(j)
}
def override toString() = {
a.map(_.mkString(" ")).mkString("\n")
}
}
This class defines a new Matrix object that can get any entry given the row/column, and can add another matrix to it. It’s primitive, but demonstrates how simple operator overloading can be. We’ve also overridden a function toString() which will allow us to check out answer. We’ve defined the operator (+=), and the other parameter to the operator (Matrix b).
We can test this in the console.
scala> var a = Array.ofDim[Float](2,2) scala> var b = Array.ofDim[Float](2,2) scala> a(0)(0) = 1 scala> var m1 = new Matrix(a) scala> var m2 = new Matrix(b) scala> m1+=m2 scala> m1
a: Array[Array[Float]] = Array(Array(0.0, 0.0), Array(0.0, 0.0))
b: Array[Array[Float]] = Array(Array(0.0, 0.0), Array(0.0, 0.0))
scala> a(1)(1) = 1
scala> b(0)(1) = 2
scala> b(1)(0) = 2
m1: Matrix =
1.0 0.0
0.0 1.0
m2: Matrix =
0.0 2.0
2.0 0.0
res5: Matrix =
1.0 2.0
2.0 1.0
Voila! We can now go crazy writing a more intuitive Matrix class than one written in Java that uses methods like “plusEquals()” or “times()”. In Scala, operators are merely functions. Note that creating our += operator is done exactly the same way as our get() function. Hence, m1+=m2 can also be called as m1.+=(m2).
This concept is even extended to numbers (which are also objects in Scala)! That is, 1+2 is equivalent to saying 1.+(2)
In this respect we are given more freedom on defining operators.