Dies ist der Befehl perlref, der beim kostenlosen Hosting-Anbieter OnWorks mit einer unserer zahlreichen kostenlosen Online-Workstations wie Ubuntu Online, Fedora Online, dem Windows-Online-Emulator oder dem MAC OS-Online-Emulator ausgeführt werden kann
PROGRAMM:
NAME/FUNKTION
perlref - Perl-Referenzen und verschachtelte Datenstrukturen
HINWEIS
Dies ist eine vollständige Dokumentation aller Aspekte von Referenzen. Für ein kürzeres Tutorial
Eine Einführung in die wesentlichen Funktionen finden Sie unter perlreftut.
BESCHREIBUNG
Vor Release 5 von Perl war es schwierig, komplexe Datenstrukturen darzustellen, weil
Alle Verweise mussten symbolisch sein – und selbst dann war es schwierig, auf eine Variable zu verweisen
anstelle eines Symboltabelleneintrags. Perl erleichtert jetzt nicht nur die symbolische Verwendung
Verweise auf Variablen, ermöglicht aber auch „harte“ Verweise auf beliebige Daten oder Daten
Code. Jeder Skalar kann eine harte Referenz enthalten. Da Arrays und Hashes Skalare enthalten,
Sie können jetzt ganz einfach Arrays aus Arrays, Arrays aus Hashes, Hashes aus Arrays, Arrays aus erstellen
Hashes von Funktionen usw.
Harte Referenzen sind intelligent – sie verfolgen automatisch die Anzahl der Referenzen für Sie
Freigeben des referenzierten Dings, wenn sein Referenzzähler auf Null geht. (Referenz zählt
für Werte in selbstreferenziellen oder zyklischen Datenstrukturen dürfen ohne a nicht auf Null gehen
kleine Hilfe; Eine ausführliche Erklärung finden Sie unter „Zirkelverweise“.) Wenn das passiert
Um ein Objekt zu sein, wird das Objekt zerstört. Weitere Informationen zu Objekten finden Sie unter perlobj. (In einem
Sinngemäß ist alles in Perl ein Objekt, aber wir behalten uns das Wort normalerweise für Verweise auf vor
Objekte, die offiziell „gesegnet“ wurden, in ein Klassenpaket.)
Symbolische Referenzen sind Namen von Variablen oder anderen Objekten, ebenso wie ein symbolischer Link in einem
Das Unix-Dateisystem enthält lediglich den Namen einer Datei. Die *glob-Notation ist so etwas wie eine
symbolische Referenz. (Symbolische Referenzen werden manchmal als „weiche Referenzen“ bezeichnet, aber
Bitte nennen Sie sie nicht so; Referenzen sind ohne nutzlose Synonyme verwirrend genug.)
Im Gegensatz dazu ähneln harte Referenzen eher harten Links in einem Unix-Dateisystem: Sie werden verwendet
auf ein zugrunde liegendes Objekt zuzugreifen, ohne Rücksicht darauf zu nehmen, wie sein (anderer) Name lautet. Wenn das
Das Wort „Referenz“ wird wie im folgenden Absatz ohne Adjektiv verwendet
Normalerweise handelt es sich um eine harte Referenz.
Referenzen sind in Perl einfach zu verwenden. Es gibt nur einen übergeordneten Grundsatz: Im Allgemeinen gilt:
Perl führt keine implizite Referenzierung oder Dereferenzierung durch. Wenn ein Skalar eine Referenz enthält,
es verhält sich immer wie ein einfacher Skalar. Es beginnt nicht auf magische Weise, ein Array oder Hash zu sein
oder Unterprogramm; Sie müssen es explizit dazu auffordern, indem Sie es dereferenzieren.
Beachten Sie jedoch, dass Perl Version 5.14 eine Ausnahme von der Regel einführt, z
syntaktische Bequemlichkeit. Experimentelles Array- und Hash-Container-Funktionsverhalten ermöglicht
Array- und Hash-Referenzen werden von Perl so behandelt, als ob sie explizit behandelt worden wären
syntaktisch dereferenziert. Siehe „Syntaktische Verbesserungen“ in perl5140delta und perlfunc
.
Making Referenzen
Referenzen können auf verschiedene Arten erstellt werden.
1. Durch die Verwendung des Backslash-Operators für eine Variable, ein Unterprogramm oder einen Wert. (Das funktioniert sehr gut
wie der &-Operator (Adresse von) in C.) Dadurch wird normalerweise erstellt ein anderer Verweis auf a
Variable, da in der Symboltabelle bereits ein Verweis auf die Variable vorhanden ist.
Aber der Symboltabellenverweis verschwindet möglicherweise, und Sie haben immer noch den Verweis darauf
Der Backslash kam zurück. Hier sind einige Beispiele:
$scalarref = \$foo;
$arrayref = \@ARGV;
$hashref = \%ENV;
$coderef = \&handler;
$globref = \*foo;
Es ist nicht möglich, einen echten Verweis auf ein IO-Handle (Dateihandle oder Dirhandle) zu erstellen.
mit dem Backslash-Operator. Das Beste, was Sie bekommen können, ist ein Verweis auf einen Typeglob.
Das ist eigentlich ein vollständiger Symboltabelleneintrag. Aber siehe die Erklärung des
*foo{THING}-Syntax unten. Sie können jedoch weiterhin Typ-Globs und Globrefs als verwenden
obwohl es sich um IO-Handles handelte.
2. Mit eckigen Klammern kann ein Verweis auf ein anonymes Array erstellt werden:
$arrayref = [1, 2, ['a', 'b', 'c']];
Hier haben wir einen Verweis auf ein anonymes Array aus drei Elementen erstellt, deren final
element ist selbst ein Verweis auf ein anderes anonymes Array aus drei Elementen. (Der
Für den Zugriff darauf kann die später beschriebene mehrdimensionale Syntax verwendet werden. Zum Beispiel,
danach hätte „$arrayref->[2][1]“ den Wert „b“.)
Einen Verweis auf eine Aufzählungsliste zu nehmen ist nicht dasselbe wie die Verwendung von Quadraten
Klammern – stattdessen ist es dasselbe wie das Erstellen einer Referenzliste!
@list = (\$a, \@b, \%c);
@list = \($a, @b, %c); # gleiche Sache!
Als Sonderfall gibt „\(@foo)“ eine Liste mit Verweisen auf den Inhalt von @foo zurück, nicht
ein Verweis auf @foo selbst. Dasselbe gilt für %foo, mit der Ausnahme, dass die Schlüsselverweise auf sind
Kopien (da die Schlüssel nur Strings und keine vollwertigen Skalare sind).
3. Mit geschweiften Klammern kann ein Verweis auf einen anonymen Hash erstellt werden:
$hashref = {
'Adam' => 'Eva',
'Clyde' => 'Bonnie',
};
Anonyme Hash- und Array-Komponisten wie diese können frei gemischt werden, um sie zu erstellen
kompliziert eine Struktur, wie Sie wollen. Die unten beschriebene mehrdimensionale Syntax
funktioniert auch für diese. Die oben genannten Werte sind Literale, aber Variablen und Ausdrücke
würde genauso gut funktionieren, weil Zuweisungsoperatoren in Perl (sogar innerhalb lokal() or
mein()) sind ausführbare Anweisungen, keine Deklarationen zur Kompilierungszeit.
Da geschweifte Klammern (geschweifte Klammern) für verschiedene andere Dinge verwendet werden, einschließlich BLOCKs,
Gelegentlich müssen Sie geschweifte Klammern am Anfang einer Anweisung von disambiguieren
Setzen Sie ein „+“ oder ein „Return“ voran, damit Perl erkennt, dass dies bei der öffnenden Klammer nicht der Fall ist
einen BLOCK starten. Der wirtschaftliche und mnemonische Wert der Verwendung von Curlies wird als wertvoll erachtet
dieser gelegentliche zusätzliche Aufwand.
Wenn Sie beispielsweise möchten, dass eine Funktion einen neuen Hash erstellt und eine Referenz darauf zurückgibt,
Sie haben diese Möglichkeiten:
sub hashem { { @_ } } # stillschweigend falsch
sub hashem { +{ @_ } } # ok
sub hashem { return { @_ } } # ok
Wenn Sie hingegen die andere Bedeutung wünschen, können Sie Folgendes tun:
sub showem { { @_ } } # mehrdeutig (derzeit ok,
# kann sich aber ändern)
sub showem { {; @_ } } # OK
sub showem { { return @_ } } # ok
Das führende „+{“ und „{;“ dienen immer dazu, den Ausdruck eindeutig zu machen
die HASH-Referenz oder der BLOCK.
4. Ein Verweis auf ein anonymes Unterprogramm kann durch die Verwendung von „sub“ ohne a erstellt werden
Untername:
$coderef = sub { print "Boink!\n" };
Beachten Sie das Semikolon. Abgesehen davon, dass der darin enthaltene Code nicht sofort ausgeführt wird, ist ein „sub
{}“ ist weniger eine Deklaration als vielmehr ein Operator, wie „do{}“ oder „eval{}“.
(Allerdings spielt es keine Rolle, wie oft Sie diese bestimmte Zeile ausführen (es sei denn, Sie befinden sich in
ein "eval("...")"), $coderef wird immer noch einen Verweis auf haben gleich anonym
Subroutine.)
Anonyme Unterprogramme fungieren als Abschlüsse in Bezug auf mein() Variablen, das heißt,
Variablen, die im aktuellen Bereich lexikalisch sichtbar sind. Schließung ist eine Vorstellung aus dem
Lisp-Welt, die besagt, ob Sie eine anonyme Funktion in einem bestimmten Lexikon definieren
Kontext, gibt es vor, in diesem Kontext ausgeführt zu werden, selbst wenn es außerhalb des Kontexts aufgerufen wird.
Aus menschlicher Sicht ist es eine lustige Art, beim Definieren Argumente an eine Unterroutine zu übergeben
es sowie wenn Sie es aufrufen. Es ist nützlich, um kleine Codeteile für die Ausführung einzurichten
später, etwa Rückrufe. Sie können damit sogar objektorientierte Dinge tun, allerdings mit Perl
bietet dafür bereits einen anderen Mechanismus – siehe perlobj.
Sie könnten sich den Abschluss auch als eine Möglichkeit vorstellen, eine Subroutinenvorlage zu schreiben, ohne sie zu verwenden
eval (). Hier ist ein kleines Beispiel, wie Schließungen funktionieren:
sub newprint {
mein $x = Verschiebung;
return sub { my $y = shift; print "$x, $y!\n"; };
}
$h = newprint("Howdy");
$g = newprint("Grüße");
# Zeit vergeht...
&$h("Welt");
&$g("Erdlinge");
Dies wird gedruckt
Hallo, Welt!
Seid gegrüßt, Erdlinge!
Beachten Sie insbesondere, dass sich $x weiterhin auf den übergebenen Wert bezieht newprint()
trotz „my $x“ hat zum Zeitpunkt der Ausführung der anonymen Unterroutine den Gültigkeitsbereich verlassen.
Darum geht es bei einer Schließung.
Dies gilt übrigens nur für lexikalische Variablen. Dynamische Variablen weiterhin
arbeiten, wie sie immer funktioniert haben. Das Schließen ist nichts, was die meisten Perl-Programmierer tun
Sie müssen sich zunächst selbst die Mühe machen.
5. Referenzen werden häufig von speziellen Unterroutinen zurückgegeben, die als Konstruktoren bezeichnet werden. Perl
Objekte sind lediglich Verweise auf einen speziellen Objekttyp, der zufällig weiß, welcher
Paket, mit dem es verknüpft ist. Konstruktoren sind nur spezielle Unterprogramme, die wissen, wie
diesen Verein zu gründen. Sie tun dies, indem sie mit einer gewöhnlichen Referenz beginnen, und zwar mit dieser
bleibt eine gewöhnliche Referenz, auch wenn es gleichzeitig ein Objekt ist. Konstrukteure sind
oft als „new()“ bezeichnet. Du können. Nennen Sie sie indirekt:
$objref = new Doggie( Tail => 'kurz', Ohren => 'lang' );
In bestimmten Fällen kann dies jedoch zu mehrdeutiger Syntax führen, daher ist die Verwendung oft besser
Der Ansatz des direkten Methodenaufrufs:
$objref = Doggie->new(Tail => 'kurz', Ohren => 'lang');
verwenden Sie Term::Cap;
$terminal = Term::Cap->Tgetent( { OSPEED => 9600 });
benutze Tk;
$main = MainWindow->new();
$menubar = $main->Frame(-relief => "erhöht",
-borderwidth => 2)
6. Referenzen des entsprechenden Typs können entstehen, wenn Sie sie dereferenzieren
in einem Kontext, der ihre Existenz voraussetzt. Weil wir nicht über Dereferenzierung gesprochen haben
Wir können Ihnen jedoch noch keine Beispiele zeigen.
7. Eine Referenz kann mithilfe einer speziellen Syntax erstellt werden, die liebevoll als bezeichnet wird
*foo{THING}-Syntax. *foo{THING} gibt einen Verweis auf den THING-Slot in *foo zurück (welcher
ist der Symboltabelleneintrag, der alles enthält, was als foo bekannt ist.
$scalarref = *foo{SCALAR};
$arrayref = *ARGV{ARRAY};
$hashref = *ENV{HASH};
$coderef = *handler{CODE};
$ioref = *STDIN{IO};
$globref = *foo{GLOB};
$formatref = *foo{FORMAT};
$globname = *foo{NAME}; # "foo"
$pkgname = *foo{PACKAGE}; # "hauptsächlich"
Die meisten davon sind selbsterklärend, aber *foo{IO} verdient besondere Aufmerksamkeit. Es
gibt das IO-Handle zurück, das für Dateihandles („open“ in perlfunc) und Sockets („socket“) verwendet wird.
in perlfunc und „socketpair“ in perlfunc) und Verzeichnishandles („opendir“ in
perlfunc). Aus Kompatibilitätsgründen mit früheren Perl-Versionen ist *foo{FILEHANDLE} ein
Synonym für *foo{IO}, obwohl es ab 5.8.0 veraltet ist. Bei Verfallswarnungen
wirksam sind, wird vor der Verwendung gewarnt.
*foo{THING} gibt undef zurück, wenn dieses bestimmte THING noch nicht verwendet wurde, außer im
Fall von Skalaren. *foo{SCALAR} gibt eine Referenz auf einen anonymen Skalar zurück, wenn $foo
wurde noch nicht verwendet. Dies könnte sich in einer zukünftigen Version ändern.
*foo{NAME} und *foo{PACKAGE} bilden die Ausnahme, da sie eher Zeichenfolgen zurückgeben
als Referenzen. Diese geben vielmehr das Paket und den Namen des Typeglobs selbst zurück
als einer, der ihm zugewiesen wurde. Nach „*foo=*Foo::bar“ wird also *foo
„*Foo::bar“ bei Verwendung als String, *foo{PACKAGE} und *foo{NAME} werden jedoch weiterhin verwendet
produzieren jeweils „main“ und „foo“.
*foo{IO} ist eine Alternative zum *HANDLE-Mechanismus aus „Typeglobs and
Dateihandles“ in Perldata zum Übergeben von Dateihandles in oder aus Unterroutinen, oder
Speicherung in größeren Datenstrukturen. Der Nachteil besteht darin, dass kein neues erstellt wird
Dateihandle für Sie. Der Vorteil besteht darin, dass Sie weniger Gefahr laufen, mehr zu beschädigen
Sie möchten mit einer Typeglob-Zuweisung. (Es werden immer noch Datei und Verzeichnis zusammengeführt
Handles jedoch.) Wenn Sie den eingehenden Wert jedoch einem Skalar statt a zuweisen
typeglob verwenden, wie wir es in den folgenden Beispielen tun, besteht kein Risiko, dass das passiert.
splutter(*STDOUT); # den ganzen Globus passieren
splutter(*STDOUT{IO}); # Übergeben Sie sowohl Datei- als auch Verzeichnishandles
sub stottern {
mein $fh = Verschiebung;
print $fh „ihr ähm, na ja, hmmm\n“;
}
$rec = get_rec(*STDIN); # den ganzen Globus passieren
$rec = get_rec(*STDIN{IO}); # Übergeben Sie sowohl Datei- als auch Verzeichnishandles
sub get_rec {
mein $fh = Verschiebung;
Skalar zurückgeben <$fh>;
}
Die richtigen Referenzen
Das war's mit der Erstellung von Referenzen. Mittlerweile möchten Sie wahrscheinlich unbedingt wissen, wie man es benutzt
Referenzen, um zu Ihren lange verlorenen Daten zurückzukehren. Es gibt mehrere grundlegende Methoden.
1. Überall dort, wo Sie einen Bezeichner (oder eine Kette von Bezeichnern) als Teil einer Variablen oder einfügen würden
Wenn Sie den Namen des Unterprogramms angeben, können Sie den Bezeichner durch eine einfache Skalarvariable ersetzen
enthält eine Referenz des richtigen Typs:
$bar = $$scalarref;
push(@$arrayref, $filename);
$$arrayref[0] = "Januar";
$$hashref{"KEY"} = "VALUE";
&$coderef(1,2,3);
print $globref "output\n";
Es ist wichtig zu verstehen, dass wir speziell sind nicht Dereferenzierung von $arrayref[0]
oder $hashref{"KEY"} dort. Die Dereferenzierung der Skalarvariablen erfolgt bevor it
führt alle wichtigen Suchvorgänge durch. Alles, was komplizierter ist als eine einfache Skalarvariable, muss
Verwenden Sie die folgenden Methoden 2 oder 3. Ein „einfacher Skalar“ enthält jedoch einen Bezeichner, der
selbst verwendet Methode 1 rekursiv. Daher wird im Folgenden „Howdy“ ausgegeben.
$refrefref = \\\"Howdy";
print $$$$refrefref;
2. Überall dort, wo Sie einen Bezeichner (oder eine Kette von Bezeichnern) als Teil einer Variablen oder einfügen würden
Wenn Sie den Namen des Unterprogramms angeben, können Sie den Bezeichner durch einen BLOCK ersetzen, der eine Referenz von zurückgibt
der richtige Typ. Mit anderen Worten, die vorherigen Beispiele könnten so geschrieben werden:
$bar = ${$scalarref};
push(@{$arrayref}, $filename);
${$arrayref}[0] = "Januar";
${$hashref}{"KEY"} = "VALUE";
&{$coderef}(1,2,3);
$globref->print("output\n"); # wenn IO::Handle geladen ist
Zugegebenermaßen ist es in diesem Fall etwas albern, die Curlies zu verwenden, aber der BLOCK kann es
beliebige Ausdrücke enthalten, insbesondere tiefgestellte Ausdrücke:
&{ $dispatch{$index} }(1,2,3); # richtige Routine aufrufen
Aufgrund der Möglichkeit, die Curls für den einfachen Fall von $$x wegzulassen, kommt es häufig vor
Machen Sie den Fehler, die Dereferenzierungssymbole als richtige Operatoren zu betrachten, und wundern Sie sich
über ihren Vorrang. Wenn dies jedoch der Fall wäre, könnten Sie stattdessen Klammern verwenden
Zahnspange. Das ist nicht der Fall. Betrachten Sie den Unterschied unten; Fall 0 ist eine Abkürzung
Version von Fall 1, nicht Fall 2:
$$hashref{"KEY"} = "VALUE"; # FALL 0
${$hashref}{"KEY"} = "VALUE"; # FALL 1
${$hashref{"KEY"}} = "VALUE"; # FALL 2
${$hashref->{"KEY"}} = "VALUE"; # FALL 3
Fall 2 ist auch insofern irreführend, als Sie auf eine Variable namens %hashref zugreifen, nicht jedoch
Dereferenzierung über $hashref auf den Hash, auf den es vermutlich verweist. Das wäre
Fall 3.
3. Unterprogrammaufrufe und Suchvorgänge einzelner Array-Elemente kommen häufig genug vor, dass dies der Fall ist
Es wird umständlich, Methode 2 zu verwenden. Als eine Form von syntaktischem Zucker sind die Beispiele für
Methode 2 kann geschrieben werden:
$arrayref->[0] = "Januar"; # Array-Element
$hashref->{"KEY"} = "VALUE"; # Hash-Element
$coderef->(1,2,3); # Unterprogrammaufruf
Die linke Seite des Pfeils kann ein beliebiger Ausdruck sein, der eine Referenz zurückgibt, einschließlich a
vorherige Dereferenzierung. Beachten Sie, dass $array[$x] ist nicht das Gleiche wie „$array->[$x]“
hier:
$array[$x]->{"foo"}->[0] = "Januar";
Dies ist einer der zuvor erwähnten Fälle, in denen Verweise auftreten können
Existenz in einem L-Wert-Kontext. Vor dieser Anweisung könnte $array[$x] gewesen sein
nicht definiert. Wenn ja, wird es automatisch mit einer Hash-Referenz definiert, damit wir es können
Suchen Sie darin nach „{“foo“}“. Ebenso wird „$array[$x]->{“foo“}“ automatisch abgerufen
mit einer Array-Referenz definiert, damit wir darin nach „[0]“ suchen können. Dieser Prozess ist
namens Autovivifizierung.
Hier noch etwas. Der Pfeil ist optional zwischen Indizes in Klammern setzen, damit Sie es können
verkleinern Sie das Obige auf
$array[$x]{"foo"}[0] = "Januar";
Was Sie im degenerierten Fall der Verwendung nur gewöhnlicher Arrays erhalten
mehrdimensionale Arrays genau wie Cs:
$score[$x][$y][$z] += 42;
Na ja, okay, eigentlich nicht ganz wie die Arrays von C. C weiß nicht, wie man es anbaut
Arrays auf Anfrage. Perl tut es.
4. Wenn eine Referenz zufällig eine Referenz auf ein Objekt ist, dann gibt es wahrscheinlich Methoden
um auf die genannten Dinge zuzugreifen, und Sie sollten sich wahrscheinlich an diese Methoden halten
es sei denn, Sie befinden sich im Klassenpaket, das die Methoden des Objekts definiert. Mit anderen Worten,
Seien Sie nett und verletzen Sie nicht die Kapselung des Objekts ohne guten Grund.
Perl erzwingt keine Kapselung. Wir sind hier keine Totalitaristen. Wir erwarten
allerdings etwas grundlegende Höflichkeit.
Die Verwendung einer Zeichenfolge oder Zahl als Referenz erzeugt eine symbolische Referenz, wie oben erläutert.
Die Verwendung einer Referenz als Zahl erzeugt eine Ganzzahl, die ihren Speicherort darstellt
Erinnerung. Das einzig Sinnvolle dabei ist der Vergleich zweier Referenzen
numerisch, um zu sehen, ob sie sich auf denselben Ort beziehen.
if ($ref1 == $ref2) { # günstiger numerischer Vergleich von Referenzen
print „Referenzen 1 und 2 beziehen sich auf dasselbe\n“;
}
Die Verwendung einer Referenz als Zeichenfolge erzeugt sowohl den Typ ihrer Referenz, einschließlich aller Pakete
Segen wie in perlobj beschrieben, sowie die numerische Adresse in Hex ausgedrückt. Der
ref() Der Operator gibt nur die Art von Objekt zurück, auf das die Referenz zeigt, ohne das
Adresse. Einzelheiten und Anwendungsbeispiele finden Sie unter „ref“ in perlfunc.
Die segnen() Der Operator kann verwendet werden, um das Objekt, auf das eine Referenz zeigt, mit a zu verknüpfen
Paket, das als Objektklasse fungiert. Siehe perlobj.
Ein Typeglob kann aufgrund der Dereferenzierung auf die gleiche Weise dereferenziert werden wie eine Referenz
Die Syntax gibt immer die Art der gewünschten Referenz an. Also „${*foo}“ und „${\$foo}“ beide
geben die gleiche Skalarvariable an.
Hier ist ein Trick zum Interpolieren eines Unterprogrammaufrufs in einen String:
print „Mein Sub hat damals @{[mysub(1,2,3)]} zurückgegeben.\n“;
Die Funktionsweise besteht darin, dass das „@{...}“ in der Zeichenfolge in doppelten Anführungszeichen angezeigt wird
als Block ausgewertet. Der Block erstellt einen Verweis auf ein anonymes Array, das das enthält
Ergebnisse des Aufrufs von „mysub(1,2,3)“. Der gesamte Block gibt also einen Verweis auf an zurück
Array, das dann durch „@{...}“ dereferenziert und in die Zeichenfolge in doppelten Anführungszeichen eingefügt wird.
Diese Schikane ist auch für beliebige Ausdrücke nützlich:
print „Das ergibt @{[$n + 5]} Widgets\n“;
Ebenso kann ein Ausdruck, der eine Referenz auf einen Skalar zurückgibt, über dereferenziert werden
„${...}“. Somit kann der obige Ausdruck wie folgt geschrieben werden:
print „Das ergibt ${\($n + 5)} Widgets\n“;
Kreislauf- Referenzen
Es ist möglich, in Perl einen „Zirkelverweis“ zu erstellen, der zu Speicherverlusten führen kann. A
Ein Zirkelverweis liegt vor, wenn zwei Verweise einen Verweis aufeinander enthalten, z
Dies:
mein $foo = {};
my $bar = { foo => $foo };
$foo->{bar} = $bar;
Sie können auch einen Zirkelverweis mit einer einzelnen Variablen erstellen:
mein $foo;
$foo = \$foo;
In diesem Fall erreicht der Referenzzähler für die Variablen niemals 0 und die Referenzen
werden niemals im Müll gesammelt. Dies kann zu Speicherlecks führen.
Da Objekte in Perl als Referenzen implementiert werden, ist es möglich, dass es sich um Zirkel handelt
Verweise auch auf Objekte. Stellen Sie sich eine TreeNode-Klasse vor, in der jeder Knoten auf seine Klasse verweist
übergeordnete und untergeordnete Knoten. Jeder Knoten mit einem übergeordneten Knoten ist Teil eines Zirkelverweises.
Sie können Zirkelverweise unterbrechen, indem Sie einen „schwachen Verweis“ erstellen. Eine schwache Referenz tut es
Der Referenzzähler für eine Variable wird nicht erhöht, was bedeutet, dass das Objekt ausgehen kann
verlieren und zerstört werden. Sie können eine Referenz mit der exportierten Funktion „Schwächen“ abschwächen
durch das Scalar::Util-Modul.
So können wir das erste Beispiel sicherer machen:
use Scalar::Util 'weaken';
mein $foo = {};
my $bar = { foo => $foo };
$foo->{bar} = $bar;
$foo->{bar} schwächen;
Der Verweis von $foo auf $bar wurde abgeschwächt. Wenn die Variable $bar ausgeht
Umfang, es wird im Garbage Collection gesammelt. Schauen Sie sich das nächste Mal den Wert an
„$foo->{bar}“-Taste, es wird „undef“ sein.
Diese Aktion aus der Ferne kann verwirrend sein, daher sollten Sie bei der Verwendung von vorsichtig sein
schwächen. Sie sollten die Referenz in der Variablen schwächen, die den Gültigkeitsbereich verlässt zuerst.
Auf diese Weise enthält die langlebigere Variable die erwartete Referenz, bis sie erlischt
des Umfangs.
Symbolisch Referenzen
Wir haben gesagt, dass Referenzen bei Bedarf entstehen, wenn sie undefiniert sind, aber wir
Ich habe nicht gesagt, was passiert, wenn ein als Referenz verwendeter Wert bereits definiert ist, aber nicht a
harte Referenz. Wenn Sie es als Referenz verwenden, wird es als symbolische Referenz behandelt.
Das heißt, der Wert des Skalars wird als angenommen Name einer Variablen statt a
direkter Link zu einem (möglicherweise) anonymen Wert.
Die Leute erwarten häufig, dass es so funktioniert. So ist es.
$name = "foo";
$$name = 1; # Setzt $foo
${$name} = 2; # Setzt $foo
${$name x 2} = 3; # Setzt $foofoo
$name->[0] = 4; # Setzt $foo[0]
@$name = (); # Löscht @foo
&$name(); # Ruft &foo() auf
$pack = "DAS";
${"${pack}::$name"} = 5; # Setzt $THAT::foo ohne Auswertung
Das ist kraftvoll und leicht gefährlich, da es möglich ist, (mit dem Äußersten) zu beabsichtigen
Aufrichtigkeit), eine harte Referenz zu verwenden und stattdessen versehentlich eine symbolische Referenz zu verwenden. Zu
davor schützen, könnte man sagen
benutze strikte 'refs';
und dann sind für den Rest des umschließenden Blocks nur harte Referenzen zulässig. Ein
Der innere Block kann dem widersprechen
keine strengen „Referenzen“;
Für symbolische Referenzen sind nur Paketvariablen (globale Variablen, auch wenn sie lokalisiert sind) sichtbar.
Lexikalische Variablen (deklariert mit mein()) befinden sich nicht in einer Symboltabelle und sind daher für sie unsichtbar
dieser Mechanismus. Zum Beispiel:
lokaler $Wert = 10;
$ref = "Wert";
{
mein $value = 20;
$$ref drucken;
}
Dadurch wird immer noch 10 und nicht 20 ausgegeben. Denken Sie daran lokal() wirkt sich auf Paketvariablen aus, die
sind alle „global“ für das Paket.
Nicht so symbolisch Referenzen
Klammern um eine symbolische Referenz können einfach dazu dienen, einen Bezeichner oder eine Variable zu isolieren
Namen aus dem Rest eines Ausdrucks, so wie sie es immer in einer Zeichenfolge tun. Für
Beispiel
$push = "pop on";
print „${push}over“;
wollte schon immer „pop on over“ drucken, auch wenn „push“ ein reserviertes Wort ist. Das ist
verallgemeinert, um ohne die einschließenden doppelten Anführungszeichen genauso zu funktionieren
${push} drucken. "über";
und sogar
drucken ${ push } . "über";
wird den gleichen Effekt haben. Dieses Konstrukt ist nicht als symbolische Referenz betrachtet
wenn Sie strikte Referenzen verwenden:
benutze strikte 'refs';
${ Bareword }; # Okay, bedeutet $bareword.
${ "bareword" }; # Fehler, symbolischer Verweis.
Ebenso gilt wegen der ganzen Subskription, die mit einzelnen Wörtern erfolgt, die gleiche Regel
gilt für jedes Bareword, das zum Subskribieren eines Hashs verwendet wird. Also jetzt, statt zu schreiben
$array{ "aaa" }{ "bbb" }{ "ccc" }
du kannst einfach schreiben
$array{ aaa }{ bbb }{ ccc }
und keine Sorge darüber, ob die Indizes reservierte Wörter sind. Für den seltenen Fall, dass Sie
Ich möchte so etwas tun
$array{ Verschiebung }
Sie können die Interpretation als reserviertes Wort erzwingen, indem Sie alles hinzufügen, was es zu mehr als macht
ein bloßes Wort:
$array{ Shift() }
$array{ +shift }
$array{ Shift @_ }
Das Pragma „Verwendungswarnungen“ oder das -w Der Schalter warnt Sie, wenn er ein reserviertes Wort interpretiert
als String. Es wird Sie jedoch nicht mehr vor der Verwendung von Kleinbuchstaben warnen, da die
string wird effektiv in Anführungszeichen gesetzt.
Pseudo-Hashes: Die richtigen an Array as a Hash-
Pseudo-Hashes wurden aus Perl entfernt. Das Pragma „Felder“ bleibt verfügbar.
Funktion Template
Wie oben erläutert, handelt es sich um eine anonyme Funktion mit Zugriff auf die sichtbaren lexikalischen Variablen
Wenn diese Funktion kompiliert wurde, wird ein Abschluss erstellt. Der Zugriff auf diese Variablen bleibt erhalten
auch wenn es erst später ausgeführt wird, beispielsweise in einem Signalhandler oder einem Tk-Rückruf.
Durch die Verwendung eines Abschlusses als Funktionsvorlage können wir viele Funktionen generieren, die agieren
ähnlich. Angenommen, Sie möchten Funktionen, die nach den Farben benannt sind, die die HTML-Schriftart generiert haben
Änderungen für die verschiedenen Farben:
print „Sei“, rot („vorsichtig“), „damit“, grün („Licht“);
Die Rot() und Grün() Die Funktionen wären ähnlich. Um diese zu erstellen, weisen wir einen Abschluss zu
zu einem Typeglob des Namens der Funktion, die wir erstellen möchten.
@colors = qw(rot blau grün gelb orange lila violett);
für meinen $namen (@colors) {
keine strengen „Referenzen“; # Manipulation der Symboltabelle zulassen
*$name = *{uc $name} = sub { " @_ " };
}
Jetzt scheinen all diese verschiedenen Funktionen unabhängig voneinander zu existieren. Du kannst anrufen Rot(),
ROT(), Blau(), BLAU(), Grün()usw. Diese Technik spart sowohl Kompilierzeit als auch Speicher
Verwendung und ist außerdem weniger fehleranfällig, da Syntaxprüfungen zur Kompilierzeit erfolgen. Es ist
Es ist wichtig, dass alle Variablen in der anonymen Unterroutine lexikalische Variablen sind, um eine zu erstellen
ordnungsgemäßer Verschluss. Das sind die Gründe für die Variable „my“ in der Schleifeniteration.
Dies ist einer der wenigen Orte, an denen es sinnvoll ist, einem Verschluss einen Prototyp zu geben. Wenn
Sie wollten den Argumenten dieser Funktionen einen skalaren Kontext auferlegen (wahrscheinlich nicht).
(Eine kluge Idee für dieses spezielle Beispiel), Sie hätten es stattdessen auch so schreiben können:
*$name = sub ($) { " $_[0] " };
Da die Überprüfung des Prototyps jedoch zur Kompilierzeit erfolgt, erfolgt die obige Zuweisung
zu spät, um von großem Nutzen zu sein. Sie könnten dieses Problem beheben, indem Sie die gesamte Schleife einfügen
Zuweisungen innerhalb eines BEGIN-Blocks, wodurch die Ausführung während der Kompilierung erzwungen wird.
Zugriff auf Lexika, die sich im Laufe der Zeit ändern – im Grunde genommen die in der „for“-Schleife oben
Aliase für Elemente aus den umgebenden lexikalischen Bereichen – funktioniert nur mit anonymen Subs,
nicht mit benannten Unterprogrammen. Im Allgemeinen lassen sich benannte Unterprogramme nicht richtig verschachteln
sollte nur im Hauptpaketbereich deklariert werden.
Dies liegt daran, dass benannte Unterprogramme zur Kompilierungszeit erstellt werden, also ihre lexikalischen Variablen
werden den übergeordneten Lexika ab der ersten Ausführung des übergeordneten Blocks zugewiesen. Wenn ein
Wenn der übergeordnete Bereich ein zweites Mal eingegeben wird, werden seine Lexika erneut erstellt, während die verschachtelten
Subs verweisen immer noch auf die alten.
Anonyme Unterroutinen erfassen jedes Mal, wenn Sie den „sub“-Operator ausführen, so wie sie sind
spontan erstellt. Wenn Sie es gewohnt sind, in anderen Programmen verschachtelte Unterprogramme zu verwenden
Wenn Sie Sprachen mit eigenen privaten Variablen verwenden, müssen Sie in Perl ein wenig daran arbeiten. Der
Die intuitive Codierung dieser Art von Dingen bringt mysteriöse Warnungen mit sich, dass es nicht bleiben wird
geteilt“ aus den oben erläuterten Gründen. Dies wird beispielsweise nicht funktionieren:
sub äußere {
mein $x = $_[0] + 35;
sub inner { return $x * 19 } # FALSCH
return $x + inner();
}
Eine Problemumgehung ist die folgende:
sub äußere {
mein $x = $_[0] + 35;
local *inner = sub { return $x * 19 };
return $x + inner();
}
Jetzt innere() kann nur von innen aufgerufen werden äußere(), wegen der temporären Einsätze
des anonymen Unterprogramms. Wenn dies jedoch der Fall ist, hat es normalen Zugriff auf das Lexikon
Variable $x aus dem Bereich von äußere() zum Zeitpunkt des Aufrufs von „outer“.
Dies hat den interessanten Effekt, dass eine Funktion lokal für eine andere Funktion erstellt wird.
etwas, das normalerweise in Perl nicht unterstützt wird.
WARNUNG
Sie dürfen eine Referenz nicht (sinnvoll) als Schlüssel für einen Hash verwenden. Es wird in ein umgewandelt
Zeichenfolge:
$x{ \$a } = $a;
Wenn Sie versuchen, den Schlüssel zu dereferenzieren, wird keine harte Dereferenzierung durchgeführt, und Sie werden dies auch nicht tun
Erreiche, was du versuchst. Vielleicht möchten Sie etwas Ähnliches tun
$r = \@a;
$x{ $r } = $r;
Und dann können Sie das zumindest nutzen Werte (), die echte Schiedsrichter sein werden, anstelle der
Schlüssel(), was nicht der Fall ist.
Das Standardmodul Tie::RefHash bietet hierfür eine praktische Lösung.
Postfix Dereferenzierung Syntax
Ab v5.20.0 ist eine Postfix-Syntax für die Verwendung von Referenzen verfügbar. Es verhält sich wie
beschrieben in „Verwenden von Referenzen“, aber anstelle eines vorangestellten Siegels wird ein nachgestelltes Siegel verwendet.
Stern wird verwendet.
Beispielsweise:
$r = \@a;
@b = $r->@*; # entspricht @$r oder @{ $r }
$r = [ 1, [ 2, 3 ], 4 ];
$r->[1]->@*; # entspricht @{ $r->[1] }
Diese Syntax muss mit „use feature ‚postderef‘“ aktiviert werden. Es ist experimentell und wird es tun
warnt standardmäßig, es sei denn, „no warnings 'experimental::postderef'“ ist wirksam.
Die Postfix-Dereferenzierung sollte unter allen Umständen funktionieren, in denen eine Block-Dereferenzierung (Circumfix) erfolgt
hat funktioniert und sollte völlig gleichwertig sein. Diese Syntax ermöglicht das Schreiben einer Dereferenzierung
und vollständig von links nach rechts lesen. Folgende Äquivalenzen sind definiert:
$sref->$*; # dasselbe wie ${ $sref }
$aref->@*; # dasselbe wie @{ $aref }
$aref->$#*; # dasselbe wie $#{ $aref }
$href->%*; # dasselbe wie %{ $href }
$cref->&*; # dasselbe wie &{ $cref }
$gref->**; # dasselbe wie *{ $gref }
Beachten Sie insbesondere, dass „$cref->&*“ ist nicht Äquivalent zu „$cref->()“ und kann unterschiedlich dienen
Zwecke.
Glob-Elemente können über die Postfix-Dereferenzierungsfunktion extrahiert werden:
$gref->*{SCALAR}; # dasselbe wie *{ $gref }{SCALAR}
Postfix-Array und skalare Dereferenzierung können. in interpolierenden Zeichenfolgen verwendet werden (doppelte Anführungszeichen).
oder der „qq“-Operator), aber nur, wenn die zusätzliche Funktion „postderef_qq“ aktiviert ist.
Postfix Literaturhinweis Slicing
Wertabschnitte von Arrays und Hashes können auch mit der Postfix-Dereferenzierungsnotation erstellt werden.
mit folgenden Äquivalenten:
$aref->@[ ... ]; # dasselbe wie @$aref[ ... ]
$href->@{ ... }; # dasselbe wie @$href{ ... }
Postfix-Schlüssel/Wert-Paar-Slicing, hinzugefügt in 5.20.0 und dokumentiert im Schlüssel/Wert-Hash
Slices-Abschnitt von Perldata, verhält sich ebenfalls wie erwartet:
$aref->%[ ... ]; # dasselbe wie %$aref[ ... ]
$href->%{ ... }; # dasselbe wie %$href{ ... }
Wie beim Postfix-Array erfolgt die Dereferenzierung von Postfix-Wert-Slices können. bei der Interpolation verwendet werden
Zeichenfolgen (doppelte Anführungszeichen oder der „qq“-Operator), aber nur, wenn das zusätzliche „postderef_qq“
Funktion aktiviert ist.
Zuweisen zu Referenzen
Ab v5.22.0 kann der Referenzierungsoperator zugewiesen werden. Es führt eine
Aliasing-Operation, sodass der auf der linken Seite referenzierte Variablenname zu einem wird
Alias für das Ding, auf das auf der rechten Seite verwiesen wird:
\$a = \$b; # $a und $b zeigen jetzt auf denselben Skalar
\&foo = \&bar; # foo() bedeutet jetzt bar()
Diese Syntax muss mit „Funktion ‚Refaliasing‘ verwenden“ aktiviert werden. Es ist experimentell und
wird standardmäßig gewarnt, es sei denn, „keine Warnungen ‚experimental::refaliasing‘“ ist wirksam.
Diese Formen können zugewiesen werden und bewirken, dass die rechte Seite skalar ausgewertet wird
Kontext:
\$skalar
\@array
\%Hash
\&sub
\mein $skalar
\mein @array
\mein %hash
\state $scalar # oder @array usw.
\our $scalar # usw.
\local $scalar # usw.
\local unser $scalar # usw.
\$some_array[$index]
\$some_hash{$key}
\local $some_array[$index]
\local $some_hash{$key}
Zustand ? \$this : \$that[0] # usw.
Slicing-Operationen und Klammern bewirken, dass die rechte Seite in der Liste ausgewertet wird
Kontext:
\@array[5..7]
(\@array[5..7])
\(@array[5..7])
\@hash{'foo','bar'}
(\@hash{'foo','bar'})
\(@hash{'foo','bar'})
(\$skalar)
\($skalar)
\(mein $skalar)
\my($scalar)
(\@array)
(\%hash)
(\&sub)
\(&sub)
\($foo, @bar, %baz)
(\$foo, \@bar, \%baz)
Jedes Element auf der rechten Seite muss eine Referenz auf ein Datum des richtigen Typs sein.
Klammern, die ein Array unmittelbar umgeben (und möglicherweise auch
„mein“/„Zustand“/„unser“/„lokal“) macht jedes Element des Arrays zu einem Alias für die
entsprechender Skalar, auf den auf der rechten Seite verwiesen wird:
\(@a) = \(@b); # @a und @b haben jetzt die gleichen Elemente
\my(@a) = \(@b); # ebenfalls
\(mein @a) = \(@b); # ebenfalls
drücke @a, 3; # aber jetzt hat @a ein zusätzliches Element, das @b fehlt
\(@a) = (\$a, \$b, \$c); # @a enthält jetzt $a, $b und $c
Das Kombinieren dieser Form mit „local“ und das Setzen von Klammern direkt um einen Hash sind
verboten (weil nicht klar ist, was sie tun sollen):
\local(@array) = foo(); # FALSCH
\(%hash) = bar(); # falsch
Zuweisungen zu Referenzen und Nichtreferenzen können in Listen und bedingt kombiniert werden
ternäre Ausdrücke, sofern die Werte auf der rechten Seite den richtigen Typ haben
jedes Element auf der linken Seite, obwohl dies zu verschleiertem Code führen kann:
(mein $tom, \mein $dick, \mein @harry) = (\1, \2, [1..3]);
# $tom ist jetzt \1
# $dick ist jetzt 2 (schreibgeschützt)
# @harry ist (1,2,3)
my $type = ref $thingy;
($type ? $type == 'ARRAY' ? \@foo : \$bar : $baz) = $thingy;
Die „foreach“-Schleife kann jedoch auch einen Referenzkonstruktor für ihre Schleifenvariable annehmen
Die Syntax ist auf eine der folgenden beschränkt, mit einem optionalen „my“, „state“ oder „our“ dahinter
der Backslash:
\$s
\@A
\%H
\&C
Es sind keine Klammern zulässig. Diese Funktion ist besonders nützlich für Arrays von Arrays,
oder Arrays von Hashes:
foreach \my @a (@array_of_arrays) {
frobnicate($a[0], $a[-1]);
}
foreach \my %h (@array_of_hashes) {
$h{gelastic}++ if $h{type} == 'funny';
}
VORBEHALT: Aliasing funktioniert bei Verschlüssen nicht korrekt. Wenn Sie versuchen, einen lexikalischen Alias zu verwenden
Variablen aus einer inneren Unterroutine oder „eval“, das Aliasing ist nur innerhalb sichtbar
dieses innere Unterprogramm und hat keinen Einfluss auf das äußere Unterprogramm, in dem die Variablen deklariert sind.
Dieses bizarre Verhalten kann sich ändern.
Verwenden Sie perlref online über die Dienste von onworks.net