En Perl existen tres tipos principales de declaración de variables: my, our y state.
sub example_state { state $counter = 0; $counter++; return $counter; } for (1..3) { print example_state(), " "; # Imprimirá 1, luego 2, luego 3 }
Dónde utilizar correctamente:
my — casi siempre es la elección preferida para variables, a menos que haya una razón para el acceso global.our — para exportar variables entre módulos, cuando se requiere compartir.state — si la variable debe "recordar" un valor entre las llamadas a la función (por ejemplo, un contador de llamadas).¿Puede una variable declarada con our ser capturada en un closure al mismo nivel que my?
A menudo se responde "sí, es conveniente", pero no es así. Una variable our es global para el paquete, y el closure en esencia no está capturando su valor en el momento de la creación del closure, sino accediendo a través del nombre global. Por lo tanto, su "valor" puede cambiar desde fuera del closure y afectará a todos los closures.
our $x = 10; my $closure = sub { return $x; }; $x = 42; print $closure->(); # Devolverá 42, no 10
Historia
En un gran script para analizar logs, las variables se declararon a través de our para "facilidad de acceso" desde diferentes funciones del módulo. Como resultado, cambiar estas variables en una función provocaba un comportamiento inesperado en otra, rompiendo el procesamiento paralelo de los logs.
Historia
El uso de my para variables cuyo valor se requería mantener entre llamadas a la función (por ejemplo, un contador dentro de un recorrido recursivo) resultaba en un restablecimiento del valor en cada llamada, lo que provocaba una lógica de recorrido incorrecta. Cambiar a state resolvió la situación.
Historia
El uso incorrecto de our en un módulo importado (exportando variables sin Exporter) provocó una colisión de nombres al conectar dos módulos diferentes que utilizaban el mismo nombre de variable. Al final, los datos "saltaban" de un contexto a otro.