C'est marrant, j'ai exactement l'avis opposé. Je trouve beaucoup plus intuitif de faire obj.methode() pour une action que func(obj).
Mon commentaire, n'était pas pour ajouter des méthodes à std::string, mais pour dire que l'interface initiale est pourrie, car trop basée, comme pour les premières classes de la STL, sur des idées 1980 (code ASCII 8bits, tout le monde parle anglais, etc…), et pas assez sur l'utilisation de l'objet lui-même. Dans la réalité des codes utilisant du std::string que j'ai lu (et j'en lis beaucoup), 99.9% du temps, les indices sont inutiles, plein de bugs, etc…
L'exemple le plus flagrant, c'est lorsque je dois faire l'i18n d'une appli C++. Le développeur ne sait pas (ou a "oublié") qu'il travaillait avec de l'UTF-8, et estime, à tort que l'index d'un caractère est égal à sa position en mémoire. Avec une interface sans index à gérer, il n'y a aucun soucis. Avec std::string, c'est l'horreur. Avec une classe utilisant le pattern "from_first", "upto_last", etc, ça roule tout seul.
Traduire le code des iostreams c'est aussi une autre hérésie qui n'aurait jamais dû survivre à plus d'un standard. Le grand classique, que j'ai vu à de nombreuses reprises, c'est "cout << "There is " << animal_count << " pet" << animal_count ? 's' : '\0' << " in the store."<< endl;
En général, là, le code est à réécrire (grand moment de solitude). Franchement, séparer la présentation des données, même le C le faisait en 89 avec printf et gettext, le C++ n'y est toujours pas (il y a boost::format mais bon… boost quoi…).
De plus, l'interface des string aurait due être séparée en "méthodes" non modifiantes, "méthodes modifiantes", quitte à faire une classe "readonly_string" qui permette les recherches, les modifications de taille (ou du pointeur de début de chaîne) mais pas du contenu de la chaîne (bref: tout ce qui est requis pour parser du texte), et une classe "writeable_string" pour le reste, en ayant un héritage multiple des deux interfaces dans ce qui s'appelle la classe string. Du coup, la problématique du COW disparaît automatiquement suivant que l'on veuille en payer le prix ou non (pour le parsing, par exemple, pas de COW pour du RO).
C'est sûr, alors qu'une bonne expression régulière aurait fait des miracles en un seul appel.
Ceci dit, le pattern Fluent est vraiment agréable à utiliser (pour ceux qui font du JQuery, lodash, etc… par exemple, impossible de penser autrement maintenant).
Le vrai problème du code ci dessus vient de la signature de la fonction replace qui modifie la chaîne au lieu de retourner une nouvelle string. Si cela avait été le cas, alors l'ordre d'appel, on s'en balance. Avec un replace immutable, alors il faut, logiquement faire la recherche de la sous chaîne par la fin pour garantir que les modifications soient appliquées au bon endroit.
Mais au final, on retombe encore sur les signatures bancales de la classe string, qui ne propose qu'un nombre limité de méthodes (au nom d'une simplification de l'implémentation STL, mais qui, en pratique, force chaque projet à réimplémenter les fonctions de bases avec tous les bugs que ça impliquent). Un string replace(const string & this, const string & by_that) serait alors bien plus simple et dans la majorité des cas (le reste, c'est faisable par un erase + insert). De même pour tout ce qui est basé sur des index en fait, dans la majorité des cas, c'est inutile et vraiment pénible dès lors que l'on fait du UTF-8.
Un code comme ceci est bien plus compréhensible:
String s = "The blue cat doesn't like the yellow dog";
return s.replace("yellow", "blue").replace("blue", "yellow").replace("dog", "cat").replace("cat", "dog");
// Autre exemple, plus concret
String get_authority(const String & url) {
// Exemple: url = "http://whatever.org/path/to/index.html";
return url.from_first("://").to_first("/");
}
Le deuxième exemple, montre que, même si en interne la classe utilise des index pour trouver les sous chaînes, ils ne sont pas visibles dans la signature des méthodes, et donc c'est carrément plus intuitif. Côté performance, avec du COW, c'est mieux que du code à base de find & replace, vu qu'il ne faut plus "sortir" les index de la stack dans les fonctions supérieures, une seule fonction appelée, moins de registres utilisés et donc, au final, tourne beaucoup plus vite.
Visiblement, vous n'avez pas fait votre travail de googlemineur!
Blagues à part, pour avoir une synthèse qui ne fasse plus so 1980, la meilleure solution actuelle est Voxygen ou NeoSpeech en anglais.
Pour l'utiliser sous Linux, il y a 2 solutions.
La première solution, sur un linux basé sur Arm ou x86, c'est d'acheter le package Android à 3€ et d'utiliser la librairie qui va bien pour porter les API android sur un Linux normal (type libhybris).
L'autre solution, à 39€, c'est d'utiliser les voix Best-Of-Vox de Voxygen, via Wine (c'est le plus simple) mais c'est limité à x86.
Voir ce blog pour le "HOW-TO". Cette dernière solution fonctionne avec Speech-dispatcher.
Et puis, il y a aussi MaryTTS qui est une référence (non listée dans la liste des moteurs de synthèse) et qui s'améliore de mois en mois (qui a 3 voix en français).
Et Cereproc qui est la solution la plus ouverte sous linux (ça coûte 79€ si je me rappelle bien), mais il faut programmer pour l'utiliser (ce qui est un avantage pour moi, mais pas pour ceux qui veulent du "speech-dispatcher" compatible)
Pour conclure, aujourd'hui, ce qui limite la qualité de la voix de synthèse, c'est le manque de matériel audio correctement taggué pour pouvoir faire du "unit selection" (meilleure technologie actuelle). Ça demande un temps très important, et c'est pourquoi nous n'avons pas de modèle en Français gratuit et libre. Franchement, vu la qualité d'un Cereproc ou Voxygen (cocorico), pour le prix, j'hésite pas une seconde, je préfère passer mon temps à coder que d'enregistrer 50h d'audio à tagguer manuellement pour sortir un modèle qui sonne bien.
Posté par xryl669 .
En réponse à la dépêche Firefox : version 38.
Évalué à 5.
Dernière modification le 13 mai 2015 à 19:05.
"Bref, une majorité de fautes typiques de tout développeur en C++."
Bravo!
Sauf que…
En fait, il n'y a aucun rapport. Les problèmes énoncés sont n'ont rien à voir avec le langage de programmation.
En quoi l'interprète JS utilisé pour "recompiler" le code JS asm.js en code natif a un rapport avec le langage utilisé ?
Il pourrait être écrit en Java / brainfuck, c'est le "code compilé généré" qui est fautif, donc l'algorithme, et pas le langage.
Le lien CSS et SVG non plus (qui est en C et pas C++), l'XML compressé qui est probablement dans zlib (en C), ou les metadata du MP4 (Vala? asm ?) bref…
Du C++ bashing de base, sans fondement, dommage, c'est raté, la prochaine fois, peut-être ?
Pour information, tout projet sérieux (qui se dit l'être) utilise des vérificateurs statiques (AddressSanetizer / Clangtidy) et dynamiques (Valgrind), Firefox n'y faisant pas exception. Et ce n'est pas parce que il est écrit en C++ que c'est nécessaire (d'ailleurs, les mêmes vérificateurs sont utilisés pour des programme qui utilise du Ruby, du Fortran, du Python, du Vala, etc..), parce que on ne vit plus dans sa bulle, on linke avec des libraries écrites dans d'autres langages et que les erreurs mémoires arrivent dues à une mauvaise compréhension des API de ses librairies.
Bref, ce commentaire réduit l'intérêt de l'article, et montre le sérieux des préjugés de l'auteur.
Moi, je ne le comprends pas comme ça. Je comprends qu'il ne faut pas supprimer le logo Onlyoffice pour y mettre le tien. Rien ne t'interdit de changer le code pour faire l'interface que tu veux (y compris, déplacer ou supprimer le champ contenant le logo), du moment que tu ne t'appropries pas la marque et que tu laisses, quelque part dans ton interface (même dans une boite "à propos") le logo original d'Onlyoffice.
C'est de AGPL3, une sorte de GPL qui t'oblige à garder la source, un peu comme Flowplayer, Pydio etc… Après, on s'habitue vite à des licenses sans aucune contrepartie, mais vue l'ampleur du travail réalisé, je trouve juste de leur accorder un minimum de respect/hommage.
Tu dis: "Le correcteur ne sait pas où chercher une conjugaison adéquate. Pour parfaire le système de suggestion, il faudrait établir des passerelles entre tous les mots grammaticalement distincts sur leurs liens phonétiques éventuels."
Il me semble qu'il existe dans les entrées du dictionnaire un représentation phonétique de chaque mot (sinon, ces dictionnaires existent en opensource, par exemple chez eSpeak pour la synthèse vocale, LLIUM pour la reconnaissance vocale, etc…).
Du coup, en ajoutant une n-ième passe au préprocesseur (lors de la détection d'une erreur), qui aurait pour entrée l'index des mots en "phonétique" qui, par définition est un mapping 1:n, pourrait lors d'un mot incongru (Il s'en "fou"), chercher si un des résultats pour l'entrée phonétique "fu" pourrait convenir. Dans ce cas aussi simple, il trouverait immédiatement le verbe conjugué, et n'aurait plus qu'à choisir la bonne conjugaison parmi "fous, fout".
Après, avec un TernarySearchTree indexé sur les clés phonétiques, on pourrait même envisager une recherche approximative (type Levenshtein, distance de Hamming) pour trouver des mots dont la phonétique est "proche" de l'item erroné - Cela ne donnerait pas de faux positif puisque ceci démarrerait uniquement sur détection d'une erreur, tel qu'actuellement. On est alors clairement dans l'aide à l'utilisateur, au lieu de détecter une erreur et de ne pas savoir quoi suggérer, on pourrait envisager un menu "Ils son faux." => "son" est erroné, vouliez vous dire "sont", "sonnent" etc…
Concernant "Il est aller à la mairie", je pense qu'une dernière passe de pre-processing utilisant la technique des n-gram, (c'est à dire la découpe en entités de 3/4 lettres), puis comparaison avec un modèle statistique du langage (tel que fournis par Google en opensource), repèrerait l'incongruité statistique de la suite "est aller". C'est ce que fait Google pour ses suggestions de correction de recherche. Il faut définir des seuils (donc risque de faux positifs) quitte à laisser le seuil à 0 par défaut et laisser les utilisateurs aventureux à monter le seuil.
[^] # Re: Erreur de livre et experts C++
Posté par xryl669 . En réponse à la dépêche C++17 fixe l’ordre d’évaluation des expressions. Évalué à 4.
C'est marrant, j'ai exactement l'avis opposé. Je trouve beaucoup plus intuitif de faire obj.methode() pour une action que func(obj).
Mon commentaire, n'était pas pour ajouter des méthodes à std::string, mais pour dire que l'interface initiale est pourrie, car trop basée, comme pour les premières classes de la STL, sur des idées 1980 (code ASCII 8bits, tout le monde parle anglais, etc…), et pas assez sur l'utilisation de l'objet lui-même. Dans la réalité des codes utilisant du std::string que j'ai lu (et j'en lis beaucoup), 99.9% du temps, les indices sont inutiles, plein de bugs, etc…
L'exemple le plus flagrant, c'est lorsque je dois faire l'i18n d'une appli C++. Le développeur ne sait pas (ou a "oublié") qu'il travaillait avec de l'UTF-8, et estime, à tort que l'index d'un caractère est égal à sa position en mémoire. Avec une interface sans index à gérer, il n'y a aucun soucis. Avec std::string, c'est l'horreur. Avec une classe utilisant le pattern "from_first", "upto_last", etc, ça roule tout seul.
Traduire le code des iostreams c'est aussi une autre hérésie qui n'aurait jamais dû survivre à plus d'un standard. Le grand classique, que j'ai vu à de nombreuses reprises, c'est
"cout << "There is " << animal_count << " pet" << animal_count ? 's' : '\0' << " in the store."<< endl;
En général, là, le code est à réécrire (grand moment de solitude). Franchement, séparer la présentation des données, même le C le faisait en 89 avec printf et gettext, le C++ n'y est toujours pas (il y a boost::format mais bon… boost quoi…).
De plus, l'interface des string aurait due être séparée en "méthodes" non modifiantes, "méthodes modifiantes", quitte à faire une classe "readonly_string" qui permette les recherches, les modifications de taille (ou du pointeur de début de chaîne) mais pas du contenu de la chaîne (bref: tout ce qui est requis pour parser du texte), et une classe "writeable_string" pour le reste, en ayant un héritage multiple des deux interfaces dans ce qui s'appelle la classe string. Du coup, la problématique du COW disparaît automatiquement suivant que l'on veuille en payer le prix ou non (pour le parsing, par exemple, pas de COW pour du RO).
[^] # Re: Erreur de livre et experts C++
Posté par xryl669 . En réponse à la dépêche C++17 fixe l’ordre d’évaluation des expressions. Évalué à 5.
C'est sûr, alors qu'une bonne expression régulière aurait fait des miracles en un seul appel.
Ceci dit, le pattern Fluent est vraiment agréable à utiliser (pour ceux qui font du JQuery, lodash, etc… par exemple, impossible de penser autrement maintenant).
Le vrai problème du code ci dessus vient de la signature de la fonction replace qui modifie la chaîne au lieu de retourner une nouvelle string. Si cela avait été le cas, alors l'ordre d'appel, on s'en balance. Avec un replace immutable, alors il faut, logiquement faire la recherche de la sous chaîne par la fin pour garantir que les modifications soient appliquées au bon endroit.
Mais au final, on retombe encore sur les signatures bancales de la classe string, qui ne propose qu'un nombre limité de méthodes (au nom d'une simplification de l'implémentation STL, mais qui, en pratique, force chaque projet à réimplémenter les fonctions de bases avec tous les bugs que ça impliquent). Un string replace(const string & this, const string & by_that) serait alors bien plus simple et dans la majorité des cas (le reste, c'est faisable par un erase + insert). De même pour tout ce qui est basé sur des index en fait, dans la majorité des cas, c'est inutile et vraiment pénible dès lors que l'on fait du UTF-8.
Un code comme ceci est bien plus compréhensible:
String s = "The blue cat doesn't like the yellow dog";
return s.replace("yellow", "blue").replace("blue", "yellow").replace("dog", "cat").replace("cat", "dog");
// Autre exemple, plus concret
String get_authority(const String & url) {
// Exemple: url = "http://whatever.org/path/to/index.html";
return url.from_first("://").to_first("/");
}
Le deuxième exemple, montre que, même si en interne la classe utilise des index pour trouver les sous chaînes, ils ne sont pas visibles dans la signature des méthodes, et donc c'est carrément plus intuitif. Côté performance, avec du COW, c'est mieux que du code à base de find & replace, vu qu'il ne faut plus "sortir" les index de la stack dans les fonctions supérieures, une seule fonction appelée, moins de registres utilisés et donc, au final, tourne beaucoup plus vite.
# C'est cher, et tout pourri.
Posté par xryl669 . En réponse à la dépêche GNU/Linux s’ouvre à de nouvelles voix de synthèse !. Évalué à 6.
Visiblement, vous n'avez pas fait votre travail de googlemineur!
Blagues à part, pour avoir une synthèse qui ne fasse plus so 1980, la meilleure solution actuelle est Voxygen ou NeoSpeech en anglais.
Pour l'utiliser sous Linux, il y a 2 solutions.
La première solution, sur un linux basé sur Arm ou x86, c'est d'acheter le package Android à 3€ et d'utiliser la librairie qui va bien pour porter les API android sur un Linux normal (type libhybris).
L'autre solution, à 39€, c'est d'utiliser les voix Best-Of-Vox de Voxygen, via Wine (c'est le plus simple) mais c'est limité à x86.
Voir ce blog pour le "HOW-TO". Cette dernière solution fonctionne avec Speech-dispatcher.
Et puis, il y a aussi MaryTTS qui est une référence (non listée dans la liste des moteurs de synthèse) et qui s'améliore de mois en mois (qui a 3 voix en français).
Et Cereproc qui est la solution la plus ouverte sous linux (ça coûte 79€ si je me rappelle bien), mais il faut programmer pour l'utiliser (ce qui est un avantage pour moi, mais pas pour ceux qui veulent du "speech-dispatcher" compatible)
Pour conclure, aujourd'hui, ce qui limite la qualité de la voix de synthèse, c'est le manque de matériel audio correctement taggué pour pouvoir faire du "unit selection" (meilleure technologie actuelle). Ça demande un temps très important, et c'est pourquoi nous n'avons pas de modèle en Français gratuit et libre. Franchement, vu la qualité d'un Cereproc ou Voxygen (cocorico), pour le prix, j'hésite pas une seconde, je préfère passer mon temps à coder que d'enregistrer 50h d'audio à tagguer manuellement pour sortir un modèle qui sonne bien.
# Développeur en C++
Posté par xryl669 . En réponse à la dépêche Firefox : version 38. Évalué à 5. Dernière modification le 13 mai 2015 à 19:05.
"Bref, une majorité de fautes typiques de tout développeur en C++."
Bravo!
Sauf que…
En fait, il n'y a aucun rapport. Les problèmes énoncés sont n'ont rien à voir avec le langage de programmation.
En quoi l'interprète JS utilisé pour "recompiler" le code JS asm.js en code natif a un rapport avec le langage utilisé ?
Il pourrait être écrit en Java / brainfuck, c'est le "code compilé généré" qui est fautif, donc l'algorithme, et pas le langage.
Le lien CSS et SVG non plus (qui est en C et pas C++), l'XML compressé qui est probablement dans zlib (en C), ou les metadata du MP4 (Vala? asm ?) bref…
Du C++ bashing de base, sans fondement, dommage, c'est raté, la prochaine fois, peut-être ?
Pour information, tout projet sérieux (qui se dit l'être) utilise des vérificateurs statiques (AddressSanetizer / Clangtidy) et dynamiques (Valgrind), Firefox n'y faisant pas exception. Et ce n'est pas parce que il est écrit en C++ que c'est nécessaire (d'ailleurs, les mêmes vérificateurs sont utilisés pour des programme qui utilise du Ruby, du Fortran, du Python, du Vala, etc..), parce que on ne vit plus dans sa bulle, on linke avec des libraries écrites dans d'autres langages et que les erreurs mémoires arrivent dues à une mauvaise compréhension des API de ses librairies.
Bref, ce commentaire réduit l'intérêt de l'article, et montre le sérieux des préjugés de l'auteur.
[^] # Re: Licence intéressante
Posté par xryl669 . En réponse à la dépêche Publication des éditeurs de documents en ligne de OnlyOffice. Évalué à 3.
Moi, je ne le comprends pas comme ça. Je comprends qu'il ne faut pas supprimer le logo Onlyoffice pour y mettre le tien. Rien ne t'interdit de changer le code pour faire l'interface que tu veux (y compris, déplacer ou supprimer le champ contenant le logo), du moment que tu ne t'appropries pas la marque et que tu laisses, quelque part dans ton interface (même dans une boite "à propos") le logo original d'Onlyoffice.
C'est de AGPL3, une sorte de GPL qui t'oblige à garder la source, un peu comme Flowplayer, Pydio etc… Après, on s'habitue vite à des licenses sans aucune contrepartie, mais vue l'ampleur du travail réalisé, je trouve juste de leur accorder un minimum de respect/hommage.
# Recherche par index phonetique
Posté par xryl669 . En réponse à la dépêche Grammalecte, correcteur grammatical. Évalué à 5. Dernière modification le 22 avril 2015 à 14:17.
Tu dis: "Le correcteur ne sait pas où chercher une conjugaison adéquate. Pour parfaire le système de suggestion, il faudrait établir des passerelles entre tous les mots grammaticalement distincts sur leurs liens phonétiques éventuels."
Il me semble qu'il existe dans les entrées du dictionnaire un représentation phonétique de chaque mot (sinon, ces dictionnaires existent en opensource, par exemple chez eSpeak pour la synthèse vocale, LLIUM pour la reconnaissance vocale, etc…).
Du coup, en ajoutant une n-ième passe au préprocesseur (lors de la détection d'une erreur), qui aurait pour entrée l'index des mots en "phonétique" qui, par définition est un mapping 1:n, pourrait lors d'un mot incongru (Il s'en "fou"), chercher si un des résultats pour l'entrée phonétique "fu" pourrait convenir. Dans ce cas aussi simple, il trouverait immédiatement le verbe conjugué, et n'aurait plus qu'à choisir la bonne conjugaison parmi "fous, fout".
Après, avec un TernarySearchTree indexé sur les clés phonétiques, on pourrait même envisager une recherche approximative (type Levenshtein, distance de Hamming) pour trouver des mots dont la phonétique est "proche" de l'item erroné - Cela ne donnerait pas de faux positif puisque ceci démarrerait uniquement sur détection d'une erreur, tel qu'actuellement. On est alors clairement dans l'aide à l'utilisateur, au lieu de détecter une erreur et de ne pas savoir quoi suggérer, on pourrait envisager un menu "Ils son faux." => "son" est erroné, vouliez vous dire "sont", "sonnent" etc…
Concernant "Il est aller à la mairie", je pense qu'une dernière passe de pre-processing utilisant la technique des n-gram, (c'est à dire la découpe en entités de 3/4 lettres), puis comparaison avec un modèle statistique du langage (tel que fournis par Google en opensource), repèrerait l'incongruité statistique de la suite "est aller". C'est ce que fait Google pour ses suggestions de correction de recherche. Il faut définir des seuils (donc risque de faux positifs) quitte à laisser le seuil à 0 par défaut et laisser les utilisateurs aventureux à monter le seuil.