ProgramaciónDesarrollador Perl Full Stack

¿Cuáles son los métodos para pasar argumentos a subprogramas en Perl y cómo organizar la transmisión por referencia? ¿Cuáles son las sutilezas del trabajo con @_ y cuándo es necesario pasar por referencia?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

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.

Pasar por valor:

sub foo { my ($arg1, $arg2) = @_; $arg1 = 10; # Solo cambia la variable local }

Pasar por referencia:

sub bar { my ($array_ref) = @_; push @$array_ref, 42; } my @data = (1,2,3); bar(\@data); # @data ahora es (1,2,3,42)

Sutilezas:

  • Si deseas cambiar el arreglo o hash original, pasa una referencia.
  • Las variables normales ($foo, $bar) dentro de @_ son alias de los argumentos originales, pero al descomprimir con my ($a, $b) = @_, se crean copias.
  • Para arreglos y hashes al pasar normalmente, su contenido se expande en una lista, y perderás los límites: debes pasar una referencia o usar la especificidad de los desplazamientos.

Pregunta capciosa

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).

Ejemplo:

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

En uno de los proyectos para modificar un hash global, se llamaba a la función así: 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

Al escribir un marco de API, se pasaban muchos argumentos nombrados a las funciones, utilizando un hash. A veces se pasaba un arreglo (pero no una referencia), y los argumentos se "mezclaban", lo que llevaba a confusiones: 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.