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

I am trying to put an option into my perlscripts which
allows for a debugging switch which, when submitted to
the script, prints out debugging messages.

Problem is that I get
(a) a warning because I redefine a subroutine, and
(b) the debugging information is printed no matter if the switch is submitted or not.

Any dice, anyone???

# set debugging switch to default (off) use constant DEBUGGING => 0; # loop foreach argument foreach $_ (@ARGV) { # is argument '-d' or '-D'? if ( /^-d$/i ) { # yup. use 'no warnings;' to suppress 'subroutine redefined' w +arning no warnings; # change debugging switch to ON use constant DEBUGGING => 1; } } ... print "FUNCTION_NAME: Debugging Information\n" if DEBUGGING;

/neuroball aka /oliver

Replies are listed 'Best First'.
Re: change 'use constant' value through commandline arguments?
by chromatic (Archbishop) on Mar 14, 2002 at 15:49 UTC
    How about using an environmental variable?

    use constant DEBUGGING => $ENV{DEBUGGING} || 0;
    Otherwise, you'll have to wrap your @ARGV processing in a BEGIN {} block so it will run at compile time. That's when (and how) use statements run.
      How about using an environmental variable?
      There's no such thing as "environmental" variable, unless you're talking about $greenpeace, or something. It's "environment" variable.

      There must be some very common document that a lot of people read to get this wrong, that came out about three or four years ago. Nobody got it wrong before that. {sigh}

      -- Randal L. Schwartz, Perl hacker

        Alternate possibility: everybody who gets it wrong does so before 8 am, when their brain and fingers are not on speaking terms. :)
      The implementation of an environment variable is kind of a bit more work than I planned for a debug switch... but something to think about.

      Btw. thanks for the BEGIN/use education... even though the outcome is the same... DEBUGGING is always 1.
Re: change 'use constant' value through commandline arguments?
by derby (Abbot) on Mar 14, 2002 at 17:45 UTC
    neuroball,

    check out inlined DEBUG constant versus $DEBUG. It's discussed there and there's a nice link to a TPJ article. For pure funkiness tho how about:

    #!/usr/bin/perl use constant DEBUG_ON => 1; use constant DEBUG_OFF => 0; use vars qw( $DEBUG ); $DEBUG = ( $opt_d eq "y" ) ? DEBUG_ON : DEBUG_OFF;

    No? Yeah that's probably too much.

    -derby

    update: Since I'm not wanting to concentrate on the real job today and since nobody else has pointed it out, the reasoning for the behaviour you describe can be found in perlsub under the section "Constant Functions." Basically, since the constants.pm module defines the constant function with "()", the function is a canidate for inlining and will probably be optimized away by being folded to its value (ie, the sub will never be called).

Re: change 'use constant' value through commandline arguments?
by Juerd (Abbot) on Mar 14, 2002 at 17:02 UTC

    I am trying to put an option into my perlscripts which allows for a debugging switch which, when submitted to the script, prints out debugging messages.

    It seems like you don't want a constants, because constants tend to never change. Constants should also not be influenced by external circumstances. Try using a variable instead, like $DEBUG.

    And "constant debugging" sounds like a 24/7 job :)

    If you decide to use a constant after all (bad idea, imho), you could delay definition until @ARGV is fully parsed, and then use use constant DEBUGGING => $minus_d_found;

    U28geW91IGNhbiBhbGwgcm90MTMgY
    W5kIHBhY2soKS4gQnV0IGRvIHlvdS
    ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
    geW91IHNlZSBpdD8gIC0tIEp1ZXJk
    

(tye)Re: change 'use constant' value through commandline arguments?
by tye (Sage) on Mar 14, 2002 at 19:42 UTC

    It isn't perfect, but:     use constant DEBUGGING => grep $_ eq "-d", @ARGV; otherwise you'd need to do all of the argument processing inside a BEGIN block:

    my %options; BEGIN { # process @ARGV, putting results in %options } use constant DEBUGGING => $options{debug};

            - tye (but my friends call me "Tye")
      Here is what I did come up with through the education/help received in this thread:

      # set debugging switch to OFF my $debug_switch = 0; # go through the argument evaluation at compile time BEGIN { # check each argument foreach $_ (@ARGV) { # is the debug switch submitted? if (/^-d$/i) { # yup. set debugging switch to ON $debug_switch = 1; } } } # set DEBUGGING to the debug_switch value use constant DEBUGGING => $debug_switch;

      It works, doesn't throw any warnings, and I use a constant like it is normally done: Define once, use x times.

        Rather than just setting it to 1, it may be more flexible to use $debug_switch++ instead; that way you could increase the debug level with every -d on the command-line, letting you do things like...

        use constant VAGUE => 0; use constant DETAILED => 1; use constant PEDANTIC => 2; if ( @x ) { warn( "\@x is set\n" ) if DEBUG > VAGUE; warn( scalar(@x)," elements\n" ) if DEBUG > DETAILED; { local $" = "\n "; warn( "They are...\n @x\n" ) if DEBUG > PEDANTIC; } }

        Lame example, but hopefully you get the point... :)

            --k.


        tye's original suggestion can easilly be modified to use 1/0 instead of -d/undef for TRUE/FALSE values.... is that why you opted for his second (longer) suggestion?
        use constant DEBUGGING => (grep $_ eq "-d", @ARGV) ? 1 : 0;

        -Blake

        Would not it be easier just to code
        use Getopt::Long;
        GetOptions("debug" => \$debug_switch);
        
        or even
        use Getopt::Long;
        GetOptions("debug+" => \$debug_switch);
        
        which allows several levels of debugging.