I’m trying to figure out a more elegant way to wri...
# announcements
e
I’m trying to figure out a more elegant way to write:
Copy code
if (intent.getStringExtra(SUGGESTION_KEY) != null) {
    suggestionButton.text = intent.getStringExtra(SUGGESTION_KEY)
    suggestionButton.visibility = View.VISIBLE
} else {
    suggestionButton.visibility = View.INVISIBLE
}
I can’t write the following, because one arm returns a
String
and the other
Unit
:
Copy code
intent.getStringExtra(SUGGESTION_KEY)?.let { suggestion ->
    suggestionButton.text = suggestion
    suggestionButton.visibility = View.VISIBLE
} ?: suggestionButton.visibility = View.INVISIBLE
(I know there is a function
intent.hasStringExtra()
, but I’d like a general solution not specific to intents.) How should I rewrite the original block of code, or is it best as is?
c
You can use
run { }
for the second arm (
?.let { ... } ?: run { ... }
). Though I think the original example is more clear (maybe just drop
intent.getStringExtra
into a temporary variable to avoid the double lookup)
e
Thanks, @Casey Brooks. Why does
let ?: run
do the trick? (I’ll stick with the original code but want to understand.)
c
The whole statement is evaluated as an expression. Each branch, both the let and
?:
need an expression to return a value. Variable assignment is not an expression and cannot return a value, which is why the compiler chokes on it. Wrapping that assignment in
run { }
turns it into a Unit-returning expression
e
So if one path has
run
, the compiler knows the overall expression should return Unit (even if one path returns a value)?
b
run
can return any type as well
also consider
isInvisible
extension from ktx, in this case you can avoid branches.
Copy code
val suggestion = intent.getStringExtra(SUGGESTION_KEY)
suggestionButton.text = suggestion
suggestionButton.isInvisible = suggestion == null
e
Thanks, @bezrukov, it’s good to know about
isInvisible
, although there’s more code in the then-body than I showed.
I’d still like to know why using `let`/`run` solves the problem.
b
According to your initial question why it didn't work without run - it's because assignment in kotlin is not an expression (it is in Java, so you can write a = b = c).
And when you write
some code ?: some more code
both parts must be expression
e
I see. I assumed that the value of statements was of type Unit, but they don’t have a value at all. Thank you!
b
When you wrap the assignment into run block, it knows there is no return statement and adds
return Unit
to it
✔️ 1
l
FYI, it's possible to make intent specs to provide type-safe and key-safe usage: https://github.com/LouisCAD/Splitties/tree/master/modules/intents