Frage

Hier finden Sie einige einfache Perl die Anzahl der Male ein Wert in einem Array auftritt, zu zählen. Dies läuft ohne Warnungen.

use warnings;
use strict;

my @data = qw(1 1 2 3 4 5 5 5 9);
my %histogram;
foreach (@data)
{
    $histogram{$_}++;
}

Wenn der Schleifenkörper wird geändert

$histogram{$_} = $histogram{$_} + 1;

Perl warnt "Verwendung von nicht initialisierten Wert zusätzlich".

Was unter der Haube ist hier los? Warum ist der initialisierten Wert, wenn sie als Operand in dem ++ Operator und nicht initialisierten mit dem Operator + versorgt?

War es hilfreich?

Lösung

Der Operator + wertet sowohl das Formular auf der linken Seite und das Formular rechts von ihm, dann gibt die Summe aus beiden. Die Hash-Anruf Auswertung keinen besonderen Kontext sehen.

Der Operator ++ hat einige besondere Magie gebaut in der perlop manpage Zitierte in Bezug auf den Operator ++:.

  

„undefiniert“ wird immer als numerisch behandelt, insbesondere auf 0 geändert wird, bevor erhöht wird (so dass ein Post-Inkrement eines undef Wert 0 zurück und nicht als „undefiniert“).

Bearbeiten : auf dem Unterschied zu erarbeiten, ++ ändert den Wert in Platz, während + nur seine Argumente als Eingabe verwendet. Wenn + einen nicht definierten Wertes sieht, in der Regel ist etwas schief gegangen, aber für ++, ist Ihr Hash-Manipulation Beispiel sehr typisch - die Nutzer wollen undef als 0 behandeln, anstatt dass jedes Mal zu überprüfen und initialisieren. So scheint es, dass es sinnvoll, diese Betreiber auf diese Weise zu behandeln macht.

Andere Tipps

Es ist nicht, dass Perl notwendigerweise Werte initialisiert, aber dass es nicht immer über sie warnt. Versuchen Sie nicht, für diese über eine Regel zu denken, weil Sie immer Ausnahmen finden, und nur, wenn Sie denken, Sie haben es herausgefunden, die nächste Version von Perl werden die Warnungen auf Sie ändern.

In diesem Fall, wie Harleqin sagte, hat der Autoinkrement-Betreiber einen Sonderfall dar.

Einige Betreiber bewusst auf die „nicht initialisierte“ Warnung für Ihre Bequemlichkeit auslassen weil sie in Situationen, in denen ein 0 oder „“ Standardwert für die linken oder nur Operanden machen Sinn, häufig verwendet werden.

Diese sind: ++ und - (entweder vor oder nach), + =, - =, = | = ^ =, && =, || =

..

Beachten Sie, dass einige von ihnen fälschlicherweise der Warnung geben, wenn sie auf einem vertraglich gebundenen Variable verwendet: siehe die Tests markiert ERLEDIGT in http://perl5.git.perl.org/perl.git/blob/HEAD:/t/op/assignwarn.t .

Wie Brian erwähnt: es es immer noch tut, warnt es Sie gerade. Warnungen informieren Sie über bestimmte Manipulationen mit Effekten könnten Sie nicht beabsichtigt haben.

Sie sind speziell zu fragen für den Wert von $histogram{$_}, Zugabe von 1 bis es und dann auf den gleichen Steckplatz zuweisen. Es ist die gleiche Art und Weise, die ich nicht erwarten autovivification hier zu arbeiten:

my $hash_ref = $hash_for{$key_level_1};
$hash_ref->{$key_level_2} = $value;

, wie es tut sich hier:

$hash_for{$key_level_1}{$key_level_2} = $value;

Magie funktioniert wahrscheinlich nicht wie Optimierung. Und Compiler optimiert würde, dass a = a + 1 bemerken das gleiche wie a++ ist so, dass gab es eine Inkrementoperator in der Assemblersprache, könnte es, dass die optimierte Anweisung verwenden, anstatt so zu tun, dass es den ersten Wert zu erhalten benötigt, und überschreiben sie dann, weil es isn ‚t tatsächlich benötigt wird.

Die Optimierung ist zusätzliche Kontrolle und Overhead einmal für eine verbesserte Leistung jeden Lauf. Aber es gibt keine Garantie, in einer dynamischen Sprache, die Sie nicht Overhead mit der gleichen Rate Zugabe werden würden Sie sonst zu reduzieren versuchen.

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