Multiple dimensional arrays

I’m looking at several examples of scala multi-dimensional arrays, and I’m a bit unsettled.
Several sources are similar to this one.

Is it actually the case that Scala 2-d arrays are represented as an Array of Arrays? If so, is it left up to me the programmer to assure that the inner arrays are all the same length?
For example, what is to prevent someone from giving me what I hope is a 3x3 array, but in fact looks like this:

Array(Array(1,2,3),Array(4,5,6),Array(7,8))

Do I need to emulate 2d 3x3 arrays with a 1-d array of size 9, with accessor functions which specify row and column and internally does the multiply/add element access?

Yes, Scala’s Array type is equivalent to Java arrays and therefore JVM arrays, which do not have a low level notion of multiple dimensions. A multidimensional array is always just an array of arrays.

The type of the array also only encodes the number of dimension, but not their size, so you couldn’t write a function signature specifying a 3x3 Array anyway, your type can only specify, that it should be 2D (e.g. Array[Array[Int]] here).

If you want to have a function, where you can only pass in a certain shape of array, you’ll have to roll your own Matrix class or look for a library that provides this.

That would be one way to implement it. Alternatively, you could maybe use something like refined or shapeless to add additional constraints to types, which admittedly doesn’t have the nicest syntax.

If you what to make sure the Array given to you has the right dimension, add some code to check it would be a simple way.

If it is manditory that each of the secondary arrays have 3 elements, then I would create a case class for that. For instance:

case class InnerArray(val1: Int, val2: Int, val3: Int)
Array(InnerArray(1,2,3), InnerArray(4,5,6), InnerArray(7,8)) // doesn't compile
Array(InnerArray(1,2,3), InnerArray(4,5,6), InnerArray(7,8,9)) // compiles

Now the type of the array is Array[InnerArray] and you are guaranteed your behavior.

The requirement is not that the inner array have dimension 3, rather the requirement is that the inner array have the same dimension as the outer array. But yes, defining my own class to handle this is not so difficult.

  case class sqMatrix(val dim: Int, val tabulate: (Int, Int) => Double) {
    val arr: Array[Double] = Array.tabulate(dim * dim)((i: Int) => tabulate(i / dim, i % dim))
    override def toString:String = {
      (0 until dim).map { row => {
        val x = (0 until dim).map { col => this(row, col).toString }
        x.mkString("[", ",", "]")
      } }.mkString("[",",","]")
    }
    def apply(row: Int, col: Int): Double = arr(row * dim + col)
...
}