I want to write guard let statement in Kotlin like Swift.
For example:
guard let e = email.text , !e.isEmpty else { return }
Any advice or sample code?
I want to write guard let statement in Kotlin like Swift.
For example:
guard let e = email.text , !e.isEmpty else { return }
Any advice or sample code?
Try
val e = email.text?.let { it } ?: return
Explanation: This checks if the property email.text
is not null
. If it is not null, it assigns the value and moves to execute next statement. Else it executes the return
statement and breaks from the method.
Edit: As suggested by @dyukha in the comment, you can remove the redundant let
.
val e = email.text ?: return
If you want to check any other condition, you can use Kotlin's if
expression.
val e = if (email.text.isEmpty()) return else email.text
Or try (as suggested by @Slaw).
val e = email.text.takeIf { it.isNotEmpty() } ?: return
You may also like to try guard
function as implemented here: https://github.com/idrougge/KotlinGuard
Try
val e = email.text ?: run {
// do something, for example: Logging
return@outerFunction
}
if you want to do something else before return
.
I have a slightly different solution, if you are looking to recreate the ability that swift has of unwrapping multiple optionals and then using the unwrapped variables.
consider adding these lines in a Kotlin file
inline fun <T1, T2, T3, R> guard(
p1: T1?, p2: T2?, p3: T3?,
condition: Boolean = true,
block: (T1, T2, T3) -> R
): R? = if (p1 != null && p2 != null && p3 != null && condition)
block(p1, p2, p3)
else null
inline fun <T1, T2, T3, T4, R> guard(
p1: T1?, p2: T2?, p3: T3?, p4: T4?,
condition: Boolean = true,
block: (T1, T2, T3, T4) -> R
): R? = if (p1 != null && p2 != null && p3 != null && p4 != null && condition)
block(p1, p2, p3, p4)
else null
(I did have up to p9 but saved it for brevity)
this means you do now do
//given you have
var firstName: String? = null
var lastName: String? = null
var email: String? = null
var password: String? = null
fun createUser(name: String, lname: String, mail: String, pword: String) {
// some work
}
you can now use it like this
guard(firstName, lastName, email, password){ fName, lName, mail, pword ->
createUser(fName, lName, mail, pword) // all your variables are unwrapped!
} ?: return // <- here if you want an early return
// or
guard(firstName, lastName, email, password,
condition = email.isValid
) { fName, lName, mail, pword ->
// N.B this will not execute if the email is not valid
createUser(fName, lName, mail, pword)
}
As this function is inlined you can use it in with coroutines and you can return a value from the block
and use it.
Edit: I have put all the code in a gist here https://gist.github.com/markGilchrist/b699b00e9baeaa5e725a2eb1e9e7f5d3
I used this:
it ?: return
Simple and short
I found another way to do that. Simply create following function:
inline fun <T: Any> T?.guard(block: () -> Unit): T {
if (this == null) block(); return this!!
}
Then you can use it like that:
val date: Date?
date = Date()
val nonNullableDate = date.guard { return }
nonNullableDate
is then of type Date
.
Anyway, as it is not during creation of a variable like in swift, NullPointerExceptions
are possible so make sure you exit the code part with a return
i.e.
Hopefully Kotlin is adding a guard
keyword in the future.