Arrays von Arrays, Hashes von Hashes und andere komplexe Datenstrukturen werden in Perl mit Hilfe von Referenzen aufgebaut. Dieser Ansatz ermöglicht es, hierarchische/verzweigte Strukturen leicht zu erstellen, erfordert jedoch Sorgfalt beim Zugriff, Kopieren und Ändern, da standardmäßig die Referenz und nicht der Inhalt gespeichert wird.
Ursprünglich unterstützte Perl nur flache Arrays und Hashes ohne Verschachtelung. Später wurde die Unterstützung für Referenzen hinzugefügt, was das Erstellen aller Kombinationen ermöglichte: Arrays von Arrays, Hashes von Hashes, Strukturen wie „Baum“, „Graf“ usw.
Die Arbeit mit komplexen Strukturen erfordert, dass man sich daran erinnert, dass die Zugriffs-, Schreib- und Kopieroperationen mit Referenzen arbeiten. Fehler treten häufig auf, weil es zu Verwirrung zwischen einem Element und einer Referenz auf ein Element kommt. Dies führt zu zahlreichen Bugs, beispielsweise wenn Änderungen an einem Ort die gesamte Struktur beeinflussen, wenn die Referenz von mehreren Teilen des Programms gleichzeitig verwendet wird.
Um ein Array von Arrays zu erstellen:
my @matrix; for my $i (0..2) { for my $j (0..2) { $matrix[$i][$j] = $i * $j; } } print $matrix[1][2]; # 2
Für einen Hash von Hashes:
my %data; $data{'user1'}{'name'} = 'Alex'; $data{'user1'}{'age'} = 20;
Gemischte Strukturen:
my %complex = ( 'list' => [1, 2, 3], 'map' => { foo => 'bar' }, );
Was passiert, wenn man versucht, ein Array einem anderen zur Kopierung der Struktur zuzuweisen?
Eine solche Zuweisung kopiert die verschachtelten Strukturen nicht, sondern nur die Referenzen auf diese (es findet also eine „flache Kopie“ statt).
my @a = ([1,2], [3,4]); my @b = @a; $a[0][0] = 99; printf "$b[0][0] "; # Gibt 99 aus, da @b Referenzen auf dieselben Arrays wie @a enthält.
Was ist der Unterschied zwischen dem Zugriff auf ein Element als $array[$i] vs $array->[$i]?
Die erste Variante funktioniert, wenn wir ein Array haben, die zweite – wenn wir einen auf ein Array verweisenden Skalar haben. Für verschachtelte Strukturen ist die am häufigsten verwendete Syntax die Pfeilnotation ($foo->[0]).
Warum kann man nicht einfach eine Kopie der Struktur mit dclone in standardmäßigem Perl machen?
Weil dclone nicht Teil der Standardinstallation von Perl ist. Für das tiefe Kopieren komplexer Strukturen verwendet man das Modul Storable und die Funktion dclone:
use Storable 'dclone'; my $deep_copy = dclone(\%complex);
Im Projekt werden Arrays von Arrays durch einfache Zuweisung kopiert (@copy = @org), und nach einer Reihe von Änderungen bemerken sie plötzlich, dass die Daten des „Originals“ sich zusammen mit der Kopie geändert haben.
Vorteile:
Nachteile:
Die Verwendung des Moduls Storable und der Funktion dclone zum Kopieren von Arrays und Hashes, dokumentiert dies explizit im Code und unterscheidet klar zwischen Referenzen und Nicht-Referenzen.
Vorteile:
Nachteile: