Reputation: 8580
Consider this nice utility extension function i wanted to use :
inline infix fun <T> T?.otherwise(other: () -> Unit): T? {
if (this != null) return this
other()
return null
}
It could be very useful for logging stuff when expressions evaluated to null for example:
val x: Any? = null
x?.let { doSomeStuff() } otherwise {Log.d(TAG,"Otherwise happened")}
but I see that it wont work for :
val x: Any? = null
x?.otherwise {Log.d(TAG,"Otherwise happened")}
see here for running example
Well when thinking about it i guess that makes sense that if x
is null the ?
makes the postfix not be executed, but i dont understand why the let
in the first example is any different?
Is it possible to fix the utility to be more robust and work without having to have let
in the chain?
Upvotes: 0
Views: 2368
Reputation: 23091
First, you can simplify the implementation:
inline infix fun <T> T?.otherwise(other: () -> Unit): T? {
if (this == null) { other() }
return this
}
Or
inline infix fun <T> T?.otherwise(other: () -> Unit): T? =
also { if (it == null) other() }
When you do this:
null?.otherwise { println("Otherwise happened") }
?.
means "execute if not null", so otherwise
is not executed.
What you need to write is:
null otherwise { println("Otherwise happened") }
Note this is very similar to the ?:
operator (as Vadik pointed out in the comments):
null ?: println("Otherwise happened")
The difference is that otherwise
always returns the value on the left (the same as also
), but ?:
returns the value on the right when the value on the left is null.
In my opinion, otherwise
is confusing, especially as it always returns the left value despite the name. You would be better to use the ?:
operator. Or perhaps rename it to something like alsoIfNull
.
Upvotes: 3
Reputation: 76
x?.let { doSomeStuff() }.otherwise {Log.d(TAG,"Otherwise happened")}
// ⬇️
val value = if (x != null) {
doSomeStuff()
} else {
null
}
value.otherwise {Log.d(TAG,"Otherwise happened")}
x?.otherwise { Log.d(TAG,"Otherwise happened") }
// ⬇️
if (x != null) {
otherwise { Log.d(TAG,"Otherwise happened") }
} else {
null
}
?.
means if the value is not null then execute the method and return the result otherwise return null
Upvotes: 0
Reputation: 2577
The let
example executes because, when you don't utilize the infix feature, it looks like this:
x?.let {}.otherwise {println("1")}
Notice that it's not ?.otherwise
; therefore, it always executes.
So to use otherwise
without let
, you can omit the ?
.
x.otherwise { ... }
Upvotes: 2