在 Perl 中让两个模块互相使用函数的最佳方式是什么?
不幸的是,在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
拥有循环依赖并不是一个好的做法。 我建议将某些东西分解到第三个模块,这样你就可以让 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.
所以...将公共代码分解到另一个模块中的建议是
一个很好的。 但是,您不应该将模块命名为 *.pl,也不应该
通过
require
-ing 某个路径名来加载它们(如require
)。 (一方面,说“..”会让你的脚本“../lib/foo.pl”;
依赖于每次都从同一工作目录执行。
因此,当您将脚本作为
perl foo.pl
运行时,它可能会工作,但它不会当您将其作为
perl YourApp/foo.pl
运行时,它就可以工作。 这通常不好。)假设您的应用程序名为 YourApp。 你应该建立你的
应用程序作为一组模块,位于
lib/
目录中。 为了例如,这是一个“Foo”模块; 它的文件名是
lib/YourApp/Foo.pm
。现在,假设您有一个名为“Bar”的模块,它依赖于“Foo”。
您只需创建
lib/YourApp/Bar.pm
并说:(作为高级练习,您可以使用
Sub::Exporter
或Exporter
来让
use YourApp::Foo
在使用包的安装子例程命名空间,这样你就不必在之前编写
YourApp::Foo::
一切。)
无论如何,您可以像这样构建整个应用程序。 逻辑部分
功能上应该分组在模块中(或者更好,
类)。
为了使这一切运行起来,您需要编写一个如下所示的小脚本(我
将它们放入
bin/
中,所以我们将其称为bin/yourapp.pl
):这里的关键是,您的任何代码都不在模块之外,除了
一点点样板来启动您的应用程序运行。 这很容易
维护,更重要的是,它使编写自动化变得容易
测试。 您可以不用从命令行运行某些东西
只需调用具有某些值的函数即可。
不管怎样,现在这可能已经是题外话了。 但我认为这很重要
知道。
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 inrequire
). (For one thing, saying '..' makes your script"../lib/foo.pl";
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'twork 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. Forexample, here is a "Foo" module; its filename is
lib/YourApp/Foo.pm
.Now, let's say you have a module called "Bar" that depends on "Foo".
You just make
lib/YourApp/Bar.pm
and say:(As an advanced exercise, you can use
Sub::Exporter
orExporter
tomake
use YourApp::Foo
install subroutines in the consuming package'snamespace, so that you don't have to write
YourApp::Foo::
beforeeverything.)
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 itbin/yourapp.pl
):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.
简单的答案是不要使用 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.)