C'est un vaste sujet\u00A0! Il est possible d'écrire un long livre à ce propos, et plusieurs personnes l'ont fait (cherche «\u00A0unicode book\u00A0» sur Amazon pour en voir quelques exemples).
La gestion des caractères dans les ordinateurs était bien plus simple dans les décennies précédentes, quand les programmeurs partaient du principe que l'anglais était la seule langue importante. Donc\u00A0: 26 lettres, majuscules et minuscules, 10 chiffres, plusieurs signes de ponctuation, plus un code (0x07) pour faire sonner une cloche, et tout cela tenait sur 7 bits\u00A0: le jeu de caractères ASCII.
Naturellement, les gens ont commencé à demander ce qu'il en était de à, ä et Ł, puis d'autres ont demandé pour ऄ, ஹ et ญ, et les jeunes voulaient des emojis 😱. Que faire\u00A0?
Pour faire court, de nombreuses personnes intelligentes et patientes ont dû siéger dans des comités pendant des années, pour définir les détails du jeu de caractères Unicode et des encodages comme UTF-8, et beaucoup de logiciels ont eu besoin d'une réécriture très compliquée. De plus, beaucoup de nouveaux bugs ont été introduits.
Pour éviter que tout ne casse, la conception d'Unicode/UTF-8 garantit que les 127 premiers codes sont identiques à ceux de l'ASCII (même la cloche).
Les langages conçus après 2005 environ ont l'énorme avantage qu'une norme Unicode raisonnablement stable existait déjà.
Julia (dont la première version est sortie en 2012) a pu partir du principe que tout serait en Unicode\u00A0: les caractères, les strings, les noms de variables et de fonctions, les opérateurs mathématiques...
Pour citer le manuel\u00A0: «\u00A0Julia rend le traitement du texte ASCII simple et efficace, et la gestion d'Unicode aussi simple et efficace que possible.\u00A0» Note le «\u00A0que possible\u00A0», c'est une partie importante de la phrase.
Les littéraux de caractère s'écrivent entre guillemets simples, et sont distincts des strings écrites entre guillemets doubles.
C'est évident pour les personnes venant du monde C/C++, mais peut être déroutant pour les programmeurs Python et JavaScript.
julia> a = 'a' # Roman alphabet
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
julia> typeof(a)
Char
julia> jha = 'झ' # Devanagari alphabet
'झ': Unicode U+091D (category Lo: Letter, other)
julia> typeof(jha)
Char
julia> '❤' # heart emoji
'❤': Unicode U+2764 (category So: Symbol, other)
On voit dans ces exemples que le type est Char, et que Julia dispose d'informations supplémentaires sur la catégorie du caractère.
En y regardant de plus près, il apparaît que ces caractères peuvent être représentés par 4 chiffres hexadécimaux. Le jeu de caractères complet nécessite jusqu'à 6 chiffres hexadécimaux.
Ces nombres sont appelés «\u00A0points de code\u00A0», et vont actuellement de U+0000 à U+10FFFF.
Ils s'affichent dans le REPL, mais dans le code, utilise codepoints() pour les obtenir.
La conversion entre Char et Int est simple\u00A0:
julia> Int('a')
97
julia> Char(97)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
Le compilateur autorise certaines formes d'arithmétique entière sur les Chars\u00A0:
julia> 'b' - 'a' # interval, in alphabetic order
1
julia> 'b' + 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)
julia> 'a' + 5
'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)
julia> 'f' + ('A' - 'a') # same as `uppercase('f')`
'F': ASCII/Unicode U+0046 (category Lu: Letter, uppercase)
De nombreuses fonctions de manipulation de strings peuvent aussi fonctionner sur une entrée de type Char.
uppercase() et lowercase().isuppercase() et islowercase().isletter() couvre de nombreux alphabetsisdigit(), teste strictement les chiffres de 0 à 9isnumeric(), plus large que isdigit, donc true pour ¾ et diverses écritures non européennesisxdigit(), les chiffres hexadécimauxisascii(), caractère antérieur à Unicodeispunct(), la ponctuationisspace(), n'importe quel caractère d'espacementisprint(), les caractères imprimables (l'inverse est iscntrl())islowercase('A') # false
uppercase('γ') # 'Γ': Unicode U+0393 (category Lu: Letter, uppercase)
ispunct('@') # true
isdigit('A') # false
isxdigit('A') # true
Pour passer d'une String à un vecteur de Char, on peut utiliser collect().
Pour passer d'un vecteur de Char à une String, il y a le constructeur String().
julia> s = "abcde"
"abcde"
julia> cv = collect(s)
5-element Vector{Char}:
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)
julia> String(cv)
"abcde"
Cela fonctionne avec n'importe quel caractère, pas seulement ASCII.
julia> collect("❤,😱")
3-element Vector{Char}:
'❤': Unicode U+2764 (category So: Symbol, other)
',': ASCII/Unicode U+002C (category Po: Punctuation, other)
'😱': Unicode U+1F631 (category So: Symbol, other)
Note que le constructeur String() opère sur un Vector.
Pour convertir un seul Char en une string d'un seul caractère, la fonction est string(), avec un s minuscule.
julia> string('a')
"a"
Tout ce qui précède dans ce document semble relativement simple, alors y a-t-il vraiment si peu de choses à craindre\u00A0?
Malheureusement, c'est trop optimiste\u00A0!
Une complication vient du besoin de «\u00A0jusqu'à\u00A0» 6 chiffres hexadécimaux par point de code. Cela signifie que différents caractères nécessitent différentes quantités de mémoire lorsqu'ils sont encodés en UTF-8.
Un octet ne peut stocker que des nombres (non signés) jusqu'à 255, soit deux chiffres hexadécimaux, donc UTF-8 utilise un nombre variable d'octets (de 1 à 4) pour stocker un Char.
On les appelle des «\u00A0unités de code\u00A0», et la fonction ncodeunits() renvoie le nombre nécessaire pour un caractère donné.
julia> codepoint(jha) # jha 'झ' is defined in an earlier example
0x0000091d
julia> ncodeunits(jha)
3
julia> ncodeunits('a') # ASCII character
1
julia> ncodeunits('😱') # emoji
4
De plus, tout ce qui peut s'afficher à l'écran n'a pas forcément son propre point de code unique. Certains caractères visuellement distincts sont considérés comme dérivés d'autres, si bien qu'Unicode les traite comme un caractère parent suivi d'un modificateur.
Ce problème concerne les String, où il pose des difficultés pour l'indexation.
Dans cet exercice, tu vas implémenter un ensemble partiel de fonctions utilitaires pour aider un développeur à nettoyer des noms d'identifiants.
Au fil des 6 tâches, tu vas construire progressivement la fonction transform, qui convertit des caractères isolés, et la fonction clean, qui convertit des strings.
Un identifiant valide comprend zéro ou plusieurs lettres, tirets bas, tirets, points d'interrogation et émojis.
Si on passe une string vide à la fonction clean, celle-ci doit renvoyer une string vide.
Implémente la fonction transform pour remplacer les tirets par des tirets bas.
julia> transform('-')
"_"
Supprime tous les caractères d'espacement. Cela inclut les espaces en début et en fin de chaîne.
julia> transform(' ')
""
Modifie la fonction transform pour qu'elle convertisse camelCase en kebab-case.
julia> transform('D')
"-d"
Modifie la fonction transform pour qu'elle omette tous les caractères numériques.
julia> transform('7')
""
Modifie la fonction transform pour qu'elle remplace toutes les lettres grecques comprises entre 'α' et 'ω'.
julia> transform('β')
"?"
Implémente la fonction clean pour appliquer ces opérations à une string entière.
Les caractères qui ne relèvent pas de ces règles doivent passer sans modification.
julia> clean(" a2b Cd-ω😀 ")
"ab-cd_?😀"
Inscris-toi sur Exercism pour apprendre et maîtriser Julia avec 35 concepts128 exercices, et un vrai mentorat humain, le tout gratuitement.