modules metacpan mcpan manager library perl module

metacpan - ¿Hay alguna manera de "usar" un único archivo que a su vez utiliza varios más en Perl?



perl package manager (6)

Algo como esto debería funcionar:

http://mail.pm.org/pipermail/chicago-talk/2008-March/004829.html

Básicamente, crea tu paquete con muchos módulos:

package Lots::Of::Modules; use strict; # strictly optional, really # These are the modules we want everywhere we say "use Lots::Of::Modules". # Any exports are re-imported to the module that says "use Lots::Of::Modules" use Carp qw/confess cluck/; use Path::Class qw/file dir/; ... sub import { my $caller = caller; my $class = shift; no strict; *{ $caller. ''::''. $_ } = /*{ $class. ''::''. $_ } for grep { !/(?:BEGIN|import)/ } keys %{ $class. ''::'' }; }

Luego use Lots :: Of :: Modules en otro lugar;

use Lots::Of::Modules; confess ''OH NOES'';

Me gustaría crear varios módulos que se utilizarán en casi todos los scripts y módulos de mi proyecto. Estos podrían usarse d en cada uno de mis scripts de esta manera:

#!/usr/bin/perl use Foo::Bar; use Foo::Baz; use Foo::Qux; use Foo::Quux; # Potentially many more.

¿Es posible mover todas estas instrucciones de uso a un nuevo módulo Foo::Corge y luego solo use Foo::Corge en cada uno de mis scripts y módulos?


Sí, es posible, pero no, no deberías hacerlo.

Acabo de pasar dos semanas para deshacerme de un módulo que no hacía más que usar otros módulos. Supongo que este módulo comenzó simple e inocente. Pero a lo largo de los años se convirtió en una gran bestia con muchas y muchas declaraciones de uso, la mayoría de las cuales no eran necesarias para ninguna ejecución de nuestra aplicación web. Finalmente, tomó unos 20 segundos solo para ''usar'' ese módulo. Y es compatible con la creación de módulos de copiado y pegado.

Así que de nuevo: puede lamentar ese paso en un par de meses o años. ¿Y qué obtienes por el lado positivo? Has guardado escribiendo un par de líneas en un par de módulos. Vaya cosa.


Sí.

En Foo / Corge.pm

use Foo::Bar; use Foo::Baz; use Foo::Qux; use Foo::Quux; 1; # Be successful

Todo lo que queda es conseguir que el directorio que contiene el subdirectorio Foo agregue a la ruta de su biblioteca ( @INC ). Alternativamente, crea Foo.pm y Foo.pm que use los otros módulos. Estarían en un sub-directorio de Foo al lado de Foo.pm

Si lo piensas, todos los módulos complejos de Perl que usan otros módulos hacen esto todo el tiempo. No están necesariamente en el mismo paquete de nivel superior ( Foo en este ejemplo), pero se usan de la misma manera.

Si bien puedes usar Carp, y Path :: Class y confesar, y así sucesivamente (como lo sugiere jrockway), eso parece excesivo desde donde estoy sentado.


Otra opción sería que Foo :: Corge simplemente reexportara cualquier artículo de interés normalmente:

package Foo::Corge; use base ''Exporter''; BEGIN { our @EXPORT_OK = qw( bar baz qux quux ); use Foo::Bar qw( bar ); use Foo::Baz qw( baz ); use Foo::Qux qw( qux ); use Foo::Quux qw( quux ); } 1;

(Las instrucciones de ''uso'' probablemente salgan del BEGIN , pero ahí es donde estaban en el código que verifiqué para verificar que funcionó como yo pensaba. Ese código realmente eval el use s, por lo que tiene una razón para que estén dentro de BEGIN que probablemente no se aplique en su caso).


[EDITAR: Mi solución anterior que implica el use Lots::Of::Modules; tenía un error sutil - ver abajo. La solución hace que las cosas sean un poco más feas, pero todavía funcionables.]

[EDITAR # 2: se agregó BEGIN { ... } alrededor del código para garantizar que las funciones definidas estén disponibles en tiempo de compilación. Gracias a jrockway por señalar esto.]

El siguiente código hará exactamente lo que hace el código de jrockway, solo que más simple y claro:

En Lots / Of / Modules.inc:

use Carp qw/confess cluck/; use Path::Class qw/file dir/; 0; # Flag an error if called with "use" or "require" instead of "do"

Para importar esas 4 funciones:

BEGIN { defined( do ''Lots/Of/Modules.inc'' ) or die; }

Porque no tenemos un package Lots::Of::Modules; declaración al comienzo de este archivo, las instrucciones de use se exportarán al paquete de la persona que llama.

Debemos usar do lugar de use o require , ya que este último solo cargará el archivo una vez (causando fallas si se use Lots::Of::Modules; se llama más de una vez, por ejemplo, en módulos separados use d por el programa principal). El más primitivo do no lanza una excepción si no puede encontrar el archivo nombrado por su argumento en @INC , de ahí la necesidad de verificar el resultado con defined .


usar @EXPORT en lugar de @EXPORT_OK, es más simple

Biblioteca es:

package mycommon; use strict; use warnings; use base ''Exporter''; our @EXPORT = qw(test); sub test { print "this is a test"; } 1;

usarlo:

#!/usr/bin/perl use strict; use warnings; use mycommon; common::test()