Ashutosh Panda
10/14/2019, 5:16 PMvar nullTest:Int?=null
nullTest?println("1"):println("0")
Ruckus
10/14/2019, 5:19 PMif (nullTest != null) println("1") else println("0")
Casey Brooks
10/14/2019, 5:19 PMvar nullTest: Int? = null
println("${nullTest ?: 0}")
Casey Brooks
10/14/2019, 5:20 PMif
expression Ruckus postedPablichjenkov
10/14/2019, 5:24 PMnullTest?.let {
println("1")
} ?: run {
println("0")
}
Pablichjenkov
10/14/2019, 5:34 PMif let
in swift. For this simple usage it is overkilling. But if you want to extract a non-null and operate on it, or else run some code. I haven't found anything better than bellow.
nullTest?.let { nullTestNonNull ->
nullTestNonNull.safeAccess()
} ?: run {
println("nullTest is null, do something else")
}
Adam Powell
10/14/2019, 5:42 PMprintln(if (nullTest != null) 1 else 0)
Adam Powell
10/14/2019, 5:43 PM?.let {} ?: run {}
is because it does not behave like the if/else people try to use this asAdam Powell
10/14/2019, 5:43 PMlet {}
evaluates to null the second run
branch will executeAdam Powell
10/14/2019, 5:44 PMAdam Powell
10/14/2019, 5:45 PMPablichjenkov
10/14/2019, 5:45 PMAdam Powell
10/14/2019, 5:47 PMPablichjenkov
10/14/2019, 5:47 PMguard
and if let
from swift.Pablichjenkov
10/14/2019, 5:48 PMYago Lasse
10/14/2019, 5:48 PM?:
gets null, then the run { }
is calledYago Lasse
10/14/2019, 5:49 PMAdam Powell
10/14/2019, 5:50 PMYago Lasse
10/14/2019, 5:50 PMfun main() {
val x: Int? = null
x?.let { print("x is not null") } ?: run { print("x is null") }
}
Yago Lasse
10/14/2019, 5:50 PMx is null
Pablichjenkov
10/14/2019, 5:50 PMwhen
but in my opinion is extremely verbose for such a simple thingAdam Powell
10/14/2019, 5:51 PMPablichjenkov
10/14/2019, 5:54 PMfun main() {
val x: Int? = 1
x?.let {
print("x is not null")
null
} ?: run { print("x is null") }
}
Pablichjenkov
10/14/2019, 5:54 PMnull
accidentally. Both branches execute.Yago Lasse
10/14/2019, 5:55 PMmyList?.takeIf { it.isNotEmpty() }?.forEach {
// do some stuff
} ?: run {
// otherwise
}
Yago Lasse
10/14/2019, 5:56 PMAdam Powell
10/14/2019, 5:56 PM// do some stuff
Adam Powell
10/14/2019, 5:58 PMforEach
- which kind of illustrates the point - it's very much not an if/else 🙂Adam Powell
10/14/2019, 5:58 PMYago Lasse
10/14/2019, 6:04 PMlet
instead of forEach
then the let
result would matter for the run block to be executedYago Lasse
10/14/2019, 6:05 PMSteve Young
10/14/2019, 7:48 PMPablichjenkov
10/14/2019, 7:49 PMpublic inline fun <T, R> T?.whenNonNullOrElse(
nonNullBlock: (T) -> R,
nullBlock: (() -> R)
): R? {
return if (this != null) { nonNullBlock(this) } else { nullBlock()}
}
Then
fun main() {
val x: Int? = null
val y: Int? = x.whenNonNullOrElse(
{
println("x is not null")
null
},
{
println("x is null")
-1
}
)
print("y = $y")
}
Ruckus
10/14/2019, 7:56 PMif
? (Besides a massive reduction in readability of course.)Ruckus
10/14/2019, 7:57 PMfun main() {
val x: Int? = null
val y: Int? = if (x != null) {
println("x is not null")
null
} else {
println("x is null")
-1
}
print("y = $y")
}
Yago Lasse
10/14/2019, 8:00 PMif(x != null) {
x.method()
} else {
print("null")
}
Then u have to tell somehow to the compiler that x is not null, because it still thinks that x may have changed.Pablichjenkov
10/14/2019, 8:00 PMYago Lasse
10/14/2019, 8:01 PMfun String.isNullOrBlank()
exists and use compiler contracts (and dont need ?
safe call operator)Ruckus
10/14/2019, 8:01 PMval _x = x
Ruckus
10/14/2019, 8:02 PMPablichjenkov
10/14/2019, 8:02 PMval _x = x
it start polluting the codeRuckus
10/14/2019, 8:03 PMx.whenNullOrElse({ ... }, { ... })
Ruckus
10/14/2019, 8:08 PM_x
should be replaced with a better name, but since when do we get names right? 🧌)Pablichjenkov
10/14/2019, 8:09 PMx.whenNullOrElse({ ... }, { ... })
is longer and more verbose its still a one liner shot. You can concatenated with stuff like apply
and also
Instead val x = x
force you to write more than one line.Yago Lasse
10/14/2019, 8:10 PMx?.let { } ?: run { }
and take care of what you return inside let
, and it will kinda work like a if not null/elseYago Lasse
10/14/2019, 8:11 PMit
is not null inside the let
block.Ruckus
10/14/2019, 8:13 PMPablichjenkov
10/14/2019, 8:15 PMRuckus
10/14/2019, 8:17 PMPablichjenkov
10/14/2019, 8:17 PMx?.let { null } ?: run {}
Yago Lasse
10/14/2019, 8:18 PMprint(if(x != null) 1 else 0)
.
But if we need the non null value, how to make it without a !!
? Shadowing a variable is really the best option here?Ruckus
10/14/2019, 8:18 PMPablichjenkov
10/14/2019, 8:22 PMif/else
the least possibleRuckus
10/14/2019, 8:22 PMPablichjenkov
10/14/2019, 8:27 PMif/else
🙂. When you have a functional language that let you do cleaner stuff.Ruckus
10/14/2019, 8:49 PMPablichjenkov
10/14/2019, 9:03 PMbranch creation
in code. if/else
are a good contributors to it, when not used as expression.
val xLocal = x
val yLocal = y
val z = if (xLocal != null) {
if (yLocal != null) {
(xLocal + yLocal)*(xLocal + yLocal)
} else {
xLocal*xLocal + 0
}
} else {
if (yLocal != null) {
0 + yLocal*yLocal
} else {
0 + 0
}
}
vs
val z = x.whenNonNullOrElse(
{ it }
, { 0 }
) + y.whenNonNullOrElse(
{ it }
, { 0 }
).map{
it*it
}
karelpeeters
10/14/2019, 9:03 PMif
is completely functional, it doesn't have state or something like that.karelpeeters
10/14/2019, 9:04 PMval z = (xLocal ?: 0) + (yLocal ?: 0)
Pablichjenkov
10/14/2019, 9:05 PMRuckus
10/14/2019, 9:06 PMkarelpeeters
10/14/2019, 9:06 PMwhenNotNullOrElse
is cleaner than some other alternative.Pablichjenkov
10/14/2019, 9:29 PMvar z = 0
if (xLocal != null) {
if (yLocal != null) {
z = xLocal + yLocal
} ...//missing branch, no compiling error but Business Logic error(worst)
} else {
if (yLocal != null) {
z = 0 + yLocal
} else {
z = 0 + 0
}
}
@karelpeeters I agree that in many cases using the if/else
expressiveness and the elvis operator will reduce verbosity.
However, for the case when we want to apply an operation on a nullable receiver or else doSomething different, it makes it very concise to my liking.
But well I agree with Ruckus I kind of diverge from the initial use case.