Is there a reason the nullable operator + `let` is...
# compose
c
Is there a reason the nullable operator +
let
is broken going from version 1.0.1 of compose to alpha01? Code in thread.
1
Previously I could do this:
Copy code
var composableTitle: (@Composable () -> Unit)? = null,
composableTitle?.let {
    it()
} ?: run {
    Text(text = title, maxLines = 1, overflow = TextOverflow.Ellipsis)
}
but after migrating to alpha01 this seems to invoke the nullable composable even if it's null and never get to the run block.
j
It invokes the nullable composable? Do you mean to say you get a null pointer exception?
c
Oh, sorry I think I misspoke. It seems to create an empty composable. I.e it runs the let but
composableTitle
is null so actually I would expect a NPE if it runs through the let and tries to invoke it but instead I get nothing. By that I mean when I look in the layout inspector I don't see this composable at all. It's as though it skipped it. Instead I'd expect it to go to the run block. This leads me to believe that composableTitle is an empty lambda but when I debug through it it's null. I haven't changed this code except to upgrade the compose version
j
Yeah, just tried it myself, I'm reducing the problem now, hold tight.
🙏 1
👍 1
Ok, here is the reduced code:
Copy code
val lambda: (@Composable () -> Unit) = { throw Error("Should not be invoked") }
val v = if(false) { lambda(); } else null
if(v == Unit) throw Error("Should not be Unit")
if(v != null) throw Error("Should be null")
It didn't have anything to do with the let nor nullable operator, and the composable lambda isn't actually invoked. It's probably a bug where our branch group logic is special cased to handle
Unit
and that logic is wrong.
Thanks for reporting!
c
Ah, gotcha. I thought it'd be weird for compose to create a problem with part of the Kotlin language lol. Thanks for looking into this so fast! We'll just use if/elses in the meantime 🙂
j
Using if-else won't help you there because it's a bug in the branching group logic.
What you could do is:
Copy code
var composableTitle: (@Composable () -> Unit)? = null
composableTitle?.let {
    it()
    null
} ?: run {
    Text(text = title, maxLines = 1, overflow = TextOverflow.Ellipsis)
}
(Notice the
null
as the last statement inside the let block)
c
🤔 it does seem to work if I do
Copy code
if (composableTitle == null) {
    Text(text = title, maxLines = 1, overflow = TextOverflow.Ellipsis)
} else {
    composableTitle()
}
you're saying this shouldn't work ^?
j
Ah, that would work. I meant you can't just replace the nullable operator with an if/else statement and continue (ie. continuing to use the return value)
👍 1
if you change the logic of the program to avoid using the return value, that's fine.
c
Gotcha. Yeah that makes sense. I'll try out returning null in the let though because I like
lets
more lol
j
🤦
be careful of playing kotlin golf
😄 1
and make sure you add a comment explaining why the null and pointing to the linked bug.
c
Thanks, will do!
c
I have hit this bug too. I had some code like:
Copy code
val myDomainObject by myStateFlow.collectAsState()

myDomainObject?.let {
  // Show some UI
} ?: CircularProgressIndicator()
And on upgrade from compose 1.0.1 to 1.1.0-beta02 I lost my progress indicators. I can get the progress indicator back by adding a null check like:
Copy code
if (myDomainObject == null) {
  CircularProgressIndicator()
}