Perché utilizzare rigorose e avvertenze?


104

Mi sembra che molte delle domande nel tag Perl potrebbero essere risolte se le persone usassero:

use strict;
use warnings;

Penso che alcune persone li considerino simili a ruote di addestramento o complicazioni inutili, il che chiaramente non è vero, dal momento che anche programmatori Perl molto abili li usano.

Sembra che la maggior parte delle persone esperte di Perl usino sempre questi due pragmi, mentre coloro che trarrebbero maggior beneficio dall'usarli raramente lo fanno. Quindi, ho pensato che sarebbe stata una buona idea avere una domanda a cui collegarsi quando si incoraggiano le persone a use stricte warnings.

Allora, perché dovrebbe uno sviluppatore Perl use stricte warnings?


14
Mi chiedo sempre per cose come questa perché non lo rendono solo l'impostazione predefinita e lo sviluppatore deve effettivamente allentare attivamente le cose, dov'è iluse loose;
Paul Tyng

12
Come molte cose interessanti e utili Perl è iniziato come un hack, come uno strumento per il ragazzo che lo inventa. Successivamente è diventato più popolare e un numero crescente di persone non qualificate ha iniziato a usarlo. Questo è il momento in cui inizi a pensare che qualcosa del genere use strictfosse una buona idea, ma la retrocompatibilità è già diventata un vero problema per te :-(
Daniel Böhmer

14
@JB Nizet, @Paul T., In realtà, use strict;è attivo per impostazione predefinita quando richiedi il linguaggio Perl 5.12 (o superiore). Prova perl -e"use v5.012; $x=123;". no strict;in realtà lo spegne.
ikegami

1
Anche se alla fine il tuo punto è vero, più volte lo diciamo, forse più persone ascolteranno. Ultimamente c'è stato un brontolio nel tentativo di rendere disponibili tutorial Perl più / migliori / moderni e di certo ci saranno avvertimenti severi in cima a ciascuno di questi. Per il mio ho intenzione di avere s / w in cima a ogni frammento, solo in modo che tutti i neofiti lo vedano ogni volta
Joel Berger

5
@ JoelBerger No, in realtà non è per niente del genere. Proprio come ho detto, ha solo parole simili nel titolo. È per compatibilità con le versioni precedenti. è la prima frase nella risposta accettata, come proponi che si applichi alla mia domanda?
TLP

Risposte:


83

Per cominciare, use strict;(e in misura minore,use warnings; ) aiuta a trovare errori di battitura nei nomi delle variabili. Anche i programmatori esperti commettono errori del genere. Un caso comune è dimenticare di rinominare un'istanza di una variabile durante la pulizia o il refactoring del codice.

L'utilizzo use strict; use warnings;rileva molti errori prima di quanto verrebbero rilevati altrimenti, il che rende più facile trovare le cause alla radice degli errori. La causa principale potrebbe essere la necessità di un errore o di un controllo di convalida e ciò può accadere indipendentemente dall'abilità del programmatore.

La cosa positiva degli avvisi Perl è che raramente sono falsi, quindi non c'è quasi nessun costo per usarli.


Lettura correlata: Perché usare my?


2
@ TLP, non ho intenzione di fare uno studio per quantificare quanto aiuta. Basti dire che aiutano incondizionatamente.
ikegami

1
Perché è reso opzionale se ha così tanti vantaggi? Perché non abilitarlo di default (come qualcuno ha commentato sopra)? È per motivi di compatibilità?
Jean

4
@ Jean, retrocompatibilità. Notare che use strict;è abilitato per impostazione predefinita se si utilizza la versione 5.12 o successiva della lingua ( use 5.012;).
ikegami

@Jean, se stai scrivendo un semplice script, non vuoi essere avvisato da avvisi sui nomi dei gestori di file o per non aver dichiarato la variabile prima di usarli :-)
user2676847

28

Apparentemente use strictdovrebbe (deve) essere usato quando si vuole forzare perl a codificare correttamente, cosa che potrebbe forzare la dichiarazione, essere esplicita su stringhe e sottotitoli, cioè bareword o usare refs con cautela. Nota: se ci sono errori, use strict interromperà l'esecuzione se utilizzato.

Anche se use warnings;ti aiuterà a trovare errori di battitura nel programma come se avessi perso un punto e virgola, hai usato "elseif" e non "elsif", stai usando una sintassi o una funzione deprecata, qualunque cosa del genere. Nota: l'uso degli avvisi fornirà solo avvisi e continuerà l'esecuzione, ovvero non interromperà l'esecuzione.

Comunque, sarebbe meglio se entrassimo nei dettagli, che sto specificando di seguito

Da perl.com (il mio preferito):

utilizzare "vars" rigorosi;

il che significa che devi sempre dichiarare le variabili prima di usarle.

Se non dichiari, probabilmente riceverai un messaggio di errore per la variabile non dichiarata

Il simbolo globale "$ variablename" richiede un nome di pacchetto esplicito in nomescript.pl riga 3

Questo avviso significa che Perl non è esattamente chiaro su quale sia l'ambito della variabile. Quindi devi essere esplicito riguardo alle tue variabili, il che significa dichiararle conmy modo che siano limitate al blocco corrente, o fare riferimento ad esse con il loro nome completo (ad esempio: $ MAIN :: variablename).

Pertanto, viene attivato un errore in fase di compilazione se si tenta di accedere a una variabile che non ha soddisfatto almeno uno dei seguenti criteri:

  • Predefinito da Perl stesso, come @ARGV,% ENV e tutte le variabili di punteggiatura globali come $. o $ _.

  • Dichiarato con our (per un globale) o mio (per un lessicale).

  • Importato da un altro pacchetto. (L'uso vars pragma falsifica un'importazione, ma usa il nostro invece.)

  • Completamente qualificato utilizzando il nome del pacchetto e il separatore di pacchetto con due punti.

utilizzare "sottotitoli" rigorosi;

Considera due programmi

# 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 entrambi i casi abbiamo un sub test_value () e vogliamo mettere il suo risultato in $ a. Eppure, quando eseguiamo i due programmi, otteniamo due risultati diversi:

Nel primo programma, al punto in cui arriviamo $a = test_value;, Perl non conosce alcun sub test_value (), e test_value è interpretato come stringa "test_value". Nel secondo programma, la definizione di test_value () viene prima della $a = test_value;riga. Perl pensa che test_value sia una chiamata secondaria.

Il termine tecnico per parole isolate come test_value che potrebbero essere sottotitoli e potrebbero essere stringhe a seconda del contesto, tra l'altro, è bareword . La gestione delle bareword da parte di Perl può creare confusione e può causare bug nel programma.

Il bug è quello che abbiamo incontrato nel nostro primo programma, ricordate che Perl non aspetterà di trovarlo test_value(), quindi poiché non ha già visto test_value (), presume che vogliate una stringa. Quindi, se tu use strict subs;, causerà la morte di questo programma con un errore:

Bareword "test_value" non è consentito mentre "strict subs" è in uso in ./a6-strictsubs.pl riga 3.

La soluzione a questo errore sarebbe
1. Usa le parentesi per chiarire che stai chiamando un sub. Se Perl vede $ a = test_value () ;,
2. Dichiara il tuo sub prima di usarlo per la prima volta

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. E se intendi usarlo come una stringa, citalo.

Quindi, questa limitazione fa sì che Perl tratti tutte le bareword come errori di sintassi. * Una parola nuda nuda è qualsiasi nome o identificatore semplice che non ha altre interpretazioni forzate dal contesto. (Il contesto è spesso forzato da una parola chiave o da un token nelle vicinanze, o dalla predichiarazione della parola in questione.) * Quindi se intendi usarlo come una stringa, citalo e se intendi usarlo come chiamata di funzione, dichiaralo in anticipo o usa le parentesi.

Le parole nude sono pericolose a causa di questo comportamento imprevedibile. use strict; (or use strict 'subs';)li rende prevedibili, perché le parole semplici che potrebbero causare strani comportamenti in futuro faranno morire il tuo programma prima che possano provocare il caos

C'è un posto in cui è OK usare bareword anche quando hai attivato sottotitoli rigorosi: quando assegni le chiavi hash.

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

Le parole nude nelle chiavi hash vengono sempre interpretate come stringhe, quindi non c'è ambiguità.

usa "refs" rigorosi;

Ciò genera un errore di runtime se si utilizzano riferimenti simbolici, intenzionalmente o in altro modo. Un valore che non è un riferimento reale viene quindi trattato come un riferimento simbolico . Cioè, il riferimento viene interpretato come una stringa che rappresenta il nome di una variabile globale.

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.

utilizzare avvertenze;

Questo pragma con ambito lessicale consente un controllo flessibile sugli avvertimenti incorporati di Perl, sia quelli emessi dal compilatore che quelli dal sistema run-time.

Da perldiag:

Quindi la maggior parte dei messaggi di avviso dalle classificazioni seguenti, ad esempio W, D e S, possono essere controllati utilizzando il warningspragma.

(W) Un avviso (opzionale)
(D) Un deprecazione (abilitato per impostazione predefinita)
(S) Un avviso grave (abilitato per impostazione predefinita)

Ho elencato alcuni dei messaggi di avviso che spesso si verificano di seguito in base alle classificazioni. Per informazioni dettagliate su di essi e altri messaggi fare riferimento a perldiag

(W) Un avvertimento (opzionale):

Argomento mancante in% s
Argomento mancante su -% c
(Intendevi invece &% s?)
(Intendevi "locale" invece di "nostro"?)
(Intendevi $ o @ invece di%?)
'% S 'non è una
lunghezza di riferimento del codice () usata su% s
Misplaced _ in number

(D) Una deprecazione (abilitata per impostazione predefinita):

definito (@array) è deprecato
definito (% hash) è deprecato L'
uso deprecato di my () in condizioni false
$ # non è più supportato

(S) Un avviso grave (abilitato per impostazione predefinita)

elseif dovrebbe essere elsif
% s trovato dove l'operatore previsto
(Operatore mancante prima di% s?)
(Punto e virgola mancante sulla riga precedente?)
% s mai introdotto
Operatore o punto e virgola mancante prima di% s
Problema di precedenza: open% s dovrebbe essere aperto (% s)
Mancata corrispondenza del prototipo:% s vs% s
Avviso: l'uso di "% s" senza parentesi è ambiguo
Impossibile aprire% s:% s


10

Questi due pragmi possono identificare automaticamente i bug nel codice.

Lo uso sempre nel mio codice:

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

FATALfa morire il codice sugli avvisi, proprio come strictfa.

Per ulteriori informazioni, vedere: Diventa più severo con gli avvisi di utilizzo FATAL => 'all';

Inoltre ... Le critiche, secondo Seuss


In realtà, devi ritardare il FATAL => "all"tempo di esecuzione della cassa, assegnando a $SIG{__WARN__} = sub { croak "fatalized warning @_" };oppure rovini il compilatore cercando di dirti di cosa ha bisogno.
Cristo

6
@tchrist: questo ha sempre funzionato per me così com'è e come documentato. Se hai trovato un caso in cui non funziona come documentato, applica una patch alla documentazione usando perlbug.
toolic


3

Fonte :: diversi blog

Use esporterà funzioni e nomi di variabili nello spazio dei nomi principale chiamando la funzione import () dei moduli.

Un pragma è un modulo che influenza alcuni aspetti del tempo di compilazione o il comportamento in fase di esecuzione di perl.Pragmas dà suggerimenti al compilatore.

Use warnings - Perl reclami sulle variabili usate solo una volta, conversioni improprie di stringhe in numeri, .Tentando di scrivere su file che non sono aperti .s accade in fase di compilazione. Viene usato per controllare gli avvertimenti.

Usa rigoroso: dichiara l'ambito delle variabili. Viene utilizzato per impostare una sorta di disciplina nello script. Se nel codice vengono utilizzate parole semplici, queste vengono interpretate. A tutte le variabili dovrebbe essere assegnato un ambito, come my, our o local.


1

La direttiva "use strict" dice a Perl di eseguire controlli extra durante la compilazione del codice. L'uso di questa direttiva ti farà risparmiare tempo nel debugging del tuo codice Perl perché trova bug di codifica comuni che potresti trascurare altrimenti.


0

Rigidi e avvisi assicurano che le tue variabili non siano globali.

È molto più ordinato essere in grado di avere variabili univoche per i singoli metodi piuttosto che dover tenere traccia di ogni nome di variabile.

$ _, o nessuna variabile per certe funzioni, può anche essere utile per scrivere codice più compatto più velocemente.

Tuttavia, se non usi strict e warnings, $ _ diventa globale!


0
use strict;
use warnings;

Rigoroso e avvertenze sono le modalità del programma perl. Permette all'utente di inserire il codice in modo più libero e, soprattutto, quel codice perl avrà un aspetto formale e il suo standard di codifica sarà efficace.

warnings ha lo stesso significato -wdella riga perl shebang, quindi ti fornirà gli avvisi generati dal programma perl, verranno visualizzati nel terminale

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.