Proposal: Allow get and set operators to be used a...
# language-proposals
r
Proposal: Allow get and set operators to be used at the same time For example, if we have the following interfaces
Copy code
interface Slot {
    operator fun plus(count: Int): Slot
    operator fun minus(count: Int): Slot
}

interface Shelf {
    operator fun get(row: Int, col: Int): Slot
    operator fun set(row: Int, col: Int, items: Slot)
}
We should be able to do this
Copy code
shelf[3, 7] += 2
Currently that show an error: > No set method providing array access
c
This works when overriding `plusAssign`:
Copy code
private interface Slot {
    operator fun plusAssign(count: Int): Unit
    operator fun minus(count: Int): Slot
}

private interface Shelf {
    operator fun get(row: Int, col: Int): Slot
    operator fun set(row: Int, col: Int, items: Slot)
}

private fun foo() {
    val shelf = object: Shelf {
        override fun get(row: Int, col: Int): Slot {
            TODO()
        }

        override fun set(row: Int, col: Int, items: Slot) {
            TODO()
        }
    }

    val slot = shelf[1, 2]
    shelf[1, 2] += 2
    shelf[1, 2] = slot - 1
}
r
I don't want to make the slot mutable. The point is that I get a slot from the shelf, run an operation that returns a new slot, and re-instert that slot in the same location in the shelf. A more limited version already exists in the language for primitives:
Copy code
interface Shelf {
    operator fun get(row: Int, col: Int): Int
    operator fun set(row: Int, col: Int, items: Int)
}

shelf[3, 7] += 2  // This works fine
I would just like to see it abstracted out to include the use case I provided
a
This is not the same semantic. += means adding something to the existing value. Set means replacing the current value. += implies a merge of values and set does not do this at all.
r
But it's not adding something to the existing value. The integer is immutable, so
self[3, 7] += 2
in this example is getting the value, calculating a new value, and setting to the new value. Or did I misunderstand what you meant?
Here is a simplified example that shows the getter and setter are indeed being called: https://pl.kotl.in/cgrArLlpU
Interestingly it works if the addend is the same type, so this works fine as well: https://pl.kotl.in/bnAjKS0Pf Note that
get
,
plus
, and
set
are indeed all called, so why not work with a different addend type so long as the result is the same type?
a
For me, += means that the left value is updated, not replaced. Therefore, using get, plus and set is not equivalent to plusAssign in term of memory/object management. If inplace update is a strong criterion of the operator (personnally, I think it should, but that is a personal opinion), then the compiler should never allow += to be replaced by get, plus and set. Otherwise (in-place update not enforced), then yes, your propsal is valid.
r
Ah, I see where you're coming from, but that's not what
+=
means according to the language specification. It is specifically designed to use either
plus
or
plusAssign
. https://kotlinlang.org/docs/operator-overloading.html#augmented-assignments
Also, the idea that
+=
should only update and not replace would remove the most common use case of increasing a var int:
Copy code
var x = 7
x += 3