Frage

Warum funktioniert die folgende Schnipsel Arbeit überhaupt? Und was das Böse könnte möglich sein, dies mit? Aber im Ernst, gibt es keinen Grund, wird der Code in ${} überhaupt ausgewertet und dann als skalare Referenz verwendet?

use strict;
no strict 'refs';

our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";
War es hilfreich?

Lösung

Es ist in Ordnung, , wenn Sie symbolische Referenzen verwenden . Nehmen wir den folgenden Code:

my %messages = (hello => "Hello world!", bye => "Bye-bye, world!");
sub get_message_ref { return \$messages{$_[0]} }; # returns scalarref
print "${ get_message_ref('bye') }\n";

Agree, seine Nützlichkeit nicht offensichtlich mit scalarrefs ist, aber es ist sehr nützlich, mit arrayrefs.

print "keys: @{[keys %messages]}\n";

Andere Tipps

Wir erklären dies in der Tiefe in Intermediate Perl .

Die allgemeine Syntax für variable Lookups ist:

 SIGIL  BLOCK  INDEXY-THING

Für einen einfachen skalar, das aussieht wie:

 print $   { foo };

Sie haben dies wahrscheinlich zu sehen, wenn Sie benötigen einen Variablennamen von den Dingen zu trennen, die es umgibt:

 print "abc${foo}def\n";

Wenn Sie nur eine Perl-Kennung in dem Block haben und kein umgebendes Chaos, können Sie die Klammern weglassen, was der gemeinsame Fall ist:

 print $foo;

Dies ist jedoch das Gleiche für dereferencing eine Referenz:

 SIGIL  BLOCK-RETURNING-REFERENCE  INDEXY-THINGS

Wenn das, was Sie in dem Block erhalten, ist eine Referenz, versucht Perl es dereferenzieren wie Sie es auch gefragt:

 my $ref = \ '12345';
 print $     { $ref };

Das ist ein echter Block aber, und nicht nur Zucker. Sie können so viele Aussagen haben, wie Sie dort mögen:

 print $     { my $ref = \ '1234'; $ref };

Jetzt sind Sie nicht nur eine Perl Kennung angeben, so Perl geht nicht davon aus, dass Sie ihm eine Kennung geben und es führt einen Code und verwendet das Ergebnis als Referenz. Betrachten Sie den Unterschied zwischen diesen fast identisch say Aussagen:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }

say ${foo};
say ${foo;};

In diesem zweiten say sieht Perl das Semikolon, erkennt es nicht eine Kennung, interpretiert den Code innerhalb der geschweiften Klammern als Text, und gibt das Ergebnis. Da das Ergebnis eine Referenz ist, verwendet er die ${...} es dereferenzieren. Es spielt keine Rolle, wo Sie dies tun, so dass Sie es in einem doppelten Anführungszeichen Zeichenfolge nicht besonders.

Beachten Sie auch die our dort. Das ist jetzt wichtig, dass Sie etwas ein wenig komplizierter prüfen gehen:

    use 5.010;
our $foo = "I'm the scalar";

sub foo { \ "I'm the sub" }
sub baz { 'foo' }

say ${foo};
say ${foo;};
say ${baz;};

Perl intreprets die letzte say als Code und sieht das Ergebnis nicht eine Referenz; es ist die einfache Zeichenfolge foo. Perl sieht, dass es keine Referenz ist, aber es ist jetzt in einem dereferencing Kontext, so dass es eine symbolische Referenz hat (wie Greg Speck beschreibt ). Da symbolische Referenzen mit Variablen in der Symboltabelle arbeiten, dass $foo hatte ein Paket variabel sein.

Da ist es leicht zu verwirren diese auf, hat strict eine praktische Prüfung für sie. Wenn Sie jedoch deaktivieren, seien Sie nicht überrascht, wenn es Sie beißt. :)

Von der "Verwenden von Referenzen" -Abschnitt der perlref Dokumentation :

  

überall würden Sie eine Kennung gesetzt (oder eine Kette von Kennungen) als Teil einer Variablen oder Unterprogrammnamen, können Sie die Kennung mit einem Block ersetzen einen Verweis des richtigen Typs zurück. Mit anderen Worten könnten die vorherigen Beispiele wie folgt geschrieben werden:

$bar = ${$scalarref};
push(@{$arrayref}, $filename);
${$arrayref}[0] = "January";
${$hashref}{"KEY"} = "VALUE";
&{$coderef}(1,2,3);
$globref->print("output\n");  # iff IO::Handle is loaded
     

Zugegeben, es ist ein wenig albern die curlies in diesem Fall zu verwenden, aber die BLOCK jeden beliebigen Ausdruck enthalten kann, insbesondere indizierte Ausdrücke:

&{ $dispatch{$index} }(1,2,3);    # call correct routine
     

Da der Lage zu sein, die curlies für den einfachen Fall von $$x zu verzichten, die Menschen oft den Fehler, die dereferencing Symbole als richtigen Betreiber sehen, und wundern sich über ihre Priorität. Wenn sie waren, obwohl, können Sie Klammern statt Klammern verwenden. Das ist nicht der Fall. Betrachten Sie den Unterschied unten; 0 Fall ist eine kurze Hand-Version von Fall 1 nicht Fall 2:

$$hashref{"KEY"}   = "VALUE";     # CASE 0
${$hashref}{"KEY"} = "VALUE";     # CASE 1
${$hashref{"KEY"}} = "VALUE";     # CASE 2
${$hashref->{"KEY"}} = "VALUE";   # CASE 3
     

Fall 2 ist auch in trügerisch, dass Sie eine Variable namens %hashref zugreifst, nicht dereferencing durch $hashref zu dem Hash es vermutlich ist verweist. Das wäre Fall 3.

Später in "Symbolische Referenzen":

  

Wir haben gesagt, dass Verweise in die Existenz als notwendig Frühling, wenn sie nicht definiert sind, haben wir aber nicht sagen, was passiert, wenn ein Wert als Referenz verwendet, geschieht bereits definiert ist, ist aber nicht eine harte Referenz. Wenn Sie es als Referenz verwenden, wird es als eine symbolische Referenz behandelt werden. Das heißt, der Wert des skalars genommen der Namen einer Variablen, anstatt eine direkte Verbindung zu einem (möglicherweise) anonymen Wert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top