brief function code for null check in kotlin - kotlin

I have a test function and return Int.
fun test ():Int {
colors?.let { colorsArrayList ->
color1 = colorsArrayList.getOrNull(0)?.let {
return if (HexColorValidator().validate(it)) {
Color.parseColor(it)
} else {
Color.parseColor("#8DE7C1")
}
} ?: kotlin.run {
return Color.parseColor("#8DE7C1")
}
} ?: run {
return Color.parseColor("#8DE7C1")
}
return Color.parseColor("#8DE7C1")
}
}
can I write a brief then now?
return Color.parseColor("#8DE7C1")
this very repeated. can brief this line code?

Whenever I see code with a lot of conditional logic, I try to remember that I can "push" nulls rightward. Instead of handling if/else every time you need to test for null, imagine that you just take what you want (happy path) and pass the nulls on. Eventually, at the end, you'll end up with either the answer you want or null, and can return the value you want.
For example (mostly untested):
fun test() =
colors
?.getOrNull(0)
?.let { if(HexColorValidator().validate(it)) Color.parseColor(it) else null }
?: Color.parseColor("#8DE7C1")
Another way to make this easier to read is to extend String (what I'm presuming you have in colors) to hide the call to HexColorValidator:
fun String.parseColor(): Int? =
if (HexColorValidator().validate(this)) Color.parseColor(this)
else null
And then your test() function gets a bit simpler:
fun test(): Int =
colors
?.getOrNull(0)
?.parseColor()
?: Color.parseColor("#8DE7C1")

Related

kotlin: If value is null then exit, else use that value as not nullable

Essentially this is in the title. I have a value that could be null. If it is, I just want to exit with a message. If it's not null, then there's a whole slew of work I need to do with this value.
I've found similar, but not quite this exact situation. And it's the subtle difference that's driving me nuts. Here is my code in java:
if (value == null) {
print("error!");
return;
}
print(value);
doFunStuff(value);
etc(value);
All those methods using value require it to be non-null.
But I'm having a difficult time figuring this out in kotlin. With everything I try, the compiler still insists that value is still nullable and refuses to use it in the functions.
What is the kotlin way of doing this very common code flow?
If your methods truly have non-null parameters, the Kotlin compiler should be smart enough to do a smart cast to Object from Object?.
fun yourMethod(value: Object?) {
if (value == null) {
print("error!")
return
}
print(value) // Smart cast happens here
doFunStuff(value)
etc(value)
}
fun print(value: Object) {
// Implementation
}
fun doFunStuff(value: Object) {
// Implementation
}
fun etc(value: Object) {
// Implementation
}
But you can also force the conversion by using the !! operator (though in this case the compiler will tell you it's not necessary):
fun yourMethod(value: Object?) {
if (value == null) {
print("error!")
return
}
val nonNullValue = value!!
print(nonNullValue)
doFunStuff(nonNullValue)
etc(nonNullValue)
}
fun print(value: Object) {
// Implementation
}
fun doFunStuff(value: Object) {
// Implementation
}
fun etc(value: Object) {
// Implementation
}
If your value is a local variable or a function parameter, you won't have this problem, because the compiler will smart-cast it to not-null.
So, I'm assuming value in this case is a member property.
Option 1 is to copy it to a local variable to use in the function:
val value = value
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
Option 2 is to use the let or also scope functions to do the same thing, but this might not be a good option here because so much code would become nested. This is more useful when you're only calling one or two functions with the object, in which case, you wouldn't even have to name it (just call it it).
value.let { value ->
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
}
If your entire function works with this one property, you can avoid the nesting problem like this, if you don't mind it returning something besides Unit:
fun foo() = value.also { value ->
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
}
Option 3 is to assert non-null every time you use it, but this is very ugly. This is only safe if you know the property is only ever accessed from the same thread this function is ever called on.
if (value == null) {
print("error!")
return
}
print(value!!)
doFunStuff(value!!)
etc(value!!)
Expanding on #Mehul's answer, this would only run the code in the let if the value was not null. If null, you could run the outside process and return from it.
value?.let { nonNullValue ->
print(nonNullValue);
doFunStuff(nonNullValue);
etc(nonNullValue);
}?: run { print("error!") ; return }
That said, since you are no longer needing the return to abort the function if null, you could simply do this and further clean it up replacing the lambda.
value?.let {
print(it);
doFunStuff(it);
etc(it);
}?: print("error!")
Well, have you already tried something like this and this is not what you expect?
value?.let { nonNullValue ->
print(nonNullValue);
doFunStuff(nonNullValue);
etc(nonNullValue);
}
basically the code inside let block will run only if the value isn't null.

Is there a more elegant way to check if a String is a valid Int in Kotlin?

This is Kotlin/JVM
I currently have this code :
fun String.isValidInt(): Boolean {
var isInt: Boolean = false
try {
if (this.toInt().toString() == this) {
isInt = true
}
} catch (e: NumberFormatException) {
isInt = false
}
return isInt
}
and I was wondering if there was a more elegant way to approach this, specficially the way I set the return value isInt to true or false.
Here is a playground link to my code and a main function to test with.
For a start, try can return an expression. Together with using the expression form of the function body, removing the redundant if and this, and avoiding the local variable, it becomes:
fun String.isValidInt()
= try {
toInt().toString() == this
} catch (x: NumberFormatException) {
false
}
However, that still unnecessarily creates a String object.
There's a toIntOrNull() function which would make it simpler and more efficient:
fun String.isValidInt() = toIntOrNull() != null
Note that in all these cases it's actually performing the conversion (and discarding the result). In most cases, I'd expect you want to use the result, so you may be better off having your code call toIntOrNull() directly.

How can I `return` from inside of a call to `use`?

In Kotlin, this code compiles:
private fun bar(): Boolean = TODO()
fun works(): Int {
while (true) {
if (bar()) {
return 5
}
}
}
(This is a pared down example of my real code to illustrate the issue I'm running into.)
I actually need to use a file during this loop, and close on exit:
fun openFile(): InputStream = TODO()
fun doesnt_work(): Int {
openFile().use { input ->
while (true) {
if (bar()) {
return 5
}
}
}
} // line 42
This doesn't compile. I get the error:
Error:(42, 5) Kotlin: A 'return' expression required in a function with a block body ('{...}')
I've found two ways to work around this, but both are kind of awkward.
One way is to use a variable to hold the result, and break from the loop right when it's set:
fun works_but_awkward(): Int {
openFile().use { input ->
val result: Int
while (true) {
if (bar()) {
result = 5
break
}
}
return result
}
}
This is especially awkward in my real code, as I have a nested loop, and so I need to use a labelled break.
The other way to work around this is to have a named function for the loop:
fun workaround_with_named_function(): Int {
fun loop(input: InputStream): Int {
while (true) {
if (bar()) {
return 5
}
}
}
return openFile().use { loop(it) }
}
This seems a bit better, but I'm still surprised that the use abstraction is so leaky that I can't do an early return from within a loop. Is there a way to use use with an early return in a loop that's less awkward?
Cause Kotlin compiler isn't smart enough to undestand that use with code inside will return something from the function. The reason of such behavior is inability to guarantee compiler that lambda will be called exactly once.
Another way to workaround this is throwing exception in the end of the function:
fun doesnt_work(): Int {
openFile().use { input ->
while (true) {
if (bar()) {
return 5
}
}
}
throw IllegalStateException("Something goes wrong")
}
P.S. I am not sure, but seems it can be compiled without any hacks when contract system will be added to Kotlin. And it is probably going to be in version 1.3
This should work.
fun openFile(): InputStream = TODO()
fun doesnt_work(): Int {
return openFile().use { input ->
while (true) {
if (bar()) {
return#use 5
}
}
-1 // unreachable return value
// just to help Kotlin infer the return type
}
}
Remember, use is a function whose return value is exactly the same with the return value of the lambda. So returning the value (here it's 5) in the lambda and return the return value of use should work.
Also, if I were you, I'll write the function like this:
fun doesnt_work() = openFile().use { input ->
while (true) if (bar()) return#use 5
-1
}

Idiomatic way to return if not null in Kotlin

I am looking for an idiomatic way to return if not null a variable in Kotlin. For example, I would like something such as:
for (item in list) {
getNullableValue(item).? let {
return it
}
}
But it's not possible to return inside a let block in Kotlin.
Is there a good way to do this without having to do this:
for (item in list) {
val nullableValue = getNullableValue(item)
if (nullableValue != null) {
return nullableValue
}
}
Not sure if this would be called idiomatic, but you could do this:
val nullableValue = list.find { it != null }
if (nullableValue != null) {
return nullableValue
}
Edit:
Based on s1m0nw1's answer, you can probably reduce it to this:
list.find { it != null }?.let {
return it
}
It is possible to return from let, as you can read in the documentation:
The return-expression returns from the nearest enclosing function, i.e. foo. (Note that such non-local returns are supported only for lambda expressions passed to inline functions.)
let() is an inline function and therefore you automatically return from the enclosing function whenever you do return within let, like in this example:
fun foo() {
ints.forEach {
if (it == 0) return // nonlocal return from inside lambda directly to the caller of foo()
print(it)
}
}
To modify the behavior, "labels" can be used:
fun foo() {
ints.forEach lit# {
if (it == 0) return#lit
print(it)
}
}
The "right" idiomatic way of doing this is using the "first" method.
Example:
val x = listOf<Int?>(null, null, 3, null, 8).first { it != null }
His specific example would be
return list.first {getNullableValue(it) != null}
It could be something like:
for (item in list) {
getNullableValue(item)?.also {
return it
}
}
I am assuming the external loop is needed. If that is not the case, Ryba suggested solution should work.

Best way to null check in Kotlin?

Should I use double =, or triple =?
if(a === null) {
//do something
}
or
if(a == null) {
//do something
}
Similarly for 'not equals':
if(a !== null) {
//do something
}
or
if(a != null) {
//do something
}
A structural equality a == b is translated to
a?.equals(b) ?: (b === null)
Therefore when comparing to null, the structural equality a == null is translated to a referential equality a === null.
According to the docs, there is no point in optimizing your code, so you can use a == null and a != null
Note that if the variable is a mutable property, you won't be able to smart cast it to its non-nullable type inside the if statement (because the value might have been modified by another thread) and you'd have to use the safe call operator with let instead.
Safe call operator ?.
a?.let {
// not null do something
println(it)
println("not null")
}
You can use it in combination with the Elvis operator.
Elvis operator ?: (I'm guessing because the interrogation mark looks like Elvis' hair)
a ?: println("null")
And if you want to run a block of code
a ?: run {
println("null")
println("The King has left the building")
}
Combining the two
a?.let {
println("not null")
println("Wop-bop-a-loom-a-boom-bam-boom")
} ?: run {
println("null")
println("When things go null, don't go with them")
}
Kotlin ways of handling null
Secure Access Operation
val dialog : Dialog? = Dialog()
dialog?.dismiss() // if the dialog will be null,the dismiss call will be omitted
Let function
user?.let {
//Work with non-null user
handleNonNullUser(user)
}
Early exit
fun handleUser(user : User?) {
user ?: return //exit the function if user is null
//Now the compiler knows user is non-null
}
Immutable shadows
var user : User? = null
fun handleUser() {
val user = user ?: return //Return if null, otherwise create immutable shadow
//Work with a local, non-null variable named user
}
Default value
fun getUserName(): String {
//If our nullable reference is not null, use it, otherwise use non-null value
return userName ?: "Anonymous"
}
Use val instead of var
val is read-only, var is mutable. It’s recommended to use as many read-only properties as you can, they are thread-safe.
Use lateinit
Sometimes you can’t use immutable properties. For example, it happens on Android when some property is initialized in onCreate() call. For these situations, Kotlin has a language feature called lateinit.
private lateinit var mAdapter: RecyclerAdapter<Transaction>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mAdapter = RecyclerAdapter(R.layout.item_transaction)
}
fun updateTransactions() {
mAdapter.notifyDataSetChanged()
}
Both approaches generate the same bytecode so you can choose whatever you prefer.
Addition to #Benito Bertoli,
the combination is actually unlike if-else
"test" ?. let {
println ( "1. it=$it" )
} ?: let {
println ( "2. it is null!" )
}
The result is:
1. it=test
But if:
"test" ?. let {
println ( "1. it=$it" )
null // finally returns null
} ?: let {
println ( "2. it is null!" )
}
The result is:
1. it=test
2. it is null!
Also, if use elvis first:
null ?: let {
println ( "1. it is null!" )
} ?. let {
println ( "2. it=$it" )
}
The result is:
1. it is null!
2. it=kotlin.Unit
Check useful methods out, it could be useful:
/**
* Performs [R] when [T] is not null. Block [R] will have context of [T]
*/
inline fun <T : Any, R> ifNotNull(input: T?, callback: (T) -> R): R? {
return input?.let(callback)
}
/**
* Checking if [T] is not `null` and if its function completes or satisfies to some condition.
*/
inline fun <T: Any> T?.isNotNullAndSatisfies(check: T.() -> Boolean?): Boolean{
return ifNotNull(this) { it.run(check) } ?: false
}
Below is possible example how to use those functions:
var s: String? = null
// ...
if (s.isNotNullAndSatisfies{ isEmpty() }{
// do something
}
I want to respond to answers of #Benito Bertoli and #BingLi224 and provide imho correct solution.
Problem is with using let, because result of let is it's last expression. You just want to pass the same thing as is passed into it, so also is a better solution. At the same time, after using elvis operator, let is impossible to use, because there is no object to call extension function to so I am using run (functional version). More on that in the scope functions official documentation
Another downside of this compared to using if/when is not being able to use this as an expression so I wouldn't recommend using it :-)
Final code:
"test"?.also {
println("1. it=$it")
} ?: run {
println("2. it is null!")
}
"test"?.also {
println("1. it=$it")
null
} ?: run {
println("2. it is null!")
}
null?.also {
println("1. it is null!")
} ?: run {
println("2. it is null")
}
null?.also {
println("1. it is null!")
null
} ?: run {
println("2. it is null")
}
And output:
1. it=test
1. it=test
2. it is null
2. it is null