Warum strenge und Warnungen verwenden?

104

Es scheint mir, dass viele der Fragen im Perl-Tag gelöst werden könnten, wenn die Leute Folgendes verwenden würden:

use strict;
use warnings;

Ich denke, einige Leute halten diese für Stützräder oder unnötige Komplikationen, was eindeutig nicht der Fall ist, da sie selbst von sehr erfahrenen Perl-Programmierern verwendet werden.

Es scheint, als ob die meisten Leute, die Perl beherrschen, diese beiden Pragmas immer verwenden, während diejenigen, die am meisten davon profitieren würden, dies selten tun. Daher dachte ich, es wäre eine gute Idee, eine Frage zu haben, auf die man sich beziehen kann, wenn man Menschen dazu ermutigt, use strictund warnings.

Also, warum sollte ein Perl-Entwickler use strictund warnings?

TLP
quelle
14
Ich frage mich immer für solche Sachen, warum sie es nicht einfach zum Standard machen und der Entwickler tatsächlich aktiv Sachen lockern muss, wo ist deruse loose;
Paul Tyng
12
Wie viele coole und nützliche Dinge begann Perl als Hack, als Werkzeug für den Typ, der es erfindet. Später wurde es populärer und eine zunehmende Anzahl von ungelernten Menschen begann es zu benutzen. Dies ist, wenn Sie anfangen zu denken, dass etwas wie use stricteine gute Idee war, aber Abwärtskompatibilität ist bereits ein echtes Problem für Sie geworden :-(
Daniel Böhmer
14
@JB Nizet, @Paul T., Ist use strict;standardmäßig aktiviert, wenn Sie die Sprache Perl 5.12 (oder höher) anfordern. Versuchen Sie es perl -e"use v5.012; $x=123;". no strict;schaltet es tatsächlich aus.
Ikegami
1
Obwohl Ihr Standpunkt am Ende wahr ist, werden die Leute vielleicht umso mehr hören, je öfter wir ihn sagen. In letzter Zeit gab es einige Gerüchte darüber, mehr / bessere / moderne Perl-Tutorials zur Verfügung zu stellen, und sicherlich werden strenge / Warnungen auf jedem dieser Tutorials stehen. Für meine habe ich vor, s / w oben auf jedem Snippet zu haben, nur damit alle Neulinge es jedes Mal sehen
Joel Berger
5
@ JoelBerger Nein, eigentlich ist es nichts Vergleichbares. Wie ich schon sagte, es hat nur ähnliche Wörter im Titel. Es dient der Abwärtskompatibilität. Ist der erste Satz in der akzeptierten Antwort, wie schlagen Sie das für meine Frage vor?
TLP

Antworten:

83

Für den Anfang use strict;(und in geringerem Maße use warnings;) hilft es, Tippfehler in Variablennamen zu finden. Selbst erfahrene Programmierer machen solche Fehler. Ein häufiger Fall ist das Vergessen, eine Instanz einer Variablen beim Bereinigen oder Umgestalten von Code umzubenennen.

Die Verwendung use strict; use warnings;fängt viele Fehler früher ab, als sie sonst abgefangen würden, was es einfacher macht, die Grundursachen der Fehler zu finden. Die Hauptursache könnte die Notwendigkeit einer Fehler- oder Validierungsprüfung sein, und dies kann unabhängig von den Fähigkeiten des Programmierers geschehen.

Das Gute an Perl-Warnungen ist, dass sie selten falsch sind, sodass ihre Verwendung so gut wie keine Kosten verursacht.


Verwandte Lektüre: Warum verwenden my?

Ikegami
quelle
2
@ TLP, ich werde keine Studie machen, um zu quantifizieren, wie viel es hilft. Es sollte genügen zu sagen, dass sie bedingungslos helfen.
Ikegami
1
Warum wird es dann optional gemacht, wenn es so viele Vorteile hat? Warum nicht standardmäßig aktivieren (wie oben kommentiert)? Ist es aus Kompatibilitätsgründen?
Jean
4
@ Jean, Abwärtskompatibilität. Beachten Sie, dass dies use strict;standardmäßig aktiviert ist, wenn Sie Version 5.12 oder höher der Sprache ( use 5.012;) verwenden.
Ikegami
@ Jean, wenn Sie ein einfaches Skript schreiben, möchten Sie wirklich nicht durch Warnungen über File-Handler-Namen oder dafür, dass Sie die Variable nicht deklariert haben, bevor Sie sie verwenden,
benachrichtigt werden
28

Anscheinend use strictsollte (muss) verwendet werden, wenn Sie Perl zwingen möchten, richtig zu codieren, was dazu führen kann, dass die Deklaration erzwungen wird, explizit auf Zeichenfolgen und Unterzeichen, dh Barwords, Bezug genommen wird oder Refs mit Vorsicht verwendet werden. Hinweis: Wenn Fehler auftreten, bricht die Verwendung von strict die Ausführung ab, wenn sie verwendet wird.

Während use warnings;Sie Tippfehler im Programm finden können, als hätten Sie ein Semikolon verpasst, haben Sie 'elseif' und nicht 'elsif' verwendet. Sie verwenden jedoch eine veraltete Syntax oder Funktion, wie auch immer. Hinweis: Verwenden Sie Warnungen, um nur Warnungen bereitzustellen und die Ausführung fortzusetzen, dh die Ausführung wird nicht abgebrochen.

Wie auch immer, es wäre besser, wenn wir auf Details eingehen, die ich unten spezifiziere

Von perl.com (mein Favorit):

benutze strenge 'vars';

Dies bedeutet, dass Sie Variablen immer deklarieren müssen, bevor Sie sie verwenden.

Wenn Sie nicht deklarieren, erhalten Sie wahrscheinlich eine Fehlermeldung für die nicht deklarierte Variable

Das globale Symbol "$ variablename" erfordert einen expliziten Paketnamen in Zeile 3 von scriptname.pl

Diese Warnung bedeutet, dass Perl nicht genau weiß, welchen Umfang die Variable hat. Sie müssen Ihre Variablen also explizit angeben, dh sie mit deklarieren, mydamit sie auf den aktuellen Block beschränkt sind, oder mit ihrem vollständig qualifizierten Namen auf sie verweisen (z. B. $ MAIN :: Variablenname).

Daher wird ein Fehler bei der Kompilierung ausgelöst, wenn Sie versuchen, auf eine Variable zuzugreifen, die mindestens eines der folgenden Kriterien nicht erfüllt:

  • Vordefiniert von Perl selbst wie @ARGV,% ENV und allen globalen Interpunktionsvariablen wie $. oder $ _.

  • Erklärt mit unserem (für ein globales) oder meinem (für ein lexikalisches).

  • Aus einem anderen Paket importiert. (Die Verwendung vars pragma fälscht einen Import, aber verwenden Sie stattdessen unsere.)

  • Vollständig qualifiziert mit seinem Paketnamen und dem Doppelpunkt-Pakettrennzeichen.

benutze strenge 'subs';

Betrachten Sie zwei Programme

# prog 1
   $a = test_value;
   print "First program: ", $a, "\n";
   sub test_value { return "test passed"; }
 Output: First program's result: test_value

# prog 2
   sub test_value { return "test passed"; }
   $a = test_value;
   print "Second program: ", $a, "\n";
 Output: Second program's result: test passed

In beiden Fällen haben wir ein test_value () -Unter und möchten das Ergebnis in $ a setzen. Wenn wir jedoch die beiden Programme ausführen, erhalten wir zwei unterschiedliche Ergebnisse:

Im ersten Programm $a = test_value;kennt Perl an dem Punkt, an dem wir ankommen, kein test_value () -Unter, und test_value wird als Zeichenfolge 'test_value' interpretiert. Im zweiten Programm steht die Definition von test_value () vor der $a = test_value;Zeile. Perl denkt test_value als Unteraufruf.

Der Fachbegriff für isolierte Wörter wie test_value, die je nach Kontext Unter- und Zeichenfolgen sein können, ist übrigens Barwort . Perls Umgang mit Barwörtern kann verwirrend sein und Programmfehler verursachen.

Der Fehler ist der, auf den wir in unserem ersten Programm gestoßen sind. Denken Sie daran, dass Perl sich nicht darauf freut, ihn zu finden test_value(). Da test_value () noch nicht gesehen wurde, wird davon ausgegangen, dass Sie einen String möchten. Wenn Sie use strict subs;dies tun , wird dieses Programm mit einem Fehler sterben:

Barwort "test_value" nicht zulässig, solange "strenge Subs" in Zeile 3 von ./a6-strictsubs.pl verwendet werden.

Die Lösung für diesen Fehler wäre
1. Verwenden Sie Klammern, um zu verdeutlichen, dass Sie ein Sub aufrufen. Wenn Perl $ a = test_value (); sieht,
2. Deklarieren Sie Ihr Sub, bevor Sie es zum ersten Mal verwenden

use strict;
sub test_value;  # Declares that there's a test_value() coming later ...
my $a = test_value;  # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }

3. Und wenn Sie es als Zeichenfolge verwenden möchten, zitieren Sie es.

Aufgrund dieser Einschränkung behandelt Perl alle Barwörter als Syntaxfehler. * Ein Barwort ist ein bloßer Name oder eine Kennung, für die keine andere Interpretation durch den Kontext erzwungen wird. (Der Kontext wird häufig durch ein nahe gelegenes Schlüsselwort oder Token oder durch eine Vordeklaration des betreffenden Wortes erzwungen.) * Wenn Sie es also als Zeichenfolge verwenden möchten, zitieren Sie es und wenn Sie es als Funktionsaufruf verwenden möchten, deklarieren Sie es oder verwenden Sie Klammern.

Barwörter sind wegen dieses unvorhersehbaren Verhaltens gefährlich. use strict; (or use strict 'subs';)macht sie vorhersehbar, da Barewords, die in Zukunft seltsames Verhalten verursachen könnten, Ihr Programm sterben lassen, bevor sie Chaos anrichten können

Es gibt einen Ort, an dem es in Ordnung ist, Barewords zu verwenden, selbst wenn Sie strenge Subs aktiviert haben: wenn Sie Hash-Schlüssel zuweisen.

$hash{sample} = 6;   # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );

Barwörter in Hash-Schlüsseln werden immer als Zeichenfolgen interpretiert, sodass keine Mehrdeutigkeit besteht.

benutze strenge 'refs';

Dies erzeugt einen Laufzeitfehler, wenn Sie absichtlich oder auf andere Weise symbolische Referenzen verwenden. Ein Wert, der keine feste Referenz ist, wird dann als symbolische Referenz behandelt . Das heißt, die Referenz wird als Zeichenfolge interpretiert, die den Namen einer globalen Variablen darstellt.

use strict 'refs';

$ref = \$foo;       # Store "real" (hard) reference.
print $$ref;        # Dereferencing is ok.

$ref = "foo";       # Store name of global (package) variable.
print $$ref;        # WRONG, run-time error under strict refs.

Warnungen verwenden;

Dieses Pragma mit lexikalischem Gültigkeitsbereich ermöglicht eine flexible Steuerung der integrierten Warnungen von Perl, sowohl der vom Compiler als auch des Laufzeitsystems.

Von perldiag:

Die meisten Warnmeldungen aus den folgenden Klassifikationen, dh W, D & S, können mithilfe des warningsPragmas gesteuert werden .

(W) Eine Warnung (optional)
(D) Eine Abwertung (standardmäßig aktiviert)
(S) Eine schwerwiegende Warnung (standardmäßig aktiviert)

Ich habe einige Warnmeldungen aufgelistet, die häufig unten durch Klassifizierungen auftreten. Detaillierte Informationen zu ihnen und anderen Nachrichten finden Sie unter perldiag

(W) Eine Warnung (optional):

Fehlendes Argument in% s
Fehlendes Argument für -% c
(Meinten Sie stattdessen &% s?)
(Meinten Sie "lokal" anstelle von "unser"?)
(Meinten Sie $ oder @ anstelle von%?)
'% S. 'ist keine Code-Referenzlänge
(), die für% s
falsch platzierte _ in Nummer verwendet wird

(D) Eine Verwerfung (standardmäßig aktiviert):

defined (@array) ist veraltet
definiert (% hash) ist veraltet Die
veraltete Verwendung von my () in der falschen Bedingung
$ # wird nicht mehr unterstützt

(S) Eine schwerwiegende Warnung (standardmäßig aktiviert)

elseif sollte elsif
% s gefunden werden, wo der Operator erwartet wurde
(Fehlender Operator vor% s?)
(Fehlendes Semikolon in der vorherigen Zeile?)
% s nie eingeführt
Operator oder Semikolon fehlen vor% s
Vorrangproblem: offen% s sollte offen sein (% s)
Nicht übereinstimmende Prototypen:% s vs% s
Warnung: Die Verwendung von "% s" ohne Klammern ist nicht eindeutig.
% S:% s kann nicht geöffnet werden

Ikegami
quelle
10

Diese beiden Pragmas können Fehler in Ihrem Code automatisch identifizieren.

Ich benutze dies immer in meinem Code:

use strict;
use warnings FATAL => 'all';

FATALLässt den Code bei Warnungen sterben, genau wie dies der strictFall ist.

Weitere Informationen finden Sie unter: Strengere Verwendung von Warnungen FATAL => 'all';

Auch ... Die Strikturen laut Seuss

Werkzeug
quelle
Eigentlich müssen Sie die FATAL => "all"Kassenlaufzeit verzögern , indem $SIG{__WARN__} = sub { croak "fatalized warning @_" };Sie den Compiler zuweisen oder vermasseln, um Ihnen zu sagen, was er braucht.
Tchrist
6
@tchrist: Das hat bei mir immer so funktioniert wie es ist und wie dokumentiert. Wenn Sie einen Fall gefunden haben, in dem es nicht wie dokumentiert funktioniert, patchen Sie die Dokumentation mit perlbug.
Toolic
9

Es gibt einen guten Thread über Perlmonks zu dieser Frage.

Der Hauptgrund ist offensichtlich, dass strenge und Warnungen Ihnen massiv helfen, Fehler zu erkennen und das Debuggen zu unterstützen.

Moodywoody
quelle
3

Quelle :: Verschiedene Blogs

Mit use werden Funktionen und Variablennamen in den Hauptnamespace exportiert, indem die Funktion import () der Module aufgerufen wird.

Ein Pragma ist ein Modul, das einen Aspekt der Kompilierungszeit oder des Laufzeitverhaltens von Perl beeinflusst. Pragmas geben dem Compiler Hinweise.

Warnungen verwenden - Perl-Beschwerden über Variablen, die nur einmal verwendet werden, falsche Konvertierung von Zeichenfolgen in Zahlen. Versuch, in Dateien zu schreiben, die nicht geöffnet sind. Dies geschieht zur Kompilierungszeit. Wird zur Steuerung von Warnungen verwendet.

Verwenden Sie den Gültigkeitsbereich strict - deklarieren Sie den Variablenbereich. Es wird verwendet, um eine Art Disziplin im Skript festzulegen. Wenn Barwörter im Code verwendet werden, werden sie interpretiert. Alle Variablen sollten einen Gültigkeitsbereich haben, wie z. B. my, our oder local.

Rahul Reddy
quelle
1

Die Direktive "use strict" weist Perl an, während der Kompilierung Ihres Codes zusätzliche Überprüfungen durchzuführen. Durch die Verwendung dieser Anweisung sparen Sie Zeit beim Debuggen Ihres Perl-Codes, da häufig auftretende Codierungsfehler gefunden werden, die Sie sonst möglicherweise übersehen.

MikasaAckerman
quelle
0

Strenge und Warnungen stellen sicher, dass Ihre Variablen nicht global sind.

Es ist viel übersichtlicher, Variablen zu haben, die für einzelne Methoden eindeutig sind, anstatt jeden einzelnen Variablennamen im Auge zu behalten.

$ _ oder keine Variable für bestimmte Funktionen kann auch nützlich sein, um kompakteren Code schneller zu schreiben.

Wenn Sie jedoch keine strengen Warnungen und Warnungen verwenden, wird $ _ global!

Andreas Ährlund
quelle
0
use strict;
use warnings;

Streng und Warnungen sind der Modus für das Perl-Programm. Es ermöglicht dem Benutzer, den Code großzügiger und darüber hinaus einzugeben. Der Perl-Code sieht formal aus und sein Codierungsstandard ist wirksam.

Warnungen bedeutet dasselbe wie -w in der Perl-Shebang-Zeile. Sie erhalten also die vom Perl-Programm generierten Warnungen und werden im Terminal angezeigt

Dhana Govindarajan
quelle