Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Use strict warnings and diagnostics

by tachyon (Chancellor)
on Jun 13, 2001 at 02:42 UTC ( [id://87956]=perlmeditation: print w/replies, xml ) Need Help??

Alternate title: Read this if you want to cut your development time in half!

This is the brutally edited executive summary. The full version of this tutorial with extended discussion and examples is available at Use strict warnings and diagnostics or die

Perl has three pragmas specifically designed to make your life easier:

use strict;
use warnings;
use diagnostics;

The benefits of using these far outweigh the short learning curve. Once you get in the habit of using these pragmas you will find Perl isolates many problems automatically for you and can reduce development time by half or more (given that most of the time spent developing code is spent debugging).

So let's get down to it!

Bondage and discipline - use strict;

To activate the strict pragma we add the line use strict; just below the shebang line.
#!/usr/bin/perl
use strict;

By far the most useful thing use strict does is make you declare your variables. With use strict Perl complains if you try to use a variable that you have not previously declared.

$foo = 'bar'; 	# OK

use strict;
$foo = 'bar'; 	# Triggers an error

Fantastic you say, my simple program is now broken, and for what. For your sanity that's why. Consider this slightly longer (silly) example that counts down from ten then calls a sub liftoff. The liftoff sub is designed to count the number of liftoffs:

$count = 10;
while ($count > 0) {
    print "$count ";
    $count--;
    liftoff() if $count == 0;
}

sub liftoff {
    $count++; # count liftoffs
    print "This is liftoff $count\n";
}

Perfectly valid code, but if these two snippets were separated by other code the fact that this is an infinite loop might be harder to spot, especially without the print statements. The problem occurs because of the global variable $count, which is changed within the liftoff sub. As a result the while loop never exits, and repeatedly calls the liftoff sub. Whilst this is very simplified the fact is that common variables like $count, $line, $data, $i, $j etc are often used many times within a program. If we do not localise them to where they are used some very nasty bugs can arise. These bugs can often be hard to find.

You declare your variables under strict using the my keyword. The localisation (lexical scope) of a variable declared via my is most simply explained by example:

my $count = 10;
print "$count\n"; 	# $count is 10 here

{
    my $count = 5;
    print "$count\n";   # $count is 5 here 
}

print "$count\n"; 	# $count is 10 here again

In this example we have a $count with a wide scope and another *different* $count with a narrow scope. The narrow scope of one of the $count variables extends from the first opening curly before the my declaration to the corresponding closing curly. Talk about have your cake and eat it to!

For an extensive expert discussion of localising (scoping) variables see Coping with Scoping and Seven Useful Uses of Local by Mark-Jason Dominus.

Another reason to declare variables is tpyos. Consider this snippet of code:

use strict;
my $input_recieved = <STDIN>;
print $input_received;

See the error. Perl does. Because of the mis-spelling of received perl complains that we are using a variable we have not declared. This is very, very useful.

Baby help me please - the use warnings pragma

You activate the use warnings pragma with the "-w" flag like this:

#!/usr/bin/perl -w

Unlike strict when perl generates warnings it does not abort running your code, but it can fill up your screen :-) Here is a simple example of how warnings can *really* help:

$input_received = <STDIN>;
exit if $input_recieved =~ m/exit/i;
print "Looks like you want to continue!\n";

Three lines - what could be easier. We get some input from STDIN and exit if the user types exit. Otherwise we print something. When we run the code we find that regardless of what we type it prints. Why no exit?? If we had added the "-w" flag then perl would have told us:

Name "main::input_received" used only once: possible typo at test.pl line 3.
Name "main::input_recieved" used only once: possible typo at test.pl line 4.
test.pl syntax OK

So we have a syntax error, fix that and we are off and running. If we were using strict the code would not have run in the first place but that's another story. Typos like this can be hard for humans to spot but perl does it in a jiffy.

Use of a what in a where like how? - use diagnostics

When you first start to use warnings some of the messages appear quite cryptic. Don't worry, the "use diagnostics;" pragma has been designed to help. When this is active the warnings generated by "-w" are expanded greatly. All that happens is that Perl automatically looks up the warning in perlman:perldiag and gives you the full version. Save you from looking it up yourself! You will probably only need to use diagnostics for a few weeks as you soon become familiar with all the messages!

To finish off, here is another example:

#!/usr/bin/perl -w
use strict;
use diagnostics;

my @stuff = qw(1 2 3 4 5 6 7 8 9 10);
print "@stuff" unless $stuff[10] == 5;

If you run this code without warnings it runs OK, but does it? Sure it prints the array but there is a subtle problem. $stuff[10] does not exist! Perl is creating it for us on the fly. Use warnings catches this subtle trap and if we add the use diagnostics; pragma we will get a blow by blow description of our sins.

Use of uninitialized value in numeric eq (==) at test.pl line 4 (#1)
    
    (W uninitialized) An undefined value was used as if it were already
    defined.  It was interpreted as a "" or a 0, but maybe it was a mistake.
    To suppress this warning assign a defined value to your variables.

If you have reached here you are already well on the road to Perl nirvana. I hope you enjoy the journey.

tachyon

Credits

Lexicon, dragonchild, pmas, mpolo

Replies are listed 'Best First'.
Re: Use strict warnings and diagnostics
by chipmunk (Parson) on Jun 18, 2001 at 06:58 UTC
    How about adding an explanation about how the diagnostics pragma works? It simply looks up error messages in perldiag and includes the descriptions in the error output.

    I think it will be useful for Perl programmers to know that there is a whole document that lists all of Perl's error messages (not to mention a few error messages from other sources), and that error messages can be looked up there when one doesn't use diagnostics.

Re: Use strict warnings and diagnostics
by John M. Dlugosz (Monsignor) on Jun 13, 2001 at 22:41 UTC
    The section on the warnings pragma says it is enabled with -w. It never mentions the newer "use warnings;" form, although it is used that way in the intro.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://87956]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2024-03-28 14:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found