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. #41
    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 cmcmc Voir le message
    Tout d'abord, ici il est essentiel de renvoyer soit la liste vide (), soit une référence à un hash ($h ou \%h).
    en fait ce qui serait bien serait de pouvoir renvoyer soit une hashref, soit rien du tout... Ce n'est pas possible directement dans le corps du map, mais ...
    Peut-être que le mieux dans ce genre de situation c'est d'insérer une sub anonyme et de distinguer les deux types renvoyés par des appels explicites à return :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     	my @table = map {
                (sub {
                     if (m{<TH>}msi) {
                         @headers = m{<TH>(.*?)</TH>}imsg;
                         return ();
                     } else {
                         die "pas d'entêtes trouvés pour la table N° $tablecnt" unless @headers;
                         my %h;
                         @h{@headers} = m{<TD>(.*?)</TD>}imsg;
                         return \%h;
                     }
                 })->($_);
    	} m{(<TR.*?</TR>)}imsg;
    ...c'est effectivement possible depuis une sub anonyme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     	my @table = map {
                (sub {
                     if (m{<TH>}msi) {
                         @headers = m{<TH>(.*?)</TH>}imsg;
                         return;
                     } else {
                         die "pas d'entêtes trouvés pour la table N° $tablecnt" unless @headers;
                         my %h;
                         @h{@headers} = m{<TD>(.*?)</TD>}imsg;
                         return \%h;
                     }
                 })->();
    	} m{(<TR.*?</TR>)}imsg;
    Il y a deux différences à noter : la plus importante est celle de la ligne 5. Au lieu de renvoyer la liste vide on ne renvoie plus rien. Ca marche, mais c'est peut-être une perversion de map...

    la seconde différence est en ligne 12 la suppression de $_ dans les paramètres passés à la sub anonyme. J'avais commencé par éditer mon post initial pour le supprimer mais je l'y ai remis pour pouvoir critiquer cette ligne honnêtement . Il ne sert à rien de passer quoi que ce soit en paramètre à cette sub puisqu'on ne les dépile pas... En fait le $_ qui est utilisé implicitement dans les m{...} des lignes 3, 4 et 9 c'est bien la variable de topic du bloc du map. C'est peut-être un peu piégeux...
    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. #42
    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 cmcmc Voir le message
    À l'inverse le coût de génération d'une référence anonyme (\%hash, \@liste, \$scalaire, ...) est constant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ \%h ]) while (--$cnt); sub foo {}'
     
    real	0m1.153s
    user	0m0.000s
    sys	0m0.031s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 10; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ \%h ]) while (--$cnt); sub foo {}'
     
    real	0m1.019s
    user	0m0.031s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 100; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ \%h ]) while (--$cnt); sub foo {}'
     
    real	0m1.191s
    user	0m0.030s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1000; %h = 1 .. 2*$size; $cnt = 1_000_000; foo([ \%h ]) while (--$cnt); sub foo {}'
     
    real	0m1.173s
    user	0m0.015s
    sys	0m0.031s
    Taisha:~/tttmp/hyperliens $
    oups, lire plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1; %h = 1 .. 2*$size; $cnt = 1_000_000; foo( \%h ) while (--$cnt); sub foo {}'
     
    real	0m0.636s
    user	0m0.047s
    sys	0m0.000s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 10; %h = 1 .. 2*$size; $cnt = 1_000_000; foo( \%h ) while (--$cnt); sub foo {}'
     
    real	0m0.553s
    user	0m0.015s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 100; %h = 1 .. 2*$size; $cnt = 1_000_000; foo( \%h ) while (--$cnt); sub foo {}'
     
    real	0m0.595s
    user	0m0.015s
    sys	0m0.031s
    Taisha:~/tttmp/hyperliens $ time perl -e '$size = 1000; %h = 1 .. 2*$size; $cnt = 1_000_000; foo( \%h ) while (--$cnt); sub foo {}'
     
    real	0m0.550s
    user	0m0.016s
    sys	0m0.015s
    Taisha:~/tttmp/hyperliens $
    puisqu'on compare bien les coûts respectifs de [ %h ] et \%h, et non pas [ \%h ] qui n'a rien à voir ... (mais ça ne change rien à la conclusion).
    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. #43
    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
    Le code d'origine qui m'a valu ma remarque sur $h (qui était sans doute plus à prendre dans un contexte de fonction que de map ; je me suis un peu emballé, mais c'est plutôt le retour d'un objet à forme multiple qui me choquait).
    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
    sub extracteur_tables {
        my ($fulltext) = @_;
        my $tablecnt = 0;
        my %data = map {
    	++$tablecnt;
    	my @headers;
    	my @table = map {
    	    my $h;
    	    if (m{<TH>}ims) {
    		@headers = m{<TH>(.*?)</TH>}imsg;
    	    } else {
    		die "pas d'entêtes trouvés pour la table N° $tablecnt" unless @headers;
    		@{$h}{@headers} = m{<TD>(.*?)</TD>}imsg;
    	    }
    	    $h || ();
    	} m{(<TR.*?</TR>)}imsg;
    	"table_$tablecnt" => \@table
        } $fulltext =~ m{(<TABLE.*?</TABLE>)}imsg;
        return \%data;
    }
    J'ai relu en détail le code que tu as écris concernant $h, et j'ai compris l'intérêt de la liste vide à retourner.
    Cela dit, je reste sur l'idée qu'il est préférable de toujours essayer de retourner un élément "du même type" (fonction ou map), hormis dans le cas de l'utilisation du polymorphisme à l'aide de wantarray.
    Ainsi, on pouvait utiliser %h et toujours retourner \%h en ajoutant devant le map un filtrage pour supprimer les hash vide (celui qui correspond à la ligne contenant les TH) "grep %$_, map { ..."

    Mais c'est un détail qui a relativement peu d'importance et j'admets que dans le cas présent, la remarque était superflue.
    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. #44
    Membre confirmé
    Avatar de cmcmc
    Homme Profil pro
    Inscrit en
    Juillet 2013
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2013
    Messages : 316
    Points : 641
    Points
    641
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    ...c'est plutôt le retour d'un objet à forme multiple qui me choquait
    Moi j'aime bien, j'en ai un peu trop bavé avec le typage strict dans d'autres langages .
    je reste sur l'idée qu'il est préférable de toujours essayer de retourner un élément "du même type" (fonction ou map), hormis dans le cas de l'utilisation du polymorphisme à l'aide de wantarray.

    Ainsi, on pouvait utiliser %h et toujours retourner \%h en ajoutant devant le map un filtrage pour supprimer les hash vide (celui qui correspond à la ligne contenant les TH) "grep %$_, map { ..."
    J'y avais pensé également, mais ça fait un étage de plus dans le pipeline...

    Mais c'est un détail qui a relativement peu d'importance...
    Pas tant que ça d'un point de vue lisibilité. Cette discussion a été très éclairante pour moi et montre bien qu'il y a une difficulté de lecture de la version map. C'est ce que je voulais dire quand je disais préférer la version foreach propre parce que le cas particulier des entêtes y est traité plus naturellement.

    En théorie des langages fonctionnels, il me semble que map ne devrait jamais avoir d'effets de bord (ce qui permet par exemple de la paralléliser). Clairement ici on en a au moins deux : incrémentation (et utilisation) de $tablecnt, et traitement du cas particulier des entêtes... Ce devrait probablement être un indice conduisant à préférer une solution fondée sur foreach.
    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. #45
    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
    Moi j'aime bien, j'en ai un peu trop bavé avec le typage strict dans d'autres langages .
    Quand je parle "type", c'est au sens perl, c'est à dire mélanger "scalaire" et liste ... ça reste tout de souple...
    J'y avais pensé également, mais ça fait un étage de plus dans le pipeline...
    Il n'y a pas vraiment de pipeline dans le parseur : il y a deux parseurs imbriqués, mais pas un 2e parseur qui parse le résultat du 1er...
    Par ailleurs, sur quel critère te base-tu pour ne pas favoriser l'ajout d'un élément de pipeline ?
    Pas tant que ça d'un point de vue lisibilité. Cette discussion a été très éclairante pour moi et montre bien qu'il y a une difficulté de lecture de la version map. C'est ce que je voulais dire quand je disais préférer la version foreach propre parce que le cas particulier des entêtes y est traité plus naturellement.
    Je suis entièrement d'accord.
    En théorie des langages fonctionnels, il me semble que map ne devrait jamais avoir d'effets de bord (ce qui permet par exemple de la paralléliser). Clairement ici on en a au moins deux : incrémentation (et utilisation) de $tablecnt, et traitement du cas particulier des entêtes... Ce devrait probablement être un indice conduisant à préférer une solution fondée sur foreach.
    Il est difficile de résister à ce genre de chose (par exemple, pour réaliser la fonction uniq : @a = grep !$a{$_}++, @a;).
    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

  6. #46
    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 n'y a pas vraiment de pipeline dans le parseur : il y a deux parseurs imbriqués, mais pas un 2e parseur qui parse le résultat du 1er...
    ? Par pipeline, j'entendais bien une construction de type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @b = grep { ... } # troisième étage
         map  { ... } # deuxième étage
         map  { ... } # premier étage
         @a;
    Par ailleurs, sur quel critère te base-tu pour ne pas favoriser l'ajout d'un élément de pipeline ?
    l'efficacité ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Taisha:~/tttmp $ time perl -e '$size = 1000; @a = 1 .. $size; $cnt = 10_000; $x = 2; while ($cnt--) {@b = grep %$_, map { $_ % 2 ? {$_ => $_} : {} } @a}'
     
    real	0m16.240s
    user	0m0.047s
    sys	0m0.000s
    Taisha:~/tttmp $ time perl -e '$size = 1000; @a = 1 .. $size; $cnt = 10_000; $x = 2; while ($cnt--) {@b = map { hov }  @a} sub hov { return {$_ => $_} if $_ % 2; return }'
     
    real	0m11.889s
    user	0m0.031s
    sys	0m0.000s
    Taisha:~/tttmp $
    Si je peux économiser un étage je suis probablement gagnant... (pas forcément en lisibilité, je te l'accorde )
    Il est difficile de résister à ce genre de chose (par exemple, pour réaliser la fonction uniq : @a = grep !$a{$_}++, @a;).
    yup +1
    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. #47
    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
    ? Par pipeline, j'entendais bien une construction de type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @b = grep { ... } # troisième étage
         map  { ... } # deuxième étage
         map  { ... } # premier étage
         @a;
    Sauf erreur, l'algo d'analyse est récursif, par en pipeline, du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @b = map { map { } @... } @...
    l'efficacité ?
    Je pensais bien à ce critère. En fait, je pars du principe qu'il faut d'abord un code clair et que les considérations de performances doivent être prises en compte seulement si elles deviennent nécessaires, car elles signifient trop souvent "optimisation" et :
    - diminution de la lisibilité/maintenabilité
    - recherche d'optimisation longue et potentiellement, qui peut conduire à une perte de portabilité
    - ...
    Je considère que, perl disposant de paradigmes de programmation avancés tel que les pipeline et les opérateurs de liste, il est déjà optimisé pour ce genre de traitements.
    Par ailleurs, si tu prends comme critère les performances, il faut à la fois regarder les aspects de temps d'exécution, et les aspects de consommation mémoire (je ne juge pas ce cas précis, je parle "en général").

    Bref, je regarde rarement les problèmes de performance quand j'écris mon algorithme, sauf s'il est évident à la vue de l'énoncé qu'ils entrerons en ligne de compte assez rapidement (comme devoir traiter des fichiers de séquences ADN de plusieurs milliards de nucléotides, ou des dictionnaires de mots de plusieurs millions de lignes, le tout avec une combinatoire importante ; deux exemples que je traite encore et qui m'obligent à prendre en compte les aspects de consommation mémoire ET de temps CPU pendant la conception algorithmique).

    Ceci n'est pas pour dire que tu fais cas trop rapidement de ce critère, mais pour donner mon point de vue à ce sujet.
    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. [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