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.