stringkotlindeprecatedcapitalization

Is there a shorter replacement for Kotlin's deprecated String.capitalize() function?


Kotlin deprecated the capitalize function on String class, and their suggested replacement is obnoxiously long. This is an example of a situation where they made the right call on deprecating it, but the wrong call on the user experience.

For example, this code:

val x = listOf("foo", "bar", "baz").map { it.capitalize() }

is "cleaned up" by the IDE to become:

val x = listOf("foo", "bar", "baz").map { it.replaceFirstChar {
                    if (it.isLowerCase()) it.titlecase(
                        Locale.getDefault()
                    ) else it.toString()
                } }

This is preeeeetty ugly. What can we do about it?


Solution

  • The suggested replacement is ugly because it needs to be equivalent to what capitalize() used to do:

    1. dependent on the default locale
    2. NOT converting an uppercase first char into titlecase (e.g. capitalize does NOT transform a leading 'DŽ' character into its 'Dž' titlecase version)

    If you didn't care too much about this behaviour, you can use a simpler expression using an invariant locale and unconditionally titlecasing the first character even if uppercase:

    val x = listOf("foo", "bar", "baz").map { it.replaceFirstChar(Char::titlecase) }
    

    This means that if the first character is uppercase like 'DŽ', it will be transformed into the titlecase variant 'Dž' anyway, while the original code wouldn't touch it. This might actually be desirable.

    One of the reasons capitalize() has been deprecated is because the behaviour of the method was unclear. For instance:

    If you want to keep the exact current behaviour on purpose, but make it more convenient to use, you can always roll your own extension function with a name that suits you ("capitalize(d)" might not give enough info to the unaware reader):

    fun String.titlecaseFirstCharIfItIsLowercase() = replaceFirstChar { 
        if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() 
    }
    

    Or for the version with invariant locale that titlecases the uppercase chars:

    fun String.titlecaseFirstChar() = replaceFirstChar(Char::titlecase)