# If needs else branch in expression of type Unit

**URL:** <https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970>\
**Category:** Language Design\
**Created:** [May 31, 2018, 1:21pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970 "2018-05-31T13:21:25Z")\
**Posts on this page:** 19\
**Page:** 1

<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:** [May 31, 2018, 1:21pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/1 "2018-05-31T13:21:25Z")

</div>

I just ran into a interesting situation. Normally when you use `if ... else` as an expression you can not emit the else branch and I understand why. But let’s look at this situation

```kotlin
enum SomeEnum {
  A,
  B 
}

fun foo(e: SomeEnum): Unit = when(e) {
    A -> {
      doSomething()
      if(someCondition) {
        doSomethingElseAsWell()
      }
    }
    B -> ...
}

```

Compiling this fails with this error

> ‘if’ must have both main and ‘else’ branches if used as an expression

I can fix it by adding an empty `else` branch, but this looks stupid. I could also not use an expression body for the function but in that case I loose the check that I am exhaustive with my `when` expression.

I wonder if this is something that should be changed, so that if an `if`-expression returns `Unit` it can omit the `else` branch. Any thoughts?

---

<div class="post-metadata">

**Author:** ![pdvrieze](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/pdvrieze/32/1882_2.png) [@pdvrieze](https://discuss.kotlinlang.org/u/pdvrieze)\
**Post date:** [May 31, 2018, 2:20pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/2 "2018-05-31T14:20:12Z")

</div>

Live with block syntax in this case as your use isn’t as expression.

---

<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:** [May 31, 2018, 2:22pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/3 "2018-05-31T14:22:15Z")

</div>

Agreed, but I would still like to have the compiler check that the when expression is exhaustive and I can not do that without using it as an expression.

---

<div class="post-metadata">

**Author:** ![pdvrieze](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/pdvrieze/32/1882_2.png) [@pdvrieze](https://discuss.kotlinlang.org/u/pdvrieze)\
**Post date:** [May 31, 2018, 6:15pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/4 "2018-05-31T18:15:24Z")

</div>

I agree on that one, perhaps a worthy enhancement proposal.

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [May 31, 2018, 7:06pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/5 "2018-05-31T19:06:57Z")

</div>

> [@If operator in function expression](https://discuss.kotlinlang.org/t/if-operator-in-function-expression/7227):
>
> Hello guys, I have bumped into interesting language feature that I cannot make sense of. In Kotlin we can use expression as function body, e.g. fun foo(x: Int, y: Int) = x + y I tried today write following function: fun log() = if (isError()) logError() surprisingly this function couldn’t be compiled. The reason is following: Error:(128, 39) ‘if’ must have both main and ‘else’ branches if used as an expression Can anyone explain me why if listed above is not legit?

---

<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:** [May 31, 2018, 7:10pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/6 "2018-05-31T19:10:03Z")

</div>

Thx I understand how expressions work. As you might have noticed I was one of the people replying to that topic and I think I have explained my reasons why I would like to see an exception in this case, especially when the function is declared to return `Unit`.

---

<div class="post-metadata">

**Author:** ![tieskedh](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tieskedh/32/2816_2.png) [@tieskedh](https://discuss.kotlinlang.org/u/tieskedh)\
**Post date:** [June 1, 2018, 5:38am UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/7 "2018-06-01T05:38:45Z")

</div>

That’s why I fiund it strange to bring up again…  
If we don’t want to change it in the topic, but we do want to change it overhere, what makes the difference?

---

<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:** [June 2, 2018, 11:35am UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/8 "2018-06-02T11:35:49Z")

</div>

The difference as I explained is that I’d like to have exhaustive `when` but don’t want to use it as an expression because I just return `Unit` in all cases

---

<div class="post-metadata">

**Author:** ![klitosk](https://avatars.discourse-cdn.com/v4/letter/k/13edae/32.png) [@klitosk](https://discuss.kotlinlang.org/u/klitosk)\
**Post date:** [June 5, 2018, 2:07pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/9 "2018-06-05T14:07:55Z")

</div>

Why do you want the inconsistency of enforcing an exhaustive when while allowing a non-exhaustive if?

---

<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:** [June 5, 2018, 2:33pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/10 "2018-06-05T14:33:27Z")

</div>

I want the ability to have an exhaustive when without using it as an expression, if that is not possible yes I want a non-exhaustive if in case of a `Unit` result. I personally think that Kotlin is a bit strict about expressions in case of a `Unit` result, because all branches lead to the same result anyways.

---

<div class="post-metadata">

**Author:** ![roschlau](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@roschlau](https://discuss.kotlinlang.org/u/roschlau)\
**Post date:** [June 5, 2018, 2:45pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/11 "2018-06-05T14:45:45Z")

</div>

Would this be acceptable to you?

```auto
fun foo(e: SomeEnum): Unit = when(e) {
    A -> {
      doSomething()
      if(someCondition) {
        doSomethingElseAsWell()
      }
      Unit
    }
    B -> ...
}

```

That way you’re explicitly stating, yep, this block does return Unit and not whatever the if-statement returns.

---

<div class="post-metadata">

**Author:** ![klitosk](https://avatars.discourse-cdn.com/v4/letter/k/13edae/32.png) [@klitosk](https://discuss.kotlinlang.org/u/klitosk)\
**Post date:** [June 5, 2018, 2:50pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/12 "2018-06-05T14:50:36Z")

</div>

Rochlau’s post makes sense. Kotlin treats if and when consistently: they’re both exhaustive as an expression and non-exhaustive as a statement. If you want ‘if’ to be non-exhaustive, then use it as a statement.

---

<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:** [June 5, 2018, 3:03pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/13 "2018-06-05T15:03:24Z")

</div>

Not really. I state explicitly that I return Unit at the function header, so I don’t really see why I need to state it again. I know the possible workarounds, that’s what I’m not looking for.  
Maybe I put more value onto exhaustive whens. IMO when should always be exhaustive and this is where my problem is. I want an exhaustive when but I don’t want to deal with stupid unnecessary code just to support that.

* * *

Kotlin will not change when to be exhaustive, because this would be a breaking change, therefor I argue for a special treatment of `if` in case of a `Unit` result.

> [@klitosk](#):
>
> If you want ‘if’ to be non-exhaustive, then use it as a statement.

I can’t because I want the `when` to be exhaustive although I could argue that I am using it as a statement and the compiler should infer the `Unit` statement at the end.  
Also I am not sure but this might be possible after [https://youtrack.jetbrains.com/issue/KT-19878](https://youtrack.jetbrains.com/issue/KT-19878).

---

<div class="post-metadata">

**Author:** ![abrownvt](https://avatars.discourse-cdn.com/v4/letter/a/7ea924/32.png) [@abrownvt](https://discuss.kotlinlang.org/u/abrownvt)\
**Post date:** [June 6, 2018, 12:50am UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/14 "2018-06-06T00:50:25Z")

</div>

I would just give into the else branch. Just say (if I’m not mistaken)  
`else Unit`

Maybe `exhaustive` could be a modifier on `when` if we really can’t live with that though

Or if the required destination type is Unit, then Unit can be inferred from any non-expression statement.

---

<div class="post-metadata">

**Author:** ![roschlau](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@roschlau](https://discuss.kotlinlang.org/u/roschlau)\
**Post date:** [June 6, 2018, 7:54am UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/15 "2018-06-06T07:54:16Z")

</div>

I don’t think special treatment of `if` in such a special edge case is justified. Kotlin tries to push you toward immutability and reducing side effects, and a `when` expression with a `Unit` return type just screams “SIDE EFFECT”. Sure, a lot of the time you can’t avoid those cases, but I’m not sure the language should actively encourage them. I think having a little more verbosity in a case like this is quite acceptable, because it makes inadvertently creating side effects harder.

---

<div class="post-metadata">

**Author:** ![svd](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/svd/32/1756_2.png) [@svd](https://discuss.kotlinlang.org/u/svd)\
**Post date:** [June 6, 2018, 8:23am UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/16 "2018-06-06T08:23:44Z")

</div>

I stole the definition of

```nohighlight
val Any.exhaust = Unit

```

from some blog to make Unit when statements exhaustive. It is a nice and usefull trick.

---

<div class="post-metadata">

**Author:** ![nyxcode](https://avatars.discourse-cdn.com/v4/letter/n/3da27b/32.png) [@nyxcode](https://discuss.kotlinlang.org/u/nyxcode)\
**Post date:** [July 13, 2018, 3:03pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/17 "2018-07-13T15:03:48Z")

</div>

Interesting suggestion!  
This would allow me to write something like

```auto
fun test() = if(condition) value

```

Seems usefull in some _(rare)_ cases, but maybe a bit confusing.

> [@If needs else branch in expression of type Unit](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/15):
>
> I don’t think special treatment of if in such a special edge case is justified. Kotlin tries to push you toward immutability and reducing side effects, and a when expression with a Unit return type just screams “SIDE EFFECT”. Sure, a lot of the time you can’t avoid those cases, but I’m not sure the language should actively encourage them. I think having a little more verbosity in a case like this is quite acceptable, because it makes inadvertently creating side effects harder.

Yeah, I can agree with that.

---

<div class="post-metadata">

**Author:** ![gidds](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/gidds/32/10865_2.png) [@gidds](https://discuss.kotlinlang.org/u/gidds)\
**Post date:** [December 17, 2020, 9:06pm UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/18 "2020-12-17T21:06:18Z")

</div>

At the risk of re-opening an old wound^H^H^H^H^Hthread, it’s not always obvious when Kotlin is expecting an expression.⠀Here’s the skeleton of a case I just hit in Kotlin 1.4.21:

```
fun read(reader: Reader) {
    reader.use {
        if (someCondition) {
            someList.add(null)
        } else if (someOtherCondition) { // <-- ERROR here
            // …
        }
    }
}

```

The return type of `use()` is inferred from the contents (and NOT from that of the function, which can only be Unit).⠀And to make it especially non-obvious, `add()` returns a Boolean (though that’s easy to miss as it’s nearly always ignored).⠀So the compiler insists on every other branch returning a Boolean too…⠀(In fact, my case was even worse, as the last block had a nested `if`, and every branch of _that_ needed to return a Boolean as well…)

The best workarounds seem to be to specify the type parameters (`use<Reader, Unit> {`), to append a `Unit` line to the first branch, or to append `else Unit` to the last.

If both the error and the workarounds are a little unexpected and tricky for a seasoned Kotlin dev, how baffling and off-putting must they be for the less-experienced?⠀Is there nothing that can be done to avoid these cases (without breaking existing valid code)?

---

<div class="post-metadata">

**Author:** ![kyay10](https://avatars.discourse-cdn.com/v4/letter/k/c57346/32.png) [@kyay10](https://discuss.kotlinlang.org/u/kyay10)\
**Post date:** [December 18, 2020, 10:52am UTC](https://discuss.kotlinlang.org/t/if-needs-else-branch-in-expression-of-type-unit/7970/19 "2020-12-18T10:52:33Z")

</div>

In this specific case, an extension like this would probably work quite well:

```auto
val Any?.ignoreResult get() = Unit

```
