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. #1
    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 Questions de style : concision, nommage, conventions, etc.
    Bonjour à tous,

    les questions de style donnent souvent lieu à des échanges plus ou moins passionnés, qui pour intéressants qu'ils puissent être, finissent par parasiter les fils où ils prennent naissance. J'espère que vous ne m'en voudrez pas de déplacer ici une discussion de ce type, que je trouve effectivement intéressante, mais qui s'appuie sur plusieurs fils dans lesquels elle est selon moi hors sujet.

    Dans mon esprit cette discussion est ouverte à tous, et pourraît être un forum de débat et d'analyse, notamment de formes que certains jugent bizarres ou dangereuses alors que d'autres les trouvent au contraire parfaitement banales et légitimes. N'hésitez pas à intervenir, poser des questions, demander des éclaircissements, faire part de votre expérience et de vos anecdotes (heureuses ou tragiques...).

    En attendant, poursuite de la discussion (Pour rétablir le contexte, le plus simple est sans doute de partir d'ici pour le fil principal, et de suivre les liens donnés dans le texte ci-dessous pour retrouver les échanges annexes) :


    Sur la concision, l'intelligibilité et l'appropriation
    Citation Envoyé par Lolo78 Voir le message
    ...Il faut juste faire attention à qui on s'adresse. Sur un forum, par exemple, utiliser des concepts trop avancés face à un débutant risque de le faire fuir. ...
    J'entends bien. Mais il me semble que c'est peut-être un mauvais service à leur rendre que de leur donner d'entrée une solution parfaite qu'ils peuvent utiliser par copier/coller. Le risque alors est qu'ils ne la comprennent pas complètement et que cela leur pose des difficultés plus tard s'ils doivent intervenir dessus.

    Je pars du principe que ceux qui posent des questions sur ce forum ne le font pas dans le cadre du choix d'un langage pour résoudre leur problème : Perl a déjà été choisi. Et mes réponses ne devraient pas les faire fuir si, comme je le fais systématiquement, je démontre qu'elles fonctionnent, d'une manière qu'ils peuvent reproduire et expérimenter tranquillement chez eux. Au contraire, elles devraient éveiller leur curiosité.

    Il est important que le demandeur s'approprie la solution proposée, et en particulier comprenne l'algorithme sous-jacent et les mécanismes mis en œuvre pour l'implémenter. Lors de ce travail d'appropriation, si la solution est présentée de manière trop concise pour lui dans un premier temps, il va devoir la décomposer, peut être introduire des variables intermédiaires qui vont dénommer d'une manière qui a un sens pour lui à ce stade de sa propre réflexion certains éléments ou concepts manipulés. C'est très bien comme cela.

    Et tu noteras par ailleurs j'espère que je ne rechigne pas à accompagner les demandeurs dans ce travail d'appropriation lorsqu'ils ont des difficultés.

    Sur le nommage des variables

    Citation Envoyé par Philou67430 Voir le message
    Ainsi, je n'utilise JAMAIS de boucle foreach avec $_.
    Citation Envoyé par Lolo78 Voir le message
    Souvent, par exemple quand je lis un fichier, j'utilise souvent $_ dans un premier temps, parce qu'il me permet de réaliser facilement toute une série d'actions "techniques" (chomp, s///g, m//, lc, uc, length, split, etc.), puis je passe à une variable nommée quand je rentre dans la complexité fonctionnelle ou algorithmique. Je ne dis pas que ma solution est la bonne, mais juste que je suis plus à l'aise avec des variables nommées quand le fonctionnel ou l'algo deviennent compliqués.
    Je n'aime effectivement pas les variables 'documentaires' triviales, ni celles qui semblent l'être mais ne le sont pas. Pour illustrer cette seconde catégorie, reprenons ton exemple
    Citation Envoyé par Lolo78 Voir le message
    Plutôt que $a[@b] ou même $a[scalar(@b)] qui n'apporte pas grand chose de plus, je préfère écrire un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    my $nb_prestas = @b ; # ou my $nb_prestas = scalar @b;
    my $something = $a[$nb_prestas];
    La différence, c'est que l'on a ajouté un nom de variable qui commente le code.
    Pour moi hors contexte c'est incompréhensible. Pourquoi $nb_prestas et pas $nb_b ? Qu'est-ce qu'il y a dans @b ? C'est le tableau des prestas ? Alors, surement il devrait s'appeler @prestas, non ? Ou bien est-ce qu'on découvre incidemment que la taille de @b est identique au nombre de prestas, et c'est cela qu'on commente ? Est-ce qu'on se sert de $nb_prestas ailleurs dans le bloc ? Etc.

    De manière plus fondamentale, et pour répondre de manière peut être plus argumentée que je ne l'ai fait précédemment à Philou67430, je trouve que nommer explicitement la variable de boucle dans un while (<...>) ou un foreach tend non seulement à parasiter la lecture plutôt qu'apporter du sens (à l'exception notable de certaines boucles imbriquées), mais peut également s'avérer dangereux. Je le démontre sur ce code extrait d'un autre fil:
    Citation Envoyé par Lolo78 Voir le message
    Voici une version de mon programme donnant les numérotations sous une forme 1.a.A et non plus 1.1.1:

    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
    my @master_list = qw / 1 a A/;
    my @level_list = qw /0 0 0/;
    my @sommaire = qw/ x x-x x x-x x-x x-x-x x x-x x-x-x x-x-x x-x-x x-x x-x-x x x-x x-x x-x-x x-x-x /;
    my @new_sommaire;
    for my $inter (@sommaire) {
    	my @fields = split /-/, $inter;
    	my $level = $#fields;
    	$level_list[$level]++ ;
    	my @out;
    	for (0..$#master_list) {
    		my $i = $master_list[$_];
    		$i++ for (0..$level_list[$_]-2);
    		push @out, $i;
    	}  
    	$inter = join '-', @out[0..$level];
    	push @new_sommaire, $inter;
    	$level_list[$_] = 0  for ($level+1..$#master_list);
    }
    print "@new_sommaire \n";
    J'ai déjà dit dans le fil en question tout le bien que je pensais de l'initialisation de @level_list en ligne 2, et de la boucle en ligne 17, tu as répondu, je n'y reviendrai pas. Intéressons-nous ici à la variable $inter. Comme tu le sais puisque tu le rappelle obligeamment dans ton tutoriel, c'est (je cite) un alias sur chaque élément successif du tableau ou de la liste ; en modifiant $item, on modifie bien le contenu du tableau. En ligne 15 tu modifies @sommaire. Est-ce délibéré ? Il semble que non, puisque tu produits @new_sommaire, et que par ailleurs cette modification ne sert pas dans l'algorithme. Aurais tu codé cette ligne 15 comme suit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $_ = join '-', @out[0..$level];
    et utilisé $_ dans le push de la ligne 16, si tu n'avais pas déclaré $inter ? Probablement pas, car dans ce cas une myriade de signaux d'alarme auraient retenti dans ta tête, même à 1h30 du matin. En l'occurrence, rien n'a retenti, et quand tu as repris ton programme le lendemain à tête reposée tu n'as rien vu de bizarre. CQFD. (Tu me diras que ce n'est pas un bug, que le programme fonctionne quand même, que tu l'aurais corrigé dans une version de production, bla bla bla. Pour moi il reste que ça fait mauvais effet.)

    Tant qu'on est dans le nommage, ta déclaration de $level en ligne 7 me fait plus que tiquer. Pas parce que tu introduits une variable, mais parce que tu l'appelles $level, et que ça frotte sévèrement avec @level_list. Le level de $level, c'est la profondeur de l'entrée courante sur laquelle on travaille (entre 0 et 2). Les level de @level_list, ce sont les index numériques maximaux atteints à ce stade pour chaque niveau de profondeur dans le sommaire (de 1 au nombre de sections rencontrées jusqu'à présent à chaque niveau de profondeur). Franchement, c'est extrêmement perturbant pour quelqu'un qui lit ton code, et prétendre qu'il y gagne en clarté me semble pour le moins capillotracté.

    Ne crois pas que je cherche à te prendre comme tête de turc, ce n'est vraiment pas le cas (ou peut-être un petit peu, mais uniquement parce qu'en tant que 'Membre Expert' il me semble que tu aurais vocation à être exemplaire : n'y vois donc rien de personnel). En particulier je suis parfaitement conscient que le code ci-dessus a été écrit à la va-vite à une heure tardive, a été publié dans une discussion qui ne s'adressait pas à des débutants, et n'est dans tous les cas certainement pas représentatif de ta production habituelle.

    Mais je cherche effectivement à montrer, en particulier aux débutants qui nous lisent, que tes préconisations et celles de Philou67430 demandent en fait beaucoup plus de travail et de discipline qu'il n'y paraît au premier abord, et peuvent même s'avérer piégeuses. Et qu'elles ne sont clairement pas une garantie de qualité, ni même un garde-fou pouvant préserver de certaines erreurs. Et que du coup mes propres recommandations, bien que provenant d'un rédacteur nettement moins étoilé dans la marge, ne sont pas forcément complètement dépourvues de substance.

    Sur la maintenabilité du code

    C'est moi qui mets en gras le contenu entre parenthèses ci-dessous :
    Citation Envoyé par Lolo78 Voir le message
    Je veux produire du code suffisamment facile à comprendre pour ceux qui vont devoir maintenir ce code (notamment et surtout si c'est moi).
    Je ne sais pas ce qu'il en est pour toi, mais en ce qui me concerne, la personne qui a écrit le code que j'ai pondu il y a trois mois est un étranger complet. On partage sans doute une certaine culture mais il y a de grandes chances que le concept de level qu'il utilisait à l'époque quand l'algorithme était tout chaud dans son crâne soit différent de celui que je vais plaquer maintenant sur la variable $level que j'y trouve. Parce qu'entre temps, j'ai travaillé sur autre chose, d'autres structures de données, avec un level tout aussi pertinent mais différent de celui là.

    Ca n'est pas différent de la situation dans laquelle se trouverait un autre programmeur qui aurait à comprendre et à intervenir sur ce code.

    Quand j'en arrive au point où un code semble fonctionner, j'ai tendance à réduire le nombre de variables (en particulier toute variable qui n'est utilisée qu'une fois est sauf rare exception condamnée à disparaître, exemple ici), et je m'assure que celles qui restent sont vraiment essentielles. J'essaie ensuite de généraliser le code autant que possible, ce qui va déporter un certain nombre de variables à leur vraie place, à savoir des paramètres ou des options, qui sont documentés. Il est rare que je donne un nom très significatif aux variables qui restent à ce stade. Par contre je peux leur associer un commentaire explicatif.

    Résultat : la personne qui aura à intervenir sur ce code, que ce soit moi ou un autre, devra se le réapproprier comme je l'évoquais au début de ce post. Elle ne sera pas distraite ou fourvoyée par une dénomination étrangère ou nébuleuse. Et c'est une bonne chose.

    Cette méthode ne m'est pas venue par hasard. C'est le résultat de 30+ années d'expérience de programmeur dans des langages variés. Mes priorités sont que mon code soit 1) correct 2) maintenable. Si pour les assurer je dois sacrifier une prétendue intelligibilité qui ne serait de toute façon que de facade, je le fais sans remords. Ca ne veut pas dire que je produis du code délibérément obscur. Mais du code concis, oui. Et c'est une vertu.

    Pour qu'on puisse partager une même compréhension d'un code, le plus important est qu'on en ait la même lecture. C'est pourquoi je considère qu'une des premières choses que les débutants doivent maîtriser est la différence entre contexte scalaire et contexte de liste, et la lecture correcte des indexations et tranchages. Cela n'est pas difficile, et évite de s'embarrasser de règles nuisibles, comme l'affirmation "$a[@b] n'a pas vraiment de sens" ou "est un exemple de ce qu'il ne faut pas faire", qui reposent en fait selon moi sur un processus de lecture approximatif, et sont rendues caduques par cette maîtrise. Et pour le coup je reconnais que je t'en veux de propager ce type de "règles" et surtout de persister. Aucune "règle" de ce type ne figure dans les perlfaqs, et ce pour de bonnes raisons.

    Cela ne signifie pas que les conventions de codage soient à jeter. Mais selon moi elles servent plus à faciliter la collaboration au sein d'une équipe qu'à garantir une quelconque qualité. Et en fait, en dehors de conventions de formatage (pour lesquelles le plus simple est de s'aligner sur perlstyle) et peut-être de quelques patrons de codage ou conventions de passage de paramètres, il n'y a pas grand chose à convenir pour peu qu'on lise Perl de la même manière...

    Il reste vrai qu'un programmeur ou un groupe de programmeurs peut bénéficier de garde-fous. Mais pour moi et depuis des années ces garde-fous sont assurés par une politique très agressive de test, que ce soit pour des modules ou pour des scripts. J'en ai donné des exemples dans ce fil. C'est beaucoup de travail. Mais en fin de compte c'est ça qui donne au final le plus confiance quand je dois reprendre mon code. Et si je dois reprendre celui des autres, et que la base de test est inexistante ou me paraît insuffisante, je commence par la créer ou l'étoffer avant même de toucher au code lui même.

    Bon, j'espère ne pas avoir été trop toxique... J'ai probablement tendance à réagir violemment face à certaines recommandations, pour les avoir en fait respectées à un certain stade de mon évolution de programmeur, et pour avoir réalisé plus tard à quel point elles m'avaient nui en réalité... Mais chacun élève sa statue intérieure, et contribue à l'édifice collectif, à sa manière. Ce que j'ai décrit fonctionne pour moi. Que chacun prenne ses responsabilités .

    Et je reste bien entendu ouvert à la discussion
    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. #2
    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 je cherche effectivement à montrer, en particulier aux débutants qui nous lisent, que tes préconisations et celles de Philou67430 demandent en fait beaucoup plus de travail et de discipline qu'il n'y paraît au premier abord, et peuvent même s'avérer piégeuses. Et qu'elles ne sont clairement pas une garantie de qualité, ni même un garde-fou pouvant préserver de certaines erreurs. Et que du coup mes propres recommandations, bien que provenant d'un rédacteur nettement moins étoilé dans la marge, ne sont pas forcément complètement dépourvues de substance.
    Je n'ai pas trouvé dans ton texte qu'une convention de nommage de variable puisse être piégeuse (par convention, disons simplement : une variable => un nom). En revanche, l'usage d'un nom universel de variable (tel que $_) est source de confusion dans des blocs imbriqués.

    Je suis d'accord sur le fait de limiter au maximum de nombre de variables à ce qui est absolument nécessaire (je rencontre souvent du code remplis de variables qui ne servent la plupart du temps à rien ; je les supprime, car elles nuisent à la lisibilité, car on ne comprends pas leur utilité). En outre, ça permet bien souvent de simplifier la problématique/algorithmique.

    Mais pour ce qui est des variables qui restent, leur nommage me semble plus "utile" que "source d'erreur" (et nécessaire la plupart du temps, en dehors d'un contexte "mono-instructionnel").
    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. #3
    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
    Je n'ai pas trouvé dans ton texte qu'une convention de nommage de variable puisse être piégeuse (par convention, disons simplement : une variable => un nom).
    Ce que j'entendais par discipline était une certaine attention à la sémantique et un effort pour ne pas mélanger les notions (cf. $level vs. @level_list).

    Le côté piégeux faisait plutôt référence à l'affectation involontaire à un alias. Quand on déclare la variable de boucle dans un foreach, c'est un alias, pas une copie. Dans le code en référence, affecter quelque chose à $inter (opération banale s'il en est) modifie effectivement le sommaire. C'est très bien si c'est ce qu'on veut, mais est-ce vraiment le cas dans le code cité ? Je crois qu'on y réfléchit un peu plus (l'opération est moins banale) avant d'affecter quelque chose à $_.

    Autrement dit, je crois que dans la majorité des cas d'utilisation un code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach my $var (@list) { ... }
    serait plus sûr et plus conforme à l'intention du programmeur s'il était rédigé plutôt sous la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach (@list) { my $var = $_; ... }
    avec laquelle on ne risque pas d'altération accidentelle de @list.

    Et une fois que l'on a choisi cette seconde forme, se pose le problème de savoir si nommer $_ est vraiment utile...




    En revanche, l'usage d'un nom universel de variable (tel que $_) est source de confusion dans des blocs imbriqués.
    Pas toujours... Dans un projet récent j'avais à travailler sur des données hiérarchiques avec plusieurs niveaux de délimiteurs, de type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TAG/a::b/cde:f:g:h///i:j/k
    dans lequel j'ai des composants séparés par des /, eux même constitués d'élements séparés par des :. Le premier composant est un tag, et pour des besoins d'interface avec d'autres outils j'ai besoin d'associer chaque élement à un nom de la forme TAG_x_y (par exemple, a est TAG_1_1, j est TAG_5_2, etc. J'ai utilisé un code de la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    my ($tag, @c) = split q{/}, ...;
    foreach my $ci (1 .. @c) {
        for ($c[$ci-1]) {
            my @e = split q{:};
            foreach my $ei (1 .. @e) {
                for ($e[$ei-1]) {
                    $h{"${tag}_${ci}_${ei}"} = $_;
                }
            }
        }
    }
    La ligne 7 est juste indicative, pour montrer qu'on dispose à ce stade de toutes les infos pour travailler : le $tag, les indices $ci et $ei (démarrant à 1), et le contenu de l'élément dans $_.
    Ce code illustre un cas où effectivement je déclare une variable de boucle. Mais je le fais parce que j'ai besoin simultanément 1) de l'élément de la liste, et 2) de son index. Et tu noteras que les foreach portent sur les index, pas sur les listes elle-mêmes.
    Il illustre également l'utilisation de la topicalisation par for, pour isoler l'objet d'intérêt à différents points du code, sans pour autant avoir à le nommer. En ligne 3, on isole le composant sur lequel on va travailler. De même, en ligne 6 on isole l'élément sur lequel on va travailler. On en profite dans les deux cas pour faire l'adaptation nécessaire sur l'origine de l'index. Je trouve ça plutôt cool.

    En conclusion, j'aurais tendance à réserver l'utilisation de foreach my $var (...) à deux une situations :
    1. quand j'itère comme ci-dessus sur des index et non sur une liste
    2. quand je suis susceptible de modifier en place la liste passée en paramètre


    [édit : en fait, même pas dans mon code récent : quand je modifie la liste en place j'utilise maintenant systématiquement l'affectation à $_]

    je n'en fais certes pas une préconisation générale, et ne prétends pas m'y astreindre systématiquement, mais il me semble que cela va dans le sens d'une de tes propres préoccupations (c'est moi qui mets en gras ci-dessous)
    Citation Envoyé par Philou67430 Voir le message
    Ces manières de faire me semblent plus robustes face à la maintenance du code (notamment par plusieurs personnes différentes), car elles souffrent moins d'ajouts/suppressions de code. En plus, elles sont souvent plus "lisibles".
    en ce sens que si lors d'un ajout de code on est tenté de nommer la variable de boucle, on doit se poser des questions : est-ce que je ne risque pas de modifier accidentellement la liste ? est-ce que je ne ferais pas mieux de déclarer localement cette variable comme une copie plutôt qu'un alias ?



    Je suis d'accord sur le fait de limiter au maximum de nombre de variables à ce qui est absolument nécessaire (je rencontre souvent du code remplis de variables qui ne servent la plupart du temps à rien ; je les supprime, car elles nuisent à la lisibilité, car on ne comprends pas leur utilité). En outre, ça permet bien souvent de simplifier la problématique/algorithmique.

    Mais pour ce qui est des variables qui restent, leur nommage me semble plus "utile" que "source d'erreur" (et nécessaire la plupart du temps, en dehors d'un contexte "mono-instructionnel").
    On est d'accord en ce qui concerne les variables qui ont survécu à ce nettoyage et cette simplification
    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

  4. #4
    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
    Le côté piégeux faisait plutôt référence à l'affectation involontaire à un alias. Quand on déclare la variable de boucle dans un foreach, c'est un alias, pas une copie. Dans le code en référence, affecter quelque chose à $inter (opération banale s'il en est) modifie effectivement le sommaire. C'est très bien si c'est ce qu'on veut, mais est vraiment le cas dans le code cité ? Je crois qu'on y réfléchit un peu plus avant d'affecter quelque chose à $_.

    Autrement dit, je crois que dans la majorité des cas d'utilisation un code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach my $var (@list) { ... }
    serait plus sûr et plus conforme à l'intention du programmeur s'il était rédigé plutôt sous la forme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach (@list) { my $var = $_; ... }
    avec laquelle on ne risque pas d'altération accidentelle de @list.

    Et une fois que l'on a choisi cette seconde forme, se pose le problème de savoir si nommer $_ est vraiment utile...
    Je pense d'une manière différente, que lorsqu'un débutant apprend que l'élément d'une boucle est un alias (c'est valable pour un pratiquant habituel aussi), ce n'est pas son nommage qui lui permet d'identifier qu'il s'agit d'un alias.
    De plus, le non nommage explicite de cet élément "aliasé" offre plus facilement le risque de modification non désiré de la liste d'origine tant les fonctions/opérateurs utilisant le topic $_ comme valeur par défaut sont courants. Je pense donc exactement à l'inverse.

    En fait, je m'aperçois que j'ai tendance, quand cela n'est pas trop complexe, à utiliser map en lieu et place d'un foreach pour modifier une liste (ce qui me semble rendre compte plus facilement de la topicalisation du traitement de liste). Mais je n'en fait pas une règle générale.

    En tout cas, je préfère nettement le ton de la discussion ici même.
    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

  5. #5
    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
    Je pense d'une manière différente, que lorsqu'un débutant apprend que l'élément d'une boucle est un alias (c'est valable pour un pratiquant habituel aussi), ce n'est pas son nommage qui lui permet d'identifier qu'il s'agit d'un alias.
    De plus, le non nommage explicite de cet élément "aliasé" offre plus facilement le risque de modification non désiré de la liste d'origine tant les fonctions/opérateurs utilisant le topic $_ comme valeur par défaut sont courants. Je pense donc exactement à l'inverse.
    Pour le coup on n'est effectivement vraiment pas d'accord.

    Il me semble que ton argument ne tient pas car l'écrasante majorité de ces fonctions/opérateurs qui utilisent le topic $_ par défaut ne le font pas en tant que lvalue : alarm, chomp, chop, chr, chroot, close, cos, defined, eval, exit, exp, glob, hex, int, lc, lcfirst, length, log, lstat, m//, mkdir, oct, ord, pos, print, quotemeta, rand, readlink, readpipe, ref, require, reverse, rmdir, say, sin, sleep, sqrt, split, study, uc, ucfirst, unlink, etc. (j'en ai peut-être oublié...) ne modifient pas $_.

    [édit: eh non, chomp et chop modifient leur argument! Merci Lolo78 et Philou67430]

    Ok, chomp, chop, s/// et tr/// ou y/// le font, mais ce sont des exceptions très spécifiques.

    Quand à map et grep :
    En fait, je m'aperçois que j'ai tendance, quand cela n'est pas trop complexe, à utiliser map en lieu et place d'un foreach pour modifier une liste (ce qui me semble rendre compte plus facilement de la topicalisation du traitement de liste).
    Je me rappelle de guerres enflammées sur l'utilisation de map en contexte vide, ce qui est si je comprends bien ce que tu suggères ici, par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/tttmp $ perl -WE '@a = 1 .. 4; map { $_ *= 2 } @a; say "@a"'
    2 4 6 8
    Taisha:~/tttmp $
    Avant 5.8.1 cette construction était découragée pour une raison d'efficacité, car map produisait alors quand même une liste qui était immédiatement jetée. Depuis 5.8.1 ce n'est plus le cas mais je reconnais avoir pris à l'époque l'habitude d'utiliser plutôt un foreach qu'un map en contexte vide...

    L'argument le plus convaincant pour moi à l'époque était qu'on dispose de deux outils pour opérer sur une liste : foreach, et map. Cela a un sens de réserver map pour les cas où on veut produire une liste, et foreach pour les autres utilisations. Et quand je vois un map en contexte vide je le demande vraiment pourquoi on n'a pas employé un foreach...

    Il y a certes une subtilité liée au contexte d'évaluation : map expr, ... ou map {...} ... imposent un contexte de liste lors de l'évaluation de expr ou du bloc, alors que ce n'est pas le cas pour foreach. Si on a vraiment besoin de ce contexte de liste avec un foreach, il faut le forcer comme en lignes 7 et 9 ci-dessous:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Taisha:~/tttmp $ perl -E 'sub foo { say wantarray ? 1 : 0 }; map { foo } qw(0)'
    1
    Taisha:~/tttmp $ perl -E 'sub foo { say wantarray ? 1 : 0 }; do { foo } foreach qw(0)'
    0
    Taisha:~/tttmp $ perl -E 'sub foo { say wantarray ? 1 : 0 }; foreach (qw(0)) { do { foo } }'
    0
    Taisha:~/tttmp $ perl -E 'sub foo { say wantarray ? 1 : 0 }; () = do { foo } foreach qw(0)'
    1
    Taisha:~/tttmp $ perl -E 'sub foo { say wantarray ? 1 : 0 }; foreach (qw(0)) { () = do { foo } }'
    1
    Taisha:~/tttmp $
    mais franchement ça me paraît académique (je ne me souviens pas en avoir jamais eu besoin). Et si ça devait m'arriver, pour documenter cette dépendance inhabituelle à un contexte de liste, j'utiliserai probablement quand même les formes en lignes 7 et 9 ci-dessus plutôt qu'un map en contexte vide.

    Il n'est pas fréquent que j'utilise map à la fois pour la liste retournée et pour des effets de bord. Si je le fais je le documente. Mais je ne me souviens pas avoir jamais délibérément 1) retourné une liste et 2) modifié la liste d'origine dans un même map.

    Quoi qu'il en soit effectivement rien ne t'empêche d'utiliser map comme tu le proposes, même si ça risque de me faire soupirer quand j'en verrai dans ton code

    En tout cas, je préfère nettement le ton de la discussion ici même.
    Je t'entends. J'assume, mais je vais essayer de mieux me tenir
    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. #6
    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 me revient Une autre raison pour laquelle je n'utilise pas map en contexte vide est que des warnings utiles ne sont alors pas émis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Taisha:~/tttmp $ perl -wE 'chr foreach 32'
    Useless use of chr in void context at -e line 1.
    Taisha:~/tttmp $ perl -wE 'map { chr } 32'
    Taisha:~/tttmp $
    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

  7. #7
    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
    Ouah, CMC, ouvrir un post de plus de 2200 mots juste pour m'attaquer, avec pas moins de cinq citations nommément attribuées mas retirés de leur contexte, tu me fais vraiment trop d'honneur.

    DSL, je n'ai pas le temps de répondre point par point (en tout cas pas maintenant), je vais juste en relever quelques uns.

    Et tu noteras par ailleurs j'espère que je ne rechigne pas à accompagner les demandeurs dans ce travail d'appropriation lorsqu'ils ont des difficultés.
    Je te rends bien volontiers cette justice, je l'ai moi-même constaté par écrit.

    Pour moi hors contexte c'est incompréhensible. Pourquoi $nb_prestas et pas $nb_b ? Qu'est-ce qu'il y a dans @b ? C'est le tableau des prestas ? Alors, surement il devrait s'appeler @prestas, non ? Ou bien est-ce qu'on découvre incidemment que la taille de @b est identique au nombre de prestas, et c'est cela qu'on commente ? Est-ce qu'on se sert de $nb_prestas ailleurs dans le bloc ? Etc.
    Ce n'est pas intellectuellement honnête de ta part. C'est toi qui avait nommé un tableau @b et j'avais juste repris ton exemple en disant que je préférais désigner la variable contenant le nombre d'éléments du tableau avec un nom donnant du sens, par exemple un nom rappelant qu'il s'agit du nombre de presta.

    Quant à tes critiques sur un bout de programme posté à la va-vite à 1h35 du matin (et tu le sais pertinemment je te l'ai déjà fait remarquer), posté juste pour donner une idée d'algorithme différent pour résoudre le problème, franchement, je ne vois pas ce qui me vaut cet acharnement de ta part à mon égard. Peut-être le fait que ce code marchait du premier coup et pas le tien

    ... parce qu'en tant que 'Membre Expert' il me semble que tu aurais vocation à être exemplaire...
    Tu sais certainement aussi bien que moi que je n'ai jamais sollicité une telle bannière, elle est attribué automatiquement par le site en fonction du nombre d'interventions et sans doute de "points positifs" reçus.

  8. #8
    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
    Pour le coup on n'est effectivement vraiment pas d'accord.

    Il me semble que ton argument ne tient pas car l'écrasante majorité de ces fonctions/opérateurs qui utilisent le topic $_ par défaut ne le font pas en tant que lvalue : alarm, chomp, chop, chr, chroot, close, cos, defined, eval, exit, exp, glob, hex, int, lc, lcfirst, length, log, lstat, m//, mkdir, oct, ord, pos, print, quotemeta, rand, readlink, readpipe, ref, require, reverse, rmdir, say, sin, sleep, sqrt, split, study, uc, ucfirst, unlink, etc. (j'en ai peut-être oublié...) ne modifient pas $_.

    Ok, s/// et tr/// ou y/// le font, mais ce sont des exceptions très spécifiques.
    Le fait que $_ ne soit pas une lvalue n'empêche pas les confusions (les erreurs engendrées sont "moins grave", donc peut-être encore moins détectables que lorsque $_ est utilisée en lvalue).
    Quant à l'exception s/// (de manière moindre tr et y), c'est une exception exceptionnelle par son usage généralement massif en perl.

    Quand à map et grep :
    Je me rappelle de guerres enflammées sur l'utilisation de map en contexte vide
    ...
    L'argument le plus convaincant pour moi à l'époque était qu'on dispose de deux outils pour opérer sur une liste : foreach, et map. Cela a un sens de réserver map pour les cas où on veut produire une liste, et foreach pour les autres utilisations. Et quand je vois un map en contexte vide je le demande vraiment pourquoi on n'a pas employé un foreach...
    Je l'avais indiqué dans ma réponse initiale, mais je l'ai perdue lors d'une fausse manip sous Firefox. Je voulais bien parler d'un map en contexte de liste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @liste = map { calcule_nouvel_element($_) } @liste
    (ceci est un exemple, je n'utilise pas systématiquement le même tableau à droite et à gauche).
    Il n'est pas fréquent que j'utilise map à la fois pour la liste retournée et pour des effets de bord. Si je le fais je le documente. Mais je ne me souviens pas avoir jamais délibérément 1) retourné une liste et 2) modifié la liste d'origine dans un même map.
    Je l'évite également.
    Quoi qu'il en soit effectivement rien ne t'empêche d'utiliser map comme tu le proposes, même si ça risque de me faire soupirer quand j'en verrai dans ton code
    Je te rassure sur ce point, ce genre de code me fait aussi soupirer.
    Je t'entends. J'assume, mais je vais essayer de mieux me tenir
    C'est le prix à payer pour disposer d'interlocuteurs
    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

  9. #9
    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
    Citation Envoyé par cmcmc Voir le message
    Il me semble que ton argument ne tient pas car l'écrasante majorité de ces fonctions/opérateurs qui utilisent le topic $_ par défaut ne le font pas en tant que lvalue : (...) ... chop, etc. (j'en ai peut-être oublié...) ne modifient pas $_.
    Ben, ça modifie quand même le contenu, non?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ~
    $ perl -e '@c = qw/toto titi/; map {chop} @c; print "@c"'
    tot tit

  10. #10
    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
    Ouah, CMC, ouvrir un post de plus de 2200 mots juste pour m'attaquer, avec pas moins de cinq citations nommément attribuées mas retirés de leur contexte, tu me fais vraiment trop d'honneur.
    J'admets avoir été trop sarcastique, tu as raison de pointer que certaines citations étaient hors contexte (même si je donnais le lien permettant de l'atteindre, ce que tu ne fais pas toujours ), il y a des clous que je n'aurais pas dû enfoncer. D'un autre côté je suis un peu maniaque, et ce que j'ai considéré -- peut-être à tort -- comme de la légèreté dans certaines de tes réponses m'avait fait voir rouge. Ce n'était pas le cas pour les dernières, j'aurais dû en tenir compte, je ne l'ai pas fait, je le regrette, et je te prie de bien vouloir accepter mes excuses.

    Ceci dit, ne prends pas le melon , le post en question n'a en aucune manière été composé pour t'attaquer personnellement. La première et troisième parties ne te visent pas (ah si, un peu, sur les règles "nuisibles", si tu veux revenir dessus fais-le s'il te plait dans un message séparé dans ce fil). Et pour la seconde, il se trouve simplement qu'un code que tu as écrit s'est trouvé être le support d'une partie de mon argumentation, celle qui allait contre la préconisation de Philou67430 de toujours déclarer la variable de boucle d'un foreach. Sur ce sujet précis, considère toi comme une victime des circonstances, pas comme une cible. La discussion sur ce point précis est vive dans ce fil, et je suis curieux d'avoir ton avis.

    Pour @b/$nb_prestas, je pourrais te renvoyer l'argument d'honnêteté intellectuelle. Je défendais initialement les formes $x = $a[@b] ou à la rigueur $x=$a[scalar(@b)] qui me paraissent parfaitement saines. Tu objectes au nom de la clarté, et proposes en remplacement un combo "my $nb_prestas = @b; $x = $a[$nb_prestas]". Excuse moi mais je maintiens mes objections. Présente moi un exemple réel extrait d'un code de production. Et si cet exemple est "my $nb_prestas = @prestas; $x = $a[$nb_prestas]" et que $nb_prestas n'est pas utilisé ailleurs dans le bloc, je maintiendrai que tu as perdu ton temps et celui du lecteur du code.

    Pour les level, je te ferai remarquer que j'avais auparavant essayé de pointer poliment la maladresse que j'ai finalement mis en exergue. Ma remarque pour autant qu'on sache de quel level on parle (ici) visait précisément cette ambiguité $level/@level_list. C'était peut-être un peu trop discret, comme les précédentes ici et ici, que j'avais été obligé de développer pour qu'on comprenne à quoi je faisais référence, puisque tu y avais répondu de manière agressivement défensive ("c'est bien moins clair", "tu sembles penser que la clarté ne sert à rien") et sans un mot d'explication, qu'il a fallu te faire accoucher.

    Alors je reconnais que tu m'avais passablement chauffé avec la clarté, et qu'il était difficile de résister à exhiber le clash $level/@level_list dans la mesure ou tu t'étais donné la peine de mettre en exergue l'introduction de $level comme "un moyen d'auto-commenter le code". D'autant plus que, très intéressé par le fil en question, je me suis naturellement penché sur ton code. Tu l'avais bien publié pour ça, non ? Et qu'en fait de clarté, j'ai du me débattre avec des fragments de code inutiles (excusables quoique trompeurs : en quoi est-ce important pour l'algorithme ? ), une constante manifeste (excusable également), des nommages contradictoires (moins excusables étant donné ton attachement vigoureusement affirmé à la clarté).

    Soyons clairs : ce qui m'intéresse en premier lieu dans cette discussion, ce sont les "bonnes pratiques" au sens où elles facilitent la production d'un code correct et maintenable. Ce qui tend à faire tourner les discussions sur le style, les conventions et les pratiques de codage à des guerres enflammées, c'est souvent l'affrontement de deux prétentions : chacun prétend détenir la vérité, sa recette pour atteindre le Graal du code correct et maintenable.

    Le juge de paix, c'est le code effectivement produit.

    Et l'objectif de s'imbiber de bonnes pratiques est selon moi d'être capable de produire un code correct et maintenable en toutes circonstances, y compris en situation de stress ou de fatigue. Sur quoi je considère, arguments à l'appui, que l'auteur de l'exemple donné n'as pas complètement réussi. Il se trouve que c'est toi. Mais comprends bien que ce n'est pas toi que j'attaque, mais plutôt une pratique qui me semble en fait contre-productive, en l'occurrence un attachement à une clarté que je trouve passablement nébuleuse. Comme je l'ai écrit, la substance de ma position est
    Mes priorités sont que mon code soit 1) correct 2) maintenable. Si pour les assurer je dois sacrifier une prétendue intelligibilité qui ne serait de toute façon que de facade, je le fais sans remords.
    et j'attends avec intérêt tes commentaires ou réfutations.

    Bon, je crois avoir à peu près vidé l'abcès en ce qui me concerne. Je te réitère mes excuses, espère sincèrement que nos échanges vont continuer, et m'engage à faire de mon mieux pour rester civil dans l'avenir.
    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. #11
    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
    Ben, ça modifie quand même le contenu, non?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ~
    $ perl -e '@c = qw/toto titi/; map {chop} @c; print "@c"'
    tot tit
    Bien vu ! +1 et Merci !
    (j'édite immédiatement le message en question).
    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

  12. #12
    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
    Citation Envoyé par cmcmc Voir le message
    Bon, je crois avoir à peu près vidé l'abcès en ce qui me concerne. Je te réitère mes excuses, espère sincèrement que nos échanges vont continuer, et m'engage à faire de mon mieux pour rester civil dans l'avenir.
    J'aimerais avoir le temps de te répondre point par point, mais, bon DSL, la seconde partie de mon tuto sur la programmation fonctionnelle en Perl est pour moi prioritaire (et je peux te dire que c'est vraiment chronophage d'essayer de faire quelque chose de bien). Je prendrai peut-être le temps de répondre (j'aimerais vraiment le faire, pas juste pour te montrer que j'ai raison ou crois avoir raison, cela ne m'intéresse que modérément, mais aussi pour recueillir ton avis), mais je n'ai pas le temps tout de suite.

    Pour moi, il n'y a pas d'abcès, pas de problème entre nous. J'accepte volontiers tes excuses, bien que je n'en ai pas demandé. Et je te présente les miennes si je t'ai choqué le moins du monde.

    Et je suis super content de voir de nouvelles têtes sur ce site, même si nous ne sommes d'accord sur tout.

  13. #13
    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 Lolo78 Voir le message
    Et je suis super content de voir de nouvelles têtes sur ce site, même si nous ne sommes d'accord sur tout.
    [ame="http://www.youtube.com/watch?v=fFjH2wrvRgw"]Ça c'est vrai ça[/ame]
    ... mince, ça ne nous rajeuni pas.
    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

  14. #14
    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
    Bien vu ! +1 et Merci !
    (j'édite immédiatement le message en question).
    J'avais aussi oublié de la dire dans ma réponse.
    Au passage, il y a aussi son compagnon : chomp

    Par ailleurs, même si elles ne modifient pas $_, certaines fonctions ont des effets de bord non négligeables : alarm, chroot, close, eval, exit, mkdir, print, readpipe, require, rmdir, say, sleep, study, unlink.
    Certes, les tests permettent d'identifier certains mauvais usages, mais certains effets de bords non désirés ne sont toujours facilement détectables.
    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. #15
    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
    Je pense d'une manière différente, que lorsqu'un débutant apprend que l'élément d'une boucle est un alias (c'est valable pour un pratiquant habituel aussi), ce n'est pas son nommage qui lui permet d'identifier qu'il s'agit d'un alias.
    Bon, après plusieurs lectures dont la dernière à tête reposée je ne comprends toujours pas ce que tu veux dire. Peux tu t'expliquer sur un exemple ?

    Citation Envoyé par Philou67430 Voir le message
    Le fait que $_ ne soit pas une lvalue n'empêche pas les confusions (les erreurs engendrées sont "moins grave", donc peut-être encore moins détectables que lorsque $_ est utilisée en lvalue).
    Là non plus. De quelles confusions veux-tu parler? Peux tu donner un exemple ?
    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

  16. #16
    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
    J'expliquais (dans l'autre discussion), que lorsque l'étendue de l'utilisation d'un topic est limitée, il n'est pas "pénalisant" (en terme de lisibilité/maintenance) d'utiliser $_ (notamment si l'étendue en question n'inclue pas des sous-blocs).
    Donc une étendue comme celle proposée par given/when, map, grep, ne me semble pas à priori un problème pour l'usage de $_ en tant que topic courant.
    En revanche, dès lors que l'étendue est importante (nombreuses instructions, imbrications de boucles et de test), le topic varie au fil du programme, mais son nom ($_) ne varie jamais. C'est de cette confusion dont je parle.

    Ainsi, entre écrire :
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unlink $intermediate_file;
    j'y vois une différence essentielle qui est que dans le 2e cas, on connait immédiatement le sujet sur lequel on fait le unlink.

    Bien entendu, s'il s'agit de ne supprimer qu'une liste de fichier sans autre traitement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    foreach (@files) {
      unlink;
    }
    est tout à fait acceptable. Et dans ce cas, je préfère même
    (non pas pour la concision, mais pour "montrer" que ce qui est important dans cette instruction, c'est que l'on souhaite supprimer des fichiers, plutôt que "montrer" que l'on veut boucler sur une liste de fichier pour faire quelque chose).

    Dans le même ordre d'idée, dirais-tu également qu'il faut topicaliser avec $_ un objet perl (blessed reference) ? (pour ma part, il est toujours nommé $self).
    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. #17
    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
    En revanche, dès lors que l'étendue est importante (nombreuses instructions, imbrications de boucles et de test), le topic varie au fil du programme, mais son nom ($_) ne varie jamais. C'est de cette confusion dont je parle.
    Ça ne m'a jamais paru être un problème ou une source de confusion. C'est en tout point du programme l'objet instantané du discours ou de l'action, et l'entité dont il s'agit est facile à identifier. Mais OK, admettons.

    Le sujet est je le rappelle de prévenir la modification accidentelle de la liste source d'un foreach (cf $inter/@sommaire dans le message initial de ce fil).

    Et je ne comprends toujours pas pourquoi tu rejettes l'alternative 'sécurisée' que je te propose
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach (@sommaire) { my $inter = $_; ... }
    qui évite de travailler sur $_ dans le reste du bloc et prévient toute modification accidentelle de @sommaire via une affectation à $inter, car cette dernière est alors une copie et non un alias.

    Dans la très grande majorité des cas, la liste source n'est pas modifiée (ou ne devrait pas l'être). Déclarer la variable à l'extérieur dans un tel cas, et donc en faire un alias, c'est de mon point de vue armer son pistolet pour se tirer dans le pied :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    foreach my $inter (@sommaire) {
        ...
        ...
        ...
        $inter = ...; #BOOOOOOOOOOM
        ...
    }
    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. #18
    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
    Le sujet est je le rappelle de prévenir la modification accidentelle de la liste source d'un foreach (cf $inter/@sommaire dans le message initial de ce fil).
    Il m'avait semblé que le sujet était plus largement axé sur le style de programmation, mais OK, admettons
    Et je ne comprends toujours pas pourquoi tu rejettes l'alternative 'sécurisée' que je te propose
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foreach (@liste) { my $var = $!; ... }
    qui évite de travailler sur $_ dans le reste du bloc et prévient toute modification accidentelle de @liste via une affectation à $var, qui est alors une copie et non un alias.
    Je ne crois pas avoir dit que je rejetais cette alternative.
    Je crois avoir dit que je rejetais la boucle foreach sans élément nommé (et j'ai donné en exemple le classique nommage par "alias").
    Je trouve d'ailleurs que cet alias ne devrait pas être fait "par défaut", comme, dans un autre contexte, l'auto-vivification.

    On aurait par exemple pu imaginer qu'un opérateur/fonction (autre que foreach) ait été créé pour topicaliser sous forme d'un alias (forthis par exemple). Il semble que l'aliasing est présent pour des raisons de rapidité d'exécution.

    Dans la très grande majorité des cas, la liste source n'est pas modifiée (ou ne devrait pas l'être). Déclarer la variable à l'extérieur dans un tel cas, et donc en faire un alias, c'est de mon point de vue armer son pistolet pour se tirer dans le pied :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    foreach my $inter (@sommaire) {
        ...
        ...
        ...
        $inter = ...; #BOOOOOOOOOOM
        ...
    }
    Et c'est d'autant plus facile à faire avec les opérateurs/fonctions sur le topic. Ici, on visualise clairement qu'on agit sur l'élément du tableau et on voit que c'est un alias parce qu'il est défini dans le foreach. Si l'on avait eu $_ (avec s/// par exemple, ou chomp), ça me parait moins clair.
    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. #19
    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
    Il m'avait semblé que le sujet était plus largement axé sur le style de programmation, mais OK, admettons
    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 $_

    Je ne crois pas avoir dit que je rejetais cette alternative.
    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.

    Ici, on visualise clairement qu'on agit sur l'élément du tableau et on voit que c'est un alias parce qu'il est défini dans le foreach.
    Seulement si on y est attentif, ce qui est difficile à assurer sur un bloc étendu, et c'est le cœur de mon argument. Un scénario possible qui pourrait expliquer cette écriture involontaire dans @sommaire serait que les lignes 16 et 17 aient été initialement confondues:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    push @new_sommaire, join '-', @out[0..$level];
    et que pour faciliter le suivi dans un debugger ou rajouter une instruction de trace, l'auteur ait été amené à les décomposer. Je ne dis pas que c'est ce qui s'est passé, mais c'est certainement quelque chose qui pourrait m'arriver. Effet tunnel classique : je peux utiliser $inter pour ça, je ne m'en sert plus d'ici la fin du bloc, l'instruction est découpée, je rajoute un warn de trace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            ...
            ...
            $inter = join '-', @out[0..$level];
            warn $inter;
            push @new_sommaire, $inter;
            $level_list[$_] = 0  for ($level+1..$#master_list);
    }
    Je teste, je vérifie que ça marche, je vire le warn, et je passe à autre chose. Patatras.

    Ce qui se passe ici est que la déclaration de $inter comme alias est trop loin des lignes sur lesquelles on est en train de se concentrer. Et que rien n'indique localement que $inter est d'une autre nature que les variables locales @fields, $level, @out que j'ai sous les yeux ou à portée. Et c'est ce qui rend cette déclaration de $inter dangereuse à mes yeux.

    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 ce scénario est je pense impossible si $inter n'est pas déclarée du tout. Parce que même fatigué il est inimaginable que je découpe la ligne comme suit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            ...
            ...
            $_ = join '-', @out[0..$level];
            warn $_;
            push @new_sommaire, $_;
            $level_list[$_] = 0  for ($level+1..$#master_list);
    }
    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 ?
    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. #20
    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
    CMC, je n'ai pas eu et n'ai toujours pas le temps de te répondre en détail sur touts les points que tu soulèves, mais il y a au moins un point que je dois corriger. Tu me prêtes des intentions que je n'avais pas et surtout des bugs qui n'existent pas, si ce n'est dans ton esprit. Le programme que j'ai présenté marche et n'a pas de bug (ou en tout cas pas celui que tu crois voir). Dire, comme tu le fais, que ça aurait pu être un bug si le programme avait fonctionné autrement, c'est de la fiction et de l'enfantillage. Il y a d'un côté ton imagination et de l'autre la réalité. Oui, si le programme avait fonctionné autrement, ça aurait peut-être été un dysfonctionnement, mais il se trouve qu'il ne fonctionne pas autrement et qu'il fonctionne bien.

    Pour information, mon intention initiale était bel et bien de modifier le tableau d'origine @sommaire, ce qui ne pose aucune espèce de problème puisqu'il ne sert qu'une fois. Et mon programme a fonctionné de cette façon, et il fonctionnait très bien, j'ai pu l'observer. J'ai changé ensuite d'avis et créé au dernier moment le nouveau tableau @new_sommaire uniquement parce que, pour une solution complète (que je n'ai pas eu le temps de coder), il fallait encore retirer de la liste les éléments de sommaire avec une astérisque (et leurs fils) et qu'il aurait pu être scabreux de retirer des éléments d'une liste que je parcourais avec une boucle for. C'est pour cette raison que j'ai ajouté au dernier moment la ligne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    push @new_sommaire, $inter;
    ajouté la déclaration de ce tableau et modifié le print final.

    Je n'avais alors aucune raison de modifier le reste du code, puisqu'il marchait déjà très bien. Dans un contexte réel et surtout avec un peu de temps, j'aurais sans doute aussi pris la peine de créer une nouvelle variable ou de "pousser" (push) directement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    join '-', @out[0..$level]
    dans le nouveau tableau. Pas à une heure et demie du matin.

    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. Cela ne fait d'ailleurs qu'affaiblir considérablement tes démonstrations.

    Des bugs, j'en écris sans doute plusieurs fois par semaine (et j'en corrige sans doute au moins autant). Je n'aurais donc aucune raison de me vexer que tu me dises qu'il y ait un bug dans mon programme, cela aurait pu très bien arriver. Mais je commence à trouver assez pénible que tu veuilles absolument en trouver un là où il n'y en avait pas (ou, du moins, pas celui dont tu crois avoir décelé qu'il aurait pu exister si les choses avaient été différentes que ce qu'elles sont), 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.

    Sur ce, j'en ai un peu assez de devoir perdre mon temps à me justifier, j'ai bien mieux à faire. J'espérais prendre le temps de te répondre sur le fond un de ces jours, mais je crois que je vais renoncer. Je suis tout-à-fait prêt à avoir une discussion franche et ouverte avec quelqu'un ayant des opinions divergentes des miennes et désirant les confronter loyalement, 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. Une discussion constructive, oui, un duel ou un combat de coqs, non merci. Bref, je n'ai plus trop envie d'intervenir sur ce fil.

    Bonsoir à tous.

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