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]]}]
]
}
]
+$
"lusbuc"
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 |=(a=@ +(a))
--
> two.c
2
> (increment.c 11)
12
+*
"lustar"
Defines aliases within doors.
Syntax
Regular: variadic.
+* a=term b=hoon
c=term d=hoon
...
e=term f=hoon
a
, c
, e
are arm names and b
, d
, f
are any Hoon expression. Note that unlike all other
runes with a variable number of arguments, the list of arguments of +*
does
not end with a terminator.
+*
arms must always come at the beginning of the battery, before any other
type of lus arm.
Discussion
The primary use of +*
is to create aliases within doors (see Examples below).
Aliases given by +*
do not count towards the number of arms in the door and
thus are also called "virtual arms", which
can be important for things like Gall app cores that require a fixed number of arms.
Under the hood, +*
gets compiled as =*
's. +* foo bar
rewrites each ++
arm beneath it in the core to include
=* foo bar
. For example, the interpreter sees the Nock compiled from this Hoon expression
|_ z=@ud
+* n 1
++ x (add z n)
++ y (sub z n)
--
as being identical the Nock compiled from this one:
=| z=@ud
|%
++ x
=* n 1
(add z n)
++ y
=* n 1
(sub z n)
--
Examples
To assign an alias to a door, we often write the following.
|_ foo
+* this .
This is the idomatic way to assign the alias this
to the door.
Sometimes cores, such as Gall app cores, have a fixed number of arms, but you'd
like to include more. This is where aliases employed as "virtual arms" may be of
use. We note that it is often better style to compose cores with =>
or =<
to add more arms to a
Gall app core. This usage of +*
is controversial and should be minimized.
|_ =bowl:gall
+* this .
samp +<
cont +>
This assigns the door the alias this
, the sample of the door samp
, and the
context of the door cont
.
You may also call functions with +*
by making use of e.g. the %~
rune.
=<
|_ a=@
+* do ~(. +> a)
++ stuff foo:do
::etc
--
|_ b=@
++ foo %bar
::etc
--