Strings
A redefinição: a string é UTF-8 invariante com unidade explícita (
s[i]é proibido) e comparar é método, porque “igual” é ambíguo.
O conceito
Seção intitulada “O conceito”String parece simples até você lembrar que UTF-8 tem três unidades distintas (bytes, codepoints e
graphemes, os caracteres visuais) e que “essas duas strings são iguais?” depende de normalização e
locale. A maioria das linguagens esconde isso: s[i] te dá algo (byte? char?), e == faz alguma
comparação. O conforto é uma mentira de superfície.
Como Makoto redefine
Seção intitulada “Como Makoto redefine”A string é sempre UTF-8 válido e expõe três visões: .bytes, .codepoints, .chars
(grapheme). s[i] cru é proibido: você qualifica a unidade (s.bytes[i], s.chars[i]), porque
indexar sem dizer o quê é ambíguo, e a ambiguidade esconde o custo (byte é O(1); grapheme é O(n)).
Comparação tem um corte deliberado: os operadores ==/!=/</> existem, mas são byte-a-byte
(igualdade de bytes, ordem lexicográfica, o caso comum e rápido, que alimenta um sort direto). A
semântica Unicode (normalização, collation, case-insensitive) é método (a.equals(b, .semantic)), não operador. E não há ===: um segundo operador de igualdade só criaria a pergunta
“qual é a verdadeira?”.
Interpolação é {{ }} via a interface Display, não uma mini-linguagem de format dentro da string.
O raciocínio
Seção intitulada “O raciocínio”O critério é o mesmo que governa o resto da linguagem: o que é trivial e mapeável na cabeça é
operador; o que é decisão semântica dependente de ambiente é método. Comparar bytes é trivial: você
sabe exatamente o que acontece. Comparar “São” com “Sao” respeitando locale não é trivial: depende
de normalização, de tabelas Unicode, de uma escolha. Esconder essa escolha atrás de um == seria
mágica; expô-la como equals(_, mode) é honestidade, e sinaliza, pelo próprio fato de ser método, que
ali mora complexidade (e que as tabelas Unicode pesam, então são opt-in).
Proibir s[i] é o mesmo princípio aplicado a acesso: a string te força a escolher a unidade, porque
não existe uma resposta única e barata. É o nome honesto (cap. 12) levado à indexação: s.bytes e
s.chars dizem exatamente o que você pega e quanto custa.
Por que não as alternativas
Seção intitulada “Por que não as alternativas”s[i]permitido. O programador nunca saberia se paga O(1) (byte) ou O(n) (grapheme), e qual unidade recebe. Viola a linearidade-visível; a unidade explícita resolve.- Comparação Unicode transparente no operador (Swift et al.). Esconde a decisão de locale/
normalização atrás de um
<que parece trivial, e quando a plataforma faz collation onde você queria bytes (ou vice-versa), você está em terreno minado sem aviso. Método torna a decisão visível. ===para igualdade bit-exata. Duas igualdades obrigam a perguntar qual é a canônica; é “deixar a resposta errada ser barata”.==já é byte-equality inequívoca; o resto é método.- Mini-linguagem de format na string (
%d,{:.2}). Uma segunda gramática dentro da string.{{ expr }}viaDisplayreusa a interface e deixa cada tipo controlar a própria renderização.
A dor concreta
Seção intitulada “A dor concreta”O “localization hell”: o == que compara certo no seu locale e errado no do usuário; o s[i] que
parte um emoji no meio porque indexou byte achando que era caractere; o .length que conta unidades de
código UTF-16 e mente sobre quantos caracteres há. Cada uma é a unidade ambígua ou a comparação
escondida cobrando o preço, quase sempre em produção, quase sempre num idioma que não é o do
desenvolvedor.
O modelo mental
Seção intitulada “O modelo mental”Comparar string é método explícito porque “igual” é ambíguo. E indexar exige dizer a unidade, porque não há uma resposta única e barata.
A fricção aceita
Seção intitulada “A fricção aceita”Você digita mais: s.bytes.len em vez de s.len, a.equals(b, .semantic) em vez de a == b quando
quer Unicode. O caso comum (bytes) continua curto, mas o semântico custa uma chamada, de propósito,
porque é onde a decisão real mora. A string recusa o conforto de superfície em troca de você sempre
saber o que está comparando e quanto está pagando.
Próximo: 10 · FFI