2010-02-25 16 views
6

Warum diesen Druck 42:Warum kann ich den Wert einer Perl-Variablen nicht für den Zugriff auf den Namen einer lexikalischen Variablen verwenden?

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

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

aber nicht:

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

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

Ich vermute, dass $ Antwort einen globalen Bereich definiert, und meine $ Antwort definiert einen lokalen Bereich. –

+0

@Paul, aber print $ answer würde funktionieren ... Wie erstellt $ {$ variable} einen globalen Bereich? – ennuikiller

+2

Verwenden Sie immer 'use strict; Verwenden Sie Warnungen; 'und Sie werden dieses Problem nie sehen. Noch besser: Verwenden Sie niemals den Wert einer Variablen, um eine andere Variable zu erhalten. Hashes sind viel besser. – Ether

Antwort

15

Nur Paketvariablen (die in Ihrem ersten Beispiel deklarierte Art) können über symbolische Referenzen abgezielt werden. Lexikalische (my) Variablen, kann nicht sein, weshalb Ihr zweites Beispiel fehlschlägt.

Sehen Sie den ausgezeichneten Artikel Coping with Scoping für, wie die zwei unterschiedlichen variablen Systeme in Perl arbeiten. Und siehe auch die hervorragende Why it's stupid to use a variable variable name dafür, warum das blöd ist. :)

6

Perl hat zwei völlig getrennte, aber weitgehend kompatibel variable Systeme, Paketgrößen, wie in Ihrem ersten Beispiel und lexikalische Variablen, wie in der zweiten. Es gibt ein paar Dinge, die jeder tun kann, aber die andere kippen:

Paketgrößen sind die einzige, das sein kann:

  1. lokalisierte (mit local)
  2. als Ziel für eine symbolische Referenz verwendet (der Grund, das zweite Beispiel nicht funktioniert das OP)
  3. als Barewords verwendet (Unter Definitionen, Datei-Handles)
  4. mit Typeglobs verwendet (weil das ist, was das Symbol wirklich unter der Haube ist)

Lexikalische Variablen sind die einzigen, die geschlossen werden können (in einem lexikalischen Abschluss).

Die Verwendung von strict würde helfen, indem Sie gezwungen werden, Paketvariablen mit our zu deklarieren, was den Unterschied deutlicher macht.

Es gibt mehrere Zeiten, in denen symbolischen Referenzen nützlich sind in Perl, die meisten drehen sich um die Symboltabelle Manipulation (wie Ihre eigenen import in einem Modul zu schreiben anstatt Exporter, Affe-Patchen Module zur Laufzeit, verschiedene andere Meta-Programmieraufgaben). All dies sind fortgeschrittene Themen.

Für andere Aufgaben gibt es normalerweise einen besseren Weg, wie mit einem Hash zu tun. Die allgemeine Faustregel lautet, immer unter use warnings; use strict; zu laufen, es sei denn, Sie wissen, dass es keinen anderen Weg gibt, als einen Teil des Pragmas zu deaktivieren (z. B. no strict 'refs'; in einem möglichst kleinen Umfang zu verwenden).

4

Das Problem besteht darin, dass Sie eine symbolische Referenz nicht verwenden können, um auf eine lexikalische Variable zu verweisen. In beiden Beispielen sucht ${$variable} nach $main::answer. In der ersten, $answer ist ein Paket global und kurz für $main::answer, so die Referenz findet es. In der zweiten, $answer ist eine lexikalische Variable und lebt nicht in einem Paket, so dass die Referenz es nicht finden kann.

Weitere Details in perlref unter der Überschrift Symbolic references.

5

Symbolische Referenzen funktionieren nur mit Paketvariablen. Die Symboltabelle verfolgt keine lexikalischen Variablen (was der ganze Punkt davon ist, dass sie lexikalisch sind).