Urbit / Docs

Arms + “lus”

A core is a cell of [battery payload]. The battery is made of one or more arms, each of which is a computation on its parent core.

Arm runes are used to define arms in a core, and thus can only be used from within an expression that produces a multi-arm core. That means arm runes cannot be used to mark the beginning of a first-class expression -- there is no such thing in Hoon as an arm without a core.

There are various arm runes you can use to produce different kinds of arms. Normal arms use ++; arms defining a structure (or 'mold') use +$; and constructor arms use +*.

Runes

+| "lusbar"

Chapter label.

Syntax

Regular: 1-fixed.

+|  %label
Discussion

The +| doesn't produce an arm. It instead provides a label for the arms that follow it. The arms of a core can be divided into chapters for 'organization'. Chapter labels aren't part of the underlying noun of the core; they're stored as type system metadata only.

See tome in the Hoon standard library.

Examples

Let's look at what the Hoon compiler's parser, ream, does with the +| rune:

> (ream '|%  +|  %numbers  ++  two  2  ++  three  3  --')
[ %brcn
  p=~
    q
  { [ p=%numbers
      q=[p=~ q={[p=%three q=[%sand p=%ud q=3]] [p=%two q=[%sand p=%ud q=2]]}]
    ]
  }
]

Notice that p.q has the label %numbers. Contrast with:

> (ream '|%  ++  two  2  ++  three  3  --')
[ %brcn
  p=~
    q
  { [ p=%$
      q=[p=~ q={[p=%three q=[%sand p=%ud q=3]] [p=%two q=[%sand p=%ud q=2]]}]
    ]
  }
]

+$ "lusbus"

Produce a structure arm (type definition).

Syntax

Regular: 2-fixed.

+$  p=term  q=spec

p is an arm name, and q is any structure expression.

Discussion

Arms produced by +$ are essentially type definitions. They should be used when one wants to define custom types using core arms.

The Hoon subexpression, q, must be a structure expression. That is, it must be either a basic structure expression (*, ~, ^, ?, and @), or a complex expression made with the $ family of runes (including irregular variants). Names of structures are also permitted (e.g., tape).

Examples
> =c |%
       +$  atom-pair  $:(@ @)
       +$  flag-atom  $:(? @)
     --

> `atom-pair.c`[12 14]
[12 14]

> `atom-pair.c`[12 [22 33]]
nest-fail

> `flag-atom.c`[& 22]
[%.y 22]

++ "luslus"

Produce a normal arm.

Syntax

Regular: 2-fixed.

++  p=term  q=hoon

p is the arm name, and q is any Hoon expression.

Discussion

All arms must have a name (e.g., add). An arm is computed by name resolution. (This resolution is implicit in the case of $ arms. See |=, |-, and |^.) The ++ rune is used for explicitly giving a name to an arm.

Any Hoon expression, q, may be used to define the arm computation.

Examples
> =c |%
       ++  two  2
       ++  increment  |=([email protected] +(a))
     --

> two.c
2

> (increment.c 11)
12

+* "lustar"

Produce a type constructor arm.

Syntax

Regular: 2-fixed.

+*  p=term  [q=term]  r=spec

p is the arm name, q is the name of the argument for the constructor function enclosed in square brackets, and r is a structure expression that defines the constructor function.

Discussion

Arms produced by +* are essentially type constructors. They are used to construct new types from ones you already have. Consider list, which takes some type -- e.g., @, tape, etc. -- and returns a new type, e.g., (list @), (list tape), etc.

The Hoon subexpression, r, must be a structure expression. That is, it must be either a basic structure expression (*, ~, ^, ?, and @), or a complex expression made with the $ family of runes (including irregular variants).

Examples
> =c |%
       +*  triple  [a]  [a a a]
       +*  wrap-flag  [a]  [? a]
     --

> `(triple.c @)`[12 14 16]
[12 14 16]

> `(triple.c ?)`[12 14 16]
nest-fail

> `(triple.c ?)`[& | |]
[%.y %.n %.n]

> `(wrap-flag.c @)`[& 22]
[%.y 22]