Today I wrote a script in which I had a sub declaration near the top:
sub chk_timer;
then at some point one or more lines like
chktimer $_ for @timers;
and at the end the actual sub definition:
sub chktimer { # ... }
As you can see I mistyped the declaration, or changed my mind way through. Whatever, perl -c told me everything was OK. Incidentally, I always
use strict; use warnings;
However I couldn't spot that typo and what I got was a runtime error:
Can't access `chktimer' field in class Proc::ProcessTable::Process at +./scriptname.pl line 75
instead. BTW: unfortunately in this case, the condition in which the actual line(s) in which the (alleged) function call is executed is very rare, so I had to wait quite a while until I could spot that error.

Now, of course perl has no way to understand that chk_timer was a typo for chktimer, but I wonder if it could be sensible to have a warning about subs that have been declared but not defined.

I can foresee objections to such a proposal in terms of deliberate symbol table manipulations, but even then I'm not really sure what the best choice could be... this is just a meditation after all!

Replies are listed 'Best First'.
Re: Warning for "unused sub declarations"?
by chromatic (Archbishop) on May 19, 2005 at 17:47 UTC

    How could Perl know this in the face of AUTOLOAD, run-time module loading, and symbol table manipulation?

    The best I can see it doing is trying to resolve subroutine calls as they happen and throwing errors if it can't find them.

    (I think your code has a bareword problem that makes it give an ambiguous error message, but that's just a guess looking at the snippet and not its context.)

      How could Perl know this in the face of AUTOLOAD, run-time module loading, and symbol table manipulation?

      It wouldn't be foolproof, but could the warning be somewhat like the "Name %s used only once" warnings with package variables? Example included for those who don't know what I'm talking about:

      $ perl -wle '$foo = 1; print 5' Name "main::foo" used only once: possible typo at -e line 1. 5

      Not to mention even $obj->$method( ) or $methref = $obj->can( "kwyjibo" ).

Re: Warning for "unused sub declarations"?
by brian_d_foy (Abbot) on May 19, 2005 at 18:49 UTC

    A warning for subs that you declare but then don't use would be really annoying for those who are doing more advanced things behind-the-scenes. I might want to declare a subroutine name, but then define it at run-time.

    In this case you declared two different subroutines names and only happened to use one. However, perl can't know that you are only going to use one until you are completely done with the program.

    I don't run into this problem because I like parens that give perl a bit of extra help with the parsing (and keep maintenance programmers from getting too confused too).

    chk_timer( $_ ) for ...;
    --
    brian d foy <brian@stonehenge.com>
      But then your argument is just as valid for the annoying warning about a possible typo when using a package variable only once. Who says, I don't do advanced things behind-the-scenes then?

      So if Perl warns me in this case, why not when declaring and failing to define a subroutine?

      Paul

        I don't like that "variable used once" either. If I've declared a variable so that use strict doesn't complain, but I only use it once, I don't want to see a warning. I've seen a lot of code that uses a variable in void context just to get around that warning.

        --
        brian d foy <brian@stonehenge.com>
      A warning for subs that you declare but then don't use would be really annoying for those who are doing more advanced things behind-the-scenes. I might want to declare a subroutine name, but then define it at run-time.
      Indeed in the very same script I had
      sub killp; *killp = DEBUG ? \&_killp_debug : \&_killp_real;
      although I bet that many Perl hackers wouldn't regard this as a good practice.

      However we already do e.g.

      no strict 'refs'; # and no warnings 'uninitialized';
      all the time. A 'used only once' warning as suggested by someone else wouldn't be that bad after all.
      I don't run into this problem because I like parens that give perl a bit of extra help with the parsing (and keep maintenance programmers from getting too confused too).
      Well, that's to a very large extent a matter of personal preferences, just like so many other things in Perl. I find code having as few parentheses as possible to be best readable.
        I find code having as few parentheses as possible to be best readable.

        Depends. There are some situations where parens add clarity, and there are others where they don't. Generally speaking, if there's a significant potential for someone's not having memorized the precedence table to result in confusion, it's better to include the parens, but otherwise you can leave them off. Obviously, different people have different threshholds for how divergent the precedences in question have to be before the potential to misread is sufficiently small to justify leaving off the parens, but I think in principle most of us can agree that there are some pairs of operations with a very similar precedence, in which case the parens add clarity, but there are other pairs of operators that have such markedly different precedence that any clarity the parens add is extremely marginal and not worth the tradeoff. It becomes a question, then, of where to draw the line.

        A good example of the latter scenerio is when you're using the loose-binding spelled-out logical ops to join together expressions containing tightly-bound operators, as in $foo .= <BAR> or return $foo;. Nobody with significant Perl experience needs parens to help them through that one. On the other end of the scale you can have expressions that include bitwise operators and other relatively obscure ops for which many people don't remember the precedence. In those cases, the parens are a Good Idea.


        "In adjectives, with the addition of inflectional endings, a changeable long vowel (Qamets or Tsere) in an open, propretonic syllable will reduce to Vocal Shewa. This type of change occurs when the open, pretonic syllable of the masculine singular adjective becomes propretonic with the addition of inflectional endings."  — Pratico & Van Pelt, BBHG, p68
Re: Warning for "unused sub declarations"?
by revdiablo (Prior) on May 19, 2005 at 17:04 UTC

    I don't know much about how this kind of thing would be implemented, so I don't know whether it's feasible or not. But I just wanted to put my voice out there as agreeing to this. I think it would be a good idea, if at all possible.

    You say there might be people who complain because they want to do symbol table manipulation, or similar things. Well, they can just turn off that warning. :-) People who are used to doing fancy things are already accustomed to turning off warnings and stricture when they need to. I can't see how this would be a major problem for them.

Re: Warning for "unused sub declarations"?
by thor (Priest) on May 19, 2005 at 18:36 UTC
    I'm no expert, but is it necessary to put a sub declaration there at all? Whenever I write a program, the only time a sub is mentioned when it's defined, and I put all of my sub definitions at the end of the file. I've never had a problem.

    thor

    Feel the white light, the light within
    Be your own disciple, fan the sparks of will
    For all of us waiting, your kingdom will come

      Run this:

      #use strict; use warnings; sub bar { print $foo; } my $foo = 1; foo(); bar(); sub foo { print $foo; }
      Now uncomment out the use strict; and run it. FWIW, i do the same as you ... but yes, there are consequences.

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      B--B--B--B--B--B--B--B--
      H---H---H---H---H---H---
      (the triplet paradiddle with high-hat)
      
        Maybe I'm a little slow, but are you and I talking about two different things? As far as I can tell, your bar routine depends on the global variable $foo which doesn't exist when bar is defined. What I was talking about was the need (or lack thereof) to put a superfluous declaration of all user-defined subs at the beginning of the file.

        thor

        Feel the white light, the light within
        Be your own disciple, fan the sparks of will
        For all of us waiting, your kingdom will come

      If the sub isn't declared or defined before use, then you can't call it like a builtin - without & and parentheses around the arguments. That's the main disadvantage for me.
      chas
        If the sub isn't declared or defined before use, then you can't call it like a builtin - without & and parentheses around the arguments. That's the main disadvantage for me.
        Huh?!? You're joking? Indeed I do declare my subs to be able to call them without parentheses - fair enough. But it is never stressed enough that in Perl5 (as opposed to Perl4 and previous versions) the &-form of of sub call should never ever be used unless you really need it, i.e. you do know what you're doing. See perlsub.
        Fair enough. But, now I'm curious. Since Perl doesn't have type checking, what good does declaring the subroutine get you? Why is perl not able to parse the file, say "hey, chas has subroutines foo, bar, and baz, so if I see them referenced, I'll use them"? Just seems odd to me.

        thor

        Feel the white light, the light within
        Be your own disciple, fan the sparks of will
        For all of us waiting, your kingdom will come

Re: Warning for "unused sub declarations"?
by ambrus (Abbot) on May 19, 2005 at 20:50 UTC

    It is for the sake of C compatibility that there is no such warning:)