Tablice tablic, hashe haszy i inne złożone struktury danych są w Perl budowane za pomocą odniesień. Takie podejście pozwala łatwo tworzyć hierarchiczne/rozgałęzione struktury, ale wymaga ostrożności przy ich używaniu, kopiowaniu i modyfikacji, ponieważ domyślnie zapamiętywana jest sama referencja, a nie zawartość.
Początkowo Perl obsługiwał tylko płaskie tablice i hashe, bez zagnieżdżenia. Później pojawiło się wsparcie dla odniesień, co umożliwiło budowanie dowolnych kombinacji: tablice tablic, hashe haszy, struktury „drzewo”, „graf” itp.
Praca ze złożonymi strukturami wymaga pamiętania, że operacje odczytu, zapisu i kopiowania działają na odniesieniach. Błędy często pojawiają się z powodu zamieszania między elementem a odniesieniem do elementu. To prowadzi do licznych błędów, na przykład zmiana danych w jednym miejscu odzwierciedla się w całej strukturze, jeśli odniesienie jest używane przez różne części programu jednocześnie.
Aby stworzyć tablicę tablic:
my @matrix; for my $i (0..2) { for my $j (0..2) { $matrix[$i][$j] = $i * $j; } } print $matrix[1][2]; # 2
Dla hasha haszy:
my %data; $data{'user1'}{'name'} = 'Alex'; $data{'user1'}{'age'} = 20;
Mieszane struktury:
my %complex = ( 'list' => [1, 2, 3], 'map' => { foo => 'bar' }, );
Co się stanie, jeśli spróbujesz przypisać jedną tablicę do drugiej, aby skopiować strukturę?
Takie przypisanie nie kopiuje zagnieżdżonych struktur, a jedynie odniesienia do nich (czyli następuje „płytkie kopiowanie”).
my @a = ([1,2], [3,4]); my @b = @a; $a[0][0] = 99; printf "$b[0][0] "; # Wydrukuje 99, ponieważ @b zawiera odniesienia do tych samych tablic, co @a
Czym różni się dostęp do elementu jako $array[$i] a $array->[$i]?
Pierwsza wersja działa, jeśli mamy tablicę, druga — jeśli mamy skalar odwołujący się do tablicy. Dla złożonych struktur najczęściej używanym składnikiem jest strzałkowy ($foo->[0]).
Dlaczego nie można po prostu skopiować struktury przez dclone w standardowym Perl?
Ponieważ dclone nie jest częścią podstawowej instalacji Perla. Aby wykonać głębokie kopiowanie złożonych struktur, używa się modułu Storable i funkcji dclone:
use Storable 'dclone'; my $deep_copy = dclone(\%complex);
W projekcie kopiuje się tablicę tablic przez zwykłe przypisanie (@copy = @org), a po serii zmian nagle zauważają, że dane „oryginału” zmieniły się razem z kopią.
Plusy:
Minusy:
Używają modułu Storable i funkcji dclone do kopiowania tablic i hashy, wyraźnie dokumentując to w kodzie i wyraźnie rozróżniając, gdzie jest odniesienie, a gdzie nie ma odniesienia.
Plusy:
Minusy: