I'll preface by repeating, your advice is generally to be preferred over
mine. I know what an excellent hacker and thinker you are.
Thank you. I'm happy to acknowledge the compliment (if for no other reason
than to stop you from repeating it a third time :). But, FYI, I don't need my
ego stroked. I've argued here where I disagree, not because I got my feelings
hurt.
Regarding updates: if it's meant to be a living doc, it shouldn't be in a
SoPW reply where the updates are not dated and the piece itself says the code
is older than 2000.
Feel free to post nodes how you prefer. I might repost this when I have
something more significant to add to it. I could've put dates on my "update"
notices but I'm not usually personally hung up on the date of advice so I
didn't. I don't see how "2000-12-07" indicates "older than 2000". It seems
you didn't pay much attention if you actually thought that the node contents
hadn't been updated since the end of 2000.
#!/usr/bin/env perl is a nice idiom which I think is better than the
one you use and I used to.
That always seemed rather hackish to me. But I can see some cases where it
would be a good choice. Since I haven't heard any real problems reported
against it after all of this time, I'm less leary of using it. I'd rather
the kernel just supported #!perl ... for cases where "the first perl
executable in my current $ENV{PATH}" is the right choice, but it doesn't
(that I've seen). Given that many people still seem to be set against
accepting Larry's advice about /usr/bin/perl, I may even adopt your suggestion
as the best/right thing to use when publishing a Perl script.
Putting in a piece of boiler plate which serves (mostly?) to help
Apache::Registry which is as I understand it, a shim to give one time to get
one's code correctly setup for modperl seems like a mistake.
Well, that seems like a bit of an abuse of the term "boilerplate" to describe
the single keyword "BEGIN". And, no, the "BEGIN" is not even mostly about
mod_perl / Apache::Registry. It is about making sure that "static"
("state", whatever) variables are initialized before they get used. It is
also about pointing out that initialization code needs to be run even if
"run time" has not yet reached the subroutine definition (or will never, such
as due to the explicit 'exit(0)' at the top, as I noted). It is also about
encouraging only simple initializations in such places, initialization that
can be done safely at compile time.
And it is part of a pattern for dealing with initializations in Perl.
Initializations in Perl have been a source of problems for a long time.
I think I've finally put together a pattern that makes enough of an
improvement here that I'm just finishing up a module to help address
the problems (as I already mentioned).
Someone has notched up the "error" output of one of my modules by turning on
$^W in one of the dependencies (and displaying tons of harmless warnings
about yet another dependency, not my code). I think it's great for
development. I don't think you should do things that cause secondary effects
in other code for production.
I'm not completely sure I understand your first sentence, in particular what
"someone has" is meant to convey. I think you are describing a real incident
from the past, so you might want to clarify if I'm incorrect about that.
There seem to be a lot of people who think that warnings that originate from
a module are due to code from that module. That is certainly sometimes the
case. But I find that warnings are much more context-sensitive than most
fatal errors. For example, warnings are often about data. And data often
originates from outside the module where the warning was generated.
Then there is the impression that testing with warnings enabled will tell you
whether warnings will be generated when the code goes into production. I find
that warnings are much more likely than fatal errors to appear in production
when they never showed up in testing. So I often won't enable even
"use warnings;" in the main script when it goes into production.
So, yes, I have more than once written about disabling warnings when going into
production. If I can arrange for warnings to not be seen by the users and
to be routed back to the proper developers, then I'll leave warnings enabled
in production.
The example template is more about scripts that I write for my own use, though
(no, I didn't make that clear, but it is also doesn't matter except on this
one point). And I like to turn on warnings globally. If that causes a bunch
of pointless warnings (not usually the case, in my experience), then I'll
deal with that.
In particular, I think it is a pretty bad idea to "use warnings;" inside of
module code. Indeed, the old practice (of only having warnings enabled or
disabled based on the main program) created problems (which lead to the
creation of warnings.pm). I really like warnings.pm, but I think the
simplistic way people are encouraged to use it has as many problems as the
situation from before it existed.
And the above actually gives me an idea for a module. (But, no, I don't feel
like going into that at this time.)
by turning on $^W in one of the dependencies
Gawd, what an awful idea. Of course, my template didn't encourage such.
The fact that you end up using camel and underscores together sort of
underscores my point that it's bad style.
No, it underscores that I don't have a violent personal pet peeve against
either style. So you are implying that you don't use both styles? So you
must refuse to use a huge fraction of CPAN. As I noted, simply loading
ExtUtils::MakeMaker requires use of CamelCase.
A better example is probably DBI which pretty consistently uses
under_scored identifiers for methods and CamelCase identifiers for standard
attributes (hash keys). I'd personally reverse that choice since hash keys
don't have to worry about conflicting with reserved words (even without
quoting, at least since some rather ancient version of Perl 5). But if you
don't "use both", then I guess you refuse to use DBI.
I see the issue it "saves" you from. [....]If you really see the
"reserved word" as a serious problem, patching perl might be a better idea.
I'm not sure what you think you "see", but you clearly don't understand what
I'm talking about even after I tried to explain it to you twice. It would be
far more than a "patch" to Perl to eliminate the possibility of conflicts over
reserved words when using (sigil-less) function names.
I think the last time we had this discussion your justification was that it
was necessary because of CGI::Tr.
Yeah, it seems that you may not have took in much of what I said back then.
It seems clear that you didn't understand it. I'm not sure what "necessary
because of CGI::Tr" even means, though. But by your own argument, the fact
that CGI.pm was forced to resort to capitalization against the
author's chosen style (under_scored) demonstrates that the style choice was
a bad choice.
I choose to use both styles. I am not forced to abandon my
style choice.
I use under_scored-style identifiers for subroutine names because I work on
software where that was the style already chosen. I don't choose that style
for subroutine names on new projects because, as CGI::Tr (and CGI::Sub)
demonstrates, that can get you into trouble. It can get you into a few
different types of trouble regarding conflicts with different classes of
reserved words.
I never saw the message before
The "future reserved word" warning was a simple demonstration of the fact
that using an /^[a-z]+$/ identifier is acknowledged as being a bad idea
because there are no guarantees that such might not become a reserved work
in a future version of Perl. The warning itself is not a problem that I'm
trying to avoid much less "the problem".
because I either use strict or call subs with more explicit syntax.
Calling (non-method) subs with more explicit syntax doesn't help. For example:
Go ahead, write a sub called tr() and call it. I'll wait. [Perl doesn't
mind in the least you writing a subroutine called tr(), BTW.]
Okay, I'm willing to bet money that you didn't resort to &tr(...)
because you seem to be way too caught up in style issues (that would surely
"look like Perl 4" and feel "jarring", no?). But the alternatives that also
work are even uglier.
The early design of Perl used sigils to prevent the problem of user identifiers
conflicting with Perl's built-in identifiers. The use of sigils was done in a
way where they were more useful than just preventing namespace conflicts and
so many Perl programmers now like sigils. But the ampersand sigil for
calling user-defined subroutines didn't provide any other benefits and so the
push to nearly deprecate it (as ugly, unnecessary "noise") shouldn't have been
a big surprise.
But it would have been nice if that push had been accompanied by tools to save
people from wasting time when they stumbled across such namespace conflicts.
It wasn't until Perl 5.8 that we got any warnings for this. But most of the
cases still just silently don't work. Even Perl 5.10 is still happy
as can be to let you write:
#!/usr/bin/env perl -wl
use strict;
sub x { return "ex" }
sub y { return "why" }
print y( $foo );
print x( $foo );
Unfortunately, even warning for conflicts with existing reserved words wouldn't
be enough. Because an old version of Perl still wouldn't warn you about
"sub our { ... }" but you'd still get burned by that choice when you upgraded
Perl. And even if you chose "sub state { ... }", you'd still have to rename
it eventually (and still might get burned when you didn't notice that
"use Modern::Perl;" broke your code, etc.).
It is hard enough for me to have a perfect memory of every current Perl
reserved word. It is impossible for me to predict every future Perl
reserved word. So I choose to not have to worry about either these days.
I've wasted time long ago by writing "sub dump" or "sub log" and I've
seen CGI.pm have a quirky interface because of "sub Sub" and "sub Tr".
(I wish CGI.pm supported $q->sub() and $q->tr() since I don't use the
export-dozens-of-functions interface to CGI.pm anyway.) And I've seen
other people waste time.
An honest version of Perl would warn about "sub frob { ... }" with "Use of
all-lowercase subroutine name may conflict with future reserved word".
But such honesty will never be implemented. :) Maybe Perl 6, which
distinguishes subs from methods has a better story here.
And it'd be nice print if( $foo ); checked for &if being defined
and issued a warning at that point. (But then foo() would always issue
a warning because 'foo' could always become a future reserved word, so this
will never happen -- too much attachment to style issues for that.)
Perl 5.10 took a new approach and decided that it just couldn't get away with
adding more reserved words by default. But this is causing its own set of
friction and so might not be the way things happen when the next reserved
word(s) are added. Nor does it completely prevent a conflict from causing
you problems. But I don't have to care.
So, to nail down some details: Method calls don't care about reserved words.
Imported functions only fail against some reserved words (for the
others, they actually override the built-in, which can still be a problem if
it is done by accident and there is no way to tell Perl that you meant
to export over the top of a reserved word). Local subroutines have the worst
problems because they can't be called if they conflict with any
reserved word (unless you use & or call it as a method). At least
Perl finally gives a warning for some of those last cases.
#!/usr/bin/env perl -lw
use strict;
package Test;
sub if { return "if($_[-1])" }
sub log { return "log($_[-1])" }
BEGIN {
*main::if= \&if;
*main::log= \&log;
}
my $foo= 1;
$_= 'Oops!';
$|= 1;
print if( $foo );
print Test->if( $foo );
print log( $foo );
print '';
package main;
print if( $foo );
print main->if( $foo );
print log( $foo );
produces:
Ambiguous call resolved as CORE::log(), qualify as such or use & at -
+line 16.
Oops!
if(1)
0
Oops!
if(1)
log(1)
in your rush
Replying over 50 hours later is considered "rushing" by you? What word do
you use for your replying after 2.5 hours (or even originally after 23 hours),
then? I hope that demonstrates how skewed your impression can be.
That you got snarky
Um, snarky is more about my natural state than some emotional response.
My snark is almost always delivered with a smile. You might want to paint
your response as dispassionate and mine as something else. But I'm glad you
don't appear to have been cowed (which wasn't my intent nor desire) and
provided useful feedback. Most of the above response was helpful, mostly in
pointing out areas where I can explain better (I never explained the thing
much).
makes me think this particular topic is personal to you
Well, would you expect otherwise after criticizing my personal
collection of best practices collected over a span of years and criticizing
with no actual information content, just vague disparagement? But taking the
first response somewhat personally doesn't mean my response was irrational. :)
and got the version stuff wrong
Yeah... right.
To me, style-wise, it reads like a C-hacker's impression of perl 5.4.
When I first posted it, I noted that it might look like somebody trying to
cling to writing in a C style but wasn't. When I finally needed a sub, I
chose "main" as the name due to (like much of Perl syntax) inspiration from
C. But the final form was more in spite of it appearing "like C" than
because of it.
The first point was to stop scattering executable code all over, particularly
between subroutine definitions. The second point was to provide a limited
scope for variables that should be local to the main body of code. The third
point was to not manipulate command-line arguments directly via @ARGV as it
complicated some refactoring attempts (this also keeps @ARGV unmodified which
has been useful several times). And it was about having a place to skip to
when debugging, as I mentioned.
The "5.4" style is because if it ain't broke, little point in fixing it.
You seem much more obsessed with "style" than I. And when writing modules
I'm very much more likely to write in a "style" that doesn't preclude people
from using my module with, for example, 5.6.0. Less than 2 years ago, when
writing even main scripts for work, I needed to make sure they would work on
5.6.0 as well, at least if I expected some co-workers to use them.
Plus there are the reasons I already touched on where the "new" way isn't
always better (unless you can't deal with the code not being stylish
enough).
Thanks again for the feedback. It was quite helpful.
|