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:

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: