kotlindictionaryrecursionfold

Idiomatic Kotlin Value Mapping


I have an extension function for an interface that will replace a single argument in the path and return a new anonymous implementation of that interface. When applying this pattern for multiple arguments, though, I've only been able to get it to work by iterating over the map of arguments and values and assigning the result to a var.

The reassignment of a var in this implementation doesn't feel like it's the "right" approach, though. Is there a more idiomatic way to accomplish the same goal?

interface NavRoute {
    val path: String
    val title: Int
}

fun NavRoute.withArgument(argument: String, value: Any) : NavRoute {
    val newPath = this.path.replace("{$argument}", value.toString())
    val thisTitle = this.title

    return object : NavRoute {
        override val path: String = newPath
        override val title: Int = thisTitle
    }
}

fun NavRoute.withArguments(arguments: Map<String, Any>) : NavRoute {
    var newRoute = this
    arguments.map {
        newRoute = newRoute.withArgument(it.key, it.value)
    }
    return newRoute
}

I attempted to rewrite this using a recursive approach, but I couldn't ever get anything to compile.


Solution

  • You can avoid var by first converting the arguments Map to an Iterable and then folding on that:

    fun NavRoute.withArguments(arguments: Map<String, Any>): NavRoute =
        arguments.entries.fold(this) { route, entry -> route.withArgument(entry.key, entry.value) }
    

    Your version is more readable though.

    BTW, you have "{$argument}", is that really what you want?