2009-04-08 14 views
18

me gustaría exponer a todos los subtítulos en mi espacio de nombres sin tener que enumerarlos uno a la vez:¿Cómo puedo exportar todos los subs en un paquete Perl?

@EXPORT = qw(firstsub secondsub third sub etc); 

El uso de nombres completos requeriría montón de cambio de código existente así que prefiero no hacerlo.

¿Hay @EXPORT_ALL?

Creo que la documentación dice que es una mala idea, pero me gustaría hacerlo de todos modos, o al menos saber cómo.

Responde Jon por qué: ahora mismo para una refactorización rápida Quiero mover un montón de subs en su propio paquete con menos problemas y cambios de código a los scripts existentes (donde esos subs se usan actualmente y se repiten a menudo).

Además, en su mayoría, solo tenía curiosidad. (ya que parecía que el exportador puede ser que también tenga que, como característica estándar, pero hasta cierto punto sorprendente basa en respuestas hasta el momento no)

+0

Quizás si pudieras decirnos * por qué * quieres hacerlo.¿Sólo por diversión? –

+0

OK, agregué algunas razones. –

Respuesta

23

No haga ningún tipo de exportación y no declare un nombre de paquete en su biblioteca. Simplemente cargue el archivo con require y todo estará en el paquete actual. Pan comido.

+0

¡Excelente respuesta! –

+0

¡Doh! Toqué toda la solución sin pensarlo. (Pero rompe la expectativa de que un módulo tenga su propio espacio de nombres, lo que puede sorprender). –

+3

¿Cómo debo "cargar" el archivo? –

2

Usted siempre puede llamar a subrutinas allí especificado totalmente formulario:

MyModule::firstsub(); 

Para los módulos que escribo internamente, creo que esta convención funciona bastante bien. Es un poco más tipeo, pero tiende a ser una mejor documentación.

Eche un vistazo a perldoc perlmod para obtener más información acerca de lo que está tratando de lograr.

De forma más general, podría consultar el código de Exporter y ver cómo utiliza el aliasing de glob. O puede examinar el espacio de nombres de su módulo y exportar cada subrutina. (No me importa a buscar cómo hacerlo en este momento, pero Perl hace que este bastante fácil.) O usted podría pegarse sus subrutinas en el main paquete:

package main; 
sub firstsub() { ... } 

(no creo eso es una buena idea, pero usted sabe mejor que yo lo que está tratando de lograr.)

no hay nada malo en hacer esto proporcionado usted sabe lo que está haciendo y no está tratando de evitar pensar en su interfaz con el mundo exterior.

+0

Sí, estoy al tanto de eso, pero ¿qué tal si no tengo que decir MyModule :: para cada sub? Estoy buscando EXPORTAR ¿TODOS? –

+0

@Ville M: ​​A menudo es difícil saber qué otra persona conoce si no lo dice. ;-) –

+0

Me viene a la mente algo sobre el sonido y el árbol cayendo en el bosque ... de todos modos, gracias por tu ayuda –

3

Advertencia, el siguiente código es tan mala idea como la exportación en todo:

package Expo; 

use base "Exporter"; 

seek DATA, 0, 0; #move DATA back to package 

#read this file looking for sub names 
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 :() } <DATA>; 

my $sub = sub {}; #make sure anon funcs aren't grabbed 

sub foo($) { 
    print shift, "\n"; 
} 

sub bar ($) { 
    print shift, "\n"; 
} 

sub baz{ 
    print shift,"\n"; 
} 

sub quux { 
    print shift,"\n"; 
} 

1; 

__DATA__ 

Aquí está el código que utiliza el módulo:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Expo; 

print map { "[$_]\n" } @Expo::EXPORT; 

foo("foo"); 
bar("bar"); 
baz("baz"); 
quux("quux"); 

Y aquí es su salida:

[foo] 
[bar] 
[baz] 
[quux] 
foo 
bar 
baz 
quux 
+0

Genial, exactamente lo que esperaba, no hay una forma estándar en el exportador, supongo, pero esto definitivamente hace lo que necesito, Muchas gracias –

+1

Creo que simplemente caminaría a través de la tabla de símbolos y buscaría las entradas de código definidas. Hay muchas formas en que la expresión regular puede fallar. –

+0

¿Podría explicar cómo "caminar a través de la tabla de símbolos"? –

10

No. Pero si realmente desea ... escriba un import personalizado que recorre la tabla de símbolos y exporta todas las subrutinas mencionadas.

# Export all subs in package. Not for use in production code! 
sub import { 
    no strict 'refs'; 

    my $caller = caller; 

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) { 
     next if  $name eq 'BEGIN'; # don't export BEGIN blocks 
     next if  $name eq 'import'; # don't export this sub 
     next unless *{$symbol}{CODE}; # export subs only 

     my $imported = $caller . '::' . $name; 
     *{ $imported } = \*{ $symbol }; 
    } 
} 
+0

También ver la respuesta de Leon en http://stackoverflow.com/questions/607282/whats-the-best-way-to-discover- all-subroutines-a-perl-module-has –

2

Tal vez estaría interesado en uno de los módulos de exportación * en CPAN que le permite marcar submarinos como exportables simplemente añadiendo un atributo a la definición de sub? (no recuerdo cuál era, sin embargo.)

+0

¿era esto en lo que estabas pensando? http://search.cpan.org/dist/Exporter-NoWork/lib/Exporter/NoWork.pm –

+0

@Chas. Owens - no, estaba pensando en Exporter :: Simple – ysth

1

Aunque no es típicamente prudente volcar todos sub s de módulo en el espacio de nombres de llamadas, a veces es útil (y más seco!) Para generar automáticamente @EXPORT_OK y %EXPORT_TAGS variables.

El método más fácil es extender el exportador. Un ejemplo sencillo es algo como esto:

package Exporter::AutoOkay; 
# 
# Automatically add all subroutines from caller package into the 
# @EXPORT_OK array. In the package use like Exporter, f.ex.: 
# 
#  use parent 'Exporter::AutoOkay'; 
# 
use warnings; 
use strict; 
no strict 'refs'; 

require Exporter; 

sub import { 
    my $package = $_[0].'::'; 

    # Get the list of exportable items 
    my @export_ok = (@{$package.'EXPORT_OK'}); 

    # Automatically add all subroutines from package into the list 
    foreach (keys %{$package}) { 
     next unless defined &{$package.$_}; 
     push @export_ok, $_; 
    } 

    # Set variable ready for Exporter 
    @{$package.'EXPORT_OK'} = @export_ok; 

    # Let Exporter do the rest 
    goto &Exporter::import; 
} 

1; 

Nota el uso de goto que nos saca de la pila de llamadas.

Puede encontrar un ejemplo más completo aquí: http://pastebin.com/Z1QWzcpZ Genera automáticamente grupos de etiquetas a partir de prefijos de subrutina.

1

caso 1

Biblioteca es:

package mycommon; 

use strict; 
use warnings; 

sub onefunctionthatyoumadeonlibary() { 
} 
1; 

que puede usarlo, llamando común :::

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

common::onefunctionthatyoumadeonlibary() 

el caso 2

Biblioteca es, yousimple exportarlos:

package mycommon; 

use strict; 
use warnings; 

use base 'Exporter'; 

our @EXPORT = qw(onefunctionthatyoumadeonlibary); 
sub onefunctionthatyoumadeonlibary() { 
} 
1; 

uso en mismo "nombre":

#!/usr/bin/perl 
use strict; 
use warnings; 
use mycommon qw(onefunctionthatyoumadeonlibary); 

onefunctionthatyoumadeonlibary() 

También podemos hacer una mezcla de estos dos casos, podemos exportar las funciones más comunes de utilizar sin llamar el nombre de paquetes y otras funciones que sólo llámalo con el nombre del paquete y los que no necesitan ser exportados.

Cuestiones relacionadas