What does "use strict;" in Perl do?

What does use strict; in Perl really get you? By default three things, which can be specified separately or turned off separately:

# All on by default when using use strict;
use strict "vars";
use strict "subs";
use strict "refs";

# One or more can be turned off if need be
no strict "subs";

use strict "vars";

This part of strict helps you avoid scoping issues, misspelled variable names and is probably the thing you think of when you use strict;.

If a variable is not explicitely declared or fully qualified you'll recieve a compile time error:

Variable "$var" is not imported at vars.pl line XX.
Global symbol "$var" requires explicit package name at vars.pl line XX.
Execution of vars.pl aborted due to compilation errors

The following script demonstrates what use strict "vars"; requires:

#!/usr/bin/perl

use strict "vars";

# Can't get away with this anymore:
# $var = 'value';

# You'll need to fully qualify ALL your variables:
$main::foo = "fully qualified in default package\n";
$bar::foo  = "fully qualified in 'bar' package\n";

print $main::foo;
print $bar::foo;

# or declare the variable within it's desired scope:
my $local = "top level variable\n"; # our, state, use vars
                                    # would also work but
                                    # are subtly different
{
        my $local = "second level variable\n";
        print $local;
}
print $local;

Which outputs:

fully qualified in default package
fully qualified in 'bar' package
second level variable
top level variable

The exceptions to this rule are the $a and $b variables used by the sort() function if you are defining your own comparison in a block or subroutine.

use strict "subs";

This prevents you from leaving barewords lying around your script. If Perl expects a key for a hash, or a filehandle you can still get away with it but overall you can't simply put plain text in your script unless it's quoted, etc.

The following script shows what's possible before use strict "subs"; and after:

#!/usr/bin/perl

# scalar $foo is now "shazam"
my $foo = shazam;
print $foo . "\n";

sub shazam {
    return "abracadabra";
}
# shazam is now a function in main
# it's run and its output used to set $foo: "abracadabra"
my $bar = shazam;
print $bar . "\n";

# Start over in a new package, this time using strict subs
package strict;
use strict "subs";

# This no longer works
# my $foo = shazam;
# print $foo . "\n";

# now that shazam has been defined in package 'strict'
# we can use it as a bareword to set $foo: "hocus pocus"
sub shazam {
    return "hocus pocus";
}
my $bar = shazam;
print $bar . "\n";

# but isn't this a lot less confusing:
package readable;
sub shazam {
    return "alakazam";
}
my $foo = &shazam; # clearly a call to a subroutine!
print $foo . "\n";

And it presents you with the following output:

shazam
abracadabra
hocus pocus
alakazam

With use strict "subs"; you'll see this error if you do leave a bareword in the wrong place:

Bareword "shazam" not allowed while "strict subs" in use at subs.pl line XX.
Execution of subs.pl aborted due to compilation errors.

use strict "refs";

If you think of Perl variables like a filesystem then use strict "refs"; forces you to use only hard references not soft references (Perl gurus don't like using the term symlink or symbolic reference). All Perl variables are objects in this filesystem, and references are hard references(links) to those files -- they increment the reference count and when all of them are gone the object can be cleaned up.

Soft references, which use strict "refs"; disallows, would be like a symlink, it's not a reference to the object but rather the name of where you can find a hard reference to an object.

The following script demonstrates what use strict "refs"; prevents you from doing, and what it still allows:

#!/usr/bin/perl

# Deferencing a scalar that is not a reference
my $foo = "alpha\n";
my $ref = \$foo . ""; # reference is now considered
                      # a string $ref is now a
                      # "soft reference"
print "string representation of ref:\t" . $ref . "\n";
# This "works" -- but not output
print "dereference of string ref:\t" . $$ref . "\n";

my $file = "STDOUT";
# works kinda how you would expect
# prints output to STDOUT as specified by a
# string scalar - a "soft reference"
print $file "using a reference to our FH:\tbaker\n";

package strict;
use strict 'refs';

# This is what use strict 'refs'; wants you to do
my $foo = "charlie\n";
my $ref = \$foo;     # scalar $ref is a
                     # reference to scalar $foo
print "derefence a ref to a scalar:\t" . $$ref;

# However, there's an exception:
sub refme {
        return "delta\n";
}
# make a soft reference to the refme subroutine
my $subref = \&{"refme"};
# and this still works event with use strict "refs";
print "soft reference to a subroutine:\t" . &$subref;

Which produces the following output:

string representation of ref:   SCALAR(0x24a7b10)
dereference of string ref:
using a reference to our FH:    baker
derefence a ref to a scalar:    charlie
soft reference to a subroutine: delta

Trying to use a soft reference with use strict "refs"; enabled generates this kind of error message:

Can't use string ("STDOUT") as a symbol ref while "strict refs" in use at refs.pl line XX.