These runes modify the subject. (Or more precisely, they evaluate at least one of their subexpressions with a modified subject.)
Overview
Hoon doesn't have variables in the ordinary sense. If you want to bind a name
to a value, e.g., a to 12, you do so by pinning 12 to the subject and
associating the name with it. This sort of operation is done with the =
family of runes.
Let's say you have some old subject p. To 'pin' a value to the head means to
modify the subject by repacing it with a cell of [new-value p]. The head of
the cell is the new value. So to pin 12 with the face a the new subject
would be: [a=12 p].
Of course there are many variations on ways to modify the subject, useful for
different situations. Hence the whole family of = runes.
Runes
=> "tisgar"
[%tsgr p=hoon q=hoon]: compose two expressions.
Produces
the product of q, with the product of p taken as the subject.
Syntax
Regular: 2-fixed.
Examples
> =>([a=1 b=2 c=3] b)
2
> =>((add 2 4) [. .])
[6 6]=| "tisbar"
[%tsbr p=spec q=hoon]: combine a default type value with the subject.
Expands to
=+(*p q)
Syntax
Regular: 2-fixed.
Discussion
The default (or 'bunt') value of p is pinned to the head of the subject. Usually p includes a name for ease of reference.
Speaking more loosely, =| usually "declares a variable" which is "uninitialized," presumably because you'll set it in a loop or similar.
Examples
~zod:dojo> =foo |= a=@
=| b=@
=- :(add a b c)
c=2
~zod:dojo> (foo 5)
7=: "tiscol"
[%tscl p=(list (pair wing hoon)) q=hoon]: change multiple legs in the subject.
Expands to
=>(%_(. p) q)
Syntax
Regular: jogging, then 1-fixed.
Discussion
This rune is like =., but for modifying the values of multiple legs of the subject.
Examples
~zod:dojo> =+ a=[b=1 c=2]
=: c.a 4
b.a 3
==
a
[b=3 c=4]=, "tiscom"
[%tscm p=hoon q=hoon]: expose namespace
p evaluates to a noun with some namespace. From within q you may access p's names without a wing path (i.e., you can use face b rather than b.p). This is especially useful for calling arms from an imported library core or for calling arms from a stdlib core repeatedly.
Syntax
Regular: 2-fixed.
Examples
With an imported core:
> (sum -7 --7)
-find.sum
[crash message]
> (sum:si -7 --7)
--0
> =, si (sum -7 --7)
--0With a dojo-defined face:
> =/ fan [bab=2 baz=[3 qux=4]]
=, fan
[bab qux.baz]
[2 4]=. "tisdot"
[%tsdt p=wing q=hoon r=hoon]: change one leg in the subject.
Expands to
=>(%_(. p q) r)
Syntax
Regular: 3-fixed.
Discussion
Technically the =. rune doesn't change the subject. It creates
a new subject just like the old one except for a changed value at p. Note that the mutation uses %_ ("cencab"), so the type at p doesn't change. Trying to change the value type results in a nest-fail.
Examples
> =+ a=[b=1 c=2]
=. b.a 3
a
[b=3 c=2]
> =+ a=[b=1 c=2]
=.(b.a 3 a)
[b=3 c=2]
> =+ a=[b=1 c=2]
=.(b.a "hello" a)
nest-fail=- "tishep"
[%tshp p=hoon q=hoon]: combine a new noun with the subject, inverted.
Expands to
=>([q .] p)
Syntax
Regular: 2-fixed.
Discussion
=- is just like =+ but its subexpressions are reversed. =- looks better than =+ when the expression you're pinning to the subject is much smaller than the expression that uses it.
Examples
~zod:dojo> =foo |= a=@
=+ b=1
=- (add a b c)
c=2
~zod:dojo> (foo 5)
8=^ "tisket"
[%tskt p=skin q=wing r=hoon s=hoon]: pin the head of a pair; change
a leg with the tail.
Expands to
=/(p -.r =.(q +.r s))
Syntax
Regular: 4-fixed.
Discussion
p is a new name (possibly with type annotation, e.g., a=@) of a value to be pinned to the subject. The value of p is the head of the product of r. q is given the value of the tail of r's product. Then s is evaluated against this new subject.
We generally use =^ when we have a state machine with a function, r, that
produces a cell, whose head is a result and whose tail is a new
state. The head value is given a new name p, and the
tail is stuffed back into wherever we stored the old state, q.
This may also remind you of Haskell's State monad.
Examples
The og core is a stateful pseudo-random number generator.
We have to change the core state every time we generate a
random number, so we use =^:
~zod:dojo> =+ rng=~(. og 420)
=^ r1 rng (rads:rng 100)
=^ r2 rng (rads:rng 100)
[r1 r2]
[99 46]=< "tisgal"
[%tsgl p=hoon q=hoon]: compose two expressions, inverted.
Expands to
=>(q p)
Syntax
Regular: 2-fixed.
Irregular: foo:baz is =<(foo baz).
Discussion
=< is just => backwards.
Examples
~zod:dojo> =<(b [a=1 b=2 c=3])
2
~zod:dojo> =< b
[a=1 b=2 c=3]
2
~zod:dojo> b:[a=1 b=2 c=3]
2
~zod:dojo> [. .]:(add 2 4)
[6 6]=+ "tislus"
[%tsls p=hoon q=hoon]: combine a new noun with the subject.
Expands to
=>([p .] q)
Syntax
Regular: 2-fixed.
Discussion
The subject of the =+ expression, call it a, becomes the cell [p a] for the evaluation of q. That is, =+ 'pins a value', p, to the head of the subject.
Loosely speaking, =+ is the simplest way of "declaring a variable."
Examples
=; "tismic"
[%tsmc p=skin q=hoon r=hoon]: combine a named noun with the subject, possibly with type annotation; inverted order.
Expands to
=/(p r q)
Syntax
Regular: 3-fixed.
Discussion
=; is exactly like =/ except that the order of its last two subexpressions is reversed.
Examples
~zod:dojo> =foo |= a=@
=/ b 1
=; c=@ :(add a b c)
2
~zod:dojo> (foo 5)
8=/ "tisfas"
[%tsfs p=skin q=hoon r=hoon]: combine a named noun with the subject, possibly with type annotation.
Expands to
if p is a name, (e.g. a):
=+(^=(p q) r)
if p is a name with a type (e.g., a=@):
=+(^-(p q) r)
Desugaring
?@ p
=+ p=q
r
=+ ^-($=(p.p q.p) q)
r
Syntax
Regular: 3-fixed.
Discussion
p can be either a name or a name=type. If it's just a name,
=/ ("tisfas") "declares a type-inferred variable." If it has a type, =/
"declares a type-checked variable."
Examples
~zod:dojo> =foo |= a=@
=/ b 1
=/ c=@ 2
:(add a b c)
~zod:dojo> (foo 5)
8=~ "tissig"
[%tssg p=(list hoon)]: compose many expressions.
Produces
The product of the chain composition.
Syntax
Regular: running.
Examples
~zod:dojo> =~ [sub (mul 3 20) (add 10 20)]
(sub +)
+(.)
==
31
~zod:dojo> =foo =| n=@
=< =~ increment
increment
increment
n
==
|%
++ increment
..increment(n +(n))
--
~zod:dojo> foo
3=* "tistar"
[%tstr p=term q=hoon r=hoon]: define a macro.
Produces
r, compiled with a subject in which p is a macro for q.
Syntax
Regular: 3-fixed.
Discussion
The difference between macroing and pinning is that pinning changes the subject, but for macroing the subject noun stays the same. The macro'd expression, q, is recorded in the type information of p. q is calculated every time you use the p macro.
Examples
~zod:dojo>
=+ a=1
=* b a
[a b]
[1 1]
~zod:dojo>
=+ a=1
=* b a
=. a 2
[a b]
[2 2]=? "tiswut"
[$tswt p=wing q=hoon r=hoon s=hoon]: conditionally change one leg in the subject.
Expands to
=. p ?:(q r p)
s
Syntax
Regular: 4-fixed.
Discussion
Use =? to replace the value of leg p with r on condition q. As
usual, we are not actually mutating the subject, just creating
a new subject with a changed value. The change in value includes a
type check against the old subject; the type of r must nest under
the type of p.
Examples
> =a 12
> =?(a =(1 1) 22 a)
22
> =?(a =(1 2) 22 a)
12