in reply to Bad news for IO::Handle magic

Don't use single-word all-upper-case package names.

Your example isn't the only way that you'll run into problems with such poor package names. Don't follow the bad examples of CGI.pm and CPAN.pm (which are badly named for more than just this reason, as anyone who ever tried to talk about "CGI" or "CPAN" knows; Net::CGI and Net::CPAN would be much better).

For that matter, don't use bareword file handles. Your example isn't the only way you'll run into problems using those.

Now, you can make an exception for STDIN, STDOUT, STDERR, and DATA. But if you really write "package STDIN;", then you deserve all of the grief you get.

Below are some other things you shouldn't do. Perl has a lot of DWIM features and DWIM always implies ambiguity and the possibility that Perl will misinterpet what you thought you meant.

Don't use single-word, all-lower-case subroutine names. If you do, then you can reduce your risk by either calling them like &mysub(...) or by putting them into a module (and then import them, use the full name with package name in front, or use OO).

Note that writing &mysub(...) will likely get you yelled at by people who think it is "bad style" or "looks like Perl 4" or some other bogus reason [such as confusing &mysub(...) with &mysub;].

And if you make the mistake of using a prototype, then you probably shouldn't be writing &myprototypedsub(...) but that's okay because using a prototype means you should put the function into a module anyway (but OO isn't an option in this case) -- and you should include an apology in the module's POD.

Similarly, don't use single-word, all-upper-case subroutine names or single-word all-lower-case package names.

In fact, don't use single-word package names. Make sure all of your package names contain :: (with exceptions for "main" or other package names that you don't get to pick).

Don't leave off parentheses when calling a function as part of an expression. If you use an assignment as part of an expression, put parens around it. If you use bit-wise operators, remember that their precedence just doesn't make sense and so put in explicit parens inside and out. Don't use here-docs; they break on invisible spaces (trailing spaces) or if you reindent. Don't use unless, it is confusing (even though it doesn't seem like it at first) and isn't any clearer (even if it seems so at first). use vars not our (as discussed in other threads). Don't use source filter modules. Use strict and (at least during development) enable warnings. etc. (:

- tye        

Updated: Moved a misplaced sentence.

Replies are listed 'Best First'.
Re^2: Bad news for IO::Handle magic (SWYM or sink)
by Stevie-O (Friar) on Jul 07, 2004 at 03:35 UTC
    While my examples always used STDIN, that was for brevity. Any code can play tricks on you if you use the Module->sub() OO syntax.
    $ perl -MCGI -le 'select(select(CGI)); print CGI->new' Can't locate object method "new" via package "IO::Handle" at -e line 1 +.
    This isn't limited to all-caps names, either:
    perl -MFile::Spec -le 'select(select(File::Spec)); print File::Spec->r +ootdir' Can't locate object method "rootdir" via package "IO::Handle" at -e li +ne 1.
    --Stevie-O
    $"=$,,$_=q>|\p4<6 8p<M/_|<('=> .q>.<4-KI<l|2$<6%s!<qn#F<>;$, .=pack'N*',"@{[unpack'C*',$_] }"for split/</;$_=$,,y[A-Z a-z] {}cd;print lc

      I said not to use bareword file handles. Using mixed-case bareword file handles is an even worse idea and you deserve any grief you cause yourself if you do that.

      Though, with other problems, I'm starting to think "File::Spec"->method() is the better syntax. But more than that I prefer putting the module's factory (which for many modules is simply the module's name) into a scalar, even better if this can be done as part of the use or require for the module.

      - tye        

      I'm curious to know how you found the select select trick.
        Stolen^WBorrowed straight outta Symbol's geniosym:
        sub geniosym () { my $sym = gensym(); # force the IO slot to be filled select(select $sym); *$sym{IO}; }
        --Stevie-O
        $"=$,,$_=q>|\p4<6 8p<M/_|<('=> .q>.<4-KI<l|2$<6%s!<qn#F<>;$, .=pack'N*',"@{[unpack'C*',$_] }"for split/</;$_=$,,y[A-Z a-z] {}cd;print lc
Re^2: Bad news for IO::Handle magic (SWYM or sink)
by Joost (Canon) on Jul 07, 2004 at 22:44 UTC
    Hi tye, good points, but I have a question about this remark:
    Don't use single-word, all-lower-case subroutine names. If you do, then you can reduce your risk by either calling them like &mysub(...) or by putting them into a module (and then import them, use the full name with package name in front, or use OO).

    I can see there is a potential problem in that calling single word subroutines without parentheses can be confusing to the parser, but what's the difference in this regard between all-lower-case subroutines and (for example) CamelCase subroutines? Or are you warning against redefining future keywords/build-ins?

    Joost.

      #!/usr/bin/perl use strict; # For debugging: sub dump { my( $name, $ref ) = @_; require Data::Dumper; my $dumper = Data::Dumper->new( [$ref], [$name] ); $dumper->Indent(1)->Useqq(1)->Terse(1); print STDERR $dumper->Dump(); } my $foo = "Test value"; dump( foo => $foo ); # Should instead used: #&dump( foo => $foo ); # ...

      produces:

      abnormal program termination

      Helpful, isn't it? I suspect quite a few people don't immediately see what the problem is. I also suspect that no small number of people could waste quite a bit of time trying to figure this problem out before the solution comes to them and they snack themselves in the forehead.

      Adding the & or renaming the sub to debugDump or moving the sub to a module will solve the problem.

      The problem is that dump is a built-in. I don't care to memorize the entire list of Perl built-ins nor to put my code at risk when new built-ins are added (rarely).

      - tye