[Text strings](https://en.wikipedia.org/wiki/String_%28computer_science%29%) are sequences of characters. At one level, the file containing code is itself a string—at a more fine-grained level, we take strings to mean either byte sequences obtained from literals (like `'Hello Mars'`) or from external APIs. This blog post will expand on [existing docs](https://developers.urbit.org/guides/additional/strings) to explain what is going on with text in various corners of Hoon.
A `cord` is a [UTF-8](https://en.wikipedia.org/wiki/UTF-8) [LSB](https://en.wikipedia.org/wiki/Bit_numbering#Least_significant_byte) atom used to represent text directly. A `cord` is denoted by single quotes `'surrounding the text'` and has no restrictions other than requiring valid UTF-8 content (thus all Unicode characters). `cord`s are preferred over `tape`s when text is not being processed.
```hoon
> *@t
''
> ((sane %t) 'Hello Mars!')
%.y
```
One big difference between `cord`s and strings in other languages is that Urbit uniformly expects escape characters (such as `\n`, newline) to be written as their ASCII value in hexadecimal: thus, Hoon uses `\0a` for C-style `\n`.
### `knot` (`@ta`)
A `knot` is an atom type that permits only a subset of the URL-safe ASCII characters (thus excluding control characters, spaces, upper-case characters, and ``!"#$%&'()*+,/:;<=>?@[\]^` {|}``). Stated positively, `knot`s can contain lower-case characters, numbers, and `-._~`. A `knot` is denoted by starting with the unique prefix `~.` sigdot. Generally `knot`s are used for paths (as in Clay, for wires, and so forth).
As the Dojo doesn't actually check for atom validity, it is possible to erroneously "cast" a value into a `knot` representation when it is not a valid `knot`. Use `++sane` to produce a check gate to avoid attempting to parse invalid `knot`s.
```hoon
> *@ta
~.
> ((sane %ta) 'Hello Mars!')
%.n
> ((sane %ta) 'hellomars')
%.y
```
You can see all ASCII characters checked for their `knot` compatibility using ``(turn (gulf 32 127) |=(a=@ [`@t`a ((sane %ta) a)]))``. `++wood` is a `cord` escape: it catches `@ta`-invalid characters in `@t`s and converts them lossily to `@ta`.
### `term` (`@tas`)
A `term` is an atom type intended for marking tags, types, and labels. A value prefixed with `%` cen such as `%hello` is first a _constant_ (_q.v._) and only possesses `term`-nature if explicitly marked as such with `@tas`. A term is [defined](https://developers.urbit.org/reference/hoon/basic) as “an atomic ASCII string which obeys symbol rules: lowercase anddigit only, infix hyphen, first character must be a lowercase letter.”
As with `knot`s, values can be incorrectly cast to `@tas` in the Dojo. Use `++sane` to avoid issues as a result of this behavior.
Here we also use the _type spear_`-:!>` to extract the type of the values demonstratively.
```hoon
> *@tas
%$
> -:!>(%hello-mars)
#t/%hello-mars
> -:!>(`@tas`%hello-mars)
#t/@tas
> ((sane %tas) 'Hello Mars!')
%.n
> ((sane %tas) 'hello-mars')
%.y
> -:!>(%~)
#t/%~
```
### `tape` (`(list @tD)`)
A `tape` is a list of `@tD` 8-bit atoms. Similar to `cord`s, `tape`s support UTF-8 text and all Unicode characters. Each byte is represented as its own serial entry, rather than as a whole character. `tape`s are `list`s not atoms, meaning they can be easily parsed and processed using `list` tools such as `++snag`, `++oust`, and so forth.
```hoon
> ""
""
> `(list @)`""
~
> "Hello Mars!"
"Hello Mars!"
> "Hello \"Mars\"!"
"Hello \"Mars\"!"
> `(list @t)`"Hello \"Mars\"!"
<|H e l l o " M a r s " !|>
```
The `tape` type is slightly more restrictive than just `(list @t)`, and so `(list @t)` has a slightly different representation yielded to it by the pretty-printer.
What's the `@tD` doing in `(list @tD)`? By convention, a suffixed upper-case letter indicates the size of the entry in bits, with `A` for 2⁰ = 1, `B` for 2¹ = 2, `C` for 2² = 4, `D` for 2³ = 8, and so forth. While the inclusion of `D` isn't coercive, it is advisory: a `tape` is processed in such a way that multi-byte characters are broken into successive bytes:
- [`++slaw`](https://developers.urbit.org/reference/hoon/stdlib/4m#slaw) converts a `cord` representation—in Hoon aura notation—into an `unit` of `@` atom.
Most commonly, developers will represent text using either `tape`s or `cord`s. Both of these facilitate straightforward direct representation as string literals using either single quotes `'example of cord'` or double quotes `"example of tape"`.
As a practical matter, `tape`s occupy more space than their corresponding `cord`s. `tape`s are implemented as linked lists in the runtime. These are easy to work with but consume more memory and can take longer to process in some ways.
A `cord` can be transformed into a `tape` using `++trip` (mnemonic "tape rip"). The reverse transformation, from `tape` to `cord`, is accomplished via `++crip` (mnemonic "cord rip").
Unicode is a chart of character representations, with each character receiving a unique number or _codepoint_. This codepoint is then represented in various ways in binary encodings, the most common of which is [UTF-8](https://en.wikipedia.org/wiki/UTF-8). UTF-8 is a variable-byte encoding scheme which balances the economy of representing common characters like ASCII using only a single byte with the ability to represent characters from more complex character sets like Chinese `漢語` or Cherokee `ᏣᎳᎩ ᎦᏬᏂᎯᏍᏗ`. While something of a pain when processing byte-by-byte, this allows for an adaptively compact way of writing values (rather than the mostly-zeroes [UTF-32](https://en.wikipedia.org/wiki/UTF-32) mode, available in Urbit as `@c`.) A `char` is a self-conscious UTF-8 single byte in Hoon, but it's simply an alias for `@t` and doesn't enforce bitwidth.
Joel Spolsky wrote [a classic article on Unicode](https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/) which happily has been partly-superseded by much more extensive software support in the two decades since its publication.
As just mentioned, Unicode has several distinct encoding schemes. [UTF-32](https://en.wikipedia.org/wiki/UTF-32) can represent any Unicode value in four bytes, meaning that index accesses are direct (rather than needing to be calculated as with UTF-8). Urbit provides UTF-32 `@c` data for the terminal stack to use with terminal cursor position, but otherwise they are not used much. You never see these in practice in userspace.
One library, `l10n`, proposes to handle text as a list of UTF-8 multi-byte characters, `calf` or `(list @t)`, rather than a `tape`, which has each byte as a separate entry. This eases processing for certain Unicode text operations.
Moving past the simple text types, we find that text alone provides little information about structure or display. Formatted print trees, or `tank`s, are commonly used to produce error messages and other data displays within the Dojo.
A `tank` is a structure of tagged values. The tag indicates to the pretty-printer how to convert the final value to a `tape` for output (using `ram:re`).
Gall agents and Clay both use `path`s to uniquely identify resources such as noun data on the file system or subscriptions. Furthermore, a `wire` is an alias for a `path` which particularly denotes the subscriber's identification, preferably unique. Any valid `@ta` value separated by `/` fas values becomes a `path`, and `=` tis entries in the first three slots are expanded to the Clay `beak`.
[JSON](https://en.wikipedia.org/wiki/JSON) is a data interchange format based on text. Web apps and several other platforms use JSON as a fairly concise human-readable way to transmit information, including text.
Hoon represents the equivalent structure of the JSON as a tagged noun. This requires parsing a JSON string into a tagged noun structure, then reparsing that into particular Hoon values.
Notice at this point that most of the values in the `json` data structure are tagged with `%s` string except for a few: `%a` array, `%b` boolean, `%n` number, and `%o` map. The tricky part to deal with in reparsing these values back to and from text are the `%n` numbers, since Hoon has several number types.
Thus we must consider how to convert `json` values [to](https://developers.urbit.org/reference/hoon/zuse/2d_6) and [from](https://developers.urbit.org/reference/hoon/zuse/2d_1-5) Hoon representations. Fortunately, most gates one would need are already included in the Zuse standard library for handling `json` structures. The standard JSON-style operations include:
Another category of converters are the MIME parsers. These are nominally for webpages serving content, but prove useful in a variety of other situations as well.
Sail is Hoon's internal markup for HTML and XML. It can support all HTML tags and attributes. The [Sail guide](https://developers.urbit.org/guides/additional/sail) contains full details on how to work with the markup format, but here I want to briefly demonstrate how text in Sail is handled.
The `;` markers open a tag or, within a string like `<p>`'s content, mark subsequent lines. Since the entire Sail file is a `tape`, we can use `tape` interpolation to inject the results of Hoon expressions.
This article may be considered a sister to the Hoon School pages on [“Trees and Addressing (Tapes)”](https://developers.urbit.org/guides/core/hoon-school/G-trees#exercise-tapes-for-text) and [“Text Processing I”](https://developers.urbit.org/guides/core/hoon-school/J-stdlib-text). There are further details on many elements of working with strings in [“Working with Strings”](https://developers.urbit.org/guides/additional/strings), unsurprisingly.