Search code examples
scalascala-breezend4j

Workaround for chained indexing Scala compiler error?


Chained indexing in ND4S and Breeze produces a Scala compiler error:

var m = Nd4j.create(2, 3)
var a = m(0, ->)
var b = a(0)
var c = m(0, ->)(0)

The first two work but the third produces:

not enough arguments for method apply: (implicit ev: org.nd4s.NDArrayEvidence[org.nd4j.linalg.api.ndarray.INDArray,B], implicit ev2: scala.reflect.Manifest[B])org.nd4j.linalg.api.ndarray.INDArray in class RichINDArray.

I tried with (0, 0) instead of (0) since it is still 2d, but that didn't matter. And many variations of extra parenthesis.

Is this the Scala parser thinking it is some other construct or a bug in ND4S? Is there some workaround syntax that can make chaining work?

EDIT:

Under Breeze:

var m = DenseMatrix.zeros[Int](5,5)
var a = m(0, ::)
var b = a(0)
var c = m(0, ::)(0)

a and b work but c produces this compiler error:

type mismatch; found : Int(0) required: breeze.linalg.support.CanSlice2[breeze.linalg.DenseMatrix[Int],Int,collection.immutable.::.type,?]

Maybe this is parsing as curried function calls, or a macro expands in a way that doesn't work here. And while I guess a person never needs to chain indexing, since m(0, 0) works above and any indexing can be collapsed, is there some solution for the general case of tricking Scala in these situations?

Also, chaining works with multidimensional arrays:

var n = Array.ofDim[Double](2, 3)
var x = n(0)(0)

Solution

  • Both methods m(0, ->) and m(0, ::) take a second implicit parameter list. Thus chaining the calls is interpreted by Scala as trying to provide this implicit parameter list explicitly. That's why it reports the argument number mismatch and the argument type mismatch.

    Try using (m(0, ->))(0) or m(0, ->).apply(0) (or the Breeze analogue). This forces Scala to provide the implicit parameter list implicitly, and your second call then becomes a normal function call as you had intended.