Les tableaux de tableaux, hachages de hachages et autres structures de données complexes sont construits en Perl à l'aide de références. Cette approche permet de créer facilement des structures hiérarchiques/branchées, mais nécessite de la prudence lors de l'accès, de la copie et de la modification, car par défaut, c'est la référence qui est mémorisée, et non le contenu.
À l'origine, Perl ne supportait que des tableaux et des hachages plats, sans imbrication. Plus tard, le support des références a été ajouté, ce qui a permis de construire n'importe quelle combinaison : tableaux de tableaux, hachages de hachages, structures "arbre", "graphe", etc.
Travailler avec des structures complexes nécessite de se rappeler que les opérations d'accès, d'écriture et de copie travaillent avec des références. Les erreurs surviennent souvent en raison de la confusion entre un élément et la référence à cet élément. Cela engendre de nombreux bogues, par exemple, la modification des données à un endroit se reflète sur toute la structure, si la référence est utilisée par plusieurs parties du programme simultanément.
Pour créer un tableau de tableaux :
my @matrix; for my $i (0..2) { for my $j (0..2) { $matrix[$i][$j] = $i * $j; } } print $matrix[1][2]; # 2
Pour un hachage de hachages :
my %data; $data{'user1'}{'name'} = 'Alex'; $data{'user1'}{'age'} = 20;
Pour des structures mixtes :
my %complex = ( 'list' => [1, 2, 3], 'map' => { foo => 'bar' }, );
Que se passe-t-il si vous essayez d'assigner un tableau à un autre pour copier la structure ?
Cette assignation ne copie pas les structures imbriquées, mais seulement les références à celles-ci (c'est-à-dire qu'il s'agit d'une "copie superficielle").
my @a = ([1,2], [3,4]); my @b = @a; $a[0][0] = 99; printf "$b[0][0] "; # Affichera 99, car @b contient des références aux mêmes tableaux que @a
Quelle est la différence entre accéder à un élément comme $array[$i] et $array->[$i] ?
La première option fonctionne si nous avons un tableau, la seconde — si nous avons un scalaire qui référence un tableau. Pour des structures imbriquées, la syntaxe la plus courante est celle avec flèche ($foo->[0]).
Pourquoi ne peut-on pas simplement faire une copie de la structure via dclone dans le Perl standard ?
Parce que dclone n'est pas inclus dans la distribution de base de Perl. Pour la copie profonde de structures complexes, le module Storable et la fonction dclone sont utilisés :
use Storable 'dclone'; my $deep_copy = dclone(\%complex);
Dans le projet, un tableau de tableaux est copié par une assignation normale (@copy = @org), et après un certain nombre de modifications, ils remarquent soudain que les données de "l'original" ont changé en même temps que la copie.
Avantages :
Inconvénients :
Ils utilisent le module Storable et la fonction dclone pour copier des tableaux et des hachages, en documentant clairement cela dans le code et en distinguant clairement où est la référence et où ce n'est pas une référence.
Avantages :
Inconvénients :