Ïðèãëàøàåì ïîñåòèòü
Õëåáíèêîâ (hlebnikov.lit-info.ru)

5.3 use strict in Detail

Previous Table of Contents Next

5.3 use strict in Detail

use strict is actually the same as saying


use strict 'vars';

use strict 'subs';

use strict 'refs';

Each of these statements confers a different benediction. Let's consider each one in detail.

5.3.1 use strict 'vars'

use strict 'vars' forces you to use my. Well, more or less. This is a cunning way of catching typos. use strict 'vars' requires that all variables either be declared with my or that they be fully qualified with their package names (since they must be package variables if they are not declared with my). The two exceptions to this rule are package variables declared with our or named by use vars; they need not be fully qualified.

No, it is not good enough to say, "Okay, I'll use my, just don't make me use strict 'vars'." It's too easy to make a mistake no matter how careful your typing. Suppose you decide that a good way to announce a successful return from a function is:


my $x = func() and print "\$x is true: set to $x\n";

Unfortunately, the $x in the print() is not the same $x declared by my. The scope of the new $x has not yet started (it starts with the following statement). Therefore the $x in the print() is in fact the package variable $x, which may be set to a completely different value or none at all. Only with use strict will you get the error:


Global symbol "$x" requires explicit package name

The scoping becomes clearer when we discover that internally, Perl converted the and to an if. You can see this with the B::Deparse module:


% perl -MO=Deparse -e 'my $x = func() and print $x'

print $x if my $x = func();

That shows us that even within the same statement, the print comes before the my. "But wait," you cry, "isn't the postfixed if exactly equivalent to a real if?" Not in this case. Observe:


% perl -Mstrict -wle 'print $x if my $x = $]'

Global symbol "$x" requires explicit package name at -e line 1.

Execution of -e aborted due to compilation errors.

% perl -Mstrict -wle 'if (my $x = $]) { print $x }'

5.008003

I printed a variable instead of a literal because with a literal, Perl warns about finding an assignment inside a condition. The $] variable contains the version number of the perl program. In order to turn a version number like "5.8.3" into a value that can be compared as a true number, Perl formats it as you see here.

So you should make sure that the use of any lexical variable does not start until at least the statement following its declaration. Perl provides some helpful shortcuts that you might consider to violate this distinction. You can declare a lexical variable in a condition or as a for/foreach loop variable:


if (my ($word) = /(\w+)/) { ... }

for my $person ($db->person_search) { ... }

and Perl will restrict the scope of the lexical to the attached block, as though you had written:


{

  my $word;

  if ($word = /(\w+)/) { ... }

}

{

  my $person;

  for $person ($db->person_search) { ... }

}

In fact, Perl allows you to put my just about anywhere. It's really just a modifier on a variable. For example, if you need to pass a reference to a variable to some function, so that function can write into the variable, you can write:


func(\my $foo);

print "func() set \$foo to $foo\n");

which, bizarre as it might look, works. A realistic use of this feature is in the getopts() function exported by Getopt::Std, which can populate a hash with command-line options if a reference to the hash is passed as the second argument:


use Getopt::Std;

getopts("dif:v", \my %Opt) or die $Usage;

$Opt{f} or die "The -f option is mandatory\n";

Note that subroutines are still package variables. There are no lexical subroutines this side of Perl 6. If you're paranoid about people calling your internal subroutines and want to keep them private, then make them anonymous subroutine references and assign them to lexical variables, like so:


# Before:

sub dumpit

{

  require Data::Dumper;

  print Data::Dumper::Dumper(\@_);

}

# [...]

dumpit(@args);



# After:

my $dumpit = sub { require Data::Dumper;

                   print Data::Dumper::Dumper(\@_)

                 };

# [...]

$dumpit->(@args);

Now nothing outside the lexical scope of $dumpit can get at that subroutine.

5.3.2 use strict 'subs'

This stricture disables the use of barewords as strings. Let's take a deep breath and find out just what Perl thinks our poem-cum-admonishment means:


% perl -MO=Deparse

do you, each reader, accept risks, close calls

and wait until failure

and then; alarm rings and people, listen shocked, horrified

or do you, "use strict" and "use warnings" and sleep soundly;



my main $message; study earnestly while you-can;

do this, cos I, tell you

and you, can be free;

^D

'???';;

do 'you', 'use strict' and 'use warnings' and sleep 'soundly' 

unless alarm 'rings' and '???', listen(shocked, 'horrified');

my $message;

study 'earnestly' while 'you' - 'can';

'???', 'be'->can('free') if do 'this', cos 'I', tell you;

- syntax OK

Explaining why Perl interprets this piece of creative writing this way would be somewhat off topic.[2] Notice instead that many of the words in the input were interpreted as strings, as we see from the quotes that Deparse put around them.

[2] But incidentally, the '???' is Deparse notation for "a string that had a constant value that Perl put somewhere I can't get at."

Now let's see what happens with use strict 'subs':


% perl -Mstrict=subs -c

[...]

^D

Bareword "people" not allowed while "strict subs" in use at - line 4.

Bareword "then" not allowed while "strict subs" in use at - line 1.

Bareword "rings" not allowed while "strict subs" in use at - line 3.

[...]

- had compilation errors.

Just as use strict 'vars' expects variables either to be declared lexical or used fully qualified, use strict 'subs' expects subroutines either to be declared prior to being referenced as barewords, or called using explicit subroutine invocation syntax.

It is not a compilation error to call a subroutine that hasn't been defined. Perl is permissive enough to let you define subroutines at run time, so it's impossible to say at compilation time that a subroutine is missing.

Here are examples of the effect of use strict 'subs'on calling a subroutine with no arguments:


outgrabe;    # ok only if sub outgrabe has already appeared

outgrabe();  # ok

&outgrabe;   # ok

&outgrabe(); # ok

There is no such restriction on method calls; when Perl sees -> followed by an identifier or simple scalar it knows that it must be a method call regardless of whether it has seen its declaration yet or not.

If for some reason you want to call a subroutine without parentheses before Perl has seen its declaration, you can put a forward declaration of that subroutine earlier than the call, like so:


sub outgrabe;   # No code body

# [...]

outgrabe;

Now the Perl compiler knows that outgrabe is a subroutine call. It doesn't need to have seen the code for that subroutine because while it's compiling it just needs to know how to interpret each token it finds in the source. As long as the code for outgrabe exists by the time the Perl run time system reaches the last line everything will be fine.[3]

[3] Provided that, if either the forward declaration or the real declaration of the subroutine uses a subroutine prototype, both use the same prototype.

Alternatively, just as variables can be snuck past use strict 'vars' with use vars, Perl can be persuaded to refrain from complaining about barewords if you claim that they're subroutines-to-be with use subs:


use subs qw(outgrabe);

# [...]

outgrabe;

no strict 'subs'—the opposite of use strict 'subs'—is referred to in Perl as "poetry mode," for reasons that should now be plain. It interprets any bareword that doesn't look like a subroutine call as a string, as though it had quotes around it.

5.3.3 use strict 'refs'

If you're expecting consistency, you've come to the wrong language. strict is billed as a pragma, a module that affects the compilation of a program. But use strict 'refs' takes effect at run time, so we can't say that it prohibits code containing symbolic references; what Perl does instead is to issue a fatal exception when it tries to execute such a reference. However, here's the puzzle: Until Perl 5, symbolic references were the only ways of referring to things indirectly. So why the hard line? Let's look closer.

This question appears on Perl newsgroups so often that it should have its own song: How can I access a variable whose name I have in another variable? The questioner is developing something along the lines of:


my %names_of_badges;  # Keys: badge numbers. Values: names.

my %names_of_users;   # Keys: usernames. Values: names.

print "Lookup by (b)adge or (u)sername? ";

chomp(my $answer = <STDIN>);

my $choice = ($answer =~ /^b/ ? "badges" : "users");

# How do I get at %"names_of_$choice"???

The answer to the question is, "Don't try." The way to do what this code is really attempting to accomplish is either with a hash, a "hard" reference, or both.

The questioner is thinking that having formed a string equal to the name of the hash they want to access, they must have nearly solved the problem. And with a symbolic reference, they would be right. But symbolic references have several problems. One is that they only work on package variables, so there's no way to access the lexical hashes in the example above using symbolic references.

Another, and more important problem is that they're the wrong approach. If you want to get at one of two possible hashes you shouldn't do it using an accessor—in this case, the string containing the hash name—whose possible values span the entire universe of strings. One typo and your program is toast. The proper solution is to make a hard reference to each original hash, so that now you just have to choose between the two references. I'll show examples of this in Section 6.2.13.

So symbolic references are bad, but they were all we had in Perl 4. Now that we no longer need to use them—save for mostly esoteric purposes I'll touch on later—we use strict 'refs' to ensure that we don't put in any by accident. Symbolic references are also used for manipulating the symbol table, and there are better ways to do that if that's what you have in mind.

5.3.4 use strict 'DWIM'

No, there really isn't a pragma to "Do What I Mean" with strictness. But if you put that statement in, Perl will not complain, because it just silently ignores any type of strictness you request that it doesn't know about.[4] It's better to say use strict and get every kind of strictness than to try selectively enabling only the ones you think you need; one day, you, like, I, will type use strict 'sbus' by accident. I'll talk about how to turn off ones that get in your way in Section 5.5.

[4] Unless you're using Perl 5.8.1 or later, wherein this has been fixed.

    Previous Table of Contents Next