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.
8 Comments
You might prefer using .proverc config file instead of an alias for this.
good point!
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. =)
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.
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?
True, but it's almost certainly a bug, even if it doesn't cause problems without import.
Another reason why mac sucks :)
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.