IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Questions de style : concision, nommage, conventions, etc.


Sujet :

Langage Perl

  1. #21
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    Donc, je t'en prie, arrête de fonder tes démonstrations sur un bug imaginaire qui n'existe pas dans mon programme et est purement sorti de ton imagination fertile.
    Contrairement à ce que tu sembles croire, je ne cherche pas à te persécuter, ou t'humilier, ou que sais-je encore. S'il te plaît arrête avec cette paranoïa. J'ai donné un exemple de scénario pouvant aboutir à un bug, en mentionnant explicitement "Je ne dis pas que c'est ce qui s'est passé, mais c'est certainement quelque chose qui pourrait m'arriver". Parce que je sais que ça m'est déjà arrivé, pas sur ce problème précis mais dans des situations comparables. Quand j'écris "Je rajoute un warn de trace", le Je, c'est moi ! Et quand j'identifie (ou crois identifier) un scénario pouvant aboutir à un bug, eh bien je l'approfondis et cherche des moyens structurels de le prévenir. C'est une des raisons d'être de ce fil, de pouvoir évaluer de tels scénarios, et d'en dériver des recommandations que chacun est libre de suivre ou pas.

    J'admets tout à fait que ton code fonctionne, et j'accepte tes explications pour ce que je pensais être des anomalies. Merci de les avoir données.

    Mais ta réaction serait-elle la même si le scénario étudié était basé sur un fragment de code provenant d'une autre source ? D'un débutant qui n'aurait pas ta maîtrise ? Si c'était mon propre code que j'avais démonté ? Ce que j'essaie de mettre en évidence, c'est un mécanisme qui peut potentiellement être dangereux. Pas pour toi, c'est entendu. Mais pour moi. Ou de possibles lecteurs de ce fil.

    Cela ne fait d'ailleurs qu'affaiblir considérablement tes démonstrations.
    Je ne vois pas en quoi et je ne t'ai pas encore vu intervenir sur le fond.

    ... et que tu épilogues sur probablement plus de 10.000 mots sur un prétendu bug qui n'existe pas dans mon code mais seulement virtuellement dans ta tête.
    Une fois de plus je me fous éperdument que ce soit ton code, et si tu parvenais à prendre un peu de distance tu devrais pouvoir en faire autant. Ce qui est en train de se construire dans ma tête, et qui justifie les 10000 mots dépensés (je te fais confiance, je ne les compte pas), notamment dans des échanges pour l'instant constructifs avec Philou67430, c'est de trouver une manière d'écrire une boucle foreach qui ne risque pas de modifier la liste source (j'ai une certaine nostalgie de la const-correctness de C++...). Tu peux trouver cet objectif ridicule (je ne suis pas loin de penser que c'est déjà l'avis de Philou67430 qui se retient de me le le dire par politesse), et si c'est le cas démontre le moi, et je t'en serai reconnaissant. Et si tu as des idées sur cet objectif, n'hésite pas.

    ...mais n'ai pas forcément envie de croiser le fer avec quelqu'un qui dissèque mes propos (ou mes programmes) pour essayer d'y trouver une faute.
    J'ai bien compris et je ne compte plus faire le moindre commentaire sur les codes que tu publieras ou auras publié sur ce site, en particulier parce que nous n'avons clairement pas la même notion de ce qui constitue un bug ou une anomalie. Ça t'évitera d'avoir à y répondre, tu auras plus de temps pour des interventions substantielles, et tout le monde y gagnera. Je me réserve cependant la possibilité d'émettre une opinion contradictoire sur d'autres propos.

    De mon côté je suis avide de critique, et tout moyen susceptible d'améliorer mon code ou ma connaissance de Perl est bienvenu. J'ai sincèrement apprécié la correction sur chop et chomp, et il me semble l'avoir montré. J'écouterai avec attention toute remarque ou correction allant dans ce sens.
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  2. #22
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    C'est dingue comme les affaires de styles sont toujours à l'origine de discussions enflammées...

    Allez, je paye pas tournée :
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  3. #23
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    En général oui, c'est plus large, mais dans nos échanges jusqu'à présent dans ce fil j’essayais surtout de comprendre ta position je n'utilise JAMAIS de boucle foreach avec $_
    C'est plus clair maintenant. Ce que tu rejettes en fait c'est bien l'utilisation de $_ comme topic par défaut dans les blocs étendus.
    C'est bien cela.
    Seulement si on y est attentif, ce qui est difficile à assurer sur un bloc étendu, et c'est le cœur de mon argument.
    Je me limite à cette citation, car dans toutes mes précédentes interventions, je ne faisais pas du tout référence à ton exemple de @sommaire.
    Pour moi, lorsque l'on utilise une fonction/un opérateur avec une variable nommée, le programmeur est automatiquement attentif à l'action qu'il souhaite opérer sur l'objet en question (puisqu'il voit clairement avec le nom, de quel objet il s'agit).
    En revanche, pour le cas d'un topic anonyme $_, il me semble justement qu'il sera automatiquement moins attentif au topic, car le topic dépend du contexte, et qu'il doit donc d'abord reprendre connaissance du contexte pour bien identifier le topic concerné (je parle toujours d'un contexte "étendu"). Et il est tellement plus facile d'utiliser les fonctions/opérateur avec leur opérande $_ par défaut (surtout m//, s///, ...).
    Du coup, est-ce qu'on est d'accord sur le fait que lorsqu'on ne modifie pas la liste, il est préférable de ne pas déclarer de variable de boucle extérieure ?
    Non, je dirais plutôt qu'il serait préférable de toujours définir la variable de boucle en tant que copie et non d'alias (et si on l'a défini en alias, éventuellement ajouter un commentaire pour les utilisateurs non attentif à cet état de fait). C'est ainsi que je penserais.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  4. #24
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Du coup, est-ce qu'on est d'accord sur le fait que lorsqu'on ne modifie pas la liste, il est préférable de ne pas déclarer de variable de boucle extérieure ?
    Non, je dirais plutôt qu'il serait préférable de toujours définir la variable de boucle en tant que copie et non d'alias (et si on l'a défini en alias, éventuellement ajouter un commentaire pour les utilisateurs non attentif à cet état de fait). C'est ainsi que je penserais.
    Mais comment définis-tu la variable de boucle en tant que copie et non alias sinon par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach (@liste) {my $variable_de_boucle = $_; ...}
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  5. #25
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    C'est dingue comme les affaires de styles sont toujours à l'origine de discussions enflammées...
    C'est pour ça que j'espère qu'elle seront contenues sur ce fil et ne pollueront pas les autres

    Allez, je paye pas tournée :
    je trinque avec plaisir Kampai, Yec'hed mat , Salud, Cheers, Salute et toutes ces sortes de choses
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  6. #26
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2013
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 247
    Points : 406
    Points
    406
    Par défaut
    Bon je vais apporter mon humble contribution au sujet en espérant ne pas déchainer trop de passion

    Je pense qu'il est préférable d'utiliser des variables avec un nom informatif le plus souvent possible (quitte à alourdir un peu le code). Cela permet une reprise beaucoup plus aisé du code, par soit même mais surtout par une autre personne.
    Utiliser un style parfait mais qui demande des connaissances du langages plus poussé que l'apprentissage de base ne me parait pas, en entreprise, optimal car si il faut 2j au stagiaire ou collègue pour comprendre le code afin de faire une modification mineure (plus que s'il l'avait recodé )...

    Sinon pour reprendre les cas des $_ $1..., je préfère m'en débarasser le plus souvent possible afin d'éviter certains problèmes de "redéfinitions intempestives"

    En bref, je préfère un code très simple à comprendre plutôt que très "joli"

  7. #27
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Mais comment définis-tu la variable de boucle en tant que copie et non alias sinon par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach (@liste) {my $variable_de_boucle = $_; ...}
    Je ne connais pas d'autre manière

    Citation Envoyé par cmcmc Voir le message
    je trinque avec plaisir Kampai, Yec'hed mat , Salud, Cheers, Salute et toutes ces sortes de choses
    'S gilt ! Bis bàll !
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  8. #28
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Bonjour à tous, et notamment à @6ril23 (bienvenue dans ce fil )

    Citation Envoyé par 6ril23 Voir le message
    En bref, je préfère un code très simple à comprendre plutôt que très "joli"
    Pour essayer de mettre du concret dans les discussions sur le topic par défaut, la topicalisation et consorts, j'aimerais soumettre à votre jugement un code que j'ai commis dans un autre fil. En deux mots, pour démontrer la mise en œuvre d'une ossature de traitement que je proposais, et ne voulant pas dépendre de bibliothèques du CPAN pour cette démo, j'ai été amené à développer rapidement une fonction d'extraction de tables HTML simples (ou, en première approximation, compatible avec le jeu de données sympathiquement fourni par le demandeur). La première version ne me satisfaisait pas, j'en ai commis une seconde qui me convient mieux. J'aimerais avoir votre avis sur cette seconde version (vos commentaires sur la première sont les bienvenus également).

    Cette seconde version est assez représentative d'un style compact qui fait la part belle à l'utilisation du topic par défaut $_ (jamais exhibé mais oh combien utilisé ). La première également, qui (ab)use en plus de la topicalisation par for. Et la différence majeure entre les deux est que le moteur de la première version est foreach, tandis que celui de la seconde version est map.

    Donc, questions :
    • Sur une échelle de 1 (illisible) à 10 (limpide), comment évaluez vous ce(s) code(s) sous l'angle de la lisibilité ?
    • Auriez vous des difficultés à le(s) maintenir ?
    • Avec quelle version êtes vous le plus confortable ?
    • Qu'est-ce qui vous gêne ? Qu'est-ce qui vous gêne le plus ?
    • Qu'est ce que vous changeriez si vous deviez le prendre en charge ?
    • Est-ce qu'il faudrait ajouter des variables ? Lesquelles, où, pourquoi ?
    • Est-ce qu'il faudrait décomposer le processus, en ajoutant des fonctions ? Lesquelles, pourquoi, et comment ?
    • Est-ce qu'il faudrait ajouter des commentaires ? Où et pourquoi ?


    Toutes vos observations sont bienvenues. Que vous soyez débutant ou confirmé, votre avis m'intéresse, et il n'y a pas de question bête. Lâchez vous, n'hésitez pas, j'ai le cuir épais .

    Incidemment, je n'ai pas vérifié que le code faisait effectivement ce qu'il prétend, donc bonus à qui trouve des bugs ... Si bug il y a, indiquez le évidemment là bas, mais s'il s'agit uniquement de critiques de style, je vous remercie de vous limiter à les communiquer dans ce fil.

    La seconde version est là. La première juste au dessus dans le fil.

    Merci d'avance
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  9. #29
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 469
    Points
    12 469
    Billets dans le blog
    1
    Par défaut
    Je pense que nous nous sommes mal compris.

    J'apprécie tes commentaires à leur juste valeur (qu'ils me fassent plaisir ou non, peu importe) et je crois avoir répondu avec candeur, ingénuité, franchise et ouverture d'esprit, voire avec humour, aux premiers que tu m'as fait.

    J'ai bien compris et je ne compte plus faire le moindre commentaire sur les codes que tu publieras ou auras publié sur ce site,
    Ce n'est vraiment pas ce que je souhaitais, je suis vraiment intéressé par tout commentaire sur ce que j'écris (commentaire ou code), je pense avoir à apprendre des autres gens, surtout quand ils sont compétents. Je te demande donc expressément de ne pas prendre ainsi mes propos.

    Là où je proteste, c'est quand tu crées successivement pas moins de dix (10) posts (et même un nouveau fil) juste pour pilonner mon post qui contenait au départ un malheureux programme de 13 lignes de code. Un programme certes écrit à la va-vite à 1h30 du matin, mais un programme, je suis désolé de devoir le répéter, qui marchait et faisait parfaitement ce qu'il devait faire.

    Là, je dis que ta réponse est, pour employer un langage de juriste (ma fille fait des études de droit, ça finit par influer ma façon de parler), complètement disproportionnée. Paranoïa de ma part? Allons, sois sérieux, quand on prend dix obus lourds sur la tronche, on est peut-être fondé à commencer à penser que quelqu'un vous en veut, non? Je ne pense être ni paranoïaque, ni même particulièrement susceptible. Il faudrait que tu sois complètement insensible à l'effet que tu fais à autrui, voire à moitié autiste, pour ne pas comprendre cela.

    Une fois de plus je me fous éperdument que ce soit ton code
    Je me doute bien que tu t'en fous, mais pas moi, n'es-tu pas capable de comprendre cela? C'est tout de même très singulier d'être à ce point imperméable à la sensibilité des autres gens.

    Imagine que je prenne une phrase quelconque et complètement anodine de ta part, disons celle-ci:

    Ce scénario ne pose pas de problème si $inter est déclarée à l'intérieur de la boucle comme copie de $_.
    Et suppose que je dise: "cette phrase est grammaticalement fausse." Bien sûr, elle ne l'est pas. Mais imagine que j'insiste: ce dont tu voulais vraiment parler, c'est de ces scénarios, pas ce scénario. Et, donc, puisque tu entendais le pluriel, tu aurais dû écrire "posent", pas "pose". Donc, je te corrige: "Ta grammaire est vraiment nulle, tu ne sais même pas accorder ton verbe 'poser' avec ton sujet, qui aurait dû être au pluriel." Absurde, n'est-ce pas? Imagine maintenant de surcroît que je crée une dizaine de posts sur ce sujet et même, pour faire bonne mesure, un nouveau fil. Ce ne serait plus seulement absurde, mais aussi complètement démesuré, n'est-ce pas? Ne serais-tu pas fondé à être quelque peu agacé? Rassure-toi, je ne le ferai pas, je n'ai nullement envie de passer pour un bouffon.

    Cette situation hypothétique, pourtant, c'est exactement ce que tu m'as fait. Pas une seule fois, mais dans dix posts de (très longues) pages. Ne peux-tu pas comprendre que cette façon d'agir finisse par m'indisposer?

    Cela dit (car il fallait tout de même le dire), je ne suis aucunement rancunier et je suis tout-à-fait prêt à passer l'éponge sur ce qui m'a déplu, sans aucune condition, là, maintenant et tout de suite. J'ai vraiment envie d'avoir une relation de discussion cordiale avec toi, et pas du tout envie de me prendre la tête dans de stériles querelles de personnes. Nous pouvons bien sûr nous ignorer et éviter de nous parler, mais je préférerais mille fois que nous nous la jouions collaboration loyale et enrichissement réciproque. J'oublie volontiers et d'un seul trait de plume tout ce que je t'ai reproché plus haut et je te demande humblement d'en faire autant à mon égard si tu as des choses à me reprocher. Voilà, c'est ce que je te propose, on arrête les hostilités, on a bien mieux à faire, et je suis sûr que nous pouvons progresser chacun de nos expériences respectives. Bref, je propose un accord gagnant-gagnant.

    Et, comme on dit en Breton (je ne suis pas breton, mais j'aime beaucoup la Bretagne), yer mat pour l'apéro.

  10. #30
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Lolo78 Voir le message
    Je pense que nous nous sommes mal compris.
    ...
    je suis sûr que nous pouvons progresser chacun de nos expériences respectives. Bref, je propose un accord gagnant-gagnant.

    Et, comme on dit en Breton (je ne suis pas breton, mais j'aime beaucoup la Bretagne), yer mat pour l'apéro.
    Pas mieux. Tope là !
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  11. #31
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Donc, questions :
    • Sur une échelle de 1 (illisible) à 10 (limpide), comment évaluez vous ce(s) code(s) sous l'angle de la lisibilité ?
    Foreach/for: 3 (introduction d'indentations parasites dues aux topicalisations par for, notamment). Dans ce cas précis, on se demande d'ailleurs pourquoi avoir utilisé while (m{...}) { $topic = $_; for ($topic) ... alors qu'il suffisait d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		foreach (m{(<TR[ >].*?</TR>)}msg) {
    Une remarque un peu similaire ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	while (m{(<TABLE.*?</TABLE>)}msg) {
    	    ++$tablecnt;
    	    my $tabletext = $1;
    Avec en outre l'introduction d'une instruction entre la récupération de $1 et l'exécution de l'opération de recherche de motif... l'usage du foreach () permettait d'éviter l'affectation manuelle de $1 et faisait la topicalisation en même temps.

    Map : 7 (l'utilisation de deux map imbriqués implique une lecture du code inversée par rapport à l'analyse du texte HTML, mais la concision des blocs rends la lecture relativement facile).
    • Auriez vous des difficultés à le(s) maintenir ?
    Non, mais c'est plus dépendant du mainteneur que du code lui-même. Personnellement, la topicalisation par for m'aurait déroutée, et je l'aurais virée (d'autant qu'à la base, le topic était nommé).
    • Avec quelle version êtes vous le plus confortable ?
    La 2e sans hésiter.
    • Qu'est-ce qui vous gêne ? Qu'est-ce qui vous gêne le plus ?
    J'ai répondu dans les 2 premiers points
    • Qu'est ce que vous changeriez si vous deviez le prendre en charge ?
    Idem.
    Je n'ai pas vu l'intérêt dans la 2e version (map) de définir $h au lieu de %h. De même, initialiser $h = {} (ou simplement utiliser %h, sans même le définir à l'ensemble vide) me semble plus correct que de post-garantir que $h ne sera pas undef (plus robuste aux évolutions il me semble).
    • Est-ce qu'il faudrait ajouter des variables ? Lesquelles, où, pourquoi ?
    Je n'en aurait pas ajouté. J'aurais peut-être supprimé @table dans la 2e version, pour affecter directement "table_$tablecnt" => map { ... }
    • Est-ce qu'il faudrait décomposer le processus, en ajoutant des fonctions ? Lesquelles, pourquoi, et comment ?
    Je ne vois pas... le code est suffisamment décomposé il me semble.
    • Est-ce qu'il faudrait ajouter des commentaires ? Où et pourquoi ?
    Il me semble toujours utile d'ajouter des commentaires avant chaque bloc de code (avant chaque map, boucle ou if)
    Toutes vos observations sont bienvenues. Que vous soyez débutant ou confirmé, votre avis m'intéresse, et il n'y a pas de question bête. Lâchez vous, n'hésitez pas, j'ai le cuir épais .
    J'ai fait une lecture superficielle, en m'attardant plus sur la version map, celle avec laquelle je suis le plus à l'aise.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  12. #32
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    ...on se demande d'ailleurs pourquoi avoir utilisé while (m{...}) { $topic = $_; for ($topic) ... alors qu'il suffisait d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		foreach (m{(<TR[ >].*?</TR>)}msg) {
    Une remarque un peu similaire ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	while (m{(<TABLE.*?</TABLE>)}msg) {
    	    ++$tablecnt;
    	    my $tabletext = $1;
    Avec en outre l'introduction d'une instruction entre la récupération de $1 et l'exécution de l'opération de recherche de motif... l'usage du foreach () permettait d'éviter l'affectation manuelle de $1 et faisait la topicalisation en même temps.
    L'explication est la suivante : il me semble que lorsqu'on veut faire des m//g imbriqués ou entrelacés, on n'a pas trop le choix : on est obligé de tester le m//g en contexte scalaire, comme ci-dessous (exemple très simplifié):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Taisha:~/tttmp $ perl -E '$s = q{A123BC12D}; while ($s =~ m/([A-Z])/gc) { $a = $1; while ($s =~ m/\G([0-9])/gc) { say qq{$a$1} } }'
    A1
    A2
    A3
    C1
    C2
    Taisha:~/tttmp $
    je sortais d'un codage de ce genre (nettement plus chevelu ) et j'avais ce mécanisme en tête, et l'ai employé sans réfléchir. Ce n'est que quand j'ai repris le temps de respirer que j'ai réalisé qu'ici je pouvais utiliser m//g en contexte de liste. Ça a été une motivation très forte pour reprendre le code et produire la seconde version, je n'aime pas non plus utiliser les variables de regexp si je n'y suis pas obligé.

    Je n'ai pas vu l'intérêt dans la 2e version (map) de définir $h au lieu de %h. De même, initialiser $h = {} (ou simplement utiliser %h, sans même le définir à l'ensemble vide) me semble plus correct que de post-garantir que $h ne sera pas undef (plus robuste aux évolutions il me semble).
    Deux points :
    1. l'instruction n'est pas une simple sécurité : $h contient pour chaque ligne valeur (celles qui contiennent les TD) l'ensemble des associations nom_de_colonne => valeur pour cette ligne. Quand on traite la ligne d'entête (celle qui contient les TH); on ne doit pas produire de hash. D'où la liste vide dans ce cas (qui sera avalée). Le map sur les TR produit une liste contenant un élément de moins que le nombre total de TR pour la table en cours.
    2. comme on doit retourner une référence, déclarer %h ne présente pas d'intérêt et forcera à retourner \%h, qui plus est de manière passablement disgracieuse

    J'ai hésité à initialiser explicitement : my $h = undef; qui est la seule solution que je vois au niveau code pour attirer l'attention sans ajouter un commentaire. Mais c'est probablement un endroit ou j'aurais effectivement dû en ajouter un.
    J'aurais peut-être supprimé @table dans la 2e version, pour affecter directement "table_$tablecnt" => map { ... }
    Ce n'est pas simple. Ca ne marche pas, en tous cas pas sous cette forme : la partie droite de => doit être une référence, pas une liste. On ne peut pas utiliser l'opérateur \, qui va prendre les références de tous les élements de la liste. Reste l'utilisation d'une sub anonyme comme ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    sub extracteur_tables {
        my ($fulltext) = @_;
        my $tablecnt = 0;
        my %data = map {
    	++$tablecnt;
    	my @headers;
     	"table_$tablecnt" => sub { return \@_ }->(
                                                      map {
                                                          my $h;
                                                          if (m{<TH>}msi) {
                                                              @headers = m{<TH>(.*?)</TH>}imsg;
                                                          } else {
                                                              die "pas d'entêtes trouvés pour la table N° $tablecnt" unless @headers;
                                                              @{$h}{@headers} = m{<TD>(.*?)</TD>}imsg;
                                                          }
                                                          $h || ();
                                                      } m{(<TR.*?</TR>)}imsg
                                                     )
        } $fulltext =~ m{(<TABLE.*?</TABLE>)}imsg;
        return \%data;
    }
    qui fonctionne, mais il n'est pas évident de trouver une forme d'indentation qui véhicule l'intention du programmeur sans consommer un espace horizontal démesuré... Et je crois que pour le coup la note globale de lisibilité en prendrait un coup

    J'ai fait une lecture superficielle, en m'attardant plus sur la version map, celle avec laquelle je suis le plus à l'aise.
    Tu as très bien fait, il est très utile pour moi de voir où une telle lecture superficielle peut achopper pour m'indiquer ce qui doit être un peu plus détaillé ou commenté (le pourquoi du $h, le fait que le map sur les TR produit un élement de moins qu'en entrée). Je n'ai pas repris tes autres commentaires ci-dessus parce que les citations imbriquées disparaissent quand on répond et qu'il est fastidieux de les réinsérer manuellement, mais sache que je les ai bien notés.

    +1, et merci beaucoup
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  13. #33
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    A tous :

    ce n'est pas parce que Philou67430 s'est exprimé que le sujet de l'évaluation est clos Son regard n'est pas le vôtre, et une fois de plus tous vos commentaires sont les bienvenus.

    Petite note : si vous avez peu de temps, concentrez vous sur la seconde version. La première a été codée très vite pour fournir une preuve de concept, et devrait être retravaillée si l'objectif était de comparer une version 'propre' à base de foreach à une version 'propre' à base de map, ce qui n'est pas le cas ici.
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  14. #34
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    L'explication est la suivante : il me semble que lorsqu'on veut faire des m//g imbriqués ou entrelacés, on n'a pas trop le choix : on est obligé de tester le m//g en contexte scalaire, comme ci-dessous (exemple très simplifié):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Taisha:~/tttmp $ perl -E '$s = q{A123BC12D}; while ($s =~ m/([A-Z])/gc) { $a = $1; while ($s =~ m/\G([0-9])/gc) { say qq{$a$1} } }'
    A1
    A2
    A3
    C1
    C2
    Taisha:~/tttmp $
    Ce n'est pas l'imbrication de m//g qui l'oblige, c'est l'utilisation du modifier /c : lorsque tu utilises foreach (), un contexte de liste est fourni ce qui produit immédiatement l'évaluation de toutes les recherches de motif.
    Or, dans ton exemple, tu ne veux récupérer qu'une seule évaluation à la fois, pour pouvoir en intercaler une autre à la fin de chacune d'elle.

    En revanche, dans l'exemple du HTML, l'imbrication de la recherche se fait par "extraction d'un tableau" puis, au sein de cette extraction, une "extraction de cellules". Dans ce cas, les deux chaines pour la recherche de motif sont différentes, et il n'y a pas de "race condition" entre ces deux recherches de motifs, elles peuvent se faire "globalement" sans contrainte de synchronisation entre les deux.
    Exemple simplissime :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ perl -E '$s = q{A123BC12D}; foreach my $a ($s =~ m/([A-Z].*?[A-Z])/g) { foreach my $b ($a =~ m/([0-9])/g) { say substr($a, 0, 1), $b, substr($a, -1, 1); } }'
    A1B
    A2B
    A3B
    C1D
    C2D
    je sortais d'un codage de ce genre (nettement plus chevelu ) et j'avais ce mécanisme en tête, et l'ai employé sans réfléchir. Ce n'est que quand j'ai repris le temps de respirer que j'ai réalisé qu'ici je pouvais utiliser m//g en contexte de liste. Ça a été une motivation très forte pour reprendre le code et produire la seconde version, je n'aime pas non plus utiliser les variables de regexp si je n'y suis pas obligé.
    Ceci explique celà
    Je répondrai aux autres remarques dans un autre message.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  15. #35
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Deux points :
    1. l'instruction n'est pas une simple sécurité : $h contient pour chaque ligne valeur (celles qui contiennent les TD) l'ensemble des associations nom_de_colonne => valeur pour cette ligne. Quand on traite la ligne d'entête (celle qui contient les TH); on ne doit pas produire de hash. D'où la liste vide dans ce cas (qui sera avalée). Le map sur les TR produit une liste contenant un élément de moins que le nombre total de TR pour la table en cours.
    Je ne suis pas sûr de comprendre en quoi ce point concerne ma remarque, mais oublions, je n'ai pas revu en détail ce bout de code.
    1. comme on doit retourner une référence, déclarer %h ne présente pas d'intérêt et forcera à retourner \%h, qui plus est de manière passablement disgracieuse
    Pour retourner une référence, je procède presque toujours ainsi :
    ce qui a l'avantage, de mon point de vue, de toujours retourner une référence (alors que %h ? \%h : () retourne soit une référence, soit undef en contexte scalaire ou une liste vide en contexte de liste).
    J'ai hésité à initialiser explicitement : my $h = undef; qui est la seule solution que je vois au niveau code pour attirer l'attention sans ajouter un commentaire. Mais c'est probablement un endroit ou j'aurais effectivement dû en ajouter un.
    Pourquoi undef au lieu de {} ?
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  16. #36
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc
    Ce n'est pas simple. Ca ne marche pas, en tous cas pas sous cette forme : la partie droite de => doit être une référence, pas une liste. On ne peut pas utiliser l'opérateur \, qui va prendre les références de tous les élements de la liste. Reste l'utilisation d'une sub anonyme comme ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    sub extracteur_tables {
        my ($fulltext) = @_;
        my $tablecnt = 0;
        my %data = map {
    	++$tablecnt;
    	my @headers;
     	"table_$tablecnt" => sub { return \@_ }->(
                                                      map {
                                                          my $h;
                                                          if (m{<TH>}msi) {
                                                              @headers = m{<TH>(.*?)</TH>}imsg;
                                                          } else {
                                                              die "pas d'entêtes trouvés pour la table N° $tablecnt" unless @headers;
                                                              @{$h}{@headers} = m{<TD>(.*?)</TD>}imsg;
                                                          }
                                                          $h || ();
                                                      } m{(<TR.*?</TR>)}imsg
                                                     )
        } $fulltext =~ m{(<TABLE.*?</TABLE>)}imsg;
        return \%data;
    }
    qui fonctionne, mais il n'est pas évident de trouver une forme d'indentation qui véhicule l'intention du programmeur sans consommer un espace horizontal démesuré... Et je crois que pour le coup la note globale de lisibilité en prendrait un coup
    Il y a, comme indiqué précédemment, la solution du tableau anonyme, qui celui moi, reste simple à comprendre, et ne nuit pas à la lisibilité. D'ailleurs, le tableau anonyme est couramment utilisé pour l'initialisation de "structures", donc largement utilisé.
    Exemple :
    Voila, j'ai fini de répondre

    Edit :
    pour l'indentation, cperl-mode de Emacs n'indente pas l'{ du map après le [, mais après "clé", ce qui ne place pas le code important du map à droite.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  17. #37
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Ce n'est pas l'imbrication de m//g qui l'oblige, c'est l'utilisation du modifier /c
    ...dont j'ai besoin dans cette approche (avec /G), mais oui c'est exact.
    Exemple simplissime :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ perl -E '$s = q{A123BC12D}; foreach my $a ($s =~ m/([A-Z].*?[A-Z])/g) { foreach my $b ($a =~ m/([0-9])/g) { say substr($a, 0, 1), $b, substr($a, -1, 1); } }'
    A1B
    A2B
    A3B
    C1D
    C2D
    +1 ! Du coup je pourrais effectivement reprendre mon exemple comme suit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Taisha:~/tttmp $ perl -E '$s = q{A123BC12D1}; foreach my $a ($s =~ m/([A-Z].*?)(?:(?=[A-Z])|$)/g) { foreach my $b ($a =~ m/([0-9])/g) { say substr($a, 0, 1), $b}}'
    A1
    A2
    A3
    C1
    C2
    D1
    Taisha:~/tttmp $
    bien que je n'aime pas trop l'alternation | qui peut poser des problèmes d'efficacité (quoique peut-être pas trop dans ce cas). Il faudra que je voie comment ça peut se transposer dans d'autres cas.

    Ceci explique celà
    ehh oui ... Du coup j'ai regardé comment faire une version propre avec foreach. J'en suis là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    sub extracteur_tables_foreach {
        my ($fulltext) = @_;
        my (%tables, $tablecnt);
        foreach ($fulltext =~ m{(<TABLE.*?</TABLE>)}imsg) {
            ++$tablecnt;
            my (@entetes, @lignes);
            foreach (m{(<TR.*?</TR>)}imsg) {
    	    if (m{<TH>}ims) {
    		@entetes = m{<TH>(.*?)</TH>}imsg;
    	    } else {
    		die "pas d'entêtes trouvés pour la table N° $tablecnt" unless @entetes;
    		@{$lignes[@lignes]}{@entetes} = m{<TD>(.*?)</TD>}imsg;
    	    }
            }
            $tables{"table_$tablecnt"} = \@lignes;
        }
        return \%tables;
    }
    A ce stade je préfère cette dernière version à la version map, parce que je trouve que le cas particulier des entêtes est traité plus naturellement. En particulier je trouve la ligne 12 absolument délicieuse (insertion en fin de @lignes d'une référence à un hash autovivifié et initialisé à la volée... ). Ça résout plein de problèmes ou plutôt de tensions qu'on a avec map quand on aurait besoin d'une sortie anticipée du bloc (analogue à un return au milieu d'une fonction). Du coup je n'ai pas l'impression qu'il faille ajouter de commentaire nulle part, le code est autosuffisant et sans pièges... Qu'en penses-tu ? Est-ce que ça mérite pour toi une meilleure note en lisibilité ?
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  18. #38
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par cmcmc Voir le message
    Du coup je n'ai pas l'impression qu'il faille ajouter de commentaire nulle part, le code est autosuffisant et sans pièges... Qu'en penses-tu ?
    C'est lisible et compréhensible sans commentaire.
    Est-ce que ça mérite pour toi une meilleure note en lisibilité ?
    Oui, notamment parce que l'ordre exécution du parsing est identique à l'ordre de lecture du code (le map inverse l'ordre, ce qui mets "le topic" à la fin du traitement de ce topic, et dans l'ordre inverse des imbrications).
    Au moins +1.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  19. #39
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    Pour retourner une référence, je procède presque toujours ainsi :
    ce qui a l'avantage, de mon point de vue, de toujours retourner une référence (alors que %h ? \%h : () retourne soit une référence, soit undef en contexte scalaire ou une liste vide en contexte de liste).
    Pourquoi undef au lieu de {} ?
    Ouh là ... Plusieurs choses à dire :

    Tout d'abord, ici il est essentiel de renvoyer soit la liste vide (), soit une référence à un hash ($h ou \%h). On renvoie la liste vide () quand on parse le TR d'entête (celui qui contient les <TH>col</TH>), parce que justement dans ce cas on ne peut pas renvoyer de hashref puisqu'on n'a pas encore de valeurs... Ce n'est que quand on lit un TR de ligne ou de valeur (c'est à dire contenant des <TD>val</TD>) que l'on peut construire le hash { col1 => val1, col2 => val2, ... , coln => valn} pour cette ligne.

    Pour une table avec 1 TR d'entête et m TR de lignes, le map sur les TR renvoie conceptuellement la liste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (), $hashref1, $hashref2, ..., $hashrefm
    La liste vide est aplatie et disparaît lors de l'affectation à @table dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	my @table = map { ... } m{(<TR.*?</TR>)}imsg;
    et c'est exactement ce qu'on veut.

    C'est pourquoi la valeur de retour du map est ici $h || (). C'est la forme adaptée au besoin, elle tient compte du fait qu'on est en contexte de liste (affectation à une table), et les considérations sur sa valeur en contexte scalaire (aussi exactes soient-elles ) ne sont pas pertinentes ici.

    C'est également pourquoi $h doit être laissé non-initialisé, ou bien initialisé à undef (uniquement pour marquer le coup, le résultat est le même), et surtout pas initialisé à {} car dans ce dernier cas $h est vrai et le test $h || () renvoie toujours $h ce qui est désastreux.

    Peut-être que le mieux dans ce genre de situation c'est d'insérer une sub anonyme et de distinguer les deux types renvoyés par des appels explicites à return :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     	my @table = map {
                (sub {
                     if (m{<TH>}msi) {
                         @headers = m{<TH>(.*?)</TH>}imsg;
                         return ();
                     } else {
                         die "pas d'entêtes trouvés pour la table N° $tablecnt" unless @headers;
                         my %h;
                         @h{@headers} = m{<TD>(.*?)</TD>}imsg;
                         return \%h;
                     }
                 })->($_);
    	} m{(<TR.*?</TR>)}imsg;
    ça marche, on peut si on préfère déclarer %h plutôt que $h, et c'est peut-être plus clair... Tu préfères cela ?

    (je vais répondre sur \%h vs. [ %h ] dans un message séparé).
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  20. #40
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Comme convenu je reviens sur \%h vs. [ %h ], et je rajoute $h pour faire bon poids :
    Citation Envoyé par Philou67430 Voir le message
    Je n'ai pas vu l'intérêt dans la 2e version (map) de définir $h au lieu de %h.
    Comme on va retourner une référence, déclarer un hash ne sert à rien. On l'a vu précédemment, la valeur de retour du map doit être soit un hashref, soit la liste vide (), ce qu'on exprime comme suit pour la référence
    et comme suit pour le hash explicite
    Outre le fait que la première forme est plus élégante que la seconde, elle est également significativement (au moins trois fois) plus efficace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Taisha:~/tttmp $ time perl -e '%{$h} = 1 .. 2; $cnt = 10_000_000; foo ($h || ()) while (--$cnt); sub foo {}'
    real	0m3.796s
    user	0m0.031s
    sys	0m0.015s
    Taisha:~/tttmp $ time perl -e '%h = 1 .. 2; $cnt = 10_000_000; foo (%h ? \%h : ()) while (--$cnt); sub foo {}'
     
    real	0m12.268s
    user	0m0.030s
    sys	0m0.031s
    Taisha:~/tttmp $
    Ce qui n'est pas cependant un motif légitime pour la sélectionner, parce qu'à l'inverse, l'initialisation @h{@headers) = ... est plus rapide que @{$h}{@headers} = ... :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1; @k = 1 .. $size; @v = 1 .. $size; $cnt = 1_000_000; @h{@k} = @v while (--$cnt)'
     
    real	0m0.554s
    user	0m0.015s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 10; @k = 1 .. $size; @v = 1 .. $size; $cnt = 1_000_000; @h{@k} = @v while (--$cnt)'
     
    real	0m1.441s
    user	0m0.016s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 100; @k = 1 .. $size; @v = 1 .. $size; $cnt = 1_000_000; @h{@k} = @v while (--$cnt)'
     
    real	0m11.127s
    user	0m0.046s
    sys	0m0.000s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1; @k = 1 .. $size; @v = 1 .. $size; $cnt = 1_000_000; @{$h}{@k} = @v while (--$cnt)'
     
    real	0m0.605s
    user	0m0.015s
    sys	0m0.031s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 10; @k = 1 .. $size; @v = 1 .. $size; $cnt = 1_000_000; @{$h}{@k} = @v while (--$cnt)'
     
    real	0m2.088s
    user	0m0.047s
    sys	0m0.000s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 100; @k = 1 .. $size; @v = 1 .. $size; $cnt = 1_000_000; @{$h}{@k} = @v while (--$cnt)'
     
    real	0m18.465s
    user	0m0.015s
    sys	0m0.031s
    Taisha:~/tttmp/hyperliens $
    Donc effectivement tu as raison, malgré l'inélégance de la forme à retourner, déclarer %h semble meilleur que déclarer $h

    Par contre :


    Citation Envoyé par Philou67430 Voir le message
    Pour retourner une référence, je procède presque toujours ainsi :
    Pas moi...

    Citation Envoyé par Philou67430 Voir le message
    Il y a, comme indiqué précédemment, la solution du tableau anonyme, qui celui moi, reste simple à comprendre, et ne nuit pas à la lisibilité. D'ailleurs, le tableau anonyme est couramment utilisé pour l'initialisation de "structures", donc largement utilisé.
    Exemple :
    Là non plus je ne l'utiliserais pas... Peut-être plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "clé" => (sub {my @list = map ... ; \@list})->()
    (ou (sub { \@_ })->(map ... ) comme je l'ai écrit dans un post précédent).

    Le problème de [ ... ], le constructeur de liste anonyme, est qu'il effectue une copie de ses arguments. Ça ne porte pas à conséquence pour de toute petites listes mais je n'aime pas ces coûts évitables.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ %h ]) while (--$cnt); sub foo {}'
     
    real	0m1.399s
    user	0m0.016s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 10; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ %h ]) while (--$cnt); sub foo {}'
     
    real	0m4.767s
    user	0m0.046s
    sys	0m0.000s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 100; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ %h ]) while (--$cnt); sub foo {}'
     
    real	0m37.664s
    user	0m0.000s
    sys	0m0.031s
    À l'inverse le coût de génération d'une référence anonyme (\%hash, \@liste, \$scalaire, ...) est constant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ \%h ]) while (--$cnt); sub foo {}'
     
    real	0m1.153s
    user	0m0.000s
    sys	0m0.031s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 10; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ \%h ]) while (--$cnt); sub foo {}'
     
    real	0m1.019s
    user	0m0.031s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 100; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ \%h ]) while (--$cnt); sub foo {}'
     
    real	0m1.191s
    user	0m0.030s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1000; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ \%h ]) while (--$cnt); sub foo {}'
     
    real	0m1.173s
    user	0m0.015s
    sys	0m0.031s
    Taisha:~/tttmp/hyperliens $
    Donc effectivement je n'utilise pas [ ... ] quand je ne connais pas la taille de la liste, le réservant pour des formes quasi littérales comme [ $x, $y, $z ] (ce à quoi j'imagine tu fais référence en parlant d'initialisation de "structures").
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

Discussions similaires

  1. [POO] Question de style et méthode de codage
    Par elitemedia dans le forum Langage
    Réponses: 1
    Dernier message: 23/12/2006, 22h03
  2. Réponses: 3
    Dernier message: 03/11/2006, 18h16
  3. [RCP] Petite question de style :)
    Par Laph95 dans le forum Eclipse Platform
    Réponses: 2
    Dernier message: 06/10/2006, 16h14
  4. Questions en vrac : bit shift, frustrum etc
    Par LapinGarou dans le forum Moteurs 3D
    Réponses: 13
    Dernier message: 21/08/2006, 17h35
  5. Question de style ;)
    Par kinta dans le forum C++
    Réponses: 16
    Dernier message: 21/02/2006, 14h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo