【问题标题】:In Perl, why do I need Exporter?在 Perl 中,为什么我需要 Exporter?
【发布时间】:2016-07-05 02:26:41
【问题描述】:

我的perl\lib 文件夹中有一个名为 hsfSubs.pm 的模块。我在模块中什么都没有,只有子例程和最后的1;

例如,一个子例程被命名为pause。我没有实施任何导入或导出例程。

在我的主程序中,我只是说use hsfSubs;,然后我可以毫无问题地调用pause。如果我说use hsfSubs qw(pause);,也是如此。

为什么我需要使用 Exporter、@EXPORT@EXPORT_OK 等或任何其他复杂功能?

Stack Overflow 上关于 Exporter 的问题的多个答案告诉了如何使用它,但我不明白为什么要使用它。

【问题讨论】:

    标签: perl module perl-exporter


    【解决方案1】:

    简短的版本是你想要一个模块,但你最终得到了this 所谓的库。这些不好,因为它们污染了调用者的命名空间(这会导致很多问题)。但更关键的是,使用requireuse(与do 相反)加载它们是错误的。

    如果它被正确地编写为模块,您的示例将无法运行。 Exporter 是解决这个问题的方法。


    让我们深入了解细节。

    就像我说的,你的模块有问题。正如您所注意到的,尽管存在错误,它有时也能正常工作。

    $ cat Buggy.pm
    sub test { "ok!" }
    1;
    
    $ perl -e'use Buggy; CORE::say(test());'
    ok!
    

    但这只是因为你的例子太简单了。让我们添加一个正确编写的[1] 模块。

    $ cat Buggy.pm
    sub test { "ok!" }
    1;
    
    $ cat Other.pm
    package Other;
    use Buggy;
    1;
    
    $ perl -e'use Other; use Buggy; CORE::say(test());'
    Undefined subroutine &main::test called at -e line 1.
    

    您的模块中的错误是它没有package 指令。使用userequire 加载的模块必须始终使用package 指令。但是一旦你添加了它,你的模块就会停止工作。

    $ cat NotBuggy.pm
    package NotBuggy;
    sub test { "ok!" }
    1;
    
    $ perl -e'use NotBuggy; CORE::say(test());'
    Undefined subroutine &main::test called at -e line 1.
    

    Exporter 就是用来解决这个问题的。

    $ cat Final.pm
    package Final;
    use Exporter qw( import );
    our @EXPORT = qw( test );
    sub test { "ok!" }
    1;
    
    $ perl -e'use Final; CORE::say(test());'
    ok!
    

    1. 嗯,不是真的。如果编写得当,它将包括使用use strict; use warnings 'all';。总是包括那个!此处省略以保持视觉上的简单性。

    【讨论】:

    • 谢谢。我看到了区别。但“图书馆”确实是我想要的。我可能想要一个模块的唯一原因是如果没有其他方法可以获取库。说如果我写得好它就行不通,这有点奇怪。哈哈。我想“污染”在旁观者的脑海中。我不认为访问我自己的子程序是一种污染。不必要的复杂性就是污染。
    • 污染不是想要的东西的存在;这是不需要的东西的存在。问题是您不仅可以访问要导出的子程序,还可以访问模块内部的子程序。它是全局变量的子等价物。编程就是限制范围,与您所说的完全相反。使所有内容都全局化会使事情变得更难阅读、调试、维护等等。不,这不是风格问题。 20 年前,当 Perl 添加对命名空间支持的支持时,所有 Perl 程序员都停止使用这些“库”。
    • 长话短说,划分代码需要一些额外的代码,但这会使程序不那么复杂。
    • 也许你应该包括为什么你的第二个例子停止工作。当使用userequire 时,Perl 只加载文件一次。它跟踪它加载的内容(在%INC 中)。因为没有命名空间,所以 subs 被放入首先加载的当前命名空间。如果您尝试再次加载它,它将忽略它并仅再次运行import,但由于没有要导入的内容,因此没有任何反应。然后你的新当前命名空间(在这种情况下为main)没有 sub,并且出现 undefined 错误。
    • @PerlDog;这是很多额外的打字!无论您使用@EXPORT 还是@EXPORT_OK,您始终可以在 use 行中明确记录您将从每个模块中使用的功能,无论模块中的所有子模块是否已导入:use Foo qw(bar baz);。只需跳到脚本的顶部,然后搜索有问题的函数。此外,许多编辑器/IDE 允许您“跟进”子组件的实际定义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 2012-05-21
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多