on 514b5fc help sign in
476 lines 13 kB history raw
1+++
2title = "Hoon Style Guide"
3weight = 40
4template = "doc.html"
5aliases = ["docs/learn/hoon/style/"]
6+++
8Welcome to the Hoon style guide. It’s important to familiarize yourself with our way of writing Hoon code.
10## Layout
12Hoon’s position on layout is: so long as your code is (a) correctly commented,
13(b) free from blank or overlong lines, (c) parses, and (d) looks good, it’s good
14layout.
16When a layout standard or other fundamental coding convention is
17not perfectly rigid, code can develop some individual flavor.
18But Hoon’s layout rules, though not rigid, are still strict. The
19flavor should never overwhelm the content.
21### General outline of Hoon syntax
23There are two forms of syntax in Hoon: wide and tall. Wide forms
24fit on a single line, use single spaces to separate syntax, and
25generally use enclosing terminators (like parentheses to close an
26expression). Tall forms can use multiple lines, separate syntax
27with two spaces at minimum and arbitrary whitespace at maximum,
28and avoid terminators when the content has a fixed structure.
30For example, the wide form `=+(a b)` could be written in tall form
31as
33```hoon
34 =+ a
35 b
36```
38or
40```hoon
41 =+ a b
42```
44These are regular forms -- every rune can be written this way.
45Hoon also has a variety of wide [irregular forms](/docs/hoon/reference/irregular). All tall
46forms are regular. All code within a wide form is wide.
47Almost all code has both wide and tall forms, the exception
48being named [cores](/docs/glossary/core/).
50The goal of wide/tall forms is to resemble the look of
51procedural code, with its statement/expression distinction,
52in a purely functional language. In particular, complex code in
53functional languages tends to develop a diagonal shape, since
54child nodes in the syntax tree are indented right.
56### Tall layout conventions
58In wide form, the parser allows no freedom of layout (and no
59comments, either). In tall form, there is too much freedom, and so we need
60conventions. These conventions aren’t absolute, but
61you shouldn’t defy them unless you have a good reason to do so.
63Syntactically, there are three kinds of runes: fixed sequences,
64variable sequences, and cores/engines. Let’s talk about each.
66#### Fixed sequences and backstep indentation
68A fixed sequence is a rune with a fixed number of children. Most
69runes are fixed sequences. In wide mode we terminate a fixed
70sequence with a right-parenthesis (“rit”). In tall mode there is
71no terminator.
73With a fixed sequence, we typically use “backstep indentation.”
74The goal of a backstep is for the largest child node of the rune
75to end up on the same left margin as the rune itself. This
76design ensures that the body of the code flows down the page, not
77across the page.
79With one child:
81```hoon
82!:
84```
86With two:
88```hoon
89=+ a
91```
93With three:
95```hoon
96?: a
97 b
99```
101With four (the maximum rune fanout):
103```hoon
104:^ a
105 b
106 c
108```
110It is sometimes acceptable to not backstep -- especially in tuple
111runes: `:-`, `:_`, `:+` and `+^`. But you should have a specific reason:
112for example: emphasizing symmetry in a tuple.
114#### Variable sequences
116Variable sequences can have an arbitrary number of elements, so
117they can’t self-terminate. They are terminated by a `==` marker.
118The sequence, or its variable part, is indented and vertical:
120```hoon
121:* a
122 b
123 c
124==
125```
127Another representation wastes a line, but saves an indent. Use
128this only for very long sequences:
130```hoon
131:*
132 a
133 b
134 c
135==
136```
138Some variable sequences are sequences of pairs; some of these
139start with fixed sequences of nodes. Pair sequences are in
140either “kingside” or “queenside” convention, depending on what
141looks better for this particular code.
143Kingside format:
145```hoon
146?+ x default
147 %foo 99
148 %foobar ?: y
149 42
150 (add 2 2)
151 37 36
152==
153```
155Queenside format:
157```hoon
158?+ x
159 default
160::
161 %foo
162 99
163::
164 %foobar
165 ?: y
166 42
167 (add 2 2)
168==
169```
171The queenside format is more useful when the tails are bigger.
172It is also usually hard to read without linebreak comments,
173as demonstrated above.
175We sometimes end up with multiple terminators on separate lines,
176two or more spaces apart. These lines can be collapsed:
178```hoon
179?+ x default
180 %foo 99
181 37 36
182 %foobar ?- y
183 %moo 9
184 %bar 10
185== ==
186```
188## General naming style
190Modern Hoon naming is **verbose**.
192**Never**: abbreviate a label; pack characters (try to reduce the
193length of labels, or make lengths match up between parallel
194labels); use intentionally vague and meaningless words; or use
195nonsense text that isn’t a word.
197It can’t be repeated too often: **do not abbreviate words, unless
198you would use the same abbreviations in written English**. To
199save a trivial, one-time amount of work in typing, you are adding
200a nontrivial amount of work and ambiguity in reading.
202### Comments and unparsed bytes
204Hoon comments are 8-column lines which contain whitespace, then
205`::`, then optional text.
207Blank lines are lines containing no characters, or only whitespace.
208There must never be blank lines in a Hoon file.
210Empty lines are lines containing `::` only. There must never be
211two empty lines in a row in a Hoon file.
213Whitespace is semi-significant. The difference between a
214space and a gap (more than one space) is significant. But two or
215more spaces, newlines, or comments are one gap.
217#### Comment conventions
219Hoon suggests “breathing comments.” There should always be an
220empty comment line between a comment and the line **below** it:
222```hoon
223:: look, code
224::
225this.is.code
226:: we are going to need more code
227::
228this.is.more.code
229```
231Sometimes dense code does need air on both sides. Also
232legitimate:
234```hoon
235:: look, code
236::
237this.is.code
238::
239:: we are going to need more code
240::
241this.is.more.code
242```
244But air on both sides is needed less often than you may think.
246Crowded comments are comments on lines which also contain code.
247Older code has a lot of these, especially the “column 56”
248standard.
250Crowded comments are considered harmful -- don’t use them. Hoon,
251like any higher-order functional language, can be very dense and
252powerful. We almost never want it to be **more** dense.
254#### Megalithic comments
256In older code you’ll also see attempts to produce large, visually
257salient geometries as separators, like:
259```
260::
261::::
262::
263```
265or
267```
268::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
269```
271Please don’t do this in new code. Normal conventions should be
272legible. Use more deeply qualified positions if your code is
273hard to navigate.
275### Structure of all comments, formal and informal
277If any comment cannot be parsed as a formal comment, we treat it
278as an informal comment and ignore it.
280There are four types of formal comments: feature comments (which
281annotate named features), product comments (which describe what
282the expression below makes), flow comments (which describe the
283computation flow), and development comments (which describe the
284development process).
286All kinds of formal comments have the same structure: simple or
287complex.
289A simple formal comment is a one-line headline. A headline is
290optional whitespace; then `::`; then two spaces; then a parsed
291line of **lowercase** ASCII whose syntax depends on the comment
292type. Like this:
294```hoon
295 :: $foo: the definition of a foo
296```
298A complex formal comment is the headline; then an empty line;
299then an udon body with paragraphs broken by empty lines, indented
300four spaces, in ASCII mixed case:
302```hoon
303:: $foo: the definition of a foo
304::
305:: The source of the word “foo” is lost in history. Some
306:: think it comes from the WWII military term “FUBAR,”
307:: in which “UBAR” stands for “up beyond all retrieval.”
308::
309:: Somehow “FUBAR” became “foobar.” The rest is history.
310::
311```
313The point is: sometimes we want to see a deep explanation;
314sometimes we just want a summary. So we require you to either
315(a) provide a line-length explanation, or (b) a long screed
316but with a line-length summary/headline.
318### Feature comments
320A feature headline is `::`, then two spaces, then a qualified
321location, then `:`, then a freeform string. Like:
323```hoon
324:: $foo: a the definition of a foo
325::
326+$ foo [head=@ tail=^]
327```
329We find the feature `$foo` relative to the current location and
330move the comment there, as described above. In most cases it
331becomes a product comment. For a `|chapter` (which does not
332resolve to any data value) it becomes the chapter description.
334### Product comments
336Product comments describe the product of the expression below.
337The headline is a string in parentheses:
339```hoon
340:: (a very strange $foo indeed)
341::
342make:a:strange:foo
343```
345### Flow comments and legends
347Flow comments use a new commenting concept called **legends**.
349#### Legends
351One of the problems with Hoon as a language is that it takes some
352time to learn to look at a tree of runes and “see the function.”
353Seeing the function is beautiful and pleasant. But until the new
354Hoon student has put in a lot of practice, this experience is
355inaccessible. And tracing runes with a manual is hard.
357Canonical flow comments are one way to ease this burden.
358We first need to write descriptive names (not necessarily
359unique) for every leg of every rune case. Then, we introduce a
360narration of the code with these descriptions.
362For example, let’s fix `[%wtcl p=hoon q=hoon r=hoon]`. Let’s
363make it … `[%wtcl if=hoon then=hoon else=hoon]`. Then we
364could write flow comments as follows:
366```hoon
367?: :: if, it is winter
368 ::
369 is-winter
370 :: then, why not rome?
371 ::
372 visit-italy
373:: else, amsterdam is nice in the summer
374::
375visit-holland
376```
378The headline of a flow comment uses a **legend**: the name of
379this leg in the parent rune, then a message,
381For someone who doesn’t know Hoon, these pseudo-keywords are
382a lifesaver. For someone who does, they are not too annoying
383and may still be helpful.
385Of course, to use this we need to write useful “leg ends” for all
386appropriate legs of all appropriate runes. But that will
387probably help us document them, anyway.
389#### Flow promotion
391Sometimes, just for cosmetic reasons, we like to raise the
392comment on the first leg of a rune up above the parent:
394```hoon
395:: if, it is winter
396::
397?: is-winter
398 :: then, why not rome?
399 ::
400 visit-italy
401:: else, amsterdam is nice in the summer
402::
403visit-holland
404```
406This can make flow comments collide, as in “else, if,” below:
408```hoon
409:: if, it is winter
410::
411?: is-winter
412 :: then, why not rome?
413 ::
414 visit-italy
415:: else, if, sprechen sie deutsch?
416::
417?: speak-german
418 :: then, maybe berlin?
419 ::
420 visit-berlin
421:: else, everyone in amsterdam speaks english
422::
423visit-holland
424```
426#### Flow comments, traces, and interpolation
428Flow comments, because they describe what your code is doing, are
429embedded in the stack trace, using the same hint mechanism as
430`~|`. A trace is an explanation of everything your code was
431doing when it crashed.
433And data interpolation, in `{}`, also works in flow comments.
434Your flow comments just describe what your code is doing, in
435English, including data.
437## Grading
439How do we define the superficial quality of Hoon code? (Setting
440aside, of course, the question of whether the code is computing
441the right thing in the right way.)
443There are five grades of Hoon: incomplete (F), compiling (D),
444correct (C), complete (B), and annotated (A).
446Any file that looks like code and opens in an editor gets an F.
447If it compiles, and it is Hoon, it gets a D.
449A Hoon file that follows the layout, structure, and naming
450conventions in this document has earned a C. Weird indents,
451cryptic or abbreviated names, etc, etc, preclude an A or B
452grade -- regardless of documentation.
454A Hoon file gets a B if and only if **every symbol in the file is
455defined, where introduced, by a formal comment**. You do not get
456to make up a name without writing a one-line definition.
458For an A, there are two criteria.
460One: every symbol that needs an explanation (a multiline comment
461after the definition) has an explanation. This is obviously a
462judgment call, as a grade of A should always be. If a definition
463doesn’t call for any explanation, it must be dead obvious.
465Two: every `%constant` we use must be defined where it is used,
466not just where it’s declared.
468The advantage of a `%constant` over a classic `typedef`: there is no
469need to search formally for a symbol. The disadvantage: there is
470no trivial way to find out what the symbol actually means. So
471when I send some `%foobar` move, I should define what I think
472`%foobar` means. Just copy and paste the original definition.
474Code shouldn’t even try for an A until it is quite stable. The worst
475thing in the world is code that changes without updating the documentation.
476Any **incorrect** comment in a file drops it all the way back to a D.