[Feature Request] "pesudo-assign" operator


#1

Proposal

Add a “pseudo-assign” operator <- (hopefully with a better name) .

The function would be:

operator fun pesudoAssign(value: <T>): Unit

It has the same structure as the plusAssign function.

This allows for adding behavior to “assignments” without changing the behavior of the = operator.

This is already possible by overloading an augmented assignment operator (e.g. +=) or even get or invoke, but using += for this behavior is ugly and ambiguous. I think pseudo-assignment would have enough use cases to be worth giving its own operator (given that there is enough uses to add inline classes, and these are extremely useful for them).

Inline classes could even be given a <- operator by default for their internal property.

Examples

data class Wrapper(var v: Int){

     operator fun pesudoAssign(value: Number){ v = value.toInt() }

     operator fun pesudoAssign(value: String){ v = value.toInt() }
}

data class Example2(var v: Int, val map: MutableMap<String, String>){

    operator fun pesudoAssign(value: Number){ v = value.toInt() }

    operator fun pesudoAssign(value: Map<String, String>){

        map.clear()

        map.putAll(value)

    }
}

// innerValue is a placeholder for however this would be done in the Int class
operator fun Double.pesudoAssign(value: Number){ innerValue = value.toDouble() } 

fun main(args: Array<String>){
    val wrapped = Wrapper(4)

    wrapped <- 3
    println(wrapped.value) // prints 3

    wrapped <- "90"
    println(wrapped.value) // prints 90

    val doub = 4.5
    doub <- 7
    println(doub) // prints 7.0

}

Use Cases

Wrapper types (especially with upcoming inline classes).

Pesudo-assign to different properties depending on type.

Use a single pesudo-assignment to set multiple properties (e.g. pesudo-assign a pair, assign the first value to one property, and the second to a different property).

Optional, explicitly defined (pseudo-)assignment compatibility (e.g. pseudo-assign a Double to an Int).

Additional behavior on pesudo-assignment (e.g. pesudo-assign an id, make a database request to get property values for that id).

In general, there seem to be two main use cases: assigning to an internal variable or allowing assignment compatibility with a different type.

Similarity to Implicit Casting

This is notably similar to implicit casting, which is (thankfully) not going to be part of Kotlin. There are a few notable differences that keep this from having the same problems:

  • The possibility for other behavior (like accessing properties, see the Wrapper example).
  • No actual casting occurs.
  • There much less ambiguity, no more than other operators.

Plus, pseudo-assignment is already achievable using existing operators, this would just give it its own operator.

Caveat: Object Creation

There are cases where you would want to pesudo-assign an entirely new object. For example, if you have a class that queries data for an id (such as an Exposed DAO class) and a <- operator that changes the id, it would be easier to return an entirely new object for the new id, that then would be assigned to the left-hand variable. However, I didn’t see an easy way to implement that (without having two very very similar operators), and there aren’t that many use cases (and they are all doable by changing properties, although it can get messy).


#2

Please don’t turn Kotlin into Scala. Adding hundred of operators won’t make it better.


#3

In my opinion it brings semantics from other languages, which is not necessary.
This <- is used in Go for channel operations, and there it’s also not very comfortable.

If it works like += it should be +=


#4

@Beholder, I don’t disagree with you. The case I’m making is that this particular operator is useful enough and fills a distinct enough niche that it should be included. Kotlin’s support for wrappers (see inline classes) provides a use case that this operator is extremely useful in, to the point where it wouldn’t be out of place as a default method in inline classes.

@AlexeySoshin the example with += is to show that the operation can be done with += (because the method signature is the same), but the meaning is different. Using += for this would be like using /= to add an item to a list. Its possible, but unreadable and misleading.