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

时间:2019-11-29 15:38:18

标签: perl import module require

Having just figured out this,我想知道-M将如何处理附加到软件包名称的终端::

$ perl -MFoo:: -e1

我得到的是...

  

Foo/.pm中找不到@INC(您可能需要安装Foo::模块)(@INC包含:[...])。

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

$ mkdir Foo;
$ echo "package Foo {  sub k { die 42 }  }; 1;" > Foo/.pm
$ PERL5LIB=. perl -MFoo:: -e'Foo::->k'

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

使用这种模式,我可以做到

Foo/.pm         # package Foo
Foo/Bar/.pm     # package Foo::Bar
Foo/Bar/Baz/.pm # package Foo::Bar::Baz;

那我就可以做

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;

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

的好处
  1. 让我所有的班级都措手不及。
  2. use和调用之间添加一致性。

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

2 个答案:

答案 0 :(得分:8)

  

使用惯例是否是mod ::;决定支持mod / .pm吗?

否。

在接受::时,解析器过于宽松,让您做一些荒唐的事情。

$ 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.

使用非规范形式会导致问题。

$ 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.

类似地,不应将use Foo::Bar::加载Foo/Bar/.pm作为有意的,受支持的功能。

  

以前有没有人想到过这个很棒的主意?

那实际上是一团糟。

对于初学者,您将不得不使用use Foo::Bar::;而不是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::;'

$

但是仅使用use Foo::Bar::;是不够的,因为从未调用过import。 package指令需要与要调用的package Foo::Bar::的文件名(import)匹配,这意味着您还必须调整对该软件包的合格引用。

$ 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.

简单地说,这是不可取的。

即使您的模块目前没有import方法,这种方法也可能会发生变化,并且具有两种不同且不兼容的加载模块约定很有害。


  

此行为来自何处

虽然表达式Foo::Bar::生成字符串Foo::Bar,但是use不使用表达式。

此外,文字会传递到程序包名称到文件名音译的实现中,不执行完整性检查。 Perl仅执行等效于调用以下子项的操作:

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

答案 1 :(得分:1)

此约定的一个次要缺点是,它打破了Renderer2.appendChildconst arrayFullOfPromises = []; arrayFullOfPromises.push(mongooseModelA.find({_id: aId}).exec()); arrayFullOfPromises.push(mongooseModelB.find({_id: bId}).exec()); Promise.all(arrayFullOfPromises).then(results => console.log(results)); 中的先前假设。因此没有终端Foo/Bar.pm的{​​{1}}语句不起作用,

Foo/Bar.pm

因此use语法与已经起作用的::代码兼容。更改模块的位置会破坏与较旧的mkdir Foo mkdir Foo/Bar echo "package Foo::Bar { sub baz { } } 1" > Foo/Bar/.pm # Dies can't resolve to file, PERL5LIB=. perl -MFoo::Bar -e1 Can't locate Foo/Bar.pm in @INC ... # Works fine. PERL5LIB=. perl -MFoo::Bar:: -e1 语句的兼容性(因此也必须对其进行更新)。