¿Cuándo debe usar una variable de paquete frente a una variable léxica (y cuál es la diferencia)?

StackOverflow https://stackoverflow.com/questions/1019617

Pregunta

Estoy viendo un código Perl más antiguo en Perl Monks para descubrir la programación con Win32 :: OLE y MS Word. Dispersos en todo el código hay variables con nombres como $ MS :: Word y similares, sin un ' my ' incluido en su declaración. Después de leer un poco en Google, entiendo que se llaman 'variables de paquete' versus 'variables léxicas' declaradas usando my .

Mi primera pregunta es ' ¿Para qué sirven las variables de paquete? '. Creo (entiendo) qué son las variables léxicas, pero no entiendo el propósito de las variables de paquete o cómo su uso difiere de las léxicas, por lo que mi segunda pregunta sería: ' ¿Cuál es la diferencia entre las variables léxicas y de paquete? ? '

¿Fue útil?

Solución

Una variable de paquete vive en una tabla de símbolos, por lo tanto, dado su nombre, es posible leerla o modificarla desde cualquier otro paquete o alcance. El alcance de una variable léxica está determinado por el texto del programa. La sección " Variables privadas a través de mi () " en la página de manual de perlsub da más detalles sobre la definición de léxicos.

Digamos que tenemos el siguiente MyModule.pm :

package MyModule;

# these are package variables
our $Name;
$MyModule::calls = "I do not think it means what you think it means.";

# this is a lexical variable
my $calls = 0;

sub say_hello {
  ++$calls;

  print "Hello, $Name!\n";
}

sub num_greetings {
  $calls;
}

1;

Observe que contiene un paquete $ calls y un léxico $ calls . Cualquiera puede acceder al primero, pero el módulo controla el acceso al segundo:

#! /usr/bin/perl

use warnings;
use strict;

use MyModule;

foreach my $name (qw/ Larry Curly Moe Shemp /) {
  $MyModule::Name = $name;
  MyModule::say_hello;
}

print MyModule::num_greetings, "\n";

print "calls = $MyModule::calls\n";

La salida del programa es

Hello, Larry!
Hello, Curly!
Hello, Moe!
Hello, Shemp!
4
calls = I do not think it means what you think it means.

Como puede ver, las variables del paquete son globales, por lo que se aplican todos los trucos y consejos habituales. A menos que se proporcione acceso explícitamente, es imposible que el código fuera del paquete MyModule acceda a su $ calls léxico.

La regla general es que casi siempre quieres usar léxicos. Mejores prácticas de Perl de Damian Conway es directo: " Nunca hacer que las variables formen parte de la interfaz de un módulo " (énfasis en el original).

Otros consejos

Debería leer Enfrentando el alcance por MJD.

perldoc perlmod también sería una lectura útil.

El código está fuera de este mundo feo. Pisotea todo tipo de espacios de nombres sin preocupación en el mundo solo porque el autor parece pensar que $ author :: email es genial.

Una mejor manera hubiera sido usar un hash:

my %author = (
   email => 'author@example.com',
   ...
);

No es necesario pisotear la tabla de símbolos.

Tengo algunos ejemplos de Win32 :: OLE : http: // www.unur.com/comp/ que no son obras de arte pero creo que son mejoras en este estilo. Ver también ¿Por qué el número de páginas en un documento de Word es diferente en Perl y Word VBA?

Voy a despotricar un poco :

@pgm::runtime_args = @ARGV ;

Entonces, renunciamos a la matriz estándar @ARGV para pisotear el espacio de nombres pgm . No solo eso, cada programador de Perl sabe qué es @ARGV . En cualquier caso, @pgm :: runtime_args no se usa nuevamente en el script.

$pgm::maxargs = $#pgm::runtime_args + 1 ;

Por supuesto, @pgm :: runtime_args en contexto escalar nos daría la cantidad de elementos en esa matriz. No tengo idea de por qué $ pgm :: maxargs podría ser necesario, pero si fuera así, esta línea debería haber sido:

$pgm::maxargs = @pgm::runtime_args;

No voy a citar más de estas cosas. Supongo que esto es lo que sucede cuando los programadores de Cobol intentan escribir Perl.

$program::copyright = "Copyright (c) 02002 - Kenneth Tomiak : All rights reserved.";

Me alegra que haya asignado cinco dígitos para el año. ¡Nunca se sabe!

PD: Creo que mis extractos constituyen un uso justo.

Las variables del paquete son variables globales; son visibles en todas partes en todo el programa (incluso en otros módulos). Son útiles cuando quiere o necesita ese nivel de visibilidad y / o influencia externa. Por ejemplo, el módulo Text :: Wrap los usa para permitir un único punto de configuración para la cantidad de columnas en las que se ajusta el texto. Además, las variables de paquete le permiten usar algo llamado "alcance dinámico". - pero ese es un concepto algo avanzado y ligeramente esotérico.

Para su segunda pregunta, consulte ¿Cuál es la diferencia entre mi y nuestro en Perl?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top