Las matrices de matrices, hashes de hashes y otras estructuras de datos complejas se construyen en Perl utilizando referencias. Este enfoque permite crear fácilmente estructuras jerárquicas/diversificadas, pero requiere cuidado al acceder, copiar y modificar, ya que por defecto se recuerda la referencia y no el contenido.
Inicialmente, Perl solo soportaba matrices y hashes planos, sin anidaciones. Posteriormente, se introdujo el soporte de referencias, lo que permitió construir cualquier combinación: matrices de matrices, hashes de hashes, estructuras de "árbol", "grafo", etc.
Trabajar con estructuras complejas requiere recordar que las operaciones de acceso, escritura y copia funcionan con referencias. Los errores surgen a menudo debido a la confusión entre el elemento y la referencia al elemento. Esto genera numerosos errores, por ejemplo, modificar datos en un lugar se refleja en toda la estructura si la referencia es utilizada por varias partes del programa simultáneamente.
Para crear una matriz de matrices:
my @matrix; for my $i (0..2) { for my $j (0..2) { $matrix[$i][$j] = $i * $j; } } print $matrix[1][2]; # 2
Para un hash de hashes:
my %data; $data{'user1'}{'name'} = 'Alex'; $data{'user1'}{'age'} = 20;
Estructuras mixtas:
my %complex = ( 'list' => [1, 2, 3], 'map' => { foo => 'bar' }, );
¿Qué sucederá si intentamos asignar una matriz a otra para copiar la estructura?
Tal asignación no copia estructuras anidadas, sino que solo se copian referencias a ellas (es decir, se realiza una "copia superficial").
my @a = ([1,2], [3,4]); my @b = @a; $a[0][0] = 99; printf "$b[0][0] "; # Imprimirá 99, ya que @b contiene referencias a las mismas matrices que @a
¿Cuál es la diferencia entre acceder a un elemento como $array[$i] vs $array->[$i]?
La primera opción funciona si tenemos una matriz, la segunda — si tenemos un escalar que referencia a una matriz. Para estructuras anidadas, la sintaxis más común es la de flecha ($foo->[0]).
¿Por qué no se puede simplemente tomar una copia de la estructura a través de dclone en Perl estándar?
Porque dclone no forma parte de la distribución básica de Perl. Para copias profundas de estructuras complejas se utiliza el módulo Storable y la función dclone:
use Storable 'dclone'; my $deep_copy = dclone(\%complex);
En el proyecto, se copian matrices de matrices mediante una simple asignación (@copy = @org), y después de varios cambios se dan cuenta de que los datos del "original" cambiaron junto con la copia.
Ventajas:
Desventajas:
Se utiliza el módulo Storable y la función dclone para copiar matrices y hashes, documentando esto claramente en el código y diferenciando explícitamente dónde está la referencia y dónde no.
Ventajas:
Desventajas: