据我所知,在Perl中,我们可以通过使用这些技术调用从模块子程序:
- 出口子程序
foo
,导入具有这个子程序模块。 最后把它在你的Perl脚本。 - 创建一个
Object
在你的Perl脚本,模块的最后调用foo
使用Object
。 - 直接调用
foo
使用其路径,这样myDir::Module::foo();
。
如果我一直困惑,这是更好调用子程序的方法foo
。 如果我有一个动态脚本,这是我从浏览器中运行,而不是命令行,这接近一个应该去这样脚本花费较少的时间。
谢谢。
还有就是最快的,并调用代码在Perl的最佳方式之间的差异。
编辑:请参阅simbabques回答为好。 他特别涵盖之间#1和#3,为什么你会使用任何的差异。
#1,#3:函数调用
你的#1和#3是相同的:子程序在全局可见的命名空间有一个独特的名字。 许多名字可以通过别名映射到一个子程序,或导入模块。
如果要调用在编译时已知函数的名称,子将在编译时得到解决。 这里假设你不自发地重新定义的功能。 如果确切功能在运行时才知道,这仅仅是一个哈希查找了。
有三种方法的功能如何可以被称为:
foo(@args);
&foo(@args);
@_ = @args; goto &foo;
数字一(括号有时可选)是默认,并验证你对原型子参数(不使用原型)。 此外,整个调用堆栈帧(具有许多有用的调试信息)被构造。 这需要时间。
排名第二跳过protoype验证,并假定你知道自己在做什么。 这稍快。 我认为这是草率的风格。
排名第三的是一个尾调用。 这将返回从返回值当前子foo
。 这是速度快,因为原型被忽略,并且当前调用堆栈帧可重复使用。 这是没有用的,很多时候,并有丑陋的语法。 内嵌代码是约一个数量级的速度(即在Perl中,我们更喜欢在循环递归☹)。
#2:方法调用
OO的灵活性是一个沉重的性价比:如您拨打上从来不知道,直到运行时消息的对象的类型,实际的方法只能在运行时解决。
这意味着, $foo->bar()
查找功能bar
,该包装$foo
是bless
编辑成。 如果它不能在那里找到,它会搜索在父类。 这是缓慢的。 如果你想使用OO,注意浅的层次结构(→少的查询)。 难道还注意到,皮尔斯默认方法解析顺序是不寻常的。
你一般不能减少方法调用一个函数调用,即使你知道的类型。
如果$foo
,如果类的Foo
和Foo::bar
是一分,然后Foo::bar($foo)
将跳过方法resultution,甚至可能会奏效。 然而,这打破了封装,将打破一度Foo
是子类。 另外,如果这不起作用Foo
没有定义bar
,但在父类中定义的方法。
我一般是倾向于面向对象的,直到其与基准,这将不会提供您所需要的性能清晰。
- 出口子程序FOO,导入具有这个子程序模块。 最后把它在你的Perl脚本。
为了做到这一点,你将使用出口商在模块/ package
实现了分。 你告诉你的模块是什么将通过出口@EXPORT_OK
和@EXPORT
。 如果您use
的模块,东西被导入到在编译时你当前的命名空间。 下面以语句是等价的。
# This is the same...
use Module;
# ... as this
BEGIN {
require Module;
Module->import();
}
你想,如果你有东西,你要在你的主脚本中使用,或者你要经常使用做到这一点。 一些例子是列表::的Util , 数据::自卸车或use feature 'say'
。 当然,你也可以在其他模块中使用它。
use Data::Dumper;
use List::Util qw(max);
use feature qw(say);
my @foo = (1, 2, 3, 4, 5, 23);
print Dumper \@foo;
say max(@foo);
美中不足的是,在这里,你“污染”的命名空间。 如果你必须这样做,但请记住,它发生在编译时,所以它是不是条件 。 你不能说 :
if ($foo) {
use Some::Module 'foo';
foo($foo);
} else {
use Something::Else 'bar';
bar();
}
这将同时加载Some::Module
和 Something::Else
在编译时间,从而提高您的程序所消耗的时间和内存。 该条件将工作过程中的,但它是没有效率的。
- 在你的perl脚本创建模块的对象使用该对象最后调用foo。
这是面向对象的方法。 它是(如上所述)不compairable到其他方法。 你并不需要导入对象的方法。 您只需加载你的类(这是一个模块)或者与use
或require
(见上文),创建一个实例,并使用它的方法根据自己的喜好。 但是,你需要的是一个面向对象的模块。 如果您在如何工作的interestend,通过采取一看开始perlootut 。
- 直接调用foo使用其路径,这样MYDIR ::模块:: foo的();.
它实际上不是其相当的路径,而是它的名字(空间)。 例如,数据::自卸车是Dumper.pm
所在的文件夹Data
,在某个地方lib
目录。 但是,这并不重要。
第一种方法的主要区别是,你ommit进口部分。 如果你想建立的东西,有条件地加载某些模块这是有用的,或者如果你是在一个巨大的(也许遗留)应用程序,不想污染命名空间。
if ($order_has_some_condition) {
require Very::Long::NameSpace::For::This::Condition::Module;
Very::Long::NameSpace::For::This::Condition::Module::do_stuff_with_an_order($order);
}
想象一下,这段代码是在传统子带2k行和很多东西怎么回事,大部分是从来没有在我们的情况下调用。 我们不希望use
我们的模块,使其可用于每个了在这个庞大的代码来处理的,也许100不同的情况。 相反,我们希望如果我们真的需要它来只加载它。 现在,我们require
的模块,并调用它使用全名子直接。
在conclusing,第一和第三种方式有其可取之处。 他们都需要存在,并且它们都应该在适当使用。 在某些情况下,它只是味道,但在另一些有意义的决定。 第二,面向对象,方法完全是另一回事。
有没有真正的速度差异,并作为鲍罗廷说,Perl是快。 当然,如果你不import
的东西,你不必为进口“买单”。 在10班轮脚本,这并不重要。 在与潜在的成千上万的一个巨大的文件,代码和许多用例的行传统的软件,这是相当重要的。
我希望这可以帮助你决定。