En Perl, toda la argumentación de funciones se realiza a través de la matriz @_. Al llamar a un subprograma, todos los parámetros transmitidos se encuentran dentro de esta matriz, y originalmente es una lista, no una copia, es decir, si cambias $_[0], modificas el original.
sub foo { my ($arg1, $arg2) = @_; $arg1 = 10; # Solo cambia la variable local }
sub bar { my ($array_ref) = @_; push @$array_ref, 42; } my @data = (1,2,3); bar(\@data); # @data ahora es (1,2,3,42)
my ($a, $b) = @_, se crean copias.Si en Perl se pasa un arreglo a una función así:
myfunc(@arr), y dentro de la función se accede a$_[0], ¿qué habrá allí?
Respuesta correcta: ¡Habrá el primer elemento valor del arreglo, no una referencia a todo el arreglo! Para pasar un arreglo como un objeto entero, utiliza una referencia: myfunc(\@arr).
sub print_first { print $_[0], " "; } my @a = qw/foo bar baz/; print_first(@a); # Imprimirá 'foo', no una referencia al arreglo print_first(\@a); # Imprimirá ARRAY(0x...) — referencia a todo el arreglo
Historia
update_hash(%global). Dentro se modificaba $_[0]. Como resultado, solo se cambiaba un segmento local del array de argumentos, mientras que el hash global no se modificaba. La solución correcta fue pasar una referencia: update_hash(\%global).Historia
myfunc(@arr, %opts). Resultó que algunas claves del hash eran reemplazadas por los valores del arreglo, y descubrir el error no era fácil.Historia
Al implementar un recorrido recursivo de un árbol, se quería modificar los elementos internos. Se pasaban arreglos "tal cual", no por referencia. Se crearon copias, y los cambios no se reflejaban en el contexto externo. El problema se resolvió al cambiar a un estilo de transmisión por referencia.