Envoyé par
Philou67430
Pour retourner une référence, je procède presque toujours ainsi :
ce qui a l'avantage, de mon point de vue, de toujours retourner une référence (alors que %h ? \%h : () retourne soit une référence, soit undef en contexte scalaire ou une liste vide en contexte de liste).
Pourquoi undef au lieu de {} ?
Ouh là ... Plusieurs choses à dire :
Tout d'abord, ici il est essentiel de renvoyer soit la liste vide (), soit une référence à un hash ($h ou \%h). On renvoie la liste vide () quand on parse le TR d'entête (celui qui contient les <TH>col</TH>), parce que justement dans ce cas on ne peut pas renvoyer de hashref puisqu'on n'a pas encore de valeurs... Ce n'est que quand on lit un TR de ligne ou de valeur (c'est à dire contenant des <TD>val</TD>) que l'on peut construire le hash { col1 => val1, col2 => val2, ... , coln => valn} pour cette ligne.
Pour une table avec 1 TR d'entête et m TR de lignes, le map sur les TR renvoie conceptuellement la liste
(), $hashref1, $hashref2, ..., $hashrefm
La liste vide est aplatie et disparaît lors de l'affectation à @table dans
my @table = map { ... } m{(<TR.*?</TR>)}imsg;
et c'est exactement ce qu'on veut.
C'est pourquoi la valeur de retour du map est ici $h || (). C'est la forme adaptée au besoin, elle tient compte du fait qu'on est en contexte de liste (affectation à une table), et les considérations sur sa valeur en contexte scalaire (aussi exactes soient-elles ) ne sont pas pertinentes ici.
C'est également pourquoi $h doit être laissé non-initialisé, ou bien initialisé à undef (uniquement pour marquer le coup, le résultat est le même), et surtout pas initialisé à {} car dans ce dernier cas $h est vrai et le test $h || () renvoie toujours $h ce qui est désastreux.
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 :
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; |
ça marche, on peut si on préfère déclarer %h plutôt que $h, et c'est peut-être plus clair... Tu préfères cela ?
(je vais répondre sur \%h vs. [ %h ] dans un message séparé).
Partager