--- navhome: /docs/ sort: 14 next: true title: Concepts --- # Concepts and terminology Usually, a new language is an improvement on one you already know. If it isn't, it probably at least shares concepts with a large family of relatives. These concepts come with words, like _variable_ or _function_, that map cleanly onto its semantics. In Hoon we throw away many of these words and invent new ones, which mean almost the same things. But why? ## Motivation Hoon has no close relatives. The normal jargon of programming maps poorly onto its semantics. Some of the common concepts used only informally in Hoon include "function," "object," "event," "variable," "label," "closure", "environment," "scope," and probably a few more. We do use these words informally, but we're always making an analogy whose precision depends on context. Hoon has concepts *like* all these abstractions, but they remain *false cognates*. The closer an inexact cognate, the more unsettling it feels when the abstractions don't match. Learning a few new words is a small price for avoiding this pain point. ## Concepts A few major Hoon concepts: `noun` (data), `nock` (interpreter), [`hoon`](#-hoon) (AST node), [`mint`](#-mint) (compiler), [`type`](#-type) (type), `gate` (function), `mold` (constructor), `core` (object), `mark` (protocol). ### `noun` (data value) A value in Hoon is called a `noun`. A noun is either a unsigned integer of any size (`atom`), or an ordered pair of any two nouns (`cell`). Nouns are like Lisp S-expressions, but simpler (Lisp atoms effectively have dynamic type bits). The simplest noun syntax uses brackets, like `[a b]` for the cell of `a` and `b`. Brackets nest right; `[a b c d]` is `[a [b [c d]]]`. A noun list, by convention, goes from left to right and is null-terminated. That said, Hoon uses tuples (improper nouns) more freely than Lisp; only genuinely iterative structures are null-terminated lists. When an atom is used as a string (a `cord`), the bytes are always UTF-8 in LSB first order. When you see `'foo'` and `%foo`, this refers to the integer `0x6f.6f66`, aka `7.303.014`. (Hoon syntax uses `.` to break integer atoms in the German style, because `.`'s are URL-safe and `,`'s aren't.) One common operation on nouns is `slot`, a tree addressing scheme which maps an atom to a subtree. The whole noun is slot `1`; the left child of `n` is `2n`, the right child `2n+1`. Nothing in Nock, Hoon, or Urbit can create cycles in a noun or detect pointer equivalence. Nouns are generally implemented with reference counting, and have a lazy short Merkle hash to help with equality testing and associative containers. ### `nock` (interpreter) Hoon compiles itself to the [Nock](../../nock) VM. Nock is a Turing-complete, non-lambda combinator function. The function takes a cell `{subject formula}`, and produces a noun `product`. To program in Hoon, this is all you need to know about Nock. But it's still fun and useful to [learn more](../../nock). ## Compilation concepts ### `hoon` (AST node) A [`hoon`](../reference) is the result of parsing a Hoon source expression into an AST node. These AST nodes are nouns, like all other Hoon data. Because every Hoon program is, in its entirety, a single expression of Hoon, the result of parsing the whole thing into an AST is a single `hoon`. A hoon is a tagged union of the form `[%tag data]`, where the tag is a constant such as `%brts` (from the source `|=`, i.e. "bartis"), and is matched up with the appropriate type of data (often more `hoon`s, from source subexpressions). For example, the expression `:-(2 17)`, once parsed into an AST, becomes the following: ``` [%clhp p=[%sand p=%ud q=2] q=[%sand p=%ud q=17]] ``` The `%clhp` is produced from the rune `:-` (i.e. "colhep"). The 2 and 17 have each been parsed as `%sand`-tagged hoons, which represent atoms (in this case each with an aura of `%ud`, i.e. unsigned decimal). To parse Hoon source into a hoon AST, use `ream` on a `cord` containing Hoon source. Try the following in `dojo`: ``` (ream ':+(12 7 %a)') ``` The result should be: ``` [%clls p=[%sand p=%ud q=12] q=[%sand p=%ud q=7] r=[%rock p=%tas q=97]] ``` ### `mint` (compiler) [`mint`](#-mint) is the Hoon compiler. It maps a cell `[type hoon]` to a cell `[type nock]`, where a [`type`](#-type) is type information, a [`hoon`](#-hoon) is a parsed expression (AST), and a `nock` is a Nock formula. `mint` takes as input the subject type and a parsed source expression; it produces a product type and an executable formula. Calculating the output type from the input `hoon` and subject type is called "type inference". If you've used another typed functional language, like Haskell, the Hoon compiler's type inference does the same job but with less intelligence. Haskell infers backward and forward; Hoon only infers forward. Hoon can't figure out the type of a noun from how you use it, only from how you make it. Hoon can infer tail recursion, but not head recursion. Low-powered type inference means you need more type annotations, which makes your program more readable anyway. Also, the dumber the compiler, the easier it is for a dumb human to understand what the compiler is thinking. The `mint` gate is inside the core `++ ut`, so call it using the following syntax: ``` (~( ) ) ``` The `` is mint, the `` is `ut`, `` is the subject type, and `` is the parsed Hoon AST (i.e., a `hoon` from the last section). What's ``? It's another piece of type information. As part of the type-checking process, mint checks that the output type "nests" within the input type, i.e. that the output type is a subset of the input type. If not, mint halts with a `nest-fail` crash. Let's compile an example `hoon` from the last subsection into Nock. Try the following in Dojo: (~(mint ut %noun) %noun [%clhp p=[%sand p=%ud q=2] q=[%sand p=%ud q=17]]) ### `type` (type, as range) A `type` defines a set (finite or infinite) of nouns and ascribes some semantics to it. There is no direct syntax for defining types; they are always defined by inference (i.e., by [`mint`](#-mint)), usually using a constructor (`mold`). All types are assembled out of base types defined in `++type`. (Look up `++ type` in hoon.hoon for examples.) When the compiler does type-inference on a program, it assembles complex types out of the simpler built-in types. ### `gate` (function) A `gate` is a Hoon function (lambda or closure). Other constructs in Urbit are functions in the mathematical sense -- for instance, a Nock formula is also a function. But a gate is not a formula. The gate's argument is its *sample*; the result is its *product*. ### `core` (object) A `core` has no exact equivalent in conventional languages, but the closest equivalent is an object. An object has methods; a core has functionally computed attributes (*arms*). An arm that produces a gate is the Hoon equivalent of a conventional method; think of it as a computed attribute whose value is a lambda. A gate is a special case of a core: a core with one arm, whose name is the empty string. The shape of a core is `[battery payload]`, where *battery* is a tree of Nock formulas ### `mold` (constructor) A `mold` is a constructor function (`gate`). Its sample is any noun; its product is a structured noun. A mold is idempotent; `(mold (mold x))` always equals `(mold x)`. Because there's no such thing as a [`type`](#-type) declaration, we use molds to define useful types by example; we also use them to validate untrusted network data. ### `face` (named variable) In a conventional language, we have a scope, environment or symbol table. Declaring a variable, like e.g. `int foo = 3`, adds the name `foo` to the table with type `int`. The Hoon analogue is `=/(foo atom 3 ...)`, where `foo` is a `face` and `atom` is the type. But Hoon has a homoiconic heap; there is no inscrutable scope or environment. There is just the subject, which is one noun. To "declare a variable" is to make a cell `[variable old-subject]`, and use that as the subject of the next expression. The label `foo` isn't a key in a symbol table; it's stored as a kind of metadata, in the type ([`type`](#-type)) of the new value. It's not a variable named `foo`, whose value is of type `atom`; it's a subtree of type `foo:atom`. ### `limb` (attribute or variable reference) A [`limb`](../limb/limb/), like `foo`, is Hoon's equivalent of a variable reference. A limb is a [`hoon`](#-hoon); given a subject [`type`](#-type), [`mint`](#-mint) resolves it to a Nock formula and a product [`type`](#-type). To resolve limb `foo`, [`mint`](#-mint) searches the subject depth-first, head-first for either a `face` named `foo`, or a `core` with the arm `foo`. If it finds a face, the product is a *leg*, or subtree of the subject. If it finds a core, it computes the arm formula with that core as the subject. A limb can also be a slot (direct tree address), like `+15`. The hoon compiler always resolves a limb to a tree axis lookup, regardless of the kind of limb. `boo:[foo=12 baz=23 boo=34]` evaluates to `34`. `+6:[foo=12 baz=23 boo=34]` evaluates to `baz=23`. ### `wing` ([`limb`](#-limb) path) A [wing](../limb/wing/) is a list of limbs. Like attribute references in a conventional language, it uses the syntax `a.b.c`, but inside out: Hoon `a.b.c` means "a within b within c", the equivalent of `c.b.a` in any other language. All limbs but the last, here `a`, must be legs. ### `mark` (type, as protocol name) A `mark` (really an Arvo concept, not a Hoon concept) is Urbit's version of a MIME type, if a MIME type was an executable specification. The mark is just a label that's used as a path to a local source file in the Arvo filesystem. This source file defines a core that can mold untrusted data, diff and patch, convert to other marks, etc. If this sounds like magic, it isn't quite magic. There's no way for different urbits to make sure they mean the same thing by the same mark. However, when incompatibility happens, marks ensure that we at least handle the situation in a predictable way.