2009-04-09 9 views
3

J'essaie de rendre plus facile de suivre certains Perl Best Practices en créant un module Constants qui exporte plusieurs des scalaires utilisés dans le livre. Un en particulier, $EMPTY_STRING, je peux utiliser dans à peu près tous les scripts Perl que j'écris. Ce que j'aimerais, c'est exporter automatiquement ces scalaires pour pouvoir les utiliser sans les définir explicitement dans chaque script.Comment exporter des variables Readonly avec mod_perl?

#!perl 
package Example::Constants; 

use Exporter qw(import); 
use Readonly; 

Readonly my $EMPTY_STRING => q{}; 
our @EXPORT = qw($EMPTY_STRING); 

Un exemple d'utilisation:

#!perl 
use Example::Constants; 
print $EMPTY_STRING . 'foo' . $EMPTY_STRING; 

En utilisant le code ci-dessus produit une erreur:

Global symbol "$EMPTY_STRING" requires explicit package name 

Si je change la déclaration Readonly à:

Readonly our $EMPTY_STRING => q{}; # 'our' instead of 'my' 

L'erreur devient:

Attempt to reassign a readonly scalar 

Est-ce que ce n'est tout simplement pas possible avec mod_perl?

Répondre

2

Vous avez eu 4 problèmes:

  1. Vous ne avez pas compris les strict et warnings pragma
  2. Il est préférable d'inclure l'exportateur par l'base pragma (puisqu'il définit @ISA pour vous)
  3. seulement les variables du package (c.-à-d. our variables) peuvent être exportées
  4. Les modules doivent se terminer par une valeur réelle

Voici le module corrigé.

package Example::Constants; 

use strict; 
use warnings; 
use base 'Exporter'; 
use Readonly; 

Readonly our $EMPTY_STRING => q{}; 
our @EXPORT = qw($EMPTY_STRING); 

1; 

Hmm, j'ai raté le peu de tenter d'attribuer à une lecture seule, il semble que le module est chargé de se plus d'une fois. Je crois que mod_perl a un mechanism pour charger des modules séparés des scripts eux-mêmes. Ce chargement se produit une seule fois, vous devriez donc l'utiliser.

+0

que je fais déjà 1, 3 et 4, je les ai juste laissés hors de l'exemple pour la brièveté. Aussi, utilisez Exportateur qw (import) est la méthode préférée, ne pas utiliser base qw (Exporter). L'ajout du module à PerlRequire génère toujours l'erreur, une pour chaque processus http démarré. – cowgod

+0

Qu'en est-il de PerlModule? –

+0

Aussi, avez-vous supprimé "use Example :: Constants;" de votre script? –

0

Je n'ai pas d'instance mod_perl pratique à tester, donc je ne peux pas tester ces suggestions. J'espère qu'ils vont voir.

Essayez d'utiliser Scalar::Util::readonly pour vérifier si la variable a déjà été marquée en lecture seule.

#!perl 
package Example::Constants; 

use Exporter qw(import); 
use Readonly; 
use Scalar::Util qw(readonly); 

our $EMPTY_STRING; 
our @EXPORT = qw($EMPTY_STRING); 

if (!readonly($EMPTY_STRING)) { 
    Readonly $EMPTY_STRING => q{}; 
} 

Vous pouvez également essayer use vars:

#!perl 
package Example::Constants; 

use Exporter qw(import); 
use Readonly; 
use vars qw($EMPTY_STRING); 

Readonly $EMPTY_STRING => q{}; 
our @EXPORT = qw($EMPTY_STRING); 

Vous pouvez également utiliser une constante de typeglob:

#!perl 
package Example::Constants; 

use Exporter qw(import); 
use Readonly; 

our $EMPTY_STRING; 
*EMPTY_STRING = \q{}; 
our @EXPORT = qw($EMPTY_STRING); 

En utilisant une constante de typeglob semble parfaite, puisque la grande limitation de la technique (il nécessite un paquet global) n'est pas un problème ici.

3

Je suis l'auteur du module Readonly. La prochaine version de Readonly fournira un support pour mod_perl, en particulier à cause de ce problème.

Je sais que cela ne résout pas votre problème maintenant, mais ... eh bien, je travaille là-dessus :-)

- Eric

+0

wow, vous vous êtes inscrit juste pour le dire? Je suis impressionné. –

+0

Génial! Merci beaucoup. Si c'est important, j'utilise aussi le module Readonly :: XS. – cowgod

+3

Eh bien Eric, ça fait un an. Des progrès avec ça? :) – cowgod

Questions connexes