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 :

Comportement des références différent entre 5.8 et 5.14


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 605
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 605
    Par défaut Comportement des références différent entre 5.8 et 5.14
    Bonjour la Communauté

    Je viens à vous parce que j'ai un léger soucis dans un script Perl conçu autrefois sous Perl 5.6, qui fonctionne nickel sous Perl 5.8 mais qui plante sous la 5.14.

    L'objectif : migration d'un vieux Linux à un Linux plus récent. Je suis donc en train de tester les comportements de mes programmes personnels et je bloque sur l'un d'eux.

    J'ai un hash de liste tout bête. Chaque clé du hash est bien évidemment unique et contient une liste de 5 valeurs.

    J'alimente ce hash à partir d'un fichier txt contenant par ligne "clé, valeur1, valeur2, ..., valeur 5.

    Mon hash de liste ressemble au final à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $hash{cle1}[0] = "valeur1";
    $hash{cle1}[1] = "valeur2";
    $hash{cle1}[2] = "valeur3";
    $hash{cle1}[3] = "valeur4";
    $hash{cle1}[4] = "valeur5";
    ... ... ...
    $hash{cle1500}[0] = "valeur1";
    $hash{cle1500}[1] = "valeur2";
    $hash{cle1500}[2] = "valeur3";
    $hash{cle1500}[3] = "valeur4";
    $hash{cle1500}[4] = "valeur5";
    Comme vous le voyez, rien de bien méchant.

    J'ai 6 hash que j'envoie dans une fonction et, bien entendu, j'utilise les références pour bien retrouver mes petits.

    Pour les hash de construction simple (hash{clé}->{valeur}), ça se passe super bien.
    Pour CE hash de liste (hash{clé}->[valeur]), ça fait planter le script lors de l'appel de la fonction.

    L'appel de la fonction se fait comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    TraiteData(\%{$hash_simple1{valeur1}}, \%{$hash_simple2{valeur1}}, 
    \%{$hash_simple3{valeur1}}, \%{$hash_simple4{valeur1}},
     \%{$hash_simple5{valeur1}},
    \%{$hash_de_liste{valeur1}}) # <--- mon hash de liste
    Le début de ma fonction TraiteData :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    sub TraiteData
    {
        my (@hash_simple1, @hash_simple2, @hash_simple3,
     @hash_simple4, @hash_simple5, @hash_de_liste);
     
        (@hash_simple1, @hash_simple2, @hash_simple3, 
    @hash_simple4, @hash_simple5, @hash_de_liste) = @_;
    }
    A l'appel de cette fonction, j'ai droit à un "NOT HASH REFERENCE".

    J'ai isolé les hash un par un et j'ai trouvé que c'était mon hash de liste qui ne passait plus sous Perl 5.14 alors qu'il marche sous 5.8.

    Qu'y a-t-il de mauvais dans ma syntaxe lorsque j'envoie la référence de mon hash de liste à la fonction ?

  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
    Billets dans le blog
    1
    Par défaut
    A vrai dire, je suis surpris que ton code fonctionne en 5.8.

    En principe, si tu passes des références (donc des scalaires) à ta fonction, tu dois récupérer des références dans la fonction appelée, pas directement des tableaux.

  3. #3
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Même remarque que Lolo78, ton code est mal écrit et son fonctionnement sous Perl 5.6 et 5.8 est déjà douteux .

    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
    #!/usr/bin/perl
    use strict;
    use warnings;
     
    my %hash;
    $hash{cle1}[0] = "valeur1";
    $hash{cle1}[1] = "valeur2";
    $hash{cle1}[2] = "valeur3";
    $hash{cle1}[3] = "valeur4";
    $hash{cle1}[4] = "valeur5";
    $hash{cle1500}[0] = "valeur1";
    $hash{cle1500}[1] = "valeur2";
    $hash{cle1500}[2] = "valeur3";
    $hash{cle1500}[3] = "valeur4";
    $hash{cle1500}[4] = "valeur5";
     
    TraiteData($hash{cle1}, $hash{cle1500});
     
    sub TraiteData {
    	my ($ref_tab1, $ref_tab2)= @_;
     
    	foreach my $valeur ( @{$ref_tab1} ) {
    		print "$valeur\n";
    	}
    	print "-----\n";
    	foreach my $valeur ( @{$ref_tab2} ) {
    		print "$valeur\n";
    	}
     
    	return;
    }
    Voici le code clean. À l'appel de la procédure, je passe en argument $hash{cle1}, $hash{cle2}... car les valeurs sont des références de tableaux. Dans la procédure, je récupère ainsi ces dernières.

  4. #4
    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
    Billets dans le blog
    1
    Par défaut
    Bonsoir Arioch,

    pour en avoir le cœur net, j'ai essayé une version légèrement simplifiée de ton code (deux paramètres passés à la procédure, au lieu de cinq, mais en gardant ta syntaxe), j'ai été limite un peu surpris de voir qu'il compile correctement, mais beaucoup moins surpris de voir qu'il ne marche pas (du moins en 5.10). Je ne vois vraiment pas comment il pouvait marcher en 5.8.

    Après quelques modifications pour utiliser correctement les références, j'obtiens au final un code essentiellement analogue à celui de Djibril à quelques nuances près, et ça marche:

    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
    #!/usr/bin/perl
    use strict;
    use warnings;
     
    my (%hash, %hash_simple1);
    $hash{cle1}[0] = "valeur1";
    $hash{cle1}[1] = "valeur2";
    $hash{cle1}[2] = "valeur3";
    $hash{cle1}[3] = "valeur4";
    $hash{cle1}[4] = "valeur5";
    $hash{cle1500}[0] = "valeur1";
    $hash{cle1500}[1] = "valeur2";
     
    $hash_simple1{"val1"} = "val1";
     
    TraiteData(\$hash_simple1{val1}, $hash{cle1});
     
    sub TraiteData
    {
        my ($hash_simple1_ref, $hash_de_liste_ref) = @_;
        print $$hash_simple1_ref, "\n";
        print "$_\n" foreach @{$hash_de_liste_ref};
    }
    Ce qui imprime:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ perl hash_s.pl
    val1
    valeur1
    valeur2
    valeur3
    valeur4
    valeur5
    Les modifications essentielles sont les suivantes.

    Dans l'appel à la fonction ("TraiteData(\$hash_simple1{val1}, $hash{cle1});"), je passe à la fonction une référence à la valeur contenue dans $hash_simple1{val1} et une référence au tableau contenu dans $hash{cle1}.

    Dans la fonction elle-même, je récupère ces deux valeurs (deux références, donc, deux scalaires), que je déréférence pour imprimer d'abord la valeur contenue dans $hash_simple1{val1}, puis les cinq valeurs contenues dans le tableau pointé par $hash_de_liste_ref, à savoir les cinq valeurs du tableau contenu dans le tableau pointé par $hash{cle1}.

    Remarque: dans le cas des hash simples, passer une référence sur la valeur contenue dans le hash n'a en fait aucun intérêt dans le cas du code ci-dessus se contentant d'imprimer la valeur, un passage par valeur suffisait amplement. Passer une référence au contenu du hash a éventuellement un intérêt si l'on désire modifier le contenu du hash; mais même dans ce cas, un passage par valeur et un retour de la valeur modifiée serait sans doute préférable (code plus lisible et n'utilisant pas des variables globales plus ou moins camouflées, donc, code a priori réentrant). Quelque chose comme cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $hash_simple1{"val1"} = "17";
    $hash_simple1{"val1"} = traite_data2( $hash_simple1{"val1"} ); # $hash_simple1{"val1"} vaut maintenant 35
     
    sub traite_data2  {
         my $local_val = shift;
         $local_val ++;
         return 5 * $local_val /2; 
    }
    Bien que, dans ce cas, je ne me fatiguerais même pas à donner une valeur initiale au hash_simple et écrirais plutôt:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    my $var17 = 17;
    $hash_simple1{"val1"} = traite_data2( $var17 ); 
     
    sub traite_data2  {
         my $local_val = shift;
         $local_val ++;
         return 5 * $local_val /2; 
    }
    ou même:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $hash_simple1{"val1"} = traite_data2( 17 ); 
     
    sub traite_data2  {
         # ...
    }

  5. #5
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 605
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 605
    Par défaut
    Merci à vous deux de vous être penchés sur mon cas

    J'ai finalement corrigé mon appel à la fonction comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    TraiteData(\%{$hash_simple1{valeur1}}, \%{$hash_simple2{valeur1}}, 
    \%{$hash_simple3{valeur1}}, \%{$hash_simple4{valeur1}},
     \%{$hash_simple5{valeur1}},
    \@{$hash_de_liste{valeur1}}) # <--- mon hash de liste
    Dans la dernière variable envoyée, j'ai juste remplacé le \% par \@ et ça ne bugge plus.

    Je viens sinon de tester un bout de code similaire sur le Perl 5.8.8 du boulot. Bout de code qui fonctionnait ce week end encore sur le Perl 5.8 de mon ancien Linux. Là, il plante sur la 5.8.8.

    J'ai juste l'impression qu'avant la 5.8.8, le compilateur de Perl était un peu permissif...

    Merci encore !

    Ca m'a permis de refaire un tour ici, comme au bon vieux temps

  6. #6
    Responsable Perl et Outils

    Avatar de djibril
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    19 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 19 822
    Par défaut
    Ta façon de faire n'est toujours pas bonne Arioch. Du moins, elle fonctionnera mais n'est pas bonne.

    Ce code \%{$hash_simple1{valeur1}} est inutile car tu crées la référence d'un hash que tu déréférences. Autant envoyer directement la référence.

    Donc $hash_simple1{valeur1} au lieu de \%{$hash_simple1{valeur1}}

Discussions similaires

  1. Comportement des Layout différent en fonction du style utilisé
    Par atha2 dans le forum Composants graphiques
    Réponses: 3
    Dernier message: 17/12/2012, 18h47
  2. [COM] Comportement des références
    Par Sangdrax1604 dans le forum VB.NET
    Réponses: 1
    Dernier message: 17/03/2008, 17h11
  3. Réponses: 12
    Dernier message: 26/10/2007, 16h27
  4. tri des données différent entre 2 bases
    Par j6m dans le forum Oracle
    Réponses: 2
    Dernier message: 12/03/2006, 10h17
  5. Comportement différent entre un bouton et une image
    Par MicheMTP13 dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 07/11/2005, 08h47

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