2009-11-09 12 views
7

módulo foo/bar.pmPerl: símbolos de exportación de módulo que tiene> 1 paquete

package foo::bar; 
stuff 
stuff 
package foo::wizzy; 
require Exporter; 
our @ISA=qw(Exporter); 
our @EXPORT=qw(x); 
use constant 
{ 
    x=>1 
}; 

un consumidor que hace

use Foo::bar; 

no recibe la exportación foo::wizzy::x

sé Puedo convertirlo en dos módulos separados, pero aún así debería poder hacer que esto funcione, ¿no es así?

+1

thx a todos - el consenso parece - 2 ficheros uso sólo estaba siendo perezoso y prometo decir Foo foo no – pm100

+2

En ese caso, te upvote! :) – Ether

Respuesta

3

Al final del módulo, puso:

BEGIN { $INC{'foo/wizzy.pm'} = 1 } 

Luego código puede simplemente decir:

use foo::bar; 
use foo::wizzy; 

para obtener las exportaciones de foo :: wizzy.

+0

ooo - eso es bueno - thx – pm100

7

Cuando se llama a use foo::bar, lo que realmente sucede es esencialmente:

BEGIN { 
    require foo::bar; 
    foo::bar->import; 
} 

(ver perldoc -f use)

Así import nunca está recibiendo llamadas en foo::wizzy. Si también desea importar esos símbolos, puede llamar al BEGIN { foo::wizzy->import } usted mismo (después de use foo::bar). O, como dijiste, simplemente divide estos dos paquetes en archivos separados, que serían mucho más legibles para los humanos.

(Por cierto, no es aconsejable el uso de nombres de paquetes entubados inferior, como los que son generalmente reservados para prágmata Perl.)

+1

El OP también podría escribir un método personalizado de 'importación' para foo :: bar que exporta las cosas desde Foo :: wizzy. (No es que lo haga de esa manera.) –

+4

@Michael: sí, solo puse paquetes juntos para el código de la servilleta, así que en este punto iría "f-- it, estoy No ahorras tiempo para tener estos dos paquetes en un solo archivo "y los divides. – Ether

+0

+1 especialmente para el comentario anterior. –

7

Puede hacerlo utilizando el método del exportador export_to_level tener el "paquete principal" re -export símbolos del "otro" paquete de este modo:

sub import { 
    my $self = shift; 
    $self->export_to_level(1, @_); 
    Some::Other::Module->export_to_level(1); 
} 

aunque si Some::Other::Module hace algo más complicado que "exportar todo" es probable que necesite un manejo más elegante para @_.

que realmente tiene que preguntarse por qué , aunque — No me puedo imaginar un uso para esto que es compatible con las palabras "bueno" :) código

+0

+1 Me olvidé de 'export_to_level' y casi recreé la funcionalidad ;-) –

+1

Sí, siempre empiezo a ponerme un poco a la defensiva cuando veo a otra persona jugando con mi tabla de símbolos ... es como una invasión del espacio personal: tú mejor estar en una emergencia, o casado conmigo :) – Ether

2

En primer lugar, me parece útil el uso de llaves encerrando para controlar el alcance cuando se incluyen múltiples paquetes en un archivo. Además, adjuntar el paquete en un bloque BEGIN hace que funcione más como si se usara un use adecuado para cargarlo, pero esto es principalmente si estoy introduciendo el paquete en el script principal.

use Foo es lo mismo que BEGIN { require Foo; Foo->import }.

lo tanto, usted tiene dos opciones:

  • llamada BEGIN{ Foo::Whizzy->import; } en el script principal.
  • make Foo::Bar::import disparador Foo::Whizzy::import en el módulo de llamada.

En Foo/Bar.pm:

{ package Foo::Bar; 
    use Exporter qw(export_to_level); 

    # Special custom import. Not needed if you call Foo::Whizzy->import 
    sub import { 
    shift; 
    export_to_level('Foo::Whizzy', 1, @_); 
    } 

    # stuff 
    # stuff 
} 

{ package Foo::Whizzy; 
    require Exporter; 

    our @ISA=qw(Exporter); 
    our @EXPORT=qw(x); 
    use constant { x=>1 }; 

} 

1; # return true 

En su código principal:

use Foo::Bar; 

# If you don't do a custom import for Foo::Bar, add this line: 
BEGIN { Foo::Whizzy->import }; 
Cuestiones relacionadas