https://kotlinlang.org logo
Title
a

alex cole

01/09/2021, 12:12 AM
Hi, when using the get() operator overload, what type of info do you get when you put multiple parameters in there? for example
val x = object[5,3]
What type of data is the 5, 3 representing.
e

ephemient

01/09/2021, 12:13 AM
nothing, it works just like a normal method call
operator fun get(i: Int, j: Int)
would get
i=5 j=3
a

alex cole

01/09/2021, 12:14 AM
this would be for
operator fun Object.get(value: SomeDataType){}
I have to do that for every case or can I just read that value in as a string and parse from there?
e

ephemient

01/09/2021, 12:15 AM
if that's the only
operator fun get
then you can't write
object[i, j]
just as if you only defined
fun get(value: SomeDataType)
, you can't call
get(5, 3)
a

alex cole

01/09/2021, 12:15 AM
It would not default to an IntList?
e

ephemient

01/09/2021, 12:15 AM
no
if you defined a
operator fun get(vararg indices: Int)
then there would be an IntArray created to pass the varargs
but this certainly doesn't happen on its own. it really works like a normal function call, just with square brackets instead of round brackets
a

alex cole

01/09/2021, 12:19 AM
So I have a project where I am duplicating numpy's ND array. What would be the best way to get that index of my value through the get operator?
e

ephemient

01/09/2021, 12:20 AM
vararg
on the flip side, Python's behavior of magically squashing all the get arguments into a single tuple makes it impossible to distinguish
object[1]
from
object[(1, )]
a

alex cole

01/09/2021, 12:22 AM
could vararg take in colons in order to select sections of my array objects?
e

ephemient

01/09/2021, 12:26 AM
no, colon syntax for ranges does not exist in Kotlin. you could accept IntRange though, e.g.
operator fun get(range: IntRange)
object[1..5]
a

alex cole

01/09/2021, 12:27 AM
How would this work for a custom 2d array?
something like
object[1, 3..5]
e

ephemient

01/09/2021, 12:28 AM
there's no type-safe way to accept a variable mix of Int and IntRange, but if your dimensionality is fixed at d=2,
operator fun <T> Array2D<T>.get(x: Int, y: Int): T
operator fun <T> Array2D<T>.get(x: Int, y: IntRange): Array1D<T>
operator fun <T> Array2D<T>.get(x: IntRange, y: Int): Array1D<T>
operator fun <T> Array2D<T>.get(x: IntRange, y: IntRange): Array2D<T>
isn't too many overloads to deal with
a

alex cole

01/09/2021, 12:29 AM
But for N dimensional?
e

ephemient

01/09/2021, 12:29 AM
statically, you can't determine the types
a

alex cole

01/09/2021, 12:31 AM
Maybe ill just build a string parser.
e

ephemient

01/09/2021, 12:31 AM
something like
operator fun ArrayND.get(vararg indices: Any): Any
would allow for any mix, with the logic inside attempting to cast to Int or IntRange, but it can't be done in a type-safe manner. the caller will also have to perform an unsafe cast
unless you always return an ArrayND even if every index is specified exactly, in which case... how do you fetch a single element
a

alex cole

01/09/2021, 12:31 AM
What would you mean by its unsafe?
e

ephemient

01/09/2021, 12:32 AM
object[String, Object, List, Map, Array]
would compile
and obviously fail at runtime
as far as API design goes, I think you'd be better off leaving []/get retrieving a single element, and use a view (via a
.slice
property, perhaps) to achieve the rest, one dimension at a time
a

alex cole

01/09/2021, 12:34 AM
So I would have to make a set of rules that get parsed from the vararg and through an error if there is something other than an finite range or finite value.
e

ephemient

01/09/2021, 12:34 AM
there are no infinite ranges in Kotlin
a

alex cole

01/09/2021, 12:35 AM
Sorry meant whole.
So if I have a 3d matrix and want return a specific 1d array what would be the best way to use that in the get operator?
Would it be ArrayND[5, 3, -1] or should I just use ArrayND[5, 3]?
e

ephemient

01/09/2021, 12:41 AM
to elaborate, in my opinion it would be a better Kotlin API to separate
object[x, y, z]
0-D and
object.slice[x][y..y][z].asArrayND()
, where
operator fun <T> ArrayND<T>.get(vararg indices: Int): T
val <T> ArrayND<T>.slice: Slice<T> get() = ...
operator fun <T> Slice<T>.get(index: Int): Slice<T>
operator fun <T> Slice<T>.get(index: IntRange): Slice<T>
that way there is never any type confusion
a

alex cole

01/09/2021, 12:42 AM
Thank you very much. I think this will work.
Would you recommend that I interface with the Array Class?
e

ephemient

01/09/2021, 3:05 AM
in what way? conversions to/from collections or arrays, providing wrapped views around arrays, views as collections? all should be possible. depends on what you're using though
a

alex cole

01/09/2021, 3:07 AM
I was mainly building this library as a numpy replacement built off of ArrayND but many of the Array methods look very useful. I am still learning the kotlin style guide.
e

ephemient

01/09/2021, 3:08 AM
standard collections methods like
.map()
etc? that would make sense, although it might be hard to find reasonable semantics for others like
.filter()
a

alex cole

01/09/2021, 3:09 AM
I mainly wanted something easy to use like matlab or numpy.