@@ -0,0 +1,502 @@
7+This document discusses hoon's two main string types: `cord`s (as well as its
8+subsets `knot` and `term`) and `tape`s. Cords are strings encoded in atoms, and
9+tapes are strings encoded as lists of single characters. The focus of this
10+document is on their basic properties, syntax and the most common text-related
11+functions you'll regularly encounter. In particular, it discusses conversions
12+and the encoding/decoding of atom auras in strings.
14+Hoon has a system for writing more elaborate functional parsers, but that is not
15+touched on here. Instead, see the [Parsing](/docs/hoon/guides/parsing) guide.
16+Hoon also has a type for UTF-32 strings, but those are rarely used and not
17+discussed in this document.
19+There are a good deal more text manipulation functions than are discussed here.
20+See the [Further Reading](#further-reading) section for details.
26+A [`cord`](/docs/hoon/reference/stdlib/2q#cord) has an aura of
27+`@t`. It denotes UTF-8 text encoded in an atom, little-endian. That is, the
28+first character in the text is the least-significant byte. A cord may contain
29+any UTF-8 characters, there are no restrictions.
31+The `hoon` syntax for a cord is some text wrapped in single-quotes like:
37+single-quotes and backslashes must be escaped with a backslash like:
40+'\'quotes\' \\backslashes\\'
43+Characters can also be entered as hex, they just have to be escaped by a
44+backslash. For example, `'\21\21\21'` will render as `'!!!'`. This is useful for
45+entering special characters such as line breaks like `'foo\0abar'`.
47+Cords divided over multiple lines are allowed. There are two ways to do this.
48+The first is to start and end with three single-quotes like:
58+The line endings will be encoded Unix-style as line feed characters like:
64+The second is to begin with a single-quote like usual, then break the line by
65+ending it with a backslash and start the next line with a forward-slash like:
73+This will be parsed to:
81+A [`knot`](/docs/hoon/reference/stdlib/2q#knot) has an aura of
82+`@ta`, and is a subset of a [`cord`](#cord). It allows lower-case letters,
83+numbers, and four special characters: Hyphen, tilde, underscore and period. Its
84+restricted set of characters is intended to be URL-safe.
86+The `hoon` syntax for a knot is a string containing any of the aforementioned
87+characters prepended with `~.` like:
95+A [`term`](/docs/hoon/reference/stdlib/2q#term) has an aura of
96+`@tas`, and is a subset of a [`knot`](#knot). It only allows lower-case letters,
97+numbers, and hyphens. Additionally, the first character cannot be a hyphen. This
98+is a very restricted text atom, and is intended for naming data structures and
101+The `hoon` syntax for a term is a string conforming to the prior description,
102+prepended with a `%` like:
108+#### A note about `term` type inference
110+There is actually an even more restricted text atom form with the same `%foo`
111+syntax as a term, where the type of the text is the text itself. For example, in
119+The hoon parser will, by default, infer the type of `%foo`-style syntax this
120+way. If we try with the dojo type printer:
128+This type-as-itself is used for many things, such as unions like:
134+In order to give `%foo` the more generic `@tas` aura, it must be explicitly
143+This is something to be wary of. For example, if you wanted to form a `(set @tas)` you might think to do:
146+(silt (limo ~[%foo %bar %baz]))
149+However, this will actually form a set of the union `?(%foo %bar %baz)` due to
150+the specificity of type inference:
153+> ? (silt (limo ~[%foo %bar %baz]))
154+ ?(%~ [?(n=%bar n=%baz n=%foo) l=nlr(?(%bar %baz %foo)) r=nlr(?(%bar %baz %foo))])
155+[n=%baz l={%bar} r={%foo}]
158+One further note about the type-as-itself form: Ocassionally you may wish to
159+form a union of strings which contain characters disallowed in `term`s. To get
160+around this, you can enclose the text after the `%` with single-quotes like
163+### Aura type validity
165+The hoon parser will balk at `cord`s, `knot`s and `term`s containing invalid
166+characters. However, because they're merely auras, any atom can be cast to them.
167+When cast (or clammed), they will **not** be validated in terms of whether the
168+characters are allowed in the specified aura.
170+For example, you can do this:
177+This means you cannot rely on mere aura-casting if you need the text to conform
178+to the specified aura's restrictions. Instead, there are a couple of function in
179+the standard library to check text aura validity:
180+[`+sane`](/docs/hoon/reference/stdlib/4b#sane) and
181+[`+sand`](/docs/hoon/reference/stdlib/4b#sane).
183+The `+sane` function takes an argument of either `%ta` or `%tas` to validate
184+`@ta` and `@tas` respectively (you can technically give it `%t` for `@t` too but
185+there's no real point). It will return `%.y` if the given atom is valid for the
186+given aura, and `%.n` if it isn't. For example:
189+> ((sane %tas) 'foo')
191+> ((sane %tas) 'foo!')
195+The `+sand` function does the same thing, but rather than returning a `?` it
196+returns a `unit` of the given atom, or `~` if validation failed. For example:
199+> `(unit @tas)`((sand %tas) 'foo')
201+> `(unit @tas)`((sand %tas) 'foo!')
207+A [`tape`](/docs/hoon/reference/stdlib/2q#tape) is the other
208+main string type in hoon. Rather than a single atom, it's instead a list of
209+individual `@tD` characters (the `D` specifies a bit-length of 8, see the
210+[Auras](/docs/hoon/reference/auras#bitwidth) documentation for
211+details). The head of the list is the first character in the string.
213+The `hoon` syntax for a tape is some text wrapped in double-quotes like:
219+Double-quotes, backslashes and left-braces must be escaped by a backslash
223+"\"double-quotes\" \\backslash\\ left-brace:\{"
226+Like with `cord`s, characters can also be entered as hex escaped by a backslash
227+so `"\21\21\21"` renders as `"!!!"`.
229+Tapes divided over multiple lines are allowed. Unlike [`cord`](#cord)s, there is
230+only one way to do this, which is by starting and ending with three
241+The line endings will be encoded Unix-style as line feed characters like:
247+As mentioned earlier, tapes are lists of single characters:
250+> `tape`~['f' 'o' 'o']
254+This means they can be manipulated with ordinary list functions:
257+> `tape`(turn "foobar" succ)
263+Tapes, unlike cords, allow string interpolation. Arbitrary `hoon` may be
264+embedded in the tape syntax and its product will be included in the resulting
265+tape. There are two ways to do it:
269+In the first case, the code to be evaluated is enclosed in braces. The type of
270+the product of the code must itself be a tape. For example, if the `@p` of our
271+ship is stored in `our`, simply doing `"{our}"` will fail because its type will
272+be `@p` rather than `tape`. Instead, we must explicitly use the
273+[`+scow`](/docs/hoon/reference/stdlib/4m#scow) function to
274+render `our` as a tape:
284+> "[{(scow %p our)} {(scow %da now)}]"
285+"[~zod ~2021.10.3..08.59.10..2335]"
290+Rather than having to manually render data as a `tape`, angle brackets _inside_
291+the braces tell the interpreter to automatically pretty-print the product of the
292+expression as a tape. This way we needn't use functions like `+scow` and can
293+just reference things like `our` directly:
311+"[~zod ~2021.10.3..09.01.14..1654]"
316+Tapes can easily be converted to cords and vice versa. There are two stdlib
317+functions for this purpose: [`+crip`](/docs/hoon/reference/stdlib/4b#crip) and
318+[`+trip`](/docs/hoon/reference/stdlib/4b#trip). The former converts a `tape` to
319+a `cord` and the latter does the opposite. For example:
328+Knots and terms can also be converted to tapes with `+trip`:
337+Likewise, the output of `+crip` can be cast to a knot or term:
340+> `@tas`(crip "foobar")
342+> `@ta`(crip "foobar")
344+> `@tas`(need ((sand %tas) (crip "foobar")))
350+It's common to encode atoms in cords or knots, particularly when constructing a
351+[scry](/docs/arvo/concepts/scry) [`path`](/docs/hoon/reference/stdlib/2q#path)
352+or just a `path` in general. There are two main functions for this purpose:
353+[`+scot`](/docs/hoon/reference/stdlib/4m#scot) and
354+[`+scow`](/docs/hoon/reference/stdlib/4m#scow). The former produces a `knot`,
355+and the latter produces a `tape`. Additionally, there are two more functions for
356+encoding `path`s in cords and tapes respectively:
357+[`+spat`](/docs/hoon/reference/stdlib/4m#spat) and
358+[`+spud`](/docs/hoon/reference/stdlib/4m#spud).
360+### `+scot` and `+spat`
362+`+scot` encodes atoms of various auras in a `knot` (or `cord`/`term` with
363+casting). It takes two arguments: the aura in a `@tas` and the atom to be
364+encoded. For example:
371+~.~2021.10.4..07.35.54..6d41
373+> (scot %ux 0xaa.bbbb)
377+Note the aura of the atom needn't actually match the specified aura:
384+Hoon can of course be evaluated in its arguments as well:
387+> (scot %ud (add 1 1))
391+You'll most commonly see this used in constructing a `path` like:
394+> /(scot %p our)/garden/(scot %da now)/foo/(scot %ud 123.456)
395+[~.~zod %garden ~.~2021.10.4..07.43.14..a556 %foo ~.123.456 ~]
397+> `path`/(scot %p our)/garden/(scot %da now)/foo/(scot %ud 123.456)
398+/~zod/garden/~2021.10.4..07.43.23..9a0f/foo/123.456
401+`+spat` simply encodes a `path` in a cord like:
404+> (spat /foo/bar/baz)
408+### `+scow` and `+spud`
410+`+scow` is the same as [`+scot`](#scot-and-spat) except it produces a tape
411+rather than a knot. For example:
418+"~2021.10.4..07.45.25..b720"
420+> (scow %ux 0xaa.bbbb)
424+`+spud` simply encodes a `path` in a tape:
427+> (spud /foo/bar/baz)
431+## Decoding from text
433+For decoding atoms of particular auras encoded in cords, there are three
434+functions: [`+slat`](/docs/hoon/reference/stdlib/4m#slat),
435+[`+slav`](/docs/hoon/reference/stdlib/4m#slav), and
436+[`+slaw`](/docs/hoon/reference/stdlib/4m#slaw). Additionally, there is
437+[`+stab`](/docs/hoon/reference/stdlib/4m#stab) for decoding a cord to a path.
439+`+slav` parses the given cord with the aura specified as a `@tas`, crashing if
440+the parsing failed. For example:
443+> `@da`(slav %da '~2021.10.4..11.26.54')
446+> `@p`(slav %p '~zod')
450+dojo: hoon expression failed
453+`+slaw` is like `+slav` except it produces a `unit` which is null if parsing
454+failed, rather than crashing. For example:
457+> `(unit @da)`(slaw %da '~2021.10.4..11.26.54')
458+[~ ~2021.10.4..11.26.54]
460+> `(unit @p)`(slaw %p '~zod')
467+`+slat` is a curried version of `+slaw`, meaning it's given the aura and
468+produces a new gate which takes the actual cord. For example:
471+> `(unit @da)`((slat %da) '~2021.10.4..11.26.54')
472+[~ ~2021.10.4..11.26.54]
474+> `(unit @p)`((slat %p) '~zod')
481+Finally, `+stab` parses a cord containing a path to a `path`. For example:
484+> (stab '/foo/bar/baz')
490+- [Parsing](/docs/hoon/guides/parsing) - A guide to writing fully-fledged
491+ functional parsers in hoon.
492+- [Auras](/docs/hoon/reference/auras) - Details of auras in hoon.
494+- [stdlib 2b: List logic](/docs/hoon/reference/stdlib/2b) - Standard library
495+ functions for manipulating lists, which are useful for dealing with tapes.
496+- [stdlib 2q: Molds and Mold-builders](/docs/hoon/reference/stdlib/2q) - Several
497+ text types are defined in this section of the standard library.
498+- [stdlib 4b: Text processing](/docs/hoon/reference/stdlib/4b) - Standard
499+ library functions for manipulating and converting tapes and strings.
501+- [stdlib 4m: Formatting functions](/docs/hoon/reference/stdlib/4m) - Standard
502+ library functions for encoding and decoding atom auras in strings.