Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

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

by tye (Cardinal)
on Nov 09, 2009 at 20:35 UTC ( #806015=note: print w/ replies, xml ) Need Help??


in reply to Re^3: RFC: Creating unicursal stars
in thread RFC: Creating unicursal stars

To be fair, Your Mother is from before 2000 (though I don't recall using Perl v2 that year) and was probably conceived even before that. That is clearly enough reason to discount something with no further justificaiton. Oh, wait, I forgot to make a dubious style argument. Unfortunately, most have not seen how he dresses, so I'll omit that. (:

was probably mostly developed even earlier

Perhaps you are unfamiliar with the meaning of the words "updated" and "update"?

Actually, much (I'm not sure "most") originated before 2000. And I've updated it quite recently (and several times before that) and so anything from before 2000 must be some of the best of that style since it has survived unchanged for so long.

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).

As to CamelCase, I'll disagree that it is bad and also that it is uncommon in Perl. I seriously doubt you are using the modules file_handle, ext_utils::make_maker, dyna_loader, auto_loader, math::big_int, or time::hi_res to name just a tiny fraction. And the motivations for using CamelCase in module names at least partly matches my motivations for using it in subroutine names.

Compare the output of perl -we "print this" vs. perl -we "print This" and you'll see that the second avoids:

Unquoted string "this" may clash with future reserved word

Unfortunately, it seems that most Perl guides pretty much ignore the problems with the following code:

sub log { warn timestamp(), "@_"; } sub dump { log( Dumper( \@_ ) ); }

I expect a significant fraction of serious Perl coders to notice the problem with line 1 (I'm not sure if it would be more or less than half of them). I expect only a small fraction to notice the problem with line 5. I expect many to go so far as to deny the problem with line 2.

Personally, I much prefer a style that simply prevents all of those problems. Which means I updated my standard template to not use "sub main". The two routes I considered were CamelCase and under_scored. under_scored would have meant either "sub _main" or "sub main_" and the former of those already is well-established style for "private" and so would be quite confusing while the latter I consider rather silly looking and much, much more unusual than "sub Main", which is what I standardized on. (And going with "sub Main" with the intent of keeping underscores would lead to the Under_Scored_Capitalized style which I find rather "the worst of both worlds".)

I don't personally grumble when I run into under_scored-style identifiers in Perl code (much less go publicly proclaiming such to be "bad"). But I do dislike the relative difficulty of typing _, that fact that documentation about such identifiers usually ends up with the _ being wider than whitespace and thus the spacing conveys rather the opposite of what _ is meant to convey, and that things like HTML links often make such style very hard_to read with_confidence. While I almost never run into identifiers that get to the point of being difficult to read whenWrittenInCamelCase (and can't think of any other down sides to camelCase). So I personally consider CamelCase to be slightly better than under_scored in several ways and worse than under_scored in no practical ways. But I end up using both under_scored and CamelCase quite a bit in Perl code.

But, of coure, the point of that template has extremely little to do with what style one uses for their variable names. I really don't want anybody to declare a lexical with the name $putMainVarsHere.

As for some more "modern" alternatives, I actually prefer -w over warnings.pm for this specific case (and prefer neither for writing modules), though I do value and use warnings.pm in much more limited scenarios (but I won't go into the "why"s in this node -- though I have discussed at least much of that elsewhere around here).

I often prefer use vars over our, especially in modules. But I do use our when it is worth it. I'm probably even more likely to replace use vars qw( $Globals ); in that template with my $Global= ...;. But the distinction between any of those three choices isn't the point of that terse example, either.

Then there are state variables. A great many of the Perl installs that I use right now don't support such. It certainly isn't time for me to consider standardizing on using them. Nor do I believe that I'd always replace my current pattern even when state $x is an option. Actually, the next module I'll be putting on CPAN (perhaps this week) deals with this type of stuff.

- tye        


Comment on Re^4: RFC: Creating unicursal stars (agism)
Select or Download Code
Re^5: RFC: Creating unicursal stars (agism)
by ikegami (Pope) on Nov 09, 2009 at 21:05 UTC

    (though I don't recall using Perl v2 that year)

    Versions, not revisions. Not counting development releases, the three versions of Perl since 2000 are 5.6, 5.8, 5.10.

    #define PERL_REVISION 5 /* age */ #define PERL_VERSION 6 /* epoch */ #define PERL_SUBVERSION 2 /* generation */

      Nice quoting of p5git://patchlevel.h. But I stand by my assessment of that usage as unusual, even strange.

      "Perl version 6" finds ~55k references for something I expected to be a quite common usage. Since, according to you, Your Mother, and patchlevel.h there actually aren't any versions of "Perl revision 6" (well, it seems premature to me, anyway), I'm pretty sure that google isn't actually finding (many) instances of "Perl version 6.0" (4 isn't "many", especially since 3 of them are actually talking about "Perl subversion 6.0.0" or something even more specific).

      By (extreme) contrast, "Perl revision 6" finds 6 hits (7 by now, surely) and it looks like at least half of them aren't even talking about "revisions of Perl" as you seem to think we should. :)

      I also expect it to be quite common to read something like "Perl version 5.6.1"[2M] (and not to say "Perl subversion 5.6.1"[0!]).

      So, the internet appears to know that "Perl version" applies to things like "6" and like "5.6.1", the two positions where the term shouldn't be applied. I'm not sure how to use google to prove that when people write "Perl verison 5.6" they usually are just using it as shorthand for "Perl subverison 5.6.0" and not for "Perl subversions from 5.6.0 but before 5.7.0", but I really believe that they usually are.

      After meditating on the definitions of "revision" and "version", I can support the use of "revision" for things like "Perl 6" from a linguistic point of view. But the internet proves that such usage wouldn't be adopted (patchlevel.h has used those terms for a very long time). So I'd probably go with something more like version.genus.release (lots of synonyms for "genus" could be substituted but "genus" is my favorite so far) but realize that "major version" or "major revision" is probably required for clarity (and realize that "genus" still wouldn't be clear just because nobody much talks about such things).

      - tye        

        But I stand by my assessment of that usage as unusual, even strange

        Outside of Perl, sure. In Perl, the second number has long been treated as the major version. This is especially true now that the top number can't be bumped without conflicting with the name of another language.

        By (extreme) contrast, "Perl revision 6" finds 6 hits

        I don't know why would you expect "Perl revision 6" to get matches. I'm surprised "Perl version 6" gets as much as 6% of "Perl 6" + "Perl6", though.

        I also expect it to be quite common to read something like "Perl version 5.6.1"

        Me too.

Re^5: RFC: Creating unicursal stars (agism)
by Your Mother (Canon) on Nov 09, 2009 at 23:09 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. 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.

      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        

Re^5: RFC: Creating unicursal stars (agism)
by ysth (Canon) on Dec 02, 2009 at 19:04 UTC

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2014-09-22 02:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (177 votes), past polls