Code accessibility cannot be an afterthought for Urbit development. Hoon has had a reputation for being a language of dense expressions, which we believe is now being cleared by sunshine. However, Hoon's extensive sugar syntax and irregular expressiveness can make it challenging for those relatively new to Hoon to decipher programs.
Code accessibility must be a priority for userspace Hoon. We can support developer learning and entry into the ecosystem by defining a subset of Hoon syntax that we adhere to in all of the appropriate guides and some of the userspace code.
Let's call this subset "Hoon Prime" (H´). Hoon Prime will be a code discipline within Hoon to promote a clear pathway for newer developers to understand the nature of Hoon programs before needing to grapple with the entire panoply of syntax and runes. Hoon Prime may not alway be the most concise Hoon code, and it will likely fail to maintain certain well-established preferences. (Even if there is a "better" way to write it, we should prefer this restricted discipline in H´.) Hoon Prime will allow us to onboard developers into producing generators and agents from %base-distributed models as quickly as possible.
The first concerns are to limit the scope of runes that must be learned to the top 27 most important ones, with another 27 context-specific runes included for particular code constructions.
%:cencol:*coltar%=cenhep (sugar preferred but not mandated)|=bartis^-kethep%~censig=/tisfas (specifically preferred over=+and=-)?:wutcol?~wutsig%-cenhep|-barhep:~colsig:-colhep?-wuthep.+dotlus (only as sugar syntax+())=>tisgar|%barcen|.bardot!!zapzap;:miccol?+wutlus|^barket~&sigpam (with logging levels)|_barcab$%buccen$?bucwut$:buccol
The following are allowed in specific contexts or forms:
^=kettis (only as sugar syntaxp=q)=<tisgal (illustrative in a few particular cases)=.tisdot (illustrative for "edit a variable").=dottis (only as sugar syntax=());~micsig (only for parsers)^:ketcol (only to explain structure v. value mode; prefer sugar syntax,)^*kettar (only as sugar syntax*)?>wutgar (only for type resolution)?&wutpam (only as sugar syntax&())%+cenlus (as contrastive with%-and%:)=^tisket|*bartar=*tistar (only standard agent boilerplate)~|sigbar?!wutzap (only as sugar syntax!)?|wutbar (only as sugar syntax|())!>zapgar (mainly for illustration)!,zapcom (mainly for illustration)!=zaptis (mainly for illustration)$_buccab (only as sugar syntax_);;micmic?^wutket?@wutpat!<zapgal;/micfas and other Sail runes (except in Sail materials).^dotket;<micgal
The following should be specifically avoided in Hoon Prime:
=+tislus?=wuttis^+ketlus?.wutdot~sig runes generally, aside from~&sigpam?<wutgal=|tisbar:_colcab (mentioned in resources but not used in H´ code)=?tiswut:+collus=-tishep:^colket%^cenket=,tiscom%_cencab^?ketwut^.ketdot|~barsig%.cendot|$barbuc|@barpat (unless needed for|*wet gates)?<watgal.*dottar (except in Nock materials)=;tismic=:tiscol^|ketbar%*centar|:buccol (prefer$_buccab in irregular form)!?zapwut=~tissig.?dotwut (except in Nock materials)^~ketsig?#wuthax (decision may be revised vis-à-vis?=wuttis)|?barwut!@zappat^&ketpam
To reiterate, these are not claims about Hoon generally—Hoon Prime is a pedagogical code discipline, not the future of Hoon.
Sugar syntax should be deployed thoughtfully.
The following syntax expressions are explicitly blessed:
.+dotlus (only as sugar syntax+())^=kettis (only as sugar syntaxp=q).=dottis (only as sugar syntax=())^:ketcol (only to explain structure v. value mode; prefer sugar syntax,)^*kettar (only as sugar syntax*)?&wutpam (only as sugar syntax&())?!wutzap (only as sugar syntax!)?|wutbar (only as sugar syntax|())$_buccab (only as sugar syntax_)$?bucwut (as both?()and explicitly)
The following constructions are explicitly barred:
- Do not use
tag+value; prefer[%tag value].- See the note on
eachbelow.
- See the note on
- Do not use
`thisfor an empty set of cards; prefer[~ this]. (The structure is the same but the intent of aunitis different.)
Specific rules will accustom developers to use patterns before running into deeper concepts like the Hoon type system. These may be controversial but each has a specific pedagogical motivation.
- Prefer head-tagged unions of values when multiple kinds of values should be included, e.g. in a
$?bucwut type union. - Type unions can only be made over constants. (No
?(@t tape)sorts of expressions.) - Explicitly mark
lists as such, rather than relying on null-terminated tuples. - All
:col runes can be used when explaining rune alternatives.
Hoon Prime should also adopt a standard of literate programming. Several example files already display such a self-documenting nature:
simple.hoonfor solid-state subscriptionsdeco.hoonfor doccordspals.hoonfor%palsrudder.hoonfor serving websites
Our userspace code accessibility model should allow contributors from widely different skill levels to interact. We need to surface and document code patterns as cleanly as possible in the code we distribute.
We need to upgrade as much code as possible to A standards per the style guide.
Agent files should hew to the following standards:
/lib/agent-name.hoon- There should only be one
/libfile per agent. - If JSON handling is necessary, store it in a file
/lib/agent-name/json.hoonwith++dejsand++enjsarms.
- There should only be one
/mar/agent-name/action.hoon- There should be one
/marfile per agent action. - Agent actions should be named from
action,update,result,effect. - Defer all JSON handling to the appropriate mark, never in the main
/appfile.
- There should be one
/sur/agent-name.hoon- There should be only one
/surfile per agent.
- There should be only one
Prefer these constructions:
=* this .- Use the
agentiolibrary when possible. - Use Rudder and Schooner when possible.
- Use
(pole knot)overpathin agent arms. (Just don't teachpathin beginner materials in that context.) - After it has been introduced pedagogically, prefer the nested core pattern about 50% of the time. Show both versions (conventional and nested core) when feasible. Treat the nested core pattern as a release version refactor rather than a starting point for many learner cases.
- Do not weigh heavier expressions down to the bottom with rune inversion (like
:_or=-). (Some of the Hoon Style Guide is strategically deprecated for Hoon Prime code.) - Do not privilege three-letter and four-letter names in userspace. There could still be a naming pattern (like five-letter words) that increases the code aesthetics (gap alignment in blocks &c.).
- Be careful with metaphors. A good metaphor can illuminate, while a bad one will obfuscate. Still, have fun.
- In working with type unions, use
eachto distinguish values. All values should be head-tagged semantically, and this need not match the aura form (as with+scot); that is, prefer%textinstead of%tfor a string. - Userspace apps put out by the Urbit Foundation or submitted in completion of a bounty should include tests and docs (see below).
We need to include comments and unit tests so people can see how and why code works like it does.
/tests/agent-name/tests.hoonwith multiple test files permitted if desired.
Documentation should be compatible with %docs.
/doc/agent-nameshould include the appropriate Udon (Markdown) files.
This document has benefited from a decade of Hoon code and organic best practices.
If
tag+valueis barred, I'd saytag/valueandvalue^valueshould also be forbidden.