Tom's Tom's - 5 months ago 19
Perl Question

Perl way of execute/ignore code (like assert in C)

I'm a real beginner in Perl programming (v 5.20.2 on Debian 8) and I'm looking to a way of implementing a "debugging" with no overhead at Perl execution-time when I don't need to debug.

In C, we can do that with

assert
and the
-D
gcc option (and in general, you can do your own assert by following the same way with your own define constante like
MY_DEBUG
).

Well, first idea is simply to set a global variable
debug
and test again it, but it will generate a bunch of useless test when I will don't want to be in debug mode.

There are CPAN Module like assertions or Carp::Assert, but it's seem that there will be an if test even when I don't want debugging.

Is there a Perl way for deactivate portion of code depending on "something"?

Bonus question: I want to make a Perl module with the same functionality, so if there is a way to say "enable/disable debugging" when I do the
use MyModule
, well, I will be a happy Perl developer.

Answer

Perl does not have that built-in. There is also no compiling happening like in C because Perl is an interpreted language. The fact that Carp::Assert exists (and is written by someone who is involved in the Perl core) is a pretty good assertion (pun intended) that this feature is not there in Perl directly.

In general, a couple of if DEBUG or if $debug or similar are not big deal. Computers today are so fast that those operations hardly matter unless you have them in a loop that gets called millions of times, or you have extremely time-critical code. In your average program, you can ignore that overhead.

In fact perl1 will optimize those out if you use a constant. Consider this program.

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

If run with B::Deparse, it will produce the following output.

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

There's our print statement. But if you turn the DEBUG constant to 0 and run the same command, you get something else.

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

As you can see, the print is gone. All that remains is '???';, which is a NOOP.

Let's run the same thing with B::Concise. First, with DEBUG turned to 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

And then with DEBUG set to 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

As you can see, there are more operations. The print "stuff" if DEBUG is in fact optimized out. This is pretty much the same thing as what you describe in your C example.

Go ahead and try out with those two modules to see if it behaves the same when using Carp::Assert.


If you don't like that, take a look at Smart::Comments. It introduces comment syntax that get executed when you use it. That's pretty cool, because those can just sit around and not do stuff when you don't load the module.

use Smart::Comments;

my $var = suspect_value();

### $var

There is also Devel::Comments, which seems to do the same.

1) perl with a small p is the interpreter program, not the language