Hi! :slightly_smiling_face: I have a Matrix class...
# announcements
m
Hi! 🙂 I have a Matrix class with a primary constructor that takes two integer arguments (rows and columns) and a supplier function that tells it how to get its next element based on its indices:
Copy code
class Matrix<N : Number>(private val rows: Int, private val columns: Int, f: (Int, Int) -> N) : List<List<N>>
by List(rows, { i -> List(columns) { j -> f.invoke(i, j) } }) {
Now I want to add a secondary constructor that would take an iterable (list or array) of elements, like this:
Copy code
constructor(rows: Int, columns: Int, values: Iterable<N>) {
    val iterator = values.iterator()
    Matrix(rows, columns) { _, _ -> iterator.next() }
}
This doesn't work, says "call to primary constructor expected" Any advice on how to address this problem, Kotlin-style?
j
I think your constructor should do something like this:
Copy code
constructor(rows: Int, columns: Int, values: Iterable<N>) : this(rows, columns...)
m
this is meant to call a primary constructor and then add some extra properties to it
j
Copy code
constructor(rows: Int, columns: Int, values: Iterable<N>): this(rows, columns, { _, _ -> values.iterator().next() })
m
that won't work, it will set all elements to the first value of the list
j
To me it looks the same as your example
m
in your code, for each element, a new instance of iterator will be created
j
you want to call the primary constructor like
Matrix(...)
m
and thus in will provide the first element, always
j
perhaps
m
i tried that 🙂
j
ah
yeah perhaps make a static helper function?
m
yeah, this would do probably
i also tried making two "secondary" constructors (so none of them primary)
but then i don't know how to delegate properly
j
Copy code
companion object {
		operator fun <N: Number> invoke(rows: Int, columns: Int, values: Iterable<N>) {
			val iterator = values.iterator()
			Matrix(rows, columns) { _, _ -> iterator.next() }
		}
	}
then you can call it like this:
Copy code
Matrix(5, 5, listOf(5))
of course I miss a return statement 😄 but you get the gist
m
ah, so you mean like a helper Invoke function so that my constructor would work?
i thought you meant make a factory function instead of a secondary constructor
j
yep
m
but i think if i make a helper invoke function, it will still complain that a call to the primary constructor is expected
that's the point, if i have a primary constructor, the secondary one MUST call the primary one
j
as I said the return was missed
Copy code
companion object {
		operator fun <N: Number> invoke(rows: Int, columns: Int, values: Iterable<N>): Matrix<N> {
			val iterator = values.iterator()
			return Matrix(rows, columns) { _, _ -> iterator.next() }
		}
	}
This helper function instantiates a Matrix<N> object
m
oh Kotlin, some of your features are extra obscure =_=
j
so basically you override the invoke() function of the companion object with a certain set of arguments
m
ah, so this would be instead of a secondary constructor
j
which in terms you make it return the actual object
m
not a factory function, but rather an invoke
yeah, that would work
thanks!
I also did this:
Copy code
constructor(rows: Int, columns: Int, values: List<N>) : this(rows, columns, { i, j -> values[i * columns + j] })