on fc8a545 help sign in
urbit.org/docs/hoon/syntax.md
395 lines 13 kB history raw
1---
2navhome: /docs/
3sort: 12
4next: true
5title: Syntax
6---
8# Hoon syntax
10Hoon's syntax is unusual, and to beginners it can look a lot more
11complex than it really is. However, we believe that anyone who
12learns Hoon syntax will find that it has a number of advantages.
14# Motivation
16Hoon syntax is trying to solve three serious
17problems in functional syntax design. These are *terminator
18piles*, *indentation creep*, and *feature/label confusion*.
20## Terminator piles
22*Terminator piles* are like Lisp's stacks of right parentheses.
23Significant whitespace solves this problem and creates others.
25Hoon has no terminator piles. Except for a 1-space / more-space
26distinction, it has no significant whitespace.
28## Indentation creep
30*Indentation creep* is a problem caused by indentation conventions
31where the indentation point is a function of expression tree
32depth. This problem is especially irritating when working with
33long functions. It's true that short functions are better, but
34long ones sometimes need to be written.
36A procedural block has a backbone of statements which flows
37straight down. Most expressions are flat and of limited depth.
38With some bulging, a long function flows *down* the page.
40A functional language lacks the expression/statement distinction.
41So a long function means a deep tree. Given normal indentation
42conventions, a long function wants to flow *down and across*.
43This *diagonal* shape fits poorly into most editor windows.
45Thanks to backstep indentation (see below), Hoon programs are
46shaped more or less like procedural programs.
48## Feature/label confusion
50*Feature/label confusion* (FLC) is the result of any syntax that
51makes it hard for the eye to tell whether a token on the screen is
52a feature of the language, or a label in the program. For example,
53in Lisp a special form has the same syntax as a function call.
55The worst-case result of FLC is "DSL cancer." Every source file
56is effectively written in its own domain-specific language. To
57read a new file is to learn a new language—"write-only code."
59User-level macros, operator overloading, even excessive use of
60higher-order programming, can all lead quickly to the tragedy of
61write-only code.
63Hoon has no FLC, user-level macros, or overloading. It does
64support higher-order programming; write-only Hoon can certainly be
65(and has been) written. But good Hoon style is to avoid it.
67# Design
69Hoon has a general syntax design with common principles and
70regularities. We'll cover those here.
72## Glyphs and characters
74Hoon source uses ASCII text. Hoon does not accept non-ASCII
75text in source files, except UTF-8 in quoted strings. Hard
76tab characters are illegal.
78Hoon is a heavy punctuation user. Reading off code aloud
79using the proper names of ASCII symbols is tedious, so we've
80mapped each punctuation glyph to a syllable:
82```
83ace [1 space] gal < pal (
84bar | gap [>1 space, nl] par )
85bas \ gar > sel [
86buc $ hax # sem ;
87cab _ hep - ser ]
88cen % kel { sig ~
89col : ker } soq '
90com , ket ^ tar *
91doq " lus + tec `
92dot . pam & tis =
93fas / pat @ wut ?
94zap !
95```
97You don't need to memorize these glyph names, but it might help.
98Code is often vocalized or subvocalized. "pal" is easier to say,
99aloud or silently, than "left paren".
101Note that the list includes two separate whitespace forms: `ace`
102for a single space; `gap` is either 2+ spaces or a newline. In Hoon,
103the only significance in whitespace is the difference between
104`ace` and `gap`. Comments also count as `gap` whitespace&mdash;they
105start with `::` and run to the end of the line.
107An 80-column right margin is strongly encouraged. Really
108well-groomed Hoon uses a 55-column code margin and puts a standard
109line comment at column 57.
111## Expressions and Runes
113Each regular Hoon expression begins with a
114[rune](https://urbit.org/docs/about/glossary#rune). A rune is a pair
115of ASCII punctuation marks (a digraph)&mdash;e.g., `:-`. The first
116glyph in the rune indicates the category&mdash;e.g., `:` runes make
117[cells](https://urbit.org/docs/about/glossary#cell) (i.e., ordered
118pairs). We pronounce runes using their glyph names&mdash;for `:-`,
119we say "colhep".
121Each rune is followed by one or more subexpressions. The number and
122kind of subexpressions depend on which rune is used.
124```
125:- 25
127```
129The `:-` rune is always followed by two 'value' subexpressions to
130produce a cell: `[25 3]`. The first subexpression, when evaluated,
131becomes the *head* (i.e., the left) of the cell, and the second
132becomes the *tail* (i.e., the right).
134There are two kinds of expressions in Hoon: *value* and *pattern*.
135Value expressions evaluate to any sort of data. They can be as simple
136as `25`, or they may require more computation, as in `(add 22 3)`. The
137`:-` expression above is itself a value expression, as are the vast
138majority of Hoon expressions.
140A pattern expression must be a *mold*, which we'll explain a bit
141[later](https://urbit.org/docs/hoon/basic).
143## Tall and flat styles
145There are two styles of Hoon expression syntax: *tall* and *flat*.
146Most runes can be used in both tall and flat styles. Tall expressions
147are (typically) multi-line, but flat expressions must not have line
148breaks in them. Tall expressions may contain flat ones, but not vice
149versa.
151The `:-` expression in the last subsection was in tall style. Here's
152the flat equivalent:
154`:-(25 3)`
156Visually, the tall style looks more "statement"-like and flat-style
157looks "expression"-like, preserving the attractive visual shape of
158procedural code without the nasty side effects.
160## Regular and irregular forms
162Most runes have *regular forms*, which share a common design.
163There is a regular flat form and a regular tall form; most runes
164have both kinds of implementation. All tall forms are regular.
166Some runes also have *irregular forms*, which follow no
167general principles at all. All irregular forms are flat.
169```
170.= 22
17123
172```
174The `.=` rune tests for equality the two subexpressions that
175follow, and returns a boolean. Above is the tall, regular form of
176`.=`. Below is the irregular form:
178`=(22 23)`
180Some kinds of expression have *only* irregular forms.
182## Tall regular form
184Tall regular forms start with a rune followed by a `gap`.
185(Remember, a `gap` is any whitespace other than `ace`, or a line
186break.) After that are the number and types of subexpressions
187appropriate for that rune. Each subexpression is separated from
188its neighboring subexpressions by a `gap`.
190Everything after the initial rune in an expression is called the
191*body*. There are four body types: *fixed*, *running*, *jogging*,
192and *[battery](https://urbit.org/docs/about/glossary#battery)*.
194Runes with a *fixed* number of subexpressions self-terminate. For
195instance, the `:-` and `.=` runes each have two subexpressions
196and are self-terminating. Otherwise the body is terminated by a
197`gap` followed by either `==` (*running* or *jogging*, most runes)
198or `--` (*battery*).
200The *running* body is a list of *children* (i.e., subexpressions).
201The *jogging* body is a list of child pairs, where the members of
202each pair are separated by a `gap`. The *battery* body is
203a list of symbol-child pairs, each separated by a `gap`. See below
204for examples of each body type.
206This definition is enough to write Hoon that will parse. But
207writing code with optimal whitespace management requires some
208additional informal conventions.
210Whitespace design in Hoon is an art, not a science. It involves
211both tall/flat style switches and well-shaped gaps. (Hoon layout
212could probably be done automatically with reasonable quality.
213But it would at least take machine learning, not a rule engine.)
215There are only two real *rules* in Hoon whitespace design: don't
216go past 80 characters, and don't use (completely) blank lines.
217Otherwise, if it looks good and is easy to read, it's fine. The
218best way to learn the art is to do everything by convention
219until you know what you're doing. Here are the conventions:
221### Conventions: *fixed*
223Expressions with *fixed* bodies use "backstep" indentation, which
224slopes backward and to the right by two spaces per line.
226Some *1-fixed*, *2-fixed*, *3-fixed* and *4-fixed* examples:
228```
229|.
232=| p
235?: p
236 q
239%^ p
240 q
241 r
243```
245In optimal usage of backstep indentation, the most complicated
246expressions are at the bottom, keeping code flow vertical rather than
247diagonal.
249### Conventions: *running*
251A *running* body (a simple child list of arbitrary length) puts the
252first child two spaces after the end of the rune, and the following
253children straight down:
255A *running* example:
257```
258:* p
259 q
260 r
261 s
262 t
263==
264```
266### Conventions: *jogging*
268A *jogging* body (a list of child pairs of arbitrary length) is like
269a running body, but with a pair of children on each line separated by
270two spaces. Most jogging bodies start with a *fixed* sequence;
271the first pair is below and two steps backward from the
272last fixed child.
274There are two jogging conventions: *flat* (pair on one line) and
275*tall* (pair split across lines).
277A *flat jogging* example (preceded by *1-fixed* `p`)
279```
280?- p
281 q r
282 s t
283 u v
284==
285```
287A *tall jogging* example (preceded by *1-fixed* `p`):
289```
290?- p
291 q
292 r
293 s
294 t
295 u
296 v
297==
298```
300### Conventions: *battery*
302A *battery* body has a list of symbol-child pairs, for the
303[battery](https://urbit.org/docs/about/glossary#battery)
304of a
305[core](https://urbit.org/docs/about/glossary#core). A
306conventional example:
308```
309|%
310++ dry-arm-foo
311 %p
312++ dry-arm-bar
313 %q
314+- wet-arm-baz
315 %r
316--
317```
319## Flat regular form
321Flat regular form starts with the rune, followed by `pal`, `(`
322(left parenthesis), followed by a body whose subexpressions
323are all separated by `ace`s (single spaces), followed by `par`,
324`)` (right parenthesis).
326A expression in flat form, `?:`, which is 3-fixed:
328`?:(p q r)`
330The only exception is *jogging* bodies, in which subexpression
331pairs are separated by commas:
333```
334foo(bar 42, baz 55, moo 17)
335```
337There is no flat regular form for *battery* bodies. Be tall.
339## Naming conventions
341Hoon does not enforce any rule on symbols, except that capitals
342are not allowed (use kebab-case). However, a lot of system code
343is written using "lapidary" conventions that need explanation.
345Naming things is one of the hard problems in CS. Dodging this
346problem is one of the reasons mathematicians use Greek letters,
347not variable names. Meaningful names also interpose a verbal
348interpretation, distracting at best and confusing at worst, on
349the formula or algorithm. Greek letters are not *meaningful*,
350but they are *memorable*. And their interpretation is defined by
351the formula and nothing else.
353### Lapidary and ultralapidary
355In the *lapidary* naming style, labels are pronounceable
356three-letter strings, usually CVC (consonant-vowel-consonant).
357Sometimes they encode a mnemonic, but usually they are just
358memorable. Labels are reused wherever the analogy seems
359appropriate.
361In the *ultralapidary* naming style, labels are single letters,
362starting in order of construction from `a`, or within a tuple
363[mold](https://urbit.org/docs/about/glossary#mold) `p`. Hoon
364uses single-letter names for the same reason Algol style
365languages pass arguments by order, rather than keyword. Naming
366items by order makes sense when there are no more than three or
367four; five is stretching it; six is outright ridiculous.
369For example, when defining `add`, we want to name the operands
370`a` and `b`. It's silly to call them `foo` and `bar`, let alone
371`left-operand` and `right-operand`. The smaller the scale of an
372algorithm, the simpler its names should be.
374### When in doubt, don't be lapidary
376This works in the other direction: namelessness doesn't scale.
377Most normal code shouldn't use lapidary naming at all. (Everyone
378agrees: there is *way* too much lapidary Hoon in Urbit.)
380Lapidary naming is only for *inherently simple code*: code that
381both aspires to high elegance and clarity, and *is solving a
382simple and elegant problem*.
384Given an ugly or complex problem, lapidary naming is a liability,
385no matter the excellence of the programmer. When in doubt, use
386long names and/or kebab-case.
388## Freedom
390If you came all this way to learn how to write apps, you're all
391set. This is about all you need to know to start getting your
392hands dirty. Refer back here or to the [standard library](../../hoon/library) when
393needed, but for now, move on to [Arvo](../../arvo) to continue learning.
395If, however, good enough is *not* enough, feel free to dive deeper: