Swift stakes out one of the most interesting points in the design space by completely encapsulating the internal representation and requiring all accessors to be explicit in whether they operate on the string's encoding (e.g. as UTF-8), its Unicode code points, or its grapheme clusters. All positions within the string are represented using abstract iterators that don't reveal their numeric quantities.
Diametrically opposite in the design space is Go (close to C and C++), in which a string is simply an array of bytes, conventionally treated as UTF-8. To access code points requires explicit decoding (or a range loop), and to access grapheme clusters requires a text package.
Ruby is another interesting choice: a string is a pair of a (mutable!) byte array and value indicating how to decode those bytes into code points. This representation works well when you have to deal with strings in obscure encodings as it preserves the original bytes, so, for example, you can read file names from a directory then delete those files.
There are a great many other designs in wide use---Haskell, Java, and Python being the most unnecessarily complicated---but these three designs seemed the most defensible to me.
What does make it a bit complicated is that there are about four other different string types to choose between, besides the default String type, which should never be used for anything performance-sensitive.
This is probably the only right way because 1. it admits multiple implementations (like packing into tagged pointers) and 2. a string isn't simply an array of anything. Strings are made of all of bytes/codepoints/grapheme clusters/words/lines/etc at different levels.
Raku passes all the tests. He mentions he didn't find any language that upper-cases "baffle" correctly but Raku does.
Here's my REPL test
> my $n = "noe\x[0308]l"
noël
> $n.chars
4
> $n.flip
lëon
> $n.substr(0, 3)
noë
> my $b = "baffle"
baffle
> $b.substr(2, 1).uniname
LATIN SMALL LIGATURE FFL
> $b.uc
BAFFLE
> "noe\x[0308]l" eq "no\x[00EB]l"
True
HN doesn't handle the cat emojis, so they are not included, but they worked fine.We call it NFG for Normalized Form Grapheme.
The JVM and JavaScript backends currently use the built-in string handling features. Which means that they are just as broken as the rest of the code running on them.
---
Of further note, you can use ignorecase in regexes to match "baffle".
"baffle" ~~ /:ignorecase BAFfLE /;