Pascal wrote: > Anyway, does anyone have a style guide they could share, or point me to one > in the wiki?
I can point you at: http://code.jsoftware.com/wiki/PersonalTaste <http://code.jsoftware.com/wiki/PersonalTaste> and http://code.jsoftware.com/wiki/User:Dan_Bron/Style <http://code.jsoftware.com/wiki/User:Dan_Bron/Style> and http://rosettacode.org/wiki/J/HouseStyle <http://rosettacode.org/wiki/J/HouseStyle> But these were all created many years ago, and they’re all just initial braindumps: disorganized and far from comprehensive. They really never got past the “initial thoughts” phase (and mostly represent only my [Dan’s] initial thoughts, at that). > Of course I could make my own rules, but I'd like to stay somewhat consistent > with whatever other people are doing. I can tell you my personal guidelines, which are broadly consistent with what I see on the Forums and other places I find code in the wild: > I'm talking about things like camelCase vs snake_case, verbs start with > capital letters etc etc. + Capitalization is primarily used to distinguish the parts of speech with visual hints: - Global nouns (particularly constants) are UPPERCASE o As a subclass of global nouns, for members of enums (fixed set of enumerated values), I often use ENUMNAME_MEMBERNAME (i.e. with underscores) - Verbs, having primacy in J and being the most common wordclass, are lowercase, or, when called for, camelCase with an initial lowercase letter. - Adverbs and conjunctions, being the remaining and least common wordclass, get the remaining distinguishable case: InitialUppercase (again, with CamelCase as needed) - I tend to aim for purely tacit formulations, where I can get them, so I don’t use explicit code as much, but when I do, local nouns are simply lowercase. Other considerations: + Code layout: - When writing large tacit verbs, I try to break them up into functional, digestible pieces (which individually are easy to analyze on sight, or with less than 2 minutes of review). - This is made possible by J’s assumption that of as-yet-undefined names are verbs (which is a strong clue that that’s how J, i.e. Ken, expected you to do it). - I lay these pieces out in my script with indentation that reflects their calling tree, so that I can grok the high-level verb first, refining my understanding of the details as I progress down the script. - Another benefit is, at any given level, the implementation details of that level are indented to the right, so if I’m not interested in those yet, I can simply scan down the file to the next entry at the same indentation level. - Typically, these intermediate names are ephemeral, meaning they are never called outside the scope of the enclosing function, so I assign them locally. - At the bottom/end of the top-level definition, I assign theVerb =: theVerb f. to remove the dependency on these intermediate, ephemeral names (otherwise, you’d get value errors invoking theVerb, because the definitions of its components would have gone out of scope). + Indentation - I indent tacit definitions with two space characters (32{a.), because it keeps the “paragraph” defining the top-level function compact and easy to distinguish as an atomic grouping. Also because tacit code, even when modularized, can lead to some very long lines already. - I indent explicit definitions with a single tab character (9{a.) because I find anything narrower makes it hard to pick out the lone ) which terminates that specific definition. o One quibble I’ve always had with the Project Manager is that when it coalesces scripts, it removes this indentation, and so it makes it really hard to identify where one explicit definition ends and another begins, an issue exacerbated when the ultimate script has many sequential explicit definitions. + Naming - Is the hardest problem in computer science. I’d prefer a job doing cache invalidation any day. - That said, (J) verbs tend to be (English) verbs, (J) nouns tend to be (English) nouns, and operators tend to be ad-hoc (i.e. I have no rules yet). + Data - Inline (noun defines) to permit, to the extent possible, data-driven or table-driven code, with the minimum of overhead or redundancy. Data speaks for itself, and to the extent you can allow it to speak for your code, the better. - Sometimes a (noun define) at the bottom that either uses 0!:2 or a bunch of asserts as a kind of informal test script (turned off by default, but when turned on, tests correctness when the script is load’ed) + Comments - Large comment at the top of the script, laying out its purposes, usage, and caveats. - I also tend to make mention of any limitations imposed by the language/notation/implementation proper, so if/when the language evolves, I’ll be able to refactor or simplify my definitions accordingly. - About a paragraph of comments above every public (exported) name. Again, a sentence or two on motivations / purposes, and then examples of expected inputs and outputs, and caveats if any. I used to prefix executable examples with NB. EG: but I didn’t keep up the habit. - Large (noun define) at the bottom of the script walking through concrete examples (simulating or literal copy/paste of a live J session) Here’s an example of my indentation style and preference for data- or table-driven logic, from something I knocked together for a poster on the J forums in 2013 [1]: NB. Scoring tables 'GROUPS POINTS' =. <"_1 |: ".;._2 noun define 5 ; 3 2 1 NB. 5 <= #riders <= 10 11 ; 7 5 4 3 2 1 NB. 11 <= #riders <= 20 21 ; 8 6 5 4 3 2 1 NB. 21 <= #riders <= 49 50 ; 10 8 7 6 5 4 3 2 1 NB. 50 or more #riders ) NB. Logic report =: tally/@:|:@:record tally =. ~.@[ sortStich catSumCount@;/. sortStich =. ,. /: ] catSumCount =. +/ (category ; ;) # category =. 4 <. 1 + 35 30 20 I. (* 2&<:) record =. [: ; (,: <"0@scores)~/&.|:&.>@:races scores =. [: score 0 ". ;:^:_1 score =. scorePlace pointGroup scorePlace =. (0,]) {~ [ * (<: #) pointGroup =. (0;POINTS) {::~ (<:;GROUPS) I. # races =. [: cutRaces LF , toJ@fread@jpath Pf cutRaces =. <@:cutFields;.1~ (LF,'--') E. ] cutFields=. 0 1 }. RE (rxmatches rxfrom ])Pf ] You’ll need the complete script, from [2], to actually get it to run. There are more scripts in my SVN repository — of, I must warn you, wildly varying and inconsistent quality — illustrating the other considerations I’ve discussed here, in particular heavy commenting, automated testing, (noun defines), etc. -Dan [1] Scoring a road race in J, from “my programm looks terrible” in Oct 2013: http://www.jsoftware.com/pipermail/chat/2013-October/005364.html <http://www.jsoftware.com/pipermail/chat/2013-October/005364.html> [2] The complete script which will allow you to run the above code, scoreRoadRace.ijs: http://jsoftware.com/svn/DanBron/trunk/uncategorized/scoreRoadRace.ijs <http://jsoftware.com/svn/DanBron/trunk/uncategorized/scoreRoadRace.ijs> This script illustrates some, but not all, of the conventions I’ve expounded on here. If you remove the /uncategorized/scoreRoadRace.ijs suffix from the URL, you will be able to browse my larger code base. Most of the more mature scripts are in /environment, /general, and /uncategorized, but there’s really no good way to to tell what type of quality you’re dealing with just from the filenames, you’ll just have to poke around. ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
