Lukasz Kalnik
11/29/2024, 10:05 AMwhen
block, where I assert on properties of a type from a library being not null (so they cannot be smart-cast). I don't want to use !!
inside the when
cases, I also don't want to use ?.let { ... }
everytime.
Right now I solved it, that I assign every property to a local variable before the when block:
val result = ... // Result is a type from external library
// Assigning result properties to local variables, so they can be smart cast
val error = result.error
val product = result.product
// There are more properties
when {
error != null -> handleError(error) // Smart cast here to non-nullable error
product != null -> handleProduct(product) // same
// ...
}
Is there some other approach to get around this limitation?Sam
11/29/2024, 10:08 AM?.let
approach seems like the most idiomatic. What's the reason you don't want to write it that way?Lukasz Kalnik
11/29/2024, 10:11 AM?.let
on it. Also it adds a level of nesting.
More importantly, some of the when
cases check multiple values in combination, e.g.
when {
error != null && product != null -> // Do something with error and product
// ...
}
Sam
11/29/2024, 10:13 AMlet
without the when
. But that still wouldn't make it any easier when using multiple values.Sam
11/29/2024, 10:15 AMLukasz Kalnik
11/29/2024, 10:15 AMSam
11/29/2024, 10:16 AMLukasz Kalnik
11/29/2024, 10:16 AMLukasz Kalnik
11/29/2024, 10:17 AMwhen {
error != null -> {
with(error) {
if (ERROR_CODES_THAT_TRIGGER_REMINDER.contains(code)) {
CartRepository.instance.showReminderToScanProductsAtCashRegister = true
}
handleScanError(TextString(message))
}
}
fractionalQuantityInfo != null && !products.isNullOrEmpty() -> {
handleFractionalQuantityProduct(
products.first().toUi(scannedCode.type),
fractionalQuantityInfo,
)
}
!products.isNullOrEmpty() -> handleProducts(
products.map { it.toUi(scannedCode.type) },
)
voucher != null -> handleVoucher(voucher)
}
Lukasz Kalnik
11/29/2024, 10:19 AMLukasz Kalnik
11/29/2024, 10:19 AMLukasz Kalnik
11/29/2024, 10:20 AMRonny Bräunlich
11/29/2024, 12:15 PMfun something() {
val result = ...
val error = result.error
val product = result.product
when {
isNotNull(result.error) -> handleError(result.error)
isNotNull(result.product) -> handleProduct(result.product)
// ...
}
}
@OptIn(ExperimentalContracts::class)
private fun isNotNull(any: Any?): Boolean {
contract { returns(true) implies (any != null) }
return any != null
}
Lukasz Kalnik
11/29/2024, 12:22 PMwhen
cases.Lukasz Kalnik
11/29/2024, 12:22 PMRonny Bräunlich
11/29/2024, 12:23 PMLukasz Kalnik
11/29/2024, 12:23 PMLukasz Kalnik
11/29/2024, 12:24 PMLukasz Kalnik
11/29/2024, 12:24 PMLukasz Kalnik
11/29/2024, 12:24 PMKlitos Kyriacou
11/29/2024, 2:00 PM[A smart cast on a val property can only be used] if the check is performed in the same module where the property is declaredYou can't use a smart cast because
result
is an instance of a class declared in an external library. This makes sense because, as far as the compiler can see, there is no guarantee that successive invocations of this val
property will return the same value.Lukasz Kalnik
11/29/2024, 2:02 PMKlitos Kyriacou
11/29/2024, 2:03 PMLukasz Kalnik
11/29/2024, 2:03 PMLukasz Kalnik
11/29/2024, 2:03 PMLukasz Kalnik
11/29/2024, 2:04 PMKlitos Kyriacou
11/29/2024, 2:06 PMresult.error?.let { ... }
for example, also introduces a local variable of sorts ("it").Lukasz Kalnik
11/29/2024, 2:08 PM