2010-02-25 3 views
6

Pourquoi cette impression 42:Pourquoi ne puis-je pas utiliser la valeur d'une variable Perl pour accéder à un nom de variable lexical?

$answer = 42; 
$variable = "answer"; 

print ${$variable} . "\n"; 

mais cela ne:

my $answer = 42; 
my $variable = "answer"; 

print ${$variable} . "\n"; 
+0

Je suppose que $ answer définit une portée globale et my $ définit une portée locale. –

+0

@Paul, mais print $ answer fonctionnerait bien ... comment $ {$ variable} crée-t-il une portée globale? – ennuikiller

+2

Toujours utiliser 'use strict; utiliser des avertissements; 'et vous ne verrez jamais ce problème. Mieux encore, n'utilisez jamais la valeur d'une variable pour obtenir une autre variable. Les hachages sont bien meilleurs. – Ether

Répondre

15

Seules les variables de package (le type déclaré dans votre premier exemple) peuvent être ciblées via des références symboliques. Les variables lexicales (my) ne peuvent pas l'être, ce qui explique pourquoi votre second exemple échoue.

Voir l'excellent article Coping with Scoping pour savoir comment fonctionnent les deux systèmes de variables séparés en Perl. Et voir l'excellent Why it's stupid to use a variable variable name pourquoi c'est stupide. :)

6

Perl dispose de deux systèmes variables entièrement distincts mais largement compatibles, les variables de package, comme dans votre premier exemple, et lexical variables, comme dans la seconde. Il y a quelques petites choses que chacun peut faire, mais l'autre dévers:

Les variables de package sont les seuls qui peuvent être:

  1. localisée (avec local)
  2. utilisé comme cible pour une référence symbolique (la raison pour laquelle le travail deuxième exemple ne marche pas de OP)
  3. utilisé comme barewords (sous les définitions, les descripteurs de fichiers)
  4. utilisé avec typeglobs (parce que ce symbole est vraiment sous le capot)

Les variables lexicales sont les seules qui peuvent être fermées (utilisées dans une fermeture lexicale). L'utilisation de strict vous aidera à déclarer les variables de package avec our, ce qui rendra la différence plus claire.

Il y a plusieurs moments où les références symboliques sont utiles en Perl, plus le centre autour de la manipulation de la table des symboles (comme écrire votre propre import dans un module plutôt que d'utiliser Exporter, modules ragréage singe lors de l'exécution, diverses autres tâches méta-programmation). Tous ces sujets sont avancés.

Pour d'autres tâches, il existe généralement une meilleure façon de le faire, par exemple avec un hachage. La règle générale est de toujours exécuter sous use warnings; use strict; sauf si vous savez qu'il n'y a pas d'autre moyen que de désactiver une partie du pragma (par exemple en utilisant no strict 'refs'; dans une portée aussi réduite que possible).

4

Le problème est que vous ne pouvez pas utiliser une référence symbolique pour faire référence à une variable lexicale. Dans les deux exemples, ${$variable} recherche $main::answer. Dans le premier, $answer est un paquet global et court pour $main::answer, donc la référence le trouve. Dans la seconde, $answer est une variable lexicale et ne réside dans aucun package, donc la référence ne peut pas le trouver.

Plus de détails dans perlref sous la rubrique Symbolic references.

5

Les références symboliques ne fonctionnent qu'avec les variables de package. La table des symboles ne suit pas les variables lexicales (ce qui est le point entier de celles-ci étant lexical :).

Questions connexes