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

Dear Brethren and Sisters,

with the following code

#!/usr/bin/perl use strict; use warnings; my $val = $Some::Nonexistent::Pkg::variable;

Perl tells me (exactly as expected):

$ ./warnme.pl Name "Some::Nonexistent::Pkg::variable" used only once: possible typo +at ./warnme.pl line 6. $ _

When putting this same code in a module I would have expected to be warned similarly. However, no messages, nothing. Even quieter than Perlmonks on weekends.

___ ./WarnMe.pm ___

package WarnMe; use strict; use warnings; my $val = $Some::Nonexistent::Pkg::variable; 1;

___ ./warnme.pl ___

#!/usr/bin/perl use strict; use warnings; use WarnMe; # ...

___

$ ./warnme.pl $ _

Is this the way it's supposed to work? Can't I take advantage of this used only once: possible typo warn facility within modules? I couldn't find anything related in the docs...

( I've been playing with this for a while now, and although, for the life of me, I can't tell what I'm doing wrong, I have that sneaking feeling this is going to be something embarrassing for me in one way or another... But what the heck? Your chance to tell a little chick how Perl really works ;)

Replies are listed 'Best First'.
Re: "possible typo" warnings in modules
by diotalevi (Canon) on Feb 17, 2007 at 18:35 UTC

    The answer is that the warning does not apply to modules. I assume the expectation is that referring to some other global in a module might not be unusual.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: "possible typo" warnings in modules
by almut (Canon) on Feb 17, 2007 at 19:46 UTC

    Thanks for your answers, everyone - and diotalevi in particular.   A couple of related questions:

    How exactly is "in module" defined? Playing some more with this shows that do "WarnMe.pm"; for example (instead of use WarnMe;) also does not yield the warning (with or without the package declaration).

    Is there some way to enable/force this warn feature explicitly in modules?

    Is there a listing somewhere (within source code is fine) of which warnings do apply in which contexts (like "in module", etc.)?

    Thanks.

      For this particular warning, "in-module" means the path to it is absolute, it has /lib/ in in somewhere or the name has a .pm in it. I don't think you can really abstract the idea of "in module" elsewhere. This was a pretty specific bit of code.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        Thanks again.   I actually looked it up in the sources now (guess I should've done so earlier), and I presume it's this part in Perl_gv_check(), gv.c:1251:

        /* performance hack: if filename is absolute and it's a standa +rd * module, don't bother warning */ #ifdef MACOS_TRADITIONAL # define LIB_COMPONENT ":lib:" #else # define LIB_COMPONENT "/lib/" #endif if (file && PERL_FILE_IS_ABSOLUTE(file) && (instr(file, LIB_COMPONENT) || instr(file, ".pm"))) { continue; } CopLINE_set(PL_curcop, GvLINE(gv)); #ifdef USE_ITHREADS CopFILE(PL_curcop) = (char *)file; /* set for warning */ #else CopFILEGV(PL_curcop) = gv_fetchfile(file); #endif Perl_warner(aTHX_ packWARN(WARN_ONCE), "Name \"%s::%s\" used only once: possible typo", HvNAME_get(stash), GvNAME(gv)); ... with PERL_FILE_IS_ABSOLUTE being defined as (for my platform): #define PERL_FILE_IS_ABSOLUTE(f) (*(f) == '/')

        So, I removed the .pm extension (the other two criteria, i.e. /lib/ and absolute path, don't apply in my case -- I even checked with strace(1) what it's really loading). (Update: actually, taking a closer look, I see it's PERL_FILE_IS_ABSOLUTE(file) && ..., so the other two shouldn't apply anyway...)

        Interestingly, still none of the following do issue the warning:

        require "WarnMe"; --- do "WarnMe"; --- my $code = join '', <DATA>; eval $code; __DATA__ my $val = $Some::Nonexistent::Pkg::variable; --- eval 'my $val = $Some::Nonexistent::Pkg::variable';

        Well, I guess some other hack is playing tricks on me...   Anyway. :)

Re: "possible typo" warnings in modules
by Sagacity (Monk) on Feb 17, 2007 at 18:13 UTC

    almut, The main difference that I can best express to you about your two scripts is this:

    When you are writing code and executing the warnme.pl script, the call to

    my $val = $Some::Nonexistent::Pkg::variable;

    tells Perl to find and use that pre-existing package and assign its value to $val .

    When you are coding in the package warnme.pm, the call to

    my $val = $Some::Nonexistent::Pkg::variable;

    tells Perl to search for the pre-existing package, but if not found, CREATE the package and assign it to $val .

    Now I am sure that I don't have it nailed down exactly, but in concept, I believe I am right.

    A study of perlboot, perltoot, and perlobj will help distinguish the differences more clearly.

    A look at ISA may shed some light on this, as well.

      You are wrong. They are both compiled identically. The statement my $val = $Some::Nonexistent::Pkg::variable does a lookup to the glob *Some::Nonexistent::Pkg::variable in both cases. As I said in my other node, the warning is disabled for modules.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: "possible typo" warnings in modules
by zentara (Cardinal) on Feb 17, 2007 at 17:52 UTC
    I'm no expert at this, but it appears to me that at compile time, the Perl interpreter only scans the modules for "syntax errors", it dosn't eval every statement to see if they are good in reality.
    my $val = $Some:Nonexistent::Pkg::variable; # a missing :
    or
    my $val = $Some::Nonexistent::Pkg::variable; my $val; print $val;
    will yield errors.

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum

      You are wrong. There is no separate check for "syntax errors" and later for "evaling." It sounds like your mental model of perl's internal workings are far off. Perl compiles into the same form, always. This form is directly executable. Code that is present at a module's file or "top" level is run just as soon as the file has finished being compiled.

      I have the impression that you think perl is executing the statements by uh "evaling" them as source code at runtime kind of like bash or DOS batch files. That is far from the truth. The directly executable form I already mentioned is closer to being like an internal or hidden lisp. As perl reaches each instruction, it just follows a C function pointer to run each instruction. Every instruction returns the address of the next instruction in memory so the runloop does this very much like for ( $op = START; $op = $op->(); ){}.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        Well how do you account for the behaviour that there are no errors when the syntax is correct, but an error when the syntax is wrong ( like a missing colon or scalars define twice with my)? Then if the syntax is ok, it lets it run and evaluation errors appear at runtime?

        UPDATE added example

        For instance this will stop at compile time:

        #!/usr/bin/perl use strict; use warnings; use lib '.'; use WarnMe; print "1\n"; print $WarnMe::val,"\n"; print "2\n";
        package WarnMe; use strict; use warnings; # syntax error my $val = $Some:Nonexistent::Pkg::variable; 1;
        outputs:
        zentara@:zentara$ ./WarnMe Global symbol "$Some" requires explicit package name at WarnMe.pm line + 7. syntax error at WarnMe.pm line 7, near "$Some:" Compilation failed in require at ./WarnMe line 5. BEGIN failed--compilation aborted at ./WarnMe line 5.

        Clearly the Perl compiler is checking syntax first. If you fix that syntax error, the script will compile and run with issuing a non-fatal runtime error:

        Name "WarnMe::val" used only once: possible typo at ./WarnMe line 8. 1 Use of uninitialized value in print at ./WarnMe line 8. 2

        I'm not really a human, but I play one on earth. Cogito ergo sum a bum

      it dosn't eval every statement to see if they are good in reality.

      First of all, it can't. For example, how could it run a statment before its containing block has finished compiling?

      Secondly, it's impossible to detect most programming errors. For a system to check for errors, it would have to know what you are trying to do, but if it knew what you wanted to do, there would be no need to write a program to tell it what to do. It is possible for the system to look for patterns that usually result in errors. When Perl detects such a pattern, it issues a warning. Some at compile-time, some at run-time.

      Finally, how does your post relate to its parent post?