执行/忽略代码的Perl方式(如C中的assert)

时间:2016-07-06 08:06:21

标签: perl

我是Perl编程的真正初学者(Debian 8上的v 5.20.2),我正在寻找一种实现“调试”的方法,在Perl执行时没有开销,而我不需要调试。

在C中,我们可以使用assert-D gcc选项(通常,您可以通过与您自己的定义constante相同的方式执行自己的断言,例如{{1 }})。

嗯,首先想法只是设置一个全局变量MY_DEBUG并再次测试它,但是当我不想进入调试模式时,它会产生一堆无用的测试。

有CPAN模块,如assertionsCarp::Assert,但即使我不想调试,似乎也会有if测试。

是否有一种Perl方式可以根据“某些内容”停用代码部分?

奖金问题:我想制作一个具有相同功能的Perl模块,所以如果我在debug做一个方法来说“启用/禁用调试”,那么,我将是一个快乐的Perl显影剂。

1 个答案:

答案 0 :(得分:9)

Perl没有内置功能。由于Perl是一种解释型语言,因此也没有像C中那样的编译事件。 Carp::Assert存在的事实(并且由参与Perl核心的人编写)是一个非常好的断言(双关语),这个特性在Perl中不存在。

一般来说,一些if DEBUGif $debug或类似的东西都没什么大不了的。今天的计算机速度如此之快,以至于这些操作几乎不重要,除非你将它们置于一个被称为数百万次的循环中,或者你拥有极其时间关键的代码。在您的普通程序中,您可以忽略该开销。

事实上,如果使用常量,perl 1 将优化它们。考虑一下这个程序。

use constant DEBUG => 1;
print "stuff" if DEBUG;

如果使用B::Deparse运行,则会产生以下输出。

$ perl -MO=Deparse scratch.pl 
use constant ('DEBUG', 1);
print 'stuff';
scratch.pl syntax OK

我们的print声明。但是如果你将DEBUG常量变为0并运行相同的命令,你就会得到别的东西。

$ perl -MO=Deparse scratch.pl 
use constant ('DEBUG', 0);
'???';
scratch.pl syntax OK

如您所见,print已消失。剩下的就是'???';,这是一个NOOP。

让我们用B::Concise运行相同的东西。首先,DEBUG转为0

$ perl -MO=Concise scratch.pl 
3  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 120 scratch.pl:1129) v:{ ->3
-     <0> ex-const v*/4,FOLD ->3
scratch.pl syntax OK

然后将DEBUG设置为1

$ perl -MO=Concise scratch.pl 
6  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 120 scratch.pl:1129) v:{ ->3
5     <@> print vK/FOLD ->6
3        <0> pushmark s ->4
4        <$> const(PV "stuff") s ->5
scratch.pl syntax OK

如您所见,还有更多操作。 print "stuff" if DEBUG实际上已经过优化。这与您在C示例中描述的内容几乎完全相同。

继续尝试使用这两个模块,看看在使用Carp::Assert时它是否表现相同。

如果您不喜欢,请查看Smart::Comments。它引入了在use时执行的注释语法。这很酷,因为当你不加载模块时,那些可以只是坐着而不做事情。

use Smart::Comments;

my $var = suspect_value();

### $var

还有Devel::Comments,似乎也是如此。

1)带有小p的 perl 是解释程序,而不是语言