Enthält ein nicht initialisierte Hash-Schlüssel einen Standardwert von Null in Perl hat?

StackOverflow https://stackoverflow.com/questions/811515

  •  03-07-2019
  •  | 
  •  

Frage

Ich habe Perl-Code ähnlich den folgenden:

# -- start --

my $res;

# run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{
    if( $row->[4] =~ /PA/ ) {
        $res->{ipv6}{pa}{$row->[2]}++;
    } elsif( $row->[4] eq 'PI' ) {
        $res->{ipv6}{pi}{$row->[2]}++;
    }
}

# -- stop --

An keiner Stelle wird $res jemals vor gesetzt über die Abfrageergebnisse iterieren noch der Code läuft gut.

Wenn ich print-Anweisungen setzen vor jedem Wert ich Leerzeichen in beiden Fällen aber, wenn die Druckanweisungen kommen, nachdem der Zuwachs angewendet wurde bekomme ich einen Wert von> = 1, je nachdem, wie viele IPv6-Ressourcen der Organisation.

Meine Frage ist, nehme ich dies ein nicht initialisierte Hash-Schlüssel in Perl automatisch einen Wert von Null hat zu bedeuten?

Sorry, wenn es über als Neuling Frage kommt, aber ich bin einfach nicht vertraut mit solchen Konstrukt d.h. $hashref->{foo}->{bar}++ wobei ein Wert noch werden muss explizit $hashref->{foo}->{bar} zugeordnet. Vielen Dank im Voraus!

War es hilfreich?

Lösung

Der Wert ist nicht automatisch Null. Der Wert ist zunächst nicht definiert. Allerdings, wenn Sie es wie eine Nummer behandelt (zB gelten ++ es), dann Perl behandelt sie wie Null. Wenn Sie es wie eine Zeichenfolge behandeln (zB gelten . es), dann Perl behandelt sie wie eine leere Zeichenfolge.

Von perldoc perlsyn unter 'Erklärungen':

  

Das einzige, was müssen Sie erklären in   Perl sind Berichtsformate und   Subroutinen (und manchmal nicht einmal   Subroutinen). Eine Variable hält die   undefinierter Wert ( „undef“), bis er hat   wurde ein definierter Wert zugewiesen, der   ist etwas anderes als „undefiniert“. Wann   als Nummer verwendet wird, wird „undef“ behandelt   als 0; wenn sie als Zeichenfolge verwendet wird, ist es   als leere Zeichenfolge behandelt, „“; und   wenn als Referenz verwendet das ist nicht   wobei zugewiesen, wird es als behandelte   Fehler.

Andere Tipps

Um auf Telemachos zu erarbeiten post, werden die nicht initialisierte Werte undefiniert. Die tiefen Teile der Struktur sind autovivified . Dies ist eine praktische Funktion, wo Datenstrukturen werden automatisch für Sie erstellt. Autovivification ist groß, wenn Sie es wollen, aber es kann ein Schmerz, wenn Sie es verhindern wollen. Es gibt viele Tutorials, Artikel und Beiträge rund um das Netz auf autovivification zu verstehen.

So eine undefinierte $ref und $ref->{ipv6}{pa}{'foo'}++ gegeben wird $ref einen Wert von zugewiesen werden:

$ref = { 
     ipv6 => { 
          pa => { 
              foo => undef
          }
     }
};

Dann wird der undef erhöht werden, da undef numifies auf 0, erhalten wir 0 ++, die 1 ist. Für ein endgültiges Ergebnis:. ref->{ipv6}{pa}{'foo'} == 1

Wenn Sie Warnungen aktiviert ist, (Sie tun use warnings;, nicht wahr?) Erhalten Sie eine „nicht initialisierte Wert“ Warnung erhalten, wenn Sie auf diesen undefinierten Werten betreiben. Wenn es das gewünschte Verhalten ist der unitialized Wert zu erhöhen, dann können Sie die gewünschte Gruppe von Warnungen aus über einen begrenzten Teil des Codes schalten:

use strict;
use warnings;
my $res;

// run query to fetch IPv6 resources
while( my $row = $org_ip6_res->fetchrow_arrayref )
{   no warnings 'uninitialized';
    if( $row->[4] =~ /PA/ ) {
        $res->{ipv6}{pa}{$row->[2]}++;
    } elsif( $row->[4] eq 'PI' ) {
        $res->{ipv6}{pi}{$row->[2]}++;
    }
}

Sie können die Warnungen Hierarchie finden in perllexwarn .

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

Der Begriff in Perl parlance ist 'autovivified'.

Was möchten Sie wahrscheinlich tun, verwenden Sie die existiert Stichwort :

$res->{ipv6}{pa}{$row->[2]}++ if exists($res->{ipv6}{pa}{$row->[2]});

Es gibt nicht so etwas wie einen nicht initialisierten Hash Schlüssel . Die Sache, die nicht initialisiert werden kann, ist der Wert für einen bestimmten Schlüssel. Ein Hash-Wert ist nur ein skalarer Wert ist; es ist nicht anders als eine Variable wie $foo.

Es gibt ein paar verschiedene Perl in Ihrem Beispiel Funktionen interagieren.

Am Anfang $res ist nicht definiert (das heißt hat sie den Wert undef). Wenn Sie einen nicht initialisierten Wert als Hash-Referenz (wie in $res->{ipv6}...) Perl „autovivifies“ als eines. Das heißt, Perl erstellt einen anonymen Hash und ersetzt den Wert von undef mit einem Verweis auf den neuen Hash. Dieser Vorgang wiederholt sich (leise) jedes Mal, wenn der resultierende Wert als Referenz verwenden.

Schließlich autovivify Sie Ihren Weg $res->{ipv6}{pa}{$row->[2]}, die nicht definiert ist. Denken Sie daran, dass dies nur ein Einzelwert wie $foo ist. Das Verhalten ist das gleiche wie zu sagen

my $foo;
$foo++;

Perl tut spezielle Dinge, wenn Sie nicht definierte Werte verwenden. Wenn Sie sie als Nummer verwenden, konvertiert Perl sie auf 0, wenn Sie sie als String verwenden, Perl konvertiert sie in das ‚‘ (leerer String). In den meisten Fällen finden Sie eine „Verwendung von nicht initialisierten Wert ...“ Warnung erhalten, wenn Sie Warnungen aktiviert haben (die Sie sollten). Die Autoinkrement Operator (++) ist ein obwohl Sonderfall. Der Einfachheit halber, wandelt es still um den Wert von undef vor Erhöhen sie 0.

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