mikehearn
06/21/2023, 10:36 AMif (val foobar != null) { ... }
where foobar
is earlier declared as a nullable var. Today you can do this by writing foobar?.let { foobar -> .... }
but I dislike this:
1. It is a conditional but looks nothing like one. The meaning isn't obvious to someone new to Kotlin even if it's logical.
2. The name of the variable is repeated twice.
3. It requires an even uglier form if you're doing a type based smart cast i.e. (foobar as? Thing)?.let { ... }
, compare to if (val foobar is Thing) { ... }
.
This new syntactic form would combine the check with capturing current value of the variable onto the stack and shadowing the name.Adam S
06/21/2023, 10:53 AMfun main() {
var x: Number? = 1
when (val x = x) {
null -> println("x is null")
is Int -> println("x is an int $x")
is Long -> println("x is a long $x")
}
}
Although there’s a warning for name shadowing.
What might be more idiomatic is to create a new function, then x
will be typecastable
fun main() {
var x: Number? = 1
process(x)
}
fun process(x: Number?) {
when (x) {
null -> println("x is null")
is Int -> println("x is an int $x")
is Long -> println("x is a long $x")
}
}
However, it would mean any code following process(x)
wouldn’t know about the type of x
. Maybe contracts could help?
fun main() {
var x: Int? = 1
if(process(x)) {
x.toLong() // no `?` needed - x is known not to be null
}
}
@OptIn(ExperimentalContracts::class)
fun process(x: Number?): Boolean {
contract { returns(true) implies (x != null) }
when (x) {
null -> {
println("x is null")
return false
}
is Int -> println("x is an int $x")
is Long -> println("x is a long $x")
}
return true
}
Anyway, I agree that the scope functions are often confusing, and easy to overuse. Although, I’m glad they exist in the stdlib, because if they didn’t then every library would be implementing their own alternatives!
Rather than a ?.let { ... }
I’d much rather have
var foobar; Int? = null
val foobarValue = foobar
if (foobarValue != null) {
// ...
}
mikehearn
06/21/2023, 11:10 AMval foobar = foobar
but then you end up with name shadowing warnings and an apparently useless statement the meaning of which is only obvious if you already know Kotlin well. And the scope outlasts the scope of the conditional, which is usually not what you need.jw
06/21/2023, 11:23 AMmikehearn
06/21/2023, 11:25 AMjw
06/21/2023, 11:31 AMAlexis Manin
06/21/2023, 11:42 AMrequire (foobar != null)
and require(foobar is Thing)
enough ? As long as foobar is a val and not a var, it shiuld be autocasted in the following statementsjw
06/21/2023, 11:43 AMmikehearn
06/21/2023, 12:34 PM