StringBuilder.replaceRange()

Recently I met a bug:

sb.replaceRange(…), but indeed nothing happened.

After clicking into StringBuilder.replaceRange(), I found this method is extended on CharSequence, treating StringBuilder as an immutable, and then returns a new modified copy of it. And I think this is definitely most ones don’t expect.

Would you guys like to see a new standalone StringBuilder.raplaceRange(…) added into the stdlib?

fun main() {
//sampleStart
val sb = StringBuilder()
sb.append("Hello World")
sb.replace(2, 4, "ZZZZ")
println(sb.toString())
//sampleEnd
}

Works fine for me.

2 Likes

Indeed. To override CharSequence.replaceRange with this meaning for StringBuilder would be invalid as the function contract implies immutability. I will say that the naming is perhaps a bid unfortunate, but not something that can be changed at this point.

This might be a problem with extension functions in general. The CharString.replaceRange function was written with readonly access to the data. This is fine for nearly all CharSequences. I guess 99% of the time they are String and therefor immutable.
This does not however work well with StringBuilder where each member function is supposed to change the state of the builder and not return a new instance. Also it’s not easy to tell that StringBuilder.replace is a better alternative.
This get’s even more confusing when you try to use CharSequence.replace(regex, replacement) on a StringBuilder. Now you have 2 functions with the same name on the same object, one modifying the state and the other returning a new instance.
I’m not sure, but maybe the functions defined in String.kt in the standard library should have extended String instead of CharSequence. That way they would not pollute StringBuilder.