Hat ein nicht initialisierter Hash-Schlüssel in Perl einen Standardwert von Null?

8

Ich habe Perl-Code ähnlich dem folgenden:

%Vor%

Zu keinem Zeitpunkt wird $res vor dem Iterieren der Abfrageergebnisse gesetzt, der Code läuft jedoch einwandfrei.

Wenn ich print-Anweisungen vor jeden Wert schreibe, bekomme ich in beiden Fällen Leerzeichen, aber wenn die print-Anweisungen nach dem Inkrement kommen, bekomme ich einen Wert von & gt; = 1, abhängig davon, wie viele IPv6-Ressourcen die Organisation hat.

Meine Frage ist, nehme ich an, dass ein nicht initialisierter Hash-Schlüssel in Perl automatisch den Wert Null hat?

Tut mir leid, wenn es als Anfängerfrage erscheint, aber ich kenne ein solches Konstrukt einfach nicht d.h. $hashref->{foo}->{bar}++ wo ein Wert explizit noch $hashref->{foo}->{bar} zugewiesen werden muss. Vielen Dank im Voraus!

    
freakwincy 01.05.2009, 14:10
quelle

4 Antworten

26

Der Wert ist nicht automatisch Null. Der Wert ist zunächst undefiniert. Wenn Sie es jedoch wie eine Zahl behandeln (z. B. ++ darauf anwenden), behandelt Perl es wie Null. Wenn Sie sie wie eine Zeichenfolge behandeln (z. B. . darauf anwenden), behandelt Perl sie wie eine leere Zeichenfolge.

Von perldoc perlsyn , unter 'Deklarationen':

  

Die einzigen Dinge, die Sie deklarieren müssen   Perl sind Reportformate und   Subroutinen (und manchmal nicht einmal   Unterroutinen). Eine Variable enthält die   undefinierter Wert ("undef") bis es ist   wurde ein definierter Wert zugewiesen, der   ist alles andere als "undef". Wann   Als Nummer wird "undef" behandelt   als 0; wenn es als eine Schnur verwendet wird, ist es   behandelt als die leere Zeichenfolge, ""; und   wenn es als Referenz verwendet wird, ist dies nicht der Fall   zugeordnet wird, wird es wie behandelt   Fehler.

    
Telemachus 01.05.2009, 14:28
quelle
5

Um Telemachs Beitrag zu erläutern, sind die nicht initialisierten Werte undefiniert. Die tiefen Teile der Struktur sind autovivifiziert . Dies ist eine praktische Funktion, bei der Datenstrukturen automatisch für Sie erstellt werden. Autovivification ist großartig, wenn Sie es wollen, aber es kann ein Schmerz sein, wenn Sie es verhindern wollen. Es gibt viele Tutorials, Artikel und Posts rund um das Internet zum Verständnis der Autovivi zierung.

Bei einem undefinierten $ref und $ref->{ipv6}{pa}{'foo'}++ wird $ref den folgenden Wert zugewiesen:

%Vor%

Dann wird der Undef inkrementiert, da Undef zu 0 wird, erhalten wir 0 ++, was 1 ist. Für ein Endergebnis von: ref->{ipv6}{pa}{'foo'} == 1 .

Wenn Sie Warnungen aktiviert haben (Sie tun use warnings; , nicht wahr?), erhalten Sie eine Warnung "nicht initialisierter Wert", wenn Sie mit diesen undefinierten Werten arbeiten. Wenn es das gewünschte Verhalten ist, den vereinheitlichten Wert zu erhöhen, können Sie die gewünschte Gruppe von Warnungen für einen begrenzten Teil Ihres Codes deaktivieren:

%Vor%

Sie finden die Warning-Hierarchie in perllexwarn .

    
daotoad 01.05.2009 15:11
quelle
4

Es ist im Grunde undefiniert, aber behandelt, als ob es Null war, wenn Sie es erhöhen.

Der Ausdruck im Perl-Sprachgebrauch ist "autovivifiziert".

Wahrscheinlich möchten Sie das Keyword exists verwenden:

%Vor%     
Robert S. Barnes 01.05.2009 14:34
quelle
2

Es gibt keine nicht initialisierte Hash Taste . Die Sache, die nicht initialisiert werden kann, ist der Wert für einen bestimmten Schlüssel. Ein Hash-Wert ist nur ein Skalarwert; Es ist nicht anders als eine Variable wie $foo .

In Ihrem Beispiel interagieren ein paar verschiedene Perl-Funktionen.

Anfangs $res ist nicht definiert (d. h. es hat den Wert undef ). Wenn Sie einen nicht initialisierten Wert als Hashreferenz verwenden (wie in $res->{ipv6}... ), "autoviviert" Perl es als eins. Das heißt, Perl erstellt einen anonymen Hash und ersetzt den Wert von undef durch einen Verweis auf den neuen Hash. Dieser Vorgang wird jedes Mal wiederholt, wenn Sie den resultierenden Wert als Referenz verwenden.

Schließlich autovivifierst du deinen Weg zu $res->{ipv6}{pa}{$row->[2]} , was undefiniert ist. Denken Sie daran, dass dies nur ein Skalarwert wie $foo ist. Das Verhalten ist dasselbe wie das Sprechen von

%Vor%

Perl macht besondere Dinge, wenn Sie undefinierte Werte verwenden. Wenn Sie sie als Zahl verwenden, konvertiert Perl sie in 0. Wenn Sie sie als Zeichenfolge verwenden, konvertiert Perl sie in '' (die leere Zeichenfolge). In den meisten Fällen erhalten Sie eine Warnung "Verwendung von nicht initialisierten Werten ...", wenn Warnungen aktiviert sind (was Sie tun sollten). Der Autoinkrement -Operator ( ++ ) ist jedoch ein Sonderfall . Aus praktischen Gründen konvertiert es den Wert von undef nach 0 , bevor er inkrementiert wird.

    
Michael Carman 01.05.2009 18:03
quelle

Tags und Links