2010-06-04 18 views
6

De todo lo que he leído sobre el uso de módulos de Perl, el uso básico es:Perl - Paquete Temas/Módulo

  • archivo de módulo con .pm extensión, que incluye la declaración package <name>, donde <name> es el nombre del archivo de la módulo sin la extensión.
  • El archivo de código que usa el módulo contiene la instrucción use <name>;.

La aplicación que estoy codificando tiene un script de código principal que usa aproximadamente 5 módulos. Había olvidado incluir la declaración package <name> en los módulos, pero mi código aún funcionaba bien con la declaración use <name>. Comencé a recibir errores Undefined subroutine con uno de los módulos, por lo que agregué la declaración del paquete a cada uno de los módulos. Ahora el resto de esos módulos detuvo el funcionamiento de. ¿Lo que da?

Ejemplo:

mainapp.pl

#!/usr/bin/perl 
use UtyDate; 
my $rowDate = CurrentDate("YYYYMMDD"); 

UtyDate.pm

#!/usr/bin/perl 
package UtyDate; 
sub CurrentDate 
{ 
    #logic 
} 
return 1; 

Cuando funciono el código anterior, consigo el error Undefined subroutine &main::CurrentDate called at.... Sin embargo, si elimino la línea package UtyDate; de UtyDate.pm, no obtengo ningún error. Esta situación existe para varios pero no para todos mis módulos.

Obviamente hay mucho más código que no se muestra, pero estoy confundido sobre cómo el código que no estoy mostrando podría afectar las construcciones de paquete/uso que he mostrado aquí.

Respuesta

10

Cuando se utiliza un módulo, el código en el módulo se ejecuta en tiempo de compilación. A continuación, se invoca la importación en el nombre del paquete para el módulo. Así, use Foo; es lo mismo que BEGIN { require Foo; Foo->import; }

Su código trabajó sin los package declaraciones porque todo el código se ejecuta en el paquete main, que es utilizado por el código principal de la aplicación.

Al añadir las declaraciones package que dejó de funcionar, debido a que las subrutinas que ha definido ya no se define en main, pero en UtyDate.

Puede acceder a las subrutinas utilizando un nombre totalmente calificado UtyDate::CurrentDate(); o mediante la importación de las subrutinas en el espacio de nombre actual cuando use el módulo.

UtyDate.pm

package UtyDate; 
use strict; 
use warnings; 

use Exporter 'import'; 

# Export these symbols by default. Should be empty!  
our @EXPORT =(); 

# List of symbols to export. Put whatever you want available here. 
our @EXPORT_OK = qw(CurrentDate AnotherSub ThisOneToo); 

sub CurrentDate { 
    return 'blah'; 
} 

sub AnotherSub { return 'foo'; } 

programa principal:

#!/usr/bin/perl 
use strict; 
use warnings; 

use UtyDate 'CurrentDate'; 

# CurrentDate is imported and usable.  
print CurrentDate(), " CurrentDate worked\n"; 

# AnotherSub is not 
eval { AnotherSub() } or print "AnotherSub didn't work: [email protected]\n"; 

# But you can still access it by its fully qualified name 
print UtyDate::AnotherSub(), " UtyDate::AnotherSub works though\n"; 

Ver Exporter documentos para obtener más información.

+2

OP debería leer ' perlmod' (http://search.cpan.org/perldoc/perlmod) primero como prerrequisito para entender lo que sucede en 'Exporter'. – mob

+0

Gran explicación, gracias. Había visto Exporter usado en algunos de los ejemplos que vi, pero no todos, así que pensé que no estaba relacionado. Echaré un vistazo al doc también mobrule, gracias. – brydgesk

3

Falta el código de encabezado perl del exportador. Usted tendrá que añadir algo como lo siguiente a la parte superior de su archivo pm por debajo de la sentencia de paquete:

package UtyDate; 
BEGIN { 
    use Exporter(); 
    use vars qw($VERSION @ISA @EXPORT); 
    $VERSION = "1.0.0"; 
    @ISA = qw(Exporter); 
    @EXPORT = qw(&CurrentDate); 
} 

ver este enlace: http://perldoc.perl.org/Exporter.html#DESCRIPTION

+0

Edite de acuerdo con http://p3rl.org/Exporter#Good_Practices o use mejor [Sub :: Exporter] (http://p3rl.org/Sub::Exporter) en primer lugar. – daxim

1

Como alternativa a la sugerencia de gris, se puede hacer esto:

use UtyDate; 
UtyDate::CurrentDate(...); 
0

además de utilizar el exportador, como señala Gray, usted podría (feo, pero funciona) también llamar a las funciones con el nombre del módulo ..

usted fu nctiond/procedimientos no funcionan, ya que ahora están en un espacio de nombres diferen (definido por el nombre del módulo)

use UtyDate; 

UtyDate::CurrentDate() 
+1

Eso no es feo; esa es la forma estándar de llamar a funciones que no están escritas en un estilo OO. – Ether

+0

El espacio de nombre se define mediante la llamada 'paquete', no el nombre del módulo. Es solo una convención (aunque buena) que el nombre del paquete y el nombre del módulo son los mismos. – mob

+0

@Ether: ser estándar no es lo mismo que "no feo", me temo. Además, quise decir 'feo' en comparación con la 'solución' de Gray, que requería mucho menos cambio en el código ya escrito ('mucho cambio' es lo que considero 'feo' como en: cambio engendra errores. YMMV – lexu

Cuestiones relacionadas