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 :

Message : Not an ARRAY reference, parfois, parfois pas


Sujet :

Langage Perl

  1. #1
    Membre habitué

    Homme Profil pro
    Statisticien
    Inscrit en
    Novembre 2010
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Statisticien

    Informations forums :
    Inscription : Novembre 2010
    Messages : 122
    Points : 134
    Points
    134
    Par défaut Message : Not an ARRAY reference, parfois, parfois pas
    Bonjour,

    Voulant faire un tri schwartzien, j'ai eu comme message "Not an ARRAY reference at Epingle.pm line 850."
    J'ai retravailler le code en le minimisant pour chercher l'erreur, et si j'exécute
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    my  @sc=   map { [$_, -$_] } (20,23);
    say @sc;
    say Dumper @sc;
    say Dumper sort { $a->[1] <=> $b->[1] } @sc;
    dans un petit fichier qui ne fait que ça, j'ai le bon résultat.

    Si je l'exécute dans mon programme Kandela (plein de ligne, Moose,...), j'ai le message indiqué, ici, sur la ligne 4.(les 2 premiers say étant bien les mêmes)
    J'exécute bien des "sort" ailleurs dans un contexte plus classique sans problème.
    J'imagine donc un problème de contexte, mais je ne vois pas par quel bout attaquer le problème.

    Une idée ?

  2. #2
    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
    Bonjour,

    je ne vois rien d'incorrect dans le code que tu as présenté, et je ne vois pas comment il pourrait produire l'erreur que tu mentionnes. Il faudrait que tu montres le bout de code réel produisant cette erreur.

    Cela dit, faire une pseudo transformation de Schwartz pour un cas aussi simple me paraît inutilement complexe. Déjà, tu n'as pas besoin de générer un tableau de tableaux, mais peux transformer directement les données en entrée puis en sortie:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      DB<1> print Dumper map -$_, sort {$a <=> $b} map -$_, (20,23);
    $VAR1 = 23;
    $VAR2 = 20;
    L'inversion du signe étant une transformation très peu coûteuse, tu peux aussi le faire directement dans le sort, cela ne pénalisera pas les performances de façon mesurable:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      DB<2>  print join "\n", sort {-$a <=> -$b}  (20, 23, 25);
    25
    23
    20

    Ou, plus simplement encore, modifier le tri en intervertissant $a et $b:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      DB<3> print join "\n", sort {$b <=> $a} (20, 23, 25);
    25
    23
    20
    ce qui devrait donner a priori le même résultat pour tous les cas de figure auxquels je peux penser.

    Ou encore appliquer la fonction reverse au résultat du tri:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      DB<4>  print join "\n", reverse  sort {$a <=> $b}  (20, 23, 25);
    25
    23
    20

  3. #3
    Membre habitué

    Homme Profil pro
    Statisticien
    Inscrit en
    Novembre 2010
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Statisticien

    Informations forums :
    Inscription : Novembre 2010
    Messages : 122
    Points : 134
    Points
    134
    Par défaut
    Bonjour,

    Je me suis mal fait comprendre.

    Le code que je donne est en effet correct, et fonctionne si on le met dans un simple fichier qui ne fait que ça. L'exemple que je donne est une simplification à outrance de quelque chose de bien plus compliqué, mais qui fait appel à des objets,...

    Mon but n'est donc pas de trier par ordre décroissant, mais de montrer que ce code dysfonctionne dans mon programme, je pense qu'il y a donc un problème de contexte, et je n'ai que ce message d'erreur comme piste.

    Entre temps j'ai essayé perl -d, mais sans plus de résultat. Un 's' sur la ligne du "sort" me renvoie la même erreur.

    PS : Je précise donc, que c'est bien le même code qui fonctionne dans un simple fichier, et pas dans mon programme.

  4. #4
    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 alainbb Voir le message
    Entre temps j'ai essayé perl -d, mais sans plus de résultat. Un 's' sur la ligne du "sort" me renvoie la même erreur.
    bizarre... Essaie peut-être de rajouter une impression de debug dans le corps du sort pour voir ce qu'il reçoit dans $a et $b :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ... sort { print Dumper($a); print Dumper($b); ... } ...
    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. #5
    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
    J'ai bien compris, mais je ne peux pas trop t'aider sans voir le vrai code produisant l'erreur.

    Citation Envoyé par alainbb Voir le message
    Entre temps j'ai essayé perl -d, mais sans plus de résultat. Un 's' sur la ligne du "sort" me renvoie la même erreur.
    Retente en mode debug comme ceci: juste avant d’exécuter la ligne comportant le sort en mode debug, fait un "x" sur le tableau pour voir sa structure, ou mieux sur une référence vers ce tableau. Et, si ça ne te donne pas l'explication, poste le résultat.

    Exemple de session de débogage avec le bout de code qui tu as posté dans le premier message:
    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
    $ perl -dE '
    > my  @sc=   map { [$_, -$_] } (20,23);
    > say @sc;
    > say Dumper @sc;
    > say Dumper sort { $a->[1] <=> $b->[1] } @sc;
    > '
    
    Loading DB routines from perl5db.pl version 1.33
    Editor support available.
    
    Enter h or `h h' for help, or `man perldebug' for more help.
    
    main::(-e:2):   my  @sc=   map { [$_, -$_] } (20,23);
      DB<1> s
    main::(-e:2):   my  @sc=   map { [$_, -$_] } (20,23);
      DB<1> s
    main::(-e:2):   my  @sc=   map { [$_, -$_] } (20,23);
      DB<1> s
    main::(-e:3):   say @sc;
      DB<1> s
    ARRAY(0x60005f250)ARRAY(0x60005f2e0)
    main::(-e:4):   say Dumper @sc;
      DB<1> s
    main::(-e:5):   say Dumper sort { $a->[1] <=> $b->[1] } @sc;
      DB<1> x @sc
    0  ARRAY(0x60005f250)
       0  20
       1  '-20'
    1  ARRAY(0x60005f2e0)
       0  23
       1  '-23'
      DB<2> x \@sc;
    0  ARRAY(0x6000674c0)
       0  ARRAY(0x60005f250)
          0  20
          1  '-20'
       1  ARRAY(0x60005f2e0)
          0  23
          1  '-23'
      DB<3>
    La deuxième commande en rouge ci-dessus est l'équivalent de ce que tu dois faire avec ton programme.

  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
    Citation Envoyé par cmcmc Voir le message
    bizarre... Essaie peut-être de rajouter une impression de debug dans le corps du sort pour voir ce qu'il reçoit dans $a et $b :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ... sort { print Dumper($a); print Dumper($b); ... } ...
    En fait si tu travailles sur une grosse liste et que le problème est intermittent essaie plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ... sort { if (!ref $a or ref $a ne 'ARRAY' or !ref $b or ref $b ne 'ARRAY') { die "\$a: ", Dumper($a), "\$b: ", Dumper($b) } ... } ...
    qui devrait être plus facile à exploiter...
    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
    Membre habitué

    Homme Profil pro
    Statisticien
    Inscrit en
    Novembre 2010
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Statisticien

    Informations forums :
    Inscription : Novembre 2010
    Messages : 122
    Points : 134
    Points
    134
    Par défaut
    Bonjour,

    En mode debug, j'ai le même résultat, par contre un say Dumper dans le "sort" me donne en effet quelque chose d'assez bizarre.
    Il me donne (en normal ou en debug)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $VAR1 = [
              20,
              -20
            ];
    $VAR1 = bless( {
                     'circleType' => 'arc',
                     'color2' => 'red',
                     'arcs' => [
    ...
                     'width' => 3,
                     'ordre_tri' => 1
                   }, 'Epingle' );
    Tk::Error: Not an ARRAY reference at Epingle.pm line 850.
    (le Tk::Error peut-être ignoré, il apparait seulement si je provoque l'erreur via l'interface graphique)
    Le Dumper($b) renvoie donc, non pas une array, mais un objet Epingle. J'utilise Moose, et mon code se trouve dans Epingle.pm.
    J'ai déjà eu un problème similaire mais je n'avais pas réussi à le minimiser comme celui-ci, et je l'ai finalement contourné.

    Voici mon code, il est pas des plus clean (si mon nouveau serveur Raspberry daigne ne pas planter)
    http://www.barbason.be/bug/
    vous lancer le programme avec ./kandela.pl -file bruxelles.lace
    Vous verrez 25 cercles reliés entre eux. Faites un "Ctrl-e" (erase), un click-gauche souris-glisser sur une cercle, qui devrait disparaitre et le message d'erreur honni apparaître. Ligne 847-850 dans Epingle.pm
    Bon, je vais essayer de cibler l'erreur, je peux déjà dire que si je mets les 4 lignes dans le main (kandela.pl/sub init), elles fonctionnent correctement.

    Os : Debian Jessie

  8. #8
    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 alainbb Voir le message
    Voici mon code...
    Sans regarder plus loin, commence par remplacer dans le fragment ci-dessous les utilisations de $b par $bbb ou autre chose (en tous cas *pas* $b) et regarde si ça change quelque chose. $a et $b ne fonctionnent dans le sort que si ce sont des variables globales (au niveau package). Ici tu déclares un my $b qui va masquer la variable globale avec des effets, disons, inattendus.
    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
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    after supprime => sub {
        my $self=shift;
        $::pat->deselectAll;
        my $h=find($self->center->addi(Point->new(0,-80)));
        $bord{$h->id}=1 if ($h);
        map {$::pat->get_el($_)->supprime} $h->all_cO()    if ($h) ;
        my $hg=find($self->center->addi(Point->new(-40,-40)));
        $bord{$hg->id}=1 if ($hg);
        map {$::pat->get_el($_)->supprime} $hg->all_cO()    if ($hg) ;
        my $hd=find($self->center->addi(Point->new(40,-40)));
        $bord{$hd->id}=1 if ($hd);
        map {$::pat->get_el($_)->supprime} $hd->all_cO()    if ($hd) ;
        my $b=find($self->center->addi(Point->new(0,80)));
        $bord{$b->id}=1 if ($b);
        map {$::pat->get_el($_)->supprime} $b->all_cE()    if ($b) ;
        my $bg=find($self->center->addi(Point->new(-40,40)));
        $bord{$bg->id}=1 if ($bg);
        map {$::pat->get_el($_)->supprime} $bg->all_cE()    if ($bg) ;
        my $bd=find($self->center->addi(Point->new(40,40)));
        $bord{$bd->id}=1 if ($bd);
        map {$::pat->get_el($_)->supprime} $bd->all_cE()    if ($bd) ;
        my $g=find($self->center->addi(Point->new(-80,0)));
        $bord{$g->id}=1 if ($g);
        my $d=find($self->center->addi(Point->new(80,0)));
        $bord{$d->id}=1 if ($d);
        $self->hidden();
        say Dumper %bord;
        say "23 13 11 1 19 8 14 20";
        # recherch en haut a gauche
        my ($debut)=keys(%bord);
        foreach my $id (keys(%bord)) {
             if ($::pat->get_el($id)->center->y<$::pat->get_el($debut)->center->y) {
                $debut=$id;
            } elsif
             ($::pat->get_el($id)->center->y==$::pat->get_el($debut)->center->y &&
            $::pat->get_el($id)->center->x<$::pat->get_el($debut)->center->x) {
                $debut=$id;
            }
        }
        say "debut : $debut";
        my ($fin)=keys(%bord);
        foreach my $id (keys(%bord)) {
             if ($::pat->get_el($id)->center->y>$::pat->get_el($fin)->center->y) {
                $fin=$id;
            } elsif
             ($::pat->get_el($id)->center->y==$::pat->get_el($fin)->center->y &&
            $::pat->get_el($id)->center->x>$::pat->get_el($fin)->center->x) {
                $fin=$id;
            }
        }
        say "fin   : $fin";
    #say map { $_->[0] }
    say  keys(%bord);
    say Dumper (20,23);
    #my  @sc=   map { [$_, $::pat->get_el($_)->center->y] } (20,23);
    my  @sc=   map { [$_, -$_] } (20,23);
    say @sc;
    say Dumper @sc;
    say Dumper sort { print Dumper($a); print Dumper($b);$a->[1] <=> $b->[1] } @sc;
    };
    C'est le même problème (en moins pernicieux parce que toi au moins tu as une erreur ) que ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Taisha:~/perl/forum $ perl -E 'my $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    2
    1
    0
    3
    4
    5
    6
    7
    Taisha:~/perl/forum $
    alternativement, tu peux peut-être explicitement déclarer que tu utilises les variables globales $a et $b dans le corps du sort avec la déclaration our ($a,$b);(mais je ne jurerais pas que ça marche tout le temps et pour toutes les versions de perl...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Taisha:~/perl/forum $ perl -E 'my $b = 2; say for sort { our ($a, $b); $a <=> $b } reverse 0 .. 7'
    0
    1
    2
    3
    4
    5
    6
    7
    Taisha:~/perl/forum $
    tu peux aussi définir une fonction de tri explicite (qu'il faut me semble-t-il prototyper avec ($$) ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Taisha:~/perl/forum $ perl -E 'my $b = 2; sub sorter($$) { $_[0] <=> $_[1] }; say for sort sorter reverse 0 .. 7'
    0
    1
    2
    3
    4
    5
    6
    7
    Taisha:~/perl/forum $
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  9. #9
    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
    Pour info, il existe (au moins) une règle pour Perl::Critic qui permet de détecter et prévenir les utilisations dangereuses de $a et $b (non testé) : DollarAB
    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. #10
    Membre habitué

    Homme Profil pro
    Statisticien
    Inscrit en
    Novembre 2010
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Statisticien

    Informations forums :
    Inscription : Novembre 2010
    Messages : 122
    Points : 134
    Points
    134
    Par défaut
    C'était bien my $b. C'est vrai que ces variables $a,$b m'ont paru toujours suspectes... Ca m'apprendra à résumé $bas en $b...

    Dire que j'ai lu PBP (en français je sais plus son titre), que j'utilisAIS perlcritic... va falloir m'y remettre.

    Un grand merci.

  11. #11
    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
    Sans regarder plus loin, commence par remplacer dans le fragment ci-dessous les utilisations de $b par $bbb ou autre chose (en tous cas *pas* $b) et regarde si ça change quelque chose. $a et $b ne fonctionnent dans le sort que si ce sont des variables globales (au niveau package). Ici tu déclares un my $b qui va masquer la variable globale avec des effets, disons, inattendus.
    Bien vu. ++

    Citation Envoyé par cmcmc Voir le message
    C'est le même problème (en moins pernicieux parce que toi au moins tu as une erreur ) que ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Taisha:~/perl/forum $ perl -E 'my $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    2
    1
    0
    3
    4
    5
    6
    7
    Curieusement, j'ai pour ma part une erreur avec ce code (version Perl: 5.14):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $ perl -E  'my $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    Can't use "my $b" in sort comparison at -e line 1.
    Il est possible de s'en débarrasser et d'obtenir le bon résultat avec ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $ perl -E  'local  $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    0
    1
    2
    3
    4
    5
    6
    7
    Mais il est largement préférable de choisir un autre nom de variable.

    EDIT: j'ai la même erreur même en Perl 5.10 sur un vieux serveur AIX:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $perl -E  'my $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    Can't use "my $b" in sort comparison at -e line 1.

  12. #12
    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
    Curieusement, j'ai pour ma part une erreur avec ce code (version Perl: 5.14):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $ perl -E  'my $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    Can't use "my $b" in sort comparison at -e line 1.
    Bonne remarque, . Ca a effectivement été transformé en warning à partir de la version 5.18 (et il faut donc les activer pour le voir ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Taisha:~/perl/forum $ perl -v | head -2
    
    This is perl 5, version 22, subversion 0 (v5.22.0) built for MSWin32-x86-multi-thread-64int
    Taisha:~/perl/forum $ perl -wE 'my $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    "my $b" used in sort comparison at -e line 1.
    2
    1
    0
    3
    4
    5
    6
    7
    Taisha:~/perl/forum $
    extrait du perldelta pour 5.18 :
    The 'Can't use "my %s" in sort comparison' error has been downgraded to a
    warning, '"my %s" used in sort comparison' (with 'state' instead of 'my'
    for state variables).  In addition, the heuristics for guessing whether
    lexical $a or $b has been misused have been improved to generate fewer
    false positives.  Lexical $a and $b are no longer disallowed if they are
    outside the sort block.  Also, a named unary or list operator inside the
    sort block no longer causes the $a or $b to be ignored [perl #86136].
    Mais du coup, le code d'alainbb devrait au moins produire un warning, or je n'en vois pas apparaître ... Ceci dit je n'ai pas vérifié si les warnings n'étaient pas trappés quelque part dans son programme, ou par Moose, ou par Tk. De plus il me semble que ce warning est normalement émis par le tokenizer perl, qui est d'une complexité confondante, et il est aussi possible qu'il n'arrive tout simplement pas à l'émettre dans ce cas particulier...

    Je me demande du coup si Perl::Critic parviendra de son côté à détecter le problème mais je n'ai pas le courage de tester... Alainbb, si tu t'y remets, tu nous dira ?
    Sauf indication contraire tous les codes que je présente sont utilisables et testés (mais sans garantie d'aucune sorte)
    J'apporte beaucoup de soin à la rédaction de mes posts et apprécie les retours donc merci de s'il vous paraissent pertinents ou utiles
    Lazyness, Impatience and Hubris are good for you

  13. #13
    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
    Bonne remarque, . Ca a effectivement été transformé en warning à partir de la version 5.18 (et il faut donc les activer pour le voir ) :
    OK, merci de l'info ++, j'avais initialement décidé de tester le bout de code précisément pour vérifier si les warnings détectaient le problème et ce qu'ils disaient, mais je n'ai pas pu le faire vu que j'obtenais une erreur.

  14. #14
    Membre habitué

    Homme Profil pro
    Statisticien
    Inscrit en
    Novembre 2010
    Messages
    122
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Statisticien

    Informations forums :
    Inscription : Novembre 2010
    Messages : 122
    Points : 134
    Points
    134
    Par défaut
    Perlcritic ne reconnait pas l'erreur.
    Damned,... encore raté.

  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 cmcmc Voir le message
    De plus il me semble que ce warning est normalement émis par le tokenizer perl, qui est d'une complexité confondante, et il est aussi possible qu'il n'arrive tout simplement pas à l'émettre dans ce cas particulier...
    En approfondissant, il s'avère effectivement que le warning n'est émis que pour des cas triviaux. Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Taisha:~/perl/forum $ perl -MData::Dump -wE 'my $b = "B"; dd sort { $a cmp $b } reverse "A" .. "D"'
    "my $b" used in sort comparison at -e line 1.
    ("B", "A", "C", "D")
    Taisha:~/perl/forum $
    mais dès qu'on complique un peu l'expression de comparaison le warning disparaît. Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/perl/forum $ perl -MData::Dump -wE 'my $b = "B"; dd sort { my ($aa,$bb) = ($a,$b); $aa cmp $bb } reverse "A" .. "D"'
    ("B", "A", "C", "D")
    Taisha:~/perl/forum $
    ou bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/perl/forum $ perl -MData::Dump -wE 'my $b = "B"; dd sort { lc $a cmp lc $b } reverse "A" .. "D"'
    ("B", "A", "C", "D")
    Taisha:~/perl/forum $
    malheureusement le fait de déréférencer $a ou $b prévient également la production du warning:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/perl/forum $ perl -MData::Dump -wE 'my $b = ["B", "B"]; dd map $_->[0] => sort { $a->[1] cmp $b->[1] } map [$_,$_] => reverse "A" .. "D"'
    ("B", "A", "C", "D")
    Taisha:~/perl/forum $
    Du coup le seul moyen de se protéger semble être d'ajouter our($a,$b) au début du bloc du sort :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Taisha:~/perl/forum $ perl -MData::Dump -wE 'my $b = ["B", "B"]; dd map $_->[0] => sort { our ($a,$b); $a->[1] cmp $b->[1] } map [$_,$_] => reverse "A" .. "D"'
    ("A" .. "D")
    Taisha:~/perl/forum $
    Cela a jusqu'à présent fonctionné sur tous les exemples que j'ai testés, et sur un large éventail de versions de perl (au moins depuis 5.10). Je ne recommande pas forcément de l'ajouter systématiquement, mais c'est peut-être un truc à garder en tête lorsqu'on a un doute sur un sort...
    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
    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
    Intéressant.

    Si l'on doit vraiment utiliser une variable $a ou $b, ceci fonctionne, comme je l'ai déjà dit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $ perl -E  'local  $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    Mais comme je ne vois pas pourquoi on devrait vraiment utiliser ainsi une variable $b, je dirais que le mieux est simplement de l'éviter en employant un autre nom de variable.

    La situation est différente si l'on désire utiliser les propriétés particulières de $a et $b pour autre chose qu'un tri, par exemple pour implémenter une fonction de type reduce, tout en se prémunissant du risque de perturber un tri. Alors l'emploi de local $a ou local $b peut être réellement utile.

  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 Lolo78 Voir le message
    Intéressant.

    Si l'on doit vraiment utiliser une variable $a ou $b, ceci fonctionne, comme je l'ai déjà dit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $ perl -E  'local  $b = 2; say for sort { $a <=> $b } reverse 0 .. 7'
    Ca ne fonctionne pas mieux que de ne pas utiliser local. Ca va juste changer la portée dynamique de la variable globale (i.e. de package) $b, avec potentiellement des effets pervers ailleurs. $a et $b sont des exceptions, et n'ont pas besoin d'être déclarées pour passer les strictures :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Taisha:~/perl/forum $ perl -Mstrict -wE '$b = 1; say for sort { $a <=> $b } reverse 0 .. 3'
    0
    1
    2
    3
    Taisha:~/perl/forum $
    de plus sort peut être utilisé de manière imbriquée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Taisha:~/perl/forum $ perl -MData::Dump -Mstrict -wE 'sub min { (sort { $a <=> $b } @_)[0] } dd sort { min(@$a) <=> min(@$b) } [1,2,3], [0,1], [3]'
    ([0, 1], [1, 2, 3], [3])
    Taisha:~/perl/forum $ perl -MData::Dump -Mstrict -wE 'dd sort { (sort { $a <=> $b } @$a)[0] <=> (sort { $a <=> $b } @$b)[0] } [1,2,3], [0,2], [3]'
    ([0, 2], [1, 2, 3], [3])
    Taisha:~/perl/forum $
    et sa cohabitation avec List::Util::reduce ne pose pas de problème particulier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Taisha:~/perl/forum $ perl -MData::Dump -Mstrict -MList::Util=reduce -wE 'sub sum { reduce { $a + $b } 0, @_ } dd sort { sum(@$a) <=> sum(@$b) } [1,2,3], [0,1], [3]'
    ([0, 1], [3], [1, 2, 3])
    Taisha:~/perl/forum $ perl -MData::Dump -Mstrict -MList::Util=reduce -wE 'dd sort { reduce { $a + $b } 0, @$a <=> reduce { $a + $b } 0, @$b } [1,2,3], [0,1], [3]'
    ([0, 1], [3], [1, 2, 3])
    Taisha:~/perl/forum $
    c'est juste l'utilisation de variables $a et $b lexicales (i.e. déclarées avec my) qui pose problème. Donc tu as raison, la meilleure option est de ne jamais le faire
    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

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [ XML::Simple] Problème "Not an ARRAY reference"
    Par Sweet dans le forum Modules
    Réponses: 3
    Dernier message: 14/01/2014, 16h36
  2. Réponses: 1
    Dernier message: 13/02/2012, 11h16
  3. jQuery erreur "Warning:" parfois mais pas tout le temps
    Par elizabeth dans le forum jQuery
    Réponses: 6
    Dernier message: 02/01/2012, 11h30
  4. [Débutant] Message d'erreur que je ne comprends pas
    Par Le Furet dans le forum Langage
    Réponses: 2
    Dernier message: 25/02/2006, 17h37
  5. Réponses: 2
    Dernier message: 07/09/2005, 09h55

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