Por que usar estrito e avisos?

104

Parece-me que muitas das questões na tag Perl poderiam ser resolvidas se as pessoas usassem:

use strict;
use warnings;

Acho que algumas pessoas consideram isso como rodinhas de treinamento, ou complicações desnecessárias, o que claramente não é verdade, já que até programadores Perl muito habilidosos as usam.

Parece que a maioria das pessoas que são proficientes em Perl sempre usa esses dois pragmas, enquanto aqueles que mais se beneficiariam com eles raramente o fazem. Então, achei que seria uma boa ideia ter uma pergunta para vincular ao incentivar as pessoas a use stricte warnings.

Então, por que um desenvolvedor Perl use stricte warnings?

TLP
fonte
14
Eu sempre me pergunto por que coisas como essa não tornam isso o padrão e fazem com que o desenvolvedor tenha que soltar as coisas ativamente, onde está ouse loose;
Paul Tyng
12
Como muitas coisas legais e úteis, Perl começou como um hack, uma ferramenta para o cara que o inventa. Mais tarde, tornou-se mais popular e um número crescente de pessoas não qualificadas começou a usá-lo. É aí que você começa a pensar que algo como use strictuma boa ideia, mas a compatibilidade com versões anteriores já se tornou um problema real para você :-(
Daniel Böhmer
14
@JB Nizet, @Paul T., Na verdade, use strict;está ativado por padrão quando você solicita o idioma Perl 5.12 (ou superior). Experimente perl -e"use v5.012; $x=123;". no strict;realmente desliga.
ikegami
1
Embora no final o seu ponto seja verdadeiro, quanto mais vezes o dissermos, talvez mais pessoas ouçam. Ultimamente tem havido alguns rumores de tentar fazer mais / melhores / modernos tutoriais Perl disponíveis e certamente estrito / avisos estarão no topo de cada um deles. Para o meu, pretendo ter s / w no topo de cada trecho, apenas para que todos os novatos vejam sempre
Joel Berger
5
@JoelBerger Não, na verdade não é nada parecido. Como eu disse, só tem palavras semelhantes no título. É para compatibilidade com versões anteriores. é a primeira frase na resposta aceita, como você propõe que se aplique à minha pergunta?
TLP

Respostas:

83

Para começar, use strict;(e em menor medida, use warnings;) ajuda a encontrar erros de digitação em nomes de variáveis. Até programadores experientes cometem tais erros. Um caso comum é esquecer de renomear uma instância de uma variável ao limpar ou refatorar o código.

O uso use strict; use warnings;captura muitos erros mais cedo do que seriam detectados de outra forma, o que torna mais fácil encontrar a causa raiz dos erros. A causa raiz pode ser a necessidade de um erro ou verificação de validação, e isso pode acontecer independentemente da habilidade do programador.

O que é bom sobre os avisos Perl é que eles raramente são espúrios, então quase não há custo para usá-los.


Leitura relacionada: Por que usar my?

ikegami
fonte
2
@TLP, não vou fazer um estudo para quantificar o quanto isso ajuda. Basta dizer que eles ajudam incondicionalmente.
ikegami
1
Por que é opcional, se tem tantos benefícios? Por que não habilitá-lo por padrão (como alguém comentou acima)? É por razões de compatibilidade?
Jean
4
@Jean, compatibilidade com versões anteriores. Observe que use strict;é habilitado por padrão se você usar a versão 5.12 ou mais recente do idioma ( use 5.012;).
ikegami
@Jean se você está escrevendo um script simples, você realmente não quer ser alertado por avisos sobre nomes de manipuladores de arquivos ou por não declarar a variável antes de usá-los :-)
user2676847
28

Aparentemente, use strictdeve (deve) ser usado quando você deseja forçar o perl a codificar apropriadamente, o que poderia estar forçando uma declaração, sendo explícito em strings e subs, ou seja, barewords ou usando refs com cautela. Nota: se houver erros, usar estrito abortará a execução, se usado.

Embora use warnings;ajude você a encontrar erros de digitação no programa, como você perdeu um ponto-e-vírgula, você usou 'elseif' e não 'elsif', você está usando sintaxe ou função obsoleta, qualquer coisa assim. Nota: use warnings apenas fornecerá avisos e continuará a execução, ou seja, não abortará a execução.

De qualquer forma, seria melhor entrarmos em detalhes, que estou especificando abaixo

De perl.com (meu favorito):

use estrito 'vars';

o que significa que você deve sempre declarar variáveis ​​antes de usá-las.

Se você não declarar irá provavelmente obter uma mensagem de erro para a variável não declarada

O símbolo global "$ variablename" requer um nome de pacote explícito em scriptname.pl linha 3

Este aviso significa que o Perl não é exatamente claro sobre qual é o escopo da variável. Portanto, você precisa ser explícito sobre suas variáveis, o que significa declará-las com de mymodo que elas fiquem restritas ao bloco atual, ou referindo-se a elas com seu nome totalmente qualificado (por exemplo: $ MAIN :: nomedavariável).

Portanto, um erro de tempo de compilação é disparado se você tentar acessar uma variável que não atenda a pelo menos um dos seguintes critérios:

  • Predefinido pelo próprio Perl, como @ARGV,% ENV, e todas as variáveis ​​de pontuação globais como $. ou $ _.

  • Declarado com nosso (para um global) ou meu (para um léxico).

  • Importado de outro pacote. (O uso vars pragma simula uma importação, mas use nosso em vez disso.)

  • Totalmente qualificado usando seu nome de pacote e o separador de pacote de dois pontos duplos.

usar 'subs' estritos;

Considere dois programas

# 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

Em ambos os casos, temos um sub test_value () e queremos colocar seu resultado em $ a. E ainda, quando executamos os dois programas, obtemos dois resultados diferentes:

No primeiro programa, no ponto em que chegamos $a = test_value;, Perl não sabe de nenhum sub test_value (), e test_value é interpretado como string 'test_value'. No segundo programa, a definição de test_value () vem antes da $a = test_value;linha. Perl pensa test_value como sub chamada.

O termo técnico para palavras isoladas como test_value que podem ser subs e podem ser strings dependendo do contexto, a propósito, é bareword . O tratamento de barewords do Perl pode ser confuso e pode causar bug no programa.

O bug é o que encontramos em nosso primeiro programa. Lembre-se de que o Perl não espera encontrar test_value(), portanto, como ainda não viu test_value (), ele assume que você deseja uma string. Então, se você use strict subs;, isso fará com que este programa morra com um erro:

Bareword "test_value" não permitido enquanto "estrito subs" em uso em ./a6-strictsubs.pl linha 3.

A solução para esse erro seria
1. Use parênteses para deixar claro que você está chamando um sub. Se Perl vir $ a = test_value () ;,
2. Declare seu sub antes de usá-lo pela primeira vez

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 você pretende usá-lo como uma string, cite-o.

Portanto, esta restrição faz com que Perl trate todas as barewords como erros de sintaxe. * Uma bareword é qualquer nome ou identificador simples que não tem outra interpretação forçada pelo contexto. (O contexto é frequentemente forçado por uma palavra-chave ou token próximo, ou pela pré-declaração da palavra em questão.) * Então, se você pretende usá-lo como uma string, coloque-o entre aspas e se você pretende usá-lo como uma chamada de função, pré-declare-o ou use parênteses.

Barewords são perigosos por causa desse comportamento imprevisível. use strict; (or use strict 'subs';)os torna previsíveis, porque barewords que podem causar comportamento estranho no futuro farão seu programa morrer antes que possam causar estragos

Há um lugar onde não há problema em usar barewords mesmo quando você ativou subs estritas: quando você está atribuindo chaves hash.

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

Barewords em chaves hash são sempre interpretados como strings, portanto, não há ambigüidade.

use 'refs' estritos;

Isso gera um erro de tempo de execução se você usar referências simbólicas, intencionalmente ou não. Um valor que não é uma referência rígida é então tratado como uma referência simbólica . Ou seja, a referência é interpretada como uma string que representa o nome de uma variável global.

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.

use avisos;

Este pragma com escopo léxico permite controle flexível sobre os avisos internos do Perl, tanto aqueles emitidos pelo compilador quanto aqueles do sistema de tempo de execução.

De perldiag:

Portanto, a maioria das mensagens de advertência das classificações abaixo, ou seja, W, D e S, podem ser controladas usando o warningspragma.

(W) Um aviso (opcional)
(D) Uma depreciação (ativado por padrão)
(S) Um aviso grave (ativado por padrão)

Listei algumas das mensagens de advertência que ocorrem frequentemente abaixo por classificações. Para obter informações detalhadas sobre eles e outras mensagens, consulte perldiag

(W) Um aviso (opcional):

Argumento ausente em% s
Argumento ausente para -% c
(Você quis dizer &% s em vez disso?)
(Você quis dizer "local" em vez de "nosso"?)
(Você quis dizer $ ou @ em vez de%?)
'% S 'não é um
comprimento de referência de código () usado em% s
mal colocado _ no número

(D) Uma suspensão de uso (habilitada por padrão):

definido (@array) está obsoleto
definido (% hash) está obsoleto O
uso obsoleto de my () na condição falsa
$ # não é mais suportado

(S) Um aviso severo (habilitado por padrão)

elseif deveria ser encontrado elsif
% s onde o operador esperava
(operador ausente antes de% s?)
(ponto e vírgula ausente na linha anterior?)
% s nunca introduzido
Operador ou ponto e vírgula ausente antes de% s
Problema de precedência: aberto% s deve estar aberto (% s)
Incompatibilidade de protótipo:% s vs% s
Aviso: o uso de "% s" sem parênteses é ambíguo
Não é possível abrir% s:% s

ikegami
fonte
10

Esses dois pragmas podem identificar automaticamente bugs em seu código.

Eu sempre uso isso em meu código:

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

FATALfaz o código morrer em avisos, assim como strictfaz.

Para obter informações adicionais, consulte: Seja mais estrito com avisos de uso FATAL => 'all';

Além disso ... As restrições, de acordo com Seuss

útil
fonte
Na verdade, você tem que atrasar o FATAL => "all"tempo de execução do till, atribuindo a $SIG{__WARN__} = sub { croak "fatalized warning @_" };ou então você bagunça o compilador tentando dizer o que ele precisa.
cristão
6
@tchrist: Isso sempre funcionou para mim como está e conforme documentado. Se você encontrou um caso em que não funciona conforme documentado, faça o patch da documentação usando perlbug.
toolic
9

um bom tópico sobre perlmonks sobre essa questão.

A razão básica, obviamente, é que avisos estritos e pesados ​​ajudam a detectar erros e ajudam na depuração.

temperamental
fonte
3

Fonte :: Blogs diferentes

Use irá exportar funções e nomes de variáveis ​​para o namespace principal chamando a função import () dos módulos.

Um pragma é um módulo que influencia algum aspecto do tempo de compilação ou comportamento de tempo de execução do perl. Os pragmas fornecem dicas para o compilador.

Use avisos - reclamações perl sobre variáveis ​​usadas apenas uma vez, conversões impróprias de strings em números,. Tentativa de escrever em arquivos que não são abertos. Isso acontece em tempo de compilação. É usado para controlar avisos.

Use estrito - declara o escopo das variáveis. É usado para definir algum tipo de disciplina no script. Se as palavras de barra forem usadas no código, elas serão interpretadas. Todas as variáveis ​​devem ter escopo, como my, our ou local.

Rahul Reddy
fonte
1

A diretiva "use strict" diz ao Perl para fazer verificações extras durante a compilação do seu código. Usar esta diretiva economizará tempo ao depurar seu código Perl porque ela encontra bugs de codificação comuns que você pode ignorar de outra forma.

MikasaAckerman
fonte
0

Restrito e avisos garantem que suas variáveis ​​não sejam globais.

É muito mais simples poder ter variáveis ​​exclusivas para métodos individuais, em vez de ter que acompanhar cada nome de variável.

$ _, ou nenhuma variável para certas funções, também pode ser útil para escrever um código mais compacto mais rápido.

No entanto, se você não usar estrito e avisos, $ _ se tornará global!

Andreas Ährlund
fonte
0
use strict;
use warnings;

Strict e warnings são os modos do programa perl. É permitir que o usuário insira o código de forma mais liberal e mais do que isso, que o código perl parecerá formal e seu padrão de codificação será eficaz.

warnings significa o mesmo que -wna linha perl shebang, então ele irá fornecer a você os avisos gerados pelo programa perl, que serão exibidos no terminal

dhana govindarajan
fonte