Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Why no bareword warnings while inside of BEGIN

by JayBonci (Curate)
on Mar 22, 2004 at 22:32 UTC ( [id://338801]=perlquestion: print w/replies, xml ) Need Help??

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

Hey there, here's a question for the class. Why don't you get bareword warnings under "use strict" while you're in a BEGIN {} block. Here's some code:

#!/usr/bin/perl use strict; #use warnings; #require strict; sub BEGIN { #while(calldepth < 5) { } #$strict_error_here =1; }; sub foo { #while(calldepth < 5) { } } #while(calldepth < 5) { }

Some notes about the following code:
  • Uncommenting the while() inside of BEGIN throws no warning. Doing so with use warnings in effect gives a non-numeric warning, but still allows the code to loop forever.
  • Uncommenting the while in the subroutine foo() and by itself, both produce the warning under strict;
  • Placing a use strict; doesn't do anything inside of BEGIN
  • Uncommenting $strict_error_here actually causes a parse error
  • Switching the calldepth to something like calldepth++, also produces the error.


So I guess my question is, why doesn't a bareword throw an error inside of a BEGIN function (under strict)?

My second question is, is there any reason at all for perl to not warn you when comparing against a constant in a while() or unless() function, as in the functions above.

Any insight into perl's murkiness here would be great


    --jaybonci

Replies are listed 'Best First'.
Re: Why no bareword warnings while inside of BEGIN (more)
by tye (Sage) on Mar 22, 2004 at 23:20 UTC

    It appears that the test for barewords happens after compiling is finished. The test for undeclared variables also appears to wait until compilation is finished but happens sooner:

    > perl -w use strict; BEGIN { while( calldepth < 5 ) { sleep 1; } print $n; } Global symbol "$n" requires explicit package name at - line 6. BEGIN not safe after errors--compilation aborted at - line 7.

    Note that I don't even have to type end-of-file there but that the error didn't appear until I finished the BEGIN block. If the infinite loop ever finished, then you'd get the 'bareword' error:

    > perl -w use strict; BEGIN { my $n= 5; while( calldepth < $n ) { warn $n--; } } Argument "calldepth" isn't numeric in numeric lt (<) at - line 4. 5 at - line 5. 4 at - line 5. 3 at - line 5. 2 at - line 5. 1 at - line 5. my $x = 5; BEGIN { warn "interesting" } Bareword "calldepth" not allowed while "strict subs" in use at - line +4. BEGIN not safe after errors--compilation aborted at - line 12.

    Note that I still didn't have to type end-of-file. And it didn't take until the file was finished being compiled. So it seems like this might be a problem that can be fixed. The BEGIN block can't be run until it is done being compiled. The check for barewords is happening after the block is done being compiled but after the block is run.

    So the next step is to figure out why it waits (until a subsequent BEGIN block is declared, in the above example) before the check for barewords is done?

    Updated.

    - tye        

      The code to execute BEGIN immediately doesn't properly check the compilation error flag before executing the block. Here's a patch against 5.8.3:
      --- op.c.orig 2004-03-22 16:59:09.000000000 -0800 +++ op.c 2004-03-22 16:59:25.000000000 -0800 @@ -4359,7 +4359,7 @@ if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I') goto done; - if (strEQ(s, "BEGIN")) { + if (strEQ(s, "BEGIN") && !PL_error_count) { I32 oldscope = PL_scopestack_ix; ENTER; SAVECOPFILE(&PL_compiling);
      It already appears to be fixed in 5.9.1.
Re: Why no bareword warnings while inside of BEGIN
by Limbic~Region (Chancellor) on Mar 22, 2004 at 22:57 UTC
    JayBonci,
    If you want to see it blow up you will have to do:
    BEGIN { while( calldepth < 5 ) { last; } }
    From perldoc perlmod
    A BEGIN subroutine is executed as soon as possible, that is, the moment it is completely defined, even before the rest of the containing file is parsed.

    You have put it into an infinite loop - never giving it a chance to throw the error.

    Cheers - L~R

      The BEGIN block *can't* be run until the block is finished being compiled. If the block is finished being compiled, it is reasonable to expect that barewords would have been detected. As I show elsewhere, other types of 'strict' errors are handled correctly here.

      So I don't see how your reading of the documentation explains this problem away. The quoted section says that it runs before the "rest of the containing file is parsed". The error is in the code being run. It certainly can and should report fatal errors in that code before it runs it.

      - tye        

        tye,
        So this is a bug/feature, I see it in your reply below.
        I thought:

        Because a BEGIN block executes immediately,...

        Meant that it executed and then execeptions were thrown. After running it through perl -MO=Deparse, I thought it was expected behavior since it doesn't seem to matter what kind of loop it is - the error isn't thrown until after it is completed.

        Cheers - L~R

        Update: Changed bug/feature to statement rather than question after seeing tye's reply further down in thread

Re: Why no bareword warnings while inside of BEGIN
by ChemBoy (Priest) on Mar 22, 2004 at 22:54 UTC

    I don't know the answer, but I suspect it has to do with the "run-as-soon-as-possible" nature of BEGIN blocks. One reason I suspect this is that if you change calldepth < 5 to calldepth > 5, you get a bareword error. Also, you get a bareword error (or at least, I do) if you run a similar one-liner:

    perl -e 'use strict;BEGIN{if (bareword > 1) {1} }'
    which probably makes the answer obvious to some people, though it doesn't to me. :-)



    If God had meant us to fly, he would *never* have given us the railroads.
        --Michael Flanders

      Okay, so a pared down example of why this is kinda scarry is this:
      perl -e "use strict; BEGIN { while(bareword < 1) {1} }"
      Cycles forever. No error
      perl -e "use strict; BEGIN { while(bareword > 1) {1} }"
      Throws the bareword error ...wierd. --jay


          --jaybonci
        JayBonci,
        See my post below. The while loop is infinite because 0 < 1. It never enters the loop when 0 > 1. Not throwing the error until after the code is run may or may not be expected behavior as tye points out.

        Cheers - L~R

Re: Why no bareword warnings while inside of BEGIN
by muba (Priest) on Mar 22, 2004 at 22:41 UTC
    update: nevermind

    Just know that a BEGIN block is not marked by a sub keyword. You just use BEGIN {...}

    Also, IIRC, the strict and warning pragma's are imported *after* the BEGIN block. But it's very good possible I'm wrong here.
      Also, IIRC, the strict and warning pragma's are imported *after* the BEGIN block.

      There's one way to find out :)

      $ perl use strict; BEGIN { $x = 'y'; $$x = 1; print $y } Global symbol "$x" requires explicit package name at - line 2. Global symbol "$x" requires explicit package name at - line 2. Global symbol "$y" requires explicit package name at - line 2. BEGIN not safe after errors--compilation aborted at - line 2.

      As it turns out, use calls reduce to BEGIN blocks and BEGIN blocks fire in order of encountering.

      A BEGIN block is not marked by the sub keyword. Instead, you just use BEGIN {...}

      It can be, though. "sub BEGIN" doesn't create a normal sub called BEGIN, but it is valid syntax. In fact, it is how B::Deparse deparses BEGIN blocks. The same goes for CHECK, INIT and END. See also what perlmod has to say about this.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

require strict?
by Anonymous Monk on Mar 22, 2004 at 23:08 UTC
    what do you mean require strict? That's no good

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://338801]
Approved by Vautrin
Front-paged by Vautrin
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (5)
As of 2024-04-24 07:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found