La respuesta trillada es que tiene que usar local
porque my *FH
es un error de sintaxis.
La respuesta "correcta" (pero no muy instructiva) es que lo estás haciendo mal. Debería usar filehandles léxicos y la forma de tres argumentos de open
.
sub newopen {
my $path = shift;
my $fh;
open($fh, '<', $path) or do {
warn "Can't read file '$path' [$!]\n";
return;
}
return $fh;
}
Para responder realmente qué requiere una explicación de la diferencia entre las variables léxicas y mundiales y entre el alcance de una variable y su duración.
El alcance de una variable es la parte del programa donde su nombre es válido. El alcance es una propiedad estática. La duración de una variable, por otro lado, es una propiedad dinámica. La duración es el tiempo durante la ejecución de un programa en el que la variable existe y contiene un valor.
my
declara una variable léxica. Las variables léxicas tienen un alcance desde el punto de declaración hasta el final del bloque adjunto (o archivo). Puede tener otras variables con el mismo nombre en diferentes ámbitos sin conflicto. (También puede volver a utilizar un nombre en ámbitos superpuestos, pero no lo haga). La duración de las variables léxicas se gestiona mediante el recuento de referencias. ¡Siempre y cuando haya al menos una referencia a una variable, el valor existe, incluso si el nombre no es válido dentro de un alcance particular! my
también tiene un efecto de tiempo de ejecución: asigna una nueva variable con el nombre dado.
local
es un poco diferente. Opera en variables globales. Las variables globales tienen un alcance global (el nombre es válido en todas partes) y una duración de toda la vida del programa. Lo que hace local
es realizar un cambio temporal en el valor de una variable global. Esto a veces se conoce como "alcance dinámico". El cambio comienza en el punto de la declaración local
y persiste hasta el final del bloque delimitador después del cual se restaura el valor anterior. Es importante tener en cuenta que el nuevo valor no está restringido al bloque; es visible en todas partes (incluidas las subrutinas llamadas). Las reglas de recuento de referencias aún se aplican, por lo que puede tomar y mantener una referencia a un valor localizado después de que el cambio haya expirado.
Volver al ejemplo: *FH
es una variable global. Más exactamente, es un "typeglob": un contenedor para un conjunto de variables globales. Un typeglob contiene una ranura para cada uno de los tipos de variables básicas (escalar, matriz, hash) más algunas otras cosas. Históricamente, Perl utilizaba typeglobs para almacenar filehandles y local
-izing them ayudó a asegurar que no se peleaban entre sí. Las variables léxicas no tienen typeglobs por lo que decir my *FH
es un error de sintaxis.
En las versiones modernas de Perl, las variables léxicas pueden y deben usarse como manejadores de archivos en su lugar. Y eso nos lleva de vuelta a la respuesta "correcta".
Programming Perl, 3ra Edición fue escrita hace mucho tiempo, en una galaxia muy, muy lejana. ¡Y tienes una versión incluso más antigua que eso! –
... y ahora estamos en la 6ª edición, creo que – osirisgothra