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
each
below.
- See the note on
- Do not use
`this
for an empty set of cards; prefer[~ this]
. (The structure is the same but the intent of aunit
is 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
list
s 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.hoon
for solid-state subscriptionsdeco.hoon
for doccordspals.hoon
for%pals
rudder.hoon
for 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
/lib
file per agent. - If JSON handling is necessary, store it in a file
/lib/agent-name/json.hoon
with++dejs
and++enjs
arms.
- There should only be one
/mar/agent-name/action.hoon
- There should be one
/mar
file 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
/app
file.
- There should be one
/sur/agent-name.hoon
- There should be only one
/sur
file per agent.
- There should be only one
Prefer these constructions:
=* this .
- Use the
agentio
library when possible. - Use Rudder and Schooner when possible.
- Use
(pole knot)
overpath
in agent arms. (Just don't teachpath
in 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
each
to distinguish values. All values should be head-tagged semantically, and this need not match the aura form (as with+scot
); that is, prefer%text
instead of%t
for 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.hoon
with multiple test files permitted if desired.
Documentation should be compatible with %docs
.
/doc/agent-name
should include the appropriate Udon (Markdown) files.
This document has benefited from a decade of Hoon code and organic best practices.
If
tag+value
is barred, I'd saytag/value
andvalue^value
should also be forbidden.