Just like my original reply, I think most people would assume speed ?= someVlue to perform just like the Ruby a ||= b (if left side is null, assign some value).
ORIGINAL:
I think this would have limited gain.
Something like
speed ?= someValue
is only short for
if (speed == null) speed = someValue
or
speed = speed ?: someValue
IMO, although speed ?= someValue is slightly shorter than the current options, the current options work fine as they are now.
All of these options assume we’re working with non-final fields. Maybe I’m missing some use case where you have a ton of null properties that need to be set to default values.
val maybeSpeed: Int? = record["speed"] as Int?
if(maybeSpeed != null) speed = maybeSpeed
I was wrong comparing it to ruby. Ruby’s a ||= b is more like speed = speed ?: defaultValue
But what I want is compare right side expression to null, and only if its not null then assign.
And yes I have a lot of code like that. Its mostly untyped data transfer maps in which most keys can absent
The meaning is to assign only if not null (maybe it would work on either side - aka a field reference on a null object). I can see how ?= may be confusing though. I like the concept, I’m not sure on the syntax.
I think no, the value should stay the same, and not reassigned or reset to default when right-hand side is null. speed is just a var property, in this particular case it is delegated to some ORM-like storage like var speed: Int? by Storage.attribute<Int?>("columnName") but it doesn’t actually matter
Normally you would use one of the proposed solutions above (using ?:) to provide a default value, but in your case you want to keep the current value unless the new value is not null.
The version with let is the shortest way to write what you need at this moment. If you find it hard to read, you could write a function yourself. But this will make the code a bit longer:
fun <T: Any> assignIfNotNull(value: T?, block: (T) -> Unit) {
if (value != null) {
block(value)
}
}
fun main(args: Array<String>) {
val record = mapOf("speed2" to 2)
var speed: Int? = 1
assignIfNotNull(record["speed"] as Int?, { speed = it })
println(speed)
assignIfNotNull(record["speed2"] as Int?, { speed = it })
println(speed)
}
A shorter syntax would be nice, but I agree that ?= is not appropriate, because the question mark currently always evaluates the expression before it. Maybe reverse it: =?
I know reflection can be costly at times, but in this case I wonder how much of an impact it would be on the application. It runs fine in JavaScript as well.
I’d love to see some performance metrics to show if this use case really is costly.
Not expressing an opinion on the proposal, but that is subtly different in that it always sets speed. For standard setters, it doesn’t matter but with custom setters it could be a big difference.
I got confused again
groovy’s new operator checks if left side is null but in the first message of the post I wanted simpler syntax to check right side, and assign it only when it contains something but null
if there would be both ?= and =? for that two cases that would make sense, but isn’t it too much, WDYT?