Why I sometimes hate require

Reading time: 2 minutes

Can you spot the error in this code?

package Foo;
use strict;
use warnings;

use Moo;
use MooX::Types::Mooselike::Base qw/Num/;

has count => (
    is => 'ro',
    isa => Num,
);

1;

Not yet? Here’s the error I get compiling it:

$ perl -c Foo.pm 
Bareword "Num" not allowed while "strict subs" in use at Foo.pm line 9.
Foo.pm had compilation errors.

What the heck? I imported Num, so why is it not allowed? (Spot the error yet?)

Here’s a hint: I’m using a Mac.

Does this make it clearer:

$ perl -MAcme::require::case -c Foo.pm 
MooX/Types/Mooselike/Base.pm has incorrect case (maybe you want MooX/Types/MooseLike/Base.pm instead?) at Foo.pm line 7.
BEGIN failed--compilation aborted at Foo.pm line 7.

Aha! I said “Mooselike” instead of “MooseLike”. And the Mac OSX filesystem is case insensitive. Here’s what happens internally when I say ‘use MooX::Types::Mooselike::Base qw/Num/;

BEGIN {
    require MooX::Types::Mooselike::Base;
    if ( my $code = MooX::Types::Mooselike::Base->can("import") ) {
        $code->( 'MooX::Types::Mooselike::Base', 'Num' );
    }
}

The standard require call works fine despite the typo because the file system is case insensitive. But the package name is wrong, so the import method is not found and thus not called.

The Acme::require::case module overrides CORE::GLOBAL::require to do a case-sensitive search for the file requested and fail if the name requested differs from the case the file system thinks is correct.

To help me catch these sorts of stupid typo errors, I’ve added it to an alias for prove.

alias prove="PERL5OPT=-MAcme::require::case prove"

I’ll probably add it to my editor’s compiler config as well.

•      •      •

If you enjoyed this or have feedback, please let me know by or