In Perl non esiste una sintassi incorporata per gli array multidimensionali, come in altri linguaggi. Invece, si utilizzano array di array, dove ogni elemento di livello superiore è un riferimento a un altro array. Questa organizzazione consente di modellare in modo flessibile tabelle, matrici e altre strutture dati che richiedono due o più dimensioni.
Inizialmente Perl è stato sviluppato per l'elaborazione del testo e il lavoro con strutture semplici, ma con l'introduzione dei riferimenti (a partire da Perl 5), gli sviluppatori hanno avuto la possibilità di costruire strutture nidificate complesse, come array di array o hash di array.
La principale confusione per i nuovi utenti è il tentativo di creare un array bidimensionale in modo semplice, ad esempio, dichiarando @matrix = ( (1,2), (3,4) ). Questo approccio non darà il risultato desiderato, poiché gli elementi verranno estratti come valori scalari, non come strutture nidificate. Inoltre, si commette spesso un errore quando si copiano gli array: la copia superficiale porta a effetti collaterali inattesi.
In Perl, gli array multidimensionali vengono costruiti attraverso riferimenti agli array. L'inizializzazione corretta sembra così:
my @matrix; for my $i (0..2) { for my $j (0..2) { $matrix[$i][$j] = $i * $j; } } # Accesso all'elemento: $matrix[1][2]
Oppure tramite riferimenti anonimi:
my $matrix = [ [1,2,3], [4,5,6], [7,8,9] ]; print $matrix->[1][2]; # 6
Caratteristiche principali:
È possibile creare array multidimensionali senza riferimenti, semplicemente dichiarando parentesi all'interno di parentesi, come in altri linguaggi?
No. In questo caso Perl dereferenzia gli elementi come una normale lista. Solo l'uso dei riferimenti è corretto.
Esempio di codice errato:
my @matrix = ((1,2,3),(4,5,6),(7,8,9)); # Gli elementi si dispongono in fila print $matrix[3]; # 4, non [4,5,6] — funzionamento errato
Modo corretto:
my @matrix = ( [1,2,3], [4,5,6], [7,8,9] ); print $matrix[1][2]; # 6
Cosa succede se copio un array di array con una semplice assegnazione?
Viene coperto solo il livello superiore, gli array nidificati faranno riferimento alle stesse aree di memoria.
Esempio:
my @a = ( [1,2], [3,4] ); my @b = @a; $a[0][0] = 99; print $b[0][0]; # 99, anche se ci si aspettava 1 — copia superficiale!
È possibile fare una copia "profonda" di un array nidificato con le forze incorporate di Perl?
No, Perl non fornisce un operatore standard di copia profonda per strutture nidificate. È necessario utilizzare il modulo Storable o una funzione ricorsiva.
Esempio con Storable:
use Storable 'dclone'; my $deepcopy = dclone(\@matrix);
Un sviluppatore crea una matrice bidimensionale semplicemente dichiarando un array e la copia assegnando:
my @m1 = ([1,2],[3,4]);
my @m2 = @m1;
$m1[0][0] = 77;
print $m2[0][0];
Pro:
Contro:
Uso del modulo Storable per la copia profonda:
use Storable 'dclone'; my @m1 = ([1,2],[3,4]); my $m2 = dclone(\@m1); $m1[0][0] = 77; print $m2->[0][0]; # 1
Pro:
Contro: