Why I sometimes hate require

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.

This entry was posted in perl programming and tagged , , . Bookmark the permalink. Both comments and trackbacks are currently closed.

8 Comments

  1. Erik
    Posted February 22, 2013 at 6:09 am | Permalink

    You might prefer using .proverc config file instead of an alias for this.

  2. Posted February 25, 2013 at 10:51 am | Permalink

    I'd endorse 'use strict' learning how to croak when a case mismatch is detected, backward compatibility be damned.

    Also, 'Mooselike' is probably a better capitalization than 'MooseLike' anyway, because it's something with the quality of Meese, not something that likes Meese. =)

    • Posted February 25, 2013 at 11:17 am | Permalink

      I actually think it should be a warning from the core 'requires' function for any operating system known to have a case-insensitive but case-preserving default filesystem.

      • Posted February 25, 2013 at 11:24 am | Permalink

        Well, 'require' itself doesn't really cause any problems when the case is mismatched, does it? It's more the mismatch of 'require' and 'import' semantics, triggered by 'use', right?

  3. Posted February 25, 2013 at 11:47 am | Permalink

    True, but it's almost certainly a bug, even if it doesn't cause problems without import.

  4. Alex
    Posted February 28, 2013 at 2:52 pm | Permalink

    Another reason why mac sucks :)

  5. Kris Shannon
    Posted March 1, 2013 at 4:26 am | Permalink

    This is why I've always used the case-sensitive version of HFS+; many years ago when I first did that quite a lot of stuff would break - these days my only two problems are Valve's Steam and Oracle's VirtualBox.

© 2009-2014 David Golden All Rights Reserved