【问题标题】:What's the best way to have two modules which use functions from one another in Perl?在 Perl 中让两个模块相互使用函数的最佳方法是什么?
【发布时间】:2009-02-24 03:54:12
【问题描述】:

不幸的是,在使用 Perl 创建包、导出等方面,我完全是个菜鸟。我尝试阅读一些模块,并且经常发现自己从冗长的章节中打瞌睡。如果我可以在一个简单的网页中找到我需要了解的内容而无需向下滚动,那将会很有帮助。 :P

基本上我有两个模块,A 和 B,A 将使用 B 的一些函数,B 将使用 A 的一些函数。当我尝试通过 perl -c 编译时,我收到大量关于函数重新定义的警告.

有没有办法正确地做到这一点?还是我的设计迟缓了?如果是这样,什么是更好的方法?因为我这样做的原因是避免复制 n 将其他模块函数再次粘贴到该模块中并重命名它们。

【问题讨论】:

    标签: perl exporter module-management


    【解决方案1】:

    循环依赖并不是一个很好的做法。我建议将某些东西或其他东西分解到第三个模块,这样你就可以让 A 依赖于 B,A 依赖于 C,B 依赖于 C。

    【讨论】:

    • @chaos 这就是我害怕的:P 最初我写了模块 A,因为我被告知它将是一个独立的脚本,然后它变成了网页 LAMP 样式。谢谢
    【解决方案2】:

    所以...将通用代码分解到另一个模块中的建议是 一个很好的。但是,您不应该将模块命名为 *.pl,也不应该 通过require-ing 某个路径名(如require "../lib/foo.pl";)加载它们。 (一方面,说 '..' 使你的脚本 依赖于每次都从同一个工作目录执行。 因此,当您以perl foo.pl 运行它时,您的脚本可能会工作,但它不会 当你以perl YourApp/foo.pl 运行它时工作。这通常不好。)

    假设您的应用名为 YourApp。你应该建立你的 应用程序作为一组位于lib/ 目录中的模块。为了 例如,这是一个“Foo”模块;它的文件名是lib/YourApp/Foo.pm

    package YourApp::Foo;
    use strict;
    
    sub do_something {
        # code goes here
    }
    

    现在,假设您有一个名为“Bar”的模块,它依赖于“Foo”。 你只需让lib/YourApp/Bar.pm 说:

    package YourApp::Bar;
    use strict;
    use YourApp::Foo;
    
    sub do_something_else {
        return YourApp::Foo::do_something() + 1;
    }
    

    (作为高级练习,您可以使用Sub::ExporterExporter 来 make use YourApp::Foo 在消费包中安装子例程 命名空间,这样你之前就不必写YourApp::Foo:: 一切。)

    无论如何,您都可以像这样构建整个应用程序。逻辑碎片 在功能上应该在模块中组合在一起(甚至更好, 类)。

    为了让这一切运行起来,你编写了一个看起来像这样的小脚本(我 把这些放在bin/,我们就叫它bin/yourapp.pl):

     #!/usr/bin/env perl
    
     use strict;
     use warnings;
     use feature ':5.10';
    
     use FindBin qw($Bin);
     use lib "$Bin/../lib";
    
     use YourApp;
     YourApp::run(@ARGV);
    

    这里的关键是你的代码都没有在模块之外,除了一个 启动您的应用程序运行的一小部分样板文件。这很容易 维护,更重要的是,它使编写自动化变得容易 测试。而不是从命令行运行某些东西,您可以 只需调用具有某些值的函数即可。

    无论如何,现在这可能是题外话了。但我认为这很重要 知道。

    【讨论】:

      【解决方案3】:

      简单的答案是不要使用 perl -c 测试编译模块...使用 perl -e'use Module' 或 perl -e0 -MModule 代替。 perl -c 旨在对脚本进行测试编译,而不是模块。当你运行它 在你的一个

      递归使用模块时,关键是要确保尽早设置外部引用的任何内容。通常这意味着至少要在编译时构造中设置使用 @ISA(在 BEGIN{} 中或通过“使用父级”或已弃用的“使用基础”),并在 BEGIN{} 中设置@EXPORT 和朋友。

      基本问题是,如果模块 Foo 使用模块 Bar(它使用 Foo),则 Foo 的编译会在该点停止,直到 Bar 完全编译并且它的主线代码已经执行。确保 Foo Bar 的任何部分的编译和运行主线代码 有需要就有答案。

      (在许多情况下,您可以明智地将功能分离为更多模块并中断递归。这是最好的。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-11
        • 2011-04-20
        • 1970-01-01
        • 2015-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多