In Perl per eseguire una copia profonda delle strutture annidate (ad esempio, hash di array, array di hash) non si possono utilizzare semplici assegnazioni o funzioni standard (@b = @a, %b = %a, $clone = $orig). Queste operazioni creano solo una copia superficiale: gli oggetti annidati continuano a riferirsi alle stesse aree di memoria.
Per la copia profonda si utilizza:
Storable:use Storable 'dclone'; my $deep_copy = dclone($structure);
Clone: applicazione analoga.È importante ricordare: vengono coperti tutti i livelli di annidamento, comprese le referenze all'interno della struttura.
Cosa succede con un'assegnazione semplice di una struttura dati complessa: si copiano gli elementi annidati?
Risposta: No, viene coperto solo il livello superiore. Gli array e hash interni rimangono condivisi tra l'originale e la copia.
my $orig = { a => [1,2,3], b => { x => 7 } }; my $copy = $orig; $copy->{a}[0] = 99; # $orig->{a}[0] diventa anch'esso 99!
Solo l'uso della clonazione profonda darà una copia completamente indipendente.
Storia 1
In un'applicazione REST API, sono state clonate richieste per diversi clienti tramite una semplice assegnazione di riferimento. Di conseguenza, le modifiche alla risposta di un cliente si riflettevano immediatamente su tutti gli altri — perché tutti lavoravano con la stessa struttura dati annidata.
Storia 2
Nell'aggregare dati di una struttura complessa di array si è utilizzata la copia tramite push (push @new, @old), dimenticando i livelli annidati. Una modifica casuale di un hash annidato ha corrotto i dati di tutti gli aggregati — il bug ha tardato a essere identificato.
Storia 3
Per elaborare i log, in uno script si è duplicata la struttura tramite Clone, ma non si sono considerate le particolari "magiche" aree di oggetti — di conseguenza, si sono perse le necessarie funzioni/attributi. Alla fine la funzionalità era non valida, e l'errore si è riprodotto solo in produzione.