Setting global variable defaults (perl)

From Devpit
Jump to: navigation, search

Try running this, and also try it with perl -c:

#!/usr/bin/perl
use strict;
use warnings;
# From http://perldoc.perl.org/perlmod.html#BEGIN%2c-UNITCHECK%2c-CHECK%2c-INIT-and-END
            print "10. Ordinary code runs at runtime.\n";
END {       print "16.   So this is the end of the tale.\n" }
INIT {      print " 7. INIT blocks run FIFO just before runtime.\n" }
UNITCHECK { print " 4.   And therefore before any CHECK blocks.\n" }
CHECK {     print " 6.   So this is the sixth line.\n" }
            print "11.   It runs in order, of course.\n";
BEGIN {     print " 1. BEGIN blocks run FIFO during compilation.\n" }
END {       print "15.   Read perlmod for the rest of the story.\n" }
CHECK {     print " 5. CHECK blocks run LIFO after all compilation.\n" }
INIT {      print " 8.   Run this again, using Perl's -c switch.\n" }
            print "12.   This is anti-obfuscated code.\n";
END {       print "14. END blocks run LIFO at quitting time.\n" }
BEGIN {     print " 2.   So this line comes out second.\n" }
UNITCHECK { print " 3. UNITCHECK blocks run LIFO after each file is compiled.\n" }
INIT {      print " 9.   You'll see the difference right away.\n" }
            print "13.   It merely _looks_ like it should be confusing.\n";
__END__

Note which run with -c and which don't. Also note that the UNITCHECK seems be new in Perl 5.9, so just delete those lines in older versions. The rest work since at least 5.6.1.

Anyway, the point is, here's a nice way to initialize global variables.

sub some_function_that_caches_things {
        our $cache;
        INIT { $cache = {}; }
        # Now assign things to $cache or whatever.
}

or

our $config;
INIT {
        $config = {
                "username" => $ENV{"USER"},
        };
}

This has some advantages over using an if-defined-assign-default check:

  • It happens before any other code. Let's say for example that you're exporting a config variable for another module to tweak. You can initialize the variable's default value before any other module's code has a chance to change it, regardless of what order modules are "use"d in. (Unless of course, the other module uses an INIT, CHECK, or BEGIN block to set the variable, but that would be explicitly asking for trouble.)
  • It doesn't make it so that you can't use undef to mean other things.
  • You don't execute the if-defined check on every iteration, which can be more efficient, although this is typically an unmeasurable difference.

See Also