Pourquoi Perl moderne évite-t-il l'UTF-8 par défaut?

557

Je me demande pourquoi la plupart des solutions modernes construites à l'aide de Perl n'activent pas UTF-8 par défaut.

Je comprends qu'il existe de nombreux problèmes hérités pour les scripts Perl de base, où cela peut casser les choses. Mais, de mon point de vue, au 21ème siècle, les grands nouveaux projets (ou projets avec une grande perspective) devraient faire de leur logiciel UTF-8 une preuve à partir de zéro. Je ne vois toujours pas cela se produire. Par exemple, Moose active les avertissements stricts et non Unicode . Modern :: Perl réduit également le passe-partout, mais pas de manipulation UTF-8.

Pourquoi? Y a-t-il des raisons d'éviter l'UTF-8 dans les projets Perl modernes en 2011?


Commenter @tchrist est devenu trop long, alors je l'ajoute ici.

Il semble que je n'ai pas été clair. Permettez-moi d'essayer d'ajouter quelques éléments.

Tchrist et moi voyons la situation de façon assez similaire, mais nos conclusions sont complètement opposées. Je suis d'accord, la situation avec Unicode est compliquée, mais c'est pourquoi nous (utilisateurs Perl et codeurs) avons besoin d'une couche (ou pragma) qui rend la gestion UTF-8 aussi simple qu'elle doit l'être de nos jours.

tchrist a souligné de nombreux aspects à couvrir, je vais les lire et y réfléchir pendant des jours, voire des semaines. Pourtant, ce n'est pas mon point. tchrist essaie de prouver qu'il n'y a pas une seule façon "d'activer UTF-8". Je n'ai pas tellement de connaissances pour contester cela. Donc, je m'en tiens à des exemples vivants.

J'ai joué avec Rakudo et UTF-8 était juste là comme j'avais besoin . Je n'ai eu aucun problème, cela a juste fonctionné. Peut-être qu'il y a des limites quelque part plus profondément, mais au début, tout ce que j'ai testé a fonctionné comme je m'y attendais.

Cela ne devrait-il pas aussi être un objectif dans Perl 5 moderne? J'insiste davantage: je ne suggère pas UTF-8 comme jeu de caractères par défaut pour le noyau Perl, je suggère la possibilité de le déclencher avec un clin d' œil pour ceux qui développent de nouveaux projets.

Un autre exemple, mais avec un ton plus négatif. Les cadres devraient faciliter le développement. Il y a quelques années, j'ai essayé des frameworks Web, mais je les ai simplement jetés parce que "activer UTF-8" était tellement obscur. Je n'ai pas trouvé comment et où accrocher le support Unicode. Cela prenait tellement de temps que j'ai trouvé plus facile de suivre l'ancienne voie. Maintenant, j'ai vu ici qu'il y avait une prime pour faire face au même problème avec Mason 2: Comment nettoyer Mason2 UTF-8? . C'est donc un cadre assez nouveau, mais son utilisation avec UTF-8 nécessite une connaissance approfondie de ses composants internes. C'est comme un grand panneau rouge: STOP, ne m'utilise pas!

J'aime vraiment Perl. Mais traiter avec Unicode est douloureux. Je me retrouve toujours à courir contre les murs. D'une certaine manière, tchrist a raison et répond à mes questions: les nouveaux projets n'attirent pas l'UTF-8 car c'est trop compliqué dans Perl 5.

wk
la source
15
Je suis désolé mais je suis d'accord avec @tchrist - UTF-8 est extrêmement difficile. Il n'y a pas de framework ou d'outil qui "retourne un interrupteur" et le gère correctement. C'est quelque chose que vous devez penser directement lors de la conception de votre application - pas quelque chose que n'importe quel type de cadre ou de langage peut gérer pour vous. Si rakudo venait juste de fonctionner pour vous, vous n'étiez pas assez aventureux avec vos cas de test - car il faudra alors plusieurs exemples dans la réponse et la boucherie de @ tchrist.
Billy ONeal
12
Qu'espérez-vous exactement que Moose ou Modern :: Perl fera? Transformez-vous comme par magie des données de caractères codées au hasard dans des fichiers et des bases de données en données valides?
jrockway
13
Qu'est-ce que ça veut dire? L'orignal n'a rien à voir avec la manipulation de texte. Pourquoi devrait-il connaître l'encodage des caractères, et encore moins en choisir un par défaut pour vous? (Quoi qu'il en soit, la raison pour laquelle les pragmas que vous répertoriez ne touchent pas l'encodage est que la convention veut que les pragmas de Perl affectent le comportement lexical . En supposant que le monde entier, autres modules inclus, est UTF-8, c'est simplement la mauvaise chose à faire Ce n'est pas PHP ou Ruby ici.)
jrockway
8
(Aussi ... "la plupart des applications Perl modernes" se cassent sur UTF-8? Je n'ai certainement jamais écrit d'application, Perl ou autre, qui n'est pas propre à Unicode.)
jrockway
11
Nb. tchrist (Tom Christiansen) a publié son [ training.perl.com/OSCON2011/index.html Documents de Tom Christiansen pour OSCON 2011] sur Unicode. Celui intitulé «Shootout de support Unicode: le bon, le mauvais et le (surtout) laid» parle du support Unicode dans différents langages de programmation. Seuls Google Go et Perl5 prennent en charge Unicode complet, uniquement Google Go intégré (aucune mention de Perl6).
Jakub Narębski

Réponses:

1146

𝙎𝙞𝙢𝙥𝙡𝙚𝙨𝙩 : 𝟕 𝘿𝙞𝙨𝙘𝙧𝙚𝙩𝙚 𝙍𝙚𝙘𝙤𝙢𝙢𝙚𝙣𝙙𝙖𝙩𝙞𝙤𝙣𝙨

  1. Réglez votre PERL_UNICODEenvariable sur AS. Cela décode tous les scripts Perl @ARGVen chaînes UTF-8 et définit le codage des trois stdin, stdout et stderr sur UTF-8. Ces deux effets sont globaux et non lexicaux.

  2. En haut de votre fichier source (programme, module, bibliothèque, dosuçon), assurez-vous que vous exécutez perl version 5.12 ou mieux via:

    use v5.12;  # minimal for unicode string feature
    use v5.14;  # optimal for unicode string feature
  3. Activez les avertissements, car la déclaration précédente n'active que les restrictions et les fonctionnalités, pas les avertissements. Je suggère également de promouvoir les avertissements Unicode en exceptions, alors utilisez ces deux lignes, pas seulement l'une d'entre elles. Notez cependant que sous v5.14, la utf8classe d'avertissement comprend trois autres subwarnings qui peuvent tous être séparément activé: nonchar, surrogateet non_unicode. Vous pourriez souhaiter exercer un plus grand contrôle sur ces éléments.

    use warnings;
    use warnings qw( FATAL utf8 );
  4. Déclarez que cette unité source est codée en UTF-8. Bien qu'il fut un temps où ce pragma faisait autre chose, il sert maintenant ce seul but singulier et aucun autre:

    use utf8;
  5. Déclarez que tout ce qui ouvre un descripteur de fichier dans cette portée lexicale, mais pas ailleurs, suppose que ce flux est codé en UTF-8, sauf indication contraire. De cette façon, vous n'affectez pas le code d'un autre module ou d'un autre programme.

    use open qw( :encoding(UTF-8) :std );
  6. Activez les caractères nommés via \N{CHARNAME}.

    use charnames qw( :full :short );
  7. Si vous avez un DATAhandle, vous devez définir explicitement son encodage. Si vous voulez que ce soit UTF-8, alors dites:

    binmode(DATA, ":encoding(UTF-8)");

Il n'y a bien sûr pas de fin à d'autres questions qui pourraient éventuellement vous préoccuper, mais celles-ci suffiront à rapprocher l'objectif de l'État de «tout faire fonctionner avec l'UTF-8», bien que pour un sens quelque peu affaibli de ces termes.

Un autre pragma, bien qu'il ne soit pas lié à Unicode, est:

      use autodie;

C'est fortement recommandé.

🌴 🐪🐫🐪 🌞 𝕲𝖔 𝕿𝖍𝖔𝖚 𝖆𝖓𝖉 𝕯𝖔 𝕷𝖎𝖐𝖊𝖜𝖎𝖘𝖊 🌞 🐪🐫🐪 🐁


🎁 🐪 𝕭𝖔𝖎𝖑𝖊𝖗⸗𝖕𝖑𝖆𝖙𝖊 𝖋𝖔𝖗 𝖀𝖓𝖎𝖈𝖔𝖉𝖊⸗𝕬𝖜𝖆𝖗𝖊 𝕮𝖔𝖉𝖊 🐪 🎁


Ces jours-ci, mon propre passe-partout a tendance à ressembler à ceci:

use 5.014;

use utf8;
use strict;
use autodie;
use warnings; 
use warnings    qw< FATAL  utf8     >;
use open        qw< :std  :utf8     >;
use charnames   qw< :full >;
use feature     qw< unicode_strings >;

use File::Basename      qw< basename >;
use Carp                qw< carp croak confess cluck >;
use Encode              qw< encode decode >;
use Unicode::Normalize  qw< NFD NFC >;

END { close STDOUT }

if (grep /\P{ASCII}/ => @ARGV) { 
   @ARGV = map { decode("UTF-8", $_) } @ARGV;
}

$0 = basename($0);  # shorter messages
$| = 1;

binmode(DATA, ":utf8");

# give a full stack dump on any untrapped exceptions
local $SIG{__DIE__} = sub {
    confess "Uncaught exception: @_" unless $^S;
};

# now promote run-time warnings into stack-dumped
#   exceptions *unless* we're in an try block, in
#   which case just cluck the stack dump instead
local $SIG{__WARN__} = sub {
    if ($^S) { cluck   "Trapped warning: @_" } 
    else     { confess "Deadly warning: @_"  }
};

while (<>)  {
    chomp;
    $_ = NFD($_);
    ...
} continue {
    say NFC($_);
}

__END__

🎅 𝕹 𝖔 𝕸 𝖆 𝖌 𝖎 𝖈 𝕭 𝖚 𝖑 𝖑 𝖊 𝖙 🎅


Dire que «Perl devrait [ quelque sorte! ] Activer Unicode par défaut »ne commence même pas à commencer à penser à en dire assez pour être même marginalement utile dans une sorte de cas rare et isolé. Unicode est bien plus qu'un simple répertoire de caractères plus vaste; c'est aussi la façon dont ces personnages interagissent tous de nombreuses façons.

Même les mesures minimales simples que (certaines) personnes semblent penser vouloir sont garanties de briser misérablement des millions de lignes de code, du code qui n'a aucune chance de «mettre à niveau» vers votre nouveau style modernité courageuse Brave New World .

C'est beaucoup plus compliqué que ce que les gens prétendent. J'y ai beaucoup pensé ces dernières années. J'aimerais qu'on me montre que j'ai tort. Mais je ne pense pas que je le suis. Unicode est fondamentalement plus complexe que le modèle que vous souhaitez lui imposer, et il y a ici une complexité que vous ne pouvez jamais balayer sous le tapis. Si vous essayez, vous casserez votre propre code ou celui de quelqu'un d'autre. À un moment donné, il vous suffit de vous décomposer et de savoir de quoi parle Unicode. Vous ne pouvez pas prétendre que ce n'est pas quelque chose.

🐪 fait tout son possible pour rendre Unicode facile, bien plus que tout ce que j'ai jamais utilisé. Si vous pensez que c'est mauvais, essayez autre chose pendant un moment. Revenez ensuite à 🐪: soit vous serez retourné dans un monde meilleur, soit vous en apporterez la connaissance afin que nous puissions utiliser vos nouvelles connaissances pour améliorer 🐪 dans ces domaines.


💡 𝕴𝖉𝖊𝖆𝖘 𝖋𝖔𝖗 𝖆 𝖀𝖓𝖎𝖈𝖔𝖉𝖊 ⸗ 𝕬𝖜𝖆𝖗𝖊 🐪 𝕷𝖆𝖚𝖓𝖉𝖗𝖞 𝕷𝖎𝖘𝖙 💡


Au minimum, voici certaines choses qui semblent nécessaires pour que 🐪 "active Unicode par défaut", comme vous le dites:

  1. Tout 🐪 le code source doit être en UTF-8 par défaut. Vous pouvez l'obtenir avec use utf8ou export PERL5OPTS=-Mutf8.

  2. La DATApoignée should doit être en UTF-8. Vous devrez le faire sur une base par paquet, comme dans binmode(DATA, ":encoding(UTF-8)").

  3. Les arguments du programme pour les scripts 🐪 doivent être compris comme étant UTF-8 par défaut. export PERL_UNICODE=A, ou perl -CA, ouexport PERL5OPTS=-CA .

  4. Les flux d'entrée, de sortie et d'erreur standard doivent par défaut être UTF-8. export PERL_UNICODE=Spour chacun d'entre eux, ou I, Oet / ou Epour seulement certains d'entre eux. C'est commeperl -CS .

  5. Toute autre poignée ouverte par 🐪 doit être considérée comme UTF-8, sauf indication contraire; export PERL_UNICODE=Dou avec iet opour certains d'entre eux; export PERL5OPTS=-CDtravaillerait. Qui fait-CSAD pour chacun d'eux.

  6. Couvrez les deux bases ainsi que tous les flux avec lesquels vous ouvrez export PERL5OPTS=-Mopen=:utf8,:std. Voir uniquote .

  7. Vous ne voulez pas manquer des erreurs d'encodage UTF-8. Essayez export PERL5OPTS=-Mwarnings=FATAL,utf8. Et assurez-vous que vos flux d'entrée sont toujours binmodevers :encoding(UTF-8), pas seulement vers:utf8 .

  8. Les points de code compris entre 128 et 255 doivent être compris par 🐪 comme étant les points de code Unicode correspondants, et pas seulement des valeurs binaires non approuvées. use feature "unicode_strings"ou export PERL5OPTS=-Mfeature=unicode_strings. Cela fera uc("\xDF") eq "SS"et "\xE9" =~ /\w/. Un simple export PERL5OPTS=-Mv5.12ou meilleur obtiendra également cela.

  9. Les caractères Unicode nommés ne sont pas activés par défaut, alors ajoutez-en export PERL5OPTS=-Mcharnames=:full,:short,latin,greekou certains. Voir uninames et tcgrep .

  10. Vous avez presque toujours besoin d'accéder aux fonctions du module standard deUnicode::Normalize divers types de décompositions. export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKD, puis exécutez toujours les éléments entrants via NFD et les éléments sortants à partir de NFC. Il n'y a pas encore de couche d'E / S pour celles-ci à ma connaissance, mais voir nfc , nfd , nfkd et nfkc .

  11. Les comparaisons de chaînes à l' aide 🐪 eq, ne, lc, cmp, sort, etc. & cc ont toujours tort. Donc, au lieu de @a = sort @b, vous avez besoin @a = Unicode::Collate->new->sort(@b). Autant ajouter cela à votre export PERL5OPTS=-MUnicode::Collate. Vous pouvez mettre en cache la clé pour les comparaisons binaires.

  12. 🐪 les modules intégrés aiment printfet writefont la mauvaise chose avec les données Unicode. Vous devez utiliser le Unicode::GCStringmodule pour le premier, et à la fois cela et aussi le Unicode::LineBreakmodule pour le second. Voir uwc et unifmt .

  13. Si vous voulez qu'ils comptent comme des entiers, alors vous devrez exécuter vos \d+captures via la Unicode::UCD::numfonction car atoi (3) intégré à isn't n'est pas actuellement assez intelligent.

  14. Vous allez avoir des problèmes de système de fichiers sur les systèmes de fichiers. Certains systèmes de fichiers appliquent silencieusement une conversion en NFC; d'autres appliquent silencieusement une conversion à NFD. Et d'autres font encore autre chose. Certains ignorent même complètement la question, ce qui entraîne des problèmes encore plus graves. Vous devez donc faire votre propre manipulation NFC / NFD pour rester sain d'esprit.

  15. Tous vos 🐪 impliquant le code a-zou A-Zet tel doit être CHANGÉ , y compris m//, s///et tr///. Il devrait ressortir comme un drapeau rouge hurlant que votre code est cassé. Mais il n'est pas clair comment cela doit changer. Obtenir les bonnes propriétés et comprendre leurs dossiers est plus difficile que vous ne le pensez. J'utilise des unichars et uniprops tous les jours.

  16. Le code qui utilise \p{Lu}est presque aussi faux que le code qui utilise[A-Za-z] . Vous devez utiliser à la \p{Upper}place et connaître la raison. Oui, \p{Lowercase}et \p{Lower}sont différents de \p{Ll}et \p{Lowercase_Letter}.

  17. Code qui utilise [a-zA-Z] est encore pire. Et il ne peut pas utiliser \pLou \p{Letter}; il doit utiliser \p{Alphabetic}. Tous les alphabétiques ne sont pas des lettres, vous savez!

  18. Si vous recherchez 🐪 variables avec /[\$\@\%]\w+/, alors vous avez un problème. Vous devez rechercher /[\$\@\%]\p{IDS}\p{IDC}*/, et même cela ne pense pas aux variables de ponctuation ou aux variables de package.

  19. Si vous recherchez des espaces, vous devez choisir entre \het \v, selon. Et vous ne devriez jamais utiliser\s , car cela NE SIGNIFIE PAS [\h\v] , contrairement à la croyance populaire.

  20. Si vous utilisez \n pour une limite de ligne, ou même \r\n, alors vous le faites mal. Vous devez utiliser \R, ce qui n'est pas la même chose!

  21. Si vous ne savez pas quand et si vous devez appeler Unicode :: Stringprep , vous feriez mieux d'apprendre.

  22. Les comparaisons insensibles à la casse doivent vérifier si deux choses sont les mêmes lettres, peu importe leurs signes diacritiques et autres. La façon la plus simple de le faire est d' utiliser le module Unicode :: Collate standard . Unicode::Collate->new(level => 1)->cmp($a, $b). Il existe également des eqméthodes et autres, et vous devriez probablement aussi en apprendre davantage sur les méthodes matchet substr. Ce sont des avantages distincts par rapport aux 🐪 intégrés.

  23. Parfois, ce n'est toujours pas suffisant, et vous avez plutôt besoin du module Unicode :: Collate :: Locale , comme dans Unicode::Collate::Locale->new(locale => "de__phonebook", level => 1)->cmp($a, $b)plutôt. Considérez que Unicode::Collate::->new(level => 1)->eq("d", "ð")c'est vrai, mais Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d", " ð")c'est faux. De même, "ae" et "æ" sonteq si vous n'utilisez pas de paramètres régionaux, ou si vous utilisez l'anglais, mais ils sont différents dans les paramètres régionaux islandais. Maintenant quoi? C'est difficile, je vous le dis. Vous pouvez jouer avec ucsort pour tester certaines de ces choses.

  24. Considérez comment faire correspondre le modèle CVCV (consonne, voyelle, consonne, voyelle) dans la chaîne « niño ». Sa forme NFD - que vous aviez bien mieux sacrée avoir pensé à mettre - devient "nin \ x {303} o". Maintenant que vas-tu faire? Même en prétendant qu'une voyelle est [aeiou](ce qui est faux d'ailleurs), vous ne pourrez pas faire quelque chose comme ça (?=[aeiou])\X)non plus, car même dans NFD un point de code comme 'ø' ne se décompose pas ! Cependant, il sera testé égal à un «o» en utilisant la comparaison UCA que je viens de vous montrer. Vous ne pouvez pas compter sur NFD, vous devez compter sur UCA.


💩 𝔸 𝕤 𝕤 𝕦 𝕞 𝕖 𝔹 𝕣 𝕠 𝕜 𝕖 𝕟 𝕟 𝕖 𝕤 𝕤 💩


Et ce n'est pas tout. Il y a un million d'hypothèses brisées que les gens font à propos d'Unicode. Jusqu'à ce qu'ils comprennent ces choses, leur code 🐪 sera cassé.

  1. Le code qui suppose qu'il peut ouvrir un fichier texte sans spécifier l'encodage est rompu.

  2. Le code qui suppose que l'encodage par défaut est une sorte d'encodage de plate-forme native est rompu.

  3. Le code qui suppose que les pages Web en japonais ou en chinois occupent moins d'espace en UTF-16 qu'en UTF-8 est incorrect.

  4. Le code qui suppose que Perl utilise UTF-8 en interne est incorrect.

  5. Le code qui suppose que les erreurs de codage déclenchent toujours une exception est incorrect.

  6. Le code qui suppose que les points de code Perl sont limités à 0x10_FFFF est incorrect.

  7. Le code qui suppose que vous pouvez définir $/quelque chose qui fonctionnera avec n'importe quel séparateur de ligne valide est incorrect.

  8. Le code qui suppose l'égalité aller-retour sur le dossier, comme lc(uc($s)) eq $sou uc(lc($s)) eq $s, est complètement rompu et incorrect. Considérez que le uc("σ")et uc("ς") sont les deux "Σ", maislc("Σ") ne peuvent pas renvoyer les deux.

  9. Le code qui suppose que chaque point de code en minuscule en a un distinct en majuscule, ou vice versa, est rompu. Par exemple, "ª"est une lettre minuscule sans majuscule; considérant que les deux "ᵃ"et "ᴬ"sont des lettres, mais ce ne sont pas des lettres minuscules; cependant, ce sont deux points de code en minuscules sans versions majuscules correspondantes. C'est compris? Ils ne le sont pas\p{Lowercase_Letter} , bien qu'ils soient à la fois \p{Letter}et \p{Lowercase}.

  10. Le code qui suppose de changer la casse ne change pas la longueur de la chaîne est rompu.

  11. Le code qui suppose qu'il n'y a que deux cas est cassé. Il y a aussi le titlecase.

  12. Le code qui suppose que seules les lettres ont la casse est cassé. Au-delà des lettres, il s'avère que les chiffres, les symboles et même les marques ont de la casse. En fait, changer le boîtier peut même faire changer quelque chose à sa principale catégorie générale, comme le \p{Mark}transformer en a \p{Letter}. Il peut également le faire passer d'un script à un autre.

  13. Le code qui suppose que la casse n'est jamais dépendante des paramètres régionaux est rompu.

  14. Le code qui suppose qu'Unicode donne une figure sur les locales POSIX est cassé.

  15. Le code qui suppose que vous pouvez supprimer les signes diacritiques pour obtenir les lettres ASCII de base est mauvais, immobile, cassé, endommagé au cerveau, faux et justifie la peine capitale.

  16. Le code qui suppose que les signes diacritiques \p{Diacritic}et les marques \p{Mark}sont la même chose est rompu.

  17. Code qui suppose \p{GC=Dash_Punctuation} couvre autant que\p{Dash} est cassé.

  18. Le code qui suppose que les tirets, les tirets et les inconvénients sont identiques les uns aux autres, ou qu'il n'y en a qu'un seul, est cassé et incorrect.

  19. Le code qui suppose que chaque point de code occupe plus d'une colonne d'impression est rompu.

  20. Code qui suppose que tous \p{Mark} caractères occupent zéro colonne d'impression est rompu.

  21. Code qui suppose que les caractères qui se ressemblent sont brisés.

  22. Code qui suppose que les caractères qui ne se ressemblent pas ne le sont pas identiques est cassé.

  23. Code qui suppose qu'il y a une limite au nombre de points de code dans une ligne qu'un seul \X peut correspondre est incorrect.

  24. Un code qui suppose \Xne peut jamais commencer par un\p{Mark} caractère est incorrect.

  25. Le code qui suppose qu'il \Xne peut jamais contenir deux \p{Mark}caractères non est incorrect.

  26. Le code qui suppose qu'il ne peut pas utiliser "\x{FFFF}"est incorrect.

  27. Le code qui suppose un point de code non BMP qui nécessite deux unités de code UTF-16 (de substitution) sera codé en deux caractères UTF-8 distincts, un par unité de code, est incorrect. Ce n'est pas le cas: il code en un seul point de code.

  28. Le code qui transcode UTF ‐ 16 ou UTF ‐ 32 avec les nomenclatures principales en UTF ‐ 8 est rompu s'il place une nomenclature au début de l'UTF-8 résultant. C'est tellement stupide que l'ingénieur devrait se faire enlever les paupières.

  29. Le code qui suppose que le CESU-8 est un codage UTF valide est incorrect. De même, le code qui considère le codage U + 0000 comme"\xC0\x80" UTF-8 est cassé et incorrect. Ces gars-là méritent également le traitement des paupières.

  30. Le code qui suppose que les caractères comme >pointe toujours vers la droite et <pointe toujours vers la gauche est faux - car ils ne le font pas.

  31. Code qui suppose que si vous sortez d'abord un caractère Xpuis un caractère Y, ceux-ci apparaîtront comme XYétant faux. Parfois non.

  32. Le code qui suppose que l'ASCII est assez bon pour écrire correctement l'anglais est stupide, myope, illettré, brisé, mauvais et mauvais. Enlevez leur têtes! Si cela semble trop extrême, nous pouvons faire des compromis: désormais ils ne peuvent taper qu'avec leur gros orteil d'un pied. (Le reste sera scotché.)

  33. Le code qui suppose que tous les \p{Math}points de code sont des caractères visibles est incorrect.

  34. Le code qui suppose \wne contient que des lettres, des chiffres et des traits de soulignement est incorrect.

  35. Le code qui suppose que ^et ~sont des signes de ponctuation est incorrect.

  36. Le code qui suppose qu'il üa un tréma est incorrect.

  37. Le code qui croit que des choses comme contenir des lettres sont incorrectes.

  38. Le code qui croit \p{InLatin}est le même que celui qui \p{Latin}est abominablement brisé.

  39. Code qui croit que \p{InLatin} c'est presque toujours utile est presque certainement faux.

  40. Un code qui croit que donné $FIRST_LETTERcomme première lettre d'un alphabet et $LAST_LETTERcomme dernière lettre de ce même alphabet, qui [${FIRST_LETTER}-${LAST_LETTER}]a une signification quelconque est presque toujours complet, rompu, faux et vide de sens.

  41. Un code qui croit que le nom d'une personne ne peut contenir que certains caractères est stupide, offensant et erroné.

  42. Le code qui tente de réduire Unicode en ASCII n'est pas simplement faux, son auteur ne devrait plus jamais être autorisé à travailler à nouveau en programmation. Période. Je ne suis même pas certain qu'ils devraient même être autorisés à revoir, car cela ne leur a manifestement pas fait beaucoup de bien jusqu'à présent.

  43. Le code qui croit qu'il existe un moyen de prétendre qu'il n'existe aucun encodage de fichier texte est cassé et dangereux. Pourrait aussi bien pousser l'autre œil.

  44. Le code qui convertit les caractères inconnus ?est cassé, stupide, braindead et va à l'encontre de la recommandation standard, qui dit de NE PAS FAIRE CELA! RTFM pour pourquoi pas.

  45. Le code qui croit pouvoir deviner de manière fiable l'encodage d'un fichier texte non marqué est coupable d'un mélange fatal d'orgueil et de naïveté que seul un éclair de Zeus corrigera.

  46. Le code qui croit que vous pouvez utiliser les printflargeurs 🐪 pour remplir et justifier les données Unicode est cassé et incorrect.

  47. Le code qui croit qu'une fois que vous avez réussi à créer un fichier par un nom donné, que lorsque vous exécutez lsou readdirsur son répertoire englobant, vous trouverez réellement que le fichier avec le nom sous lequel vous l'avez créé est bogué, cassé et incorrect. Arrêtez d'être surpris par ça!

  48. Le code qui croit que l'UTF-16 est un encodage à largeur fixe est stupide, cassé et faux. Révoquer leur licence de programmation.

  49. Le code qui traite les points de code d'un avion un peu différemment de ceux de n'importe quel autre avion est ipso facto cassé et faux. Retourne à l'école.

  50. Code qui croit que des choses comme /s/ine peuvent que correspondre "S"ou "s"sont cassées et erronées. Tu serais surpris.

  51. Le code utilisé \PM\pM*pour rechercher des grappes de graphèmes au lieu d'utiliser \Xest cassé et incorrect.

  52. Les personnes qui souhaitent retourner dans le monde ASCII devraient être chaleureusement encouragées à le faire, et en l'honneur de leur glorieuse mise à niveau, elles devraient recevoir gratuitement une machine à écrire manuelle pré-électrique pour tous leurs besoins de saisie de données. Les messages qui leur sont envoyés doivent être envoyés via un télégraphe à 40 caractères par ligne et remis en mains propres par un service de messagerie. ARRÊTEZ.


😱 𝕾 𝖀 𝕸 𝕸 𝕬 𝕽 𝖄 😱


Je ne sais pas combien plus "Unicode par défaut dans 🐪" vous pouvez obtenir que ce que j'ai écrit. Eh bien, oui je le fais: vous devriez utiliser Unicode::CollateetUnicode::LineBreak aussi. Et probablement plus.

Comme vous le voyez, il y a beaucoup trop de choses Unicode que vous avez vraiment n'avoir à se soucier pour qu'il y ait jamais existe une telle chose comme « défaut Unicode ».

Ce que vous allez découvrir, tout comme nous l'avons fait en 🐪 5.8, qu'il est tout simplement impossible d'imposer toutes ces choses à du code qui n'a pas été conçu dès le début pour en tenir compte. Votre égoïsme bien intentionné vient de briser le monde entier.

Et même une fois que vous l'avez fait, il y a encore des problèmes critiques qui nécessitent beaucoup de réflexion pour être correct. Il n'y a aucun interrupteur que vous pouvez actionner. Rien que du cerveau, et je veux dire du vrai cerveau , suffira ici. Il y a beaucoup de choses à apprendre. Modulo la retraite à la machine à écrire manuelle, vous ne pouvez tout simplement pas espérer passer par ignorance. Nous sommes au 21ˢᵗ siècle, et vous ne pouvez pas désirer Unicode par ignorance volontaire.

Vous devez l'apprendre. Période. Il ne sera jamais aussi facile que «tout fonctionne,» car cela garantira que beaucoup de choses ne fonctionnent - ce qui invalide l'hypothèse qu'il peut jamais y avoir un moyen de «faire fonctionner tout cela».

Vous pourrez peut-être obtenir quelques valeurs par défaut raisonnables pour un nombre très limité et très limité d'opérations, mais non sans penser aux choses beaucoup plus que je ne le pense.

À titre d'exemple, l'ordre canonique va provoquer de vrais maux de tête. 😭 "\x{F5}" 'õ' , "o\x{303}" 'õ' , "o\x{303}\x{304}" 'ȭ' et "o\x{304}\x{303}" 'ō̃' devraient tous correspondre à 'õ' , mais comment allez-vous faire cela dans le monde? C'est plus difficile qu'il n'y paraît, mais c'est quelque chose dont vous devez tenir compte. 💣

S'il y a une chose que je sais sur Perl, c'est ce que ses bits Unicode font et ne font pas, et cette chose que je vous promets: "̲ᴛ̲ʜ̲ᴇ̲ʀ̲ᴇ̲ ̲ɪ̲s̲ ̲ɴ̲ᴏ̲ ̲U̲ɴ̲ɪ̲ᴄ̲ᴏ̲ᴅ̲ᴇ̲ ̲ᴍ̲ᴀ̲ɢ̲ɪ̲ᴄ̲ ̲ʙ̲ᴜ̲ʟ̲ʟ̲ᴇ̲ᴛ̲ ̲" 😞

Vous ne pouvez pas simplement modifier certains paramètres par défaut et obtenir une navigation en douceur. Il est vrai que je lance 🐪 avec PERL_UNICODEset to "SA", mais c'est tout, et même c'est surtout pour les choses en ligne de commande. Pour un vrai travail, je passe par toutes les étapes décrites ci-dessus, et je le fais très, ** très ** avec soin.


😈 ¡ƨdləɥ ƨᴉɥʇ ədoɥ puɐ ʻλɐp əɔᴉu ɐ əʌɐɥ ʻʞɔnl poo⅁ 😈

tchrist
la source
56
Comme l'a souligné Sherm Pendley: "Tous!". Si j'écris aujourd'hui quelque chose de nouveau, l'UTF-8 devrait être le moyen le plus simple de faire avancer les choses. Ce n'est pas. Votre passe-partout le prouve. Tout le monde n'a pas une telle connaissance pour tourner autant de gobelets vers les bonnes positions. Je suis désolé, j'ai eu une journée longue et difficile, donc je commenterai dans l'entrée principale demain plus d'exemples.
semaine
17
Une conclusion devrait être évidente à la lecture de la liste ci-dessus: ne pas plier la casse. Mais ne le fais pas. Déjà. Calculs coûteux et avec une sémantique qui dépend de façon cruciale de ce que "locale" essaie sans succès d'identifier.
Tim Bray
72
Suis-je le seul à trouver ironique que cet article de tchrist soit si radicalement différent sur FF / Chrome / IE / Opera, parfois jusqu'à l'illisibilité?
damageboy
15
Bien que j'aime généralement le message et que j'aie voté positivement, une chose me dérange. Il y a beaucoup de "code qui ... est cassé". Bien que je ne conteste pas la déclaration, je pense qu'il serait bon de montrer le bris. De cette façon, il passerait (cette partie de la réponse) d'une diatribe à l'éducation.
36
@xenoterracide Non, je n'ai pas utilisé de points de code intentionnellement problématiques; c'est un complot pour vous permettre d'installer la police Symbola super génial de George Douros , qui couvre Unicode 6.0. 😈 @depesz Il n'y a pas de place ici pour expliquer pourquoi chaque hypothèse cassée est fausse. @leonbloy Beaucoup et beaucoup de ceci s'applique à Unicode en général, pas seulement à Perl. Certains de ces documents peuvent apparaître dans 🐪 Programming Perl 🐪, 4e édition , qui devrait sortir en octobre. 🎃 Il me reste un mois pour ✍ travailler dessus, et Unicode est ᴍᴇɢᴀ là; regexes, aussi
tchrist
96

Le traitement du texte Unicode se déroule en deux étapes. Le premier est "comment puis-je le saisir et le sortir sans perdre d'informations". La seconde est "comment traiter le texte selon les conventions linguistiques locales".

Le message de tchrist couvre les deux, mais la deuxième partie est d'où proviennent 99% du texte de son message. La plupart des programmes ne gèrent même pas les E / S correctement, il est donc important de comprendre cela avant même de commencer à vous soucier de la normalisation et du classement.

Ce message vise à résoudre ce premier problème

Lorsque vous lisez des données dans Perl, peu importe leur encodage. Il alloue de la mémoire et y stocke les octets. Si vous dites print $str, il transfère simplement ces octets à votre terminal, qui est probablement configuré pour supposer que tout ce qui y est écrit est UTF-8, et votre texte apparaît.

Merveilleux.

Sauf que non. Si vous essayez de traiter les données comme du texte, vous verrez que quelque chose de mauvais se produit. Vous n'avez pas besoin d'aller plus loin que lengthde voir que ce que Perl pense de votre chaîne et ce que vous pensez de votre chaîne ne sont pas d'accord. Écrivez une ligne comme: perl -E 'while(<>){ chomp; say length }'et tapez 文字化けet vous obtenez 12 ... pas la bonne réponse, 4.

C'est parce que Perl suppose que votre chaîne n'est pas du texte. Vous devez lui dire que c'est du texte avant qu'il ne vous donne la bonne réponse.

C'est assez simple; le module Encode a les fonctions pour le faire. Le point d'entrée générique estEncode::decode (ouuse Encode qw(decode) bien sûr). Cette fonction prend une chaîne du monde extérieur (ce que nous appellerons "octets", une façon de dire "octets 8 bits"), et la transforme en un texte que Perl comprendra. Le premier argument est un nom de codage de caractères, comme "UTF-8" ou "ASCII" ou "EUC-JP". Le deuxième argument est la chaîne. La valeur de retour est le scalaire Perl contenant le texte.

(Il y a aussi Encode::decode_utf8 , qui suppose UTF-8 pour l'encodage.)

Si nous réécrivons notre one-liner:

perl -MEncode=decode -E 'while(<>){ chomp; say length decode("UTF-8", $_) }'

Nous tapons 文字 化 け et obtenons "4" comme résultat. Succès.

C'est là, la solution à 99% des problèmes Unicode en Perl.

La clé est, chaque fois qu'un texte entre dans votre programme, vous devez le décoder. Internet ne peut pas transmettre de caractères. Les fichiers ne peuvent pas stocker de caractères. Il n'y a aucun personnage dans votre base de données. Il n'y a que des octets et vous ne pouvez pas traiter les octets comme des caractères en Perl. Vous devez décoder les octets encodés en caractères Perl avec le module Encode.

L'autre moitié du problème consiste à extraire des données de votre programme. C'est facile à; vous dites simplement use Encode qw(encode), décidez de l'encodage de vos données (UTF-8 pour les terminaux qui comprennent UTF-8, UTF-16 pour les fichiers sous Windows, etc.), puis encode($encoding, $data)sortez le résultat au lieu de simplement le sortir $data.

Cette opération convertit les caractères de Perl, sur lesquels votre programme fonctionne, en octets pouvant être utilisés par le monde extérieur. Ce serait beaucoup plus facile si nous pouvions simplement envoyer des caractères sur Internet ou à nos terminaux, mais nous ne pouvons pas: octets uniquement. Nous devons donc convertir les caractères en octets, sinon les résultats ne sont pas définis.

Pour résumer: encoder toutes les sorties et décoder toutes les entrées.

Nous allons maintenant parler de trois problèmes qui rendent cela un peu difficile. Le premier est les bibliothèques. Gèrent-ils correctement le texte? La réponse est ... ils essaient. Si vous téléchargez une page Web, LWP vous rendra votre résultat sous forme de texte. Si vous appelez la bonne méthode sur le résultat, c'est-à-dire (et il se trouve que decoded_contentnon content, qui n'est que le flux d'octets qu'il a obtenu du serveur.) Les pilotes de base de données peuvent être floconneux; si vous utilisez DBD :: SQLite avec seulement Perl, cela fonctionnera, mais si un autre outil a mis du texte stocké sous forme d'encodage autre que UTF-8 dans votre base de données ... eh bien ... ça ne sera pas géré correctement jusqu'à ce que vous écriviez du code pour le gérer correctement.

La sortie des données est généralement plus facile, mais si vous voyez "caractère large en caractères d'imprimerie", alors vous savez que vous gâchez l'encodage quelque part. Cet avertissement signifie "hé, vous essayez de divulguer des caractères Perl au monde extérieur et cela n'a aucun sens". Votre programme semble fonctionner (car l'autre extrémité gère généralement correctement les caractères Perl bruts), mais il est très endommagé et peut cesser de fonctionner à tout moment. Fixez-le avec un explicite Encode::encode!

Le deuxième problème est le code source codé UTF-8. Sauf si vous le dites use utf8en haut de chaque fichier, Perl ne supposera pas que votre code source est UTF-8. Cela signifie que chaque fois que vous dites quelque chose comme my $var = 'ほげ', vous injectez des déchets dans votre programme qui vont tout casser horriblement. Vous n'avez pas à "utiliser utf8", mais si vous ne le faites pas, vous ne devez pas utiliser de caractères non ASCII dans votre programme.

Le troisième problème est de savoir comment Perl gère le passé. Il y a longtemps, Unicode n'existait pas et Perl supposait que tout était du texte latin-1 ou binaire. Ainsi, lorsque des données arrivent dans votre programme et que vous commencez à les traiter comme du texte, Perl traite chaque octet comme un caractère Latin-1. C'est pourquoi, lorsque nous avons demandé la longueur de "文字 化 け", nous en avons obtenu 12. Perl a supposé que nous fonctionnions sur la chaîne latine-1 "æååã" (qui est de 12 caractères, dont certains ne sont pas imprimés).

C'est ce qu'on appelle une «mise à niveau implicite», et c'est une chose parfaitement raisonnable à faire, mais ce n'est pas ce que vous voulez si votre texte n'est pas Latin-1. C'est pourquoi il est essentiel de décoder explicitement l'entrée: si vous ne le faites pas, Perl le fera, et il pourrait le faire mal.

Les gens rencontrent des problèmes lorsque la moitié de leurs données est une chaîne de caractères appropriée et que certaines sont encore binaires. Perl interprétera la partie qui est encore binaire comme s'il s'agissait de texte Latin-1, puis la combinera avec les données de caractères correctes. Cela donnera l'impression que la gestion correcte de vos personnages a interrompu votre programme, mais en réalité, vous ne l'avez pas suffisamment corrigé.

Voici un exemple: vous avez un programme qui lit un fichier texte encodé en UTF-8, vous clouez un Unicode PILE OF POOsur chaque ligne et vous l'imprimez. Vous l'écrivez comme:

while(<>){
    chomp;
    say "$_ 💩";
}

Et puis exécutez sur certaines données encodées UTF-8, comme:

perl poo.pl input-data.txt

Il imprime les données UTF-8 avec un caca à la fin de chaque ligne. Parfait, mon programme fonctionne!

Mais non, vous faites juste une concaténation binaire. Vous lisez des octets du fichier, supprimez un \navec chomp, puis clouez sur les octets dans la représentation UTF-8 du PILE OF POOpersonnage. Lorsque vous révisez votre programme pour décoder les données du fichier et encoder la sortie, vous remarquerez que vous obtenez des ordures ("ð ©") au lieu du caca. Cela vous amènera à croire que le décodage du fichier d'entrée n'est pas la bonne chose à faire. Ce n'est pas.

Le problème est que le caca est implicitement mis à niveau en latin-1. Si vous use utf8faites le texte littéral au lieu de binaire, alors cela fonctionnera à nouveau!

(C'est le problème numéro un que je vois en aidant les gens avec Unicode. Ils se sont bien débrouillés et cela a cassé leur programme. C'est ce qui est triste avec des résultats indéfinis: vous pouvez avoir un programme de travail pendant longtemps, mais quand vous commencez à le réparer, ne vous inquiétez pas; si vous ajoutez des instructions d'encodage / décodage à votre programme et qu'il se casse, cela signifie simplement que vous avez plus de travail à faire. La prochaine fois, lorsque vous concevrez avec Unicode à l'esprit depuis le début, ce sera beaucoup plus facile!)

C'est vraiment tout ce que vous devez savoir sur Perl et Unicode. Si vous dites à Perl quelles sont vos données, elles ont le meilleur support Unicode parmi tous les langages de programmation populaires. Si vous supposez qu'il saura comme par magie quel type de texte vous l'alimentez, alors vous allez détruire vos données de manière irrévocable. Ce n'est pas parce que votre programme fonctionne aujourd'hui sur votre terminal UTF-8 qu'il fonctionnera demain sur un fichier encodé UTF-16. Alors sécurisez-le maintenant et évitez le casse-tête de mettre à la poubelle les données de vos utilisateurs!

La partie facile de la gestion d'Unicode est l'encodage de la sortie et le décodage de l'entrée. La partie difficile consiste à trouver toutes vos entrées et sorties, et à déterminer de quel encodage il s'agit. Mais c'est pourquoi vous obtenez le gros lot :)

jrockway
la source
Le principe est bien expliqué, mais l'approche pratique pour les E / S fait défaut. L'utilisation explicite du Encodemodule est fastidieuse et sujette aux erreurs, et cela rend la lecture du code concernant les E / S vraiment pénible. Les couches d'E / S offrent une solution car elles encodent et décodent de manière transparente, le cas échéant. openet binmodepermettre leur spécification, et pragma opendéfinit les valeurs par défaut, comme le recommande tchrist dans sa réponse.
Palec
48

Nous sommes tous d'accord pour dire que c'est un problème difficile pour de nombreuses raisons, mais c'est précisément la raison pour essayer de le rendre plus facile pour tout le monde.

Il existe un module récent sur CPAN, utf8 :: all , qui tente de "mettre en marche Unicode. Tout cela".

Comme cela a été souligné, vous ne pouvez pas par magie faire en sorte que l'ensemble du système (programmes externes, requêtes Web externes, etc.) utilise également Unicode, mais nous pouvons travailler ensemble pour créer des outils sensés qui facilitent la résolution des problèmes courants. C'est la raison pour laquelle nous sommes programmeurs.

Si utf8 :: all ne fait pas quelque chose que vous pensez qu'il devrait, améliorons-le pour l'améliorer. Ou créons des outils supplémentaires qui, ensemble, peuvent répondre au mieux aux besoins variés des gens.

"

Randy Stauner
la source
5
Je vois beaucoup de place pour l'amélioration dans le utf8::allmodule cité . Il a été écrit avant la unicode_stringsfonctionnalité, que Fɪɴᴀʟʟʏ ᴀɴᴅ ᴀᴛ Lᴏɴɢ Lᴀsᴛ corrige pour les regexes /u. Je ne suis pas convaincu que cela soulève une exception sur les erreurs de codage, et c'est quelque chose que vous devez vraiment avoir. Il ne se charge pas dans le use charnames ":full"pragma, qui n'est pas encore chargé automatiquement. Il ne met pas en garde contre [a-z]et telles, printfles largeurs de chaîne, en utilisant \nau lieu de \Ret .au lieu de \X, mais c'est peut-être plus une Perl::Criticquestion. Si c'était moi, j'ajouterais 𝐍𝐅𝐃 et 𝐍𝐅𝐂 dehors.
tchrist
13
@tchrist Le suivi des problèmes pour utf8 :: all est ici. github.com/doherty/utf8-all/issues Ils adoreraient entendre vos suggestions.
Schwern
4
@Schwern: ᴇɴᴏᴛᴜɪᴛs, mais n'hésitez pas à dérober et à pincer les choses que j'ai écrites ici. Pour être honnête, je ressens / apprends toujours ce qui peut être fait par rapport à ce qui devrait être fait, et où. Voici un bel exemple de déchargeant de tri: unichars -gs '/(?=\P{Ll})\p{Lower}|(?=\P{Lu})\p{Upper}/x' | ucsort --upper | cat -n | less -r. De même, les petites étapes de prétraitement comme ... | ucsort --upper --preprocess='s/(\d+)/sprintf "%#012d", $1/ge'peuvent être très bien aussi, et je ne voudrais pas prendre les décisions des autres à leur place. Je construis toujours ma boîte à outils Unicode .
tchrist
35

Je pense que vous comprenez mal Unicode et sa relation avec Perl. Peu importe la façon dont vous stockez les données, Unicode, ISO-8859-1 , ou bien d'autres choses, votre programme doit savoir comment interpréter les octets qu'il reçoit en entrée (décodage) et comment représenter les informations qu'il souhaite produire (codage ). Obtenez cette interprétation erronée et vous brouillez les données. Il n'y a pas de configuration par défaut magique à l'intérieur de votre programme qui va dire aux choses en dehors de votre programme comment agir.

Vous pensez que c'est difficile, très probablement, parce que vous êtes habitué à tout ce qui est ASCII. Tout ce à quoi vous auriez dû penser a été tout simplement ignoré par le langage de programmation et toutes les choses avec lesquelles il devait interagir. Si tout n'utilisait que de l'UTF-8 et que vous n'aviez pas le choix, alors l'UTF-8 serait tout aussi simple. Mais tout n'utilise pas UTF-8. Par exemple, vous ne voulez pas que votre handle d'entrée pense qu'il obtient des octets UTF-8 à moins qu'il ne le soit réellement, et vous ne voulez pas que vos poignées de sortie soient UTF-8 si la chose qui les lit peut gérer UTF-8 . Perl n'a aucun moyen de savoir ces choses. Voilà pourquoi vous êtes le programmeur.

Je ne pense pas qu'Unicode dans Perl 5 soit trop compliqué. Je pense que c'est effrayant et les gens l'évitent. Il y a une différence. À cette fin, j'ai mis Unicode dans Learning Perl, 6th Edition , et il y a beaucoup de choses Unicode dans la programmation Perl efficace . Vous devez passer du temps pour apprendre et comprendre Unicode et son fonctionnement. Sinon, vous ne pourrez pas l'utiliser efficacement.

brian d foy
la source
3
Je pense que vous avez un point: c'est effrayant. Devrait-ce être? Pour moi, c'est la bénédiction Unicode, son utilisation en Perl5 ne l'est pas (je ne suppose pas que quoi que ce soit soit ASCII, ma langue maternelle a besoin d'au moins iso8859-4). J'ai installé Rakudo et tout ce que j'ai essayé avec UTF-8 (dans ce bac à sable limité) a fonctionné hors de la boîte. Ai-je oublié quelque chose? Je le souligne à nouveau: il est bon d'avoir un support Unicode affiné, mais la plupart du temps, cela n'est pas nécessaire. Pour éloigner la peur du sujet, une façon est que tout le monde lit beaucoup pour comprendre les internes. Autre: nous avons un pragma spécial qui use utf8_everywhererend les gens heureux. Pourquoi pas le dernier?
semaine
3
Je pense toujours que vous manquez le point. Qu'est-ce qui a fonctionné? Vous n'avez pas besoin de comprendre les internes. Vous devez comprendre les éléments externes et savoir comment gérer les chaînes qui ont différents encodages et différentes représentations des mêmes caractères. Lisez à nouveau les conseils de Tom. La plupart de ce qu'il dit, je parie que vous trouverez que Rakudo ne gère pas pour vous.
brian d foy
1
@wk: relisez la réponse de Randy. Il vous a déjà dit quelles sont les limites.
brian d foy
2
@brian d foy: je pense que ces limitations sont très bien, comme le dit tchrist, il n'y a pas de solution miracle pour chaque aspect (j'avoue: je n'en ai pas vu la plupart avant de poser cette question ici). Donc, lorsque nous couvrons beaucoup de choses de base avec quelque chose comme utf8 :: all, tout le monde n'a pas besoin de construire son propre passe-partout énorme pour que les bases de la gestion de utf8 fonctionnent. Avec "aucune peur du tout", je veux dire: tout le monde peut commencer ses projets en sachant que les bases sont couvertes. Oui, vous avez raison, il y a encore beaucoup de problèmes. Mais lorsque le démarrage est plus facile, nous aurons plus de personnes impliquées dans la résolution de ces problèmes. IMHO
sem
1
@wk - le seul "mauvais" avec "utf8: all" ou "uni :: perl n'est qu'un - ils ne sont pas dans le CORE - donc tout le monde doit l'installer depuis le CPAN. Et si vous pensez que ce n'est pas un gros deal - repensez s'il vous plaît - oui, il est plus facile d'utiliser utf8 avec un module d'assistance. Sans lui, le CORE perl a toujours le support unicode - mais beaucoup beaucoup compliqué. Et c'est faux.
jm666
28

En lisant ce fil, j'ai souvent l'impression que les gens utilisent " UTF-8 " comme synonyme de " Unicode ". Veuillez faire une distinction entre les "points de code" d'Unicode qui sont un parent élargi du code ASCII et les différents "encodages" d'Unicode. Et il y en a quelques-uns, dont UTF-8, UTF-16 et UTF-32 sont les actuels et quelques autres sont obsolètes.

S'il vous plaît, UTF-8 (ainsi que tous les autres encodages ) existe et n'a de sens qu'en entrée ou en sortie uniquement. En interne, depuis Perl 5.8.1, toutes les chaînes sont conservées en tant que «points de code» Unicode. Certes, vous devez activer certaines fonctionnalités comme précédemment admirablement couvertes.

MeirG
la source
19
Je suis d'accord que les gens confondent trop souvent Uɴɪᴄᴏᴅᴇ avec UTF-8⧸16⧸32, mais il n'est fondamentalement et absolument pas vrai que Uɴɪᴄᴏᴅᴇ n'est qu'un jeu de caractères élargi par rapport à ᴀsᴄɪɪ. Tout au plus, ce n'est rien d'autre que le simple ɪsᴏ ‑ 10646 . Uɴɪᴄᴏᴅᴇ comprend bien plus : règles de classement, de casfolding, de formulaires de normalisation, de grappes de graphèmes, de saut de mots et de lignes, de scripts, d'équivs numériques, de largeurs, de bidirectionnalité, de variantes de glyphes, de comportement contextuel, de paramètres régionaux, de regex, de combinaisons de classes, de centaines de propriétés, & beaucoup plus‼
tchrist
15
@tchrist: la première étape consiste à introduire des données dans votre programme et à les diffuser dans le monde extérieur sans les jeter. alors vous pouvez vous soucier de l'assemblage, du pliage du boîtier, des variantes de glyphes, etc.
jrockway
7
Je suis d'accord, obtenir que perl ne supprime pas l'entrée ou la sortie de la corbeille doit être la première priorité. Ce que j'aimerais, c'est avoir un module ou un pragma qui pourrait incarner la conversation fictive suivante: "- Cher Perl. Pour ce programme, toutes les entrées et sorties seront exclusivement en UTF-8. Pourriez-vous s'il vous plaît ne pas jeter mes données? - Donc, seulement vous dites UFT-8. Êtes-vous sûr? - Oui. - Vraiment, vraiment sûr? - Absolument. - Et vous acceptez que je puisse me comporter étrangement si des données non UTF-8 me sont fournies? - Oui, très bien. - Alors ok."
hlovdal
10

Il y a une quantité vraiment horrible de code ancien dans la nature, en grande partie sous la forme de modules CPAN communs. J'ai constaté que je dois être assez prudent en activant Unicode si j'utilise des modules externes qui pourraient être affectés par celui-ci, et j'essaie toujours d'identifier et de corriger certaines défaillances liées à Unicode dans plusieurs scripts Perl que j'utilise régulièrement (en particulier, iTiVo échoue mal sur tout ce qui n'est pas ASCII 7 bits en raison de problèmes de transcodage).

geekosaure
la source
Je voulais dire utiliser l' -Coption pour m'assurer que Perl est sur la même page que je suis en Unicode, car je continue de le faire décider d'utiliser ISO 8859/1 au lieu d'Unicode même si je le configure explicitement $LANGet $LC_ALLcorrectement. (Cela peut en fait refléter des bogues dans les bibliothèques de paramètres régionaux de la plate-forme.) Quoi qu'il en soit, il est très ennuyeux de ne pas pouvoir utiliser iTivo sur des programmes avec des accents, car les scripts Perl qui font le travail tombent avec des erreurs de conversion.
geekosaur
3
Un seul -Csans options est bogué et sujet aux erreurs . Vous brisez le monde. Réglez l' PERL5OPTenvariable sur -Cet vous verrez ce que je veux dire. Nous avons essayé de cette façon dans la version 5.8, et ce fut un désastre. Vous ne pouvez tout simplement pas et ne devez pas dire aux programmes qui ne s'y attendent pas qu'ils traitent maintenant avec Unicode, qu'ils le veuillent ou non. Il y a aussi des problèmes de sécurité. À tout le moins, tout ce qui print while <>se cassera si des données binaires sont transmises. Il en sera de même pour tout le code de la base de données. C'est une terrible idée.
tchrist
1
Je parlais de façon générique, en fait, pas spécifiquement -Csans options. L'invocation spécifique avec laquelle je travaillais était -CSDA. Cela dit, j'ai été bloqué avec 5.8.x pendant longtemps (bonjour MacPorts ...), alors peut-être que cela en faisait partie.
geekosaur
1
Je cours avec PERL_UNICODE réglé sur SA. Vous NE POUVEZ PAS le régler sur D.
tchrist
@tchrist: Certains varmint Perl ont publié un code montrant l'utilisation de -CSDA et PERL_UNICODE = SDA . Veuillez utiliser votre influence dans la communauté. Il doit être arrêté!
Ashley
1

Vous devez activer la fonction de chaînes unicode, et c'est la valeur par défaut si vous utilisez la v5.14;

Vous ne devriez pas vraiment utiliser les identifiants unicode esp. pour le code étranger via utf8 car ils ne sont pas sécurisés en perl5, seul cperl a obtenu ce droit. Voir par exemple http://perl11.org/blog/unicode-identifiers.html

Concernant utf8 pour vos descripteurs de fichiers / flux: vous devez décider vous-même de l'encodage de vos données externes. Une bibliothèque ne peut pas le savoir, et comme même libc ne prend pas en charge utf8, les données utf8 appropriées sont rares. Il y a plus de wtf8, l'aberration des fenêtres d'utf8.

BTW: Moose n'est pas vraiment "Modern Perl", ils ont juste détourné le nom. Moose est parfait Perl postmoderne de style Larry Wall mélangé à tout le style Bjarne Stroustrup, avec une aberration éclectique de la syntaxe perl6 appropriée, par exemple en utilisant des chaînes pour les noms de variable, une syntaxe de champs horrible et une implémentation naïve très immature qui est 10x plus lente qu'une bonne mise en œuvre. cperl et perl6 sont les véritables perls modernes, où la forme suit la fonction, et l'implémentation est réduite et optimisée.

rurban
la source