目录/.pm是否曾经是约定,为什么存在?

Eva*_*oll 2 import perl module require

刚弄清楚这一点,我想知道该如何-M处理::贴在程序包名称上的终端,

$ perl -MFoo:: -e1
Run Code Online (Sandbox Code Playgroud)

我得到的是...

无法找到Foo/.pm@INC(你可能需要安装Foo::模块)(@INC包括:[...])。

这似乎表明它不起作用,所以好奇心迫使我....

$ mkdir Foo;
$ echo "package Foo {  sub k { die 42 }  }; 1;" > Foo/.pm
$ PERL5LIB=. perl -MFoo:: -e'Foo::->k'
Run Code Online (Sandbox Code Playgroud)

这确实有效。use mod::;解决这个约定是否mod/.pm受支持?这是古代的遗留物吗?这种行为从何而来?

有了这个模式,我可以做到

Foo/.pm         # package Foo
Foo/Bar/.pm     # package Foo::Bar
Foo/Bar/Baz/.pm # package Foo::Bar::Baz;
Run Code Online (Sandbox Code Playgroud)

那我就可以

use Foo::;            # resolves to Foo/.pm
use Foo::Bar::;       # resolves to Foo/Bar/.pm
use Foo::Bar::Baz::;  # resolves to Foo/Bar/Baz/.pm

Foo::->new;
Foo::Bar::->new;
Foo::Bar::Baz::->new;
Run Code Online (Sandbox Code Playgroud)

我喜欢这样,因为这增加了

  1. 使我所有的课程都空话。
  2. use和调用之间增加一致性。

这种设计是出于意图吗?它记录在任何地方吗?以前有没有人想到过这个好主意?

ike*_*ami 6

Is this convention of use mod::; resolving to mod/.pm supported?

No.

The parser is too liberal when it comes to accepting ::, allowing you do rather absurd things.

$ cat Foo/Bar.pm
package Foo::Bar;
sub import { print "imported.\n"; }
print "loaded.\n";
1

$ perl -I. -e'require Foo::Bar'
loaded.

$ perl -I. -e'require Foo::::::Bar'
loaded.
Run Code Online (Sandbox Code Playgroud)

Using the non-canonical form leads to problems.

$ perl -I. -e'use Foo::Bar; use Foo::Bar; use Foo::Bar;'
loaded.
imported.
imported.
imported.

$ perl -I. -e'use Foo::::::Bar; use Foo::::::Bar; use Foo::Bar;'
loaded.
loaded.
imported.
Run Code Online (Sandbox Code Playgroud)

Similarly, that use Foo::Bar:: loads Foo/Bar/.pm shouldn't be taken as an intentional, supported feature.

Has anyone ever thought of this awesome idea before?

It actually would be a mess.

For starters, you would you have to use use Foo::Bar::; instead of use Foo::Bar;.

$ cat Foo/Bar/.pm
package Foo::Bar;
sub import { print "imported.\n"; }
sub baz { print "ok.\n"; }
1

$ perl -I. -e'use Foo::Bar;'
Can't locate Foo/Bar.pm in @INC ...

$ perl -I. -e'use Foo::Bar::;'

$
Run Code Online (Sandbox Code Playgroud)

But using use Foo::Bar::; isn't enough because import was never called. The package directive would need to match the file name (package Foo::Bar::) for import to be called, which means you'd have to adjust qualified references to the package as well.

$ cat Foo/Bar/.pm
package Foo::Bar::;
sub import { print "imported.\n"; }
sub baz { print "ok.\n"; }
1

$ perl -I. -e'use strict; use Foo::Bar; Foo::Bar::baz();'
Can't locate Foo/Bar.pm in @INC ...
BEGIN failed--compilation aborted at -e line 1.

$ perl -I. -e'use strict; use Foo::Bar::; Foo::Bar::baz();'
imported.
Undefined subroutine &Foo::Bar::baz called at -e line 1.

$ perl -I. -e'use strict; use Foo::Bar::; Foo::Bar::::baz();'
imported.
ok.
Run Code Online (Sandbox Code Playgroud)

To put it lightly, this is undesirable.

Even if your module doesn't have an import method at this time, that could change, and having two different and incompatible conventions for loading modules is hurtful.


Where did this behavior come from

While the expression Foo::Bar:: produces the string Foo::Bar, use doesn't take an expression.

Additionally, the literal is passed to an implementation of package name to file name transliteration that performs no sanity checks. Perl simply performs an operation equivalent to calling the following sub:

 sub pkg_to_qfn { ( $_[0] =~ s{::}{/}gr ) . '.pm' }
Run Code Online (Sandbox Code Playgroud)