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)
a: Array[Array[Float]] = Array(Array(0.0, 0.0), Array(0.0, 0.0))

scala> var b = Array.ofDim[Float](2,2)
b: Array[Array[Float]] = Array(Array(0.0, 0.0), Array(0.0, 0.0))

scala> a(0)(0) = 1   

scala> a(1)(1) = 1

scala> b(0)(1) = 2

scala> b(1)(0) = 2

scala> var m1 = new Matrix(a)
m1: Matrix = 
1.0 0.0
0.0 1.0

scala> var m2 = new Matrix(b)
m2: Matrix = 
0.0 2.0
2.0 0.0

scala> m1+=m2

scala> m1   
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. 

Notes

  1. fooyeahcode reblogged this from publicboolean
  2. publicboolean posted this