From e10d61c1aec14f00feeeead8c02db21ad53e39d8 Mon Sep 17 00:00:00 2001 From: Sigilante Date: Tue, 4 Aug 2026 15:05:12 -0600 Subject: [PATCH] docs: document typed paths ($pith, $iota, +pave, +pout, +stip) Against urbit@08026c84b2. Typed paths were entirely undocumented. Every example below was run on a fake ship (urbit-408k-rc1.pill). Molds (stdlib/4o.md): $iota typed path segment (hoon.hoon:2105) -- either a bare @tas, or a tagged pair naming the aura of the value it holds $pith typed urbit path (hoon.hoon:2097) -- (list iota), a path whose segments carry their aura rather than being flattened to @ta Formatting functions (stdlib/4m.md): +pave path -> pith (hoon.hoon:5999); segments that match no known aura fall back to [%ta segment] +pout pith -> path (hoon.hoon:5992); the inverse, rendering each iota with +scot +stip typed path parser (hoon.hoon:5972), with its two arms: +spot:stip parse one segment +swot:stip parse a whole /-separated path The core reduces to +swot, so +stip used directly parses a path. The trap worth documenting, found by trying it rather than reading it: casting a $path to a $pith does NOT parse the segments. > (pave /foo/123/0xdead) ~[%foo [%ud 123] [%ux 0xdead]] > `pith`/foo/123 ~[%foo %123] The cast merely retypes the existing @ta segments, so `%123` stays a term rather than becoming [%ud 123]. Anyone reaching for a $pith by casting gets something that type-checks and is wrong. Noted in both $pith and +pave. All examples verified: (pave /foo/123/0xdead) ~[%foo [%ud 123] [%ux 0xdead]] (pout (pave /foo/123/0xdead)) /foo/123/0xdead (rash '123' spot:stip) [%ud 123] (rash '0xdead' spot:stip) [%ux 0xdead] (rash '/foo/123' swot:stip) [%foo [i=[%ud 123] t=~]] NOT included here: +hew. It belongs in stdlib/2c.md at exactly the insertion point the undocumented-Hoon-features PR uses for +ham, so adding it on this branch would conflict. It is being added to that branch instead, where it belongs alongside the other bit-arithmetic arms. All anchors verified to resolve. Co-Authored-By: Claude Opus 5 --- content/hoon/stdlib/4m.md | 115 ++++++++++++++++++++++++++++++++++++++ content/hoon/stdlib/4o.md | 70 +++++++++++++++++++++++ 2 files changed, 185 insertions(+) diff --git a/content/hoon/stdlib/4m.md b/content/hoon/stdlib/4m.md index 5e39f141..9bc0a25e 100644 --- a/content/hoon/stdlib/4m.md +++ b/content/hoon/stdlib/4m.md @@ -15,6 +15,76 @@ layout: # 4m: Formatting Functions +## `+pave` {#pave} + +Parse `$path` to [`$pith`](4o.md#pith). + +Parses each segment of a `$path` into a typed [`$iota`](4o.md#iota). A segment that does not parse as any recognised aura is kept as `[%ta segment]`. + +#### Accepts + +`.path` is a `$path`. + +#### Produces + +A [`$pith`](4o.md#pith). + +#### Source + +```hoon +++ pave + |= =path + ^- pith + %+ turn path + |= i=@ta + (fall (rush i spot:stip) [%ta i]) +``` + +#### Examples + +``` +> (pave /foo/123/0xdead) +~[%foo [%ud 123] [%ux 0xdead]] +``` + +Note that a cast does not do this — `` `pith`/foo/123 `` produces `~[%foo %123]`, leaving the segments as bare `@tas`. + +--- + +## `+pout` {#pout} + +Render [`$pith`](4o.md#pith) to `$path`. + +The inverse of [`+pave`](#pave): renders each [`$iota`](4o.md#iota) back to a `@ta` segment with [`+scot`](#scot). + +#### Accepts + +`.pith` is a [`$pith`](4o.md#pith). + +#### Produces + +A `$path`. + +#### Source + +```hoon +++ pout + |= =pith + ^- path + %+ turn pith + |= i=iota + ?@(i i (scot i)) +``` + +#### Examples + +``` +> (pout (pave /foo/123/0xdead)) +/foo/123/0xdead +``` + +--- + ## `+scot` {#scot} Render `$dime` as `$cord`. @@ -527,6 +597,51 @@ A `$path`, or crash. --- +## `+stip` {#stip} + +Typed path parser. + +A parser core for [`$pith`](4o.md#pith)s. Used by [`+pave`](#pave). + +#### Source + +```hoon +++ stip + =< swot + |% + ++ swot |=(n=nail (;~(pfix fas (more fas spot)) n)) + :: + ++ spot + %+ sear (soft iota) +``` + +The core reduces to `+swot`, so `+stip` used directly parses a whole path. + +### `+spot:stip` {#spotstip} + +Parses a single path segment into an [`$iota`](4o.md#iota). + +``` +> (rash '123' spot:stip) +[%ud 123] +``` + +``` +> (rash '0xdead' spot:stip) +[%ux 0xdead] +``` + +### `+swot:stip` {#swotstip} + +Parses a whole `/`-separated path into a [`$pith`](4o.md#pith). + +``` +> (rash '/foo/123' swot:stip) +[%foo [i=[%ud 123] t=~]] +``` + +--- + ## `+stap` {#stap} Path parser. diff --git a/content/hoon/stdlib/4o.md b/content/hoon/stdlib/4o.md index ebe42ea9..63f2c713 100644 --- a/content/hoon/stdlib/4o.md +++ b/content/hoon/stdlib/4o.md @@ -99,6 +99,76 @@ See also: [`$base`](#base), aura reference --- +## `$iota` {#iota} + +Typed path segment. + +A single segment of a [`$pith`](#pith). Either a bare `@tas`, or a tagged pair naming the aura of the value it holds. + +#### Source + +```hoon ++$ iota + $+ iota + $~ [%n ~] + $@ @tas + $% [%ub @ub] [%uc @uc] [%ud @ud] [%ui @ui] + [%ux @ux] [%uv @uv] [%uw @uw] + [%sb @sb] [%sc @sc] [%sd @sd] [%si @si] + [%sx @sx] [%sv @sv] [%sw @sw] + [%da @da] [%dr @dr] + [%f ?] [%n ~] + [%if @if] [%is @is] + [%t @t] [%ta @ta] + [%p @p] [%q @q] + [%rs @rs] [%rd @rd] [%rh @rh] [%rq @rq] + == +``` + +#### Examples + +``` +> (rash '123' spot:stip) +[%ud 123] +``` + +``` +> (rash '0xdead' spot:stip) +[%ux 0xdead] +``` + +--- + +## `$pith` {#pith} + +Typed Urbit path. + +A `$pith` is a `(list iota)` — a path whose segments carry their aura, rather than being flattened to `@ta` as in an ordinary `$path`. + +#### Source + +```hoon ++$ pith (list iota) +``` + +#### Examples + +``` +> (pave /foo/123/0xdead) +~[%foo [%ud 123] [%ux 0xdead]] +``` + +Note that **casting a `$path` to a `$pith` does not parse the segments** — it merely retypes them as bare `@tas`: + +``` +> `pith`/foo/123 +~[%foo %123] +``` + +Use [`+pave`](4m.md#pave) to actually parse a `$path` into a `$pith`. + +--- + ## `$base` {#base} Base type.