Skip to content

Instantly share code, notes, and snippets.

@belden
Created February 12, 2015 16:07
Show Gist options
  • Select an option

  • Save belden/acab0f2ecb293fae1c6c to your computer and use it in GitHub Desktop.

Select an option

Save belden/acab0f2ecb293fae1c6c to your computer and use it in GitHub Desktop.
Make all your modules deadly
use strict;
use warnings;
package Deathly::Hallows;
# Add a hook to force `use warnings (FATAL => 'all');` at the head of
# all Adama modules.
#
# 'perldoc -f require' will tell you about adding coderef hooks to @INC.
#
# Note that this toy module doesn't keep itself at the head of @INC, which
# makes it unsuitable for real-world debugging. (Modules may 'use lib ...' or
# 'unshift @INC, qw(...)' which would move \&Deathly::Hallows::INC off the
# head of @INC. See https://metacpan.org/source/BELDEN/Array-Sticky-0.01/lib/Array/Sticky/INC.pm
# for a module that fixes that problem.
sub BEGIN {
unshift @INC, \&Deathly::Hallows::INC;
}
sub Deathly::Hallows::INC {
my ($c, $filename) = @_;
# find file somewhere else in @INC, or give up and let perl take over
my ($match) = grep { -f "$_/$filename" } grep { "$_" ne "$c" } @INC;
return () unless $match;
# slurp the module into an array
open my $fh, '<', "$match/$filename" or die "read $match/$filename $!\n";
my @contents = (<$fh>);
close $fh;
# add whatever we want to the head of this module
if ($filename =~ /Adama/) {
unshift @contents, (
"use warnings (FATAL => 'all');\n",
);
}
# return a generator function to that produces the source for our module
return sub {
$_ = shift @contents;
return defined $_;
};
}
1;
@belden
Copy link
Author

belden commented Feb 12, 2015

Jay Hannah asks what the difference is between this module and use autodie. There's quite a big difference, actually.

use autodie lexically replaces core functions with versions that automatically terminate program execution ("die") when they encounter a failure. A failure at the core-function level generally means "the system" is not set up as the programmer expects.[1]

Deathly::Hallows seeks to elevate all warnings to exceptions. Warnings are generated by mistakes the developer has made in programming; making them exceptions gets the programmer's attention immediately.

[1]: For example, a program that reads a file might look like this:

open my $fh, '<', '/some/file' or die "/some/file: $!\n";
print while (<$fh>);

Here, the programmer is defensibly guarding against the circumstance where /some/file does not exist on the system. The defense is simply to terminate the program's execution. With use autodie, the above code looks like this:

use autodie qw(open);
open my $fh, '<', '/some/file';
print while (<$fh>);

The pay-off of use autodie comes when the programmer needs to open another file: now there's no need to add the redundant stanza or die "...$!\n" to the code.

If the programmer were to write code that generates a warning:

use autodie qw(open);
my $filename = '/some/file';
my $filename = '/some/file';    # perl warns that $filename has already been declared
open my $fh, '<', $filename;
print while (<$fh>);

but which executes properly, then autodie will not be helpful in identifying that $filename has been declared twice in the same scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment