in reply to Re^2: open and list context (?)
in thread open and list context (?)
- Cᴀᴠᴇᴀᴛ Lᴇᴄᴛᴏʀ:
- If by chance you’re one to be easily bothered by strong opinions, especially those against which you have an irrational, emotional reaction, please do us all a favor and skip reading this posting. 🙈 🙉 🙊
On Monday, 13 June 2011 at 10:28 ㏂ ᴍᴅᴛ, chromatic in quoting yours truly has done me the honor to write:
› Always use parens on you[r] function calls…Quite so! Rem acū tetigistī!I’ve given that advice too, but what makes open a function call and die not?
Not merely a just question, it would also seem a perfectly straightfoward question as well. The operative term there is seem, as your seemingly simple question comes accompanied by seriously subobvious traps to trouble both the unwary and the hypervigilant alike.
Sorry it took me so long to answer … 💬
☣ Caveat wrǽððu
I had fully intended to answer you the same day you posted your question, but this was not to be. So first please accept my sincere apologies for not responding sooner. I hope the unscheduled delay has not banished the question from your mind.Frustrating my whilom goal of a quick turnaround is a somewhat messy tale, although one mostly of personal (but not private) concern only. It turns out that during the target response period, my body, mind, and soul have like so many spoils of war been variously divvied up in a trilateral crapshoot between Mycoplasma pneumoniae, Alces alces shirasi, and Camelus dromedarius quartus. Multiple winners have each claimed their pound of flesh, even going so far as to further quarrel over these small spoils.
As I have not myself been so fortunate as to be numbered amongst said victors, there just hasn’t been enough of me (in a nonphysical sense) to go spreading myself still thinner without risking becoming even more the wrathful wraith than I am already become.
’Nuff said.
The reason that die is neither a function call nor a subroutine, method, procedure, or anything else of that ilk is because of what subroutines at their machine‐level foundation really are. When you factor out matters of register allocation and arugment transmission, they all of then do one key thing: they push on the (per‐thread, per‐intepreter) sᴘ the address of the next ᴘᴄ to be executed after the intended subroutine call eventually returns.
This would work a bit like -(SP) = PC; PC = FUNCNAME. Then at the end of the “call”, the subprogram pops the return address off the stack and hies itself thither with PC = (SP)+. There exist simpler solutions involving fancier instructions like JSR and RTS, but you must get the central idea here. And die just doesn’t work that way — at all. Functions that return fewer times than they’re called, and in some cases, even return more times than they’re called, are sneaky little buggers that strain any reasonable definition of what a function call really is.
Other functions that break the function model outlined above and therefore give call‐graph analysis programs serious conniptions include not just exit but even moreso longjmp and setjmp. That’s because setjmp returns more times than it’s called (as so too can open!), while longjump, like exit and die, never bothers to return at all.
Interesting though all that may be, I suspect that wasn’t what you were really asking. I recognize that I may be wrong, though, and so it is just barely conceivable that you really were asking the subtler question, not the simpler one.
Even though code I’ve written ever since v1.0 of Perl for the most part looks pretty much as it always has, my own coding practices have changed a little over the years. I like to think they’ve converged on a degree of stylistic consistency that facilitates not just the reading of my code, but also its predictability.
Yes, that does mean that today’s code does not always quite match up exactly with yesteryear’s in all possible regards, so please do not go digging up prehistoric Perl code of mine to tout as though it were someone an examplar of cavalier inconsistency. It wouldn’t be. More importantly, it just doesn’t bear discussing.
Nevertheless, I believe that if you examine any of my recent code, such as the many examples found in my Unicode Tool Chest, you will quickly see a clear and consistent style used not religiously, but consistently in all of that code.
In fact, I would even go so far as to say that if ever you find exceptions to larger stylistic patterns in that code, you have either discovered a more specific rule than the general rule you had believed you had been previously operating under, or as is more likely, you have discovered a style bug that I myself would prefer to see updated for consistency’s sake.
I am not fond of using parentheses for functions and methods whose dative (or ablative (or instrumental)) slot is occupied, because the result looks disconcertingly Lispish. That means I avoid parens for things like print, printf, map, grep, and sort — just to name a few. Additionally and for precisely the same reason (although somewhat moderated by pipelined, left‐to‐right listop stacking and on certain perlocentric syntactosemantic exceptions discussed below), I also tend to avoid parentheses on methods‐qua‐listops.
I recognize this runs somewhat counter to the bashfulᵃʰᵉᵐConventional Wisdom that spooks up an intensely aversive reaction in many novice Perl programmers who just don’t know any better. But since I actually do know where their peculiar ambiguities lurk in stealthful ambuscade, I simply do not write them in an ambiguous fashion, and the payoff is improved readability. It really is a nonissue for me, and I have never once been gotchaed as so many others report having befallen them.
It is also a tiny niche in one little corner of the language, one which for me does not even arise with any great frequency. Given that, it generates a level of controversy I feel wholly unreasonable and disproportionately larger than it has any business doing. This is itself distressing. Why do that? Let’s not and say we didn’t. Just let it go, ok please?
For me, the parens are needed to tell my brain where the argument list stops. A semicolon or a close round/square/curly bracket will all do this. But if you expect the argument list to stop for any other reason, I get nervous. I am far too aware of the ways that prototypes change the parse to trust any funny business there. I do not like trailing English words changing the parse, either, since the function likely started as a leading English word. That’s why I’ll write:
As in the point that you yourself have raied, there are times I relax that, and indeed it’s usually on things like print or die. As should be immmediately obvious from the code fragment cited above, one thing that’s especially important to me is interlineal vertical alignment. That isn’t quite properly stated, but the idea is that if the code that looks the same should be in the same column despite being on different lines so that the eye can quickly pick out the parts that are different. We’re very good at that as humans.pod2usage(0) if $Opt{help}; pod2usage(-exitstatus => 0, -verbose => 2) if $Opt{man}; @ARGV = (1) unless @ARGV; pod2usage("$0: missing arguments") if @ARGV == 0;
That’s just one of the many reasons I always use the more readable form of the vexing Logical-ᴏʀ, although there are other reasons for that, too. Please note very very carefully, that even without the alternate, hard‐to‐parse newfangled construct anywhere to be seen or unseen, my own code — mirabile visu! — is simultaneously safe, clear, and unconfusing. “They” tell this can’t be done, but “there” are demonstrably wrong, considering how I never, never, never make the pernicious and pervasive operator precedence errors that seem to plague most Perl programmers, especially those who put too much stock into contemptible mindless cargo‐cult pseudo‐rules instead of in actual thought.
Do things for reasons other than because you were told to: learn the whys and wherefores, not the rules. But if there is one rule to follow without giving it further thought, please make it this one:
Please, please, please think of those who’ll come after you — preferably before they do so — and use parentheses to delimit the arguments to your functions calls.
Nevertheless, I do believe that taken as a whole, my personal style is consistent, predictable, readable, and pedagogically useful. I should’t be surprised if it were found to be so idiosyncratically mine that it would prove readily identifiable as tchrist–code by one of those clever machine‐learning program trying to identify plagiarism.
The fiftyish programs in my Unicode Tool Chest are often a lot more useful, or can be used in many clever ways other than are immediately apparent. Some of those that I use daily or more include:
There are around 50 programs, modules, and libraries in that directory, almost all having to do with Unicode. Some are one‐shots, some are well‐documented standard tools I use daily, and all I believe have something to say about Perl (and sometimes C and sometimes Java) programming. Some delightful little simpletons are genuine lifesavers, but you’d never know it without playing around with them a bit. And some are just downright hilarious in the extreme.
You’ll see.
I recognize this and abhor it, and I profoundly apologize. But please understand that these grew organically over a period of a few months, and so it wasn’t at all clear just what should be factored out, what the ᴀᴘɪ needed to be, or how it all fit together as the whole that it has increasingly become. Too much was under constant development to try to do that a priori before having written it. That’s because premature optimization, while perhaps not quite up to the standard of Rᴀᴅɪx Mᴀʟᴏʀᴠᴍ Cᴠᴘɪᴅɪᴛᴀs Esᴛ 😈, is definitely one of my idea of the Seven Deadly Sins of Programming, and so I beg of you if not your forgivenness, at least then your forebearance, in this unintended wickedness. It will get fixed.
Too much framework and too little code is just pointless over‐engineering and needless conplication. I despise those things, but learning to discern what the right time and place for what level of abstraction is, isn’t something that always comes immediately. Sometimes you have to build working prototypes first, then look ack at them to figure out how to refactor for the good of all.
In short, there’s a queasy measure of duplication across programs that should and almost must be factored out and placed into a set of common modules. I am painfully aware of that, and very much hope to someday find the time to do so.
And you will also see certain things that are not there. There are elements that someone or other may have told you that you should include in order for your code to pass muster. Sometimes it’s unjustly beating someone over the head with Damian’s Perl Best Practices, and sometimes the supercilious bashing comes from other sources. But it is all bogus and unnecessary, and I believe that in the balance it has now done more harm than good. Tʜᴇʀᴇ’s ᴍᴏʀᴇ ᴛʜᴀɴ ᴏɴᴇ ᴡᴀʏ ᴛᴏ ᴅᴏ ɪᴛ, and don’t you dare forget it.
¡ʞʍɐ uᴉ əpoɔ ɹnoλ əʇᴉɹʍəɹ noλ əʞɐɯ puɐ uʍop noλ ʞɔɐɹʇ ⁎llᴉʍ⁎ I əƨlə ɹO
Looking over my recent code, I guarantee that you will learn a whole lot about my notions of good coding style, including but hardly limited to the proper use and placement of parentheses, much better than I could ever here put into short, simple words. Osmosis works a lot better.
Sure, I certainly have my rules and ideas, but I am not sure I’m ready to explain them in English. And I especially never want to imply that you must code your Perl as I do mine.
I just want you to see what I do, understand why due to its consistency it works as a coherent, reliable, safe, and predictable style (perltidy and Perl::Critic be damned!), and only then consider making your own decisions about what you do or do not fancy. I don’t expect everyone to agree with everything. In fact, I would be disappointed if it turned out that way.
The single overarching point about my code is that it has a distinctive and readily identifiable style running throughout, which has therefore extreme inherent virtue, no matter whether you agree with certain of its particulars or not.
The point is not following other people’s rules, howsoever well‐meaning those rules might have originally been. This point is almost always lost these days, and it is a crying shame.
My Perl code itself should be crystal clear. If it isn’t, then I’m not doing something right. Anything in there that isn’t aeons old (of which there are only two) should also be wholly neoteric, completely self‐consistent, and in places even a pleasure to read.
|
|---|