Perl5,pb: affectation d'un hashage dans une boucle. trivial?

Bonjour,

:angry: comme toujours après une trop longue pause entre 2 séquences de programmation Perl ( Perl5 ), je me heurte à un bug trivial.

[code]my @CHAMPS=qw( COMITE NOM DATE MISSION RAPPORT CONCLUSION CERTIFIE NOTE RAPPEL ) ;
my %CHAMPS_pour; # La variable de base !
my @lettres=qw( A B C );

@CHAMPS

@lettres

foreach my $nom ( @CHAMPS ) {
say $nom;

while ( my $lettre=shift(@lettres) ) {
    ### $lettre
    my $cle="$nom"."$lettre";
    $CHAMPS_pour{$cle}="$nom".'-'."$lettre" ;
};

};[/code]

sans la boucle while, la boucle foreach parcourt bien tout le tableau @CHAMPS ( DE COMITE à RAPPEL )
Avec la boucle while, seul le 1er élément (COMITE) semble parcouru.( la boucle while fonctionne avec cet élément )

[size=85]L’ affichage des variables est réalisé au fur et à mesure avec les commentaires « ### $var » du module Smart::Comments[/size]

[size=85]J’ai écrit cette portion de programme pour tenter de comprendre le BUG d’un script plus élaboré, ce qui explique le caractère sinon absurde de sa fonction.[/size]

Merci pour votre aide ( et pour votre bienveillante compréhension.. )

[edit] le titre initial

est sans doute faux

je le remplace par

et je m’explique:

1 Le code:
( j’ai mis en sous-programme la boucle while, et ajouter des affichages de variables )

[code]#!/usr/bin/perl -w
use 5.010;
use warnings;
use strict;
use diagnostics;
use Smart::Comments ;

my @CHAMPS=qw( COMITE NOM DATE ) ;
my %CHAMPS_pour; # La variable de base !
my @lettres=qw( A B C );

@CHAMPS

@lettres

foreach my $nom ( @CHAMPS ) {
### $nom;
### appel à assembler sur: $nom
assembler($nom);
};

sub assembler {
my ($N)=@_ ;
### assembler avec : $N
while ( my $lettre=shift(@lettres) ) {
### assembler: $N
### while avec: $lettre
my $cle=« $N ».« $lettre »;
### $cle
my $val=« $N ».‹ - ›.« $lettre »
$CHAMPS_pour{$cle} = $val ; # L’erreur survient ici
### $CHAMPS_pour{$cle}
};
return;
}

%CHAMPS_pour[/code]

2 L’affichage: les lignes du type ### $cle ou ### %CHAMPS_pour affichent les variables comme print (scalaires) ou comme Dumper ( tableaux, hashages )

[code]./hashage.pl

@CHAMPS: [

‹ COMITE ›,

‹ NOM ›,

‹ DATE ›

]

@lettres: [

‹ A ›,

‹ B ›,

‹ C ›

]

$nom: ‹ COMITE ›

appel à assembler sur: ‹ COMITE ›

assembler avec : ‹ COMITE ›

assembler: ‹ COMITE ›

while avec: ‹ A ›

$cle: ‹ COMITEA ›

$val: ‹ COMITE-A ›

$CHAMPS_pour{$cle} L’ERREUR APPARAÎT ICI

                   (attendu: COMITE-A, résultat de l'affectation de $CHAMPS_pour{COMITEA} )

assembler: ‹ COMITE ›

while avec: ‹ B ›

$cle: ‹ COMITEB ›

$val: ‹ COMITE-B ›

$CHAMPS_pour{$cle}

assembler: ‹ COMITE ›

while avec: ‹ C ›

$cle: ‹ COMITEC ›

$val: ‹ COMITE-C ›

$CHAMPS_pour{$cle}

$nom: ‹ NOM ›

appel à assembler sur: ‹ NOM ›

assembler avec : ‹ NOM ›

$nom: ‹ DATE ›

appel à assembler sur: ‹ DATE ›

assembler avec : ‹ DATE ›

%CHAMPS_pour: {

COMITEA => ‹ COMITE-A ›,

COMITEB => ‹ COMITE-B ›,

COMITEC => ‹ COMITE-C ›

}

[/code]

L’ affichage

montre que l’affectation ne se fait pas ( Pourtant elle a été faite 1 fois, avec le 1er tour de boucle foreach, comme l’indique l’affichage final de %CHAMPS_pour )

Dans l’état actuel de ma compréhension limitée, ma question est donc pourquoi la ligne du type:

$CHAMPS_pour{$cle}=$val
n’ utilise-t-elle pas la valeur de $cle pour affecter la valeur à cette clé ?

2 Tests qui fonctionnent comme attendu:

Le 1er, avec foreach:

[code]my @CHAMPS=qw( COMITE NOM DATE ) ;
my %CHAMPS_pour ; # La variable de base !
my @lettres=qw( A B C );

@CHAMPS

@lettres

foreach my $champs ( @CHAMPS ) {
my $cle=‘cle_’."$champs" ;
$CHAMPS_pour{$cle}=$champs ;
### %CHAMPS_pour
};[/code]

Le 2e avec while:

[code]my @CHAMPS=qw( COMITE NOM DATE ) ;
my %CHAMPS_pour ; # La variable de base !
my @lettres=qw( A B C );

@CHAMPS

@lettres

while ( my $champs=shift @CHAMPS ) {
my $cle=‘cle_’."$champs" ;
$CHAMPS_pour{$cle}=$champs ;
### %CHAMPS_pour
};[/code]

Les 2 affichent exactement la même chose, attendue:

[code]

%CHAMPS_pour: {

cle_COMITE => ‘COMITE’

}

%CHAMPS_pour: {

cle_COMITE => ‘COMITE’,

cle_NOM => ‘NOM’

}

%CHAMPS_pour: {

cle_COMITE => ‘COMITE’,

cle_DATE => ‘DATE’,

cle_NOM => ‘NOM’

[/code]}

Jusqu’ici je ne vois pas où est mon BUG

:confusion-confused: Autre présentation, peut-être plus lisible, du même bug:

[code]my $scalaire;
my @tableau= qw( un deux trois );
my %hashage;

$scalaire=‘valeur’;

$scalaire

$hashage{cle1} = $scalaire;

%hashage;

foreach my $new ( ‘Nouveau1’ , ‘nouveau2’ ) {
### $new
while ( my $a = shift @tableau ) {
### $a
#my $new = ‘Nouveau’;
$hashage{$a}=$new;

    ### @tableau
};
### @tableau
### %hashage

}; # fin de foreach
[/code]

qui renvoie:

[code]### $scalaire: ‘valeur’

%hashage;

$new: ‘Nouveau1’

$a: ‘un’

@tableau: [

‘deux’,

‘trois’

]

$a: ‘deux’

@tableau: [

‘trois’

]

$a: ‘trois’

@tableau: []

@tableau: []

%hashage: {

cle1 => ‘valeur’,

deux => ‘Nouveau1’,

trois => ‘Nouveau1’,

un => ‘Nouveau1’

}

$new: ‘nouveau2’

@tableau: []

%hashage: {

cle1 => ‘valeur’,

deux => ‘Nouveau1’,

trois => ‘Nouveau1’,

un => ‘Nouveau1’

}

[/code]

On voit que seule le 1er élément du tableau exploré par foreach semble être passé à la boucle while

Aucune erreur (de syntaxe) n’est signalée par warning , strict ou diagnostics.
Il y a donc vraisemblablement une erreur de logique qui m’échappe.
Espace de nom ? mes tests n’ont rien trouvé.

Je rame à en creuser la falaise ! :angry-banghead:

Et en inversant l’imbricaion des boucles ( foreach dans un while ), je rencontre la même limite:

[code]my $scalaire;
my @tableau= qw( un deux trois );
my %hashage;
my @table_de_hashage;

$scalaire=‘valeur’;

$scalaire

$hashage{cle1} = $scalaire;

%hashage;

while ( my $a = shift @tableau ) {
### $a
foreach my $new ( ‘Nouveau1’ , ‘nouveau2’ ) {
### $new
$hashage{$new}=$a;
### %hashage
push @table_de_hashage, %hashage;
}; # fin de foreach
}; # Fin de while
### @table_de_hashage[/code]

Une seule affectation du tableau de hashage a été faite correctement ( les autres sont créées, mais vides ):

[code]### $scalaire: ‘valeur’

%hashage;

$a: ‘un’

$new: ‘Nouveau1’

%hashage: {

Nouveau1 => ‘un’,

cle1 => ‘valeur’

}

$new: ‘nouveau2’

%hashage: {

Nouveau1 => ‘un’,

cle1 => ‘valeur’,

nouveau2 => ‘un’

}

$a: ‘deux’

$new: ‘Nouveau1’

%hashage: {

Nouveau1 => ‘deux’,

cle1 => ‘valeur’,

nouveau2 => ‘un’

}

$new: ‘nouveau2’

%hashage: {

Nouveau1 => ‘deux’,

cle1 => ‘valeur’,

nouveau2 => ‘deux’

}

$a: ‘trois’

$new: ‘Nouveau1’

%hashage: {

Nouveau1 => ‘trois’,

cle1 => ‘valeur’,

nouveau2 => ‘deux’

}

$new: ‘nouveau2’

%hashage: {

Nouveau1 => ‘trois’,

cle1 => ‘valeur’,

nouveau2 => ‘trois’

}

@table_de_hashage: [

{

Nouveau1 => ‘trois’,

cle1 => ‘valeur’,

nouveau2 => ‘trois’

},

$VAR1->[0][0],

$VAR1->[0][0],

$VAR1->[0][0],

$VAR1->[0][0],

$VAR1->[0][0]

]

[/code]

ça avance, mais toujours dans la falaise :character-smurfgrandpa: