Related
I can't figure out what ?: does in for example this case
val list = mutableList ?: mutableListOf()
and why can it be modified to this
val list = if (mutableList != null) mutableList else mutableListOf()
TL;DR: If the resulting object reference [first operand] is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. Additionally, the operator can throw an exception if null is returned.
The Elvis operator is part of many programming languages, e.g. Kotlin but also Groovy or C#.
I find the Wikipedia definition pretty accurate:
In certain computer programming languages, the Elvis operator ?: is a binary operator that returns its first operand if that operand is true, and otherwise evaluates and returns its second operand. It is a variant of the ternary conditional operator, ? :, found in those languages (and many others): the Elvis operator is the ternary operator with its second operand omitted.
The following is especially true for Kotlin:
Some computer programming languages have different semantics for this operator. Instead of the first operand having to result in a boolean, it must result in an object reference. If the resulting object reference is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. If the second operand is null, the operator is also able to throw an exception.
An example:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
The Elvis Operator is represented by a question mark followed by a colon: ?: and it can be used with this syntax:
first operand ?: second operand
It enables you to write a consise code, and works as such:
If first operand isn't null, then it will be returned. If it is null, then the second operand will be returned. This can be used to guarantee that an expression won't return a null value, as you'll provide a non-nullable value if the provided value is null.
For example(in Kotlin):
fun retrieveString(): String { //Notice that this type isn't nullable
val nullableVariable: String? = getPotentialNull() //This variable may be null
return nullableVariable ?: "Secondary Not-Null String"
}
In this case, if the computed value of getPotentialNull is not null, it will be returned by retrieveString; If it is null, the second expression "Secondary Not-Null String" will be returned instead.
Also note that the right-hand side expression is evaluated only if the left-hand side is null.
In Kotlin, you could use any expression as second operand, such as a throw Exception expression
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
The name Elvis Operator comes from the famous American singer Elvis Presley. His hairstyle resembles a Question Mark
Source: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Packt Publishing
This is called the Elvis operator and it does... Exactly what you've described in your question. If its left hand side is a null value, it returns the right side instead, sort of as a fallback. Otherwise it just returns the value on the left hand side.
a ?: b is just shorthand for if (a != null) a else b.
Some more examples with types:
val x: String? = "foo"
val y: String = x ?: "bar" // "foo", because x was non-null
val a: String? = null
val b: String = a ?: "bar" // "bar", because a was null
Let's take a look at the defintion:
When we have a nullable reference r, we can say "if r is not null, use
it, otherwise use some non-null value x":
The ?: (Elvis) operator avoids verbosity and makes your code really concise.
For example, a lot of collection extension functions return null as fallback.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?: gives you a way to handle the fallback case elgantely even if you have multiple layers of fallback. If so, you can simply chain multiply Elvis operators, like here:
val l = listOf(1, 2, 3)
val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
If you would express the same with if else it would be a lot more code which is harder to read.
The elvis operator in Kotlin is used for null safety.
x = a ?: b
In the above code, x will be assigned the value of a if a is not null and b if a is null.
The equivalent kotlin code without using the elvis operator is below:
x = if(a == null) b else a
Simply we can say that, you have two hands. You want to know, is your left hand working right now?. If left hand not working, return empty else busy
Example for Java:
private int a;
if(a != null){
println("a is not null, Value is: "+a)
}
else{
println("a is null")
}
Example for Kotlin:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
Consider below example,
var myStr:String? = null
//trying to find out length of myStr, but it could be null, so a null check can be put as,
val len = if (myStr != null){
myStr.length
}
else{
-1
}
Using the elvis operator, the above code can be written in a single line
val len = myStr?.length ?: -1 // will return -1 if myStr is null else will return length
In addition to what has been already stated there is one good pattern that was not obvious for me, but which is common, e.g. you're writing a long function, but if something is null there is no sense to continue and the only thing you can do is to return from the function. Normally you'd write
something = expression
if (something == null) {
return
}
With elvis it becomes shorter and more elegant:
something = expression ?: return
Basically, if the left side of Elvis returns null for some reason, returns the right side instead.
i.e.
val number: Int? = null
println(number ?: "Number is null")
So, if number is NOT null, it will print number, otherwise will print "Number is null".
A little addition though is this
X = A ?: B
X will still be null if both A and B evaluate to null
Therefore, if you want X to always be non-null, make sure B is always a non-null or that B always evaluates to non-null if it's a function or expression.
I have an instance which can be null. Fox example
var str: String? = null
So I need to check if str is String. Do I need to check for null if I use the is operator.
First option:
if(str is String) {}
Second option:
if(str != null && str is String) {}
Please help me which way is better to use ?
The is operator is safe and returns false in the case you supply a null instance
https://pl.kotl.in/HIECwc4Av
Somewhere, you HAVE to nullcheck.
Kotlin provides many ways to enforce non-null:
Use a non-null type:
var nonNull : String = ""
var nullable : String? = "" // notice the ?
nullable = null // works fine!
nonNull = null // compiler error
and if you encounter a nullable type, you can use let {} ?: run {} construct to unwrap it and execute your code with a non-nullable:
nullable?.let { // use "it" to access the now non-null value
print(it)
} ?: run { // else
print("I am null! Big Sad!")
}
Kotlin strictly distinguishes between nullable T? and nonnull T.
Use T wherever possible to avoid null checks.
I can't figure out what ?: does in for example this case
val list = mutableList ?: mutableListOf()
and why can it be modified to this
val list = if (mutableList != null) mutableList else mutableListOf()
TL;DR: If the resulting object reference [first operand] is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. Additionally, the operator can throw an exception if null is returned.
The Elvis operator is part of many programming languages, e.g. Kotlin but also Groovy or C#.
I find the Wikipedia definition pretty accurate:
In certain computer programming languages, the Elvis operator ?: is a binary operator that returns its first operand if that operand is true, and otherwise evaluates and returns its second operand. It is a variant of the ternary conditional operator, ? :, found in those languages (and many others): the Elvis operator is the ternary operator with its second operand omitted.
The following is especially true for Kotlin:
Some computer programming languages have different semantics for this operator. Instead of the first operand having to result in a boolean, it must result in an object reference. If the resulting object reference is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. If the second operand is null, the operator is also able to throw an exception.
An example:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
The Elvis Operator is represented by a question mark followed by a colon: ?: and it can be used with this syntax:
first operand ?: second operand
It enables you to write a consise code, and works as such:
If first operand isn't null, then it will be returned. If it is null, then the second operand will be returned. This can be used to guarantee that an expression won't return a null value, as you'll provide a non-nullable value if the provided value is null.
For example(in Kotlin):
fun retrieveString(): String { //Notice that this type isn't nullable
val nullableVariable: String? = getPotentialNull() //This variable may be null
return nullableVariable ?: "Secondary Not-Null String"
}
In this case, if the computed value of getPotentialNull is not null, it will be returned by retrieveString; If it is null, the second expression "Secondary Not-Null String" will be returned instead.
Also note that the right-hand side expression is evaluated only if the left-hand side is null.
In Kotlin, you could use any expression as second operand, such as a throw Exception expression
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
The name Elvis Operator comes from the famous American singer Elvis Presley. His hairstyle resembles a Question Mark
Source: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Packt Publishing
This is called the Elvis operator and it does... Exactly what you've described in your question. If its left hand side is a null value, it returns the right side instead, sort of as a fallback. Otherwise it just returns the value on the left hand side.
a ?: b is just shorthand for if (a != null) a else b.
Some more examples with types:
val x: String? = "foo"
val y: String = x ?: "bar" // "foo", because x was non-null
val a: String? = null
val b: String = a ?: "bar" // "bar", because a was null
Let's take a look at the defintion:
When we have a nullable reference r, we can say "if r is not null, use
it, otherwise use some non-null value x":
The ?: (Elvis) operator avoids verbosity and makes your code really concise.
For example, a lot of collection extension functions return null as fallback.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?: gives you a way to handle the fallback case elgantely even if you have multiple layers of fallback. If so, you can simply chain multiply Elvis operators, like here:
val l = listOf(1, 2, 3)
val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
If you would express the same with if else it would be a lot more code which is harder to read.
The elvis operator in Kotlin is used for null safety.
x = a ?: b
In the above code, x will be assigned the value of a if a is not null and b if a is null.
The equivalent kotlin code without using the elvis operator is below:
x = if(a == null) b else a
Simply we can say that, you have two hands. You want to know, is your left hand working right now?. If left hand not working, return empty else busy
Example for Java:
private int a;
if(a != null){
println("a is not null, Value is: "+a)
}
else{
println("a is null")
}
Example for Kotlin:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
Consider below example,
var myStr:String? = null
//trying to find out length of myStr, but it could be null, so a null check can be put as,
val len = if (myStr != null){
myStr.length
}
else{
-1
}
Using the elvis operator, the above code can be written in a single line
val len = myStr?.length ?: -1 // will return -1 if myStr is null else will return length
In addition to what has been already stated there is one good pattern that was not obvious for me, but which is common, e.g. you're writing a long function, but if something is null there is no sense to continue and the only thing you can do is to return from the function. Normally you'd write
something = expression
if (something == null) {
return
}
With elvis it becomes shorter and more elegant:
something = expression ?: return
Basically, if the left side of Elvis returns null for some reason, returns the right side instead.
i.e.
val number: Int? = null
println(number ?: "Number is null")
So, if number is NOT null, it will print number, otherwise will print "Number is null".
A little addition though is this
X = A ?: B
X will still be null if both A and B evaluate to null
Therefore, if you want X to always be non-null, make sure B is always a non-null or that B always evaluates to non-null if it's a function or expression.
For simple check like
if (variable != null) {
doSomething(variable)
}
We could change to
variable?.let { doSometing(it) }
However for a case with else
if (variable != null) {
doSomething(variable)
} else {
doOtherThing()
}
Is there a way of doing so in a single function? Is there something like either?
You can use the elvis-operator ?: like so:
variable?.let { doSomething(it) } ?: doOtherThing()
However personally I think that this gets quite unreadable very quickly. There is nothing wrong with an if-expression.
Another approach which might ring well with functional style is the use of when, which is very close to pattern matching:
when(variable) {
null -> doOtherThingSomething()
else -> doSomething(variable)
}
I would argue, however, that you should be careful with abandoning the classic if statement, if what you're after is its natural purpose - conditional execution. If you're calculating a value in two different ways and then using it in the same way, this approach makes sense. But if your code paths diverge at this point and don't meet again, then if provides a clearer intent.
You can map null-able value if not null by using ternary operator to check not null condition with If...Else Statements.
Here, I had wrote some code snippet to check value null or not ,
Case 1: value initialized
fun main(args: Array<String>) {
val value:Int ?= 10
val mapped = value?.let { "Value is == $value" } ?: "Value not initialized..."
println(mapped)
}
You gotta result: Value is == 10
Case 2: value set remains null
fun main(args: Array<String>) {
val value:Int ?= null
val mapped = value?.let { "Value is == $value" } ?: "Value not initialized..."
println(mapped)
}
You gotta result: Value not initialized...
Let f() return a nullable value.
What I want to do is that
if f() is null, get an empty list,
else if f() is not null, get a list of the single item value.
In Scala, we can do something like this:
Option(f()).toList
or more verbosely
Option(f()).map(v => List(v)).getOrElse(List.empty)
In Kotlin, there is no Option (assuming no Funktionale library), and null does not have toList() unlike (None: Option) in Scala.
We have the Elvis operator, but null will be inside the listOf() function, so it will be
listOf(f() ?: /* What can I do here? */)
What we want for null is listOf(/*no argument */), but the Elvis operator requires an argument, so listOf(f() ?: ) will result in a compile error.
At least we can do
val v = f()
if (v == null) listOf() else listOf(v)
but it is a two liner.
Is there some expression for this?
Where I will use this expression is in the class's primary constructor default argument, so if it is not a one liner, it will be enclosed in brackets, so something like this:
class A(
val p1: List<V> = run {
val v = f()
if (v == null) listOf() else listOf(v)
},
val p2: ... = ...,
...)
This looks pretty ugly, isn't it?
EDIT
As #Naetmul pointed out, listOfNotNull(f()) is syntactically better to what I originally posted below, and also takes a variable number of arguments, for example
val myList = listOfNotNull(f(), g(), h())
will return a list of all the results that were not null.
I would use let here.
val myList = f()?.let { listOf(it) } ?: emptyList()
Use a ?. safe call on the return value of f(), then use let to run a code block. If f() is null, it won't run this block of code, resulting in a null value. Then we use the ?: elvis operator to fall back to an empty list.
Here it is broken up into several lines for a better understanding
val myValue = f()
val myList: List<Any>
if (myValue != null) {
myList = listOf(myValue)
} else {
myList = emptyList()
}
For this specific question, I can do
listOfNotNull(f())