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

Monks ~

First, the code:
use constant DEBUG => 1; DEBUG && BEGIN { use CGI::Carp qw/ fatalsToBrowser /; };
I'm using the DEBUG constant for a number of purposes in the script (local vs. remote server paths, logging, etc.) and thought it would be nice to use it for fatalsToBrowser as well. The above code doesn't do what I want, though: the script 'use's CGI::Carp regardless of the value of DEBUG.

I'm sure this is evidence of my incomplete understanding. Can someone point me in the right direction?

Thanks,

legs

Replies are listed 'Best First'.
Re: BEGIN and 'use' question
by jwest (Friar) on May 07, 2002 at 18:15 UTC
    'use' implies a BEGIN block. Also, the DEBUG && BEGIN {} looks suspect to me. What you want instead is likely:

    use constant DEBUG => 1; BEGIN { if (! DEBUG) { require CGI::Carp; import CGI::Carp qw/ fatalsToBrowser /; } }


    --jwest

    -><- -><- -><- -><- -><-
    All things are Perfect
        To every last Flaw
        And bound in accord
             With Eris's Law
     - HBT; The Book of Advice, 1:7
    
Re: BEGIN and 'use' question
by jsprat (Curate) on May 07, 2002 at 18:19 UTC
    A BEGIN block will execute immediately (I use this term loosely:-), before any other code is run. This means your begin block runs before the comparison is made by the'&&' operator.

    To fix this, you want to check the value of DEBUG inside the BEGIN block, not prior to it.

    Update:Thanks, Elian for pointing out my mistake. I was answering why the begin block was executing regardless of the value of DEBUG. I didn't look carefully inside the BEGIN block to see that the OP was trying to 'use' a module in there.

      Aha! That's the information I needed - thanks!
      --
      man with no legs, inc.
        It's wrong, though.

        use is a compile time statement. As soon as the compilation phase gets to the end of the statement, the use is immediately executed. No conditionals will affect it (well, there's some stuff added recently, but we'll skip that for the moment) and it will happen. Throw a use inside a BEGIN block and all that'll happen is that the use will get used before the BEGIN block is fully parsed.

        If what you want is conditional inclusion, you need to do it the longer way, with require and import, both of which are runtime statements. Something like:

        BEGIN { if (DEBUG) { require foo; import foo; } }
        There's more documentation on this in the use section of perlfunc.
Re: BEGIN and 'use' question
by Anonymous Monk on May 08, 2002 at 12:41 UTC
    The first thing one must realize is that BEGIN is a special subroutine. sub BEGIN { ... }. But for certain subroutines (BEGIN END CHECK INIT DESTROY, did I miss any?) no sub keyword is needed. Now it's clear that one can't write DEBUG && sub BEGIN { ... } and expect it to be sane. But yes, it does indeed compile. This is when you come to hate indirect object syntax even more.

    The indirect syntax allows a block as it's first argument (so you can resolve the object, look at the documentation for print.) This means you can write method BLOCK and optionally have some arguments. Now, in DEBUG && ... the dots are expected to be an expression, not a sub declaration. So perl does what you asked it to: it parses an expression. BEGIN { ... } is an expression. It's indirect object syntax, and BEGIN is the method. do { ... } -> BEGIN Tricky eh?

    Now when we've got that straight we need to do what we want in another way. As already said you should use require and import instead of use. And since a BEGIN is a subroutine we can return from it.
    use constant DEBUG => 1; BEGIN { return unless DEBUG; require CGI::Carp; import CGI::Carp qw/ fatalsToBrowser /; }
    Cheers,
    -Anomo
      But for certain subroutines (BEGIN END CHECK INIT DESTROY, did I miss any?) no sub keyword is needed.

      I forgot AUTOLOAD. It's always the easy ones one forgets. :)

      -Anomo
Re: BEGIN and 'use' question
by cLive ;-) (Prior) on May 09, 2002 at 12:13 UTC
    For switching off CGI::Carp for command line testing, why not use:
    use constant DEBUG => $ENV{SCRIPT_NAME};

    That way it's automatically off when you run from the shell.

    .02

    cLive ;-)

    --
    seek(JOB,$$LA,0);

      That's a cool suggestion, cLive ;-), and I'll keep it in mind. I'm running the script from my local Apache though, not a shell, so it won't help for this one.
      --
      man with no legs, inc.