koknat has asked for the wisdom of the Perl Monks concerning the following question:

When I'm writing a program, I usually pepper it with debug print statements. After the program is working, I keep them in - they come in very useful if I ever need to fix a bug or add more functionality. I'm not at all worried about execution speed. Is there any better way of doing this?
my $debug = 1; ... if ($debug>=1) { print "DEBUG: \$variable = $variable\n" }

Replies are listed 'Best First'.
Re: debug statements
by Fletch (Bishop) on Oct 03, 2006 at 18:00 UTC

    If you use a constant sub (declared with the constant pragma) then the code should get optimized away at compile time.

    use constant DEBUG => 0; ## ... print "DEBUG: JINKIES!\n" if DEBUG();

    There's also an evil live comments module (specially formatted text in comments is printed as debugging output) that someone wrote but the name of which escapes me at the moment . . .

    Update: Smart::Comments, that was it. Of course that gets the usual "source filters are teh debil" warnings.

      Source filters are only evil if you invoke them, the beauty of smart comments is that normally they're just comments. Just leave 'use Smart::Comments' out of your code, then to invoke the smart comments (and the source filter), invoke your script via:
      perl -MSmart::Comments myscript.pl
      or for finer control:
      perl -MSmart::Comments='####' myscript.pl
      See Smart::Comments for details. This way you have zero overhead except when debugging. I'm surprised this simple technique isn't mentioned in the documentation.
      I have to say I really like this; I've been using Perl for a while but hadn't thought about optimising debug statements away at compile time using this trick. Thanks!
        Well it's not really optimizing debug statements away at compile time, it's optionally compiling them in at compile time. Same difference I suppose.
Re: debug statements
by derby (Abbot) on Oct 03, 2006 at 17:58 UTC
      Log4perl is great.
      Look here for a gentle introduction. The raw module docs might scare ya off if your current needs are modest.

      andyford
      or non-Perl: Andy Ford

Re: debug statements
by mreece (Friar) on Oct 03, 2006 at 19:10 UTC
    if you don't want to go with something like Log::Log4perl, you could reduce it to a subroutine call, to make the typing easier:
    use constant DEBUG => 1; debug("\$variable = $variable"); sub debug { return unless DEBUG >= 1; print 'DEBUG: ', @_, "\n"; }
    you say you are not worried about execution speed, but the above can be enhanced to support lazy evaluation of potentially expensive debugging operations by using closures:
    sub debug { return unless DEBUG >= 1; print 'DEBUG: ', ( ref $_[0] eq 'CODE' ? $_[0]->() : @_ ), "\n"; }
    that allows things like:
    debug( sub { Data::Dumper->new([$variable], ["variable"])->Dump } );
    and the expensive Dump operation will only be executed if DEBUG.
      I really like the idea of using a simple subroutine. Is there a way of making a subroutine that works like this?:
      debug(\$variable);
        You mean something like this?
        use constant DEBUG => 1; sub debug { return unless DEBUG; my $ref = shift; print STDERR Dumper $ref; } my $foo = 'foo'; my @bar = ( qw/ foo bar baz / ); debug( \$foo ); debug( \@bar );
        Output:
        $VAR1 = \'foo'; $VAR1 = [ 'foo', 'bar', 'baz' ];
        not without resorting to extreme nastiness. you could try Data::Dumper::Names to make your life a little easier (?)...
        use Data::Dumper::Names; debug( Dumper($variable) );
        note the CAVEATS in the Data::Dumper::Names documentation!
Re: debug statements
by Raster Burn (Beadle) on Oct 04, 2006 at 16:16 UTC

    Another idea for the Lazy.

    Open a global filehandle called DEBUG. Whenever you want to print a debug message, print to this filehandle. That way, if you want to silence debugging, you can open it to /dev/null, if you want to log to a file, open it to a file, and if you want to show it on the screen, open it to STDERR.