Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can "return" return a "return" in Kotlin?

The question may sound silly, but there is no typo in it.

fun test(): Any {
    return return true
}

This is actually possible in Kotlin. Although the compiler warns about

Unreachable code

for the outer return. But this is just a warning.

I don't want to compare Java with Kotlin, but I was interested whether the same would work in Java.

public class Test {
  // ...
  static int test() {
    return return 1;
  }
}

It does not!

/Test.java:8: error: illegal start of expression
      return return 1;
                 ^
/Test.java:8: error: not a statement
      return return 1;
                           ^
2 errors

Why was Kotlin designed this way?

like image 947
Willi Mentzel Avatar asked Jan 17 '18 21:01

Willi Mentzel


People also ask

Can I return 2 values from a function in Kotlin?

Kotlin has generic Pair and Triple types that can return two or three values from the function.

Can you return in Kotlin?

Returns and jumps Kotlin has three structural jump expressions: return by default returns from the nearest enclosing function or anonymous function. break terminates the nearest enclosing loop. continue proceeds to the next step of the nearest enclosing loop.

What does return mean Kotlin?

return@ is a statement in Kotlin which helps the developers to return a function to the called function. In simple words, return@ can return any value, anonymous function, simple inline function, or a lambda function.


Video Answer


2 Answers

return is an expression in Kotlin, with a return type of Nothing, the type that acts as a subtype of all other types. This enables you to, for example, do this in a type safe way and without extra lines of null checks:

fun getInt(): Int? = ...

fun printInt() {
    val int: Int = getInt() ?: return
    println(int)
}

The type of getInt() ?: return can be Int here, because that's the closest common supertype of the two sides of the Elvis operator, thanks to Nothing being a subtype of Int.

The same thing applies for throw, which you can also use neatly with the Elvis operator to indicate that you want to cancel execution on a null value without having to worry about types later.

This results in an odd quirk where things like

fun x(): Int {
    return return throw return throw throw return 0
}

are valid syntax, because the Nothing type makes each of the expressions valid read from right to left. What will actually happen is that return 0 will execute and the rest of the code will never be reached, as the compiler warns.

like image 158
zsmb13 Avatar answered Oct 17 '22 18:10

zsmb13


Because the return statement is an expression that returns Nothing. As a result, the following also compiles:

fun main(args: Array<String>) {
    val r = return
}

It's stated in the docs:

Kotlin has three structural jump expressions:

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

All of these expressions can be used as part of larger expressions:

val s = person.name ?: return

The type of these expressions is the Nothing type.

Since Nothing is a subtype of any other type, it has the power of making weird statements, like the one in your question, valid although they appear to be very wrong...

There was actually a funny talk at KotlinConf taking a look at interesting things like the following:

fun getText(): String {
  val s = return throw return "Hello"
}

println(getText())
//prints "Hello"
like image 10
s1m0nw1 Avatar answered Oct 17 '22 18:10

s1m0nw1