on 492ae2f help sign in
297 lines 8.8 kB history raw
1# Design
3Because each twig stem has its own bulb, each has its own parser
4rule. We'll describe these grammars as we go through the stems.
6But Hoon has a general syntax design with common principles and
7regularities. We'll cover those here.
9## Glyphs and characters
11Hoon is a heavy punctuation user. To make ASCII great again,
12we've mapped each punctuation glyph to a syllable:
14```
15 ace [1 space] gal < pal (
16 bar | gap [>1 space, nl] par )
17 bas \ gar > sel [
18 buc $ hax # sem ;
19 cab _ hep - ser ]
20 cen % kel { sig ~
21 col : ker } soq '
22 com , ket ^ tar *
23 doq " lus + tec `
24 dot . pam & tis =
25 fas / pat @ wut ?
26 zap !
27```
29You don't need to memorize these glyph names, but it helps. Code
30is often vocalized or subvocalized. "pal" is easier to say,
31aloud or silently, then "left paren."
33Note that the list includes two separate whitespace forms: `ace`
34for a single space, `gap` for 2+, comment or newline. Hoon
35Besides `ace` versus `gap`, whitespace is not significant.
37Comments start with `::` and run to the end of the line. Hard
38tab characters are illegal, and an 80-column right margin is
39strongly encouraged. Really well-groomed Hoon uses a 55-column
40code margin and puts a standard line comment at column 57.
42Hoon does not accept non-ASCII text in source files, except UTF-8
43in quoted strings.
45## Tall and flat forms
47There are two kinds of Hoon expression syntax: *tall* and *flat*.
48Most stems have both tall and flat forms. Tall twigs can contain
49flat twigs, but not vice versa.
51Visually, a tall twig looks like a "statement" and a flat twig
52like an "expression," preserving the attractive visual shape of
53procedural code without the nasty side effects.
55## Regular and irregular forms
57Most stems have *regular forms*, which share a common design.
58There is a regular flat form and a regular tall form; most stems
59implement both. All tall forms are regular.
61Some twigs also have *irregular forms*, which follow no
62principles at all. All irregular forms are flat.
64Some twigs (simple leafy ones) have *only* irregular forms.
66## Keywords versus runes
68A regular form starts with a *sigil*, which is either a
69*keyword* or a *rune* -- at the programmer's choice.
71A *keyword* is `:` and then the stem label - eg, `:cons`.
73A *rune* is a pair of ASCII punctuation marks (a digraph) - eg,
74`:-`. The first glyph in the rune indicates the category - eg,
75`:` runes make cells. Runes can be pronounced by their glyphs or
76by their stem -- for `:-`, you can say either "colhep" or "cons".
78Keywords may be less challenging for early learners. Rune style
79is less cluttered and distracting for experienced programmers;
80the system codebase is all in rune style. Beginners can start
81with keywords and move to runes; start with runes and stick
82with runes; or start with keywords and stick with keywords.
84Here's the FizzBuzz demo code, in idiomatic rune syntax. Compare
85with the [original](../../demo).
87```
88 |= end/atom
89 =/ count 1
90 |- ^- (list tape)
91 ?: =(100 count) ~
92 :_ $(count (add 1 count))
93 ?: =(0 (mod count 15))
94 "FizzBuzz"
95 ?: =(0 (mod count 5))
96 "Fizz"
97 ?: =(0 (mod count 3))
98 "Buzz"
99 (text !>(count))
100```
102## Tall regular form
104Tall regular form starts with the sigil, followed by a `gap`
105(any whitespace except `ace`), followed by a bulb whose twigs are
106separated by `gap`.
108There are four body subtypes: *fixed*, *running*, *jogging*, and
109*battery*. Stems with a *fixed* number of subexpressions
110self-terminate. For instance, `:if` has three subexpressions and
111is self-terminating. Otherwise the twig is terminated by a
112`gap`, then either `==` (*running* or *jogging*, most twigs) or
113`--` (*battery*).
115The *running* body is a list of twigs. The *jogging* body is a
116list of twig pairs, separated by a `gap`. The *battery* body is
117a list of symbol-twig pairs, separated by a gap, prefixed by `++`
118and then a gap.
120This definition is enough to parse. But the proper shape of the
121whitespace gaps demands an informal convention.
123Whitespace design in Hoon is an art, not a science. It involves
124both tall/flat mode switches and well-shaped gaps. (Hoon layout
125could probably be done automatically with reasonable quality.
126But it would at least take machine learning, not a rule engine.)
128There only two real *rules* in Hoon whitespace design: don't
129go past 80 characters, and don't use (completely) blank lines.
130Otherwise, if it looks good and is easy to read, it's good. But
131the best way to learn the art is to do everything by convention
132until you know what you're doing. Here are the conventions:
134### Conventions: *fixed*
136Bulbs with *fixed* fanout use "backstep" indentation, which slopes
137backward and to the right by two spaces per line. The first
138child is two spaces after the end of the sigil.
140Some *1-fixed*, *2-fixed*, *3-fixed* and *4-fixed* examples:
142```
143|.
146=| p
149?: p
150 q
153%^ p
154 q
155 r
157```
159The hope of backstep indentation is that the heaviest twigs are
160at the bottom, keeping code flow vertical rather than diagonal.
161Alternate, reversing
163### Conventions: *running*
165A *running* bulb (a simple child list) puts the first child two
166spaces after the end of the sigil, and the following children
167straight down:
169A *running* example:
171```
172:* p
173 q
174 r
175 s
176 t
177==
178```
180### Conventions: *jogging*
182A *jogging* bulb (a list of child pairs) is like a running bulb,
183but backsteps the head of the pair above the tail. Most jogging
184twigs start with a *fixed* sequence; the first jogging pair is
185below and two steps backward from the last fixed child.
187There are two jogging conventions: *flat* (pair on one line) and
188*tall* (pair split across lines).
190A *flat jogging* example (preceded by *1-fixed* `p`)
192```
193?- p
194 q r
195 s t
196 u v
197==
198```
200A *tall jogging* example (preceded by *1-fixed* `p`):
202```
203?- p
204 q
205 r
206 s
207 t
208 u
209 v
210==
211```
213### Conventions: *battery*
215A *battery* bulb is a list of symbol-twig pairs, for the battery
216of a core. A conventional example:
218```
219|%
220++ foo
221 p
222++ bar
223 q
224--
225```
227## Flat regular form
229Flat regular form starts with the sigil, followed by `pal`
230(`(`, left parenthesis), followed by a bulb whose subexpressions
231are separated by `ace` (one space), followed by `par` (`)`, right
232parenthesis).
234A twig in flat form, `:if`, `?:`, `{$if p/twig q/twig r/twig}`:
236```
237:if(p q r)
239?:(p q r)
240```
242The only exception is *jogging* bodies, in which subexpression
243pairs are separated by commas:
245```
246:make(foo bar 42, baz 55, moo 17)
247```
249There is no flat regular form for *battery* bodies. Be tall.
251## Naming conventions
253Hoon does not enforce any rule on symbols, except that capitals
254are not allowed (use kebab-case). However, a lot of system code
255is written in using "lapidary" conventions that need explanation.
257Naming things is one of the hard problems in CS. Dodging this
258problem is one of the reasons mathematicians use Greek letters,
259not variable names. Meaningful names also interpose a verbal
260interpretation, distracting at best and confusing at worst, on
261the formula or algorithm. Greek letters are not *meaningful*,
262but they are *memorable*. And their interpretation is defined by
263the formula and nothing else.
265### Lapidary and ultralapidary
267In the *lapidary* naming style, labels are pronounceable
268three-letter strings, usually CVC (consonant-vowel-consonant).
269Sometimes they encode a mnemonic, but usually they are just
270memorable. Labels are reused wherever the analogy seems
271appropriate.
273In the *ultralapidary* naming style, labels are single letters,
274starting in order of construction from `a`, or within a tuple
275mold `p`. Hoon uses single-letter names for the same reason
276Algol style languages pass arguments by order, rather than
277keyword. Naming items by order makes sense when there are no
278more than three or four; five is stretching it; six is too many.
280For example, when defining `add`, we want to name the operands
281`a` and `b`. It's silly to call them `foo` and `bar`, let alone
282`left-operand` and `right-operand`. The smaller the scale of an
283algorithm, the simpler its names should be.
285### When in doubt, don't be lapidary
287This works in the other direction: namelessness doesn't scale.
288Most normal code shouldn't use lapidary naming at all. (There is
289too much lapidary Hoon in Urbit.)
291Lapidary naming is only for *inherently simple code*: code that
292both aspires to high elegance and clarity, and *is solving a
293simple and elegant problem*.
295Given an ugly or complex problem, lapidary naming is a liability,
296no matter the excellence of the programmer. When in doubt, use
297long names and/or kebab-case.