http://www.bribes.org/perl/docfr/perlref.html#LE61666C2
Références symboliques
Nous avons déjà expliqué que, quand c'est nécessaire, les références devenaient existantes si elles sont définies, mais nous n'avons pas dit ce qui arrivait lorsqu'une valeur utilisée comme référence est déjà définie mais n'est pas une référence dure. Si vous l'utilisez comme référence dans ce cas-là, elle sera traitée comme une référence symbolique. C'est-à-dire que la valeur du scalaire est considérée comme le nom d'une variable, plutôt que comme un lien direct vers une (éventuelle) valeur anonyme.
En général, les gens s'attendent à ce que ça fonctionne de cette façon. C'est donc comme ça que ça marche.Mes questions et mes suppositions sont mises en vert
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 1 $name = "foo"; 2 $$name = 1; # Affecte $foo 3 ${$name} = 2; # Affecte $foo 4 ${$name x 2} = 3; # Affecte $foofoo 5 $name->[0] = 4; # Affecte $foo[0] 6 @$name = (); # Efface @foo 7 &$name(); # Appelle &foo() (comme en Perl 4) 8 $pack = "THAT"; 9 ${"${pack}::$name"} = 5; # Affecte $THAT::foo sans évaluation
Donc, si j'ai bien compris ...
une valeur utilisée comme référence ($$name ligne 2) est déjà définie mais n'est pas une référence dure ($name ligne 1 = scalaire).
Si vous l'utilisez comme référence dans ce cas-là, elle sera traitée comme une référence symbolique. C'est-à-dire que la valeur du scalaire ("foo" ligne 1) est considérée comme le nom d'une variable, plutôt que comme un lien direct vers une (éventuelle) valeur anonyme (table des symboles *foo = foo).
Danger :
Seules les variables (globales, même si elles sont localisées) de paquetage sont visibles par des références symboliques. Les variables lexicales (déclarées avec my()) ne font pas partie de la table des symboles, et sont donc invisibles à ce mécanisme. Par exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 local $value = 10; $ref = "value"; { my $value = 20; print $$ref; }Problème : my $value = 20; étant lexicale, elle ne fait pas partie de la table des symboles et est donc invisible par la référence symbolique $ref.Ceci imprimera 10 et non pas 20. Souvenez-vous que local() affecte les variables de paquetage, qui sont toutes «globales» au paquetage.
... je ne comprends pas la ligne $ref = "value"; ... comment Perl est-il sensé savoir que $ref est une référence? Pourquoi ne pas mettre $ref = \$value? Est-ce grâce à 'local $value' qui est placée dans la table des symboles et qui permet par la suite à $ref de savoir via $ref = "value" qu'il est une référence? Car *value = value est dans cette table.
... je suis perdue ...
Dans la FAQ
Comment générer automatiquement une fonction ?
auteur : Woufeil
En bouclant autour d'une fermeture, on peut créer des fonctions ayant un code semblable mais des noms différents. Le problème est qu'une fermeture n'a pas de nom, mais on peut le contourner : il est en effet possible de lier une référence de code à un nom déjà existant en passant par les typeglobs.
Par exemple, on veut deux fonctions fic1 et fic2 qui écrivent leurs paramètres dans des fichiers qui ont respectivement pour handle FIC1 et FIC2. Les 2 fonctions sont très proches, elles ne diffèrent que par le fichier dans lequel écrire. Voilà comment générer ces deux fonctions en bouclant autour d'une fermeture :
fic1("Salut !"); #écrit salut dans FIC1
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 foreach my $champ (qw(fic1 fic2)) { my $handle = uc $champ; #met $champ en majuscule no strict 'refs'; #Autorise les références symboliques *$champ = sub {print $handle "@_";}; #affecte la fermeture en question au typeglob }Donc, ici on parle bien de références symboliques?Envoyé par Woufeil
Donc pour conclure : les références symboliques sont utiles comme dans ce cas-ci mais peuvent être dangereuses car il faut garder à l'esprit que les variables lexicales ne sont pas visibles par ces références.
Une seule question est vraiment importante, qu'est-il important de retenir au sujet des références symboliques?
Merci pour votre aide,
Partager