HelloCW
HelloCW

Reputation: 2255

Can I add return when I use Elvis operation in Kotlin?

I have read Elvis Operator at http://mings.in/2017/03/12/Kotlin-Null-Safety.html

The Code A and Code C are OK, but Code B is error ("Type mismatch: inferred type is Int but Unit was expected" ), why?

Code A

override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)  

      val b: String?  = "hello"
      val l = b?.length ?: -1
 }

Code B

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)

      val b: String?  = "hello"
      val l = b?.length ?: return -1

    }

Code C

 fun getLength(b: String?): Int {
        val l = b?.length ?: return -1       
        return l
    }

BTW, BakaWaii told me "Code A is ok because -1 is an expression which denotes a value, so that it can be assigned to l. But in code B, return -1 is an expression which returns from a function."

I can't understand that "in code B, return -1 is an expression which returns from a function". I think that "return -1 " will return -1, why does the app occur "Type mismatch: inferred type is Int but Unit was expected" ?

And more:

Code C just like Code B, I don't know why it's OK !!!!

Upvotes: 3

Views: 6589

Answers (2)

Ircover
Ircover

Reputation: 2446

Difference between Code A and Code B that first one set -1 to your variable (now it is l), and second one set -1 as result of function work. And Type mismatch error message says that function should not return any value (or return Unit) but you are trying to return int - so it is not Elvis operator syntax error.

Then if you place your Code B in some Int function (like you did it in Code C) there would not be any errors.

Example

If you want to "convert" Int to StringBuilder you can do it like following:

fun toStringBuilder(i: Int?): StringBuilder {
    val result = i?.toString() ?: ""
    return StringBuilder(result)
}

Guess there is no questions.

Second example is absolutelly correct too.

fun toStringBuilder(i: Int?): StringBuilder {
    val result = i?.toString() ?: return StringBuilder()
    return StringBuilder(result)
}

If parameter value is null function will not reach second line because it would return at first.

And third example whould generate error (like your Code B).

fun toStringBuilder(i: Int?): StringBuilder {
    val result = i?.toString() ?: return ""
    return StringBuilder(result)
}

Again there is no error in syntax. Elvis operator is correct. Error is because you are trying to return String to function that declared as returning StringBuilder.

Upvotes: 5

BakaWaii
BakaWaii

Reputation: 6992

From Kotlin's doc:

If the expression to the left of ?: is not null, the elvis operator returns it, otherwise it returns the expression to the right. Note that, since throw and return are expressions in Kotlin, they can also be used on the right hand side of the elvis operator.

and also,

return. By default returns from the nearest enclosing function or anonymous function.

So, the answer is yes, as long as the return type of the enclosing function matches with the return value, for example:

fun getLength(b: String?): Int {
    val l = b?.length ?: return -1    //return an `Int`
    //if return -1, the code below will not execute
    return l
}

Note that code A and code B are different in control flow. If you are trying to assign an alternative/default value when the left-hand side value is null, code A will be the best approach.

Upvotes: 8

Related Questions