常量子程序,即带有空原型和常量返回值的子程序是内联的。这就是constant编译指示符定义常量的方式:
sub five() { 5 }
perl
执行的优化步骤的一些信息。
另请参见perldoc perlguts。这称为常量折叠。常量折叠不仅限于将2 ** 10在编译时转换为1024等简单情况。它还解析函数调用 - 内置和符合第6章“内联常量函数”中条件的用户声明的子例程。与FORTRAN编译器对其自身固有功能的臭名昭著的了解类似,Perl也知道在编译期间调用其自己的内置函数。这就是为什么如果您尝试取log(0.0)或sqrt负常量,您会遇到编译错误而不是运行时错误,并且解释器根本没有运行。
#!/usr/bin/perl
use strict; use warnings;
sub log_ok () { 1 }
if ( log_ok ) {
warn "log ok\n";
}
perl -MO=Deparse t.pl
输出:
sub log_ok () { 1 } use warnings; use strict 'refs'; do { warn "log ok\n" }; t.pl 语法 OK
在这里,常量折叠导致if
块被替换为do
块,因为编译器知道log_ok
总是返回真值。另一方面,对于:
#!/usr/bin/perl
use strict; use warnings;
sub log_ok () { 0.5 > rand }
if ( log_ok ) {
warn "log ok\n";
}
Deparse输出:
sub log_ok(){ use warnings; use strict 'refs'; 0.5 > rand; } use warnings; use strict 'refs'; if(log_ok){ warn "日志正常\n"; } t.pl语法OK
C
编译器可能已将if(log_ok)
替换为if(0.5> rand)
。 perl
不会这样做。
Perl只允许内联常量函数。来自perldoc perlsub:
带有原型()的函数是内联的潜在候选项。如果经过优化和常量折叠后的结果是一个常量或者没有其他引用的词法作用域标量,则它将被用于没有 & 的函数调用的位置。
我没有尝试过这些方法,但如果你有时间,可以尝试以下方法:
它们都是源代码过滤器,因此您需要检查性能的回报率。 最后一个在cpanratings上有一篇评论。(忽略Dan Dascalescu对Perl模块“airspace”的尝试规范。)
-- 实际上,最后一个Filter::Macro
使用Filter::Simple::Compile
(进而使用Module::Compile
)来编译例程,因此这个方法可能比其他源代码过滤器表现更好。但标准的源代码过滤器警告仍然适用。