Created
February 12, 2015 16:07
-
-
Save belden/acab0f2ecb293fae1c6c to your computer and use it in GitHub Desktop.
Make all your modules deadly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Jay Hannah asks what the difference is between this module and
use autodie. There's quite a big difference, actually.use autodielexically 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::Hallowsseeks 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:
Here, the programmer is defensibly guarding against the circumstance where
/some/filedoes not exist on the system. The defense is simply to terminate the program's execution. Withuse autodie, the above code looks like this:The pay-off of
use autodiecomes when the programmer needs to open another file: now there's no need to add the redundant stanzaor die "...$!\n"to the code.If the programmer were to write code that generates a warning:
but which executes properly, then
autodiewill not be helpful in identifying that$filenamehas been declared twice in the same scope.