5 votes

Quand doit-on utiliser une variable de package par rapport à une variable lexicale (et quelle est la différence) ?

Je suis en train d'examiner un ancien code Perl sur Perl Monks pour comprendre la programmation avec Win32::OLE et MS Word. Parsemés dans le code se trouvent des variables avec des noms comme $MS::Word et autres, sans 'my' inclus dans leur déclaration. Après avoir lu un peu sur Google, je comprends que celles-ci sont appelées 'variables de package' par rapport aux variables lexicales déclarées avec my.

Ma première question est 'À quoi servent les variables de package?'. Je (pense) que je comprends ce que sont les variables lexicales, mais je ne comprends pas l'utilité des variables de package ni en quoi leur utilisation diffère des lexicales, donc ma deuxième question serait, 'Quelle est la différence entre variables lexicales et variables de package?'

9voto

Sinan Ünür Points 76179

Vous devriez lire Coping with Scoping par MJD.

perldoc perlmod serait également une lecture utile.

Le code est d'une laideur incroyable. Il piétine toutes sortes d'espaces de noms sans se soucier de rien juste parce que l'auteur semble penser que $author::email est cool.

Une meilleure façon aurait été d'utiliser une hash :

my %author = (
   email => 'auteur@example.com',
   ...
);

Piétiner toute la table des symboles n'est pas nécessaire.

J'ai quelques exemples de Win32::OLE : http://www.unur.com/comp/ qui ne sont pas des chefs-d'œuvre mais je crois qu'ils améliorent ce style. Voir aussi Pourquoi le nombre de pages dans un document Word diffère-t-il en Perl et en Word VBA ?

Je vais me plaindre un peu :

@pgm::runtime_args = @ARGV ;

Ainsi, nous abandonnons le tableau standard @ARGV pour piétiner sur l'espace de noms pgm. De plus, tout programmeur Perl sait ce qu'est @ARGV. En tout cas, @pgm::runtime_args n'est plus utilisé dans le script.

$pgm::maxargs = $#pgm::runtime_args + 1 ;

Bien sûr, @pgm::runtime_args en contexte scalaire nous donnait le nombre d'éléments dans ce tableau. Je ne sais pas pourquoi $pgm::maxargs pourrait être nécessaire, mais si c'était le cas, alors cette ligne aurait dû être :

$pgm::maxargs = @pgm::runtime_args;

Je ne vais pas citer plus de cette chose. Je suppose que c'est ce qui se passe lorsque les programmeurs Cobol essaient d'écrire en Perl.

$program::copyright = "Copyright (c) 02002 - Kenneth Tomiak : Tous droits réservés.";

Je suis content qu'il ait alloué cinq chiffres pour l'année. On ne sait jamais !

PS : Je crois que mes extraits constituent une utilisation équitable.

8voto

Greg Bacon Points 50449

Une variable de package vit dans une table de symboles. Ainsi, étant donné son nom, il est possible de la lire ou de la modifier depuis n'importe quel autre package ou portée. La portée d'une variable lexicale est déterminée par le texte du programme. La section ["Variables privées via my()"](http://perldoc.perl.org/perlsub.html#Private-Variables-via-my()) dans la page du manuel perlsub donne plus de détails sur la définition des lexiques.

Disons que nous avons le MyModule.pm suivant :

package MyModule;

# ce sont des variables de package
our $Name;
$MyModule::calls = "Je ne pense pas que cela signifie ce que vous pensez que cela signifie.";

# voici une variable lexicale
my $calls = 0;

sous-programme dire_bonjour {
  ++$calls;

  print "Salut, $Name!\n";
}

sous-programme num_salutations {
  $calls;
}

1;

Remarquez qu'il contient une variable de package $calls et une variable lexicale $calls. Tout le monde peut accéder à la première, mais le module contrôle l'accès à la seconde :

#! /usr/bin/perl

use warnings;
use strict;

use MyModule;

foreach my $name (qw/ Larry Curly Moe Shemp /) {
  $MyModule::Name = $name;
  MyModule::dire_bonjour;
}

print MyModule::num_salutations, "\n";

print "calls = $MyModule::calls\n";

La sortie du programme est

Bonjour, Larry!
Bonjour, Curly!
Bonjour, Moe!
Bonjour, Shemp!
4
calls = Je ne pense pas que cela signifie ce que vous pensez que cela signifie.

Comme vous pouvez le voir, les variables de package sont des globales, donc toutes les habituelles erreurs à éviter et conseils s'appliquent. À moins d'un accès explicite fourni, il est impossible pour un code extérieur au package MyModule d'accéder à sa variable lexicale $calls.

La règle de base est que vous voulez presque toujours utiliser des lexiques. Perl Best Practices de Damian Conway est clair : "Ne jamais rendre les variables partie de l'interface d'un module" (souligné dans l'original).

5voto

Michael Carman Points 21983

Les variables de package sont des variables globales; elles sont visibles partout dans le programme entier (même dans d'autres modules). Elles sont utiles lorsque vous souhaitez ou avez besoin de ce niveau de visibilité et/ou d'influence externe. Par exemple, le module Text::Wrap les utilise pour permettre un point de configuration unique pour le nombre de colonnes où envelopper le texte. De plus, les variables de package vous permettent d'utiliser quelque chose appelé "portée dynamique" -- mais c'est un concept quelque peu avancé et légèrement ésotérique.

Pour votre deuxième question, consultez Quelle est la différence entre my et our en Perl?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X