# Make return optional

**URL:** <https://discuss.kotlinlang.org/t/make-return-optional/19520>\
**Category:** Uncategorized\
**Created:** [October 15, 2020, 10:50pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520 "2020-10-15T22:50:20Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![alamothe](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@alamothe](https://discuss.kotlinlang.org/u/alamothe)\
**Post date:** [October 15, 2020, 10:50pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/1 "2020-10-15T22:50:20Z")

</div>

Hello,  
Are there any proposals currently lying around to make `return` keyword optional? I would like to subscribe if there are any.

`return` still remains a huge pain and a source of numerous bugs for us. It is plain weird that it is optional in lambdas but not in top-level functions.

Thanks!

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [October 16, 2020, 12:46am UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/2 "2020-10-16T00:46:25Z")

</div>

The return keyword already is optional for functions\* in Kotlin.

A source of bugs? That’s surprising since using explicit returns is one of the major things recommend for languages like Groovy (where return is optional everywhere) to prevent bugs.

The reason it’s optional for lambdas is for the use case of short lambdas–it’s practicality for quick actions out waighs the cons of the increased chance of bugs from leaving it out.

For functions, the short use case is well covered by the expression form:

```kotlin
fun getGreeting(): String = "hello world"

fun triple(n: Int) = n * 3

fun prize(place: Int) = where(place) {
    1 -> "gold"
    2 -> "silver"
    3 -> "bronze"
    else -> "none"
}

fun pickPet(allergies: Boolean): Animal = if (allergies) Fish() else Dog()

```

Longer functions with block bodies make the cost of adding an explicit return small and the benefits of having it high.

You can see this decision in play when you have long lambdas or nested lambdas–where a developer can increase the clearity by explicitly returning from a lambda and possibly adding a label.

If there’s a lot of use cases for block body functions where optional returns can provide some benefit then there might be a case. IMHO I suspect there aren’t any use cases that are not already well covered by the expression function form.

---

<div class="post-metadata">

**Author:** ![alamothe](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@alamothe](https://discuss.kotlinlang.org/u/alamothe)\
**Post date:** [October 16, 2020, 6:47pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/3 "2020-10-16T18:47:48Z")

</div>

The inconsistency is actually the source of distress and bugs.

In our experience, developers don’t know where to put `return`. Consider this (option 1):

```auto
fun foo(...) {
    // large block
    bar {
          // large block
          return baz
    }
}

```

versus (option 2):

```auto
fun foo(...) {
    // large block
    return bar {
          // large block
          baz
    }
}

```

Which is extremely common in Kotlin. We found that developers will put return randomly between these two options. So here’s a common pitfall:

- Developer A implements `bar` but forgets `crossinline`.
- Developer B implements `foo` which uses `bar` and places `return` as in the option 2.

This easily creates a bug and wastes thousands of dollars and precious human lives are lost.

The dilemma doesn’t exist if `return` is always required (JavaScript):

```auto
fun foo(...) {
    // large block
    return bar {
          // large block
          return baz
    }
}

```

Here they have to pace `return` at both points. Or, if `return` is completely optional (ideal Kotlin):

```auto
fun foo(...) {
    // large block
    bar {
          // large block
          baz
    }
}

```

So, inconsistency itself is a huge problem.

Let me point out another example of distress:

```auto
fun foo(...) {
    // large block
    return baz
}

```

So far so good. But let’s wrap it up with `bar` (again, extremely common in Kotlin):

```auto
fun foo(...) = bar {
    // large block
    baz
}

```

So now it is required to make a change to remove `return` on a completely unrelated line! This messes up blame big time. If again `bar` is removed, which is often, then the developer has to go back and see where they need to add return.

I don’t see how any “clarity” is achieved by adding this 6 character word when its place is always at the last expression. Or, isn’t in case of a lambda.

This change would be completely backward compatible since we would only make `return` optional. If you prefer to use it, fine, and this can be achieved with IDE (“inspections”).

---

<div class="post-metadata">

**Author:** ![chipays](https://avatars.discourse-cdn.com/v4/letter/c/ad7895/32.png) [@chipays](https://discuss.kotlinlang.org/u/chipays)\
**Post date:** [October 16, 2020, 7:18pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/4 "2020-10-16T19:18:29Z")

</div>

> In our experience, developers don’t know where to put `return` . Consider this
> 
> ```auto
> (code)
> 
> ```
> 
> This easily creates a bug and wastes thousands of dollars and precious human lives are lost.

Could you clarify this further? The two code snippets are functionally the same, both of them will return `baz`. What exactly is the bug here?

> The dilemma doesn’t exist if `return` is always required (JavaScript)

JavaScript behaves exactly like Kotlin in this regard. ‘standard’ functions require an explicit `return`, arrow functions (`x => x + 1`) return the last (and only) statement implicitly. You might wish to choose another language to motivate your argument.

> Let me point out another example of distress
> 
> ```auto
> (code)
> 
> ```

A valid point, although in my own experience you’ll find that most of these scenarios involve wrapping the code in an `inline` function, where the `return` statement is equally valid.

---

<div class="post-metadata">

**Author:** ![alamothe](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@alamothe](https://discuss.kotlinlang.org/u/alamothe)\
**Post date:** [October 16, 2020, 9:53pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/5 "2020-10-16T21:53:39Z")

</div>

> [@chipays](#):
>
> Could you clarify this further? The two code snippets are functionally the same, both of them will return `baz` . What exactly is the bug here?

This actually goes to show that even experienced developers like yourself are easily fooled. Consider if `bar` is implemented like:

```auto
inline fun<T> bar(block: () -> T): T {
    val result = block()
    println("Closing important resources")
    return result
}

```

Then in option 1 important resources are **not** closed. They are absolutely not the same! Here is a full example:

```auto
	inline fun <T> bar(block: () -> T): T {
		val result = block()
		println("Closing important resources")
		return result
	}

	@Test
	fun testFoo() {
		foo()
	}

	fun foo(): Int {
		bar {
			return 10
		}
	}

```

`return` here is a top-level return, not return from a lambda. How confusing!

> [@chipays](#):
>
> JavaScript behaves exactly like Kotlin in this regard. ‘standard’ functions require an explicit `return` , arrow functions ( `x => x + 1` ) return the last (and only) statement implicitly. You might wish to choose another language to motivate your argument.

Only single expression functions do not need return in JavaScript, all others need it. In Kotlin, the situation is quite different.

> [@chipays](#):
>
> A valid point, although in my own experience you’ll find that most of these scenarios involve wrapping the code in an `inline` function, where the `return` statement is equally valid.

As the example shows, it is absolutely **not** valid. It’s a recipe for disaster.

---

<div class="post-metadata">

**Author:** ![alamothe](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@alamothe](https://discuss.kotlinlang.org/u/alamothe)\
**Post date:** [October 16, 2020, 9:58pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/6 "2020-10-16T21:58:16Z")

</div>

When I teach Kotlin in my company, I spend **hours** explaining how return works in Kotlin, and everyone is baffled.

There is no other language with such an ominous semantics.

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [October 16, 2020, 10:23pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/7 "2020-10-16T22:23:36Z")

</div>

I think the problems you’re discovering with returns are better solved by explicitly marking returns everywhere or taking a second look at the [reference page on returns](https://kotlinlang.org/docs/reference/returns.html)

Making returns optional everywhere would allow for more confusing code as a developer would go from having two options to three–the solution to incorrectly choosing what/when to return is not hiding the return.

---

<div class="post-metadata">

**Author:** ![Wasabi375](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wasabi375/32/4741_2.png) [@Wasabi375](https://discuss.kotlinlang.org/u/Wasabi375)\
**Post date:** [October 16, 2020, 10:29pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/8 "2020-10-16T22:29:15Z")

</div>

I don’t see how you spend hours explaining `return` in kotlin. `return` will always return from the nearest `fun`.  
Also I’d argue that your implementation of `bar` is wrong. The `block` lambda should have been marked with the `crossinline` keyword. Maybe there is an argument to be made that `crossinline` should have been the default and instead there should have been a keyword to allow for non local returns but it’s a bit late to change that. Maybe that could be changed with an optional compiler flag.

---

<div class="post-metadata">

**Author:** ![alamothe](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@alamothe](https://discuss.kotlinlang.org/u/alamothe)\
**Post date:** [October 17, 2020, 12:17am UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/9 "2020-10-17T00:17:20Z")

</div>

> [@arocnies](#):
>
> I think the problems you’re discovering with returns are better solved by explicitly marking returns everywhere or taking a second look at the [reference page on returns](https://kotlinlang.org/docs/reference/returns.html)

Explicitly marking every return would open a whole new can of worms. What if a developer forgets to mark it with `@xyz`? What if they marked it with a wrong `@xyz`? Can this really be enforced or caught during code review? How?

Now we have gone from return having a single meaning (albeit inconsistent from a developer perspective) to “one can return from any lambda to any lambda” situation. Not to mention that lambdas are not unique (you can have `run` inside a `run` inside a `run` — which run will return return?).

Pointing to a reference page is not very helpful. I understand how it works. I am pointing to a problem that we are seeing in practice where how it works creates bugs and headaches, and even proposing a backwards compatible solution.

It’s like arguing that comparing null, undefined, false and 0 in JavaScript can be confusing, and a smart guy just points us to a reference page. Thanks but you’re not adding value to the discussion.

---

<div class="post-metadata">

**Author:** ![alamothe](https://avatars.discourse-cdn.com/v4/letter/a/c4cdca/32.png) [@alamothe](https://discuss.kotlinlang.org/u/alamothe)\
**Post date:** [October 17, 2020, 12:21am UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/10 "2020-10-17T00:21:47Z")

</div>

> [@Wasabi375](#):
>
> Also I’d argue that your implementation of `bar` is wrong. The `block` lambda should have been marked with the `crossinline` keyword. Maybe there is an argument to be made that `crossinline` should have been the default and instead there should have been a keyword to allow for non local returns but it’s a bit late to change that. Maybe that could be changed with an optional compiler flag.

I explicitly said in my original post that developer A forgot to add `crossinline`, so you’re pointing to the obvious here. How many Kotlin developers would think that option 1 and 2 are the same? And isn’t that a problem?

---

<div class="post-metadata">

**Author:** ![chipays](https://avatars.discourse-cdn.com/v4/letter/c/ad7895/32.png) [@chipays](https://discuss.kotlinlang.org/u/chipays)\
**Post date:** [October 17, 2020, 6:29am UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/11 "2020-10-17T06:29:23Z")

</div>

I agree with Wasabi here, the problem doesn’t seem to originate from `return` but the default behaviour of `inline` functions. Making returns optional does not fix situations where people would want a early return from a lambda:

```kotlin
fun foo(...) : Code {
    //opens stream and closes it at the end of the function, not made crossinline by accident
    return bar { it: InpustStream 
        //code
        if(condition) return Code.Error //BUG! stream won't close 
        //code
        Code.Okay //okay, bar finished normally
    }
}

```

---

<div class="post-metadata">

**Author:** ![Wasabi375](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/wasabi375/32/4741_2.png) [@Wasabi375](https://discuss.kotlinlang.org/u/Wasabi375)\
**Post date:** [October 17, 2020, 8:28am UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/12 "2020-10-17T08:28:42Z")

</div>

> [@alamothe](#):
>
> I explicitly said in my original post that developer A forgot to add `crossinline`

I know. What I wanted to say is that `return` isn’t the real problem here. `crossinline` is. Your suggestion to change `return` looks to me like a bandaid over a different problem, without affecting the underlying cause. Sry, if I didn’t express that properly.  
Kotlin’s non local return is a powerful feature that allows inline functions to behave as if they are language constructs. Removing return statements or non local returns from the language would break more than it would fix.

---

<div class="post-metadata">

**Author:** ![nickallendev](https://avatars.discourse-cdn.com/v4/letter/n/cdc98d/32.png) [@nickallendev](https://discuss.kotlinlang.org/u/nickallendev)\
**Post date:** [October 17, 2020, 4:19pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/13 "2020-10-17T16:19:12Z")

</div>

Resource clean up should be in a finally block (ideally you can just leverage `use`) . Even with crossinline there, the definition appears flawed since an exception would result in a resource leak.

Unexpected non local return seems like it’d only cause an issue if you are writing code that is already incorrect and broken for cases involving exceptions.

---

<div class="post-metadata">

**Author:** ![ccfnz](https://avatars.discourse-cdn.com/v4/letter/c/dec6dc/32.png) [@ccfnz](https://discuss.kotlinlang.org/u/ccfnz)\
**Post date:** [October 19, 2020, 8:36pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/15 "2020-10-19T20:36:13Z")

</div>

Wow, yes, that is real confusing to a non Kotlin guru (obviously like myself…)

Without seeing your implementation (and testing it for myself) I would not have followed that logic flow… I can definitely see how this could get confusing (referring to the example with println(“Closing important resources”).

Thanks for bringing this up… better hit the reference manual…

Is there any scope for an optional compiler warning at least? E.g. This is non local return, are you sure you want it… or consider marking this param as crossinline…?

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [October 19, 2020, 9:30pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/16 "2020-10-19T21:30:35Z")

</div>

It’s already an error to return from a crossinline lambda. Here’s the screenshot from IntelliJ, notice how it suggests fixing it by explicitly returning to the lambda with `return@bar2`

 ![Screen Shot 2020-10-19 at 5.20.30 PM](https://us1.discourse-cdn.com/flex019/uploads/kotlinlang/original/2X/1/1e5674011f92e4a153660149727c668bbc900ba4.png)  
Since returns are pretty important, it’s a compiler error in this case.

@ccfnz as you learn Kotlin, watch how many times a return confusion comes up in practice. I bet most of the confusion points will be solved with explicitly marked returns.

If we’re talking about the specific `println(“Closing important resources”)` example you’ll see I placed that code in a finally block as chipays mentions. Without it, a caller can easily orphan the resource regardless of return behavior is the following:

```kotlin
// ...
bar { 
    error("Some error...")
    // ...
    return // notice it doesn't matter if bar accidentally early returns or not.
} 

```

As @Wasabi375 explains, returns aren’t too complicated. We `return` to the nearest function unless otherwise specified (see the [reference page for runnable examples](https://kotlinlang.org/docs/reference/returns.html#return-at-labels)). Unlabeled returns always behave this way and the only way to get a different behavior is by using a labelled return.

> [@alamothe](#):
>
> `return` here is a top-level return, not return from a lambda. How confusing!

The reason it’s not confusing is that the behavior is consistent. Every unlabeled `return` is the same and you never have to confuse it with a local return.

---

<div class="post-metadata">

**Author:** ![ccfnz](https://avatars.discourse-cdn.com/v4/letter/c/dec6dc/32.png) [@ccfnz](https://discuss.kotlinlang.org/u/ccfnz)\
**Post date:** [October 19, 2020, 10:10pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/17 "2020-10-19T22:10:31Z")

</div>

I guess that is the key, needing to know (or needing to remember) that you need (or at least should consider) `crossinline` on the block parameter…

Also take your point in the example that closing/clearing resources is best in try finally block.

---

<div class="post-metadata">

**Author:** ![arocnies](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/arocnies/32/5143_2.png) [@arocnies](https://discuss.kotlinlang.org/u/arocnies)\
**Post date:** [October 19, 2020, 10:13pm UTC](https://discuss.kotlinlang.org/t/make-return-optional/19520/18 "2020-10-19T22:13:54Z")

</div>

Yup.

I can see the desire to lock the returns into one behavior and use some special marker for local returns–I imagine without that it would be confusing. I’m glad it works that way already especially with a compiler error to force stop you from writing confusing returns.

> [@alamothe](#):
>
> When I teach Kotlin in my company, I spend **hours** explaining how return works in Kotlin, and everyone is baffled.
> 
> There is no other language with such an ominous semantics.

For beginners learning Kotlin, you could just never mention local returns so that they don’t have to worry about it. They’ll use returns the way they expect from whatever language they came from.

Eventually they may see a label on a return and you could explain it’s a nice way to be explicit inside a lambda that they’re used to implicitly returning the last line.
