Was bedeutet `$ hash {$ key} | = {}` in Perl tun?
-
03-07-2019 - |
Frage
Ich ringe mit einigen Perl, die Hashreferenzen verwendet.
Am Ende stellte sich heraus, dass mein Problem war die Zeile:
$myhash{$key} |= {};
Das heißt, "$ myhash {$ key} einen Verweis auf einen leeren Hash zuweisen, es sei denn, es bereits einen Wert hat".
Dereferenzierung diese und versuchen, es als Hash-Referenz zu verwenden, jedoch ergab Interpreter Fehler über einen String als Hash-Referenz.
Ändern Sie es an:
if( ! exists $myhash{$key}) {
$myhash{$key} = {};
}
... die Dinge funktionieren.
So habe ich nicht ein Problem . Aber ich bin gespannt, was los war.
Kann mir jemand erklären?
Lösung
Der Grund, warum Sie einen Fehler sind zu sehen, um einen String als Hash-Referenz verwendet, weil Sie den falschen Operator verwenden. |=
bedeutet "bitweise-or-assign." Mit anderen Worten:
$foo |= $bar;
ist die gleiche wie
$foo = $foo | $bar
Was passiert in Ihrem Beispiel ist, dass Ihre neue anonyme Hashreferenz Zeichenfolge wird immer dann bitweise ODER-Verknüpfung mit dem Wert von $myhash{$key}
. Um die Sache weiter zu verwirren, wenn $myhash{$key}
zu dem Zeitpunkt nicht definiert ist, ist der Wert die einfache stringification der die Hash-Referenz, die wie HASH(0x80fc284)
aussieht. Wenn Sie also eine oberflächliche Prüfung der Struktur zu tun, kann es aussehen wie eine Hash-Referenz, aber es ist nicht. Hier einige nützliche Ausgabe über Data::Dumper
:
perl -MData::Dumper -le '$hash{foo} |= { }; print Dumper \%hash'
$VAR1 = {
'foo' => 'HASH(0x80fc284)'
};
Und hier ist das, was Sie bekommen, wenn Sie den richtigen Operator verwenden:
perl -MData::Dumper -le '$hash{foo} ||= { }; print Dumper \%hash'
$VAR1 = {
'foo' => {}
};
Andere Tipps
Perl hat Stenografie Zuweisungsoperatoren. Der ||=
Operator wird häufig auf Standardwerte für die Variablen aufgrund Perl Merkmal mit logischen Operatoren geben den letzten Wert ausgewertet verwendet. Das Problem ist, dass Sie |=
verwendet, die ein bitweise oder anstelle von ||=
, welches ein logischer oder.
Wie von Perl 5.10 ist es besser //=
stattdessen zu verwenden. //
ist die logische definiert-oder Betreiber und nicht scheitern in der Ecke Fall, in dem der aktuelle Wert definiert ist aber falsch.
Ich denke, Ihr Problem "|=
" (bitweise oder Zuweisung) anstelle von "||=
" wurde mit (zuweisen, wenn false).
Beachten Sie, dass Ihr neuer Code nicht genau entspricht. Der Unterschied besteht darin, dass „$myhash{$key} ||= {}
“ ersetzt vorhandene-but-falschen Werte mit einer Hash-Referenz, aber die neuen nicht. In der Praxis ist dies wahrscheinlich nicht relevant.
Versuchen Sie folgendes:
my %myhash;
$myhash{$key} ||= {};
Sie können einen Hash deklarieren -Element in einer my
Klausel, soweit ich weiß. Sie erklären den Hash zuerst, dann in das Element hinzuzufügen.
Edit: Ich sehe Sie die my
herausgenommen haben. Wie wäre es ||=
statt |=
versuchen? Ersteres ist idiomatisch für „faul“ Initialisierung.