在 Perl 中让两个模块互相使用函数的最佳方式是什么?

发布于 2024-07-14 00:51:27 字数 310 浏览 9 评论 0原文

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

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

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

Unfortunately, I'm a totally noob when it comes to creating packages, exporting, etc in Perl. I tried reading some of the modules and often found myself dozing off from the long chapters. It would be helpful if I can find what I need to understand in just one simple webpage without the need to scroll down. :P

Basically I have two modules, A & B, and A will use some function off from B and B will use some functions off from A. I get a tons of warning about function redefined when I try to compile via perl -c.

Is there a way to do this properly? Or is my design retarded? If so what would be a better way? As the reason I did this is to avoid copy n pasting the other module functions again into this module and renaming them.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

〆凄凉。 2024-07-21 00:51:27

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

It's not really good practice to have circular dependencies. I'd advise factoring something or another to a third module so you can have A depends on B, A depends on C, B depends on C.

墨离汐 2024-07-21 00:51:27

所以...将公共代码分解到另一个模块中的建议是
一个很好的。 但是,您不应该将模块命名为 *.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
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);

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

不管怎样,现在这可能已经是题外话了。 但我认为这很重要
知道。

So... the suggestion to factor out common code into another module is
a good one. But, you shouldn't name modules *.pl, and you shouldn't
load them by require-ing a certain pathname (as in require
"../lib/foo.pl";
). (For one thing, saying '..' makes your script
depend on being executed from the same working directory every time.
So your script may work when you run it as perl foo.pl, but it won't
work when you run it as perl YourApp/foo.pl. That is generally not good.)

Let's say your app is called YourApp. You should build your
application as a set of modules that live in a lib/ directory. For
example, here is a "Foo" module; its filename is lib/YourApp/Foo.pm.

package YourApp::Foo;
use strict;

sub do_something {
    # code goes here
}

Now, let's say you have a module called "Bar" that depends on "Foo".
You just make lib/YourApp/Bar.pm and say:

package YourApp::Bar;
use strict;
use YourApp::Foo;

sub do_something_else {
    return YourApp::Foo::do_something() + 1;
}

(As an advanced exercise, you can use Sub::Exporter or Exporter to
make use YourApp::Foo install subroutines in the consuming package's
namespace, so that you don't have to write YourApp::Foo:: before
everything.)

Anyway, you build your whole app like this. Logical pieces of
functionally should be grouped together in modules (or even better,
classes).

To make all this run, you write a small script that looks like this (I
put these in bin/, so let's call it 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);

The key here is that none of your code is outside of modules, except a
tiny bit of boilerplate to start your app running. This is easy to
maintain, and more importantly, it makes it easy to write automated
tests. Instead of running something from the command-line, you can
just call a function with some values.

Anyway, this is probably off-topic now. But I think it's important
to know.

浮生未歇 2024-07-21 00:51:27

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

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

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

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

The simple answer is to not test compile modules with perl -c... use perl -e'use Module'
or perl -e0 -MModule instead.
perl -c is designed for doing a test compile of a script, not a module. When you run it
on one of your

When recursively using modules, the key point is to make sure anything externally referenced is set up early. Usually this means at least making use @ISA be set in a compile time construct (in BEGIN{} or via "use parent" or the deprecated "use base") and @EXPORT and friends be set in BEGIN{}.

The basic problem is that if module Foo uses module Bar (which uses Foo), compilation of Foo stops right at that point until Bar is fully compiled and it's mainline code has executed. Making sure that whatever parts of Foo Bar's compile and run-of-mainline-code
need are there is the answer.

(In many cases, you can sensibly separate out the functionality into more modules and break the recursion. This is best of all.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文