# Eliminating the usage of exceptions where possible (like accessing an index in a list)

**URL:** <https://discuss.kotlinlang.org/t/eliminating-the-usage-of-exceptions-where-possible-like-accessing-an-index-in-a-list/9750>\
**Category:** Language Design\
**Created:** [October 9, 2018, 8:00am UTC](https://discuss.kotlinlang.org/t/eliminating-the-usage-of-exceptions-where-possible-like-accessing-an-index-in-a-list/9750 "2018-10-09T08:00:13Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![tylerwbrown](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tylerwbrown/32/5588_2.png) [@tylerwbrown](https://discuss.kotlinlang.org/u/tylerwbrown)\
**Post date:** [October 9, 2018, 8:00am UTC](https://discuss.kotlinlang.org/t/eliminating-the-usage-of-exceptions-where-possible-like-accessing-an-index-in-a-list/9750/1 "2018-10-09T08:00:13Z")

</div>

Right now the following code:

```
val q = listOf("potato", "tomato")[3]

```

will throw an exception (index out of bounds).

The fix for this, in Kotlin, is this:

```
val q = listOf("potato", "tomato").getOrNull(3)

```

What’s the reasoning behind this verbosity? There are other languages (Elm for example) that default to the optional behavior for index retrievals.

I think it’s best to move away from exceptions where possible. (compile-time safety \> runtime errors)

I feel like the first code snippet should return a `String?` and then if you want an exception to be thrown in the case of a failure, you’d have to explicitly call to that:

```
val q = listOf("potato", "tomato").getOrException(3)

```

I think applying this null \> exceptions universally will result in fewer runtime failures.

In a similar vein, I think it’d be cool to be able to run Kotlin with a config option that turns all `Any!` types to `Any?`, so when utilizing Java libraries we don’t have to worry about NPEs. I understand the reasoning behind this (to get people to move to Kotlin from Java without having to implement safety that they didn’t have before), but I think that decision should only be temporary.

---

<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:** [October 9, 2018, 9:32am UTC](https://discuss.kotlinlang.org/t/eliminating-the-usage-of-exceptions-where-possible-like-accessing-an-index-in-a-list/9750/2 "2018-10-09T09:32:45Z")

</div>

Changing the function would mean a breaking change and will probably not going to happen.

Second, I agree.

---

<div class="post-metadata">

**Author:** ![tylerwbrown](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tylerwbrown/32/5588_2.png) [@tylerwbrown](https://discuss.kotlinlang.org/u/tylerwbrown)\
**Post date:** [October 9, 2018, 5:04pm UTC](https://discuss.kotlinlang.org/t/eliminating-the-usage-of-exceptions-where-possible-like-accessing-an-index-in-a-list/9750/3 "2018-10-09T17:04:14Z")

</div>

That’s a fair point. Maybe on a major release they’ll consider making non-backwards compatible changes? (2.0 etc.)

---

<div class="post-metadata">

**Author:** ![ilya.gorbunov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/ilya.gorbunov/32/1645_2.png) [@ilya.gorbunov](https://discuss.kotlinlang.org/u/ilya.gorbunov)\
**Post date:** [October 9, 2018, 5:33pm UTC](https://discuss.kotlinlang.org/t/eliminating-the-usage-of-exceptions-where-possible-like-accessing-an-index-in-a-list/9750/4 "2018-10-09T17:33:08Z")

</div>

Let’s take the `Map.get(K): V?` operation as an example. It returns `null` when the value is not in the map — so it behaves exactly the same as you propose the operation `List.get` should behave.

This nullable return type proved to be inconvenient in the following situations:

- when you want to perform an augmented assignment operation on a map value:

```auto
val map: MutableMap<Key, List<Value>> = ...
map[someKey] += anotherValue

```

- when you want to navigate through nested structures:

```auto
val map: Map<Key1, Map<Key2, Value>> = ...
val value = map[key1][key2]

```

Both of the above examples do not compile because of the nullable return type of `Map.get`. Thus it is questionable whether the proposed change will improve code in the common use cases.

> [@tylerwbrown](#):
>
> The fix for this, in Kotlin, is this:
> 
> ```auto
> val q = listOf("potato", "tomato").getOrNull(3)
> 
> ```

Another possible fix is to avoid querying the list with an index out of its bounds and still use the operator `[]` .

---

<div class="post-metadata">

**Author:** ![tylerwbrown](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/tylerwbrown/32/5588_2.png) [@tylerwbrown](https://discuss.kotlinlang.org/u/tylerwbrown)\
**Post date:** [October 9, 2018, 9:30pm UTC](https://discuss.kotlinlang.org/t/eliminating-the-usage-of-exceptions-where-possible-like-accessing-an-index-in-a-list/9750/5 "2018-10-09T21:30:30Z")

</div>

Those are good points I hadn’t considered.

Do you think there are other ways we could achieve the conciseness of the above while still having compile-time safety for these exception-prone operations?

The thing about the following code:

```auto
val map = mutableMapOf<String, List<String>>()
map["potato"] = (map["potato"] ?: listOf()) + "newItem"

```

vs the following code with potential to throw:

```auto
val map = mutableMapOf<String, List<String>>()
map["potato"] += "newItem"

```

is the former is safer, and defines default functionality. I agree it’s a bit too verbose, and the only solution I can think of is simply a different flow (inspired by `getOrPut`):

```auto
val map = mutableMapOf<String, List<String>>()
map.appendOrPut("potato", "newItem", listOf())

```

appendOrPut being:

```auto
fun <T, Q> MutableMap<T, List<Q>>.appendOrPut(key: T, value: Q, default: List<Q>) {
    this[key] = (this[key] ?: default) + value
}

```

> [@ilya.gorbunov](#):
>
> Another possible fix is to avoid querying the list with an index out of its bounds and still use the operator `[]` .

Yes, this is doable if you know the bounds of the list and trust the programmer doesn’t make a mistake in figuring this out. I believe that this type of job (validating bounds) would be better suited for a compiler, though.

In a world where `li[key]` returns `T?`, we could just smart cast in situations where the compiler can verify the length of a list.  
This could play into another post I have about refinement types; we could expect a parameter of type

```auto
li: List<String> :: { it.size > 4 && it.size < 12 }

```

and then:  
`li[2]` would return `null`,  
`li[7]` would return `String`,  
`li[16]` would return `null`

but even without refinement types, you could still do local smart casting if the list is not mutable.
