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 :

Réduction de liste


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 david0o Voir le message


    Vindiou !
    Je pensais pas que ma petite question provoquerai autant de réflexion !
    Désolé, j'ai pas le trop le temps de tout décortiquer tout de suite (je travail en alternance, et là faut que je passe à tout autre chose, mais j'y reviendrai). En tout cas je suis épaté !
    J'ai bien l'impression que cela dépasse (largement) mon niveau, et comme le dit Lolo78, je n'en demandais pas tant. Ce que j'ai me suffit (pour l'instant...).
    J'ose espérer trouver le temps de comprendre tout ça ceci dit.
    C'était une question intéressante

    Comme je l'écrivais, j'ai tendance à code de manière un peu compacte pour pouvoir démontrer dans des conditions de place raisonnables le fonctionnement de mes propositions. N'hésite pas à poser des questions s'il y a des choses que tu ne comprends pas. En particulier l'utilisation que je fais de fonctions anonymes n'a rien de magique ou de complexe, c'est juste un coup à prendre.

    SI tu as peu de temps, je te conseille de te concentrer sur la version bog (ici) et en particulier sur la fin du post (avec un reader et un writer adaptés je crois pile poil à ton besoin).

    Citation Envoyé par david0o Voir le message
    Merci, ça fait plaisir
    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
    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
    Allez, on ne se décourage pas, encore une petite pour la route

    Un petit problème avec la fonction pr est que c'est elle qui est en charge de l'itération sur les données d'entrée. Imaginons qu'on travaille sur des enregistrements extraits d'une base de données avec DBI. Un scénario d'utilisation basique est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      $sth = $dbh->prepare("SELECT foo, bar FROM table WHERE baz=?");
     
      $sth->execute( $baz );
     
      while ( $ary_ref = $sth->fetch ) {
        print "@$ary_ref\n";
      }
    Sachant qu'on a des millions d'enregistrements dans la base, on n'a pas envie de les changer en mémoire pour les passer à pr... Dans ce cas on pourrait bien sûr définir un reader adapté mais on perdrait en lisibilité. En fait ici l'idéal serait de remplacer l'appel à print ci-dessus par une alimentation item par item de l'algorithme.

    Qu'à cela ne tienne, on va remplacer notre fonction pr par un objet procédural, par exemple :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    Taisha:~/perl/forum $ cat Prop.pm
    use strict;
    use warnings;
    package Prop;
     
    sub new {
        my ($class, %h) = @_;
        my ($reader, $writer, $starter, $combiner, $builder) = @h{qw(reader writer starter combiner builder)};
        bless [undef, $reader, $writer, $starter, $combiner, $builder], $class;
    }
     
    sub set_reader {
        my $self = shift;
        $self->[1] = shift;
    }
     
    sub step {
        my $self = shift; 
        my ($writer, $starter, $combiner, $builder) = @{$self}[2..5];
        for my $item (@_) {
    	my $group = $self->[0];
    	if (!defined($group) or $starter->($group, $item)) {
    	    $writer->($group) if defined($group);
    	    $self->[0] = $builder->($item);
    	} else {
    	    $combiner->($group, $item);
    	}
        }
    }
     
    sub finish {
        my $self = shift;
        my ($group, $writer) = @{$self}[0,2];
        $writer->($group) if defined($group);
        $self->[0] = undef;
    }
     
    sub slurp {
        my $self = shift;
        my $reader = $self->[1];
        while (defined(my $item = $reader->())) {
    	step($self, $item);
        }
        finish($self);
    }
     
    1;
    Taisha:~/perl/forum $
    Que l'on peut utiliser comme suit :
    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
    32
    33
    34
    35
    36
    37
    Taisha:~/perl/forum $ perl -MProp -MList::MoreUtils=natatime -E 'do "l.pl";
    my $prop = Prop->new(
        writer   => sub { say "@{$_[0]}" },
        starter  => sub { $_[0][0] ne $_[1][0] },
        combiner => sub { $_[0][1] = $_[1][1] if $_[1][1] > $_[0][1] },
        builder  => sub { [ @{$_[0]} ] }
        );
    say "------ step & finish";
    $prop->step($_) for @l;
    $prop->finish;
    say "------ multi-step & finish";
    my $it = natatime(3, @l);
    while (my @x = $it->()) { $prop->step(@x) }
    $prop->finish;
    say "------ slurp";
    $prop->set_reader(do { my $lpos; sub { $lpos < @l ? $l[$lpos++] : undef }});
    $prop->slurp;
    '
    ------ step & finish
    id1 12.7
    id2 6.5
    id3 7.8
    id4 15.6
    id1 9.3
    ------ multi-step & finish
    id1 12.7
    id2 6.5
    id3 7.8
    id4 15.6
    id1 9.3
    ------ slurp
    id1 12.7
    id2 6.5
    id3 7.8
    id4 15.6
    id1 9.3
    Taisha:~/perl/forum $
    En mode slurp (qui impose de fournir un reader), l'objet itère directement sur les données d'entrée. C'est comparable à utiliser pr.

    En mode step & finish, pas de reader, on lui donne à manger item par item. Ca irait pile poil pour le scénario ci-dessus, avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      my $prop = Prop->new(....);
      ...
      while ( $ary_ref = $sth->fetch ) {
        $prop->step($ary_ref);
      }
      $prop->finish;
    Le mode multistep & finish est équivalent, à ceci près qu'on peut fournir plusieurs items à chaque step (pratique si l'on lit la base de données par pages, par exemple via fetchall_arrayref).
    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

  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
    C'est vrai et j'aurais pu me limiter à la solution initiale et laisser le demandeur s'en débrouiller. J'avoue qu'étant donné les efforts fournis pour expliciter la démarche, montrer les dangers, justifier en détails l'implémentation, fournir des exemples, analyser le comportement en termes d'occupation mémoire, etc... le fait que personne ne se soit donné la peine de qualifier ce fil d'intéressant, ou (à part peut-être le demandeur initial) de ces contributions, est assez décourageant .
    La richesse est dans la multitude (de solutions).
    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
    Ca aura pris du temps mais j'ai enfin une version de la solution initiale sans duplication de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Taisha:~/perl/forum $ perl -E 'do "l.pl"; sub X::DESTROY { say "@{$_[0]}" } for (@l) {if ($_->[0] ne $g->[0]) {$g = bless [@$_], 'X' } else { $g->[1] = $_->[1] if $_->[1] > $g->[1] }}'
    id1 12.7
    id2 6.5
    id3 7.8
    id4 15.6
    id1 9.3
    Taisha:~/perl/forum $
    Muhahahahaha You just gotta love Perl.
    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
    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
    Le gain associé à la factorisation des ID est limité. Au mieux on gagne 50% sur la taille d'un item. La consommation mémoire est bien en O(taille_du_plus_grand_groupe), donc parler d'un coût mémoire a priori faible ne me semble pas avoir de sens.
    Là, tu as tronqué la citation. Je précisais dans la phrase suivante qu'il était faible notamment par rapport à un:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ... = map { ...} map {...} LIST
    que tu présentais comme fonctionnellement équivalent, mais qui duplique plusieurs fois les données derrière la scène.

    Et il est faible si les données ressemblent à celles présentées par l'OP et n'ont pas la forme pathologique que tu sembles redouter.

    Je travaille assez souvent sur des fichiers ayant des centaines de millions d'enregistrements avec à chaque fois typiquement 5 à 20 enregistrements pour une même entité (par ex. un même client, mais il y a 35 millions de clients dans mon cas de figure). Regrouper ces 5 à 20 enregistrements dans un itérateur pour renvoyer la structure de données relative à un client au code appelant a un coût mémoire très faible, négligeable, même. Et pour comparer par exemple deux fichiers de ce type, j'ai deux exemplaires de cet itérateur (créés avec le même code), un pour chaque fichier, et, dans mon code appelant, je n'ai plus à comparer, pour chaque client, que des structures de données de faible dimension, déjà reformatées et éventuellement triées pour permettre une comparaison facile. Cela simplifie vraiment le travail.

    Tous les problèmes ne sont pas du même type, certes, mais c'est tout de même assez typique comme cas de figure.

    Citation Envoyé par cmcmc Voir le message
    L'idée est intéressante. A priori il y a quelques petits trucs qui me gênent, comme la copie en ligne 3 ci-dessus, ou la nécessité d'initialiser $max (ce qui ne s'est jamais avéré necessaire dans les différentes incarnations de ma solution). Je serais curieux de voir son implémentation en "code de production".
    La copie est juste là pour figurer (représenter) des données locales à la fermeture (et ne pas modifier, en l'occurrence, @_). La copie est inutile si je me moque de modifier @_ au fur et à mesure que je prélève des données. Dans la vraie vie, c'est probablement l'ouverture d'un fichier qui aurait lieu là, et c'est le file handle qui serait local à la fonction d'itération, et l'itérateur se contenterait de lire les lignes du fichier une à une.

    Initialiser $max n'est nécessaire que pour ne pas avoir de warning ("use of initialized value ..."). Plusieurs de tes solutions auraient ce warning si tu prenais la peine d'activer les warnings.

    Citation Envoyé par cmcmc Voir le message
    Je rappelle cependant que j'avais immédiatement émis des réserves sur cette solution, à cause de la duplication du code d'émission du résultat.
    C'est un problème récurrent et classique quand on a affaire à des données à regrouper et que l'on ne sait que l'on a fini avec un groupe qu'en lisant des données d'un nouveau groupe. Les solutions simples sont:
    - charger tout dans un tableau, mais au prix d'une occupation mémoire éventuellement rédhibitoire;
    - traiter les données de façon différée (c'est-à-dire par exemple traiter un groupe de données quand on a lu la première donnée d'un nouveau groupe), mais il faut alors bien souvent dupliquer du code pour traiter le dernier groupe.

    Il y a bien sûr des solutions pour éviter cela (comme les itérateurs), mais encore faut-il (à mes yeux) que la solution ne soit pas bien plus complexe que la petite verrue qu'elle est censée éliminer. C'est parfois le cas, mais pas toujours, tout dépend du problème. Mais, par exemple, ajouter 15 lignes de code pour éviter la duplication d'une seule ligne de code en fin de boucle est peut-être conforme au principe DRY (don't repeat yourself), mais certainement pas au principe KISS (keep it simple and stupid). Bon, en la matière comme pour beaucoup d'autres sujets, tout est affaire d'essayer de trouver le meilleur compromis (ou trade-off) entre des principes parfois antagonistes. Et tout le monde n'aura pas la même vision du compromis idéal (et je dirais même: moi-même n'aurai pas la même vision du meilleur compromis à des moments différents, je ferais probablement aujourd'hui certaines choses différemment de la façon dont je les ai faites il y a un an ou dont je les ferai dans un an).

    Citation Envoyé par cmcmc Voir le message
    J'avoue qu'étant donné les efforts fournis pour expliciter la démarche, montrer les dangers, justifier en détails l'implémentation, fournir des exemples, analyser le comportement en termes d'occupation mémoire, etc... le fait que personne ne se soit donné la peine de qualifier ce fil d'intéressant, ou (à part peut-être le demandeur initial) de ces contributions, est assez décourageant .
    Je suis un peu surpris que tu dise cela précisément dans une réponse à mon post, comme si c'est à moi que tu le reprochais, alors que j'ai justement pris la peine de le faire, me semble-t-il.

    Et, BTW, j'ai plusieurs de tes posts. (Bien que tu m'aies dit toi même il y a quelques mois que tu n'avais pas trop le temps de le faire pour les posts des autres. Mais peut-être as-tu changé ton point de vue sur le sujet depuis... )

  6. #26
    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
    Là, tu as tronqué la citation.
    Ce n'était pas mon intention mais après relecture attentive je conçois qu'on puisse le prendre ainsi. Désolé.

    Citation Envoyé par Lolo78 Voir le message
    Je précisais dans la phrase suivante qu'il était faible notamment par rapport à un:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ... = map { ...} map {...} LIST
    que tu présentais comme fonctionnellement équivalent, mais qui duplique plusieurs fois les données derrière la scène.
    C'était conceptuellement, pas fonctionnellement. Au sens où on sépare les phases de partitionnement et de réduction, au lieu de les faire ensemble à la volée. Mais OK.

    Citation Envoyé par Lolo78 Voir le message
    Et il est faible si les données ressemblent à celles présentées par l'OP et n'ont pas la forme pathologique que tu sembles redouter.

    Je travaille assez souvent sur des fichiers ayant des centaines de millions d'enregistrements avec à chaque fois typiquement 5 à 20 enregistrements pour une même entité (par ex. un même client, mais il y a 35 millions de clients dans mon cas de figure). Regrouper ces 5 à 20 enregistrements dans un itérateur pour renvoyer la structure de données relative à un client au code appelant a un coût mémoire très faible, négligeable, même. Et pour comparer par exemple deux fichiers de ce type, j'ai deux exemplaires de cet itérateur (créés avec le même code), un pour chaque fichier, et, dans mon code appelant, je n'ai plus à comparer, pour chaque client, que des structures de données de faible dimension, déjà reformatées et éventuellement triées pour permettre une comparaison facile. Cela simplifie vraiment le travail.

    Tous les problèmes ne sont pas du même type, certes, mais c'est tout de même assez typique comme cas de figure.
    On ne parlait pas de la même chose. Pour moi faible n'a pas de sens dans un contexte de mesure de complexité algorithmique ou d'occupation mémoire. Mais je conviens bien volontiers que le coût est certainement acceptable ou supportable dans les utilsations que tu cites.

    Citation Envoyé par Lolo78 Voir le message
    La copie est juste là pour figurer (représenter) des données locales à la fermeture (et ne pas modifier, en l'occurrence, @_). La copie est inutile si je me moque de modifier @_ au fur et à mesure que je prélève des données. Dans la vraie vie, c'est probablement l'ouverture d'un fichier qui aurait lieu là, et c'est le file handle qui serait local à la fonction d'itération, et l'itérateur se contenterait de lire les lignes du fichier une à une.
    Je sais bien que tu es parfaitement capable d'éviter une copie inutile (tes tutoriels le montrent amplement ). Le problème ici (notamment pour un débutant) est alors de faire la part entre ce qui est essentiel et ce qui est là pour 'figurer'. C'est pourquoi j'essaie systématiquement de présenter mes codes 'en situation'.

    Citation Envoyé par Lolo78 Voir le message
    Initialiser $max n'est nécessaire que pour ne pas avoir de warning ("use of initialized value ...").
    Non, car si c'était le cas tu pourrais te contenter de l'initialiser à 0.

    Citation Envoyé par Lolo78 Voir le message
    Plusieurs de tes solutions auraient ce warning si tu prenais la peine d'activer les warnings.
    Hors unilignes, le code que je publie passe normalement use strict et use warnings (et je te remercie d'avance de me le faire savoir si d'aventure cela ne devait pas être le cas). Pour les unilignes c'est délibéré. L'interprétation de undef comme nul en contexte numérique, chaine vide en contexte textuel, et liste vide en contexte de liste est à mon avis trop utile pour s'en passer dans un code compact destiné à illustrer une idée ou un algorithme. Le préambule perl -wE 'no warnings qw(uninitialized); ...' est trop lourd pour être utilisé couramment. Par ailleurs je crois que ce warning est le seul que mes unilignes soient susceptibles de générer.

    Citation Envoyé par Lolo78 Voir le message
    Je rappelle cependant que j'avais immédiatement émis des réserves sur cette solution, à cause de la duplication du code d'émission du résultat.
    Là c'est toi qui tronque Rétablissons le contexte :
    Citation Envoyé par Lolo78 Voir le message
    Citation Envoyé par cmcmc Voir le message
    Je rappelle cependant que j'avais immédiatement émis des réserves sur cette solution, à cause de la duplication du code d'émission du résultat :
    ...if ($i ne $pi) { say "$pi:$m" if $pi; ($pi, $m) = ($i, $n) } else { $m = $n if $n > $m }} say "$pi:$m"
    car s'il y a quelque chose que j'ai retenu de mes décennies de codage c'est bien l'importance de l'exigence cardinale de ne pas dupliquer de code (DRY : don't repeat yourself) car toute duplication de code est potentiellement un cauchemar de maintenance.

    Et franchement la manière dont le demandeur s'est initialement approprié la solution (en reconnaissant qu'il n'a pas codé de manière très propre ) me conforte dans cette position :
    ...
    		push @csv_best, "$prot_desc_prev;$pi;$prot_score_prev;$m;$prot_sequences_prev;$prot_pi_prev\n" if $pi;
    	...
    push @csv_best, "$prot_desc_prev;$pi;$prot_score_prev;$m;$prot_sequences_prev;$prot_pi_prev\n";
    
    Si la duplication de mon malheureux say "$pi:$m" me causait de l'inconfort , on peut imaginer ce que ces deux lignes m'inspirent

    Alors je suis peut-être obsédé par la qualité logicielle mais pour moi c'est un problème sérieux. Et qui à défaut de meilleure solution justifie amplement l'introduction d'un writer. Ce n'est pas de l'over-engineering, c'est une stratégie de survie.
    C'est un problème récurrent et classique quand on a affaire à des données à regrouper et que l'on ne sait que l'on a fini avec un groupe qu'en lisant des données d'un nouveau groupe.
    Je dirais plutôt une circonstance récurrente et classique. Qui devient un problème lorsqu'elle provoque ou justifie une duplication de code. Quand je dis que DRY est une exigence cardinale, c'est qu'elle est non négociable et je m'en veux de ne pas avoir rédigé ma solution initiale en
    my $p = sub { my ($i, $m) = @_; say "$pi:$m"}...if ($i ne $pi) { $p->($pi,$m) if $pi; ($pi, $m) = ($i, $n) } else { $m = $n if $n > $m }} $p->($pi,$m)
    que le demandeur se serait probablement approprié de manière plus propre que ce qu'il a fait. Je ne sais pas s'il reviendra sur ce fil, et s'il nettoiera son code. En l'état, si lui même ou un autre pauvre bougre se retrouve avec des problèmes de maintenance d'ici un an ou deux sur ce script ce sera quelque part un peu de ma faute. Et ça m'ennuie.

    Citation Envoyé par Lolo78 Voir le message
    Les solutions simples sont:
    - charger tout dans un tableau, mais au prix d'une occupation mémoire éventuellement rédhibitoire;
    - traiter les données de façon différée (c'est-à-dire par exemple traiter un groupe de données quand on a lu la première donnée d'un nouveau groupe), mais il faut alors bien souvent dupliquer du code pour traiter le dernier groupe.

    Il y a bien sûr des solutions pour éviter cela (comme les itérateurs), mais encore faut-il (à mes yeux) que la solution ne soit pas bien plus complexe que la petite verrue qu'elle est censée éliminer. C'est parfois le cas, mais pas toujours, tout dépend du problème. Mais, par exemple, ajouter 15 lignes de code pour éviter la duplication d'une seule ligne de code en fin de boucle est peut-être conforme au principe DRY (don't repeat yourself), mais certainement pas au principe KISS (keep it simple and stupid). Bon, en la matière comme pour beaucoup d'autres sujets, tout est affaire d'essayer de trouver le meilleur compromis (ou trade-off) entre des principes parfois antagonistes. Et tout le monde n'aura pas la même vision du compromis idéal (et je dirais même: moi-même n'aurai pas la même vision du meilleur compromis à des moments différents, je ferais probablement aujourd'hui certaines choses différemment de la façon dont je les ai faites il y a un an ou dont je les ferai dans un an).
    Comme je le dis plus haut je refuse de compromettre DRY. Il y a toujours une solution, au pire l'introduction d'une fonction comme montré ci-dessus, pour éviter la duplication. Par ailleurs on n'a pas la même définition du principe KISS qui pour moi est la version initiale 'Keep it simple, stupid', destinée à prévenir la prolifération de fonctionnalités (feature creep) dans des projets mal spécifiés, et certainement pas une exhortation à écrire du code simple et stupide . A part cela je suis d'accord. mais comme je prends (peut-être à tort) ce paragraphe un peu pour moi je ferai remarquer qu'à mon avis les différentes évolutions que j'ai proposées dans ce fil sont DRY et KISS (hormis la première pour DRY) :
    • la solution initiale (ici), pour le calcul du max dans chaque groupe d'un attribut unique
    • la version bog (ici), pour calculer le max d'un attribut et véhiculer d'autres attributs non variants dans chaque groupe
    • la version pr (ici et ), pour permettre le calcul de plusieurs réductions si plusieurs attributs sont variants dans chaque groupe
    • la version Prop (ici), pour simplifier l'utilisation dans cas ou un reader ou itérateur n'est pas adapté au contexte d'utilisation
    • la solution initiale amendée pour être DRY (http://www.developpez.net/forums/d15...e/#post8436115), pour le calcul du max dans chaque groupe d'un attribut unique

    Si ce n'est pas votre avis je serais ravi d'en discuter

    Citation Envoyé par Lolo78 Voir le message
    Citation Envoyé par cmcmc Voir le message
    J'avoue qu'étant donné les efforts fournis pour expliciter la démarche, montrer les dangers, justifier en détails l'implémentation, fournir des exemples, analyser le comportement en termes d'occupation mémoire, etc... le fait que personne ne se soit donné la peine de qualifier ce fil d'intéressant, ou (à part peut-être le demandeur initial) de ces contributions, est assez décourageant .
    Je suis un peu surpris que tu dise cela précisément dans une réponse à mon post, comme si c'est à moi que tu le reprochais, alors que j'ai justement pris la peine de le faire, me semble-t-il.
    Ca ne t'était pas particulièrement destiné, et je te remercie de ton attention. Il n'en reste pas moins vrai qu'à cette date aucun de mes posts dans ce fil n'a plus de deux , et que personne ne s'est donné la peine de noter cette discussion, pourtant à mon avis passablement plus substantielle que celle-ci par exemple. J'apporte beaucoup de soin à la rédaction de mes posts et je trouve frustrant de ne pas avoir plus de retours. Je comprends que les lecteurs n'aient pas nécessairement de choses à dire ou de remarques particulières à faire. Mais dans ce cas un petit retour (positif si le post qu'il viennent de lire est manifestement bien construit et informatif, négatif s'il y a des défauts patents) n'est pas difficile.

    J'attends peut-être un peu trop de ce forum. Avec à ce stade 389 lectures pour 24 posts dans ce fil, il devrait y avoir un minimum une bonne quinzaine de lecteurs, plus en fait si on prend en compte la croissance progressive du fil. Avoir un retour apparent de trois ou quatre d'entre eux paraît peu, et pose la question de savoir si ce sont des lecteurs réels ou des robots.


    Citation Envoyé par Lolo78 Voir le message
    Et, BTW, j'ai plusieurs de tes posts. (Bien que tu m'aies dit toi même il y a quelques mois que tu n'avais pas trop le temps de le faire pour les posts des autres. Mais peut-être as-tu changé ton point de vue sur le sujet depuis... )
    Encore une fois je t'en remercie. Pour info j'ai fait de même pour chacun des tiens dans ce fil à part le premier qui avait un bug . Ensuite, j'imagine que tu fais référence à cet échange :

    Citation Envoyé par cmcmc Voir le message
    Dans tous les cas merci de voter pour (ou contre) ce message et/ou cette discussion
    C'est la seconde fois que je te vois demander des votes, mais toi, tu ne votes pratiquement jamais sur les postes des autres.
    C'est parce que tu en as manqué une. Dans les trois cas où j'ai, comme tu dis, demandé des votes, les messages correspondants m'avaient pris largement plus de deux heures à composer. Dans de tels cas un peu de feedback est bienvenu pour que je ne sois pas tenté par l'alternative oh combien séduisante de faire autre chose de mon temps.

    Enfin je vote peu (ça m'arrive, essentiellement positivement) parce que me retiens. Je n'aime pas les fautes d'orthographe ou de syntaxe, ni les imprécisions ou approximations. On ne se refait pas...
    J'ai été pour diverses raisons absent du forum depuis fin 2013 (ce que je regrette profondément car je n'ai pas pu mener à terme certaines discussions en cours, notamment avec bayouta et Justin Loïc) mais à part cela le temps n'a jamais eu d'influence sur mes votes. Ma position n'a pas changé (encore que je devienne plus indulgent sur les ).

    Et je tiens à dire que j'apprécie nos échanges et tes autres contributions. Il est clair que nous ne sommes pas d'accord sur de nombreux points et que nous avons des styles différents. Mais je crois que nous avons l'un et l'autre la même propension didactique, ce qui est bon pour un forum comme celui-ci. Et je pense qu'il est bon également de disposer de plusieurs éclairages sur les sujets abordés. Keep up the good work !
    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. #27
    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
    Non, car si c'était le cas tu pourrais te contenter de l'initialiser à 0.
    Seulement si on est sûr de ne pas avoir de valeurs négatives en entrée. Là, j'ai juste voulu prendre des précautions supplémentaires.
    Citation Envoyé par cmcmc Voir le message
    Hors unilignes, le code que je publie passe normalement use strict et use warnings (et je te remercie d'avance de me le faire savoir si d'aventure cela ne devait pas être le cas).
    Bien sûr, je voulais juste dire que l'utilisation des warnings t'aurait obligé à initialiser un max sous une forme ou une autre dans plusieurs de tes unilignes.

    D'ailleurs, quand tu publies de longs (ou très longs) "unilignes", pourrais-tu les mettre sur plusieurs lignes, ça rend la lecture du code plus facile, je trouve.

    Citation Envoyé par cmcmc Voir le message
    Là c'est toi qui tronque Rétablissons le contexte :
    J'ai certes tronqué, mais c'était vraiment compliqué avec les citations dans les citations dans les citations, j'ai juste voulu reprendre dans une citation courte l'essence de ce que tu disais, et je ne pense pas voir trahi ta pensée d'une quelconque façon. DSL, bien sûr, si je l'ai fait en quelque manière.
    Citation Envoyé par cmcmc Voir le message
    Et je tiens à dire que j'apprécie nos échanges et tes autres contributions.
    Merci. Et j'apprécie les tiennes.
    Citation Envoyé par cmcmc Voir le message
    Il est clair que nous ne sommes pas d'accord sur de nombreux points et que nous avons des styles différents.
    Ah, voici le point essentiel qui m'a incité à te répondre une nouvelle fois, tout ce qui précède n'est que détail.

    Je ne suis pas du tout convaincu que nous ne soyons pas d'accord sur de nombreux points. Je pense au contraire que nous sommes d'accord sur le plupart des points. La différence entre nous est que tu as des convictions fermement ancrées (et j'avais la même façon de penser quand j'étais bien plus jeune) et que j'en suis arrivé à être beaucoup plus tolérant pour l'imperfection et à essayer systématiquement d'être ouvert aux autres opinions. Et aussi à relativiser les convictions, même quand je les partage. Ce qui peut m'amener à la limite à critiquer (ou plutôt relativiser) tes propos alors que j'aurais pu tenir presque les mêmes, parce que j'essaie aussi de me mettre dans la position de personne ayant une perspective différente ou une expérience plus limitée. Et je ne parle pas seulement de programmation informatique, mais j'ai acquis la même attitude pour ce qui est des jugements sociaux ou moraux, des opinions politiques, etc.: j'ai des opinions personnelles arrêtées, mais ne prétends plus pour autant détenir la vérité.

    Bref, je pense que nous sommes en fait d'accord sur beaucoup plus de points que tu ne le croies. Mais, oui, nous n'avons sans doute pas le même style.

  8. #28
    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
    Hors unilignes, le code que je publie passe normalement use strict et use warnings (et je te remercie d'avance de me le faire savoir si d'aventure cela ne devait pas être le cas). Pour les unilignes c'est délibéré. L'interprétation de undef comme nul en contexte numérique, chaine vide en contexte textuel, et liste vide en contexte de liste est à mon avis trop utile pour s'en passer dans un code compact destiné à illustrer une idée ou un algorithme. Le préambule perl -wE 'no warnings qw(uninitialized); ...' est trop lourd pour être utilisé couramment. Par ailleurs je crois que ce warning est le seul que mes unilignes soient susceptibles de générer.
    J'espère ne pas être à coté de la plaque en répondant, car j'avoue que même si les débats sont intéressants, je n'ai pas vraiment eu le temps de tout lire en détail. La plupart du temps, dans mes scripts, j'utilise la faculté d'une variable à ne pas être initialisée (cela permet de distinguer qu'une fonctionnalité est activée ou non tout en permettant d'en contenir sa configuration). Pour éviter l'usage d'une variable non initialisée, je recours alors très souvent à l'opérateur // pour lui donner une valeur par défaut.
    Citation Envoyé par cmcmc
    Ca ne t'était pas particulièrement destiné, et je te remercie de ton attention. Il n'en reste pas moins vrai qu'à cette date aucun de mes posts dans ce fil n'a plus de deux , et que personne ne s'est donné la peine de noter cette discussion, pourtant à mon avis passablement plus substantielle que celle-ci par exemple.
    Je n'avais même pas vu qu'on pouvait noter des discussions

    Cela dit, je crois qu'il y a relativement peu de lecteurs suffisamment passionnés par Perl pour participer à des discussions "philosophiques" ; on voit d'ailleurs que sur ce forum, ce sont essentiellement toujours les mêmes qui répondent, que les questions sont majoritairement du niveau débutant (ce qui n'a rien de péjoratif, car entre autre, cela permet aussi aux contributeurs de développer leurs qualités didactiques), et que globalement, les sujets "intéressants" se trouvent plutôt dans les commentaires sur des articles publiés par les rédacteurs (Laurent en premier lieu). J'aime bien pour ma part que certains sujets "anodins" (comme celui-ci) puisse être l'occasion "d'aller plus loin", même si l'auteur original n'en a pas fait la demande. Cela permet d'animer ce forum sans quoi cela se résumerais trop à un forum d'exercices.
    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. #29
    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
    Bien sûr, je voulais juste dire que l'utilisation des warnings t'aurait obligé à initialiser un max sous une forme ou une autre dans plusieurs de tes unilignes.
    Ahhh, non , et c'est justement une des beautés de la solution. Regarde bien, on n'a jamais besoin d'initialiser un max. Dans la solution initiale, sous -w, le warning est déclenché lors du test de changement de groupe, pas dans la réduction. Les autres versions peuvent produire des warnings mais ces derniers ne sont jamais liés à la réduction.
    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

  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 Philou67430 Voir le message
    Cela dit, je crois qu'il y a relativement peu de lecteurs suffisamment passionnés par Perl pour participer à des discussions "philosophiques" ; on voit d'ailleurs que sur ce forum, ce sont essentiellement toujours les mêmes qui répondent, que les questions sont majoritairement du niveau débutant (ce qui n'a rien de péjoratif, car entre autre, cela permet aussi aux contributeurs de développer leurs qualités didactiques), et que globalement, les sujets "intéressants" se trouvent plutôt dans les commentaires sur des articles publiés par les rédacteurs (Laurent en premier lieu). J'aime bien pour ma part que certains sujets "anodins" (comme celui-ci) puisse être l'occasion "d'aller plus loin", même si l'auteur original n'en a pas fait la demande. Cela permet d'animer ce forum sans quoi cela se résumerais trop à un forum d'exercices.
    Hmmm. Philosophique ? Anodin ? J'avais le sentiment d'avoir montré une progression technique rigoureuse suivant un enrichissement progressif des spécifications... Penses-tu que j'aurais mieux fait de faire un article ?

    Et je n'ai pas eu de retour concernant ma propre requête de suggestions pour rendre DRY la solution initiale (celle ci), ni de commentaires sur la solution amendée (celle là). Peut-être quand tu auras un moment ?
    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
    Hmmm. Philosophique ? Anodin ? J'avais le sentiment d'avoir montré une progression technique rigoureuse suivant un enrichissement progressif des spécifications... Penses-tu que j'aurais mieux fait de faire un article ?
    Pour ne pas se méprendre sur mes intentions :
    - quand je parle de philosopher, je parle de débattre, dans une discussion initialement "purement technique", des paradigmes de programmation, des méthodes de développement (KISS, DRY), ... Et je parle plus généralement, pas uniquement à propos de cette discussion
    - quand je parle d'un sujet anodin : je ne parle pas de son développement avec les réponses qui y sont apportées, mais de la question initiale, souvent basique et très limitée. Il ne s'agit pas d'en diminuer l'intérêt, et je disais justement que je trouve intéressant de prendre pour prétexte ce genre de discussion pour des débats plus approfondis, plus ... "philosophiques"
    Et je n'ai pas eu de retour concernant ma propre requête de suggestions pour rendre DRY la solution initiale (celle ci), ni de commentaires sur la solution amendée (celle là). Peut-être quand tu auras un moment ?
    Malheureusement, le temps, c'est bien ce qui me manque le plus. Et là, je n'aurais pas un moment de libre avant lundi...
    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

Discussions similaires

  1. Réponses: 8
    Dernier message: 27/12/2009, 23h58
  2. [Bison] Liste des "décalage/réduction"
    Par minirop dans le forum Autres éditeurs
    Réponses: 10
    Dernier message: 25/04/2009, 12h19
  3. tri de liste chainée
    Par RezzA dans le forum C
    Réponses: 7
    Dernier message: 26/01/2003, 20h25
  4. Compter le nombre ligne listée (COUNT) ?
    Par StouffR dans le forum Langage SQL
    Réponses: 7
    Dernier message: 02/09/2002, 09h41
  5. Listes déroulantes liées entre elles
    Par denisC dans le forum Général JavaScript
    Réponses: 0
    Dernier message: 27/07/2002, 15h53

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