Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re^5: RFC: Creating unicursal stars (agism)

by Your Mother (Archbishop)
on Nov 09, 2009 at 23:09 UTC ( [id://806069]=note: print w/replies, xml ) Need Help??


in reply to Re^4: RFC: Creating unicursal stars (agism)
in thread RFC: Creating unicursal stars

I'll preface by repeating, your advice is generally to be preferred over mine. I know what an excellent hacker and thinker you are. That you got snarky and got the version stuff wrong in your rush to put me in my place makes me think this particular topic is personal to you. It's not to me.

So, did you actually have any real critique to offer (other than the one style point)? I'm sure people would love to learn what can be improved and how (and why).

I was responding to the assertion that it was an excellent template to be emulated or used by anyone. To me, style-wise, it reads like a C-hacker's impression of perl 5.4. Which is fine. I just personally find it jarring and wouldn't recommend it.

#!/usr/bin/env perl is a nice idiom which I think is better than the one you use and I used to. It would have saved me a lot of headaches earlier this year if I had been using the env trick all along.

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.

The part I see in there that might have saved me headaches in my own stuff is the Main(@ARGV) but I think that has more to do with me misunderstanding ARGV for a long time than anything else.

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.

The fact that you end up using camel and underscores together sort of underscores my point that it's bad style. I see the issue it "saves" you from. I have never hit it. I think the last time we had this discussion your justification was that it was necessary because of CGI::Tr. If you really see the "reserved word" as a serious problem, patching perl might be a better idea. I never saw the message before because I either use strict or call subs with more explicit syntax.

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.

Replies are listed 'Best First'.
Re^6: RFC: Creating unicursal stars (thanks)
by tye (Sage) on Nov 12, 2009 at 06:47 UTC
    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.

    - tye        

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://806069]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2024-04-24 19:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found