Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions content/hoon/rune/zap.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,17 +426,19 @@ None

#### Discussion

`.p` is a wing reference like `foo`, `bar.foo`, etc. If `.p` exists, `.q`. If `.p` does not exist, `.r`. Essentially, this is like `?:` for wing existence.
`.p` is a wing reference like `foo`, `bar.foo`, etc. If `.p` does *not* exist, `.q`. If `.p` does exist, `.r`. Essentially, this is like `?:` for wing existence, with the non-existence case first.

Note the branch order: `.q` is the "missing" branch and `.r` is the "found" branch. This order was reversed in 2025; code written against the previous ordering will compile but take the wrong branch.

#### Examples

```
> =foo 42

> !@(foo 'exists' 'does not exist')
> !@(foo 'does not exist' 'exists')
'exists'

> !@(baz 'exists' 'does not exist')
> !@(baz 'does not exist' 'exists')
'does not exist'
```

Expand Down
5 changes: 3 additions & 2 deletions content/hoon/stdlib/1b.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ Specifically, `+peg` just concatenates the bits of the input, excluding the most

#### Accepts

`.a` is an `$atom`.
`.a` is an `$atom`. It must be non-zero; `+peg` crashes on `0`.

`.b` is an `$atom`.
`.b` is an `$atom`. It must also be non-zero; `+peg` crashes on `0`.

#### Produces

Expand All @@ -243,6 +243,7 @@ An `$atom`.
~/ %peg
|= [a=@ b=@]
?< =(0 a)
?< =(0 b)
^- @
?- b
%1 a
Expand Down
9 changes: 5 additions & 4 deletions content/hoon/stdlib/2h.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ A `$flag`.
=| [l=(unit) r=(unit)]
|. ^- ?
?~ a &
?& ?~(l & (gor n.a u.l))
?~(r & (gor u.r n.a))
?~(l.a & ?&((mor n.a n.l.a) $(a l.a, l `n.a)))
?~(r.a & ?&((mor n.a n.r.a) $(a r.a, r `n.a)))
?& ?~(l & &((gor n.a u.l) !=(n.a u.l)))
?~(r & &((gor u.r n.a) !=(u.r n.a)))
?~(l.a & ?&((mor n.a n.l.a) !=(n.a n.l.a) $(a l.a, l `n.a)))
?~(r.a & ?&((mor n.a n.r.a) !=(n.a n.r.a) $(a r.a, r `n.a)))
==
```

Expand Down Expand Up @@ -267,6 +267,7 @@ A `+set`.
++ del
~/ %del
|* b=*
=> .(b `_?>(?=(^ a) n.a)`b)
|- ^+ a
?~ a
~
Expand Down
77 changes: 43 additions & 34 deletions content/hoon/stdlib/2i.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,15 +207,13 @@ See section [`2f`](2f.md) for more information on `$noun` ordering.

Bifurcate.

Splits `+map` `.a` into two `+map`s `.l` and `.r`, which contain the items either side of key `.b` with value `.c` but not including the pair of key `.b` and value `.c`.
Splits `+map` `.a` into two `+map`s `.l` and `.r`, which contain the items either side of key `.b`, not including the item at key `.b`.

#### Accepts

`.a` is a `+map`, and is the sample of `+by`.

`.b` is a `$noun`.

`.c` is a `$noun`.
`.b` is a `$noun`, the key to split at.

#### Produces

Expand All @@ -226,41 +224,54 @@ A cell of two `+map`s.
```hoon
++ bif
~/ %bif
|* [b=* c=*]
^+ [l=a r=a]
=< +
|- ^+ a
|* b=*
|- ^+ [l=a r=a]
?~ a
[[b c] ~ ~]
[~ ~]
?: =(b p.n.a)
?: =(c q.n.a)
a
a(n [b c])
+.a
?: (gor b p.n.a)
=+ d=$(a l.a)
?> ?=(^ d)
d(r a(l r.d))
[l.d a(l r.d)]
=+ d=$(a r.a)
?> ?=(^ d)
d(l a(r l.d))
[a(r l.d) r.d]
```

#### Examples

```
> =a (malt `(list [@tas @])`~[a+1 b+2 c+3 d+4 e+5])

> (~(bif by a) b+2)
[l=[n=[p=%e q=5] l=~ r=~] r=[n=[p=%d q=4] l=~ r=[n=[p=%c q=3] l={[p=%a q=1]} r={}]]]
> (~(bif by a) %b)
[ l=[n=[p=%e q=5] l=~ r=~]
r=[n=[p=%d q=4] l=~ r=[n=[p=%c q=3] l={[p=%a q=1]} r={}]]
]

> `[(map @tas @) (map @tas @)]`(~(bif by a) b+2)
> `[(map @tas @) (map @tas @)]`(~(bif by a) %b)
[{[p=%e q=5]} {[p=%d q=4] [p=%a q=1] [p=%c q=3]}]
```

#### Discussion

Note that `+map`s are horizontally ordered by the [`+mug`](2e.md#mug) hash of their keys and vertically ordered by the double-`+mug` hash of their keys. This means bifurcating the `+map` `(malt ~[10^10 20^20 30^30 40^40 50^50])` at `30^30` will not produce `[{10^10 20^20} {40^40 50^50}]`, but rather `[{20^20} {10^10 40^40 50^50}]` due to the tree structure resulting from their `+mug` hashes.

`+bif:by` formerly took two arguments, a key `.b` and a value `.c`, and inserted
that pair if it was absent. It now takes the key alone and never inserts. Because
the sample is `b=*`, **calling it the old way does not raise an error** — the two
arguments are passed as the single cell `[b c]`, so the map is split at that cell
rather than at the key, and the item at `.b` is left in the result. Callers written
against the old signature therefore fail silently. For example:

```
> `[(map @tas @) (map @tas @)]`(~(bif by a) b+2)
[{[p=%e q=5] [p=%b q=2] [p=%d q=4] [p=%a q=1]} {[p=%c q=3]}]
```

The map is split on the noun `[%b 2]`, and `[p=%b q=2]` is still present in the
result rather than having been removed.

---

### `+del:by` {#delby}
Expand All @@ -285,6 +296,7 @@ A `+map`.
++ del
~/ %del
|* b=*
=> .(b `_?>(?=(^ a) p.n.a)`b)
|- ^+ a
?~ a
~
Expand Down Expand Up @@ -338,23 +350,20 @@ A `+map`.
```hoon
++ dif
~/ %dif
=+ b=a
|@
++ $
|- ^+ a
?~ b
a
=+ c=(bif p.n.b q.n.b)
?> ?=(^ c)
=+ d=$(a l.c, b l.b)
=+ e=$(a r.c, b r.b)
|- ^- [$?(~ _a)]
?~ d e
?~ e d
?: (mor p.n.d p.n.e)
d(r $(d r.d))
e(l $(e l.e))
--
|* b=_a
|- ^+ a
?~ b
a
=+ c=(bif p.n.b)
?> ?=(^ c)
=+ d=$(a l.c, b l.b)
=+ e=$(a r.c, b r.b)
|- ^- [$?(~ _a)]
?~ d e
?~ e d
?: (mor p.n.d p.n.e)
d(r $(d r.d))
e(l $(e l.e))
```

#### Examples
Expand Down
3 changes: 2 additions & 1 deletion content/hoon/stdlib/3d.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ Produces an `$atom` by using SHA-256 plus a salt input. The [bitwise XOR](2d.md)
++ shas
~/ %shas
|= [sal=@ ruz=@]
(shax (mix sal (shax ruz)))
=/ len (max 32 (met 3 sal))
(shay len (mix sal (shax ruz)))
```

#### Examples
Expand Down
30 changes: 22 additions & 8 deletions content/hoon/stdlib/4b.md
Original file line number Diff line number Diff line change
Expand Up @@ -930,26 +930,26 @@ An `$atom`.

## `+trim` {#trim}

Tape split.
List split.

Split first `.a` characters off `$tape` `.b`.
Split first `.a` elements off `+list` `.b`.

#### Accepts

`.a` is an `$atom`.

`.b` is a `$tape`.
`.b` is a `+list` of any type.

#### Produces

A cell of `$tape`s, `.p` and `.q`.
A cell of two `+list`s of the same type as `.b`, `.p` and `.q`.

#### Source

```hoon
++ trim
|= [a=@ b=tape]
^- [p=tape q=tape]
|* [a=@ b=(list)]
^+ [p=b q=b]
?~ b
[~ ~]
?: =(0 a)
Expand All @@ -962,14 +962,28 @@ A cell of `$tape`s, `.p` and `.q`.

```
> (trim 5 "lasok termun")
[p="lasok" q=" termun"]
[p=[i='l' t="asok"] q=[i=' ' t="termun"]]
```

```
> (trim 5 "zam")
[p="zam" q=""]
[p=[i='z' t="am"] q=~]
```

```
> (trim 2 `(list @ud)`~[1 2 3 4])
[p=[i=1 t=~[2]] q=[i=3 t=~[4]]]
```

#### Discussion

`+trim` was formerly a dry gate over `$tape` (`|= [a=@ b=tape]`) and is now a
wet gate over `+list`, so it works on a list of any type. One consequence is
that the product is no longer cast to `$tape`, so a tape argument produces a
list that pretty-prints structurally (`[i='l' t="asok"]`) rather than as
`"lasok"`. The value is unchanged; only the inferred type and its printed form
differ.

---

## `+trip` {#trip}
Expand Down
61 changes: 44 additions & 17 deletions content/hoon/stdlib/4f.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,11 +432,18 @@ A `$rule`.

Indentation block.

Apply `$rule` to indented block starting at current column number, omitting the leading whitespace.
Apply `$rule` to a delimited, indented block starting at the current column number, omitting the leading whitespace.

#### Accepts

`.sef` is a `$rule`.
`.ope` is a `$rule` matching the block's opening delimiter.

`.end` is a `$rule` matching the block's closing delimiter.

`.sef` is a `$rule` applied to the block's contents.

The first two are passed together as a cell, so the call shape is
`(inde [ope end] sef)`.

#### Produces

Expand All @@ -445,36 +452,56 @@ A `$rule`.
#### Source

```hoon
++ inde |* sef=rule
|= nail ^+ (sef)
=+ [har tap]=[p q]:+<
++ inde
|* [[ope=rule end=rule] sef=rule]
|= tub=nail ^+ (sef)
=* har p.tub
=* tap q.tub
=+ lev=(fil 3 (dec q.har) ' ')
=+ eol=(just `@t`10)
=+ =- roq=((star ;~(pose prn ;~(sfix eol (jest lev)) -)) har tap)
;~(simu ;~(plug eol eol) eol)
=+ and=;~(plug eol (jest lev) end)
:: get block contents without the indenting spaces
::
=/ roq
%. tub
=/ led
;~ pose
;~(sfix eol (jest lev)) :: eat leading spaces
;~(simu ;~(plug eol eol) eol) :: allow empty lines
==
;~ pfix ope led
%- star
;~(less and ;~(pose prn led))
==
?~ q.roq roq
=+ vex=(sef har(q 1) p.u.q.roq)
:: parse block contents fully
::
=+ vex=((full sef) har(q 1) p.u.q.roq)
:: indent hair, produce result, continue after block
::
=+ fur=p.vex(q (add (dec q.har) q.p.vex))
?~ q.vex vex(p fur)
=- vex(p fur, u.q -)
:+ &3.vex
&4.vex(q.p (add (dec q.har) q.p.&4.vex))
=+ res=|4.vex
|- ?~ res |4.roq
?. =(10 -.res) [-.res $(res +.res)]
(welp [`@t`10 (trip lev)] $(res +.res))
=+ vux=(and p.roq q.q.u.q.roq)
?~ q.vux vux
[p.vux ~ p.u.q.vex q.u.q.vux]
```

#### Examples

```
> `tape`(scan " foo\0a bar" ;~(pfix ace ace ace (inde (star ;~(pose prn (just '\0a'))))))
> `tape`(scan "\"\"\"\0afoo\0abar\0a\"\"\"" (inde [(jest '"""') (jest '"""')] (star ;~(pose prn (just `@`10)))))
"foo\0abar"
```

#### Discussion

Note the amount of indentation whitespace to be stripped from the beginning of each line is determined by the value of `.q` (the column) in the `$hair` when `+inde` is first called. This means something like the `+pfix` expression in the example above is necessary to set the level of indentation. Additionally, the `$rule` given to `+inde` must consume the whole line including the line ending.
Note the amount of indentation whitespace to be stripped from the beginning of each line is determined by the value of `.q` (the column) in the `$hair` when `+inde` is first called. Additionally, the `$rule` given to `+inde` must consume the whole line including the line ending.

`+inde` previously took only `.sef` and was called as `(inde sef)`, with the
indentation level established by a preceding `+pfix`. It was rewritten to take
explicit opening and closing delimiters; the one-argument call now fails to
compile with `mull-grow` / `-find.sef`. The kernel uses it this way to parse
`"""` block strings (see `+quote-innards` in `sys/hoon.hoon`).

---

Expand Down
Loading