Po co stosować ścisłe i ostrzeżenia?

104

Wydaje mi się, że wiele pytań w tagu Perla można by rozwiązać, gdyby ludzie użyli:

use strict;
use warnings;

Myślę, że niektórzy uważają, że są one podobne do kółek treningowych lub niepotrzebnych komplikacji, co jest oczywiście nieprawdą, ponieważ używają ich nawet bardzo utalentowani programiści Perla.

Wydaje się, że większość ludzi biegle posługujących się Perlem zawsze używa tych dwóch pragm, podczas gdy ci, którzy najbardziej skorzystaliby na ich stosowaniu, rzadko to robią. Pomyślałem więc, że dobrym pomysłem byłoby mieć pytanie, do którego można by się odnieść, zachęcając ludzi do use stricti warnings.

Dlaczego więc programista Perl use stricti warnings?

TLP
źródło
14
Zawsze zastanawiam się na rzeczy, jak to, dlaczego nie tylko sprawiają, że domyślne i mieć dev rzeczywiście aktywnie poluzować rzeczy, gdzie jestuse loose;
Paul Tyng
12
Podobnie jak wiele fajnych i przydatnych rzeczy, Perl zaczynał jako hack, jako narzędzie dla faceta, który go wymyśla. Później stał się bardziej popularny i coraz więcej osób niewykwalifikowanych zaczęło z niego korzystać. Wtedy zaczynasz myśleć, że coś takiego use strictbyło dobrym pomysłem, ale kompatybilność wsteczna już stała się dla ciebie prawdziwym problemem :-(
Daniel Böhmer
14
@JB Nizet, @Paul T., Właściwie, use strict;jest domyślnie włączone, gdy zażądasz języka Perl 5.12 (lub nowszego). Spróbuj perl -e"use v5.012; $x=123;". no strict;faktycznie go wyłącza.
ikegami
1
Chociaż ostatecznie twój punkt widzenia jest prawdziwy, im więcej razy to mówimy, może tym więcej ludzi usłyszy. Ostatnio pojawiły się zamieszanie związane z próbami udostępnienia większej liczby / lepszych / nowoczesnych samouczków Perla i na pewno surowe / ostrzeżenia będą na szczycie każdego z nich. Dla mnie planuję umieścić s / w na górze każdego fragmentu, tak aby wszyscy nowicjusze widzieli go za każdym razem
Joel Berger,
5
@JoelBerger Nie, właściwie to nic takiego. Tak jak powiedziałem, ma tylko podobne słowa w tytule. To dla wstecznej kompatybilności. jest pierwsze zdanie w zaakceptowanej odpowiedzi, jak proponujecie, aby odnosiło się to do mojego pytania?
TLP

Odpowiedzi:

83

Na początek use strict;(i w mniejszym stopniu use warnings;) pomaga znaleźć literówki w nazwach zmiennych. Nawet doświadczeni programiści popełniają takie błędy. Typowym przypadkiem jest zapomnienie o zmianie nazwy wystąpienia zmiennej podczas czyszczenia lub refaktoryzacji kodu.

Użycie pozwala use strict; use warnings;wychwycić wiele błędów wcześniej, niż zostałyby one wykryte w innym przypadku, co ułatwia znalezienie pierwotnych przyczyn błędów. Główną przyczyną może być potrzeba błędu lub sprawdzenia poprawności, a to może się zdarzyć niezależnie od umiejętności programisty.

Zaletą ostrzeżeń Perla jest to, że rzadko są one fałszywe, więc ich używanie jest praktycznie bezpłatne.


Powiązana lektura: Dlaczego warto używać my?

ikegami
źródło
2
@ TLP, nie mam zamiaru przeprowadzać badań, aby określić, ile to pomaga. Wystarczy powiedzieć, że pomagają bezwarunkowo.
ikegami
1
Dlaczego więc jest opcjonalny, skoro ma tak wiele zalet? Dlaczego nie włączyć go domyślnie (jak ktoś skomentowany powyżej)? Czy to ze względu na kompatybilność?
Jean
4
@Jean, wsteczna kompatybilność. Zauważ, że use strict;jest to domyślnie włączone, jeśli używasz wersji 5.12 lub nowszej języka ( use 5.012;).
ikegami
@Jean Jeśli piszesz prosty skrypt, naprawdę nie chcesz otrzymywać ostrzeżeń o nazwach
programów
28

Najwyraźniej use strictpowinno (musi) być używane, gdy chcesz zmusić perl do poprawnego kodowania, co może wymuszać deklarację, być jawnym na łańcuchach i subskrybowanych, tj. Gołych słowach lub używać referencji z ostrożnością. Uwaga: jeśli wystąpią błędy, użyj opcji strict, jeśli zostanie użyta, przerwie wykonywanie.

Chociaż use warnings;pomoże ci znaleźć błędy w pisaniu w programie, takie jak pominięcie średnika, użyłeś „elseif”, a nie „elsif”, używasz przestarzałej składni lub funkcji, cokolwiek takiego. Uwaga: ostrzeżenia o używaniu będą tylko zapewniać ostrzeżenia i kontynuować wykonywanie, tj. Nie przerywają wykonywania.

W każdym razie byłoby lepiej, gdybyśmy zagłębili się w szczegóły, które określam poniżej

Z perl.com (mój ulubiony):

używaj ścisłych „vars”;

co oznacza, że ​​zawsze musisz zadeklarować zmienne przed ich użyciem.

Jeśli nie zadeklarujesz, prawdopodobnie otrzymasz komunikat o błędzie dla niezadeklarowanej zmiennej

Globalny symbol "$ variableblename" wymaga wyraźnej nazwy pakietu w linii 3 scriptname.pl

To ostrzeżenie oznacza, że ​​Perl nie jest dokładnie pewien, jaki jest zakres zmiennej. Musisz więc wyraźnie określać swoje zmienne, co oznacza albo deklarowanie ich za pomocą, myaby były ograniczone do bieżącego bloku, albo odwoływanie się do nich z ich w pełni kwalifikowaną nazwą (na przykład: $ MAIN :: zmienna nazwa).

Tak więc błąd kompilacji jest wyzwalany, jeśli spróbujesz uzyskać dostęp do zmiennej, która nie spełnia co najmniej jednego z poniższych kryteriów:

  • Predefiniowane przez samego Perla, takie jak @ARGV,% ENV i wszystkie globalne zmienne interpunkcyjne, takie jak $. lub $ _.

  • Zadeklarowane z naszym (dla globalnego) lub my (dla leksykalu).

  • Zaimportowano z innego pakietu. (Polecenie use vars pragma udaje import, ale zamiast tego użyj naszego).

  • W pełni kwalifikowany przy użyciu nazwy pakietu i separatora pakietu z podwójnym dwukropkiem.

użyj ścisłych „sub”;

Rozważ dwa programy

# 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

W obu przypadkach mamy sub test_value () i chcemy umieścić jego wynik w $ a. A jednak po uruchomieniu tych dwóch programów otrzymujemy dwa różne wyniki:

W pierwszym programie, w punkcie, do którego docieramy $a = test_value;, Perl nie wie o żadnej funkcji test_value (), a test_value jest interpretowana jako łańcuch „test_value”. W drugim programie definicja test_value () znajduje się przed $a = test_value;linią. Perl uważa test_value za wywołanie podrzędne.

Nawiasem mówiąc, termin techniczny dla izolowanych słów, takich jak test_value, które mogą być znakami zastępczymi i łańcuchami w zależności od kontekstu, to zwykłe słowo . Obsługa zwykłych słów w Perlu może być myląca i może spowodować błąd w programie.

Błąd jest tym, co napotkaliśmy w naszym pierwszym programie, pamiętaj, że Perl nie będzie czekał na znalezienie test_value(), więc ponieważ nie widział jeszcze test_value (), zakłada, że ​​chcesz napisać. Więc jeśli tak use strict subs;, spowoduje to śmierć tego programu z błędem:

Zwykłe słowo „test_value” jest niedozwolone, gdy używane są „ścisłe subskrybcje” w ./a6-strictsubs.pl wiersz 3.

Rozwiązaniem tego błędu byłoby
1. Użyj nawiasów, aby wyraźnie zaznaczyć, że dzwonisz do subskrybenta. Jeśli Perl widzi $ a = test_value () ;,
2. Zadeklaruj sub przed pierwszym użyciem

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. A jeśli masz zamiar użyć tego jako ciągu, zacytuj go.

Tak więc to ograniczenie sprawia, że ​​Perl traktuje wszystkie zwykłe słowa jako błędy składniowe. * Samo słowo to dowolna nazwa lub identyfikator, które nie mają innej interpretacji narzuconej przez kontekst. (Kontekst jest często wymuszany przez pobliskie słowo kluczowe lub token, lub przez deklarację danego słowa.) * Więc jeśli masz zamiar użyć go jako ciągu, zacytuj go, a jeśli chcesz użyć go jako wywołania funkcji, zadeklaruj go wcześniej lub użyj nawiasów.

Samotne słowa są niebezpieczne z powodu tego nieprzewidywalnego zachowania. use strict; (or use strict 'subs';)sprawia, że ​​są przewidywalne, ponieważ zwykłe słowa, które mogą powodować dziwne zachowanie w przyszłości, spowodują, że Twój program umrze, zanim zdążą siać spustoszenie

Jest jedno miejsce, w którym można używać zwykłych słów, nawet po włączeniu ścisłych subskrybentów: podczas przypisywania kluczy skrótu.

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

Zwykłe słowa w kluczach skrótu są zawsze interpretowane jako ciągi, więc nie ma niejednoznaczności.

używaj ścisłych „referencji”;

Powoduje to błąd w czasie wykonywania, jeśli celowo lub w inny sposób używasz odwołań symbolicznych. Wartość, która nie jest stałym odniesieniem, jest następnie traktowana jako odniesienie symboliczne . Oznacza to, że odwołanie jest interpretowane jako ciąg reprezentujący nazwę zmiennej globalnej.

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.

używaj ostrzeżeń;

Ta pragma o zasięgu leksykalnym pozwala na elastyczną kontrolę nad wbudowanymi ostrzeżeniami Perla, zarówno tymi emitowanymi przez kompilator, jak i tymi z systemu czasu wykonywania.

Od perldiag:

Tak więc większość komunikatów ostrzegawczych z poniższych klasyfikacji, tj. W, D i S, można kontrolować za pomocą warningspragmy.

(W) Ostrzeżenie (opcjonalne)
(D) Wycofanie (domyślnie włączone)
(S) Poważne ostrzeżenie (domyślnie włączone)

Wymieniłem kilka komunikatów ostrzegawczych, które często pojawiają się poniżej, według klasyfikacji. Szczegółowe informacje o nich i innych wiadomościach znajdziesz w perldiag

(W) Ostrzeżenie (opcjonalnie):

Brakuje argumentu w% s
Missing argument -% c
(? Czy chodziło &% s zamiast)
(? Czy chodziło Ci o "lokalny" zamiast "nasz")
(Czy chodziło Ci o $ lub @ zamiast%?)
„% S 'nie jest
długością odniesienia kodu () używaną w% s
błędnie umieszczonym _ w numerze

(D) Wycofanie (domyślnie włączone):

zdefiniowana (@array) jest przestarzała
zdefiniowana (% hash) jest przestarzała
odrzuconej przetwarzanie moich () w fałszywym warunkowego
$ # nie jest już obsługiwany

(S) Poważne ostrzeżenie (domyślnie włączone)

elseif powinno być elsif
% s znaleziono tam, gdzie oczekiwano operatora
(Brak operatora przed% s?)
(Brak średnika w poprzednim wierszu?)
% s nigdy nie wprowadzono
Operator lub średnik brak przed% s
Problem z pierwszeństwem: otwórz% s powinno być otwarte (% s)
Niezgodność prototypu:% s vs% s
Ostrzeżenie: użycie „% s” bez nawiasów jest niejednoznaczne
Nie można otworzyć% s:% s

ikegami
źródło
10

Te dwie pragmy mogą automatycznie identyfikować błędy w kodzie.

Zawsze używam tego w moim kodzie:

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

FATALsprawia, że ​​kod umiera po ostrzeżeniach, tak jak to strictrobi.

Aby uzyskać dodatkowe informacje, zobacz: Bardziej restrykcyjne dzięki ostrzeżeniom dotyczącym użytkowania FATAL => 'all';

Poza tym ... Zaostrzenia, według Seussa

narzędzie
źródło
Właściwie musisz opóźnić FATAL => "all"czas wykonania do momentu, przypisując go $SIG{__WARN__} = sub { croak "fatalized warning @_" };lub spieprzysz kompilator, próbując powiedzieć ci, co musi.
tchrist
6
@tchrist: To zawsze działało dla mnie tak, jak jest i zgodnie z dokumentacją. Jeśli znalazłeś przypadek, w którym nie działa to zgodnie z dokumentacją, popraw dokumentację za pomocą perlbug.
Toolic
9

Jest dobry wątek na temat perlmonków na ten temat.

Podstawowym powodem jest oczywiście to, że restrykcje i ostrzeżenia znacznie pomagają wychwycić błędy i ułatwiają debugowanie.

moodywoody
źródło
3

Źródło :: Różne blogi

Użycie spowoduje wyeksportowanie funkcji i nazw zmiennych do głównej przestrzeni nazw przez wywołanie funkcji import () modułu.

Pragma to moduł, który wpływa na pewien aspekt czasu kompilacji lub zachowanie perl w czasie wykonywania. Pragmy dają wskazówki kompilatorowi.

Użyj ostrzeżeń - perl narzeka na zmienne użyte tylko raz, niewłaściwa konwersja łańcuchów na liczby, Próba zapisu do plików, które nie są otwierane, zdarza się w czasie kompilacji, służy do kontrolowania ostrzeżeń.

Użyj ścisłego - deklaruj zakres zmiennych. Służy do ustalenia jakiejś dyscypliny w skrypcie. Jeśli w kodzie są używane gołe słowa, są one interpretowane. Wszystkim zmiennym należy nadać zakres, jak my, nasze lub lokalne.

Rahul Reddy
źródło
1

Dyrektywa "użyj ścisłego" mówi Perlowi, aby sprawdzał dodatkowo podczas kompilacji twojego kodu. Użycie tej dyrektywy pozwoli zaoszczędzić czas podczas debugowania kodu Perla, ponieważ znajduje ona typowe błędy w kodowaniu, które w przeciwnym razie można by przeoczyć.

Mikasa Ackerman
źródło
0

Ścisłe i ostrzeżenia zapewniają, że zmienne nie są globalne.

Znacznie lepiej jest mieć zmienne unikalne dla poszczególnych metod, zamiast śledzić każdą nazwę zmiennej.

$ _ lub brak zmiennej dla niektórych funkcji może być również przydatna do szybszego pisania bardziej zwartego kodu.

Jeśli jednak nie użyjesz ścisłych i ostrzeżeń, $ _ stanie się globalne!

Andreas Ęhrlund
źródło
0
use strict;
use warnings;

Ścisły i ostrzeżenia to tryb działania programu Perl. Pozwala użytkownikowi na bardziej swobodne wprowadzanie kodu, a co więcej, kod Perla będzie wyglądał formalnie, a jego standard kodowania będzie skuteczny.

ostrzeżenia oznacza to samo co -ww linii perl shebang, więc dostarczy ostrzeżenia wygenerowane przez program w perlu, wyświetli się w terminalu

dhana govindarajan
źródło