It&#x27;s possible to do better than existing mainstream solutions:<p>(0) Dependent types: The type of valid indices into a string depends, well, on the string. It&#x27;s this type, not `uint`, that should be used by functions like `str.find()` and `re.match()`. This makes it a compile error to, say, slice a string with an index to another string. Internally, or course, all indices are represented as `uint`s, but your program has no business knowing this. It&#x27;s an abstract type. IMO, this solution is particularly useful for systems languages, where the increased flexibility and fine-grained control are worth the increase in complexity.<p>(1) Coalgebras: `str.find()` shouldn&#x27;t return an index. Instead, it should return in O(1) time, and allocating O(1) additional space, the left and right slices of the original string, split at the desired index. (If the string can be split in multiple places, `str.find()` should return an iterator whose element type is such left-right pairs.) For this to work, it&#x27;s fundamental that the left and right slices not be allocated in their own buffers, but instead share the original string&#x27;s buffer. IMO, this solution is best for high-level languages, where simplifying the API is well worth a little loss in flexibility.<p>Neither of these APIs allows the programmer to split strings at the wrong places.