# Code improvements

I'm doing exercise 11.8 from Scala for impatient, asking to write class for matrix:

Provide a class Matrix—you can choose whether you want to implement 2 × 2 matrices, square matrices of any size, or m × n matrices. Supply operations + and *. The latter should also work with scalars, for example mat * 2. A single element should be accessible as mat(row, col).

The code is working, but may be there can be improvements to make code more functional or more stable:

``````class Matrix(val n: Int, val m: Int, fun: (Int, Int) => Double) {
private val matrix = Array.tabulate[Double](n,m)(fun)

def +(another: Matrix) = {
if (n != another.n || m != another.m)
throw new IllegalArgumentException("Sizes of arrays don't match.")
else
new Matrix(n, m, (i, j) => this(i)(j) + another(i)(j))
}
def *(another: Matrix) = {
if (m != another.n)
throw new IllegalArgumentException("Sizes of arrays don't match.")
else
new Matrix(n, another.m, (i,j) => { var sum = 0.0;
for (k <- matrix(i).indices) sum += matrix(i)(k) * another(k)(j);
sum }
)
}
def *(k: Int) = new Matrix(n, m, k * matrix(_)(_) )

def apply(i: Int)(j: Int) = matrix(i)(j)

override def toString = {
var result = ""
for (row <- matrix) {
for (value <- row)
result += value + "  "

result += "\n"
}
result
}
}
``````
-
It's curious how you use a function as part of the constructor parameters. Is that proposed by the book? If so, could you give more details? If not, then I think you went the wrong way. No clue why the `tabulate` is in there either, and I'm not sure if it's something the book said that you didn't mention, or something you came up with for reasons I don't understand. –  Daniel C. Sobral Aug 10 '12 at 18:11
Hi, thanks for response. I updated the question. No, it was not part of task, I used it by myself. What's wrong with function in constructor and tabulate, could you please explain? May be Array in constructor would be better, I just decided that it's quicker to generate values with function, than create 2-dimensional array. –  damluar Aug 10 '12 at 19:54
There should be a way to update individual values in the matrix, I think. The use of the function is clever, but won't work if you are allowed to update (create a new matrix with updated) individual values. I suggest you redo the problem with that additional (implicit?) requisite. –  Daniel C. Sobral Aug 10 '12 at 20:32

Remove all `var`. Doesn't the book show `for...yield` by that point? For example:

``````(i,j) => {
var sum = 0.0;
for (k <- matrix(i).indices) sum += matrix(i)(k) * another(k)(j);
sum
}
``````

Can be replaced with:

``````(i,j) => (for (k <- matrix(i).indices) yield matrix(i)(k) * another(k)(j)).sum
``````

The `var` on `toString` can be replaced by using `mkString`. I'll let you work out for yourself how to do that, now that I called your attention to that method. And, yes, it that method works on `Array` as well, though it doesn't appear on Scaladoc for Scala up to 2.9.2 because it is added implicitly. I suggest you use the nightly scaladoc to look things up -- the documentation there is better, though it may show things not available on release versions, and so is the tool itself.

-