尽我所能(主要是为了清晰/文档),我一直试图说
use Some::Module;
use Another::Module qw( some namespaces );
在我使用其他模块的Perl模块中。
我一直在清理一些旧代码,看到我在代码中引用模块的地方,而没有use
d:
my $example = Yet::Another::Module->AFunction($data); # EXAMPLE 1
my $demo = Whats::The::Difference::Here($data); # EXAMPLE 2
所以我的问题是:
use x
并只是在代码中引用它?use
代码中没有使用的模块 - 我告诉编译器编译不必要的代码。答案 0 :(得分:3)
你实际上有很多问题。
- 是否存在性能影响(思考编译时间),没有说明使用x并只是在代码中引用它?
醇>
不,没有性能影响,因为你不能这样做。您在工作程序中使用的每个命名空间都会在某处定义。要么use
d或require
更早到它被调用的地方,或者你的一个依赖项,或者用另一种方式 1 来使Perl意识到它
Perl在符号表中跟踪这些事情。它们拥有关于命名空间和变量名称的所有知识。因此,如果您的Some::Module
不在引用的符号表中,Perl会抱怨。
- 我假设我不应该使用代码中没有使用的模块 - 我告诉编译器编译不必要的代码。
醇>
这里毫无疑问。但是,是的,你不应该这样做。
很难说这是否会影响性能。如果您有一个只运行并运行数月的大型Catalyst应用程序,那么这并不重要。在这种情况下,启动成本通常不相关。但如果这是一个每分钟运行并处理大量数据的cronjob,那么额外的模块可能会对性能产生影响。
这实际上也是为什么所有use
和require
语句应该位于顶部的原因。因此,如果您需要添加或删除一些,很容易找到它们。
- 在示例1的样式和示例2的样式中调用函数之间有什么区别?
醇>
这些主要用于不同的目的。
my $example = Yet::Another::Module->AFunction($data); # EXAMPLE 1
此语法与以下内容非常相似:
my $e = Yet::Another::Module::AFunction('Yet::Another::Module', $data)
它用于OOP中的类方法。最着名的一个是new
,如Foo->new
。它将->
前面的东西传递给左边的东西包中的名为AFunction
的函数(如果它是bless
ed,或者它是一个标识符)作为第一个论点。但它做得更多。因为它是方法调用,所以它也需要考虑继承。
package Yet::Another::Module;
use parent 'A::First::Module';
1;
package A::First::Module;
sub AFunction { ... }
在这种情况下,您的示例也会调用AFunction
,因为它继承自A :: First :: Module。除了上面引用的符号表之外,它还使用@ISA
来跟踪谁从谁继承。有关详细信息,请参阅perlobj。
my $demo = Whats::The:Difference::Here($data); # EXAMPLE 2
这有语法错误。 :
之后缺少The
。
my $demo = Whats::The::Difference::Here($data); # EXAMPLE 2
这是一个函数调用。它会调用包Here
中的函数Whats::The::Difference
并传递$data
,而不会传递任何其他内容。
请注意,作为Borodin points out in a comment,您的函数名称非常不典型且令人困惑。 Perl中的函数通常用全小写和下划线_
而不是camel case编写。因此AFunction
应为a_function
,而Here
应为here
。
1)例如,您可以在一个文件中有多个package
定义,这通常不应该这样做,或者您可以使用*Some::Namespace::frobnicate = sub {...}
之类的语法将内容直接分配到命名空间中。还有其他方法,但这个答案有点超出范围。
答案 1 :(得分:3)
我会说,如果你不确定,那么这就属于抢先优化和的范畴,然后将其保留在中。如果删除它们,则必须包含一些未使用的库
Perl通常隐藏一个简单机制背后的复杂问题,通常做你的意思而不用太多想法
简单的机制就是这些
use My::Module 'function'
与撰写
BEGIN {
require My::Module;
My::Module->import( 'function' );
}
perl第一次成功执行require
语句时,它会向全局%INC
哈希添加一个元素,该哈希具有“路径化”模块名称(在本例中为My/Module.pm
})对于一个键和绝对位置,它将源代码作为值
如果遇到同一模块的另一个require
(也就是说,它已存在于%INC
哈希中),那么require
什么都不做
所以你的问题
use
/ require
会怎么样?我们将会遇到使用,利用,包含和参考的问题,所以当我的意思是Perl语言时,我只引用use
和require
。
保持简单,这是三种可能性
如上所述,如果同一模块源多次看到require
,则在第一次之后会被忽略。唯一的开销是检查%INC
显然,如果您use
源文件不需要,那么您正在进行不必要的编译。但是Perl非常快,除非你有一个使用大量库并且看起来像use Catalyst; print "Hello, world!\n";
的程序
我们知道如果对从未编译过的类库进行方法调用会发生什么。我们得到
Can't locate object method "new" via package "My::Class" (perhaps you forgot to load "My::Class"?)
如果您使用的是功能库,那么重要的是use
中
My::Module->import( 'function' );
因为第一部分是require
,我们已经知道require
从未做过两次。调用import
通常是一个简单的函数调用,通过避免它可以节省一些重要的事情
可能不太明显的是包含多个子公司的大型模块。例如,如果我只写
use LWP::UserAgent;
然后它知道它可能需要什么,这些模块也将被编译
Carp
Config
Exporter
Exporter::Heavy
Fcntl
HTTP::Date
HTTP::Headers
HTTP::Message
HTTP::Request
HTTP::Response
HTTP::Status
LWP
LWP::MemberMixin
LWP::Protocol
LWP::UserAgent
Storable
Time::Local
URI
URI::Escape
那是在忽略pragma!
你有没有觉得自己在踢脚跟等待LWP
程序编译?
我想说,为了保持Perl代码的清晰和整洁,从编译阶段删除不必要的模块可能是个主意。但是,在进行任何移交前整理之前,不要为此烦恼,对您的构建时间进行基准测试。没有人会感谢你将构建时间减少了20ms,然后因为你删除了一个非显而易见的要求而导致他们工作了几个小时。