3

I am trying to convert an Array via fold into an indexed Map. Somehow IntelliJ flags that when I return the accumulator that it expects Unit. When I remove the return it complains that I require the datatype I originally wanted to return.

The code is as follows (Item is just a data class)

    constructor(vararg items: Item){
    val itemMap = items.fold(mutableMapOf<Int, MutableList<Item>>(), { acc, item ->
        if (acc.containsKey(item.state)) {
            acc[item.state]?.add(item)
        } else {
            acc.put(item.state, mutableListOf(item))
        }
        return acc
    })

}

Its a bit late here so I probably miss something very obvious. Any help would be very appreciated.

Thanks

hotkey
  • 140,743
  • 39
  • 371
  • 326
Oliver
  • 89
  • 2
  • 8

1 Answers1

13

Use the qualified return@fold operator instead of return. In Kotlin, return without a qualifier means 'return from the innermost fun (ignoring lambdas)'.

val itemMap = items.fold(mutableMapOf<Int, MutableList<Item>>(), { acc, item ->
    if (acc.containsKey(item.state)) {
        acc[item.state]?.add(item)
    } else {
        acc.put(item.state, mutableListOf(item))
    }
    return@fold acc
})

See Whats does “return@” mean?, Return at Labels in the language reference.

Or just use the result expression, omitting return:

val itemMap = items.fold(mutableMapOf<Int, MutableList<Item>>(), { acc, item ->
    if (acc.containsKey(item.state)) {
        acc[item.state]?.add(item)
    } else {
        acc.put(item.state, mutableListOf(item))
    }
    acc
})

Basically, this kind of fold is implemented in the standard library: see .groupBy { ... }.

hotkey
  • 140,743
  • 39
  • 371
  • 326