为什么必须在use语句中指定函数名?

时间:2016-08-09 23:35:52

标签: function perl perl-module

perl中,有时需要在use语句中指定函数名称。

例如:

use Data::DPath ('dpath');

会有效但

use Data::DPath;

不会。

其他模块不需要指定的函数名称,例如:

use WWW::Mechanize;

为什么?

2 个答案:

答案 0 :(得分:9)

每个模块默认选择导出的功能。有些人默认选择导出 no 功能,你必须要求它们。有一些很好的理由要做到这一点,还有一个不好的理由。

如果你是WWW::Mechanize之类的课程,那么你就不需要导出任何功能。一切都是类或对象方法。 my $mech = WWW::Mechanize->new

如果您是strict之类的编译指示,那么就没有函数或方法,只需加载即可完成其工作。

默认情况下,某些模块导出太多功能。一个例子是Test::Deep,它导出......

  

所有数组array_each arrayelementsonly arraylength arraylengthonly bag blessed bool cmp_bag cmp_deeply cmp_methods cmp_set code eq_deeply hash   hash_each hashkeys hashkeysonly忽略Isa isa listmethods方法noclass   none noneof num obj_isa re reftype regexpmatches regexponly regexpref   regexprefonly scalarrefonly scalref set shallow str subbagof subhashof   超级超级超级使用类超级包的子集

当另一个模块尝试导出相同的函数或者编写具有相同名称的函数时,问题就出现了。然后他们发生冲突,你会收到神秘的警告。

$ cat ~/tmp/test.plx
use Test::Deep;
use List::Util qw(all);

$ perl -w ~/tmp/test.plx
Subroutine main::all redefined at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66.
 at /Users/schwern/tmp/test.plx line 2.
Prototype mismatch: sub main::all: none vs (&@) at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66.
 at /Users/schwern/tmp/test.plx line 2.

因此,不鼓励输出大量功能。例如,the Exporter documentation advises ...

  

不要导出方法名称!

     

默认情况下,请勿在没有充分理由的情况下导出任何其他内容!

     

导出会污染模块用户的命名空间。如果必须导出尝试使用@EXPORT_OK而不是@EXPORT,并避免使用短名称或常用符号名称来降低名称冲突的风险。

不幸的是,有些模块太过分了。 Data::DPath就是一个很好的例子。它有一个非常清晰的主函数dpath(),默认情况下它应该导出。否则它基本没用。

您始终可以使用use Some::Module ();关闭导出。

答案 1 :(得分:1)

原因是某些模块只包含其中的函数,默认情况下它们可能已经或可能没有选择导出它们,这意味着它们可能需要由脚本显式导入才能直接访问或使用完全限定的名称访问它们。例如:

example.com/dir/file.php/file.php/file.php/+...+file.php ad nauseam.

# in some script
use SomeModule;
# ...
SomeModule::some_function(...);

如果模块不打算以面向对象的方式使用,即没有定义类,并且use SomeModule ('some_function'); # ... some_function(...); 之类的行不起作用,则可能出现这种情况。

如果模块已在my $obj = SomeModule->new()数组中定义了内容,则表示客户端代码只有在"请求它时才能访问它,而不是"自动" #34;当它实际出现在EXPORT_OK数组中时。

某些模块会通过EXPORT数组自动导出其内容。 This questionExporter docs有更详细的信息。

如果您实际上没有发布MCVE,很难知道您在@EXPORT模块中做了什么,可能允许您导入所有内容而不使用{{1} }和Funcs.pm数组。也许你没有在你的模块中包含EXPORT行,正如@JonathanLeffler在评论中所建议的那样。也许你做了别的事。 Perl是其中一种语言,人们为TMTOWTDI咒语感到自豪,经常是有害/适得其反的水平,恕我直言。

你提出的第二个例子非常不同而且相当简单。当你有类似的东西时:

EXPORT_OK

您只需实例化package Funcs;类型的对象并在其上调用名为use WWW::Mechanize; my $mech = new WWW::Mechanize; $mech->get("http://www.google.com"); 的实例方法。没有必要导入对象的方法,因为这些方法是对象本身的一部分。希望采用OOP方法的模块并不意味着可以输出任何东西。他们处于不同的情况。