on master help sign in
Merge branch 'urbit:master' into docs/minio-s3-guide
4a1141aTom Snelling
.gitignore+4−3
@@ -5,14 +5,13 @@
5/.pnp
5/.pnp
6.pnp.js
6.pnp.js
7
7
8−/public
9−
10# testing
8# testing
11/coverage
9/coverage
12
10
13# next.js
11# next.js
14/.next/
12/.next/
15/out/
13/out/
14+.next
16
15
17# production
16# production
18/build
17/build
@@ -37,4 +36,6 @@ yarn-error.log*
37.vercel
36.vercel
38
37
39# editors
38# editors
40−/.nova/
39+/.nova/
40+
41+yarn.lock
.npmrcnew file+1
@@ -0,0 +1 @@
1+unsafe-perm = true
components/BubbleLink.jsnew file+25
@@ -0,0 +1,25 @@
1+export default function BubbleLink(props) {
2+ return (
3+ <li className={"list-none " + props.className}>
4+ <a className={"flex"} href={props.href} target={props.target}>
5+ <div>{props.children}</div>
6+ <div className="flex flex-col ml-4">
7+ <p className="font-bold">{props.title}</p>
8+ <p className="text-wall-400 dark:text-antiwall-400 font-bold leading-snug">
9+ {props.caption}
10+ </p>
11+ </div>
12+ </a>
13+ </li>
14+ );
15+}
16+
17+BubbleLink.defaultProps = {
18+ className: "",
19+ title: "",
20+ caption: "",
21+ children: (
22+ <div className="w-12 h-12 bg-wall-500 dark:bg-antiwall-500 rounded-full" />
23+ ),
24+ target: "_blank",
25+};
components/Contact.js−6
@@ -79,12 +79,6 @@ export default function Contact({ emphasize }) {
79 Github
79 Github
80 </a>
80 </a>
81 </h4>
81 </h4>
82− <h4 className="mt-6 text-wall-500">
83− Ask questions in our{" "}
84− <a className={linkText} href={contact.discord}>
85− Discord
86− </a>
87− </h4>
88 <h4 className="mt-4 text-wall-500 flex items-baseline flex-wrap">
82 <h4 className="mt-4 text-wall-500 flex items-baseline flex-wrap">
89 Boot Urbit and join{" "}
83 Boot Urbit and join{" "}
90 <div className="md:ml-2 rounded-lg flex items-stretch">
84 <div className="md:ml-2 rounded-lg flex items-stretch">
components/EventPreview.js+42−38
@@ -4,6 +4,7 @@ import {
4 ShowOrHide,
4 ShowOrHide,
5 ReadableList,
5 ReadableList,
6 Person,
6 Person,
7+ Name,
7 DateRange,
8 DateRange,
8} from "../components/Snippets";
9} from "../components/Snippets";
9import {
10import {
@@ -14,6 +15,42 @@ import {
14 formatTimeZone,
15 formatTimeZone,
15} from "../lib/lib";
16} from "../lib/lib";
16
17
18+// JAL(2021.9.13) Couldn't quite get this to work properly. There's a trailing
19+// "and"
20+//
21+// function GuestList({ guests, textClass }) {
22+
23+// const renderGuests = guests?.length > 2 ? guests?.slice(0,2) : guests;
24+// const noRenderGuestsCount = guests?.slice(2).length;
25+
26+// return (
27+// <p className={textClass + " type-sub"}>
28+// <b>
29+// {renderGuests?.length > 1 ? "With guests " : "With guest "}
30+// </b>
31+// <ReadableList>
32+// {renderGuests?.map((guest, index) => (
33+// <>
34+// <Person
35+// key={`${guest.name}-${guest.patp}`}
36+// nameClassNames={textClass}
37+// patpClassNames={textClass}
38+// name={guest.name}
39+// patp={guest.patp}
40+// />
41+// {renderGuests?.length > 1 ? <span>, </span> : <></>}
42+// </>
43+// ))}
44+// {noRenderGuestsCount > 1 ?
45+// <Name>{noRenderGuestsCount} more </Name>
46+// :
47+// <></>
48+// }
49+// </ReadableList>
50+// </p>
51+// );
52+// }
53+
17export default function EventPreview({ event, className, big }) {
54export default function EventPreview({ event, className, big }) {
18 // Event tiles have a 'dark mode' used when their background images are dark and white text is needed for legibility.
55 // Event tiles have a 'dark mode' used when their background images are dark and white text is needed for legibility.
19 const grayText = event?.dark ? "text-washedWhite" : "text-wall-400";
56 const grayText = event?.dark ? "text-washedWhite" : "text-wall-400";
@@ -46,7 +83,11 @@ export default function EventPreview({ event, className, big }) {
46 } flex-col h-full`}
83 } flex-col h-full`}
47 >
84 >
48 <h3 className={`${blackText} mb-2`}>{event.title}</h3>
85 <h3 className={`${blackText} mb-2`}>{event.title}</h3>
86+ <p className={blackText + ""}>{event.description}</p>
87+ </div>
88+
89+ <div className="absolute p-6 left-0 bottom-0 w-full pr-32">
49− <p className={`${blackText} mb-2`}>{event.location}</p>
90+ <p className={`${blackText} type-sub mb-1`}>{event.location}</p>
50 <DateRange
91 <DateRange
51 starts={starts}
92 starts={starts}
52 ends={ends}
93 ends={ends}
@@ -54,43 +95,6 @@ export default function EventPreview({ event, className, big }) {
54 />
95 />
55 </div>
96 </div>
56
97
57− <div className="absolute p-6 left-0 bottom-0 w-full pr-32">
58− <ShowOrHide condition={event.hosts}>
59− <p className={blackText + " type-sub"}>
60− <b>{"Hosted by "}</b>
61− <ReadableList>
62− {event.hosts?.map((host, index) => (
63− <Person
64− key={`${host.name}-${host.patp}`}
65− nameClassNames={blackText}
66− patpClassNames={blackText}
67− name={host.name}
68− patp={host.patp}
69− />
70− ))}
71− </ReadableList>
72− </p>
73− </ShowOrHide>
74− <ShowOrHide condition={event.guests}>
75− <p className={blackText + " type-sub"}>
76− <b>
77− {event.guests?.length > 1 ? "With guests " : "With guest "}
78− </b>
79− <ReadableList>
80− {event.guests?.map((guest, index) => (
81− <Person
82− key={`${guest.name}-${guest.patp}`}
83− nameClassNames={blackText}
84− patpClassNames={blackText}
85− name={guest.name}
86− patp={guest.patp}
87− />
88− ))}
89− </ReadableList>
90− </p>
91− </ShowOrHide>
92− </div>
93−
94 {inFuture && event.registration_url ? (
98 {inFuture && event.registration_url ? (
95 <div className="absolute right-0 bottom-0 p-6">
99 <div className="absolute right-0 bottom-0 p-6">
96 <a
100 <a
components/Footer.js+1−1
@@ -17,7 +17,7 @@ export default function Footer() {
17 </Link>
17 </Link>
18 <Link href="/using">
18 <Link href="/using">
19 <div>
19 <div>
20− <a className="type-bold text-wall-500">Operator's Manual</a>
20+ <a className="type-bold text-wall-500">User's Manual</a>
21 </div>
21 </div>
22 </Link>
22 </Link>
23 <Link href="https://github.com/urbit/port/releases">
23 <Link href="https://github.com/urbit/port/releases">
components/Header.js+14
@@ -72,6 +72,13 @@ export default function Header(props) {
72 >
72 >
73 Docs
73 Docs
74 </ActiveLink>
74 </ActiveLink>
75+ <ActiveLink
76+ currentPath={currentPath}
77+ className="mr-5 type-ui"
78+ href="/using"
79+ >
80+ Manual
81+ </ActiveLink>
75 <ActiveLink
82 <ActiveLink
76 currentPath={currentPath}
83 currentPath={currentPath}
77 className="mr-5 type-ui"
84 className="mr-5 type-ui"
@@ -93,6 +100,13 @@ export default function Header(props) {
93 >
100 >
94 Get Started
101 Get Started
95 </ActiveLink>
102 </ActiveLink>
103+ <ActiveLink
104+ currentPath={currentPath}
105+ className="mr-5 type-ui"
106+ href="/faq"
107+ >
108+ FAQ
109+ </ActiveLink>
96 <button
110 <button
97 onClick={(e) => {
111 onClick={(e) => {
98 e.stopPropagation();
112 e.stopPropagation();
components/Markdown.js+16−4
@@ -2,9 +2,14 @@ import remark from "remark";
2import gfm from "remark-gfm";
2import gfm from "remark-gfm";
3import slug from "remark-slug";
3import slug from "remark-slug";
4import heading from "remark-heading-id";
4import heading from "remark-heading-id";
5−import html from "remark-html";
6import remarkprism from "remark-prism";
5import remarkprism from "remark-prism";
7import normalize from "mdurl/encode";
6import normalize from "mdurl/encode";
7+import merge from "deepmerge";
8+import github from "hast-util-sanitize/lib/github";
9+import remarkParse from "remark-parse";
10+import remarkRehype from "remark-rehype";
11+import rehypeStringify from "rehype-stringify";
12+import rehypeRaw from "rehype-raw";
8
13
9// img is wrapped in figure so that images can be extra wide in the blog posts
14// img is wrapped in figure so that images can be extra wide in the blog posts
10function Img(h, node) {
15function Img(h, node) {
@@ -30,19 +35,26 @@ const options = {
30 handlers: {
35 handlers: {
31 image: Img,
36 image: Img,
32 },
37 },
33− entities: "numbers",
38+ sanitize: merge(github, {
39+ // remove user-content from github.json to remark-slug work as expected
40+ clobberPrefix: "",
41+ attributes: { "*": ["className"] },
42+ }),
34};
43};
35
44
36// Converts markdown strings into markdown HTML/React components
45// Converts markdown strings into markdown HTML/React components
37export default async function Markdown({ post }) {
46export default async function Markdown({ post }) {
38 const result = await remark()
47 const result = await remark()
39− .use(html, options)
48+ .use(remarkParse, options)
40− .use(gfm)
41 .use(remarkprism, {
49 .use(remarkprism, {
42 plugins: ["show-invisibles"],
50 plugins: ["show-invisibles"],
43 })
51 })
52+ .use(gfm)
44 .use(slug)
53 .use(slug)
45 .use(heading)
54 .use(heading)
55+ .use(remarkRehype, { allowDangerousHtml: true })
56+ .use(rehypeRaw)
57+ .use(rehypeStringify)
46 .process(post.content);
58 .process(post.content);
47
59
48 return result.toString();
60 return result.toString();
components/TableOfContents.js+5−2
@@ -52,9 +52,12 @@ const useHeadingsData = (noh3s) => {
52
52
53const Headings = ({ headings, activeId }) => (
53const Headings = ({ headings, activeId }) => (
54 <ul>
54 <ul>
55− {headings.map((heading) => (
55+ {headings.map((heading, index) => (
56 <li key={heading.id}>
56 <li key={heading.id}>
57+ <a
58+ className={index === 0 ? "font-bold" : "font-medium"}
57− <a className="font-semibold" href={`#${heading.id}`}>
59+ href={`#${heading.id}`}
60+ >
58 {heading.title}
61 {heading.title}
59 </a>
62 </a>
60 {heading.items.length > 0 && (
63 {heading.items.length > 0 && (
content/blog/2021-11-18-report-from-the-field.mdnew file+94
@@ -0,0 +1,94 @@
1++++
2+title = "Report from the field: Assembly 2021"
3+date = "2021-11-18"
4+description = "The system builds the community and the community builds the system."
5+[extra]
6+author = "Galen Wolfe-Pauly"
7+ship = "~ravmel-ropdyl"
8+image = "https://storage.googleapis.com/media.urbit.org/site/posts/essays/galen-at-assembly.JPG"
9++++
10+
11+![Galen at Assembly](https://storage.googleapis.com/media.urbit.org/site/posts/essays/galen-at-assembly.JPG)
12+
13+Before Assembly I committed to write a ‘recap’ post for everyone who couldn’t make it. Originally I figured this post would be an opportunity to walk through the list of things that we shipped and showed off in Austin. But it turns out that the most important thing about Assembly was simply the way it felt to be there.
14+
15+I’m not sure it’s possible to really do the feeling in the room justice, but I’m going to try. Then I’ll get into the announcements and happenings for those of you who couldn’t make it.
16+
17+But first, a quick note:
18+
19+We ran Assembly under the [Chatham House rule](https://en.wikipedia.org/wiki/Chatham_House_Rule). Basically, you can talk about what happens at Assembly—but you can’t name anyone.
20+
21+I’ve run many of our Urbit events this way because I think it puts people at ease. Everyone in the room can just relax, connect with one another, and hang out without worrying about being named on the internet.
22+
23+I’ll try to abide by the Chatham rule in this post which is why no one is named specifically.
24+
25+![secret society shirt](https://storage.googleapis.com/media.urbit.org/site/posts/essays/secret-society-shirt.JPG)
26+
27+New world energy -
28+
29+In the months leading up to Assembly we were totally focussed on using the event as a release date for a bunch of different lines of work. Coming out of that sprint, we didn’t really know what to expect. We wanted to make sure Urbit was ready for people to build on and that everything we were going to ship worked well. What we didn’t realize was just how emphatically people are <em>ready to build</em>.
30+
31+When I got up on stage on Friday night to welcome everyone I was really impressed by the room itself. It was packed with people who looked excited and motivated. The room just looked amazing. There were so many different kinds of people staring back at me. Some who I recognized from the earliest days of the project, and lots I had never seen before. I’ve been at my share of Urbit events, but this was something totally different.
32+
33+We didn’t have much scheduled during Assembly. Most of the time was unstructured to allow for freeform discussion, sunbathing on the lawn, and gathering at picnic tables. The panels that we did schedule will go down in history. Panelists discussed questions about creators, escaping reward systems, and the role of DAOs from governance to governments. There was hard money with a computer on it, Moloch shoes, community members grabbing the mic, and a talk written two hours before it was delivered about the relationship between centralization and decentralization when it comes to UX that blew our minds.
34+
35+I spent the weekend of Assembly in almost constant conversation with people building Urbit hardware, experimenting with different kinds of Urbit software, and thinking about incredible things like a Nock chip. I talked to the lead architect of a CPU from the 90s, a former senior US government official, an editor of a well-known literary magazine, the inventor of a new display technology, musicians whose work I already admired, a fragrance designer, writers, and, of course, lots of engineers and designers from many different backgrounds. Data scientists, systems hackers, language nerds, someone running a successful currency. I watched these people get projects off the ground, start raising money, plan the future of Urbit hosting companies, and plan new features for Landscape. I saw a last-minute warehouse party come together that kept people talking well into the early hours of the morning.
36+
37+Where did these people come from? All over the place. They have this incredible <em>new world energy</em>. They understand immediately, intuitively that Urbit has the potential to be a foundation for the society they want to live in. I’ve never seen anything like it.
38+
39+This energy seems to have come from the very practical work we do day-to-day: building Urbit, refining it, making it easier to use. The crowd at Assembly was somehow brought together by Urbit itself. It’s insanely exciting. It makes working on Urbit feel even more like a form of definite optimism. The system builds the community and the community builds the system.
40+
41+![Use only beautiful computers](https://storage.googleapis.com/media.urbit.org/site/posts/essays/use-only-computers.JPG)
42+
43+Urbit is ready to be built upon -
44+
45+Sometime in early 2021 we realized that there were many lines of work converging on a single theme: ‘Urbit is ready to be built upon’. This is the spirit we wanted to bring to Assembly, and it was very much in the room in Austin. Some of that feeling is still lingering on the network. I think it comes from some very concrete improvements that have been made to the system.
46+
47+We’ve always wanted Urbit to be maintained by a self-sustaining ecosystem and, early this year, we could see what needed to be done to really let others begin doing so. There were four parallel projects that came together to hit this milestone: Software distribution, star.market, developer and operator guides, and the Foundation roadmap. We talked about all of these things in the Assembly keynote (which you can watch [here](https://www.youtube.com/watch?v=ywj36TUtbS4)), but let’s touch on them one by one.
48+
49+Software distribution
50+
51+The most important thing that we shipped just before Assembly is the ability to actually package and distribute software over Urbit itself. It’s now possible for someone to build an app, package it up, and share it with a friend directly over the network.
52+
53+For their friend, the experience is incredibly nice. You can simply send someone a link and they can install the app and run it themselves, on their own urbit, right away. The whole thing is peer-to-peer, of course. There’s no app store, no vetting process. It’s networked software like it’s supposed to be: people computing together freely.
54+
55+We’ve been saying for years that we want people to build on top of Urbit and we always meant it. Now it’s possible in a way it never has been before. To check it out, watch [this segment](https://www.youtube.com/watch?v=MA8sqFi8Bd8) from Assembly.
56+
57+Software distribution can get better in _a lot_ of ways, and we’re continuing to work on it. But it’s live, and people are experimenting with it already. There’s Chess, there’s Pokur, there are video calls (although they’re still a little buggy). Everyone seems to love ‘pals’ and ‘zone’—but you’ll have to get on the network to check those out.
58+
59+star.market
60+
61+We’ve always used the address space to fund our work as one of the primary Urbit developers. As Urbit has become more useful, and address space has become more expensive, it’s more and more difficult for others to do this. The community saw the need for developers to easily use their granted address space to fund their work and a higher resolution for the Foundation to fund contributions to Urbit.
62+
63+This is what [star.market](https://star.market/) and the WSTR project are for. WSTR is an ERC-20 token that is backed 1:1 by ERC-721 Urbit stars. Unlike a star, a WSTR token can be fractionally divided, allowing for a broader distribution of ownership of Urbit. WSTR was built by the community over the past couple of months with no involvement from Tlon. Tlon did, eventually, help to put together star.market—the interface for interacting with the WSTR contracts safely and securely.
64+
65+I’ve come to think that WSTR can be a powerful tool for funding new Urbit projects. I’m excited to see what both our early community of developers and operators can do with it, as well as the nascent Urbit Foundation.
66+
67+Guides
68+
69+As we make it easier for developers to build software, operators to participate in the economy, and communities to make Urbit their home, we need to improve our documentation. We always like to do things bottom-up: the product work comes first. Well, the product is now live.
70+To this end we recently launched:
71+
72+[operators.urbit.org](https://operators.urbit.org/) collects all of the information about participating in the Urbit economy, running infrastructure nodes, and participating in governance in one place.
73+
74+[developers.urbit.org](https://developers.urbit.org/) has an overhauled program for learning about Urbit as a system and beginning to develop on top of it.
75+
76+[network.urbit.org](https://network.urbit.org/) allows anyone to explore the network. View galaxy transfers or how many planets a star has spawned.
77+
78+We’ve got a lot more planned in this area of work in the coming months, and these three sites are a great start.
79+
80+Urbit Foundation
81+
82+Over these past few years we’ve operated the Urbit Foundation as a ‘protocol’ inside of Tlon. Our goal has been to develop that protocol to the point that it’s refined, working, and can run on its own outside of Tlon.
83+
84+Josh has done an exceptional job running the foundation protocol at Tlon over the last year or so. He and I have been working closely together on everything that Tlon builds, while also coordinating our community of contributors. I’m very excited that the Foundation, with Josh as its Director, is now separating from Tlon as a fully independent entity focussed on supporting the ecosystem.
85+
86+Assembly was the perfect moment to begin formally separating out the Foundation and, as of a week ago, it is an independent entity. We’ve thought long and hard about how to make the Foundation an enduring, stable organization. Josh will be the first Executive Director but, ultimately, the Senate of Galaxies will elect the Board. This will keep the Foundation accountable to the network as a whole and I’m optimistic it can work well.
87+
88+If you’re on the network, you can read more about the Foundation in ~wolref-podlex/foundation.
89+
90+Assembly 2022 -
91+
92+I had more than a few enthusiastic people come up to me at Assembly and ask what we were planning for Assembly 2022. I have absolutely no idea, of course. We poured all our energy into making Assembly 2021 a success.
93+
94+Given what I saw in Austin, I’m pretty confident that next year we’ll be in completely new territory. The goal of this project has always been to build a completely new digital world. And now, it seems to be building itself.
content/blog/2021-11-18-the-promise-and-paradox-of-decentralization.mdnew file+55
@@ -0,0 +1,55 @@
1++++
2+title = "The Promise and Paradox of Decentralization"
3+date = "2021-11-17"
4+description = "Is centralization just a natural tendency of all networks? Are we destined to have a 'decentralization sandwich?'"
5+[extra]
6+author = ""
7+ship = "~lableg-tadrex"
8+image = "https://storage.googleapis.com/media.urbit.org/site/posts/essays/ux-centralization.JPG"
9++++
10+
11+![Presentation](https://storage.googleapis.com/media.urbit.org/site/posts/essays/ux-centralization.JPG)
12+
13+Every so often, a platform will do something outrageous—changing its terms of use, kicking off API partners, restricting [the content category it was built on](https://www.theverge.com/2018/12/3/18123752/tumblr-adult-content-porn-ban-date-explicit-changes-why-safe-mode), banning Donald Trump, failing to ban Donald Trump, etc.—and we'll all realize we're utterly dependent on centralized entities that can make arbitrary and unaccountable decisions. Sure, you can build your own minimal Facebook or Twitter clone, if you really want, but can you build your own Cloudflare? How about your own payment network? If your company does something legal in your country but banned in America, and the US decides to sanction you, which leads to local banks cutting you off because they can't survive without access to the dollar, are you going to build your own reserve currency? Your own Taiwan Semiconductor Manufacturing Co. or ASML?
14+
15+There are, to varying extents, efforts to do all of the above. But what's worth considering is that <em>all of these bans happen through centralized actors running on decentralized systems</em>. The Internet was supposed to be a totally open set of protocols that anyone could interact with, and for a long time it was, and yet getting kicked off Facebook and Twitter means being exiled from public discourse. Banks are regulated, but every country can set up their own banking regulations, and different countries see the social role of banks very differently; for some countries they're a tool of economic planning, for others a way to help connect local companies to global markets, for others a source of money that can be channeled to politically favored groups. The chip industry was historically very open to new entrants; the transistor was developed at Bell Labs, and for political reasons AT&T licensed it to all comers at a low price.
16+
17+And yet all of these originally decentralized systems end up facing some degree of centralization.
18+
19+The promise of a decentralized system is that anyone can build anything they want, because no one owns it. There are three important features of this; two downsides and a caveat:
20+
21+- The first downside to "Anyone can build anything" is that "anyone" means <em>anyone</em>, and the people to whom decentralized systems are the most attractive are the ones who are banned from other systems, often for good reasons. Free speech absolutists want to be defending Aleksandr Solzhenitsyn or Eugene V. Debs or even Lenny Bruce, but if you want to get a sense for the typical piece of content enabled by a totally uncensored communications system, check your spam folder.
22+
23+- The second downside is that a lack of ownership means that no one is responsible when things go wrong. Bitcoin doesn't have a way to censor your decision to move money from one address to another or even a protocol-level sense of whether you're buying Alpaca socks or a rocket launcher. (nb: You are almost certainly not buying a rocket launcher with Bitcoin; you are at best getting scammed, and at worst [getting in trouble](https://www.justice.gov/usao-cdca/pr/los-angeles-county-man-pleads-guilty-federal-charge-attempting-obtain-biological-toxin)). But this also means that the protocol can't tell when you meant to send your life savings to your cold wallet and sent it to the wrong address instead.
24+
25+- The caveat is that, to quote a [<em>Diff</em> piece from last year](https://www.thediff.co/p/amazon-a-new-kind-of-antitrust-risk#:~:text=does%20it%2C%20too.-,Technology-Governance%20Fit,-Pondering%20Durian%20has) ($), "[A]ny decentralized order requires a centralized substrate, and the more decentralized the approach is the more important it is that you can count on the underlying system." This applies to cryptocurrencies (you can trust the protocols) and to the Internet (ditto). It also applies, in an interesting way, to the increasingly decentralized world of free trade and free-flowing capital: money can only flow and deals can only be made if everyone has a consistent sense of property rights and contracts, and the definition of those concepts will typically be determined by whichever participant in a transaction has the more sophisticated financial and legal system. Globalization ends up being a bit like Henry Ford's pitch: you can use any economic paradigm you want, as long as it's the American one.1
26+
27+An open, decentralized system is <em>sparse</em>: there's room for anything, which means that most of the possibility space consists of nothing at all. This creates a natural demand for onramps—Coinbase for figuring out Bitcoin, portals for figuring out the Internet, TSM for turning chip designs into functioning products, and the like. These create a complicated dynamic: these onramps are built on an open system, but part of their function is to close off some of it. And the better they do that, the more value they can capture. Meanwhile, because they have a monopoly on what they've fenced off, their economics support providing a better user experience. Make a really helpful update to the Bitcoin wiki, and you can feel good about yourself and perhaps contribute to the price of Bitcoin in a highly indirect way; design and launch an improved onboarding process at Coinbase and your contribution is quantifiable, and affects your next cycle's equity grants.
28+
29+This privatization proceeds in three different ways:
30+
31+- Some companies start building on an open protocol and then slowly make it their own. Chrome's decision to make the search bar synonymous with the address bar was a slight improvement in the interface, but also a very strong statement that Google had replaced manually typing in URLs as the default way to navigate. (The strongest evidence for this is the frequency of navigational searches; [the most commonly-searched term on Google](https://www.mondovo.com/keywords/) is "Facebook" and [the most frequently searched term on Bing is "Google"](https://www.bloomberg.com/news/articles/2021-09-28/google-tells-judges-it-s-so-popular-it-s-bing-s-top-search-term).) Typing in URLs is a sometimes-decent way to find what you're looking for, though [the half-life of links is about two years](https://blog.zomdir.com/2017/10/the-half-life-of-link-is-two-year.html). But guessing at URLs can be [perilous](https://en.wikipedia.org/wiki/Whitehouse.com). No one is responsible for fixing this, but Google is the closest approximation, because what they are responsible for is solving the "look for something on the Internet and get the wrong result" problem, a different but related one from the broader task of allowing arbitrary site owners to host arbitrary content. Privatizing is effective, and solves problems for users rather than protocol designers. But it does go against the spirit of the original network.
32+
33+- Twitter is another example, except that they basically created their own open mostly-open protocol and then slowly took control of it. Tweets were originally a simple format, with 140 characters of text and a bit more metadata (this made it compatible with SMS, which had a 160-character limit). For a while, Twitter looked like it would operate a novel protocol and let third parties decide what to put on it and what to read off it. And then the company started to realize that an open system was also one where it was trivial to filter out ads and recommendations. So the outside partners gradually got cut off.
34+
35+- Facebook—the product, not the company—is a third example. It essentially implemented a missing element to the protocol: <em>identity matters</em>. When the original protocols were being hammered out, identity was a problem taken care of by the fact that getting online required steep hurdles; if everyone involved is affiliated with a university that trusts them to use a PDP-10 responsibly, spam or abuse were not big concerns. (Not that early usage was [strictly professional](https://www.theguardian.com/science/2013/apr/19/online-high-net-drugs-deal).) With billions of people online, accessing relevant information can mean traversing a graph of people rather than links, so the identities of those people becomes important. To the user, if not to the network itself, a name and relationship is a far more important unique identifier than an IP address.
36+
37+This pattern raises a question: is centralization just a natural tendency of all networks? Are we destined to have a "decentralization sandwich," where there's a hard-to-change set of protocols, something open built on top of <em>that</em>, and a series of closed systems built on top of that, which are the only ones the average person interacts with?
38+
39+One of the interesting alternatives to this is [Urbit](https://urbit.org), which is trying to build a network in which identity exists from the start, and is neither free nor monopolized. One of Urbit's principles is that users own their data, and while they can use third-party services, they're sharing their data with services, not using a login to access information that lives on someone else's servers.
40+
41+This is a nice theoretical solution to the "build your own" problem above: if someone tries to start Twitter-but-without-banning-X, they begin with "Twitter-but-it's-100%-X," which seems bad until they reach the next stage where trolls arrive and they start to learn that Online Censorship is mostly about spam and gore and only occasionally about politics. But if they're moving their data around, and their friends graph with it, then spinning up a separate instance of the same service, pulling in the same content from their friends, and whitelisting someone who's blacklisted elsewhere is a lot more feasible.
42+
43+At least at first. One of the problems with owning your own data is that it ignores the question of what format that data is in. Data formats are sometimes considered carefully, but they can also be hammered out fast to get a minimum viable product out the door. Then they evolve over time, accumulating cruft and complexity, until they might as well be encrypted.
44+
45+And indeed, what's to stop someone from having a proprietary format that's literally encrypted? Or one that gets changed to an encrypted version later on? This is not a trivial point; if you're ever in a position where you absolutely have to share some information that you want to keep secret, the smartest thing to do is share a huge amount of confusing and poorly-explained information, or use an [annoying but technically accurate format](https://www.vice.com/en/article/gv5vxb/crypto-keys-printout-of-edward-snowdens-email-service-lavabit-ladar-levison). Strict and unalterable rules are no match for determined adversaries, whether they're trying to play a prank, make a point, or maximize shareholder value.
46+
47+But the data format questions are not rhetorical: there is actually an answer of sorts, though it's a frustrating one. Software systems are not just lines of code, but the entire extended system of people who maintain, host, and build on platforms. And the norms of those communities can push back against market pressures. I've been spending an increasing amount of time around Urbit users and devs, and they really do view the current centralized model of the Internet as anathema. They are aware that the fun apps we use are all either designed to be addictive from the start or subject to relentless evolutionary pressure to get more addictive. There's a history of [norms evolving in response to new addictive behavior](https://gist.github.com/jm3/6724931). And Urbit's architecture is a lot closer to norms than to the clumsy mechanism of laws; instead of centralized services that own data, there's a set of 256 Urbit identities that can route messages between users. Instead of single points of failure, there are a few hundred fallback options; instead of the binary of on-Facebook-or-anathematized, there's a 2^8 bit gradient.
48+
49+One possibility for the successor to the current Internet is that it will end up being a system designed to support communities that achieve cohesion based on which forms of addictive or socially corrosive technology they reject. Sort of a digital version of the Amish, [not rejecting technology wholesale but carefully considering every new technology before adopting it](https://kk.org/thetechnium/amish-hackers-a/). If you assume that the pace of change in consumer-facing Internet stays high, and that it gets more compelling over time, then in the long run the only options are a) be careful what you use, or b) accept that you're outsourcing a growing share of your decisions to product managers and growth hackers who do not necessarily have your interests at heart.
50+
51+Norms are not a perfect solution to these problems (if they were, we'd only know about issues like novel addictive behaviors, monopolies, and the homogenization of entertainment from history books). And technology can't fully solve social problems. But it can certainly have an effect on them—"you can't solve a social problem with technology" is a good guideline, but technologies mitigate them all the time. What's a streetlight if not a technological solution to the social problem that there are places where it's dangerous to be out when it's dark? What's asymmetric-key cryptography if not a technological solution to the social problem that it's hard to keep secrets? There's still a fundamental tension with open systems, where they get mature enough to be useful at which point the median user's priority is getting things done rather than adhering to the network's original design principles. But a design that recognizes this from the beginning, and a community that wants to make it happen, can stave off decline for a long time. And that's the positive story of technology: we're all fighting against entropy, which is a hard fight to win, but there are long and fascinating stalemates ahead.
52+
53+(Disclosure: I'm long decentralization by way of Bitcoin and Urbit. If you're on Urbit and would like to discuss <em>The Diff</em>, go to ~lableg-tadrex/the-diff.)
54+
55+<sup>1.</sup> There is naturally some resistance to this, both because of conflicts with different countries' norms and with other countries' natural desire to determine their own destiny. So it's a leaky abstraction, but it gets less leaky over time as economies get more integrated and thus more of the world has to standardize. The most direct example of this is the fact that [the dollar's share of global invoices is 4.7x the US's share of global imports](https://www.economist.com/schools-brief/2020/08/27/global-trades-dependence-on-dollars-lessens-its-benefits) ($, <em>Economist</em>). In the same way that English is most likely to be the shared second language of any two randomly-selected people who don't speak it as a first language, the dollar is most likely to be the second most useful currency to anyone in a country that doesn't use dollars.
content/blog/value-of-address-space-pt1.md+1−5
@@ -9,11 +9,7 @@ ship = "~patnes-rigtyn + ~ravmel-ropdyl"
9image = "https://media.urbit.org/site/posts/essays/value-of-address-space-pt1.jpg"
9image = "https://media.urbit.org/site/posts/essays/value-of-address-space-pt1.jpg"
10+++
10+++
11
11
12−<br>
13−
14−<img class="ba" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt1.jpg">
12+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt1.jpg)
15−
16−<br>
17
13
18_This is the first in a series of three posts on Urbit address space. See also [part 2](https://urbit.org/blog/value-of-address-space-pt2/) and [part 3](https://urbit.org/blog/value-of-address-space-pt3/)._
14_This is the first in a series of three posts on Urbit address space. See also [part 2](https://urbit.org/blog/value-of-address-space-pt2/) and [part 3](https://urbit.org/blog/value-of-address-space-pt3/)._
19
15
content/blog/value-of-address-space-pt2.md+11−33
@@ -9,11 +9,7 @@ ship = "~patnes-rigtyn + ~ravmel-ropdyl"
9image = "https://media.urbit.org/site/posts/essays/value-of-address-space-pt2.jpg"
9image = "https://media.urbit.org/site/posts/essays/value-of-address-space-pt2.jpg"
10+++
10+++
11
11
12−<br>
13−
14−<img class="ba" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt2.jpg">
12+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt2.jpg)
15−
16−<br>
17
13
18_This is the second in a series of three posts on Urbit address space. See also [part 1](https://urbit.org/blog/value-of-address-space-pt1/) and [part 3](https://urbit.org/blog/value-of-address-space-pt3/)._
14_This is the second in a series of three posts on Urbit address space. See also [part 1](https://urbit.org/blog/value-of-address-space-pt1/) and [part 3](https://urbit.org/blog/value-of-address-space-pt3/)._
19
15
@@ -25,21 +21,17 @@ Value and price are distinct concepts that often get conflated. In our view, Urb
25
21
26256 galaxies, ~65,000 stars, ~4B planets.
22256 galaxies, ~65,000 stars, ~4B planets.
27
23
28−<br>
29−
30−<img class="ba w-100" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt2a.svg">
24+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt2a.svg)
31−
32−<br>
33
25
34A foundational design principle of the Urbit network is that the address space is limited. This rarity helps qualify Urbit as a [collectible](https://nakamotoinstitute.org/shelling-out/), and thus creates a non-zero acquisition cost for an address. This cost discourages abuses like spam and bot-net attacks. Traditionally, these attacks are made with quasi-unlimited access to IP addresses. The unit economics of acquiring planets for these nefarious purposes is a strong deterrent.
26A foundational design principle of the Urbit network is that the address space is limited. This rarity helps qualify Urbit as a [collectible](https://nakamotoinstitute.org/shelling-out/), and thus creates a non-zero acquisition cost for an address. This cost discourages abuses like spam and bot-net attacks. Traditionally, these attacks are made with quasi-unlimited access to IP addresses. The unit economics of acquiring planets for these nefarious purposes is a strong deterrent.
35
27
36−There are 256 galaxies on the network. Each galaxy is initialized with ownership of 256 stars. Galaxies act as root nodes for peer discovery and packet routing within the Urbit network, and they are each also entitled to vote on updates to the smart contracts which govern the network. To date, galaxies trade primarily on OTC (over the counter) desks, and rarely appear on the open market.
28+There are 256 galaxies on the network. Each galaxy is initialized with ownership of 255 stars. Galaxies act as root nodes for peer discovery and packet routing within the Urbit network, and they are each also entitled to vote on updates to the smart contracts which govern the network. To date, galaxies trade primarily on OTC (over the counter) desks, and rarely appear on the open market.
37
29
38−There are 65,536 total stars on the network. In turn, each star is initialized with ownership of 65,536 planets. Stars currently trade on platforms independent of Tlon, such as [urbit.live](https://urbit.live/) and [opensea.io](https://opensea.io/). The current price range can easily be ascertained on those sites, but as of the time of this writing, stars are selling at a price that greatly discounts their planet holdings.
30+There are 65,280 total stars on the network. In turn, each star is initialized with ownership of 65,535 planets. Stars currently trade on platforms independent of Tlon, such as [urbit.live](https://urbit.live/) and [opensea.io](https://opensea.io/). The current price range can easily be ascertained on those sites, but as of the time of this writing, stars are selling at a price that greatly discounts their planet holdings.
39
31
40One would expect that in an efficient market the relative pricing of stars on one hand, and planets on the other hand would eventually align (so to speak). This may come to pass as the Urbit community increases education about Urbit, and as additional planet sellers and hosting providers enter the space.
32One would expect that in an efficient market the relative pricing of stars on one hand, and planets on the other hand would eventually align (so to speak). This may come to pass as the Urbit community increases education about Urbit, and as additional planet sellers and hosting providers enter the space.
41
33
42−Finally, there are 4,294,967,296 (or 2<sup>32</sup>) planets on the network. Planets currently trade largely in a range of $10 to $15. We expect planet prices to fluctuate from provider to provider as described in the previous post, based on the quality of services various providers offer. That said, it's worth noting that the cost to configure addresses for distribution is fairly static and this may act as something of a lower bound.
34+Finally, there are 4,294,901,760 (or ~2<sup>32</sup>) planets on the network. Planets currently trade largely in a range of $10 to $15. We expect planet prices to fluctuate from provider to provider as described in the previous post, based on the quality of services various providers offer. That said, it's worth noting that the cost to configure addresses for distribution is fairly static and this may act as something of a lower bound.
43
35
44That said, we also anticipate that planet prices will be abstracted away from most purchasers, and will be included in bundled annual packages of hosting and data routing services. For this reason, infrastructure service providers (i.e. hosting providers) will likely be the best positioned parties to capture value from planet distribution.
36That said, we also anticipate that planet prices will be abstracted away from most purchasers, and will be included in bundled annual packages of hosting and data routing services. For this reason, infrastructure service providers (i.e. hosting providers) will likely be the best positioned parties to capture value from planet distribution.
45
37
@@ -65,31 +57,21 @@ Utility is only one component of a value calculation. To further develop the inq
65
57
66Urbit IDs are individually represented by non-fungible ERC-721 tokens, and can therefore be sold by any platform that supports this token standard. Currently there are three known Urbit-exclusive sales platforms and one generalized ERC-721 platform that list Urbit IDs. Prices for stars and planets are readily available. Volume is low, as no effort has been made to promote the fact of availability, yet the number of [total transactions](https://azimuth.network/stats/events.txt) has increased steadily since the network was launched to Ethereum in 2019, even absent public messaging.
58Urbit IDs are individually represented by non-fungible ERC-721 tokens, and can therefore be sold by any platform that supports this token standard. Currently there are three known Urbit-exclusive sales platforms and one generalized ERC-721 platform that list Urbit IDs. Prices for stars and planets are readily available. Volume is low, as no effort has been made to promote the fact of availability, yet the number of [total transactions](https://azimuth.network/stats/events.txt) has increased steadily since the network was launched to Ethereum in 2019, even absent public messaging.
67
59
68−<br>
69−<img class="" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt2-tps.svg">
60+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt2-tps.svg)
70−<br>
71
61
72−<br>
73−<img class="" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt2-tss.svg">
62+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt2-tss.svg)
74−<br>
75
63
76Buying non-fungible tokens like Urbit IDs is rather different than trading quasi-fungible tokens like Bitcoin (even setting aside the issue of volume). Each Urbit ID is unique, and so they tend to be purchased by end users for their specific characteristics, rather than generically. As an example, the planet `~parret-barret` sold for about $1,000 at a time when most planets were selling for $10-20, perhaps due to its rhyming name. Planets with circular sigils also often sell for significantly more than other planets — we’re not entirely sure why this is the case.
64Buying non-fungible tokens like Urbit IDs is rather different than trading quasi-fungible tokens like Bitcoin (even setting aside the issue of volume). Each Urbit ID is unique, and so they tend to be purchased by end users for their specific characteristics, rather than generically. As an example, the planet `~parret-barret` sold for about $1,000 at a time when most planets were selling for $10-20, perhaps due to its rhyming name. Planets with circular sigils also often sell for significantly more than other planets — we’re not entirely sure why this is the case.
77
65
78## Planet Sales
66## Planet Sales
79
67
80−<br>
81−<img class="" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt2e-price-eth.svg">
68+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt2e-price-eth.svg)
82−<br>
83
69
84−<br>
85−<img class="" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt2e-price-btc.svg">
70+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt2e-price-btc.svg)
86−<br>
87
71
88## Star Sales
72## Star Sales
89
73
90−<br>
91−<img class="w-100" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt2e-price-btc-usd.svg">
74+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt2e-price-btc-usd.svg)
92−<br>
93
75
94This ID-specific trading pattern is generally appropriate in our view: Urbit ID isn’t designed to be rapidly traded at high volume. Urbit is more like a house than a fungible good like a currency.
76This ID-specific trading pattern is generally appropriate in our view: Urbit ID isn’t designed to be rapidly traded at high volume. Urbit is more like a house than a fungible good like a currency.
95
77
@@ -97,11 +79,7 @@ For the time being buying and selling of Urbit IDs happens through auctions on s
97
79
98Strictly speaking, liquidity is a measure of the degree to which a given asset will change in value due to a given transaction. In that sense, Urbit address space is likely fairly illiquid. But liquidity can’t be properly understood without volume. As noted above, the volume of transactions on the network has been steadily increasing since inception, and yet the price has remained fairly constant. This seems to indicate a healthy ratio.
80Strictly speaking, liquidity is a measure of the degree to which a given asset will change in value due to a given transaction. In that sense, Urbit address space is likely fairly illiquid. But liquidity can’t be properly understood without volume. As noted above, the volume of transactions on the network has been steadily increasing since inception, and yet the price has remained fairly constant. This seems to indicate a healthy ratio.
99
81
100−<br>
101−
102−<img class="ba w-100" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt2b.svg">
82+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt2b.svg)
103−
104−<br>
105
83
106A further impact on liquidity and volume is that of available supply. At present, the majority of Urbit address space is locked by smart contracts. These lockups began to release at varying linear rates in January 2019. All address space will be completely unlocked and tradeable by January 2025. Eventually as both understanding and demand increase, we anticipate that planets will find an equilibrium price, and stars will be repriced accordingly.
84A further impact on liquidity and volume is that of available supply. At present, the majority of Urbit address space is locked by smart contracts. These lockups began to release at varying linear rates in January 2019. All address space will be completely unlocked and tradeable by January 2025. Eventually as both understanding and demand increase, we anticipate that planets will find an equilibrium price, and stars will be repriced accordingly.
107
85
content/blog/value-of-address-space-pt3.md+5−15
@@ -11,9 +11,7 @@ image = "https://media.urbit.org/site/posts/essays/value-of-address-space-pt3.jp
11
11
12<br>
12<br>
13
13
14−<img class="ba" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt3.jpg">
14+![](https://media.urbit.org/site/posts/essays/value-of-address-space-pt3.jpg)
15−
16−<br>
17
15
18_This is the third in a series of three posts on Urbit address space. See also [part 1](https://urbit.org/blog/value-of-address-space-pt1/) and [part 2](https://urbit.org/blog/value-of-address-space-pt2/)._
16_This is the third in a series of three posts on Urbit address space. See also [part 1](https://urbit.org/blog/value-of-address-space-pt1/) and [part 2](https://urbit.org/blog/value-of-address-space-pt2/)._
19
17
@@ -53,13 +51,9 @@ A locked star is held in a contract and can neither be booted nor issue planets.
53
51
54In practice, the only Urbit IDs that are ‘locked’ are stars. A galaxy that is said to be locked is simply a galaxy whose stars are currently held by a lockup contract. A locked galaxy can be transferred (i.e. sold or simply moved to a new key) and booted (importantly, any galaxy—booted or not—can vote), but it can’t issue stars until the lockup contract expires.
52In practice, the only Urbit IDs that are ‘locked’ are stars. A galaxy that is said to be locked is simply a galaxy whose stars are currently held by a lockup contract. A locked galaxy can be transferred (i.e. sold or simply moved to a new key) and booted (importantly, any galaxy—booted or not—can vote), but it can’t issue stars until the lockup contract expires.
55
53
56−<br>
57−<img class="ba" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt3-graph1.png">
54+![Star Unlocking Schedule](https://media.urbit.org/site/posts/essays/value-of-address-space-pt3-graph1.png)
58−<br>
59
55
60−<br>
61−<img class="ba" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt3-graph2.png">
56+![Total Urbit IDs Spawned and Activated](https://media.urbit.org/site/posts/essays/value-of-address-space-pt3-graph2.png)
62−<br>
63
57
64These lockups all began to release at varying linear rates in January 2019 (specifically on Tue Jan 08 23:34:41 2019 UTC).
58These lockups all began to release at varying linear rates in January 2019 (specifically on Tue Jan 08 23:34:41 2019 UTC).
65
59
@@ -78,9 +72,7 @@ Spawning Limits –
78
72
79Unlocked stars are further gated by the number of planets they’re able to spawn. Every unlocked star was immediately able to spawn 1024 planets from the moment Urbit went live on the blockchain in January 2019—we wanted everyone to be able to invite some friends to their communities right away. From that date forward, the spawnable amount doubles every year (365 days), maxing out at 65,535 spawnable planets after 6 years.
73Unlocked stars are further gated by the number of planets they’re able to spawn. Every unlocked star was immediately able to spawn 1024 planets from the moment Urbit went live on the blockchain in January 2019—we wanted everyone to be able to invite some friends to their communities right away. From that date forward, the spawnable amount doubles every year (365 days), maxing out at 65,535 spawnable planets after 6 years.
80
74
81−<br>
82−<img class="ba" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt3-graph3.png">
75+![Total Spawnable Planets and Spawnable Planets per Star](https://media.urbit.org/site/posts/essays/value-of-address-space-pt3-graph3.png)
83−<br>
84
76
85When we layer the spawning limits over the various lockup contracts, we find that all Urbit address space is both unlocked and spawnable by January 9, 2025.
77When we layer the spawning limits over the various lockup contracts, we find that all Urbit address space is both unlocked and spawnable by January 9, 2025.
86
78
@@ -92,9 +84,7 @@ We consider the opacity of our understanding about transactions on the network t
92
84
93The chart below is an estimate (as of January 2020) based on our general understanding of how galaxies are distributed. Much of this is anecdotal, and it’s largely based on the very few transactions we’ve observed within the galaxy table since Urbit went on chain in 2019. This chart should therefore be understood as incomplete, and an estimate only.
85The chart below is an estimate (as of January 2020) based on our general understanding of how galaxies are distributed. Much of this is anecdotal, and it’s largely based on the very few transactions we’ve observed within the galaxy table since Urbit went on chain in 2019. This chart should therefore be understood as incomplete, and an estimate only.
94
86
95−<br>
96−<img class="ba" src="https://media.urbit.org/site/posts/essays/value-of-address-space-pt3-graph4.png">
87+![Estimated Galaxy Distribution](https://media.urbit.org/site/posts/essays/value-of-address-space-pt3-graph4.png)
97−<br>
98
88
99Address space distribution is best understood in terms of galaxies and stars independently, as they’re distinct assets. The chart above only illustrates galaxy distribution, but describes Tlon’s “naked” galaxy holdings, which are galaxies empty of their stars. These galaxies are empty because the stars they once contained have been distributed, primarily to Tlon contractors, employees, and to certain private buyers.
89Address space distribution is best understood in terms of galaxies and stars independently, as they’re distinct assets. The chart above only illustrates galaxy distribution, but describes Tlon’s “naked” galaxy holdings, which are galaxies empty of their stars. These galaxies are empty because the stars they once contained have been distributed, primarily to Tlon contractors, employees, and to certain private buyers.
100
90
content/docs/_index.md+1−1
@@ -6,7 +6,7 @@ template = "sections/docs.html"
6
6
7Welcome to the developer documentation for the Urbit project. This documentation
7Welcome to the developer documentation for the Urbit project. This documentation
8is maintained by [Tlon](https://tlon.io) and the Urbit community in a public
8is maintained by [Tlon](https://tlon.io) and the Urbit community in a public
9−[Github repository](https://github.com/urbit/docs). Issues and contributions are
9+[Github repository](https://github.com/urbit/urbit.org/tree/master/content/docs). Issues and contributions are
10welcome.
10welcome.
11
11
12This documentation provides a series of explainers, guides, tutorials and
12This documentation provides a series of explainers, guides, tutorials and
content/docs/arvo/_index.md+2−4
@@ -36,11 +36,11 @@ Eyre is our HTTP server. Unix sends HTTP messages to `%eyre`, and `%eyre` produc
36
36
37Ford is our build system. It handles resources and publishing.
37Ford is our build system. It handles resources and publishing.
38
38
39−## [Gall](/docs/arvo/gall/overview)
39+## [Gall](/docs/arvo/gall/gall)
40
40
41Gall is the vane for controlling userspace apps.
41Gall is the vane for controlling userspace apps.
42
42
43−## [Iris](/docs/arvo/iris/iris-api)
43+## [Iris](/docs/arvo/iris/iris)
44
44
45Iris is our HTTP client.
45Iris is our HTTP client.
46
46
@@ -51,5 +51,3 @@ Explanations of design decisions that are pervasive throughout Arvo.
51## [Tutorials](/docs/arvo/tutorials/)
51## [Tutorials](/docs/arvo/tutorials/)
52
52
53Walkthroughs that teach you more about how Arvo works.
53Walkthroughs that teach you more about how Arvo works.
54−
55−
content/docs/arvo/ames/_index.md+20
@@ -5,3 +5,23 @@ sort_by = "weight"
5template = "sections/docs/chapters.html"
5template = "sections/docs/chapters.html"
6insert_anchor_links = "right"
6insert_anchor_links = "right"
7+++
7+++
8+
9+## [Overview](/docs/arvo/ames/ames)
10+
11+An overview of Ames and its capabilities.
12+
13+## [Cryptography](/docs/arvo/ames/cryptography)
14+
15+A technical overview of how Ames implements cryptography.
16+
17+## [API Reference](/docs/arvo/ames/tasks)
18+
19+The `task`s Ames takes and the `gift`s it returns.
20+
21+## [Scry Reference](/docs/arvo/ames/scry)
22+
23+The scry endpoints of Ames.
24+
25+## [Data Types](/docs/arvo/ames/data-types)
26+
27+Reference documentation of the various data types used by Ames.
content/docs/arvo/ames/ames-api.mddeleted−292
@@ -1,292 +0,0 @@
1−+++
2−title = "API Reference"
3−weight = 10
4−template = "doc.html"
5−+++
6−
7−In this document we describe the public interface for Ames. Namely, we describe
8−each `task` that Ames can be `%pass`ed, and which `gift`(s) Ames can `%give` in return.
9−
10−Some `task`s appear to have more than one arm associated to them, e.g. there are
11−four `+on-hear` arms. We denote this where it occurs, but always refer to the
12−`on-hear:event-core` arm.
13−
14−Ames `task`s can be naturally divided into two categories: messaging tasks and
15−system/lifecycle tasks.
16−
17−## Messaging Tasks
18−
19−### `%hear`
20−
21−`%hear` handles raw packet receipt. This `task` only ever originates from Unix.
22−It does the initial processing of a packet, namely by passing the raw packet
23−information to `+decode-packet` which deserializes the packet and giving that data and the origin of the
24−packet to `+on-hear-packet`, which begins the transformation of the packet into
25−a new event in the form of a `+event-core`.
26−
27−There are multiple `+on-hear` arms in `ames.hoon`. Here we refer to
28−`on-hear:event-core`, as that is the one called by a `%hear` `task`. The other ones are used
29−primarily for ack and nack processing, or receiving message fragments.
30−
31−#### Accepts
32−
33−```hoon
34−[=lane =blob]
35−```
36−
37−`%hear` takes in a `blob`, which is essentially a large atom (around 1kB or less)
38−that is the raw data of the message, and a `lane`, which is the origin of the
39−message (typically an IP address).
40−
41−#### Returns
42−
43−`%hear` can trigger a number of possible returns. It can trigger the release of
44−zero or more additional packets via `%send` `gift`s. It may also trigger a `%boon`
45−or `%plea` `gift` (collectively referred to as a `%memo` within Ames) to a local vane in the case of a completed message.
46−
47−
48−### `%heed`
49−
50−A vane can pass Ames a `%heed` `task` to request Ames track a peer's
51−responsiveness. If our `%boon`s to it start backing up locally,
52−Ames will `give` a `%clog` back to the requesting vane containing the
53−unresponsive peer's Urbit address.
54−
55−Stop tracking a peer by sending Ames a
56−`%jilt` `task`.
57−
58−
59−#### Accepts
60−
61−```hoon
62−=ship
63−```
64−
65−The ship to be tracked.
66−
67−#### Returns
68−
69−If the `ship` is indeed being unresponsive, as measured by backed up `%boon`s,
70−Ames will `give` a `%clog` `gift` to the requesting vane containing the
71−unresponsive peer's urbit address.
72−
73−
74−### `%hole`
75−
76−`%hole` handles packet crash notification. `%hole` works much like `%hear`, in
77−that it passes an incoming raw packet to `+decode-packet` to be deserialized,
78−and then passes that data along with the source of the packet to
79−`+on-hear-packet` along with a `?` set to `%.n` denoting that there is something wrong with
80−the packet.
81−
82−#### Accepts
83−
84−```hoon
85−[=lane =blob]
86−```
87−`%hole` takes in a `blob`, which is essentially a large atom (around 1kB or less)
88−that is the raw data of the message, and a `lane`, which is the origin of the
89−message (typically an IP address).
90−
91−#### Returns
92−
93−Like `%hear`, `%hole` can trigger additional packets in the form of `%send`
94−`gift`s, and may also yield a `%boon` or `%plea` `gift` to a local vane.
95−
96−
97−### `%jilt`
98−
99−`%jilt` stops tracking a potentially unresponsive peer that was previously being
100−tracked as a result of the `%heed` `task`.
101−
102−There are two `+on-jilt` arms, this `task` utilizes `on-hear:event-core`.
103−
104−#### Accepts
105−
106−```hoon
107−=ship
108−```
109−
110−The `ship` we no longer wish to track.
111−
112−#### Returns
113−
114−This `task` returns no `gift`s.
115−
116−
117−### `%plea`
118−
119−`%plea` is the `task` used to instruct Ames to send a message. It extends the
120−`%pass`/`%give` semantics across the network. As such, it is the most
121−fundamental `task` in Ames and the primary reason for its existence.
122−
123−Ames also `pass`es a `%plea` `note` to another vane when it receives a message on a
124−"forward flow" from a peer, originally passed from one of the peer's vanes to the
125−peer's Ames.
126−
127−Ultimately `%plea` causes `%send` `gift`(s) to be sent to Unix, which tells
128−Unix to send packets. In terms of `%pass`/`%give` semantics, this is in
129−response to the `%born` `task`, which came along the Unix `duct`, rather than a
130−response to the `%plea`.
131−
132−#### Accepts
133−
134−```hoon
135−[=ship =plea]
136−```
137−
138−A `%plea` `task` takes in the `ship` the `plea` is addressed to, and a `$plea`,
139−which is
140−
141−```hoon
142− +$ plea [vane=@tas =path payload=*]
143−```
144−Here, `vane` is the destination vane on the remote ship, `path` is the internal
145−route on the receiving ship, and `payload` is the semantic message content.
146−
147−#### Returns
148−
149−This `task` returns no `gift`s.
150−
151−## System and Lifecycle Tasks
152−
153−### `%born`
154−
155−Each time you start your Urbit, the Arvo kernel calls the `%born` task for Ames.
156−
157−#### Accepts
158−
159−`%born` takes no arguments.
160−
161−#### Returns
162−
163−In response to a `%born` `task`, Ames `%give`s Jael a `%turf` `gift`.
164−
165−The `duct` along which `%born` comes is Ames' only duct to Unix, so `%send`
166−`gift`s (which are instructions for Unix to send a packet) are also returned in
167−response to `%born`.
168−
169−
170−### `%crud`
171−
172−`%crud` is called whenever an error involving Ames occurs. It produces a crash
173−report in response.
174−
175−#### Accepts
176−
177−```hoon
178−=error
179−```
180−
181−A `$error` is a `[tag=@tas =tang]`.
182−
183−#### Returns
184−
185−Ames does not `give` a `gift` in response to a `%crud` `task`, but it does
186−`%pass` Dill a `%flog` `task` instructing it to print `error`.
187−
188−
189−## `%init`
190−
191−`%init` is called a single time during the very first boot process, immediately
192−after the [larval stage](/docs/arvo/overview#larval-stage-core)
193−is completed. This initializes the vane. Jael is initialized first, followed by
194−other vanes such as Ames.
195−
196−In response to receiving the `%init` `task`, Ames subscribes to the information
197−contained by Jael.
198−
199−#### Accepts
200−
201−```hoon
202−our=ship
203−```
204−
205−`%init` takes in the name of our ship, which is a `@p`.
206−
207−#### Returns
208−
209−```hoon
210− =~ (emit duct %pass /turf %j %turf ~)
211− (emit duct %pass /private-keys %j %private-keys ~)
212−```
213−
214−`%init` sends two moves that subscribe to `%turf` and `%private-keys` in Jael.
215−
216−
217−### `%sift`
218−
219−This `task` filters debug output by ship.
220−
221−#### Accepts
222−
223−```hoon
224−ships=(list ship)
225−```
226−
227−The list of ships for which debug output is desired.
228−
229−#### Returns
230−
231−This `task` returns no `gift`s.
232−
233−
234−### `%spew`
235−
236−Sets verbosity toggles on debug output. These toggles are as follows.
237−
238−* `%snd` - sending packets
239−* `%rcv` - receiving packets
240−* `%odd` - unusual events
241−* `%msg` - message-level events
242−* `%ges` - congestion control
243−* `%for` - packet forwarding
244−* `%rot` - routing attempts
245−
246−Each toggle is a flag set to `%.n` by default.
247−
248−#### Accepts
249−
250−```hoon
251−verbs=(list verb)
252−```
253−
254−`%spew` takes in a `list` of `verb`, which are verbosity flags for Ames.
255−
256−```hoon
257−+$ verb ?(%snd %rcv %odd %msg %ges %for %rot)
258−```
259−
260−`%spew` flips each toggle given in `verbs`.
261−
262−#### Returns
263−
264−This `task` returns no `gift`s.
265−
266−
267−### `%vega`
268−
269−`%vega` is called whenever the kernel is updated. Ames currently does not do
270−anything in response to this.
271−
272−#### Accepts
273−
274−`%vega` takes no arguments.
275−
276−#### Returns
277−
278−This `task` returns no `gift`s.
279−
280−
281−### `%wegh`
282−
283−This `task` is a request to Ames to produce a memory usage report.
284−
285−#### Accepts
286−
287−This `task` has no arguments.
288−
289−#### Returns
290−
291−In response to this `task,` Ames `%give`s a `%mass` `gift` containing Ames'
292−current memory usage.
content/docs/arvo/ames/ames.md+75−75
@@ -4,6 +4,7 @@ weight = 1
4template = "doc.html"
4template = "doc.html"
5aliases = ["/docs/learn/arvo/ames/"]
5aliases = ["/docs/learn/arvo/ames/"]
6+++
6+++
7+
7Our networking protocol.
8Our networking protocol.
8
9
9Ames is the name of both our network and the vane that communicates
10Ames is the name of both our network and the vane that communicates
@@ -11,7 +12,7 @@ over it. When Unix receives a packet over the correct UDP port, it pipes
11it straight into Ames for handling. Also, all packets sent over the
12it straight into Ames for handling. Also, all packets sent over the
12Ames network are sent by the Ames vane. Apps and vanes may use
13Ames network are sent by the Ames vane. Apps and vanes may use
13Ames to directly send messages to other ships. In general, apps use
14Ames to directly send messages to other ships. In general, apps use
14−[Gall](/docs/userspace/gall/gall) and [Clay](/docs/arvo/clay/clay)
15+[Gall](/docs/arvo/gall/gall) and [Clay](/docs/arvo/clay/clay)
15to communicate with other ships rather than using Ames
16to communicate with other ships rather than using Ames
16directly, but this isn't a requirement. Of course, Gall and Clay use
17directly, but this isn't a requirement. Of course, Gall and Clay use
17Ames behind the scenes to communicate across the network. Jael is the only other
18Ames behind the scenes to communicate across the network. Jael is the only other
@@ -25,32 +26,33 @@ protocol itself, including how to route incoming packets to the correct
25vane or app, is defined in Ames.
26vane or app, is defined in Ames.
26
27
27## Technical Overview
28## Technical Overview
29+
28This section summarizes the design of Ames. Beyond this section are deeper
30This section summarizes the design of Ames. Beyond this section are deeper
29elaborations on the concepts presented here.
31elaborations on the concepts presented here.
30
32
31Ames extends [Arvo's](/docs/arvo/overview) `%pass`/`%give` `move` semantics across the network.
33Ames extends [Arvo's](/docs/arvo/overview) `%pass`/`%give` `move` semantics across the network.
32
34
33Ames receives packets as Arvo events and emits packets as Arvo
35Ames receives packets as Arvo events and emits packets as Arvo
34−effects. The runtime is responsible for transferring the bytes in
36+effects. The runtime is responsible for transferring the bytes in
35an Ames packet across a physical network to another ship.
37an Ames packet across a physical network to another ship.
36
38
37The runtime tells Ames which physical address a packet came from,
39The runtime tells Ames which physical address a packet came from,
38−represented as an opaque atom. Ames can emit a packet effect to
40+represented as an opaque atom. Ames can emit a packet effect to
39one of those opaque atoms or to the Urbit address of a galaxy
41one of those opaque atoms or to the Urbit address of a galaxy
40(root node), which the runtime is responsible for translating to a
42(root node), which the runtime is responsible for translating to a
41−physical address. One runtime implementation sends UDP packets
43+physical address. One runtime implementation sends UDP packets
42using IPv4 addresses for ships and DNS lookups for galaxies, but
44using IPv4 addresses for ships and DNS lookups for galaxies, but
43other implementations may overlay over other kinds of networks.
45other implementations may overlay over other kinds of networks.
44
46
45−A local vane can pass Ames a `%plea` request message. Ames
47+A local vane can pass Ames a `%plea` request message. Ames
46transmits the message over the wire to the peer ship's Ames, which
48transmits the message over the wire to the peer ship's Ames, which
47passes the message to the destination vane.
49passes the message to the destination vane.
48
50
49Once the peer has processed the `%plea` message, it sends a
51Once the peer has processed the `%plea` message, it sends a
50message-acknowledgment packet over the wire back to the local
52message-acknowledgment packet over the wire back to the local
51−Ames. This "ack" can either be positive to indicate the request was
53+Ames. This "ack" can either be positive to indicate the request was
52processed, or negative to indicate the request failed, in which
54processed, or negative to indicate the request failed, in which
53−case it's called a "nack". (Don't confuse Ames nacks with TCP
55+case it's called a "nack". (Don't confuse Ames nacks with TCP
54nacks, which are a different concept).
56nacks, which are a different concept).
55
57
56When the local Ames receives either a positive message-ack or a
58When the local Ames receives either a positive message-ack or a
@@ -60,11 +62,11 @@ requested the original `%plea` message be sent.
60
62
61A local vane can give Ames zero or more `%boon` response messages in
63A local vane can give Ames zero or more `%boon` response messages in
62response to a `%plea`, on the same duct that Ames used to pass the
64response to a `%plea`, on the same duct that Ames used to pass the
63−`%plea` to the vane. Ames transmits a `%boon` over the wire to the
65+`%plea` to the vane. Ames transmits a `%boon` over the wire to the
64peer's Ames, which gives it to the destination vane on the same
66peer's Ames, which gives it to the destination vane on the same
65duct the vane had used to pass the original `%plea` to Ames.
67duct the vane had used to pass the original `%plea` to Ames.
66
68
67−`%boon` messages are acked automatically by the receiver Ames. They
69+`%boon` messages are acked automatically by the receiver Ames. They
68cannot be nacked, and Ames only uses the ack internally, without
70cannot be nacked, and Ames only uses the ack internally, without
69notifying the client vane that gave Ames the `%boon`.
71notifying the client vane that gave Ames the `%boon`.
70
72
@@ -74,15 +76,15 @@ indicating the `%boon` was missed.
74
76
75`%plea` messages can be nacked, in which case the peer will send
77`%plea` messages can be nacked, in which case the peer will send
76both a message-nack packet and a naxplanation message, which is
78both a message-nack packet and a naxplanation message, which is
77−sent in a way that does not interfere with normal operation. The
79+sent in a way that does not interfere with normal operation. The
78naxplanation is sent as a full Ames message, instead of just a
80naxplanation is sent as a full Ames message, instead of just a
79packet, because the contained error information can be arbitrarily
81packet, because the contained error information can be arbitrarily
80−large. A naxplanation can only give rise to a positive ack --
82+large. A naxplanation can only give rise to a positive ack --
81never ack an ack, and never nack a naxplanation.
83never ack an ack, and never nack a naxplanation.
82
84
83Ames guarantees a total ordering of messages within a "flow",
85Ames guarantees a total ordering of messages within a "flow",
84identified in other vanes by a duct and over the wire by a `bone`:
86identified in other vanes by a duct and over the wire by a `bone`:
85−an opaque number. Each flow has a FIFO (first-in-first-out) queue of `%plea` requests
87+an opaque number. Each flow has a FIFO (first-in-first-out) queue of `%plea` requests
86from the requesting ship to the responding ship and a FIFO queue
88from the requesting ship to the responding ship and a FIFO queue
87of `%boon`'s in the other direction.
89of `%boon`'s in the other direction.
88
90
@@ -94,23 +96,23 @@ destination vane.
94
96
95Ames encrypts every message using symmetric-key encryption by
97Ames encrypts every message using symmetric-key encryption by
96performing an elliptic curve Diffie-Hellman using our private key
98performing an elliptic curve Diffie-Hellman using our private key
97−and the public key of the peer. For ships in the Jael PKI
99+and the public key of the peer. For ships in the Jael PKI
98(public-key infrastructure), Ames looks up the peer's public key
100(public-key infrastructure), Ames looks up the peer's public key
99−from Jael. Comets (128-bit ephemeral addresses) are not
101+from Jael. Comets (128-bit ephemeral addresses) are not
100cryptographic assets and must self-attest over Ames by sending a
102cryptographic assets and must self-attest over Ames by sending a
101single self-signed packet containing their public key.
103single self-signed packet containing their public key.
102
104
103When a peer suffers a continuity breach, Ames removes all
105When a peer suffers a continuity breach, Ames removes all
104−messaging state related to it. Ames does not guarantee that all
106+messaging state related to it. Ames does not guarantee that all
105−messages will be fully delivered to the now-stale peer. From
107+messages will be fully delivered to the now-stale peer. From
106Ames's perspective, the newly restarted peer is a new ship.
108Ames's perspective, the newly restarted peer is a new ship.
107Ames's guarantees are not maintained across a breach.
109Ames's guarantees are not maintained across a breach.
108
110
109A vane can pass Ames a `%heed` `$task` to request Ames track a peer's
111A vane can pass Ames a `%heed` `$task` to request Ames track a peer's
110−responsiveness. If our `%boon`'s to it start backing up locally,
112+responsiveness. If our `%boon`'s to it start backing up locally,
111Ames will give a `%clog` back to the requesting vane containing the
113Ames will give a `%clog` back to the requesting vane containing the
112−unresponsive peer's urbit address. This interaction does not use
114+unresponsive peer's urbit address. This interaction does not use
113−ducts as unique keys. Stop tracking a peer by sending Ames a
115+ducts as unique keys. Stop tracking a peer by sending Ames a
114`%jilt` `$task`.
116`%jilt` `$task`.
115
117
116Debug output can be adjusted using `%sift` and `%spew` `$task`'s.
118Debug output can be adjusted using `%sift` and `%spew` `$task`'s.
@@ -128,46 +130,46 @@ There is a 32-bit header followed by a variable width body.
128
130
129The 32-bit header is given by the following data, presented in order:
131The 32-bit header is given by the following data, presented in order:
130
132
131− - 3 bits: reserved
133+- 3 bits: reserved
132− - 1 bit: is this Ames? (i.e. not using a different protocol, such as the
134+- 1 bit: is this Ames? (i.e. not using a different protocol, such as the
133− planned remote scry protocol)
135+ planned remote scry protocol)
134− - 3 bits: Ames protocol version (currently 0)
136+- 3 bits: Ames protocol version (currently 0)
135− - 2 bits: sender address size
137+- 2 bits: sender address size
136− - 2 bits: receiver address size
138+- 2 bits: receiver address size
137− - 20 bits: checksum (truncated insecure hash of the body, done with
139+- 20 bits: checksum (truncated insecure hash of the body, done with
138− [`+mug`](/docs/hoon/reference/stdlib/2e#mug)
140+ [`+mug`](/docs/hoon/reference/stdlib/2e#mug)
139− - 1 bit: is this relayed? (if set, `origin` will be present in the body)
141+- 1 bit: is this relayed? (if set, `origin` will be present in the body)
140
142
141− Every packet sent between ships is encrypted except for self-signed attestation packets from 128-bit comets.
143+Every packet sent between ships is encrypted except for self-signed attestation packets from 128-bit comets.
142
144
143#### Body
145#### Body
144
146
145The body is of variable length and consists of the following parts in this
147The body is of variable length and consists of the following parts in this
146order:
148order:
147
149
148− - 4 bits: sender life (mod 16)
150+- 4 bits: sender life (mod 16)
149− - 4 bits: receiver life (mod 16)
151+- 4 bits: receiver life (mod 16)
150− - variable: sender address
152+- variable: sender address
151− - variable: receiver address
153+- variable: receiver address
152− - 48 bits: (optional) 48-bit `origin`
154+- 48 bits: (optional) 48-bit `origin`
153− - 128 bits: `SIV`
155+- 128 bits: `SIV`
154− - 16 bits: ciphertext size
156+- 16 bits: ciphertext size
155− - variable: ciphertext
157+- variable: ciphertext
156−
158+
157− `origin` is the IP and port of the original sender if the packet was proxied
159+`origin` is the IP and port of the original sender if the packet was proxied
158− through a relay.
160+through a relay.
159−
161+
160− `SIV` is a "synthetic initialization vector" as defined in AES-256 SIV, the encryption
162+`SIV` is a "synthetic initialization vector" as defined in AES-256 SIV, the encryption
161− algorithm utilized to encrypt Ames packets (see the page on [Ames
163+algorithm utilized to encrypt Ames packets (see the page on [Ames
162− cryptography](/docs/arvo/ames/cryptography)). It is formed from the
164+cryptography](/docs/arvo/ames/cryptography)). It is formed from the
163− following noun: `~[sender=@p receiver=@p sender-life=@ receiver-life=@]` (see
165+following noun: `~[sender=@p receiver=@p sender-life=@ receiver-life=@]` (see
164− [Life and Rift](/docs/azimuth/life-and-rift) for information on what `life`
166+[Life and Rift](/docs/azimuth/life-and-rift) for information on what `life`
165− is). As this data is in Azimuth, it is not explicitly sent over the wire. Thus
167+is). As this data is in Azimuth, it is not explicitly sent over the wire. Thus
166− the mod 16 sender and receiver life in the first 8 bits are only for quick
168+the mod 16 sender and receiver life in the first 8 bits are only for quick
167− filtering of honest packets sent to or from a stale life.
169+filtering of honest packets sent to or from a stale life.
168−
170+
169− The ciphertext is formed by `+jam`ming a `$shut-packet` and then encrypting
171+The ciphertext is formed by `+jam`ming a `$shut-packet` and then encrypting
170− using [`+en:sivc:aes:crypto`](/docs/arvo/reference/cryptography#en).
172+using [`+en:sivc:aes:crypto`](/docs/arvo/reference/cryptography#en).
171
173
172### Packeting
174### Packeting
173
175
@@ -187,9 +189,7 @@ eventually get through, and when the other side gets them it can put them in the
187correct order. If Ames doesn't get an ack on a packet then it will resend it
189correct order. If Ames doesn't get an ack on a packet then it will resend it
188until it does. The logic for determining how many packets to send or re-send at what time is performed by an Ames-specific variant of TCP's "NewReno" congestion control algorithm.
190until it does. The logic for determining how many packets to send or re-send at what time is performed by an Ames-specific variant of TCP's "NewReno" congestion control algorithm.
189
191
190−As each packet in a message is received, Ames decrypts it and stores the message fragment. Once it's received every packet for a message, Ames concatenates the fragments back into a single large atom and uses `+cue` to deserialize that back into the original message noun.
192+As each packet in a message is received, Ames decrypts it and stores the message fragment. Once it's received every packet for a message, Ames concatenates the fragments back into a single large atom and uses `+cue` to deserialize that back into the original message noun.
191−
192−
193
193
194### Acks and Nacks
194### Acks and Nacks
195
195
@@ -221,8 +221,7 @@ Thus a message-level ack must be received before the next message on the flow
221can begin. The full story is more complicated than this; see the section on
221can begin. The full story is more complicated than this; see the section on
222[flows](#flows).
222[flows](#flows).
223
223
224−
225−#### Nacks
224+#### Nacks {#nacks}
226
225
227A nack indicates a negative acknowledgement to a `%plea`, meaning that the
226A nack indicates a negative acknowledgement to a `%plea`, meaning that the
228requested action was not performed.
227requested action was not performed.
@@ -248,9 +247,11 @@ the receiver will never both perform a `%plea` and return a naxplanation.
248
247
249A fragment ack's contents (before encryption) are a pure function of the
248A fragment ack's contents (before encryption) are a pure function of the
250following noun:
249following noun:
250+
251```hoon
251```hoon
252[our-life her-life bone message-num fragment-num]
252[our-life her-life bone message-num fragment-num]
253```
253```
254+
254This means all re-sends of an ack packet will be bitwise identical to each other, unless one of the peers changes its encryption keys.
255This means all re-sends of an ack packet will be bitwise identical to each other, unless one of the peers changes its encryption keys.
255
256
256Each datum in this noun is an atom with the aura `@ud` or an aura that nests
257Each datum in this noun is an atom with the aura `@ud` or an aura that nests
@@ -269,11 +270,11 @@ A message (n)ack is a different kind of ack that is obtained by encrypting the
269```hoon
270```hoon
270[our-life her-life bone message-num ok=? lag=@dr]
271[our-life her-life bone message-num ok=? lag=@dr]
271```
272```
273+
272`ok` is a flag that is set to `%.y` for a message ack and `%.n` for a message
274`ok` is a flag that is set to `%.y` for a message ack and `%.n` for a message
273nack. In the future, `lag` will be used to
275nack. In the future, `lag` will be used to
274describe the time it took to process a message, but for now it is always zero.
276describe the time it took to process a message, but for now it is always zero.
275
277
276−
277### Flows
278### Flows
278
279
279Flows are asymmetric communication channels along which two ships send and
280Flows are asymmetric communication channels along which two ships send and
@@ -300,10 +301,10 @@ We give an example of such a partition. Let flow 12 be a flow between `~bacbel-t
300`~bacbel-tagfeg` as the `%plea` sender. Then bones 12-15 are associated with the
301`~bacbel-tagfeg` as the `%plea` sender. Then bones 12-15 are associated with the
301flow, and the types of packets for each bone are:
302flow, and the types of packets for each bone are:
302
303
303− - bone 12, `%plea`s and acks to `~worwel-sipnum`,
304+- bone 12, `%plea`s and acks to `~worwel-sipnum`,
304− - bone 13, `%boon`s and (n)acks to `~bacbel-tagfeg`,
305+- bone 13, `%boon`s and (n)acks to `~bacbel-tagfeg`,
305− - bone 14, acks of naxplanations to `~worwel-sipnum`,
306+- bone 14, acks of naxplanations to `~worwel-sipnum`,
306− - bone 15, naxplanations to `~bacbel-tagfeg`.
307+- bone 15, naxplanations to `~bacbel-tagfeg`.
307
308
308Each bone is handled separately by congestion control, and this is one reason
309Each bone is handled separately by congestion control, and this is one reason
309for their segregation. For example, say a two-packet `%plea` is sent on bone 12,
310for their segregation. For example, say a two-packet `%plea` is sent on bone 12,
@@ -379,16 +380,17 @@ private key and the public key of `~worwel-sipnum`, obtained via Jael. Then
379`~bacbel-tagfeb` sends a packet addressed to `~worwel-sipnum` to `~zod`.
380`~bacbel-tagfeb` sends a packet addressed to `~worwel-sipnum` to `~zod`.
380
381
381The packet has the following format:
382The packet has the following format:
383+
382− - The standard Ames header described in [header](#header), where the checksum
384+- The standard Ames header described in [header](#header), where the checksum
383− is the `+mug` of the body, and the sender and receiver ship types are `01`,
385+ is the `+mug` of the body, and the sender and receiver ship types are `01`,
384− denoting that the sender and receiver are planets. The "is this relayed?" bit
386+ denoting that the sender and receiver are planets. The "is this relayed?" bit
385− is set to 0 since this is the first hop on the packet route.
387+ is set to 0 since this is the first hop on the packet route.
386− - The body of this packet will be the life of `~bacbel-tagfeg` mod 16, followed
388+- The body of this packet will be the life of `~bacbel-tagfeg` mod 16, followed
387− by the life of `~worwel-sipnum` mod 16, followed by `~bacbel-tagfeg`,
389+ by the life of `~worwel-sipnum` mod 16, followed by `~bacbel-tagfeg`,
388− followed by the receiver `~worwel-sipnum`, followed by the origin `~`
390+ followed by the receiver `~worwel-sipnum`, followed by the origin `~`
389− (denoting that the ship sending the packet is the origin). After this comes
391+ (denoting that the ship sending the packet is the origin). After this comes
390− the payload.
392+ the payload.
391− - The payload of this packet will be the `+jam` of the `content`, which is an encrypted fragment of the message `%watch /path/to/recipes`.
393+- The payload of this packet will be the `+jam` of the `content`, which is an encrypted fragment of the message `%watch /path/to/recipes`.
392
394
393`~zod` receives the packet and reads the body. It sees that it is not the
395`~zod` receives the packet and reads the body. It sees that it is not the
394intended recipient of the packet, and so gets ready to forward it to
396intended recipient of the packet, and so gets ready to forward it to
@@ -398,8 +400,7 @@ with the new mug. Since the packet is being relayed, `~zod` flips the "is it
398relayed?" bit to `%.y`. `~zod` then forwards the packet to `~worwel-sipnum`.
400relayed?" bit to `%.y`. `~zod` then forwards the packet to `~worwel-sipnum`.
399
401
400In order to decrypt the packet, `~worwel-sipnum` will need to calculate the
402In order to decrypt the packet, `~worwel-sipnum` will need to calculate the
401−associated data vector utilized by SIV, which consists of `~[sender=@p
402−receiver=@p sender-life=@ receiver-life=@]`. It then passes that along with the
403+associated data vector utilized by SIV, which consists of `~[sender=@p receiver=@p sender-life=@ receiver-life=@]`. It then passes that along with the
403SIV and ciphertext to the decryption function, and receives the unencrypted
404SIV and ciphertext to the decryption function, and receives the unencrypted
404packet as a return.
405packet as a return.
405
406
@@ -463,4 +464,3 @@ hands it off the the Unix network interface to be sent.
463Now the receiving King is handed a UDP packet by Unix. The King removes the UDP
464Now the receiving King is handed a UDP packet by Unix. The King removes the UDP
464wrapper, `+jam`s the `lane` on which it heard the packet, and delivers the packet
465wrapper, `+jam`s the `lane` on which it heard the packet, and delivers the packet
465to the Ames vane as an atom by copying the bytes it heard on the UDP port.
466to the Ames vane as an atom by copying the bytes it heard on the UDP port.
466−
content/docs/arvo/ames/cryptography.md+3−3
@@ -1,6 +1,6 @@
1+++
1+++
2title = "Cryptography"
2title = "Cryptography"
3−weight = 5
3+weight = 2
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
@@ -34,7 +34,7 @@ Algorithm](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algori
34is used for authentication
34is used for authentication
35
35
36The encrypted payload of each packet is a `$shut-packet`, which is the `+jam` of
36The encrypted payload of each packet is a `$shut-packet`, which is the `+jam` of
37−a cell with the `bone`, message number, and message fragment or ack (see
37+a cell with the [$bone](/docs/arvo/ames/data-types#bone), message number, and message fragment or ack (see
38[Ames](/docs/arvo/ames/ames) for more information on packet structure). The
38[Ames](/docs/arvo/ames/ames) for more information on packet structure). The
39message fragment is signed using the authentication key. It is encrypted using
39message fragment is signed using the authentication key. It is encrypted using
40[`+en:crub:crypto`](/docs/arvo/reference/cryptography#en) found in
40[`+en:crub:crypto`](/docs/arvo/reference/cryptography#en) found in
@@ -43,7 +43,7 @@ message fragment is signed using the authentication key. It is encrypted using
43## Diffie-Hellman key exchange {#key-exchange}
43## Diffie-Hellman key exchange {#key-exchange}
44
44
45For each foreign ship a given ship has communicated with, `$ames-state` contains a
45For each foreign ship a given ship has communicated with, `$ames-state` contains a
46−`$peer-state`, inside which the `$symmetric-key` (an atom which nests under
46+[$peer-state](/docs/arvo/ames/data-types#peer-state), inside which the [$symmetric-key](/docs/arvo/ames/data-types#symmetric-key) (an atom which nests under
47`@uw`) is utilized for encrypting all Ames packets shared between the two ships.
47`@uw`) is utilized for encrypting all Ames packets shared between the two ships.
48The `symmetric-key` is derived using [`+shar:ed:crypto`](/docs/arvo/reference/cryptography#ed) found in `sys/zuse.hoon`,
48The `symmetric-key` is derived using [`+shar:ed:crypto`](/docs/arvo/reference/cryptography#ed) found in `sys/zuse.hoon`,
49which is an arm utilized for generating the symmetric key for elliptic curve
49which is an arm utilized for generating the symmetric key for elliptic curve
content/docs/arvo/ames/data-types.mdnew file+389
@@ -0,0 +1,389 @@
1++++
2+title = "Data Types"
3+weight = 5
4+template = "doc.html"
5++++
6+
7+Here are the data types used by Ames, as defined in `lull.hoon`.
8+
9+## `$address`
10+
11+```hoon
12++$ address @uxaddress
13+```
14+
15+Opaque atomic transport address to or from Unix. For Ames over UDP, it will encode the IP address and port.
16+
17+## `$verb`
18+
19+```hoon
20++$ verb ?(%snd %rcv %odd %msg %ges %for %rot)
21+```
22+
23+Verbosity flag for Ames. Use with `|ames-verb %flag1 %flag2 ...` and turn off with `|ames-verb`.
24+
25+- `%snd` - Sending packets.
26+- `%rcv` - Receiving packets.
27+- `%odd` - Unusual events.
28+- `%msg` - Message-level events.
29+- `%ges` - Congestion control.
30+- `%for` - Packet forwarding.
31+- `%rot` - Routing attempts.
32+
33+## `$blob`
34+
35+```hoon
36++$ blob @uxblob
37+```
38+
39+Raw atom to or from Unix, representing a packet.
40+
41+## `$error`
42+
43+```hoon
44++$ error [tag=@tas =tang]
45+```
46+
47+Tagged diagnostic trace.
48+
49+## `$lane`
50+
51+```hoon
52++$ lane (each @pC address)
53+```
54+
55+Ship transport address; either opaque [$address](#address) or galaxy. The runtime knows how to look up galaxies, so we don't need to know their transport addresses.
56+
57+## `$plea`
58+
59+```hoon
60++$ plea [vane=@tas =path payload=*]
61+```
62+
63+Application-level message, as a `%pass`.
64+
65+- `vane` - Destination vane on remote ship.
66+- `path` - Internal route on the receiving ship.
67+- `payload` - Semantic message contents.
68+
69+## `$bone`
70+
71+```hoon
72++$ bone @udbone
73+```
74+
75+Message flow index - mapped to `duct`s in the [$ossuary](#ossuary).
76+
77+The first `bone` is 0. They increment by 4, since each flow includes a bit for each message determining forward vs. backward and a second bit for whether the message is on the normal flow or the associated diagnostic flow (for naxplanations).
78+
79+The least significant bit of a `bone` is:
80+
81+- 1 if "forward", i.e. we send `%plea`s on this flow.
82+- 0 if "backward", i.e. we receive `%plea`s on this flow.
83+
84+The second-least significant bit is 1 if the `bone` is a naxplanation `bone`, and 0 otherwise. Only naxplanation messages can be sent on a naxplanation `bone`, as `%boon`s.
85+
86+## `$fragment`
87+
88+```hoon
89++$ fragment @uwfragment
90+```
91+
92+A message fragment.
93+
94+## `$fragment-num`
95+
96+```hoon
97++$ fragment-num @udfragmentnum
98+```
99+
100+Message fragment count.
101+
102+## `$message-blob`
103+
104+```hoon
105++$ message-blob @udmessageblob
106+```
107+
108+Unfragmented message blob.
109+
110+## `$message-num`
111+
112+```hoon
113++$ message-num @udmessagenum
114+```
115+
116+Message count.
117+
118+## `$public-key`
119+
120+```hoon
121++$ public-key @uwpublickey
122+```
123+
124+A peer's public key.
125+
126+## `$symmetric-key`
127+
128+```hoon
129++$ symmetric-key @uwsymmetrickey
130+```
131+
132+A symmetric key for encrypting messages to a peer. This is produced by performing an elliptic curve Diffie-Hellman using our private key and the peer's public key.
133+
134+## `$ack`
135+
136+```hoon
137++$ ack
138+ $% [%ok ~]
139+ [%nack ~]
140+ [%naxplanation =error]
141+ ==
142+```
143+
144+A message acknowledgement.
145+
146+- `%ok` - Positive acknowledgement.
147+- `%nack` - Negative acknowledgement.
148+- `%naxplanation` - Nack trace.
149+
150+## `$ship-state`
151+
152+```hoon
153++$ ship-state
154+ $% [%alien alien-agenda]
155+ [%known peer-state]
156+ ==
157+```
158+
159+All Ames knows about a peer.
160+
161+- `%alien` - No PKI data, so enqueue actions to perform once we learn it.
162+- `%known` - We know their `life` and public keys, so we have a channel.
163+
164+## `$alien-agenda`
165+
166+```hoon
167++$ alien-agenda
168+ $: messages=(list [=duct =plea])
169+ packets=(set =blob)
170+ heeds=(set duct)
171+ ==
172+```
173+
174+What to do when Ames learns a peer's life and keys.
175+
176+- `messages` - [$plea](#plea)s local vanes have asked Ames to send.
177+- `packets` - Packets we've tried to send.
178+- `heeds` - Local tracking requests; passed through into [$peer-state](#peer-state).
179+
180+## `$peer-state`
181+
182+```hoon
183++$ peer-state
184+ $: $: =symmetric-key
185+ =life
186+ =public-key
187+ sponsor=ship
188+ ==
189+ route=(unit [direct=? =lane])
190+ =qos
191+ =ossuary
192+ snd=(map bone message-pump-state)
193+ rcv=(map bone message-sink-state)
194+ nax=(set [=bone =message-num])
195+ heeds=(set duct)
196+ ==
197+```
198+
199+State for a peer with known life and keys.
200+
201+- `route` - Transport-layer destination for packets to the peer.
202+- `qos` - Quality of service; connection status to the peer.
203+- `ossuary` - [$bone](#bone) to `duct` mapper.
204+- `snd` - Per-`bone` message pumps to send messages as fragments.
205+- `rcv` - Per-`bone` message sinks to assemble messages from fragments.
206+- `nax` - Unprocessed nacks (negative acknowledgments).
207+- `heeds` - Listeners for `%clog` notifications.
208+
209+## `$qos`
210+
211+```hoon
212++$ qos
213+ $~ [%unborn *@da]
214+ [?(%live %dead %unborn) last-contact=@da]
215+```
216+
217+Quality of service; how is the connection to a peer doing?
218+
219+- `%live` - Peer is ok.
220+- `%dead` - Peer is not responding.
221+- `%unborn` - Peer is sunken.
222+- `last-contact` - Last time Ames heard from the peer, or if `%unborn`, the time when we first started tracking then.
223+
224+## `$ossuary`
225+
226+```hoon
227++$ ossuary
228+ $: =next=bone
229+ by-duct=(map duct bone)
230+ by-bone=(map bone duct)
231+ ==
232+```
233+
234+[$bone](#bone) to `duct` mapping, `next` is the next `bone` to map to a `duct`.
235+
236+## `$message-pump-state`
237+
238+```hoon
239++$ message-pump-state
240+ $: current=_`message-num`1
241+ next=_`message-num`1
242+ unsent-messages=(qeu message-blob)
243+ unsent-fragments=(list static-fragment)
244+ queued-message-acks=(map message-num ack)
245+ =packet-pump-state
246+ ==
247+```
248+
249+Persistent state for a `|message-pump`.
250+
251+- `current`- Sequence number of earliest message sent or being sent.
252+- `next` - Sequence number of next message to send.
253+- `unsent-messages` - Messages to be sent after current message.
254+- `unsent-fragments` - Fragments of current message waiting for sending.
255+- `queued-message-acks` - Future message acks to be applied after current.
256+- `packet-pump-state` - State of corresponding `|packet-pump`.
257+
258+## `$static-fragment`
259+
260+```hoon
261++$ static-fragment
262+ $: =message-num
263+ num-fragments=fragment-num
264+ =fragment-num
265+ =fragment
266+ ==
267+```
268+
269+A packet; a fragment of a message and metadata.
270+
271+## `$packet-pump-state`
272+
273+```hoon
274++$ packet-pump-state
275+ $: next-wake=(unit @da)
276+ live=(tree [live-packet-key live-packet-val])
277+ metrics=pump-metrics
278+ ==
279+```
280+
281+Persistent state for a `|packet-pump`.
282+
283+- `next-wake` - Last timer we've set, or null.
284+- `live` - Packets in flight; sent but not yet acked.
285+- `metrics` - Congestion control information.
286+
287+## `$pump-metrics`
288+
289+```hoon
290++$ pump-metrics
291+ $: rto=_~s1
292+ rtt=_~s1
293+ rttvar=_~s1
294+ ssthresh=_10.000
295+ cwnd=_1
296+ num-live=@ud
297+ counter=@ud
298+ ==
299+```
300+
301+Congestion control state for a `|packet-pump`.
302+
303+- `rto` - Retransmission timeout.
304+- `rtt` - Roundtrip time estimate, low-passed using EWMA.
305+- `rttvar` - Mean deviation of `rtt`, also low-passed with EWMA.
306+- `num-live` - How many packets sent, awaiting ack.
307+- `ssthresh` - Slow-start threshold.
308+- `cwnd` - Congestion window; max unacked packets.
309+
310+## `$live-packet`
311+
312+```hoon
313++$ live-packet
314+ $: key=live-packet-key
315+ val=live-packet-val
316+ ==
317+```
318+
319+A packet in flight, as tracked in the [$packet-pump-state](#packet-pump-state).
320+
321+## `$live-packet-key`
322+
323+```hoon
324++$ live-packet-key
325+ $: =message-num
326+ =fragment-num
327+ ==
328+```
329+
330+Identifier of a packet in flight.
331+
332+## `$live-packet-val`
333+
334+```hoon
335++$ live-packet-val
336+ $: packet-state
337+ num-fragments=fragment-num
338+ =fragment
339+ ==
340+```
341+
342+Content and metadata about a packet in flight.
343+
344+## `$packet-state`
345+
346+```hoon
347++$ packet-state
348+ $: last-sent=@da
349+ retries=@ud
350+ skips=@ud
351+ ==
352+```
353+
354+Sending statistics about a packet in flight.
355+
356+## `$message-sink-state`
357+
358+```hoon
359++$ message-sink-state
360+ $: last-acked=message-num
361+ last-heard=message-num
362+ pending-vane-ack=(qeu [=message-num message=*])
363+ live-messages=(map message-num partial-rcv-message)
364+ nax=(set message-num)
365+ ==
366+```
367+
368+State of a `|message-sink` to assemble received messages.
369+
370+- `last-acked` - Highest [$message-num](#message-num) Ames has fully acknowledged.
371+- `last-heard` - Highest `message-num` Ames has heard all fragments for.
372+- `pending-vane-ack` - Heard but not processed by local vane.
373+- `live-messages` - Partially received messages.
374+
375+## `$partial-rcv-message`
376+
377+```hoon
378++$ partial-rcv-message
379+ $: num-fragments=fragment-num
380+ num-received=fragment-num
381+ fragments=(map fragment-num fragment)
382+ ==
383+```
384+
385+A message for which Ames has received some fragments.
386+
387+- `num-fragments` - Total number of fragments in the message.
388+- `num-received` - How many fragments Ames has received so far.
389+- `fragments` - The received fragments themselves.
content/docs/arvo/ames/scry.mdnew file+126
@@ -0,0 +1,126 @@
1++++
2+title = "Scry Reference"
3+weight = 4
4+template = "doc.html"
5++++
6+
7+Here are the scry endpoints of Ames. All of them take a `%x` `care` and require the `desk` in the path prefix be empty, so the general format is `.^([type] %ax /=//=/[some-path])`.
8+
9+## /protocol/version
10+
11+A scry with a `%x` `care` and a `path` of `/protocol/version` will return the current Ames protocol version as a `@`.
12+
13+#### Example
14+
15+```
16+> .^(@ %ax /=//=/protocol/version)
17+0
18+```
19+
20+## /peers
21+
22+A scry with a `%x` `care` and a `path` of `/peers` will return all ships that Ames is aware of. The type returned is a `(map ship ?(%alien %known))`, where `%known` means we have PKI data for them and `%alien` means we don't.
23+
24+#### Example
25+
26+```
27+> .^((map ship ?(%alien %known)) %ax /=//=/peers)
28+{[p=~wet q=%known] [p=~nes q=%known]}
29+```
30+
31+## /peers/[ship]
32+
33+A scry with a `%x` `care` and a `path` of `/peers/[ship]` where `[ship]` is a ship name like `~dopzod` will return everything Ames knows about that ship, or crash if the ship is unknown to Ames. The type returned is a [$ship-state](/docs/arvo/ames/data-types#ship-state).
34+
35+#### Example
36+
37+```
38+> .^(ship-state:ames %ax /=//=/peers/~nes)
39+[ %known
40+ [ symmetric-key=0wEF.5-Mp4.ehBxk.a-ktl.CAUHq.~XNVq.AfPFk.TwBbj.rc7MS
41+ life=1
42+ public-key=0w9R.IG6Km.CQfuL.lP9Da.l~kh1.lOHzV.xactk.1ybiB.hekW~.VC2d0.DDRsU.h6GHl.PKmRX.p3u2-.vO4Hg.QTOlp.A4AI0.uGPVy
43+ sponsor=~nes
44+ ]
45+ route=[~ [direct=%.y lane=[%.y p=~nes]]]
46+ qos=[%dead last-contact=~2021.8.9..16.11.36..fdbc]
47+ ossuary
48+ [ next-bone=4
49+ by-duct={[p=~[/gall/sys/way/~nes/hood /gall/use/hood/0w2.4d7EV/out/~nes/hood/helm/hi/~nes /dill //term/1] q=0]}
50+ by-bone={[p=0 q=~[/gall/sys/way/~nes/hood /gall/use/hood/0w2.4d7EV/out/~nes/hood/helm/hi/~nes /dill //term/1]]}
51+ ]
52+ snd
53+ { [ p=0
54+ q
55+ [ current=2
56+ next=3
57+ unsent-messages={}
58+ unsent-fragments=~
59+ queued-message-acks={}
60+ packet-pump-state
61+ [ next-wake=[~ ~2021.8.17..02.21.14..3d23]
62+ live={[[message-num=2 fragment-num=0] [last-sent=~2021.8.17..02.19.14..3d23 retries=2.255 skips=0] num-fragments=1 fragment=0w2.QJ1qS.JzaQn.w7rMp.IzuTJ.7M7aP.-1s~1]}
63+ metrics=[rto=~m2 rtt=~s1 rttvar=~s1 ssthresh=1 cwnd=1 num-live=1 counter=1]
64+ ]
65+ ]
66+ ]
67+ }
68+ rcv={}
69+ nax={}
70+ heeds={~[/gall/sys/lag /dill //term/1]}
71+]
72+```
73+
74+## /peers/[ship]/forward-lane
75+
76+A scry with a `%x` `care` and a `path` of `/peers/[ship]/forward-lane` where `[ship]` is a ship name like `~dopzod` will return outbound routes to the given ship, or `~` if there are none. The type returned is a `(list lane:ames)`, see [$lane](/docs/arvo/ames/data-types#lane) for type details.
77+
78+#### Examples
79+
80+```
81+> .^((list lane:ames) %ax /=//=/peers/~nes/forward-lane)
82+~[[%.y p=~nes]]
83+```
84+
85+```
86+> .^((list lane:ames) %ax /=//=/peers/~nec/forward-lane)
87+~
88+```
89+
90+## /bones/[ship]
91+
92+A scry with a `%x` `care` and a `path` of `/bones/[ship]` where `[ship]` is a ship name like `~dopzod` will return inbound and outbound [$bone](/docs/arvo/ames/data-types#bone)s, which index message flows. If the ship in question is unknown to Ames, the scry will fail. The type returned is `[snd=(set bone) rcv=(set bone)]`.
93+
94+#### Example
95+
96+```
97+> .^([snd=(set bone) rcv=(set bone)] %ax /=//=/bones/~nes)
98+[snd={0} rcv={}]
99+```
100+
101+## /snd-bones/[ship]/[bone]
102+
103+A scry with a `%x` `care` and a `path` of `/snd-bones/[ship]/[bone]`, where `[ship]` is a ship name like `~dopzod` and `[bone]` is an outbound [$bone](/docs/arvo/ames/data-types#bone), will return message flow details for that `bone`. If the ship in question is unknown to Ames or the `bone` does not exist, the scry will fail. The type returned is a [$message-pump-state](/docs/arvo/ames/data-types#message-pump-state) wrapped in a `vase`.
104+
105+#### Example
106+
107+```
108+> !< message-pump-state:ames .^(vase %ax /=//=/snd-bones/~nes/0)
109+[ current=2
110+ next=3
111+ unsent-messages={}
112+ unsent-fragments=~
113+ queued-message-acks={}
114+ packet-pump-state
115+ [ next-wake=[~ ~2021.8.17..02.27.14..aaff]
116+ live
117+ { [ [message-num=2 fragment-num=0]
118+ [last-sent=~2021.8.17..02.25.14..aaff retries=2.258 skips=0]
119+ num-fragments=1
120+ fragment=0w2.QJ1qS.JzaQn.w7rMp.IzuTJ.7M7aP.-1s~1
121+ ]
122+ }
123+ metrics=[rto=~m2 rtt=~s1 rttvar=~s1 ssthresh=1 cwnd=1 num-live=1 counter=1]
124+ ]
125+]
126+```
content/docs/arvo/ames/tasks.mdnew file+193
@@ -0,0 +1,193 @@
1++++
2+title = "API Reference"
3+weight = 3
4+template = "doc.html"
5++++
6+
7+In this document we describe the public interface for Ames. Namely, we describe
8+each `task` that Ames can be `%pass`ed, and which `gift`(s) Ames can `%give` in return.
9+
10+Some `task`s appear to have more than one arm associated to them, e.g. there are
11+four `+on-hear` arms. We denote this where it occurs, but always refer to the
12+`+on-hear:event-core` arm.
13+
14+Ames `task`s can be naturally divided into two categories: messaging tasks and
15+system/lifecycle tasks.
16+
17+## Messaging Tasks
18+
19+### `%hear`
20+
21+```hoon
22+[%hear =lane =blob]
23+```
24+
25+`%hear` handles raw packet receipt.
26+
27+This `task` only ever originates from Unix. It does the initial processing of a packet, namely by passing the raw packet information to `+decode-packet` which deserializes the packet and giving that data and the origin of the packet to `+on-hear-packet`, which begins the transformation of the packet into a new event in the form of a `+event-core`.
28+
29+There are multiple `+on-hear` arms in `ames.hoon`. Here we refer to `+on-hear:event-core`, as that is the one called by a `%hear` `task`. The other ones are used primarily for ack and nack processing, or receiving message fragments.
30+
31+`%hear` takes in a [$blob](/docs/arvo/ames/data-types#blob), which is essentially a large atom (around 1kB or less) that is the raw data of the message, and a [$lane](/docs/arvo/ames/data-types#lane), which is the origin of the message (typically an IP address).
32+
33+#### Returns
34+
35+`%hear` can trigger a number of possible returns. It can trigger the release of zero or more additional packets via `%send` `gift`s. It may also trigger a `%boon` or `%plea` `gift` (collectively referred to as a `%memo` within Ames) to a local vane in the case of a completed message.
36+
37+### `%heed`
38+
39+```hoon
40+[%heed =ship]
41+```
42+
43+A vane can pass Ames a `%heed` `task` to request Ames track a peer's responsiveness. If our `%boon`s to it start backing up locally, Ames will `give` a `%clog` back to the requesting vane containing the unresponsive peer's Urbit address.
44+
45+Stop tracking a peer by sending Ames a [%jilt](#jilt) `task`.
46+
47+The `ship` field specifies the peer to be tracked.
48+
49+#### Returns
50+
51+If the `ship` is indeed being unresponsive, as measured by backed up `%boon`s,
52+Ames will `give` a `%clog` `gift` to the requesting vane containing the
53+unresponsive peer's urbit address.
54+
55+### `%jilt`
56+
57+```hoon
58+[%jilt =ship]
59+```
60+
61+`%jilt` stops tracking a potentially unresponsive peer that was previously being
62+tracked as a result of the [%heed](#heed) `task`.
63+
64+There are two `+on-jilt` arms, this `task` utilizes `+on-hear:event-core`.
65+
66+The `ship` field specifies the peer we want to stop tracking.
67+
68+#### Returns
69+
70+This `task` returns no `gift`s.
71+
72+### `%plea`
73+
74+```hoon
75+[%plea =ship =plea:ames]
76+```
77+
78+`%plea` is the `task` used to instruct Ames to send a message. It extends the
79+`%pass`/`%give` semantics across the network. As such, it is the most
80+fundamental `task` in Ames and the primary reason for its existence.
81+
82+Ames also `pass`es a `%plea` `note` to another vane when it receives a message on a
83+"forward flow" from a peer, originally passed from one of the peer's vanes to the
84+peer's Ames.
85+
86+Ultimately `%plea` causes `%send` `gift`(s) to be sent to Unix, which tells
87+Unix to send packets. In terms of `%pass`/`%give` semantics, this is in
88+response to the `%born` `task`, which came along the Unix `duct`, rather than a
89+response to the `%plea`.
90+
91+A `%plea` `task` takes in the `ship` the `plea` is addressed to, and a [$plea](/docs/arvo/ames/data-types.md#plea).
92+
93+#### Returns
94+
95+This `task` returns no `gift`s.
96+
97+## System Tasks
98+
99+### `%born`
100+
101+```hoon
102+[%born ~]
103+```
104+
105+Each time you start your Urbit, the Arvo kernel calls the `%born` `task` for Ames.
106+
107+#### Returns
108+
109+In response to a `%born` `task`, Ames `%give`s Jael a `%turf` `gift`.
110+
111+The `duct` along which `%born` comes is Ames' only duct to Unix, so `%send`
112+`gift`s (which are instructions for Unix to send a packet) are also returned in
113+response to `%born`.
114+
115+### `%init`
116+
117+```hoon
118+[%init ~]
119+```
120+
121+`%init` is called a single time during the very first boot process, immediately
122+after the [larval stage](/docs/arvo/overview#larval-stage-core)
123+is completed. This initializes the vane. Jael is initialized first, followed by
124+other vanes such as Ames.
125+
126+In response to receiving the `%init` `task`, Ames subscribes to the information
127+contained by Jael.
128+
129+#### Returns
130+
131+```hoon
132+=~ (emit duct %pass /turf %j %turf ~)
133+ (emit duct %pass /private-keys %j %private-keys ~)
134+```
135+
136+`%init` sends two moves that subscribe to `%turf` and `%private-keys` in Jael.
137+
138+### `%sift`
139+
140+```hoon
141+[%sift ships=(list ship)]
142+```
143+
144+This `task` filters debug output by ship. This `task` is used internally when the `|ames-sift` `hood` generator is run from the dojo.
145+
146+The `ships` field specifies the ships for which debug output is desired.
147+
148+#### Returns
149+
150+This `task` returns no `gift`s.
151+
152+### `%spew`
153+
154+```hoon
155+[%spew veb=(list verb)]
156+```
157+
158+Sets verbosity toggles on debug output. This `task` is used internally when the `|ames-verb` `hood` generator is run from the dojo.
159+
160+`%spew` takes in a `list` of [$verb](/docs/arvo/ames/data-types#verb), which are verbosity flags for Ames.
161+
162+`%spew` flips each toggle given in `veb`.
163+
164+#### Returns
165+
166+This `task` returns no `gift`s.
167+
168+### `%stir`
169+
170+```hoon
171+[%stir arg=@t]
172+```
173+
174+A `%stir` `task` starts timers for any flows that lack them.
175+
176+The `arg` field is unused.
177+
178+#### Returns
179+
180+This `task` returns no `gift`s.
181+
182+### `%vega`
183+
184+```hoon
185+[%vega ~]
186+```
187+
188+`%vega` is called whenever the kernel is updated. Ames currently does not do
189+anything in response to this.
190+
191+#### Returns
192+
193+This `task` returns no `gift`s.
content/docs/arvo/behn/examples.md+2−2
@@ -39,7 +39,7 @@ Below is a thread which will take a `@dr` as its argument and `%pass`es Behn a `
39(pure:m !>(~))
39(pure:m !>(~))
40```
40```
41
41
42−Save the thread to `/ted/wait.hoon` and `|commit %home`. Then we can try running the thread with a `@dr` of `~s2`:
42+Save the thread to `/ted/wait.hoon` and `|commit %base`. Then we can try running the thread with a `@dr` of `~s2`:
43
43
44```
44```
45> -wait ~s2
45> -wait ~s2
@@ -84,7 +84,7 @@ Below is a variation on the [%wake](#wake) thread. It takes a `@dr` as its argum
84(pure:m !>(~))
84(pure:m !>(~))
85```
85```
86
86
87−Save the above thread to `/ted/rest.hoon`, and `|commit %home`. Let's try run it with an argument of `~s2`:
87+Save the above thread to `/ted/rest.hoon`, and `|commit %base`. Let's try run it with an argument of `~s2`:
88
88
89```
89```
90> -rest ~s2
90> -rest ~s2
content/docs/arvo/clay/architecture.md+43−120
@@ -4,26 +4,25 @@ weight = 2
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−Clay is the primary filesystem for the [Arvo](/docs/arvo/overview) operating system,
7+Clay is the primary filesystem for the [Arvo](/docs/arvo/overview)
8−which is the [core](/docs/glossary/core/) of an urbit. The architecture of Clay is
8+operating system, which is the [core](/docs/glossary/core/) of an
9+urbit. The architecture of Clay is intrinsically connected with Arvo,
9−intrinsically connected with Arvo, but for this section we assume no knowledge of
10+but for this section we assume no knowledge of either Arvo or Urbit.
10−either Arvo or Urbit. We will point out only those features of
11+We will point out only those features of Arvo that are necessary for
11−Arvo that are necessary for an understanding of Clay, and we will
12−do so only when they arise.
12+an understanding of Clay, and we will do so only when they arise.
13
13
14The first relevant feature of Arvo is that it is a deterministic
14The first relevant feature of Arvo is that it is a deterministic
15−system where input and output are defined as a series of events
15+system where input and output are defined as a series of events and
16−and effects. The state of Arvo is simply a pure function of its event
16+effects. The state of Arvo is simply a pure function of its event log.
17−log. None of the effects from an event are emitted until the
17+None of the effects from an event are emitted until the event is
18−event is entered in the log and persisted, either to disk or
18+entered in the log and persisted, either to disk or another trusted
19−another trusted source of persistence, such as a Kafka cluster.
19+source of persistence, such as a Kafka cluster. Consequently, Arvo is
20−Consequently, Arvo is a single-level store: everything in its
20+a single-level store: everything in its state is persistent.
21−state is persistent.
22
21
23In a more traditional OS, everything in RAM can be erased at any
22In a more traditional OS, everything in RAM can be erased at any
24time by power failure, and is always erased on reboot. Thus, a
23time by power failure, and is always erased on reboot. Thus, a
25primary purpose of a filesystem is to ensure files persist across
24primary purpose of a filesystem is to ensure files persist across
26−power failures and reboots. In Arvo, both power failures and
25+power failures and reboots. In Arvo, both power failures and
27reboots are special cases of suspending computation, which is
26reboots are special cases of suspending computation, which is
28done safely since our event log is already persistent. Therefore,
27done safely since our event log is already persistent. Therefore,
29Clay is not needed in Arvo for persistence. Why, then, do we have a
28Clay is not needed in Arvo for persistence. Why, then, do we have a
@@ -37,7 +36,7 @@ tree. It is easy and intuitive to read from and write to a
37filesystem tree.
36filesystem tree.
38
37
39Second, Clay has a distributed revision-control system baked into
38Second, Clay has a distributed revision-control system baked into
40−it. Traditional filesystems are not revision controlled, so
39+it. Traditional filesystems are not revision controlled, so
41userspace software -- such as git -- is written on top of them to
40userspace software -- such as git -- is written on top of them to
42do so. Clay natively provides the same functionality as modern
41do so. Clay natively provides the same functionality as modern
43DVCSes, and more.
42DVCSes, and more.
@@ -47,25 +46,25 @@ it supports typed data and is referentially transparent.
47
46
48### Revision Control
47### Revision Control
49
48
50−Every urbit has one or more `desk`s, which are independently
49+Every urbit has one or more desks, which are independently
51−revision-controlled branches. Each `desk` contains its own `mark`
50+revision-controlled branches. Each desk contains its own `mark`
52definitions, apps, and so forth.
51definitions, apps, and so forth.
53
52
54−Traditionally, an urbit has at least a `%home` `desk` and `%kids` `desk`. The
53+Traditionally, an Urbit ship has at least a `%base` desk, and usually
55−`%home` `desk` has all the system software from the distribution, along with your
54+`%garden` and `%landscape` desks. The `%base` desk has the kernel and
56−personal files. The `%home` `desk` is a fork of the `%kids` desk of whichever ship
55+base system software. The `%garden` desk has software pertaining to
56+the home screen. The `%landscape` desk contains software for the
57+Groups app. The `%base` desk is a fork of the `%base` desk of
57−you download [OTAs](/docs/glossary/ota-updates) from - typically your sponsor,
58+whichever ship you download system updates from - typically your
58−but theoretically may be any ship. You will also find references to a `%base`
59+sponsor, but theoretically may be any ship.
59−`desk` - which is not a real `desk`, rather it just a hash associated to the
60−`desk` from which your `%home` `desk` was forked.
61
60
62−A `desk` is a series of numbered commits, the most recent of which
61+A desk is a series of numbered commits, the most recent of which
63−represents the current state of the `desk`. A commit is composed of
62+represents the current state of the desk. A commit is composed of
64(1) an absolute time when it was created, (2) a list of zero or
63(1) an absolute time when it was created, (2) a list of zero or
65more parents, and (3) a map from paths to data.
64more parents, and (3) a map from paths to data.
66
65
67Most commits have exactly one parent, but the initial commit on a
66Most commits have exactly one parent, but the initial commit on a
68−`desk` may have zero parents, and merge commits have more than one
67+desk may have zero parents, and merge commits have more than one
69parent.
68parent.
70
69
71The non-metadata is stored as a `map` of `path`s to data. It's
70The non-metadata is stored as a `map` of `path`s to data. It's
@@ -88,10 +87,10 @@ only on the data within and not on whether or not it's stored
88directly, so we may on occasion rearrange the contents of the
87directly, so we may on occasion rearrange the contents of the
89blob store for performance reasons.
88blob store for performance reasons.
90
89
91−Recall that a `desk` is a series of numbered commits. Not every
90+Recall that a desk is a series of numbered commits. Not every
92−commit in a `desk` must be numbered. For example, if the base `desk`
91+commit in a desk must be numbered. For example, if the `%base` desk
93−has had 50 commits since home was forked from it, then a merge
92+has had 50 commits since `%foo` was forked from it, then a merge
94−from base to home will only add a single revision number to home,
93+from `%base` to `%foo` will only add a single revision number to home,
95although the full commit history will be accessible by traversing
94although the full commit history will be accessible by traversing
96the parentage of the individual commits.
95the parentage of the individual commits.
97
96
@@ -101,25 +100,25 @@ the topmost commit is always numbered, and every numbered commit
101is an ancestor of every later numbered commit.
100is an ancestor of every later numbered commit.
102
101
103There are three ways to refer to particular commits in the
102There are three ways to refer to particular commits in the
104−revision history. Firstly, one can use the revision number.
103+revision history. Firstly, one can use the revision number.
105Secondly, one can use any absolute time between the one numbered
104Secondly, one can use any absolute time between the one numbered
106commit and the next (inclusive of the first, exclusive of the
105commit and the next (inclusive of the first, exclusive of the
107−second). Thirdly, every `desk` has a `map` of labels to revision
106+second). Thirdly, every desk has a `map` of labels to revision
108numbers. These labels may be used to refer to specific commits.
107numbers. These labels may be used to refer to specific commits.
109
108
110Additionally, Clay is a global filesystem, so data on other urbits
109Additionally, Clay is a global filesystem, so data on other urbits
111−is easily accessible the same way as data on our local urbit. In
110+is easily accessible the same way as data on our local urbit. In
112−general, the path to a particular revision of a `desk` is
111+general, the path to a particular revision of a desk is
113−`/~urbit-name/desk-name/revision`. Thus, to get `/try/readme/md`
112+`/~urbit-name/desk-name/revision`. Thus, to get `/try/readme/md`
114−from revision 5 of the home `desk` on `~sampel-sipnym`, we refer to
113+from revision 5 of the `%base` desk on `~sampel-sipnym`, we refer to
115−`/~sampel-sipnym/home/5/try/readme/md`. Clay's namespace is thus
114+`/~sampel-sipnym/base/5/try/readme/md`. Clay's namespace is thus
116global and referentially transparent.
115global and referentially transparent.
117
116
118### A Typed Filesystem
117### A Typed Filesystem
119
118
120Since Clay is a general filesystem for storing data of arbitrary
119Since Clay is a general filesystem for storing data of arbitrary
121types, in order to revision control correctly it needs to be
120types, in order to revision control correctly it needs to be
122−aware of types all the way through. Traditional revision control
121+aware of types all the way through. Traditional revision control
123does an excellent job of handling source code, so for source code
122does an excellent job of handling source code, so for source code
124we act very similar to traditional revision control. The
123we act very similar to traditional revision control. The
125challenge is to handle other data similarly well.
124challenge is to handle other data similarly well.
@@ -145,7 +144,7 @@ branches and merged at will.
145Suppose Alice is tasked with touching up a picture, improving the
144Suppose Alice is tasked with touching up a picture, improving the
146color balance, adjusting the contrast, and so forth, while Bob
145color balance, adjusting the contrast, and so forth, while Bob
147has the job of cropping the picture to fit where it's needed and
146has the job of cropping the picture to fit where it's needed and
148−adding textual overlay. Without type-aware revision control,
147+adding textual overlay. Without type-aware revision control,
149these changes must be made serially, requiring Alice and Bob to
148these changes must be made serially, requiring Alice and Bob to
150explicitly coordinate their efforts. With type-aware revision
149explicitly coordinate their efforts. With type-aware revision
151control, these operations may be performed in parallel, and then
150control, these operations may be performed in parallel, and then
@@ -168,87 +167,11 @@ different sentences may be flagged as a conflict. In general,
168prose should be diffed by sentence, not by line.
167prose should be diffed by sentence, not by line.
169
168
170As far as we are aware, Clay is the first generalized,
169As far as we are aware, Clay is the first generalized,
171−type-aware revision control system. We'll go into the workings
170+type-aware revision control system. We'll go into the workings
172of this system in some detail.
171of this system in some detail.
173
172
174### Marks
173### Marks
175
174
176−Central to a typed filesystem is the idea of types. In Clay, we
175+Central to a typed filesystem is the idea of file types. In Clay, we
177−call these `mark`s. A `mark` is a file that defines a type,
176+call these `mark`s. See the [Marks](/docs/arvo/clay/marks/marks)
178−conversion routines to and from the `mark`, and diff, patch, and
177+section for more details.
179−merge routines.
180−
181−For example, a `%txt` mark may be a list of lines of text, and it
182−may include conversions to `%mime` to allow it to be serialized
183−and sent to a browser or to the Unix filesystem. It will also
184−include Hunt-McIlroy diff, patch, and merge algorithms.
185−
186−A `%json` `mark` would be defined as a JSON object in the code, and
187−it would have a parser to convert from `%txt` and a printer to
188−convert back to `%txt`. The diff, patch, and merge algorithms are
189−fairly straightforward for JSON, though they're very different
190−from the text ones.
191−
192−More formally, a `mark` is a core with three [arms](/docs/glossary/arm/): `+grab`,
193−`+grow`, and `+grad`. In `+grab` is a series of functions to
194−convert from other `mark`s to the given `mark`. In `+grow` is a
195−series of functions to convert from the given `mark` to other
196−`mark`s. In `+grad` is `+diff`, `+pact`, `+join`, and `+mash`, and
197−`+form`.
198−
199−The types are as follows, in an informal pseudocode:
200−
201−```
202− ++ grab:
203− ++ mime: <mime> -> <mark-type>
204− ++ txt: <txt> -> <mark-type>
205− ...
206− ++ grow:
207− ++ mime: <mark-type> -> <mime>
208− ++ txt: <mark-type> -> <txt>
209− ...
210− ++ grad
211− ++ form: <mark-type>
212− ++ diff: (<mark-type>, <mark-type>) -> <diff-type>
213− ++ pact: (<mark-type>, <diff-type>) -> <mark-type>
214− ++ join: (<diff-type>, <diff-type>) -> <diff-type> or NULL
215− ++ mash: (<diff-type>, <diff-type>) -> <diff-type>
216−```
217−
218−These types are basically what you would expect. Not every `mark`
219−has each of these functions defined -- all of them are optional
220−in the general case.
221−
222−In general, for a particular `mark`, the `+grab` and `+grow` entries
223−(if they exist) should be inverses of each other.
224−
225−In `+grad`, `+diff` takes two instances of a `mark` and produces a diff of them
226−whose `mark` is given by `+form`. `+pact` takes an instance of a `mark` and
227−patches it with the given diff. `+join` takes two diffs and attempts to merge
228−them into a single diff. If there are conflicts, it produces null. `+mash` takes
229−two diffs and forces a merge, annotating any conflicts.
230−
231−In general, if `+diff` called with A and B produces diff D, then
232−`+pact` called with A and D should produce B. Also, if `+join`
233−of two diffs does not produce null, then `+mash` of the same
234−diffs should produce the same result.
235−
236−Alternately, instead of `+diff`, `+pact`, `+join`, and
237−`+mash`, a `mark` can provide the same functionality by defining
238−`+grad` to be the name of another `mark` to which we wish to
239−delegate the revision control responsibilities. Then, before
240−running any of those functions, Clay will convert to the other
241−`mark`, and convert back afterward. For example, the `%hoon` `mark`
242−is revision-controlled in the same way as `%txt`, so its `+grad`
243−is simply `++ grad %txt`. Of course, `+txt` must be defined in
244−`+grow` and `+grab` as well.
245−
246−Every file in Clay has a `mark`, and that `mark` must have a
247−fully-functioning `+grad`. `Mark`s are used for more than just
248−Clay, and other `mark`s don't need a `+grad`, but if a piece of
249−data is to be saved to Clay, we must know how to revision-control
250−it.
251−
252−Additionally, if a file is to be synced out to Unix, then it must
253−have conversion routines to and from the `%mime` `mark`.
254−
content/docs/arvo/clay/clay.md+4−1
@@ -5,7 +5,6 @@ template = "doc.html"
5aliases = ["/docs/learn/arvo/clay/"]
5aliases = ["/docs/learn/arvo/clay/"]
6+++
6+++
7
7
8−
9Our filesystem.
8Our filesystem.
10
9
11`%clay` is version-controlled, referentially-transparent, and global.
10`%clay` is version-controlled, referentially-transparent, and global.
@@ -56,3 +55,7 @@ Details of the various `task`s you can use to interact with Clay.
56[Examples](/docs/arvo/clay/examples)
55[Examples](/docs/arvo/clay/examples)
57
56
58Example usage of the various Clay `task`s.
57Example usage of the various Clay `task`s.
58+
59+[Marks](/docs/arvo/clay/marks/marks)
60+
61+Details of `mark`s as well as a guide to writing them and their usage.
content/docs/arvo/clay/data-types.md+2−9
@@ -68,7 +68,6 @@ to th pier) and `beam` is a domestic Clay directory.
68
68
69`pud` is an update that's waiting on a kernel upgrade.
69`pud` is an update that's waiting on a kernel upgrade.
70
70
71−
72#### `$room`, filesystem per domestic ship
71#### `$room`, filesystem per domestic ship
73
72
74```hoon
73```hoon
@@ -93,8 +92,7 @@ set of `desk`s on this ship, mapped to their `desk` state.
93+$ desk @tas
92+$ desk @tas
94```
93```
95
94
96−This is the name of a branch of the filesystem. The default `desk`s are `%home`
95+This is the name of a branch of the filesystem. The default `desk`s are `%base`, `%garden`, `%landscape`, `%webterm` and `%bitcoin`. Desks have
97−and `%kids`. More may be created by simply referencing them. `desk`s have
98independent histories and states, and they may be
96independent histories and states, and they may be
99[merged](/docs/arvo/clay/using#merging) into each other.
97[merged](/docs/arvo/clay/using#merging) into each other.
100
98
@@ -167,7 +165,6 @@ Like a `rave` but with provisions to store current versions for `%next` and `%ma
167Generally used when we store a request in our state somewhere. This is so that
165Generally used when we store a request in our state somewhere. This is so that
168we can determine whether new versions actually affect the path we're subscribed to.
166we can determine whether new versions actually affect the path we're subscribed to.
169
167
170−
171#### `$mood:clay`, single subscription request
168#### `$mood:clay`, single subscription request
172
169
173```hoon
170```hoon
@@ -194,7 +191,6 @@ any of its children.
194 +$ care ?(%a %b %c %d %e %f %p %r %s %t %u %v %w %x %y %z) :: clay submode
191 +$ care ?(%a %b %c %d %e %f %p %r %s %t %u %v %w %x %y %z) :: clay submode
195```
192```
196
193
197−
198This specifies what type of information is requested in a subscription
194This specifies what type of information is requested in a subscription
199or a scry.
195or a scry.
200
196
@@ -258,7 +254,6 @@ contents while `q.fil` is the data itself.
258this is empty. The keys are the names of the children and the values
254this is empty. The keys are the names of the children and the values
259are, recursively, the nodes themselves.
255are, recursively, the nodes themselves.
260
256
261−
262### `$arch`, shallow filesystem node
257### `$arch`, shallow filesystem node
263
258
264```hoon
259```hoon
@@ -275,6 +270,7 @@ those directories.
275The child directories are given by a `map` to null rather than a `set` so that the
270The child directories are given by a `map` to null rather than a `set` so that the
276ordering of the `map` will be the same as it is for an `axal`, allowing
271ordering of the `map` will be the same as it is for an `axal`, allowing
277efficient conversion for when the heavier node is needed.
272efficient conversion for when the heavier node is needed.
273+
278```hoon
274```hoon
279++ axal
275++ axal
280 |$ [item]
276 |$ [item]
@@ -400,7 +396,6 @@ is all the subscribers from our ship to the foreign `desk`.
400`regs` are `(map path rule)`, and so `per` is a `map` of read permissions by
396`regs` are `(map path rule)`, and so `per` is a `map` of read permissions by
401`path` and `pew` is a `map` of write permissions by `path`.
397`path` and `pew` is a `map` of write permissions by `path`.
402
398
403−
404#### `$rind`, foreign request manager
399#### `$rind`, foreign request manager
405
400
406```hoon
401```hoon
@@ -547,7 +542,6 @@ blob, and `r` is the delta.
547`%direct` is the case where we simply have the data directly. `q` is the data.
542`%direct` is the case where we simply have the data directly. `q` is the data.
548These almost always come from the creation of a file.
543These almost always come from the creation of a file.
549
544
550−
551#### `+urge`, list change
545#### `+urge`, list change
552
546
553```hoon
547```hoon
@@ -685,4 +679,3 @@ commit itself.
685revision number, whichever is smaller.
679revision number, whichever is smaller.
686
680
687`lar` is the set of new commits, and `bar` is the set of new content.
681`lar` is the set of new commits, and `bar` is the set of new content.
688−
content/docs/arvo/clay/examples.md+99−102
@@ -6,7 +6,7 @@ template = "doc.html"
6
6
7This document contains a number of examples of interacting with Clay using its various `task`s. Sections correspond to the general details in the [API Reference](/docs/arvo/clay/tasks) document.
7This document contains a number of examples of interacting with Clay using its various `task`s. Sections correspond to the general details in the [API Reference](/docs/arvo/clay/tasks) document.
8
8
9−Most examples will either use `|pass` to just send a `task` or the following thread to send a `task` and take the resulting `gift`. You can save the following thread to the `ted` directory of your `%home` `desk`:
9+Most examples will either use `|pass` to just send a `task` or the following thread to send a `task` and take the resulting `gift`. You can save the following thread to the `ted` directory of the `%base` `desk` on a fake ship:
10
10
11`send-task-take-gift.hoon`
11`send-task-take-gift.hoon`
12
12
@@ -40,7 +40,7 @@ Here we'll look at reading files by passing Clay a `%warp` `task` with a `%sing`
40Using the `send-task-take-gift.hoon` thread, let's try reading `gen/hood/hi.hoon`:
40Using the `send-task-take-gift.hoon` thread, let's try reading `gen/hood/hi.hoon`:
41
41
42```
42```
43−> -send-task-take-gift [%warp our %home ~ %sing %x da+now /gen/hood/hi/hoon]
43+> -send-task-take-gift [%warp our %base ~ %sing %x da+now /gen/hood/hi/hoon]
44```
44```
45
45
46You should see something like this as the output:
46You should see something like this as the output:
@@ -49,7 +49,7 @@ You should see something like this as the output:
49[ %writ
49[ %writ
50 p
50 p
51 [ ~
51 [ ~
52− [ p=[p=%x q=[%da p=~2021.5.20..23.37.50..e79b] r=%home]
52+ [ p=[p=%x q=[%da p=~2021.5.20..23.37.50..e79b] r=%base]
53 q=/gen/hood/hi/hoon
53 q=/gen/hood/hi/hoon
54 r
54 r
55 [ p=%hoon
55 [ p=%hoon
@@ -67,11 +67,11 @@ You should see something like this as the output:
67The `cage` in the `riot` of the `%writ` contains the file's data due to our use of an `%x` `care`. It needn't be `%x` though. If we change it to `%u`, for example, we'll get a `?` `cage` instead:
67The `cage` in the `riot` of the `%writ` contains the file's data due to our use of an `%x` `care`. It needn't be `%x` though. If we change it to `%u`, for example, we'll get a `?` `cage` instead:
68
68
69```
69```
70−> -send-task-take-gift [%warp our %home ~ %sing %x da+now /gen/hood/hi/hoon]
70+> -send-task-take-gift [%warp our %base ~ %sing %x da+now /gen/hood/hi/hoon]
71[ %writ
71[ %writ
72 p
72 p
73 [ ~
73 [ ~
74− [ p=[p=%u q=[%da p=~2021.5.20..23.42.21..bb33] r=%home]
74+ [ p=[p=%u q=[%da p=~2021.5.20..23.42.21..bb33] r=%base]
75 q=/gen/hood/hi/hoon
75 q=/gen/hood/hi/hoon
76 r=[p=%flag q=[#t/?(%.y %.n) q=0]]
76 r=[p=%flag q=[#t/?(%.y %.n) q=0]]
77 ]
77 ]
@@ -90,27 +90,27 @@ Here we'll look at subscribing to the next version of a file by passing Clay a `
90Using the `send-task-take-gift.hoon` thread, let's subscribe to the next version of `foo.txt`:
90Using the `send-task-take-gift.hoon` thread, let's subscribe to the next version of `foo.txt`:
91
91
92```
92```
93−> -send-task-take-gift [%warp our %home ~ %next %x da+now /foo/txt]
93+> -send-task-take-gift [%warp our %base ~ %next %x da+now /foo/txt]
94```
94```
95
95
96−Now, in unix, create a file called `foo.txt` in the root of the `home` directory of your ship. In the dojo, hit backspace to disconnect the thread from the dojo prompt and run `|commit %home`. You should see something like:
96+Now, in unix, create a file called `foo.txt` in the root of the `base` directory of your ship. In the dojo, hit backspace to disconnect the thread from the dojo prompt and run `|commit %base`. You should see something like:
97
97
98```
98```
99−> |commit %home
99+> |commit %base
100>=
100>=
101−[%writ p=[~ [p=[p=%x q=[%ud p=3] r=%home] q=/foo/txt r=[p=%txt q=[#t/*'' q=0]]]]]
101+[%writ p=[~ [p=[p=%x q=[%ud p=3] r=%base] q=/foo/txt r=[p=%txt q=[#t/*'' q=0]]]]]
102−+ /~zod/home/3/foo/txt
102++ /~zod/base/3/foo/txt
103```
103```
104
104
105As you can see, the `riot` in the `%writ` includes a `cage` with the data of `/foo/txt` due to our use of an `%x` `care`.
105As you can see, the `riot` in the `%writ` includes a `cage` with the data of `/foo/txt` due to our use of an `%x` `care`.
106
106
107−Now run the thread again, and this time delete the file in unix and again `|commit %home` in the dojo. You should see:
107+Now run the thread again, and this time delete the file in unix and again `|commit %base` in the dojo. You should see:
108
108
109```
109```
110−> |commit %home
110+> |commit %base
111>=
111>=
112[%writ p=~]
112[%writ p=~]
113−- /~zod/home/4/foo/txt
113+- /~zod/base/4/foo/txt
114```
114```
115
115
116You can see the `riot` is just `~` due to the file being deleted.
116You can see the `riot` is just `~` due to the file being deleted.
@@ -141,7 +141,7 @@ This thread will subscribe to `/foo/txt` with an `%x` `care` and `/bar/txt` with
141 [%u /bar/txt]
141 [%u /bar/txt]
142 ==
142 ==
143;< =bowl:strand bind:m get-bowl:strandio
143;< =bowl:strand bind:m get-bowl:strandio
144−=/ =task:clay [%warp our.bowl %home ~ %mult da+now.bowl files]
144+=/ =task:clay [%warp our.bowl %base ~ %mult da+now.bowl files]
145=/ =card:agent:gall [%pass /mult %arvo %c task]
145=/ =card:agent:gall [%pass /mult %arvo %c task]
146;< ~ bind:m (send-raw-card:strandio card)
146;< ~ bind:m (send-raw-card:strandio card)
147;< response=(pair wire sign-arvo) bind:m take-sign-arvo:strandio
147;< response=(pair wire sign-arvo) bind:m take-sign-arvo:strandio
@@ -149,27 +149,27 @@ This thread will subscribe to `/foo/txt` with an `%x` `care` and `/bar/txt` with
149(pure:m !>(~))
149(pure:m !>(~))
150```
150```
151
151
152−Save the above to `ted/sub-mult.hoon`, `|commit %home` and run with `-sub-mult`. Now, create `foo.txt` and `bar.txt` in your home directory, hit backspace in the dojo to disconnect the thread and run `|commit %home`. You should see something like:
152+Save the above to `ted/sub-mult.hoon`, `|commit %base` and run with `-sub-mult`. Now, create `foo.txt` and `bar.txt` in your base directory, hit backspace in the dojo to disconnect the thread and run `|commit %base`. You should see something like:
153
153
154```
154```
155−> |commit %home
155+> |commit %base
156>=
156>=
157[%wris p=[%da p=~2021.4.27..06.07.08..5ec4] q={[p=%u q=/bar/txt] [p=%x q=/foo/txt]}]
157[%wris p=[%da p=~2021.4.27..06.07.08..5ec4] q={[p=%u q=/bar/txt] [p=%x q=/foo/txt]}]
158−+ /~zod/home/151/foo/txt
158++ /~zod/base/151/foo/txt
159−+ /~zod/home/151/bar/txt
159++ /~zod/base/151/bar/txt
160```
160```
161
161
162You'll notice that, unlike a `%writ`, the `%wris` doesn't give you the data. It merely tells you the `care`s and `path`s of the files that changed. If you need to actually get the data, you can just scry or send a request for the files in question.
162You'll notice that, unlike a `%writ`, the `%wris` doesn't give you the data. It merely tells you the `care`s and `path`s of the files that changed. If you need to actually get the data, you can just scry or send a request for the files in question.
163
163
164−Now, run the thread again, open `bar.txt` in an editor, modify its contents, save it and `|commit %home`. You'll notice you didn't receive a `%wris`. This is because we subscribed to `/bar/txt` with `%u` care and its existence didn't change.
164+Now, run the thread again, open `bar.txt` in an editor, modify its contents, save it and `|commit %base`. You'll notice you didn't receive a `%wris`. This is because we subscribed to `/bar/txt` with `%u` care and its existence didn't change.
165
165
166−Lastly, delete `foo.txt` and `|commit %home`. You should see something like:
166+Lastly, delete `foo.txt` and `|commit %base`. You should see something like:
167
167
168```
168```
169−> |commit %home
169+> |commit %base
170>=
170>=
171[%wris p=[%da p=~2021.4.27..06.15.03..0da4] q={[p=%x q=/foo/txt]}]
171[%wris p=[%da p=~2021.4.27..06.15.03..0da4] q={[p=%x q=/foo/txt]}]
172−- /~zod/home/153/foo/txt
172+- /~zod/base/153/foo/txt
173```
173```
174
174
175As you can see, a relevant change to any of the subscribed files will trigger a response, not just when all of them change.
175As you can see, a relevant change to any of the subscribed files will trigger a response, not just when all of them change.
@@ -182,7 +182,7 @@ Here's a breakdown of the `task` we sent:
182
182
183Here we'll look at subscribing to a range of changes to a `desk` by passing Clay a `%warp` `task` with a `%many` `rave` and receiving `%writ` `gift`s when changes occur.
183Here we'll look at subscribing to a range of changes to a `desk` by passing Clay a `%warp` `task` with a `%many` `rave` and receiving `%writ` `gift`s when changes occur.
184
184
185−This thread will subscribe to changes to your `%home` `desk` for the next three minutes. The `track` is `%.y` so it will only inform you of changes, not send the full `nako`. It will only get updates if the specified file exists. It contains a `main-loop` that will take an arbitrary number of `sign`s and print them out in the dojo. Since it never ends, you'll need to stop it with the `:spider|kill` command in the dojo.
185+This thread will subscribe to changes to your `%base` `desk` for the next three minutes. The `track` is `%.y` so it will only inform you of changes, not send the full `nako`. It will only get updates if the specified file exists. It contains a `main-loop` that will take an arbitrary number of `sign`s and print them out in the dojo. Since it never ends, you'll need to stop it with the `:spider|kill` command in the dojo.
186
186
187`sub-many.hoon`
187`sub-many.hoon`
188
188
@@ -213,30 +213,30 @@ This thread will subscribe to changes to your `%home` `desk` for the next three
213 (strand-fail:strand %no-arg ~)
213 (strand-fail:strand %no-arg ~)
214=/ =path u.uarg
214=/ =path u.uarg
215;< =bowl:strand bind:m get-bowl:strandio
215;< =bowl:strand bind:m get-bowl:strandio
216−=/ =task:clay [%warp our.bowl %home ~ %many %.y da+now.bowl da+(add ~m3 now.bowl) path]
216+=/ =task:clay [%warp our.bowl %base ~ %many %.y da+now.bowl da+(add ~m3 now.bowl) path]
217=/ =card:agent:gall [%pass /many %arvo %c task]
217=/ =card:agent:gall [%pass /many %arvo %c task]
218;< ~ bind:m (send-raw-card:strandio card)
218;< ~ bind:m (send-raw-card:strandio card)
219;< ~ bind:m take-sign-loop
219;< ~ bind:m take-sign-loop
220(pure:m !>(~))
220(pure:m !>(~))
221```
221```
222
222
223−Make sure `foo.txt` doesn't exist in the root of your `%home` `desk`. Save this to `ted/sub-many.hoon`, `|commit %home`, run it like `-sub-many /foo/txt`, and hit backspace in the dojo to free up the dojo prompt. Now, add a file called `bar.txt` to your `desk` and `|commit %home`. You should see something like:
223+Make sure `foo.txt` doesn't exist in the root of your `%base` `desk`. Save this to `ted/sub-many.hoon`, `|commit %base`, run it like `-sub-many /foo/txt`, and hit backspace in the dojo to free up the dojo prompt. Now, add a file called `bar.txt` to your `desk` and `|commit %base`. You should see something like:
224
224
225```
225```
226−> |commit %home
226+> |commit %base
227>=
227>=
228−+ /~zod/home/260/bar/txt
228++ /~zod/base/260/bar/txt
229```
229```
230
230
231−Notice you've received no `%writ` from Clay. This is because `/foo/txt` doesn't exist. Now, create `foo.txt` and `|commit %home` again. You should see:
231+Notice you've received no `%writ` from Clay. This is because `/foo/txt` doesn't exist. Now, create `foo.txt` and `|commit %base` again. You should see:
232
232
233```
233```
234−> |commit %home
234+> |commit %base
235>=
235>=
236[ p=/many
236[ p=/many
237− q=[%clay [%writ p=[~ [p=[p=%w q=[%ud p=261] r=%home] q=/ r=[p=%null q=[#t/@n q=0]]]]]]
237+ q=[%clay [%writ p=[~ [p=[p=%w q=[%ud p=261] r=%base] q=/ r=[p=%null q=[#t/@n q=0]]]]]]
238]
238]
239−+ /~zod/home/261/foo/txt
239++ /~zod/base/261/foo/txt
240```
240```
241
241
242Now that `/foo/txt` exists it will inform you of updates. Note that if you delete `/foo/txt` again it will again stop sending updates.
242Now that `/foo/txt` exists it will inform you of updates. Note that if you delete `/foo/txt` again it will again stop sending updates.
@@ -244,24 +244,24 @@ Now that `/foo/txt` exists it will inform you of updates. Note that if you delet
244Now try adding `baz.txt`:
244Now try adding `baz.txt`:
245
245
246```
246```
247−> |commit %home
247+> |commit %base
248>=
248>=
249[ p=/many
249[ p=/many
250− q=[%clay [%writ p=[~ [p=[p=%w q=[%ud p=262] r=%home] q=/ r=[p=%null q=[#t/@n q=0]]]]]]
250+ q=[%clay [%writ p=[~ [p=[p=%w q=[%ud p=262] r=%base] q=/ r=[p=%null q=[#t/@n q=0]]]]]]
251]
251]
252−+ /~zod/home/262/baz/txt
252++ /~zod/base/262/baz/txt
253```
253```
254
254
255Now wait until the three minutes is up and try making a change, for example deleting `baz.txt`:
255Now wait until the three minutes is up and try making a change, for example deleting `baz.txt`:
256
256
257```
257```
258−> |commit %home
258+> |commit %base
259>=
259>=
260[ p=/many
260[ p=/many
261− q=[%clay [%writ p=[~ [p=[p=%w q=[%ud p=264] r=%home] q=/ r=[p=%null q=[#t/@n q=0]]]]]]
261+ q=[%clay [%writ p=[~ [p=[p=%w q=[%ud p=264] r=%base] q=/ r=[p=%null q=[#t/@n q=0]]]]]]
262]
262]
263[p=/many q=[%clay [%writ p=~]]]
263[p=/many q=[%clay [%writ p=~]]]
264−- /~zod/home/263/baz/txt
264+- /~zod/base/263/baz/txt
265```
265```
266
266
267You can see that along with the normal `%writ` it's also sent a second `%writ` with a null `riot` to indicate the subscription has ended. This is because it has now passed the end of the range of `case`s to which you subscribed.
267You can see that along with the normal `%writ` it's also sent a second `%writ` with a null `riot` to indicate the subscription has ended. This is because it has now passed the end of the range of `case`s to which you subscribed.
@@ -289,10 +289,10 @@ This thread will subscribe to the `%next` version of `/foo/txt`, then immediatel
289=/ m (strand ,vase)
289=/ m (strand ,vase)
290^- form:m
290^- form:m
291;< =bowl:strand bind:m get-bowl:strandio
291;< =bowl:strand bind:m get-bowl:strandio
292−=/ =task:clay [%warp our.bowl %home ~ %next %x da+now.bowl /foo/txt]
292+=/ =task:clay [%warp our.bowl %base ~ %next %x da+now.bowl /foo/txt]
293=/ =card:agent:gall [%pass /next %arvo %c task]
293=/ =card:agent:gall [%pass /next %arvo %c task]
294;< ~ bind:m (send-raw-card:strandio card)
294;< ~ bind:m (send-raw-card:strandio card)
295−=. task [%warp our.bowl %home ~]
295+=. task [%warp our.bowl %base ~]
296=. card [%pass /next %arvo %c task]
296=. card [%pass /next %arvo %c task]
297;< ~ bind:m (send-raw-card:strandio card)
297;< ~ bind:m (send-raw-card:strandio card)
298;< =riot:clay bind:m (take-writ:strandio /next)
298;< =riot:clay bind:m (take-writ:strandio /next)
@@ -300,12 +300,12 @@ This thread will subscribe to the `%next` version of `/foo/txt`, then immediatel
300(pure:m !>(~))
300(pure:m !>(~))
301```
301```
302
302
303−Save the above to `ted/stop-sub.hoon`, `|commit %home`, run it with `-stop-sub` and hit backspace to detach it from the dojo prompt. Now, add `foo.txt` to the root of your `%home` `desk` and `|commit %home`. You should see:
303+Save the above to `ted/stop-sub.hoon`, `|commit %base`, run it with `-stop-sub` and hit backspace to detach it from the dojo prompt. Now, add `foo.txt` to the root of your `%base` `desk` and `|commit %base`. You should see:
304
304
305```
305```
306−> |commit %home
306+> |commit %base
307>=
307>=
308−+ /~zod/home/266/foo/txt
308++ /~zod/base/266/foo/txt
309```
309```
310
310
311As you can see we've received no `%writ`. We can thus conclude the subscription has successfully been cancelled.
311As you can see we've received no `%writ`. We can thus conclude the subscription has successfully been cancelled.
@@ -327,11 +327,11 @@ Here we'll look at adding a file by sending Clay a `%info` `task` containing a `
327Let's try adding a `foo.txt` file with 'foo' as its contents:
327Let's try adding a `foo.txt` file with 'foo' as its contents:
328
328
329```
329```
330−> |pass [%c [%info %home %& [/foo/txt %ins %txt !>(~['foo'])]~]]
330+> |pass [%c [%info %base %& [/foo/txt %ins %txt !>(~['foo'])]~]]
331−+ /~zod/home/5/foo/txt
331++ /~zod/base/5/foo/txt
332```
332```
333
333
334−If you have a look in the home of your pier you'll see there's now a file called `foo.txt` with the text `foo` in it.
334+If you have a look in the base of your pier you'll see there's now a file called `foo.txt` with the text `foo` in it.
335
335
336We've created the `cage` of the content like `[%txt !>(~['foo'])]`, if you want to write something besides a text file you'd just give it the appropriate `mark` and `vase`.
336We've created the `cage` of the content like `[%txt !>(~['foo'])]`, if you want to write something besides a text file you'd just give it the appropriate `mark` and `vase`.
337
337
@@ -346,11 +346,11 @@ Here we'll look at deleting a file by sending Clay a `%info` `task` containing a
346Let's try deleting the `foo.txt` file created in the [previous example](#ins):
346Let's try deleting the `foo.txt` file created in the [previous example](#ins):
347
347
348```
348```
349−> |pass [%c [%info %home %& [/foo/txt %del ~]~]]
349+> |pass [%c [%info %base %& [/foo/txt %del ~]~]]
350−- /~zod/home/6/foo/txt
350+- /~zod/base/6/foo/txt
351```
351```
352
352
353−If you have a look in the home of your pier you'll see the `foo.txt` file is now gone.
353+If you have a look in the base of your pier you'll see the `foo.txt` file is now gone.
354
354
355Here's a breakdown of the `task` we sent:
355Here's a breakdown of the `task` we sent:
356
356
@@ -384,21 +384,21 @@ Since `soba` is just a `list` of `miso`, you can add a bunch of `miso` and they'
384 [/bar/txt %del ~]
384 [/bar/txt %del ~]
385 [/baz/txt %del ~]
385 [/baz/txt %del ~]
386 ==
386 ==
387−;< ~ bind:m (send-raw-card:strandio [%pass /info %arvo %c %info %home %& soba-a])
387+;< ~ bind:m (send-raw-card:strandio [%pass /info %arvo %c %info %base %& soba-a])
388−;< ~ bind:m (send-raw-card:strandio [%pass /info %arvo %c %info %home %& soba-b])
388+;< ~ bind:m (send-raw-card:strandio [%pass /info %arvo %c %info %base %& soba-b])
389(pure:m !>(~))
389(pure:m !>(~))
390```
390```
391
391
392−Save to `ted/multi-change.hoon`, `|commit %home`, and run:
392+Save to `ted/multi-change.hoon`, `|commit %base`, and run:
393
393
394```
394```
395> -multi-change
395> -multi-change
396−+ /~zod/home/37/foo/txt
396++ /~zod/base/37/foo/txt
397−+ /~zod/home/37/bar/txt
397++ /~zod/base/37/bar/txt
398−+ /~zod/home/37/baz/txt
398++ /~zod/base/37/baz/txt
399−- /~zod/home/38/foo/txt
399+- /~zod/base/38/foo/txt
400−- /~zod/home/38/bar/txt
400+- /~zod/base/38/bar/txt
401−- /~zod/home/38/baz/txt
401+- /~zod/base/38/baz/txt
402```
402```
403
403
404## Manage Mounts
404## Manage Mounts
@@ -413,44 +413,41 @@ Using the `send-task-take-gift.hoon` thread, let's make such a request:
413
413
414```
414```
415> -send-task-take-gift [%boat ~]
415> -send-task-take-gift [%boat ~]
416−[%hill p=~[%home]]
416+[%hill p=~[%base]]
417```
417```
418
418
419### `%mont`
419### `%mont`
420
420
421Here we'll look at mounting `desk`s, directories and files to unix by sending Clay a `%mont` `task`.
421Here we'll look at mounting `desk`s, directories and files to unix by sending Clay a `%mont` `task`.
422
422
423−Let's first try mounting our `%kids` desk:
423+Let's first try mounting our `%garden` desk:
424
424
425```
425```
426−> |pass [%c [%mont %kids [our %kids da+now] /]]
426+> |pass [%c [%mont %garden [our %garden da+now] /]]
427```
427```
428
428
429−If you look in your pier, you should now see a `kids` folder which contains the contents of that `desk`.
429+If you look in your pier, you should now see a `garden` folder which contains the contents of that `desk`.
430
430
431If we make a `%boat` request as detailed in the [%boat](#boat) section, we'll now see the mount point listed:
431If we make a `%boat` request as detailed in the [%boat](#boat) section, we'll now see the mount point listed:
432
432
433```
433```
434> -send-task-take-gift [%boat ~]
434> -send-task-take-gift [%boat ~]
435−[%hill p=~[%kids %home]]cruz gift. It looks like:
435+[%hill p=~[%garden %base]]
436−
437−[%cruz cez=(map @ta crew)] :: permission groups
438−The cez is just a map from group name to crew
439```
436```
440
437
441Note the mount point doesn't need to match a `desk`, file or directory. We can also do:
438Note the mount point doesn't need to match a `desk`, file or directory. We can also do:
442
439
443```
440```
444−> |pass [%c [%mont %wibbly-wobbly [our %home da+now] /]]
441+> |pass [%c [%mont %wibbly-wobbly [our %base da+now] /]]
445```
442```
446
443
447−And you'll now see that there's a `wibbly-wobbly` folder with the contents of the `%home` `desk`. You'll also notice we can mount the same file or directory more than once. There's no problem having `%home` mounted to both `home` and `wibbly-wobbly`. The only requirement is that their mount points be unique.
444+And you'll now see that there's a `wibbly-wobbly` folder with the contents of the `%base` `desk`. You'll also notice we can mount the same file or directory more than once. There's no problem having `%base` mounted to both `base` and `wibbly-wobbly`. The only requirement is that their mount points be unique.
448
445
449Let's try mounting a subdirectory and a single folder:
446Let's try mounting a subdirectory and a single folder:
450
447
451```
448```
452−> |pass [%c [%mont %gen [our %home da+now] /gen]]
449+> |pass [%c [%mont %gen [our %base da+now] /gen]]
453−> |pass [%c [%mont %hi [our %home da+now] /gen/hood/hi]]
450+> |pass [%c [%mont %hi [our %base da+now] /gen/hood/hi]]
454```
451```
455
452
456If you look in your pier you'll now see a `gen` folder with the contents of `/gen` and a `hi.hoon` file by itself. Notice how the file extension has been automatically added.
453If you look in your pier you'll now see a `gen` folder with the contents of `/gen` and a `hi.hoon` file by itself. Notice how the file extension has been automatically added.
@@ -459,10 +456,10 @@ If you look in your pier you'll now see a `gen` folder with the contents of `/ge
459
456
460Here we'll look at unmounting `desk`s, directories and files by sending Clay a `%ogre` `task`.
457Here we'll look at unmounting `desk`s, directories and files by sending Clay a `%ogre` `task`.
461
458
462−Let's unmount what we mounted in the [%mont](#mont) section. First we'll unmount the `%kids` desk:
459+Let's unmount what we mounted in the [%mont](#mont) section. First we'll unmount the `%garden` desk:
463
460
464```
461```
465−|pass [%c [%ogre %kids]]
462+|pass [%c [%ogre %garden]]
466```
463```
467
464
468Our custom mount point `%wibbly-wobbly`:
465Our custom mount point `%wibbly-wobbly`:
@@ -480,8 +477,8 @@ And the single `hi.hoon` we previously mounted by specifying its mount point `%h
480If we specify a non-existent mount point it will fail with an error printed to the dojo like:
477If we specify a non-existent mount point it will fail with an error printed to the dojo like:
481
478
482```
479```
483−> |pass [%c [%ogre %kids]]
480+> |pass [%c [%ogre %foo]]
484−[%not-mounted %kids]
481+[%not-mounted %foo]
485```
482```
486
483
487If we give it an unmounted `beam` it will not print an error but still won't work.
484If we give it an unmounted `beam` it will not print an error but still won't work.
@@ -492,11 +489,11 @@ Here we'll look at committing changed files by sending Clay a `%dirk` `task`.
492
489
493This `task` performs the same function as the `|commit` dojo command.
490This `task` performs the same function as the `|commit` dojo command.
494
491
495−With your `%home` `desk` mounted, try adding a file and send a `%dirk` to commit the change:
492+With your `%base` `desk` mounted, try adding a file and send a `%dirk` to commit the change:
496
493
497```
494```
498−> |pass [%c [%dirk %home]]
495+> |pass [%c [%dirk %base]]
499−+ /~zod/home/12/foo/txt
496++ /~zod/base/12/foo/txt
500```
497```
501
498
502Clay will print the changed files to the dojo with a leading `+`, `-` or `:` to indicate a new file, deleted file and changed file respectively.
499Clay will print the changed files to the dojo with a leading `+`, `-` or `:` to indicate a new file, deleted file and changed file respectively.
@@ -514,7 +511,7 @@ Here we'll look at merging `desk`s by sending Clay a `%merg` `task` and receivin
514First, using the `send-task-take-gift.hoon` thread, let's try creating a new `desk`:
511First, using the `send-task-take-gift.hoon` thread, let's try creating a new `desk`:
515
512
516```
513```
517−> -send-task-take-gift [%merg %foo our %home da+now %init]
514+> -send-task-take-gift [%merg %foo our %base da+now %init]
518[%mere p=[%.y p={}]]
515[%mere p=[%.y p={}]]
519```
516```
520
517
@@ -522,15 +519,15 @@ Now if we scry for our `desk`s we'll see `%foo` is there:
522
519
523```
520```
524> .^((set desk) %cd /===)
521> .^((set desk) %cd /===)
525−{%home %foo %kids}
522+{%bitcoin %base %landscape %webterm %garden %foo}
526```
523```
527
524
528Next, we'll create a merge conflict and try a couple of things. Mount `%foo` with `|mount /=foo=`, then add a `foo.txt` to both `desk`s but with different text in each and `|commit` them.
525Next, we'll create a merge conflict and try a couple of things. Mount `%foo` with `|mount /=foo=`, then add a `foo.txt` to both `desk`s but with different text in each and `|commit` them.
529
526
530−Now we'll try merging `%home` into `%foo` with a `%mate` strategy:
527+Now we'll try merging `%base` into `%foo` with a `%mate` strategy:
531
528
532```
529```
533−> -send-task-take-gift [%merg %foo our %home da+now %mate]
530+> -send-task-take-gift [%merg %foo our %base da+now %mate]
534[ /foo
531[ /foo
535 [ %clay
532 [ %clay
536 [ %mere
533 [ %mere
@@ -549,14 +546,14 @@ Now we'll try merging `%home` into `%foo` with a `%mate` strategy:
549As you can see, the merge has failed. Let's try again with a `%meld` strategy:
546As you can see, the merge has failed. Let's try again with a `%meld` strategy:
550
547
551```
548```
552−> -send-task-take-gift [%merg %foo our %home da+now %meld]
549+> -send-task-take-gift [%merg %foo our %base da+now %meld]
553[/foo [%clay [%mere p=[%.y p={/foo/txt}]]]]
550[/foo [%clay [%mere p=[%.y p={/foo/txt}]]]]
554```
551```
555
552
556Now the merge has succeeded and the `%mere` notes the file with a merge conflict. If we try with a `%only-that` strategy:
553Now the merge has succeeded and the `%mere` notes the file with a merge conflict. If we try with a `%only-that` strategy:
557
554
558```
555```
559−> -send-task-take-gift [%merg %foo our %home da+now %only-that]
556+> -send-task-take-gift [%merg %foo our %base da+now %only-that]
560[/foo [%clay [%mere p=[%.y p={}]]]]
557[/foo [%clay [%mere p=[%.y p={}]]]]
561: /~zod/foo/6/foo/txt
558: /~zod/foo/6/foo/txt
562```
559```
@@ -566,10 +563,10 @@ Now the merge has succeeded and the `%mere` notes the file with a merge conflict
566Next, let's look at subscribing for future changes. Since the `case` is specified explicitly in the `%merge` `task`, we can set it in the future:
563Next, let's look at subscribing for future changes. Since the `case` is specified explicitly in the `%merge` `task`, we can set it in the future:
567
564
568```
565```
569−> -send-task-take-gift [%merg %foo our %home da+(add ~m2 now) %only-that]
566+> -send-task-take-gift [%merg %foo our %base da+(add ~m2 now) %only-that]
570```
567```
571
568
572−Now change the text in the `foo.txt` in the `%home` `desk`, hit backspace to detach the thread and `|commit %home`. After the two minutes pass you should see:
569+Now change the text in the `foo.txt` in the `%base` `desk`, hit backspace to detach the thread and `|commit %base`. After the two minutes pass you should see:
573
570
574```
571```
575[/foo [%clay [%mere p=[%.y p={}]]]]
572[/foo [%clay [%mere p=[%.y p={}]]]]
@@ -589,7 +586,7 @@ Here we'll look at setting permissions by sending Clay a `%perm` `task`.
589First, let's allow `~nes` to read `/gen/hood/hi/hoon`:
586First, let's allow `~nes` to read `/gen/hood/hi/hoon`:
590
587
591```
588```
592−> |pass [%c [%perm %home /gen/hood/hi/hoon %r ~ %white (sy [%.y ~nes]~)]]
589+> |pass [%c [%perm %base /gen/hood/hi/hoon %r ~ %white (sy [%.y ~nes]~)]]
593```
590```
594
591
595...and we'll do a `%p` scry to see that the permission was set:
592...and we'll do a `%p` scry to see that the permission was set:
@@ -602,7 +599,7 @@ First, let's allow `~nes` to read `/gen/hood/hi/hoon`:
602You can see that `~nes` is now in the read whitelist. Next, let's try a write permission:
599You can see that `~nes` is now in the read whitelist. Next, let's try a write permission:
603
600
604```
601```
605−> |pass [%c [%perm %home /ted %w ~ %white (sy [%.y ~nes]~)]]
602+> |pass [%c [%perm %base /ted %w ~ %white (sy [%.y ~nes]~)]]
606```
603```
607
604
608You can see `~nes` can now write to `/ted`:
605You can see `~nes` can now write to `/ted`:
@@ -624,7 +621,7 @@ Since we've set it for the whole `/ted` directory, if we check a file inside it
624Now let's try setting both read and write permissions:
621Now let's try setting both read and write permissions:
625
622
626```
623```
627−> |pass [%c [%perm %home /gen/help/hoon %rw `[%black (sy [%.y ~nes]~)] `[%white (sy [%.y ~nes]~)]]]
624+> |pass [%c [%perm %base /gen/help/hoon %rw `[%black (sy [%.y ~nes]~)] `[%white (sy [%.y ~nes]~)]]]
628```
625```
629
626
630```
627```
@@ -637,7 +634,7 @@ Lastly, let's look at deleting a permission rule we've previously set. To do tha
637For example, to remove a read permission (or write if you specify `%w`):
634For example, to remove a read permission (or write if you specify `%w`):
638
635
639```
636```
640−> |pass [%c [%perm %home /gen/help/hoon %r ~]]
637+> |pass [%c [%perm %base /gen/help/hoon %r ~]]
641```
638```
642
639
643```
640```
@@ -648,7 +645,7 @@ For example, to remove a read permission (or write if you specify `%w`):
648...and to remove both read and write at the same time:
645...and to remove both read and write at the same time:
649
646
650```
647```
651−> |pass [%c [%perm %home /gen/help/hoon %rw ~ ~]]
648+> |pass [%c [%perm %base /gen/help/hoon %rw ~ ~]]
652```
649```
653
650
654```
651```
@@ -692,8 +689,8 @@ Here we'll look at retrieving a list of all files and directories in all `desk`s
692First we'll set a couple of permissions for the `foo` group we created in the [%cred](#cred) section:
689First we'll set a couple of permissions for the `foo` group we created in the [%cred](#cred) section:
693
690
694```
691```
695−> |pass [%c [%perm %home /gen/hood/hi/hoon %w ~ %white (sy [%.n 'foo']~)]]
692+> |pass [%c [%perm %base /gen/hood/hi/hoon %w ~ %white (sy [%.n 'foo']~)]]
696−> |pass [%c [%perm %home /ted %w ~ %white (sy [%.n 'foo']~)]]
693+> |pass [%c [%perm %base /ted %w ~ %white (sy [%.n 'foo']~)]]
697```
694```
698
695
699Notice we use a `%.n` in the `whom` to indicate a group rather than the `%.y` of a ship.
696Notice we use a `%.n` in the `whom` to indicate a group rather than the `%.y` of a ship.
@@ -704,7 +701,7 @@ Now we'll use the `send-task-take-gift.hoon` thread to try `%crow`:
704> -send-task-take-gift [%crow 'foo']
701> -send-task-take-gift [%crow 'foo']
705[ %croz
702[ %croz
706 rus
703 rus
707− { [ p=%home
704+ { [ p=%base
708 q
705 q
709 [ r={}
706 [ r={}
710 w
707 w
@@ -725,29 +722,29 @@ See the [Foreign Ships](/docs/arvo/clay/tasks#foreign-ships) section of the [API
725
722
726Here we'll look at reading files on a foreign ship by sending Clay a `%warp` `task` with a foreign ship in the `wer` field and receiving a `%writ` `gift` in response.
723Here we'll look at reading files on a foreign ship by sending Clay a `%warp` `task` with a foreign ship in the `wer` field and receiving a `%writ` `gift` in response.
727
724
728−We'll use a fake ~nes as the the foreign ship and a fake ~zod as the local ship.
725+We'll use a fake `~nes` as the the foreign ship and a fake `~zod` as the local ship.
729
726
730−First we'll set permissions on the foreign ship. Create a file called `foo.txt` in the `%home` of ~nes, then send a `%perm` request to allow ~zod to read and write the file:
727+First we'll set permissions on the foreign ship. Create a file called `foo.txt` in the `%base` of ~nes, then send a `%perm` request to allow ~zod to read and write the file:
731
728
732```
729```
733−> |pass [%c [%perm %home /foo/txt %rw `[%white (sy [%.y ~zod]~)] `[%white (sy [%.y ~zod]~)]]]
730+> |pass [%c [%perm %base /foo/txt %rw `[%white (sy [%.y ~zod]~)] `[%white (sy [%.y ~zod]~)]]]
734```
731```
735
732
736−If we scry the file for its permissions with a `%p` `care`, we'll see ~zod is now whitelisted:
733+If we scry the file for its permissions with a `%p` `care`, we'll see `~zod` is now whitelisted:
737
734
738```
735```
739> .^([r=dict:clay w=dict:clay] %cp /===/foo/txt)
736> .^([r=dict:clay w=dict:clay] %cp /===/foo/txt)
740[r=[src=/foo/txt rul=[mod=%white who=[p={~zod} q={}]]] w=[src=/foo/txt rul=[mod=%white who=[p={~zod} q={}]]]]
737[r=[src=/foo/txt rul=[mod=%white who=[p={~zod} q={}]]] w=[src=/foo/txt rul=[mod=%white who=[p={~zod} q={}]]]]
741```
738```
742
739
743−Back on ~zod: Using the `send-task-take-gift.hoon` thread, send a `%x` read request for `/foo/txt` on ~nes like:
740+Back on `~zod`: Using the `send-task-take-gift.hoon` thread, send a `%x` read request for `/foo/txt` on ~nes like:
744
741
745```
742```
746−> -send-task-take-gift [%warp ~nes %home ~ %sing %x da+now /foo/txt]
743+> -send-task-take-gift [%warp ~nes %base ~ %sing %x da+now /foo/txt]
747[ %writ
744[ %writ
748 p
745 p
749 [ ~
746 [ ~
750− [ p=[p=%x q=[%da p=~2021.5.3..08.24.22..9ce7] r=%home]
747+ [ p=[p=%x q=[%da p=~2021.5.3..08.24.22..9ce7] r=%base]
751 q=/foo/txt
748 q=/foo/txt
752 r=[p=%txt q=[#t/txt=*'' q=[7.303.014 0]]]
749 r=[p=%txt q=[#t/txt=*'' q=[7.303.014 0]]]
753 ]
750 ]
@@ -758,11 +755,11 @@ Back on ~zod: Using the `send-task-take-gift.hoon` thread, send a `%x` read requ
758As you can see, we've received a `%writ` containing the requested data just as we would with a local request. Let's try a `%u`:
755As you can see, we've received a `%writ` containing the requested data just as we would with a local request. Let's try a `%u`:
759
756
760```
757```
761−> -send-task-take-gift [%warp ~nes %home ~ %sing %u da+now /foo/txt]
758+> -send-task-take-gift [%warp ~nes %base ~ %sing %u da+now /foo/txt]
762[ %writ
759[ %writ
763 p
760 p
764 [ ~
761 [ ~
765− [ p=[p=%u q=[%da p=~2021.5.3..08.26.32..88cf] r=%home]
762+ [ p=[p=%u q=[%da p=~2021.5.3..08.26.32..88cf] r=%base]
766 q=/foo/txt
763 q=/foo/txt
767 r=[p=%flag q=[#t/?(%.y %.n) q=0]]
764 r=[p=%flag q=[#t/?(%.y %.n) q=0]]
768 ]
765 ]
@@ -773,7 +770,7 @@ As you can see, we've received a `%writ` containing the requested data just as w
773If we send a `%d` request however, it will crash:
770If we send a `%d` request however, it will crash:
774
771
775```
772```
776−> -send-task-take-gift [%warp ~nes %home ~ %sing %d da+now /foo/txt]
773+> -send-task-take-gift [%warp ~nes %base ~ %sing %d da+now /foo/txt]
777call: failed
774call: failed
778/sys/vane/clay/hoon:<[4.085 3].[4.314 5]>
775/sys/vane/clay/hoon:<[4.085 3].[4.314 5]>
779...
776...
content/docs/arvo/clay/marks/_index.mdnew file+23
@@ -0,0 +1,23 @@
1++++
2+title = "Marks"
3+weight = 10
4+sort_by = "weight"
5+template = "sections/docs/chapters.html"
6+insert_anchor_links = "right"
7++++
8+
9+[Overview](/docs/arvo/clay/marks/marks)
10+
11+Overview of `mark`s.
12+
13+[Writing Marks](/docs/arvo/clay/marks/writing-marks)
14+
15+A practical walk-through of writing a `mark` file.
16+
17+[Using Marks](/docs/arvo/clay/marks/using-marks)
18+
19+Details of using `mark` conversion gates and `mark` cores in your own code.
20+
21+[Examples](/docs/arvo/clay/marks/examples)
22+
23+The example code used in the Writing Marks guide.
content/docs/arvo/clay/marks/examples.mdnew file+248
@@ -0,0 +1,248 @@
1++++
2+title = "Examples"
3+weight = 4
4+template = "doc.html"
5++++
6+
7+These are the files used in the [Writing Marks](/docs/arvo/clay/marks/writing-marks) guide.
8+
9+## `/lib/csv/hoon`
10+
11+```hoon
12+|%
13+++ validate :: All rows same length?
14+ |= csv=(list (list @t))
15+ ^- ?
16+ =/ result
17+ %+ roll csv
18+ |= [row=(list @t) =flag ref=(unit @ud)]
19+ ?. flag
20+ [flag ref]
21+ ?~ ref
22+ [flag `(lent row)]
23+ ?. =(u.ref (lent row))
24+ [%.n ref]
25+ [flag ref]
26+ flag.result
27+++ en-csv :: csv -> atom (to mime)
28+ |= csv=(list (list @t))
29+ |^ ^- @t
30+ (cat 3 (crip (join '\0a' (turn csv en-row))) '\0a')
31+ ++ en-row :: encode row
32+ |= row=(list @t)
33+ ^- @t
34+ (crip (join ',' (turn row en-field)))
35+ ++ en-field :: encode field
36+ |= field=@t
37+ ^- @t
38+ %+ rash
39+ field
40+ %+ cook
41+ |= =tape
42+ ^- @t
43+ ?~ tape ''
44+ ?: =('"' i.tape)
45+ (cat 3 (crip tape) '"')
46+ (crip tape)
47+ ;~ pose
48+ (full (star ;~(less (mask "\",\0a\0d") next)))
49+ ;~ plug
50+ (easy '"')
51+ (star ;~(pose (cold '""' doq) next))
52+ ==
53+ ==
54+ --
55+++ de-csv :: atom -> csv (from mime)
56+ |= dat=@t
57+ |^ ^- (list (list @t))
58+ =/ parsed (parse dat)
59+ ?. (validate parsed)
60+ ~|(%mixed-col-count !!)
61+ parsed
62+ ++ parse :: parse cord
63+ |= dat=@t
64+ |^ ^- (list (list @t))
65+ %+ rash
66+ dat
67+ %+ most
68+ ;~(pose (jest '\0d\0a') (mask "\0a\0d"))
69+ (most com parse-field)
70+ ++ parse-field :: parse field from cord
71+ |^
72+ %+ cook
73+ |=(a=tape (crip a))
74+ ;~(pose unenclosed enclosed)
75+ ++ unenclosed :: unquoted field
76+ ;~ sfix
77+ (star ;~(less (mask "\",\0a\0d") next))
78+ ;~ pose
79+ ;~ plug
80+ ;~(pose (jest '\0d\0a') (mask "\0a\0d"))
81+ ;~(less next (easy ~))
82+ ==
83+ ;~(less doq (easy ~))
84+ ==
85+ ==
86+ ++ enclosed :: quoted field
87+ |^
88+ ;~ sfix
89+ (ifix [prefix suffix] content)
90+ ;~ pose
91+ ;~(simu (mask ",\0a\0d") (easy ~))
92+ ;~ plug
93+ ;~(pose (jest '\0d\0a') (mask "\0a\0d"))
94+ ;~(less next (easy ~))
95+ ==
96+ ;~(less next (easy ~))
97+ ==
98+ ==
99+ ++ content :: quoted field contents
100+ %- star
101+ ;~ pose
102+ (cold '"' (jest '""'))
103+ %+ cold '\0a'
104+ ;~(pose (jest '\0d\0a') (just '\0d'))
105+ ;~(less doq next)
106+ ==
107+ ++ prefix ;~(pose ;~(plug (star ace) doq) doq) :: quoted field prefix
108+ ++ suffix ;~(pose ;~(plug doq (star ace)) doq) :: quoted field suffix
109+ --
110+ --
111+ --
112+ --
113+++ csv-join
114+ |= [ali=(urge:clay (list @t)) bob=(urge:clay (list @t))]
115+ ^- (unit (urge:clay (list @t)))
116+ |^
117+ =. ali (clean ali)
118+ =. bob (clean bob)
119+ |- ^- (unit (urge:clay (list @t)))
120+ ?~ ali `bob
121+ ?~ bob `ali
122+ ?- -.i.ali
123+ %&
124+ ?- -.i.bob
125+ %&
126+ ?: =(p.i.ali p.i.bob)
127+ %+ bind $(ali t.ali, bob t.bob)
128+ |=(cud=(urge:clay (list @t)) [i.ali cud])
129+ ?: (gth p.i.ali p.i.bob)
130+ %+ bind $(p.i.ali (sub p.i.ali p.i.bob), bob t.bob)
131+ |=(cud=(urge:clay (list @t)) [i.bob cud])
132+ %+ bind $(ali t.ali, p.i.bob (sub p.i.bob p.i.ali))
133+ |=(cud=(urge:clay (list @t)) [i.ali cud])
134+ ::
135+ %|
136+ ?: =(p.i.ali (lent p.i.bob))
137+ %+ bind $(ali t.ali, bob t.bob)
138+ |=(cud=(urge:clay (list @t)) [i.bob cud])
139+ ?: (gth p.i.ali (lent p.i.bob))
140+ %+ bind $(p.i.ali (sub p.i.ali (lent p.i.bob)), bob t.bob)
141+ |=(cud=(urge:clay (list @t)) [i.bob cud])
142+ ~
143+ ==
144+ ::
145+ %|
146+ ?- -.i.bob
147+ %|
148+ ?. =(i.ali i.bob)
149+ ~
150+ %+ bind $(ali t.ali, bob t.bob)
151+ |=(cud=(urge:clay (list @t)) [i.ali cud])
152+ ::
153+ %&
154+ ?: =(p.i.bob (lent p.i.ali))
155+ %+ bind $(ali t.ali, bob t.bob)
156+ |=(cud=(urge:clay (list @t)) [i.ali cud])
157+ ?: (gth p.i.bob (lent p.i.ali))
158+ %+ bind $(ali t.ali, p.i.bob (sub p.i.bob (lent p.i.ali)))
159+ |=(cud=(urge:clay (list @t)) [i.ali cud])
160+ ~
161+ ==
162+ ==
163+ ++ clean :: clean
164+ |= wig=(urge:clay (list @t))
165+ ^- (urge:clay (list @t))
166+ ?~ wig ~
167+ ?~ t.wig wig
168+ ?: ?=(%& -.i.wig)
169+ ?: ?=(%& -.i.t.wig)
170+ $(wig [[%& (add p.i.wig p.i.t.wig)] t.t.wig])
171+ [i.wig $(wig t.wig)]
172+ ?: ?=(%| -.i.t.wig)
173+ $(wig [[%| (welp p.i.wig p.i.t.wig) (welp q.i.wig q.i.t.wig)] t.t.wig])
174+ [i.wig $(wig t.wig)]
175+ --
176+--
177+```
178+
179+## `/mar/csv/hoon`
180+
181+```hoon
182+/+ *csv
183+|_ csv=(list (list @t))
184+++ grab
185+ |%
186+ ++ mime |=((pair mite octs) (de-csv q.q))
187+ ++ noun
188+ |= n=*
189+ ^- (list (list @t))
190+ =/ result ((list (list @t)) n)
191+ ?> (validate result)
192+ result
193+ --
194+++ grow
195+ |%
196+ ++ mime
197+ ?> (validate csv)
198+ [/text/csv (as-octs:mimes:html (en-csv csv))]
199+ ++ noun
200+ ?> (validate csv)
201+ csv
202+ --
203+++ grad
204+ |%
205+ ++ form %csv-diff
206+ ++ diff
207+ |= bob=(list (list @t))
208+ ^- (urge:clay (list @t))
209+ ?> (validate csv)
210+ ?> (validate bob)
211+ (lusk:differ csv bob (loss:differ csv bob))
212+ ++ pact
213+ |= dif=(urge:clay (list @t))
214+ ^- (list (list @t))
215+ =/ result (lurk:differ csv dif)
216+ ?> (validate result)
217+ result
218+ ++ join
219+ |= $: ali=(urge:clay (list @t))
220+ bob=(urge:clay (list @t))
221+ ==
222+ ^- (unit (urge:clay (list @t)))
223+ (csv-join ali bob)
224+ ++ mash
225+ |= $: [ship desk (urge:clay (list @t))]
226+ [ship desk (urge:clay (list @t))]
227+ ==
228+ ^- (urge:clay (list @t))
229+ ~|(%csv-mash !!)
230+ --
231+--
232+```
233+
234+## `/mar/csv-diff/hoon`
235+
236+```hoon
237+|_ dif=(urge:clay (list @t))
238+++ grab
239+ |%
240+ ++ noun (urge:clay (list @t))
241+ --
242+++ grow
243+ |%
244+ ++ noun dif
245+ --
246+++ grad %noun
247+--
248+```
content/docs/arvo/clay/marks/marks.mdnew file+59
@@ -0,0 +1,59 @@
1++++
2+title = "Overview"
3+weight = 1
4+template = "doc.html"
5++++
6+
7+Clay is a typed filesystem, and we call these file types `mark`s. When talking about Hoon and Arvo we'll often talk of types like `@ud`, `(list @t)`, etc. A `mark` will specify such a type for its files, but it does more than just that - it also defines conversion routines to and from other `mark`s, as well as diff, patch, and merge routines.
8+
9+For example, a `%txt` `mark` defines the type of a `%txt` file as a `wain` (a `(list @t)`). It defines a conversion function to a `%mime` `mark` to allow it to be serialized and sent to a browser or to the Unix filesystem. It also includes Hunt-McIlroy diff, patch, and merge algorithms. Conversion functions will be different for different `mark`s, as will things like diff algorithms. An image file like a `%png`, for example, just replaces the old blob of data with the new one rather than implementing a complex binary diff and patch algorithm, so how these functions are implemented depends on the file type and use case.
10+
11+`mark` files are stored in the `/mar` directory. The `path` of the `%txt` `mark`, for example, is `/mar/txt/hoon`.
12+
13+A `mark` is a door (a core with a sample) with three arms: `+grab`, `+grow`, and `+grad`. The door's sample defines its type. In `+grab` is a series of functions to convert from other `mark`s to the given `mark`. In `+grow` is a series of functions to convert from the given `mark` to other `mark`s. In `+grad` is `+diff`, `+pact`, `+join`, `+mash`, and `+form`.
14+
15+Here's its basic structure in an informal pseudocode:
16+
17+```
18+|_ <mark-type>
19+++ grab:
20+ ++ noun: <noun> -> <mark-type>
21+ ++ mime: <mime> -> <mark-type>
22+ ++ txt: <txt> -> <mark-type>
23+ ...
24+++ grow:
25+ ++ noun: <mark-type> -> <noun>
26+ ++ mime: <mark-type> -> <mime>
27+ ++ txt: <mark-type> -> <txt>
28+ ...
29+++ grad
30+ ++ form: <diff-mark>
31+ ++ diff: (<mark-type>, <mark-type>) -> <diff-type>
32+ ++ pact: (<mark-type>, <diff-type>) -> <mark-type>
33+ ++ join: (<diff-type>, <diff-type>) -> <diff-type> or NULL
34+ ++ mash: (<diff-type>, <diff-type>) -> <diff-type>
35+```
36+
37+These types are basically what you would expect. In `+grab`, only a `+noun` arm is mandatory, the rest are optional. The `+grow` arm itself is optional, as are any arms within it. In `+grad`, all arms are mandatory unless revision control is delegated to another `mark`, which we'll discuss later.
38+
39+In general, for a particular `mark`, the `+grab` and `+grow` entries should be inverses of each other. They needn't be symmetrical though - you may want to be able to convert from your `mark` to `%json` but not from `%json` to your `mark`, for example.
40+
41+In `+grad`, `+diff` takes two instances of a `mark` and produces a diff of them whose `mark` is given by `+form`. `+pact` takes an instance of a `mark` and patches it with the given diff. In general, if `+diff` called with A and B produces diff D, then `+pact` called with A and D should produce B.
42+
43+`+join` takes two diffs and attempts to merge them into a single diff. If there are conflicts, it produces null. `+mash` takes two diffs and forces a merge, even if there are conflicts. How your `+mash` function force-merges conflicting diffs is up to you. The `%txt` `mark` annotates any conflicts, for example, but there may be other ways. If `+join` of two diffs does not produce null, then `+mash` of the same diffs should produce the same result. Note that `+mash` is not used by Clay in its ordinary filesystem operations, so you may wish to leave it as a dummy arm that crashes if called.
44+
45+Alternately, instead of `+form`, `+diff`, `+pact`, `+join`, and `+mash`, a `mark` can provide the same functionality by defining `+grad` to be the name of another `mark` to which we wish to delegate the revision control responsibilities. Then, before running any of those functions, Clay will convert to the other `mark`, and convert back afterward. For example, the `%hoon` `mark` is revision-controlled in the same way as `%txt`, so its `+grad` is simply `++ grad %txt`. Of course, `+txt` must be defined in `+grow` and `+grab` as well.
46+
47+We mentioned that `+noun` is the only mandatory arm in `+grab`, but there are a couple of others that, while not mandatory, are of particular interest.
48+
49+The first is a `+mime` arm for converting to and from the `%mime` `mark`. When you `|commit` a file to a `desk` mounted to Unix, Clay will receive the data as a `%mime` `mark`, and then convert it to the `mark` matching the file extension. It will perform the same operation in reverse when mounting a `desk` to Unix. For this reason, any `mark` you wish to be able to access from the Unix filesystem should have `%mime` conversion routines. In certain cases (such as the scry interface), Eyre will also need to convert your `mark` to a `%mime` in order to encode it in an HTTP response, so you may require a `+mime` arm for that reason as well.
50+
51+The second case of interest is the `+json` arm for converting to and from a `%json` `mark`. If, for example, you want to write a Gall agent to which you can subscribe through Eyre's channel system, it must produce data with a `mark` containing `%json` conversion routines. If it doesn't, Eyre will not be able to deliver the data to the subscribed HTTP client in the SSE stream.
52+
53+## Sections
54+
55+[Writing Marks](/docs/arvo/clay/marks/writing-marks) - A practical walk-through of writing a `mark` file.
56+
57+[Using Marks](/docs/arvo/clay/marks/using-marks) - Details of using `mark` conversion gates and `mark` cores in your own code.
58+
59+[Examples](/docs/arvo/clay/marks/examples) - The example code used in the Writing Marks guide.
content/docs/arvo/clay/marks/using-marks.mdnew file+240
@@ -0,0 +1,240 @@
1++++
2+title = "Using Marks"
3+weight = 3
4+template = "doc.html"
5++++
6+
7+In the last document, [Writing Marks](/docs/arvo/clay/marks/writing-marks), we walked through writing `mark` files and touched on how Clay handles them. They needn't just be left to background vane processes though, you can also use them yourself in your code.
8+
9+There are two kinds of cores that Clay can build for you: A `mark` conversion gate and a `mark` core. Each has two kinds: Statically typed and dynamically typed. Clay has a `care` for producing each of these:
10+
11+- `%b` - Build a dynamically typed `mark` core.
12+- `%c` - Build a dynamically typed `mark` conversion gate.
13+- `%e` - Build a statically typed `mark` core.
14+- `%f` - Build a statically typed `mark` conversion gate.
15+
16+You can either use these by `%pass`ing Clay a [%warp task](/docs/arvo/clay/tasks#warp) with the appropriate `care`, or else with a [Clay scry](/docs/arvo/clay/scry). In the examples here we've used the latter.
17+
18+## mark conversion gates
19+
20+`mark` conversion gates simply convert from one `mark` to another.
21+
22+### Static
23+
24+A static `mark` conversion gate looks like `$-(a b)`, where `a` is the type of the `mark` you're converting _from_, and `b` is type of the `mark` you're converting _to_. For example, a `mark` conversion gate from `%txt` to `%mime` would look like `$-(wain mime)`. You'd simply feed it a `wain` and get a `$mime` in return.
25+
26+#### Example
27+
28+We get our `%txt` to `%mime` `mark` conversion gate with a `%f` scry like so:
29+
30+```
31+> =txt-to-mime .^($-(wain mime) %cf /===/txt/mime)
32+```
33+
34+Note we had to specify the type of the gate as `$-(wain mime)` in the scry - if the type returned by the scry doesn't match that specification it'll fail. This is where a statically typed `mark` conversion gate differs from the dynamically typed gate, which we'll discuss later.
35+
36+Now that we have our conversion gate, we can just call it with a valid `wain` and we'll get our `$mime` in return:
37+
38+```
39+> (txt-to-mime ~['foo'])
40+[p=/text/plain q=[p=3 q=7.303.014]]
41+```
42+
43+### Dynamic
44+
45+A dynamically typed `mark` conversion gate is called a `$tube:clay`, and looks like:
46+
47+```hoon
48++$ tube $-(vase vase)
49+```
50+
51+As you can see from the type definition, it takes and returns a `vase` rather than needing the types explicitly defined. Rather than failing on a type mismatch when the scry is performed, it'll instead fail when it's actually run and fed a `vase` of the wrong type. Apart from handling `vase`s, it otherwise behaves the same as a statically typed `mark` conversion gate.
52+
53+#### Example
54+
55+We get our `%txt` to `%mime` `$tube` with a `%c` scry like so:
56+
57+```
58+> =txt-mime-tube .^(tube:clay %cc /===/txt/mime)
59+```
60+
61+And then we can again feed it the `wain` that a `%txt` `mark` wants, only this time it's wrapped in a `vase`:
62+
63+```
64+> !< mime (txt-mime-tube !>(~['foo']))
65+[p=/text/plain q=[p=3 q=7.303.014]]
66+```
67+
68+We then get our `$mime` back, but also in a `vase`.
69+
70+## mark cores
71+
72+While a `mark` conversion gate is built from functions defined in `+grab` and `+grow`, a `mark` core gives you everything in `+grad` so you can create diffs, merge diffs, patch files, etc. An extra arm `+vale` is also included that lets you convert a `noun` to the type the `%mark` takes by running the `+noun` arm of `+grab` in the original `mark` file.
73+
74+### Static
75+
76+A statically typed `mark` core is a `(nave:clay a b)` where `a` is the type of the `mark` and `b` is the type for diffs (which is the type of the `mark` specified in `+form:grad`). For example, a static `mark` core for a `%txt` `mark` looks like `(nave:clay wain (urge:clay cord))`.
77+
78+`+nave:clay` looks like this in full:
79+
80+```hoon
81+++ nave
82+ |$ [typ dif]
83+ $_
84+ ^?
85+ |%
86+ ++ diff |~([old=typ new=typ] *dif)
87+ ++ form *mark
88+ ++ join |~([a=dif b=dif] *(unit (unit dif)))
89+ ++ mash
90+ |~ [a=[ship desk dif] b=[ship desk dif]]
91+ *(unit dif)
92+ ++ pact |~([typ dif] *typ)
93+ ++ vale |~(noun *typ)
94+ --
95+```
96+
97+In brief, the arms of the core do the following:
98+
99+- `+form` - `mark` for diffs.
100+- `+vale` - Clam `noun` to the `mark`'s type.
101+- `+diff` - Create diff of two files.
102+- `+pact` - Patch a file with a diff.
103+- `+join` - Merge two diffs, returning `~` if there's a conflict.
104+- `+mash` - Force merge of two diffs.
105+
106+#### Examples
107+
108+First we get the `%txt` `mark` core with a `%e` scry:
109+
110+```
111+> =txt-nave .^((nave:clay wain (urge:clay cord)) %ce /===/txt)
112+```
113+
114+Note we specified the `mark` type `wain` and diff type `(urge:clay cord)` in the `nave` returned by the scry.
115+
116+We can see the `mark` for diffs with `+form`:
117+
118+```
119+> form.txt-nave
120+%txt-diff
121+```
122+
123+To clam a noun to the type of the `mark` (a `wain` in the case of a `%txt` `mark`), we can call `+vale` with a `noun`:
124+
125+```
126+> (vale:txt-nave ~['foo' 'bar'])
127+<|foo bar|>
128+```
129+
130+We can create a diff of two files with `+diff`:
131+
132+```
133+> (diff:txt-nave ~['foo' 'bar' 'baz'] ~['foo' 'zoo' 'baz'])
134+~[[%.y p=1] [%.n p=<|bar|> q=<|zoo|>] [%.y p=1]]
135+```
136+
137+Let's create some more diffs for experimentation:
138+
139+```
140+> =diff-a (diff:txt-nave ~['foo' 'bar' 'baz'] ~['foo' 'zoo' 'baz'])
141+> =diff-b (diff:txt-nave ~['foo' 'bar' 'baz'] ~['zap' 'bar' 'baz'])
142+> =diff-c (diff:txt-nave ~['foo' 'bar' 'baz'] ~['foo' 'bla' 'baz'])
143+```
144+
145+If we try merging diffs `a` and `b` with `+join`, we get a new merged diff back in a `unit`:
146+
147+```
148+> (join:txt-nave diff-a diff-b)
149+[~ [~ ~[[%.n p=<|foo|> q=<|zap|>] [%.n p=<|bar|> q=<|zoo|>] [%.y p=1]]]]
150+```
151+
152+If we try merging diffs `a` and `c` however, we get `~` because of a conflict:
153+
154+```
155+> (join:txt-nave diff-a diff-c)
156+[~ ~]
157+```
158+
159+If we run `+mash` on `a` and `b` we get the same diff as with `+join` (sans the `unit`):
160+
161+```
162+> (mash:txt-nave [our %home diff-a] [our %blah diff-b])
163+[~ ~[[%.n p=<|foo|> q=<|zap|>] [%.n p=<|bar|> q=<|zoo|>] [%.y p=1]]]
164+```
165+
166+If we `+mash` `a` and `c`, however, we get a diff with the conflict annotated rather than just `~`:
167+
168+```
169+> (mash:txt-nave [our %home diff-a] [our %blah diff-c])
170+[ ~
171+ ~[
172+ [%.y p=1]
173+ [ %.n
174+ p=<|bar|>
175+ q
176+ <|>>>>>>>>>>>> ~zod/home zoo ++++++++++++ bar ------------ bla <<<<<<<<<<<< ~zod/blah|>
177+ ]
178+ [%.y p=1]
179+ ]
180+]
181+```
182+
183+Note that the `%txt` `mark` annotates conflicts, but there are no specific rules around how the `+mash` arm should force-merge conflicting diffs apart from that it must return a valid diff, however the `mark` specified in `+form` defines that.
184+
185+Finally, we can patch our `wain` with diff `a` and get a new, modified `wain`:
186+
187+```
188+> (pact:txt-nave ~['foo' 'bar' 'baz'] diff-a)
189+<|foo zoo baz|>
190+```
191+
192+### Dynamic
193+
194+A dynamically typed `mark` core is a `$dais:clay`, which looks like:
195+
196+```hoon
197++$ dais
198+ $_ ^|
199+ |_ sam=vase
200+ ++ diff |~(new=_sam *vase)
201+ ++ form *mark
202+ ++ join |~([a=vase b=vase] *(unit (unit vase)))
203+ ++ mash
204+ |~ [a=[ship desk diff=vase] b=[ship desk diff=vase]]
205+ *(unit vase)
206+ ++ pact |~(diff=vase sam)
207+ ++ vale |~(noun sam)
208+ --
209+```
210+
211+It has the same arms as the statically typed `mark` core, the difference is that it takes and returns `vase`s rather than the data directly. Additionally, it's a door rather than an ordinary core, and takes the type of the `mark` wrapped in a `vase` as its argument.
212+
213+#### Examples
214+
215+We can get a `%txt` `mark` `dais` with a `%b` scry:
216+
217+```
218+> =txt-dais .^(dais:clay %cb /===/txt)
219+```
220+
221+Its `+form` arm functions the same as a static core:
222+
223+```
224+> form.txt-dais
225+%txt-diff
226+```
227+
228+So does `+vale` except it returns a `vase`:
229+
230+```
231+> !< wain (vale:txt-dais ~['foo' 'bar'])
232+<|foo bar|>
233+```
234+
235+All the other arms also deal in `vase`s. Because it's a door, the `+pact` and `+diff` arms take the original file in a `vase` as the door sample rather than being given directly to the arm. Calling `+diff` arm, for example, works like so:
236+
237+```
238+> !< (urge:clay cord) (~(diff txt-dais !>(~['foo' 'bar'])) !>(~['foo' 'baz']))
239+~[[%.y p=1] [%.n p=<|bar|> q=<|baz|>]]
240+```
content/docs/arvo/clay/marks/writing-marks.mdnew file+333
@@ -0,0 +1,333 @@
1++++
2+title = "Writing Marks"
3+weight = 2
4+template = "doc.html"
5++++
6+
7+Here we'll walk through a practical example of writing a `mark` file.
8+
9+We'll create a `mark` for CSV (comma separated values) files, a simple format for storing tabular data in a text file. Note that there's already a `csv.hoon` `mark` and library, but we'll create new ones for demonstrative purposes. It shouldn't be an issue to overwrite the existing ones on a fakezod.
10+
11+CSV files separate fields with commas and rows with line breaks. They look something like:
12+
13+```
14+foo,bar,baz
15+blah,blah,blah
16+1,2,3
17+```
18+
19+There is a little complexity surrounding special characters in fields and line endings, but otherwise the only other rule is that all rows must have the same number of fields. You can refer to [RFC4180 on the IETF website](https://datatracker.ietf.org/doc/html/rfc4180) for more details.
20+
21+We'll represent such a structure in Hoon as a `(list (list @t))` like:
22+
23+```hoon
24+[['foo' 'bar' 'baz' ~] ['blah' 'blah' 'blah' ~] ['1' '2' '3' ~] ~]
25+```
26+
27+We could perhaps create the type with a `$|` rune to include row-length validation in the mold itself, but a `(list (list @t))` is simpler for demonstrative purposes.
28+
29+## A simple mark
30+
31+Let's begin with the simplest `mark` file:
32+
33+```hoon
34+|_ csv=(list (list @t))
35+++ grab
36+ |%
37+ ++ noun (list (list @t))
38+ --
39+++ grow
40+ |%
41+ ++ noun csv
42+ --
43+++ grad %noun
44+--
45+```
46+
47+The door takes a `(list (list @t))` as its sample, and we've given it a face of `csv` so we can easily reference it. Note its face could be anything, it needn't be the name of our `mark`. When we're doing something with data that has a `%csv` `mark` like converting it to another `mark` or creating a diff, this is where our data will reside.
48+
49+Next we have the `+grab` arm of our door, which contains a core with arms for converting _to_ our `mark` _from_ other `mark`s. We've given it one arm for the `%noun` `mark` - the most generic `mark` which will take any `noun`. Our `+noun` arm will simply clam whatever it's given with the `(list (list @t))` `mold`.
50+
51+Next is the `+grow` arm which does the inverse of `+grab`, converting _from_ our `mark` _to_ another `mark`. We've also given it a `+noun` arm, this time it will simply return the door's sample named `csv`, which is of course already a `noun`.
52+
53+Note that the `+noun` arm is _mandatory_ in `+grab`. Clay cannot build a `mark` core without it. Conversion arms for any other `mark`s apart from `%noun` are optional.
54+
55+Finally we have the `+grad` arm. This arm specifies functions for revision control like creating diffs, patching files and so on. In our case, rather than writing all those functions, we've just delegated those tasks to the `%noun` `mark`. We can do this because we've specified conversion routines to and from the `%noun` `mark` in our `+grow` and `+grab` arms. When we modify a file with a `%csv` `mark`, Clay will convert our data to a `%noun` `mark`, execute the necessary `+grad` functions from the `%noun` `mark` file, and then convert it back to a `%csv` `mark` again.
56+
57+So now we have a valid `%csv` `mark` file. If we save this as `csv.hoon` in the `/mar` directory we could store `%csv` data in Clay. This may be sufficient for some applications, but what if we want to import a CSV file from Unix or elsewhere? In the next section, we'll look at conversions to and from a `%mime` `mark` to address this.
58+
59+## `%mime` conversions
60+
61+The `$mime` type represents raw data from Unix or elsewhere. For example, if a text file from Unix containing the word `foo` were converted to a `$mime` type in Urbit, it would look something like:
62+
63+```hoon
64+[/text/plain q=[p=3 q=7.303.014]]
65+```
66+
67+`/text/plain` is its [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) and `p.q` is the byte-length of `q.q`, which is the data itself as an `atom`.
68+
69+The `%mime` `mark` is used by Clay to store and convert `$mime` data. It's an important `mark` for moving files from Unix to Urbit and vice versa. When you add a file to a `desk` you have mounted to Unix and `|commit` the change, Clay will first receive the file as a `%mime` `mark`, then convert from a `%mime` to whatever `mark` matches the file extension. For example, `foo.txt` will be converted from `%mime` to `%txt`. Additionally, data fetched by Iris over HTTP will come in as a `$mime-data:http`, which is an unvalidated form of `$mime` that you may wish to convert to a `%mime` `mark` and then to another `mark`. Likewise with Eyre, some of the lower-level interfaces receive HTTP requests with `$mime-data:http` in them.
70+
71+So with the nature of the `%mime` `mark` hopefully now clear, the reason we want conversion methods to and from `%mime` in our `%csv` `mark` is so we can import CSV files from Unix and vice versa.
72+
73+Since a CSV file on Unix will just be a long string with ASCII or UTF-8 encoding, we can treat `q.q` in the `$mime` as a `cord`, and thus write a parser to convert it to a `(list (list @t))`. For this purpose, here's a library: `csv.hoon`, which you can view in full on the [Examples](/docs/arvo/clay/marks/examples#libcsvhoon) page.
74+
75+The library contains four functions:
76+
77+- `+de-csv` - Parse a CSV `cord` to a `(list (list @t))`.
78+- `+en-csv` - Encode a `(list (list @t))` as a CSV `cord`.
79+- `+validate` - Check all rows of `(list (list @t))` are the same length.
80+- `+csv-join` - Ignore this for now, we'll use it later on.
81+
82+The decoding and encoding arms use parsing functions from the Hoon standard library. It's not important to be familiar with parsing in Hoon for our purposes here, but you can have a look at the [Parsing Guide](/docs/hoon/guides/parsing) in the Hoon documentation if you're interested. The important thing to note is that `+de-csv` takes a valid CSV-format `@t` and returns a `(list (list @t))`, and `+en-csv` does the reverse - it takes a `(list (list @t))` and returns a CSV-format `@t`.
83+
84+Let's try the library in the dojo. After we've added it to `/lib` and run `|commit`, we can build the file:
85+
86+```
87+> =csv -build-file %/lib/csv/hoon
88+```
89+
90+...try decode a CSV-format `@t`:
91+
92+```
93+> (de-csv:csv 'foo,bar,baz\0ablah,blah,blah\0a1,2,3')
94+~[<|foo bar baz|> <|blah blah blah|> <|1 2 3|>]
95+```
96+
97+...and try encode a `(list (list @t))` as a CSV-format `@t`:
98+
99+```
100+> (en-csv:csv [['foo' 'bar' 'baz' ~] ['blah' 'blah' 'blah' ~] ['1' '2' '3' ~] ~])
101+'foo,bar,baz\0ablah,blah,blah\0a1,2,3\0a'
102+```
103+
104+With that working, we can add an import for our library to our `%csv` `mark` defintion and add a `+mime` arm to both our `+grab` and `+grow` arms:
105+
106+```hoon
107+/+ *csv
108+|_ csv=(list (list @t))
109+++ grab
110+ |%
111+ ++ mime |=((pair mite octs) (de-csv q.q))
112+ ++ noun
113+ |= n=*
114+ ^- (list (list @t))
115+ =/ result ((list (list @t)) n)
116+ ?> (validate result)
117+ result
118+ --
119+++ grow
120+ |%
121+ ++ mime
122+ ?> (validate csv)
123+ [/text/csv (as-octs:mimes:html (en-csv csv))]
124+ ++ noun
125+ ?> (validate csv)
126+ csv
127+ --
128+++ grad %noun
129+--
130+```
131+
132+In `+grab` we've added a `+mime` arm to convert _from_ a `%mime` `mark` _to_ our `%csv` `mark`. It's a simple gate that takes a `$mime` (specified as `(pair mite octs)` to avoid conflict with the arm name), runs the data through the `+de-csv` function and returns a `(list (list @t))` of the CSV data.
133+
134+We've also added a `+mime` arm to `+grow` for converting _from_ our `%csv` `mark` _to_ a `%mime` `mark`. We encode our `(list (list @t))` `csv` sample with our `+en-csv` function and then run that through `as-octs:mimes:html` to get a `$octs` (so it has the byte-length). We also add the `/text/csv` MIME type so it's a valid `$mime`.
135+
136+Additionally, we've used the `+validate` function in a few places to make sure our CSV data has consistent row lengths.
137+
138+If we save the above mark file as `csv.hoon` in `/mar` and `|commit %home`, we should now be able to import CSV files into Urbit. Let's give it a go. In the root of our `%home` `desk`, let's add a file named `foo.csv` with the following contents:
139+
140+```
141+foo,bar,baz
142+blah,blah,blah
143+1,2,3
144+```
145+
146+If we now `|commit %home`, we should see it's been successfully added:
147+
148+```
149+> |commit %home
150+>=
151++ /~zod/home/4/foo/csv
152+```
153+
154+And if we try reading the file with the `-read` thread:
155+
156+```
157+> -read [%x our %home da+now /foo/csv]
158+~[<|foo bar baz|> <|blah blah blah|> <|1 2 3|>]
159+```
160+
161+We can see our `%csv` `mark` has successfully converted our `foo.csv` file to a `(list (list @t))` when it was imported.
162+
163+Let's try the other direction now. We can create a new `bar.csv` files in the root of `%home` from the dojo like so:
164+
165+```
166+> */bar/csv ~[['abc' 'def' ~] ['ghi' 'jkl' ~]]
167++ /~zod/home/5/bar/csv
168+```
169+
170+And if we check it in the terminal on the Unix side we can see it's been correctly encoded:
171+
172+```
173+> cat zod/home/bar.csv
174+abc,def
175+ghi,jkl
176+```
177+
178+So now our `%csv` `mark` lets us move data in and out of Urbit. In the next section, we'll look at the `+grad` arm in more detail.
179+
180+## `+grad`
181+
182+So far we've just delegated `+grad` functions to the `%noun` `mark`, but now we'll look at writing our own.
183+
184+For demonstrative purposes, we can just poach the algorithms used in the `+grad` arm of the `%txt` `mark` and modify them to take our `(list (list @t))` type instead of a `wain`. It's not the most efficient algorithm for a CSV file but it'll do the job.
185+
186+Our diff format will be a `(urge:clay (list @t))`, and we'll use some `differ` functions from `zuse.hoon` like `+loss`, `+lusk` and `+lurk` to produce diffs and apply patches.
187+
188+The [csv.hoon library](/docs/arvo/clay/marks/examples#libcsvhoon) we imported also contains a `+csv-join` function which we'll use in the `+join` arm, just to save space here.
189+
190+Here's the new `%csv` `mark` defintion:
191+
192+```hoon
193+/+ *csv
194+|_ csv=(list (list @t))
195+++ grab
196+ |%
197+ ++ mime |=((pair mite octs) (de-csv q.q))
198+ ++ noun
199+ |= n=*
200+ ^- (list (list @t))
201+ =/ result ((list (list @t)) n)
202+ ?> (validate result)
203+ result
204+ --
205+++ grow
206+ |%
207+ ++ mime
208+ ?> (validate csv)
209+ [/text/csv (as-octs:mimes:html (en-csv csv))]
210+ ++ noun
211+ ?> (validate csv)
212+ csv
213+ --
214+++ grad
215+ |%
216+ ++ form %csv-diff
217+ ++ diff
218+ |= bob=(list (list @t))
219+ ^- (urge:clay (list @t))
220+ ?> (validate csv)
221+ ?> (validate bob)
222+ (lusk:differ csv bob (loss:differ csv bob))
223+ ++ pact
224+ |= dif=(urge:clay (list @t))
225+ ^- (list (list @t))
226+ =/ result (lurk:differ csv dif)
227+ ?> (validate result)
228+ result
229+ ++ join
230+ |= $: ali=(urge:clay (list @t))
231+ bob=(urge:clay (list @t))
232+ ==
233+ ^- (unit (urge:clay (list @t)))
234+ (csv-join ali bob)
235+ ++ mash
236+ |= $: [ship desk (urge:clay (list @t))]
237+ [ship desk (urge:clay (list @t))]
238+ ==
239+ ^- (urge:clay (list @t))
240+ ~|(%csv-mash !!)
241+ --
242+--
243+```
244+
245+In our modified `+grad` arm, we've replaced the `%noun` delegation with a core containing five arms: `+form`, `+diff`, `+pact`, `+join`, and `+mash`. These arms are all required for a valid `+grad` if it's not delegated to another `mark`. We'll now look at each in detail.
246+
247+### `+form`
248+
249+```hoon
250+++ form %csv-diff
251+```
252+
253+`+form` simply specifies the `mark` of the diff file that may be produced by other `+grad` functions. If your diff is the same type as your `mark`, it could just specify itself like `%csv`. In our case our diff is a `(urge:clay (list @t))` rather than a `(list (list @t))`, so we need a separate mark file for the diff itself.
254+
255+Here's another `mark` file which can be saved as `csv-diff.hoon` in `/mar`:
256+
257+```hoon
258+|_ dif=(urge:clay (list @t))
259+++ grab
260+ |%
261+ ++ noun (urge:clay (list @t))
262+ --
263+++ grow
264+ |%
265+ ++ noun dif
266+ --
267+++ grad %noun
268+--
269+```
270+
271+It's very bare-bones, we just need it for our `%csv` `mark` to work. In our `%csv` `mark`, we've specified it as `%csv-diff` in `+form`.
272+
273+### `+diff`
274+
275+```hoon
276+++ diff
277+ |= bob=(list (list @t))
278+ ^- (urge:clay (list @t))
279+ ?> (validate csv)
280+ ?> (validate bob)
281+ (lusk:differ csv bob (loss:differ csv bob))
282+```
283+
284+This arm produces the diff of two `%csv` files. The first `%csv` file will be given as the sample of the parent door, which if you'll recall we gave a face of `csv`. The second `%csv` file will be given as the sample of the gate in `+diff`, which we've named `bob` here. We then just produce the diff of these two files and return it as the type of the mark specified in `+form`, which in our case is `(urge:clay (list @t))` for a `%csv-diff`. Clay will use `+diff` when a file is revised, so it doesn't have to store a whole new copy of the file each time it's modified.
285+
286+### `+pact`
287+
288+```hoon
289+++ pact
290+ |= dif=(urge:clay (list @t))
291+ ^- (list (list @t))
292+ =/ result (lurk:differ csv dif)
293+ ?> (validate result)
294+ result
295+```
296+
297+`+pact` patches a `%csv` file with the given diff. Its gate takes a diff and applies it to the `%csv` given as the sample of the parent door (which we gave a face of `csv`). If the patch succeeds, it will return a new `%csv` file - a valid `(list (list @t))`. When we read a file that's been modified in Clay, Clay will apply all the diffs it has with `+pact` and return the resulting file.
298+
299+### `+join`
300+
301+```hoon
302+++ join
303+ |= $: ali=(urge:clay (list @t))
304+ bob=(urge:clay (list @t))
305+ ==
306+ ^- (unit (urge:clay (list @t)))
307+ (csv-join ali bob)
308+```
309+
310+The `+join` arm merges two different diffs. It takes them both as the sample of its gate (which we've named `ali` and `bob`), and returns a new diff wrapped in a `unit` like `(unit (urge:clay (list @t)))`. The `unit` will be `~` if the merge failed due to a conflict. This is used by Clay in some cases when `desk`s are merged. If diff merges are not possible for your use case, you could just have it always return `~`.
311+
312+### `+mash`
313+
314+```hoon
315+++ mash
316+ |= $: [ship desk (urge:clay (list @t))]
317+ [ship desk (urge:clay (list @t))]
318+ ==
319+ ^- (urge:clay (list @t))
320+ ~|(%csv-mash !!)
321+```
322+
323+This is like `+join` except it forces a diff merge even if there's a conflict. Rather than returning a `unit`, it just returns the diff - a `(urge:clay (list @t))` in our case. Also unlike `+join`, it takes the `ship` and `desk` each diff came from as well as the diff itself.
324+
325+The `+mash` arm is not used by Clay in its file revision operations, so it's safe to just make it a dummy arm that crashes as we've done here. If you were to use it, it would likely just be used manually in an agent, thread or generator.
326+
327+An example of its use would be the `%txt` `mark`, which includes a proper `+mash` function that produces a diff with any conflicts annotated, though how you have `+mash` handle conficts would depend on your use case. If there were no conflicts between the two diffs, it should produce the same diff as the `+join` arm.
328+
329+## Conclusion
330+
331+So there you have it, a fully functional `mark` for CSV files. A `mark` file can be as complex or as simple as you'd like, they're very flexible depending on your use case. Additional conversion methods can always be added as they're needed. For example, with just a few lines of code we could add arms for converting CSV files to `%json` or `%txt` and vice versa.
332+
333+In the next document, we'll look at building and using `mark` cores and `mark` conversion gates in our own code.
content/docs/arvo/clay/scry.md+6−6
@@ -8,7 +8,7 @@ The various Clay scries are specified by a `care`, which is a single character c
8
8
9```
9```
10> /===
10> /===
11−[~.~zod ~.home ~.~2021.4.26..02.29.03..d31b ~]
11+[~.~zod ~.base ~.~2021.4.26..02.29.03..d31b ~]
12```
12```
13
13
14## %a - Build hoon.
14## %a - Build hoon.
@@ -51,7 +51,7 @@ Example:
51
51
52```
52```
53> .^((set desk) %cd /===)
53> .^((set desk) %cd /===)
54−{%home %kids}
54+{%bitcoin %base %landscape %webterm %garden}
55```
55```
56
56
57## %e - Static mark core.
57## %e - Static mark core.
@@ -213,12 +213,12 @@ This will return the most recent revision number of a `desk` that has been fully
213Example:
213Example:
214
214
215```
215```
216−> .^(=cass:clay %cs /(scot %p (sein:title our now our))/kids/1/late)
216+> .^(=cass:clay %cs /(scot %p (sein:title our now our))/base/1/late)
217cass=[ud=50 da=~2021.4.22..10.38.50..57a8]
217cass=[ud=50 da=~2021.4.22..10.38.50..57a8]
218```
218```
219
219
220```
220```
221−> .^(=cass:clay %cs /~sampel/kids/1/late)
221+> .^(=cass:clay %cs /~sampel/base/1/late)
222cass=[ud=0 da=~2000.1.1]
222cass=[ud=0 da=~2000.1.1]
223```
223```
224
224
@@ -229,12 +229,12 @@ This will return the mergebase (i.e. most recent common ancestor) between two `d
229Examples:
229Examples:
230
230
231```
231```
232−> .^((list tako:clay) %cs /===/base/(scot %p (sein:title our now our))/kids)
232+> .^((list tako:clay) %cs /===/base/(scot %p (sein:title our now our))/base)
233~[102.787.244.596.033.419.950.995.540.301.493.841.569.518.772.322.508.085.465.561.801.703.148.627.263.473]
233~[102.787.244.596.033.419.950.995.540.301.493.841.569.518.772.322.508.085.465.561.801.703.148.627.263.473]
234```
234```
235
235
236```
236```
237−> .^((list tako:clay) %cs /===/base/~sampel/kids)
237+> .^((list tako:clay) %cs /===/base/~sampel/base)
238~
238~
239```
239```
240
240
content/docs/arvo/clay/tasks.md+2−2
@@ -108,7 +108,7 @@ This subscribes to all changes to a `desk` for the specified range of `case`s. N
108If the `track` is `%.y` it will just return a `%writ` like:
108If the `track` is `%.y` it will just return a `%writ` like:
109
109
110```hoon
110```hoon
111−[%writ p=[~ [p=[p=%w q=[%ud p=256] r=%home] q=/ r=[p=%null q=[#t/@n q=0]]]]]
111+[%writ p=[~ [p=[p=%w q=[%ud p=256] r=%base] q=/ r=[p=%null q=[#t/@n q=0]]]]]
112```
112```
113
113
114...that merely informs you of a change. If you want the actual data you'll have to request it separately.
114...that merely informs you of a change. If you want the actual data you'll have to request it separately.
@@ -494,7 +494,7 @@ Note that if you're reading a whole `desk` or directory, all subfolders and file
494
494
495To merge a foreign `desk` into a local one, you just send Clay a `%merg` `task` (as you would for a local merge) and specify the foreign ship in the `her` field. For details on making such requests, see the [Merge Desks](#merge-desks) section.
495To merge a foreign `desk` into a local one, you just send Clay a `%merg` `task` (as you would for a local merge) and specify the foreign ship in the `her` field. For details on making such requests, see the [Merge Desks](#merge-desks) section.
496
496
497−The foreign ship will respond only if correct permissions have been set. See the [Permissions](#permissions) section for details. By default, a ship's `%kids` desk is set to be publicly readable, so unless permissions have been manually modified, you should be able to merge from any `%kids` `desk`.
497+The foreign ship will respond only if correct permissions have been set. See the [Permissions](#permissions) section for details.
498
498
499Note that all subfolders and individual files within the `desk` must permit your reading in order for the merge to succeed. If even one file does not permit you reading it, the remote ship will not respond to the request at all.
499Note that all subfolders and individual files within the `desk` must permit your reading in order for the merge to succeed. If even one file does not permit you reading it, the remote ship will not respond to the request at all.
500
500
content/docs/arvo/clay/using.md+67−61
@@ -6,50 +6,51 @@ template = "doc.html"
6
6
7### Reading and Subscribing
7### Reading and Subscribing
8
8
9−When reading from Clay, there are three types of requests. A
9+When reading from Clay, there are three types of requests. A
10−`%sing` request asks for data at single revsion. A `%next`
10+`%sing` request asks for data at single revsion. A `%next`
11request asks to be notified the next time there's a change to
11request asks to be notified the next time there's a change to
12−given file. A `%many` request asks to be notified on every
12+given file. A `%many` request asks to be notified on every
13change in a `desk` for a range of changes.
13change in a `desk` for a range of changes.
14
14
15For `%sing` and `%next`, there are generally three things to be
15For `%sing` and `%next`, there are generally three things to be
16−queried. A `%u` request simply checks for the existence of a
16+queried. A `%u` request simply checks for the existence of a
17−file at a path. A `%x` request gets the data in the file at a
17+file at a path. A `%x` request gets the data in the file at a
18−path. A `%y` request gets a hash of the data in the file at the
18+path. A `%y` request gets a hash of the data in the file at the
19−path combined with all its children and their data. Thus, `%y`
19+path combined with all its children and their data. Thus, `%y`
20of a node changes if it or any of its children change.
20of a node changes if it or any of its children change.
21
21
22−A `%sing` request is fulfilled immediately if possible. If the
22+A `%sing` request is fulfilled immediately if possible. If the
23requested revision is in the future, or is on another ship for
23requested revision is in the future, or is on another ship for
24which we don't have the result cached, we don't respond
24which we don't have the result cached, we don't respond
25−immediately. If the requested revision is in the future, we wait
25+immediately. If the requested revision is in the future, we wait
26−until the revision happens before we respond to the request. If
26+until the revision happens before we respond to the request. If
27the request is for data on another ship, we pass on the request
27the request is for data on another ship, we pass on the request
28−to the other ship. In general, Clay subscriptions, like most
28+to the other ship. In general, Clay subscriptions, like most
29things in Urbit, aren't guaranteed to return immediately.
29things in Urbit, aren't guaranteed to return immediately.
30They'll return when they can, and they'll do so in a
30They'll return when they can, and they'll do so in a
31referentially transparent manner.
31referentially transparent manner.
32
32
33A `%next` request checks the query at the given revision, and it
33A `%next` request checks the query at the given revision, and it
34produces the result of the query the next time it changes, along
34produces the result of the query the next time it changes, along
35−with the revision number when it changes. Thus, a `%next` of a
35+with the revision number when it changes. Thus, a `%next` of a
36`%u` is triggered when a file is added or deleted, a `%next` of a
36`%u` is triggered when a file is added or deleted, a `%next` of a
37`%x` is triggered when a file is added, deleted, or changed, and
37`%x` is triggered when a file is added, deleted, or changed, and
38a `%next` of a `%y` is triggered when a file or any of its
38a `%next` of a `%y` is triggered when a file or any of its
39children is added, deleted, or changed.
39children is added, deleted, or changed.
40
40
41A `%many` request is triggered every time the given `desk` has a
41A `%many` request is triggered every time the given `desk` has a
42−new revision. Unlike a `%next`, a `%many` has both a start and
42+new revision. Unlike a `%next`, a `%many` has both a start and
43−an end revision, after which it stops returning. For `%next`, a
43+an end revision, after which it stops returning. For `%next`, a
44single change is reported, and if the caller wishes to hear of
44single change is reported, and if the caller wishes to hear of
45−the next change, it must resubscribe. For `%many`, every revision
45+the next change, it must resubscribe. For `%many`, every revision
46−from the start to the end triggers a response. Since a `%many`
46+from the start to the end triggers a response. Since a `%many`
47request doesn't ask for any particular data, there aren't `%u`,
47request doesn't ask for any particular data, there aren't `%u`,
48`%x`, and `%y` versions for it.
48`%x`, and `%y` versions for it.
49
49
50### Unix sync
50### Unix sync
51
51
52Usage:
52Usage:
53+
53```
54```
54|mount %/path/to/directory %mount-point
55|mount %/path/to/directory %mount-point
55|commit %mount-point
56|commit %mount-point
@@ -76,123 +77,128 @@ be automatically committed with `|autocommit %mount-point`.
76### Merging
77### Merging
77
78
78Usage:
79Usage:
80+
79```
81```
80|merge %target-desk ~source-ship %source-desk
82|merge %target-desk ~source-ship %source-desk
81|merge %target-desk ~source-ship %source-desk, =gem %strategy
83|merge %target-desk ~source-ship %source-desk, =gem %strategy
82|merge %target-desk ~source-ship %source-desk, =cas ud+5
84|merge %target-desk ~source-ship %source-desk, =cas ud+5
83```
85```
84
86
85−Clay supports various merge strategies. A "commit" is a snapshot of
87+Clay supports various merge strategies. A "commit" is a snapshot of
86−the files with a list of parents plus a date. Most commits have
88+the files with a list of parents plus a date. Most commits have
87−one parent; a "merge" commit is a commit with two parents. The
89+one parent; a "merge" commit is a commit with two parents. The
88−%home `desk` starts with an initial commit with no parents; commits
90+`%base` `desk` starts with an initial commit with no parents; commits
89with several parents ("octopus merges") are possible but we don't
91with several parents ("octopus merges") are possible but we don't
90generate them right now.
92generate them right now.
91−
93+
92Unless otherwise specified, all of the following create a new commit
94Unless otherwise specified, all of the following create a new commit
93with the source and destination commits as parents.
95with the source and destination commits as parents.
94−
96+
95−Several strategies need a "merge-base". They find it by identifying
97+Several strategies need a "merge-base". They find it by identifying
96−the most recent common ancestor of the two `desk`s. If none, fail
98+the most recent common ancestor of the two `desk`s. If none, fail
97with `%merge-no-merge-base`; if there are two or more, pick one.
99with `%merge-no-merge-base`; if there are two or more, pick one.
98
100
99#### Strategies
101#### Strategies
100−
102+
101−**`%init`**: the only way to create a `desk`. Not a true merge, since it
103+**`%init`**: the only way to create a `desk`. Not a true merge, since it
102simply assigns the source commit to the destination.
104simply assigns the source commit to the destination.
103−
105+
104**`%fine`**: if source or destination are in the ancestry of each other,
106**`%fine`**: if source or destination are in the ancestry of each other,
105−use the newer one; else abort. If the destination is ahead of the
107+use the newer one; else abort. If the destination is ahead of the
106−source, succeed but do nothing. If the source is ahead of the
108+source, succeed but do nothing. If the source is ahead of the
107destination, assign the next revision number to the source commit.
109destination, assign the next revision number to the source commit.
108Some call this "fast-forward".
110Some call this "fast-forward".
109−
111+
110**`%meet`**: combine changes, failing if both sides changed the same file.
112**`%meet`**: combine changes, failing if both sides changed the same file.
111Specifically, take diff(merge-base,source) and
113Specifically, take diff(merge-base,source) and
112diff(merge-base,destination) and combine them as long as those diffs
114diff(merge-base,destination) and combine them as long as those diffs
113touch different files.
115touch different files.
114−
116+
115**`%mate`**: combine changes, failing if both sides changed the same part
117**`%mate`**: combine changes, failing if both sides changed the same part
116−of a file. Identical to `%meet`, except that some marks, like `%hoon`,
118+of a file. Identical to `%meet`, except that some marks, like `%hoon`,
117allow intelligent merge of changes to different parts of a file.
119allow intelligent merge of changes to different parts of a file.
118−
120+
119**`%meld`**: combine changes; if both sides changed the same part of a
121**`%meld`**: combine changes; if both sides changed the same part of a
120file, use the version of the file in the merge-base.
122file, use the version of the file in the merge-base.
121−
123+
122**`%only-this`**: create a merge commit with exactly the contents of the
124**`%only-this`**: create a merge commit with exactly the contents of the
123destination `desk`.
125destination `desk`.
124−
126+
125**`%only-that`**: create a merge commit with exactly the contents of the
127**`%only-that`**: create a merge commit with exactly the contents of the
126source commit.
128source commit.
127−
129+
128**`%take-this`**: create a merge commit with exactly the contents of the
130**`%take-this`**: create a merge commit with exactly the contents of the
129destination `desk` except take any files from the source commit which
131destination `desk` except take any files from the source commit which
130are not in the destination `desk`.
132are not in the destination `desk`.
131−
133+
132**`%take-that`**: create a merge commit with exactly the contents of the
134**`%take-that`**: create a merge commit with exactly the contents of the
133source commit except preserve any files from the destination `desk`
135source commit except preserve any files from the destination `desk`
134which are not in the source commit.
136which are not in the source commit.
135−
137+
136**`%meet-this`**: merge as in `%meet`, except if both sides changed the same
138**`%meet-this`**: merge as in `%meet`, except if both sides changed the same
137file, use the version in the destination `desk`.
139file, use the version in the destination `desk`.
138−
140+
139**`%meet-that`**: merge as in `%meet`, except if both sides changed the same
141**`%meet-that`**: merge as in `%meet`, except if both sides changed the same
140file, use the version in the source commit.
142file, use the version in the source commit.
141−
143+
142#### Examples and notes:
144#### Examples and notes:
143−
145+
144The most common merge strategy is `%mate`, which is a normal 3-way
146The most common merge strategy is `%mate`, which is a normal 3-way
145merge which aborts on conflict.
147merge which aborts on conflict.
146−
148+
147−`%take-that` is useful to "force" an OTA. After running `%take-that`,
149+`%take-that` is useful to "force" an OTA. After running `%take-that`,
148you're guaranteed to have exactly the files in the source commit plus
150you're guaranteed to have exactly the files in the source commit plus
149any files you separately added.
151any files you separately added.
150−
152+
151−We speak of merging into a destination *`desk`* from a source *commit*
153+We speak of merging into a destination _`desk`_ from a source _commit_
152because while you can only merge on top of a `desk`, you can merge from
154because while you can only merge on top of a `desk`, you can merge from
153−historical commits. For example,
155+historical commits. For example,
156+
154−```
157+```
155−|merge %old our %home, =cas ud+5, =gem %init
158+|merge %old our %base, =cas ud+5, =gem %init
156```
159```
160+
157−will create a new `desk` called `%old` with the 5th commit in `%home`.
161+will create a new `desk` called `%old` with the 5th commit in `%base`.
158You can revert the contents of a `desk` to what they were yesterday
162You can revert the contents of a `desk` to what they were yesterday
159with
163with
164+
160```
165```
161−|merge %home our %home, =cas da+(sub now ~d1), =gem %only-that
166+|merge %base our %base, =cas da+(sub now ~d1), =gem %only-that
162```
167```
163−
168+
164Note this is a normal `%only-that merge`, which means you're creating a
169Note this is a normal `%only-that merge`, which means you're creating a
165−*new* commit with the old *contents*.
170+_new_ commit with the old _contents_.
166−
171+
167`%meld` is rarely used on its own, however if you specify `%auto` or
172`%meld` is rarely used on its own, however if you specify `%auto` or
168omit the merge strategy, `%kiln` will run a `%meld` merge into a scratch
173omit the merge strategy, `%kiln` will run a `%meld` merge into a scratch
169`desk` and then annotate the conflicts there.
174`desk` and then annotate the conflicts there.
170−
175+
171If you resolve merge conflicts manually, for example by mounting the
176If you resolve merge conflicts manually, for example by mounting the
172`desk`s, copying the files in Unix and then running `|commit`, you
177`desk`s, copying the files in Unix and then running `|commit`, you
173−should usually run an `%only-this merge`. This will not change the
178+should usually run an `%only-this merge`. This will not change the
174newly-fixed contents of your `desk`, but it will record that the merge
179newly-fixed contents of your `desk`, but it will record that the merge
175happened so that those conflicts don't reappear in later merges.
180happened so that those conflicts don't reappear in later merges.
176−
181+
177If you get a `%merge-no-merge-base` error, this means you're trying to
182If you get a `%merge-no-merge-base` error, this means you're trying to
178−merge two `desk`s which have no common ancestors. You need to give
183+merge two `desk`s which have no common ancestors. You need to give
179them a common ancestor by choosing a merge strategy which doesn't
184them a common ancestor by choosing a merge strategy which doesn't
180need a merge-base, like `%only-this`, `%only-that`, `%take-this`, or
185need a merge-base, like `%only-this`, `%only-that`, `%take-this`, or
181`%take-that`.
186`%take-that`.
182−
187+
183`%take-this` could be useful to install 3rd party software, but you
188`%take-this` could be useful to install 3rd party software, but you
184couldn't get subsequent updates this way, since the files would
189couldn't get subsequent updates this way, since the files would
185−already exist in the destination `desk`. Something like "take only
190+already exist in the destination `desk`. Something like "take only
186the files which aren't in my OTA source or any other 3rd party app"
191the files which aren't in my OTA source or any other 3rd party app"
187−would be basically correct. This would require a parameter listing
192+would be basically correct. This would require a parameter listing
188the `desk`s to not conflict with.
193the `desk`s to not conflict with.
189−
194+
190`%meet-this` and `%meet-that` imply the existence of `%mate-this` and
195`%meet-this` and `%meet-that` imply the existence of `%mate-this` and
191`%mate-that`, but those don't exist yet.
196`%mate-that`, but those don't exist yet.
192
197
193### Autosync
198### Autosync
194
199
195Usage:
200Usage:
201+
196```
202```
197|sync %target-desk ~source-ship %source-desk
203|sync %target-desk ~source-ship %source-desk
198```
204```
content/docs/arvo/concepts/_index.md+4
@@ -8,6 +8,10 @@ insert_anchor_links = "right"
8
8
9Other concepts related to the way Arvo works.
9Other concepts related to the way Arvo works.
10
10
11+## [Scries](/docs/arvo/concepts/scries)
12+
13+Details of performing scries.
14+
11## [Subscriptions](/docs/arvo/concepts/subscriptions)
15## [Subscriptions](/docs/arvo/concepts/subscriptions)
12
16
13Urbit relies heavily on subscriptions throughout the stack. We strongly prefer reactive data flow compared to querying or polling, which is why for example our equivalent to git natively supports subscriptions to its data.
17Urbit relies heavily on subscriptions throughout the stack. We strongly prefer reactive data flow compared to querying or polling, which is why for example our equivalent to git natively supports subscriptions to its data.
content/docs/arvo/concepts/scry.mdnew file+77
@@ -0,0 +1,77 @@
1++++
2+title = "Scries"
3+weight = 40
4+template = "doc.html"
5++++
6+
7+### What is a scry?
8+
9+A scry is a read-only request to Arvo's global namespace.
10+
11+Vanes and agents define _scry endpoints_ which allow one to request data from their respective states. The endpoints can process the data in any way before returning it, but they cannot alter the actual state - scries can _only_ read, not modify.
12+
13+### Why scry?
14+
15+The subject available in something like a Gall agent or thread contains a great many functions and structures from the standard library as well as `zuse` and `lull`, but it does not include any of the actual data stored elsewhere in the ship. All it has is its own state, a `bowl` and any `card`s it has been passed. Ordinarily, in order to access such data, one would need to `%poke` or `%watch` other agents, or `%pass` `task`s to vanes, then wait for a response. Arvo's scry system is the one exception to this; it allows direct retrieval of data from other vanes or agents in situ, from any context, without any of the normal messaging rigmarole.
16+
17+### How do I scry?
18+
19+Scries are performed exclusively with the dotket rune: `.^`
20+
21+For details of its usage, see the [dotket](/docs/hoon/reference/rune/dot#-dotket) section of the Nock rune documentation. In addition to the dotket documentation, below is a colour-coded diagram breaking down the structure of a dotket scry expression with some additional notes.
22+
23+![Scry diagram](https://media.urbit.org/docs/arvo/scry-diagram-v2.svg)
24+
25+One further note on `care`s (which can sometimes be confusing): While `care`s are part of the global namespace, they're most extensively used by Clay in particular. In Clay, `care`s specify Clay submodules with specific behaviour, and are used both in scries as well as `task`s and `gift`s. For example, a `%x` `care` reads the data of a file, a `%p` `care` reads file permissions, and so forth. To see all of Clay's `care`s and what they do, you can refer to Clay's [Scry Reference](/docs/arvo/clay/scry).
26+
27+Most other vanes also make use of `care`s in their scry endpoints. While such vanes don't have corresponding submodules with strictly defined behaviour like Clay, the `care`s still confer the general nature of the endpoint. The most widely used `care` is `%x`, which implies reading data in a general sense. Gall has special handling of `%x` scries as described in the [Gall agents](#gall-agents) section below, but otherwise `care`s have no special behaviour for non-Clay vanes (though they must still be included if the endpoint specifies it).
28+
29+### What can I scry?
30+
31+There are two places where scry endpoints are defined:
32+
33+#### Vanes
34+
35+Each of Arvo's eight vanes (kernel modules) include a `+scry` arm which defines that vane's scry endpoints. The number of endpoints and extent of data available varies between vanes. For example, Clay has a very extensive set of scry endpoints which provide read access to all files in all desks across all revisions, as well as the ability to build files, perform `mark` conversions, and various other functions. Jael provides access to a great deal of PKI data. On the other hand, Dill has only a couple of endpoints which are mostly useful for debugging, and Iris has none at all (apart from standard memory reporting endpoints you'd not typically use in your applications).
36+
37+To explore what scry endpoints are available for vanes, you can refer to the Scry Reference section of each vane in the [Arvo](/docs/arvo/overview) section of the documents.
38+
39+#### Gall agents
40+
41+Gall has a single scry endpoint of its own to check for the existence of an agent, but otherwise all Gall scries are passed through to one of the agents it manages. The target agent to scry is specified in place of the `desk` as described in the diagram above. Each Gall agent includes a `+on-peek` arm that defines its own scry endpoints. For example, `%graph-store` has a number of scry endpoints to access the data it stores, such as chat messages and the like.
42+
43+Gall agents can expose scry endpoints with any `care`, but most commonly they'll take a `%x` `care`. Gall handles `%x` scries specially - it expects an extra field at the end of the `path` that specifies a `mark`. Gall will attempt to perform a `mark` conversion from the `mark` returned by the scry endpoint to the `mark` specified. Note the trailing `mark` in the `path` will not be passed through to the agent itself.
44+
45+### What is an endpoint?
46+
47+"Endpoint" refers to a specific scry path in a vane or agent. They will sometimes informally be noted in documentation or source comments like `/x/foo/bar/baz` or maybe just `/foo/bar/baz`. The first part of the former example is the `care`, then the rest is the `path` portion as noted in the diagram earlier.
48+
49+If an agent's scry endpoints don't have formal documentation, you may need to refer to the `+on-peek` arm in its source code to determine its endpoints. While there's no exact pattern that's consistent across different agents, the general pattern will be some initial tests and conversions followed by a `?+` rune, whose cases will typically correspond to the endpoints. The `+on-peek` arm always return a `(unit (unit cage))` (a `cage` is a cell of `[mark vase]`), so each endpoint will typically finish by composing such a structure.
50+
51+Here's an example from the `+on-peek` arm of `%graph-store`:
52+
53+```hoon
54+ [%x %keys ~]
55+:- ~ :- ~ :- %graph-update-2
56+!>(`update:store`[now.bowl [%keys ~(key by graphs)]])
57+```
58+
59+The case in the beginning says it takes a `%x` `care` and has a `path` of `/keys`. Additionally, it returns data with a `mark` of `%graph-update-2`. Assuming we wanted the `%graph-update-2` `mark` converted to a `%json` `mark`, our scry would be composed along the lines of:
60+
61+```hoon
62+.^(json %gx /(scot %p our)/graph-store/(scot %da now)/keys/json)
63+```
64+
65+### Web scries
66+
67+The webserver vane Eyre has a system which allows clients like web browsers to perform scries over HTTP. For details, refer to the [Scry section of Eyre's External API Reference](/docs/arvo/eyre/external-api-ref#scry).
68+
69+### Further reading
70+
71+[dotket](/docs/hoon/reference/rune/dot#-dotket) - Documentation of the `.^` rune which performs scries.
72+
73+[Arvo](/docs/arvo/overview) - Each vane has a Scry Reference section with details of their endpoints as well as examples.
74+
75+[Eyre's External API Reference](/docs/arvo/eyre/external-api-ref#scry) - Documentation of Eyre's scry system which allows web clients to perform scries over HTTP.
76+
77+[The Gall Guide](/docs/userspace/gall-guide) - The Gall tutorial includes a section about `+on-peek` and writing scry endpoints.
content/docs/arvo/concepts/subscriptions.md+43−43
@@ -4,7 +4,7 @@ weight = 50
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−Urbit relies heavily on subscriptions throughout the stack. We strongly
7+Urbit relies heavily on subscriptions throughout the stack. We strongly
8prefer reactive data flow compared to querying or polling, which is why
8prefer reactive data flow compared to querying or polling, which is why
9for example our equivalent to git natively supports subscriptions to its
9for example our equivalent to git natively supports subscriptions to its
10data.
10data.
@@ -12,7 +12,7 @@ data.
12We have many application-level styles of subscription, but we only have
12We have many application-level styles of subscription, but we only have
13three true subscription types in Arvo, named for the vane they're
13three true subscription types in Arvo, named for the vane they're
14implemented in: Clay subscriptions (filesystem), Gall subscriptions
14implemented in: Clay subscriptions (filesystem), Gall subscriptions
15−(applications), and Jael subscriptions (Urbit ID info). They're at
15+(applications), and Jael subscriptions (Urbit ID info). They're at
16three different points in the idea maze of subscriptions, and we'll
16three different points in the idea maze of subscriptions, and we'll
17encounter each of them here.
17encounter each of them here.
18
18
@@ -28,9 +28,9 @@ later request.
28### Exactly-once updates
28### Exactly-once updates
29
29
30Some subscriptions need the subscriber to receive each update separately
30Some subscriptions need the subscriber to receive each update separately
31−instead of collapsing them into a single diff. Sometimes a subscription
31+instead of collapsing them into a single diff. Sometimes a subscription
32is really a sequence of commands, in which case there's no meaningful
32is really a sequence of commands, in which case there's no meaningful
33−way to collapse them. Similarly, software updates may be expected to be
33+way to collapse them. Similarly, software updates may be expected to be
34applied in order.
34applied in order.
35
35
36### Syncing data
36### Syncing data
@@ -38,79 +38,79 @@ applied in order.
38Other times, it's more natural to think of a subscription as
38Other times, it's more natural to think of a subscription as
39communicating a data structure, where the only goal is to keep the data
39communicating a data structure, where the only goal is to keep the data
40structure on the subscriber's side up-to-date with what's on the
40structure on the subscriber's side up-to-date with what's on the
41−publisher's side. In this case, it's perfectly fine to collapse several
41+publisher's side. In this case, it's perfectly fine to collapse several
42updates into one large update, or even to resend the entire data
42updates into one large update, or even to resend the entire data
43−structure. Partial updates exist only as an optimization.
43+structure. Partial updates exist only as an optimization.
44
44
45For this sort of subscription, we commonly use terms like "diff" instead
45For this sort of subscription, we commonly use terms like "diff" instead
46of "message" or "update", and we say that we "apply a diff" instead of
46of "message" or "update", and we say that we "apply a diff" instead of
47−"process an update". We also often identify the subscription with the
47+"process an update". We also often identify the subscription with the
48data structure itself.
48data structure itself.
49
49
50## Memory pressure
50## Memory pressure
51
51
52Naively implemented, subscriptions pose a memory leak risk if the
52Naively implemented, subscriptions pose a memory leak risk if the
53subscriber can't receive updates as fast as the publisher wants to send
53subscriber can't receive updates as fast as the publisher wants to send
54−them. This commonly happens when the subscriber goes offline for an
54+them. This commonly happens when the subscriber goes offline for an
55−extended period of time (possibly forever; especially for comets). It's
55+extended period of time (possibly forever; especially for comets). It's
56sufficient to bound the amount of memory dedicated to any particular
56sufficient to bound the amount of memory dedicated to any particular
57subscriber.
57subscriber.
58
58
59In a synchronous system, you don't have to worry about what happens if
59In a synchronous system, you don't have to worry about what happens if
60−one side or the other ceases to be available. All of our subscriptions,
60+one side or the other ceases to be available. All of our subscriptions,
61though, can happen between ships.
61though, can happen between ships.
62
62
63### Small data
63### Small data
64
64
65For particularly low-volume subscriptions, it may be acceptable to
65For particularly low-volume subscriptions, it may be acceptable to
66−ignore the problem. Jael uses this approach, since the only time it's
66+ignore the problem. Jael uses this approach, since the only time it's
67used across ships is to update moon keys, which is very low-volume and
67used across ships is to update moon keys, which is very low-volume and
68−less than 1KB per update. If these subscriptions are used for more,
68+less than 1KB per update. If these subscriptions are used for more,
69this strategy will have to be revisited.
69this strategy will have to be revisited.
70
70
71### Buffers
71### Buffers
72
72
73−A common solution to this problem is the venerable buffer. If more than
73+A common solution to this problem is the venerable buffer. If more than
74−N updates need to be sent, start dropping updates. There are several
74+N updates need to be sent, start dropping updates. There are several
75options for what to do when the buffer is full and the publisher wishes
75options for what to do when the buffer is full and the publisher wishes
76to send another message:
76to send another message:
77
77
78−- Drop the oldest message. Particularly suitable for systems where new
78+- Drop the oldest message. Particularly suitable for systems where new
79−messages obsolete old ones. For example, if you just need the latest
79+ messages obsolete old ones. For example, if you just need the latest
80−ticker price for an asset, you could use a buffer size of one and
80+ ticker price for an asset, you could use a buffer size of one and
81−replaced it any time you have a new price.
81+ replaced it any time you have a new price.
82
82
83−- Don't add the new message to the buffer. Semantically this is usually
83+- Don't add the new message to the buffer. Semantically this is usually
84−less helpful, but mechanically it can be simpler and reduce memory
84+ less helpful, but mechanically it can be simpler and reduce memory
85−churn, since the buffer stops changing and new messages are simply
85+ churn, since the buffer stops changing and new messages are simply
86−ignored.
86+ ignored.
87
87
88−- Drop the newest message and close the subscription. Unlike the
88+- Drop the newest message and close the subscription. Unlike the
89−previous two, this is compatible with the principle of exactly-once
89+ previous two, this is compatible with the principle of exactly-once
90−messaging. Specifically, it preserves the guarantee that you won't
90+ messaging. Specifically, it preserves the guarantee that you won't
91−receive two non-consecutive subscription updates, at the cost of making
91+ receive two non-consecutive subscription updates, at the cost of making
92−you resubscribe if you fall behind.
92+ you resubscribe if you fall behind.
93
93
94−Gall subscriptions use the last of these. The buffer is bounded by a
94+Gall subscriptions use the last of these. The buffer is bounded by a
95simple heuristic, and when a subscription exceeds that buffer, it is
95simple heuristic, and when a subscription exceeds that buffer, it is
96closed and the app is expected to resubscribe when they come back
96closed and the app is expected to resubscribe when they come back
97−online. Note that even though the subscription is closed, messages in
97+online. Note that even though the subscription is closed, messages in
98flight cannot be removed until they've been acknowledged since Ames
98flight cannot be removed until they've been acknowledged since Ames
99guarantees exactly-once messaging, so those last few messages will be
99guarantees exactly-once messaging, so those last few messages will be
100stuck in memory until the subscriber comes back online.
100stuck in memory until the subscriber comes back online.
101
101
102Buffers are commonly bounded by size, but this puts constraints on the
102Buffers are commonly bounded by size, but this puts constraints on the
103−types of messages may be sent. They may also be bounded in time: if the
103+types of messages may be sent. They may also be bounded in time: if the
104subscriber stops taking messages for at least X time, the buffer is
104subscriber stops taking messages for at least X time, the buffer is
105−full. Gall taks a hybrid approach; currently the heuristic is that the
105+full. Gall taks a hybrid approach; currently the heuristic is that the
106buffer counts as full if it has at least five messages and it has been
106buffer counts as full if it has at least five messages and it has been
10730 seconds since a message was acknowledged.
10730 seconds since a message was acknowledged.
108
108
109### One at a time
109### One at a time
110
110
111−Another scheme is to avoid multi-message subscriptions. Instead of
111+Another scheme is to avoid multi-message subscriptions. Instead of
112allowing the subscriber to subscribe to all future updates on a path,
112allowing the subscriber to subscribe to all future updates on a path,
113−allow them to "subscribe" to the *next* update only. When they get that
113+allow them to "subscribe" to the _next_ update only. When they get that
114update, they subscribe to the new next update, so that they ultimately
114update, they subscribe to the new next update, so that they ultimately
115get every message.
115get every message.
116
116
@@ -122,41 +122,41 @@ This is near the theoretical ideal for memory usage, since you'll never
122queue up several messages to send to the subscriber.
122queue up several messages to send to the subscriber.
123
123
124It also encourages processing each update in order rather than zooming
124It also encourages processing each update in order rather than zooming
125−forward from time to time. It's possible (if a little awkward) to
125+forward from time to time. It's possible (if a little awkward) to
126simulate this with buffers though, and it's possible to allow zooming
126simulate this with buffers though, and it's possible to allow zooming
127forward in the one-at-a-time scheme by having the requests be "most
127forward in the one-at-a-time scheme by having the requests be "most
128recent after update N" instead of "next after update N".
128recent after update N" instead of "next after update N".
129
129
130This scheme is at its strongest, then, when you're already storing
130This scheme is at its strongest, then, when you're already storing
131intermediate states or updates, or when you don't care about
131intermediate states or updates, or when you don't care about
132−intermediate states and always send the most recent one. Otherwise,
132+intermediate states and always send the most recent one. Otherwise,
133buffers are a convenient place to temporarily store updates that you
133buffers are a convenient place to temporarily store updates that you
134−don't want to store internally. Of course, if it's semantically
134+don't want to store internally. Of course, if it's semantically
135important that you give each update separately, buffers won't save you
135important that you give each update separately, buffers won't save you
136from having to store the intermediate updates, since they may fill up.
136from having to store the intermediate updates, since they may fill up.
137
137
138Another conceptual advantage is that it has no notion of "connectivity".
138Another conceptual advantage is that it has no notion of "connectivity".
139−It operates forever in a single mode. By contrast, buffer-based
139+It operates forever in a single mode. By contrast, buffer-based
140solutions must keep track of whether the buffer is full and react to
140solutions must keep track of whether the buffer is full and react to
141−that. This increases complexity in the system, and complexity is the
141+that. This increases complexity in the system, and complexity is the
142great evil.
142great evil.
143
143
144The biggest disadvantage of this system is that it takes much longer to
144The biggest disadvantage of this system is that it takes much longer to
145−process many small updates. With buffers, the publisher could have a
145+process many small updates. With buffers, the publisher could have a
146dozen small updates in flight at the same time, while in this scheme
146dozen small updates in flight at the same time, while in this scheme
147they would only send one at a time, waiting for a response between each
147they would only send one at a time, waiting for a response between each
148−one. Losing this pipelining can be quite significant for some
148+one. Losing this pipelining can be quite significant for some
149applications, but for low-volume subscriptions (certainly anything that
149applications, but for low-volume subscriptions (certainly anything that
150updates less than once per minute) this will have no noticeable effect.
150updates less than once per minute) this will have no noticeable effect.
151
151
152−Clay uses this scheme. It's low-volume, it stores all previous states
152+Clay uses this scheme. It's low-volume, it stores all previous states
153anyway (since it's a revision-control system), and it's sometimes
153anyway (since it's a revision-control system), and it's sometimes
154important to get updates one at a time (for example when downloading OTA
154important to get updates one at a time (for example when downloading OTA
155−software updates). Ships that send OTA updates often have many ships
155+software updates). Ships that send OTA updates often have many ships
156subscribed to them, and the updates themselves may be large, so it's
156subscribed to them, and the updates themselves may be large, so it's
157important they don't queue up when ships inevitably disappear.
157important they don't queue up when ships inevitably disappear.
158
158
159I tend to think most Gall subscriptions should follow this pattern as
159I tend to think most Gall subscriptions should follow this pattern as
160−well. Our most latency-sensitive subscriptions are chat messages, and
160+well. Our most latency-sensitive subscriptions are chat messages, and
161while I haven't tested it, I would guess that even those wouldn't be
161while I haven't tested it, I would guess that even those wouldn't be
162affected by this scheme.
162affected by this scheme.
content/docs/arvo/dill/_index.md+16
@@ -5,3 +5,19 @@ sort_by = "weight"
5template = "sections/docs/chapters.html"
5template = "sections/docs/chapters.html"
6insert_anchor_links = "right"
6insert_anchor_links = "right"
7+++
7+++
8+
9+[Overview](/docs/avro/dill/dill)
10+
11+A brief overview of the Dill vane.
12+
13+[API Reference](/docs/arvo/dill/tasks)
14+
15+The `task`s Dill takes and the `gift`s it returns.
16+
17+[Scry Reference](/docs/arvo/dill/scry)
18+
19+The scry endpoints of Dill.
20+
21+[Data Types](/docs/arvo/dill/data-types)
22+
23+Reference documentation of the data types used by Dill.
content/docs/arvo/dill/data-types.mdnew file+187
@@ -0,0 +1,187 @@
1++++
2+title = "Data Types"
3+weight = 4
4+template = "doc.html"
5++++
6+
7+Here are the data types used by Dill, as defined in `/sys/lull.hoon`.
8+
9+## `$blew`
10+
11+```hoon
12+ +$ blew [p=@ud q=@ud]
13+```
14+
15+Terminal dimension; `p` is columns, `q` is rows. This structure is passed to Dill by the runtime in a [%blew](/docs/arvo/dill/tasks#blew) `task` whenever the dimensions of the terminal changes.
16+
17+## `$belt`
18+
19+```hoon
20++$ belt
21+ $? bolt
22+ $% [%mod mod=?(%ctl %met %hyp) key=bolt]
23+ [%txt p=(list @c)]
24+ [%ctl p=@c]
25+ [%met p=@c]
26+ == ==
27+```
28+
29+Terminal client input.
30+
31+A `$belt` is passed to Dill in a [%belt](/docs/arvo/dill/tasks#belt) `task` by the runtime whenever there is input, such as a user typing in the console. This is only used between the terminal client and Dill, a [$dill-belt](#dill-belt) is used between Dill and Arvo.
32+
33+May either be a [$bolt](#bolt) or one of:
34+
35+- `%mod` - Modifier (Ctrl, Meta or Hyper) plus [key].
36+- `%txt` - A series of characters
37+- `%ctl` - Ctrl+[key], deprecated in favour of `%mod`.
38+- `%met` - Meta+[key], deprecated in favour of `%mod`.
39+
40+## `$bolt`
41+
42+```hoon
43++$ bolt
44+ $@ @c
45+ $% [%aro p=?(%d %l %r %u)]
46+ [%bac ~]
47+ [%del ~]
48+ [%hit r=@ud c=@ud]
49+ [%ret ~]
50+ ==
51+```
52+
53+Simple input.
54+
55+Either a single simple character or one of:
56+
57+- `%aro` - Arrow keys.
58+- `%bac` - Backspace key.
59+- `%del` - Delete key.
60+- `%hit` - Mouse click - `r` is row and `c` is column. Note these are zero-indexed, with `[0 0]` being the _bottom left_ corner.
61+- `%ret` - Return (Enter) key.
62+
63+## `$blit`
64+
65+```hoon
66++$ blit
67+ $% [%bel ~]
68+ [%clr ~]
69+ [%hop p=@ud]
70+ [%klr p=stub]
71+ [%lin p=(list @c)]
72+ [%mor ~]
73+ [%sag p=path q=*]
74+ [%sav p=path q=@]
75+ [%url p=@t]
76+ ==
77+```
78+
79+Terminal client output.
80+
81+A `$blit` is given to the terminal client by Dill in a `%blit` `gift` when it wants to print some text, clear the screen, go _ding_ or what have you.
82+
83+This is only used between Dill and the terminal client, a [$dill-blit](#dill-blit) is used instead between Arvo and Dill.
84+
85+A `$blit` is one of:
86+
87+- `%bel` - Ring the terminal bell.
88+- `%clr` - Clear the screen.
89+- `%hop` - Set cursor position, `p` specifies its position on the prompt line.
90+- `%klr` - Set styled line, the `$stub` specifies the text and style.
91+- `%lin` - Set current line, `p` contains the text.
92+- `%mor` - Newline.
93+- `%sag` - Save to jamfile, typically in `/[pier]/.urb/put/`. `p` is `/[path]/[filename]/[extension]`. For example, `/foo/bar` will save it in `/[pier]/.urb/put/foo.bar`, `/a/b/c/foo/bar` will save it in `/[pier]/.urb/put/a/b/c/foo.bar`, and `/foo` will save it in `/[pier]/.urb/put.foo`. `q` is the `noun` to `jam` and save in the file.
94+- `%sav` - Save to file. Same behaviour as `%sag` except `q` is an `atom` rather than a `noun` and therefore doesn't need to be `jam`med. The `atom` is written to disk as if it were the bytestring in the tail of an `$octs`. That is, `%sav`ing the `cord` `'abcdef'`, whose `@ux` value is `0x6665.6463.6261`, results in a unix file whose hex dump renders as `61 62 63 64 65 66`.
95+- `%url` - Activate URL, `p` is the URL.
96+
97+## `$dill-belt`
98+
99+```hoon
100++$ dill-belt
101+ $% [%aro p=?(%d %l %r %u)]
102+ [%bac ~]
103+ [%cru p=@tas q=(list tank)]
104+ [%ctl p=@]
105+ [%del ~]
106+ [%hey ~]
107+ [%met p=@]
108+ [%ret ~]
109+ [%rez p=@ud q=@ud]
110+ [%txt p=(list @c)]
111+ [%yow p=gill:gall]
112+ ==
113+```
114+
115+Terminal input for Arvo.
116+
117+While [$belt](#belt) is used between the terminal client and Dill, `$dill-belt` is used between Dill and Arvo.
118+
119+a `$dill-belt` is one of:
120+
121+- `%aro` - Arrow keys.
122+- `%bac` - Backspace key.
123+- `%cru` - Echo error, `p` is an error `@tas` and `q` is a traceback.
124+- `%ctl` - Ctrl+[key].
125+- `%del` - Delete key.
126+- `%hey` - Refresh.
127+- `%met` - Meta+[key].
128+- `%ret` - Return key (Enter).
129+- `%rez` - Terminal resized, `p` is columns and `q` is rows.
130+- `%txt` - Text input.
131+- `%yow` - Connect to app.
132+
133+## `$dill-blit`
134+
135+```hoon
136++$ dill-blit
137+ $% [%bel ~]
138+ [%clr ~]
139+ [%hop p=@ud]
140+ [%klr p=stub]
141+ [%mor p=(list dill-blit)]
142+ [%pom p=stub]
143+ [%pro p=(list @c)]
144+ [%qit ~]
145+ [%out p=(list @c)]
146+ [%sag p=path q=*]
147+ [%sav p=path q=@]
148+ [%url p=@t]
149+ ==
150+```
151+
152+Terminal output from Arvo.
153+
154+While [$blit](#blit) is used between Dill and the terminal client, `$dill-blit` is used between Arvo and Dill.
155+
156+A `$dill-blit` is one of:
157+
158+- `%bel` - Terminal bell.
159+- `%clr` - Clear screen.
160+- `%hop` - Set cursor position, `p` is its horizontal position on the prompt line.
161+- `%klr` - Styled text, the `$stub` specifies both the text and style.
162+- `%mor` - Multiple `$dill-blit`.
163+- `%pom` - Styled prompt, the `$stub` specifies both the text and style.
164+- `%pro` - Set prompt, `p` is the text for the prompt.
165+- `%qit` - Close console.
166+- `%out` - Print text.
167+- `%sag` - Save `noun` to jamfile. See [$blit](#blit) section for further details.
168+- `%sav` - Save `atom` to file. See [$blit](#blit) section for further details.
169+- `%url` - Activate URL.
170+
171+## `$flog`
172+
173+```hoon
174++$ flog
175+ $% [%crop p=@ud]
176+ [%crud p=@tas q=(list tank)]
177+ [%heft ~]
178+ [%meld ~]
179+ [%pack ~]
180+ [%text p=tape]
181+ [%verb ~]
182+ ==
183+```
184+
185+Wrapped Dill `task`s.
186+
187+These are a subset of Dill's `task`s which can be wrapped in a `%flog` `task`. See the [API Reference](/docs/arvo/dill/tasks) document for details of each of these `task`s.
content/docs/arvo/dill/dill-api.mddeleted−366
@@ -1,366 +0,0 @@
1−+++
2−title = "API Reference"
3−weight = 10
4−template = "doc.html"
5−+++
6−
7−In this document we describe the public interface for Dill. Namely, we describe
8−each `task` that Dill can be `pass`ed, and which `gift`(s) Dill can `give` in return.
9−
10−Dill is unique among vanes since it is technically the first vane to be booted (though we
11−regard Jael as the "true" first vane). As a result, there are four `task`s in
12−`task:able:dill` for which Dill acts only as a middleman that passes the `task`s
13−directly to the Arvo kernel. Thus we have split this document into a [Dill
14−tasks](#dill-tasks) section and an [Arvo tasks](#arvo-tasks) section.
15−
16−## Dill Tasks
17−
18−
19−### `%belt`
20−
21−Every keystroke entered into the console triggers a `%belt` `task` for Dill which contains information about the keystroke, such as which key was pressed
22−and from which terminal.
23−
24−#### Accepts
25−
26−`%belt` `task`s come in a number of different types, corresponding to different
27−keystrokes. You can find this list in `+dill-belt` in `zuse.hoon`.
28−
29−```hoon
30−++ dill-belt :: new belt
31− $% {$aro p/?($d $l $r $u)} :: arrow key
32− {$bac ~} :: true backspace
33− {$cru p/@tas q/(list tank)} :: echo error
34− {$ctl p/@} :: control-key
35− {$del ~} :: true delete
36− {$hey ~} :: refresh
37− {$met p/@} :: meta-key
38− {$ret ~} :: return
39− {$rez p/@ud q/@ud} :: resize, cols, rows
40− {$txt p/(list @c)} :: utf32 text
41− {$yow p/gill:gall} :: connect to app
42− == ::
43−```
44−
45−#### Returns
46−
47−Dill returns no `gift` in response to a `%belt` `task`.
48−
49−
50−### `%blew`
51−
52−This `task` is called whenever the terminal emulator is resized, so that Dill can adjust
53−the text output to fit the new window size.
54−
55−#### Accepts
56−
57−```hoon
58−[p=@ud q=@ud]
59−```
60−
61−`p` is the number of columns and `q` is the number of rows.
62−
63−#### Returns
64−
65−Dill returns no `gift` in response to a `%blew` `task`.
66−
67−
68−### `%boot`
69−
70−This `task` is used only once, when Arvo first enters the [adult
71−stage](/docs/arvo/overview#structural-interface-core). Dill is
72−technically the first vane to be activated, via the `%boot` `task`, which then
73−send Jael (considered the the "true" first vane) an `%init` `task`, which then goes on to
74−call `%init` `task`s for other vanes (including Dill).
75−
76−#### Accepts
77−
78−`%boot` takes an argument that is either `%dawn` or `%fake`. `%dawn` is the one
79−used in any typical scenario and activates the ordinary vane initialization
80−process outlined above, while `%fake` is a debugging tool.
81−
82−#### Returns
83−
84−`%boot` does not return a `gift`.
85−
86−
87−
88−### `%crud`
89−
90−This `task` is used by Dill to produce error reports. It prints the received
91−error message(s) (a `(list tank)`) to the terminal. The level of detail of the
92−error message is set by `$log-level`, which is either `%hush`, `%soft`, or `%loud`.
93−
94−#### Accepts
95−
96−```hoon
97−[err=@tas tac=(list tank)]
98−```
99−
100−`err` is the type of error and `tac` is the associated error message.
101−
102−#### Returns
103−
104−`%crud` does not return a `gift`.
105−
106−
107−### `%flog`
108−
109−A `%flog` `task` is a wrapper over a `task` sent by another vane. Dill removes the wrapper
110−and sends the bare `task` to itself over the default `duct`.
111−
112−#### Accepts
113−
114−`%flog` `task`s can take any valid Dill `task` as an argument.
115−
116−#### Returns
117−
118−`%flog` never returns a `gift` on its own, but the wrapped `task` might.
119−
120−#### Example
121−
122−`%crud` `task`s from other vanes are typically passed to Dill wrapped in a
123−`%flog` `task` to print errors to the terminal.
124−
125−
126−
127−### `%flow`
128−
129−This `task` is not used.
130−
131−
132−### `%hail`
133−
134−`%hail` refreshes the terminal by sending an empty message to the default duct
135−for Dill,
136−causing the terminal to redraw itself (?)
137−
138−#### Accepts
139−
140−```hoon
141−[ ~ ]
142−```
143−
144−#### Returns
145−
146−`%hail` returns no `gift`s.
147−
148−
149−### `%heft`
150−
151−`%heft` causes Dill to `pass` a `%wegh` `task` to all other vanes (but not to
152−itself), thus obtaining a complete digest of Arvo's memory usage.
153−
154−#### Accepts
155−
156−```hoon
157−[ ~ ]
158−```
159−
160−#### Returns
161−
162−`%heft` does not directly return any `gift`s, but each `%wegh` `task` sent will
163−return a `%mass` `gift`.
164−
165−
166−### `%hook`
167−
168−This task is not used.
169−
170−
171−### `%harm`
172−
173−This `task` is not used.
174−
175−
176−### `%init`
177−
178−This `task` is called only once, when Arvo first enters the [adult
179−stage](/docs/arvo/overview#structural-interface-core). It performs
180−initial setup for Dill, such as setting the width of the console.
181−
182−Note that this is not actually the first `task` passed to Dill - see [%boot](#%boot).
183−
184−#### Accepts
185−
186−`%init` takes no arguments.
187−
188−#### Returns
189−
190−`%init` returns no `gift`s.
191−
192−
193−### `%knob`
194−
195−`%knob` sets the verbosity level for each error tag.
196−
197−#### Accepts
198−
199−```hoon
200−[tag=@tas level=log-level]
201−```
202−
203−`tag` is the error tag. `level` is the verbosity, set to either `%hush`,
204−`%soft`, or `%loud`.
205−
206−#### Returns
207−
208−`%knob` does not return a gift.
209−
210−
211−
212−
213−### `%noop`
214−
215−`%noop` does nothing - it stands for "no operation".
216−
217−#### Accepts
218−
219−```hoon
220−[ ~ ]
221−```
222−
223−#### Returns
224−
225−This `task`, predictably, returns nothing.
226−
227−#### Example
228−
229−This can be useful if a shell command requires a Dill `task` but you don't want
230−Dill to do anything.
231−
232−
233−
234−### `%talk`
235−
236−This `task` is not used.
237−
238−### `%text`
239−
240−This `task` prints a `tape` to the dojo by first converting it from a UTF8
241−`tape` to a `list` of UTF32 codepoints (`@c`'s) and then recursively popping off a character from the
242−`tape` and sending it to to Unix to be printed into the terminal via a `%blit` event.
243−
244−#### Accepts
245−
246−```hoon
247−[p=tape]
248−```
249−
250−#### Returns
251−
252−This `task` returns zero or more `%blit` `gift`s, each containing a .
253−
254−
255−### `%trim`
256−
257−`%trim` is a common vane `task` used to reduce memory usage. However, it does
258−nothing for Dill.
259−
260−#### Accepts
261−
262−```hoon
263−[p=@ud]
264−```
265−
266−This is a common parameter for `%trim` `task`s across all vanes but does nothing
267−for Dill.
268−
269−#### Returns
270−
271−This `task` returns no `gift`s.
272−
273−
274−
275−### `%vega`
276−
277−This is a common vane `task` used to inform the vane that the kernel has been
278−upgraded. Dill does not do anything in response to this.
279−
280−#### Accepts
281−
282−```hoon
283−[ ~ ]
284−```
285−
286−#### Returns
287−
288−This `task` returns no `gift`s.
289−
290−
291−
292−## Arvo tasks
293−
294−These `task`s live in `task:able:dill` but are passed directly to the Arvo
295−kernel for processing.
296−
297−### `%lyra`
298−
299−This `task` updates the kernel.
300−
301−#### Accepts
302−
303−```hoon
304−[p=@t q=@t]
305−```
306−
307−`p` is the contents of the new `hoon.hoon` and `q` is the contents of the new `arvo.hoon`.
308−
309−#### Returns
310−
311−This `task` returns no `gift`s.
312−
313−
314−### `%pack`
315−
316−This `task` defragments and deduplicates Arvo's memory. This is ultimately
317−performed by the interpreter so you won't find the code in `arvo.hoon` but
318−rather under `c3__pack` in `urbit/worker/main.c`.
319−
320−#### Accepts
321−
322−```hoon
323−[ ~ ]
324−```
325−
326−#### Returns
327−
328−This `task` returns no `gift`s.
329−
330−
331−### `%veer`
332−
333−This `task` is used to install `zuse` and vanes. It is handled by `+veer` in
334−`arvo.hoon`.
335−
336−#### Accepts
337−
338−```hoon
339−[p=@ta q=path r=@t]
340−```
341−
342−`p` is the vane letter, `q` is the formal `path` to the
343−vane, and `r` is the source code for the vane. The vane letter is `%` followed
344−by the first letter of the vane in lowercase, such as `%d` for Dill. `p=%$` in
345−the case of `zuse`.
346−
347−#### Returns
348−
349−This `task` returns no `gift`s.
350−
351−
352−### `%verb`
353−
354−This `task` toggles verbose mode for all of Arvo, which is located here since
355−Dill is the vane that prints errors. To be precise, `%verb` toggles the laconic
356−bit `lac` in the [Arvo state](/docs/arvo/overview#the-state).
357−
358−#### Accepts
359−
360−```hoon
361−[ ~ ]
362−```
363−
364−#### Returns
365−
366−This `task` returns no `gift`s.
content/docs/arvo/dill/dill.md+35−18
@@ -4,21 +4,38 @@ weight = 1
4template = "doc.html"
4template = "doc.html"
5aliases = ["/docs/learn/arvo/dill/"]
5aliases = ["/docs/learn/arvo/dill/"]
6+++
6+++
7+
7−Our terminal driver.
8+The terminal driver vane.
8−
9+
9−Unix sends keyboard events to `%dill` from either the console or telnet,
10+Keyboard events and the like from Unix are received by Dill as [%belt](/docs/arvo/dill/tasks#belt) `task`s, and Dill sends `%blit` `gift`s containing [$blit](/docs/arvo/dill/data-types#blit)s back to the runtime to be displayed in the Unix terminal. The manner of interacting with Dill differs depending on whether you're in userspace or kernelspace, as we'll explore below.
10−and `%dill` produces terminal output. The only app that should directly
11+
11−talk to `%dill` is the terminal app. Command-line apps are run by,
12+## Kernelspace
12−receive input from, and produce output to, the `%shell` app, which is
13+
13−controlled by `%terminal`, which talks to `%dill`, which talks to unix.
14+For technical reasons, Dill performs a handful of system tasks related to booting a ship and some memory operations. Aside from those, other Vanes mostly just pass Dill [tasks](/docs/arvo/dill/tasks) to print error messages and the like to the terminal.
14−Clay also uses `%dill` directly to print out the filesystem change
15+
15−events, but this is questionable behavior.
16+## Userspace
16−
17+
17−`%dill` has two main components. First, it controls the terminal on a
18+Unlike in kernelspace, userspace applications are unlikely to `%pass` Dill `task`s directly. Instead, Dill looks at things in terms of sessions. A session is a pipeline between a client and a handler, where:
18−very basic, event-by-event level. This includes keeping track of things
19+
19−like the dimensions of the terminal, the prompt type (plain text or
20+- The client is an external input source and output sink; a terminal with with dimensions and so forth.
20−password), which duct to produce effects on, and so forth. Second, it
21+- The handler is an application in Urbit that interprets input, maybe does something with it, maybe produces output to be displayed in the client, etc.
21−handles terminal events, keystroke by keystroke. Most characters are
22+
22−simply pushed onto the buffer and blitted to the screen, but some
23+There are plans for Dill to support multiple independent sessions (i.e. independent terminal clients displaying and processing different information at the same time), but at this stage Dill only supports a single session. The client for this default session is just the Unix terminal via the Urbit runtime. The handler for the default session is the `%hood` app, whose `drum` module does the heavy lifting.
23−characters, including control-modified keys, arrow keys, etc. require
24+
24−special handling. Most of the readline functionality is in `%dill`.
25+`drum` is the CLI app manager. By default you'll have a couple of CLI applications running—`%dojo` and `%chat-cli`—which you can switch between with `ctrl+x`. You may also have additional CLI apps which you have attached with the `|link` command. It's `drum` that keeps track of which one is active, which one input should be routed to, which one should be displayed, what each prompt should look like, and so forth. Dill itself is oblivious to the distinction between these CLI apps. It only sees the default session with `drum`, so it just passes all input to `drum` and display whatever `drum` gives it.
26+
27+While `drum` talks with Dill in `$dill-belt`s and `$dill-blit`s, it talks to CLI apps with `$sole-action`s and `$sole-event`s, which are defined in the `sole` library. For more information on the `sole` library and the related `shoe` library, and for information on how to build CLI apps, you can refer to the [CLI app tutorial](/docs/hoon/guides/cli-tutorial).
28+
29+To give a basic idea of how keyboard events flow through these systems and produce terminal output, here's a diagram showing the messages in pseudo-Hoon:
30+
31+![Dill userspace diagram](https://media.urbit.org/docs/arvo/dill/dill-userspace.svg)
32+
33+You can use a [move trace](/docs/arvo/tutorials/move-trace) to get a hands-on feel for this data flow.
34+
35+## Sections
36+
37+[API Reference](/docs/arvo/dill/tasks) - The `task`s Dill takes and the `gift`s it returns.
38+
39+[Scry Reference](/docs/arvo/dill/scry) - The scry endpoints of Dill.
40+
41+[Data Types](/docs/arvo/dill/data-types) - Reference documentation of the data types used by Dill.
content/docs/arvo/dill/scry.mdnew file+45
@@ -0,0 +1,45 @@
1++++
2+title = "Scry Reference"
3+weight = 3
4+template = "doc.html"
5++++
6+
7+Here are the scry endpoints of Dill. They take a `%x` `care` and require the `desk` in the path prefix be empty, so the general format is `.^([type] %dx /=//=/[some-path])`.
8+
9+Dill only has a couple of scry endpoints, both of which begin with `/session//`. The empty `//` would be where the target session would be specified, but at this stage Dill can only return a result for the default session, so it's always empty.
10+
11+## /sessions//line
12+
13+A scry with a `care` of `%x` and a `path` of `/sessions//line` returns the current text of the prompt line of the default session. The type returned is a [$blit](/docs/arvo/dill/data-types#blit).
14+
15+#### Example
16+
17+```
18+> .^(blit:dill %dx /=//=/sessions//line)
19+[ %lin
20+ p
21+ ~[
22+ ~-~~
23+ ~-z
24+ ~-o
25+ ~-d
26+ ~-~3a.
27+ ~-d
28+ ~-o
29+ ~-j
30+ ~-o
31+ ...truncated for brevity...
32+ ]
33+]
34+```
35+
36+## /sessions//cursor
37+
38+A scry with a `care` of `%x` and a `path` of `/sessions//cursor` returns the current horizontal position of the cursor in the default session. The type returned is a `@ud`.
39+
40+#### Example
41+
42+```
43+> .^(@ud %dx /=//=/sessions//cursor)
44+44
45+```
content/docs/arvo/dill/tasks.mdnew file+342
@@ -0,0 +1,342 @@
1++++
2+title = "API Reference"
3+weight = 2
4+template = "doc.html"
5++++
6+
7+In this document we describe the public interface for Dill. Namely, we describe each `task` that Dill can be `pass`ed, and which `gift`(s) Dill can `give` in return.
8+
9+## `%belt`
10+
11+```hoon
12+[%belt p=belt]
13+```
14+
15+Terminal input.
16+
17+The runtime sends a `%belt` `task` to Dill whenever there is input in the terminal, such as a keystroke.
18+
19+The [$belt](/docs/arvo/dill/data-types#belt) in `p` contains the input such as which key was pressed.
20+
21+Dill will convert the `$belt` into a [$dill-belt](/docs/arvo/dill/data-types#dill-belt) and `%poke` the session handler (typically `drum`) with it.
22+
23+This `task` would not typically be used from userspace.
24+
25+#### Returns
26+
27+Dill returns no `gift` in response to a `%belt` `task`.
28+
29+## `%blew`
30+
31+```hoon
32+[%blew p=blew]
33+```
34+
35+Terminal resized.
36+
37+The runtime passes Dill a `%blew` `task` whenever the terminal is resized.
38+
39+The [$blew](/docs/arvo/dill/data-types#blew) specifies the new dimensions.
40+
41+Dill will convert the `$blew` into a `%rez` [$dill-belt](/docs/arvo/dill/data-types#dill-belt) and `%poke`s the session handler (typically `drum`) with it.
42+
43+This `task` would not typically be used from userspace.
44+
45+#### Returns
46+
47+Dill returns no `gift` in response to a `%blew` `task`.
48+
49+## `%boot`
50+
51+```hoon
52+[%boot lit=? p=*]
53+```
54+
55+This `task` is used only once, when Arvo first enters the [adult stage](/docs/arvo/overview#structural-interface-core). Dill is technically the first vane to be activated, via the `%boot` `task`, which then sends Jael (considered the "true" first vane) the `%dawn` or `%fake` `task` wrapped in the `%boot` `task`. Jael then goes on to call `%init` `task`s for other vanes (including Dill).
56+
57+`lit` specifies whether to boot in lite mode. `p` is either a [%dawn](/docs/arvo/jael/data-types#dawn) or [%fake](/docs/arvo/jael/tasks#fake) `task:jael`. `%dawn` is for an ordinary boot and `%fake` is for booting a fake ship.
58+
59+This `task` would not be used from userspace.
60+
61+#### Returns
62+
63+Dill returns no `gift` in response to a `%boot` `task`, but it will `%pass` the wrapped `%dawn` or `%fake` `task` to Jael.
64+
65+## `%crop`
66+
67+```hoon
68+[%crop p=@ud]
69+```
70+
71+Trim kernel state.
72+
73+This `task` is the same as the [%trim](#trim) `task`. Like `%trim`, Dill does nothing with it.
74+
75+#### Returns
76+
77+Dill returns no `gift` in response to a `%crop` `task`.
78+
79+## `%crud`
80+
81+```hoon
82+[%crud p=@tas q=(list tank)]
83+```
84+
85+Print error.
86+
87+Dill prints the given error to the terminal. The verbosity for the particular `@tas` error tag specified in `p` is determined by the `level` set by a [%knob](#knob) `task` - either `%hush`, `%soft` or `%loud`. The default is `%loud`, where it will print the full `(list tank)` specified in `q`. See [%knob](#knob) for details of verbosity levels.
88+
89+#### Returns
90+
91+Dill does not return a `gift` in response to a `%crud` `task`.
92+
93+## `%flee`
94+
95+```hoon
96+[%flee session=~]
97+```
98+
99+Unwatch a session to which you've previously subscribed with [%view](#view).
100+
101+The ability to specify a session is not yet implemented in Dill, so `session` is always `~`, the default session.
102+
103+#### Returns
104+
105+Dill does not return a `gift` in response to a `%flee` `task`.
106+
107+## `%flog`
108+
109+```hoon
110+[%flog p=flog]
111+```
112+
113+A `%flog` `task` is a wrapper over a `task` sent by another vane. Dill removes the wrapper and sends the bare `task` to itself over the default `duct`.
114+
115+A `%flog` `task` takes a [$flog](/docs/arvo/dill/data-types#flog) as its argument. A `$flog` is a subset of Dill's `task`s.
116+
117+#### Returns
118+
119+Dill does not return a `gift` in response to a `%flog` `task`.
120+
121+## `%flow`
122+
123+```hoon
124+[%flow p=@tas q=(list gill:gall)]
125+```
126+
127+Terminal config.
128+
129+This `task` is not used.
130+
131+## `%hail`
132+
133+```hoon
134+[%hail ~]
135+```
136+
137+Refresh.
138+
139+Dill converts a `%hail` `task` into a `%hey` [$dill-belt](/docs/arvo/dill/data-types#dill-belt) and `%poke`s the session handler (typically `drum`) with it to handle the refresh.
140+
141+This `task` would not be used from userspace.
142+
143+#### Returns
144+
145+Dill returns no `gift` in response to a `%hail` `task`.
146+
147+## `%heft`
148+
149+```hoon
150+[%heft ~]
151+```
152+
153+Produce memory report.
154+
155+When Dill receives a `%heft` `task` it passes Arvo a `%whey` `waif` to obtain a memory report and prints it to the terminal.
156+
157+#### Returns
158+
159+Dill does not return a `gift` in response to a `%heft` `task`.
160+
161+## `%hook`
162+
163+```hoon
164+[%hook ~]
165+```
166+
167+This terminal hung up.
168+
169+This task is not used.
170+
171+## `%harm`
172+
173+```hoon
174+[%harm ~]
175+```
176+
177+All terminals hung up.
178+
179+This `task` is not used.
180+
181+## `%init`
182+
183+```hoon
184+[%init ~]
185+```
186+
187+This `task` is called only once, when Arvo first enters the [adult stage](/docs/arvo/overview#structural-interface-core). It performs initial setup for Dill, such as setting the width of the console.
188+
189+Note that this is not actually the first `task` passed to Dill - see [%boot](#%boot).
190+
191+This `task` would not be used from userspace.
192+
193+#### Returns
194+
195+Dill does not return a `gift` in response to a `%init` `task`.
196+
197+## `%meld`
198+
199+```
200+[%meld ~]
201+```
202+
203+Deduplicate persistent state.
204+
205+Dill asks the runtime to perform the memory deduplication.
206+
207+#### Returns
208+
209+Dill does not return a `gift` in response to a `%meld` `task`.
210+
211+## `%noop`
212+
213+```hoon
214+[%noop ~]
215+```
216+
217+No operation.
218+
219+A `%noop` `task` does nothing, as the name implies.
220+
221+#### Returns
222+
223+Dill does not return a `gift` in response to a `%noop` `task`.
224+
225+## `%pack`
226+
227+```hoon
228+[%pack ~]
229+```
230+
231+Defragment persistent state.
232+
233+Dill asks the runtime to perform the defragmentation.
234+
235+#### Returns
236+
237+Dill does not return a `gift` in response to a `%meld` `task`.
238+
239+## `%talk`
240+
241+```hoon
242+[%talk p=tank]
243+```
244+
245+This `task` is not used.
246+
247+## `%text`
248+
249+```hoon
250+[%text p=tape]
251+```
252+
253+Print `tape` to terminal.
254+
255+Upon receiving a `%text` `task`, Dill will convert the `tape` given in `p` to a `(list @c)` and give it to the runtime in a `%blit` `gift` including a `%lin` [$blit](/docs/arvo/dill/data-types#blit).
256+
257+#### Returns
258+
259+Dill does not return a `gift` in response to a `%text` `task`, but it does give a `%blit` `gift` to the runtime which looks like:
260+
261+```hoon
262+[%blit p=(list blit)]
263+```
264+
265+## `%view`
266+
267+```hoon
268+[%view session=~]
269+```
270+
271+Watch session.
272+
273+A `%view` `task` subscribes for a copy of all `%blit` `gift`s which Dill `%give`s for the default session. This `task` is used by the `%herm` app so it can convert the `$blit`s to JSON and render them in the web terminal.
274+
275+The ability to specify a session is not yet implemented in Dill, so `session` is always `~`, the default session.
276+
277+#### Returns
278+
279+Dill will `%give` a copy of all `%blit`s for the default session. A `%blit` `gift` is:
280+
281+```hoon
282+[%blit p=(list blit)]
283+```
284+
285+## `%trim`
286+
287+```hoon
288+[%trim p=@ud]
289+```
290+
291+`%trim` is a common vane `task` used to reduce memory usage. It does nothing for Dill because Dill only keeps a minimal necessary state.
292+
293+#### Returns
294+
295+Dill does not return a `gift` in response to a `%trim` `task`.
296+
297+## `%vega`
298+
299+```hoon
300+[%vega ~]
301+```
302+
303+This is a common vane `task` used to inform the vane that the kernel has been
304+upgraded. Dill does not do anything in response to this.
305+
306+This `task` would not be used from userspace.
307+
308+#### Returns
309+
310+Dill returns no `gift` in response to a `%vega` `task`.
311+
312+## `%verb`
313+
314+```hoon
315+[%verb ~]
316+```
317+
318+This `task` toggles verbose mode for all of Arvo, which is located here since
319+Dill is the vane that prints errors. To be precise, `%verb` toggles the laconic
320+bit `lac` in the [Arvo state](/docs/arvo/overview#the-state) by passing a `%verb` `waif` to Arvo.
321+
322+#### Returns
323+
324+Dill does not return a `gift` in response to a `%verb` `task`.
325+
326+## `%knob`
327+
328+```hoon
329+[%knob tag=term level=?(%hush %soft %loud)]
330+```
331+
332+`%knob` sets the verbosity level for each error tag. The error `tag` can be any `@tas`. The given `tag` and `level` will be added to Dill's `veb` which maps tags to levels. Subsequent [%crud](#crud) `task`s will then print with the specified verbosity.
333+
334+The `level`s behave like so:
335+
336+- `%hush` - Completely silent, print nothing.
337+- `%soft` - Just print `crud: %error-tag event failed`, ignore any `tang` given in the `%crud`.
338+- `%loud` - Print the `%soft` message as well as the full `tang` given in the `%crud` `task`.
339+
340+#### Returns
341+
342+Dill does not return a `gift` in response to a `%knob` `task`.
content/docs/arvo/eyre/_index.md+1−1
@@ -26,6 +26,6 @@ The scry endpoints of Eyre.
26
26
27Reference documentation of the various data types used by Eyre.
27Reference documentation of the various data types used by Eyre.
28
28
29−## [Examples](/docs/arvo/eyre/examples)
29+## [Guide](/docs/arvo/eyre/guide)
30
30
31Practical examples of the different ways of using Eyre.
31Practical examples of the different ways of using Eyre.
content/docs/arvo/eyre/external-api-ref.md+4−4
@@ -4,7 +4,7 @@ weight = 2
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−This document contains reference information about Eyre's external APIs including [the channel system](#channels) and [scries](#scry). Each section will also have practical examples in the [Examples](/docs/arvo/eyre/examples) document.
7+This document contains reference information about Eyre's external APIs including [the channel system](#channels) and [scries](#scry). Each section will also have practical examples in the [Guide](/docs/arvo/eyre/guide) document.
8
8
9## Authentication
9## Authentication
10
10
@@ -14,7 +14,7 @@ To use Eyre's channel system, run threads or perform scries you must first obtai
14| ----------- | -------------------------------------- | ---------- | ----------------------------------------------------------------------------------- |
14| ----------- | -------------------------------------- | ---------- | ----------------------------------------------------------------------------------- |
15| `POST` | `password=lidlut-tabwed-pillex-ridrup` | `/~/login` | The password is your web login code which can be obtained with `+code` in the dojo. |
15| `POST` | `password=lidlut-tabwed-pillex-ridrup` | `/~/login` | The password is your web login code which can be obtained with `+code` in the dojo. |
16
16
17−See the [examples](/docs/arvo/eyre/examples#authenticating) for an example of how to do this using the curl.
17+See the [Guide](/docs/arvo/eyre/guide#authenticating) for an example of how to do this using the curl.
18
18
19Eyre's response will include a `set-cookie` header like:
19Eyre's response will include a `set-cookie` header like:
20
20
@@ -51,7 +51,7 @@ All the events that Eyre sends you on a channel must be [ack](#ack)ed so that Ey
51
51
52When you're finished with a channel, you can send Eyre a [delete action](#delete-channel) to close it.
52When you're finished with a channel, you can send Eyre a [delete action](#delete-channel) to close it.
53
53
54−See the [Using the Channel System](/docs/arvo/eyre/examples#using-the-channel-system) section of the [Examples](/docs/arvo/eyre/examples) document for a practical example.
54+See the [Using the Channel System](/docs/arvo/eyre/guide#using-channels) section of the [Guide](/docs/arvo/eyre/guide) document for a practical example.
55
55
56### HTTP Requests
56### HTTP Requests
57
57
@@ -352,7 +352,7 @@ The `{mark}` is the type you want returned. It needn't just be `json` as with th
352
352
353If your session cookie is invalid or missing, Eyre will respond with a 403 Forbidden status. If the scry endpoint cannot be found, Eyre will respond with a 404 Missing status. If the `mark` conversions can't be done, Eyre will respond with a 500 Internal Server Error status. Otherwise, Eyre will respond with a 200 OK status with the requested data in the body of the HTTP response.
353If your session cookie is invalid or missing, Eyre will respond with a 403 Forbidden status. If the scry endpoint cannot be found, Eyre will respond with a 404 Missing status. If the `mark` conversions can't be done, Eyre will respond with a 500 Internal Server Error status. Otherwise, Eyre will respond with a 200 OK status with the requested data in the body of the HTTP response.
354
354
355−See the [Scrying](/docs/arvo/eyre/examples#scrying) section of the [Examples](/docs/arvo/eyre/examples) document for a practical example.
355+See the [Scrying](/docs/arvo/eyre/guide#scrying) section of the [Guide](/docs/arvo/eyre/guide) document for a practical example.
356
356
357## Spider
357## Spider
358
358
content/docs/arvo/eyre/eyre.md+5−5
@@ -18,7 +18,7 @@ Eyre's channel system is the primary way of interacting with Gall agents from ou
18
18
19The channel system is designed to be extremely simple with just a handful of `action` and `response` JSON objects to deal. Essentially it's a thin layer on top of the underlying Gall agent interface. You can poke agents, subscribe for updates, etc, just like you would from within Urbit.
19The channel system is designed to be extremely simple with just a handful of `action` and `response` JSON objects to deal. Essentially it's a thin layer on top of the underlying Gall agent interface. You can poke agents, subscribe for updates, etc, just like you would from within Urbit.
20
20
21−Detailed documentation of the channel system's JSON API is provided in the [External API Reference](/docs/arvo/eyre/external-api-ref) document with corresponding examples in the [Examples](/docs/arvo/eyre/examples#using-the-channel-system) document.
21+Detailed documentation of the channel system's JSON API is provided in the [External API Reference](/docs/arvo/eyre/external-api-ref) document with corresponding examples in the [Guide](/docs/arvo/eyre/guide#using-the-channel-system) document.
22
22
23## Scrying
23## Scrying
24
24
@@ -34,19 +34,19 @@ Spider (the Gall agent that manages threads) has an Eyre binding that allows you
34
34
35Generators, which are like Hoon scripts, can also be used through Eyre. Rather than having a predefined JSON API, they instead handle HTTP requests and return HTTP responses directly, and are therefore a more complex case that you're less likely to use.
35Generators, which are like Hoon scripts, can also be used through Eyre. Rather than having a predefined JSON API, they instead handle HTTP requests and return HTTP responses directly, and are therefore a more complex case that you're less likely to use.
36
36
37−Their usage is explained in the [%serve](/docs/arvo/eyre/tasks#serve) section of the [Internal API Reference](/docs/arvo/eyre/tasks) documentation and a practical example is provided in the [Generators](/docs/arvo/eyre/examples#generators) section of the [Examples](/docs/arvo/eyre/examples) document.
37+Their usage is explained in the [%serve](/docs/arvo/eyre/tasks#serve) section of the [Internal API Reference](/docs/arvo/eyre/tasks) documentation and a practical example is provided in the [Generators](/docs/arvo/eyre/guide#generators) section of the [Guide](/docs/arvo/eyre/guide) document.
38
38
39## Direct HTTP Handling With Gall Agents
39## Direct HTTP Handling With Gall Agents
40
40
41As well as the [Channel System](#the-channel-system) and [Scries](#scrying), it's also possible for Gall agents to deal directly with HTTP requests. This method is much more complicated than the channel system so you're unlikely to use it unless you want to build a custom HTTP-based API or something like that.
41As well as the [Channel System](#the-channel-system) and [Scries](#scrying), it's also possible for Gall agents to deal directly with HTTP requests. This method is much more complicated than the channel system so you're unlikely to use it unless you want to build a custom HTTP-based API or something like that.
42
42
43−This method is explained in the [%connect](/docs/arvo/eyre/tasks#connect) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document and a detailed example is provided in the [Direct HTTP Handling With Gall Agents](/docs/arvo/eyre/examples#direct-http-handling-with-gall-agents) section of the [Examples](/docs/arvo/eyre/examples) document.
43+This method is explained in the [%connect](/docs/arvo/eyre/tasks#connect) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document and a detailed example is provided in the [Agents: Direct HTTP](/docs/arvo/eyre/guide#agents-direct-http) section of the [Guide](/docs/arvo/eyre/guide) document.
44
44
45## Cross-Origin Resource Sharing
45## Cross-Origin Resource Sharing
46
46
47Eyre supports both simple [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) requests and OPTIONS preflight requests. It has a CORS registry with three categories - `approved`, `rejected` and `requests`. Eyre will respond positively for origins in its `approved` list and negatively for all others. Eyre will add origins in requests that it doesn't have in either its `approved` or `rejected` lists to its `requests` list. Eyre always allows all methods and headers over CORS.
47Eyre supports both simple [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) requests and OPTIONS preflight requests. It has a CORS registry with three categories - `approved`, `rejected` and `requests`. Eyre will respond positively for origins in its `approved` list and negatively for all others. Eyre will add origins in requests that it doesn't have in either its `approved` or `rejected` lists to its `requests` list. Eyre always allows all methods and headers over CORS.
48
48
49−There are three generators - `+cors-registry`, `|cors-approve`, and `|cors-reject` to view, approve, and deny origins respectively from the dojo. Eyre also has [tasks](/docs/arvo/eyre/tasks) to [approve](/docs/arvo/eyre/tasks#approve-origin) and [reject](/docs/arvo/eyre/tasks#reject-origin) origins programmatically, and a number of [scry endpoints](/docs/arvo/eyre/scry) to query them. Examples are also included in the [Managing CORS Origins](/docs/arvo/eyre/examples#managing-cors-origins) section of the Examples document.
49+There are three generators - `+cors-registry`, `|cors-approve`, and `|cors-reject` to view, approve, and deny origins respectively from the dojo. Eyre also has [tasks](/docs/arvo/eyre/tasks) to [approve](/docs/arvo/eyre/tasks#approve-origin) and [reject](/docs/arvo/eyre/tasks#reject-origin) origins programmatically, and a number of [scry endpoints](/docs/arvo/eyre/scry) to query them. Examples are also included in the [Managing CORS Origins](/docs/arvo/eyre/guide#managing-cors-origins) section of the Guide document.
50
50
51## Sections
51## Sections
52
52
@@ -58,4 +58,4 @@ There are three generators - `+cors-registry`, `|cors-approve`, and `|cors-rejec
58
58
59[Data Types](/docs/arvo/eyre/data-types) - Reference documentation of the various data types used by Eyre.
59[Data Types](/docs/arvo/eyre/data-types) - Reference documentation of the various data types used by Eyre.
60
60
61−[Examples](/docs/arvo/eyre/examples) - Practical examples of the different ways of using Eyre.
61+[Guide](/docs/arvo/eyre/guide) - Practical examples of the different ways of using Eyre.
content/docs/arvo/eyre/examples.md → content/docs/arvo/eyre/guide.mdrenamed+29−23
@@ -1,16 +1,22 @@
1+++
1+++
2−title = "Examples"
2+title = "Guide"
3weight = 6
3weight = 6
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−This documents contains practical examples of the various ways of interacting with Eyre.
7+This document walks through practical examples of the various ways of interacting with Eyre. The [Basic](#basic) sections goes over the common methods of interacting through Eyre from an HTTP client, and the [Advanced](#advanced) section explains how to handle HTTP directly with generators and Gall agents.
8
8
9General documentation of the `task`s and methods described here are available in the [External API Reference](/docs/arvo/eyre/external-api-ref) document and the [Internal API Reference](/docs/arvo/eyre/tasks) document.
9General documentation of the `task`s and methods described here are available in the [External API Reference](/docs/arvo/eyre/external-api-ref) document and the [Internal API Reference](/docs/arvo/eyre/tasks) document.
10
10
11−## Authenticating
11+## Basic
12
12
13+Eyre's channel system is the typical way of interacting with Gall agents from an HTTP client. It provides a simple JSON API for actions like pokes, watches, etc, and an SSE event stream for subscription updates. Additionally, Eyre has a scry interface so you can retrieve data in a more ad-hoc manner. These examples use `curl` to be more language agnostic and to show the nitty-gritty details. In practice you'd probably use an "airlock" library (like [http-api](https://github.com/urbit/urbit/tree/master/pkg/npm/http-api) for Javascript) which abstracts things like ack'ing events, incrementing event IDs, manually composing the JSON for actions, etc.
14+
15+It's advisable to have a read through the [External API Reference](/docs/arvo/eyre/external-api-ref) before going through these examples.
16+
17+### Authenticating
18+
13−In most cases we must obtain a valid session cookie by [authenticating](/docs/arvo/eyre/external-api-ref#authentication) with our web login code (which can be obtained by running `+code` in the dojo) before we can use Eyre's interfaces (such as the channel system or scry interface).
19+You must have a valid session cookie in order to use Eyre's interfaces (such as the channel system or scry interface). If your HTTP client is served from your ship, your browser will automatically add the session cookie it obtained upon login, so there's no need to worry about authentication in practice. If your client does not run in the browser or is not served by your ship, [authenticating](/docs/arvo/eyre/external-api-ref#authentication) with your web login code (which can be obtained by running `+code` in the dojo) is necessary.
14
20
15Here we'll try authenticating with the default fakezod code.
21Here we'll try authenticating with the default fakezod code.
16
22
@@ -32,7 +38,7 @@ set-cookie: urbauth-~zod=0v3.j2062.1prp1.qne4e.goq3h.ksudm; Path=/; Max-Age=6048
32
38
33The `urbauth-....` cookie can be now be included in subsequent requests (e.g. to the channel system) by providing it in a Cookie HTTP header.
39The `urbauth-....` cookie can be now be included in subsequent requests (e.g. to the channel system) by providing it in a Cookie HTTP header.
34
40
35−## Using The Channel System
41+### Using Channels
36
42
37Here we'll look at a practical example of Eyre's channel system. You can refer to the [Channels](/docs/arvo/eyre/external-api-ref#channels) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document for relevant details.
43Here we'll look at a practical example of Eyre's channel system. You can refer to the [Channels](/docs/arvo/eyre/external-api-ref#channels) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document for relevant details.
38
44
@@ -147,7 +153,7 @@ curl --header "Content-Type: application/json" \
147
153
148With our channel deleted, we can now close the connection on the client side.
154With our channel deleted, we can now close the connection on the client side.
149
155
150−## Scrying
156+### Scrying
151
157
152Here we'll look at performing scries through Eyre. You can refer to the [Scry](/docs/arvo/eyre/external-api-ref#scry) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document for relevant details.
158Here we'll look at performing scries through Eyre. You can refer to the [Scry](/docs/arvo/eyre/external-api-ref#scry) section of the [External API Reference](/docs/arvo/eyre/external-api-ref) document for relevant details.
153
159
@@ -198,12 +204,16 @@ Server: urbit/vere-1.5
198set-cookie: urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm; Path=/; Max-Age=604800
204set-cookie: urbauth-~zod=0v1.1pseu.tq7hs.hps2t.ltaf1.tmqjm; Path=/; Max-Age=604800
199content-type: text/html
205content-type: text/html
200
206
201−<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>There was an error while handling the request for /foo/bar/baz.json.</p><code>no scry result</code></body></html>
207+&lt;html>&lt;head>&lt;title>404 Not Found&lt;/title>&lt;/head>&lt;body>&lt;h1>Not Found&lt;/h1>&lt;p>There was an error while handling the request for /foo/bar/baz.json.&lt;/p>&lt;code>no scry result&lt;/code>&lt;/body>&lt;/html>
202```
208```
203
209
204−## Direct HTTP Handling With Gall Agents
210+## Advanced
205
211
206−In many cases you'll just want to interact with Gall agents through the JSON API of the channel system, but it's also possible to bypass all that and just deal with HTTP requests directly. Here we'll take a look at how that practically works.
212+Rather than using things like Eyre's channel system described in the [Basic](#basic) section, it's possible to handle HTTP requests directly in Gall agents or generators. This is useful if you want to implement a custom API or work with `sail` to dynamically compose HTML inside an agent.
213+
214+### Agents: Direct HTTP
215+
216+Here we'll look at handling HTTP requests directly in Gall agents rather than using Eyre's channel system.
207
217
208You can refer to the [%connect](/docs/arvo/eyre/tasks#connect) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document for relevant details.
218You can refer to the [%connect](/docs/arvo/eyre/tasks#connect) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document for relevant details.
209
219
@@ -244,7 +254,7 @@ Note that this example does a lot of things manually for demonstrative purposes.
244 ~& [mark req]
254 ~& [mark req]
245 ?+ method.request.q.req
255 ?+ method.request.q.req
246 =/ data=octs
256 =/ data=octs
247− (as-octs:mimes:html '<h1>405 Method Not Allowed</h1>')
257+ (as-octs:mimes:html '&lt;h1>405 Method Not Allowed&lt;/h1>')
248 =/ content-length=@t
258 =/ content-length=@t
249 (crip ((d-co:co 1) p.data))
259 (crip ((d-co:co 1) p.data))
250 =/ =response-header:http
260 =/ =response-header:http
@@ -262,7 +272,7 @@ Note that this example does a lot of things manually for demonstrative purposes.
262 ::
272 ::
263 %'GET'
273 %'GET'
264 =/ data=octs
274 =/ data=octs
265− (as-octs:mimes:html '<h1>Hello, World!</h1>')
275+ (as-octs:mimes:html '&lt;h1>Hello, World!&lt;/h1>')
266 =/ content-length=@t
276 =/ content-length=@t
267 (crip ((d-co:co 1) p.data))
277 (crip ((d-co:co 1) p.data))
268 =/ =response-header:http
278 =/ =response-header:http
@@ -309,19 +319,15 @@ Note that this example does a lot of things manually for demonstrative purposes.
309Save the above to `/app/eyre-agent.hoon`. Commit it:
319Save the above to `/app/eyre-agent.hoon`. Commit it:
310
320
311```
321```
312−> |commit %home
322+> |commit %base
313>=
323>=
314−+ /~zod/home/2/app/eyre-agent/hoon
324++ /~zod/base/2/app/eyre-agent/hoon
315```
325```
316
326
317...and start it:
327...and start it:
318
328
319```
329```
320−> |start %eyre-agent
321−>=
322−gall: loading %eyre-agent
323−activated app home/eyre-agent
324−[unlinked from [p=~zod q=%eyre-agent]]
330+> |rein %base [& %eyre-agent]
325```
331```
326
332
327Now, first we need to bind a URL to our app. In the `++ on-poke` arm, our agent will send a [%connect](/docs/arvo/eyre/tasks#connect) `task` to Eyre when poked with `%bind`:
333Now, first we need to bind a URL to our app. In the `++ on-poke` arm, our agent will send a [%connect](/docs/arvo/eyre/tasks#connect) `task` to Eyre when poked with `%bind`:
@@ -368,7 +374,7 @@ Content-Type: text/html
368Content-Length: 22
374Content-Length: 22
369transfer-encoding: chunked
375transfer-encoding: chunked
370
376
371−<h1>Hello, World!</h1>%
377+&lt;h1>Hello, World!&lt;/h1>%
372```
378```
373
379
374...which has succeed! This is because the `+on-poke` arm tests for http GET requests and responds with `Hello, World!` when it sees one:
380...which has succeed! This is because the `+on-poke` arm tests for http GET requests and responds with `Hello, World!` when it sees one:
@@ -376,7 +382,7 @@ transfer-encoding: chunked
376```hoon
382```hoon
377 %'GET'
383 %'GET'
378=/ data=octs
384=/ data=octs
379− (as-octs:mimes:html '<h1>Hello, World!</h1>')
385+ (as-octs:mimes:html '&lt;h1>Hello, World!&lt;/h1>')
380=/ content-length=@t
386=/ content-length=@t
381 (crip ((d-co:co 1) p.data))
387 (crip ((d-co:co 1) p.data))
382=/ =response-header:http
388=/ =response-header:http
@@ -424,13 +430,13 @@ Eyre subscribed to /http-response/~.eyre_0v3.1knjk.l544e.5uds6.fn9l2.f8929.
424
430
425This is a very rudimentary app but it demonstrates the basic mechanics of dealing with HTTP requests and serving responses.
431This is a very rudimentary app but it demonstrates the basic mechanics of dealing with HTTP requests and serving responses.
426
432
427−## Generators
433+### Generators
428
434
429Here we'll look at running a generator via Eyre. Eyre doesn't have a mediated JSON API for generators, instead it just passes through the HTTP request and returns the HTTP response composed by the generator.
435Here we'll look at running a generator via Eyre. Eyre doesn't have a mediated JSON API for generators, instead it just passes through the HTTP request and returns the HTTP response composed by the generator.
430
436
431You can refer to the [%serve](/docs/arvo/eyre/tasks#serve) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document for relevant details.
437You can refer to the [%serve](/docs/arvo/eyre/tasks#serve) section of the [Internal API Reference](/docs/arvo/eyre/tasks) document for relevant details.
432
438
433−Here's a very simple generator that will just echo back the body of the request (if available) along with the current datetime. You can save it in the `/gen` directory and `|commit %home`.
439+Here's a very simple generator that will just echo back the body of the request (if available) along with the current datetime. You can save it in the `/gen` directory and `|commit %base`.
434
440
435Note that this example does some things manually for demonstrative purposes. In practice you'd likely want to use a library like `/lib/server.hoon` to cut down on boilerplate code.
441Note that this example does some things manually for demonstrative purposes. In practice you'd likely want to use a library like `/lib/server.hoon` to cut down on boilerplate code.
436
442
@@ -478,7 +484,7 @@ The [$binding](/docs/arvo/eyre/data-types#binding) specifies the site and URL pa
478Let's bind our generator to the `/mygen` URL path with the `|pass` command in the dojo:
484Let's bind our generator to the `/mygen` URL path with the `|pass` command in the dojo:
479
485
480```
486```
481−|pass [%e [%serve `/mygen %home /gen/eyre-gen/hoon ~]]
487+|pass [%e [%serve `/mygen %base /gen/eyre-gen/hoon ~]]
482```
488```
483
489
484Note that Eyre responds with a `%bound` `gift` to indicate whether the binding succeeded but `|pass` doesn't take such responses so it's not shown.
490Note that Eyre responds with a `%bound` `gift` to indicate whether the binding succeeded but `|pass` doesn't take such responses so it's not shown.
content/docs/arvo/eyre/tasks.md+5−5
@@ -6,7 +6,7 @@ template = "doc.html"
6
6
7This document details all the `task`s you're likely to use to interact with Eyre, as well as the `gift`s you'll receive in response.
7This document details all the `task`s you're likely to use to interact with Eyre, as well as the `gift`s you'll receive in response.
8
8
9−The primary way of interacting with Eyre is from the outside with HTTP requests. As a result, most of its `task`s are only used internally and you're unlikely to need to deal with them directly. The ones you may want to use in certain cases are [%connect](#connect), [%serve](#serve), [%disconnect](#disconnect), [%approve-origin](#approve-origin) and [%reject-origin](#reject-origin), and they are also demonstrated in the [Examples](/docs/arvo/eyre/examples) document. The rest are just documented for completeness.
9+The primary way of interacting with Eyre is from the outside with HTTP requests. As a result, most of its `task`s are only used internally and you're unlikely to need to deal with them directly. The ones you may want to use in certain cases are [%connect](#connect), [%serve](#serve), [%disconnect](#disconnect), [%approve-origin](#approve-origin) and [%reject-origin](#reject-origin), and they are also demonstrated in the [Guide](/docs/arvo/eyre/guide) document. The rest are just documented for completeness.
10
10
11Many of the types referenced are detailed in the [Data Types](/docs/arvo/eyre/data-types) document. It may also be useful to look at the `+eyre` section of `/sys/lull.hoon` in Arvo where these `task`s, `gift`s and data structures are defined.
11Many of the types referenced are detailed in the [Data Types](/docs/arvo/eyre/data-types) document. It may also be useful to look at the `+eyre` section of `/sys/lull.hoon` in Arvo where these `task`s, `gift`s and data structures are defined.
12
12
@@ -110,7 +110,7 @@ The `accepted` field says whether the binding succeeded and the `binding` is the
110
110
111#### Example
111#### Example
112
112
113−See the [Direct HTTP Handling With Gall Agents](/docs/arvo/eyre/examples#direct-http-handling-with-gall-agents) section of the [Examples](/docs/arvo/eyre/examples) document for an example.
113+See the [Agents: Direct HTTP](/docs/arvo/eyre/guide#agents-direct-http) section of the [Guide](/docs/arvo/eyre/guide) document for an example.
114
114
115## `%serve`
115## `%serve`
116
116
@@ -146,7 +146,7 @@ Eyre will return a `%bound` `gift` as described at the end of the [%connect](#co
146
146
147#### Example
147#### Example
148
148
149−See the [Generators](/docs/arvo/eyre/examples#generators) section of the [Examples](/docs/arvo/eyre/examples) document for an example.
149+See the [Generators](/docs/arvo/eyre/guide#generators) section of the [Guide](/docs/arvo/eyre/guide) document for an example.
150
150
151## `%disconnect`
151## `%disconnect`
152
152
@@ -192,7 +192,7 @@ Eyre returns no `gift` in response to a `%approve-origin` `task`.
192
192
193#### Example
193#### Example
194
194
195−See the [Managing CORS Origins](/docs/arvo/eyre/examples#managing-cors-origins) section of the [Examples](/docs/arvo/eyre/examples) document for an example.
195+See the [Managing CORS Origins](/docs/arvo/eyre/guide#managing-cors-origins) section of the [Guide](/docs/arvo/eyre/guide) document for an example.
196
196
197## `%reject-origin`
197## `%reject-origin`
198
198
@@ -210,4 +210,4 @@ Eyre returns no `gift` in response to a `%reject-origin` `task`.
210
210
211#### Example
211#### Example
212
212
213−See the [Managing CORS Origins](/docs/arvo/eyre/examples#managing-cors-origins) section of the [Examples](/docs/arvo/eyre/examples) document for an example.
213+See the [Managing CORS Origins](/docs/arvo/eyre/guide#managing-cors-origins) section of the [Guide](/docs/arvo/eyre/guide) document for an example.
content/docs/arvo/gall/data-types.mdnew file+492
@@ -0,0 +1,492 @@
1++++
2+title = "Data Types"
3+weight = 5
4+template = "doc.html"
5++++
6+
7+This document describes the data types for Gall defined in `lull.hoon`.
8+
9+## `bitt`
10+
11+```hoon
12++$ bitt (map duct (pair ship path))
13+```
14+
15+Incoming subscriptions.
16+
17+This is the structure Gall uses to keep track of subscribers to our Gall agent.
18+The `sup` field of a [`bowl`](#bowl) contains the `bitt` for our agent.
19+
20+## `boat`
21+
22+```hoon
23++$ boat
24+ %+ map [=wire =ship =term]
25+ [acked=? =path]
26+```
27+
28+Outgoing subscriptions.
29+
30+This is the structure Gall uses to keep track of subscriptions our agent has
31+initiated. The `wex` field of a [`bowl`](#bowl) contails the `boat` for that
32+agent.
33+
34+The `wire` field is the `wire` which [`sign:agent`](#signagent)s will come in on.
35+The `ship` and `term` fields are the ship and the name of the agent to which our
36+agent has subscribed.
37+
38+The `acked` field is `%.y` if they have acknowledged our subscription request,
39+and `%.n` if they have not. The `path` field is the `path` on the other agent to
40+which our agent has subscribed.
41+
42+## `bowl`
43+
44+```hoon
45++$ bowl :: standard app state
46+ $: $: our=ship :: host
47+ src=ship :: guest
48+ dap=term :: agent
49+ == ::
50+ $: wex=boat :: outgoing subs
51+ sup=bitt :: incoming subs
52+ == ::
53+ $: act=@ud :: change number
54+ eny=@uvJ :: entropy
55+ now=@da :: current time
56+ byk=beak :: load source
57+ == == ::
58+```
59+
60+Additional agent state.
61+
62+A `bowl` is given to the agent core each time an event comes in. The fields are
63+as follows:
64+
65+- `our`: Our ship.
66+- `src`: The ship from which the current request originated.
67+- `dap`: The name of our agent.
68+- `wex`: Outgoing subscriptions. That is, subscriptions our agent has initiated.
69+ See the [`boat`](#boat) section for details of the type.
70+- `sup`: Incoming subscriptions. That is, subscriptions others have made to our
71+ agent. See the [`bitt`](#bitt) section for details of the type.
72+- `act`: The total number of [`move`](/docs/arvo/overview#move)s our agent has
73+ processed so far.
74+- `eny`: 512 bits of entropy.
75+- `now`: The current date-time.
76+- `byk`: The ship, desk and `case` in Clay from which this agent was loaded. The
77+ `case` will be `[%da @da]` where the `@da` is the when the agent was loaded. A
78+ `beak` is a triple of `[ship desk case]`.
79+
80+## `dude`
81+
82+```hoon
83++$ dude term
84+```
85+
86+Agent name.
87+
88+## `gill`
89+
90+```hoon
91++$ gill (pair ship term)
92+```
93+
94+A general contact: A pair of the ship and agent name.
95+
96+## `scar`
97+
98+```hoon
99++$ scar
100+ $: p=@ud
101+ q=(map duct bone)
102+ r=(map bone duct)
103+ ==
104+```
105+
106+Opaque duct - used internally.
107+
108+## `suss`
109+
110+```hoon
111++$ suss (trel dude @tas @da)
112+```
113+
114+Configuration report.
115+
116+## `well`
117+
118+```hoon
119++$ well (pair desk term)
120+```
121+
122+Desk and agent.
123+
124+## `neat`
125+
126+```hoon
127++$ neat
128+ $% [%arvo =note-arvo]
129+ [%agent [=ship name=term] =deal]
130+ [%pyre =tang]
131+ ==
132+```
133+
134+Like a [`note:agent`](#noteagent), except the `%agent` case has a [`deal`](#deal) instead
135+of just a [`task:agent`](#taskagent). This is used for messages that come in over the
136+network and would not be used manually.
137+
138+## `deal`
139+
140+```hoon
141++$ deal
142+ $% [%raw-poke =mark =noun]
143+ task:agent
144+ ==
145+```
146+
147+Like a [`task:agent`](#taskagent) but with the additional case of a raw poke.
148+This is used for messages that come in over the network and would not be used
149+manually.
150+
151+## `unto`
152+
153+```hoon
154++$ unto
155+ $% [%raw-fact =mark =noun]
156+ sign:agent
157+ ==
158+```
159+
160+Like a [`sign:agent`](#signagent) but with the additional case of a raw fact.
161+This is used for messages that come in over the network and would not be used
162+manually.
163+
164+## `agent`
165+
166+```hoon
167+++ agent
168+ =< form
169+ |%
170+```
171+
172+Container for Gall agent types. The most significant arm is
173+[`form:agent`](#formagent), which specifies the structure of the agent itself.
174+There are also some additional structures defined here, mostly defining the
175+kinds of messages agents can send. The different arms of the core in `agent`
176+are considered separately below.
177+
178+### `step:agent`
179+
180+```hoon
181++$ step (quip card form)
182+```
183+
184+A cell of [`card:agent`](#cardagent)s to be sent and a new agent state. This is the
185+type returned by most arms of an agent. A `(quip a b)` is the same as `[(list a) b]`, it's just a more convenient way to specify it.
186+
187+### `card:agent`
188+
189+```hoon
190++$ card (wind note gift)
191+```
192+
193+An effect - typically a message to be sent to another agent or vane. A list of
194+these are returned by most agent arms along with a new state in a
195+[`step:agent`](#stepagent). A `wind` is the following:
196+
197+```hoon
198+++ wind
199+ |$ [a b]
200+ $% [%pass p=path q=a]
201+ [%slip p=a]
202+ [%give p=b]
203+ ==
204+```
205+
206+Gall will not allow a `%slip`, so in practice a `card` will be one of:
207+
208+- `[%pass path note]`
209+- `[%give gift]`
210+
211+For `%pass`, `p` specifies the `wire` on which a response should be returned.
212+See [`note:agent`](#noteagent) and [`gift:agent`](#giftagent) below for details of their
213+types.
214+
215+### `note:agent`
216+
217+```hoon
218++$ note
219+ $% [%agent [=ship name=term] =task]
220+ [%arvo note-arvo]
221+ [%pyre =tang]
222+ ==
223+```
224+
225+The type for messages initiated by our agent. This is opposed to
226+[`gift:agent`](#giftagent), which is the type for responding to other agents or
227+vanes, or for sending out updates to subscribers. The three cases are:
228+
229+- `%agent`: Poke another agent, subscribe to another agent, or cancel a
230+ subscription to another agent. The `ship` and `name` fields are the ship and
231+ agent to which the `task` should be sent. The `task` is the request itself,
232+ see [`task:agent`](#taskagent) below for its possible types.
233+- `%arvo`: Pass a `task` to a vane. The type of a `note-arvo` is:
234+ ```hoon
235+ +$ note-arvo
236+ $~ [%b %wake ~]
237+ $% [%a task:ames]
238+ [%b task:behn]
239+ [%c task:clay]
240+ [%d task:dill]
241+ [%e task:eyre]
242+ [%g task:gall]
243+ [%i task:iris]
244+ [%j task:jael]
245+ [%$ %whiz ~]
246+ [@tas %meta vase]
247+ ==
248+ ```
249+ You can refer to the `/sys/lull.hoon` source code for all the possible vane
250+ tasks, or see each vane's API Reference section in the [Arvo
251+ documentation](/docs/arvo/overview)
252+- `%pyre`: This is for aborting side-effects initiated during agent
253+ installation. The `tang` is an error message.
254+
255+A `note:agent` is always wrapped in a `%pass` [`card:agent`](#cardagent).
256+
257+### `task:agent`
258+
259+```hoon
260++$ task
261+ $% [%watch =path]
262+ [%watch-as =mark =path]
263+ [%leave ~]
264+ [%poke =cage]
265+ [%poke-as =mark =cage]
266+ ==
267+```
268+
269+The types of messages initiated by our agent and sent to another agent. This is
270+in contrast to [`gift:agent`](#giftagent)s, which are responses to incoming
271+messages from agents or updates to agents already subscribed. The five kinds
272+are:
273+
274+- `%watch`: Subscribe to `path` on the target ship and agent.
275+- `%watch-as`: Same as `%watch`, except you ask the target's Gall to convert
276+ subscription updates to the `mark` you specified rather than just giving you
277+ the `mark` produced by the agent.
278+- `%leave`: Cancel subscription. The particular subscription to cancel will be
279+ determined by the `wire` given in the `p` field of the containing `%pass`
280+ [`card:agent`](#cardagent).
281+- `%poke`: Poke the target ship and agent with the given `cage`, which is a pair
282+ of `[mark vase]`.
283+- `%poke-as`: Same as `%poke`, except the `cage` will be converted to the
284+ specified `mark` before sending.
285+
286+A `task:agent` is always wrapped in a `%pass` [`card:agent`](#cardagent).
287+
288+### `gift:agent`
289+
290+```hoon
291++$ gift
292+ $% [%fact paths=(list path) =cage]
293+ [%kick paths=(list path) ship=(unit ship)]
294+ [%watch-ack p=(unit tang)]
295+ [%poke-ack p=(unit tang)]
296+ ==
297+```
298+
299+The types of messages our agent can either send in response to messages from
300+other agents, or send to subscribed agents. This is in contrast to
301+[`task:agent`](#taskagent)s, which are messages to other agents our agent
302+initiates rather than sends in response. The four kinds are:
303+
304+- `%fact`: An update to existing subscribers. The `paths` field specifies which
305+ subscription paths the update should go out to. The `cage` is the data, and is
306+ a `[mark vase]`.
307+- `%kick`: Kick subscriber, ending their subscription. The `paths` field
308+ specifies which paths the subscriber should be kicked from, and the `ship`
309+ field specifies the ship to kick. If the `ship` field is null, all subscribers
310+ on the specified paths are kicked. Gall will automatically remove the
311+ subscription from our agent's [`bitt`](#bitt) (inbound subscription `map`),
312+ and subscriber will no longer receive updates on the `path`s in question.
313+- `%watch-ack`: Acknowledge a subscription request. If `p` is null, it's an ack
314+ (positive acknowledgement), and if `p` is non-null, it's a nack (negative
315+ acknowledgement). Simply crashing will caused Gall to nack a subscription
316+ request, and not crashing but not explicitly producing a `%watch-ack` `gift`
317+ will cause Gall to ack a subscription request. Therefore, you'd typically only
318+ explicitly produce a `%watch-ack` `gift` if you wanted to nack a subscription
319+ request with a custom error in the `tang`.
320+- `%poke-ack`: Acknowledge a poke. If `p` is null, it's an ack, and if `p` is
321+ non-null, it's a nack. Simply crashing will cause Gall to nack a poke, and not
322+ crashing but not explicitly producing a `%poke-ack` `gift` will cause Gall to
323+ ack a poke. Therefore, you'd typically only explicitly produce a `%poke-ack`
324+ `gift` if you wanted to nack a poke with a custom error in the `tang`.
325+
326+A `gift:agent` is always wrapped in a `%give` [`card:agent`](#cardagent).
327+
328+### `sign:agent`
329+
330+```hoon
331++$ sign
332+ $% [%poke-ack p=(unit tang)]
333+ [%watch-ack p=(unit tang)]
334+ [%fact =cage]
335+ [%kick ~]
336+ ==
337+```
338+
339+A `sign` is like a [`gift:agent`](#giftagent) but it's something that comes
340+_in_ to our agent from another agent rather than something we send out. The
341+possible types are:
342+
343+- `%poke-ack`: Another agent has acked (positively acknowledged) or nacked
344+ (negatively acknowledged) a `%poke` [`task:agent`](#taskagent) we previously
345+ sent. It's an ack if `p` is null and a nack if `p` is non-null. The `tang`
346+ contains an error or traceback if it's a nack.
347+- `%watch-ack`: Another agent has acked or nacked a `%watch`
348+ [`task:agent`](#taskagent) (subscription request) we previously sent. It's an
349+ ack if `p` is null and a nack if `p` is non-null. The `tang` contains an error
350+ or traceback if it's a nack. If it's a nack, Gall will automatically remove
351+ the subscription from our agent's [`boat`](#boat) (outbound subscription
352+ map).
353+- `%fact`: An update from another agent to which we've previously subscribed
354+ with a `%watch` [`task:agent`](#taskagent) (subscription request). The `cage`
355+ contains the data, and is a `[mark vase]`.
356+- `%kick`: Our subscription to another agent has been ended, and we'll no longer
357+ receive updates. A `%kick` may be intentional, but it may also happen due to
358+ certain network conditions or other factors. As a result, it's best to try and
359+ resubscribe with another `%watch` [`task:agent`](#taskagent), and if they
360+ nack the `%watch`, we can conclude it was intentional and give up.
361+
362+### `form:agent`
363+
364+```hoon
365+++ form
366+ $_ ^|
367+ |_ bowl
368+ ++ on-init
369+ *(quip card _^|(..on-init))
370+ ::
371+ ++ on-save
372+ *vase
373+ ::
374+ ++ on-load
375+ |~ old-state=vase
376+ *(quip card _^|(..on-init))
377+ ::
378+ ++ on-poke
379+ |~ [mark vase]
380+ *(quip card _^|(..on-init))
381+ ::
382+ ++ on-watch
383+ |~ path
384+ *(quip card _^|(..on-init))
385+ ::
386+ ++ on-leave
387+ |~ path
388+ *(quip card _^|(..on-init))
389+ ::
390+ ++ on-peek
391+ |~ path
392+ *(unit (unit cage))
393+ ::
394+ ++ on-agent
395+ |~ [wire sign]
396+ *(quip card _^|(..on-init))
397+ ::
398+ ++ on-arvo
399+ |~ [wire sign-arvo]
400+ *(quip card _^|(..on-init))
401+ ::
402+ ++ on-fail
403+ |~ [term tang]
404+ *(quip card _^|(..on-init))
405+ --
406+--
407+```
408+
409+This defines the structure of the agent itself. The agent is a door with a [`bowl`](#bowl) as its sample and exactly ten arms. Below we'll describe each arm briefly.
410+
411+#### `on-init`
412+
413+- Accepts: Nothing.
414+- Produces: [`step:agent`](#stepagent)
415+
416+This arm is called when the agent is initially installed.
417+
418+#### `on-poke`
419+
420+- Accepts: `cage`
421+- Produces: [`step:agent`](#stepagent)
422+
423+This arm is called when another agent pokes our agent.
424+
425+#### `on-watch`
426+
427+- Accepts: `path`
428+- Produces: [`step:agent`](#stepagent)
429+
430+This arm is called when another agent subscribes to our agent.
431+
432+#### `on-leave`
433+
434+- Accepts: `path`
435+- Produces: [`step:agent`](#stepagent)
436+
437+This arm is called when another agent unsubscribes from a subscription path on
438+our agent.
439+
440+#### `on-peek`
441+
442+- Accepts: `path`
443+- Produces: `(unit (unit cage))`
444+
445+This arm is called when a [scry](/docs/arvo/concepts/scry) is performed on our
446+agent.
447+
448+#### `on-agent`
449+
450+- Accepts: `[wire sign:agent]`
451+- Produces: [`step:agent`](#stepagent)
452+
453+This arm is called when another agent give our agent a
454+[`sign:agent`](#signagent).
455+
456+#### `on-arvo`
457+
458+- Accepts: `[wire sign-arvo]`
459+- Produces: [`step:agent`](#stepagent)
460+
461+This arm is called when a vane gives our agent a `gift`. A `sign-arvo` is:
462+
463+```hoon
464++$ sign-arvo
465+ $% [%ames gift:ames]
466+ $: %behn
467+ $% gift:behn
468+ $>(%wris gift:clay)
469+ $>(%writ gift:clay)
470+ $>(%mere gift:clay)
471+ $>(%unto gift:gall)
472+ ==
473+ ==
474+ [%clay gift:clay]
475+ [%dill gift:dill]
476+ [%eyre gift:eyre]
477+ [%gall gift:gall]
478+ [%iris gift:iris]
479+ [%jael gift:jael]
480+ ==
481+```
482+
483+You can refer to the `/sys/lull.hoon` source code, or the API Reference of each
484+vane in the [Arvo documentation](/docs/arvo/overview).
485+
486+#### `on-fail`
487+
488+- Accepts: `[term tang]`
489+- Produces: [`step:agent`](#stepagent)
490+
491+This arm is called if certain errors occur in Gall, such as if our agent tries
492+to create a duplicate subscription.
content/docs/userspace/gall/gall-api.md → content/docs/arvo/gall/gall-api.mdrenamed+24−24
@@ -1,6 +1,6 @@
1+++
1+++
2title = "API Reference"
2title = "API Reference"
3−weight = 10
3+weight = 3
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
@@ -296,7 +296,7 @@ List of cards and new agent
296
296
297Expose state for saving.
297Expose state for saving.
298
298
299−This arm is called immediately before the agent is upgraded. It packages the
299+This arm is called immediately before the agent is upgraded. It packages the
300permament state of the agent in a vase for the next version of the agent.
300permament state of the agent in a vase for the next version of the agent.
301Unlike most handlers, this cannot produce effects. It is not a gate and has no input.
301Unlike most handlers, this cannot produce effects. It is not a gate and has no input.
302
302
@@ -319,7 +319,7 @@ Unlike most handlers, this cannot produce effects. It is not a gate and has no i
319
319
320Application upgrade.
320Application upgrade.
321
321
322−This arm is called immediately after the agent is upgraded. It receives
322+This arm is called immediately after the agent is upgraded. It receives
323a vase of the state of the previously-running version of the agent, obtained
323a vase of the state of the previously-running version of the agent, obtained
324from `+on-save`, which allows it to cleanly upgrade from the old agent.
324from `+on-save`, which allows it to cleanly upgrade from the old agent.
325
325
@@ -362,7 +362,7 @@ List of cards and new agent
362
362
363Handle application poke.
363Handle application poke.
364
364
365−This arm is called when the agent is "poked". The input is a cage, so
365+This arm is called when the agent is "poked". The input is a cage, so
366it's a pair of a mark and a dynamic vase.
366it's a pair of a mark and a dynamic vase.
367
367
368#### Accepts
368#### Accepts
@@ -445,16 +445,16 @@ List of cards and new agent.
445Handle new subscriber.
445Handle new subscriber.
446
446
447This arm is called when a program wants to subscribe to the agent on a
447This arm is called when a program wants to subscribe to the agent on a
448−particular path. The agent may or may not need to perform setup steps
448+particular path. The agent may or may not need to perform setup steps
449−to intialize the subscription. It may produce a `%give`
449+to intialize the subscription. It may produce a `%give`
450`%subscription-result` to the subscriber to get it up to date, but after
450`%subscription-result` to the subscriber to get it up to date, but after
451this event is complete, it cannot give further updates to a specific
451this event is complete, it cannot give further updates to a specific
452−subscriber. It must give all further updates to all subscribers on a
452+subscriber. It must give all further updates to all subscribers on a
453specific path.
453specific path.
454
454
455If this arm crashes, then the subscription is immediately terminated.
455If this arm crashes, then the subscription is immediately terminated.
456More specifcally, it never started -- the subscriber will receive a
456More specifcally, it never started -- the subscriber will receive a
457−negative `%watch-ack`. You may also produce an explicit `%kick` to
457+negative `%watch-ack`. You may also produce an explicit `%kick` to
458close the subscription without crashing -- for example, you could
458close the subscription without crashing -- for example, you could
459produce a single update followed by a `%kick`.
459produce a single update followed by a `%kick`.
460
460
@@ -501,11 +501,11 @@ Handle unsubscribe.
501
501
502This arm is called when a program becomes unsubscribed to you.
502This arm is called when a program becomes unsubscribed to you.
503Subscriptions may close because the subscriber intentionally
503Subscriptions may close because the subscriber intentionally
504−unsubscribed, but they also could be closed by an intermediary. For
504+unsubscribed, but they also could be closed by an intermediary. For
505example, if a subscription is from another ship which is currently
505example, if a subscription is from another ship which is currently
506unreachable, Ames may choose to close the subscription to avoid queueing
506unreachable, Ames may choose to close the subscription to avoid queueing
507−updates indefinitely. If the program crashes while processing an
507+updates indefinitely. If the program crashes while processing an
508−update, this may also generate an unsubscription. You should consider
508+update, this may also generate an unsubscription. You should consider
509subscriptions to be closable at any time.
509subscriptions to be closable at any time.
510
510
511#### Accepts
511#### Accepts
@@ -540,8 +540,8 @@ List of cards and new agent.
540Handle scry request.
540Handle scry request.
541
541
542This arm is called when a program reads from the agent's "scry"
542This arm is called when a program reads from the agent's "scry"
543−namespace, which should be referentially transparent. Unlike most
543+namespace, which should be referentially transparent. Unlike most
544−handlers, this cannot perform IO, and it cannot change the state. All
544+handlers, this cannot perform IO, and it cannot change the state. All
545it can do is produce a piece of data to the caller, or not.
545it can do is produce a piece of data to the caller, or not.
546
546
547#### Accepts
547#### Accepts
@@ -568,8 +568,8 @@ The path being scryed for.
568```
568```
569
569
570If this arm produces `[~ ~ data]`, then `data` is the value at the the
570If this arm produces `[~ ~ data]`, then `data` is the value at the the
571−given path. If it produces `[~ ~]`, then there is no data at the given
571+given path. If it produces `[~ ~]`, then there is no data at the given
572−path and never will be. If it produces `~`, then we don't know yet whether
572+path and never will be. If it produces `~`, then we don't know yet whether
573there is or will be data at the given path. The head of the path is known as the
573there is or will be data at the given path. The head of the path is known as the
574`care`. Requests with a care of `%x` should return a vase that matches or is
574`care`. Requests with a care of `%x` should return a vase that matches or is
575convertible to the mark at the end of the scry request. This mark is not
575convertible to the mark at the end of the scry request. This mark is not
@@ -625,8 +625,8 @@ Handle `%pass` card
625This arm is called to handle responses to `%pass` cards to other agents.
625This arm is called to handle responses to `%pass` cards to other agents.
626It will be one of the following types of response:
626It will be one of the following types of response:
627
627
628−- `%poke-ack`: acknowledgment (positive or negative) of a poke. If the
628+- `%poke-ack`: acknowledgment (positive or negative) of a poke. If the
629− value is `~`, then the poke succeeded. If the value is `[~ tang]`,
629+ value is `~`, then the poke succeeded. If the value is `[~ tang]`,
630 then the poke failed, and a printable explanation (eg a stack trace)
630 then the poke failed, and a printable explanation (eg a stack trace)
631 is given in the `tang`.
631 is given in the `tang`.
632
632
@@ -716,7 +716,7 @@ This arm is called to handle responses for `%pass` cards to vanes.
716`wire` is the wire from the `++gift` that triggered `++on-arvo`.
716`wire` is the wire from the `++gift` that triggered `++on-arvo`.
717
717
718`sign` is the response from the vane. The list of possible responses from the
718`sign` is the response from the vane. The list of possible responses from the
719−vanes is statically defined in sys/zuse.hoon (grep for `++ sign-arvo`).
719+vanes is statically defined in sys/zuse.hoon (grep for `++ sign-arvo`).
720
720
721#### Returns
721#### Returns
722
722
@@ -761,9 +761,9 @@ List of cards and new agent.
761Handle error.
761Handle error.
762
762
763If an error happens in `+on-poke`, the crash report goes into the
763If an error happens in `+on-poke`, the crash report goes into the
764−`%poke-ack` response. Similarly, if an error happens in
764+`%poke-ack` response. Similarly, if an error happens in
765`+on-subscription`, the crash report goes into the `%watch-ack`
765`+on-subscription`, the crash report goes into the `%watch-ack`
766−response. If a crash happens in any of the other handlers, the report
766+response. If a crash happens in any of the other handlers, the report
767is passed into this arm.
767is passed into this arm.
768
768
769#### Accepts
769#### Accepts
@@ -821,9 +821,9 @@ subscription content for all subscribers on a given path.
821```
821```
822
822
823`(list path)` is a list of the paths to send the update on. If no path is
823`(list path)` is a list of the paths to send the update on. If no path is
824− given, then the update is only given to the program that instigated the
824+given, then the update is only given to the program that instigated the
825− request. Typical use of this mode is in `+on-watch` to give an initial update
825+request. Typical use of this mode is in `+on-watch` to give an initial update
826− to a new subscriber to get them up to date.
826+to a new subscriber to get them up to date.
827
827
828`cage` is a cage of the subscription update.
828`cage` is a cage of the subscription update.
829
829
@@ -938,7 +938,7 @@ This note is given to subscribe to an application at a path
938
938
939Unsubscribe from an application.
939Unsubscribe from an application.
940
940
941− This note is passed to unsubscribe from an application. It should be passed on
941+This note is passed to unsubscribe from an application. It should be passed on
942the same wire that the corresponding `%watch` note for the subscription was
942the same wire that the corresponding `%watch` note for the subscription was
943passed on.
943passed on.
944
944
content/docs/userspace/gall/gall.md → content/docs/arvo/gall/gall.mdrenamed

The content is the same.

content/docs/arvo/gall/overview.mddeleted−11
@@ -1,11 +0,0 @@
1−+++
2−title = "Overview"
3−weight = 1
4−template = "doc.html"
5−+++
6−
7−**Gall** is the application-management [vane](/docs/glossary/vane). Userspace apps –⁠ daemons, really –⁠ are started, stopped, and sandboxed by Gall. Gall provides developers with a consistent interface for connecting their app to [Arvo](/docs/arvo/arvo). It allows applications and other vanes to send messages to applications and subscribe to data streams. Messages coming into Gall are routed to the intended application, and the response comes back along the same route. If the intended target is on another [ship](/docs/glossary/ship), Gall will route it behind the scenes through [Ames](/docs/arvo/ames/ames) to the other ship.
8−
9−Gall is located at `/home/sys/vane/gall.hoon` within Arvo.
10−
11−For more details, see the [userspace](/docs/userspace/gall/gall) section.
content/docs/arvo/iris/example.md+1−1
@@ -4,7 +4,7 @@ weight = 4
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−Here we'll look at a simple example of fetching a remote HTTP resource with Iris. We'll use the following thread, which you can save in the `/ted` directory of your `%home` desk:
7+Here we'll look at a simple example of fetching a remote HTTP resource with Iris. We'll use the following thread, which you can save in the `/ted` directory of your `%base` desk:
8
8
9`iris-thread.hoon`
9`iris-thread.hoon`
10
10
content/docs/arvo/jael/examples.md+3−3
@@ -32,7 +32,7 @@ Here we'll look at subscribing to private key updates from Jael. We'll use a thr
32(pure:m !>(~))
32(pure:m !>(~))
33```
33```
34
34
35−Save the above thread in the `/ted` directory of your `%home` desk and `|commit %home`.
35+Save the above thread in the `/ted` directory of your `%base` desk and `|commit %base`.
36
36
37Now let's run the thread:
37Now let's run the thread:
38
38
@@ -106,7 +106,7 @@ Here's a thread that performs these actions:
106
106
107Note this example was performed on a comet as a fake ship won't have the required information in Jael.
107Note this example was performed on a comet as a fake ship won't have the required information in Jael.
108
108
109−Save the above thread in the `/ted` directory and `|commit %home`. The thread takes a `ship` as an argument, so we'll try to subscribe to pubkey updates for `~dopzod`. Let's run the thread:
109+Save the above thread in the `/ted` directory and `|commit %base`. The thread takes a `ship` as an argument, so we'll try to subscribe to pubkey updates for `~dopzod`. Let's run the thread:
110
110
111```
111```
112> -sub-pub ~dopzod
112> -sub-pub ~dopzod
@@ -197,7 +197,7 @@ Here's a simple thread that'll pass Jael a `%turf` `task`, take the `%turf` `gif
197(pure:m !>(~))
197(pure:m !>(~))
198```
198```
199
199
200−Save in in the `/ted` directory of your ship and `|commit %home`. Next, let's try running it:
200+Save in in the `/ted` directory of your ship and `|commit %base`. Next, let's try running it:
201
201
202```
202```
203> -turf
203> -turf
content/docs/arvo/overview.md+2−2
@@ -45,7 +45,7 @@ Arvo is designed to avoid the usual state of complex event networks: event spagh
45
45
46Unlike any other popular operating system, it is possible for a single human to understand every aspect of Arvo due to its compact size. The entire Urbit stack is around 30,000 lines of code, while the Arvo kernel is only about 1,000 lines of code. We strive for a small codebase because the difficulty in administering a system is roughly proportional to the size of its code base.
46Unlike any other popular operating system, it is possible for a single human to understand every aspect of Arvo due to its compact size. The entire Urbit stack is around 30,000 lines of code, while the Arvo kernel is only about 1,000 lines of code. We strive for a small codebase because the difficulty in administering a system is roughly proportional to the size of its code base.
47
47
48−## An operating function
48+## An operating function {#operating-function}
49
49
50Arvo is the world's first _purely functional_ operating system, and as such it may reasonably be called an _operating function_. The importance of understanding this design choice and its relevance to the overarching goal cannot be understated. If you knew only a single thing about Arvo, let it be this.
50Arvo is the world's first _purely functional_ operating system, and as such it may reasonably be called an _operating function_. The importance of understanding this design choice and its relevance to the overarching goal cannot be understated. If you knew only a single thing about Arvo, let it be this.
51
51
@@ -543,7 +543,7 @@ As of this writing, we have nine vanes, which each provide the following service
543- [Eyre](/docs/arvo/eyre/eyre): an http server. Unix sends http messages to `%eyre`, and `%eyre` produces http messages in response.
543- [Eyre](/docs/arvo/eyre/eyre): an http server. Unix sends http messages to `%eyre`, and `%eyre` produces http messages in response.
544- [Ford](/docs/arvo/ford/ford): a build system also utilized for marks
544- [Ford](/docs/arvo/ford/ford): a build system also utilized for marks
545 (file types) and debugging.
545 (file types) and debugging.
546−- [Gall](/docs/userspace/gall/gall): manages our userspace applications. `%gall` keeps state and manages subscribers.
546+- [Gall](/docs/arvo/gall/gall): manages our userspace applications. `%gall` keeps state and manages subscribers.
547- [Iris](/docs/arvo/iris/iris): an http client.
547- [Iris](/docs/arvo/iris/iris): an http client.
548- [Jael](/docs/arvo/jael/jael): storage for Azimuth information.
548- [Jael](/docs/arvo/jael/jael): storage for Azimuth information.
549
549
content/docs/arvo/reference/filesystem.md+65−31
@@ -4,34 +4,39 @@ weight = 20
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−Here we describe what each of the primary folders present in the `%home` `desk`
7+Here we describe what each of the primary folders present in a Clay desk. This
8−are used for. This organization is merely a convention, and the exact location
8+organization is merely a convention, and the exact location of any file does not
9−of any file does not affect its operation. That being said, some [Ford
9+affect its operation. That being said, some [Ford runes](/docs/arvo/ford/ford)
10−runes](/docs/arvo/ford/ford) are designed with this structure in mind, and
10+are designed with this structure in mind, and applications such as dojo and
11−applications such as dojo look in specific folders for code to run. Furthermore,
11+spider look in specific folders for code to run. Furthermore, this organization
12−this organization is not perfectly adhered to - sometimes you may find structure
12+is not perfectly adhered to - sometimes you may find structure definitions in
13−definitions in `/lib`, for example.
13+`/lib`, for example.
14
14
15- `/app` contains userspace applications, i.e. [Gall
15- `/app` contains userspace applications, i.e. [Gall
16− agents](/docs/userspace/gall/gall).
16+ agents](/docs/arvo/gall/gall).
17−- `/gen` contains generators. Many applications make use of generators, but
17+- `/gen` contains generators. Many applications make use of generators, but also
18− also each generator in this folder may be run from dojo using `+`. For
18+ each generator in this folder may be run from dojo using `+`. For example,
19− example, `/gen/foo/hoon` is run with `+foo`.
19+ `/gen/foo/hoon` in the `%base` desk is run with `+foo`. Generators on desks
20+ other than `%base` can be run with `+desk!generator` like `+garden!foo`.
20- `/lib` contains libraries that may be shared by multiple agents, threads,
21- `/lib` contains libraries that may be shared by multiple agents, threads,
21 generators, etc. However, this is not the location of the standard libraries
22 generators, etc. However, this is not the location of the standard libraries
22 (see `/sys`). Libraries are imported from `/lib` with `/+`.
23 (see `/sys`). Libraries are imported from `/lib` with `/+`.
23−- `/mar` contains [mark](/docs/arvo/clay/architecture#marks) definitions.
24+- `/mar` contains [mark](/docs/arvo/clay/marks/marks) definitions.
24- `/sur` contains shared [structure](/docs/hoon/reference/rune/) definitions.
25- `/sur` contains shared [structure](/docs/hoon/reference/rune/) definitions.
25− Whenever you expect structures to be used by code across multiple files, it
26+ Whenever you expect structures to be used by code across multiple files, it is
26− is recommended to place their shared structures in `/sur`. Structures are
27+ recommended to place their shared structures in `/sur`. Structures are
27 imported from `/sur` with `/-`.
28 imported from `/sur` with `/-`.
28−- `/sys` contains the code that defines the kernel and standard libraries.
29+- `/sys` contains the code that defines the kernel and standard libraries. Note
30+ that only the `%base` desk should contain these `/sys` files, other desks
31+ omit the directory and instead just depend on `%base`. `/sys/vane` contains
29− `/sys/vane` contains the code for the vanes, aka kernel modules. `/sys` is
32+ the code for the vanes, aka kernel modules. `/sys` is the exception to the
30− the exception to the rule - structures and functions that are central to
33+ rule - structures and functions that are central to Hoon, Arvo, and its vanes,
31− Hoon, Arvo, and its vanes, are all located within this folder rather than in
34+ are all located within this folder rather than in `/lib` and `/sur`. See
32− `/lib` and `/sur`. See [below](#sys) for more information on `/sys`.
35+ [below](#sys) for more information on `/sys`.
33−- `/ted` contains [threads](/docs/userspace/threads/overview). These may be
36+- `/ted` contains [threads](/docs/userspace/threads/overview). These may be run
34− run from dojo using `-`. For example, `/ted/foo/hoon` is run with `-foo`.
37+ from dojo using `-`. For example, `/ted/foo/hoon` on the `%base` desk is run
38+ with `-foo`. Threads on desks other than the `%base` desk can be run with
39+ `-desk!thread` like `-garden!foo`.
35- `/tests` contains unit tests intended to be run using the `test` thread. To
40- `/tests` contains unit tests intended to be run using the `test` thread. To
36 run a particular test `+test-bar` in `/tests/foo.hoon` in dojo, enter `-test %/tests/foo/test-bar ~`. If a file is specified, every test in that file will
41 run a particular test `+test-bar` in `/tests/foo.hoon` in dojo, enter `-test %/tests/foo/test-bar ~`. If a file is specified, every test in that file will
37 run. If a folder is specified, every test in that folder will run.
42 run. If a folder is specified, every test in that folder will run.
@@ -39,9 +44,10 @@ definitions in `/lib`, for example.
39## `/sys` {#sys}
44## `/sys` {#sys}
40
45
41`/sys` contains four files: `hoon.hoon`, `arvo.hoon`, `lull.hoon`, and
46`/sys` contains four files: `hoon.hoon`, `arvo.hoon`, `lull.hoon`, and
42−`zuse.hoon`. These are the files used to construct kernelspace. The chain of
47+`zuse.hoon`. These are the files used to construct kernelspace. Only the `%base`
48+desk contains these files, other desks omit the `/sys` directory and instead
43−dependencies is `hoon.hoon` -> `arvo.hoon` -> `lull.hoon` -> `zuse.hoon`. We
49+just depend on `%base`. The chain of dependencies is `hoon.hoon` -> `arvo.hoon`
44−give a brief description of each of them.
50+-> `lull.hoon` -> `zuse.hoon`. We give a brief description of each of them.
45
51
46- `hoon.hoon` contains the Hoon compiler and the [Hoon standard
52- `hoon.hoon` contains the Hoon compiler and the [Hoon standard
47 library](/docs/hoon/reference/stdlib/table-of-contents). The Hoon
53 library](/docs/hoon/reference/stdlib/table-of-contents). The Hoon
@@ -58,12 +64,40 @@ give a brief description of each of them.
58 of `arvo.hoon`.
64 of `arvo.hoon`.
59- `lull.hoon` primarily contains structures shared among the kernel and its
65- `lull.hoon` primarily contains structures shared among the kernel and its
60 vanes, as well as a few functions. In particular, this includes the
66 vanes, as well as a few functions. In particular, this includes the
61− definitions of the `card`s utilized by each vane, each of which are
67+ definitions of the `task`s and `gift`s utilized by each vane, each of which
62− documented in their respective documentation. `lull.hoon` is loaded by the
68+ are documented in their respective documentation. `lull.hoon` is loaded by the
63− kernel during the [larval stage](/docs/arvo/overview#larval-stage-core)
69+ kernel during the [larval stage](/docs/arvo/overview#larval-stage-core) in
64− in order to prepare to create the vanes. `arvo.hoon` is the subject of `lull.hoon`.
70+ order to prepare to create the vanes. `arvo.hoon` is the subject of
71+ `lull.hoon`.
65- `zuse.hoon` is the Arvo standard library. It consists primarily of functions
72- `zuse.hoon` is the Arvo standard library. It consists primarily of functions
66 shared by the kernel and vanes, such as the ones related to
73 shared by the kernel and vanes, such as the ones related to
67− [cryptography](/docs/arvo/reference/cryptography). `zuse.hoon` is loaded
74+ [cryptography](/docs/arvo/reference/cryptography). `zuse.hoon` is loaded by
68− by the larval kernel following `lull.hoon`. `lull.hoon` is the subject of
75+ the larval kernel following `lull.hoon`. `lull.hoon` is the subject of
69− `zuse.hoon`. Then `zuse` is the subject of the vanes.
76+ `zuse.hoon`. Then `zuse` is the subject of the vanes. Some of the functions in
77+ Zuse are documented [here](/docs/hoon/reference/zuse/table-of-contents).
78+
79+## Desks
80+
81+A desk is an independently revision-controlled branch of a ship that uses the
82+Clay filesystem. Each desk contains its own apps, mark definitions, files, and
83+so forth. The basic filesystem structure is the same for all desks, with the
84+exception that only the `%base` desk contains a [`/sys`](#sys) directory.
85+Additionally, there are a handful of special files related to the management of
86+desks and their Gall agents:
87+
88+- `sys.kelvin` - This specifies the version of Arvo the desk is compatible with.
89+ This file is mandatory in all desks.
90+- `desk.bill` - This file specifies the Gall agents on a desk which should be
91+ automatically started when it's installed. This file may be omitted if there
92+ are no agents to start.
93+- `desk.docket-0` - This file configures the tile,
94+ [glob](/docs/userspace/dist/glob) and other metadata for apps with a
95+ front-end. This file may be omitted if the desk does not have a tile or
96+ front-end to be installed. This file is versioned so the number appended may
97+ change in the future as changes to its specification are made. See the [Docket
98+ File](/docs/userspace/dist/docket) documentation for more details.
99+- `desk.ship` - This specifies the original publisher of the desk and is useful
100+ if a desk is being republished. It is optional and may be omitted.
101+
102+For more details of creating and distributing desks, see the
103+[Distribution](/docs/userspace/dist/dist) documentation.
content/docs/azimuth/_index.md+26−7
@@ -6,17 +6,36 @@ template = "sections/docs/chapters.html"
6insert_anchor_links = "right"
6insert_anchor_links = "right"
7+++
7+++
8
8
9−
10−## [Azimuth](/docs/azimuth/azimuth)
9+### [Azimuth](/docs/azimuth/azimuth)
11
10
12An overview of the Ethereum-based public key infrastructure utilized by Urbit.
11An overview of the Ethereum-based public key infrastructure utilized by Urbit.
13
12
13+### [Urbit HD Wallet](/docs/azimuth/hd-wallet)
14+
15+Azimuth has its own optional hierarchical deterministic wallet system, often
16+referred to as a "master ticket".
17+
18+### [Data Flow](/docs/azimuth/flow)
19+
20+Diagrams and explanations of how data flows between Bridge and the various
21+components inside Urbit involved with layer 2.
22+
14−## [Life and Rift](/docs/azimuth/azimuth)
23+### [Azimuth.eth](/docs/azimuth/azimuth-eth)
15
24
16−An explanation of how Azimuth keeps track of the most recent set of networking
25+A description of the `azimuth.eth` smart contract, which is the data store for
17−keys necessary to communicate with a ship.
26+Azimuth.
18
27
19−## [Advanced Azimuth Tools](/docs/azimuth/advanced-azimuth-tools)
28+### [Ecliptic.eth](/docs/azimuth/ecliptic)
20
29
30+A description of the `ecliptic.eth` smart contract, which is the business logic
31+for `azimuth.eth`. This includes an overview of all function calls available.
32+
33+### [Advanced Azimuth Tools](/docs/azimuth/advanced-azimuth-tools)
34+
21−Expert-level tooling for generating, signing, and sending Azimuth-related
35+Expert-level tooling for generating, signing, and sending layer 1 Azimuth-related
22transactions from within Urbit itself.
36transactions from within Urbit itself.
37+
38+### [Life and Rift](/docs/azimuth/azimuth)
39+
40+An explanation of how Azimuth indexes networking keys and breaches to keep track
41+of the most recent set of networking keys necessary to communicate with a ship.
content/docs/azimuth/advanced-azimuth-tools.md+82−25
@@ -1,19 +1,43 @@
1+++
1+++
2title = "Advanced Azimuth Tools"
2title = "Advanced Azimuth Tools"
3−weight = 4
3+weight = 7
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−This document outlines some advanced techniques for generating, signing, and sending Azimuth-related transactions from within Urbit itself. It's strongly discouraged to do this unless you're very confident as Azimuth transactions are permanent and will cost ETH to complete. However, until you upload a signed transaction to the blockchain no transaction will take place so it's safe to explore these tools. It will also be very helpful to have at least a rudimentary understanding of Hoon in order to read and modify parts of the code.
7+This document outlines some advanced techniques for generating, signing, and
8−
8+sending Azimuth-related transactions from within Urbit itself. It's strongly
9+discouraged to do this unless you're very confident as Azimuth transactions are
10+permanent and will cost ETH to complete. However, until you upload a signed
11+transaction to the blockchain no transaction will take place so it's safe to
12+explore these tools. It will also be very helpful to have at least a rudimentary
13+understanding of Hoon in order to read and modify parts of the code.
14+
15+These tools are currently only available for layer 1 transactions. Tooling for
16+layer 2 transactions is forthcoming.
17+
18+First you will want to [boot a
9−First you will want to [boot a fakezod](https://urbit.org/using/develop/#creating-a-development-ship). You can do this with your live running ship but at this time this will need you to modify the code so it's best to do this on a ship you can make mistakes on.
19+fakezod](https://urbit.org/using/develop/#creating-a-development-ship). You can
10−
20+do this with your live running ship but at this time this will need you to
21+modify the code so it's best to do this on a ship you can make mistakes on.
22+
11−Be sure to have mounted your home desk so you can easily edit files on it.
23+Be sure to have mounted your home desk so you can easily edit files on it. The
24+first edit that will probably need to be made is in
12−The first edit that will probably need to be made is in [`app/claz.hoon`](https://github.com/urbit/urbit/blob/85435e9a81e105809d5d381b5d34fae1d4daa3b8/pkg/arvo/app/claz.hoon#L14). The listed url will need to be changed to a valid Ethereum endpoint. infura.io provides an Ethereum API that you can use.
25+[`app/claz.hoon`](https://github.com/urbit/urbit/blob/85435e9a81e105809d5d381b5d34fae1d4daa3b8/pkg/arvo/app/claz.hoon#L14).
13−
26+The listed url will need to be changed to a valid Ethereum endpoint. infura.io
14−The second change that may potentially be needed is to modify the [gas limit](https://github.com/urbit/urbit/blob/85435e9a81e105809d5d381b5d34fae1d4daa3b8/pkg/arvo/app/claz.hoon#L179). This number here is the maximum number of gas units that will be used. In future this will be configurable but for now you may need to change this manually. For a guide to what to set it to you can use the [constants in bridge](https://github.com/urbit/bridge/blob/29f4a14869489481a950a1af53f583d751897444/src/lib/constants.js#L23) as a guide based on what action you are going to be performing. The maximum cost of your transaction will be the maximum gas units multiplied by the gwei you're going to set later. You'll need at least this much in your account.
27+provides an Ethereum API that you can use.
15−
28+
29+The second change that may potentially be needed is to modify the [gas
30+limit](https://github.com/urbit/urbit/blob/85435e9a81e105809d5d381b5d34fae1d4daa3b8/pkg/arvo/app/claz.hoon#L179).
31+This number here is the maximum number of gas units that will be used. In future
32+this will be configurable but for now you may need to change this manually. For
33+a guide to what to set it to you can use the [constants in
34+bridge](https://github.com/urbit/bridge/blob/29f4a14869489481a950a1af53f583d751897444/src/lib/constants.js#L23)
35+as a guide based on what action you are going to be performing. The maximum cost
36+of your transaction will be the maximum gas units multiplied by the gwei you're
37+going to set later. You'll need at least this much in your account.
38+
16−Once you have made these changes be sure to run `|commit %home` to get them into your ship.
39+Once you have made these changes be sure to run `|commit %home` to get them into
40+your ship.
17
41
18Next run `|start %claz` after which you'll be able to generate transactions.
42Next run `|start %claz` after which you'll be able to generate transactions.
19
43
@@ -21,27 +45,45 @@ Next run `|start %claz` after which you'll be able to generate transactions.
21:claz [%generate %/spawn/eth-txs %mainnet author %single %spawn ~ship to]
45:claz [%generate %/spawn/eth-txs %mainnet author %single %spawn ~ship to]
22```
46```
23
47
24−Here we have an example of generating a transaction to spawn a ship. Something to note is that for this to be successful you'll need to actually have the right to spawn the ship in question. Let's break down the command.
48+Here we have an example of generating a transaction to spawn a ship. Something
49+to note is that for this to be successful you'll need to actually have the right
50+to spawn the ship in question. Let's break down the command.
25
51
26
52
27`%generate` is how all commands to `claz` are going to start.
53`%generate` is how all commands to `claz` are going to start.
28
54
29`%/spawn/eth-txs` is simply the path for the output file
55`%/spawn/eth-txs` is simply the path for the output file
30
56
31−`%mainnet` specifies which network this is going to sent out on. Other options are possible including the test-net `%ropsten`.
57+`%mainnet` specifies which network this is going to sent out on. Other options
58+are possible including the test-net `%ropsten`.
32
59
33−`author` here is an Ethereum address that is issuing the transaction. It will need to be written in `@ux` notation, e.g. `0x3b17.d097.d9dd.711e.4ef8.517a.bbf1.8b2b.a643.81fe`.
60+`author` here is an Ethereum address that is issuing the transaction. It will
61+need to be written in `@ux` notation, e.g.
62+`0x3b17.d097.d9dd.711e.4ef8.517a.bbf1.8b2b.a643.81fe`.
34
63
64+`%single` specifies what kind of batch that will be created. If you are going to
65+do multiple transactions you will need to either set this to `%more` followed by
35−`%single` specifies what kind of batch that will be created. If you are going to do multiple transactions you will need to either set this to `%more` followed by a _list_ of batches, or generate the next transaction after having submitted the previous one to the blockchain.
66+a _list_ of batches, or generate the next transaction after having submitted the
67+previous one to the blockchain.
36
68
37−`[%spawn ~ship to]` is the transaction we want to issue. The arguments are will vary based on the transaction. `~ship` will be the ship to be spawned. `to` is the Ethereum address to spawn the ship to.
69+`[%spawn ~ship to]` is the transaction we want to issue. The arguments are will
70+vary based on the transaction. `~ship` will be the ship to be spawned. `to` is
71+the Ethereum address to spawn the ship to.
38
72
73+You will want to read
39−You will want to read [`/sur/claz.hoon`](https://github.com/urbit/urbit/blob/85435e9a81e105809d5d381b5d34fae1d4daa3b8/pkg/arvo/sur/claz.hoon).
74+[`/sur/claz.hoon`](https://github.com/urbit/urbit/blob/85435e9a81e105809d5d381b5d34fae1d4daa3b8/pkg/arvo/sur/claz.hoon).
40−This will contain more details about the various kinds of transactions you can perform particularly `++call`
75+This will contain more details about the various kinds of transactions you can
76+perform particularly `++call`
41
77
78+After running this command you should find a csv file at the output path you
42−After running this command you should find a csv file at the output path you specified. You can examine this file to learn how they are constructed. You are able to modify the nonces, gas limit and price without changing the functionality of the transaction but it's not important for this guide.
79+specified. You can examine this file to learn how they are constructed. You are
80+able to modify the nonces, gas limit and price without changing the
81+functionality of the transaction but it's not important for this guide.
43
82
44−This file can now be signed and uploaded. At this point, you can transfer this file to an airgapped machine which has your keys, if you want. If you choose to do that you will need to download the `urbit` binary as well as the most recent pill file or a copy of the fakezod pier you have already booted.
83+This file can now be signed and uploaded. At this point, you can transfer this
84+file to an airgapped machine which has your keys, if you want. If you choose to
85+do that you will need to download the `urbit` binary as well as the most recent
86+pill file or a copy of the fakezod pier you have already booted.
45
87
46For this guide, we'll continue on the same ship.
88For this guide, we'll continue on the same ship.
47
89
@@ -53,16 +95,31 @@ Run `|start %eth-sender` and then you can use it to sign the transaction file.
53
95
54Let's break this down again.
96Let's break this down again.
55
97
98+`%sign` is the action we are going to perform here. `eth-sender` can also be
56−`%sign` is the action we are going to perform here. `eth-sender` can also be used to submit batches of transactions to the network in various ways, but details on that are outside of the scope of this guide.
99+used to submit batches of transactions to the network in various ways, but
100+details on that are outside of the scope of this guide.
57
101
58`%/spawn-signed/txt` is the path to the output file.
102`%/spawn-signed/txt` is the path to the output file.
59
103
60−`%/spawn/eth-txs` is the path to the transaction file we generated earlier. It will need to be accessible so don't forget to `|commit %home` if you moved it to a different pier.
104+`%/spawn/eth-txs` is the path to the transaction file we generated earlier. It
105+will need to be accessible so don't forget to `|commit %home` if you moved it to
106+a different pier.
61
107
62−`%/mykey/txt` is the path to your private key file. It should contain your private key beginning with 0x and followed by a hex string with no dots, and where capital letters are fine. This file is most likely the reason you will want to use an airgapped machine so that your private key never touches a networked computer. Opsec is left to the reader.
108+`%/mykey/txt` is the path to your private key file. It should contain your
109+private key beginning with 0x and followed by a hex string with no dots, and
110+where capital letters are fine. This file is most likely the reason you will
111+want to use an airgapped machine so that your private key never touches a
112+networked computer. Opsec is left to the reader.
63
113
114+`~[40 80]` is a list of gas prices, in gwei; a signed transaction file will be
115+created for each one listed. Here we just specify 40 and 80 gwei. You may want
64−`~[40 80]` is a list of gas prices, in gwei; a signed transaction file will be created for each one listed. Here we just specify 40 and 80 gwei. You may want to adjust this list based on current Ethereum network traffic and your time preference for the transactions.
116+to adjust this list based on current Ethereum network traffic and your time
117+preference for the transactions.
65
118
66Now you should have one file in your pier for each gwei costs.
119Now you should have one file in your pier for each gwei costs.
67
120
121+To actually transmit the transaction, paste the contents of one of these files
68−To actually transmit the transaction, paste the contents of one of these files into https://etherscan.io/pushTx or whatever other transmission system you would like to use. **This is the action that will actually cost you ETH and perform the transaction on the network. Only do this step if you want to actually perform the action.**
122+into https://etherscan.io/pushTx or whatever other transmission system you would
123+like to use. **This is the action that will actually cost you ETH and perform
124+the transaction on the network. Only do this step if you want to actually
125+perform the action.**
content/docs/azimuth/azimuth-eth.mdnew file+158
@@ -0,0 +1,158 @@
1++++
2+title = "Azimuth.eth"
3+weight = 5
4+template = "doc.html"
5++++
6+
7+[Azimuth.eth](https://etherscan.io/address/azimuth.eth) is used for storing all
8+data related to Azimuth points and their ownership, and should be considered to
9+be the ledger for Azimuth. This contract is just a data store - it only contains
10+the bare minimum of business logic. See [Ecliptic.eth](/docs/azimuth/ecliptic)
11+for the contract containing the business logic for this ledger. `Azimuth.eth`
12+cannot be modified directly by [galaxy vote](/docs/glossary/upgrade) - they are
13+only eligible to modify the Ecliptic.
14+
15+## Global state {#global}
16+
17+The global state of `Azimuth.eth` is given by the following.
18+
19+```solidity
20+ // points: per point, general network-relevant point state
21+ //
22+ mapping(uint32 => Point) public points;
23+
24+ // rights: per point, on-chain ownership and permissions
25+ //
26+ mapping(uint32 => Deed) public rights;
27+
28+ // operators: per owner, per address, has the right to transfer ownership
29+ // of all the owner's points (ERC721)
30+ //
31+ mapping(address => mapping(address => bool)) public operators;
32+
33+ // dnsDomains: base domains for contacting galaxies
34+ //
35+ // dnsDomains[0] is primary, the others are used as fallbacks
36+ //
37+ string[3] public dnsDomains;
38+```
39+
40+Urbit ID's are formalized as [ERC-721 non-fungible
41+tokens](https://eips.ethereum.org/EIPS/eip-721) and are indexed by a number
42+between `0` and `2^32-1`, e.g. a `uint32`. There are two data structures
43+associated to a given `uint32`: a `Point` and a `Deed`.
44+
45+## `Point`s {#points}
46+
47+A `Point` contains data about networking keys and sponsorship status, arranged
48+in the following `struct`:
49+
50+```solidity
51+ struct Point
52+ {
53+ // encryptionKey: (curve25519) encryption public key, or 0 for none
54+ //
55+ bytes32 encryptionKey;
56+ //
57+ // authenticationKey: (ed25519) authentication public key, or 0 for none
58+ //
59+ bytes32 authenticationKey;
60+ //
61+ // spawned: for stars and galaxies, all :active children
62+ //
63+ uint32[] spawned;
64+ //
65+ // hasSponsor: true if the sponsor still supports the point
66+ //
67+ bool hasSponsor;
68+
69+ // active: whether point can be linked
70+ //
71+ // false: point belongs to prefix, cannot be configured or linked
72+ // true: point no longer belongs to prefix, can be configured and linked
73+ //
74+ bool active;
75+
76+ // escapeRequested: true if the point has requested to change sponsors
77+ //
78+ bool escapeRequested;
79+
80+ // sponsor: the point that supports this one on the network, or,
81+ // if :hasSponsor is false, the last point that supported it.
82+ // (by default, the point's half-width prefix)
83+ //
84+ uint32 sponsor;
85+
86+ // escapeRequestedTo: if :escapeRequested is true, new sponsor requested
87+ //
88+ uint32 escapeRequestedTo;
89+
90+ // cryptoSuiteVersion: version of the crypto suite used for the pubkeys
91+ //
92+ uint32 cryptoSuiteVersion;
93+
94+ // keyRevisionNumber: incremented every time the public keys change
95+ //
96+ uint32 keyRevisionNumber;
97+
98+ // continuityNumber: incremented to indicate network-side state loss
99+ //
100+ uint32 continuityNumber;
101+ }
102+```
103+
104+## `Deed`s {#deeds}
105+
106+A `Deed` says which Ethereum address owns a given `Point` as well as several
107+[proxies](/docs/using/id/proxies) for that `Point`.
108+
109+```solidity
110+struct Deed
111+ {
112+ // owner: address that owns this point
113+ //
114+ address owner;
115+
116+ // managementProxy: 0, or another address with the right to perform
117+ // low-impact, managerial operations on this point
118+ //
119+ address managementProxy;
120+
121+ // spawnProxy: 0, or another address with the right to spawn children
122+ // of this point
123+ //
124+ address spawnProxy;
125+
126+ // votingProxy: 0, or another address with the right to vote as this point
127+ //
128+ address votingProxy;
129+
130+ // transferProxy: 0, or another address with the right to transfer
131+ // ownership of this point
132+ //
133+ address transferProxy;
134+ }
135+```
136+
137+## Other state {#other}
138+
139+Finally, each Ethereum address may set for itself a number of `operators`, as
140+defined and required by the [ERC-721
141+standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-721/).
142+These are for third party brokers/wallets/auctioneers/etc such as
143+[OpenSea](http://opensea.io), which facilitate exchange of ERC-721 tokens.
144+
145+`Azimuth.eth` also contains some other state—`dnsDomains`—which are domain names by
146+which the IP address of a galaxy may be looked up, e.g. `zod.urbit.org` resolves
147+to `35.247.119.159`. This is used for bootstrapping the network from DNS. Three
148+domains may be listed here, but as of today they are all `urbit.org`. This may
149+only be updated by the owner of Ecliptic, but arguably each galaxy ought to be
150+able to set its own domain name and so we do not expect this to remain the case
151+forever.
152+
153+All data in this ledger is stored and processed locally on your ship by the
154+[`%azimuth` Gall agent](/docs/azimuth/flow#azimuth), including [layer
155+2](/docs/azimuth/l2/layer2) data. Because state transitions resulting from layer 2
156+transactions are not included in this ledger, in general the local store will
157+differ from what is kept in `Azimuth.eth`.
158+
content/docs/azimuth/azimuth.md+126−137
@@ -5,145 +5,134 @@ template = "doc.html"
5aliases = ["/docs/learn/azimuth"]
5aliases = ["/docs/learn/azimuth"]
6+++
6+++
7
7
8+Azimuth is a general-purpose public-key infrastructure (PKI) on the Ethereum
8−Azimuth is a general-purpose public-key infrastructure (PKI) on the Ethereum blockchain, used as a platform for _Urbit identities_. You need such an identity to use the Arvo network.
9+blockchain, used as a platform for _Urbit identities_. You need such an identity
10+to use the Arvo network.
9
11
10−The primary way to interact with Azimuth is through our [Bridge](https://github.com/urbit/bridge) application and the node libraries that it depends on, [azimuth-js](https://github.com/urbit/azimuth-js) and [urbit-key-generation](https://github.com/urbit/urbit-key-generation). Take a look at the source and play around, or see [Getting Started](/getting-started/).
12+The primary way to interact with Azimuth is through
13+[Bridge](https://github.com/urbit/bridge) and the node libraries that it depends
14+on, [azimuth-js](https://github.com/urbit/azimuth-js) and
15+[urbit-key-generation](https://github.com/urbit/urbit-key-generation). Take a
16+look at the source and play around, or see [Getting Started](/getting-started/).
11
17
12## Arvo vs. Azimuth
18## Arvo vs. Azimuth
13
19
14−Urbit is a project, not a single computer system. It has multiple components: Arvo, the operating system; and Azimuth, the identity system. Let's compare them.
20+Urbit is a project, not a single computer system. It has multiple components:
21+Arvo, the operating system, and Azimuth, the identity system. Let's compare
22+them.
23+
24+**Arvo** is an operating system that provides the software for a personal
25+server. These personal servers together constitute the peer-to-peer Arvo
26+network. To make this network work on the social level, Arvo is built to work
27+with a system of scarce and immutable identities.
28+
29+**Azimuth** is the public-key infrastructure built to be a system of scarce and
30+immutable identities. It consists of a suite of [smart contracts on the Ethereum
31+blockchain](https://github.com/urbit/azimuth) as well as [several
32+apps](/docs/azimuth/flow) run locally on your urbit. Togeter, they determine
33+which Ethereum addresses own which Urbit ID's as well as the public keys needed
34+to communicate with those ID's. All identity-related operations, such as
35+transfers, are governed by Azimuth. Azimuth isn't built strictly for Arvo -- the
36+smart contracts on Ethereum are sufficient to be used as a generalized identity
37+system for other projects. Azimuth is considered to be the technical
38+nomenclature for the PKI, while Urbit ID is the common nomenclature.
39+
40+These otherwise-parallel systems meet when you want to connect to the Arvo
41+network. Your Arvo personal server, called your _ship_, needs to be able to
42+prove cryptographically that it is who it says it is. This proof comes in the
43+form of a keyfile, derived from your identity, that you use to start your ship.
44+
45+A metaphor might help illustrate the relationship between these two systems: the
46+Arvo network is the neighborhood that you live in; Azimuth is the bank vault
47+that stores the deed to your house.
48+
49+## Smart contracts
50+
51+Azimuth consists of the following smart contracts:
52+
53+ - [Azimuth.eth](https://etherscan.io/address/azimuth.eth)
54+ `0x223c067f8cf28ae173ee5cafea60ca44c335fecb`: contains all on-chain state for
55+ Azimuth. Most notably, ownership and public keys. Can't be modified directly,
56+ you must use the Ecliptic.
57+ - [Ecliptic.eth](https://etherscan.io/address/ecliptic.eth):
58+ `0x9ef27de616154FF8B38893C59522b69c7Ba8A81c ` is used as an interface for
59+ interacting with your points on-chain. Allows you to configure keys, transfer
60+ ownership, etc.
61+ - [Polls](https://etherscan.io/address/0x7fecab617c868bb5996d99d95200d2fa708218e4):
62+ `0x7fecab617c868bb5996d99d95200d2fa708218e4` registers votes by the Galactic
63+ Senate on proposals. These can be either static documents or Ecliptic
64+ upgrades.
65+ - [Linear Star
66+ Release](https://etherscan.io/address/0x86cd9cd0992f04231751e3761de45cecea5d1801):
67+ facilitates the release of blocks of stars to their owners over a period of
68+ time.
69+ - [Conditional Star
70+ Release](https://etherscan.io/address/0x8c241098c3d3498fe1261421633fd57986d74aea):
71+ `0x8c241098c3d3498fe1261421633fd57986d74aea` facilitates the release of
72+ blocks of stars to their owners based on milestones.
73+ - [Claims](https://etherscan.io/address/0xe7e7f69b34d7d9bd8d61fb22c33b22708947971a):
74+ `0xe7e7f69b34d7d9bd8d61fb22c33b22708947971a` allows point owners to make
75+ claims about (for example) their identity, and associate that with their
76+ point.
77+ - [Censures](https://etherscan.io/address/0x325f68d32bdee6ed86e7235ff2480e2a433d6189):
78+ `0x325f68d32bdee6ed86e7235ff2480e2a433d6189` simple reputation management,
79+ allowing galaxies and stars to flag points for negative reputation.
80+ - [Delegated
81+ Sending](https://etherscan.io/address/0xf6b461fe1ad4bd2ce25b23fe0aff2ac19b3dfa76):
82+ enables network-effect like distributing of planets.
83+
84+Walkthroughs of some of the smart contracts are linked to [below](#other).
85+
86+## Naive rollups
87+
88+In 2021, Tlon introduced a new system to Azimuth intended to reduce gas costs
89+for working with Urbit ID and friction associated with using cryptocurrency in
90+general called **naive rollups**, often referred to as **layer 2** or L2. This system
91+allows batches of Azimuth transactions to be submitted together as a single
92+transaction using an Urbit node known as a "roller". The PKI state transitions
93+resulting from these transactions are computed locally by your urbit rather than
94+by the [Ethereum Virtual Machine](https://ethereum.org/en/developers/docs/evm/).
95+
96+Due to the dramatically reduced cost, Tlon offers their own roller that is free
97+for ordinary public use. This enables new users to get started with a permanent
98+Azimuth identity without any prior knowledge of Ethereum, cryptocurrency, or
99+blockchains. However, anybody can run a roller, and even using your own ship as
100+a roller to submit single transactions results in significant savings.
101+
102+A casual overview of the naive rollups system can be found on the
103+[blog](/blog/rollups). Developers are encouraged to read our Layer 2
104+documentation, starting with the [Layer 2 Overview](/docs/azimuth/l2/layer2).
105+
106+## Other resources {#other}
107+
108+### [Urbit HD Wallet](/docs/azimuth/hd-wallet)
109+
110+Azimuth has its own optional hierarchical deterministic wallet system, often
111+referred to as a "master ticket".
112+
113+### [Data Flow](/docs/azimuth/flow)
114+
115+Diagrams and explanations of how data flows between Bridge and the various
116+components inside Urbit involved with Azimuth and L2.
117+
118+### [Azimuth.eth](/docs/azimuth/azimuth-eth)
119+
120+A description of the `azimuth.eth` smart contract, which is the data store for
121+Azimuth.
122+
123+### [Ecliptic.eth](/docs/azimuth/ecliptic)
124+
125+A description of the `ecliptic.eth` smart contract, which is the business logic
126+for `azimuth.eth`. This includes an overview of all function calls available.
127+
128+### [Advanced Azimuth Tools](/docs/azimuth/advanced-azimuth-tools)
129+
130+Expert-level tooling for generating, signing, and sending layer 1 Azimuth
131+transactions from within Urbit itself.
132+
133+### [Life and Rift](/docs/azimuth/azimuth)
134+
135+An explanation of how Azimuth indexes networking keys revisions and breaches to
136+keep track of the most recent set of networking keys necessary to communicate
137+with a ship.
15
138
16−**Arvo** is an operating system that provides the software for a personal server. These personal servers together constitute the peer-to-peer Arvo network. To make this network work on the social level, Arvo is built to work with a system of scarce and immutable identities.
17−
18−**Azimuth** is the public-key infrastructure built to be such a system. A suite of smart-contracts on the Ethereum blockchain, Azimuth determines which Ethereum addresses own which Azimuth identities, called _Urbit identities_, or just _identities_. All identity-related operations, such as transfers, are governed at this layer. But Azimuth isn't built strictly for Arvo -- it could be used as a generalized identity system for other projects.
19−
20−These otherwise-parallel systems meet when you want to connect to the Arvo network. Your Arvo personal server, called your _ship_, needs to be able to prove cryptographically that it is who it says it is. This proof comes in the form of a keyfile, derived from your identity, that you use to start your ship.
21−
22−A metaphor might help illustrate the relationship between these two systems: the Arvo network is the neighborhood that you live in; Azimuth is the bank vault that stores the deed to your house.
23−
24−## The Urbit HD Wallet
25−
26−Owners of Urbit identities need safeguards that allow for the use of Urbit without jeopardizing cryptographic ownership of their assets. Toward this end, we created the **Urbit Hierarchical Deterministic (HD) Wallet** for the storage of identities. The Urbit HD Wallet is not one key-pair, but a system of related key-pairs that each have distinct powers, from setting networking keys for communicating in the Arvo network to transferring ownership of identities.
27−
28−The Urbit HD Wallet's derivation paths have a hierarchical structure, so that
29−keys with different powers can be physically separated. A "master ticket" can
30−[re-derive the entire wallet](#hd-wallet-generation) in case of loss. The
31−encryption and authentication keys that identities ships use to sign messages
32−within the network are also derived from the wallet.
33−
34−Another HD wallet option you may wish to utilize to store your Urbit are hardware
35−wallets such as Trezor or Ledger. We compare this method to the Urbit HD wallet
36−[below](#hardware-hd-wallet).
37−
38−Urbit HD wallets are composed of the following items, which are each assigned to their own individual Ethereum key-pairs.
39−
40−### Master Ticket
41−
42−Think of your master ticket like a very high-value password. The master ticket is the secret code from which all of your other keys are derived. Technically, your master ticket is seed entropy. You should never share it with anyone, and store it very securely. This ticket can derive all of your other keys: your ownership key and all of the related proxies.
43−
44−### Ownership Address
45−
46−An ownership address has all rights over the assets deeded to it. These rights are on-chain actions described and implemented in [Ecliptic](/docs/glossary/ecliptic), Azimuth's suite of governing smart-contracts.
47−
48−### Proxies
49−
50−Proxy addresses allow you to execute non-ownership related actions like spawning child identities, voting, and setting networking keys without jeopardizing the keys you've designated with ownership rights. Setting proxy rights is optional, but it is recommended for on-chain actions you will execute more frequently.
51−
52−- **Management Proxy**
53−
54− Can configure or set Arvo networking keys and conduct sponsorship related
55− operations.
56−
57−- **Voting Proxy**
58−
59− Galaxies only. Galaxies are the part of the [Galactic Senate](/docs/glossary/senate), and this means
60− they can cast votes on new proposals including changes to Ecliptic.
61−
62−- **Spawn Proxy**
63−
64− For stars and galaxies only. Can create new child identities.
65−
66−### HD wallet generation
67−
68−Your Urbit HD wallet is generated from a `@q` seed called `T`, which looks
69−something like `~sampel-ticket-bucbel-sipnem`. This is the string known as your
70−"Master Ticket" that you input into Bridge to sign in. This is put through a
71−series of algorithms that ultimately generate your keys and the Ethereum addresses at which they are stored.
72−
73−![](https://media.urbit.org/fora/proposals/UP-8.jpg)
74−
75−First, your `@q` is converted into a numeric value `E` as an intermediary step
76−by adding [salt](<https://en.wikipedia.org/wiki/Salt_(cryptography)>). Then by
77−adding additional salts, `E` is converted into a set of BIP39 seed phrases -
78−these are 24 word mnemonic sequences used to generate Ethereum wallets. You end up
79−with one seed phrase for each proxy associated with your ship, and these seed
80−phrases are then used to generate Ethereum wallets.
81−
82−One of the wallets will store your Azimuth point, an [ERC-721](#erc-721) token,
83−which will be known as your ownership address. Bridge then automatically uses
84−your ownership address to assign the other proxies to the other wallets
85−generated.
86−
87−### ERC-721
88−
89−Most Ethereum tokens use the ERC-20 standard for smart contracts. Urbit identities
90−are, however, essentially different from most Ethereum tokens, due to identities not
91−being fungible. Since any two stars will handle social-networking realities in a
92−different way, they will carry a different reputation.
93−
94−The ERC-721 standard, having been made specifically to provide a smart-contract
95−interface for non-fungible assets, serves our needs well. This is the standard
96−that we use for deeding Urbit identities.
97−
98−Identities, and all of their blockchain operations, are governed by Ecliptic. Ecliptic is an Ethereum smart-contract that governs identity state and the
99−ownership, spawn, management, and voting rights affiliated with your identities.
100−
101−For the technical implementation details, take a look at Azimuth's
102−[Github repository](https://github.com/urbit/azimuth).
103−
104−## Hardware HD wallet
105−
106−You may also store your Urbit using a hardware HD wallet such as a Trezor or
107−Ledger. This option is used instead of a master ticket - it is a totally
108−separate process from that outlined above. How hardware wallets work are
109−outside of the scope of this document, but here we explain how you may utilize
110−your hardware wallet in a similar fashion to the Urbit HD wallet.
111−
112−A hardware HD wallet is generated from a seed phrase that should be thought of
113−as analogous to the `@q` `T` used to generate the Urbit HD wallet in the above
114−diagram. This seed phrase is a human readable sequence of words that may be used
115−to generate private keys to a near-limitless number of wallets created by adding
116−salt. Some hardware
117−wallets also allow an additional passphrase to go into the generation of these
118−wallets. The seed phrase and passphrase should be considered equal in
119−value to the master ticket `T`- never share these with anyone!
120−
121−In order to use your hardware wallet as your Urbit wallet, you first need to
122−generate a set of addresses on which you would like to store your Azimuth point
123−and proxies. Consult your wallet vendor on how to do this. Then login to Bridge
124−using your current method (likely a master ticket) and transfer ownership to the
125−wallet address you generated on your hardware wallet for ownership.
126−
127−Next, login to Bridge using your hardware wallet. While Bridge supports Trezor
128−and Ledger natively, this may require using Metamask as an intermediary anyways,
129−depending on which firmware you are running. Then [accept the
130−transfer](/using/id/using-bridge#accept-your-transfer). Your Azimuth
131−point is now stored on your hardware wallet.
132−
133−To finish the process, use Bridge to set your management, voting, and spawn
134−proxies to the other addresses you generated as applicable. You are now using
135−your hardware HD wallet in an analogous fashion to the Urbit HD wallet.
136−
137−## Heightened security practices
138−
139−A common security pattern is to have "hot" and "cold" wallets. For higher value
140−points such as stars and galaxies, you may consider having your ownership
141−address live on a "cold" wallet that never touches an
142−internet-connected computer, and the various proxies on a "hot" wallet that is
143−permitted to connect to internet-connected devices. This could be accomplished
144−with multiple hardware wallets, a combination of paper and hardware wallet, a
145−hardware cold wallet and Metamask hot wallet, etc.
146−
147−One tool useful for this setup is `claz`, located at `app/claz.hoon`. `claz` is
148−used for making and signing Bridge transactions from an offline computer. A
149−guide to using `claz` is forthcoming.
content/docs/azimuth/ecliptic.mdnew file+436
@@ -0,0 +1,436 @@
1++++
2+title = "Ecliptic.eth"
3+weight = 6
4+template = "doc.html"
5++++
6+
7+[Ecliptic.eth](https://etherscan.io/address/ecliptic.eth) holds the business
8+logic for the ledger kept by `Azimuth.eth`. It may be modified by [galaxy
9+vote](/docs/glossary/upgrade). This determines things such as what the various
10+proxies are capable of, how keys are changed, or verifying that a request is
11+valid.
12+
13+`Ecliptic.eth` uses external contracts such as
14+[Azimuth.eth](/docs/azimuth/azimuth-eth) and
15+[Polls](https://github.com/urbit/azimuth/blob/master/contracts/Polls.sol) for
16+data storage so that it can easily be replaced in case the logic needs to be
17+changed without affecting the data. These data contracts are owned by
18+`Ecliptic.eth`, and this ownership is passed to the new Ecliptic contract
19+whenever it is replaced. Thus it is advised for clients to not store Ecliptic's
20+contract address directly, but instead ask the `Azimuth.eth` contract for its
21+`owner` attribute to ensure that transactions are sent to the latest Ecliptic
22+contract. Alternatively, the [ENS](https://ens.domains/) name `Ecliptic.eth`
23+will always resolve to the latest Ecliptic.
24+
25+You can read about [Urbit's first
26+upgrade](https://github.com/urbit/azimuth/pull/35) to Ecliptic, which occurred
27+in the summer of 2021, [here](https://urbit.org/blog/first-contract). The
28+[second](https://github.com/urbit/azimuth/pull/43) occurred later in the year
29+and consisted of several small modifications to ready the PKI for the
30+introduction of [naive rollups](/docs/azimuth/l2/layer2).
31+
32+`Ecliptic.eth` implements the [ERC-721](https://eips.ethereum.org/EIPS/eip-721)
33+interface for non-fungible tokens, as well as the
34+[ERC-165](https://eips.ethereum.org/EIPS/eip-165) standard for interface
35+detection.
36+
37+There are currently [28 functions](#write) which may be called to write to
38+the Ecliptic, and [17 functions](#read) to read data from the Ecliptic. Many of these
39+have a corresponding [layer 2 action](/docs/azimuth/l2/l2-actions), and/or can be
40+performed using [Bridge](/using/id/using-bridge). We note these facts where
41+applicable.
42+
43+## Write functions {#write}
44+
45+Here we briefly describe each function in `Ecliptic.eth` which allows one to write
46+data to Ethereum. These can be called using
47+[Etherscan](https://etherscan.io/address/ecliptic.eth#writeContract), but
48+the most common functions may be called from within Bridge.
49+
50+We only document here the write functions specific to `Ecliptic.eth` and not the
51+standard functions that are part of the ERC-721 or ERC-165 interfaces.
52+
53+### `Point`s interface
54+
55+These functions are available to each owner of a
56+[`Point`](/docs/azimuth/azimuth-eth#points), and a subset of them are available
57+to its [proxies](#proxies). All of these actions may be performed from Bridge.
58+
59+#### `configureKeys`
60+
61+```solidity
62+ function configureKeys(uint32 _point,
63+ bytes32 _encryptionKey,
64+ bytes32 _authenticationKey,
65+ uint32 _cryptoSuiteVersion,
66+ bool _discontinuous)
67+```
68+
69+Configure `_point` with network public keys `_encryptionKey`,
70+`_authenticationKey`, and corresponding `_cryptoSuiteVersion`, incrementing the
71+`Point`'s [`keyRevisionNumber`](/docs/azimuth/azimuth-eth#points) if the keys
72+have changed and `continuityNumber` number if `_discontinuous` is set to true
73+(see [Life and Rift](/docs/azimuth/life-and-rift)).
74+
75+Corresponds to the layer 2 `%configure-keys` action.
76+
77+#### `spawn`
78+
79+```solidity
80+ function spawn(uint32 _point, address _target)
81+```
82+
83+Spawn `_point`, then either give, or allow `_target` to take, ownership of `_point`.
84+
85+If `_target` is the `:msg.sender`, `_target` owns the `_point` right away.
86+otherwise, `_target` becomes the transfer proxy of `_point`.
87+
88+Requirements:
89+ - `_point` must not be active
90+ - `_point` must not be a planet with a galaxy prefix
91+ - `_point`'s prefix must be linked and under its spawn limit
92+ - `:msg.sender` must be either the owner of `_point`'s prefix, or an authorized spawn proxy for it
93+
94+Corresponds to the layer 2 `%spawn` action.
95+
96+#### `transferPoint`
97+
98+```solidity
99+ function transferPoint(uint32 _point, address _target, bool _reset)
100+```
101+
102+Transfer `_point` to `_target`, clearing all permissions data and keys if
103+`_reset` is true. `_reset` set to makes this transaction a
104+[breach](/using/id/guide-to-breaches), and thus this action increments the
105+[`continuityNumber`](/docs/azimuth/azimuth-eth#points) of `_point`, and usually
106+the `keyRevisionNumber` as well (see [Life and
107+Rift](/docs/azimuth/life-and-rift)).
108+
109+Requirements:
110+ - `:msg.sender` must be either `_point`'s current owner, authorized to transfer
111+ `_point`, or authorized to transfer the current owner's points (i.e. is
112+ listed as an ERC-721 operator in [`operators`](/docs/azimuth/azimuth-eth#other)).
113+ - `_target` must not be the zero address.
114+
115+Corresponds to the layer 2 `%transfer-point` action.
116+
117+#### `escape`
118+
119+```solidity
120+ function escape(uint32 _point, uint32 _sponsor)
121+```
122+
123+Request escape as `_point` to `_sponsor`.
124+
125+If an escape request is already active, this overwrites the existing request.
126+
127+Requirements:
128+ - `:msg.sender` must be the owner or manager of `_point`,
129+ - `_point` must be able to escape to `_sponsor` as per to `canEscapeTo()`
130+
131+ Corresponds to the layer 2 `%escape` action.
132+
133+#### `cancelEscape`
134+
135+```solidity
136+ function cancelEscape(uint32 _point)
137+```
138+
139+Cancel the currently set escape for `_point`.
140+
141+Corresponds to the layer 2 `%cancel-escape` action.
142+
143+#### `adopt`
144+
145+```solidity
146+ function adopt(uint32 _point)
147+```
148+
149+As the relevant sponsor, accept the `_point`.
150+
151+Requirements:
152+ - `:msg.sender` must be the owner or management proxy
153+ of `_point`'s requested sponsor
154+
155+Corresponds to the layer 2 `%adopt` action.
156+
157+#### `reject`
158+
159+```solidity
160+ function reject(uint32 _point)
161+```
162+
163+As the relevant sponsor, deny the `_point`'s `adopt` request.
164+
165+Requirements:
166+ - `:msg.sender` must be the owner or management proxy
167+ of `_point`'s requested sponsor
168+
169+Corresponds to the layer 2 `%reject` action.
170+
171+#### `detach`
172+
173+```solidity
174+ function detach(uint32 _point)
175+```
176+
177+As the `_sponsor`, stop sponsoring the `_point`.
178+
179+Requirements:
180+ - `:msg.sender` must be the owner or management proxy
181+ of `_point`'s current sponsor
182+
183+Corresponds to the layer 2 `%detach` action.
184+
185+Unlike all other layer 1 actions, layer 1 sponsors may use a layer 1 `detach` on
186+a layer 2 sponsee. See the [Layer 2](/docs/azimuth/l2/layer2#sponsorship)
187+section for more detail. The detach action available in Bridge is a layer 2
188+action, so a layer 1 detach must be done
189+[manually](https://etherscan.io/address/ecliptic.eth#writeContract).
190+
191+### Proxy management {#proxies}
192+
193+These functions are used to manage the various
194+[proxies](/docs/using/id/proxies). All of these actions may be performed from Bridge.
195+
196+#### `setManagementProxy`
197+
198+```solidity
199+ function setManagementProxy(uint32 _point, address _manager)
200+```
201+
202+Configure the management proxy for `_point`.
203+
204+The management proxy may perform "reversible" operations on
205+behalf of the owner. This includes public key configuration and
206+operations relating to sponsorship.
207+
208+Requirements:
209+ - `:msg.sender` must be either `_point`'s current owner or the management proxy.
210+
211+Corresponds to the layer 2 `%set-management-proxy` action.
212+
213+#### `setSpawnProxy`
214+
215+```solidity
216+ function setSpawnProxy(uint16 _prefix, address _spawnProxy)
217+```
218+
219+Give `_spawnProxy` the right to spawn points with the prefix `_prefix` using the
220+`spawn` function.
221+
222+Requirements:
223+ - `:msg.sender` must be either `_point`'s current owner or the spawn proxy.
224+
225+Corresponds to the layer 2 `%set-spawn-proxy` action.
226+
227+#### `setVotingProxy`
228+
229+```solidity
230+ function setVotingProxy(uint8 _galaxy, address _voter)
231+```
232+
233+Configure the voting proxy for `_galaxy`.
234+
235+The voting proxy is allowed to start polls and cast votes on the point's behalf.
236+
237+Requirements:
238+ - `:msg.sender` must be either `_point`'s current owner or the voting proxy.
239+
240+There is no corresponding layer 2 action since voting must occur on layer 1.
241+
242+#### `setTransferProxy`
243+
244+```solidity
245+ function setTransferProxy(uint32 _point, address _transferProxy)
246+```
247+
248+Give `_transferProxy` the right to transfer `_point`.
249+
250+Requirements:
251+ - `:msg.sender` must be either `_point`'s current owner, an operator for the
252+ current owner, or the transfer proxy.
253+
254+Corresponds to the layer 2 `%set-transfer-proxy` action.
255+
256+### Poll actions
257+
258+Most of these are functions only available to galaxies. They are related to
259+[voting](/docs/glossary/voting). As voting does not occur on layer 2, there are
260+no corresponding layer 2 actions for poll actions.
261+
262+Upgrade and document polls last for 30 days, or once a majority is achieved,
263+whichever comes first. If a majority (129) of yes or no votes is achieved, the
264+final vote cast in favor of the winning option also triggers `updateUpgradePoll`
265+or `updateDocumentPoll` as appropriate. Otherwise, if a quorum of 64 votes is
266+achieved, with a majority voting for yes, and the 30 day voting period has
267+expired, then _any_ Ethereum address may call `updateUpgradePoll` or
268+`updateDocumentPoll` as appropriate.
269+
270+#### `startUpgradePoll`
271+
272+```solidity
273+ function startUpgradePoll(uint8 _galaxy, EclipticBase _proposal)
274+```
275+
276+As `_galaxy`, start a poll for the Ecliptic upgrade `_proposal`.
277+
278+Requirements:
279+ - `:msg.sender` must be the owner or voting proxy of `_galaxy`,
280+ - the `_proposal` must expect to be upgraded from this specific
281+ contract, as indicated by its `previousEcliptic` attribute.
282+
283+This action must be performed manually - it is not available in Bridge.
284+
285+#### `startDocumentPoll`
286+
287+```solidity
288+ function startDocumentPoll(uint8 _galaxy, bytes32 _proposal)
289+```
290+
291+As `_galaxy`, start a poll for the `_proposal`. Document polls last for 30 days,
292+or once a majority is achieved, whichever comes first.
293+
294+The `_proposal` argument is the keccak-256 hash of any arbitrary
295+document or string of text.
296+
297+This action must be performed manually - it is not available in Bridge.
298+
299+#### `castUpgradeVote`
300+
301+```solidity
302+ function castUpgradeVote(uint8 _galaxy,
303+ EclipticBase _proposal,
304+ bool _vote)
305+```
306+
307+As `_galaxy`, cast a `_vote` on the Ecliptic upgrade `_proposal`.
308+
309+`_vote` is true when in favor of the proposal, false otherwise.
310+
311+This action may be performed from Bridge.
312+
313+#### `castDocumentVote`
314+
315+```solidity
316+ function castDocumentVote(uint8 _galaxy, bytes32 _proposal, bool _vote)
317+```
318+
319+As `_galaxy`, cast a `_vote` on the `_proposal`.
320+
321+`_vote` is true when in favor of the proposal, false otherwise.
322+
323+This action may be performed from Bridge.
324+
325+#### `updateUpgradePoll`
326+
327+```solidity
328+ function updateUpgradePoll(EclipticBase _proposal)
329+```
330+
331+Check whether the `_proposal` has achieved majority, upgrading to it if it has.
332+Any Ethereum address may call this function.
333+
334+This action eiher occurs as part of a vote that achieves a majority, or must be
335+performed manually. It is not available in Bridge.
336+
337+#### `updateDocumentPoll`
338+
339+```solidity
340+ function updateDocumentPoll(bytes32 _proposal)
341+```
342+
343+Check whether the `_proposal` has achieved majority. Any Ethereum address may
344+call this function.
345+
346+This action eiher occurs as part of a vote that achieves a majority, or must be
347+performed manually. It is not available in Bridge.
348+
349+### Contract owner operations
350+
351+The following functions may only be performed by the owner of the contract.
352+There are only two such functions, one of which is to spawn galaxies. As all
353+galaxies have already been spawned, it is no longer of any use. Thus only
354+`setDnsDomains` is relevant today.
355+
356+#### `createGalaxy`
357+
358+```solidity
359+ function createGalaxy(uint8 _galaxy, address _target)
360+```
361+
362+Grant `_target` ownership of the `_galaxy` and register it for voting. Galaxies
363+are given by a `uint8`, and since all 256 galaxies have already been spawned,
364+this function has no valid arguments.
365+
366+#### `setDnsDomains`
367+
368+```solidity
369+ function setDnsDomains(string _primary, string _secondary, string _tertiary)
370+```
371+
372+Sets 3 DNS domains by which galaxy IP addresses may be looked up as part of the
373+bootstrap process to get on the network. Currently, all three domains are `urbit.org`.
374+
375+## Read functions {#read}
376+
377+Here we briefly describe each function in the Ecliptic which allows one to read
378+data from the contract. These can be called using
379+[Etherscan](https://etherscan.io/address/ecliptic.eth#readContract).
380+
381+We only document here the read functions specific to Ecliptic and not the
382+standard functions that are part of the ERC-721 or ERC-165 interfaces.
383+
384+#### `depositAddress`
385+
386+This returns the deposit address for [layer 2](/docs/azimuth/l2/layer2), which is
387+`0x1111111111111111111111111111111111111111`. Ships sent to this address are
388+controlled on layer 2 instead of via Ecliptic.
389+
390+#### `canEscapeTo`
391+
392+```solidity
393+ function canEscapeTo(uint32 _point, uint32 _sponsor)
394+```
395+
396+Returns a `bool` that is true if `_point` could try to escape to `_sponsor`.
397+
398+#### `azimuth`
399+
400+Returns the address of the [Azimuth.eth](/docs/azimuth/azimuth-eth) contract: `0x223c067f8cf28ae173ee5cafea60ca44c335fecb`.
401+
402+#### `claims`
403+
404+Returns the address of the
405+[Claims](https://etherscan.io/address/0xe7e7f69b34d7d9bd8d61fb22c33b22708947971a)
406+contract: `0x1df4ea30e0b1359c9692a161c5f30cd1a6b64ebf`.
407+
408+#### `polls`
409+
410+Returns the address of the
411+[Polls](https://etherscan.io/address/0x7fecab617c868bb5996d99d95200d2fa708218e4)
412+contract: `0x7fecab617c868bb5996d99d95200d2fa708218e4`.
413+
414+#### `previousEcliptic`
415+
416+Returns the address of the previous Ecliptic address.
417+
418+#### `getSpawnLimit`
419+
420+```solidity
421+ function getSpawnLimit(uint32 _point, uint256 _time)
422+```
423+
424+Returns a `uint32` that is the total number of children the `_point` is allowed
425+to spawn at `_time`.
426+
427+There is no limit for galaxies. Instead, for most galaxies, all stars have
428+already been spawned and placed into one of the lockup contracts: [Linear Star
429+Release](https://etherscan.io/address/0x86cd9cd0992f04231751e3761de45cecea5d1801)
430+and [Conditional Star
431+Release](https://etherscan.io/address/0x8c241098c3d3498fe1261421633fd57986d74aea).
432+
433+Beginning in 2019, stars may spawn at most 1024 planets. This limit doubles
434+every subsequent year until the maximum is reached. However, this limit is not
435+currently implemented on [Layer 2](/docs/azimuth/l2/layer2).
436+
content/docs/azimuth/flow.mdnew file+232
@@ -0,0 +1,232 @@
1++++
2+title = "Azimuth Data Flow"
3+weight = 4
4+template = "doc.html"
5++++
6+
7+This document summarizes the various components involved with Azimuth and
8+how they communicate with each other. This also constitutes an explanation for
9+how Urbit implements the data flow of naive rollups.
10+
11+## Bridge
12+
13+The primary way in which users interact with Azimuth is via
14+[Bridge](https://bridge.urbit.org). Bridge is responsible for collecting
15+transactions from users, signing them, and forwarding them to a roller via an
16+HTTP API.
17+
18+## Azimuth
19+
20+Azimuth was originally defined as a set of smart contracts on Ethereum that
21+defines the [state](/docs/azimuth/azimuth-eth) and [business
22+logic](/docs/azimuth/ecliptic) of the PKI for layer 1. With the introduction of
23+naive rollups, this has also come to include the set of components used for
24+dealing with the PKI within Urbit, as now the complete PKI state is stored
25+offchain (though this state is derived entirely from on-chain data). The
26+following sections outline what each component is responsible for and how it
27+communicates with the others.
28+
29+The Gall agents involved with Azimuth are summarized as follows:
30+ - [`%azimuth`](#azimuth) - obtains and holds PKI state.
31+ - [`%azimuth-rpc`](#azimuth-rpc) - JSON RPC-API for `%azimuth`.
32+ - [`%eth-watcher`](#eth-watcher) - Ethereum event log collector.
33+ - [`%roller`](#roller) - submits batches of L2 transactions to Ethereum.
34+ - [`%roller-rpc`](#roller-rpc) - JSON RPC-API for `%roller`.
35+
36+The transaction processing library is [`/lib/naive.hoon`](#naive).
37+
38+### Gall agents
39+
40+#### `%azimuth` {#azimuth}
41+
42+`%azimuth`, located at `/app/azimuth.hoon`, is a Gall agent and thread handler
43+responsible for finding Azimuth transactions gathered by `%eth-watcher`,
44+keeping track of the PKI state, and exposing that data via scries.
45+
46+The following diagram illustrates `%azimuth`'s and `%eth-watcher`'s role in the system.
47+
48+![Azimuth components](https://media.urbit.org/docs/layer2/l2-azimuth-azimuth.svg)
49+
50+The state held by `%azimuth` is the following.
51+
52+```hoon
53+++ app-state
54+ $: %3
55+ url=@ta
56+ whos=(set ship)
57+ nas=^state:naive
58+ own=owners
59+ logs=(list =event-log:rpc:ethereum)
60+ ==
61+```
62+
63+`whos` is the set of ships currently known by Azimuth. `nas` is the PKI state,
64+as defined in [`naive.hoon`](#naive). `own` is a `jug` of Ethereum addresses and
65+the set of ships owned by that address. `logs` is a list of all Azimuth-related
66+Ethereum event logs known by the ship.
67+
68+Scries can be inferred from the `+on-peek` arm:
69+
70+```hoon
71+++ on-peek
72+ |= =path
73+ ^- (unit (unit cage))
74+ ?+ path (on-peek:def path)
75+ [%x %logs ~] ``noun+!>(logs.state)
76+ [%x %nas ~] ``noun+!>(nas.state)
77+ [%x %dns ~] ``noun+!>(dns.nas.state)
78+ [%x %own ~] ``noun+!>(own.state)
79+ ==
80+```
81+
82+#### `%azimuth-rpc` {#azimuth-rpc}
83+
84+`%azimuth-rpc`, located at `app/azimuth-rpc.hoon`, is a JSON RPC-API for getting
85+`point` and `dns` data from the Azimuth PKI state kept by `%azimuth`.
86+
87+#### `%eth-watcher` {#eth-watcher}
88+
89+`%eth-watcher`, located at `/app/eth-watcher.hoon`, is responsible for listening
90+to an Ethereum node and collecting event logs from it. It is general-purpose and
91+not particular to Azimuth. It sends collected transactions to `+on-agent` in
92+`%azimuth`, which then obtains the resulting PKI state transitions by passing them to
93+[`naive.hoon`](#naive).
94+
95+[![Eth-watcher](https://media.urbit.org/docs/layer2/roller-agents.png)](https://media.urbit.org/docs/layer2/roller-agents.png)
96+
97+#### `%roller` {#roller}
98+
99+`%roller`, stored at `/app/roller.hoon`, is a Gall agent responsible for
100+collecting and submitting batches of layer 2 transactions to the Ethereum
101+blockchain. Among other things, it keeps
102+track of a list of pending transactions to be sent, transactions it has sent
103+that are awaiting confirmation, history of transactions sent organized by
104+Ethereum address, and when the next batch of transactions will be sent. See also
105+[Rollers](/docs/azimuth/l2/roller) for more information on the roller.
106+
107+The following diagram illustrates how the roller interacts with Bridge and
108+Ethereum at a high level.
109+
110+[![High level overview](https://media.urbit.org/docs/layer2/l2-high.png)](https://media.urbit.org/docs/layer2/l2-high.png)
111+
112+The relationship between the roller and other agents is outlined in the
113+following diagram.
114+
115+[![Roller](https://media.urbit.org/docs/layer2/roller-agents.png)](https://media.urbit.org/docs/layer2/roller-agents.png)
116+
117+`%roller` has a number of scries available, intended primarily to
118+display data to the end user in Bridge. They can be inferred from the `+on-peek`
119+arm:
120+
121+```hoon
122+ ++ on-peek
123+ |= =path
124+ ^- (unit (unit cage))
125+ |^
126+ ?+ path ~
127+ [%x %pending ~] ``noun+!>(pending)
128+ [%x %pending @ ~] (pending-by i.t.t.path)
129+ [%x %tx @ %status ~] (status i.t.t.path)
130+ [%x %history @ ~] (history i.t.t.path)
131+ [%x %nonce @ @ ~] (nonce i.t.t.path i.t.t.t.path)
132+ [%x %spawned @ ~] (spawned i.t.t.path)
133+ [%x %next-batch ~] ``atom+!>(next-batch)
134+ [%x %point @ ~] (point i.t.t.path)
135+ [%x %points @ ~] (points i.t.t.path)
136+ [%x %config ~] config
137+ [%x %chain-id ~] ``atom+!>(chain-id)
138+ ==
139+```
140+
141+This app is not responsible for communicating with Bridge via HTTP. Instead, that is
142+handled by `%roller-rpc`. The scries are also communicated to Bridge via
143+`%roller-rpc`.
144+
145+#### `%roller-rpc`
146+
147+`%roller-rpc`, stored at `/app/roller-rpc.hoon`, is a very simple Gall app responsible for receiving HTTP RPC-API
148+calls, typically sent from other Urbit ID users via Bridge. It then translates
149+these API calls from JSON to a format understood by `%roller` and
150+forwards them to `%roller`. This app
151+does not keep any state - its only purpose is to act as an intermediary between
152+Bridge and `%roller`. See [here](/docs/azimuth/l2/layer2-api) for more
153+information on the JSON RPC-API.
154+
155+### `naive.hoon` {#naive}
156+
157+`/lib/naive.hoon` consists of a gate whose sample is a `verifier`, `chain-id=@ud`,
158+`state`, and `input`, which outputs a cell of `[effects state]`. This is the
159+transition function which updates the state of the PKI stored in `%azimuth`
160+which handles state transitions caused by both layer 1 and layer 2 transactions.
161+A high-level overview of how `naive.hoon` functions can be found
162+[here](/docs/azimuth/l2/layer2#layer-2).
163+
164+A `verifier` is a gate whose sample is of the form `[dat=octs v=@ r=@ s=@]` and
165+which returns `(unit address)`:
166+
167+```hoon
168++$ verifier $-([dat=octs v=@ r=@ s=@] (unit address))
169+```
170+
171+The `verifier` in use by `naive.hoon` runs the keccak hash function on `dat` to
172+verify that `dat` is data signed by the ECDSA signature given by the `[v r s]`
173+tuple, according to the format for signed transactions outlined in the
174+[bytestring format](/docs/azimuth/l2/bytestring) documentation.
175+
176+`chain-id` is the ID used by the Ethereum blockchain, which is `1337`. See [bytestring
177+format](/docs/azimuth/l2/bytestring) for more information. This is used so that
178+e.g. transactions on the Ropsten test network cannot be replayed on the mainnet.
179+
180+`state` is the current state of the PKI. This is structured similarly to the
181+state held in [Azimuth.eth](/docs/azimuth/azimuth-eth), but will differ in
182+general since `state` takes into account layer 2 transactions as well. See the
183+[Layer 2 Overview](/docs/azimuth/l2/layer2#state) for more on how PKI state is handled.
184+
185+```hoon
186++$ state
187+ $: =points
188+ =operators
189+ dns=(list @t)
190+ ==
191++$ points (tree [ship point])
192+++ point
193+ $: :: domain
194+ ::
195+ =dominion
196+ ::
197+ :: ownership
198+ ::
199+ $= own
200+ $: owner=[=address =nonce]
201+ spawn-proxy=[=address =nonce]
202+ management-proxy=[=address =nonce]
203+ voting-proxy=[=address =nonce]
204+ transfer-proxy=[=address =nonce]
205+ ==
206+ ::
207+ :: networking
208+ ::
209+ $= net
210+ $: rift=@ud
211+ =keys
212+ sponsor=[has=? who=@p]
213+ escape=(unit @p)
214+ ==
215+ ==
216++$ dominion ?(%l1 %l2 %spawn)
217++$ operators (jug address address)
218+```
219+
220+`points` should be self-explanatory if you are already familiar with the
221+structure of [Azimuth.eth](/docs/azimuth/azimuth-eth). The only new addition is
222+`dominion`, whose value says
223+whether a ship is on layer 1, layer 2, or layer 1 with a layer 2 spawn proxy.
224+See [Layer 2 actions](/docs/azimuth/l2/l2-actions) for an overview of how
225+`dominion` determines the PKI actions available to a ship.
226+
227+`operators` already existed on layer 1 and are defined as a part of the [ERC-721
228+standard](https://eips.ethereum.org/EIPS/eip-721).
229+
230+`dns` is a list of DNS entries by which galaxy IP addresses may be looked up. At
231+present, this is always `~['urbit.org' 'urbit.org' 'urbit.org']`.
232+
content/docs/azimuth/hd-wallet.mdnew file+137
@@ -0,0 +1,137 @@
1++++
2+title = "Urbit HD Wallet"
3+weight = 3
4+template = "doc.html"
5++++
6+
7+Owners of Urbit identities need safeguards that allow for the use of Urbit
8+without jeopardizing cryptographic ownership of their assets. Toward this end,
9+we created the **Urbit Hierarchical Deterministic (HD) Wallet** for the storage
10+of identities. The Urbit HD Wallet is not one key-pair, but a system of related
11+key-pairs that each have distinct powers, from setting networking keys for
12+communicating in the Arvo network to transferring ownership of identities.
13+
14+The Urbit HD Wallet's derivation paths have a hierarchical structure, so that
15+keys with different powers can be physically separated. A "master ticket" can
16+[re-derive the entire wallet](#hd-wallet-generation) in case of loss. The
17+encryption and authentication keys that identities ships use to sign messages
18+within the network are also derived from the wallet.
19+
20+Another HD wallet option you may wish to utilize to store your Urbit are
21+hardware wallets such as Trezor or Ledger. We compare this method to the Urbit
22+HD wallet [below](#hardware-hd-wallet).
23+
24+Urbit HD wallets are composed of the following items, which are each assigned to
25+their own individual Ethereum key-pairs.
26+
27+### Master Ticket
28+
29+Think of your master ticket like a very high-value password. The master ticket
30+is the secret code from which all of your other keys are derived. Technically,
31+your master ticket is a cryptographic seed. You should never share it with anyone, and
32+store it very securely. This ticket can derive all of your other keys: your
33+ownership key and all of the related proxies.
34+
35+### Ownership Address
36+
37+An ownership address has all rights over the assets deeded to it. These rights
38+are on-chain actions described and implemented in
39+[Ecliptic](/docs/glossary/ecliptic), Azimuth's suite of governing
40+smart-contracts.
41+
42+### Proxies
43+
44+Each permanent Urbit ID can designate one or more
45+[proxies](/docs/using/id/proxies), which are Ethereum addresses capable of a
46+limited subset of Urbit ID transactions, such as spawning planets or rotating
47+keys. The HD wallet automatically generates additional addresses utilized as
48+proxies according to what is appropriate for your Urbit ID.
49+
50+### HD wallet generation
51+
52+Your Urbit HD wallet is generated from a `@q` seed called `T`, which looks
53+something like `~sampel-ticket-bucbel-sipnem`. This is the string known as your
54+"Master Ticket" that you input into Bridge to sign in. This is put through a
55+series of algorithms that ultimately generate your keys and the Ethereum
56+addresses at which they are stored.
57+
58+![](https://media.urbit.org/fora/proposals/UP-8.jpg)
59+
60+First, your `@q` is converted into a numeric value `E` as an intermediary step
61+by adding [salt](<https://en.wikipedia.org/wiki/Salt_(cryptography)>). Then by
62+adding additional salts, `E` is converted into a set of BIP39 seed phrases -
63+these are 24 word mnemonic sequences used to generate Ethereum wallets. You end
64+up with one seed phrase for each proxy associated with your ship, and these seed
65+phrases are then used to generate Ethereum wallets.
66+
67+One of the wallets will store your Azimuth point, an [ERC-721](#erc-721) token,
68+which will be known as your ownership address. Bridge then automatically uses
69+your ownership address to assign the other proxies to the other wallets
70+generated.
71+
72+### ERC-721
73+
74+Most Ethereum tokens use the ERC-20 standard for smart contracts. Urbit
75+identities are, however, essentially different from most Ethereum tokens, due to
76+identities not being fungible. Since any two stars will handle social-networking
77+realities in a different way, they will carry a different reputation.
78+
79+The ERC-721 standard, having been made specifically to provide a smart-contract
80+interface for non-fungible assets, serves our needs well. This is the standard
81+that we use for deeding Urbit identities.
82+
83+Identities, and all of their blockchain operations, are governed by Ecliptic.
84+Ecliptic is an Ethereum smart-contract that governs identity state and the
85+ownership, spawn, management, and voting rights affiliated with your identities.
86+
87+For the technical implementation details, take a look at Azimuth's [Github
88+repository](https://github.com/urbit/azimuth).
89+
90+## Hardware HD wallet
91+
92+You may also store your Urbit using a hardware HD wallet such as a Trezor or
93+Ledger. This option is used instead of a master ticket - it is a totally
94+separate process from that outlined above. How hardware wallets work are outside
95+of the scope of this document, but here we explain how you may utilize your
96+hardware wallet in a similar fashion to the Urbit HD wallet.
97+
98+A hardware HD wallet is generated from a seed phrase that should be thought of
99+as analogous to the `@q` `T` used to generate the Urbit HD wallet in the above
100+diagram. This seed phrase is a human readable sequence of words that may be used
101+to generate private keys to a near-limitless number of wallets created by adding
102+salt. Some hardware wallets also allow an additional passphrase to go into the
103+generation of these wallets. The seed phrase and passphrase should be considered
104+equal in value to the master ticket `T`- never share these with anyone!
105+
106+In order to use your hardware wallet as your Urbit wallet, you first need to
107+generate a set of addresses on which you would like to store your Azimuth point
108+and proxies. Consult your wallet vendor on how to do this. Then login to Bridge
109+using your current method (likely a master ticket) and transfer ownership to the
110+wallet address you generated on your hardware wallet for ownership.
111+
112+Next, login to Bridge using your hardware wallet. While Bridge supports Trezor
113+and Ledger natively, this may require using Metamask as an intermediary anyways,
114+depending on which firmware you are running. Then [accept the
115+transfer](/using/id/using-bridge#accept-your-transfer). Your Azimuth point is
116+now stored on your hardware wallet.
117+
118+To finish the process, use Bridge to set your management, voting, and spawn
119+proxies to the other addresses you generated as applicable. You are now using
120+your hardware HD wallet in an analogous fashion to the Urbit HD wallet.
121+
122+## Heightened security practices
123+
124+A common security pattern is to have "hot" and "cold" wallets. For higher value
125+points such as stars and galaxies, you may consider having your ownership
126+address live on a "cold" wallet that never touches an internet-connected
127+computer, and the various proxies on a "hot" wallet that is permitted to connect
128+to internet-connected devices. This could be accomplished with multiple hardware
129+wallets, a combination of paper and hardware wallet, a hardware cold wallet and
130+Metamask hot wallet, etc. See the [User Manual](/using/id/hd-wallet) for
131+concrete suggestions on security practices.
132+
133+One tool useful for this setup is `claz`, located at `app/claz.hoon`. `claz` is
134+used for making and signing Bridge transactions from an offline computer. A
135+guide to using `claz` is available [here](/docs/azimuth/advanced-azimuth-tools).
136+
137+
content/docs/azimuth/l2/_index.mdnew file+35
@@ -0,0 +1,35 @@
1++++
2+title = "Layer 2"
3+weight = 800
4+sort_by = "weight"
5+template = "sections/docs/chapters.html"
6+insert_anchor_links = "right"
7++++
8+
9+Documentation of the technical details of naive rollups, our Layer 2 solution
10+for the reduction of Urbit ID gas prices and friction associated with the usage
11+of cryptocurrency.
12+
13+### [Layer 2 Overview](/docs/azimuth/l2/layer-2)
14+
15+A high-level technical description of the functionality of the naive rollups
16+"Hoon smart contract" and associated apps, such as Bridge and the roller.
17+
18+### [Layer 2 Actions](/docs/azimuth/l2/l2-actions)
19+
20+An exhaustive list of what Azimuth actions can be performed for any given tuple
21+`(ship rank, layer 2 status)`.
22+
23+### [Transaction Format](/docs/azimuth/l2/bytestring)
24+
25+The bytestring format for layer 2 transactions and batches.
26+
27+### [Rollers](/docs/azimuth/l2/roller)
28+
29+How rollers work.
30+
31+### [Roller HTTP RPC API](/docs/azimuth/l2/layer2-api)
32+
33+Documentation on the HTTP RPC API used for Urbit to communicate with Bridge to
34+manage layer 2 transactions.
35+
content/docs/azimuth/l2/bytestring.mdnew file+201
@@ -0,0 +1,201 @@
1++++
2+title = "Transaction Format"
3+weight = 8
4+template = "doc.html"
5++++
6+
7+This document gives the bytestring format for layer 2 transactions and batches.
8+
9+[Recall](/docs/azimuth/l2/layer2.md) that a layer 2 transaction is a compact
10+representation of an Azimuth action (format given below), along with a 65-byte
11+ECDSA signature. A `batch` is an atom that is a concatenation of one or more
12+layer 2 transactions and associated signatures. This atom is what is posted on
13+the Ethereum blockchain by a roller.
14+
15+We remark that each transaction from a given ship in a batch needs a separate
16+signature, since data such as the nonce are not included in the transaction but
17+are used in the signature. Thus a ship cannot submit multiple transactions with
18+a single signature for all of them - a different signature is needed for each
19+transaction.
20+
21+## Byte format
22+
23+We describe the byte format of a `batch` and its components in the following.
24+All atoms described here are read by the parser as little-endian - i.e. it reads
25+the last digit first and proceeds backwards.
26+
27+For the purposes of concatenation, all atoms are encoded using `octs=(pair @ud
28+@)`, which is a way to represent atoms with a fixed width in order to account
29+for leading zeroes. Here `@ud` will be the length of the atom in bytes, while
30+the `@` is actual atom.
31+
32+### Batches {#batch}
33+
34+A `batch` is an atom that is the concatenation of several raw transactions,
35+which are themselves atoms. `naive.hoon` starts reading the `batch` from the end
36+and working backwards (little-endian). A `batch` looks like:
37+
38+```
39+action-n
40+signature-n
41+action-(n-1)
42+signature-(n-1)
43+...
44+action-2
45+signature-2
46+action-1
47+signature-1
48+```
49+
50+Be careful to distinguish between an "action" and an "unsigned transaction". An
51+action is a short bytestring that describes an Azimuth action as given in the
52+[following section](#actions), while an unsigned transaction is an action plus
53+the nonce, chain ID, header. Actions are what are submitted to Ethereum, while
54+unsigned transactions are what are signed and used as the signatures in the
55+above `batch` format. When `naive.hoon` parses a batch it adds the appropriate
56+nonce, chain ID, and header to a given action and uses that to verify the
57+corresponding signature, rather than just the action itself. This reduces the
58+number of bytes in the batch, making transactions cheaper.
59+
60+### Actions {#actions}
61+
62+The byte format of an action as they appear in a `batch` is as
63+follows. They are parsed by the `+parse-tx` arm in `naive.hoon`.
64+
65+```
66+remainder: arguments
67+7 bits: operation
68+4 bytes: ship sending the transaction
69+5 bits: padding
70+3 bits: proxy
71+```
72+
73+The `proxy` is an atom between `0` and `4`, which corresponds as follows:
74+```
75+%0 %own
76+%1 %spawn
77+%2 %manage
78+%3 %vote
79+%4 %transfer
80+```
81+Note that `%vote` proxies are not supported by layer 2.
82+
83+The ship is its `@p` encoded as an `@`. As we are working with fixed width
84+atoms, the full 4 bytes is used, even if the bit length of the `@p` is shorter.
85+
86+The operation is an atom between `0` and `10` corresponding as follows:
87+
88+```
89+%0 %transfer-point
90+%1 %spawn
91+%2 %configure-keys
92+%3 %escape
93+%4 %cancel-escape
94+%5 %adopt
95+%6 %reject
96+%7 %detach
97+%8 %set-management-proxy
98+%9 %set-spawn-proxy
99+%10 %set-transfer-proxy
100+```
101+
102+Since the operation is represented with 7 bits, to complete the byte the
103+arguments either use the remaining bit as a binary flag or as padding.
104+
105+#### `%transfer-point`
106+
107+```
108+20 bytes: address to transfer to
109+1 bit: breach?
110+```
111+
112+#### `%spawn`
113+
114+As before, the length of the ship argument is always 4 bytes.
115+
116+```
117+20 bytes: address to set transfer proxy of spawned ship to
118+4 bytes: ship to spawn
119+1 bit: padding
120+```
121+
122+#### `%configure-keys`
123+
124+```
125+4 bytes: crypto suite
126+32 bytes: encryption public key
127+32 bytes: authentication public key
128+1 bit: breach?
129+```
130+
131+#### `%escape`, `%cancel-escape`, `%adopt`, `%reject`, `%detach`
132+
133+Each of these actions have the same argument - a single ship. Again, the length
134+of the ship argument is always 4 bytes.
135+
136+```
137+4 bytes: ship
138+1 bit: padding
139+```
140+
141+#### `%set-management-proxy`, `%set-spawn-proxy`, `%set-transfer-proxy`
142+
143+Each of these actions have the same argument - an Ethereum address:
144+
145+```
146+20 bytes: address
147+1 bit: padding
148+```
149+
150+### Unsigned transactions {#unsigned}
151+
152+An unsigned transaction is an atom consisting of the concatentation of an Ethereum signed
153+message header, an Urbit ID header, a chain ID, a nonce, and an action. This has the following format:
154+
155+```hoon
156+%: cad 3
157+ 26^'\19Ethereum Signed Message:\0a'
158+ (met 3 len)^len
159+ 14^'UrbitIDV1Chain'
160+ (met 3 chain-t)^chain-t
161+ 1^':'
162+ 4^nonce
163+ action
164+ ~
165+==
166+```
167+
168+Here `+cad` is a gate in `/lib/tiny.hoon` that concatenates atoms given in `octs` format. The
169+argument `3` is a `bloq` size meaning `2^3=8` bits (one byte), and the head of
170+each cell (which are `octs`) in the arguments that follow is the number of blocks (number of bytes
171+in this scenario) of each entry, with the tail being the actual data.
172+
173+`len` is the length measured in bytes of everything following it except the
174+signature. `chain-t` is the chain ID, which is to distinguish between e.g. the
175+Ethereum test net and main net, to ensure that transaction used in one cannot be
176+rebroadcast on the other (see
177+[EIP-155](https://eips.ethereum.org/EIPS/eip-155)). We note that `len` and
178+`chain-t` are both ASCII decimals (`@t` in Hoon), while `nonce` and `action` are
179+`@ud`s.
180+
181+Again we emphasize that unsigned transactions are _not_ what is submitted in a
182+batch - an [action](#actions) and a [signature](#signatures) are. A ship
183+submitting a layer 2 transaction to a roller signs an unsigned transaction and
184+this signature is included along with the action, which does not include the
185+additional data listed above. When a ship determines whether or not a given
186+layer 2 action is valid, it adds the additional data to the action to form an
187+unsigned transaction and verifies the signature against that.
188+
189+### Signatures {#signatures}
190+
191+The signature is a 65-byte ECDSA signature as described in
192+[EIP-191](https://eips.ethereum.org/EIPS/eip-191) and is compatible with
193+`personal_sign`. The precise format of the signature depends on which wallet was
194+used to sign it. Layer 2 supports all major signature formats, including
195+Metamask, Trezor, Ledger, and others. Signatures in batches are obtained by signing
196+an [unsigned transaction](#unsigned).
197+
198+Because of the format of signatures, it may have leading zeroes resulting in a
199+64-byte signature, and so it is important to use `octs` to ensure that it is
200+interpreted as being 65 bytes.
201+
content/docs/azimuth/l2/l2-actions.mdnew file+183
@@ -0,0 +1,183 @@
1++++
2+title = "Layer 2 Actions"
3+weight = 6
4+template = "doc.html"
5++++
6+
7+There are a total of eleven layer 2 actions, each corresponding to a familiar
8+[layer 1 action](/docs/azimuth/ecliptic): `%transfer-point`, `%spawn`,
9+`%configure-keys`, `%escape`, `%cancel-escape`, `%adopt`, `%reject`, `%detach`,
10+`%set-management-proxy`, `%set-spawn-proxy`, and `%set-transfer-proxy`.
11+Descriptions of what these actions do may be found by searching for them at
12+[Azimuth.eth](/docs/azimuth/azimuth-eth).
13+
14+Once a ship moves to layer 2, the owner will still utilize the same private keys
15+they used before the transfer to perform Azimuth actions. This includes the ownership
16+key as well as proxies. Stars and galaxies may move their spawn proxy to layer 2
17+while otherwise remaining on layer 1, but it is not possible to transfer only
18+the management proxy to layer 2; it may only happen as a side-effect of
19+transferring ownership to layer 2.
20+
21+### Moving a pre-existing ship to L2
22+
23+In order to move your ship from layer 1 to layer 2, transfer ownership of your
24+ship to the address `0x1111111111111111111111111111111111111111`. The easiest
25+way to accomplish this is using [Bridge](/docs/glossary/bridge). The Azimuth
26+smart contracts interpret any ship at this address as being on layer 2.
27+
28+### Dominion
29+
30+Layer 2 Azimuth data for a given ship includes which layer that ship is on. We
31+call this the ship's _dominion_. There are three dominions: `%l1`, `l2`, and
32+`%spawn`. Planets may exist in dominion `%l1` or `%l2`, stars may exist in any
33+of the three dominions, and galaxies may exist in dominion `%l1` or `%spawn`. We
34+detail what this means in each case in the following.
35+
36+### Planets
37+
38+*Permitted dominions:* `%l1`, `%l2`.
39+
40+#### `%l1` planets
41+
42+*Permitted layer 2 actions:*
43+ - owner: `%escape`, `%cancel-escape`
44+ - management proxy: `%escape`, `%cancel-escape`
45+ - transfer proxy: none
46+
47+A planet in dominion `%l1` is said to exist on layer 1, which is the default
48+state for all planets prior to the introduction of naive rollups. In addition to
49+the ordinary layer 1 Azimuth actions a planet can perform, they may also choose to
50+`%escape` or `%cancel-escape` on layer 2 using either their ownership key or
51+[management proxy](/docs/glossary/proxies). See the [layer 2 sponsorship](/docs/azimuth/l2/layer2#sponsorship)
52+section for more information on layer 1 ships performing layer 2
53+sponsorship actions.
54+
55+Layer 1 planets may also move to dominion `%l2` by depositing their ownership to
56+the layer 2 deposit address.
57+
58+#### `%l2` planets
59+
60+*Permitted layer 2 actions:*
61+ - owner: `%transfer-point`, `%configure-keys`,
62+`%escape`, `%cancel-escape`, `%set-management-proxy`, `%set-transfer-proxy`
63+ - management proxy: `%configure-keys`, `%escape`, `%cancel-escape`,
64+`%set-management-proxy`
65+ - transfer proxy: `%transfer-point`, `%set-transfer-proxy`
66+
67+A planet in dominion `%l2` is said to exist on layer 2. A planet may be on layer
68+2 either by previously being a layer 1 planet deposited to the layer 2 address,
69+or by being spawned by a star in dominion `%spawn` or `%l2`, in which case it
70+will always be on layer 2.
71+
72+A layer 2 planet is no longer capable of performing any layer 1 actions, and
73+cannot move to layer 1.
74+
75+### Stars
76+
77+*Permitted dominions:* `%l1`, `%spawn`, `%l2`.
78+
79+#### `%l1` stars
80+
81+*Permitted layer 2 actions:*
82+ - owner: `%escape`, `%cancel-escape`, `%adopt`,
83+`%reject`, `%detach`
84+ - management proxy: `%escape`, `%cancel-escape`, `%adopt`,
85+`%reject`, `%detach`
86+ - spawn proxy: none
87+ - transfer proxy: none
88+
89+A star in dominion `%l1` is said to exist on layer 1, which is the default state
90+for all stars prior to the introduction of naive rollups. In addition to the
91+ordinary Azimuth actions a star can perform, they may also perform any
92+sponsorship-related actions on layer 2.
93+
94+A `%l1` dominion star may move to dominion `%spawn` by depositing its spawn proxy to the
95+layer 2 deposit address, or may move to dominion `%l2` by depositing its ownership
96+to the layer 2 deposit address. Both actions are irreversible.
97+
98+#### `%spawn` stars
99+
100+*Permitted layer 2 actions:*
101+ - owner: `%escape`, `%cancel-escape`, `%adopt`,
102+`%reject`, `%detach`, `%spawn`, `%set-spawn-proxy`
103+ - management proxy: `%escape`,
104+`%cancel-escape`, `%adopt`, `%reject`, `%detach`
105+ - spawn proxy: `%spawn`,
106+`%set-spawn-proxy`
107+ - transfer proxy: none
108+
109+A star in dominion `%spawn` is said to exist on layer 1.
110+
111+A star in dominion `%spawn` may spawn planets directly on layer 2, but will no
112+longer be able to spawn layer 1 planets and will no longer be able to set its
113+spawn proxy on layer 1. All other layer 1 Azimuth actions may still be performed
114+by the star.
115+
116+A star moving from `%l1` to `%spawn` has no effect on sponsorship status of any
117+of its sponsored planets. Moving to `%spawn` from `%l1` is currently
118+irreversible - the only further change to dominion permitted is moving to `%l2`.
119+
120+#### `%l2` stars
121+
122+*Permitted layer 2 actions:*
123+ - owner: `%transfer-point`, `%spawn`, `%configure-keys`, `%escape`,
124+`%cancel-escape`, `%adopt`, `%reject`, `%detach`, `%set-management-proxy`,
125+`%set-spawn-proxy`,`%set-transfer-proxy`
126+ - management proxy: `%escape`,
127+`%cancel-escape`, `%adopt`, `%reject`, `%detach`, `%configure-keys`,
128+`%set-management-proxy`
129+ - spawn proxy: `%spawn`, `%set-spawn-proxy`
130+ - transfer proxy: `%transfer-point`, `%set-transfer-proxy`
131+
132+A star in dominion `%l2` is said to exist on layer 2. A star may exist on layer
133+2 by being deposited to the layer 2 deposit address from layer 1, or by being
134+spawned by a `%spawn` dominion galaxy.
135+
136+A star in dominion `%l2` cannot perform any layer 1 actions.
137+
138+### Galaxies
139+
140+*Permitted dominions:* `%l1`, `%spawn`.
141+
142+#### `%l1` galaxies
143+
144+*Permitted layer 2 actions:*
145+ - owner: `%adopt`, `%reject`, `%detach`
146+ - management proxy: `%adopt`, `%reject`, `%detach`
147+ - spawn proxy: none
148+ - transfer proxy: none
149+ - voting proxy: none.
150+
151+A galaxy in dominion `%l1` is said to exist on layer 1, which is the default state
152+for all galaxies prior to the introduction of naive rollups. In addition to the
153+ordinary Azimuth actions a galaxy can perform, they may also perform any
154+sponsorship-related actions on layer 2. `%l1` galaxies can perform all the usual
155+layer 1 Azimuth actions, and may also perform layer 2 sponsorship actions.
156+
157+A `%l1` dominion galaxy may move to dominion `%spawn` by depositing its spawn proxy to the
158+layer 2 deposit address. This action is irreversible. Note, however that the
159+majority of galaxies already have all of their stars spawned in the [Linear
160+Star Release
161+Contract](https://etherscan.io/address/0x86cd9cd0992f04231751e3761de45cecea5d1801).
162+Layer 2 has no interactions with this contract - all stars released in this
163+manner are `%l1` dominion stars. Moving to the `%spawn` dominion has no effect
164+on sponsorship status.
165+
166+#### `%spawn` galaxies
167+
168+*Permitted layer 2 actions:*
169+ - owner: `%adopt`, `%reject`, `%detach`, `%spawn`,
170+`%set-spawn-proxy`
171+ - management proxy: `%adopt`, `%reject`, `%detach`
172+ - spawn proxy: `%spawn`, `%set-spawn-proxy`
173+ - transfer proxy: none
174+ - voting proxy: none
175+
176+Galaxies may either remain on layer 1, or, similar to stars, they may
177+deposit their spawn proxy to layer 2. They cannot move their ownership,
178+management proxy, or voting proxy to layer 2. However, as with stars,
179+sponsorship actions may be performed on layer 2 using the ownership or
180+management proxies regardless of the dominion status of the galaxy.
181+
182+
183+
content/docs/azimuth/l2/layer2-api.mdnew file+14
@@ -0,0 +1,14 @@
1++++
2+title = "Roller HTTP RPC-API"
3+weight = 10
4+template = "doc.html"
5++++
6+
7+With the introduction of Layer 2 arrived a new set of Gall agents equipped with
8+an HTTP RPC-API primarily intended for interacting with Bridge. The
9+documentation for this API is coming soon.
10+
11+The set of API calls available is summarized in the following diagram.
12+
13+[![JSON RPC-API](https://media.urbit.org/docs/layer2/l2-json-rpc.svg)](https://media.urbit.org/docs/layer2/l2-json-rpc.svg)
14+
content/docs/azimuth/l2/layer2.mdnew file+402
@@ -0,0 +1,402 @@
1++++
2+title = "Layer 2 Overview"
3+weight = 5
4+template = "doc.html"
5++++
6+
7+This document provides technical details on Azimuth's "Layer 2" scaling solution
8+for Azimuth, known more formally as "naive rollups". We focus here primarily on the
9+"Hoon smart contract" located at `/lib/naive.hoon` in your ship's pier, as well
10+as other proximal topics.
11+
12+This is intended for developers that desire a deeper understanding of how this
13+protocol works, how secure it is, and how to extract data from layer 2 to obtain
14+a complete picture of the Arvo network.
15+
16+This is not intended for everyday users who only wish to know how
17+to either transfer their ship to layer 2 or perform layer 2 actions. For that,
18+see ((bridge documentation yet to be written)). For a casual overview of the
19+rationale and functionality of layer 2, please see this [blog
20+post](/blog/rollups). For more information on how Azimuth works more generally,
21+including interactions with Bridge and Ethereum, see the page on [Azimuth data flow](/docs/azimuth/flow).
22+
23+This page is also not where to find instruction on how to run your own "aggregator"/"roller".
24+Documentation for this process is forthcoming. However, this page does contain
25+essential background information for anybody in this category.
26+
27+## Summary
28+
29+Naive rollups were developed in response to rising gas costs for performing
30+Azimuth actions. They also serve the dual purpose of making onboarding easier,
31+as it is now possible to acquire a planet and get on Urbit without any knowledge
32+of Ethereum or cryptocurrency.
33+
34+In this section we give a high-level summary of how naive rollups function and
35+how they affect the end user. Later sections elaborate on this summary.
36+
37+### Layer 1
38+
39+We briefly review how "Layer 1", i.e. the [Azimuth](/docs/glossary/azimuth) smart
40+contract suite, functions. An update to the Azimuth PKI data stored on your urbit
41+occurs with four steps:
42+
43+ 1. A transaction is posted to the Ethereum blockchain.
44+ 2. The [Ethereum Virtual Machine](https://ethereum.org/en/developers/docs/evm/)
45+ calculates the resulting state transition and checks its validity, then
46+ updates the state if it is a valid transition.
47+ 3. Your urbit downloads the new state from an Ethereum node.
48+ 4. Your urbit makes the final decision on whether the new state is valid.
49+
50+By default, step four always succeeds. It has always been possible in theory for
51+your urbit to dispute what it read on Ethereum, but there has never been any
52+reason to do so.
53+
54+### Layer 2 {#layer-2}
55+
56+Layer 1 still functions identically today as it did before naive rollups. Naive
57+rollups work via the following process.
58+
59+ 1. A batch of one or more transactions is posted to the Ethereum blockchain by
60+ an urbit node called a roller or aggregator.
61+ 2. Your urbit downloads the transactions from an Ethereum node.
62+ 3. Your urbit computes the resulting state transitions from the transactions
63+ and checks them for validity.
64+ 4. Your urbit updates its locally stored Azimuth state using state transitions
65+ from the batch that have been deemed valid.
66+
67+ In comparison with Layer 1, the EVM no longer checks the validity or computes
68+ the state transitions for any given transaction. It is now being used solely as
69+ a database of submitted transactions, and the business logic of computing what
70+ these transactions mean has been offloaded to your urbit. Thus we think of
71+ `naive.hoon` as being the first "Hoon smart contract". You could also consider
72+steps 3 and 4 of the Layer 2 process as being a fattening of the trivial step 4
73+ of the layer 1 process.
74+
75+Here we briefly elaborate on the layer 2 steps, but see below for more technical
76+detail.
77+
78+A roller is any urbit node - even a moon, comet, or fakezod will do - to which
79+batches of transactions are submitted. You could use your own ship as a roller
80+if you wanted. The roller collects batches of transactions from whichever
81+parties they choose and submits them to the Ethereum blockchain all at once.
82+We expect this to either happen on a regular interval, or once some minimum
83+threshold of transactions is reached, but the decision on when to submit is
84+ultimately up to the roller.
85+
86+Computing the resulting state transitions obtained from downloaded Ethereum
87+transactions is done using `/lib/naive.hoon`, which is a gate that accepts both layer
88+1 transaction logs and layer 2 batches, and then computes the resulting state
89+transitions and updates the ship's internal Azimuth data held in
90+the Gall agent `/app/azimuth.hoon` accordingly.
91+
92+### Savings in gas costs
93+
94+There are several dimensions by which naive rollups saves on gas over layer 1.
95+They are:
96+
97+ 1. Gas is not spent on instructing the EVM to compute state transitions and
98+ confirm validity.
99+ 2. Layer 2 Azimuth state is not stored on Ethereum, so the only data storage
100+ gas costs is for the transactions themselves.
101+ 3. Layer 2 transactions are written in a highly compressed form. E.g., instead
102+ of calling the spawn action by name, it is simply referred to as action `%1`.
103+ 4. By collecting multiple layer 2 transactions and submitting them as a single
104+ "batch transaction", additional gas savings are achieved by not needing to
105+ duplicate information such as which smart contract the transactions are
106+ intended for.
107+
108+Put together, these create a reduction in gas costs of at least 65x when adding
109+a transaction to a sufficiently large batch (approximately 30 or more
110+transactions). A single transaction submitted as a batch is approximately 5x
111+cheaper, while 10 transaction submitted as a batch is approximately 30x cheaper.
112+Thus using one's own ship to submit a single-transaction batch is still a
113+cost-saving measure.
114+
115+### One way trip
116+
117+Moving to layer 2 is a one-way trip for now. This means that once a ship moves
118+to layer 2, it cannot be moved back to layer 1. We believe it to be technically
119+possible to engineer a return trip, and expect that someday this will be the
120+case, but there are no plans to implement this in the near future.
121+
122+## Interacting with L2
123+
124+Layer 2 ships can perform the same actions on layer 2 that they could on
125+layer 1, but are no longer able to perform any layer 1 actions. Layer 1 ships
126+can also perform a subset of layer 2 actions - namely the ones related to
127+sponsorship.
128+
129+For a complete list of what layer 2 actions each ship rank, layer, and proxy can
130+perform, see [Layer 2 Actions](/docs/azimuth/l2/l2-actions). For an explicit
131+description of the byte format of Layer 2 Ethereum transaction, see [Bytestring format](/docs/azimuth/l2/bytestring).
132+
133+### Sponsorship {#sponsorship}
134+
135+Due to the possibility of sponsors and sponsees existing on different layers,
136+the precise logic of how sponsorship works is complex. However, under common
137+circumstances it is simple.
138+
139+If either the sponsor or sponsee are on layer 2, then sponsorship actions must
140+occur on layer 2. The only exception to this is detaching. A sponsor on layer 1
141+may perform a layer 1 detach action on a layer 2 sponsee, and this will result
142+in the sponsee having no sponsor on layer 1, and layer 2 as well if they were
143+the sponsor on layer 2. This is necessary to simplify the logic, but it also
144+guarantees that there is no hard requirement to ever utilize layer 2. Without
145+this exception, sponsors with sponsees that move to layer 2 would be forced to
146+detach them as a layer 2 action if they wanted to cease sponsorship. This would
147+also have an unacceptable impact on ships owned by [smart contracts](#smart-contracts).
148+
149+If both sponsor and sponsee are on layer 1 then sponsorship actions may occur on
150+either layer. As long as all sponsorship actions betweeen the two parties occur
151+on a single layer, behavior will be as expected.
152+
153+In most cases this is sufficient to understand how sponsorship works. However
154+there are a number of edge cases that make this more complicated that developers
155+may need to concern themselves with in scenarios where layer 1 sponsor and
156+sponsees are mixing layer 1 and layer 2 actions. In the [Sponsorship state
157+transitions](#sponsorship-state-transitions) section below, we give a table that
158+shows how the sponsor and escape status of a ship changes according to which
159+actions are taken.
160+
161+### Smart contracts {#smart-contracts}
162+
163+Smart contracts are unable to own layer 2 ships, and thus cannot sign layer 2
164+transactions. This creates a hard requirement that layer 1 ships be allowed to
165+perform a layer 1 detach operation on a layer 2 ships.
166+
167+## Azimuth state {#state}
168+
169+The introduction of layer 2 presents additional complication in understanding
170+Azimuth state. In order to be precise we define the following terminology:
171+
172+ - _Layer 1 Azimuth state_ refers to the state of Azimuth as reflected on the
173+ Ethereum blockchain. This excludes all layer 2 transactions. Depositing to
174+ layer 2 is considered a layer 1 action, so the layer 1 Azimuth state is aware
175+ of which ships are on layer 2, but is blind to everything that happens to
176+ them afterward.
177+ - _Layer 2 Azimuth state_ refers to the state of Azimuth as stored in
178+ `/app/azimuth.hoon` on your ship. The state here takes into account
179+ transactions that occur on both layers. No distinction between the
180+ layers is made in the state here - e.g. a ship only has one sponsor in Layer 2
181+ Azimuth state, not a layer 1 sponsor and a layer 2 sponsor. This is the state
182+ actually in use by Urbit. Layer 1 Azimuth state is now only an input for
183+ generating Layer 2 Azimuth state, so any time a ship needs to check e.g. the
184+ public key of a ship (regardless of which layer it is on), it will check the
185+ Layer 2 Azimuth state, not the Layer 1 Azimuth state.
186+ - _Layer-2-Only Azimuth state_ refers to the state of Azimuth as reflected
187+ solely by layer 2 transactions. This state is not explicitly stored anywhere,
188+ but is computed as part of the process to create the Layer 2 Azimuth state.
189+ We do not make any further references to this state, but it is important to
190+ keep in mind conceptually.
191+
192+Layer 1 Azimuth state is computed by the Ethereum Virtual Machine. Layer 2
193+Azimuth state is computed by taking in the Layer 1 Azimuth state and modifying
194+it according to layer 2 transactions using `/lib/naive.hoon`. When we are being
195+precise about which state we are referring to we will utilize capitalization as above.
196+
197+Layer 2 Azimuth state is held by the Azimuth Gall app located at
198+`/lib/azimuth.hoon`. Layer 1 and layer 2 state are not held separately - your
199+ship holds only one canonical Azimuth state, generated by parsing both layer 1
200+and layer 2 Ethereum transactions using `/lib/naive.hoon`. It is important to
201+keep in mind that Layer 1 Azimuth state is entirely unaware of Layer 2 Azimuth
202+state. Thus, for instance, the Azimuth PKI on Ethereum (Layer 1 Azimuth state)
203+may claim that the sponsor of `~sampel-palnet` is `~marzod`, while the Azimuth
204+state held on your ship (Layer 2 Azimuth state) claims that the sponsor of
205+`~sampel-palnet` is `~dopzod`. Under this circumstance, this would mean that the
206+sponsor of `~sampel-palnet` was `~marzod` before `~sampel-palnet` was deposited
207+to layer 2, and thus the Azimuth PKI on Ethereum will forever reflect this.
208+
209+For more information on how Azimuth state is handled, including how this
210+integrates with Bridge and Ethereum, see [Azimuth data flow](/docs/azimuth/flow).
211+
212+### Sponsorship state transitions
213+
214+When either a sponsor or sponsee is on layer 2, then all sponsorship actions
215+occur on layer 2 and layer 1 Azimuth state is ignored. The exception to this, as
216+noted [above](#sponsorship), is when a layer 1 sponsor performs a layer 1 detach
217+action on a layer 2 sponsee. Furthermore, any time a ship moves from layer 1 to
218+layer 2, its sponsorship status is automatically maintained in layer 2.
219+
220+The only potentially complicated scenario is when both sponsee and (potential)
221+sponsor exist on layer 1. Then because layer 1 actions can modify layer 2 state,
222+careful consideration is required for interactions that mix the two. If you
223+and your sponsor/sponsee are not mixing layer 1 and layer 2 sponsorship actions
224+between yourselves, then you have nothing to worry about and may safely ignore this
225+section.
226+
227+But, for instance, if both `~sampel-palnet` and `~dopzod` are on layer 1, it is
228+technically possible for `~sampel-palnet` to escape to `~dopzod` on layer 1, and
229+then `~dopzod` can accept the escape on layer 2. This will result in `~dopzod`
230+appearing as the sponsor in the Layer 2 Azimuth state (and thus be
231+`~sampel-palnet`'s "true" sponsor), and the sponsor in the Layer 1 Azimuth state
232+will remain unchanged. While it is difficult to imagine a good reason to do
233+this, developers working with layer 2 need to keep in mind these edge cases and
234+ought to read on.
235+
236+In the following table, columns `E_1` and `S_1` represent the escape status and
237+sponsor of a given ship as reflected by the Layer 1 Azimuth state. Columns `E_2`
238+and `S_2` represent the escape status and sponsor of a given ship as reflected
239+in the Layer 2 Azimuth State. The "true" escape status and sponsor of a ship is
240+always what is listed in the Layer 2 Azimuth state. In other words, at the end
241+of the day, `S_2` is always the sponsor that matters, but layer 1 actions can
242+affect the values of `E_2` and `S_2`.
243+
244+A tar `*` entry represents any value and if an event shows a transition
245+from `*` to `*` that means that value is not altered by the transition. The
246+transitions marked with `!!` are prohibited by the layer 1 Azimuth smart
247+contract and thus never occur. `A1` and `A2` represent two distinct ships.
248+
249+```
250+Event | E_1 | E_2 | S_1 | S_2 | -> | E_1 | E_2 | S_1 | S_2
251+L1-escape A1 | * | * | * | * | -> | A1 | A1 | * | *
252+L1-cancel A1 | ~ | * | * | * | -> !! :: no cancel if not escaping
253+L1-cancel A1 | A1 | * | * | * | -> | ~ | ~ | * | *
254+L1-adopt A1 | A1 | * | * | * | -> | ~ | ~ | A1 | A2
255+L1-adopt A1 | ~ | * | * | * | -> !! :: no adopt if not escaping
256+L1-adopt A1 | A2 | * | * | * | -> !! :: no adopt if not escaping
257+L1-detach A1 | * | * | A1 | A1 | -> | * | * | ~ | ~
258+L1-detach A1 | * | * | A1 | A2 | -> | * | * | ~ | A2
259+L1-detach A1 | * | * | A1 | ~ | -> | * | * | ~ | ~
260+L2-escape A1 | * | * | * | * | -> | * | A1 | * | *
261+L2-cancel A1 | * | * | * | * | -> | * | ~ | * | *
262+L2-adopt A1 | * | A1 | * | * | -> | * | ~ | * | A1
263+L2-adopt A1 | * | A2 | * | * | -> | * | A2 | * | *
264+L2-adopt A1 | * | ~ | * | * | -> | * | ~ | * | *
265+L2-reject A1 | * | A1 | * | * | -> | * | ~ | * | *
266+L2-reject A1 | * | A2 | * | * | -> | * | A2 | * | *
267+L2-reject A1 | * | ~ | * | * | -> | * | ~ | * | *
268+L2-detach A1 | * | * | * | A1 | -> | * | * | * | ~
269+L2-detach A1 | * | * | * | A2 | -> | * | * | * | A2
270+L2-detach A1 | * | * | * | ~ | -> | * | * | * | ~
271+```
272+
273+## Aggregators
274+
275+An "aggregator" or "roller" is any Urbit node that collects signed layer 2
276+transactions (typically via `/app/azimuth-rpc.hoon`), combines them into a
277+"batch", and then submits the batch as an Ethereum transaction. Any urbit can be
278+a roller, including moons, comets, and even fakezods. You can also use your own
279+ship as a roller.
280+
281+Tlon has set up our own roller that is free to use by the community. Using
282+Bridge, a ship may submit X transactions to Tlon's roller per Y period free of
283+charge. Tlon's roller submits on a regular schedule: a submission occurs when a
284+total of A layer 2 transactions have been submitted to it since the the previous
285+submitted Ethereum transaction, or every Z time, whichever occurs first.
286+
287+There are no security risks in utilizing an aggregator. The transactions you
288+submit to it are signed with your private key, and so if an aggregator alters
289+them the signature will no longer match and `naive.hoon` will reject it as an
290+invalid transaction. The worst an aggregator can do is not submit your transaction.
291+
292+## Multi-keyfiles
293+
294+As part of the layer 2 upgrade, Tlon has expanded the role of
295+[keyfiles](/docs/glossary/keyfile). One of our goals with layer 2 was to reduce
296+the amount of friction experienced when getting onto Urbit. The enormous
297+reduction in fees has made a new boot method which allows instantaneous sale of
298+layer 2 planets or stars to be cost effective.
299+
300+The ideal situation would be for the end user to be able to buy or receive a
301+planet and immediately boot it without having to wait for an aggregator to
302+submit a transaction that spawns the planet. In order to bring about this
303+circumstance, "multi-keyfiles" have been introduced.
304+
305+Multi-keyfiles are keyfiles used to boot an urbit for first time that contains
306+more than one set of keys, the purpose of which is to initially utilize one set
307+of keys on a temporary basis, and then the other set of keys soon after. This
308+works as follows. A star owner prespawns a number of layer 2 planets ready to be
309+sold at any time for which they posess the initial key. When a user acquires a
310+planet from a star owner, the star owner immediately hands the initial keys to
311+boot the planet to the buyer. The buyer then queues a transaction at a roller to
312+rotate the keys to a new value only known by the buyer (this step is performed
313+automatically by Bridge). The buyer then downloads a keyfile from Bridge
314+containing both keys and uses that to boot their planet for the first time.
315+After the transaction setting the new keys is submitted by the roller to
316+Ethereum, the purchased planet will automatically switch to them once it reads
317+the corresponding transaction from Ethereum.
318+
319+This process introduces a short period of time in which both the buyer and
320+seller are in possession of the keys of a planet. A malicious seller could
321+theoretically sell a planet to more than one party in this time period. However,
322+they would quickly be found out as two identical ships on the network
323+immediately creates problems, and the seller's reputation would be tarnished.
324+Due to the expense or effort needed to acquire a star, this seems an unlikely
325+scenario as the reward is much less than the cost. Nonetheless, buyers should
326+always make an effort to purchase from a reputable star, as is the case with all
327+transactions in life. If you want to be absolutely sure that you've received the
328+planet, just wait for the batch to be sent and confirmed.
329+
330+Multi-keyfiles were possible before layer 2, but as the cost of configuring keys
331+was comparable to the cost of buying a planet, they were not practical.
332+
333+## Security measures
334+
335+In the process of designing naive rollups, we felt it to be of the utmost
336+importance that there not be any loss in the security of a layer 2 ship over a
337+layer 1 ship. In this section we outline several relevant facets of Urbit as
338+well as particular measures that were taken to ensure that naive rollups were
339+free of bugs and exploits. We think of `naive.hoon` as being the first "Hoon
340+smart contract", and thus its functionality needs to be as rock-solid and
341+guaranteed as the Azimuth Ethereum smart contracts.
342+
343+### Arvo is deterministic
344+
345+Crucial to the functionality of Ethereum smart contracts is that they work the
346+same way every time since the Ethereum Virtual Machine is deterministic.
347+Similarly, as the state of Arvo is evolved via [a single pure
348+function](/docs/arvo/overview#an-operating-function), Arvo is deterministic as
349+well. This property makes it well-suited for cases where side effects are
350+unacceptable such as smart contracts, and thus `naive.hoon` is worthy of the
351+name "Hoon smart contract".
352+
353+### Restricted standard library
354+
355+A standard security practice is to reduce the surface area of attack to be as
356+minimal as possible. One common source of exploits among all programming
357+languages are issues with the standard library of functions, and this is one factor
358+that leads to the existence of multiple implementations of standard library functions for
359+a given programming language. For instance, `glibc` is the most widely used
360+standard library for the C programming language, but sheer size gives a large
361+surface area in which to find exploits. Thus, other standard libraries have been
362+written such as `musl` that are much smaller, and some argue to be more secure
363+at least partially due to fewer lines of code. Hoon is not yet popular enough to have
364+multiple standard library implementations, but `naive.hoon` shucks the usual
365+standard library and so its subject contains only the exact standard library
366+functions needed for it to function. This library is known as `tiny` and is
367+found at `/lib/tiny.hoon`.
368+
369+### Unit tests
370+
371+`naive.hoon` is among the most well-tested software in Urbit. The test suite,
372+which may be run with `-test %/lib/tests/naive ~` from dojo, is larger than any
373+other test suite both in number of lines of code and number of tests. We believe
374+branch coverage to be at or very close to 100%
375+
376+### Nonces
377+
378+In the Layer 2 Azimuth state, each proxy belonging to a given ship (including
379+the ownership "proxy") has a non-negative integer associated to it called a
380+"nonce". Each transaction submitted by a given proxy also have a nonce value. If
381+the current nonce of a proxy in the Layer 2 Azimuth state is `n`, then only a
382+transaction from that proxy with a nonce of `n+1` will be considered valid.
383+Otherwise the transaction is discarded. A valid transaction, by which we
384+mean one in which the nonce and signature are correct, will increment the nonce
385+of the proxy in the Layer 2 Azimuth state by one once processed by `naive.hoon`.
386+Note that "valid transactions" also include ones where the action will fail,
387+such as a planet attempting to `%spawn` another planet. For the purposes of
388+incrementing the nonce, only the nonce and signature matter.
389+
390+The use of nonces prevents "replay attacks", which is when a malicious party collects
391+valid transactions and attempts to resubmit them in order to perform the action
392+again. Since a valid transaction increments the nonce associated to the proxy
393+that submitted it, it is only ever possible for a given transaction to alter the
394+Layer 2 Azimuth state once.
395+
396+The use of nonces also eliminates potential issues caused by submitting a
397+transaction to more than one roller. This might happen if the first roller
398+submitted to is taking too long for your liking, and you want to try again with
399+another. If both rollers end up submitting the transaction, only the first one
400+will succeed, as the second one will be ignored by `naive.hoon` for having the
401+wrong nonce.
402+
content/docs/azimuth/l2/roller.mdnew file+66
@@ -0,0 +1,66 @@
1++++
2+title = "Rollers"
3+weight = 9
4+template = "doc.html"
5++++
6+
7+Here we outline how the naive rollup rollers work. This page is only a quick
8+summary - the full documentation of the API is coming soon.
9+
10+## Overview
11+
12+The following diagram illustrates the most important parts of the plumbing
13+present in the roller.
14+
15+[![Roller internals](https://media.urbit.org/docs/layer2/roller-internal.png)](https://media.urbit.org/docs/layer2/roller-internal.png)
16+
17+We elaborate on the components of this diagram below.
18+
19+## `%roller-rpc`
20+
21+The roller communicates with the outside world via a JSON-RPC API, which is
22+implemented with a Gall agent `%roller-rpc`. This is how Bridge communicates
23+with a roller. See the [RPC
24+documentation](https://documenter.getpostman.com/view/16338962/Tzm3nx7x#5a698656-8e7e-433f-9eff-1c6047b9eace)
25+for detailed information on the API.
26+
27+## `%roller`
28+
29+`%roller` is the Gall agent which collects layer 2 Azimuth **transactions**, which
30+are a concatenation of an
31+[action](/docs/azimuth/l2/bytestrings#actions) and a
32+[signature](/docs/azimuth/l2/bytestrings#signatures) and forms them into
33+[batches](/docs/azimuth/l2/bytestrings#batch) to be submitted periodically to the
34+Ethereum blockchain.
35+
36+### Transaction format
37+
38+See [Bytestring Format](/docs/azimuth/l2/bytestring) for a technical description of
39+how layer 2 transactions are formatted.
40+
41+### Pending transactions
42+
43+`%roller` maintains in its state a list of transactions that have been submitted
44+to it since the most recent roll it submitted to Ethereum. These are referred to as
45+**pending transactions**.
46+
47+### Signing the batch
48+
49+Each pending transaction already includes a signature from its sender, but the roller
50+itself must also sign the entire batch of transactions with its private key to
51+submit it as a single Ethereum transaction. This signed batch is known as a **roll**.
52+
53+### Predicted state
54+
55+Once a roll has been submitted to an Ethereum node, there is a waiting period
56+before a miner includes it in a block.
57+
58+During this waiting period, the roller applies the submitted batch to the
59+locally held Azimuth state to get a predicted state. This predicted state is
60+presented to the user in Bridge, such as to show which points a given address owns.
61+
62+### Timer
63+
64+Each roller may choose to submit rolls on a regular basis, periodically
65+and/or whenever a certain number of pending transactions is reached.
66+
content/docs/azimuth/life-and-rift.md+7−5
@@ -1,6 +1,6 @@
1+++
1+++
2title = "Life and Rift"
2title = "Life and Rift"
3−weight = 3
3+weight = 8
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
@@ -13,10 +13,12 @@ and [Jael](/docs/arvo/jael/jael-api) to ensure that communication between
13ships is always done with the most recent set of networking keys, and that
13ships is always done with the most recent set of networking keys, and that
14networking state is appropriately reset when a breach has occurred.
14networking state is appropriately reset when a breach has occurred.
15
15
16−Every ship begins with a `life` and `rift` of 0. For
16+Every ship begins with a `life` and `rift` of 0. For galaxies, stars, and
17−galaxies, stars, and planets, these values are stored in the Azimuth PKI, while
17+planets, these values are stored in the [Azimuth
18+PKI](/docs/azimuth/azimuth-eth#points) as `keyRevisionNumber` and
18−for moons, these values are stored by their parent. Comets cannot change their
19+`continuityNumber`, while for moons, these values are stored by their parent.
19−networking keys, nor can they breach, and so their `life` and `rift` are always 0.
20+Comets cannot change their networking keys, nor can they breach, and so their
21+`life` and `rift` are always 0.
20
22
21You can check your current `life` and `rift` number by running the `+keys our`
23You can check your current `life` and `rift` number by running the `+keys our`
22generator in dojo. You can inspect another ship's `life` and `rift` by running
24generator in dojo. You can inspect another ship's `life` and `rift` by running
content/docs/development/develop.md+4−4
@@ -13,7 +13,7 @@ contribute to. At a high level, you can:
13- [Build clients](#clients), which use Urbit as their back-end to store data and
13- [Build clients](#clients), which use Urbit as their back-end to store data and
14 interact with the network
14 interact with the network
15- [Develop agents](#agents), or more precisely [_gall_
15- [Develop agents](#agents), or more precisely [_gall_
16− agents](/docs/userspace/gall/gall), which are written in [Hoon](/docs/hoon/)
16+ agents](/docs/arvo/gall/gall), which are written in [Hoon](/docs/hoon/)
17 and can best be thought of as microservices
17 and can best be thought of as microservices
18- [Contribute to Urbit's core](#core), which involves contributing to Urbit
18- [Contribute to Urbit's core](#core), which involves contributing to Urbit
19 itself &mdash; either the operating system
19 itself &mdash; either the operating system
@@ -60,8 +60,8 @@ library called `shoe`, which you can learn more about
60Gall agents can be best thought of as individual services with a
60Gall agents can be best thought of as individual services with a
61statically-typed interface and built-in database. They're written in
61statically-typed interface and built-in database. They're written in
62[Hoon](/docs/hoon/overview) and all conform to a specific
62[Hoon](/docs/hoon/overview) and all conform to a specific
63−[interface](/docs/userspace/gall/gall-api) that's defined by the kernel vane
63+[interface](/docs/arvo/gall/gall-api) that's defined by the kernel vane
64−called [Gall](/docs/userspace/gall/gall).
64+called [Gall](/docs/arvo/gall/gall).
65
65
66Applications built on Urbit utilize a collection of different agents, each of
66Applications built on Urbit utilize a collection of different agents, each of
67which handle specific functionality. The [Landscape
67which handle specific functionality. The [Landscape
@@ -70,7 +70,7 @@ to see how this pattern works in practice.
70
70
71If you want to learn how to build gall agents, your best bet is to first [learn
71If you want to learn how to build gall agents, your best bet is to first [learn
72the Hoon programming language](/docs/hoon/hoon-school/), and then follow that
72the Hoon programming language](/docs/hoon/hoon-school/), and then follow that
73−up with the [Gall guide](/docs/userspace/gall/tutorial).
73+up with the [Gall guide](/docs/userspace/gall-guide).
74
74
75### Contribute to Urbit Core {#core}
75### Contribute to Urbit Core {#core}
76
76
content/docs/development/environment.md+269−20
@@ -8,25 +8,7 @@ template = "doc.html"
8This guide covers best practices for preparing your environment to develop
8This guide covers best practices for preparing your environment to develop
9within the Urbit ecosystem.
9within the Urbit ecosystem.
10
10
11−## Creating a development ship
12−
13−To do work with Hoon, we recommended using a "fake" ship -- one that's not
14−connected to the network.
15−
16−Because such a ship has no presence on the network, you don't need an Azimuth
17−identity. You just need to have [installed the Urbit binary](/getting-started).
18−
19−To create a fake ship named `~zod`, run the command below. You can replace `zod`
20−with any valid Urbit ship-name.
21−
22−```
23−./urbit -F zod
24−```
25−
26−This should take a couple of minutes, during which you should see a block of boot
27−messages, starting with the Urbit version number.
28−
29−## Hoon support in text editors
11+## Text editors
30
12
31A variety of plugins have been built to provide support for the Hoon language in
13A variety of plugins have been built to provide support for the Hoon language in
32different text editors:
14different text editors:
@@ -61,4 +43,271 @@ with [hoon-mode.el](https://github.com/urbit/hoon-mode.el).
61
43
62Vim is free and open-source and runs on all major operating systems. It is
44Vim is free and open-source and runs on all major operating systems. It is
63available [here](https://www.vim.org/). Hoon support is available with
45available [here](https://www.vim.org/). Hoon support is available with
64−[hoon.vim](https://github.com/urbit/hoon.vim) and is maintained by Tlon.
46+[hoon.vim](https://github.com/urbit/hoon.vim).
47+
48+## Development ships
49+
50+### Creating a fake ship
51+
52+To do work with Hoon, we recommended using a "fake" ship — one that's not
53+connected to the network.
54+
55+Because such a ship has no presence on the network, you don't need an Azimuth
56+identity. You just need to have [installed the Urbit binary](/getting-started/cli).
57+
58+To create a fake ship named `~zod`, run the command below. You can replace `zod`
59+with any valid Urbit ship-name.
60+
61+```
62+./urbit -F zod
63+```
64+
65+This should take a couple of minutes, during which you should see a block of boot
66+messages, starting with the Urbit version number.
67+
68+### Fake ship networking
69+
70+Fake ships on the same machine can automatically talk to one another. Having
71+created a fakezod, you can create a fake `~bus` the same way:
72+
73+```
74+./urbit -F bus
75+```
76+
77+Now in the fakezod's dojo, try:
78+
79+```
80+> |hi ~bus
81+>=
82+hi ~bus successful
83+```
84+
85+### Faster fake ship booting
86+
87+While working with Hoon, you'll often want to delete an old fake ship and
88+recreate a fresh one. Rather than having to wait a few minutes for the fresh
89+ship to be initialised, you can instead create a backup copy of a fake ship.
90+That way you can just delete the current copy, replace it with the backup, and
91+reboot in a matter of seconds.
92+
93+To do this, boot a fresh fake ship like usual, but with a different name:
94+
95+```
96+./urbit -F zod -c zod.new
97+```
98+
99+Once it's finished booting, it's a good idea to mount its desks so you don't
100+have to do it again each time. In the dojo:
101+
102+```
103+> |mount %base
104+>=
105+> |mount %garden
106+>=
107+> |mount %landscape
108+>=
109+> |mount %bitcoin
110+>=
111+> |mount %webterm
112+>=
113+```
114+
115+Next, shut the ship down with `ctrl+D`. Then, copy the pier and start using the
116+copy instead:
117+
118+```
119+cp -r zod.new zod
120+./urbit zod
121+```
122+
123+Now whenever you want a fresh fakezod, you can just shut it down and do:
124+
125+```
126+rm -r zod
127+cp -r zod.new zod
128+./urbit zod
129+```
130+
131+## Working with desks
132+
133+If you're just working in the dojo or experimenting with generators, committing
134+to the `%base` desk on a fake ship is fine. If you're working on a Gall agent or
135+developing a desk for distribution, you'll most likely want to work on a
136+separate desk and it's slightly more complicated.
137+
138+### Mount a desk
139+
140+To mount a desk to Unix so you can add files, you just need to run the `|mount`
141+command in the dojo and specify the name of the desk to mount:
142+
143+```
144+|mount %base
145+```
146+
147+The desk will now appear in the root of your pier (zod in this case):
148+
149+```
150+zod
151+└── base
152+```
153+
154+You can unmount it again by running the `|unmount` command in the dojo:
155+
156+```
157+|unmount %base
158+```
159+
160+### Create a new desk
161+
162+To create a new desk, you'll need to merge from an existing one, typically
163+`%base`. In the dojo, run the following (you can change `%mydesk` to your
164+preferred name):
165+
166+```
167+|merge %mydesk our %base
168+```
169+
170+If you now mount it, you'll have `/mydesk` directory in your pier with all the
171+files of the `%base` desk inside. You can then delete the contents, copy in your
172+own files and `|commit` it.
173+
174+Desks must contain all the `mark` files, libraries, etc, that they need. A
175+`sys.kelvin` file is mandatory, and there are a few `mark` files necessary as
176+well. In the next couple of sections we'll look at different ways to populate a
177+new desk with the necessary files.
178+
179+### Minimal desk
180+
181+This is the absolute minimal desk you'll be able to commit:
182+
183+```
184+skeleton
185+├── mar
186+│ ├── hoon.hoon
187+│ ├── kelvin.hoon
188+│ ├── mime.hoon
189+│ ├── noun.hoon
190+│ ├── txt-diff.hoon
191+│ └── txt.hoon
192+└── sys.kelvin
193+```
194+
195+`sys.kelvin` specifies the kernel kelvin version with which the desk is
196+compatible. You can copy it across from the `%base` desk, or just run the
197+following in the terminal from within the desk directory:
198+
199+```sh
200+echo "[%zuse 419]" > sys.kelvin
201+```
202+
203+The other `mark` files can just be copied across from the `%base` desk.
204+
205+### Using dev desks
206+
207+If you're working on something more complex, for example a desk with agents and
208+a front-end, there will be a number of `mark` files, libraries, etc, that will
209+be necessary. Rather than having to manually copy all the files from the
210+relevant default desks, the [urbit git repo](https://github.com/urbit/urbit)
211+includes some dev desks which can be used as a base. To get these, make sure you
212+have git installed and then clone the repo:
213+
214+```
215+git clone https://github.com/urbit/urbit ~/git/urbit
216+```
217+
218+If you now change to the `~/git/urbit/pkg` directory, you'll see the source for
219+the default desks, among other things:
220+
221+```
222+cd ~/git/urbit/pkg
223+```
224+
225+The desks ending in `-dev`, like `base-dev` and `garden-dev`, contain files for
226+interfacing with those respective desks. If you're creating a new desk that has
227+a tile and front-end, for example, you might like to use `base-dev` and
228+`garden-dev` as a base. To create such a base, there's a `symbolic-merge.sh`
229+script included in the directory. You can use it like so:
230+
231+```
232+./symbolic-merge base-dev mydesk
233+./symbolic-merge garden-dev mydesk
234+```
235+
236+After running that, you'll have a `mydesk` desk in the `pkg` directory that
237+contains the symlinked files from both those dev desks. To copy the files into
238+your pier, you can create and mount a mydesk desk in the dojo:
239+
240+```
241+|merge %mydesk our %base
242+|mount %mydesk
243+```
244+
245+Then, you can go into your pier:
246+
247+```
248+cd /path/to/fake/zod
249+```
250+
251+Delete the contents of `mydesk`:
252+
253+```
254+rm -r mydesk/*
255+```
256+
257+And then copy in the contents of the desk you created:
258+
259+```
260+cp -rL ~/git/urbit/pkg/mydesk/* mydesk
261+```
262+
263+Note you have to use `cp -rL` rather than just `cp -r` because the
264+`symbolic-merge.sh` script creates symlinks, so the `L` flag is to resolve them
265+and copy the actual files.
266+
267+Now you can just add a `sys.kelvin` file:
268+
269+```
270+echo "[%zuse 419]" > mydesk/sys.kelvin
271+```
272+
273+And you'll be able to mount the desk with `|commit %mydesk`.
274+
275+## Project organization
276+
277+When you're developing a desk, it's best to structure your working directory
278+with the same hierarchy as a real desk. For example, `~/project/mydesk` might
279+look like:
280+
281+```
282+mydesk
283+├── app
284+│ └── foo.hoon
285+├── desk.bill
286+├── desk.docket-0
287+├── lib
288+│ └── foo.hoon
289+├── mar
290+│ └── foo
291+│ ├── action.hoon
292+│ └── update.hoon
293+├── sur
294+│ └── foo.hoon
295+└── sys.kelvin
296+
297+```
298+
299+That way, whenever you want to test your changes, you can just copy it across to
300+your pier like:
301+
302+```
303+cp -ruv mydesk/* /path/to/fake/zod/mydesk
304+```
305+
306+And then just commit it in the dojo:
307+
308+```
309+|commit %mydesk
310+```
311+
312+If you're [using dev desks](#using-dev-desks) as a base, it's best to keep those
313+files separate from your own code.
content/docs/development/precepts.md+1−1
@@ -135,7 +135,7 @@ We’ll start with a brief description of many principles, then we’ll go into
135
135
136<img class="ba" src="https://media.urbit.org/site/posts/essays/pre-03.jpg">
136<img class="ba" src="https://media.urbit.org/site/posts/essays/pre-03.jpg">
137
137
138−### B: Specific Design
138+### B: Specific Design {#specific}
139
139
1401) Always ack a dupe; never ack an ack.
1401) Always ack a dupe; never ack an ack.
141
141
content/docs/glossary/aqua.md−4
@@ -10,7 +10,3 @@ category = "arvo"
10Aqua is a [Gall](/docs/glossary/gall) app that runs an [Arvo](/docs/glossary/arvo) instance or instances in userspace. It pretends to be [Vere](/docs/glossary/vere), and as such it loads [Pills](/docs/glossary/pill) to boot up a virtual ship or fleet of ships and then manages them from within the parent Arvo instance. Running tests for a virtual fleet of Aqua ships is done using [pH](/docs/glossary/ph).
10Aqua is a [Gall](/docs/glossary/gall) app that runs an [Arvo](/docs/glossary/arvo) instance or instances in userspace. It pretends to be [Vere](/docs/glossary/vere), and as such it loads [Pills](/docs/glossary/pill) to boot up a virtual ship or fleet of ships and then manages them from within the parent Arvo instance. Running tests for a virtual fleet of Aqua ships is done using [pH](/docs/glossary/ph).
11
11
12Aqua is jetted with the usual [Nock](/docs/glossary/nock) interpreter and thus virtual ships do not run any slower than the parent ship.
12Aqua is jetted with the usual [Nock](/docs/glossary/nock) interpreter and thus virtual ships do not run any slower than the parent ship.
13−
14−### Further Reading
15−
16−- [The Gall tutorial](/docs/userspace/gall/gall): A technical guide to the Gall vane.
content/docs/glossary/azimuth.md+27−6
@@ -3,16 +3,37 @@ title = "Azimuth"
3template = "doc.html"
3template = "doc.html"
4+++
4+++
5
5
6−**Azimuth** is Urbit's identity layer, built as a suite of smart contracts on the Ethereum blockchain. It is Urbit's method of securing digital identities that are required to use the [Arvo](/docs/glossary/arvo) peer-to-peer network, without the need for a central authority. Azimuth identities exist as non-fungible tokens, which are owned by Ethereum addresses and can be transferred between such addresses. Identities can use the [claims](/docs/glossary/claims) contract to make assertions – real-world or otherwise – about their owner.
6+**Azimuth** is Urbit's identity layer, built as a suite of smart contracts on
7+the Ethereum blockchain and several apps run locally on your
8+[ship](/docs/glossary/ship). It is Urbit's method of securing digital identities
9+that are required to use the [Arvo](/docs/glossary/arvo) peer-to-peer network,
10+without the need for a central authority. Azimuth identities exist as
11+non-fungible tokens, which are owned by Ethereum addresses and can be
12+transferred between such addresses. Identities can use the
13+[claims](/docs/glossary/claims) contract to make assertions – real-world or
14+otherwise – about their owner.
7
15
16+The primary way to interact with Azimuth and to manage your identities is
17+through our [Bridge](https://bridge.urbit.org) application. Bridge is a
8−The primary way to interact with Azimuth and to manage your identities is through our [Bridge](https://bridge.urbit.org) application. Bridge is a front-end for [Ecliptic](/docs/glossary/ecliptic), the Azimuth contract that's used to perform actions on the blockchain.
18+front-end for [Ecliptic](/docs/glossary/ecliptic), the Azimuth contract that's
19+used to perform actions on the blockchain.
9
20
10−There are a limited number of Azimuth identities which results in identities having value. This allows for identities to function as reputation primitives, since such scarcity creates an economic incentive for identities to remain static and to keep the network friendly. Undesirable behavior – spamming, scamming, and malware-spreading - will generally result in a [censure](/docs/glossary/censure) from [galaxies](/docs/glossary/galaxy) and [stars](/docs/glossary/star), marking the bad actor.
21+There are a limited number of Azimuth identities which results in identities
22+having value. This allows for identities to function as reputation primitives,
23+since such scarcity creates an economic incentive for identities to remain
24+static and to keep the network friendly. Undesirable behavior – spamming,
25+scamming, and malware-spreading - will generally result in a
26+[censure](/docs/glossary/censure) from [galaxies](/docs/glossary/galaxy) and
27+[stars](/docs/glossary/star), marking the bad actor.
11
28
12−It should be noted that Azimuth isn't built just for Arvo. It can be used as an identity system for other projects.
29+It should be noted that Azimuth isn't built just for Arvo. It can be used as an
30+identity system for other projects.
13
31
14### Further Reading
32### Further Reading
15
33
16−- [The Azimuth concepts page](/docs/azimuth/advanced-azimuth-tools): A more in-depth explanation of Azimuth, including information the storage of Urbit identities.
34+- [The Azimuth concepts page](/docs/azimuth/azimuth): A more in-depth
35+ explanation of Azimuth.
17−- [Install instructions](/getting-started/): Guide to installing Urbit, which includes instructions on booting with your Urbit identity.
36+- [Install instructions](/getting-started/): Guide to installing Urbit, which
37+ includes instructions on booting with your Urbit identity.
18- [Understanding Urbit ID](/understanding-urbit/urbit-id)
38- [Understanding Urbit ID](/understanding-urbit/urbit-id)
39+
content/docs/glossary/desk.md+1−1
@@ -8,7 +8,7 @@ category = "arvo"
8
8
9A **desk** is an independently revision-controlled branch of a [ship](/docs/glossary/ship) that uses the [Clay](/docs/glossary/clay) filesystem. Each desk contains its own apps, [mark](/docs/glossary/mark) definitions, files, and so forth.
9A **desk** is an independently revision-controlled branch of a [ship](/docs/glossary/ship) that uses the [Clay](/docs/glossary/clay) filesystem. Each desk contains its own apps, [mark](/docs/glossary/mark) definitions, files, and so forth.
10
10
11−Traditionally a ship has at least a base desk and a home desk. The base desk has all the system software from the distribution, and the home desk is a fork of base with all the items specific to the user of the ship. A desk is a series of numbered commits, the most recent of which represents the current state of the desk. A commit is composed of `1` an absolute time when it was created, `2` a list of zero or more parents, and `3` a map from paths to data.
11+Traditionally a ship has at least a `%base` desk, and typically `%garden` and `%landscape` desk among others. The `%base` desk has the kernel and base system software, while other desks are usually each for different apps. A desk is a series of numbered commits, the most recent of which represents the current state of the desk. A commit is composed of `1` an absolute time when it was created, `2` a list of zero or more parents, and `3` a map from paths to data.
12
12
13### Further Reading
13### Further Reading
14
14
content/docs/glossary/dojo.md+2−1
@@ -11,4 +11,5 @@ The other default command-line app is [Chat](/docs/glossary/chat). To switch bet
11and [Chat](/docs/glossary/chat) press Ctrl-X. The Dojo is the first thing you encounter after successfully booting your [ship](/docs/glossary/ship).
11and [Chat](/docs/glossary/chat) press Ctrl-X. The Dojo is the first thing you encounter after successfully booting your [ship](/docs/glossary/ship).
12
12
13### Further Reading
13### Further Reading
14+
14−- [Hoon Tutorial Lesson 1.1: Setup](/docs/hoon/hoon-school/setup): A great way to get started with using Hoon in the Dojo.
15+- [Hoon Tutorial Lesson 1.1: Introduction](/docs/hoon/hoon-school/intro): A great way to get started with using Hoon in the Dojo.
content/docs/glossary/gall.md+2−1
@@ -14,4 +14,5 @@ Gall is located at `/home/sys/vane/gall.hoon` within Arvo.
14
14
15- [The Hoon Tutorial](/docs/hoon/hoon-school/): Our guide to learning the Hoon programming language that will give you the foundation necessary for app development.
15- [The Hoon Tutorial](/docs/hoon/hoon-school/): Our guide to learning the Hoon programming language that will give you the foundation necessary for app development.
16 - [Lesson 2.7: Gall](/docs/hoon/hoon-school/gall): A Hoon Tutorial lesson that explains how to write a simple Gall app.
16 - [Lesson 2.7: Gall](/docs/hoon/hoon-school/gall): A Hoon Tutorial lesson that explains how to write a simple Gall app.
17+- [Gall vane documentation](/docs/arvo/gall/gall): Documentation of the Gall vane.
17−- [The Gall tutorial](/docs/userspace/gall/gall): A technical guide to the Gall vane.
18+- [Gall Guide](/docs/userspace/gall-guide): A tutorial for writing Gall agents.
content/docs/glossary/hdwallet.md+2−1
@@ -14,4 +14,5 @@ If a proxy or ownership address is compromised or has its keys lost, it can alwa
14
14
15### Further Reading
15### Further Reading
16
16
17−- [The Azimuth concepts page](/docs/azimuth/advanced-azimuth-tools): A more in-depth explanation of Azimuth, including information about the HD wallet.
17+- [The Azimuth concepts page](/docs/azimuth/azimuth): A more in-depth explanation of Azimuth.
18+- [Urbit HD Wallet](/docs/azimuth/hd-wallet): An in-depth explanation of the HD wallet.
content/docs/glossary/proxies.md+6−1
@@ -6,7 +6,12 @@ template = "doc.html"
6category = "azimuth"
6category = "azimuth"
7+++
7+++
8
8
9−**Proxies** are Ethereum addresses in the [Urbit HD Wallet](/docs/glossary/hdwallet) system that have limited powers. They are lower-powered "siblings" of the ownership key, which has the sole power to transfer the assigned Urbit identity. Using [Bridge](/docs/glossary/bridge), you can change the Ethereum addresses used for your proxies.
9+**Proxies** are Ethereum addresses in the [Urbit ID](/docs/glossary/azimuth)
10+system that have limited powers. They are lower-powered "siblings" of the
11+ownership key, which has the sole power to transfer the assigned Urbit identity.
12+Using [Bridge](/docs/glossary/bridge), you can change the Ethereum addresses
13+used for your proxies. If you use the [Urbit HD
14+wallet](/docs/glossary/hdwallet), your proxies have already been set.
10
15
11There are three types of proxy.
16There are three types of proxy.
12
17
content/docs/glossary/rollups.mdnew file+30
@@ -0,0 +1,30 @@
1++++
2+title = "Naive rollups"
3+template = "doc.html"
4+[extra]
5+category = "azimuth"
6++++
7+
8+**Naive rollups**, also referred to as **layer 2**, is an upgrade to
9+[Azimuth](/docs/glossary/azimuth) implemented in 2021 that reduces Ethereum gas
10+costs associated with Urbit ID transactions and friction associated with using
11+cryptocurrency in general.
12+
13+This system allows batches of Urbit ID transactions to be submitted together as
14+a single transaction using an urbit node known as a "roller". The PKI state
15+transitions resulting from these transactions are computed locally by your
16+[ship](/docs/glossary/ship) rather than by the [Ethereum Virtual
17+Machine](https://ethereum.org/en/developers/docs/evm/).
18+
19+Due to the dramatically reduced cost, Tlon offers their own roller that is free
20+for ordinary public use. This enables new users to get started with a permanent
21+Urbit ID without any prior knowledge of Ethereum, cryptocurrency, or
22+blockchains.
23+
24+### Further reading
25+
26+- [The Gang Solves the Gas Crisis](/blog/rollups): A casual overview of how
27+naive rollups works.
28+- Pilot's Guide to layer 2 : insert link
29+- [Layer 2 Overview](/docs/azimuth/l2/layer2): where developers should go to learn
30+about the technical details of naive rollups.
content/docs/hoon/guides/_index.md+4
@@ -11,3 +11,7 @@ insert_anchor_links = "right"
11## [CLI Apps](/docs/hoon/guides/cli-tutorial)
11## [CLI Apps](/docs/hoon/guides/cli-tutorial)
12
12
13## [Parsing](/docs/hoon/guides/parsing)
13## [Parsing](/docs/hoon/guides/parsing)
14+
15+## [Strings](/docs/hoon/guides/strings)
16+
17+## [JSON](/docs/hoon/guides/json-guide)
content/docs/hoon/guides/json-guide.mdnew file+511
@@ -0,0 +1,511 @@
1++++
2+title = "JSON"
3+weight = 4
4+template = "doc.html"
5++++
6+
7+If you are working on a Gall agent with any kind of web interface, it's likely you will encounter the problem of converting Hoon data structures to JSON and vice versa. This is what we'll look at in this document.
8+
9+Urbit represents JSON data with the `$json` structure (defined in `lull.hoon`). You can refer to the [json type](#the-json-type) section below for details.
10+
11+JSON data on the web is encoded in text, so Urbit has two functions in `zuse.hoon` for dealing with this:
12+
13+- [`+en-json:html`](/docs/hoon/reference/zuse/2e_2-3#en-jsonhtml) - For printing `$json` to a text-encoded form.
14+- [`+de-json:html`](/docs/hoon/reference/zuse/2e_2-3#de-jsonhtml) - For parsing text-encoded JSON to a `$json` structure.
15+
16+You typically want `$json` data converted to some other `noun` structure or vice versa, so Urbit has three collections of functions for this purpose, also in `zuse.hoon`:
17+
18+- [`+enjs:format`](/docs/hoon/reference/zuse/2d_1-5#enjsformat) - Functions for converting various atoms and structures to `$json`.
19+- [`+dejs:format`](/docs/hoon/reference/zuse/2d_6#dejsformat) - Many "reparsers" for converting `$json` data to atoms and other structures.
20+- [`+dejs-soft:format`](/docs/hoon/reference/zuse/2d_7#dejs-softformat) - Largely the same as `+dejs:format` except its reparsers produce `unit`s which are null upon failure rather than simply crashing.
21+
22+The relationship between these types and functions look like this:
23+
24+![json diagram](https://media.urbit.org/docs/json-diagram.svg)
25+
26+Note this diagram is a simplification - the `+dejs:format` and `+enjs:format` collections in particular are tools to be used in writing conversion functions rather than simply being used by themselves, but it demonstrates the basic relationships. Additionally, it is less common to do printing/parsing manually - this would typically be handled automatically by Eyre, though it may be necessary if you're retrieving JSON data via the web client vane Iris.
27+
28+### In practice
29+
30+A typical Gall agent will have a number of structures defined in a file in the `/sur` directory. These will define the type of data it expects to be `%poke`ed with, the type of data it will `%give` to subscribers, and the type of data its scry endpoints produce.
31+
32+If the agent only interacts with other agents inside Urbit, it may just use a `%noun` `mark`. If, however, it needs to talk to a web interface of some kind, it usually must handle `$json` data with a `%json` mark.
33+
34+Sometimes an agent's interactions with a web interface are totally distinct from its interactions with other agents. If so, the agent could just have separate scry endpoints, poke handlers, etc, that directly deal with `$json` data with a `%json` mark. In such a case, you can include `$json` encoding/decoding functions directly in the agent or associated libraries, using the general techniques demonstrated in the [$json encoding and decoding example](#json-encoding-and-decoding-example) section below.
35+
36+If, on the other hand, you want a unified interface (whether interacting with a web client or within Urbit), a different approach is necessary. Rather than taking or producing either `%noun` or `%json` marked data, custom `mark` files can be created which specify conversion methods for both `%noun` and `%json` marked data.
37+
38+With this approach, an agent would take and/or produce data with some `mark` like `%my-custom-mark`. Then, when the agent must interact with a web client, the webserver vane Eyre can automatically convert `%my-custom-mark` to `%json` or vice versa. This way the agent only ever has to handle the `%my-custom-mark` data. This approach is used by `%graph-store` with its `%graph-update-2` mark, for example, and a number of other agents.
39+
40+For details of creating a `mark` file for this purpose, the [mark file example](#mark-file-example) section below walks through a practical example.
41+
42+## The `$json` type
43+
44+Urbit represents JSON data with the `$json` structure (defined in `/sys/lull.hoon`):
45+
46+```hoon
47++$ json :: normal json value
48+ $@ ~ :: null
49+ $% [%a p=(list json)] :: array
50+ [%b p=?] :: boolean
51+ [%o p=(map @t json)] :: object
52+ [%n p=@ta] :: number
53+ [%s p=@t] :: string
54+ == ::
55+```
56+
57+The correspondence of `$json` to JSON types is fairly self-evident, but here's a table comparing the two for additional clarity:
58+
59+| JSON Type | `$json` Type | JSON Example | `$json` Example |
60+| :-------- | :--------------------- | ------------------------- | :----------------------------------------------------------- |
61+| Null | `~` | `null` | `~` |
62+| Boolean | `[%b p=?]` | `true` | `[%b p=%.y]` |
63+| Number | `[%n p=@ta]` | `123` | `[%n p=~.123]` |
64+| String | `[%s p=@t]` | `"foo"` | `[%s p='foo']` |
65+| Array | `[%a p=(list json)]` | `["foo",123]` | `[%a p=~[[%s p='foo'] [%n p=~.123]]]` |
66+| Object | `[%o p=(map @t json)]` | `{"foo":"xyz","bar":123}` | `[%o p={[p='bar' q=[%n p=~.123]] [p='foo' q=[%s p='xyz']]}]` |
67+
68+Since the `$json` `%o` object and `%a` array types may themselves contain any `$json`, you can see how JSON structures of arbitrary complexity can be represented. Note the `%n` number type is a `@ta` rather than something like a `@ud` that you might expect. This is because JSON's number type may be either an integer or floating point, so it's left as a `knot` which can then be parsed to a `@ud` or `@rd` with the appropriate [`+dejs:format`](/docs/hoon/reference/zuse/2d_6) function.
69+
70+## `$json` encoding and decoding example
71+
72+Let's have a look at a practical example. Here's a core with three arms. It has the structure arm `$user`, and then two more: `+to-js` converts a `$user` structure to `$json`, and `+from-js` does the opposite. Usually we'd define the structure in a separate `/sur` file, but for simplicity it's all in the one core.
73+
74+#### `json-test.hoon`
75+
76+```hoon
77+|%
78++$ user
79+ $: username=@t
80+ name=[first=@t mid=@t last=@t]
81+ joined=@da
82+ email=@t
83+ ==
84+++ to-js
85+ |= usr=user
86+ |^ ^- json
87+ %- pairs:enjs:format
88+ :~
89+ ['username' s+username.usr]
90+ ['name' name]
91+ ['joined' (sect:enjs:format joined.usr)]
92+ ['email' s+email.usr]
93+ ==
94+ ++ name
95+ :- %a
96+ :~
97+ [%s first.name.usr]
98+ [%s mid.name.usr]
99+ [%s last.name.usr]
100+ ==
101+ --
102+++ from-js
103+ =, dejs:format
104+ ^- $-(json user)
105+ %- ot
106+ :~
107+ [%username so]
108+ [%name (at ~[so so so])]
109+ [%joined du]
110+ [%email so]
111+ ==
112+--
113+```
114+
115+### Try it out
116+
117+First we'll try using our `$json` encoding/decoding library, and afterwards we'll take a closer look at its construction. To begin, save the code above in `/lib/json-test.hoon` of the `%base` desk on a fake ship and `|commit` it:
118+
119+```
120+> |commit %base
121+>=
122++ /~zod/base/5/lib/json-test/hoon
123+```
124+
125+Then we need to build it so we can use it. We'll give it a face of `user-lib`:
126+
127+```
128+> =user-lib -build-file %/lib/json-test/hoon
129+```
130+
131+Let's now create an example of a `$user` structure:
132+
133+```
134+> =usr `user:user-lib`['john456' ['John' 'William' 'Smith'] now 'john.smith@example.com']
135+> usr
136+[ username='john456'
137+ name=[first='John' mid='William' last='Smith']
138+ joined=~2021.9.12..09.47.58..1b65
139+ email='john.smith@example.com'
140+]
141+```
142+
143+Now we can try calling the `+to-js` function with our data to convert it to `$json`:
144+
145+```
146+> =usr-json (to-js:user-lib usr)
147+> usr-json
148+[ %o
149+ p
150+ { [p='email' q=[%s p='john.smith@example.com']]
151+ [p='name' q=[%a p=~[[%s p='John'] [%s p='William'] [%s p='Smith']]]]
152+ [p='username' q=[%s p='john456']]
153+ [p='joined' q=[%n p=~.1631440078]]
154+ }
155+]
156+```
157+
158+Let's also see how that `$json` would look as real JSON encoded in text. We can do that with `+en-json:html`:
159+
160+```
161+> (crip (en-json:html (to-js:user-lib usr)))
162+'{"joined":1631440078,"username":"john456","name":["John","William","Smith"],"email":"john.smith@example.com"}'
163+```
164+
165+Finally, let's try converting the `$json` back to a `$user` again with our `+from-js` arm:
166+
167+```
168+> (from-js:user-lib usr-json)
169+[ username='john456'
170+ name=[first='John' mid='William' last='Smith']
171+ joined=~2021.9.12..09.47.58
172+ email='john.smith@example.com'
173+]
174+```
175+
176+### Analysis
177+
178+#### Converting to `$json`
179+
180+Here's our arm that converts a `$user` structure to `$json`:
181+
182+```hoon
183+++ to-js
184+ |= usr=user
185+ |^ ^- json
186+ %- pairs:enjs:format
187+ :~
188+ ['username' s+username.usr]
189+ ['name' name]
190+ ['joined' (sect:enjs:format joined.usr)]
191+ ['email' s+email.usr]
192+ ==
193+ ++ name
194+ :- %a
195+ :~
196+ [%s first.name.usr]
197+ [%s mid.name.usr]
198+ [%s last.name.usr]
199+ ==
200+ --
201+```
202+
203+There are different ways we could represent our `$user` structure as JSON, but in this case we've opted to encapsulate it in an object and have the `name` as an array (since JSON arrays preserve order).
204+
205+[`+enjs:format`](/docs/hoon/reference/zuse/2d_1-5#enjsformat)includes the convenient [`+pairs`](/docs/hoon/reference/zuse/2d_1-5#pairsenjsformat) function, which converts a list of `[@t json]` to an object containing those key-value pairs. We've used this to assemble the final object. Note that if you happen to have only a single key-value pair rather than a list, you can use [`+frond`](/docs/hoon/reference/zuse/2d_1-5#frondenjsformat) instead of `+pairs`.
206+
207+For the `joined` field, we've used the [`+sect`](/docs/hoon/reference/zuse/2d_1-5#sectenjsformat) function from `+enjs` to convert the `@da` to a Unix seconds timestamp in a `$json` number. The `+sect` function, like others in `+enjs`, takes in a noun (in this case a `@da`) and produces `$json` (in this case a `[%n @ta]` number). `+enjs` contains a handful of useful functions like this, but for the rest we've just hand-made the `$json` structure. This is fairly typical when encoding `$json`, it's usually [decoding](#converting-from-json) that makes more extensive use of the `$json` utility functions in `+format`.
208+
209+For the `name` field we've just formed a cell of `%a` and a list of `$json` strings, since a `$json` array is `[%a p=(list json)]`. Note we've separated this part into its own arm and wrapped the whole thing in a `|^` - a core with a `$` arm that's computed immediately. This is simply for readability - our structure here is quite simple but when dealing with deeply-nested `$json` structures or complex logic, having a single giant function can quickly become unwieldy.
210+
211+#### Converting from `$json`
212+
213+Here's our arm that converts `$json` to our `$user` structure:
214+
215+```hoon
216+++ from-js
217+ =, dejs:format
218+ ^- $-(json user)
219+ %- ot
220+ :~
221+ [%username so]
222+ [%name (at ~[so so so])]
223+ [%joined du]
224+ [%email so]
225+ ==
226+```
227+
228+This is the inverse of the [encoding](#converting-to-json) function described in the previous section.
229+
230+We make extensive use of [`+dejs:format`](/docs/hoon/reference/zuse/2d_6) functions here, so we've used `=,` to expose the namespace and allow succinct `+dejs` function calls.
231+
232+We use the [`+ot`](/docs/hoon/reference/zuse/2d_6#otdejsformat) function from `+dejs:format` to decode the `$json` object to a n-tuple. It's a wet gate that takes a list of pairs of keys and other `+dejs` functions and produces a new gate that takes the `$json` to be decoded (which we've given it in `jon`).
233+
234+The [`+so`](/docs/hoon/reference/zuse/2d_6#sodejsformat) functions just decode `$json` strings to `cord`s. The [`+at`](/docs/hoon/reference/zuse/2d_6#atdejsformat) function converts a `$json` array to a tuple, decoding each element with the respective function given in its argument list. Like `+ot`, `+at` is also a wet gate that produces a gate that takes `$json`. In our case we've used `+so` for each element, since they're all strings.
235+
236+For `joined`, we've used the [`+du`](/docs/hoon/reference/zuse/2d_6#dudejsformat) function, which converts a Unix seconds timestamp in a `$json` number to a `@da` (it's basically the inverse of the `+sect:enjs:format` we used earlier).
237+
238+Notice how `+ot` takes in other `+dejs` functions in its argument. One of its arguments includes the `+at` function which itself takes in other `+dejs` functions. There are several `+dejs` functions like this that allow complex nested JSON structures to be decoded. For other examples of common `+dejs` functions like this, see the [More `+dejs`](#more-dejs) section below.
239+
240+There are dozens of different functions in [`+dejs:format`](/docs/hoon/reference/zuse/2d_6) that will cover a great many use cases. If there isn't a `+dejs` function for a particular case, you can also just write a custom function - it just has to take `$json`. Note there's also the [`+dejs-soft:format`](/docs/hoon/reference/zuse/2d_7) functions - these are similar to `+dejs` functions except they produce `unit`s rather than simply crashing if decoding fails.
241+
242+## More `+dejs`
243+
244+We looked at the commonly used `+ot` function in the [first example](#converting-from-json), now let's look at a couple more common `+dejs` functions.
245+
246+### `+of`
247+
248+The [`+of`](/docs/hoon/reference/zuse/2d_6#ofdejsformat) function takes an object containing a single key-value pair, decodes the value with the corresponding `+dejs` function in a key-function list, and produces a key-value tuple. This is useful when there are multiple possible objects you might receive, and tagged unions are a common data structure in hoon.
249+
250+Let's look at an example. Here's a gate that takes in some `$json`, decodes it with an `+of` function that can handle three possible objects, casts the result to a tagged union, switches against its head with `?-`, performs some transformation and finally returns the result. You can save it as `gen/of-test.hoon` in the `%base` desk of a fake ship and `|commit %base`.
251+
252+#### `of-test.hoon`
253+
254+```hoon
255+|= jon=json
256+|^ ^- @t
257+=/ =fbb
258+ (to-fbb jon)
259+?- -.fbb
260+ %foo (cat 3 +.fbb '!!!')
261+ %bar ?:(+.fbb 'Yes' 'No')
262+ %baz :((cury cat 3) p.fbb q.fbb r.fbb)
263+==
264++$ fbb
265+ $% [%foo @t]
266+ [%bar ?]
267+ [%baz p=@t q=@t r=@t]
268+ ==
269+++ to-fbb
270+=, dejs:format
271+%- of
272+:~ foo+so
273+ bar+bo
274+ baz+(at ~[so so so])
275+==
276+--
277+```
278+
279+Let's try it:
280+
281+```
282+> +of-test (need (de-json:html '{"foo":"Hello"}'))
283+'Hello!!!'
284+
285+> +of-test (need (de-json:html '{"bar":true}'))
286+'Yes'
287+
288+> +of-test (need (de-json:html '{"baz":["a","b","c"]}'))
289+'abc'
290+```
291+
292+### `+ou`
293+
294+The [`+ou`](/docs/hoon/reference/zuse/2d_6#oudejsformat) function decodes a `$json` object to an n-tuple using the matching functions in a key-function list. Additionally, it lets you set some key-value pairs in an object as optional and others as mandatory. The mandatory ones crash if they're missing and the optional ones are replaced with a given noun.
295+
296+`+ou` is different to other `+dejs` functions - the functions it takes are `$-((unit json) grub)` rather than the usual `$-(json grub)` of most `+dejs` functions. There are only two `+dejs` functions that fit this - [`+un`](/docs/hoon/reference/zuse/2d_6#undejsformat) and [`+uf`](/docs/hoon/reference/zuse/2d_6#ufdejsformat). These are intended to be used with `+ou` - you would wrap each function in the key-function list of `+ou` with either `+un` or `+uf`.
297+
298+`+un` crashes if its argument is `~`. `+ou` gives functions a `~` if the matching key-value pair is missing in the `$json` object, so `+un` crashes if the key-value pair is missing. Therefore, `+un` lets you set key-value pairs as mandatory.
299+
300+`+uf` takes two arguments - a noun and a `+dejs` function. If the `(unit json)` it's given by `+ou` is `~`, it produces the noun it was given rather than the product of the `+dejs` function. This lets you specify key-value pairs as optional, replacing missing ones with whatever you want.
301+
302+Let's look at a practical example. Here's a generator you can save in the `%base` desk of a fake ship in `gen/ou-test.hoon` and `|commit %base`. It takes in a `$json` object and produces a triple. The `+ou` in `+decode` has three key-function pairs - the first two are mandatory and the last is optional, producing the bunt of a set if the `%baz` key is missing.
303+
304+#### `ou-test.hoon`
305+
306+```hoon
307+|= jon=json
308+|^ ^- [@t ? (set @ud)]
309+(decode jon)
310+++ decode
311+=, dejs:format
312+%- ou
313+:~ foo+(un so)
314+ bar+(un bo)
315+ baz+(uf *(set @ud) (as ni))
316+==
317+--
318+```
319+
320+Let's try it:
321+
322+```
323+> +ou-test (need (de-json:html '{"foo":"hello","bar":true,"baz":[1,2,3,4]}'))
324+['hello' %.y {1 2 3 4}]
325+
326+> +ou-test (need (de-json:html '{"foo":"hello","bar":true}'))
327+['hello' %.y {}]
328+
329+> +ou-test (need (de-json:html '{"foo":"hello"}'))
330+[%key 'bar']
331+dojo: hoon expression failed
332+```
333+
334+### `+su`
335+
336+The [`+su`](/docs/hoon/reference/zuse/2d_6#sudejsformat) function parses a string with the given parsing `rule`. Hoon's functional parsing library is very powerful and lets you create arbitrarily complex parsers. JSON will often have data types encoded in strings, so this function can be very useful. The writing of parsers is outside the scope of this guide, but you can see the [Parsing Guide](/docs/hoon/guides/parsing) and sections 4e to 4j of the standard library documentation for details.
337+
338+Here are some simple examples of using `+su` to parse strings:
339+
340+```
341+> `@ux`((su:dejs:format hex) s+'deadbeef1337f00D')
342+0xdead.beef.1337.f00d
343+
344+> `(list @)`((su:dejs:format (most lus dem)) s+'1+2+3+4')
345+~[1 2 3 4]
346+
347+> `@ub`((su:dejs:format ven) s+'+>-<->+<+')
348+0b11.1000.1101
349+```
350+
351+Here's a more complex parser that will parse a GUID like `824e7749-4eac-9c00-db16-4cb816cd6f19` to a `@ux`:
352+
353+#### `su-test.hoon`
354+
355+```hoon
356+|= jon=json
357+^- @ux
358+%. jon
359+%- su:dejs:format
360+%+ cook
361+|= parts=(list [step @])
362+^- @ux
363+(can 3 (flop parts))
364+;~ plug
365+ (stag 4 ;~(sfix (bass 16 (stun 8^8 six:ab)) hep))
366+ (stag 2 ;~(sfix qix:ab hep))
367+ (stag 2 ;~(sfix qix:ab hep))
368+ (stag 2 ;~(sfix qix:ab hep))
369+ (stag 6 (bass 16 (stun 12^12 six:ab)))
370+ (easy ~)
371+==
372+```
373+
374+Save it in the `/gen` directory of the `%base` desk and `|commit` it. We can then try it with:
375+
376+```
377+> +su-test s+'5323a61d-0c26-d8fa-2b73-18cdca805fd8'
378+0x5323.a61d.0c26.d8fa.2b73.18cd.ca80.5fd8
379+```
380+
381+If we delete the last character it'll no longer be a valid GUID and the parsing will fail:
382+
383+```
384+> +su-test s+'5323a61d-0c26-d8fa-2b73-18cdca805fd'
385+/gen/su-test/hoon:<[2 1].[16 3]>
386+/gen/su-test/hoon:<[3 1].[16 3]>
387+{1 36}
388+syntax error
389+dojo: naked generator failure
390+```
391+
392+## `mark` file example
393+
394+Here's a simple `mark` file for the `$user` structure we created in the [first example](#json-encoding-and-decoding-example). It imports the [json-test.hoon](#json-testhoon) library we created and saved in our `%base` desk's `/lib` directory.
395+
396+#### `user.hoon`
397+
398+```hoon
399+/+ *json-test
400+|_ usr=user
401+++ grab
402+ |%
403+ ++ noun user
404+ ++ json from-js
405+ --
406+++ grow
407+ |%
408+ ++ noun usr
409+ ++ json (to-js usr)
410+ --
411+++ grad %noun
412+--
413+```
414+
415+The [Marks section](/docs/arvo/clay/marks/marks) of the Clay documentation covers `mark` files comprehensively and is worth reading through if you want to write a mark file.
416+
417+In brief, a mark file contains a `door` with three arms. The door's sample type is the type of the data in question - in our case the `$user` structure. The `+grab` arm contains methods for converting _to_ our mark, and the `+grow` arm contains methods for converting _from_ our mark. The `+noun` arms are mandatory, and then we've added `+json` arms which respectively call the `+from-js` and `+to-js` functions from our `json-test.hoon` library. The final `+grad` arm defines various revision control functions, in our case we've delegated these to the `%noun` mark.
418+
419+From this mark file, Clay can build mark conversion gates between the `%json` mark and our `%user` mark, allowing the conversion of `$json` data to a `$user` structure and vice versa.
420+
421+### Try it out
422+
423+First, we'll save the code above as `user.hoon` in the `/mar` directory our of `%base` desk:
424+
425+```
426+> |commit %base
427+>=
428++ /~zod/base/9/mar/user/hoon
429+```
430+
431+Let's quickly create a `$json` object to work with:
432+
433+```
434+> =jon (need (de-json:html '{"joined":1631440078,"username":"john456","name":["John","William","Smith"],"email":"john.smith@example.com"}'))
435+> jon
436+[ %o
437+ p
438+ { [p='email' q=[%s p='john.smith@example.com']]
439+ [p='name' q=[%a p=~[[%s p='John'] [%s p='William'] [%s p='Smith']]]]
440+ [p='username' q=[%s p='john456']]
441+ [p='joined' q=[%n p=~.1631440078]]
442+ }
443+]
444+```
445+
446+We'll also build our library so we can use its types from the dojo:
447+
448+```
449+> =user-lib -build-file %/lib/json-test/hoon
450+```
451+
452+Now we can ask Clay to build a mark conversion gate from a `%json` mark to our `%user` mark. We'll use a scry with a `%f` `care` which produces a static mark conversion gate:
453+
454+```
455+> =json-to-user .^($-(json user:user-lib) %cf /===/json/user)
456+```
457+
458+Let's try converting our `$json` to a `$user` structure with our new mark conversion gate:
459+
460+```
461+> =usr (json-to-user jon)
462+> usr
463+[ username='john456'
464+ name=[first='John' mid='William' last='Smith']
465+ joined=~2021.9.12..09.47.58
466+ email='john.smith@example.com'
467+]
468+```
469+
470+Now let's try the other direction. We'll again scry Clay to build a static mark conversion gate, this time _from_ `%user` _to_ `%json` rather than the reverse:
471+
472+```
473+> =user-to-json .^($-(user:user-lib json) %cf /===/user/json)
474+```
475+
476+Let's test it out by giving it our `$user` data:
477+
478+```
479+> (user-to-json usr)
480+[ %o
481+ p
482+ { [p='email' q=[%s p='john.smith@example.com']]
483+ [p='name' q=[%a p=~[[%s p='John'] [%s p='William'] [%s p='Smith']]]]
484+ [p='username' q=[%s p='john456']]
485+ [p='joined' q=[%n p=~.1631440078]]
486+ }
487+]
488+```
489+
490+Finally, let's see how that looks as JSON encoded in text:
491+
492+```
493+> (crip (en-json:html (user-to-json usr)))
494+'{"joined":1631440078,"username":"john456","name":["John","William","Smith"],"email":"john.smith@example.com"}'
495+```
496+
497+Usually (though not in all cases) these mark conversions will be performed implicitly by Gall or Eyre and you'd not deal with the mark conversion gates directly, but it's still informative to see them work explicitly.
498+
499+## Further reading
500+
501+[The Zuse library reference](/docs/hoon/reference/zuse/table-of-contents) - This includes documentation of the JSON parsing, printing, encoding and decoding functions.
502+
503+[The Marks section of the Clay documentation](/docs/arvo/clay/marks/marks) - Comprehensive documentation of `mark`s.
504+
505+[The External API Reference section of the Eyre documentation](/docs/arvo/eyre/external-api-ref) - Details of the webserver vane Eyre's external API.
506+
507+[The Iris documentation](/docs/arvo/iris/iris) - Details of the web client vane Iris, which may be used to fetch external JSON data among other things.
508+
509+[Strings Guide](/docs/hoon/guides/strings) - Atom printing functions like `+scot` will often be useful for JSON encoding - see the [Encoding in Text](/docs/hoon/guides/strings#encoding-in-text) section for usage.
510+
511+[Parsing Guide](/docs/hoon/guides/parsing) - Learn how to write functional parsers in hoon which can be used with `+su`.
content/docs/hoon/guides/parsing.md+48−21
@@ -9,6 +9,8 @@ knowledge of parsing is required, and we will explain the basic structure of how
9parsing works in a purely functional language such as Hoon before moving on to
9parsing works in a purely functional language such as Hoon before moving on to
10how it is implemented in Hoon.
10how it is implemented in Hoon.
11
11
12+**Note:** For JSON printing/parsing and encoding/decoding, see the [JSON Guide](/docs/hoon/guides/json-guide).
13+
12## What is parsing? {#what-is-parsing}
14## What is parsing? {#what-is-parsing}
13
15
14A program which takes a raw sequence of characters as an input and produces a data
16A program which takes a raw sequence of characters as an input and produces a data
@@ -42,20 +44,24 @@ the parsing routine on the string `"1"` and looks for an integer, and so it
42returns the integer `1`. However, taking into account what was said above about
44returns the integer `1`. However, taking into account what was said above about
43parsers returning the unparsed portion of the string as well, we should
45parsers returning the unparsed portion of the string as well, we should
44represent this return as a tuple. So we should expect something like this:
46represent this return as a tuple. So we should expect something like this:
47+
45```
48```
46> (parse "1" integer)
49> (parse "1" integer)
47[1 ""]
50[1 ""]
48> (parse "123" integer)
51> (parse "123" integer)
49[1 "23"]
52[1 "23"]
50```
53```
54+
51What if we wish to parse the rest of the string? We would need to apply the
55What if we wish to parse the rest of the string? We would need to apply the
52`parse` function again:
56`parse` function again:
57+
53```
58```
54> (parse (parse "123" integer) integer)
59> (parse (parse "123" integer) integer)
55[12 "3"]
60[12 "3"]
56> (parse (parse (parse "123" integer) integer) integer)
61> (parse (parse (parse "123" integer) integer) integer)
57[123 ""]
62[123 ""]
58```
63```
64+
59So we see that we can parse strings larger than one character by stringing
65So we see that we can parse strings larger than one character by stringing
60together parsing functions for single characters. Thus in addition to parsing
66together parsing functions for single characters. Thus in addition to parsing
61functions for single input characters, we want _parser combinators_ that
67functions for single input characters, we want _parser combinators_ that
@@ -75,15 +81,14 @@ are quite a few), but ought to be
75sufficient to get started with parsing in Hoon and be equipped to discover the
81sufficient to get started with parsing in Hoon and be equipped to discover the
76remainder yourself.
82remainder yourself.
77
83
78−
79## Basic types
84## Basic types
80
85
81In this section we discuss the types most commonly used for Hoon parsers. In short:
86In this section we discuss the types most commonly used for Hoon parsers. In short:
82
87
83− - A `hair` is the position in the text the parser is at,
88+- A `hair` is the position in the text the parser is at,
84− - A `nail` is parser input,
89+- A `nail` is parser input,
85− - An `edge` is parser output,
90+- An `edge` is parser output,
86− - A `rule` is a parser.
91+- A `rule` is a parser.
87
92
88### `hair`
93### `hair`
89
94
@@ -102,6 +107,7 @@ is in case it hits something unexpected during parsing.
102```hoon
107```hoon
103++ nail [p=hair q=tape]
108++ nail [p=hair q=tape]
104```
109```
110+
105We recall from our [discussion above](#what-is-parsing) that parsing functions must keep
111We recall from our [discussion above](#what-is-parsing) that parsing functions must keep
106track of both what has been parsed and what has yet to be parsed. Thus a `nail`
112track of both what has been parsed and what has yet to be parsed. Thus a `nail`
107consists of both a `hair`, giving the line and column up to which the input
113consists of both a `hair`, giving the line and column up to which the input
@@ -122,6 +128,7 @@ what has theoretically already been parsed up to that point.
122```hoon
128```hoon
123++ edge [p=hair q=(unit [p=* q=nail])]
129++ edge [p=hair q=(unit [p=* q=nail])]
124```
130```
131+
125An `edge` is the output of a parser. If parsing succeeded, `p` is the location
132An `edge` is the output of a parser. If parsing succeeded, `p` is the location
126of the original input `tape `up to which the text has been parsed. If parsing
133of the original input `tape `up to which the text has been parsed. If parsing
127failed, `p` will be the first `hair` at which parsing failed.
134failed, `p` will be the first `hair` at which parsing failed.
@@ -136,6 +143,7 @@ of what is to be parsed. If `q` is not null, `p` and `p.q.q` are identical.
136```hoon
143```hoon
137++ rule _|:($:nail $:edge)
144++ rule _|:($:nail $:edge)
138```
145```
146+
139A `rule` is a gate which takes in a `nail` and returns an `edge` - in other
147A `rule` is a gate which takes in a `nail` and returns an `edge` - in other
140words, a parser.
148words, a parser.
141
149
@@ -160,6 +168,7 @@ of the input `nail`.
160> edg
168> edg
161[p=[p=1 q=2] q=[~ [p='a' q=[p=[p=1 q=2] q="bc"]]]]
169[p=[p=1 q=2] q=[~ [p='a' q=[p=[p=1 q=2] q="bc"]]]]
162```
170```
171+
163We note that `p.edg` is `[p=1 q=2]`, indicating that the next character to be
172We note that `p.edg` is `[p=1 q=2]`, indicating that the next character to be
164parsed is in line 1, column 2. `q.edg` is not null, indicating that parsing
173parsed is in line 1, column 2. `q.edg` is not null, indicating that parsing
165succeeded. `p.q.edg` is `'a'`, which is the result of the parse. `p.q.q.edg` is the same as `p.edg`, which is always the case for
174succeeded. `p.q.edg` is `'a'`, which is the result of the parse. `p.q.q.edg` is the same as `p.edg`, which is always the case for
@@ -167,11 +176,13 @@ succeeded. `p.q.edg` is `'a'`, which is the result of the parse. `p.q.q.edg` is
167`q.q.edg` is `"bc"`, which is the part of the input `tape` that has yet to be parsed.
176`q.q.edg` is `"bc"`, which is the part of the input `tape` that has yet to be parsed.
168
177
169Now let's see what happens when parsing fails.
178Now let's see what happens when parsing fails.
179+
170```
180```
171> =edg ((just 'b') [[1 1] "abc"])
181> =edg ((just 'b') [[1 1] "abc"])
172> edg
182> edg
173[p=[p=1 q=1] q=~]
183[p=[p=1 q=1] q=~]
174```
184```
185+
175Now we have that `p.edg` is the same as the input `hair`, `[1 1]`, meaning the
186Now we have that `p.edg` is the same as the input `hair`, `[1 1]`, meaning the
176parser has not advanced since parsing failed. `q.edg` is null, indicating that
187parser has not advanced since parsing failed. `q.edg` is null, indicating that
177parsing has failed.
188parsing has failed.
@@ -186,11 +197,13 @@ produces a `rule` that attempts to match that `cord` against the beginning of
186the input.
197the input.
187
198
188Let's see what happens when we successfully parse the entire input `tape`.
199Let's see what happens when we successfully parse the entire input `tape`.
200+
189```
201```
190> =edg ((jest 'abc') [[1 1] "abc"])
202> =edg ((jest 'abc') [[1 1] "abc"])
191> edg
203> edg
192[p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=""]]]]
204[p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=""]]]]
193```
205```
206+
194`p.edg` is `[p=1 q=4]`, indicating that the next character to be parsed is at
207`p.edg` is `[p=1 q=4]`, indicating that the next character to be parsed is at
195line 1, column 4. Of course, this does not exist since the input `tape` was only
208line 1, column 4. Of course, this does not exist since the input `tape` was only
1963 characters long, so this actually indicates that the entire `tape` has been
2093 characters long, so this actually indicates that the entire `tape` has been
@@ -199,21 +212,25 @@ successfully parsed (since the `hair` does not advance in the case of failure).
199remains to be parsed.
212remains to be parsed.
200
213
201What happens if we only match some of the input `tape`?
214What happens if we only match some of the input `tape`?
215+
202```
216```
203> =edg ((jest 'ab') [[1 1] "abc"])
217> =edg ((jest 'ab') [[1 1] "abc"])
204> edg
218> edg
205[p=[p=1 q=3] q=[~ [p='ab' q=[p=[p=1 q=3] q="c"]]]]
219[p=[p=1 q=3] q=[~ [p='ab' q=[p=[p=1 q=3] q="c"]]]]
206```
220```
221+
207Now we have that the result, `p.q.edg`, is `'ab'`, while the remainder `q.q.q.edg`
222Now we have that the result, `p.q.edg`, is `'ab'`, while the remainder `q.q.q.edg`
208is `"c"`. So `+jest` has successfully parsed the first two characters, while the
223is `"c"`. So `+jest` has successfully parsed the first two characters, while the
209last character remains. Furthermore, we still have the information that the
224last character remains. Furthermore, we still have the information that the
210remaining character was in line 1 column 3 from `p.edg` and `p.q.q.edg`.
225remaining character was in line 1 column 3 from `p.edg` and `p.q.q.edg`.
211
226
212What happens when `+jest` fails?
227What happens when `+jest` fails?
228+
213```
229```
214> ((jest 'bc') [[1 1] "abc"])
230> ((jest 'bc') [[1 1] "abc"])
215[p=[p=1 q=1] q=~]
231[p=[p=1 q=1] q=~]
216```
232```
233+
217Despite the fact that `'bc'` appears in `"abc"`, because it was not at the
234Despite the fact that `'bc'` appears in `"abc"`, because it was not at the
218beginning the parse failed. We will see in [parser
235beginning the parse failed. We will see in [parser
219combinators](#parser-combinators) how to modify this `rule` so that it
236combinators](#parser-combinators) how to modify this `rule` so that it
@@ -237,6 +254,7 @@ replaces the parsing result with `cus`.
237
254
238Here we see that `p.q` of the `edge` returned by the `rule` created with `+cold`
255Here we see that `p.q` of the `edge` returned by the `rule` created with `+cold`
239is `%foo`.
256is `%foo`.
257+
240```
258```
241> ((cold %foo (just 'a')) [[1 1] "abc"])
259> ((cold %foo (just 'a')) [[1 1] "abc"])
242[p=[p=1 q=2] q=[~ u=[p=%foo q=[p=[p=1 q=2] q="bc"]]]]
260[p=[p=1 q=2] q=[~ u=[p=%foo q=[p=[p=1 q=2] q="bc"]]]]
@@ -246,7 +264,6 @@ One common scenario where `+cold` sees play is when writing [command line
246interface (CLI) apps](/docs/hoon/guides/cli-tutorial). We usher the
264interface (CLI) apps](/docs/hoon/guides/cli-tutorial). We usher the
247reader there to find an example where `+cold` is used.
265reader there to find an example where `+cold` is used.
248
266
249−
250### `+knee`
267### `+knee`
251
268
252Another important function in the parser builder library is `+knee`, used for building
269Another important function in the parser builder library is `+knee`, used for building
@@ -254,7 +271,6 @@ recursive parsers. We delay discussion of `+knee` to the
254[section below](#recursive-parsers) as more context is needed to explain it
271[section below](#recursive-parsers) as more context is needed to explain it
255properly.
272properly.
256
273
257−
258## Outside callers
274## Outside callers
259
275
260Since `hair`s, `nail`s, etc. are only utilized within the context of writing
276Since `hair`s, `nail`s, etc. are only utilized within the context of writing
@@ -295,7 +311,6 @@ For additional information including additional examples see [4g: Parsing (Outsi
295For the remainder of this tutorial we will make use of `+scan` so that we do not
311For the remainder of this tutorial we will make use of `+scan` so that we do not
296need to deal directly with `nail`s except where it is ilustrative to do so.
312need to deal directly with `nail`s except where it is ilustrative to do so.
297
313
298−
299### Parsing atoms
314### Parsing atoms
300
315
301[Recall](/docs/hoon/hoon-school/lists) that `cord`s are atoms with the aura
316[Recall](/docs/hoon/hoon-school/lists) that `cord`s are atoms with the aura
@@ -312,7 +327,6 @@ The standard library provides a number of gates that take a `rule` and
312produce a new modified `rule` according to some process. We call these _parser modifiers_. These are
327produce a new modified `rule` according to some process. We call these _parser modifiers_. These are
313documented among the [parser builders](/docs/hoon/reference/stdlib/4f).
328documented among the [parser builders](/docs/hoon/reference/stdlib/4f).
314
329
315−
316### `+ifix`
330### `+ifix`
317
331
318`+ifix` modifies a `rule` so that it matches that `rule` only when it is
332`+ifix` modifies a `rule` so that it matches that `rule` only when it is
@@ -322,11 +336,11 @@ surrounded on both sides by text that matches a pair of `rule`s, which is discar
322> (scan "(42)" (ifix [pal par] (jest '42')))
336> (scan "(42)" (ifix [pal par] (jest '42')))
323'42'
337'42'
324```
338```
339+
325`+pal` and `+par` are shorthand for `(just '(')` and `(just ')')`, respectively. All
340`+pal` and `+par` are shorthand for `(just '(')` and `(just ')')`, respectively. All
326ASCII glyphs have counterparts of this sort, documented
341ASCII glyphs have counterparts of this sort, documented
327[here](/docs/hoon/reference/stdlib/4h).
342[here](/docs/hoon/reference/stdlib/4h).
328
343
329−
330### `+star` {#star}
344### `+star` {#star}
331
345
332`+star` is used to apply a `rule` repeatedly. Recall that `+just` only parses
346`+star` is used to apply a `rule` repeatedly. Recall that `+just` only parses
@@ -343,7 +357,9 @@ We can use `+star` to get the rest of the `tape`:
343> ((star (just 'a')) [[1 1] "aaa"])
357> ((star (just 'a')) [[1 1] "aaa"])
344[p=[p=1 q=4] q=[~ [p=[i='a' t=<|a a|>] q=[p=[p=1 q=4] q=""]]]]
358[p=[p=1 q=4] q=[~ [p=[i='a' t=<|a a|>] q=[p=[p=1 q=4] q=""]]]]
345```
359```
360+
346and we note that the parsing ceases when it fails.
361and we note that the parsing ceases when it fails.
362+
347```
363```
348> ((star (just 'a')) [[1 1] "aaab"])
364> ((star (just 'a')) [[1 1] "aaab"])
349[p=[p=1 q=4] q=[~ [p=[i='a' t=<|a a|>] q=[p=[p=1 q=4] q="b"]]]]
365[p=[p=1 q=4] q=[~ [p=[i='a' t=<|a a|>] q=[p=[p=1 q=4] q="b"]]]]
@@ -358,9 +374,11 @@ combinators](/docs/hoon/reference/stdlib/4e). First we introduce a few
358combinators, then we examine more closely how `;~` is used to chain them together.
374combinators, then we examine more closely how `;~` is used to chain them together.
359
375
360The syntax to combine `rule`s is
376The syntax to combine `rule`s is
377+
361```hoon
378```hoon
362;~(combinator rule1 rule2 ... ruleN)
379;~(combinator rule1 rule2 ... ruleN)
363```
380```
381+
364The `rule`s are composed together using the combinator as an
382The `rule`s are composed together using the combinator as an
365intermediate function, which takes product of a `rule` (an `edge`) and a `rule` and turns
383intermediate function, which takes product of a `rule` (an `edge`) and a `rule` and turns
366it into a sample (a `nail`) for the next `rule` to handle. We elaborate on this
384it into a sample (a `nail`) for the next `rule` to handle. We elaborate on this
@@ -409,42 +427,46 @@ take this opportunity to think about it carefully.
409The `rule` created by `;~(combinator [list rule])` may be understood
427The `rule` created by `;~(combinator [list rule])` may be understood
410inductively. To do this, let's consider the base case where our `[list rule]` has only a
428inductively. To do this, let's consider the base case where our `[list rule]` has only a
411single entry.
429single entry.
430+
412```
431```
413> (scan "star" ;~(plug (jest 'star')))
432> (scan "star" ;~(plug (jest 'star')))
414'star'
433'star'
415```
434```
435+
416Our output is identical to that given by `scan "star" (jest 'star')`. This is to
436Our output is identical to that given by `scan "star" (jest 'star')`. This is to
417be expected. The combinator `+plug` is specifically used for chaining together
437be expected. The combinator `+plug` is specifically used for chaining together
418`rule`s in the `[list rule]`, but if there is only one `rule`, there is nothing
438`rule`s in the `[list rule]`, but if there is only one `rule`, there is nothing
419to chain. Thus, swapping out `+plug` for another combinator makes no difference here:
439to chain. Thus, swapping out `+plug` for another combinator makes no difference here:
440+
420```
441```
421> (scan "star" ;~(pose (jest 'star')))
442> (scan "star" ;~(pose (jest 'star')))
422'star'
443'star'
423> (scan "star" ;~((glue com) (jest 'star')))
444> (scan "star" ;~((glue com) (jest 'star')))
424'star'
445'star'
425```
446```
447+
426`;~` and the combinator only begin to play a role once the `[list rule]` has at
448`;~` and the combinator only begin to play a role once the `[list rule]` has at
427least two elements. So let's look at an example done with `+plug`, the simplest
449least two elements. So let's look at an example done with `+plug`, the simplest
428combinator.
450combinator.
451+
429```
452```
430> (scan "star" ;~(plug (jest 'st') (jest 'ar')))
453> (scan "star" ;~(plug (jest 'st') (jest 'ar')))
431['st' 'ar']
454['st' 'ar']
432```
455```
456+
433Our return suggests that we first parsed `"star"` with the `rule` `(jest 'st')` and passed
457Our return suggests that we first parsed `"star"` with the `rule` `(jest 'st')` and passed
434−the resulting `edge` to `(jest 'ar')` - in other words, we called `+plug` on `(jest
458+the resulting `edge` to `(jest 'ar')` - in other words, we called `+plug` on `(jest 'st')` and the `edge` returned once it had been used to parse `"star"`. Thus
435−'st')` and the `edge` returned once it had been used to parse `"star"`. Thus
436`+plug` was the glue that allowed us to join the two `rule`s, and `;~` performed
459`+plug` was the glue that allowed us to join the two `rule`s, and `;~` performed
437the gluing operation. And so, swapping `+plug` for `+pose` results in a crash,
460the gluing operation. And so, swapping `+plug` for `+pose` results in a crash,
438which clues us into the fact that the combinator now has an effect since there
461which clues us into the fact that the combinator now has an effect since there
439is more than one `rule`.
462is more than one `rule`.
463+
440```
464```
441> (scan "star" ;~(pose (jest 'st') (jest 'ar')))
465> (scan "star" ;~(pose (jest 'st') (jest 'ar')))
442{1 3}
466{1 3}
443syntax error
467syntax error
444```
468```
445
469
446−
447−
448## Parsing numbers
470## Parsing numbers
449
471
450Functions for parsing numbers are documented in [4j: Parsing (Bases and Base
472Functions for parsing numbers are documented in [4j: Parsing (Bases and Base
@@ -461,15 +483,19 @@ for parsing decimal numbers.
461## Recursive parsers
483## Recursive parsers
462
484
463Naively attempting to write a recursive `rule`, i.e. like
485Naively attempting to write a recursive `rule`, i.e. like
486+
464```
487```
465> |-(;~(pose den ;~(pose $ (easy ~))))
488> |-(;~(pose den ;~(pose $ (easy ~))))
466```
489```
490+
467results in an error.
491results in an error.
492+
468```
493```
469-find.,.+6
494-find.,.+6
470-find.,.+6
495-find.,.+6
471rest-loop
496rest-loop
472```
497```
498+
473Thus some special sauce is required, the `+knee` function.
499Thus some special sauce is required, the `+knee` function.
474
500
475`+knee` takes in a noun that is the default value of the parser, typically given
501`+knee` takes in a noun that is the default value of the parser, typically given
@@ -494,7 +520,6 @@ the parser to improve performance. In [parsing arithmetic
494expressions](#parsing-arithmetic-expressions) we will be writing a recursive
520expressions](#parsing-arithmetic-expressions) we will be writing a recursive
495parser making use of `+knee` and `~+` throughout.
521parser making use of `+knee` and `~+` throughout.
496
522
497−
498# Parsing arithmetic expressions
523# Parsing arithmetic expressions
499
524
500In this section we will be applying what we have learned to write a parser for
525In this section we will be applying what we have learned to write a parser for
@@ -514,6 +539,7 @@ for arithmetic expressions informally.
514First lets look at the code we're going to use, and then dive into explaining
539First lets look at the code we're going to use, and then dive into explaining
515it. If you'd like to follow along, save the following as `expr-parse.hoon` in
540it. If you'd like to follow along, save the following as `expr-parse.hoon` in
516your `gen/` folder.
541your `gen/` folder.
542+
517```hoon
543```hoon
518:: expr-parse: parse arithmetic expressions
544:: expr-parse: parse arithmetic expressions
519::
545::
@@ -544,9 +570,10 @@ your `gen/` folder.
544```
570```
545
571
546Informally, the grammar here is:
572Informally, the grammar here is:
573+
547− - A factor is either an integer or an expression surrounded by parentheses.
574+- A factor is either an integer or an expression surrounded by parentheses.
548− - A term is either a factor or a factor times a term.
575+- A term is either a factor or a factor times a term.
549− - An expression is either a term or a term plus an expression.
576+- An expression is either a term or a term plus an expression.
550
577
551### Factors, terms, and expressions
578### Factors, terms, and expressions
552
579
@@ -568,8 +595,7 @@ for expressions.
568A _factor_ is either a decimal number or an expression surrounded by parentheses. Put
595A _factor_ is either a decimal number or an expression surrounded by parentheses. Put
569into Hoon terms, a decimal number is parsed by the `rule` `+dem` and an
596into Hoon terms, a decimal number is parsed by the `rule` `+dem` and an
570expression is parsed by removing the surrounding parentheses and then passing
597expression is parsed by removing the surrounding parentheses and then passing
571−the result to the expression parser arm `+expr`, given by the `rule` `(ifix [pal
598+the result to the expression parser arm `+expr`, given by the `rule` `(ifix [pal par] expr)`. Since we want to parse our expression with one or the other, we
572−par] expr)`. Since we want to parse our expression with one or the other, we
573chain these two `rule`s together using the monadic applicator rune `;~` along
599chain these two `rule`s together using the monadic applicator rune `;~` along
574with `+pose`, which says to try each rule in succession until one of them works.
600with `+pose`, which says to try each rule in succession until one of them works.
575
601
@@ -578,6 +604,7 @@ recursive rule. Thus we need to make use of `+knee`. The first argument for
578`+knee` is `*@ud`, since our final answer should be a `@ud`.
604`+knee` is `*@ud`, since our final answer should be a `@ud`.
579
605
580Then follows the definition of the gate utilized by `+knee`:
606Then follows the definition of the gate utilized by `+knee`:
607+
581```hoon
608```hoon
582 |. ~+
609 |. ~+
583 ;~ pose
610 ;~ pose
@@ -585,6 +612,7 @@ Then follows the definition of the gate utilized by `+knee`:
585 (ifix [pal par] expr)
612 (ifix [pal par] expr)
586 ==
613 ==
587```
614```
615+
588`~+` is used to cache the parser, so that it does not need to be computed over
616`~+` is used to cache the parser, so that it does not need to be computed over
589and over again. Then it follows the `rule` we described above.
617and over again. Then it follows the `rule` we described above.
590
618
@@ -615,7 +643,6 @@ accomplish this:
615The rest of the `+expr` arm is structured just like how `+factor` is, and for
643The rest of the `+expr` arm is structured just like how `+factor` is, and for
616the same reasons.
644the same reasons.
617
645
618−
619#### Parsing terms
646#### Parsing terms
620
647
621A _term_ is either a factor times a term or a factor. This is handled similarly
648A _term_ is either a factor times a term or a factor. This is handled similarly
content/docs/hoon/guides/strings.mdnew file+531
@@ -0,0 +1,531 @@
1++++
2+title = "Strings"
3+weight = 4
4+template = "doc.html"
5++++
6+
7+This document discusses hoon's two main string types: `cord`s (as well as its
8+subsets `knot` and `term`) and `tape`s. The focus of this
9+document is on their basic properties, syntax and the most common text-related
10+functions you'll regularly encounter. In particular, it discusses conversions
11+and the encoding/decoding of atom auras in strings.
12+
13+Hoon has a system for writing more elaborate functional parsers, but that is not
14+touched on here. Instead, see the [Parsing](/docs/hoon/guides/parsing) guide.
15+Hoon also has a type for UTF-32 strings, but those are rarely used and not
16+discussed in this document.
17+
18+There are a good deal more text manipulation functions than are discussed here.
19+See the [Further Reading](#further-reading) section for details.
20+
21+## `tape`s vs. text atoms
22+
23+As mentioned, urbit mainly deals with two kinds of strings: `tape`s and
24+`cord`/`knot`/`term`s. The former is a list of individual UTF-8 characters.
25+The latter three encode UTF-8 strings in a single atom.
26+
27+Cords may contain any UTF-8 characters, while `knot`s and `term`s only allow a
28+smaller subset. Each of these are discussed below in the [Text
29+atoms](#text-atoms) section.
30+
31+Text atoms like `cord`s are more efficient to store and move around. They are
32+also more efficient to manipulate with simple bitwise operations. Their downside
33+is that UTF-8 characters vary in their byte-length. ASCII characters are all
34+8-bit, but others can occupy up to four bytes. Accounting for this variation in
35+character size can complicate otherwise simple functions. Tapes, on the other
36+hand, don't have this problem because each character is a separate item in the
37+list, regardless of it byte-length. This fact makes it much easier to process
38+tapes in non-trivial ways with simple list functions.
39+
40+In light of this, a general rule of thumb is to use cords for simple things like
41+storing chat messages or exchanging them over the network. If text requires
42+complex processing on the other hand, it is generally easier with tapes. Note
43+there _are_ cord manipulation functions in the standard library, so you needn't
44+always convert cords to tapes for processing, it just depends on the case.
45+
46+Next we'll look at these different types of strings in more detail.
47+
48+## Text atoms
49+
50+### `cord`
51+
52+A [`cord`](/docs/hoon/reference/stdlib/2q#cord) has an aura of `@t`. It denotes
53+UTF-8 text encoded in an atom, little-endian. That is, the first character in
54+the text is the least-significant byte. A cord may contain any UTF-8 characters,
55+there are no restrictions.
56+
57+The `hoon` syntax for a cord is some text wrapped in single-quotes like:
58+
59+```hoon
60+'This is a cord!'
61+```
62+
63+single-quotes and backslashes must be escaped with a backslash like:
64+
65+```hoon
66+'\'quotes\' \\backslashes\\'
67+```
68+
69+Characters can also be entered as hex, they just have to be escaped by a
70+backslash. For example, `'\21\21\21'` will render as `'!!!'`. This is useful for
71+entering special characters such as line breaks like `'foo\0abar'`.
72+
73+Cords divided over multiple lines are allowed. There are two ways to do this.
74+The first is to start and end with three single-quotes like:
75+
76+```hoon
77+'''
78+foo
79+bar
80+baz
81+'''
82+```
83+
84+The line endings will be encoded Unix-style as line feed characters like:
85+
86+```hoon
87+'foo\0abar\0abaz'
88+```
89+
90+The second is to begin with a single-quote like usual, then break the line by
91+ending it with a backslash and start the next line with a forward-slash like:
92+
93+```hoon
94+'foo\
95+/bar\
96+/baz'
97+```
98+
99+This will be parsed to:
100+
101+```hoon
102+'foobarbaz'
103+```
104+
105+### `knot`
106+
107+A [`knot`](/docs/hoon/reference/stdlib/2q#knot) has an aura of `@ta`, and is a
108+subset of a [`cord`](#cord). It allows lower-case letters, numbers, and four
109+special characters: Hyphen, tilde, underscore and period. Its restricted set of
110+characters is intended to be URL-safe.
111+
112+The `hoon` syntax for a knot is a string containing any of the aforementioned
113+characters prepended with `~.` like:
114+
115+```hoon
116+~.abc-123.def_456~ghi
117+```
118+
119+### `term`
120+
121+A [`term`](/docs/hoon/reference/stdlib/2q#term) has an aura of `@tas`, and is a
122+subset of a [`knot`](#knot). It only allows lower-case letters, numbers, and
123+hyphens. Additionally, the first character cannot be a hyphen or number. This is
124+a very restricted text atom, and is intended for naming data structures and the
125+like.
126+
127+The `hoon` syntax for a term is a string conforming to the prior description,
128+prepended with a `%` like:
129+
130+```hoon
131+%foo-123
132+```
133+
134+#### A note about `term` type inference
135+
136+There is actually an even more restricted text atom form with the same `%foo`
137+syntax as a term, where the type of the text is the text itself. For example, in
138+the dojo:
139+
140+```
141+> `%foo`%foo
142+%foo
143+```
144+
145+The hoon parser will, by default, infer the type of `%foo`-style syntax this
146+way. If we try with the dojo type printer:
147+
148+```
149+> ? %foo
150+ %foo
151+%foo
152+```
153+
154+This type-as-itself is used for many things, such as unions like:
155+
156+```hoon
157+?(%foo %bar %bas)
158+```
159+
160+In order to give `%foo` the more generic `@tas` aura, it must be explicitly
161+upcast like:
162+
163+```
164+> ? `@tas`%foo
165+ @tas
166+%foo
167+```
168+
169+This is something to be wary of. For example, if you wanted to form a `(set @tas)` you might think to do:
170+
171+```hoon
172+(silt (limo ~[%foo %bar %baz]))
173+```
174+
175+However, this will actually form a set of the union `?(%foo %bar %baz)` due to
176+the specificity of type inference:
177+
178+```
179+> ? (silt (limo ~[%foo %bar %baz]))
180+ ?(%~ [?(n=%bar n=%baz n=%foo) l=nlr(?(%bar %baz %foo)) r=nlr(?(%bar %baz %foo))])
181+[n=%baz l={%bar} r={%foo}]
182+```
183+
184+One further note about the type-as-itself form: Ocassionally you may wish to
185+form a union of strings which contain characters disallowed in `term`s. To get
186+around this, you can enclose the text after the `%` with single-quotes like
187+`%'HELLO!'`.
188+
189+### Aura type validity
190+
191+The hoon parser will balk at `cord`s, `knot`s and `term`s containing invalid
192+characters. However, because they're merely auras, any atom can be cast to them.
193+When cast (or clammed), they will **not** be validated in terms of whether the
194+characters are allowed in the specified aura.
195+
196+For example, you can do this:
197+
198+```
199+> `@tas`'!%* $@&'
200+%!%* $@&
201+```
202+
203+This means you cannot rely on mere aura-casting if you need the text to conform
204+to the specified aura's restrictions. Instead, there are a couple of function in
205+the standard library to check text aura validity:
206+[`+sane`](/docs/hoon/reference/stdlib/4b#sane) and
207+[`+sand`](/docs/hoon/reference/stdlib/4b#sane).
208+
209+The `+sane` function takes an argument of either `%ta` or `%tas` to validate
210+`@ta` and `@tas` respectively (you can technically give it `%t` for `@t` too but
211+there's no real point). It will return `%.y` if the given atom is valid for the
212+given aura, and `%.n` if it isn't. For example:
213+
214+```
215+> ((sane %tas) 'foo')
216+%.y
217+> ((sane %tas) 'foo!')
218+%.n
219+```
220+
221+The `+sand` function does the same thing, but rather than returning a `?` it
222+returns a `unit` of the given atom, or `~` if validation failed. For example:
223+
224+```
225+> `(unit @tas)`((sand %tas) 'foo')
226+[~ %foo]
227+> `(unit @tas)`((sand %tas) 'foo!')
228+~
229+```
230+
231+## `tape`
232+
233+A [`tape`](/docs/hoon/reference/stdlib/2q#tape) is the other
234+main string type in hoon. Rather than a single atom, it's instead a list of
235+individual `@tD` characters (the `D` specifies a bit-length of 8, see the
236+[Auras](/docs/hoon/reference/auras#bitwidth) documentation for
237+details). The head of the list is the first character in the string.
238+
239+The `hoon` syntax for a tape is some text wrapped in double-quotes like:
240+
241+```hoon
242+"This is a tape!"
243+```
244+
245+Double-quotes, backslashes and left-braces must be escaped by a backslash
246+character:
247+
248+```hoon
249+"\"double-quotes\" \\backslash\\ left-brace:\{"
250+```
251+
252+Like with `cord`s, characters can also be entered as hex escaped by a backslash
253+so `"\21\21\21"` renders as `"!!!"`.
254+
255+Tapes divided over multiple lines are allowed. Unlike [`cord`](#cord)s, there is
256+only one way to do this, which is by starting and ending with three
257+double-quotes like:
258+
259+```hoon
260+"""
261+foo
262+bar
263+baz
264+"""
265+```
266+
267+The line endings will be encoded Unix-style as line feed characters like:
268+
269+```hoon
270+"foo\0abar\0abaz"
271+```
272+
273+As mentioned earlier, tapes are lists of single characters:
274+
275+```
276+> `tape`~['f' 'o' 'o']
277+"foo"
278+```
279+
280+This means they can be manipulated with ordinary list functions:
281+
282+```
283+> `tape`(turn "foobar" succ)
284+"gppcbs"
285+```
286+
287+### Interpolation
288+
289+Tapes, unlike cords, allow string interpolation. Arbitrary `hoon` may be
290+embedded in the tape syntax and its product will be included in the resulting
291+tape. There are two ways to do it:
292+
293+#### Manual
294+
295+In the first case, the code to be evaluated is enclosed in braces. The type of
296+the product of the code must itself be a tape. For example, if the `@p` of our
297+ship is stored in `our`, simply doing `"{our}"` will fail because its type will
298+be `@p` rather than `tape`. Instead, we must explicitly use the
299+[`+scow`](/docs/hoon/reference/stdlib/4m#scow) function to
300+render `our` as a tape:
301+
302+```
303+> "{(scow %p our)}"
304+"~zod"
305+```
306+
307+Another example:
308+
309+```
310+> "[{(scow %p our)} {(scow %da now)}]"
311+"[~zod ~2021.10.3..08.59.10..2335]"
312+```
313+
314+#### Automatic
315+
316+Rather than having to manually render data as a `tape`, angle brackets _inside_
317+the braces tell the interpreter to automatically pretty-print the product of the
318+expression as a tape. This way we needn't use functions like `+scow` and can
319+just reference things like `our` directly:
320+
321+```
322+> "{<our>}"
323+~zod
324+```
325+
326+Another example:
327+
328+```
329+> "{<(add 1 2)>}"
330+"3"
331+```
332+
333+And another:
334+
335+```
336+> "{<our now>}"
337+"[~zod ~2021.10.3..09.01.14..1654]"
338+```
339+
340+## Conversions
341+
342+Tapes can easily be converted to cords and vice versa. There are two stdlib
343+functions for this purpose: [`+crip`](/docs/hoon/reference/stdlib/4b#crip) and
344+[`+trip`](/docs/hoon/reference/stdlib/4b#trip). The former converts a `tape` to
345+a `cord` and the latter does the opposite. For example:
346+
347+```
348+> (crip "foobar")
349+'foobar'
350+> (trip 'foobar')
351+"foobar"
352+```
353+
354+Knots and terms can also be converted to tapes with `+trip`:
355+
356+```
357+> (trip %foobar)
358+"foobar"
359+> (trip ~.foobar)
360+"foobar"
361+```
362+
363+Likewise, the output of `+crip` can be cast to a knot or term:
364+
365+```
366+> `@tas`(crip "foobar")
367+%foobar
368+> `@ta`(crip "foobar")
369+~.foobar
370+> `@tas`(need ((sand %tas) (crip "foobar")))
371+%foobar
372+```
373+
374+## Encoding in text
375+
376+It's common to encode atoms in cords or knots, particularly when constructing a
377+[scry](/docs/arvo/concepts/scry) [`path`](/docs/hoon/reference/stdlib/2q#path)
378+or just a `path` in general. There are two main functions for this purpose:
379+[`+scot`](/docs/hoon/reference/stdlib/4m#scot) and
380+[`+scow`](/docs/hoon/reference/stdlib/4m#scow). The former produces a `knot`,
381+and the latter produces a `tape`. Additionally, there are two more functions for
382+encoding `path`s in cords and tapes respectively:
383+[`+spat`](/docs/hoon/reference/stdlib/4m#spat) and
384+[`+spud`](/docs/hoon/reference/stdlib/4m#spud).
385+
386+### `+scot` and `+spat`
387+
388+`+scot` encodes atoms of various auras in a `knot` (or `cord`/`term` with
389+casting). It takes two arguments: the aura in a `@tas` and the atom to be
390+encoded. For example:
391+
392+```
393+> (scot %p ~zod)
394+~.~zod
395+
396+> (scot %da now)
397+~.~2021.10.4..07.35.54..6d41
398+
399+> (scot %ux 0xaa.bbbb)
400+~.0xaa.bbbb
401+```
402+
403+Note the aura of the atom needn't actually match the specified aura:
404+
405+```
406+> (scot %ud ~zod)
407+~.0
408+```
409+
410+Hoon can of course be evaluated in its arguments as well:
411+
412+```
413+> (scot %ud (add 1 1))
414+~.2
415+```
416+
417+You'll most commonly see this used in constructing a `path` like:
418+
419+```
420+> /(scot %p our)/garden/(scot %da now)/foo/(scot %ud 123.456)
421+[~.~zod %garden ~.~2021.10.4..07.43.14..a556 %foo ~.123.456 ~]
422+
423+> `path`/(scot %p our)/garden/(scot %da now)/foo/(scot %ud 123.456)
424+/~zod/garden/~2021.10.4..07.43.23..9a0f/foo/123.456
425+```
426+
427+`+spat` simply encodes a `path` in a cord like:
428+
429+```
430+> (spat /foo/bar/baz)
431+'/foo/bar/baz'
432+```
433+
434+### `+scow` and `+spud`
435+
436+`+scow` is the same as [`+scot`](#scot-and-spat) except it produces a tape
437+rather than a knot. For example:
438+
439+```
440+> (scow %p ~zod)
441+"~zod"
442+
443+> (scow %da now)
444+"~2021.10.4..07.45.25..b720"
445+
446+> (scow %ux 0xaa.bbbb)
447+"0xaa.bbbb"
448+```
449+
450+`+spud` simply encodes a `path` in a tape:
451+
452+```
453+> (spud /foo/bar/baz)
454+"/foo/bar/baz"
455+```
456+
457+## Decoding from text
458+
459+For decoding atoms of particular auras encoded in cords, there are three
460+functions: [`+slat`](/docs/hoon/reference/stdlib/4m#slat),
461+[`+slav`](/docs/hoon/reference/stdlib/4m#slav), and
462+[`+slaw`](/docs/hoon/reference/stdlib/4m#slaw). Additionally, there is
463+[`+stab`](/docs/hoon/reference/stdlib/4m#stab) for decoding a cord to a path.
464+
465+`+slav` parses the given cord with the aura specified as a `@tas`, crashing if
466+the parsing failed. For example:
467+
468+```
469+> `@da`(slav %da '~2021.10.4..11.26.54')
470+~2021.10.4..11.26.54
471+
472+> `@p`(slav %p '~zod')
473+~zod
474+
475+> (slav %p 'foo')
476+dojo: hoon expression failed
477+```
478+
479+`+slaw` is like `+slav` except it produces a `unit` which is null if parsing
480+failed, rather than crashing. For example:
481+
482+```
483+> `(unit @da)`(slaw %da '~2021.10.4..11.26.54')
484+[~ ~2021.10.4..11.26.54]
485+
486+> `(unit @p)`(slaw %p '~zod')
487+[~ ~zod]
488+
489+> (slaw %p 'foo')
490+~
491+```
492+
493+`+slat` is a curried version of `+slaw`, meaning it's given the aura and
494+produces a new gate which takes the actual cord. For example:
495+
496+```
497+> `(unit @da)`((slat %da) '~2021.10.4..11.26.54')
498+[~ ~2021.10.4..11.26.54]
499+
500+> `(unit @p)`((slat %p) '~zod')
501+[~ ~zod]
502+
503+> ((slat %p) 'foo')
504+~
505+```
506+
507+Finally, `+stab` parses a cord containing a path to a `path`. For example:
508+
509+```
510+> (stab '/foo/bar/baz')
511+/foo/bar/baz
512+```
513+
514+## Futher reading
515+
516+- [Parsing](/docs/hoon/guides/parsing) - A guide to writing fully-fledged
517+ functional parsers in hoon.
518+
519+- [Auras](/docs/hoon/reference/auras) - Details of auras in hoon.
520+
521+- [stdlib 2b: List logic](/docs/hoon/reference/stdlib/2b) - Standard library
522+ functions for manipulating lists, which are useful for dealing with tapes.
523+
524+- [stdlib 2q: Molds and Mold-builders](/docs/hoon/reference/stdlib/2q) - Several
525+ text types are defined in this section of the standard library.
526+
527+- [stdlib 4b: Text processing](/docs/hoon/reference/stdlib/4b) - Standard
528+ library functions for manipulating and converting tapes and strings.
529+
530+- [stdlib 4m: Formatting functions](/docs/hoon/reference/stdlib/4m) - Standard
531+ library functions for encoding and decoding atom auras in strings.
content/docs/hoon/hoon-school/_index.md+28−33
@@ -7,36 +7,31 @@ aliases = ["/docs/byte/0/", "/docs/byte", "/docs/learn/hoon/hoon-tutorial/"]
7insert_anchor_links = "right"
7insert_anchor_links = "right"
8+++
8+++
9
9
10−This series is designed to teach you Hoon without assuming you have an extensive
10+- [1.1 Introduction](https://urbit.org/docs/hoon/hoon-school/intro)
11−programming background. In fact, you should be able to follow much of it even if
11+- [1.1.1 Walkthrough: List of Numbers](https://urbit.org/docs/hoon/hoon-school/list-of-numbers)
12−you have no programming experience at all, though of course experience helps. We
12+- [1.2 Nouns](https://urbit.org/docs/hoon/hoon-school/nouns)
13−strongly encourage you to try out all the examples of each lesson. These lessons
13+- [1.3 Hoon Syntax](https://urbit.org/docs/hoon/hoon-school/hoon-syntax)
14−are meant for the beginner, but they aren't meant to be skimmed. Each lesson
14+- [1.3.1 Walkthrough: Conditionals](https://urbit.org/docs/hoon/hoon-school/conditionals)
15−falls into one of two categories: **readings**, which are prose-heavy
15+- [1.4 Gates (Hoon Functions)](https://urbit.org/docs/hoon/hoon-school/gates)
16−explanations of Hoon fundamentals, and **walkthroughs**, which are line-by-line
16+- [1.4.1 Walkthrough: Recursion](https://urbit.org/docs/hoon/hoon-school/recursion)
17−explanations of example programs. Walkthroughs are found between readings,
17+- [1.5 Lists](https://urbit.org/docs/hoon/hoon-school/lists)
18−offering a practical implementation of the concepts taught in the reading
18+- [1.5.1 Walkthrough: Fibonacci Sequence](https://urbit.org/docs/hoon/hoon-school/fibonacci)
19−before.
19+- [1.6 The Subject and Its Legs](https://urbit.org/docs/hoon/hoon-school/the-subject-and-its-legs)
20−
20+- [1.6.1 Walkthrough: Ackermann Function](https://urbit.org/docs/hoon/hoon-school/ackermann)
21−If you're curious about why Urbit is written in this new language, we recommend
21+- [1.7 Arms and Cores](https://urbit.org/docs/hoon/hoon-school/arms-and-cores)
22−reading the [Hoon overview](/docs/hoon/overview) that covers the high-level
22+- [1.7.1 Walkthrough: Caesar Cipher](https://urbit.org/docs/hoon/hoon-school/caesar)
23−design decisions behind the language.
23+- [1.8 Doors](https://urbit.org/docs/hoon/hoon-school/doors)
24−
24+- [1.8.1 Bank Account](https://urbit.org/docs/hoon/hoon-school/bank-account)
25−Chapter 1 introduces and explains the fundamental concepts you need in order to
25+- [1.9 Generators](https://urbit.org/docs/hoon/hoon-school/generators)
26−understand Hoon's semantics.
26+- [2.1 Atoms, Auras, and Simple Cell Types](https://urbit.org/docs/hoon/hoon-school/atoms-auras-and-simple-cell-types)
27−
27+- [2.2 Type Checking and Type Inference](https://urbit.org/docs/hoon/hoon-school/type-checking-and-type-inference)
28−Hoon is a "subject-oriented" programming language &mdash; every expression of
28+- [2.3 Structures and Complex Types](https://urbit.org/docs/hoon/hoon-school/structures-and-complex-types)
29−Hoon is evaluated relative to a **subject**. The subject is a piece of data that
29+- [2.3.1 Walkthrough: Libraries](https://urbit.org/docs/hoon/hoon-school/libraries)
30−represents the environment, or the context, of an expression. After reading
30+- [2.3.2 Molds](https://urbit.org/docs/hoon/hoon-school/molds)
31−Chapter 1 you should understand what the subject is and how to refer to its
31+- [2.4 Standard Library: Trees, Sets, and Maps](https://urbit.org/docs/hoon/hoon-school/trees-sets-and-maps)
32−various parts. In this chapter you'll also learn about
32+- [2.5 Type Polymorphism](https://urbit.org/docs/hoon/hoon-school/type-polymorphism)
33−**[cores](/docs/glossary/core/)**, which are an important data structure in
33+- [2.5.1 Walkthrough: Iron Polymorphism and Wet Polymorphism](https://urbit.org/docs/hoon/hoon-school/iron-polymorphism)
34−Hoon. Once you get the hang of [cores](/docs/glossary/core/) you'll be able to
34+- [2.5.2 Walkthrough: Lead Polymorphism](https://urbit.org/docs/hoon/hoon-school/lead-polymorphism)
35−write your own functions in Hoon.
35+- [2.6 Behn](https://urbit.org/docs/hoon/hoon-school/behn)
36−
36+- [2.7 Gall](https://urbit.org/docs/hoon/hoon-school/gall)
37−Chapter 2 covers the type system, writing basic apps, and the workings of the
37+- [2.7.1 Gall Walkthrough: Egg Timer](https://urbit.org/docs/hoon/hoon-school/egg-timer)
38−Arvo kernel.
39−
40−You should also consider enrolling in Hooniversity, a regularly held
41−community-run course which follows along the Hoon School curriculum and may be
42−found at [Hooniversity](https://hooniversity.org/).
content/docs/hoon/hoon-school/caesar.md+25−25
@@ -27,7 +27,7 @@ information. Implementing it in a program is just a fun exercise.
27Below is a generator that performs a Caesar cipher on a tape. This example
27Below is a generator that performs a Caesar cipher on a tape. This example
28isn't the most compact implementation of such a cipher in Hoon, but it
28isn't the most compact implementation of such a cipher in Hoon, but it
29demonstrates important principles that more laconic code would not. Save it as
29demonstrates important principles that more laconic code would not. Save it as
30−`caesar.hoon` in your `/gen` directory.
30+`caesar.hoon` in the `/gen` directory of your `%base` desk.
31
31
32```hoon
32```hoon
33!:
33!:
@@ -131,7 +131,7 @@ itself before reading the explanation.
131The `!:` in the first line of the above code enables a full stack trace in the
131The `!:` in the first line of the above code enables a full stack trace in the
132event of an error.
132event of an error.
133
133
134−`|= [msg=tape steps=@ud]` creates a [gate](/docs/glossary/gate/) that takes a cell. The head of this cell
134+`|= [msg=tape steps=@ud]` creates a [gate](/docs/glossary/gate/) that takes a cell. The head of this cell
135is a `tape`, which is a string type that's a list of `cord`s. Tapes are represented
135is a `tape`, which is a string type that's a list of `cord`s. Tapes are represented
136as text surrounded by double-quotes, such as this: `"a tape"`. We give this input
136as text surrounded by double-quotes, such as this: `"a tape"`. We give this input
137tape the face `msg`. The tail of our cell is a `@ud` -- an unsigned decimal [atom](/docs/glossary/atom/)
137tape the face `msg`. The tail of our cell is a `@ud` -- an unsigned decimal [atom](/docs/glossary/atom/)
@@ -141,7 +141,7 @@ tape the face `msg`. The tail of our cell is a `@ud` -- an unsigned decimal [ato
141second child expression as the subject. In this case, we evaluate the
141second child expression as the subject. In this case, we evaluate the
142expressions in the code chunk below against the [core](/docs/glossary/core/) declared later, which
142expressions in the code chunk below against the [core](/docs/glossary/core/) declared later, which
143allows us reference the core's contained [arms](/docs/glossary/arm/) before they are defined. Without
143allows us reference the core's contained [arms](/docs/glossary/arm/) before they are defined. Without
144−`=<`, we would need to put the code chunk below at the bottom of our program. In Hoon, as previously
144+`=<`, we would need to put the code chunk below at the bottom of our program. In Hoon, as previously
145stated, we always want to keep the longer code towards the bottom of our programs - `=<` helps us do that.
145stated, we always want to keep the longer code towards the bottom of our programs - `=<` helps us do that.
146
146
147```hoon
147```hoon
@@ -150,19 +150,19 @@ stated, we always want to keep the longer code towards the bottom of our program
150(unshift msg steps)
150(unshift msg steps)
151```
151```
152
152
153−`=. msg (cass msg)` changes the input string `msg` to lowercases. `=.` changes
153+`=. msg (cass msg)` changes the input string `msg` to lowercases. `=.` changes
154the leg of the subject to something else. In our case, the leg to be changed is
154the leg of the subject to something else. In our case, the leg to be changed is
155`msg`, and the thing to replace it is `(cass msg)`. `cass` is a standard-library
155`msg`, and the thing to replace it is `(cass msg)`. `cass` is a standard-library
156gate that converts uppercase letters to lowercase.
156gate that converts uppercase letters to lowercase.
157
157
158−`:- (shift msg steps)` and `(unshift msg steps)` simply composes a
158+`:- (shift msg steps)` and `(unshift msg steps)` simply composes a
159cell of a right-shifted cipher and a left-shifted cipher of our original message.
159cell of a right-shifted cipher and a left-shifted cipher of our original message.
160We will see how this is done using the core described below, but this is the final
160We will see how this is done using the core described below, but this is the final
161output of our generator.
161output of our generator.
162
162
163`|%` creates a `core`, the second child of `=<`. Everything after `|%` is part of that
163`|%` creates a `core`, the second child of `=<`. Everything after `|%` is part of that
164second child `core`, and will be used as the subject of the first child of `=<`, described
164second child `core`, and will be used as the subject of the first child of `=<`, described
165−above. The various parts, or `arm`s, of the `core` are denoted by `++` beneath it, for
165+above. The various parts, or `arm`s, of the `core` are denoted by `++` beneath it, for
166instance:
166instance:
167
167
168```hoon
168```hoon
@@ -174,21 +174,21 @@ instance:
174```
174```
175
175
176The `rotation` arm takes takes a specified number of characters off of a tape and
176The `rotation` arm takes takes a specified number of characters off of a tape and
177−puts them on the end of the tape. We're going to use this to create our shifted alphabet,
177+puts them on the end of the tape. We're going to use this to create our shifted alphabet,
178based on the number of `steps` given as an argument to our gate.
178based on the number of `steps` given as an argument to our gate.
179
179
180−`|= [my-alphabet=tape my-steps=@ud]` creates a gate that takes two arguments: `my-alphabet`, a `tape`,
180+`|= [my-alphabet=tape my-steps=@ud]` creates a gate that takes two arguments: `my-alphabet`, a `tape`,
181and `my-steps`, a `@ud`.
181and `my-steps`, a `@ud`.
182
182
183−`=/ length=@ud (lent my-alphabet)` stores the length of `my-alphabet` to make the following
183+`=/ length=@ud (lent my-alphabet)` stores the length of `my-alphabet` to make the following
184code a little clearer.
184code a little clearer.
185
185
186`trim` is a a gate from the standard library that splits a tape at into two
186`trim` is a a gate from the standard library that splits a tape at into two
187−parts at a specified position. So `=+ (trim (mod my-steps length) my-alphabet)` splits the
187+parts at a specified position. So `=+ (trim (mod my-steps length) my-alphabet)` splits the
188tape `my-alphabet` into two parts, `p` and `q`, which are now directly available in the subject.
188tape `my-alphabet` into two parts, `p` and `q`, which are now directly available in the subject.
189We call the modulus operation `mod` to make sure that the point at which we split our `tape` is
189We call the modulus operation `mod` to make sure that the point at which we split our `tape` is
190a valid point inside of `my-alphabet` even if `my-steps` is greater than `length`, the length of
190a valid point inside of `my-alphabet` even if `my-steps` is greater than `length`, the length of
191−`my-alphabet`. Try trim in the dojo:
191+`my-alphabet`. Try trim in the dojo:
192
192
193```
193```
194> (trim 2 "abcdefg")
194> (trim 2 "abcdefg")
@@ -221,42 +221,42 @@ A `map` is a type equivalent to a dictionary in other languages: it's a data str
221associates a key with a value. If, for example, we wanted to have an association
221associates a key with a value. If, for example, we wanted to have an association
222between `a` and 1 and `b` and 2, we could use a `map`.
222between `a` and 1 and `b` and 2, we could use a `map`.
223
223
224−`|= [a=tape b=tape]` builds a gate that takes two tapes, `a` and `b`, as its
224+`|= [a=tape b=tape]` builds a gate that takes two tapes, `a` and `b`, as its
225sample.
225sample.
226
226
227−`^- (map @t @t)` casts the gate to a `map` with a `cord` (or `@t`) key and a `cord`
227+`^- (map @t @t)` casts the gate to a `map` with a `cord` (or `@t`) key and a `cord`
228value.
228value.
229
229
230You might wonder, if our gate in this arm takes `tape`s, why then are we producing
230You might wonder, if our gate in this arm takes `tape`s, why then are we producing
231a map of `cord` keys and values?
231a map of `cord` keys and values?
232
232
233−As we discussed earlier, a `tape` is a list of `cord`s. In this case what we are going to do
233+As we discussed earlier, a `tape` is a list of `cord`s. In this case what we are going to do
234is map a single element of a `tape` (either our alphabet or shifted-alphabet) to an element of
234is map a single element of a `tape` (either our alphabet or shifted-alphabet) to an element of
235−a different `tape` (either our shifted-alphabet or our alphabet). This pair will therefore be
235+a different `tape` (either our shifted-alphabet or our alphabet). This pair will therefore be
236−a pair of `cord`s. When we go to use this `map` to convert our incoming `msg`, we will take
236+a pair of `cord`s. When we go to use this `map` to convert our incoming `msg`, we will take
237each element (`cord`) of our `msg` `tape`, use it as a `key` when accessing our `map` and get
237each element (`cord`) of our `msg` `tape`, use it as a `key` when accessing our `map` and get
238the corresponding `value` from that position in the `map`. This is how we're going to encode
238the corresponding `value` from that position in the `map`. This is how we're going to encode
239or decode our `msg` `tape`.
239or decode our `msg` `tape`.
240
240
241−`=| chart=(map @t @t)` adds a [noun](/docs/glossary/noun/) to the subject with the default value of
241+`=| chart=(map @t @t)` adds a [noun](/docs/glossary/noun/) to the subject with the default value of
242the `(map @t @t)` type, and gives that noun the face `chart`.
242the `(map @t @t)` type, and gives that noun the face `chart`.
243
243
244−`?. =((lent key-position) (lent value-result))` checks if the two `tape`s are the same length. If not,
244+`?. =((lent key-position) (lent value-result))` checks if the two `tape`s are the same length. If not,
245−the program crashes with an error message of `%uneven-lengths`, using `|~ %uneven-lengths !!`.
245+the program crashes with an error message of `%uneven-lengths`, using `|~ %uneven-lengths !!`.
246
246
247If the two `tape`s are of the same length, we continue on to create a trap.
247If the two `tape`s are of the same length, we continue on to create a trap.
248`|-` creates a [trap](/docs/glossary/trap/), a gate that is called immediately.
248`|-` creates a [trap](/docs/glossary/trap/), a gate that is called immediately.
249
249
250−`?: |(?=(~ key-position) ?=(~ value-result))` checks if either `tape` is empty. If this is true, the
250+`?: |(?=(~ key-position) ?=(~ value-result))` checks if either `tape` is empty. If this is true, the
251`map-maker` arm is finished and can return `chart`, the `map` that we have been
251`map-maker` arm is finished and can return `chart`, the `map` that we have been
252creating.
252creating.
253
253
254If the above test finds that the `tape`s are not empty, we trigger a recursion
254If the above test finds that the `tape`s are not empty, we trigger a recursion
255that constructs our `map`: `$(chart (~(put by chart) i.a i.b), a t.a, b t.b)`.
255that constructs our `map`: `$(chart (~(put by chart) i.a i.b), a t.a, b t.b)`.
256This code recursively adds an entry in our `map` where the head of the `tape` `a`
256This code recursively adds an entry in our `map` where the head of the `tape` `a`
257−maps to the value of the head of `tape` `b` with `~(put by chart)`, our calling
257+maps to the value of the head of `tape` `b` with `~(put by chart)`, our calling
258of the `put` arm of the `by` map-engine core (note that `~(<wing> <door> <sample>`) is
258of the `put` arm of the `by` map-engine core (note that `~(<wing> <door> <sample>`) is
259−a shorthand for `%~ <wing> <door> <sample>` (see the [Calls % ('cen')](/docs/hoon/reference/rune/cen#censig)
259+a shorthand for `%~ <wing> <door> <sample>` (see the [Calls % ('cen')](/docs/hoon/reference/rune/cen#censig)
260documentation for more information). The recursion also "consumes"
260documentation for more information). The recursion also "consumes"
261those heads with every iteration by changing `a` and `b` to their tails using `a t.a, b t.b`.
261those heads with every iteration by changing `a` and `b` to their tails using `a t.a, b t.b`.
262
262
@@ -271,7 +271,7 @@ first.
271 (~(put by (map-maker key-position value-result)) ' ' ' ')
271 (~(put by (map-maker key-position value-result)) ' ' ' ')
272```
272```
273
273
274−`|= [key-position=tape value-result=tape]` creates a gate that takes two `tapes`.
274+`|= [key-position=tape value-result=tape]` creates a gate that takes two `tapes`.
275
275
276We use the `put` arm of the `by` core on the next line, giving it a `map` produced
276We use the `put` arm of the `by` core on the next line, giving it a `map` produced
277by the `map-maker` arm that we created before as its sample. This adds an entry to the
277by the `map-maker` arm that we created before as its sample. This adds an entry to the
@@ -300,12 +300,12 @@ that we can use to encode and decode messages.
300In both cases, we create a gate that accepts a `@ud` named `steps`.
300In both cases, we create a gate that accepts a `@ud` named `steps`.
301
301
302In `encoder`:
302In `encoder`:
303−`=/ value-tape=tape (rotation alpha steps)` creates a `value-tape` noun by calling `rotation`
303+`=/ value-tape=tape (rotation alpha steps)` creates a `value-tape` noun by calling `rotation`
304on `alpha`. `alpha` is our arm which contains a `tape` of the entire alphabet. The
304on `alpha`. `alpha` is our arm which contains a `tape` of the entire alphabet. The
305`value-tape` will be the list of `value`s in our `map`.
305`value-tape` will be the list of `value`s in our `map`.
306
306
307In `decoder`:
307In `decoder`:
308−`=/ key-tape (rotation alpha steps)` does the same work, but when passed to `space-adder`
308+`=/ key-tape (rotation alpha steps)` does the same work, but when passed to `space-adder`
309it will be the list of `key`s in our `map`.
309it will be the list of `key`s in our `map`.
310
310
311`(space-adder alpha value-tape)`, for `encoder`, and `(space-adder key-tape alpha)`, for
311`(space-adder alpha value-tape)`, for `encoder`, and `(space-adder key-tape alpha)`, for
content/docs/hoon/hoon-school/egg-timer.md+33−28
@@ -5,10 +5,10 @@ template = "doc.html"
5aliases = ["/docs/learn/hoon/hoon-tutorial/egg-timer/"]
5aliases = ["/docs/learn/hoon/hoon-tutorial/egg-timer/"]
6+++
6+++
7
7
8−The Arvo operating system is divided up into modules called vanes. Gall is the vane responsible for providing an API for building stateful applications in Urbit. Gall is a complex system that takes a lot of getting used to, so let's dip our toes in with a simple egg-timer app.
8+The Arvo operating system is divided up into modules called vanes. Gall is the vane responsible for providing an API for building stateful applications in Urbit. Gall is a complex system that takes a lot of getting used to, so let's dip our toes in with a simple egg-timer app.
9
9
10−The following code sample should be saved as `/home/app/egg-timer.hoon`
10+The following code sample should be saved as `/base/app/egg-timer.hoon`
11−After committing: `|start %egg-timer` and poke with `:egg-timer ~s10`
11+After committing: `|rein %base [& %egg-timer]` and poke with `:egg-timer ~s10`
12
12
13```hoon
13```hoon
14/+ default-agent
14/+ default-agent
@@ -46,7 +46,7 @@ After committing: `|start %egg-timer` and poke with `:egg-timer ~s10`
46--
46--
47```
47```
48
48
49−The first thing to notice is that we are creating a core (`|%`) and a door (`|_`). This is a typical style for Gall programming wherein types are defined in the first core and your application is defined in the following door.
49+The first thing to notice is that we are creating a core (`|%`) and a door (`|_`). This is a typical style for Gall programming wherein types are defined in the first core and your application is defined in the following door.
50Our door will have type `agent:gall` as specified in `sys/zuse.hoon`
50Our door will have type `agent:gall` as specified in `sys/zuse.hoon`
51
51
52```hoon
52```hoon
@@ -55,10 +55,10 @@ Our door will have type `agent:gall` as specified in `sys/zuse.hoon`
55--
55--
56```
56```
57
57
58−The core here defines only one type: `card`.
58+The core here defines only one type: `card`.
59−A `card` is a request to Arvo to do something for us. In this case, the only card used will be a `%wait` request to Behn which we'll discuss later.
59+A `card` is a request to Arvo to do something for us. In this case, the only card used will be a `%wait` request to Behn which we'll discuss later.
60
60
61−It's important to note that the name `card` is technically arbitrary. By convention, however, you will see it called `card` practically everywhere.
61+It's important to note that the name `card` is technically arbitrary. By convention, however, you will see it called `card` practically everywhere.
62
62
63The sample of the door(`|_`) is:
63The sample of the door(`|_`) is:
64
64
@@ -66,12 +66,12 @@ The sample of the door(`|_`) is:
66=bowl:gall
66=bowl:gall
67```
67```
68
68
69−You can find the full definition of `bowl` in `sys/zuse.hoon`, but for now it's enough to know that includes contextual data used by Gall with particular faces. Below are some important such faces:
69+You can find the full definition of `bowl` in `sys/zuse.hoon`, but for now it's enough to know that includes contextual data used by Gall with particular faces. Below are some important such faces:
70
70
71−- `our` The ship this code is running on
71+- `our` The ship this code is running on
72−- `src` The ship the current event originated from
72+- `src` The ship the current event originated from
73−- `eny` Guaranteed-fresh entropy
73+- `eny` Guaranteed-fresh entropy
74−- `now` The current time
74+- `now` The current time
75
75
76We give `bowl:gall` the face `bowl`.
76We give `bowl:gall` the face `bowl`.
77Additionally, we use `+*` to create two structures for future use:
77Additionally, we use `+*` to create two structures for future use:
@@ -80,10 +80,11 @@ Additionally, we use `+*` to create two structures for future use:
80+* this .
80+* this .
81 def ~(. (default-agent this %.n) bowl)
81 def ~(. (default-agent this %.n) bowl)
82```
82```
83+
83`this` is our current context(the door).
84`this` is our current context(the door).
84`def` uses `default-agent` to produce a standard `gall:agent` door, from which we will instance default definitions for our unused arms.
85`def` uses `default-agent` to produce a standard `gall:agent` door, from which we will instance default definitions for our unused arms.
85
86
86−All Gall agents have a fixed set of 10 arms. In this trivial case, we will specify only two and use the default definitions from `default-agent` for the remaining arms.
87+All Gall agents have a fixed set of 10 arms. In this trivial case, we will specify only two and use the default definitions from `default-agent` for the remaining arms.
87
88
88```hoon
89```hoon
89++ on-poke
90++ on-poke
@@ -94,33 +95,34 @@ All Gall agents have a fixed set of 10 arms. In this trivial case, we will spec
94 [%pass /egg-timer %arvo %b %wait (add now.bowl t)]~
95 [%pass /egg-timer %arvo %b %wait (add now.bowl t)]~
95```
96```
96
97
97−The `++on-poke` arm evaluates to a gate which takes a sample `[mark vase]`. `mark` is a type specification and `vase` is a cell of `[specification value]`
98+The `++on-poke` arm evaluates to a gate which takes a sample `[mark vase]`. `mark` is a type specification and `vase` is a cell of `[specification value]`
98Note: since `++on-poke` may take many different samples, it would be prudent to add a `%noun` mark check here.
99Note: since `++on-poke` may take many different samples, it would be prudent to add a `%noun` mark check here.
99−In this example, we assume that our sample will contain a `@dr` and pull it from the `vase` with `=/ t !<(@dr vase)`
100+In this example, we assume that our sample will contain a `@dr` and pull it from the `vase` with `=/ t !<(@dr vase)`
100`@dr` is an aura for a 128-bit relative date. Here are a few examples.
101`@dr` is an aura for a 128-bit relative date. Here are a few examples.
101
102
102−- `~s17` 17 seconds
103+- `~s17` 17 seconds
103−- `~m20` 20 minutes
104+- `~m20` 20 minutes
104- `~m13s37` 13 minutes, 37 seconds
105- `~m13s37` 13 minutes, 37 seconds
105−- `~d42` 42 days
106+- `~d42` 42 days
106
107
107As a matter of good type hygiene, we explicitly cast the output of this gate with `^-` to ensure we are producing the correct structure for Gall to handle.
108As a matter of good type hygiene, we explicitly cast the output of this gate with `^-` to ensure we are producing the correct structure for Gall to handle.
108−Our specification is `(quip card _this)` which produces a type, `[(list card) _this]`. Note that `_this` is irregular form of `$_(this)` which normalizes to the type of `this`, our door.
109+Our specification is `(quip card _this)` which produces a type, `[(list card) _this]`. Note that `_this` is irregular form of `$_(this)` which normalizes to the type of `this`, our door.
109
110
110−Next we use the `:_` rune which is the inverted form of `:-`, the cell construction rune.
111+Next we use the `:_` rune which is the inverted form of `:-`, the cell construction rune.
111
112
112```hoon
113```hoon
113:_ this
114:_ this
114 [%pass /egg-timer %arvo %b %wait (add now.bowl t)]~
115 [%pass /egg-timer %arvo %b %wait (add now.bowl t)]~
115```
116```
117+
116Our card should follow the basic form `[%pass /my/wire a-note]`
118Our card should follow the basic form `[%pass /my/wire a-note]`
117In this case, our card will ask Arvo to `%pass` a note along the wire `/egg-timer` to Behn(`%b`) containing a `%wait` request.
119In this case, our card will ask Arvo to `%pass` a note along the wire `/egg-timer` to Behn(`%b`) containing a `%wait` request.
118Behn will start a timer for us, and will respond along our wire, `/egg-timer`.
120Behn will start a timer for us, and will respond along our wire, `/egg-timer`.
119
121
120−`now.bowl` is the current time of type `@da`, and `t` was declared as `@dr`. Because they are both atoms, we can add `now` and `t` to produce an atom that is `t` units of time into the future from `now`. That produced atom can be interpreted as a `@da`.
122+`now.bowl` is the current time of type `@da`, and `t` was declared as `@dr`. Because they are both atoms, we can add `now` and `t` to produce an atom that is `t` units of time into the future from `now`. That produced atom can be interpreted as a `@da`.
121The calculated time will be passed via Arvo to Behn with instruction to `%wait @da`, i.e., to set a timer.
123The calculated time will be passed via Arvo to Behn with instruction to `%wait @da`, i.e., to set a timer.
122
124
123−That's all for our `++on-poke` arm. But what about when the timer goes off? Behn will create a `gift`, a similar construct to our `card` which will be dispatched back to us via Gall in the `++on-arvo` arm.
125+That's all for our `++on-poke` arm. But what about when the timer goes off? Behn will create a `gift`, a similar construct to our `card` which will be dispatched back to us via Gall in the `++on-arvo` arm.
124
126
125```hoon
127```hoon
126++ on-arvo
128++ on-arvo
@@ -130,20 +132,22 @@ That's all for our `++on-poke` arm. But what about when the timer goes off? Be
130 ~& "Timer went off!"
132 ~& "Timer went off!"
131 [~ this]
133 [~ this]
132```
134```
133−`++on-arvo` evaluates to a gate whose sample is a cell of `wire` and `sign-arvo` here given default faces. The syntax of `=wire` is a shortcut for `wire=wire`; it's a common pattern to shadow the name of a type when you only have one instance of the type and are not going to refer to the type itself.
134−A `wire` is an alias for a path. Our `wire` will be the path we provided in our `++on-poke` card. If we needed to do something particular depending on which request triggered this Arvo card, we could use the wire to do so.
135
135
136+`++on-arvo` evaluates to a gate whose sample is a cell of `wire` and `sign-arvo` here given default faces. The syntax of `=wire` is a shortcut for `wire=wire`; it's a common pattern to shadow the name of a type when you only have one instance of the type and are not going to refer to the type itself.
137+A `wire` is an alias for a path. Our `wire` will be the path we provided in our `++on-poke` card. If we needed to do something particular depending on which request triggered this Arvo card, we could use the wire to do so.
138+
136−Note: since multiple vanes can send many sorts of cards via `++on-arvo`, it would be prudent to check if `sign-arvo` is `[%b %wake *]`. Since our trivial example assumes the card is `%wake` from Behn, we will forgo that better practice here.
139+Note: since multiple vanes can send many sorts of cards via `++on-arvo`, it would be prudent to check if `sign-arvo` is `[%b %wake *]`. Since our trivial example assumes the card is `%wake` from Behn, we will forgo that better practice here.
140+
141+Next we have the same cast we used in `++on-poke` to make sure we produce the correct type for Gall. `(quip card _this)` resolves to a type `[(list card) _this]`
137
142
138−Next we have the same cast we used in `++on-poke` to make sure we produce the correct type for Gall. `(quip card _this)` resolves to a type `[(list card) _this]`
139```
143```
140~& "Timer went off!"
144~& "Timer went off!"
141```
145```
142
146
143−`~&` is the debugging printf rune. Here we're using it to output a message. We could, however, modify this line of code to do any other computation when `++on-arvo` is called.
147+`~&` is the debugging printf rune. Here we're using it to output a message. We could, however, modify this line of code to do any other computation when `++on-arvo` is called.
144
148
145We need to produce a noun of type `(quip card _this)` i.e., `[(list card) _this]`.
149We need to produce a noun of type `(quip card _this)` i.e., `[(list card) _this]`.
146−In this case, we will not produce any card or change application state. Therefore we simply produce a cell of a null list and our original context, `[~ this]`.
150+In this case, we will not produce any card or change application state. Therefore we simply produce a cell of a null list and our original context, `[~ this]`.
147
151
148```hoon
152```hoon
149++ on-init on-init:def
153++ on-init on-init:def
@@ -156,4 +160,5 @@ In this case, we will not produce any card or change application state. Therefo
156++ on-fail on-fail:def
160++ on-fail on-fail:def
157--
161--
158```
162```
163+
159Finally, we define the remaining 8 unused but required Gall Agent armsas instances of the default arms provided in `/lib/default-agent.hoon`.
164Finally, we define the remaining 8 unused but required Gall Agent armsas instances of the default arms provided in `/lib/default-agent.hoon`.
content/docs/hoon/hoon-school/generators.md+13−14
@@ -16,9 +16,8 @@ There are three kinds of generators: naked, `%say`, and `%ask`. There also used
16### Naked Generators
16### Naked Generators
17
17
18A naked generator is simply a `gate`; that is, it is an anonymous function that
18A naked generator is simply a `gate`; that is, it is an anonymous function that
19−takes a `sample` (argument) and produces a [noun](/docs/glossary/noun/). All you need to do is write a
19+takes a `sample` (argument) and produces a [noun](/docs/glossary/noun/). All you
20−`gate` and put it into a file in the `/gen` directory. Let's take a look at a
20+need to do is write a `gate` and put it into a file in the `/gen` directory of a desk on your ship. Let's take a look at a very simple one:
21−very simple one:
22
21
23```hoon
22```hoon
24|= a=*
23|= a=*
@@ -26,7 +25,8 @@ a
26```
25```
27
26
28This generator takes one argument of any noun and produces it without any
27This generator takes one argument of any noun and produces it without any
28+changes. Put this into a file named `echo.hoon` in the `/gen` directory of your
29−changes. Once you put this into a file named `echo.hoon` in the `/gen` directory, you must make your ship recognize the change by inputting `|commit %home` in the dojo. You can then run it from the dojo:
29+`%base` desk. You must make your ship recognize the change by inputting `|commit %base` in the dojo. You can then run it from the dojo:
30
30
31```
31```
32> +echo 42
32> +echo 42
@@ -64,7 +64,7 @@ generator to see something more familiar:
64```
64```
65
65
66Now let's create a generator with two arguments instead of one. Save the code
66Now let's create a generator with two arguments instead of one. Save the code
67−below as `add.hoon` in the `/gen` directory.
67+below as `add.hoon` in the `/gen` directory of your `%base` desk.
68
68
69```hoon
69```hoon
70|= [a=@ud b=@ud]
70|= [a=@ud b=@ud]
@@ -104,7 +104,7 @@ So, more formally, a `%say` generator is a `cell`. The head of that cell is the
104output data and the `mark` describing that data.
104output data and the `mark` describing that data.
105
105
106Below is an example of a `%say` generator. Save it to `add.hoon` in the `/gen`
106Below is an example of a `%say` generator. Save it to `add.hoon` in the `/gen`
107−directory.
107+directory of your `%base` desk.
108
108
109```hoon
109```hoon
110:- %say
110:- %say
@@ -133,7 +133,7 @@ Recall that the rune `:-` produces a cell, with the first following expression
133as its head and the second following expression as its tail.
133as its head and the second following expression as its tail.
134
134
135The expression above creates a cell with `%say` as the head. The tail is
135The expression above creates a cell with `%say` as the head. The tail is
136−the `|= *` expression on the line that follows.
136+the `|= *` expression on the line that follows.
137
137
138```hoon
138```hoon
139|= *
139|= *
@@ -141,10 +141,10 @@ the `|= *` expression on the line that follows.
141(add 40 2)
141(add 40 2)
142```
142```
143
143
144−`|= *` constructs a [gate](/docs/glossary/gate/) that takes a noun. This [gate](/docs/glossary/gate/) will itself produce a
144+`|= *` constructs a [gate](/docs/glossary/gate/) that takes a noun. This [gate](/docs/glossary/gate/) will itself produce a
145`cask`, which is cell formed by the prepending `:-`. The head of that `cask` is
145`cask`, which is cell formed by the prepending `:-`. The head of that `cask` is
146`%noun` and the tail is the rest of the program, `(add 40 2)`. The tail of the
146`%noun` and the tail is the rest of the program, `(add 40 2)`. The tail of the
147−`cask` will be our actual data produced by the body of the program: in this
147+`cask` will be our actual data produced by the body of the program: in this
148case, just adding 40 and 2 together.
148case, just adding 40 and 2 together.
149
149
150#### `%say` generators with arguments
150#### `%say` generators with arguments
@@ -216,7 +216,7 @@ second part, besides its position:
216```
216```
217
217
218Let's look at an example that uses all three parts. Save the code below in a
218Let's look at an example that uses all three parts. Save the code below in a
219−file called `dice.hoon` in your `/gen` directory.
219+file called `dice.hoon` in the `/gen` directory of your `%base` desk.
220
220
221```hoon
221```hoon
222:- %say
222:- %say
@@ -311,7 +311,7 @@ to explain how this kind of generator works.
311##### `%ask` example
311##### `%ask` example
312
312
313The code below is an `%ask` generator that checks if the user inputs "blue" when
313The code below is an `%ask` generator that checks if the user inputs "blue" when
314−prompted. Save it as `axe.hoon` in `/gen`.
314+prompted. Save it as `axe.hoon` in the `/gen` directory of your `%base` desk.
315
315
316```hoon
316```hoon
317/- sole
317/- sole
@@ -379,7 +379,7 @@ This code might be familiar. Just as with their `%say` cousins, `%ask`
379generators need to produce a `cell`, the head of which specifies what kind of
379generators need to produce a `cell`, the head of which specifies what kind of
380generator we are running.
380generator we are running.
381
381
382−With `|= *`, we create a gate and ignore the standard arguments we are given,
382+With `|= *`, we create a gate and ignore the standard arguments we are given,
383because we're not using them.
383because we're not using them.
384
384
385```hoon
385```hoon
@@ -434,7 +434,6 @@ use to prompt the user. In the case of our example, we use `"color: "`.
434**`produce`** is used to construct the output of the generator. In our example,
434**`produce`** is used to construct the output of the generator. In our example,
435we produce a `tang`.
435we produce a `tang`.
436
436
437−
438```hoon
437```hoon
439|= t=tape
438|= t=tape
440```
439```
@@ -458,4 +457,4 @@ This is a [known issue](https://github.com/urbit/arvo/issues/840) to be resolved
458
457
459## Conclusion
458## Conclusion
460
459
461−You've now reached the end of Chapter 1 of the Hoon tutorial. Ideally you should have a fair understanding of the fundamental concepts of subject-oriented programming: limbs, legs, faces, wings, arms, cores, gates, and [doors](/docs/glossary/door/). If you can master these concepts you should have little or no trouble learning to write substantial Hoon programs.
460+You've now reached the end of Chapter 1 of the Hoon tutorial. Ideally you should have a fair understanding of the fundamental concepts of subject-oriented programming: limbs, legs, faces, wings, arms, cores, gates, and [doors](/docs/glossary/door/). If you can master these concepts you should have little or no trouble learning to write substantial Hoon programs.
content/docs/hoon/hoon-school/hoon-syntax.md+1−1
@@ -254,7 +254,7 @@ The irregular form of the `.=` rune is just `=( )`:
254%.y
254%.y
255```
255```
256
256
257−The examples above have another irregular form: `(add 11 11)`. This is the irregular form of `%+`, which calls a [gate](/docs/glossary/gate/) (i.e., a Hoon function) with two arguments for the sample.
257+The examples above contain another irregular form: `(add 11 11)`. This is the irregular form of `%+`, which calls a [gate](/docs/glossary/gate/) (i.e., a Hoon function) with two arguments for the sample.
258
258
259```
259```
260> %+ add 11 11
260> %+ add 11 11
content/docs/hoon/hoon-school/intro.mdnew file+121
@@ -0,0 +1,121 @@
1++++
2+title = "1.1 Introduction"
3+weight = 1
4+template = "doc.html"
5+aliases = ["/docs/learn/hoon/hoon-tutorial/setup/"]
6++++
7+
8+This series is designed to teach you Hoon without assuming you have an extensive
9+programming background. In fact, you should be able to follow much of it even if
10+you have no programming experience at all, though of course experience helps. We
11+strongly encourage you to try out all the examples of each lesson. These lessons
12+are meant for the beginner, but they aren't meant to be skimmed. Each lesson
13+falls into one of two categories: **readings**, which are prose-heavy
14+explanations of Hoon fundamentals, and **walkthroughs**, which are line-by-line
15+explanations of example programs. Walkthroughs are found between readings,
16+offering a practical implementation of the concepts taught in the reading
17+before.
18+
19+If you're curious about why Urbit is written in this new language, we recommend
20+reading the [Hoon overview](/docs/hoon/overview) that covers the high-level
21+design decisions behind the language.
22+
23+Chapter 1 introduces and explains the fundamental concepts you need in order to
24+understand Hoon's semantics.
25+
26+Hoon is a "subject-oriented" programming language — every expression of
27+Hoon is evaluated relative to a **subject**. The subject is a piece of data that
28+represents the environment, or the context, of an expression. After reading
29+Chapter 1 you should understand what the subject is and how to refer to its
30+various parts. In this chapter you'll also learn about
31+**[cores](/docs/glossary/core/)**, which are an important data structure in
32+Hoon. Once you get the hang of [cores](/docs/glossary/core/) you'll be able to
33+write your own functions in Hoon.
34+
35+Chapter 2 covers the type system, writing basic apps, and the workings of the
36+Arvo kernel.
37+
38+## Environment Setup
39+
40+Before beginning, you'll need to get a development ship running and configure an
41+appropriate editor. See the [Environment Setup](/docs/development/environment)
42+guide for details.
43+
44+## Getting started
45+
46+Once you've created your development ship, let's try a basic command. Type `(add 2 2)` at the prompt and hit return. Your screen now shows:
47+
48+```
49+fake: ~zod
50+ames: czar: ~zod on 31337 (localhost only)
51+http: live (insecure, public) on 80
52+http: live (insecure, loopback) on 12321
53+> (add 2 2)
54+4
55+~zod:dojo>
56+```
57+
58+You just used a function from the Hoon standard library, `add`. Next, quit Urbit
59+with `ctrl-d`:
60+
61+```
62+> (add 2 2)
63+4
64+~zod:dojo>
65+$
66+```
67+
68+Your ship isn't running anymore and you're back at your computer's normal
69+terminal prompt. If your ship is `~zod`, then you can restart the ship by
70+typing:
71+
72+```sh
73+urbit zod
74+```
75+
76+## Another Noun
77+
78+You've already used a standard library function to produce one value, in the
79+Dojo. Now that your ship is running again, let's try another. Enter the number
80+`17`.
81+
82+We won't show the `~zod:dojo> ` prompt from here on out. We'll just show the
83+echoed command along with its result.
84+
85+You'll see:
86+
87+```
88+> 17
89+17
90+```
91+
92+You asked Dojo to evaluate `17` and it echoed the number back at you. This value
93+is a "noun". We'll talk more about [nouns](/docs/glossary/noun/) in [Lesson
94+1.2](/docs/hoon/hoon-school/nouns), but first let's write a very basic program.
95+
96+## Generators
97+
98+Generators are the most straightforward way to write Hoon programs. They are a
99+concept in Arvo, and involve saving Hoon code in a `.hoon` text file. While they
100+aren't strictly part of the Hoon language, we'll be dealing with generators
101+throughout this tutorial.
102+
103+The simplest type of generator is the **naked generator**. All naked generators
104+are `gates`: functions that take an argument and produce an output. To create a
105+generator, all you need to do is write a `gate`, save it in a `.hoon` file, and
106+add it to the `/gen` directory of a desk on your ship.
107+
108+To be able to add files easily, you'll need to mount a desk to the Unix
109+filesystem. We'll use the `%base` desk throughout Hoon School since we're using
110+a fake ship, but note a different one would be more suitable on a live ship. To
111+mount `%base`, just run `|mount %base` in the dojo. If you look in your
112+[pier](/docs/glossary/pier), you should now see a `base` folder. Once you've added
113+the `.hoon` file in `base/gen`, you'll need to run `|commit %base` in the dojo
114+so the new file is recognised by your ship. To run a generator named
115+`mygen.hoon`, you would type `+mygen <argument>` in your ship's dojo. If you
116+added it to a desk other than `%base`, you can run `+desk!mygen <argument>`
117+where `desk` is the desk you put it in.
118+
119+If this doesn't make sense yet, that's okay. In the [next
120+lesson](/docs/hoon/hoon-school/list-of-numbers), we will walk you through an
121+example `gate` that is run as a generator.
content/docs/hoon/hoon-school/list-of-numbers.md+3−3
@@ -20,7 +20,7 @@ Below is a simple Hoon program that takes a single number `n` from the user as i
20$(count (add 1 count)) :: 8
20$(count (add 1 count)) :: 8
21```
21```
22
22
23−As we mentioned in the previous lesson, the easiest way to use such a program is to run it as a _generator_. Mount your desk `|mount %` (if you didn't do it before), saving a file in the `/home/gen` directory of your ship and commiting these changes `|commit %home` allows you to run it from your ship's Dojo (command line) as a generator. Save the above code there as `list.hoon`. Now you can run it in the Dojo with the command below (remember, without the `>`):
23+As we mentioned in the previous lesson, the easiest way to use such a program is to run it as a _generator_. Mount your `%base` desk with `|mount %base` (if you didn't do it before), saving a file in the `base/gen` directory of your ship and commiting these changes `|commit %base` allows you to run it from your ship's Dojo (command line) as a generator. Save the above code there as `list.hoon`. Now you can run it in the Dojo with the command below (remember, without the `>`):
24
24
25`> +list 5`
25`> +list 5`
26
26
@@ -89,7 +89,7 @@ In this case, the rune specifies that our gate's output must be `(list @)` -- th
89
89
90`?:` is a rune that evaluates whether its first child is `true` or `false`. If that child is `true`, the program branches to the second child. If it's `false`, it branches to the third child. `?:` takes three children.
90`?:` is a rune that evaluates whether its first child is `true` or `false`. If that child is `true`, the program branches to the second child. If it's `false`, it branches to the third child. `?:` takes three children.
91
91
92−`=(end count)` checks if the user's input equals to the `count` value that we're incrementing to build the list. If these values are equal, we want to end the program, because our list has been built out to where it needs to be. Note that this expression is, in fact, a rune expression, just written a different way than you've seen so far. `=(end count)` is an _irregular form_ of `.= end count`, different in looks but identical in operation. `.=` is a rune that checks for the equality of its two children, and produces a `true` or `false` based on what it finds.
92+`=(end count)` checks if the user's input equals to the `count` value that we're incrementing to build the list. If these values are equal, we want to end the program, because our list has been built out to where it needs to be. Note that this expression is, in fact, a rune expression, just written a different way than you've seen so far. `=(end count)` is an _irregular form_ of `.= end count`, different in looks but identical in operation. `.=` is a rune that checks for the equality of its two children, and produces a `true` or `false` based on what it finds.
93
93
94`~` simply represents the `null` value. The program branches here if on line 5 it finds that `end` equals `count`. Lists in Hoon always end with `~`, so we need this to be the last thing we put in our list.
94`~` simply represents the `null` value. The program branches here if on line 5 it finds that `end` equals `count`. Lists in Hoon always end with `~`, so we need this to be the last thing we put in our list.
95
95
@@ -97,7 +97,7 @@ In this case, the rune specifies that our gate's output must be `(list @)` -- th
97
97
98`:-` is a rune that creates a **cell**, an ordered pair of two values, such as `[1 2]`. It takes two children.
98`:-` is a rune that creates a **cell**, an ordered pair of two values, such as `[1 2]`. It takes two children.
99
99
100−In our case, `:- count` creates a cell out of whatever value is stored in `count`, and then with the product of line 8.
100+In our case, `:- count` creates a cell out of whatever value is stored in `count`, and then with the product of line 8.
101
101
102## Line 8
102## Line 8
103
103
content/docs/hoon/hoon-school/recursion.md+7−8
@@ -19,8 +19,8 @@ would be:
19
19
20Let's implement a factorial calculator in Hoon. To do so, we'll write a
20Let's implement a factorial calculator in Hoon. To do so, we'll write a
21recursive `gate` (Hoon's equivalent of a function) to perform the relevant
21recursive `gate` (Hoon's equivalent of a function) to perform the relevant
22−computation. Save the code below as `factorial.hoon` in your ship's `/gen`
22+computation. Save the code below as `factorial.hoon` in the `/gen` directory of
23−directory.
23+the `%base` desk on your ship.
24
24
25```hoon
25```hoon
26|= n=@ud
26|= n=@ud
@@ -185,11 +185,10 @@ skips the first match of a name.
185### Exercises
185### Exercises
186
186
1871. Write a recursive gate that produces the first _n_
1871. Write a recursive gate that produces the first _n_
188−[Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number)
188+ [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number)
189
189
1902. Write a recursive gate that produces a list of moves to solve the
1902. Write a recursive gate that produces a list of moves to solve the
191−[Tower of Hanoi problem](https://en.wikipedia.org/wiki/Tower_of_Hanoi).
191+ [Tower of Hanoi problem](https://en.wikipedia.org/wiki/Tower_of_Hanoi).
192−Disks are stacked on a pole by decreasing order of size. Move all of the
192+ Disks are stacked on a pole by decreasing order of size. Move all of the
193−disks from one pole to another with a third pole as a spare, moving one
193+ disks from one pole to another with a third pole as a spare, moving one
194−disc at a time, without putting a larger disk on top of a smaller disk.
194+ disc at a time, without putting a larger disk on top of a smaller disk.
195−
content/docs/hoon/hoon-school/setup.mddeleted−105
@@ -1,105 +0,0 @@
1−+++
2−title = "1.1 Setup"
3−weight = 1
4−template = "doc.html"
5−aliases = ["/docs/learn/hoon/hoon-tutorial/setup/"]
6−+++
7−
8−Before we begin working on Hoon, you should first (1) have Urbit installed and (2) boot a ship that you can use for trying out Hoon examples. Interactive learning is far superior to passive reading.
9−
10−## What is an urbit?
11−
12−An **urbit** is an Urbit virtual computer with persistent state that can connect to the Urbit network. (Note the lowercase `u` here. "Urbit" is the entire software stack, whereas "an urbit" is a local instance.) Each urbit is associated with a unique number that plays three distinct roles: (1) it's an address on the Urbit network, (2) it's a cryptographic identity, and (3) it's (in principle) a human memorable name. Normally an urbit's name is represented as a string starting with `~`, as in `~zod` or `~taglux-nidsep`.
13−
14−These may not look like numbers, but they are. Each urbit name is written in a base-256 format, where each "digit" is a syllable. Imagine your phone number as a pronounceable string which sounds like a name in a foreign language. An ordinary user-level urbit is a "planet", and it's named by a 32-bit number. The latter is represented as a four-syllable string; e.g., the planet name `~taglux-nidsep` is the number 6,095,360.
15−
16−## Installing Urbit
17−
18−You can install Urbit on any Mac or Unix machine; if you're just trying out Urbit or creating a development ship, you can follow the steps for creating a development ship [here](/docs/development/environment). On Windows, make a virtual Linux machine using VirtualBox or a similar tool.
19−
20−Once you're finished, you can [boot your very own ship](/getting-started/). While you can develop in Hoon on your own ship on the live network, we strongly suggest developing on a development ship first.
21−
22−## Getting started
23−
24−Once you've created your development ship, let's try a basic command. Type `(add 2 2)` at the prompt and hit return. Your screen now shows:
25−
26−```
27−fake: ~zod
28−ames: czar: ~zod on 31337 (localhost only)
29−http: live (insecure, public) on 80
30−http: live (insecure, loopback) on 12321
31−> (add 2 2)
32−4
33−~zod:dojo>
34−```
35−
36−You just used a function from the Hoon standard library, `add`. Next, quit Urbit with `ctrl-d`:
37−
38−```
39−> (add 2 2)
40−4
41−~zod:dojo>
42−$
43−```
44−
45−Your ship isn't running anymore and you're back at your computer's normal terminal prompt. If your ship is `~zod`, then you can restart the ship by typing:
46−
47−```sh
48−urbit zod
49−```
50−
51−## Another Noun
52−
53−You've already used a standard library function to produce one value, in the Dojo. Now that your ship is running again, let's try another. Enter the number `17`.
54−
55−> We won't show the `~zod:dojo> ` prompt from here on out. We'll just show the echoed command along with its result.
56−
57−You'll see:
58−
59−```
60−> 17
61−17
62−```
63−
64−You asked Dojo to evaluate `17` and it echoed the number back at you. This value is a "noun". We'll talk more about [nouns](/docs/glossary/noun/) in [Lesson 1.2](/docs/hoon/hoon-school/nouns), but first let's write a very basic program.
65−
66−## Generators
67−
68−Generators are the most straightforward way to write Hoon programs. They are a concept in Arvo, and involve saving Hoon code in a `.hoon` text file. While they aren't strictly part of the Hoon language, we'll be dealing with generators throughout this tutorial.
69−
70−The simplest type of generator is the **naked generator**. All naked generators are `gates`: functions that take an argument and produce an output. Before creating a generator you need to [mount](/getting-started/) your `desk` to Unix. To create a generator, all you need to do is write a `gate` and put it into a file in the `/home/gen/` directory of your ship as a `.hoon` file. (Assuming you've already mounted with `|mount /=home=`.) After this, you need to run `|commit %home` in Dojo and the new file will be recognized by your ship. To run a generator named `mygen.hoon`, you would type `+mygen <argument>` in your ship's Dojo.
71−
72−If this doesn't make sense yet, that's okay. In the [next lesson](/docs/hoon/hoon-school/list-of-numbers), we will walk you through an example `gate` that is run as a generator.
73−
74−## Text editors
75−
76−Writing code in any language is typically done using a text editor, but common programs like Notepad, Microsoft Word, or OpenOffice Writer are not suitable for programming. You'll want instead a text editor that is specifically designed for writing code. This will assist with things such as colorizing keywords, finding patterns, matching parentheses and brackets, etc.
77−
78−Below is a complete list of text editors that have support for Hoon [syntax highlighting](https://en.wikipedia.org/wiki/Syntax_highlighting) -- an important tool for any programming language. For each of these editors, you'll need to download the editor and then you'll need to install some additional syntax-highlighter package. The process for adding Hoon support differs for every editor. For most newbie-friendly text editors, this is easily accomplished from within the editor itself, and you'll learn how to do so following a newbie tutorial for that editor.
79−
80−If you are brand new to programming, don't think too much about which editor to use; any of the newbie-friendly options will suit you.
81−
82−### Newbie-friendly text editors
83−
84−These editors are easy to use for first-time coders.
85−
86−#### Atom
87−Atom is free and open-source and runs on all major operating systems. It is available [here](https://atom.io/). A package for Hoon support is maintained by Tlon and may be obtained using the package manager within the editor by searching for `Hoon`.
88−
89−#### Sublime
90−Sublime is closed-source, but may be downloaded for free and there is no enforced time limit for evaluation. It runs on all major operating systems. It is available [here](https://www.sublimetext.com/).
91−
92−#### Visual Studio Code
93−Visual Studio Code is free and open-source and runs on all major operating systems. It is available [here](https://code.visualstudio.com/). Hoon support may be acquired in the Extensions menu within the editor by searching for `Hoon`.
94−
95−### Advanced text editors
96−
97−These text editors have a high learning curve and are only recommended for experienced programmers.
98−
99−#### Emacs
100−
101−Emacs is free and open-source and runs on all major operating systems. It is available [here](https://www.gnu.org/software/emacs/). Hoon support is available with [hoon-mode.el](https://github.com/urbit/hoon-mode.el).
102−
103−#### Vim
104−
105−Vim is free and open-source and runs on all major operating systems. It is available [here](https://www.vim.org/). Hoon support is available with [hoon.vim](https://github.com/urbit/hoon.vim) and is maintained by Tlon.
content/docs/hoon/hoon-school/type-polymorphism.md+81−81
@@ -5,9 +5,9 @@ template = "doc.html"
5aliases = ["/docs/learn/hoon/hoon-tutorial/type-polymorphism/"]
5aliases = ["/docs/learn/hoon/hoon-tutorial/type-polymorphism/"]
6+++
6+++
7
7
8−There are many cases in which one may want to write a function that accepts as input various different types of data. Such a function is said to be [polymorphic](https://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29). ("Polymorphism" = "many forms"; so polymorphic functions accept many forms of data as input.)
8+There are many cases in which one may want to write a function that accepts as input various different types of data. Such a function is said to be [polymorphic](https://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29). ("Polymorphism" = "many forms"; so polymorphic functions accept many forms of data as input.)
9
9
10−One relatively trivial form of polymorphism involves sub-typing. A [gate](/docs/glossary/gate/) whose sample is a raw `noun` can accept any Hoon data structure as input -- it's just that the sample will only be treated as a raw [noun](/docs/glossary/noun/). For example, consider the `copy` gate below:
10+One relatively trivial form of polymorphism involves sub-typing. A [gate](/docs/glossary/gate/) whose sample is a raw `noun` can accept any Hoon data structure as input -- it's just that the sample will only be treated as a raw [noun](/docs/glossary/noun/). For example, consider the `copy` gate below:
11
11
12```
12```
13> =copy |=(a=* [a a])
13> =copy |=(a=* [a a])
@@ -22,39 +22,39 @@ One relatively trivial form of polymorphism involves sub-typing. A [gate](/docs
22[[72 101 108 108 111 33 0] [72 101 108 108 111 33 0]]
22[[72 101 108 108 111 33 0] [72 101 108 108 111 33 0]]
23```
23```
24
24
25−`copy` takes the input, `a`, and returns a cell of `[a a]`. Because every piece of Hoon data is a noun, anything can be taken as input. Every other type in Hoon is a sub-type of `noun`. But the output of `copy` is always going to be just a cell of nouns; the type information of the original input value is not preserved by the gate. Consider the `tape` in the last example: `"Hello!"` was pretty-printed in the dojo as a raw noun, not as a string. So `copy` is a relatively uninteresting polymorphic function.
25+`copy` takes the input, `a`, and returns a cell of `[a a]`. Because every piece of Hoon data is a noun, anything can be taken as input. Every other type in Hoon is a sub-type of `noun`. But the output of `copy` is always going to be just a cell of nouns; the type information of the original input value is not preserved by the gate. Consider the `tape` in the last example: `"Hello!"` was pretty-printed in the dojo as a raw noun, not as a string. So `copy` is a relatively uninteresting polymorphic function.
26
26
27In this lesson we'll go over Hoon's support for more interesting polymorphic functions.
27In this lesson we'll go over Hoon's support for more interesting polymorphic functions.
28
28
29## Polymorphic Properties of Cores
29## Polymorphic Properties of Cores
30
30
31−Hoon supports type polymorphism at the [core](/docs/glossary/core/) level. That is, each core has certain polymorphic properties that are tracked and maintained as metadata by Hoon's type system. (See `+$ type` of `hoon.hoon`.) These properties determine the extent to which a core can be used as an interface for values of various types.
31+Hoon supports type polymorphism at the [core](/docs/glossary/core/) level. That is, each core has certain polymorphic properties that are tracked and maintained as metadata by Hoon's type system. (See `+$ type` of `hoon.hoon`.) These properties determine the extent to which a core can be used as an interface for values of various types.
32
32
33−This is rather vaguely put so far. We can clarify by talking more specifically about the kinds of polymorphism supported in Hoon. There are two kinds of type polymorphism for cores: [genericity](https://en.wikipedia.org/wiki/Generic_programming), to include certain kinds of [parametric polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism); and [variance polymorphism](https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29), which involves making use of special sub-typing rules for cores.
33+This is rather vaguely put so far. We can clarify by talking more specifically about the kinds of polymorphism supported in Hoon. There are two kinds of type polymorphism for cores: [genericity](https://en.wikipedia.org/wiki/Generic_programming), to include certain kinds of [parametric polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism); and [variance polymorphism](https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29), which involves making use of special sub-typing rules for cores.
34
34
35−If you don't understand these very well, that's okay. We'll explain them. Let's begin with the former.
35+If you don't understand these very well, that's okay. We'll explain them. Let's begin with the former.
36
36
37## Dry vs. Wet Cores
37## Dry vs. Wet Cores
38
38
39−To review briefly, a **core** is a pair of `[battery payload]`. The **battery** contains the various [arms](/docs/glossary/arm/) of the core (code), and the **payload** contains all the data needed to evaluate those arms correctly (data). Every arm is evaluated with its parent core as the subject. A **gate** (i.e., a Hoon function) is a core with exactly one arm named `$` and with a [payload](/docs/glossary/payload/) of the form: `[sample context]`. The **sample** is reserved for the function's argument value, and the **context** is any other data needed to evaluate `$` correctly.
39+To review briefly, a **core** is a pair of `[battery payload]`. The **battery** contains the various [arms](/docs/glossary/arm/) of the core (code), and the **payload** contains all the data needed to evaluate those arms correctly (data). Every arm is evaluated with its parent core as the subject. A **gate** (i.e., a Hoon function) is a core with exactly one arm named `$` and with a [payload](/docs/glossary/payload/) of the form: `[sample context]`. The **sample** is reserved for the function's argument value, and the **context** is any other data needed to evaluate `$` correctly.
40
40
41−There are two kinds of cores: **dry** and **wet**. Dry cores, which are more typical, _don't_ make use of **genericity**. Wet cores do. In order to understand generic functions in Hoon, you have to understand the difference between dry and wet cores.
41+There are two kinds of cores: **dry** and **wet**. Dry cores, which are more typical, _don't_ make use of **genericity**. Wet cores do. In order to understand generic functions in Hoon, you have to understand the difference between dry and wet cores.
42
42
43−The cores produced with the `|=`, `|-`, `|%`, and `|_` runes, among others, are all dry. The cores produced with the `|*` and `|@` runes are wet. (`|*` and `|@` are the wet versions of `|=` and `|%`, respectively.)
43+The cores produced with the `|=`, `|-`, `|%`, and `|_` runes, among others, are all dry. The cores produced with the `|*` and `|@` runes are wet. (`|*` and `|@` are the wet versions of `|=` and `|%`, respectively.)
44
44
45−Briefly, the difference between dry and wet cores has to do with how they're treated at compile time, for type inference and type checking. During the type check, the product type of each arm is inferred. For computing a dry arm type, it's assumed that the arm's subject type is of the original parent core. For computing a wet arm type, the parent core type is used, except that the payload value may vary from the original type.
45+Briefly, the difference between dry and wet cores has to do with how they're treated at compile time, for type inference and type checking. During the type check, the product type of each arm is inferred. For computing a dry arm type, it's assumed that the arm's subject type is of the original parent core. For computing a wet arm type, the parent core type is used, except that the payload value may vary from the original type.
46
46
47−Because of this, wet gates can be used as functions that take different input types at different call sites. We'll go over the dry/wet distinction in more detail below and explain why it matters.
47+Because of this, wet gates can be used as functions that take different input types at different call sites. We'll go over the dry/wet distinction in more detail below and explain why it matters.
48
48
49### Dry Cores
49### Dry Cores
50
50
51−A core's payload can change from its original value. In fact, this happens in the typical function call -- the default sample is replaced with an input value. How can we ensure that the core's arms are able to run correctly, that the payload type is still appropriate despite whatever changes it has undergone?
51+A core's payload can change from its original value. In fact, this happens in the typical function call -- the default sample is replaced with an input value. How can we ensure that the core's arms are able to run correctly, that the payload type is still appropriate despite whatever changes it has undergone?
52
52
53−There is a type check for each arm of a dry core, intended to verify that the arm's parent core has a payload of the correct type. In this section we'll describe that type check, starting with typical gate usage.
53+There is a type check for each arm of a dry core, intended to verify that the arm's parent core has a payload of the correct type. In this section we'll describe that type check, starting with typical gate usage.
54
54
55−When the `$` arm of a dry gate is evaluated it takes its parent core -- the dry gate itself -- as the subject, often with a modified sample _value_. But any change in sample _type_ should be conservative; the modified sample value must be of the same type as the default sample value (or possibly a subtype). When the `$` arm is evaluated it should have a subject of a type it knows how to use.
55+When the `$` arm of a dry gate is evaluated it takes its parent core -- the dry gate itself -- as the subject, often with a modified sample _value_. But any change in sample _type_ should be conservative; the modified sample value must be of the same type as the default sample value (or possibly a subtype). When the `$` arm is evaluated it should have a subject of a type it knows how to use.
56
56
57−For illustration, consider the gate created by `add`, a function in the Hoon standard library. The structure of the `add` gate is as follows:
57+For illustration, consider the gate created by `add`, a function in the Hoon standard library. The structure of the `add` gate is as follows:
58
58
59```
59```
60 add
60 add
@@ -64,7 +64,7 @@ For illustration, consider the gate created by `add`, a function in the Hoon sta
64 sample context
64 sample context
65```
65```
66
66
67−The `add` code depends on the fact that there are two [atoms](/docs/glossary/atom/) in the sample: the numbers to be added together. Hence, it is appropriate that only a cell of atoms is permitted for the sample. We can look at the default sample of `add` at address `+6`:
67+The `add` code depends on the fact that there are two [atoms](/docs/glossary/atom/) in the sample: the numbers to be added together. Hence, it is appropriate that only a cell of atoms is permitted for the sample. We can look at the default sample of `add` at address `+6`:
68
68
69```
69```
70> +6:add
70> +6:add
@@ -85,28 +85,28 @@ Any other type of value in the sample results in a `nest-fail` crash:
85nest-fail
85nest-fail
86```
86```
87
87
88−This function call attempts to create a modified copy of the `add` gate, replacing the original sample `[0 0]` with `[12 "hello"]`, then evaluate the `$` arm of this modified core. (We ignore the `a` and `b` faces for now.) But this piece of code failed to compile; the type system knew to reject it.
88+This function call attempts to create a modified copy of the `add` gate, replacing the original sample `[0 0]` with `[12 "hello"]`, then evaluate the `$` arm of this modified core. (We ignore the `a` and `b` faces for now.) But this piece of code failed to compile; the type system knew to reject it.
89
89
90−How does it know? The type system keeps track of two copies of the payload type for each core:
90+How does it know? The type system keeps track of two copies of the payload type for each core:
91
91
92−+ The original payload type, i.e., the type of the payload when the core was first created. In the case of `add`, the original sample type is a cell of atoms, `[@ @]`. This original type information is always preserved, regardless of the argument values used to call `add`.
92+- The original payload type, i.e., the type of the payload when the core was first created. In the case of `add`, the original sample type is a cell of atoms, `[@ @]`. This original type information is always preserved, regardless of the argument values used to call `add`.
93−+ The current payload type, i.e., the type of the payload after any substitutions or other changes have been made. In the last `add` call, `(add 12 "hello")`, the sample would be a cell whose head is an `@ud`, and whose tail is a `tape`.
93+- The current payload type, i.e., the type of the payload after any substitutions or other changes have been made. In the last `add` call, `(add 12 "hello")`, the sample would be a cell whose head is an `@ud`, and whose tail is a `tape`.
94
94
95−The type check at compile time compares these two types, and if the current payload type doesn't nest under the original payload, the compile fails with a `nest-fail` crash. (E.g., a cell of type `[@ud tape]` doesn't nest under `[@ @]`.) Otherwise, the original payload _type_ is used for evaluation, even though the original sample _value_ has been replaced. So the arm of a dry core is guaranteed to run with exactly the same subject type each time it is evaluated.
95+The type check at compile time compares these two types, and if the current payload type doesn't nest under the original payload, the compile fails with a `nest-fail` crash. (E.g., a cell of type `[@ud tape]` doesn't nest under `[@ @]`.) Otherwise, the original payload _type_ is used for evaluation, even though the original sample _value_ has been replaced. So the arm of a dry core is guaranteed to run with exactly the same subject type each time it is evaluated.
96
96
97−The type check for each arm in a dry core can be understood as implementing a version of the ["Liskov substitution principle"](https://en.wikipedia.org/wiki/Liskov_substitution_principle). The arm works for some (originally defined) payload type `P`. Payload type `Q` nests under `P`. Therefore the arm works for `Q` as well, though for type inference purposes the payload is treated as a `P`. The inferred type of the arm is based on the assumption that it's evaluated with a subject type exactly like that of its original parent core -- i.e., whose payload is of type `P`.
97+The type check for each arm in a dry core can be understood as implementing a version of the ["Liskov substitution principle"](https://en.wikipedia.org/wiki/Liskov_substitution_principle). The arm works for some (originally defined) payload type `P`. Payload type `Q` nests under `P`. Therefore the arm works for `Q` as well, though for type inference purposes the payload is treated as a `P`. The inferred type of the arm is based on the assumption that it's evaluated with a subject type exactly like that of its original parent core -- i.e., whose payload is of type `P`.
98
98
99### Wet Cores (Genericity)
99### Wet Cores (Genericity)
100
100
101−The type checking and inference rules for arms are a bit different for wet cores. Whereas the dry arm is understood as having _exactly_ its parent core type for its subject, wet arms can be evaluated with payloads of various types.
101+The type checking and inference rules for arms are a bit different for wet cores. Whereas the dry arm is understood as having _exactly_ its parent core type for its subject, wet arms can be evaluated with payloads of various types.
102
102
103Let's start again with a typical function call.
103Let's start again with a typical function call.
104
104
105−When a function call occurs on a wet arm, the [call site](https://en.wikipedia.org/wiki/Call_site) argument value type is used as the sample type -- not the original parent core sample type. Correspondingly, the inferred type of a wet arm depends, among other things, on the type of the argument value -- i.e., the modified sample value type of the core, not the original sample. Thus, the inferred product type typically varies from one call site to another.
105+When a function call occurs on a wet arm, the [call site](https://en.wikipedia.org/wiki/Call_site) argument value type is used as the sample type -- not the original parent core sample type. Correspondingly, the inferred type of a wet arm depends, among other things, on the type of the argument value -- i.e., the modified sample value type of the core, not the original sample. Thus, the inferred product type typically varies from one call site to another.
106
106
107−The arms of wet cores must be able to handle subjects of various types -- they are interestingly polymorphic in a way that dry cores cannot be. The Hoon code that defines each wet arm must be [generic](https://en.wikipedia.org/wiki/Generic_programming) with respect to the sample type.
107+The arms of wet cores must be able to handle subjects of various types -- they are interestingly polymorphic in a way that dry cores cannot be. The Hoon code that defines each wet arm must be [generic](https://en.wikipedia.org/wiki/Generic_programming) with respect to the sample type.
108
108
109−An example will clarify how wet gates work. Recall the `copy` gate from earlier in the lesson:
109+An example will clarify how wet gates work. Recall the `copy` gate from earlier in the lesson:
110
110
111```
111```
112> =copy |=(a=* [a a])
112> =copy |=(a=* [a a])
@@ -121,7 +121,7 @@ An example will clarify how wet gates work. Recall the `copy` gate from earlier
121[[72 101 108 108 111 33 0] [72 101 108 108 111 33 0]]
121[[72 101 108 108 111 33 0] [72 101 108 108 111 33 0]]
122```
122```
123
123
124−This gate is dry (as are all cores produced with `|=`), and so the inferred type of the product is determined based on the original core sample type. In this case, that's a raw noun, `*`. The dojo pretty-printer therefore has no way of knowing that the product of the last `copy` call should be printed as a pair of `tape`s -- it just sees a pair of nouns. If we want the original type information preserved, we must use a wet gate, which can be produced with `|*`:
124+This gate is dry (as are all cores produced with `|=`), and so the inferred type of the product is determined based on the original core sample type. In this case, that's a raw noun, `*`. The dojo pretty-printer therefore has no way of knowing that the product of the last `copy` call should be printed as a pair of `tape`s -- it just sees a pair of nouns. If we want the original type information preserved, we must use a wet gate, which can be produced with `|*`:
125
125
126```
126```
127> =wet-copy |*(a=* [a a])
127> =wet-copy |*(a=* [a a])
@@ -136,7 +136,7 @@ This gate is dry (as are all cores produced with `|=`), and so the inferred type
136["Hello!" "Hello!"]
136["Hello!" "Hello!"]
137```
137```
138
138
139−We see that the type information about the `tape` literal `"Hello!"` is preserved in the last function call, as desired. The original sample value of `wet-copy` is replaced with `"Hello!"`, and the original sample type is ignored in favor of the new sample type, `tape`. So the inferred arm type is a cell of `tape`s, which the dojo pretty-printer handles appropriately.
139+We see that the type information about the `tape` literal `"Hello!"` is preserved in the last function call, as desired. The original sample value of `wet-copy` is replaced with `"Hello!"`, and the original sample type is ignored in favor of the new sample type, `tape`. So the inferred arm type is a cell of `tape`s, which the dojo pretty-printer handles appropriately.
140
140
141In fact, `wet-copy` can take a Hoon value of any type you like.
141In fact, `wet-copy` can take a Hoon value of any type you like.
142
142
@@ -155,7 +155,7 @@ For another example, consider the following gate that switches the order of the
155[0b1101 0xbeef]
155[0b1101 0xbeef]
156```
156```
157
157
158−Not only does `switch` reverse the order of the values, it also reverses their respective types, as desired. The dry version of switch is not as useful:
158+Not only does `switch` reverse the order of the values, it also reverses their respective types, as desired. The dry version of switch is not as useful:
159
159
160```
160```
161> =dry-switch |=([a=* b=*] [b a])
161> =dry-switch |=([a=* b=*] [b a])
@@ -176,9 +176,9 @@ But `switch` can't take just any input:
176-find.b
176-find.b
177```
177```
178
178
179−It must take a cell, not an atom. So it's certainly possible to write a wet gate that doesn't take all possible input types.
179+It must take a cell, not an atom. So it's certainly possible to write a wet gate that doesn't take all possible input types.
180
180
181−It is good practice to include a cast in all gates, even wet gates. But in many cases the desired output type depends on the input type. How can we cast appropriately? Often we can cast by example, using the input values themselves. For example, we can rewrite `switch` as:
181+It is good practice to include a cast in all gates, even wet gates. But in many cases the desired output type depends on the input type. How can we cast appropriately? Often we can cast by example, using the input values themselves. For example, we can rewrite `switch` as:
182
182
183```
183```
184> =switch |*([a=* b=*] ^+([b a] [b a]))
184> =switch |*([a=* b=*] ^+([b a] [b a]))
@@ -187,7 +187,7 @@ It is good practice to include a cast in all gates, even wet gates. But in many
187[0xbeef "Hello"]
187[0xbeef "Hello"]
188```
188```
189
189
190−As is the case with dry arms, there is a type-check associated with each wet arm. Or, rather, there are potentially many checks for each wet arm, one for each wing in the code that resolves to a wet arm. The product type of that arm is inferred at each call site, using the argument value type given at that site. If the type inference doesn't go through -- e.g., if there is a cast that doesn't succeed relative to the call site argument value -- then the compile will crash with a `nest-fail`. Otherwise the type check goes through with the inferred type of the wet arm at that call site. So the product type of a wet gate can differ from one call site to another, as we saw with `switch` above.
190+As is the case with dry arms, there is a type-check associated with each wet arm. Or, rather, there are potentially many checks for each wet arm, one for each wing in the code that resolves to a wet arm. The product type of that arm is inferred at each call site, using the argument value type given at that site. If the type inference doesn't go through -- e.g., if there is a cast that doesn't succeed relative to the call site argument value -- then the compile will crash with a `nest-fail`. Otherwise the type check goes through with the inferred type of the wet arm at that call site. So the product type of a wet gate can differ from one call site to another, as we saw with `switch` above.
191
191
192### Parametric Polymorphism and `|$`
192### Parametric Polymorphism and `|$`
193
193
@@ -197,10 +197,10 @@ list of molds and produces a new mold. Here we take another look at this rune as
197an implementation of **parametric polymorphism** in Hoon.
197an implementation of **parametric polymorphism** in Hoon.
198
198
199For example, we have `list`s, `tree`s, and `set`s in Hoon, which are each
199For example, we have `list`s, `tree`s, and `set`s in Hoon, which are each
200−defined in `hoon.hoon` as wet gate mold builders. Take a moment to see for
200+defined in `hoon.hoon` as wet gate mold builders. Take a moment to see for
201−yourself. Each `++` arm is followed by `|$` and a list of labels for input
201+yourself. Each `++` arm is followed by `|$` and a list of labels for input
202−types inside brackets `[ ]`. After that subexpression comes another that
202+types inside brackets `[ ]`. After that subexpression comes another that
203−defines a type that is parametrically polymorphic with respect to the input values. For example, here is the definition of `list` from `hoon.hoon`:
203+defines a type that is parametrically polymorphic with respect to the input values. For example, here is the definition of `list` from `hoon.hoon`:
204
204
205```hoon
205```hoon
206++ list
206++ list
@@ -213,9 +213,9 @@ defines a type that is parametrically polymorphic with respect to the input valu
213 $@(~ [i=item t=(list item)])
213 $@(~ [i=item t=(list item)])
214```
214```
215
215
216−The `|$` rune is especially useful for defining [containers](https://en.wikipedia.org/wiki/Container_%28abstract_data_type%29) of various kinds. Indeed, `list`s, `tree`s, and `set`s are all examples of containers. You can have a `(list @)`, a `(list ^)`, a `(list *)`, and so on. Or a `(tree @)`, a `(tree ^)`, a `(tree *)`, etc. And the same for `set`.
216+The `|$` rune is especially useful for defining [containers](https://en.wikipedia.org/wiki/Container_%28abstract_data_type%29) of various kinds. Indeed, `list`s, `tree`s, and `set`s are all examples of containers. You can have a `(list @)`, a `(list ^)`, a `(list *)`, and so on. Or a `(tree @)`, a `(tree ^)`, a `(tree *)`, etc. And the same for `set`.
217
217
218−One nice thing about containers defined by `|$` is that they nest in the expected way. Intuitively a `(list @)` should nest under `(list *)`, because `@` nests under `*`. And so it does:
218+One nice thing about containers defined by `|$` is that they nest in the expected way. Intuitively a `(list @)` should nest under `(list *)`, because `@` nests under `*`. And so it does:
219
219
220```
220```
221> =a `(list @)`~[11 22 33]
221> =a `(list @)`~[11 22 33]
@@ -251,7 +251,7 @@ Let's clear the dojo subject by unbinding the faces we've used up to now in the
251
251
252## Core Variance
252## Core Variance
253
253
254−Let's say you want to write a function that takes a gate as one (or more) of its arguments. It's not hard to imagine useful cases of this. Consider `turn` from the Hoon standard library, which applies an arbitrary function to each item in a list and returns a modified list:
254+Let's say you want to write a function that takes a gate as one (or more) of its arguments. It's not hard to imagine useful cases of this. Consider `turn` from the Hoon standard library, which applies an arbitrary function to each item in a list and returns a modified list:
255
255
256```
256```
257> =b `(list @)`~[2 3 4 5]
257> =b `(list @)`~[2 3 4 5]
@@ -265,9 +265,9 @@ Let's say you want to write a function that takes a gate as one (or more) of its
265=b
265=b
266```
266```
267
267
268−It's quite useful to be able to pass cores as arguments. But let's think about how to write a function that accepts a core as input. How do we define a sample so that it accepts a core?
268+It's quite useful to be able to pass cores as arguments. But let's think about how to write a function that accepts a core as input. How do we define a sample so that it accepts a core?
269
269
270−We _could_ define the sample by example -- i.e., with `$_`, or `_` for short -- using a core. Consider the following, in which `mycore` is the example core and `apply` is function that accepts gates:
270+We _could_ define the sample by example -- i.e., with `$_`, or `_` for short -- using a core. Consider the following, in which `mycore` is the example core and `apply` is function that accepts gates:
271
271
272```
272```
273> =mycore =>([12 13] |=(a=@ +(a)))
273> =mycore =>([12 13] |=(a=@ +(a)))
@@ -284,47 +284,47 @@ We _could_ define the sample by example -- i.e., with `$_`, or `_` for short --
284123
284123
285```
285```
286
286
287−This works, but in fact `apply` is a very brittle function. It can only take as input a core whose payload is exactly like, or a subtype of, the payload of `mycore`:
287+This works, but in fact `apply` is a very brittle function. It can only take as input a core whose payload is exactly like, or a subtype of, the payload of `mycore`:
288
288
289```
289```
290> (apply 15 |=(a=@ (mul 2 a)))
290> (apply 15 |=(a=@ (mul 2 a)))
291nest-fail
291nest-fail
292```
292```
293
293
294−A core created in one place of your code isn't likely to have the same payload as a core produced elsewhere, unless you intentionally define it so that it does. This generally isn't practical, so we need another way to indicate that we want a core as input.
294+A core created in one place of your code isn't likely to have the same payload as a core produced elsewhere, unless you intentionally define it so that it does. This generally isn't practical, so we need another way to indicate that we want a core as input.
295
295
296−Why did the last example crash? To understand this, you need to understand the the different variance properties a core can have. These properties determine the nesting and type inference rules associated with each core.
296+Why did the last example crash? To understand this, you need to understand the the different variance properties a core can have. These properties determine the nesting and type inference rules associated with each core.
297
297
298The basic question to be answered is: when does one core type nest under another?
298The basic question to be answered is: when does one core type nest under another?
299
299
300−The battery nesting rules for dry cores are relatively straightforward, and they're the same for all cores, regardless of variance properties. Let `A` and `B` be two cores. The type of `B` nests under the type of `A` only if two conditions are met: (i) the batteries of `A` and `B` have exactly the same tree shape, and (ii) the product type of each `B` arm nests under the product type of the corresponding `A` arm.
300+The battery nesting rules for dry cores are relatively straightforward, and they're the same for all cores, regardless of variance properties. Let `A` and `B` be two cores. The type of `B` nests under the type of `A` only if two conditions are met: (i) the batteries of `A` and `B` have exactly the same tree shape, and (ii) the product type of each `B` arm nests under the product type of the corresponding `A` arm.
301
301
302−The payload types of `A` and `B` must also be checked. Certain payload nesting rules apply to all cores, if `B` is to nest under `A`: (i) if `A` is wet then `B` must also be wet; (ii) the original payload type of `A` must mutually nest with the current payload type of `A` (i.e., these types nest under each other); and (iii) the current payload type of `B` must nest under the original payload type of `B`.
302+The payload types of `A` and `B` must also be checked. Certain payload nesting rules apply to all cores, if `B` is to nest under `A`: (i) if `A` is wet then `B` must also be wet; (ii) the original payload type of `A` must mutually nest with the current payload type of `A` (i.e., these types nest under each other); and (iii) the current payload type of `B` must nest under the original payload type of `B`.
303
303
304### The Four Kinds of Cores: Gold, Iron, Zinc, and Lead
304### The Four Kinds of Cores: Gold, Iron, Zinc, and Lead
305
305
306But there are different sets of nesting rules for finishing the payload type check, depending on the variance properties of the core.
306But there are different sets of nesting rules for finishing the payload type check, depending on the variance properties of the core.
307
307
308−There are four kinds of cores: **gold** (invariant payload), **iron** (contravariant sample), **zinc** (covariant sample), and **lead** (bivariant sample). Information about the kind of core is tracked by the Hoon type system.
308+There are four kinds of cores: **gold** (invariant payload), **iron** (contravariant sample), **zinc** (covariant sample), and **lead** (bivariant sample). Information about the kind of core is tracked by the Hoon type system.
309
309
310Their nesting rules in brief:
310Their nesting rules in brief:
311
311
312−+ If `A` is a gold core, then core `B` nests under it only if `B` is gold and the payload of `B` doesn't vary in type from the payload of `A`. The payload `B` is **invariant** (i.e., neither co- nor contravariant) relative to the payload of an `A` it nests under. Gold cores have a read-write payload.
312+- If `A` is a gold core, then core `B` nests under it only if `B` is gold and the payload of `B` doesn't vary in type from the payload of `A`. The payload `B` is **invariant** (i.e., neither co- nor contravariant) relative to the payload of an `A` it nests under. Gold cores have a read-write payload.
313−+ If `A` is an iron core, then core `B` nests under it only if `B` is gold or iron and the sample of `A` nests under the sample of `B`. Notice that the nesting direction of the samples is the opposite of the nesting direction of the cores. I.e., the sample types are **contravariant** with respect to the iron core types. Iron cores have a write-only sample and an opaque context. ("Opaque" means neither read nor write.)
313+- If `A` is an iron core, then core `B` nests under it only if `B` is gold or iron and the sample of `A` nests under the sample of `B`. Notice that the nesting direction of the samples is the opposite of the nesting direction of the cores. I.e., the sample types are **contravariant** with respect to the iron core types. Iron cores have a write-only sample and an opaque context. ("Opaque" means neither read nor write.)
314−+ If `A` is a zinc core, then core `B` nests under it only if `B` is gold or zinc and the sample of `B` nests under the sample of `A`. Notice that the nesting direction of the samples is the same as the nesting direction of the cores. I.e., the sample types are **covariant** with respect to the zinc core types. Zinc cores have a read-only sample and an opaque context.
314+- If `A` is a zinc core, then core `B` nests under it only if `B` is gold or zinc and the sample of `B` nests under the sample of `A`. Notice that the nesting direction of the samples is the same as the nesting direction of the cores. I.e., the sample types are **covariant** with respect to the zinc core types. Zinc cores have a read-only sample and an opaque context.
315−+ If `A` is a lead core, then core `B` nests under it without any additional payload check beyond those described in the previous section. It trivially follows that the payload type both co- and contravaries with respect to the lead core types (hence lead cores are **bivariant**). Lead cores have an opaque payload.
315+- If `A` is a lead core, then core `B` nests under it without any additional payload check beyond those described in the previous section. It trivially follows that the payload type both co- and contravaries with respect to the lead core types (hence lead cores are **bivariant**). Lead cores have an opaque payload.
316
316
317Let's go through each kind more carefully.
317Let's go through each kind more carefully.
318
318
319#### Gold Cores (Invariant)
319#### Gold Cores (Invariant)
320
320
321−By default, most cores are gold. This includes the cores produced with the `|%`, `|=`, `|_`, and `|-` runes, among others.
321+By default, most cores are gold. This includes the cores produced with the `|%`, `|=`, `|_`, and `|-` runes, among others.
322
322
323−Assume that `A` is a gold core and that `B` is some other core. The type of `B` nests under the type of `A` only if the original payload types of each mutually nest -- i.e., the original payload type of `A` nests under the original payload type of `B`, and _vice versa_. Furthermore, only gold cores nest under other gold cores; so `B` must be gold to nest under `A`.
323+Assume that `A` is a gold core and that `B` is some other core. The type of `B` nests under the type of `A` only if the original payload types of each mutually nest -- i.e., the original payload type of `A` nests under the original payload type of `B`, and _vice versa_. Furthermore, only gold cores nest under other gold cores; so `B` must be gold to nest under `A`.
324
324
325−These payload nesting rules are the strictest ones for cores. The payload type is neither covariant nor contravariant; when type-checking against a gold core, the target payload cannot vary at all in type. Consequently, it is type-safe to modify every part of the payload: gold cores have a read-write payload.
325+These payload nesting rules are the strictest ones for cores. The payload type is neither covariant nor contravariant; when type-checking against a gold core, the target payload cannot vary at all in type. Consequently, it is type-safe to modify every part of the payload: gold cores have a read-write payload.
326
326
327−Usually it makes sense to cast for a gold core type when you're treating a core as a state machine. The check ensures that the payload, which includes the relevant state, doesn't vary in type. To see state machines that involve casts for gold cores, see Chapter 2 of the Hoon tutorial.
327+Usually it makes sense to cast for a gold core type when you're treating a core as a state machine. The check ensures that the payload, which includes the relevant state, doesn't vary in type. To see state machines that involve casts for gold cores, see Chapter 2 of the Hoon tutorial.
328
328
329Let's look at simpler examples here, using the `^+` rune:
329Let's look at simpler examples here, using the `^+` rune:
330
330
@@ -344,7 +344,7 @@ nest-fail
344nest-fail
344nest-fail
345```
345```
346
346
347−The first cast goes through because the right-hand gold core has the same sample type as the left-hand gold core. The sample types mutually nest. The second cast fails because the right-hand sample type is more specific than the left-hand sample type. (Not all cells, `^`, are pairs of atoms, `[@ @]`.) And the third cast fails because the right-hand sample type is broader than the left-hand sample type. (Not all nouns, `*`, are cells, `^`.)
347+The first cast goes through because the right-hand gold core has the same sample type as the left-hand gold core. The sample types mutually nest. The second cast fails because the right-hand sample type is more specific than the left-hand sample type. (Not all cells, `^`, are pairs of atoms, `[@ @]`.) And the third cast fails because the right-hand sample type is broader than the left-hand sample type. (Not all nouns, `*`, are cells, `^`.)
348
348
349Two more examples:
349Two more examples:
350
350
@@ -356,15 +356,15 @@ Two more examples:
356nest-fail
356nest-fail
357```
357```
358
358
359−In these examples, the `=>` rune is used to give each core a simple context. The context of the left-hand core in each case is a pair of atoms, `[@ @]`. The first cast goes through because the right-hand core also has a pair of atoms as its context. The second cast fails because the right-hand core has the wrong type of context -- three atoms, `[@ @ @]`.
359+In these examples, the `=>` rune is used to give each core a simple context. The context of the left-hand core in each case is a pair of atoms, `[@ @]`. The first cast goes through because the right-hand core also has a pair of atoms as its context. The second cast fails because the right-hand core has the wrong type of context -- three atoms, `[@ @ @]`.
360
360
361#### Iron Cores (Contravariant)
361#### Iron Cores (Contravariant)
362
362
363−Assume that `A` is an iron core and `B` is some other core. The type of `B` nests under the type of `A` only if the original sample type of `A` nests under the original sample type of `B`. That is, `B`'s sample type must be equivalent or more general than the sample type of `A`. Furthermore, `B` must be either iron or gold to nest under `A`.
363+Assume that `A` is an iron core and `B` is some other core. The type of `B` nests under the type of `A` only if the original sample type of `A` nests under the original sample type of `B`. That is, `B`'s sample type must be equivalent or more general than the sample type of `A`. Furthermore, `B` must be either iron or gold to nest under `A`.
364
364
365−The context type of `B` isn't checked at all; and because of the nesting rules it isn't type-safe to do type-inference on the sample of an iron gate. Thus, there are certain restrictions on iron cores that preserve type safety: (i) the context of an iron core is opaque, meaning that it cannot be written-to or read-from; and (ii) the iron core payload is write-only.
365+The context type of `B` isn't checked at all; and because of the nesting rules it isn't type-safe to do type-inference on the sample of an iron gate. Thus, there are certain restrictions on iron cores that preserve type safety: (i) the context of an iron core is opaque, meaning that it cannot be written-to or read-from; and (ii) the iron core payload is write-only.
366
366
367−Iron gates are particularly useful when you want to pass gates (having various payload types) to other gates. We can illustrate this use with a very simple example. Save the following as `gatepass.hoon` in the `gen` directory of your urbit's pier:
367+Iron gates are particularly useful when you want to pass gates (having various payload types) to other gates. We can illustrate this use with a very simple example. Save the following as `gatepass.hoon` in the `gen` directory of your `%base` desk:
368
368
369```hoon
369```hoon
370|= a=_^|(|=(@ 15))
370|= a=_^|(|=(@ 15))
@@ -373,9 +373,9 @@ Iron gates are particularly useful when you want to pass gates (having various p
373(add b 20)
373(add b 20)
374```
374```
375
375
376−This generator is mostly very simple. Everything about it should be clear except possibly the first line.
376+This generator is mostly very simple. Everything about it should be clear except possibly the first line.
377
377
378−The first line defines the sample as an iron gate and gives it the face `a`. The function as a whole is for taking some gate as input, calling it by passing it the value `10`, adding `20` to it, and returning the result. Let's try it out in the dojo:
378+The first line defines the sample as an iron gate and gives it the face `a`. The function as a whole is for taking some gate as input, calling it by passing it the value `10`, adding `20` to it, and returning the result. Let's try it out in the dojo:
379
379
380```
380```
381> +gatepass |=(a=@ +(a))
381> +gatepass |=(a=@ +(a))
@@ -388,16 +388,16 @@ The first line defines the sample as an iron gate and gives it the face `a`. Th
38850
38850
389```
389```
390
390
391−But we still haven't fully explained the first line of the code. What does `_^|(|=(@ 15))` mean? The inside portion is clear enough -- `|=(@ 15)` produces a normal (i.e., gold) gate that takes an atom and returns `15`. The `^|` rune is used to turn gold gates to iron. (Reverse alchemy!) And the `_` character turns that iron gate value into a structure, i.e. a type. So the whole subexpression means, roughly: "the same type as an iron gate whose sample is an atom, `@`, and whose product is another atom, `@`". The context isn't checked at all. This is good, because that allows us to accept gates defined and produced in drastically different environments. Let's try passing a gate with a different context:
391+But we still haven't fully explained the first line of the code. What does `_^|(|=(@ 15))` mean? The inside portion is clear enough -- `|=(@ 15)` produces a normal (i.e., gold) gate that takes an atom and returns `15`. The `^|` rune is used to turn gold gates to iron. (Reverse alchemy!) And the `_` character turns that iron gate value into a structure, i.e. a type. So the whole subexpression means, roughly: "the same type as an iron gate whose sample is an atom, `@`, and whose product is another atom, `@`". The context isn't checked at all. This is good, because that allows us to accept gates defined and produced in drastically different environments. Let's try passing a gate with a different context:
392
392
393```
393```
394> +gatepass =>([22 33] |=(a=@ +(a)))
394> +gatepass =>([22 33] |=(a=@ +(a)))
39531
39531
396```
396```
397
397
398−Yup, it still works. You can't do that with a gold core sample!
398+Yup, it still works. You can't do that with a gold core sample!
399
399
400−There's a simpler way to define an iron sample. Revise the first line of `gatepass.hoon` to the following:
400+There's a simpler way to define an iron sample. Revise the first line of `gatepass.hoon` to the following:
401
401
402```hoon
402```hoon
403|= a=$-(@ @)
403|= a=$-(@ @)
@@ -406,15 +406,15 @@ There's a simpler way to define an iron sample. Revise the first line of `gatep
406(add b 20)
406(add b 20)
407```
407```
408
408
409−If you test it you'll find that the generator behaves the same as it did before the edits. The `$-` rune is used to create an iron gate structure, i.e., an iron gate type. The first expression defines the desired sample type, and the second subexpression defines the gate's desired output type.
409+If you test it you'll find that the generator behaves the same as it did before the edits. The `$-` rune is used to create an iron gate structure, i.e., an iron gate type. The first expression defines the desired sample type, and the second subexpression defines the gate's desired output type.
410
410
411−The sample type of an iron gate is contravariant. This means that, when doing a cast with some iron gate, the desired gate must have either the same sample type or a superset.
411+The sample type of an iron gate is contravariant. This means that, when doing a cast with some iron gate, the desired gate must have either the same sample type or a superset.
412
412
413Why is this a useful nesting rule for passing gates?
413Why is this a useful nesting rule for passing gates?
414
414
415−Let's say you're writing a function `F` that takes as input some gate `G`. Let's also say you want `G` to be able to take as input any **mammal**. The code of `F` is going to pass arbitrary **mammals** to `G`, so that `G` needs to know how to handle all **mammals** correctly. You can't pass `F` a gate that only takes **dogs** as input, because `F` might call it with a **cat**. But `F` can accept a gate that takes all **animals** as input, because a gate that can handle any **animal** can handle **any mammal**.
415+Let's say you're writing a function `F` that takes as input some gate `G`. Let's also say you want `G` to be able to take as input any **mammal**. The code of `F` is going to pass arbitrary **mammals** to `G`, so that `G` needs to know how to handle all **mammals** correctly. You can't pass `F` a gate that only takes **dogs** as input, because `F` might call it with a **cat**. But `F` can accept a gate that takes all **animals** as input, because a gate that can handle any **animal** can handle **any mammal**.
416
416
417−Iron cores are designed precisely with this purpose in mind. The reason that the sample is write-only is that we want to be able to assume, within function `F`, that the sample of `G` is a **mammal**. But that might not be true when `G` is first passed into `F` -- the default value of `G` could be another **animal**, say, a **lizard**. So we restrict looking into the sample of `G` by making the sample write-only. The illusion is maintained and type safety secured.
417+Iron cores are designed precisely with this purpose in mind. The reason that the sample is write-only is that we want to be able to assume, within function `F`, that the sample of `G` is a **mammal**. But that might not be true when `G` is first passed into `F` -- the default value of `G` could be another **animal**, say, a **lizard**. So we restrict looking into the sample of `G` by making the sample write-only. The illusion is maintained and type safety secured.
418
418
419Let's illustrate iron core nesting properties:
419Let's illustrate iron core nesting properties:
420
420
@@ -441,9 +441,9 @@ nest-fail
441
441
442(As before, we use the `^|` rune to turn gold gates iron.)
442(As before, we use the `^|` rune to turn gold gates iron.)
443
443
444−The first cast goes through because the two gates have the same sample type. The second cast fails because the right-hand gate has a more specific sample type than the left-hand gate does. If you're casting for a gate that accepts any cell, `^`, it's because we want to be able to pass any cell to it. A gate that is only designed for pairs of atoms, `[@ @]`, can't handle all such cases, naturally. The third cast goes through because the right-hand gate sample type is broader than the left-hand gate sample type. A gate that can take any noun as its sample, `*`, works just fine if we choose only to pass it cells, `^`.
444+The first cast goes through because the two gates have the same sample type. The second cast fails because the right-hand gate has a more specific sample type than the left-hand gate does. If you're casting for a gate that accepts any cell, `^`, it's because we want to be able to pass any cell to it. A gate that is only designed for pairs of atoms, `[@ @]`, can't handle all such cases, naturally. The third cast goes through because the right-hand gate sample type is broader than the left-hand gate sample type. A gate that can take any noun as its sample, `*`, works just fine if we choose only to pass it cells, `^`.
445
445
446−We mentioned previously that an iron core has a write-only sample and an opaque core. Let's prove it.
446+We mentioned previously that an iron core has a write-only sample and an opaque core. Let's prove it.
447
447
448Let's define a trivial gate with a context of `[g=22 h=44 .]`, convert it to iron with `^|`, and bind it to `iron-gate` in the dojo:
448Let's define a trivial gate with a context of `[g=22 h=44 .]`, convert it to iron with `^|`, and bind it to `iron-gate` in the dojo:
449
449
@@ -457,14 +457,14 @@ Let's define a trivial gate with a context of `[g=22 h=44 .]`, convert it to iro
45733
45733
458```
458```
459
459
460−Not a complicated function, but it serves our purposes. Normally (i.e., with gold cores) we can look at a context value `p` of some gate `q` with a wing expression: `p.q`. Not so with the iron gate:
460+Not a complicated function, but it serves our purposes. Normally (i.e., with gold cores) we can look at a context value `p` of some gate `q` with a wing expression: `p.q`. Not so with the iron gate:
461
461
462```
462```
463> g.iron-gate
463> g.iron-gate
464-find.g.iron-gate
464-find.g.iron-gate
465```
465```
466
466
467−And usually we can look at the sample value using the face given in the gate definition. Not in this case:
467+And usually we can look at the sample value using the face given in the gate definition. Not in this case:
468
468
469```
469```
470> a.iron-gate
470> a.iron-gate
@@ -505,11 +505,11 @@ Let's clear up the dojo subject by unbinding `iron-gate`:
505
505
506Zinc cores are mirror versions of iron cores.
506Zinc cores are mirror versions of iron cores.
507
507
508−Assume that `A` is a zinc core and `B` is some other core. The type of `B` nests under the type of `A` only if the original sample type of `B` nests under the original sample type of `A`. That is, the target core sample type must be equivalent or a subset of the cast core sample type. Furthermore, `B` must be either zinc or gold to nest under `A`.
508+Assume that `A` is a zinc core and `B` is some other core. The type of `B` nests under the type of `A` only if the original sample type of `B` nests under the original sample type of `A`. That is, the target core sample type must be equivalent or a subset of the cast core sample type. Furthermore, `B` must be either zinc or gold to nest under `A`.
509
509
510−As with iron cores, the context of zinc cores is opaque -- they cannot be written-to or read-from. The sample of a zinc core is read-only. That means, among other things, that zinc cores cannot be used for function calls. Function calls in Hoon involve a change to the sample (the default sample is replaced with the argument value), which is disallowed as type-unsafe for zinc cores.
510+As with iron cores, the context of zinc cores is opaque -- they cannot be written-to or read-from. The sample of a zinc core is read-only. That means, among other things, that zinc cores cannot be used for function calls. Function calls in Hoon involve a change to the sample (the default sample is replaced with the argument value), which is disallowed as type-unsafe for zinc cores.
511
511
512−We can illustrate the casting properties of zinc cores with a few examples. The `^&` rune is used to convert gold cores to zinc:
512+We can illustrate the casting properties of zinc cores with a few examples. The `^&` rune is used to convert gold cores to zinc:
513
513
514```
514```
515> ^+(^&(|=(^ 15)) |=(^ 16))
515> ^+(^&(|=(^ 15)) |=(^ 16))
@@ -532,9 +532,9 @@ We can illustrate the casting properties of zinc cores with a few examples. The
532nest-fail
532nest-fail
533```
533```
534
534
535−The first two casts succeed because the right-hand core sample type is either the same or a subset of the left-hand core sample type. The last one fails because the right-hand sample type is a superset.
535+The first two casts succeed because the right-hand core sample type is either the same or a subset of the left-hand core sample type. The last one fails because the right-hand sample type is a superset.
536
536
537−Even though you can't function call a zinc core, the arms of a zinc core can be computed and the sample can be read. Let's test this with a zinc gate of our own:
537+Even though you can't function call a zinc core, the arms of a zinc core can be computed and the sample can be read. Let's test this with a zinc gate of our own:
538
538
539```
539```
540> =zinc-gate ^& |=(a=_22 (add 10 a))
540> =zinc-gate ^& |=(a=_22 (add 10 a))
@@ -557,11 +557,11 @@ Let's clear up the dojo subject again:
557
557
558#### Lead Cores (Bivariant)
558#### Lead Cores (Bivariant)
559
559
560−Lead cores have more permissive nesting rules than either iron or zinc cores. There is no restriction on which payload types nest. That means, among other things, that the payload type of a lead core is both covariant and contravariant ('bivariant').
560+Lead cores have more permissive nesting rules than either iron or zinc cores. There is no restriction on which payload types nest. That means, among other things, that the payload type of a lead core is both covariant and contravariant ('bivariant').
561
561
562−In order to preserve type safety when working with lead cores, a severe restriction is needed. The whole payload of a lead core is opaque -- the payload can neither be written-to or read-from. For this reason, as was the case with zinc cores, lead cores cannot be called as functions.
562+In order to preserve type safety when working with lead cores, a severe restriction is needed. The whole payload of a lead core is opaque -- the payload can neither be written-to or read-from. For this reason, as was the case with zinc cores, lead cores cannot be called as functions.
563
563
564−The arms of a lead core can still be evaluated, however. We can use the `^?` rune to convert a gold, iron, or zinc core to lead:
564+The arms of a lead core can still be evaluated, however. We can use the `^?` rune to convert a gold, iron, or zinc core to lead:
565
565
566```
566```
567> =lead-gate ^? |=(a=_22 (add 10 a))
567> =lead-gate ^? |=(a=_22 (add 10 a))
content/docs/hoon/reference/_index.md+6−3
@@ -36,15 +36,18 @@ The full story on Hoon's type system.
36
36
37A list of aura types for atoms.
37A list of aura types for atoms.
38
38
39−### [Runes](/docs/hoon/reference/rune/)
39+## [Runes](/docs/hoon/reference/rune/)
40
40
41Syntax and semantics for Hoon's rune system.
41Syntax and semantics for Hoon's rune system.
42
42
43−### [Limbs and Wings](/docs/hoon/reference/limbs/)
43+## [Limbs and Wings](/docs/hoon/reference/limbs/)
44
44
45How to find data inside Hoon subjects.
45How to find data inside Hoon subjects.
46
46
47−### [Standard Library](/docs/hoon/reference/stdlib/)
47+## [Standard Library](/docs/hoon/reference/stdlib/)
48
48
49Reference material for the Hoon standard library.
49Reference material for the Hoon standard library.
50
50
51+## [Zuse](/docs/hoon/reference/zuse/)
52+
53+Reference material for the Zuse library.
content/docs/hoon/reference/cheat-sheet.md+3−13
@@ -5,24 +5,14 @@ template = "doc.html"
5aliases = ["docs/reference/cheat-sheet/"]
5aliases = ["docs/reference/cheat-sheet/"]
6+++
6+++
7
7
8−Download the cheat sheet PDF [here](https://storage.googleapis.com/media.urbit.org/docs/hoon-cheat-sheet-2020-07-24.pdf).
8+Download the cheat sheet PDF [here](https://media.urbit.org/docs/hooncard-unbranded-2021-09-12.pdf)
9
9
10We've found it's useful to have a quick reference of Hoon's syntax always at
10We've found it's useful to have a quick reference of Hoon's syntax always at
11−hand. So above is a download link to a Hoon cheatsheet .pdf. It's missing a
11+hand. So above is a download link to a Hoon cheatsheet PDF.
12−few of the literal syntaxes, but it covers the most common ones.
13
12
14−This doesn't list any of the Ford runes, although there is now at least
15−some documentation for those [here](/docs/arvo/ford/ford).
16−
17−The following runes also exist, but are currently undocumented and not listed in
13+The following rune also exists, but is currently undocumented and not listed in
18the cheat sheet:
14the cheat sheet:
19
15
20```
16```
21−!: :: turn on debugging printfs
22−!. :: turn off debugging printfs
23−!; :: using the "type of type", emit the type for an expression
24−!, :: emit AST of expression
25$* :: bunt (irregular form is *)
17$* :: bunt (irregular form is *)
26−^. :: use gate to transform type
27−^& :: zinc (covariant) -- see the docs on advanced types
28```
18```
content/docs/hoon/reference/rune/ket.md+12−3
@@ -63,9 +63,18 @@ Regular: **1-fixed**.
63
63
64##### Discussion
64##### Discussion
65
65
66−A mold is an idempotent gate that is guaranteed to produce a noun of that type. If an input value isn't of the correct type, the bunt value of that type is returned. (See `^*`.)
66+A mold is an idempotent gate that is guaranteed to produce a noun of that type.
67−
67+If an input value isn't of the correct type, the bunt value of that type is
68+returned. (See `^*`.)
69+
70+`^:` is used to produce a gate that is much like a mold, except that instead of
68−`^:` is used to produce a gate that is much like a mold, except that instead of producing a bunt value when the input value is of the wrong type, it crashes.
71+producing a bunt value when the input value is of the wrong type, it crashes.
72+
73+One may expect that `^:(path /foo)` would result in a syntax error since `^:`
74+only takes one child, but instead it will parse as `=< ^ %:(path /foo)`. Since
75+`:` is the irregular syntax for `=<` this is is parsed as "get `^` (i.e. the
76+mold for cells) from a subject of `(path /foo)`", with `:` being the irregular
77+syntax for `=<`.
69
78
70##### Examples
79##### Examples
71
80
content/docs/hoon/reference/rune/mic.md+1−1
@@ -157,7 +157,7 @@ tl;dr -- `;+` converts a `manx` to a `marl`.
157
157
158`;+` is a Sail rune. Sail is a part of Hoon used for creating and operating on nouns that represent XML nodes. With the appropriate rendering pipeline, a Sail document can be used to generate a static website.
158`;+` is a Sail rune. Sail is a part of Hoon used for creating and operating on nouns that represent XML nodes. With the appropriate rendering pipeline, a Sail document can be used to generate a static website.
159
159
160−In Sail a single XML node is represented by a `manx`. A single `<p>` node `manx` can be produced in the following way:
160+In Sail a single XML node is represented by a `manx`. A single <code>&lt;p&gt;</code> node `manx` can be produced in the following way:
161
161
162```
162```
163> ;p: This will be rendered as an XML node.
163> ;p: This will be rendered as an XML node.
content/docs/hoon/reference/rune/tis.md+9−3
@@ -423,11 +423,11 @@ Regular: **running**.
423
423
424### `=*` "tistar"
424### `=*` "tistar"
425
425
426−`[%tstr p=term q=hoon r=hoon]`: define a macro.
426+`[%tstr p=term q=hoon r=hoon]`: define a deferred expression.
427
427
428##### Produces
428##### Produces
429
429
430−`r`, compiled with a subject in which `p` is a macro for `q`.
430+`r`, compiled with a subject in which `p` is a deferred expression for `q`.
431
431
432##### Syntax
432##### Syntax
433
433
@@ -435,7 +435,13 @@ Regular: **3-fixed**.
435
435
436##### Discussion
436##### Discussion
437
437
438−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.
438+`=*` assigns a name to an expression that will be evaluated in each place the
439+name is dereferenced. This allows you to "write" through it to the original
440+subject `axis`. `q` is recorded in the type information of `p`, and `q` is
441+calculated every time you use `p`.
442+
443+This rune has some similarities with macros, and some similarities with aliases,
444+but it is not really either.
439
445
440##### Examples
446##### Examples
441
447
content/docs/hoon/reference/rune/zap.md+1−1
@@ -196,7 +196,7 @@ The syntax difference is that a test for equality takes two subexpressions, and
196##### Produces
196##### Produces
197
197
198`q`, if `p` is greater than or equal to the Hoon kelvin version.
198`q`, if `p` is greater than or equal to the Hoon kelvin version.
199−(Versions count down; the current version is 141.)
199+(Versions count down; the current version is 140.)
200
200
201##### Syntax
201##### Syntax
202
202
content/docs/hoon/reference/stdlib/1a.md+403−284
@@ -4,7 +4,7 @@ weight = 1
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `++add`
7+## `++add`
8
8
9Add
9Add
10
10
@@ -23,41 +23,54 @@ An [`atom`](/docs/glossary/atom).
23#### Source
23#### Source
24
24
25```hoon
25```hoon
26− ++ add
26+++ add
27− ~/ %add
27+ ~/ %add
28− |= [a=@ b=@]
28+ |= [a=@ b=@]
29− ^- @
29+ ^- @
30− ?: =(0 a) b
30+ ?: =(0 a) b
31− $(a (dec a), b +(b))
31+ $(a (dec a), b +(b))
32```
32```
33
33
34#### Examples
34#### Examples
35
35
36```
36```
37− > (add 2 2)
37+> (add 2 2)
38− 4
38+4
39+```
39
40
41+```
40− > (add 1 1.000.000)
42+> (add 1 1.000.000)
41− 1.000.001
43+1.000.001
44+```
42
45
46+```
43− > (add 1.333 (mul 2 2))
47+> (add 1.333 (mul 2 2))
44− 1.337
48+1.337
49+```
45
50
51+```
46− > (add 'a' 4)
52+> (add 'a' 4)
47− 101
53+101
54+```
48
55
56+```
49− > (add 'a' 'b')
57+> (add 'a' 'b')
50− 195
58+195
59+```
51
60
61+```
52− > (add 0xc 0xf)
62+> (add 0xc 0xf)
53− 27
63+27
64+```
54
65
66+```
55− > `@ux`(add 0xc 0xf)
67+> `@ux`(add 0xc 0xf)
56− 0x1b
68+0x1b
57```
69```
58
70
59---
71---
72+
60−### `++dec`
73+## `++dec`
61
74
62Decrement
75Decrement
63
76
@@ -74,41 +87,47 @@ An [`atom`](/docs/glossary/atom).
74#### Source
87#### Source
75
88
76```hoon
89```hoon
77− ++ dec
90+++ dec
78− ~/ %dec
91+ ~/ %dec
79− |= a=@
92+ |= a=@
80− ~| %decrement-underflow
93+ ~_ leaf+"decrement-underflow"
81− ?< =(0 a)
94+ ?< =(0 a)
82− =+ b=0
95+ =+ b=0
83− |- ^- @
96+ |- ^- @
84− ?: =(a +(b)) b
97+ ?: =(a +(b)) b
85− $(b +(b))
98+ $(b +(b))
86```
99```
87
100
88#### Examples
101#### Examples
89
102
90```
103```
91− > (dec 7)
104+> (dec 7)
92− 6
105+6
93−
106+```
94− > (dec 0)
95− ! decrement-underflow
96− ! exit
97
107
108+```
98− > (dec 'b')
109+> (dec 0)
99− 97
110+! decrement-underflow
100− > `@t`(dec 'b')
111+! exit
101− 'a'
112+```
102
113
114+```
103− > (dec 0xc)
115+> (dec 'b')
104− 11
116+97
105− > `@ux`(dec 0xc)
117+> `@t`(dec 'b')
106− 0xb
118+'a'
107```
119```
108
120
121+```
122+> (dec 0xc)
123+11
124+> `@ux`(dec 0xc)
125+0xb
126+```
109
127
110---
128---
129+
111−### `++div`
130+## `++div`
112
131
113Divide
132Divide
114
133
@@ -127,43 +146,52 @@ An [`atom`](/docs/glossary/atom).
127#### Source
146#### Source
128
147
129```hoon
148```hoon
130− ++ div
149+++ div
131− ~/ %div
150+ ~/ %div
132− |: [a=`@`1 b=`@`1]
151+ |: [a=`@`1 b=`@`1]
133− ^- @
152+ ^- @
134− ~_ leaf+"divide-by-zero"
153+ ~_ leaf+"divide-by-zero"
135− ?< =(0 b)
154+ ?< =(0 b)
136− =+ c=0
155+ =+ c=0
137− |-
156+ |-
138− ?: (lth a b) c
157+ ?: (lth a b) c
139− $(a (sub a b), c +(c))
158+ $(a (sub a b), c +(c))
140```
159```
141
160
142#### Examples
161#### Examples
143
162
144```
163```
145− > (div 4 2)
164+> (div 4 2)
146− 2
165+2
166+```
147
167
168+```
148− > (div 17 8)
169+> (div 17 8)
149− 2
170+2
171+```
150
172
173+```
151− > (div 20 30)
174+> (div 20 30)
152− 0
175+0
176+```
153
177
178+```
154− > (div 'ab' 'a')
179+> (div 'ab' 'a')
155− 259
180+259
156− > `@`'ab'
181+> `@`'ab'
157− 25.185
182+25.185
158− > `@`a
183+> `@`a
159− 97
184+97
185+```
160
186
187+```
161− > (div 0x9f 0x29)
188+> (div 0x9f 0x29)
162− 6
189+6
163```
190```
164
191
165---
192---
193+
166−### `++dvr`
194+## `++dvr`
167
195
168Divide with remainder
196Divide with remainder
169
197
@@ -182,38 +210,47 @@ A cell of [`atoms`](/docs/glossary/atom).
182#### Source
210#### Source
183
211
184```hoon
212```hoon
185− ++ dvr
213+++ dvr
186− ~/ %dvr
214+ ~/ %dvr
187− |= [a=@ b=@]
215+ |= [a=@ b=@]
188− ^- [p=@ q=@]
216+ ^- [p=@ q=@]
189− [(div a b) (mod a b)]
217+ [(div a b) (mod a b)]
190```
218```
191
219
192#### Examples
220#### Examples
193
221
194```
222```
195− > (dvr 17 8)
223+> (dvr 17 8)
196− [p=2 q=1]
224+[p=2 q=1]
225+```
197
226
227+```
198− > (dvr 17 6)
228+> (dvr 17 6)
199− [p=2 q=5]
229+[p=2 q=5]
230+```
200
231
232+```
201− > (dvr 18 6)
233+> (dvr 18 6)
202− [p=3 q=0]
234+[p=3 q=0]
235+```
203
236
237+```
204− > (dvr 4 2)
238+> (dvr 4 2)
205− [p=2 q=0]
239+[p=2 q=0]
240+```
206
241
242+```
207− > (dvr 'ab 'a')
243+> (dvr 'ab 'a')
208− [p=259 q=62]
244+[p=259 q=62]
209− > `@`'a'
245+> `@`'a'
210− 97
246+97
211− > `@`'ab'
247+> `@`'ab'
212− 25.185
248+25.185
213```
249```
214
250
215---
251---
252+
216−### `++gte`
253+## `++gte`
217
254
218Greater-than/equal
255Greater-than/equal
219
256
@@ -232,28 +269,33 @@ A flag.
232#### Source
269#### Source
233
270
234```hoon
271```hoon
235− ++ gte
272+++ gte
236− ~/ %gte
273+ ~/ %gte
237− |= [a=@ b=@]
274+ |= [a=@ b=@]
238− ^- ?
275+ ^- ?
239− !(lth a b)
276+ !(lth a b)
240```
277```
241
278
242#### Examples
279#### Examples
243
280
244```
281```
245− > (gte 100 10)
282+> (gte 100 10)
246− %.y
283+%.y
284+```
247
285
286+```
248− > (gte 4 4)
287+> (gte 4 4)
249− %.y
288+%.y
289+```
250
290
291+```
251− > (gte 3 4)
292+> (gte 3 4)
252− %.n
293+%.n
253```
294```
254
295
255---
296---
297+
256−### `++gth`
298+## `++gth`
257
299
258Greater-than
300Greater-than
259
301
@@ -272,29 +314,33 @@ A flag.
272#### Source
314#### Source
273
315
274```hoon
316```hoon
275− ++ gth
317+++ gth
276− ~/ %gth
318+ ~/ %gth
277− |= [a=@ b=@]
319+ |= [a=@ b=@]
278− ^- ?
320+ ^- ?
279− !(lte a b)
321+ !(lte a b)
280```
322```
281
323
282−
283#### Examples
324#### Examples
284
325
285```
326```
286− > (gth 'd' 'c')
327+> (gth 'd' 'c')
287− %.y
328+%.y
329+```
288
330
331+```
289− > (gth ~h1 ~m61)
332+> (gth ~h1 ~m61)
290− %.n
333+%.n
334+```
291
335
336+```
292− > (gth 'steak' 'brisket')
337+> (gth 'steak' 'brisket')
293− %.n
338+%.n
294```
339```
295
340
296---
341---
342+
297−### `++lte`
343+## `++lte`
298
344
299Less-than/equal
345Less-than/equal
300
346
@@ -313,45 +359,56 @@ A flag.
313#### Source
359#### Source
314
360
315```hoon
361```hoon
316− ++ lte
362+++ lte
317− ~/ %lte
363+ ~/ %lte
318− |= [a=@ b=@]
364+ |= [a=@ b=@]
319− |(=(a b) (lth a b))
365+ |(=(a b) (lth a b))
320```
366```
321
367
322#### Examples
368#### Examples
323
369
324```
370```
325− > (lte 4 5)
371+> (lte 4 5)
326− %.y
372+%.y
327−
373+```
328− > (lte 5 4)
329− %.n
330−
331− > (lte 5 5)
332− %.y
333
374
375+```
334− > (lte 0 0)
376+> (lte 5 4)
335− %.y
377+%.n
378+```
336
379
380+```
381+> (lte 5 5)
382+%.y
383+```
337
384
385+```
338− > (lte 'a' 'b')
386+> (lte 0 0)
339− %.y
387+%.y
340− > `@`'a'
341− 97
342− > `@`'b'
388+```
343− 98
344
389
345− > (lte 'abraham' 'bob')
390+```
346− %.n
391+> (lte 'a' 'b')
392+%.y
393+> `@`'a'
394+97
395+> `@`'b'
396+98
397+```
347
398
348− > (lte ~m61 ~h1)
399+```
400+> (lte 'abraham' 'bob')
349− %.n
401+%.n
350```
402```
351
403
404+```
405+> (lte ~m61 ~h1)
406+%.n
407+```
352
408
353---
409---
410+
354−### `++lth`
411+## `++lth`
355
412
356Less-than
413Less-than
357
414
@@ -370,46 +427,57 @@ A flag.
370#### Source
427#### Source
371
428
372```hoon
429```hoon
373− ++ lth
430+++ lth
374− ~/ %lth
431+ ~/ %lth
375− |= [a=@ b=@]
432+ |= [a=@ b=@]
376− ^- ?
433+ ^- ?
377− ?& !=(a b)
434+ ?& !=(a b)
378− |-
435+ |-
379− ?| =(0 a)
436+ ?| =(0 a)
380− ?& !=(0 b)
437+ ?& !=(0 b)
381− $(a (dec a), b (dec b))
438+ $(a (dec a), b (dec b))
382− == == ==
439+ == == ==
383```
440```
384
441
385#### Examples
442#### Examples
386
443
387```
444```
388− > (lth 4 5)
445+> (lth 4 5)
389− %.y
446+%.y
447+```
390
448
449+```
391− > (lth 5 4)
450+> (lth 5 4)
392− %.n
451+%.n
452+```
393
453
454+```
394− > (lth 5 5)
455+> (lth 5 5)
395− %.n
456+%.n
457+```
396
458
459+```
397− > (lth 5 0)
460+> (lth 5 0)
398− %.n
461+%.n
462+```
399
463
464+```
400− > (lth 'a' 'b')
465+> (lth 'a' 'b')
401− %.y
466+%.y
402− > `@`'a'
467+> `@`'a'
403− 97
468+97
404− > `@`'b'
469+> `@`'b'
405− 98
470+98
471+```
406
472
473+```
407− > (lth 'abraham' 'bob')
474+> (lth 'abraham' 'bob')
408− %.n
475+%.n
409```
476```
410
477
411---
478---
479+
412−### `++max`
480+## `++max`
413
481
414Maximum
482Maximum
415
483
@@ -428,44 +496,59 @@ An [`atom`](/docs/glossary/atom).
428#### Source
496#### Source
429
497
430```hoon
498```hoon
431− ++ max
499+++ max
432− ~/ %max
500+ ~/ %max
433− |= [a=@ b=@]
501+ |= [a=@ b=@]
434− ^- @
502+ ^- @
435− ?: (gth a b) a
503+ ?: (gth a b) a
436− b
504+ b
437```
505```
438
506
439#### Examples
507#### Examples
440
508
441```
509```
442− > (max 10 100)
510+> (max 10 100)
443− 100
511+100
512+```
444
513
514+```
445− > (max 10.443 9)
515+> (max 10.443 9)
446− 10.443
516+10.443
517+```
447
518
519+```
448− > (max 1 1)
520+> (max 1 1)
449− 1
521+1
522+```
450
523
524+```
451− > (max 'abraham' 'bob')
525+> (max 'abraham' 'bob')
452− 30.787.873.400.840.801
526+30.787.873.400.840.801
527+```
453
528
529+```
454− > `@t`(max 'abraham' 'bob')
530+> `@t`(max 'abraham' 'bob')
455− 'abraham'
531+'abraham'
532+```
456
533
534+```
457− > `@t`(max 'abraham' 'benjamin')
535+> `@t`(max 'abraham' 'benjamin')
458− 'benjamin'
536+'benjamin'
537+```
459
538
539+```
460− > `@dr`(max ~m6 ~h1)
540+> `@dr`(max ~m6 ~h1)
461− ~h1
541+~h1
542+```
462
543
544+```
463− >`@ux`(max 0xe1 0x1e)
545+>`@ux`(max 0xe1 0x1e)
464− 0xe1
546+0xe1
465```
547```
466
548
467---
549---
550+
468−### `++min`
551+## `++min`
469
552
470Minimum
553Minimum
471
554
@@ -484,42 +567,54 @@ An [`atom`](/docs/glossary/atom).
484#### Source
567#### Source
485
568
486```hoon
569```hoon
487− ++ min
570+++ min
488− ~/ %min
571+ ~/ %min
489− |= [a=@ b=@]
572+ |= [a=@ b=@]
490− ^- @
573+ ^- @
491− ?: (lth a b) a
574+ ?: (lth a b) a
492− b
575+ b
493```
576```
494
577
495#### Examples
578#### Examples
496
579
497```
580```
498− > (min 10 100)
581+> (min 10 100)
499− 10
582+10
500−
583+```
501− > (min 10.443 9)
502− 9
503
584
585+```
504− > (min 1 1)
586+> (min 10.443 9)
505− 1
587+9
588+```
506
589
507− > (min 'abraham' 'bob')
590+```
508− 6.451.042
591+> (min 1 1)
592+1
593+```
509
594
595+```
510− > `@t`(min 'abraham' 'bob')
596+> (min 'abraham' 'bob')
511− 'bob'
597+6.451.042
598+```
512
599
600+```
513− > `@t`(min 'abraham' 'benjamin')
601+> `@t`(min 'abraham' 'bob')
514− 'abraham'
602+'bob'
603+```
515
604
516− > `@dr`(min ~m6 ~h1)
605+```
517− ~m6
606+> `@t`(min 'abraham' 'benjamin')
607+'abraham'
518```
608```
519
609
610+```
611+> `@dr`(min ~m6 ~h1)
612+~m6
613+```
520
614
521---
615---
616+
522−### `++mod`
617+## `++mod`
523
618
524Modulus
619Modulus
525
620
@@ -538,39 +633,48 @@ An [`atom`](/docs/glossary/atom).
538#### Source
633#### Source
539
634
540```hoon
635```hoon
541− ++ mod
636+++ mod
542− ~/ %mod
637+ ~/ %mod
543− |: [a=`@`1 b=`@`1]
638+ |: [a=`@`1 b=`@`1]
544− ^- @
639+ ^- @
545− ?< =(0 b)
640+ ?< =(0 b)
546− (sub a (mul b (div a b)))
641+ (sub a (mul b (div a b)))
547```
642```
548
643
549#### Examples
644#### Examples
550
645
551```
646```
552− > (mod 5 2)
647+> (mod 5 2)
553− 1
648+1
649+```
554
650
651+```
555− > (mod 5 5)
652+> (mod 5 5)
556− 0
653+0
654+```
557
655
656+```
558− > (mod 2 5)
657+> (mod 2 5)
559− 2
658+2
659+```
560
660
661+```
561− > (mod 40 20)
662+> (mod 40 20)
562− 0
663+0
664+```
563
665
666+```
564− > `@`'c'
667+> `@`'c'
565− 99
668+99
566− >`@`'a'
669+>`@`'a'
567− 97
670+97
568− > (mod 'c' 'a')
671+> (mod 'c' 'a')
569− 2
672+2
570```
673```
571
674
572---
675---
676+
573−### `++mul`
677+## `++mul`
574
678
575Multiply
679Multiply
576
680
@@ -589,39 +693,45 @@ An [`atom`](/docs/glossary/atom).
589#### Source
693#### Source
590
694
591```hoon
695```hoon
592− ++ mul
696+++ mul
593− ~/ %mul
697+ ~/ %mul
594− |: [a=`@`1 b=`@`1]
698+ |: [a=`@`1 b=`@`1]
595− ^- @
699+ ^- @
596− =+ c=0
700+ =+ c=0
597− |-
701+ |-
598− ?: =(0 a) c
702+ ?: =(0 a) c
599− $(a (dec a), c (add b c))
703+ $(a (dec a), c (add b c))
600```
704```
601
705
602#### Examples
706#### Examples
603
707
604```
708```
605− > (mul 3 4)
709+> (mul 3 4)
606− 12
710+12
607−
711+```
608− > (mul 0 1)
609− 0
610
712
611− > `@`'a'
713+```
612− 97
613− > `@`'b'
614− 98
615− > (mul 'a' 'b')
714+> (mul 0 1)
616− 9.506
715+0
716+```
617
717
618− >`@ux`(mul 0x1f 0xe)
718+```
619− 0x1b2
719+> `@`'a'
720+97
721+> `@`'b'
722+98
723+> (mul 'a' 'b')
724+9.506
620```
725```
621
726
727+```
728+>`@ux`(mul 0x1f 0xe)
729+0x1b2
730+```
622
731
623---
732---
733+
624−### `++sub`
734+## `++sub`
625
735
626Subtract
736Subtract
627
737
@@ -640,41 +750,50 @@ An [`atom`](/docs/glossary/atom).
640#### Source
750#### Source
641
751
642```hoon
752```hoon
643− ++ sub
753+++ sub
644− ~/ %sub
754+ ~/ %sub
645− |= [a=@ b=@]
755+ |= [a=@ b=@]
646− ~_ leaf+"subtract-underflow"
756+ ~_ leaf+"subtract-underflow"
647− ^- @
757+ ^- @
648− ?: =(0 b) a
758+ ?: =(0 b) a
649− $(a (dec a), b (dec b))
759+ $(a (dec a), b (dec b))
650```
760```
651
761
652−
653#### Examples
762#### Examples
654
763
655```
764```
656− > (sub 10 5)
765+> (sub 10 5)
657− 5
766+5
767+```
658
768
769+```
659− > (sub 243 44)
770+> (sub 243 44)
660− 199
771+199
772+```
661
773
774+```
662− > (sub 5 0)
775+> (sub 5 0)
663− 5
776+5
777+```
664
778
779+```
665− > (sub 0 5)
780+> (sub 0 5)
666− ! subtract-underflow
781+! subtract-underflow
667− ! exit
782+! exit
783+```
668
784
785+```
669− > (sub 'c' 'a')
786+> (sub 'c' 'a')
670− 2
787+2
671− > `@`'c'
788+> `@`'c'
672− 99
789+99
673− > `@`'a'
790+> `@`'a'
674− 97
791+97
792+```
675
793
794+```
676− > (sub 0x1f 0xe)
795+> (sub 0x1f 0xe)
677− 17
796+17
678− > `@ux`(sub 0x1f 0xe)
797+> `@ux`(sub 0x1f 0xe)
679− 0x11
798+0x11
680−```
799+```
content/docs/hoon/reference/stdlib/1b.md+125−89
@@ -7,7 +7,7 @@ template = "doc.html"
7Check out the Nock [explanation](/docs/nock/) for more
7Check out the Nock [explanation](/docs/nock/) for more
8information on the tree-addressing system.
8information on the tree-addressing system.
9
9
10−### `++cap`
10+## `++cap`
11
11
12Tree head
12Tree head
13
13
@@ -15,7 +15,6 @@ Tests whether the tree address `a` is in the head or the tail of a [`noun`](/doc
15Produces the constant [`atom`](/docs/glossary/atom) `%2` if it is within the head (subtree `+2`), or
15Produces the constant [`atom`](/docs/glossary/atom) `%2` if it is within the head (subtree `+2`), or
16the constant [`atom`](/docs/glossary/atom) `%3` if it is within the tail (subtree `+3`).
16the constant [`atom`](/docs/glossary/atom) `%3` if it is within the tail (subtree `+3`).
17
17
18−
19#### Accepts
18#### Accepts
20
19
21`a` is an [`atom`](/docs/glossary/atom).
20`a` is an [`atom`](/docs/glossary/atom).
@@ -27,46 +26,57 @@ A constant [`atom`](/docs/glossary/atom).
27#### Source
26#### Source
28
27
29```hoon
28```hoon
30− ++ cap
29+++ cap
31− ~/ %cap
30+ ~/ %cap
32− |= a=@
31+ |= a=@
33− ^- ?($2 $3)
32+ ^- ?(%2 %3)
34− ?- a
33+ ?- a
35− $2 %2
34+ %2 %2
36− $3 %3
35+ %3 %3
37− ?(%0 %1) !!
36+ ?(%0 %1) !!
38− * $(a (div a 2))
37+ * $(a (div a 2))
39− ==
38+ ==
40```
39```
41
40
42#### Examples
41#### Examples
43
42
44```
43```
45− > (cap 4)
44+> (cap 4)
46− %2
45+%2
46+```
47
47
48+```
48− > (cap 6)
49+> (cap 6)
49− %3
50+%3
51+```
50
52
53+```
51− > (cap (add 10 9))
54+> (cap (add 10 9))
52− %2
55+%2
56+```
53
57
58+```
54− > (cap 1) ::address '1' is in neither the head nor the tail
59+> (cap 1) ::address '1' is in neither the head nor the tail
55− ! exit
60+! exit
61+```
56
62
63+```
57− > (cap 0x40))
64+> (cap 0x40))
58− %2
65+%2
59− > `@`0x40
66+> `@`0x40
60− 64
67+64
68+```
61
69
70+```
62− > (cap 'a')
71+> (cap 'a')
63− %3
72+%3
64− > `@`'a'
73+> `@`'a'
65− 97
74+97
66```
75```
67
76
68---
77---
78+
69−### `++mas`
79+## `++mas`
70
80
71Address within head/tail
81Address within head/tail
72
82
@@ -84,51 +94,66 @@ An [`atom`](/docs/glossary/atom).
84#### Source
94#### Source
85
95
86```hoon
96```hoon
87− ++ mas
97+++ mas
88− ~/ %mas
98+ ~/ %mas
89− |= a=@
99+ |= a=@
90− ^- @
100+ ^- @
91− ?- a
101+ ?- a
92− 1 !!
102+ ?(%2 %3) 1
93− 2 1
103+ ?(%0 %1) !!
94− 3 1
95− * (add (mod a 2) (mul $(a (div a 2)) 2))
104+ * (add (mod a 2) (mul $(a (div a 2)) 2))
96− ==
105+ ==
97```
106```
98
107
99#### Examples
108#### Examples
100
109
101```
110```
102− > (mas 3)
111+> (mas 3)
103− 1
112+1
113+```
104
114
115+```
105− > (mas 4)
116+> (mas 4)
106− 2
117+2
118+```
107
119
120+```
108− > (mas 5)
121+> (mas 5)
109− 3
122+3
110− > (cap 5) ::`(cap a)` computes whether address `a` is in the head or the tail
123+> (cap 5) ::`(cap a)` computes whether address `a` is in the head or the tail
111− %2
124+%2
125+```
112
126
127+```
113− > (mas 7)
128+> (mas 7)
114− 3
129+3
115− > (cap 7)
130+> (cap 7)
116− %3
131+%3
132+```
117
133
134+```
118− > (mas 11)
135+> (mas 11)
119− 7
136+7
137+```
120
138
139+```
121− > (mas (mas 11))
140+> (mas (mas 11))
122− 3
141+3
142+```
123
143
144+```
124− > (cap (mas 6))
145+> (cap (mas 6))
125− %3
146+%3
147+```
126
148
127− > (mas 0)
149+```
128− ! exit ::address `0` is in neither the head nor the tail
150+> (mas 0) ::address `0` is in neither the head nor the tail
151+! exit
152+```
129
153
130− > (mas 1)
154+```
131− ! exit ::address `1` is in neither the head nor the tail
155+> (mas 1) ::address `1` is in neither the head nor the tail
156+! exit
132```
157```
133
158
134#### Discussion
159#### Discussion
@@ -166,7 +191,8 @@ Notice how the old values in the head (subtree `+2`) were not illustrated in
166this case, because `+7` is within the tail (subtree `+3`).
191this case, because `+7` is within the tail (subtree `+3`).
167
192
168---
193---
194+
169−### `++peg`
195+## `++peg`
170
196
171Address within address
197Address within address
172
198
@@ -186,43 +212,54 @@ An [`atom`](/docs/glossary/atom).
186#### Source
212#### Source
187
213
188```hoon
214```hoon
189− ++ peg
215+++ peg
190− ~/ %peg
216+ ~/ %peg
191− |= [a=@ b=@]
217+ |= [a=@ b=@]
192− ?< =(0 a)
218+ ?< =(0 a)
193− ^- @
219+ ^- @
194− ?- b
220+ ?- b
195− $1 a
221+ %1 a
196− $2 (mul a 2)
222+ %2 (mul a 2)
197− $3 +((mul a 2))
223+ %3 +((mul a 2))
198− * (add (mod b 2) (mul $(b (div b 2)) 2))
224+ * (add (mod b 2) (mul $(b (div b 2)) 2))
199− ==
225+ ==
200```
226```
201
227
202#### Examples
228#### Examples
203
229
204```
230```
205− > (peg 4 1)
231+> (peg 4 1)
206− 4
232+4
207−
233+```
208− > (peg 1 4)
209− 4
210
234
235+```
211− > (peg 4 2)
236+> (peg 1 4)
212− 8
237+4
238+```
213
239
240+```
214− > (peg 4 8)
241+> (peg 4 2)
215− 32
242+8
243+```
216
244
245+```
217− > (peg 4 (4 2))
246+> (peg 4 8)
218− 32
247+32
248+```
219
249
250+```
220− > (peg 8 45)
251+> (peg 4 (4 2))
221− 269
252+32
253+```
222
254
223− > (cap (peg 4 2)) ::`(cap a)` computes whether address `a` is in the head or the tail
255+```
224− %2
256+> (peg 8 45)
257+269
258+```
225
259
260+```
261+> (cap (peg 4 2)) ::`(cap a)` computes whether address `a` is in the head or the tail
262+%2
226```
263```
227
264
228#### Discussion
265#### Discussion
@@ -269,5 +306,4 @@ Notice how relative address `+4` is at the same position as absolute address
269 (continues...)
306 (continues...)
270```
307```
271
308
272−
273---
309---
content/docs/hoon/reference/stdlib/1c.md+201−122
@@ -4,7 +4,7 @@ weight = 3
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `$bite`
7+## `+$bite`
8
8
9Atom slice specifier.
9Atom slice specifier.
10
10
@@ -42,7 +42,7 @@ supplied, it defaults to a value of 1.
42 0
42 0
43```
43```
44
44
45−### `$bloq`
45+## `+$bloq`
46
46
47Blocksize
47Blocksize
48
48
@@ -105,33 +105,40 @@ See the [bit arithmetic](/docs/hoon/reference/stdlib/2c) section for operations
105
105
106---
106---
107
107
108−### `++each`
108+## `++each`
109
109
110Mold of fork between two types
110Mold of fork between two types
111
111
112A mold generator. Produces a discriminated fork between two types, defaulting to
112A mold generator. Produces a discriminated fork between two types, defaulting to
113−`a`.
113+`this`.
114
114
115#### Source
115#### Source
116
116
117+```hoon
117− ++ each
118+++ each
118− |*([a=mold b=mold] $%([$| p=b] [$& p=a]))
119+ |$ [this that]
119−
120+ $% [%| p=that]
121+ [%& p=this]
122+ ==
123+```
120
124
121#### Examples
125#### Examples
122
126
123```
127```
124− > ? *(each cord time)
128+> ? *(each cord time)
125− ?({$.y p/@t} {$.n p/@da})
129+ ?([%.y p=@t] [%.n p=@da])
126− [%.y p='']
130+[%.y p='']
131+```
127
132
133+```
128− > ? *(each * tape)
134+> ? *(each * tape)
129− ?({$.y p/*} {$.n p/""})
135+ ?([%.y p=*] [%.n p=""])
130− [%.y p=0]
136+[%.y p=0]
131```
137```
132
138
133---
139---
140+
134−### `++gate`
141+## `++gate`
135
142
136Function
143Function
137
144
@@ -139,7 +146,6 @@ A [`core`](/docs/glossary/core) with one arm, `$`--the empty name--which transfo
139product noun. If used dryly as a type, the subject must have a sample type of
146product noun. If used dryly as a type, the subject must have a sample type of
140`*`.
147`*`.
141
148
142−
143#### Source
149#### Source
144
150
145```hoon
151```hoon
@@ -150,16 +156,23 @@ product noun. If used dryly as a type, the subject must have a sample type of
150#### Examples
156#### Examples
151
157
152```
158```
153− > ? gate
159+> ? gate
154− <1.rdl {* <31.ohr 1.jmk $143>}>
160+ <1.ddq [* <46.hgz 1.pnw %140>]>
155− <1.rdl {* <31.ohr 1.jmk $143>}>
161+<1.ddq [* <46.hgz 1.pnw %140>]>
162+```
156
163
164+```
157− > (`gate`|=(a=* [a 'b']) 1)
165+> (`gate`|=(a=* [a 'b']) 1)
158− [1 98]
166+[1 98]
167+```
159
168
169+```
160− > (`gate`|=(a=@ [a 'b']) 1)
170+> (`gate`|=(a=@ [a 'b']) 1)
171+mint-nice
172+-need.@
173+-have.*
161− ! nest-fail
174+nest-fail
162− ! exit
175+dojo: hoon expression failed
163```
176```
164
177
165#### Discussion
178#### Discussion
@@ -171,43 +184,51 @@ mathematical sense. Any `gate` normalizes to an iron `gate`.
171See also: [`++lift`](/docs/hoon/reference/stdlib/2a#lift), [`++cork`](/docs/hoon/reference/stdlib/2n#cork)
184See also: [`++lift`](/docs/hoon/reference/stdlib/2a#lift), [`++cork`](/docs/hoon/reference/stdlib/2n#cork)
172
185
173---
186---
187+
174−### `++list`
188+## `++list`
175
189
176List
190List
177
191
178A mold generator. Generates a mold of a null-terminated list of a
192A mold generator. Generates a mold of a null-terminated list of a
179homogenous type.
193homogenous type.
180
194
181−
182#### Source
195#### Source
183
196
184```hoon
197```hoon
185− ++ list
198+++ list
186− |*(a=mold $@($~ (lest a)))
199+ |$ [item]
200+ $@(~ [i=item t=(list item)])
187```
201```
188
202
189#### Examples
203#### Examples
190
204
191```
205```
192− > *(list)
206+> *(list)
193− ~
207+~
194−
208+```
195− > `(list @)`"abc"
196− ~[97 98 99]
197
209
210+```
198− > (snag 0 "abc")
211+> `(list @)`"abc"
199− 'a'
212+~[97 98 99]
213+```
200
214
201− > `(list @)`[1 2 'j' ~]
215+```
202− ~[1 2 106]
216+> (snag 0 "abc")
217+'a'
218+```
203
219
204```
220```
221+> `(list @)`[1 2 'j' ~]
222+~[1 2 106]
223+```
224+
205#### Discussion
225#### Discussion
206
226
207See also: [`++turn`](/docs/hoon/reference/stdlib/2b#turn), [`++snag`](/docs/hoon/reference/stdlib/2b#snag)
227See also: [`++turn`](/docs/hoon/reference/stdlib/2b#turn), [`++snag`](/docs/hoon/reference/stdlib/2b#snag)
208
228
209---
229---
230+
210−### `++lone`
231+## `++lone`
211
232
212Face on mold
233Face on mold
213
234
@@ -216,56 +237,68 @@ A mold generator. Puts face of `p` on the passed-in mold.
216#### Source
237#### Source
217
238
218```hoon
239```hoon
219− ++ lone
240+++ lone
220− |*(a=mold [p=a])
241+ |$ [item]
242+ p=item
221```
243```
222
244
223#### Examples
245#### Examples
224
246
225```
247```
226− > ? *cord
248+> ? *cord
227− @t
249+@t
228− ''
250+''
251+```
252+
253+```
229− > ? *(lone cord)
254+> ? *(lone cord)
230− p/@t
255+ p=@t
231− p=''
256+p=''
257+```
258+
259+```
260+> ? *(lone @)
261+ p=@
262+p=0
263+```
232
264
233− > ? *(lone @)
265+```
234− p/@
235− p=0
236− > ? *@
266+> ? *@
237− @
267+ @
238− 0
268+0
239```
269```
240
270
241---
271---
272+
242−### `++pair`
273+## `++pair`
243
274
244Mold of pair of types
275Mold of pair of types
245
276
246A mold generator. Produces a tuple of two of the types passed in.
277A mold generator. Produces a tuple of two of the types passed in.
247
278
248−
249#### Source
279#### Source
250
280
251```hoon
281```hoon
252− ++ pair
282+++ pair
253− |*([a=mold b=mold] [p=a q=b])
283+ |$ [head tail]
284+ [p=head q=tail]
254```
285```
255
286
256#### Examples
287#### Examples
257
288
258```
289```
259− > *(pair ? cord)
290+> *(pair ? cord)
260− [p=%.y q='']
291+[p=%.y q='']
261−
292+```
262− > *(pair tape @)
263− [p="" q=0]
264
293
294+```
295+> *(pair tape @)
296+[p="" q=0]
265```
297```
266
298
267---
299---
300+
268−### `++pole`
301+## `++pole`
269
302
270Faceless [`list`](/docs/hoon/reference/stdlib/1c#list)
303Faceless [`list`](/docs/hoon/reference/stdlib/1c#list)
271
304
@@ -274,24 +307,26 @@ A mold generator. A [`list`](/docs/hoon/reference/stdlib/1c#list) without the fa
274#### Source
307#### Source
275
308
276```hoon
309```hoon
277− ++ pole
310+++ pole
278− |*(a=mold $@($~ [a (pole a)]))
311+ |$ [item]
312+ $@(~ [item (pole item)])
279```
313```
280
314
281−
282#### Examples
315#### Examples
283
316
284```
317```
285− > =/(a "asdf" ?>(?=(^ a) `(lest @tD)`a))
318+> =/(a "asdf" ?>(?=(^ a) `(lest @tD)`a))
286− [i='a' t=[i='s' t=[i='d' t=[i='f' t=~]]]]
319+[i='a' t=[i='s' t=[i='d' t=[i='f' t=~]]]]
287−
288− > `(pole char)`"asdf"
289− ['a' ['s' ['d' ['f' ~]]]]
290```
320```
291
321
322+```
323+> `(pole char)`"asdf"
324+['a' ['s' ['d' ['f' ~]]]]
325+```
292
326
293---
327---
328+
294−### `++qual`
329+## `++qual`
295
330
296Mold of 4-type tuple
331Mold of 4-type tuple
297
332
@@ -300,43 +335,49 @@ A mold generator. Produces a tuple of four of the types passed in.
300#### Source
335#### Source
301
336
302```hoon
337```hoon
303− ++ qual
338+++ qual
304− |* [a=mold b=mold c=mold d=mold]
339+ |$ [first second third fourth]
305− [p=a q=b r=c s=d]
340+ [p=first q=second r=third s=fourth]
306```
341```
307
342
308#### Examples
343#### Examples
309
344
310```
345```
311− > *(qual date time tape cord)
346+> *(qual date time tape cord)
312− [p=[[a=%.y y=0] m=0 t=[d=0 h=0 m=0 s=0 f=~]] q=~292277024401-.1.1 r="" s='']
347+[p=[[a=%.y y=0] m=0 t=[d=0 h=0 m=0 s=0 f=~]] q=~2000.1.1 r="" s='']
348+```
313
349
350+```
314− > *(qual (list @) @u @ud @ux)
351+> *(qual (list @) @u @ud @ux)
315− [p=~ q=0 r=0 s=0x0]
352+[p=~ q=0 r=0 s=0x0]
316```
353```
317
354
318---
355---
356+
319−### `++quip`
357+## `++quip`
320
358
321Mold of pair of [`list`](/docs/hoon/reference/stdlib/1c#list) and type
359Mold of pair of [`list`](/docs/hoon/reference/stdlib/1c#list) and type
322
360
323−A mold generator. Produces a tuple of a [`list`](/docs/hoon/reference/stdlib/1c#list) of `a` and the mold of `b`.
361+A mold generator. Produces a tuple of a [`list`](/docs/hoon/reference/stdlib/1c#list) of `item` and the mold of `state`.
324
362
325#### Source
363#### Source
326
364
327```hoon
365```hoon
328− ++ quip
366+++ quip
329− |*([a=mold b=mold] [(list a) b])
367+ |$ [item state]
368+ [(list item) state]
330```
369```
331
370
332#### Examples
371#### Examples
333
372
334```
373```
335− > *(quip @ _'hi')
374+> *(quip @ _'hi')
336− [~ 'hi']
375+[~ 'hi']
376+```
337
377
378+```
338− > `(quip @ @ux)`[[1 2 3 4 ~] 0x10]
379+> `(quip @ @ux)`[[1 2 3 4 ~] 0x10]
339− [~[1 2 3 4] 0x10]
380+[~[1 2 3 4] 0x10]
340```
381```
341
382
342#### Discussion
383#### Discussion
@@ -345,7 +386,33 @@ A common pattern in Hoon code is to return a `list` of changes, along with a
345new state. You'll often see `quip` used in Gall apps.
386new state. You'll often see `quip` used in Gall apps.
346
387
347---
388---
389+
390+## `++step`
391+
392+Atom size or offset, in [bloq](#bloq)s.
393+
394+#### Source
395+
396+```
397+++ step
398+ _`@u`1
399+```
400+
401+#### Examples
402+
403+```
404+> `step`0
405+0
406+```
407+
408+```
409+> `step`2
410+2
411+```
412+
413+---
414+
348−### `++trap`
415+## `++trap`
349
416
350[`Core`](/docs/glossary/core) with one arm `$`
417[`Core`](/docs/glossary/core) with one arm `$`
351
418
@@ -354,26 +421,31 @@ A trap is a [`core`](/docs/glossary/core) with one arm `$`.
354#### Source
421#### Source
355
422
356```hoon
423```hoon
357− ++ trap
424+++ trap
358− |*(a=mold _|?(*a))
425+ |$ [product]
426+ _|?($:product)
359```
427```
360
428
361#### Examples
429#### Examples
362
430
363```
431```
364− > (*trap)
432+> (*trap)
365− <1?dxy 1.oeg {a/<1|rbb {* <31.ohr 1.jmk $143>}> <31.ohr 1.jmk $143>}>
433+<1?ruo 1.mhl [product=<1|xpg [* * *]> <46.hgz 1.pnw %140>]>
366−
434+```
367− > *(*trap)
368− 0
369
435
370− > (|.(42))
436+```
371− 42
437+> *(*trap)
438+0
372```
439```
373
440
441+```
442+> (|.(42))
443+42
444+```
374
445
375---
446---
447+
376−### `++tree`
448+## `++tree`
377
449
378Tree mold generator
450Tree mold generator
379
451
@@ -383,20 +455,21 @@ left/right sub `tree` of the same type. Pretty-printed with `{}`.
383#### Source
455#### Source
384
456
385```hoon
457```hoon
386− ++ tree
458+++ tree
459+ |$ [node]
387− |*(a=mold $@($~ [n=a l=(tree a) r=(tree a)]))
460+ $@(~ [n=node l=(tree node) r=(tree node)])
388```
461```
389
462
390#### Examples
463#### Examples
391
464
392```
465```
393− > `(tree [@ tape])`[[1 "hi"] [[2 "bye"] ~ ~] ~]
466+> `(tree [@ tape])`[[1 "hi"] [[2 "bye"] ~ ~] ~]
394− {[2 "bye"] [1 "hi"]}
467+{[2 "bye"] [1 "hi"]}
395```
468```
396
469
397−
398---
470---
471+
399−### `++trel`
472+## `++trel`
400
473
401Mold of three types
474Mold of three types
402
475
@@ -405,49 +478,55 @@ A mold generator. A mold of the tuple of the three types passed in.
405#### Source
478#### Source
406
479
407```hoon
480```hoon
408− ++ trel
481+++ trel
409− |*([a=mold b=mold c=mold] [p=a q=b r=c])
482+ |$ [first second third]
483+ [p=first q=second r=third]
410```
484```
411
485
412#### Examples
486#### Examples
413
487
414```
488```
415− > *(trel @ud @t @s)
489+> *(trel @ud @t @s)
416− [p=0 q='' r=--0]
490+[p=0 q='' r=--0]
491+```
417
492
493+```
418− > *(trel cord bloq tape)
494+> *(trel cord bloq tape)
419− [p='' q=0 r=""]
495+[p='' q=0 r=""]
420```
496```
421
497
422---
498---
499+
423−### `++unit`
500+## `++unit`
424
501
425Maybe
502Maybe
426
503
427−A mold generator. A `unit` is either `~` or `[~ u=a]`, where `a` is the
504+A mold generator. A `unit` is either `~` or `[~ u=item]`, where `item` is the
428type that was passed in.
505type that was passed in.
429
506
430−
431#### Source
507#### Source
432
508
433```hoon
509```hoon
434− ++ unit
510+++ unit
435− |*(a=mold $@($~ [$~ u=a]))
511+ |$ [item]
512+ $@(~ [~ u=item])
436```
513```
437
514
438#### Examples
515#### Examples
439
516
440```
517```
441− > ? *(unit time)
518+> ? *(unit time)
442− ?({$~ u/@da} $~)
519+ u(@da)
443− ~
520+~
521+```
444
522
523+```
445− > =a |= a=@
524+> =a |= a=@
446− ^- (unit @)
525+ ^- (unit @)
447− ?~ a ~
526+ ?~ a ~
448− [~ a]
527+ [~ a]
449− > (a 2)
528+> (a 2)
450− [~ u=2]
529+[~ 2]
451```
530```
452
531
453#### Discussion
532#### Discussion
content/docs/hoon/reference/stdlib/2a.md+298−131
@@ -4,7 +4,7 @@ weight = 4
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `++biff`
7+## `++biff`
8
8
9[`Unit`](/docs/hoon/reference/stdlib/1c#unit) as argument
9[`Unit`](/docs/hoon/reference/stdlib/1c#unit) as argument
10
10
@@ -24,25 +24,27 @@ A [`unit`](/docs/hoon/reference/stdlib/1c#unit).
24#### Source
24#### Source
25
25
26```hoon
26```hoon
27− ++ biff
27+++ biff
28− |* [a=(unit) b=$-(* (unit))]
28+ |* [a=(unit) b=$-(* (unit))]
29− ?~ a ~
29+ ?~ a ~
30− (b u.a)
30+ (b u.a)
31```
31```
32
32
33#### Examples
33#### Examples
34
34
35```
35```
36− > (biff (some 5) |=(a=@ (some (add a 2))))
36+> (biff (some 5) |=(a=@ (some (add a 2))))
37− [~ u=7]
37+[~ u=7]
38−
39− > (biff ~ |=(a=@ (some (add a 2))))
40− ~
41```
38```
42
39
40+```
41+> (biff ~ |=(a=@ (some (add a 2))))
42+~
43+```
43
44
44---
45---
46+
45−### `++bind`
47+## `++bind`
46
48
47Non-unit function to [`unit`](/docs/hoon/reference/stdlib/1c#unit), producing [`unit`](/docs/hoon/reference/stdlib/1c#unit)
49Non-unit function to [`unit`](/docs/hoon/reference/stdlib/1c#unit), producing [`unit`](/docs/hoon/reference/stdlib/1c#unit)
48
50
@@ -63,27 +65,28 @@ A [`unit`](/docs/hoon/reference/stdlib/1c#unit).
63#### Source
65#### Source
64
66
65```hoon
67```hoon
66− ++ bind
68+++ bind
67− |* [a=(unit) b=gate]
69+ |* [a=(unit) b=gate]
68− ?~ a ~
70+ ?~ a ~
69− [~ u=(b u.a)]
71+ [~ u=(b u.a)]
70```
72```
71
73
72−
73#### Examples
74#### Examples
74
75
75```
76```
76− > (bind ((unit @) [~ 97]) ,@t)
77+> (bind ((unit @) [~ 97]) ,@t)
77− [~ u='a']
78+[~ u='a']
78−
79− > =a |=(a=@ (add a 1))
80− > (bind ((unit @) [~ 2]) a)
81− [~ u=3]
82```
79```
83
80
81+```
82+> =a |=(a=@ (add a 1))
83+> (bind ((unit @) [~ 2]) a)
84+[~ u=3]
85+```
84
86
85---
87---
88+
86−### `++bond`
89+## `++bond`
87
90
88Replace null
91Replace null
89
92
@@ -103,11 +106,11 @@ Either the product of `a` or the value inside of [`unit`](/docs/hoon/reference/s
103#### Source
106#### Source
104
107
105```hoon
108```hoon
106− ++ bond
109+++ bond
107− |* a=(trap)
110+ |* a=(trap)
108− |* b=(unit)
111+ |* b=(unit)
109− ?~ b $:a
112+ ?~ b $:a
110− u.b
113+ u.b
111```
114```
112
115
113#### Examples
116#### Examples
@@ -117,14 +120,16 @@ Either the product of `a` or the value inside of [`unit`](/docs/hoon/reference/s
117 1.024
120 1.024
118 > ((bond |.((bex 10))) ~)
121 > ((bond |.((bex 10))) ~)
119 1.024
122 1.024
123+```
120
124
125+```
121 > ((bond |.((bex 10))) (slaw %ud '123'))
126 > ((bond |.((bex 10))) (slaw %ud '123'))
122 123
127 123
123```
128```
124
129
125−
126---
130---
131+
127−### `++both`
132+## `++both`
128
133
129Group [`unit`](/docs/hoon/reference/stdlib/1c#unit) values into pair
134Group [`unit`](/docs/hoon/reference/stdlib/1c#unit) values into pair
130
135
@@ -145,31 +150,36 @@ A [`unit`](/docs/hoon/reference/stdlib/1c#unit) of the two initial values.
145#### Source
150#### Source
146
151
147```hoon
152```hoon
148− ++ both
153+++ both
149− |* [a=(unit) b=(unit)]
154+ |* [a=(unit) b=(unit)]
150− ?~ a ~
155+ ?~ a ~
151− ?~ b ~
156+ ?~ b ~
152− [~ u=[u.a u.b]]
157+ [~ u=[u.a u.b]]
153```
158```
154
159
155#### Examples
160#### Examples
156
161
157```
162```
158− > (both (some 1) (some %b))
163+> (both (some 1) (some %b))
159− [~ u=[1 %b]]
164+[~ u=[1 %b]]
165+```
160
166
167+```
161− > (both ~ (some %b))
168+> (both ~ (some %b))
162− ~
169+~
163```
170```
164
171
165---
172---
166−### `++clap`
167
173
174+## `++clap`
175+
168−Apply function to two [`units`](/docs/hoon/reference/stdlib/1c#unit)
176+Combine two [`units`](/docs/hoon/reference/stdlib/1c#unit) with function
169
177
170Applies a binary function `c`--which does not usually accept or produce a
178Applies a binary function `c`--which does not usually accept or produce a
171[`unit`](/docs/hoon/reference/stdlib/1c#unit)-- to the values of two [`units`](/docs/hoon/reference/stdlib/1c#unit), `a` and `b`, producing a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
179[`unit`](/docs/hoon/reference/stdlib/1c#unit)-- to the values of two [`units`](/docs/hoon/reference/stdlib/1c#unit), `a` and `b`, producing a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
172
180
181+If `a` is null, produces `b`. If `b` is null, produces `a`. Otherwise, produces the produce of `c` in a `unit`.
182+
173#### Accepts
183#### Accepts
174
184
175`a` is a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
185`a` is a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
@@ -185,32 +195,82 @@ A [`unit`](/docs/hoon/reference/stdlib/1c#unit).
185#### Source
195#### Source
186
196
187```hoon
197```hoon
188− ++ clap :: combine
198+++ clap
189− |* [a=(unit) b=(unit) c=_|=(^ +<-)]
199+ |* [a=(unit) b=(unit) c=_=>(~ |=(^ +<-))]
190− ?~ a b
200+ ?~ a b
191− ?~ b a
201+ ?~ b a
192− [~ u=(c u.a u.b)]
202+ [~ u=(c u.a u.b)]
193```
203```
194
204
195#### Examples
205#### Examples
196
206
197```
207```
198− > =u ((unit @t) [~ 'a'])
208+> (clap ~ `'b' |=([a=@tD b=@tD] `tape`[a b ~]))
199− > =v ((unit @t) [~ 'b'])
209+[~ u='b']
200− > (clap u v |=([a=@t b=@t] (welp (trip a) (trip b))))
210+```
211+
212+```
213+> (clap `'a' ~ |=([a=@tD b=@tD] `tape`[a b ~]))
214+[~ u='a']
215+```
216+
217+```
218+> (clap `'a' `'b' |=([a=@tD b=@tD] `tape`[a b ~]))
201− [~ u="ab"]
219+[~ u="ab"]
220+```
221+
222+---
223+
224+## `++clef`
225+
226+Compose two [`units`](/docs/hoon/reference/stdlib/1c#unit) with function
227+
228+Applies a binary function `c`--which does not usually accept [`units`](/docs/hoon/reference/stdlib/1c#unit)-- to the values of two [`units`](/docs/hoon/reference/stdlib/1c#unit), `a` and `b`, producing a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
229+
230+If `a` or `b` are null, produces null. Otherwise, produces the produce of `c`.
231+
232+#### Accepts
233+
234+`a` is a `unit`.
235+
236+`b` is a `unit`.
237+
238+`c` is a `gate` that takes a `cell` and produces a `unit`.
239+
240+#### Produces
241+
242+A `unit`.
243+
244+#### Source
245+
246+```hoon
247+++ clef
248+ |* [a=(unit) b=(unit) c=_=>(~ |=(^ `+<-))]
249+ ?~ a ~
250+ ?~ b ~
251+ (c u.a u.b)
252+```
253+
254+#### Examples
202
255
203− > =a ((unit @u) [~ 1])
256+```
204− > =b ((unit @u) [~ 2])
257+> (clef ~ `'b' |=([a=@tD b=@tD] `(unit tape)`[~ [a b ~]]))
205− > =c |=([a=@ b=@] (add a b))
258+~
259+```
206
260
207− > (clap a b c)
261+```
208− [~ 3]
262+> (clef `'a' ~ |=([a=@tD b=@tD] `(unit tape)`[~ [a b ~]]))
263+~
209```
264```
210
265
266+```
267+> (clef `'a' `'b' |=([a=@tD b=@tD] `(unit tape)`[~ [a b ~]]))
268+[~ "ab"]
269+```
211
270
212---
271---
272+
213−### `++drop`
273+## `++drop`
214
274
215[`Unit`](/docs/hoon/reference/stdlib/1c#unit) to list
275[`Unit`](/docs/hoon/reference/stdlib/1c#unit) to list
216
276
@@ -227,27 +287,29 @@ A list.
227#### Source
287#### Source
228
288
229```hoon
289```hoon
230− ++ drop :: enlist
290+++ drop
231− |* a=(unit)
291+ |* a=(unit)
232− ?~ a ~
292+ ?~ a ~
233− [i=u.a t=~]
293+ [i=u.a t=~]
234```
294```
235
295
236#### Examples
296#### Examples
237
297
238```
298```
239− > =a ((unit @) [~ 97])
299+> =a ((unit @) [~ 97])
240− > (drop a)
300+> (drop a)
241− [i=97 t=~]
301+[i=97 t=~]
242−
243− > =a ((unit @) [~])
244− > (drop a)
245− ~
246```
302```
247
303
304+```
305+> =a ((unit @) [~])
306+> (drop a)
307+~
308+```
248
309
249---
310---
311+
250−### `++fall`
312+## `++fall`
251
313
252Give [`unit`](/docs/hoon/reference/stdlib/1c#unit) a default value
314Give [`unit`](/docs/hoon/reference/stdlib/1c#unit) a default value
253
315
@@ -266,32 +328,125 @@ Either a [`noun`](/docs/glossary/noun) `b` or the unwrapped value of [`unit`](/d
266#### Source
328#### Source
267
329
268```hoon
330```hoon
269− ++ fall :: default
331+++ fall
270− |* [a=(unit) b=*]
332+ |* [a=(unit) b=*]
271− ?~(a b u.a)
333+ ?~(a b u.a)
334+```
335+
336+#### Examples
337+
338+```
339+> (fall ~ 'a')
340+'a'
341+> (fall [~ u=0] 'a')
342+0
343+```
344+
345+---
346+
347+## `++flit`
348+
349+Make filter
350+
351+Accepts gate `a` which produces a `?`. Applies `a` to `b`, producing `b` wrapped in a `unit` if true, otherwise produces null.
352+
353+`+flit` is a wet gate that takes `a` and produces a new wet gate that takes `b`.
354+
355+#### Accepts
356+
357+`a` is a `gate` which produces `?`, and is the sample of the outer wet gate.
358+
359+`b` is any `noun`, and is the sample of the inner wet gate.
360+
361+#### Produces
362+
363+`(unit [type])`, where `[type]` is the type of `b`.
364+
365+#### Source
366+
367+```hoon
368+++ flit
369+ |* a=$-(* ?)
370+ |* b=*
371+ ?.((a b) ~ [~ u=b])
372+```
373+
374+#### Examples
375+
376+```
377+> =f (flit |=(=@ud ?:(=(ud 1) %.y %.n)))
378+> (f 1)
379+[~ 1]
380+> (f 2)
381+~
382+```
383+
384+---
385+
386+## `++hunt`
387+
388+First of units
389+
390+Apply binary gate `ord`, which produces a `?`, to units `a` and `b`. Produce `a` if true and `b` if false. If `a` is null, produce `b`. If `b` is null, produce `a`.
391+
392+This allows selecting between two units by some rule.
393+
394+#### Accepts
395+
396+`ord` is a `$-(^ ?)` - a binary gate that produces `?`.
397+
398+`a` is a `unit`.
399+
400+`b` is a `unit`.
401+
402+#### Produces
403+
404+A `unit`.
405+
406+#### Source
407+
408+```hoon
409+++ hunt
410+ |* [ord=$-(^ ?) a=(unit) b=(unit)]
411+ ^- %- unit
412+ $? _?>(?=(^ a) u.a)
413+ _?>(?=(^ b) u.b)
414+ ==
415+ ?~ a b
416+ ?~ b a
417+ ?:((ord u.a u.b) a b)
272```
418```
273
419
274#### Examples
420#### Examples
275
421
276```
422```
277− > (fall ~ 'a')
423+> (hunt gte ~ `20)
278− 'a'
424+[~ 20]
279− > (fall [~ u=0] 'a')
425+```
280− 0
426+
427+```
428+> (hunt gte `10 ~)
429+[~ 10]
430+```
431+
432+```
433+> (hunt gte `10 `20)
434+[~ 20]
281```
435```
282
436
283---
437---
438+
284−### `++lift`
439+## `++lift`
285
440
286Curried bind
441Curried bind
287
442
288−Accepts a `++gate` `a` and produces a function that accepts [`unit`](/docs/hoon/reference/stdlib/1c#unit)
443+Accepts function `a` and produces a function that accepts [`unit`](/docs/hoon/reference/stdlib/1c#unit)
289`b` to which it applies `a`. Used when you want a function that does not accept
444`b` to which it applies `a`. Used when you want a function that does not accept
290or produce a [`unit`](/docs/hoon/reference/stdlib/1c#unit) to both accept and produce a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
445or produce a [`unit`](/docs/hoon/reference/stdlib/1c#unit) to both accept and produce a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
291
446
292#### Accepts
447#### Accepts
293
448
294−`a` is a gate.
449+`a` is a `mold`.
295
450
296`b` is a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
451`b` is a [`unit`](/docs/hoon/reference/stdlib/1c#unit).
297
452
@@ -302,25 +457,27 @@ A [`unit`](/docs/hoon/reference/stdlib/1c#unit).
302#### Source
457#### Source
303
458
304```hoon
459```hoon
305− ++ lift :: lift gate (fmap)
460+++ lift
306− |* a=gate :: flipped
461+ |* a=mold
307− |* b=(unit) :: curried
462+ |* b=(unit)
308− (bind b a) :: bind
463+ (bind b a)
309```
464```
310
465
311#### Examples
466#### Examples
312
467
313```
468```
314− > ((lift dec) `(unit @)`~)
315− ~
316−
317− > ((lift dec) `(unit @)`[~ 20])
469+> ((lift dec) `(unit @)`~)
318− [~ 19]
470+~
319```
471```
320
472
473+```
474+> ((lift dec) `(unit @)`[~ 20])
475+[~ 19]
476+```
321
477
322---
478---
479+
323−### `++mate`
480+## `++mate`
324
481
325Choose
482Choose
326
483
@@ -343,36 +500,40 @@ A [`unit`](/docs/hoon/reference/stdlib/1c#unit) or crash.
343#### Source
500#### Source
344
501
345```hoon
502```hoon
346− ++ mate :: choose
503+++ mate
347− |* [a=(unit) b=(unit)]
504+ |* [a=(unit) b=(unit)]
348− ?~ b a
505+ ?~ b a
349− ?~ a b
506+ ?~ a b
350− ?.(=(u.a u.b) ~|('mate' !!) a)
507+ ?.(=(u.a u.b) ~>(%mean.'mate' !!) a)
351```
508```
352
509
353#### Examples
510#### Examples
354
511
355```
512```
356− > =a ((unit @) [~ 97])
513+> =a ((unit @) [~ 97])
357− > =b ((unit @) [~ 97])
514+> =b ((unit @) [~ 97])
358− > (mate a b)
515+> (mate a b)
359− [~ 97]
360−
361− > =a ((unit @) [~ 97])
516+[~ 97]
362− > =b ((unit @) [~])
517+```
363− > (mate a b)
364− [~ 97]
365
518
519+```
366− > =a ((unit @) [~ 97])
520+> =a ((unit @) [~ 97])
367− > =b ((unit @) [~ 98])
521+> =b ((unit @) [~])
368− > (mate a b)
522+> (mate a b)
369− ! 'mate'
523+[~ 97]
370− ! exit
371```
524```
372
525
526+```
527+> =a ((unit @) [~ 97])
528+> =b ((unit @) [~ 98])
529+> (mate a b)
530+! 'mate'
531+! exit
532+```
373
533
374---
534---
535+
375−### `++need`
536+## `++need`
376
537
377Unwrap [`unit`](/docs/hoon/reference/stdlib/1c#unit)
538Unwrap [`unit`](/docs/hoon/reference/stdlib/1c#unit)
378
539
@@ -389,31 +550,36 @@ Either the unwrapped value of `a` (`u.a`), or crash.
389#### Source
550#### Source
390
551
391```hoon
552```hoon
392− ++ need :: demand
553+++ need
554+ ~/ %need
393− |* a=(unit)
555+ |* a=(unit)
394− ?~ a ~|(%need !!)
556+ ?~ a ~>(%mean.'need' !!)
395− u.a
557+ u.a
396```
558```
397
559
398#### Examples
560#### Examples
399
561
400```
562```
401− > =a ((unit [@t @t]) [~ ['a' 'b']])
563+> =a ((unit [@t @t]) [~ ['a' 'b']])
402− > (need a)
564+> (need a)
403− ['a' 'b']
565+['a' 'b']
404−
566+```
405− > =a ((unit @ud) [~ 17])
406− > (need a)
407− 17
408
567
568+```
409− > =a ((unit @) [~])
569+> =a ((unit @ud) [~ 17])
410− > (need a)
570+> (need a)
411− ! exit
571+17
412```
572```
413
573
574+```
575+> =a ((unit @) [~])
576+> (need a)
577+! exit
578+```
414
579
415---
580---
581+
416−### `++some`
582+## `++some`
417
583
418Wrap value in a [`unit`](/docs/hoon/reference/stdlib/1c#unit)
584Wrap value in a [`unit`](/docs/hoon/reference/stdlib/1c#unit)
419
585
@@ -430,20 +596,21 @@ A [`unit`](/docs/hoon/reference/stdlib/1c#unit).
430#### Source
596#### Source
431
597
432```hoon
598```hoon
433− ++ some :: lift (pure)
599+++ some
434− |* a=*
600+ |* a=*
435− [~ u=a]
601+ [~ u=a]
436```
602```
437
603
438#### Examples
604#### Examples
439
605
440```
606```
441− > (some ['a' 'b'])
607+> (some ['a' 'b'])
442− [~ u=['a' 'b']]
608+[~ u=['a' 'b']]
443−
444− > (some &)
445− [~ u=%.y]
446```
609```
447
610
611+```
612+> (some &)
613+[~ u=%.y]
614+```
448
615
449---
616---
content/docs/hoon/reference/stdlib/2b.md+664−431
@@ -4,7 +4,53 @@ weight = 5
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7+## `++bake`
8+
9+**Note:** This function isn't specifically a list function but is included in section 2b of the standard library so is documented here for completeness.
10+
11+Convert wet gate `f` to a dry gate by specifying argument mold `a`.
12+
13+`+bake` is a wet gate that takes a wet gate and produces a dry gate.
14+
15+#### Accepts
16+
17+`f` is a `gate`.
18+
19+`a` is a `mold`.
20+
21+#### Produces
22+
23+A dry `gate` whose sample type is `a`.
24+
25+#### Source
26+
27+```hoon
28+++ bake
29+ |* [f=gate a=mold]
30+ |= arg=a
31+ (f arg)
32+```
33+
34+#### Examples
35+
36+```
37+> =wet-gate |*(a=* [a a])
38+> (wet-gate 42)
39+[42 42]
40+> (wet-gate ['foo' 'bar'])
41+[['foo' 'bar'] 'foo' 'bar']
42+> =dry-gate (bake wet-gate @ud)
43+> (dry-gate 42)
44+[42 42]
45+> (dry-gate ['foo' 'bar'])
46+-need.@ud
47+-have.[@t @t]
48+nest-fail
49+```
50+
51+---
52+
7−### `++fand`
53+## `++fand`
8
54
9All indices in `list`
55All indices in `list`
10
56
@@ -24,42 +70,48 @@ A `list`.
24#### Source
70#### Source
25
71
26```hoon
72```hoon
27− ++ fand
73+++ fand
28− ~/ %fand
74+ ~/ %fand
29− |= [nedl=(list) hstk=(list)]
75+ |= [nedl=(list) hstk=(list)]
30− =| i=@ud
76+ =| i=@ud
31− =| fnd=(list @ud)
77+ =| fnd=(list @ud)
32− |- ^+ fnd
78+ |- ^+ fnd
33− =+ [n=nedl h=hstk]
79+ =+ [n=nedl h=hstk]
34− |-
80+ |-
35− ?: |(?=($~ n) ?=($~ h))
81+ ?: |(?=(~ n) ?=(~ h))
36− (flop fnd)
82+ (flop fnd)
37− ?: =(i.n i.h)
83+ ?: =(i.n i.h)
38− ?~ t.n
84+ ?~ t.n
39− ^$(i +(i), hstk +.hstk, fnd [i fnd])
85+ ^$(i +(i), hstk +.hstk, fnd [i fnd])
40− $(n t.n, h t.h)
86+ $(n t.n, h t.h)
41− ^$(i +(i), hstk +.hstk)
87+ ^$(i +(i), hstk +.hstk)
42```
88```
43
89
44#### Examples
90#### Examples
45
91
46```
92```
47− > (fand ~[3] ~[1 2 3])
93+> (fand ~[3] ~[1 2 3])
48− ~[2]
94+~[2]
49−
95+```
50− > (fand ~[4] ~[1 2 3])
51− ~
52
96
97+```
53− > (fand ~['a'] "cbabab")
98+> (fand ~[4] ~[1 2 3])
54− ~[2 4]
99+~
100+```
55
101
102+```
56− > (fand "ba" "cbabab")
103+> (fand ~['a'] "cbabab")
57− ~[1 3]
104+~[2 4]
58```
105```
59
106
107+```
108+> (fand "ba" "cbabab")
109+~[1 3]
110+```
60
111
61---
112---
113+
62−### `++find`
114+## `++find`
63
115
64First index in `list`
116First index in `list`
65
117
@@ -79,43 +131,52 @@ The `unit` of an atom.
79#### Source
131#### Source
80
132
81```hoon
133```hoon
82− ++ find
134+++ find
83− ~/ %find
135+ ~/ %find
84− |= [nedl=(list) hstk=(list)]
136+ |= [nedl=(list) hstk=(list)]
85− =| i=@ud
137+ =| i=@ud
86− |- ^- (unit @ud)
138+ |- ^- (unit @ud)
87− =+ [n=nedl h=hstk]
139+ =+ [n=nedl h=hstk]
88− |-
140+ |-
89− ?: |(?=($~ n) ?=($~ h))
141+ ?: |(?=(~ n) ?=(~ h))
90− ~
142+ ~
91− ?: =(i.n i.h)
143+ ?: =(i.n i.h)
92− ?~ t.n
144+ ?~ t.n
93− `i
145+ `i
94− $(n t.n, h t.h)
146+ $(n t.n, h t.h)
95− ^$(i +(i), hstk +.hstk)
147+ ^$(i +(i), hstk +.hstk)
96```
148```
97
149
98#### Examples
150#### Examples
99
151
100```
152```
101− > (find [3]~ ~[1 2 3])
153+> (find [3]~ ~[1 2 3])
102− [~ u=2]
154+[~ u=2]
155+```
103
156
157+```
104− > (find [4]~ ~[1 2 3])
158+> (find [4]~ ~[1 2 3])
105− ~
159+~
160+```
106
161
162+```
107− > (find ['c']~ "cbabab")
163+> (find ['c']~ "cbabab")
108− [~ u=0]
164+[~ u=0]
165+```
109
166
167+```
110− > (find "ab" "cbabab")
168+> (find "ab" "cbabab")
111− [~ u=1]
169+[~ u=2]
170+```
112
171
172+```
113− > (find "bab" "cbabab")
173+> (find "bab" "cbabab")
114− [~ u=2]
174+[~ u=1]
115```
175```
116
176
117---
177---
178+
118−### `++flop`
179+## `++flop`
119
180
120Reverse
181Reverse
121
182
@@ -132,31 +193,33 @@ A `list`.
132#### Source
193#### Source
133
194
134```hoon
195```hoon
135− ++ flop
196+++ flop
136− ~/ %flop
197+ ~/ %flop
137− |* a=(list)
198+ |* a=(list)
138− => .(a (homo a))
199+ => .(a (homo a))
139− ^+ a
200+ ^+ a
140− =+ b=`_a`~
201+ =+ b=`_a`~
141− |-
202+ |-
142− ?~ a b
203+ ?~ a b
143− $(a t.a, b [i.a b])
204+ $(a t.a, b [i.a b])
144```
205```
145
206
146−
147#### Examples
207#### Examples
148
208
149```
209```
150− > =a [1 2 3 ~]
210+> =a [1 2 3 ~]
151− > (flop a)
211+> (flop a)
152− ~[3 2 1]
212+~[3 2 1]
213+```
153
214
215+```
154− > (flop (flop a))
216+> (flop (flop a))
155− ~[1 2 3]
217+~[1 2 3]
156```
218```
157
219
158---
220---
221+
159−### `++gulf`
222+## `++gulf`
160
223
161List from range
224List from range
162
225
@@ -176,24 +239,28 @@ a `list`.
176#### Source
239#### Source
177
240
178```hoon
241```hoon
179− ++ gulf
242+++ gulf
180− |= [a=@ b=@]
243+ |= [a=@ b=@]
244+ ?> (lte a b)
181− ^- (list @)
245+ |- ^- (list @)
182− ?:(=(a +(b)) ~ [a $(a +(a))])
246+ ?:(=(a +(b)) ~ [a $(a +(a))])
183```
247```
184
248
185#### Examples
249#### Examples
186
250
187```
251```
188− > (gulf 1 6)
252+> (gulf 1 6)
189− ~[1 2 3 4 5 6]
253+~[1 2 3 4 5 6]
254+```
190
255
256+```
191− > `(list @t)`(gulf 99 106)
257+> `(list @t)`(gulf 99 106)
192− <|c d e f g h i j|>
258+<|c d e f g h i j|>
193```
259```
194
260
195---
261---
262+
196−### `++homo`
263+## `++homo`
197
264
198Homogenize
265Homogenize
199
266
@@ -212,7 +279,7 @@ a `list`.
212#### Source
279#### Source
213
280
214```hoon
281```hoon
215−++ homo :: homogenize
282+++ homo
216 |* a=(list)
283 |* a=(list)
217 ^+ =< $
284 ^+ =< $
218 |@ ++ $ ?:(*? ~ [i=(snag 0 a) t=$])
285 |@ ++ $ ?:(*? ~ [i=(snag 0 a) t=$])
@@ -223,23 +290,60 @@ a `list`.
223#### Examples
290#### Examples
224
291
225```
292```
226− > lyst
293+> lyst
227− [i=1 t=[i=97 t=[i=2 t=[i=98 t=[i=[~ u=10] t=~]]]]]
294+[i=1 t=[i=97 t=[i=2 t=[i=98 t=[i=[~ u=10] t=~]]]]]
295+> (homo lyst)
296+~[1 97 2 98 [~ u=10]]
297+```
298+
299+```
300+> =a (limo [1 2 3 ~])
301+> a
302+[i=1 t=[i=2 t=[i=3 t=~]]]
303+> (homo a)
304+~[1 2 3]
305+```
306+
307+---
308+
309+## `++into`
310+
311+Insert item at index
312+
313+Accepts a `list` `a`, an atom `b`, and a noun `c`, producing the list of `a` with the item `c` inserted at index `b`.
228
314
229− > (homo lyst)
315+#### Accepts
230− ~[1 97 2 98 [~ u=10]]
316+
317+`a` is a list.
318+
319+`b` is a atom.
320+
321+`c` is a noun.
322+
323+#### Produces
324+
325+the list of `a` with the item `c` inserted at index `b`.
326+
327+#### Source
328+
329+```hoon
330+++ into
331+ ~/ %into
332+ |* [a=(list) b=@ c=*]
333+ ^+ a
334+ (weld (scag b a) [c (slag b a)])
335+```
231
336
232− > =a (limo [1 2 3 ~])
337+#### Examples
233− > a
234− [i=1 t=[i=2 t=[i=3 t=~]]]
235
338
236− > (homo a)
339+```
340+> (into (limo ~[2 3 4]) 1 11)
237− ~[1 2 3]
341+~[2 11 3 4]
238```
342```
239
343
240---
344---
241
345
242−### `++join`
346+## `++join`
243
347
244Constructs a new `list`, placing `sep` between every element of `lit`.
348Constructs a new `list`, placing `sep` between every element of `lit`.
245
349
@@ -256,29 +360,32 @@ a `list`.
256#### Source
360#### Source
257
361
258```hoon
362```hoon
259− ++ join
363+++ join
260− |* [sep=* lit=(list)]
364+ |* [sep=* lit=(list)]
261− =. sep `_?>(?=(^ lit) i.lit)`sep
365+ =. sep `_?>(?=(^ lit) i.lit)`sep
262− ?~ lit ~
366+ ?~ lit ~
263− =| out=(list _?>(?=(^ lit) i.lit))
367+ =| out=(list _?>(?=(^ lit) i.lit))
264− |- ^+ out
368+ |- ^+ out
265− ?~ t.lit
369+ ?~ t.lit
266− (flop [i.lit out])
370+ (flop [i.lit out])
267− $(out [sep i.lit out], lit t.lit)
371+ $(out [sep i.lit out], lit t.lit)
268```
372```
269
373
270#### Examples
374#### Examples
271
375
272```
376```
273− > (join ' ' "hoon")
377+> (join ' ' "hoon")
274− "h o o n"
378+"h o o n"
379+```
275
380
381+```
276− > (join 0 `(list @)`~[1 2 3])
382+> (join 0 `(list @)`~[1 2 3])
277− ~[1 0 2 0 3]
383+~[1 0 2 0 3]
278```
384```
279
385
280---
386---
387+
281−### `++lent`
388+## `++lent`
282
389
283List length
390List length
284
391
@@ -295,29 +402,31 @@ an atom.
295#### Source
402#### Source
296
403
297```hoon
404```hoon
298− ++ lent
405+++ lent
299− ~/ %lent
406+ ~/ %lent
300− |= a=(list)
407+ |= a=(list)
301− ^- @
408+ ^- @
302− =+ b=0
409+ =+ b=0
303− |-
410+ |-
304− ?~ a b
411+ ?~ a b
305− $(a t.a, b +(b))
412+ $(a t.a, b +(b))
306```
413```
307
414
308#### Examples
415#### Examples
309
416
310```
417```
311− > (lent [1 2 3 4 ~]))
418+> (lent [1 2 3 4 ~]))
312− 4
419+4
313−
314− > (lent [1 'a' 2 'b' (some 10) ~])
315− 5
316```
420```
317
421
422+```
423+> (lent [1 'a' 2 'b' (some 10) ~])
424+5
425+```
318
426
319---
427---
428+
320−### `++levy`
429+## `++levy`
321
430
322Logical "and" on list
431Logical "and" on list
323
432
@@ -336,31 +445,32 @@ A boolean.
336#### Source
445#### Source
337
446
338```hoon
447```hoon
339− ++ levy
448+++ levy
340− ~/ %levy :: all of
449+ ~/ %levy
341− |* [a=(list) b=$-(* ?)]
450+ |* [a=(list) b=$-(* ?)]
342− |- ^- ?
451+ |- ^- ?
343− ?~ a &
452+ ?~ a &
344− ?. (b i.a) |
453+ ?. (b i.a) |
345− $(a t.a)
454+ $(a t.a)
346```
455```
347
456
348#### Examples
457#### Examples
349
458
350```
459```
351− > =a |=(a=@ (lte a 1))
460+> =a |=(a=@ (lte a 1))
352− > (levy `(list @)`[0 1 2 1 ~] a)
461+> (levy `(list @)`[0 1 2 1 ~] a)
353− %.n
462+%.n
354−
355− > =a |=(a=@ (lte a 3))
356− > (levy `(list @)`[0 1 2 1 ~] a)
357− %.y
358```
463```
359
464
465+```
466+> =a |=(a=@ (lte a 3))
467+> (levy `(list @)`[0 1 2 1 ~] a)
468+%.y
469+```
360
470
361---
471---
362
472
363−### `++lien`
473+## `++lien`
364
474
365Logical "or" on list
475Logical "or" on list
366
476
@@ -376,30 +486,32 @@ every element of `++list` `a`.
376#### Source
486#### Source
377
487
378```hoon
488```hoon
379− ++ lien
489+++ lien
380− ~/ %lien
490+ ~/ %lien
381− |* [a=(list) b=$-(* ?)]
491+ |* [a=(list) b=$-(* ?)]
382− |- ^- ?
492+ |- ^- ?
383− ?~ a |
493+ ?~ a |
384− ?: (b i.a) &
494+ ?: (b i.a) &
385− $(a t.a)
495+ $(a t.a)
386```
496```
387
497
388#### Examples
498#### Examples
389
499
390```
500```
391− > =a |=(a=@ (gte a 1))
501+> =a |=(a=@ (gte a 1))
392− > (lien `(list @)`[0 1 2 1 ~] a)
502+> (lien `(list @)`[0 1 2 1 ~] a)
393− %.y
503+%.y
394−
395− > =a |=(a=@ (gte a 3))
396− > (lien `(list @)`[0 1 2 1 ~]) a)
397− %.n
398```
504```
399
505
506+```
507+> =a |=(a=@ (gte a 3))
508+> (lien `(list @)`[0 1 2 1 ~]) a)
509+%.n
510+```
400
511
401---
512---
513+
402−### `++limo`
514+## `++limo`
403
515
404List Constructor
516List Constructor
405
517
@@ -416,7 +528,7 @@ A `++list`.
416#### Source
528#### Source
417
529
418```hoon
530```hoon
419−++ limo :: listify
531+++ limo
420 |* a=*
532 |* a=*
421 ^+ =< $
533 ^+ =< $
422 |@ ++ $ ?~(a ~ ?:(*? [i=-.a t=$] $(a +.a)))
534 |@ ++ $ ?~(a ~ ?:(*? [i=-.a t=$] $(a +.a)))
@@ -427,18 +539,18 @@ A `++list`.
427#### Examples
539#### Examples
428
540
429```
541```
430− > (limo [1 2 3 ~])
542+> (limo [1 2 3 ~])
431− [i=1 t=[i=2 t=[i=3 t=~]]]
543+[i=1 t=[i=2 t=[i=3 t=~]]]
432```
544```
433
545
434−
435---
546---
547+
436−### `++murn`
548+## `++murn`
437
549
438Maybe transform
550Maybe transform
439
551
440Passes each member of `list` `a` to gate `b`, which must produce a
552Passes each member of `list` `a` to gate `b`, which must produce a
441−`unit`. Produces a new list with all the results that do not produce
553+`unit`. Produces a new list with all the results that do not produce
442`~`.
554`~`.
443
555
444#### Accepts
556#### Accepts
@@ -454,28 +566,28 @@ A unit.
454#### Source
566#### Source
455
567
456```hoon
568```hoon
457− ++ murn :: maybe transform
569+++ murn
458− ~/ %murn
570+ ~/ %murn
459− |* [a=(list) b=$-(* (unit))]
571+ |* [a=(list) b=$-(* (unit))]
460− |-
572+ => .(a (homo a))
573+ |- ^- (list _?>(?=(^ a) (need (b i.a))))
461− ?~ a ~
574+ ?~ a ~
462− =+ c=(b i.a)
575+ =/ c (b i.a)
463− ?~ c
464− $(a t.a)
576+ ?~ c $(a t.a)
465− [i=u.c t=$(a t.a)]
577+ [+.c $(a t.a)]
466```
578```
467
579
468#### Examples
580#### Examples
469
581
470```
582```
471− > =a |=(a=@ ?.((gte a 2) ~ (some (add a 10))))
583+> =a |=(a=@ ?.((gte a 2) ~ (some (add a 10))))
472− > (murn `(list @)`[0 1 2 3 ~] a)
584+> (murn `(list @)`[0 1 2 3 ~] a)
473− [i=12 t=[i=13 t=~]]
585+[i=12 t=[i=13 t=~]]
474```
586```
475
587
476−
477---
588---
589+
478−### `++oust`
590+## `++oust`
479
591
480Remove
592Remove
481
593
@@ -493,25 +605,27 @@ A `++list`.
493#### Source
605#### Source
494
606
495```hoon
607```hoon
496− ++ oust :: remove
608+++ oust
497− ~/ %oust
609+ ~/ %oust
498− |* [[a=@ b=@] c=(list)]
610+ |* [[a=@ b=@] c=(list)]
499− (weld (scag a c) (slag (add a b) c))
611+ (weld (scag +<-< c) (slag (add +<-< +<->) c))
500```
612```
501
613
502#### Examples
614#### Examples
503
615
504```
616```
505− > (oust [4 5] "good day, urbit!")
617+> (oust [4 5] "good day, urbit!")
506− "good urbit!"
618+"good urbit!"
507−
508− > (oust [2 2] `(list @)`[1 2 3 4 ~])
509− ~[1 2]
510```
619```
511
620
621+```
622+> (oust [2 2] `(list @)`[1 2 3 4 ~])
623+~[1 2]
624+```
512
625
513---
626---
627+
514−### `++reap`
628+## `++reap`
515
629
516Replicate
630Replicate
517
631
@@ -530,30 +644,71 @@ A list.
530#### Source
644#### Source
531
645
532```hoon
646```hoon
533− ++ reap :: replicate
647+++ reap
534− ~/ %reap
648+ ~/ %reap
535− |* [a=@ b=*]
649+ |* [a=@ b=*]
536− |- ^- (list _b)
650+ |- ^- (list _b)
537− ?~ a ~
651+ ?~ a ~
538− [b $(a (dec a))]
652+ [b $(a (dec a))]
539```
653```
540
654
541#### Examples
655#### Examples
542
656
543```
657```
544− > (reap 20 %a)
658+> (reap 20 %a)
545− ~[%a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a]
659+~[%a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a]
660+```
546
661
662+```
547− > (reap 5 ~s1)
663+> (reap 5 ~s1)
548− ~[~s1 ~s1 ~s1 ~s1 ~s1]
664+~[~s1 ~s1 ~s1 ~s1 ~s1]
665+> `@dr`(roll (reap 5 ~s1) add)
666+~s5
667+```
668+
669+---
549
670
550− > `@dr`(roll (reap 5 ~s1) add)
671+## `++rear`
551− ~s5
672+
673+Last item of list
674+
675+Produces the last item in list `a`, crashing if `a` is null.
676+
677+#### Accepts
678+
679+`a` is a `list`.
680+
681+#### Produces
682+
683+The type of the last element in `a`.
684+
685+#### Source
686+
687+```hoon
688+++ rear
689+ ~/ %rear
690+ |* a=(list)
691+ ^- _?>(?=(^ a) i.a)
692+ ?> ?=(^ a)
693+ ?: =(~ t.a) i.a
694+ $(a t.a)
552```
695```
553
696
697+#### Examples
698+
699+```
700+> (rear ~[1 2 3])
701+3
702+```
703+
704+```
705+> (rear ~)
706+dojo: hoon expression failed
707+```
554
708
555---
709---
710+
556−### `++reel`
711+## `++reel`
557
712
558Right fold
713Right fold
559
714
@@ -582,30 +737,31 @@ The accumulator, which is a noun.
582#### Source
737#### Source
583
738
584```hoon
739```hoon
585− ++ reel
740+++ reel
586− ~/ %reel
741+ ~/ %reel
587− |* [a=(list) b=_|=([* *] +<+)]
742+ |* [a=(list) b=_=>(~ |=([* *] +<+))]
588− |- ^+ +<+.b
743+ |- ^+ ,.+<+.b
589− ?~ a
744+ ?~ a
590− +<+.b
745+ +<+.b
591− (b i.a $(a t.a))
746+ (b i.a $(a t.a))
592```
747```
593
748
594#### Examples
749#### Examples
595
750
596```
751```
597− > (reel `(list @)`[1 2 3 4 5 ~] add)
752+> (reel `(list @)`[1 2 3 4 5 ~] add)
598− 15
753+15
599
754
600− > (reel `(list @)`[6 3 1 ~] sub)
755+> (reel `(list @)`[6 3 1 ~] sub)
601− 4
756+4
602
757
603− > (reel `(list @)`[3 6 1 ~] sub)
758+> (reel `(list @)`[3 6 1 ~] sub)
604− ! subtract-underflow
759+! subtract-underflow
605− ! exit
760+! exit
606```
761```
607
762
608`+mul`'s default sample is 1, so calling `+reel` with `+mul` yields the expected behavior:
763`+mul`'s default sample is 1, so calling `+reel` with `+mul` yields the expected behavior:
764+
609```
765```
610> *mul
766> *mul
6111
7671
@@ -613,22 +769,38 @@ The accumulator, which is a noun.
613> (reel `(list @)`~[1 2 3 4] mul)
769> (reel `(list @)`~[1 2 3 4] mul)
61424
77024
615```
771```
772+
616However, if you build a gate that uses `+mul` like so, the sample defaults to 0
773However, if you build a gate that uses `+mul` like so, the sample defaults to 0
617since that is the bunt of `@`:
774since that is the bunt of `@`:
775+
618```
776```
619> (reel `(list @)`~[1 2 3 4] |=([a=@ b=@] (mul a b)))
777> (reel `(list @)`~[1 2 3 4] |=([a=@ b=@] (mul a b)))
6200
7780
621```
779```
780+
622We can fix this with `|:`:
781We can fix this with `|:`:
782+
623```
783```
624> (reel `(list @)`~[1 2 3 4] |:([a=1 b=1] (mul a b)))
784> (reel `(list @)`~[1 2 3 4] |:([a=1 b=1] (mul a b)))
62524
78524
626```
786```
627
787
788+If you check the definition of `+mul`, you'll see that it also utilizes this
789+pattern.
790+
791+We can check explicitly what sequence of operations `+reel` performs like this:
792+```
793+> =f |: [l='e_l' r='e_r']
794+ ^- @t
795+ :((cury cat 3) '(' l '*' r ')')
796+> (reel "abcde" f)
797+'(a*(b*(c*(d*(e*e_r)))))'
798+```
628
799
629
800
630---
801---
802+
631−### `++roll`
803+## `++roll`
632
804
633Left fold
805Left fold
634
806
@@ -657,13 +829,13 @@ The accumulator, which is a noun.
657#### Source
829#### Source
658
830
659```hoon
831```hoon
660− ++ roll :: left fold
832+++ roll
661− ~/ %roll
833+ ~/ %roll
662− |* [a=(list) b=_|=([* *] +<+)]
834+ |* [a=(list) b=_=>(~ |=([* *] +<+))]
663− |- ^+ +<+.b
835+ |- ^+ ,.+<+.b
664− ?~ a
836+ ?~ a
665− +<+.b
837+ +<+.b
666− $(a t.a, b b(+<+ (b i.a +<+.b)))
838+ $(a t.a, b b(+<+ (b i.a +<+.b)))
667```
839```
668
840
669#### Examples
841#### Examples
@@ -681,6 +853,7 @@ q=4
681```
853```
682
854
683`+mul`'s default sample is 1, so calling `+roll` with `+mul` yields the expected behavior:
855`+mul`'s default sample is 1, so calling `+roll` with `+mul` yields the expected behavior:
856+
684```
857```
685> *mul
858> *mul
6861
8591
@@ -688,21 +861,49 @@ q=4
688> (roll `(list @)`~[1 2 3 4] mul)
861> (roll `(list @)`~[1 2 3 4] mul)
68924
86224
690```
863```
864+
691However, if you build a gate that uses `+mul` like so, the sample defaults to 0
865However, if you build a gate that uses `+mul` like so, the sample defaults to 0
692since that is the bunt of `@`:
866since that is the bunt of `@`:
867+
693```
868```
694> (roll `(list @)`~[1 2 3 4] |=([a=@ b=@] (mul a b)))
869> (roll `(list @)`~[1 2 3 4] |=([a=@ b=@] (mul a b)))
6950
8700
696```
871```
872+
697We can fix this with `|:`:
873We can fix this with `|:`:
874+
698```
875```
699> (roll `(list @)`~[1 2 3 4] |:([a=1 b=1] (mul a b)))
876> (roll `(list @)`~[1 2 3 4] |:([a=1 b=1] (mul a b)))
70024
87724
701```
878```
879+If you check the definition of `+mul`, you'll see that it also utilizes this
880+pattern.
702
881
882+We can check explicitly what sequence of operations `+roll` performs like this:
883+```
884+> =f |: [l='e_l' r='e_r']
885+ ^- @t
886+ :((cury cat 3) '(' l '*' r ')')
887+> (roll "abcde" f)
888+'(e*(d*(c*(b*(a*e_r)))))
889+```
890+This is in contrast to what one might expect:
891+```
892+> =foldl
893+ |* [l=(list) f=$-([* *] *)]
894+ ^- f
895+ ?~ l +<-.f
896+ %= $
897+ +<-.f (f +<-.f i.l)
898+ l t.l
899+ ==
900+> (foldl "abcde" f)
901+'(((((e_l*a)*b)*c)*d)*e)'
902+```
703
903
704---
904---
905+
705−### `++scag`
906+## `++scag`
706
907
707Prefix
908Prefix
708
909
@@ -722,27 +923,29 @@ A list of the same type as `b`.
722#### Source
923#### Source
723
924
724```hoon
925```hoon
725− ++ scag :: prefix
926+++ scag
726− ~/ %scag
927+ ~/ %scag
727− |* [a=@ b=(list)]
928+ |* [a=@ b=(list)]
728− |- ^+ b
929+ |- ^+ b
729− ?: |(?=(~ b) =(0 a)) ~
930+ ?: |(?=(~ b) =(0 a)) ~
730− [i.b $(b t.b, a (dec a))]
931+ [i.b $(b t.b, a (dec a))]
731```
932```
732
933
733#### Examples
934#### Examples
734
935
735```
936```
736− > (scag 2 `(list @)`[1 2 3 4 ~])
937+> (scag 2 `(list @)`[1 2 3 4 ~])
737− [i=1 t=~[2]]
738−
739− > (scag 10 `(list @)`[1 2 3 4 ~])
740− [i=1 t=~[2 3 4]]
938+[i=1 t=~[2]]
741```
939```
742
940
941+```
942+> (scag 10 `(list @)`[1 2 3 4 ~])
943+[i=1 t=~[2 3 4]]
944+```
743
945
744---
946---
947+
745−### `++skid`
948+## `++skid`
746
949
747Separate
950Separate
748
951
@@ -765,27 +968,26 @@ A cell of two lists.
765#### Source
968#### Source
766
969
767```hoon
970```hoon
768− ++ skid :: separate
971+++ skid
769− ~/ %skid
972+ ~/ %skid
770− |* [a=(list) b=$-(* ?)]
973+ |* [a=(list) b=$-(* ?)]
771− |- ^+ [p=a q=a]
974+ |- ^+ [p=a q=a]
772− ?~ a [~ ~]
975+ ?~ a [~ ~]
773− =+ c=$(a t.a)
976+ =+ c=$(a t.a)
774− ?:((b i.a) [[i.a p.c] q.c] [p.c [i.a q.c]])
977+ ?:((b i.a) [[i.a p.c] q.c] [p.c [i.a q.c]])
775```
978```
776
979
777−
778#### Examples
980#### Examples
779
981
780```
982```
781− > =a |=(a=@ (gth a 1))
983+> =a |=(a=@ (gth a 1))
782− > (skid `(list @)`[0 1 2 3 ~] a)
984+> (skid `(list @)`[0 1 2 3 ~] a)
783− [p=[i=2 t=~[3]] q=[i=0 t=~[1]]]
985+[p=[i=2 t=~[3]] q=[i=0 t=~[1]]]
784```
986```
785
987
786−
787---
988---
989+
788−### `++skim`
990+## `++skim`
789
991
790Suffix
992Suffix
791
993
@@ -806,25 +1008,26 @@ A list.
806#### Source
1008#### Source
807
1009
808```hoon
1010```hoon
809− ++ skim :: only
1011+++ skim
810− ~/ %skim
1012+ ~/ %skim
811− |* [a=(list) b=$-(* ?)]
1013+ |* [a=(list) b=$-(* ?)]
812− |-
1014+ |-
813− ^+ a
1015+ ^+ a
814− ?~ a ~
1016+ ?~ a ~
815− ?:((b i.a) [i.a $(a t.a)] $(a t.a))
1017+ ?:((b i.a) [i.a $(a t.a)] $(a t.a))
816```
1018```
817
1019
818#### Examples
1020#### Examples
819
1021
820```
1022```
821− > =a |=(a=@ (gth a 1))
1023+> =a |=(a=@ (gth a 1))
822− > (skim `(list @)`[0 1 2 3 ~] a)
1024+> (skim `(list @)`[0 1 2 3 ~] a)
823− [i=2 t=~[3]]
1025+[i=2 t=~[3]]
824```
1026```
825
1027
826---
1028---
1029+
827−### `++skip`
1030+## `++skip`
828
1031
829Except
1032Except
830
1033
@@ -845,26 +1048,26 @@ A list of the same type as `a`.
845#### Source
1048#### Source
846
1049
847```hoon
1050```hoon
848− ++ skip :: except
1051+++ skip
849− ~/ %skip
1052+ ~/ %skip
850− |* [a=(list) b=$-(* ?)]
1053+ |* [a=(list) b=$-(* ?)]
851− |-
1054+ |-
852− ^+ a
1055+ ^+ a
853− ?~ a ~
1056+ ?~ a ~
854− ?:((b i.a) $(a t.a) [i.a $(a t.a)])
1057+ ?:((b i.a) $(a t.a) [i.a $(a t.a)])
855```
1058```
856
1059
857#### Examples
1060#### Examples
858
1061
859```
1062```
860− > =a |=(a=@ (gth a 1))
1063+> =a |=(a=@ (gth a 1))
861− > (skip `(l)`[0 1 2 3 ~]) a)
1064+> (skip `(l)`[0 1 2 3 ~]) a)
862− [i=0 t=[i=1 t=~]]
1065+[i=0 t=[i=1 t=~]]
863```
1066```
864
1067
865−
866---
1068---
1069+
867−### `++slag`
1070+## `++slag`
868
1071
869Suffix
1072Suffix
870
1073
@@ -884,27 +1087,27 @@ A list of the same type as `b`.
884#### Source
1087#### Source
885
1088
886```hoon
1089```hoon
887− ++ slag :: suffix
1090+++ slag
888− ~/ %slag
1091+ ~/ %slag
889− |* [a=@ b=(list)]
1092+ |* [a=@ b=(list)]
890− |- ^+ b
1093+ |- ^+ b
891− ?: =(0 a) b
1094+ ?: =(0 a) b
892− ?~ b ~
1095+ ?~ b ~
893− $(b t.b, a (dec a))
1096+ $(b t.b, a (dec a))
894```
1097```
895
1098
896#### Examples
1099#### Examples
897
1100
898```
1101```
899− > (slag 2 (limo [1 2 3 4 ~]))
1102+> (slag 2 (limo [1 2 3 4 ~]))
900− [i=3 t=[i=4 t=~]]
1103+[i=3 t=[i=4 t=~]]
901− > (slag 1 (limo [1 2 3 4 ~]))
1104+> (slag 1 (limo [1 2 3 4 ~]))
902− [i=2 t=[i=3 t=[i=4 t=~]]]
1105+[i=2 t=[i=3 t=[i=4 t=~]]]
903```
1106```
904
1107
905−
906---
1108---
1109+
907−### `++snag`
1110+## `++snag`
908
1111
909Index
1112Index
910
1113
@@ -924,134 +1127,144 @@ Produces an element of `b`, or crashes if no element exists at that index.
924#### Source
1127#### Source
925
1128
926```hoon
1129```hoon
927− ++ snag :: index
1130+++ snag
928− ~/ %snag
1131+ ~/ %snag
929− |* [a=@ b=(list)]
1132+ |* [a=@ b=(list)]
930− |-
1133+ |- ^+ ?>(?=(^ b) i.b)
931− ?~ b
1134+ ?~ b
932− ~|('snag-fail' !!)
1135+ ~_ leaf+"snag-fail"
1136+ !!
933− ?: =(0 a) i.b
1137+ ?: =(0 a) i.b
934− $(b t.b, a (dec a))
1138+ $(b t.b, a (dec a))
935```
1139```
936
1140
937#### Examples
1141#### Examples
938
1142
939```
1143```
940− > (snag 2 "asdf")
1144+> (snag 2 "asdf")
941− ~~d
1145+'d'
942− > (snag 0 `(list @ud)`~[1 2 3 4])
943− 1
944```
1146```
945
1147
1148+```
1149+> (snag 0 `(list @ud)`~[1 2 3 4])
1150+1
1151+```
946
1152
947---
1153---
948−### `++snoc`
949
1154
950−Append
1155+## `++snap`
951
1156
1157+Replace item at index
1158+
952−Accepts a `++list` `a` and a noun `b`, producing the list of `b` appended to `a`.
1159+Accepts a `list` `a`, an atom `b`, and a noun `c`, producing the list of `a` with the item at index `b` replaced with `c`.
953
1160
954#### Accepts
1161#### Accepts
955
1162
956`a` is a list.
1163`a` is a list.
957
1164
958−`b` is a noun.
1165+`b` is a atom.
1166+
1167+`c` is a noun.
959
1168
960#### Produces
1169#### Produces
961
1170
962−Produces a list of `b` appended to `a`.
1171+the list of `a` with the item at index `b` replaced with `c`.
963
1172
964#### Source
1173#### Source
965
1174
966```hoon
1175```hoon
967− ++ snoc
1176+++ snap
1177+ ~/ %snap
968− |* [a/(list) b/*]
1178+ |* [a=(list) b=@ c=*]
1179+ ^+ a
969− (weld a ^+(a [b]~))
1180+ (weld (scag b a) [c (slag +(b) a)])
970```
1181```
971
1182
972#### Examples
1183#### Examples
973
1184
974```
1185```
975− > `tape`(zing (snoc `(list tape)`~["a" "bc" "def"] "g"))
1186+> (snap (limo ~[2 3 4]) 1 11)
976− "abcdefg"
977− > (snoc `(list @ud)`~[1 2 3] 4)
978− ~[1 2 3 4]
1187+~[2 11 4]
979```
1188```
980
1189
981---
1190---
982−### `++snap`
983
1191
984−Replace item at index
1192+## `++snip`
985
1193
986−Accepts a `list` `a`, an atom `b`, and a noun `c`, producing the list of `a` with the item at index `b` replaced with `c`.
1194+Drop tail off list
987
1195
988−#### Accepts
1196+Removes the last element from list `a`.
989
1197
990−`a` is a list.
1198+#### Accepts
991−
992−`b` is a atom.
993−
994−`c` is a noun.
995
1199
1200+`a` is a `list`.
996
1201
997#### Produces
1202#### Produces
998
1203
999−the list of `a` with the item at index `b` replaced with `c`.
1204+A `list`.
1000
1205
1001#### Source
1206#### Source
1002
1207
1003```hoon
1208```hoon
1004− ++ snap
1209+++ snip
1210+ ~/ %snip
1005− |* [a/(list) b/@ c/*]
1211+ |* a=(list)
1006− ^+ a
1212+ ^+ a
1007− (weld (scag b a) [c (slag +(b) a)])
1213+ ?~ a ~
1214+ ?: =(~ t.a) ~
1215+ [i.a $(a t.a)]
1008```
1216```
1009
1217
1010#### Examples
1218#### Examples
1011
1219
1012```
1220```
1013− > (snap (limo ~[2 3 4]) 1 11)
1221+> `tape`(snip "foobar")
1014− ~[2 11 4]
1222+"fooba"
1223+```
1224+
1225+```
1226+> (snip ~)
1227+~
1015```
1228```
1016
1229
1017---
1230---
1018−### `++into`
1019
1231
1020−Insert item at index
1232+## `++snoc`
1021
1233
1234+Append
1235+
1022−Accepts a `list` `a`, an atom `b`, and a noun `c`, producing the list of `a` with the item `c` inserted at index `b`.
1236+Accepts a `++list` `a` and a noun `b`, producing the list of `b` appended to `a`.
1023
1237
1024#### Accepts
1238#### Accepts
1025
1239
1026`a` is a list.
1240`a` is a list.
1027
1241
1028−`b` is a atom.
1242+`b` is a noun.
1029−
1030−`c` is a noun.
1031−
1032
1243
1033#### Produces
1244#### Produces
1034
1245
1035−the list of `a` with the item `c` inserted at index `b`.
1246+Produces a list of `b` appended to `a`.
1036
1247
1037#### Source
1248#### Source
1038
1249
1039```hoon
1250```hoon
1040− ++ into
1251+++ snoc
1041− |* [a/(list) b/@ c/*]
1252+ |* [a=(list) b=*]
1042− ^+ a
1253+ (weld a ^+(a [b]~))
1043− (weld (scag b a) [c (slag b a)])
1044```
1254```
1045
1255
1046#### Examples
1256#### Examples
1047
1257
1048```
1258```
1049− > (into (limo ~[2 3 4]) 1 11)
1259+> `tape`(zing (snoc `(list tape)`~["a" "bc" "def"] "g"))
1260+"abcdefg"
1261+> (snoc `(list @ud)`~[1 2 3] 4)
1050− ~[2 11 3 4]
1262+~[1 2 3 4]
1051```
1263```
1052
1264
1053---
1265---
1266+
1054−### `++sort`
1267+## `++sort`
1055
1268
1056Quicksort
1269Quicksort
1057
1270
@@ -1072,28 +1285,29 @@ A list
1072#### Source
1285#### Source
1073
1286
1074```hoon
1287```hoon
1075− ++ sort !. :: quicksort
1288+++ sort !.
1076− ~/ %sort
1289+ ~/ %sort
1077− |* [a=(list) b=$-([* *] ?)]
1290+ |* [a=(list) b=$-([* *] ?)]
1078− => .(a ^.(homo a))
1291+ => .(a ^.(homo a))
1079− |- ^+ a
1292+ |- ^+ a
1080− ?~ a ~
1293+ ?~ a ~
1294+ =+ s=(skid t.a |:(c=i.a (b c i.a)))
1081− %+ weld
1295+ %+ weld
1082− $(a (skim t.a |=(c/_i.a (b c i.a))))
1296+ $(a p.s)
1083− ^+ t.a
1297+ ^+ t.a
1084− [i.a $(a (skim t.a |=(c/_i.a !(b c i.a))))]
1298+ [i.a $(a q.s)]
1085```
1299```
1086
1300
1087#### Examples
1301#### Examples
1088
1302
1089```
1303```
1090− > (sort `(list @)`[0 1 2 3 ~] gth)
1304+> (sort `(list @)`[0 1 2 3 ~] gth)
1091− ~[3 2 1 0]
1305+~[3 2 1 0]
1092```
1306```
1093
1307
1094−
1095---
1308---
1309+
1096−### `++spin` {#spin}
1310+## `++spin` {#spin}
1097
1311
1098Gate to list, with state
1312Gate to list, with state
1099
1313
@@ -1118,35 +1332,39 @@ A pair of a list and a noun.
1118#### Source
1332#### Source
1119
1333
1120```hoon
1334```hoon
1121− ++ spin
1335+++ spin
1122− ~/ %spin
1336+ ~/ %spin
1123− |* [a=(list) b=* c=_|=(^ [** +<+])]
1337+ |* [a=(list) b=* c=_|=(^ [** +<+])]
1124− => .(c `$-([_?>(?=(^ a) i.a) _b] [_-:(c) _b])`c)
1338+ => .(c `$-([_?>(?=(^ a) i.a) _b] [_-:(c) _b])`c)
1125− =/ acc=(list _-:(c)) ~
1339+ =/ acc=(list _-:(c)) ~
1126− |- ^- (pair _acc _b)
1340+ |- ^- (pair _acc _b)
1127− ?~ a
1341+ ?~ a
1128− [(flop acc) b]
1342+ [(flop acc) b]
1129− =^ res b (c i.a b)
1343+ =^ res b (c i.a b)
1130− $(acc [res acc], a t.a)
1344+ $(acc [res acc], a t.a)
1131```
1345```
1132
1346
1133#### Examples
1347#### Examples
1134
1348
1135```
1349```
1136− > %^ spin (limo ~[4 5 6]) :: Trivial example -- does nothing with the state
1350+> %^ spin (limo ~[4 5 6]) :: Trivial example -- does nothing with the state
1137− 0
1351+ 0
1138− |=([n=@ a=@] [n a])
1352+ |=([n=@ a=@] [n a])
1139− [p=~[4 5 6] q=0]
1353+[p=~[4 5 6] q=0]
1354+```
1140
1355
1356+```
1141− > %^ spin (limo ~[4 5 6]) :: Form a pair with `p` as the index and `q` as the list element
1357+> %^ spin (limo ~[4 5 6]) :: Form a pair with `p` as the index and `q` as the list element
1142− 0
1358+ 0
1143− |=([n=@ a=@] [`(pair)`[a n] +(a)])
1359+ |=([n=@ a=@] [`(pair)`[a n] +(a)])
1144− [p=~[[p=0 q=4] [p=1 q=5] [p=2 q=6]] q=3]
1360+[p=~[[p=0 q=4] [p=1 q=5] [p=2 q=6]] q=3]
1361+```
1145
1362
1363+```
1146− > %^ spin (reap 10 0) :: Create 10 random numbers less than `10`
1364+> %^ spin (reap 10 0) :: Create 10 random numbers less than `10`
1147− ~(. og eny)
1365+ ~(. og eny)
1148− |=([n=@ rng=_og] (rads:rng 10))
1366+ |=([n=@ rng=_og] (rads:rng 10))
1149− [p=~[7 8 6 0 1 5 4 7 9 3] q=<4.rvi {a/@uvJ <51.qyl 129.pdd 41.mac 1.ane $141>}>]
1367+[p=~[7 8 6 0 1 5 4 7 9 3] q=<4.rvi {a/@uvJ <51.qyl 129.pdd 41.mac 1.ane $141>}>]
1150```
1368```
1151
1369
1152#### Discussion
1370#### Discussion
@@ -1155,10 +1373,9 @@ A pair of a list and a noun.
1155with entropy (`eny`). The head of the product is the random number, the tail
1373with entropy (`eny`). The head of the product is the random number, the tail
1156is the continuation of the RNG.
1374is the continuation of the RNG.
1157
1375
1158−
1159−
1160---
1376---
1377+
1161−### `++spun` {#spun}
1378+## `++spun` {#spun}
1162
1379
1163Gate to list, with state
1380Gate to list, with state
1164
1381
@@ -1183,28 +1400,30 @@ A list.
1183#### Source
1400#### Source
1184
1401
1185```hoon
1402```hoon
1186− ++ spun
1403+++ spun
1187− ~/ %spun
1404+ ~/ %spun
1188− |* [a=(list) b=_|=(^ [** +<+])]
1405+ |* [a=(list) b=_|=(^ [** +<+])]
1189− p:(spin a +<+.b b)
1406+ p:(spin a +<+.b b)
1190```
1407```
1191
1408
1192#### Examples
1409#### Examples
1193
1410
1194```
1411```
1195− > %+ spun (limo ~[4 5 6]) :: `p` as the index and `q` as the list element
1412+> %+ spun (limo ~[4 5 6]) :: `p` as the index and `q` as the list element
1196− |=([n=@ a=@] [`(pair)`[a n] +(a)])
1413+ |=([n=@ a=@] [`(pair)`[a n] +(a)])
1197− ~[[p=0 q=4] [p=1 q=5] [p=2 q=6]]
1414+~[[p=0 q=4] [p=1 q=5] [p=2 q=6]]
1198−
1199− > =l (limo ~[7 8 9])
1200− > %+ spun (limo ~[4 5 6]) :: joins two lists into a list of pairs
1201− |=([n=@ a=@] [`(pair)`[(snag a l) n] +(a)])
1202− ~[[p=7 q=4] [p=8 q=5] [p=9 q=6]]
1203```
1415```
1204
1416
1417+```
1418+> =l (limo ~[7 8 9])
1419+> %+ spun (limo ~[4 5 6]) :: joins two lists into a list of pairs
1420+ |=([n=@ a=@] [`(pair)`[(snag a l) n] +(a)])
1421+~[[p=7 q=4] [p=8 q=5] [p=9 q=6]]
1422+```
1205
1423
1206---
1424---
1425+
1207−### `++swag`
1426+## `++swag`
1208
1427
1209Infix
1428Infix
1210
1429
@@ -1226,24 +1445,26 @@ A list of the same type as `c`.
1226#### Source
1445#### Source
1227
1446
1228```hoon
1447```hoon
1229− ++ swag
1448+++ swag
1230− |* [[a=@ b=@] c=(list)]
1449+ |* [[a=@ b=@] c=(list)]
1231− (scag +<-> (slag +<-< c))
1450+ (scag +<-> (slag +<-< c))
1232```
1451```
1233
1452
1234#### Examples
1453#### Examples
1235
1454
1236```
1455```
1237− > (swag [2 5] "roly poly")
1456+> (swag [2 5] "roly poly")
1238− "ly po"
1457+"ly po"
1239−
1240− > (swag [2 2] (limo [1 2 3 4 ~]))
1241− [i=3 t=[i=4 t=~]]
1242```
1458```
1243
1459
1460+```
1461+> (swag [2 2] (limo [1 2 3 4 ~]))
1462+[i=3 t=[i=4 t=~]]
1463+```
1244
1464
1245---
1465---
1466+
1246−### `++turn`
1467+## `++turn`
1247
1468
1248Gate to list
1469Gate to list
1249
1470
@@ -1263,23 +1484,27 @@ A list.
1263#### Source
1484#### Source
1264
1485
1265```hoon
1486```hoon
1266− ++ turn
1487+++ turn
1267− ~/ %turn
1488+ ~/ %turn
1268− |* [a=(list) b=gate]
1489+ |* [a=(list) b=gate]
1490+ => .(a (homo a))
1491+ ^- (list _?>(?=(^ a) (b i.a)))
1269− |-
1492+ |-
1270− ?~ a ~
1493+ ?~ a ~
1271− [i=(b i.a) t=$(a t.a)]
1494+ [i=(b i.a) t=$(a t.a)]
1272```
1495```
1273
1496
1274#### Examples
1497#### Examples
1275
1498
1276```
1499```
1277− > (turn (limo [104 111 111 110 ~]) @t)
1500+> (turn (limo [104 111 111 110 ~]) @t)
1278− <|h o o n|>
1501+<|h o o n|>
1502+```
1279
1503
1504+```
1280− > =a |=(a=@ (add a 4))
1505+> =a |=(a=@ (add a 4))
1281− > (turn (limo [1 2 3 4 ~]) a)
1506+> (turn (limo [1 2 3 4 ~]) a)
1282− ~[5 6 7 8]
1507+~[5 6 7 8]
1283```
1508```
1284
1509
1285#### Discussion
1510#### Discussion
@@ -1287,7 +1512,8 @@ A list.
1287`turn` is Hoon's version of 'map' in Haskell.
1512`turn` is Hoon's version of 'map' in Haskell.
1288
1513
1289---
1514---
1515+
1290−### `++weld`
1516+## `++weld`
1291
1517
1292Concatenate
1518Concatenate
1293
1519
@@ -1300,28 +1526,30 @@ Concatenate two `++list`s `a` and `b`.
1300#### Source
1526#### Source
1301
1527
1302```hoon
1528```hoon
1303− ++ weld
1529+++ weld
1304− ~/ %weld
1530+ ~/ %weld
1305− |* [a=(list) b=(list)]
1531+ |* [a=(list) b=(list)]
1306− => .(a ^.(homo a), b ^.(homo b))
1532+ => .(a ^.(homo a), b ^.(homo b))
1307− |- ^+ b
1533+ |- ^+ b
1308− ?~ a b
1534+ ?~ a b
1309− [i.a $(a t.a)]
1535+ [i.a $(a t.a)]
1310```
1536```
1311
1537
1312#### Examples
1538#### Examples
1313
1539
1314```
1540```
1315− > (weld "urb" "it")
1541+> (weld "urb" "it")
1316− "urbit"
1542+"urbit"
1317−
1318− > (weld (limo [1 2 ~]) (limo [3 4 ~]))
1319− ~[1 2 3 4]
1320```
1543```
1321
1544
1545+```
1546+> (weld (limo [1 2 ~]) (limo [3 4 ~]))
1547+~[1 2 3 4]
1548+```
1322
1549
1323---
1550---
1551+
1324−### `++welp`
1552+## `++welp`
1325
1553
1326Perfect weld
1554Perfect weld
1327
1555
@@ -1341,7 +1569,7 @@ A list.
1341#### Source
1569#### Source
1342
1570
1343```hoon
1571```hoon
1344−++ welp :: faceless weld
1572+++ welp
1345 ~/ %welp
1573 ~/ %welp
1346 =| [* *]
1574 =| [* *]
1347 |@
1575 |@
@@ -1355,23 +1583,27 @@ A list.
1355#### Examples
1583#### Examples
1356
1584
1357```
1585```
1358− > (welp "foo" "bar")
1586+> (welp "foo" "bar")
1359− "foobar"
1587+"foobar"
1360−
1588+```
1361− > (welp ~[60 61 62] ~[%a %b %c])
1362− [60 61 62 %a %b %c ~]
1363
1589
1590+```
1364− > ? (welp ~[60 61 62] ~[%a %b %c])
1591+> (welp ~[60 61 62] ~[%a %b %c])
1365− {@ud @ud @ud $a $b $c $~}
1366− [60 61 62 %a %b %c ~]
1592+[60 61 62 %a %b %c ~]
1367
1593
1368− > (welp [sa+1 so+2 ~] si=3)
1594+> ? (welp ~[60 61 62] ~[%a %b %c])
1369− [[%sa 1] [%so 2] si=3]
1595+ {@ud @ud @ud $a $b $c $~}
1596+[60 61 62 %a %b %c ~]
1370```
1597```
1371
1598
1599+```
1600+> (welp [sa+1 so+2 ~] si=3)
1601+[[%sa 1] [%so 2] si=3]
1602+```
1372
1603
1373---
1604---
1605+
1374−### `++zing`
1606+## `++zing`
1375
1607
1376Turns a `++list` of lists into a single list by promoting the elements of
1608Turns a `++list` of lists into a single list by promoting the elements of
1377each sublist into the higher.
1609each sublist into the higher.
@@ -1387,7 +1619,7 @@ A list.
1387#### Source
1619#### Source
1388
1620
1389```hoon
1621```hoon
1390−++ zing :: promote
1622+++ zing
1391 ~/ %zing
1623 ~/ %zing
1392 =| *
1624 =| *
1393 |@
1625 |@
@@ -1398,15 +1630,16 @@ A list.
1398 --
1630 --
1399```
1631```
1400
1632
1401−
1402#### Examples
1633#### Examples
1403
1634
1404```
1635```
1405− > (zing (limo [(limo ['a' 'b' 'c' ~]) (limo ['e' 'f' 'g' ~]) (limo ['h' 'i' 'j' ~]) ~]))
1636+> (zing (limo [(limo ['a' 'b' 'c' ~]) (limo ['e' 'f' 'g' ~]) (limo ['h' 'i' 'j' ~]) ~]))
1406− ~['a' 'b' 'c' 'e' 'f' 'g' 'h' 'i' 'j']
1637+~['a' 'b' 'c' 'e' 'f' 'g' 'h' 'i' 'j']
1638+```
1407
1639
1640+```
1408− > (zing (limo [(limo [1 'a' 2 'b' ~]) (limo [3 'c' 4 'd' ~]) ~]))
1641+> (zing (limo [(limo [1 'a' 2 'b' ~]) (limo [3 'c' 4 'd' ~]) ~]))
1409− ~[1 97 2 98 3 99 4 100]
1642+~[1 97 2 98 3 99 4 100]
1410```
1643```
1411
1644
1412---
1645---
content/docs/hoon/reference/stdlib/2c.md+713−637
@@ -4,15 +4,15 @@ weight = 6
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `++bex`
7+## `++bex`
8
8
9Binary exponent
9Binary exponent
10
10
11−Computes the result of `2^a`, producing an atom.
11+Computes the result of `2^a`, where `a` is a block size (see [$bloq](/docs/hoon/reference/stdlib/1c#bloq)), producing an atom.
12
12
13#### Accepts
13#### Accepts
14
14
15−`a` is an atom.
15+`a` is an `bloq`.
16
16
17#### Produces
17#### Produces
18
18
@@ -21,30 +21,34 @@ An atom.
21#### Source
21#### Source
22
22
23```hoon
23```hoon
24− ++ bex
24+++ bex
25− ~/ %bex
25+ ~/ %bex
26− |= a=@
26+ |= a=bloq
27− ^- @
27+ ^- @
28− ?: =(0 a) 1
28+ ?: =(0 a) 1
29− (mul 2 $(a (dec a)))
29+ (mul 2 $(a (dec a)))
30```
30```
31
31
32#### Examples
32#### Examples
33
33
34```
34```
35− > (bex 4)
35+> (bex 4)
36− 16
36+16
37+```
37
38
39+```
38− > (bex (add 19 1))
40+> (bex (add 19 1))
39− 1.048.576
41+1.048.576
42+```
40
43
44+```
41− > (bex 0)
45+> (bex 0)
42− 1
46+1
43```
47```
44
48
45---
49---
46
50
47−### `++can`
51+## `++can`
48
52
49Assemble
53Assemble
50
54
@@ -54,9 +58,12 @@ value.
54
58
55#### Accepts
59#### Accepts
56
60
57−`a` is a block size (see [`++bloq`](/docs/hoon/reference/stdlib/1c)).
61+`a` is a block size (see [`$bloq`](/docs/hoon/reference/stdlib/1c#bloq)).
58
62
59−`b` is a `list` of length-value pairs, `p` and `q`.
63+`b` is a `list` of length-value pairs, `p` and `q`:
64+
65+- `p` is a [step](/docs/hoon/reference/stdlib/1c/#step).
66+- `q` is a `@`.
60
67
61#### Produces
68#### Produces
62
69
@@ -65,45 +72,59 @@ An atom.
65#### Source
72#### Source
66
73
67```hoon
74```hoon
68− ++ can
75+++ can
69− ~/ %can
76+ ~/ %can
70− |= [a=bloq b=(list [p=@ q=@])]
77+ |= [a=bloq b=(list [p=step q=@])]
71− ^- @
78+ ^- @
72− ?~ b 0
79+ ?~ b 0
73− (add (end a p.i.b q.i.b) (lsh a p.i.b $(b t.b)))
80+ (add (end [a p.i.b] q.i.b) (lsh [a p.i.b] $(b t.b)))
74```
81```
75
82
76#### Examples
83#### Examples
77
84
78```
85```
79− > `@ub`21 :: @ub is the binary aura
86+> `@ub`21 :: @ub is the binary aura
80− 0b1.0101
87+0b1.0101
88+```
81
89
90+```
82− > `@ub`(can 3 ~[[1 21]])
91+> `@ub`(can 3 ~[[1 21]])
83− 0b1.0101
92+0b1.0101
93+```
84
94
95+```
85− > `@ub`(can 3 ~[[1 1]])
96+> `@ub`(can 3 ~[[1 1]])
86− 0b1
97+0b1
98+```
87
99
100+```
88− > `@ub`(can 0 ~[[1 255]])
101+> `@ub`(can 0 ~[[1 255]])
89− 0b1
102+0b1
103+```
90
104
105+```
91− > `@ux`(can 3 [3 0xc1] [1 0xa] ~) :: @ux is the hexadecimal aura
106+> `@ux`(can 3 [3 0xc1] [1 0xa] ~) :: @ux is the hexadecimal aura
92− 0xa00.00c1
107+0xa00.00c1
108+```
93
109
110+```
94− > `@ux`(can 3 [3 0xc1] [1 0xa] [1 0x23] ~)
111+> `@ux`(can 3 [3 0xc1] [1 0xa] [1 0x23] ~)
95− 0x23.0a00.00c1
112+0x23.0a00.00c1
113+```
96
114
115+```
97− > `@ux`(can 4 [3 0xc1] [1 0xa] [1 0x23] ~)
116+> `@ux`(can 4 [3 0xc1] [1 0xa] [1 0x23] ~)
98− 0x23.000a.0000.0000.00c1
117+0x23.000a.0000.0000.00c1
118+```
99
119
120+```
100− > `@ux`(can 3 ~[[1 'a'] [2 'bc']])
121+> `@ux`(can 3 ~[[1 'a'] [2 'bc']])
101− 0x63.6261
122+0x63.6261
102```
123```
103
124
104---
125---
105
126
106−### `++cat`
127+## `++cat`
107
128
108Concatenate
129Concatenate
109
130
@@ -112,7 +133,7 @@ atom.
112
133
113#### Accepts
134#### Accepts
114
135
115−`a` is a block size (see [`++bloq`](/docs/hoon/reference/stdlib/1c)).
136+`a` is a block size (see [`$bloq`](/docs/hoon/reference/stdlib/1c#bloq)).
116
137
117`b` is an atom.
138`b` is an atom.
118
139
@@ -125,49 +146,43 @@ An atom.
125#### Source
146#### Source
126
147
127```hoon
148```hoon
128− ++ cat
149+++ cat
129− ~/ %cat
150+ ~/ %cat
130− |= [a=bloq b=@ c=@]
151+ |= [a=bloq b=@ c=@]
131− (add (lsh a (met a b) c) b)
152+ (add (lsh [a (met a b)] c) b)
132```
153```
133
154
134#### Examples
155#### Examples
135
156
136```
157```
137− > `@ub`(cat 3 1 0) :: @ub is the binary aura
158+> `@ub`(cat 3 1 0) :: @ub is the binary aura
138− 0b1
159+0b1
139−
140− > `@ub`(cat 0 1 1)
160+> `@ub`(cat 0 1 1)
141− 0b11
161+0b11
142−
143− > `@ub`(cat 0 2 1)
162+> `@ub`(cat 0 2 1)
144− 0b110
163+0b110
145−
146− > `@ub`(cat 2 1 1)
164+> `@ub`(cat 2 1 1)
147− 0b1.0001
165+0b1.0001
148−
166+```
149− > `@ub`256
150− 0b1.0000.0000
151−
152− > `@ub`255
153− 0b1111.1111
154−
155− > `@ub`(cat 3 256 255)
156− 0b1111.1111.0000.0001.0000.0000
157−
158− > `@ub`(cat 2 256 255)
159− 0b1111.1111.0001.0000.0000
160−
161− > (cat 3 256 255)
162− 16.711.936
163
167
168+```
169+> `@ub`256
170+0b1.0000.0000
171+> `@ub`255
172+0b1111.1111
173+> `@ub`(cat 3 256 255)
174+0b1111.1111.0000.0001.0000.0000
175+> `@ub`(cat 2 256 255)
176+0b1111.1111.0001.0000.0000
177+> (cat 3 256 255)
178+16.711.936
164− > (cat 2 256 255)
179+> (cat 2 256 255)
165− 1.044.736
180+1.044.736
166```
181```
167
182
168---
183---
169
184
170−### `++cut`
185+## `++cut`
171
186
172Slice
187Slice
173
188
@@ -176,11 +191,12 @@ Slices `c` blocks of size `a` that are positioned `b` blocks from the end of
176
191
177#### Accepts
192#### Accepts
178
193
179−`a` is a block size (see [`++bloq`](/docs/hoon/reference/stdlib/1c)).
194+`a` is a block size (see [`$bloq`](/docs/hoon/reference/stdlib/1c)).
180
195
181−`b` is an atom.
196+`[b c]` where:
182
197
183−`c` is an atom.
198+- `b` is a [step](/docs/hoon/reference/stdlib/1c#step).
199+- `c` is a [step](/docs/hoon/reference/stdlib/1c#step).
184
200
185`d` is an atom.
201`d` is an atom.
186
202
@@ -191,43 +207,42 @@ An atom.
191#### Source
207#### Source
192
208
193```hoon
209```hoon
194− ++ cut
210+++ cut
195− ~/ %cut
211+ ~/ %cut
196− |= [a=bloq [b=@u c=@u] d=@]
212+ |= [a=bloq [b=step c=step] d=@]
197− (end a c (rsh a b d))
213+ (end [a c] (rsh [a b] d))
198```
214```
199
215
200#### Examples
216#### Examples
201
217
202```
218```
203− > (cut 0 [1 1] 2)
219+> (cut 0 [1 1] 2)
204− 1
220+1
205−
206− > (cut 0 [2 1] 4)
221+> (cut 0 [2 1] 4)
207− 1
222+1
208−
223+```
209− > `@t`(cut 3 [0 3] 'abcdefgh')
210− 'abc'
211−
212− > `@t`(cut 3 [1 3] 'abcdefgh') :: @t is the cord aura
213− 'bcd'
214−
215− > `@ub`(cut 0 [0 3] 0b1111.0000.1101) :: @ub is the binary aura
216− 0b101
217−
218− > `@ub`(cut 0 [0 6] 0b1111.0000.1101)
219− 0b1101
220
224
221− > `@ub`(cut 0 [4 6] 0b1111.0000.1101)
225+```
222− 0b11.0000
226+> `@t`(cut 3 [0 3] 'abcdefgh') :: @t is the cord aura
227+'abc'
228+> `@t`(cut 3 [1 3] 'abcdefgh')
229+'bcd'
230+```
223
231
232+```
233+> `@ub`(cut 0 [0 3] 0b1111.0000.1101) :: @ub is the binary aura
234+0b101
235+> `@ub`(cut 0 [0 6] 0b1111.0000.1101)
236+0b1101
237+> `@ub`(cut 0 [4 6] 0b1111.0000.1101)
238+0b11.0000
224− > `@ub`(cut 0 [3 6] 0b1111.0000.1101)
239+> `@ub`(cut 0 [3 6] 0b1111.0000.1101)
225− 0b10.0001
240+0b10.0001
226```
241```
227
242
228---
243---
229
244
230−### `++end`
245+## `++end`
231
246
232Tail
247Tail
233
248
@@ -235,8 +250,8 @@ Produces an atom by taking the last `step` blocks of size `bloq` from `b`.
235
250
236#### Accepts
251#### Accepts
237
252
238−`a` is an atom slice specifier (see [`++bite`](/docs/hoon/reference/stdlib/1c#bite)),
253+`a` is an atom slice specifier (see [`$bite`](/docs/hoon/reference/stdlib/1c#bite)),
239−which is a block size (see [`++bloq`](/docs/hoon/reference/stdlib/1c#bloq))
254+which is a block size (see [`$bloq`](/docs/hoon/reference/stdlib/1c#bloq))
240with optional block count.
255with optional block count.
241
256
242`b` is an atom.
257`b` is an atom.
@@ -248,56 +263,51 @@ An atom.
248#### Source
263#### Source
249
264
250```hoon
265```hoon
251− ++ end
266+++ end
252− ~/ %end
267+ ~/ %end
253− |= [a=bite b=@]
268+ |= [a=bite b=@]
254− =/ [=bloq =step] ?^(a a [a *step])
269+ =/ [=bloq =step] ?^(a a [a *step])
255− (mod b (bex (mul (bex bloq) step)))
270+ (mod b (bex (mul (bex bloq) step)))
256```
271```
257
272
258#### Examples
273#### Examples
259
274
260```
275```
261− > (end [2 2] 255)
276+> (end [2 2] 255)
262− 255
277+255
263−
264− > (end [3 1] 255)
278+> (end [3 1] 255)
265− 255
279+255
266−
267− > (end 3 255)
280+> (end 3 255)
268− 255
281+255
269−
270− > (end 3 256)
282+> (end 3 256)
271− 0
283+0
272−
284+```
273− > `@ub`12 :: @ub is the binary aura
274− 0b1100
275−
276− > `@ub`(end [0 3] 12)
277− 0b100
278−
279− > (end [0 3] 12)
280− 4
281−
282− > `@ub`(end [1 3] 12)
283− 0b1100
284−
285− > (end [1 3] 12)
286− 12
287−
288− > `@ux`'abc' :: @ux is the hexademical aura
289− 0x63.6261
290
285
286+```
287+> `@ub`12 :: @ub is the binary aura
288+0b1100
291− > `@ux`(end [3 2] 'abc')
289+> `@ub`(end [0 3] 12)
292− 0x6261
290+0b100
291+> (end [0 3] 12)
292+4
293+> `@ub`(end [1 3] 12)
294+0b1100
295+> (end [1 3] 12)
296+12
297+```
293
298
299+```
300+> `@ux`'abc' :: @ux is the hexademical aura
301+0x63.6261
302+> `@ux`(end [3 2] 'abc')
303+0x6261
294− > `@t`(end [3 2] 'abc') :: @t is the cord aura
304+> `@t`(end [3 2] 'abc') :: @t is the cord aura
295− 'ab'
305+'ab'
296```
306```
297
307
298---
308---
299
309
300−### `++fil`
310+## `++fil`
301
311
302Fill bloqstream
312Fill bloqstream
303
313
@@ -305,9 +315,9 @@ Produces an atom by repeating `c` for `b` blocks of size `a`.
305
315
306#### Accepts
316#### Accepts
307
317
308−`a` is a block size (see [`++bloq`](/docs/hoon/reference/stdlib/1c)).
318+`a` is a block size (see [`$bloq`](/docs/hoon/reference/stdlib/1c#bloq)).
309
319
310−`b` is an atom.
320+`b` is a [step](/docs/hoon/reference/stdlib/1c#step).
311
321
312`c` is an atom.
322`c` is an atom.
313
323
@@ -318,38 +328,48 @@ An atom.
318#### Source
328#### Source
319
329
320```hoon
330```hoon
321− ++ fil
331+++ fil
332+ ~/ %fil
322− |= [a=bloq b=@u c=@]
333+ |= [a=bloq b=step c=@]
323− =+ n=0
334+ =| n=@ud
324− =+ d=c
335+ =. c (end a c)
336+ =/ d c
325− |- ^- @
337+ |- ^- @
326− ?: =(n b)
338+ ?: =(n b)
327− (rsh a 1 d)
339+ (rsh a d)
328− $(d (add c (lsh a 1 d)), n +(n))
340+ $(d (add c (lsh a d)), n +(n))
329```
341```
330
342
331#### Examples
343#### Examples
332
344
333```
345```
334− > `@t`(fil 3 5 %a) :: @t is the cord (string) aura
346+> `@t`(fil 3 5 %a) :: @t is the cord (string) aura
335− 'aaaaa'
347+'aaaaa'
348+```
336
349
350+```
337− > `@t`(fil 5 10 %ceeb)
351+> `@t`(fil 5 10 %ceeb)
338− 'ceebceebceebceebceebceebceebceebceebceeb'
352+'ceebceebceebceebceebceebceebceebceebceeb'
353+```
339
354
355+```
340− > `@t`(fil 4 10 %eced)
356+> `@t`(fil 4 10 'eced')
341− 'ʇʇʇʇʇʇʇʇʇʇed'
357+'ecececececececececec'
358+```
342
359
360+```
343− > `@tas`(fil 4 10 %bf) :: @tas is the term aura
361+> `@tas`(fil 4 10 %bf) :: @tas is the term aura
344− %bfbfbfbfbfbfbfbfbfbf
362+%bfbfbfbfbfbfbfbfbfbf
363+```
345
364
365+```
346− > `@ub`(fil 2 6 1) :: @ub is the binary aura
366+> `@ub`(fil 2 6 1) :: @ub is the binary aura
347− 0b1.0001.0001.0001.0001.0001
367+0b1.0001.0001.0001.0001.0001
348```
368```
349
369
350---
370---
351
371
352−### `++lsh`
372+## `++lsh`
353
373
354Left-shift
374Left-shift
355
375
@@ -357,8 +377,8 @@ Produces an atom by left-shifting `b` by `step` blocks of size `bloq`.
357
377
358#### Accepts
378#### Accepts
359
379
360−`a` is an atom slice specifier (see [`++bite`](/docs/hoon/reference/stdlib/1c#bite)),
380+`a` is an atom slice specifier (see [`$bite`](/docs/hoon/reference/stdlib/1c#bite)),
361−which is a block size (see [`++bloq`](/docs/hoon/reference/stdlib/1c#bloq))
381+which is a block size (see [`$bloq`](/docs/hoon/reference/stdlib/1c#bloq))
362with optional block count.
382with optional block count.
363
383
364`b` is an atom.
384`b` is an atom.
@@ -370,41 +390,38 @@ An atom.
370#### Source
390#### Source
371
391
372```hoon
392```hoon
373− ++ lsh
393+++ lsh
374− ~/ %lsh
394+ ~/ %lsh
375− |= [a=bite b=@]
395+ |= [a=bite b=@]
376− =/ [=bloq =step] ?^(a a [a *step])
396+ =/ [=bloq =step] ?^(a a [a *step])
377− (mul b (bex (mul (bex bloq) step)))
397+ (mul b (bex (mul (bex bloq) step)))
378```
398```
379
399
380#### Examples
400#### Examples
381
401
382```
402```
383− > `@ub`1 :: @ub is the binary aura
403+> `@ub`1 :: @ub is the binary aura
384− 0b1
404+0b1
385−
386− > `@ub`(lsh [0 1] 1)
405+> `@ub`(lsh [0 1] 1)
387− 0b10
406+0b10
388−
389− > (lsh [0 1] 1)
407+> (lsh [0 1] 1)
390− 2
408+2
391−
392− > (lsh 0 1)
409+> (lsh 0 1)
393− 2
410+2
394−
411+```
395− > `@ub`255
396− 0b1111.1111
397−
398− > `@ub`(lsh [3 1] 255)
399− 0b1111.1111.0000.0000
400
412
413+```
414+> `@ub`255
415+0b1111.1111
416+> `@ub`(lsh [3 1] 255)
417+0b1111.1111.0000.0000
401− > (lsh [3 1] 255)
418+> (lsh [3 1] 255)
402− 65.280
419+65.280
403```
420```
404
421
405---
422---
406
423
407−### `++met`
424+## `++met`
408
425
409Measure
426Measure
410
427
@@ -412,45 +429,47 @@ Computes the number of blocks of size `a` in `b`, producing an atom.
412
429
413#### Accepts
430#### Accepts
414
431
415−`a` is a block size (see [`++bloq`](/docs/hoon/reference/stdlib/1c)).
432+`a` is a block size (see [`$bloq`](/docs/hoon/reference/stdlib/1c/bloq)).
416
433
417`b` is an atom.
434`b` is an atom.
418
435
419#### Source
436#### Source
420
437
421```hoon
438```hoon
422− ++ met
439+++ met
423− ~/ %met
440+ ~/ %met
424− |= [a=bloq b=@]
441+ |= [a=bloq b=@]
425− ^- @
442+ ^- @
426− =+ c=0
443+ =+ c=0
427− |-
444+ |-
428− ?: =(0 b) c
445+ ?: =(0 b) c
429− $(b (rsh a 1 b), c +(c))
446+ $(b (rsh a b), c +(c))
430```
447```
431
448
432#### Examples
449#### Examples
433
450
434```
451```
435− > (met 0 1)
452+> (met 0 1)
436− 1
453+1
437−
438− > (met 0 2)
454+> (met 0 2)
439− 2
455+2
440−
456+```
441− > (met 3 255)
442− 1
443
457
458+```
459+> (met 3 255)
460+1
444− > (met 3 256)
461+> (met 3 256)
445− 2
462+2
463+```
446
464
465+```
447− > (met 3 'abcde')
466+> (met 3 'abcde')
448− 5
467+5
449```
468```
450
469
451---
470---
452
471
453−### `++rap`
472+## `++rap`
454
473
455Assemble non-zero
474Assemble non-zero
456
475
@@ -469,41 +488,39 @@ An atom.
469#### Source
488#### Source
470
489
471```hoon
490```hoon
472− ++ rap
491+++ rap
473− ~/ %rap
492+ ~/ %rap
474− |= [a=bloq b=(list @)]
493+ |= [a=bloq b=(list @)]
475− ^- @
494+ ^- @
476− =+ ~
477− ?~ b 0
495+ ?~ b 0
478− (cat a i.b $(b t.b))
496+ (cat a i.b $(b t.b))
479```
497```
480
498
481#### Examples
499#### Examples
482
500
483```
501```
484− > `@ub`(rap 2 [1 2 3 4 ~]) :: @ub is the binary aura
502+> `@ub`(rap 2 [1 2 3 4 ~]) :: @ub is the binary aura
485− 0b100.0011.0010.0001
503+0b100.0011.0010.0001
486−
487− > `@ub`(rap 1 [1 2 3 4 ~])
504+> `@ub`(rap 1 [1 2 3 4 ~])
488− 0b1.0011.1001
505+0b1.0011.1001
489−
490− > (rap 0 [0 0 0 ~])
491− 0
492−
493− > (rap 0 [1 0 1 ~])
494− 3
495−
496− > `@ub`3
506+```
497− 0b11
498−
499− > (rap 0 [0 1 0 0 1 2 ~])
500− 11
501
507
508+```
509+> (rap 0 [0 0 0 ~])
510+0
502− > (rap 0 [1 1 2 ~])
511+> (rap 0 [1 0 1 ~])
503− 11
512+3
513+```
504
514
515+```
516+> `@ub`3
517+0b11
518+> (rap 0 [0 1 0 0 1 2 ~])
519+11
520+> (rap 0 [1 1 2 ~])
521+11
505− > `@ub`11
522+> `@ub`11
506− 0b1011
523+0b1011
507```
524```
508
525
509#### Discussion
526#### Discussion
@@ -512,7 +529,7 @@ Any element of the value `0` is not included in concatenation.
512
529
513---
530---
514
531
515−### `++rep`
532+## `++rep`
516
533
517Assemble single
534Assemble single
518
535
@@ -533,63 +550,69 @@ An atom.
533#### Source
550#### Source
534
551
535```hoon
552```hoon
536− ++ rep
553+++ rep
537− ~/ %rep
554+ ~/ %rep
538− |= [a=bite b=(list @)]
555+ |= [a=bite b=(list @)]
539− =/ [=bloq =step] ?^(a a [a *step])
556+ =/ [=bloq =step] ?^(a a [a *step])
540− =| i=@ud
557+ =| i=@ud
541− |- ^- @
558+ |- ^- @
542− ?~ b 0
559+ ?~ b 0
543− %+ add $(i +(i), b t.b)
560+ %+ add $(i +(i), b t.b)
544− (lsh [bloq (mul step i)] (end [bloq step] i.b))
561+ (lsh [bloq (mul step i)] (end [bloq step] i.b))
545```
562```
546
563
547#### Examples
564#### Examples
548
565
549```
566```
550− > `@ub`(rep 2 [1 2 3 4 ~]) :: @ub is the binary aura
567+> `@ub`(rep 2 [1 2 3 4 ~]) :: @ub is the binary aura
551− 0b100.0011.0010.0001
568+0b100.0011.0010.0001
552−
569+```
553− > (rep 0 [0 0 1 ~])
554− 4
555−
556− > (rep 0 [0 0 0 1 ~])
557− 8
558−
559− > `@ub`(rep 0 [0 0 0 1 ~])
560− 0b1000
561−
562− > `@ub`8
563− 0b1000
564−
565− > `@ub`(rep 0 [1 0 1 0 ~])
566− 0b101
567−
568− > `@ub`(rep 0 [1 2 3 4 ~])
569− 0b101
570
570
571+```
571− > (rep 0 [0 1 0 1 ~])
572+> (rep 0 [0 0 1 ~])
572− 10
573+4
574+> (rep 0 [0 0 0 1 ~])
575+8
576+```
573
577
578+```
574− > (rep 0 [1 0 1 0 1 ~])
579+> `@ub`(rep 0 [0 0 0 1 ~])
575− 21
580+0b1000
581+> `@ub`8
582+0b1000
583+```
576
584
577− > `@ub`21
585+```
578− 0b10.1010
586+> `@ub`(rep 0 [1 0 1 0 ~])
587+0b101
588+> `@ub`(rep 0 [1 2 3 4 ~])
589+0b101
590+```
579
591
580− > `@ub`(rep 3 [12 166 8 34 ~])
592+```
593+> (rep 0 [0 1 0 1 ~])
594+10
595+> (rep 0 [1 0 1 0 1 ~])
596+21
597+> `@ub`21
581− 0b10.0010.0000.1000.1010.0110.0000.1100
598+0b10.1010
599+```
582
600
583− > `*`"abcd"
601+```
584− [97 98 99 100 0]
602+> `@ub`(rep 3 [12 166 8 34 ~])
603+0b10.0010.0000.1000.1010.0110.0000.1100
604+```
585
605
606+```
607+> `*`"abcd"
608+[97 98 99 100 0]
586− > `@t`(rep 3 "abcd") :: @t is the text aura
609+> `@t`(rep 3 "abcd") :: @t is the text aura
587− 'abcd'
610+'abcd'
588```
611```
589
612
590---
613---
591
614
592−### `++rev`
615+## `++rev`
593
616
594Reverses block order, accounting for leading zeroes.
617Reverses block order, accounting for leading zeroes.
595
618
@@ -630,35 +653,30 @@ An atom.
630
653
631```
654```
632> =a 0b1111.0000.1111.1010.0011
655> =a 0b1111.0000.1111.1010.0011
633−
634> `@ub`(rev 0 20 a)
656> `@ub`(rev 0 20 a)
6350b1100.0101.1111.0000.1111
6570b1100.0101.1111.0000.1111
636−
637> `@ub`(rev 0 12 a)
658> `@ub`(rev 0 12 a)
6380b1100.0101.1111
6590b1100.0101.1111
639−
640> `@ub`(rev 2 5 a)
660> `@ub`(rev 2 5 a)
6410b11.1010.1111.0000.1111
6610b11.1010.1111.0000.1111
642−
643> `@ub`(rev 2 4 a)
662> `@ub`(rev 2 4 a)
6440b11.1010.1111.0000
6630b11.1010.1111.0000
645−
646> `@ub`(rev 2 6 a)
664> `@ub`(rev 2 6 a)
6470b11.1010.1111.0000.1111.0000
6650b11.1010.1111.0000.1111.0000
666+```
648
667
668+```
649> (rev 1 10 1.000)
669> (rev 1 10 1.000)
650179.200
670179.200
651−
652> (rev 2 5 1.000)
671> (rev 2 5 1.000)
653582.400
672582.400
654−
655> (rev 1 5 1.000)
673> (rev 1 5 1.000)
656175
674175
657```
675```
658
676
659---
677---
660
678
661−### `++rip`
679+## `++rip`
662
680
663Disassemble
681Disassemble
664
682
@@ -679,51 +697,51 @@ A list of atoms.
679#### Source
697#### Source
680
698
681```hoon
699```hoon
682− ++ rip
700+++ rip
683− ~/ %rip
701+ ~/ %rip
684− |= [a=bite b=@]
702+ |= [a=bite b=@]
685− ^- (list @)
703+ ^- (list @)
686− ?: =(0 b) ~
704+ ?: =(0 b) ~
687− [(end a b) $(b (rsh a b))]
705+ [(end a b) $(b (rsh a b))]
688```
706```
689
707
690#### Examples
708#### Examples
691
709
692```
710```
693− > `@ub`155 :: @ub is the binary aura
711+> `@ub`155 :: @ub is the binary aura
694− 0b1001.1011
712+0b1001.1011
695−
696− > (rip 0 155)
713+> (rip 0 155)
697− ~[1 1 0 1 1 0 0 1]
714+~[1 1 0 1 1 0 0 1]
698−
699− > (rip 2 155)
715+> (rip 2 155)
700− ~[11 9]
716+~[11 9]
701−
717+```
702− > (rip 0 11)
703− ~[1 1 0 1]
704−
705− > (rip 1 155)
706− ~[3 2 1 2]
707−
708− > `@ub`256
709− 0b1.0000.0000
710−
711− > (rip 0 256)
712− ~[0 0 0 0 0 0 0 0 1]
713
718
719+```
714− > (rip 2 256)
720+> (rip 0 11)
715− ~[0 0 1]
721+~[1 1 0 1]
722+> (rip 1 155)
723+~[3 2 1 2]
724+```
716
725
726+```
727+> `@ub`256
728+0b1.0000.0000
729+> (rip 0 256)
730+~[0 0 0 0 0 0 0 0 1]
731+> (rip 2 256)
732+~[0 0 1]
717− > (rip 3 256)
733+> (rip 3 256)
718− ~[0 1]
734+~[0 1]
735+```
719
736
737+```
720− > `tape`(rip 3 'abcd')
738+> `tape`(rip 3 'abcd')
721− "abcd"
739+"abcd"
722```
740```
723
741
724---
742---
725
743
726−### `++rsh`
744+## `++rsh`
727
745
728Right-shift
746Right-shift
729
747
@@ -744,56 +762,51 @@ An atom.
744#### Source
762#### Source
745
763
746```hoon
764```hoon
747− ++ rsh
765+++ rsh
748− ~/ %rsh
766+ ~/ %rsh
749− |= [a=bite b=@]
767+ |= [a=bite b=@]
750− =/ [=bloq =step] ?^(a a [a *step])
768+ =/ [=bloq =step] ?^(a a [a *step])
751− (div b (bex (mul (bex bloq) step)))
769+ (div b (bex (mul (bex bloq) step)))
752```
770```
753
771
754#### Examples
772#### Examples
755
773
756```
774```
757− > `@ub`145 :: @ub is the binary aura
775+> `@ub`145 :: @ub is the binary aura
758− 0b1001.0001
776+0b1001.0001
759−
760− > `@ub`(rsh [1 1] 145)
777+> `@ub`(rsh [1 1] 145)
761− 0b10.0100
778+0b10.0100
762−
763− > (rsh [1 1] 145)
779+> (rsh [1 1] 145)
764− 36
780+36
765−
766− > (rsh 1 145)
781+> (rsh 1 145)
767− 36
782+36
768−
769− > `@ub`(rsh [2 1] 145)
783+> `@ub`(rsh [2 1] 145)
770− 0b1001
784+0b1001
771−
772− > (rsh [2 1] 145)
785+> (rsh [2 1] 145)
773− 9
786+9
774−
787+```
775− > `@ub`10
776− 0b1010
777−
778− > `@ub`(rsh [0 1] 10)
779− 0b101
780−
781− > (rsh [0 1] 10)
782− 5
783−
784− > `@ux`'abc'
785− 0x63.6261
786
788
787− > `@t`(rsh [3 1] 'abc')
789+```
788− 'bc'
790+> `@ub`10
791+0b1010
792+> `@ub`(rsh [0 1] 10)
793+0b101
794+> (rsh [0 1] 10)
795+5
796+```
789
797
798+```
799+> `@ux`'abc'
800+0x63.6261
801+> `@t`(rsh [3 1] 'abc')
802+'bc'
790− > `@ux`(rsh [3 1] 'abc')
803+> `@ux`(rsh [3 1] 'abc')
791− 0x6362
804+0x6362
792```
805```
793
806
794---
807---
795
808
796−### `++run`
809+## `++run`
797
810
798`++turn` into atom.
811`++turn` into atom.
799
812
@@ -817,25 +830,24 @@ An atom.
817#### Source
830#### Source
818
831
819```hoon
832```hoon
820− ++ run
833+++ run
821− ~/ %run
834+ ~/ %run
822− |= [a=bite b=@ c=$-(@ @)]
835+ |= [a=bite b=@ c=$-(@ @)]
823− (rep a (turn (rip a b) c))
836+ (rep a (turn (rip a b) c))
824```
837```
825
838
826#### Examples
839#### Examples
827
840
828```
841```
829− > `@ux`65.535 :: @ux is the hexadecimal aura
842+ > `@ux`65.535 :: @ux is the hexadecimal aura
830 0xffff
843 0xffff
831−
832− > `@ux`(run 2 65.535 dec) :: dec is the decrement gate
844+ > `@ux`(run 2 65.535 dec) :: dec is the decrement gate
833 0xeeee
845 0xeeee
834```
846```
835
847
836---
848---
837
849
838−### `++rut`
850+## `++rut`
839
851
840`++turn` into list.
852`++turn` into list.
841
853
@@ -859,25 +871,80 @@ A list.
859#### Source
871#### Source
860
872
861```hoon
873```hoon
862− ++ rut
874+++ rut
863− ~/ %rut
875+ ~/ %rut
864− |* [a=bite b=@ c=$-(@ *)]
876+ |* [a=bite b=@ c=$-(@ *)]
865− (turn (rip a b) c)
877+ (turn (rip a b) c)
866```
878```
867
879
868#### Examples
880#### Examples
869
881
870```
882```
871− > `@ux`65.535 :: @ux is the hexadecimal aura
883+> `@ux`65.535 :: @ux is the hexadecimal aura
872− 0xffff
884+0xffff
885+> `(list @ux)`(rut 2 65.535 dec) :: dec is the decrement gate
886+~[0xe 0xe 0xe 0xe]
887+```
888+
889+---
890+
891+## `++sew`
892+
893+Stitch one atom into another
894+
895+Replace `c` blocks of size `a` at offset `b` of atom `e` with `c` blocks of size `a` from atom `d`.
896+
897+That is, take `(end [a c] d)` from `d` and overwrite the `(cut a [b c] e)` part of `e`.
898+
899+Or in simpler terms, take from the start of `d` and replace some part of `e` with it.
900+
901+#### Accepts
873
902
874− > `(list @ux)`(rut 2 65.535 dec) :: dec is the decrement gate
903+`a` is a [$bloq](/docs/hoon/reference/stdlib/1c#bite) (block size).
875− ~[0xe 0xe 0xe 0xe]
904+
905+`[b c d]` where:
906+
907+- `b` is a [step](/docs/hoon/reference/stdlib/1c#step) specifying the number of `bloq`s to offset.
908+- `b` is a [step](/docs/hoon/reference/stdlib/1c#step) specifying the number of `bloq`s to replace.
909+- `d` is the donor atom.
910+
911+`e` is the recipient atom.
912+
913+#### Produces
914+
915+An atom.
916+
917+#### Source
918+
919+```hoon
920+++ sew
921+ ~/ %sew
922+ |= [a=bloq [b=step c=step d=@] e=@]
923+ ^- @
924+ %+ add
925+ (can a b^e c^d ~)
926+ =/ f [a (add b c)]
927+ (lsh f (rsh f e))
928+```
929+
930+#### Examples
931+
932+```
933+> `@t`(sew 3 [0 0 'XXXX'] 'OOOO')
934+'OOOO'
935+> `@t`(sew 3 [0 1 'XXXX'] 'OOOO')
936+'XOOO'
937+> `@t`(sew 3 [2 1 'XXXX'] 'OOOO')
938+'OOXO'
939+> `@t`(sew 3 [2 2 'XXXX'] 'OOOO')
940+'OOXX'
941+> `@t`(sew 3 [0 4 'XXXX'] 'OOOO')
942+'XXXX'
876```
943```
877
944
878---
945---
879
946
880−### `++swp`
947+## `++swp`
881
948
882Reverse block order
949Reverse block order
883
950
@@ -886,7 +953,7 @@ reversing the block order of `b` using block size `a`.
886
953
887#### Accepts
954#### Accepts
888
955
889−`a` is a block size (see [`++bloq`](/docs/hoon/reference/stdlib/1c)).
956+`a` is a block size (see [`$bloq`](/docs/hoon/reference/stdlib/1c#bloq)).
890
957
891`b` is an atom.
958`b` is an atom.
892
959
@@ -897,31 +964,33 @@ An atom
897#### Source
964#### Source
898
965
899```hoon
966```hoon
967+++ swp
968+ ~/ %swp
969+ |= [a=bloq b=@]
900− ++ swp |=([a=bloq b=@] (rep a (flop (rip a b))))
970+ (rep a (flop (rip a b)))
901```
971```
902
972
903#### Examples
973#### Examples
904
974
905```
975```
906− > `@ub`24 :: @ub is the binary aura
976+> `@ub`24 :: @ub is the binary aura
907− 0b1.1000
977+0b1.1000
908−
909− > (swp 0 24)
978+> (swp 0 24)
910− 3
979+3
911−
912− > `@ub`3
980+> `@ub`3
913− 0b11
981+0b11
914−
982+```
915− > (swp 0 0)
916− 0
917
983
984+```
985+> (swp 0 0)
986+0
918− > (swp 0 128)
987+> (swp 0 128)
919− 1
988+1
920```
989```
921
990
922---
991---
923
992
924−### `++xeb`
993+## `++xeb`
925
994
926Binary logarithm
995Binary logarithm
927
996
@@ -938,38 +1007,48 @@ An atom.
938#### Source
1007#### Source
939
1008
940```hoon
1009```hoon
941− ++ xeb
1010+++ xeb
942− ~/ %xeb
1011+ ~/ %xeb
943− |= a=@
1012+ |= a=@
944− ^- @
1013+ ^- @
945− (met 0 a)
1014+ (met 0 a)
946```
1015```
947
1016
948#### Examples
1017#### Examples
949
1018
950```
1019```
951− > (xeb 31)
1020+> (xeb 31)
952− 5
1021+5
1022+```
953
1023
1024+```
954− > (xeb 32)
1025+> (xeb 32)
955− 6
1026+6
1027+```
956
1028
1029+```
957− > (xeb 49)
1030+> (xeb 49)
958− 6
1031+6
1032+```
959
1033
1034+```
960− > (xeb 0)
1035+> (xeb 0)
961− 0
1036+0
1037+```
962
1038
1039+```
963− > (xeb 1)
1040+> (xeb 1)
964− 1
1041+1
1042+```
965
1043
1044+```
966− > (xeb 2)
1045+> (xeb 2)
967− 2
1046+2
968```
1047```
969
1048
970---
1049---
971
1050
972−### `++fe`
1051+## `++fe`
973
1052
974Modulo bloq
1053Modulo bloq
975
1054
@@ -994,7 +1073,7 @@ representation.
994
1073
995#### Accepts
1074#### Accepts
996
1075
997−`a` is a `bloq`.
1076+`a` is a `bloq` (and is the sample of the parent core).
998
1077
999`b` is an atom.
1078`b` is an atom.
1000
1079
@@ -1002,40 +1081,40 @@ representation.
1002
1081
1003#### Produces
1082#### Produces
1004
1083
1005−A `@s`
1084+A `@s`.
1006
1085
1007#### Source
1086#### Source
1008
1087
1009```hoon
1088```hoon
1089+ ++ dif
1010− ++ dif |=([b=@ c=@] (sit (sub (add out (sit b)) (sit c))))
1090+ |=([b=@ c=@] (sit (sub (add out (sit b)) (sit c))))
1011```
1091```
1012
1092
1013#### Examples
1093#### Examples
1014
1094
1015```
1095```
1016− > (~(dif fe 3) 63 64)
1096+> (~(dif fe 3) 63 64)
1017− 255
1097+255
1018−
1019− > (~(dif fe 3) 5 10)
1098+> (~(dif fe 3) 5 10)
1020− 251
1099+251
1021−
1022− > (~(dif fe 3) 0 1)
1100+> (~(dif fe 3) 0 1)
1023− 255
1101+255
1024−
1102+```
1025− > (~(dif fe 0) 9 10)
1026− 1
1027−
1028− > (~(dif fe 0) 9 11)
1029− 0
1030−
1031− > (~(dif fe 0) 9 12)
1032− 1
1033
1103
1104+```
1034− > (~(dif fe 2) 9 12)
1105+> (~(dif fe 0) 9 10)
1035− 13
1106+1
1107+> (~(dif fe 0) 9 11)
1108+0
1109+> (~(dif fe 0) 9 12)
1110+1
1111+```
1036
1112
1113+```
1114+> (~(dif fe 2) 9 12)
1115+13
1037− > (~(dif fe 2) 63 64)
1116+> (~(dif fe 2) 63 64)
1038− 15
1117+15
1039```
1118```
1040
1119
1041---
1120---
@@ -1048,7 +1127,9 @@ Inverts the order of the modular field.
1048
1127
1049#### Accepts
1128#### Accepts
1050
1129
1130+`a` is a `bloq` (and is the sample of the parent core).
1131+
1051−`b` is a `bloq`. (see [`++bloq`](/docs/hoon/reference/stdlib/1c))
1132+`b` is a `bloq`. (see [`$bloq`](/docs/hoon/reference/stdlib/1c#bloq))
1052
1133
1053#### Produces
1134#### Produces
1054
1135
@@ -1057,29 +1138,30 @@ An atom.
1057#### Source
1138#### Source
1058
1139
1059```hoon
1140```hoon
1060− ++ inv |=(b=@ (sub (dec out) (sit b)))
1141+++ inv |=(b=@ (sub (dec out) (sit b)))
1061```
1142```
1062
1143
1063#### Examples
1144#### Examples
1064
1145
1065```
1146```
1066− > (~(inv fe 3) 255)
1147+> (~(inv fe 3) 255)
1067− 0
1148+0
1068−
1069− > (~(inv fe 3) 256)
1149+> (~(inv fe 3) 256)
1070− 255
1071−
1072− > (~(inv fe 3) 0)
1073− 255
1150+255
1074−
1151+```
1075− > (~(inv fe 3) 1)
1076− 254
1077
1152
1153+```
1154+> (~(inv fe 3) 0)
1155+255
1156+> (~(inv fe 3) 1)
1157+254
1078− > (~(inv fe 3) 2)
1158+> (~(inv fe 3) 2)
1079− 253
1159+253
1160+```
1080
1161
1162+```
1081− > (~(inv fe 3) 55)
1163+> (~(inv fe 3) 55)
1082− 200
1164+200
1083```
1165```
1084
1166
1085---
1167---
@@ -1092,7 +1174,9 @@ Reverses bytes within a block.
1092
1174
1093#### Accepts
1175#### Accepts
1094
1176
1177+`a` is a `bloq` (and the sample of the parent core).
1178+
1095−`b` is a `bloq`. (see [`++bloq`](/docs/hoon/reference/stdlib/1c))
1179+`b` is a `bloq`. (see [`$bloq`](/docs/hoon/reference/stdlib/1c#bloq))
1096
1180
1097#### Produces
1181#### Produces
1098
1182
@@ -1101,75 +1185,66 @@ An atom.
1101#### Source
1185#### Source
1102
1186
1103```hoon
1187```hoon
1104− ++ net |= b=@ ^- @
1188+++ net |= b=@ ^- @
1105− => .(b (sit b))
1189+ => .(b (sit b))
1106− ?: (lte a 3)
1190+ ?: (lte a 3)
1107− b
1191+ b
1108− =+ c=(dec a)
1192+ =+ c=(dec a)
1109− %+ con
1193+ %+ con
1110− (lsh c 1 $(a c, b (cut c [0 1] b)))
1194+ (lsh c $(a c, b (cut c [0 1] b)))
1111− $(a c, b (cut c [1 1] b))
1195+ $(a c, b (cut c [1 1] b))
1112```
1196```
1113
1197
1114#### Examples
1198#### Examples
1115
1199
1116```
1200```
1117− > (~(net fe 3) 64)
1201+> (~(net fe 3) 64)
1118− 64
1202+64
1119−
1120− > (~(net fe 3) 128)
1203+> (~(net fe 3) 128)
1121− 128
1204+128
1122−
1123− > (~(net fe 3) 255)
1205+> (~(net fe 3) 255)
1124− 255
1206+255
1125−
1126− > (~(net fe 3) 256)
1207+> (~(net fe 3) 256)
1127− 0
1208+0
1128−
1129− > (~(net fe 3) 257)
1209+> (~(net fe 3) 257)
1130− 1
1131−
1132− > (~(net fe 3) 500)
1133− 244
1134−
1135− > (~(net fe 3) 511)
1136− 255
1137−
1138− > (~(net fe 3) 512)
1139− 0
1140−
1141− > (~(net fe 3) 513)
1142− 1
1210+1
1143−
1211+```
1144− > (~(net fe 3) 0)
1145− 0
1146−
1147− > (~(net fe 3) 1)
1148− 1
1149−
1150− > (~(net fe 0) 1)
1151− 1
1152−
1153− > (~(net fe 0) 2)
1154− 0
1155−
1156− > (~(net fe 0) 3)
1157− 1
1158−
1159− > (~(net fe 6) 1)
1160− 72.057.594.037.927.936
1161−
1162− > (~(net fe 6) 2)
1163− 144.115.188.075.855.872
1164
1212
1213+```
1165− > (~(net fe 6) 3)
1214+> (~(net fe 3) 500)
1166− 216.172.782.113.783.808
1215+244
1216+> (~(net fe 3) 511)
1217+255
1218+> (~(net fe 3) 512)
1219+0
1220+> (~(net fe 3) 513)
1221+1
1222+```
1167
1223
1224+```
1225+> (~(net fe 3) 0)
1226+0
1227+> (~(net fe 3) 1)
1228+1
1229+> (~(net fe 0) 1)
1230+1
1168− > (~(net fe 6) 4)
1231+> (~(net fe 0) 2)
1169− 288.230.376.151.711.744
1232+0
1233+> (~(net fe 0) 3)
1234+1
1235+```
1170
1236
1237+```
1238+> (~(net fe 6) 1)
1239+72.057.594.037.927.936
1240+> (~(net fe 6) 2)
1241+144.115.188.075.855.872
1242+> (~(net fe 6) 3)
1243+216.172.782.113.783.808
1244+> (~(net fe 6) 4)
1245+288.230.376.151.711.744
1171− > (~(net fe 6) 5)
1246+> (~(net fe 6) 5)
1172− 360.287.970.189.639.680
1247+360.287.970.189.639.680
1173```
1248```
1174
1249
1175---
1250---
@@ -1182,7 +1257,7 @@ Produces the maximum integer value that the current block can store; `2^a^a`.
1182
1257
1183#### Accepts
1258#### Accepts
1184
1259
1185−`a` is a `bloq`.
1260+`a` is a `bloq` (and is the sample of the parent core).
1186
1261
1187#### Produces
1262#### Produces
1188
1263
@@ -1191,35 +1266,33 @@ An atom.
1191#### Source
1266#### Source
1192
1267
1193```hoon
1268```hoon
1194− ++ out (bex (bex a))
1269+++ out (bex (bex a))
1195```
1270```
1196
1271
1197#### Examples
1272#### Examples
1198
1273
1199```
1274```
1200− > ~(out fe 0)
1275+> ~(out fe 0)
1201− 2
1276+2
1202−
1203− > ~(out fe 1)
1277+> ~(out fe 1)
1204− 4
1278+4
1205−
1206− > ~(out fe 2)
1279+> ~(out fe 2)
1207− 16
1280+16
1208−
1209− > ~(out fe 3)
1281+> ~(out fe 3)
1210− 256
1282+256
1211−
1212− > ~(out fe 4)
1283+> ~(out fe 4)
1213− 65.536
1284+65.536
1285+```
1214
1286
1287+```
1215− > ~(out fe 10)
1288+> ~(out fe 10)
1216− \/179.769.313.486.231.590.772.930.519.078.902.473.361.797.697.894.230.657.273\/
1289+\/179.769.313.486.231.590.772.930.519.078.902.473.361.797.697.894.230.657.273\/
1217− .430.081.157.732.675.805.500.963.132.708.477.322.407.536.021.120.113.879.87
1290+ .430.081.157.732.675.805.500.963.132.708.477.322.407.536.021.120.113.879.87
1218− 1.393.357.658.789.768.814.416.622.492.847.430.639.474.124.377.767.893.424.8
1291+ 1.393.357.658.789.768.814.416.622.492.847.430.639.474.124.377.767.893.424.8
1219− 65.485.276.302.219.601.246.094.119.453.082.952.085.005.768.838.150.682.342.
1292+ 65.485.276.302.219.601.246.094.119.453.082.952.085.005.768.838.150.682.342.
1220− 462.881.473.913.110.540.827.237.163.350.510.684.586.298.239.947.245.938.479
1293+ 462.881.473.913.110.540.827.237.163.350.510.684.586.298.239.947.245.938.479
1221− .716.304.835.356.329.624.224.137.216
1294+ .716.304.835.356.329.624.224.137.216
1222− \/ \/
1295+\/ \/
1223```
1296```
1224
1297
1225---
1298---
@@ -1232,7 +1305,7 @@ Rolls `d` to the left by `c` `b`-sized blocks.
1232
1305
1233#### Accepts
1306#### Accepts
1234
1307
1235−`a` is a `bloq`.
1308+`a` is a `bloq` (and is the sample of the parent core).
1236
1309
1237`b` is a `bloq`.
1310`b` is a `bloq`.
1238
1311
@@ -1247,30 +1320,32 @@ An atom.
1247#### Source
1320#### Source
1248
1321
1249```hoon
1322```hoon
1250− ++ rol |= [b=bloq c=@ d=@] ^- @
1323+++ rol |= [b=bloq c=@ d=@] ^- @
1251− =+ e=(sit d)
1324+ =+ e=(sit d)
1252− =+ f=(bex (sub a b))
1325+ =+ f=(bex (sub a b))
1253− =+ g=(mod c f)
1326+ =+ g=(mod c f)
1254− (sit (con (lsh b g e) (rsh b (sub f g) e)))
1327+ (sit (con (lsh [b g] e) (rsh [b (sub f g)] e)))
1255```
1328```
1256
1329
1257#### Examples
1330#### Examples
1258
1331
1259```
1332```
1260− > `@ux`(~(rol fe 6) 4 3 0xabac.dedf.1213)
1333+> `@ux`(~(rol fe 6) 4 3 0xabac.dedf.1213)
1261− 0x1213.0000.abac.dedf
1334+0x1213.0000.abac.dedf
1262
1335
1263− > `@ux`(~(rol fe 6) 4 2 0xabac.dedf.1213)
1336+> `@ux`(~(rol fe 6) 4 2 0xabac.dedf.1213)
1264− 0xdedf.1213.0000.abac
1337+0xdedf.1213.0000.abac
1338+```
1265
1339
1340+```
1266− > `@t`(~(rol fe 5) 3 1 'dfgh')
1341+> `@t`(~(rol fe 5) 3 1 'dfgh')
1267− 'hdfg'
1342+'hdfg'
1268
1343
1269− > `@t`(~(rol fe 5) 3 2 'dfgh')
1344+> `@t`(~(rol fe 5) 3 2 'dfgh')
1270− 'ghdf'
1345+'ghdf'
1271
1346
1272− > `@t`(~(rol fe 5) 3 0 'dfgh')
1347+> `@t`(~(rol fe 5) 3 0 'dfgh')
1273− 'dfgh'
1348+'dfgh'
1274```
1349```
1275
1350
1276---
1351---
@@ -1283,7 +1358,7 @@ Rolls `d` to the right by `c` `b`-sized blocks.
1283
1358
1284#### Accepts
1359#### Accepts
1285
1360
1286−`a` is a `bloq`.
1361+`a` is a `bloq` (and is the sample of the parent core).
1287
1362
1288`b` is a `bloq`.
1363`b` is a `bloq`.
1289
1364
@@ -1298,49 +1373,53 @@ An atom.
1298#### Source
1373#### Source
1299
1374
1300```hoon
1375```hoon
1301− ++ ror |= [b=bloq c=@ d=@] ^- @
1376+++ ror |= [b=bloq c=@ d=@] ^- @
1302− =+ e=(sit d)
1377+ =+ e=(sit d)
1303− =+ f=(bex (sub a b))
1378+ =+ f=(bex (sub a b))
1304− =+ g=(mod c f)
1379+ =+ g=(mod c f)
1305− (sit (con (rsh b g e) (lsh b (sub f g) e)))
1380+ (sit (con (rsh [b g] e) (lsh [b (sub f g)] e)))
1306```
1381```
1307
1382
1308#### Examples
1383#### Examples
1309
1384
1310```
1385```
1311− > `@ux`(~(ror fe 6) 4 1 0xabac.dedf.1213)
1386+> `@ux`(~(ror fe 6) 4 1 0xabac.dedf.1213)
1312− 0x1213.0000.abac.dedf
1387+0x1213.0000.abac.dedf
1313
1388
1314− > `@ux`(~(ror fe 6) 3 5 0xabac.dedf.1213)
1389+> `@ux`(~(ror fe 6) 3 5 0xabac.dedf.1213)
1315− 0xacde.df12.1300.00ab
1390+0xacde.df12.1300.00ab
1316
1391
1317− > `@ux`(~(ror fe 6) 3 3 0xabac.dedf.1213)
1392+> `@ux`(~(ror fe 6) 3 3 0xabac.dedf.1213)
1318− 0xdf12.1300.00ab.acde
1393+0xdf12.1300.00ab.acde
1394+```
1319
1395
1396+```
1320− > `@t`(~(rol fe 5) 3 0 'hijk')
1397+> `@t`(~(rol fe 5) 3 0 'hijk')
1321− 'hijk'
1398+'hijk'
1322
1399
1323− > `@t`(~(rol fe 5) 3 1 'hijk')
1400+> `@t`(~(rol fe 5) 3 1 'hijk')
1324− 'khij'
1401+'khij'
1325
1402
1326− > `@t`(~(rol fe 5) 3 2 'hijk')
1403+> `@t`(~(rol fe 5) 3 2 'hijk')
1327− 'jkhi'
1404+'jkhi'
1328```
1405```
1329
1406
1330---
1407---
1331
1408
1332−### `++sit:fe`
1409+### `++sum:fe`
1333
1410
1334−Enforce modulo
1411+Sum
1335
1412
1336−Produces an atom in the current modular block representation.
1413+Sums two numbers in this modular field.
1337
1414
1338#### Accepts
1415#### Accepts
1339
1416
1340−`a` is a `bloq`.
1417+`a` is a `bloq` (and is the sample of the parent core).
1341
1418
1342`b` is an atom.
1419`b` is an atom.
1343
1420
1421+`c` is an atom.
1422+
1344#### Produces
1423#### Produces
1345
1424
1346An atom.
1425An atom.
@@ -1348,62 +1427,51 @@ An atom.
1348#### Source
1427#### Source
1349
1428
1350```hoon
1429```hoon
1351− ++ sit |=(b=@ (end a 1 b))
1430+++ sum |=([b=@ c=@] (sit (add b c)))
1352```
1431```
1353
1432
1354#### Examples
1433#### Examples
1355
1434
1356```
1435```
1357− > (~(sit fe 3) 255)
1436+> (~(sum fe 3) 10 250)
1358− 255
1359−
1360− > (~(sit fe 3) 256)
1361− 0
1362−
1363− > (~(sit fe 3) 257)
1364− 1
1365−
1366− > (~(sit fe 2) 257)
1367− 1
1368−
1369− > (~(sit fe 2) 10.000)
1370− 0
1371−
1372− > (~(sit fe 2) 100)
1373− 4
1437+4
1374−
1438+```
1375− > (~(sit fe 2) 19)
1376− 3
1377−
1378− > (~(sit fe 2) 17)
1379− 1
1380
1439
1381− > (~(sit fe 0) 17)
1440+```
1441+> (~(sum fe 0) 0 1)
1382− 1
1442+1
1443+> (~(sum fe 0) 0 2)
1444+0
1445+```
1383
1446
1384− > (~(sit fe 0) 0)
1447+```
1448+> (~(sum fe 2) 14 2)
1385− 0
1449+0
1450+> (~(sum fe 2) 14 3)
1451+1
1452+```
1386
1453
1387− > (~(sit fe 0) 1)
1454+```
1388− 1
1455+> (~(sum fe 4) 10.000 256)
1456+10.256
1457+> (~(sum fe 4) 10.000 100.000)
1458+44.464
1389```
1459```
1390
1460
1391---
1461---
1392
1462
1393−### `++sum:fe`
1463+### `++sit:fe`
1394
1464
1395−Sum
1465+Enforce modulo
1396
1466
1397−Sums two numbers in this modular field.
1467+Produces an atom in the current modular block representation.
1398
1468
1399#### Accepts
1469#### Accepts
1400
1470
1401−`a` is a `bloq`.
1471+`a` is a `bloq` (and is the sample of the parent core).
1402
1472
1403`b` is an atom.
1473`b` is an atom.
1404
1474
1405−`c` is an atom.
1406−
1407#### Produces
1475#### Produces
1408
1476
1409An atom.
1477An atom.
@@ -1411,32 +1479,40 @@ An atom.
1411#### Source
1479#### Source
1412
1480
1413```hoon
1481```hoon
1414− ++ sum |=([b=@ c=@] (sit (add b c)))
1482+++ sit |=(b=@ (end a b))
1415```
1483```
1416
1484
1417#### Examples
1485#### Examples
1418
1486
1419```
1487```
1420− > (~(sum fe 3) 10 250)
1488+> (~(sit fe 3) 255)
1421− 4
1489+255
1422−
1490+> (~(sit fe 3) 256)
1423− > (~(sum fe 0) 0 1)
1424− 1
1425−
1426− > (~(sum fe 0) 0 2)
1427− 0
1491+0
1428−
1492+> (~(sit fe 3) 257)
1429− > (~(sum fe 2) 14 2)
1493+1
1430− 0
1494+```
1431−
1432− > (~(sum fe 2) 14 3)
1433− 1
1434
1495
1496+```
1497+> (~(sit fe 2) 257)
1498+1
1435− > (~(sum fe 4) 10.000 256)
1499+> (~(sit fe 2) 10.000)
1436− 10.256
1500+0
1501+> (~(sit fe 2) 100)
1502+4
1503+> (~(sit fe 2) 19)
1504+3
1505+> (~(sit fe 2) 17)
1506+1
1507+```
1437
1508
1438− > (~(sum fe 4) 10.000 100.000)
1509+```
1439− 44.464
1510+> (~(sit fe 0) 17)
1511+1
1512+> (~(sit fe 0) 0)
1513+0
1514+> (~(sit fe 0) 1)
1515+1
1440```
1516```
1441
1517
1442---
1518---
content/docs/hoon/reference/stdlib/2d.md+55−54
@@ -4,7 +4,7 @@ weight = 7
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `++con`
7+## `++con`
8
8
9Binary OR
9Binary OR
10
10
@@ -23,22 +23,22 @@ An atom.
23#### Source
23#### Source
24
24
25```hoon
25```hoon
26− ++ con
26+++ con
27− ~/ %con
27+ ~/ %con
28− |= [a=@ b=@]
28+ |= [a=@ b=@]
29− =+ [c=0 d=0]
29+ =+ [c=0 d=0]
30− |- ^- @
30+ |- ^- @
31− ?: ?&(=(0 a) =(0 b)) d
31+ ?: ?&(=(0 a) =(0 b)) d
32− %= $
32+ %= $
33− a (rsh 0 1 a)
33+ a (rsh 0 a)
34− b (rsh 0 1 b)
34+ b (rsh 0 b)
35− c +(c)
35+ c +(c)
36− d %+ add d
36+ d %+ add d
37− %^ lsh 0 c
37+ %+ lsh [0 c]
38− ?& =(0 (end 0 1 a))
38+ ?& =(0 (end 0 a))
39− =(0 (end 0 1 b))
39+ =(0 (end 0 b))
40− ==
40+ ==
41− ==
41+ ==
42```
42```
43
43
44#### Examples
44#### Examples
@@ -97,9 +97,9 @@ contexts. That's because `0` is true in Hoon and `1` is false. Outside of Hoon,
97where `0` is false and `1` is true, bitwise OR is the logical disjunction and
97where `0` is false and `1` is true, bitwise OR is the logical disjunction and
98bitwise AND is the logical conjunction.
98bitwise AND is the logical conjunction.
99
99
100−
101---
100---
101+
102−### `++dis`
102+## `++dis`
103
103
104Binary AND
104Binary AND
105
105
@@ -118,22 +118,22 @@ An atom.
118#### Source
118#### Source
119
119
120```hoon
120```hoon
121− ++ dis
121+++ dis
122− ~/ %dis
122+ ~/ %dis
123− |= [a=@ b=@]
123+ |= [a=@ b=@]
124− =| [c=@ d=@]
124+ =| [c=@ d=@]
125− |- ^- @
125+ |- ^- @
126− ?: ?|(=(0 a) =(0 b)) d
126+ ?: ?|(=(0 a) =(0 b)) d
127− %= $
127+ %= $
128− a (rsh 0 1 a)
128+ a (rsh 0 a)
129− b (rsh 0 1 b)
129+ b (rsh 0 b)
130− c +(c)
130+ c +(c)
131− d %+ add d
131+ d %+ add d
132− %^ lsh 0 c
132+ %+ lsh [0 c]
133− ?| =(0 (end 0 1 a))
133+ ?| =(0 (end 0 a))
134− =(0 (end 0 1 b))
134+ =(0 (end 0 b))
135− ==
135+ ==
136− ==
136+ ==
137```
137```
138
138
139#### Examples
139#### Examples
@@ -187,7 +187,8 @@ where `0` is false and `1` is true, bitwise OR is the logical disjunction and
187bitwise AND is the logical conjunction.
187bitwise AND is the logical conjunction.
188
188
189---
189---
190+
190−### `++mix`
191+## `++mix`
191
192
192Binary XOR
193Binary XOR
193
194
@@ -206,19 +207,19 @@ An atom.
206#### Source
207#### Source
207
208
208```hoon
209```hoon
209− ++ mix
210+++ mix
210− ~/ %mix
211+ ~/ %mix
211− |= [a=@ b=@]
212+ |= [a=@ b=@]
212− ^- @
213+ ^- @
213− =+ [c=0 d=0]
214+ =+ [c=0 d=0]
214− |-
215+ |-
215− ?: ?&(=(0 a) =(0 b)) d
216+ ?: ?&(=(0 a) =(0 b)) d
216− %= $
217+ %= $
217− a (rsh 0 1 a)
218+ a (rsh 0 a)
218− b (rsh 0 1 b)
219+ b (rsh 0 b)
219− c +(c)
220+ c +(c)
220− d (add d (lsh 0 c =((end 0 1 a) (end 0 1 b))))
221+ d (add d (lsh [0 c] =((end 0 a) (end 0 b))))
221− ==
222+ ==
222```
223```
223
224
224#### Examples
225#### Examples
@@ -272,7 +273,8 @@ its samples and its product are stacked.
272```
273```
273
274
274---
275---
276+
275−### `++not`
277+## `++not`
276
278
277Binary NOT
279Binary NOT
278
280
@@ -294,8 +296,8 @@ An atom.
294#### Source
296#### Source
295
297
296```hoon
298```hoon
297− ++ not |= [a=bloq b=@ c=@]
299+++ not |= [a=bloq b=@ c=@]
298− (mix c (dec (bex (mul b (bex a)))))
300+ (mix c (dec (bex (mul b (bex a)))))
299```
301```
300
302
301#### Examples
303#### Examples
@@ -369,5 +371,4 @@ What's happening here may not be readily apparent. But we're only flipping the
369last block of size `1` (bitwidth 2) of the binary `0b111`. That is, we leave
371last block of size `1` (bitwidth 2) of the binary `0b111`. That is, we leave
370the "0b1" piece just the same and manipulate the "11" that the number ends with.
372the "0b1" piece just the same and manipulate the "11" that the number ends with.
371
373
372−
373−---
374+---
content/docs/hoon/reference/stdlib/2e.md+98−178
@@ -4,44 +4,7 @@ weight = 8
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `++fnv`
8−
9−FNV scrambler
10−
11−Hashes an atom with the 32-bit FNV non-cryptographic hash algorithm. Multiplies
12−`a` by the prime number 16,777,619 and then takes the [block](/docs/hoon/reference/stdlib/2c) of size
13−5 off the product's end, producing an atom.
14−
15−#### Accepts
16−
17−`a` is an atom.
18−
19−#### Produces
20−
21−An atom.
22−
23−#### Source
24−
25−```hoon
26− ++ fnv |=(a=@ (end 5 1 (mul 16.777.619 a)))
27−```
28−
29−#### Examples
30−
31−```
32− > (fnv 10.000)
33− 272.465.456
34−
35− > (fnv 10.001)
36− 289.243.075
37−
38− > (fnv 1)
39− 16.777.619
40−```
41−
42−
43−---
44−### `++mug` {#mug}
7+## `++mug` {#mug}
45
8
46murmur3 scrambler
9murmur3 scrambler
47
10
@@ -59,57 +22,70 @@ An atom.
59#### Source
22#### Source
60
23
61```hoon
24```hoon
62−++ mug :: mug with murmur3
25+++ mug
63 ~/ %mug
26 ~/ %mug
64− |= a/*
27+ |= a=*
65− |^ (trim ?@(a a (mix $(a -.a) (mix 0x7fff.ffff $(a +.a)))))
28+ |^ ?@ a (mum 0xcafe.babe 0x7fff a)
66− ++ trim :: 31-bit nonzero
29+ =/ b (cat 5 $(a -.a) $(a +.a))
30+ (mum 0xdead.beef 0xfffe b)
31+ ::
32+ ++ mum
33+ |= [syd=@uxF fal=@F key=@]
67− |= key/@
34+ =/ wyd (met 3 key)
68− =+ syd=0xcafe.babe
35+ =| i=@ud
69− |- ^- @
36+ |- ^- @F
37+ ?: =(8 i) fal
70− =+ haz=(muk syd (met 3 key) key)
38+ =/ haz=@F (muk syd wyd key)
71− =+ ham=(mix (rsh 0 31 haz) (end 0 31 haz))
39+ =/ ham=@F (mix (rsh [0 31] haz) (end [0 31] haz))
72− ?.(=(0 ham) ham $(syd +(syd)))
40+ ?.(=(0 ham) ham $(i +(i), syd +(syd)))
73 --
41 --
74```
42```
75
43
76#### Examples
44#### Examples
77
45
78```
46```
79− > (mug 10.000)
47+> (mug 10.000)
80− 795.713.195
48+795.713.195
81−
49+```
82− > (mug 10.001)
83− 420.521.697
84
50
51+```
85− > (mug 1)
52+> (mug 10.001)
86− 1.901.865.568
53+420.521.697
54+```
87
55
56+```
88− > (mug (some 10))
57+> (mug 1)
89− 2.099.076.946
58+1.901.865.568
59+```
90
60
91− > (mug [1 2 3 4 5 ~])
61+```
92− 1.719.833.228
62+> (mug (some 10))
63+750.200.080
93```
64```
94
65
66+```
67+> (mug [1 2 3 4 5 ~])
68+1.565.443.491
69+```
95
70
96---
71---
72+
97−### `++muk`
73+## `++muk`
98
74
99Standard MurmurHash3
75Standard MurmurHash3
100
76
101Implementation of the 32-bit
77Implementation of the 32-bit
102[MurmurHash3](https://en.wikipedia.org/wiki/MurmurHash#Algorithm)
78[MurmurHash3](https://en.wikipedia.org/wiki/MurmurHash#Algorithm)
103−non-cryptographic hash algorithm. Takes `a` as the seed, `b` as the key length
79+non-cryptographic hash algorithm. Takes `syd` as the seed, `len` as the key length
104−in [blocks](/docs/hoon/reference/stdlib/2c) of size 3, and `c` as the key, producing an atom.
80+in [blocks](/docs/hoon/reference/stdlib/2c) of size 3, and `key` as the key, producing an atom.
105
81
106#### Accepts
82#### Accepts
107
83
108−`a` is an atom.
84+`syd` is an atom.
109
85
110−`b` is an atom.
86+`len` is an atom.
111
87
112−`c` is an atom.
88+`key` is an atom.
113
89
114#### Produces
90#### Produces
115
91
@@ -118,63 +94,63 @@ An atom.
118#### Source
94#### Source
119
95
120```hoon
96```hoon
121− ++ muk
97+++ muk :: standard murmur3
122− ~% %muk ..muk ~
98+ ~% %muk ..muk ~
123− =+ ~(. fe 5)
99+ =+ ~(. fe 5)
124− |= [syd=@ len=@ key=@]
100+ |= [syd=@ len=@ key=@]
125− ?> &((lte (met 5 syd) 1) (lte (met 0 len) 31))
101+ =. syd (end 5 syd)
126− =/ pad (sub len (met 3 key))
102+ =/ pad (sub len (met 3 key))
127− =/ data (weld (rip 3 key) (reap pad 0))
103+ =/ data (weld (rip 3 key) (reap pad 0))
128− =/ nblocks (div len 4) :: intentionally off-by-one
104+ =/ nblocks (div len 4) :: intentionally off-by-one
129− =/ h1 syd
105+ =/ h1 syd
130− =+ [c1=0xcc9e.2d51 c2=0x1b87.3593]
106+ =+ [c1=0xcc9e.2d51 c2=0x1b87.3593]
131− =/ blocks (rip 5 key)
107+ =/ blocks (rip 5 key)
132− =/ i nblocks
108+ =/ i nblocks
133− =. h1 =/ hi h1 |-
109+ =. h1 =/ hi h1 |-
110+ ?: =(0 i) hi
134− ?: =(0 i) hi :: negative array index
111+ =/ k1 (snag (sub nblocks i) blocks) :: negative array index
135− =/ k1 (snag (sub nblocks i) blocks)
136− =. k1 (sit (mul k1 c1))
112+ =. k1 (sit (mul k1 c1))
137− =. k1 (rol 0 15 k1)
113+ =. k1 (rol 0 15 k1)
138− =. k1 (sit (mul k1 c2))
114+ =. k1 (sit (mul k1 c2))
139− =. hi (mix hi k1)
115+ =. hi (mix hi k1)
140− =. hi (rol 0 13 hi)
116+ =. hi (rol 0 13 hi)
141− =. hi (sum (sit (mul hi 5)) 0xe654.6b64)
117+ =. hi (sum (sit (mul hi 5)) 0xe654.6b64)
142− $(i (dec i))
118+ $(i (dec i))
143− =/ tail (slag (mul 4 nblocks) data)
119+ =/ tail (slag (mul 4 nblocks) data)
144− =/ k1 0
120+ =/ k1 0
145− =/ tlen (dis len 3)
121+ =/ tlen (dis len 3)
146− =. h1
122+ =. h1
147− ?+ tlen h1 :: fallthrough switch
123+ ?+ tlen h1 :: fallthrough switch
148− $3 =. k1 (mix k1 (lsh 0 16 (snag 2 tail)))
124+ %3 =. k1 (mix k1 (lsh [0 16] (snag 2 tail)))
149− =. k1 (mix k1 (lsh 0 8 (snag 1 tail)))
125+ =. k1 (mix k1 (lsh [0 8] (snag 1 tail)))
150− =. k1 (mix k1 (snag 0 tail))
126+ =. k1 (mix k1 (snag 0 tail))
151− =. k1 (sit (mul k1 c1))
127+ =. k1 (sit (mul k1 c1))
152− =. k1 (rol 0 15 k1)
128+ =. k1 (rol 0 15 k1)
153− =. k1 (sit (mul k1 c2))
129+ =. k1 (sit (mul k1 c2))
154− (mix h1 k1)
130+ (mix h1 k1)
155− $2 =. k1 (mix k1 (lsh 0 8 (snag 1 tail)))
131+ %2 =. k1 (mix k1 (lsh [0 8] (snag 1 tail)))
156− =. k1 (mix k1 (snag 0 tail))
132+ =. k1 (mix k1 (snag 0 tail))
157− =. k1 (sit (mul k1 c1))
133+ =. k1 (sit (mul k1 c1))
158− =. k1 (rol 0 15 k1)
134+ =. k1 (rol 0 15 k1)
159− =. k1 (sit (mul k1 c2))
135+ =. k1 (sit (mul k1 c2))
160− (mix h1 k1)
136+ (mix h1 k1)
161− $1 =. k1 (mix k1 (snag 0 tail))
137+ %1 =. k1 (mix k1 (snag 0 tail))
162− =. k1 (sit (mul k1 c1))
138+ =. k1 (sit (mul k1 c1))
163− =. k1 (rol 0 15 k1)
139+ =. k1 (rol 0 15 k1)
164− =. k1 (sit (mul k1 c2))
140+ =. k1 (sit (mul k1 c2))
165− (mix h1 k1)
141+ (mix h1 k1)
166− ==
142+ ==
167− =. h1 (mix h1 len)
143+ =. h1 (mix h1 len)
168− |^ (fmix32 h1)
144+ |^ (fmix32 h1)
169− ++ fmix32
145+ ++ fmix32
170− |= h=@
146+ |= h=@
171− =. h (mix h (rsh 0 16 h))
147+ =. h (mix h (rsh [0 16] h))
172− =. h (sit (mul h 0x85eb.ca6b))
148+ =. h (sit (mul h 0x85eb.ca6b))
173− =. h (mix h (rsh 0 13 h))
149+ =. h (mix h (rsh [0 13] h))
174− =. h (sit (mul h 0xc2b2.ae35))
150+ =. h (sit (mul h 0xc2b2.ae35))
175− =. h (mix h (rsh 0 16 h))
151+ =. h (mix h (rsh [0 16] h))
176− h
152+ h
177− --
153+ --
178```
154```
179
155
180#### Examples
156#### Examples
@@ -209,60 +185,4 @@ An atom.
209 246.077.549
185 246.077.549
210```
186```
211
187
212−
213−---
214−### `++mum`
215−
216−31-bit MurmurHash3 scrambler
217−
218−Hashes `a` with the 31-bit MurmurHash3 non-cryptographic hash algorithm,
219−producing an atom.
220−
221−#### Accepts
222−
223−`a` is a noun.
224−
225−#### Produces
226−
227−An atom.
228−
229−#### Source
230−
231−```hoon
232− ++ mum
233− ~/ %mum
234− |= a=*
235− |^ (trim ?@(a a (mix $(a -.a) (mix 0x7fff.ffff $(a +.a)))))
236− ++ trim
237− |= key=@
238− =+ syd=0xcafe.babe
239− |- ^- @
240− =+ haz=(muk syd (met 3 key) key)
241− =+ ham=(mix (rsh 0 31 haz) (end 0 31 haz))
242− ?.(=(0 ham) ham $(syd +(syd)))
243−```
244−
245−#### Examples
246−
247−```
248− > (mum 10.000)
249− 795.713.195
250−
251− > (mum 10.001)
252− 420.521.697
253−
254− > (mum 'jerry')
255− 1.540.161.753
256−
257− > (mum 1)
258− 1.901.865.568
259−
260− > (mum (some 10))
261− 2.099.076.946
262−
263− > (mum [1 2 3 4 5 ~])
264− 1.719.833.228
265−```
266−
267−
268---
188---
content/docs/hoon/reference/stdlib/2f.md+163−285
@@ -4,11 +4,11 @@ weight = 9
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `++aor`
7+## `++aor`
8
8
9Alphabetical order
9Alphabetical order
10
10
11−Computes whether `a` and `b` are in alphabetical order, producing a flag.
11+Computes whether `a` and `b` are in alphabetical order, producing a flag. Orders atoms before cells, and atoms in ascending LSB order.
12
12
13#### Accepts
13#### Accepts
14
14
@@ -23,62 +23,85 @@ A flag.
23#### Source
23#### Source
24
24
25```hoon
25```hoon
26− ++ aor
26+++ aor
27− ~/ %aor
27+ ~/ %aor
28− |= [a=* b=*]
28+ |= [a=* b=*]
29− ^- ?
29+ ^- ?
30− ?: =(a b) &
30+ ?: =(a b) &
31− ?. ?=(@ a)
31+ ?. ?=(@ a)
32− ?: ?=(@ b) |
32+ ?: ?=(@ b) |
33− ?: =(-.a -.b)
33+ ?: =(-.a -.b)
34− $(a +.a, b +.b)
34+ $(a +.a, b +.b)
35− $(a -.a, b -.b)
35+ $(a -.a, b -.b)
36− ?. ?=(@ b) &
36+ ?. ?=(@ b) &
37− |-
37+ |-
38− =+ [c=(end 3 1 a) d=(end 3 1 b)]
38+ =+ [c=(end 3 a) d=(end 3 b)]
39− ?: =(c d)
39+ ?: =(c d)
40− $(a (rsh 3 1 a), b (rsh 3 1 b))
40+ $(a (rsh 3 a), b (rsh 3 b))
41− (lth c d)
41+ (lth c d)
42```
42```
43
43
44#### Examples
44#### Examples
45
45
46```
46```
47− > (aor 'a' 'b')
47+> (aor 'a' 'b')
48− %.y
48+%.y
49−
50− > (aor 'b' 'a')
49+> (aor 'b' 'a')
51− %.n
50+%.n
52−
51+> (aor 'a' 'a')
52+%.y
53+
53− > (aor 'a' 'a')
54+> (aor 1 2)
55+%.y
56+> (aor 2 1)
57+%.n
58+
59+> (aor ['a' ~] 'b')
60+%.n
61+> (aor 'b' ['a' ~])
62+%.y
63+
64+> (aor ['a' ~] ['b' ~])
54− %.y
65+%.y
55−
66+> (aor ['b' ~] ['a' ~])
56− > (aor "foo" "bar")
67+%.n
57− %.n
68+
58−
69+> (aor "abca" "abcz")
59− > (aor "bar" "foo")
70+%.y
71+> (aor "abcz" "abca")
72+%.n
73+
74+> (aor 0b1011 0b1010)
75+%.n
76+> (aor 0b1010 0b1011)
77+%.y
78+
79+> (aor [1 2] [2 1])
60− %.y
80+%.y
81+> (aor [2 1] [1 2])
82+%.n
83+```
61
84
62− > (aor "abcdefz" "abcdefa")
85+Note the possible differences with `+dor` due to comparing one byte at a time:
63− %.n
64
86
65− > (aor "abcdefa" "abcdefz")
66− %.y
67−
68− > (aor 10.000 17.000)
69− %.y
70−
71− > (aor 10 9)
72− %.n
73```
87```
88+> (aor 0b1001.0000.0000 0b1000.1000.0000)
89+%.y
90+> (dor 0b1001.0000.0000 0b1000.1000.0000)
91+%.n
92+```
93+
94+#### Discussion
74
95
96+This is different than [+dor](#dor) in that it compares atoms one byte at a time, while `+dor` compares whole atoms at once. Note that because it simply compares bytes, it doesn't account for multi-byte UTF-8 characters and the like.
75
97
76---
98---
77−### `++dor`
78
99
100+## `++dor`
101+
79−Numeric order
102+Depth order
80
103
81−Computes whether `a` and `b` are in ascending numeric order, producing a flag.
104+Computes whether `a` and `b` are in ascending tree depth order, producing a flag. Orders atoms before cells, and atoms in ascending numerical order.
82
105
83#### Accepts
106#### Accepts
84
107
@@ -93,62 +116,71 @@ A flag.
93#### Source
116#### Source
94
117
95```hoon
118```hoon
96− ++ dor
119+++ dor
97− ~/ %dor
120+ ~/ %dor
98− |= [a=* b=*]
121+ |= [a=* b=*]
99− ^- ?
122+ ^- ?
100− ?: =(a b) &
123+ ?: =(a b) &
101− ?. ?=(@ a)
124+ ?. ?=(@ a)
102− ?: ?=(@ b) |
125+ ?: ?=(@ b) |
103− ?: =(-.a -.b)
126+ ?: =(-.a -.b)
104− $(a +.a, b +.b)
127+ $(a +.a, b +.b)
105− $(a -.a, b -.b)
128+ $(a -.a, b -.b)
106− ?. ?=(@ b) &
129+ ?. ?=(@ b) &
107− (lth a b)
130+ (lth a b)
108```
131```
109
132
110#### Examples
133#### Examples
111
134
112```
135```
113− > (dor 1 2)
136+> (dor 1 2)
114− %.y
137+%.y
115
138
116− > (dor 2 1)
139+> (dor 2 1)
117− %.n
140+%.n
118
141
119− > (dor ~[1 2 3] ~[1 2 4])
142+> (dor ~[1 2 3] ~[1 2 4])
120− %.y
143+%.y
121
144
122− > (dor ~[1 2 4] ~[1 2 3])
145+> (dor ~[1 2 4] ~[1 2 3])
123− %.n
146+%.n
124
147
125− > (dor `(list @)`~[99 100 10.000] ~[99 101 10.000])
148+> (dor `(list @)`~[99 100 10.000] ~[99 101 10.000])
126− %.y
149+%.y
127
150
128− > (dor ~[99 101 10.999] `(list @)`~[99 100 10.000])
151+> (dor ~[99 101 10.999] `(list @)`~[99 100 10.000])
129− %.n
152+%.n
153+```
154+
155+Note the possible difference with [+aor](#aor) due to comparing whole atoms rather than one byte at a time:
156+
157+```
158+> (aor 0b1001.0000.0000 0b1000.1000.0000)
159+%.y
160+> (dor 0b1001.0000.0000 0b1000.1000.0000)
161+%.n
130```
162```
131
163
132#### Discussion
164#### Discussion
133
165
134−If `a` and `b` are both atoms, `dor` is equivalent to [`lte`](/docs/hoon/reference/stdlib/1a). If they're
166+If `a` and `b` are both atoms, `dor` is equivalent to [`lte`](/docs/hoon/reference/stdlib/1a#lte). If they're
135cells, `dor` recurses on the heads, and then if the heads are the same it checks
167cells, `dor` recurses on the heads, and then if the heads are the same it checks
136the tails.
168the tails.
137
169
138If one sample is a cell and the other is an atom, the cell sample is treated as
170If one sample is a cell and the other is an atom, the cell sample is treated as
139"greater."
171"greater."
140
172
141−
142---
173---
143−### `++gor`
144
174
175+## `++gor`
176+
145−Hash order
177+Mug order
146
178
147Computes whether of `(mug a)` and `(mug b)` are in ascending numeric order,
179Computes whether of `(mug a)` and `(mug b)` are in ascending numeric order,
148producing a flag. If the `mug` hashes are equal, `a` and `b` are compared by
180producing a flag. If the `mug` hashes are equal, `a` and `b` are compared by
149`dor` instead.
181`dor` instead.
150
182
151−[`mug`](/docs/hoon/reference/stdlib/2e) is the the 31-bit nonzero FNV-1a hash algorithm.
183+[`mug`](/docs/hoon/reference/stdlib/2e#mug) is the the 31-bit nonzero FNV-1a hash algorithm.
152
184
153#### Accepts
185#### Accepts
154
186
@@ -163,223 +195,70 @@ A flag.
163#### Source
195#### Source
164
196
165```hoon
197```hoon
166− ++ gor
198+++ gor
167− ~/ %gor
199+ ~/ %gor
168− |= [a=* b=*]
200+ |= [a=* b=*]
169− ^- ?
201+ ^- ?
170− =+ [c=(mug a) d=(mug b)]
202+ =+ [c=(mug a) d=(mug b)]
171− ?: =(c d)
203+ ?: =(c d)
172− (dor a b)
204+ (dor a b)
173− (lth c d)
205+ (lth c d)
174```
206```
175
207
176#### Examples
208#### Examples
177
209
178```
210```
179− > (gor 'd' 'c')
211+> (gor 'd' 'c')
180− %.y
212+%.y
181−
213+
182− > 'd'
214+> 'd'
183− 'd'
215+'d'
184−
185− > 'c'
216+> 'c'
186− 'c'
217+'c'
187−
218+
188− > `@ud`'d'
219+> `@ud`'d'
189− 100
220+100
190−
191− > `@ud`'c'
221+> `@ud`'c'
192− 99
222+99
193−
223+
194− > (mug 'd')
224+> (mug 'd')
195− 1.628.185.714
225+1.628.185.714
196−
197− > (mug 'c')
226+> (mug 'c')
198− 1.712.073.811
227+1.712.073.811
199−
228+
200− > (gor 'd' 'c')
229+> (gor 'd' 'c')
201− %.y
230+%.y
202−
203− > (gor 'c' 'd')
231+> (gor 'c' 'd')
204− %.n
232+%.n
205−
206− > (gor "foo" "bar")
207− %.n
208−
209− > (gor (some 10) `(list @)`[1 2 3 ~])
210− %.n
211−```
212−
213−#### Discussion
214−
215−`map`s use `gor` on the key for horizontal ordering and `vor` for
216−vertical order. `map`s only look at the keys (the head of the key-value pair
217−elements) for ordering.
218−
219−---
220−### `++hor`
221−
222−Horizontal hash order
223−
224−If `a` and `b` are atoms, they are computed as samples of `gor`, producing a
225−flag.
226−
227−If `a` and `b` are cells, `hor` checks to see if their heads are equal. If their
228−heads are equal, `gor` is computed on their tails, producing a flag. If their
229−heads are not equal, `gor` is computed on their heads, producing a flag.
230−
231−If `a` is an atom and `b` is not, then `%.y` is produced. If `b` is an atom and
232−`a` is not, `%.n` is produced.
233−
234−#### Accepts
235−
236−`a` is a noun.
237−
238−`b` is a noun.
239−
240−#### Produces
241−
242−A flag.
243−
244−#### Source
245−
246−```hoon
247− ++ hor
248− ~/ %hor
249− |= [a=* b=*]
250− ^- ?
251− ?: ?=(@ a)
252− ?. ?=(@ b) &
253− (gor a b)
254− ?: ?=(@ b) |
255− ?: =(-.a -.b)
256− (gor +.a +.b)
257− (gor -.a -.b)
258−```
259−
260−#### Examples
261−
262```
233```
263− > (hor . 1)
264− %.n
265−
266− > (hor 1 2)
267− %.y
268−
269− > (hor "abc" "cba")
270− %.y
271−
272− > (hor 'c' 'd')
273− %.n
274−
275− > (hor 100 [1 1])
276− %.y
277−
278− > (hor [1 1] 100)
279− %.n
280−
281− > (hor 500.000.000 "foo")
282− %.y
283−
284− > (hor "foo" 500.000.000)
285− %.n
286−
287− > (hor 0 "foo")
288− %.y
289
234
290− > (gor `(list @)`[0 ~] 1)
291− %.n
292−
293− > (hor `(list @)`[50 500 5.000 ~] 1)
294− %.n
295```
235```
296−
236+> (gor "foo" "bar")
297−#### Discussion
237+%.n
298−
299−Sets (+set, +in) use `hor` for their horizontal order and `vor` for their
300−vertical order. See [`apt:in`](/docs/hoon/reference/stdlib/2h) to see how a set verifies its correctness.
301−`vor` is used to verify.
302−
303−---
304−### `++lor`
305−
306−Leg order
307−
308−Computes whether the corresponding legs of `a` and `b` are in ascending
309−numeric order, producing a flag.
310−
311−#### Accepts
312−
313−`a` is a noun.
314−
315−`b` is a noun.
316−
317−#### Accepts
318−
319−A flag.
320−
321−#### Source
322−
323−```hoon
324− ++ lor
325− ~/ %lor
326− |= [a=* b=*]
327− ^- ?
328− ?: =(a b) &
329− ?@ a
330− ?^ b &
331− (lth a b)
332− ?: =(-.a -.b)
333− $(a +.a, b +.b)
334− $(a -.a, b -.b)
335```
238```
336
239
337−#### Examples
338−
339```
240```
340− > (lor 1 2)
341− %.y
342−
343− > (lor 2 1)
344− %.n
345−
346− > (lor 9 [1 2])
347− %.y
348−
349− > (lor `(list @)`[1 2 3 ~] `(list @)`[1 2 3 4 ~])
350− %.y
351−
352− > (lor `(list @)`[1 2 3 ~] `(list @)`[1 2 2 ~])
353− %.n
354−
355− > (lor `(list @)`[1 2 3 ~] `(list @)`[2 2 ~])
241+> (gor (some 10) `(list @)`[1 2 3 ~])
356− %.y
357−
358− > (lor [2 2 5] [1 5 9 8])
359− %.n
242+%.n
360−
361− > (lor [1 5 8] [1 5 9 8])
362− %.y
363−
364− > (lor [1 2 3] [1 2])
365− !! exit
366```
243```
367
244
368#### Discussion
245#### Discussion
369
246
370−`lor` is no longer used internally.
247+`map`s use `gor` on the key for horizontal ordering and `mor` for
248+vertical order. `map`s only look at the keys (the head of the key-value pair
249+elements) for ordering.
371
250
372---
251---
373−### `++vor`
374
252
253+## `++mor`
254+
375−Vertical order
255+(more) mug order
376
256
377Computes whether the double-hashes `(mug (mug a))` and `(mug (mug b))` are in
257Computes whether the double-hashes `(mug (mug a))` and `(mug (mug b))` are in
378ascending numeric order, producing a flag. If the double-`mug` hashes are
258ascending numeric order, producing a flag. If the double-`mug` hashes are
379equal, `a` and `b` are compared by `dor` instead.
259equal, `a` and `b` are compared by `dor` instead.
380
260
381−[`mug`](/docs/hoon/reference/stdlib/2e) is the the 31-bit nonzero FNV-1a hash algorithm.
261+[`mug`](/docs/hoon/reference/stdlib/2e#mug) is the the 31-bit nonzero FNV-1a hash algorithm.
382−
383
262
384#### Accepts
263#### Accepts
385
264
@@ -394,20 +273,20 @@ A flag.
394#### Source
273#### Source
395
274
396```hoon
275```hoon
397− ++ vor
276+++ mor
398− ~/ %vor
277+ ~/ %mor
399− |= [a=* b=*]
278+ |= [a=* b=*]
400− ^- ?
279+ ^- ?
401− =+ [c=(mug (mug a)) d=(mug (mug b))]
280+ =+ [c=(mug (mug a)) d=(mug (mug b))]
402− ?: =(c d)
281+ ?: =(c d)
403− (dor a b)
282+ (dor a b)
404− (lth c d)
283+ (lth c d)
405```
284```
406
285
407#### Examples
286#### Examples
408
287
409```
288```
410− > (vor 'f' 'g')
289+ > (mor 'f' 'g')
411 %.y
290 %.y
412
291
413 > [(mug 'f') (mug 'g')]
292 > [(mug 'f') (mug 'g')]
@@ -416,22 +295,21 @@ A flag.
416 > [(mug (mug 'f')) (mug (mug 'g'))]
295 > [(mug (mug 'f')) (mug (mug 'g'))]
417 [261.421.509 1.861.258.547]
296 [261.421.509 1.861.258.547]
418
297
419− > (vor 'a' 'z')
298+ > (mor 'a' 'z')
420 %.n
299 %.n
421
300
422− > (vor 43.326 41.106)
301+ > (mor 43.326 41.106)
423 %.n
302 %.n
424```
303```
425
304
426#### Discussion
305#### Discussion
427
306
428−Maps, sets, and queues all use `vor` to check for vertical ordering. Maps and
307+Maps, sets, and queues all use `mor` to check for vertical ordering. Maps and
429−sets also use `gor` and `hor` for horizontal order, respectively, but queues use
308+sets also use `gor` for horizontal order, but queues use
430vertical ordering alone.
309vertical ordering alone.
431
310
432−Since hashing removes correlation, double-`mug`ging with `vor` removes
311+Since hashing removes correlation, double-`mug`ging with `mor` removes
433−correlation with single-`mug`ged `hor`. Vertical order becomes uncorrelated
312+correlation with single-`mug`ged `gor`. Vertical order becomes uncorrelated
434with horizontal order.
313with horizontal order.
435
314
436−
437−---
315+---
content/docs/hoon/reference/stdlib/2g.md+26−26
@@ -4,7 +4,7 @@ weight = 10
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `++pow`
7+## `++pow`
8
8
9Computes `a` raised to the power of `b`, producing an atom.
9Computes `a` raised to the power of `b`, producing an atom.
10
10
@@ -21,14 +21,14 @@ An atom.
21#### Source
21#### Source
22
22
23```hoon
23```hoon
24− ++ pow
24+++ pow
25− ~/ %pow
25+ ~/ %pow
26− |= [a=@ b=@]
26+ |= [a=@ b=@]
27− ?: =(b 0) 1
27+ ?: =(b 0) 1
28− |- ?: =(b 1) a
28+ |- ?: =(b 1) a
29− =+ c=$(b (div b 2))
29+ =+ c=$(b (div b 2))
30− =+ d=(mul c c)
30+ =+ d=(mul c c)
31− ?~ (dis b 1) d (mul d a)
31+ ?~ (dis b 1) d (mul d a)
32```
32```
33
33
34#### Examples
34#### Examples
@@ -51,7 +51,8 @@ An atom.
51```
51```
52
52
53---
53---
54+
54−### `++sqt`
55+## `++sqt`
55
56
56Computes the square root of `a` and its remainder.
57Computes the square root of `a` and its remainder.
57
58
@@ -66,20 +67,20 @@ A cell of atoms.
66#### Source
67#### Source
67
68
68```hoon
69```hoon
69− ++ sqt
70+++ sqt
70− ~/ %sqt
71+ ~/ %sqt
71− |= a=@ ^- [p=@ q=@]
72+ |= a=@ ^- [p=@ q=@]
72− ?~ a [0 0]
73+ ?~ a [0 0]
73− =+ [q=(div (dec (xeb a)) 2) r=0]
74+ =+ [q=(div (dec (xeb a)) 2) r=0]
74− =- [-.b (sub a +.b)]
75+ =- [-.b (sub a +.b)]
75− ^= b |-
76+ ^= b |-
76− =+ s=(add r (bex q))
77+ =+ s=(add r (bex q))
77− =+ t=(mul s s)
78+ =+ t=(mul s s)
78− ?: =(q 0)
79+ ?: =(q 0)
79− ?:((lte t a) [s t] [r (mul r r)])
80+ ?:((lte t a) [s t] [r (mul r r)])
80− ?: (lte t a)
81+ ?: (lte t a)
81− $(r s, q (dec q))
82+ $(r s, q (dec q))
82− $(q (dec q))
83+ $(q (dec q))
83```
84```
84
85
85#### Examples
86#### Examples
@@ -101,5 +102,4 @@ A cell of atoms.
101 ! exit
102 ! exit
102```
103```
103
104
104−
105−---
105+---
content/docs/hoon/reference/stdlib/2h.md+345−345
@@ -4,7 +4,7 @@ weight = 11
4template = "doc.html"
4template = "doc.html"
5+++
5+++
6
6
7−### `++in`
7+## `++in`
8
8
9Set operations
9Set operations
10
10
@@ -18,16 +18,16 @@ A `set`.
18#### Source
18#### Source
19
19
20```hoon
20```hoon
21− ++ in
22− ~/ %in
21+ ~/ %in
23− |_ a=(set)
22+ =| a=(tree)
23+ |@
24```
24```
25
25
26#### Examples
26#### Examples
27
27
28```
28```
29− > ~(. in (sy "asd"))
29+> ~(. in (sy "asd"))
30− <13.evb [nlr(^$1{@tD $1}) <414.fvk 101.jzo 1.ypj %164>]>
30+<16.ufw [a=?(%~ [?(n=@tD n=#1) l=nlr(?(@tD #1)) r=nlr(?(@tD ^#1.?(@tD #1)))]) <123.zao 46.hgz 1.pnw %140>]>
31```
31```
32
32
33### `++all:in`
33### `++all:in`
@@ -39,9 +39,9 @@ flag.
39
39
40#### Accepts
40#### Accepts
41
41
42−`a` is a `set`.
42+`a` is a `set`, and is the sample of `+in`.
43
43
44−`b` is a wet gate that accepts a noun and produces a flag.
44+`b` is a gate that accepts a noun and produces a flag.
45
45
46#### Produces
46#### Produces
47
47
@@ -50,28 +50,27 @@ A flag.
50#### Source
50#### Source
51
51
52```hoon
52```hoon
53− ++ all :: logical AND
53+++ all
54− ~/ %all
54+ ~/ %all
55− |* b=$-(* ?)
55+ |* b=$-(* ?)
56− |- ^- ?
56+ |- ^- ?
57− ?~ a
57+ ?~ a
58− &
58+ &
59− ?&((b n.a) $(a l.a) $(a r.a))
59+ ?&((b n.a) $(a l.a) $(a r.a))
60```
60```
61
61
62#### Examples
62#### Examples
63
63
64```
64```
65− > =b (sy `(list [@t *])`[['a' 1] ['b' [2 3]] ~])
65+> (~(all in (silt ~[1 2 3 4])) |=(a=@ (lth a 5)))
66− > (~(all in b) |=(a=* ?@(+.a & |)))
66+%.y
67− %.n
68
67
69− > =b (sy `(list @t)`['john' 'bonita' 'daniel' 'madeleine' ~])
70− > (~(all in b) |=(a=@t (gte a 100)))
68+> (~(all in (silt ~[1 2 3 4 5])) |=(a=@ (lth a 5)))
71− %.y
69+%.n
72```
70```
73
71
74---
72---
73+
75### `++any:in`
74### `++any:in`
76
75
77Logical OR
76Logical OR
@@ -81,7 +80,7 @@ flag.
81
80
82#### Accepts
81#### Accepts
83
82
84−`a` is a `set`.
83+`a` is a `set`, and is the sample of `+in`.
85
84
86`b` is a gate that accepts a noun and produces a flag.
85`b` is a gate that accepts a noun and produces a flag.
87
86
@@ -92,28 +91,27 @@ A flag.
92#### Source
91#### Source
93
92
94```hoon
93```hoon
95− ++ any :: logical OR
94+++ any
96− ~/ %any
95+ ~/ %any
97− |* b=$-(* ?)
96+ |* b=$-(* ?)
98− |- ^- ?
97+ |- ^- ?
99− ?~ a
98+ ?~ a
100− |
99+ |
101− ?|((b n.a) $(a l.a) $(a r.a))
100+ ?|((b n.a) $(a l.a) $(a r.a))
102```
101```
103
102
104#### Examples
103#### Examples
105
104
106```
105```
107− > =b (sy `(list [@t *])`[['a' 1] ['b' [2 3]] ~])
108− > (~(any in b) |=(a/* ?@(+.a & |)))
106+> (~(any in (silt ~[2 3 4 5])) |=(a=@ (lth a 3)))
109− %.y
107+%.y
110
108
111− > =b (sy `(list @t)`['john' 'bonita' 'daniel' 'madeleine' ~])
112− > (~(any in b) |=(a=@t (lte a 100)))
109+> (~(any in (silt ~[3 4 5])) |=(a=@ (lth a 3)))
113− %.n
110+%.n
114```
111```
115
112
116---
113---
114+
117### `++apt:in`
115### `++apt:in`
118
116
119Check correctness
117Check correctness
@@ -132,36 +130,38 @@ A flag.
132#### Source
130#### Source
133
131
134```hoon
132```hoon
135− ++ apt :: check correctness
133+++ apt
136− =< $
134+ =< $
137− ~/ %apt
135+ ~/ %apt
138− =| [l=(unit) r=(unit)]
136+ =| [l=(unit) r=(unit)]
139− |. ^- ?
137+ |. ^- ?
140− ?~ a &
138+ ?~ a &
141− ?& ?~(l & (gor n.a u.l))
139+ ?& ?~(l & (gor n.a u.l))
142− ?~(r & (gor u.r n.a))
140+ ?~(r & (gor u.r n.a))
143− ?~(l.a & ?&((mor n.a n.l.a) $(a l.a, l `n.a)))
141+ ?~(l.a & ?&((mor n.a n.l.a) $(a l.a, l `n.a)))
144− ?~(r.a & ?&((mor n.a n.r.a) $(a r.a, r `n.a)))
142+ ?~(r.a & ?&((mor n.a n.r.a) $(a r.a, r `n.a)))
145− ==
143+ ==
146```
144```
147
145
148#### Examples
146#### Examples
149
147
150```
148```
151− > ~(apt in ~)
149+> ~(apt in ~)
152− %.y
150+%.y
151+```
153
152
153+```
154− > =a (sy [1 2 3 4 5 6 ~])
154+> =a (silt ~[1 2 3])
155− > a
155+> a
156− [n=6 l={5 4} r={1 3 2}]
156+[n=2 l={1} r={3}]
157− > ~(apt in a)
157+> ~(apt in a)
158− %.y
158+%.y
159
159
160− > =z ?~ a ~ a(n 7)
160+> =z ?~(a ~ a(n 10))
161− > z
161+> z
162− [n=7 l={5 4} r={1 3 2}]
162+[n=10 l={1} r={3}]
163− > ~(apt in z)
163+> ~(apt in z)
164− %.n
164+%.n
165```
165```
166
166
167#### Discussion
167#### Discussion
@@ -169,15 +169,16 @@ A flag.
169See section [`2f`](/docs/hoon/reference/stdlib/2f) for more information on noun ordering.
169See section [`2f`](/docs/hoon/reference/stdlib/2f) for more information on noun ordering.
170
170
171---
171---
172+
172### `++bif:in`
173### `++bif:in`
173
174
174Bifurcate
175Bifurcate
175
176
176−Splits set `a` into two sets `l` and `r`, with any noun `b` removed.
177+Splits set `a` into sets `l` and `r`, which contain the items either side of `b` but not including `b`.
177
178
178#### Accepts
179#### Accepts
179
180
180−`a` is a set.
181+`a` is a set, and is the sample of `+in`.
181
182
182`b` is a noun.
183`b` is a noun.
183
184
@@ -188,40 +189,45 @@ A cell of two sets.
188#### Source
189#### Source
189
190
190```hoon
191```hoon
191− ++ bif :: splits a by b
192+++ bif
192− ~/ %bif
193+ ~/ %bif
193− |* b=*
194+ |* b=*
194− ^+ [l=a r=a]
195+ ^+ [l=a r=a]
195− =< +
196+ =< +
196− |- ^+ a
197+ |- ^+ a
197− ?~ a
198+ ?~ a
198− [b ~ ~]
199+ [b ~ ~]
199− ?: =(b n.a)
200+ ?: =(b n.a)
200− a
201+ a
201− ?: (gor b n.a)
202+ ?: (gor b n.a)
202− =+ c=$(a l.a)
203− ?> ?=(^ c)
204− c(r a(l r.c))
205− =+ c=$(a r.a)
203+ =+ c=$(a l.a)
206 ?> ?=(^ c)
204 ?> ?=(^ c)
205+ c(r a(l r.c))
206+ =+ c=$(a r.a)
207+ ?> ?=(^ c)
207− c(l a(r l.c))
208+ c(l a(r l.c))
208```
209```
209
210
210#### Examples
211#### Examples
211
212
212```
213```
213− > =a (sy `(list @)`[1 2 3 4 5 6 ~])
214+> =a `(set @)`(silt (gulf 1 20))
214− > a
215+> a
215− [n=6 l={5 4} r={1 3 2}]
216+{17 8 20 13 11 5 19 7 15 10 18 14 6 12 9 1 2 3 16 4}
216
217
217− > (~(bif in a) 6)
218+> (~(bif in a) 10)
218− [l=[n=4 l=[n=5 l={} r={}] r=~] r=[n=2 l=[n=1 l={} r={3}] r=~]]
219+[l=[n=11 l={17 8 20 13} r={5 19 7 15}] r=[n=12 l={18 14 6} r={9 1 2 3 16 4}]]
219
220
220− > (~(bif in a) 100)
221+> `[(set @) (set @)]`(~(bif in a) 10)
221− [l=[n=6 l=[n=4 l={5} r={}] r=[n=2 l={1 3} r={}]] r=~]
222+[{17 8 20 13 11 5 19 7 15} {18 14 6 12 9 1 2 3 16 4}]
222```
223```
223
224
225+#### Discussion
226+
227+Note that `set`s are horizontally ordered by the [mug](/docs/hoon/reference/stdlib/2e#mug) hash of their items and vertically ordered by the double-`mug` hash of their items. This means bifurcating the set of numbers `(silt ~[10 20 30 40 50])` at `30` will not produce `[{10 20} {40 50}]`, but rather `[{20} {10 40 50}]` due to the tree structure resulting from their `mug` hashes.
228+
224---
229---
230+
225### `++del:in`
231### `++del:in`
226
232
227Remove noun
233Remove noun
@@ -230,7 +236,7 @@ Removes `b` from the `set` `a`.
230
236
231#### Accepts
237#### Accepts
232
238
233−`a` is a set.
239+`a` is a set, and is the sample of `+in`.
234
240
235`b` is a noun.
241`b` is a noun.
236
242
@@ -241,41 +247,48 @@ A set.
241#### Source
247#### Source
242
248
243```hoon
249```hoon
244− ++ del :: b without any a
250+++ del
245− ~/ %del
251+ ~/ %del
246− |* b=*
252+ |* b=*
247− |- ^+ a
253+ |- ^+ a
248− ?~ a
254+ ?~ a
249− ~
255+ ~
250− ?. =(b n.a)
256+ ?. =(b n.a)
251− ?: (gor b n.a)
257+ ?: (gor b n.a)
252− a(l $(a l.a))
258+ a(l $(a l.a))
253− a(r $(a r.a))
259+ a(r $(a r.a))
254− |- ^- [$?(~ _a)]
260+ |- ^- [$?(~ _a)]
255− ?~ l.a r.a
261+ ?~ l.a r.a
256− ?~ r.a l.a
262+ ?~ r.a l.a
257− ?: (mor n.l.a n.r.a)
263+ ?: (mor n.l.a n.r.a)
258− l.a(r $(l.a r.l.a))
264+ l.a(r $(l.a r.l.a))
259− r.a(l $(r.a l.r.a))
265+ r.a(l $(r.a l.r.a))
260```
266```
261
267
262−
263#### Examples
268#### Examples
264
269
265```
270```
266− > =b (sy `(list @t)`['a' 'b' 'c' ~])
267− > (~(del in b) 'a')
271+> `(set @)`(~(del in (silt ~[1 2 3 4 5])) 3)
268− [n='b' l=[n='c' l={} r={}] r=~]
272+{5 1 2 4}
273+```
269
274
270− > =b (sy `(list @t)`['john' 'bonita' 'daniel' 'madeleine' ~])
275+```
271− > (~(del in b) 'john')
276+> `(set @t)`(~(del in (silt ~['foo' 'bar' 'baz'])) 'bar')
272− [n='madeleine' l=[n='daniel' l={} r={'bonita'}] r=~]
277+{'baz' 'foo'}
278+```
273
279
274− > (~(del in b) 'susan')
280+```
275− [n='madeleine' l=[n='daniel' l={} r={'bonita'}] r=[n='john' l={} r={}]]
281+> `(set @)`(~(del in (silt ~[1 2 3 4 5])) 10)
282+{5 1 2 3 4}
283+```
284+
285+```
286+> `(set @)`(~(del in ~) 10)
287+{}
276```
288```
277
289
278---
290---
291+
279### `++dif:in`
292### `++dif:in`
280
293
281Difference
294Difference
@@ -285,7 +298,7 @@ that are not in `b`.
285
298
286#### Accepts
299#### Accepts
287
300
288−`a` is a set.
301+`a` is a set, and is the sample of `+in`.
289
302
290`b` is a set.
303`b` is a set.
291
304
@@ -296,46 +309,39 @@ A set.
296#### Source
309#### Source
297
310
298```hoon
311```hoon
299− ++ dif :: difference
312+++ dif
300− ~/ %dif
313+ ~/ %dif
301− =+ b=a
314+ =+ b=a
302− |@
315+ |@
303− ++ $
316+ ++ $
304− |- ^+ a
317+ |- ^+ a
305− ?~ b
318+ ?~ b
306− a
319+ a
307− =+ c=(bif n.b)
320+ =+ c=(bif n.b)
308− ?> ?=(^ c)
321+ ?> ?=(^ c)
309− =+ d=$(a l.c, b l.b)
322+ =+ d=$(a l.c, b l.b)
310− =+ e=$(a r.c, b r.b)
323+ =+ e=$(a r.c, b r.b)
311− |- ^- [$?(~ _a)]
324+ |- ^- [$?(~ _a)]
312− ?~ d e
325+ ?~ d e
313− ?~ e d
326+ ?~ e d
314− ?: (mor n.d n.e)
327+ ?: (mor n.d n.e)
315− d(r $(d r.d))
328+ d(r $(d r.d))
316− e(l $(e l.e))
329+ e(l $(e l.e))
317− --
330+ --
318```
331```
319
332
320#### Examples
333#### Examples
321
334
322```
335```
323− > =c (sy 1 2 3 ~)
336+> =a (silt ~[1 2 3 4 5])
324− > =d (sy 2 3 4 ~)
337+> =b (silt ~[3 4])
325− > (~(dif in c) d)
326− [n=1 l=~ r=~]
327
338
328− > (~(dif in d) c)
329− [n=4 l=~ r=~]
330−
331− > `(set @ud)`(~(dif in c) d)
339+> `(set @)`(~(dif in a) b)
332− {1}
340+{5 1 2}
333−
334− > `(set @ud)`(~(dif in d) c)
335− {4}
336```
341```
337
342
338---
343---
344+
339### `++dig:in`
345### `++dig:in`
340
346
341Address b in a
347Address b in a
@@ -344,7 +350,7 @@ Produce the tree address of `b` within `a`.
344
350
345#### Accepts
351#### Accepts
346
352
347−`a` is a set.
353+`a` is a set, and is the sample of `+in`.
348
354
349`b` is a noun.
355`b` is a noun.
350
356
@@ -355,36 +361,36 @@ The `unit` of an atom.
355#### Source
361#### Source
356
362
357```hoon
363```hoon
358− ++ dig :: axis of a in b
364+++ dig
359− |= b=*
365+ |= b=*
360− =+ c=1
366+ =+ c=1
361− |- ^- (unit @)
367+ |- ^- (unit @)
362− ?~ a ~
368+ ?~ a ~
363− ?: =(b n.a) [~ u=(peg c 2)]
369+ ?: =(b n.a) [~ u=(peg c 2)]
364− ?: (gor b n.a)
370+ ?: (gor b n.a)
365− $(a l.a, c (peg c 6))
371+ $(a l.a, c (peg c 6))
366− $(a r.a, c (peg c 7))
372+ $(a r.a, c (peg c 7))
367```
373```
368
374
369−
370#### Examples
375#### Examples
371
376
372```
377```
373− > =a (sy `(list @)`[1 2 3 4 5 6 7 ~])
378+> =a (silt ~[1 2 3 4 5 6 7])
374− > `(set @)`a
375− {5 4 7 6 1 3 2}
376
379
377− > -.a
380+> -.a
378− n=6
381+n=6
379
382
380− > (~(dig in a) 7)
383+> (~(dig in a) 7)
381− [~ u=12]
384+[~ 12]
382
385
383− > (~(dig in a) 2)
386+> (~(dig in a) 2)
384− [~ u=14]
387+[~ 60]
385
388
386− > (~(dig in a) 6)
389+> (~(dig in a) 6)
387− [~ u=2]
390+[~ 2]
391+
392+> (~(dig in a) 10)
393+~
388```
394```
389
395
390#### Discussion
396#### Discussion
@@ -392,6 +398,7 @@ The `unit` of an atom.
392For more on the tree addressing system, see section [1b](/docs/hoon/reference/stdlib/1b).
398For more on the tree addressing system, see section [1b](/docs/hoon/reference/stdlib/1b).
393
399
394---
400---
401+
395### `++gas:in`
402### `++gas:in`
396
403
397Concatenate
404Concatenate
@@ -400,7 +407,7 @@ Insert the elements of a `list` `b` into a `set` `a`.
400
407
401#### Accepts
408#### Accepts
402
409
403−`a` is a set.
410+`a` is a set, and is the sample of `+in`.
404
411
405`b` is a list.
412`b` is a list.
406
413
@@ -411,31 +418,31 @@ A `set`.
411#### Source
418#### Source
412
419
413```hoon
420```hoon
414− ++ gas :: concatenate
421+++ gas
415− ~/ %gas
422+ ~/ %gas
416− |= b=(list _?>(?=(^ a) n.a))
423+ |= b=(list _?>(?=(^ a) n.a))
417− |- ^+ a
424+ |- ^+ a
418− ?~ b
425+ ?~ b
419− a
426+ a
420− $(b t.b, a (put i.b))
427+ $(b t.b, a (put i.b))
421```
428```
422
429
423#### Examples
430#### Examples
424
431
425```
432```
426− > =b `(set @t)`(sy `(list @t)`['bonita' 'madeleine' 'rudolf' 'john' ~])
433+> =a (silt ~['foo' 'bar' 'baz'])
427− > b
434+> `(set @t)`a
428− {'bonita' 'madeleine' 'rudolf' 'john'}
435+{'bar' 'baz' 'foo'}
429
436
430− > (~(gas in b) `(list @t)`['14' 'things' 'number' '1.337' ~])
437+> `(set @t)`(~(gas in a) ~['foo' 'foo' 'foo' 'foo'])
431− [n='number' l={'1.337' '14'} r={'things' 'bonita' 'madeleine' 'rudolf' 'john'}]
438+{'bar' 'baz' 'foo'}
432
439
433− > =s (sy `(list @t)`['a' 'b' 'c' 'd' 'e' ~])
440+> `(set @t)`(~(gas in a) ~['abc' 'xyz' '123'])
434− > (~(gas in s) `(list @t)`['1' '2' '3' ~])
441+{'xyz' 'bar' 'baz' 'foo' 'abc' '123'}
435− [n='e' l=[n='1' l={} r={'3' '2'}] r=[n='b' l={'d' 'a' 'c'} r={}]]
436```
442```
437
443
438---
444---
445+
439### `++has:in`
446### `++has:in`
440
447
441b in a?
448b in a?
@@ -444,7 +451,7 @@ Checks if `b` is an element of `a`, producing a flag.
444
451
445#### Accepts
452#### Accepts
446
453
447−`a` is a set.
454+`a` is a set, and is the sample of `+in`.
448
455
449`b` is a noun.
456`b` is a noun.
450
457
@@ -455,46 +462,37 @@ A flag.
455#### Source
462#### Source
456
463
457```hoon
464```hoon
458− ++ has
465+++ has
459− ~/ %has
466+ ~/ %has
460− |* b=*
467+ |* b=*
461− ^- ?
468+ ^- ?
462− :: wrap extracted item type in a unit because bunting fails
463− ::
464− :: If we used the real item type of _?^(a n.a !!) as the sample type,
465− :: then hoon would bunt it to create the default sample for the gate.
466− ::
467− :: However, bunting that expression fails if :a is ~. If we wrap it
468− :: in a unit, the bunted unit doesn't include the bunted item type.
469− ::
470− :: This way we can ensure type safety of :b without needing to perform
471− :: this failing bunt. It's a hack.
472− ::
473− %. [~ b]
469+ %. [~ b]
474− |= b=(unit _?>(?=(^ a) n.a))
470+ |= b=(unit _?>(?=(^ a) n.a))
475− => .(b ?>(?=(^ b) u.b))
471+ => .(b ?>(?=(^ b) u.b))
476− |- ^- ?
472+ |- ^- ?
477− ?~ a
473+ ?~ a
478− |
474+ |
479− ?: =(b n.a)
475+ ?: =(b n.a)
480− &
476+ &
481− ?: (gor b n.a)
477+ ?: (gor b n.a)
482− $(a l.a)
478+ $(a l.a)
483− $(a r.a)
479+ $(a r.a)
484```
480```
485
481
486#### Examples
482#### Examples
487
483
488```
484```
489− > =a (~(gas in `(set @t)`~) `(list @t)`['a' 'b' 'c' ~])
485+> =a (silt ~[1 2 3 4 5])
490− > (~(has in a) 'a')
491− %.y
492
486
493− > (~(has in a) 'z')
487+> (~(has in a) 2)
488+%.y
489+
490+> (~(has in a) 6)
494− %.n
491+%.n
495```
492```
496
493
497---
494---
495+
498### `++int:in`
496### `++int:in`
499
497
500Intersection
498Intersection
@@ -504,7 +502,7 @@ Produces a set of the intersection between two sets of the same type,
504
502
505#### Accepts
503#### Accepts
506
504
507−`a` is a set.
505+`a` is a set, and is the sample of `+in`.
508
506
509`b` is a set.
507`b` is a set.
510
508
@@ -515,41 +513,41 @@ A `set`.
515#### Source
513#### Source
516
514
517```hoon
515```hoon
518− ++ int :: intersection
516+++ int
519− ~/ %int
517+ ~/ %int
520− =+ b=a
518+ =+ b=a
521− |@
519+ |@
522− ++ $
520+ ++ $
523− |- ^+ a
521+ |- ^+ a
524− ?~ b
522+ ?~ b
525− ~
523+ ~
526− ?~ a
524+ ?~ a
527− ~
525+ ~
528− ?. (mor n.a n.b)
526+ ?. (mor n.a n.b)
529− $(a b, b a)
527+ $(a b, b a)
530− ?: =(n.b n.a)
528+ ?: =(n.b n.a)
531− a(l $(a l.a, b l.b), r $(a r.a, b r.b))
529+ a(l $(a l.a, b l.b), r $(a r.a, b r.b))
532− ?: (gor n.b n.a)
530+ ?: (gor n.b n.a)
533− %- uni(a $(a l.a, r.b ~)) $(b r.b)
531+ %- uni(a $(a l.a, r.b ~)) $(b r.b)
534− %- uni(a $(a r.a, l.b ~)) $(b l.b)
532+ %- uni(a $(a r.a, l.b ~)) $(b l.b)
535− --
533+ --
536```
534```
537
535
538−
539#### Examples
536#### Examples
540
537
541```
538```
542− > (~(int in `(set @t)`(sy "acmo")) `(set @t)`(sy "ham"))
539+> `(set @tD)`(~(int in (silt "foobar")) (silt "bar"))
543− [n='m' l={'a'} r={}]
540+{'r' 'b' 'a'}
544
541
545− > (~(int in (sy "acmo")) ~)
542+> `(set @tD)`(~(int in (silt "foobar")) ~)
546− ~
543+{}
547
544
548− > (~(int in `(set @t)`(sy "ac")) `(set @t)`(sy "ha"))
545+> `(set @tD)`(~(int in (silt "foobar")) (silt "baz"))
549− [n='a' l={} r={}]
546+{'b' 'a'}
550```
547```
551
548
552---
549---
550+
553### `++put:in`
551### `++put:in`
554
552
555Put b in a
553Put b in a
@@ -558,7 +556,7 @@ Add an element `b` to the set `a`, producing a set.
558
556
559#### Accepts
557#### Accepts
560
558
561−`a` is a set.
559+`a` is a set, and is the sample of `+in`.
562
560
563`b` is a noun.
561`b` is a noun.
564
562
@@ -569,49 +567,48 @@ A `set`.
569#### Source
567#### Source
570
568
571```hoon
569```hoon
572− ++ put :: puts b in a, sorted
570+++ put
573− ~/ %put
571+ ~/ %put
574− |* b=*
572+ |* b=*
575− |- ^+ a
573+ |- ^+ a
576− ?~ a
574+ ?~ a
577− [b ~ ~]
575+ [b ~ ~]
578− ?: =(b n.a)
576+ ?: =(b n.a)
579− a
577+ a
580− ?: (gor b n.a)
578+ ?: (gor b n.a)
581− =+ c=$(a l.a)
579+ =+ c=$(a l.a)
582− ?> ?=(^ c)
583− ?: (mor n.a n.c)
584− a(l c)
585− c(r a(l r.c))
586− =+ c=$(a r.a)
587 ?> ?=(^ c)
580 ?> ?=(^ c)
588 ?: (mor n.a n.c)
581 ?: (mor n.a n.c)
582+ a(l c)
583+ c(r a(l r.c))
584+ =+ c=$(a r.a)
589− a(r c)
585+ ?> ?=(^ c)
586+ ?: (mor n.a n.c)
587+ a(r c)
590− c(l a(r l.c))
588+ c(l a(r l.c))
591```
589```
592
590
593#### Examples
591#### Examples
594
592
595```
593```
596− > =a (~(gas in `(set @t)`~) `(list @t)`['a' 'b' 'c' ~])
594+> `(set @)`(~(put in (silt ~[1 2 3])) 4)
597− > =b (~(put in a) 'd')
595+{1 2 3 4}
598− > `(set @t)`b
599− {'d' 'a' 'c' 'b'}
600
596
601− > -.l.+.b
597+> `(set @)`(~(put in `(set @)`~) 42)
602− n='d'
598+{42}
603```
599```
604
600
605---
601---
602+
606### `++rep:in`
603### `++rep:in`
607
604
608Accumulate
605Accumulate
609
606
610−Accumulate the elements of `a` using a gate `b`.
607+Accumulate the elements of `a` using binary gate `b`.
611
608
612#### Accepts
609#### Accepts
613
610
614−`a` is a `set`.
611+`a` is a `set`, and is the sample of `+in`.
615
612
616`b` is a gate.
613`b` is a gate.
617
614
@@ -622,26 +619,28 @@ A noun.
622#### Source
619#### Source
623
620
624```hoon
621```hoon
625− ++ rep :: reduce to product
622+++ rep
626− ~/ %rep
623+ ~/ %rep
627− |* b=_=>(~ |=([* *] +<+))
624+ |* b=_=>(~ |=([* *] +<+))
628− |-
625+ |-
629− ?~ a +<+.b
626+ ?~ a +<+.b
630− $(a r.a, +<+.b $(a l.a, +<+.b (b n.a +<+.b)))
627+ $(a r.a, +<+.b $(a l.a, +<+.b (b n.a +<+.b)))
631```
628```
632
629
633#### Examples
630#### Examples
634
631
635```
632```
636− > =a (~(gas in *(set @)) [1 2 3 ~])
633+> (~(rep in (silt ~[1 2 3 4 5])) add)
637− > `(set @)`a
634+b=15
638− {1 3 2}
635+```
639
636
640− > (~(rep in a) |=([a=@ b=@] (add a b)))
637+```
641− b=6
638+> `@t`(~(rep in (silt ~['foo' 'bar' 'baz'])) |=(a=[@ @] (cat 3 a)))
639+'foobarbaz'
642```
640```
643
641
644---
642---
643+
645### `++run:in`
644### `++run:in`
646
645
647Apply gate to set
646Apply gate to set
@@ -662,28 +661,29 @@ A set.
662#### Source
661#### Source
663
662
664```hoon
663```hoon
665− ++ run :: apply gate to values
664+++ run
666− ~/ %run
665+ ~/ %run
667− |* b=gate
666+ |* b=gate
668− =+ c=`(set _?>(?=(^ a) (b n.a)))`~
667+ =+ c=`(set _?>(?=(^ a) (b n.a)))`~
669− |- ?~ a c
668+ |- ?~ a c
670− =. c (~(put in c) (b n.a))
669+ =. c (~(put in c) (b n.a))
671− =. c $(a l.a, c c)
670+ =. c $(a l.a, c c)
672− $(a r.a, c c)
671+ $(a r.a, c c)
673```
672```
674
673
675#### Examples
674#### Examples
676
675
677```
676```
678− > =s (sy ~["a" "A" "b" "c"])
677+> =s (silt ~["a" "A" "b" "c"])
679− > `(set tape)`s
678+> `(set tape)`s
680− {"A" "a" "c" "b"}
679+{"A" "a" "c" "b"}
681
680
682− > (~(run in s) cuss)
681+> (~(run in s) cuss)
683− {"A" "C" "B"}
682+{"A" "C" "B"}
684```
683```
685
684
686---
685---
686+
687### `++tap:in`
687### `++tap:in`
688
688
689Set to list
689Set to list
@@ -701,29 +701,30 @@ A list.
701#### Source
701#### Source
702
702
703```hoon
703```hoon
704− ++ tap :: convert to list
704+++ tap
705− =< $
705+ =< $
706− ~/ %tap
706+ ~/ %tap
707− =+ b=`(list _?>(?=(^ a) n.a))`~
707+ =+ b=`(list _?>(?=(^ a) n.a))`~
708− |. ^+ b
708+ |. ^+ b
709− ?~ a
709+ ?~ a
710− b
710+ b
711− $(a r.a, b [n.a $(a l.a)])
711+ $(a r.a, b [n.a $(a l.a)])
712```
712```
713
713
714−
715#### Examples
714#### Examples
716
715
717```
716```
718− > =s (sy `(list @t)`['a' 'b' 'c' 'd' 'e' ~])
717+> ~(tap in (silt "foobar"))
719− > s
718+"oafbr"
720− [n='e' l={} r={'d' 'a' 'c' 'b'}]
719+```
721
720
721+```
722− > ~(tap in s)
722+> ~(tap in (silt ~[1 2 3 4 5]))
723− ~['b' 'c' 'a' 'd' 'e']
723+~[4 3 2 1 5]
724```
724```
725
725
726---
726---
727+
727### `++uni:in`
728### `++uni:in`
728
729
729Union
730Union
@@ -733,7 +734,7 @@ Produces a set of the union between two sets of the same type, `a` and
733
734
734#### Accepts
735#### Accepts
735
736
736−`a` is a set.
737+`a` is a set, and is the sample of `+in`.
737
738
738`b` is a set.
739`b` is a set.
739
740
@@ -744,47 +745,47 @@ A set.
744#### Source
745#### Source
745
746
746```hoon
747```hoon
747− ++ uni :: union
748+++ uni
748− ~/ %uni
749+ ~/ %uni
749− =+ b=a
750+ =+ b=a
750− |@
751+ |@
751− ++ $
752+ ++ $
752− ?: =(a b) a
753+ ?: =(a b) a
753− |- ^+ a
754+ |- ^+ a
754− ?~ b
755+ ?~ b
755− a
756+ a
756− ?~ a
757+ ?~ a
757− b
758+ b
758− ?: =(n.b n.a)
759+ ?: =(n.b n.a)
759− b(l $(a l.a, b l.b), r $(a r.a, b r.b))
760+ b(l $(a l.a, b l.b), r $(a r.a, b r.b))
760− ?: (mor n.a n.b)
761+ ?: (mor n.a n.b)
761− ?: (gor n.b n.a)
762+ ?: (gor n.b n.a)
762− $(l.a $(a l.a, r.b ~), b r.b)
763+ $(l.a $(a l.a, r.b ~), b r.b)
763− $(r.a $(a r.a, l.b ~), b l.b)
764+ $(r.a $(a r.a, l.b ~), b l.b)
764− ?: (gor n.a n.b)
765+ ?: (gor n.a n.b)
765− $(l.b $(b l.b, r.a ~), a r.a)
766+ $(l.b $(b l.b, r.a ~), a r.a)
766− $(r.b $(b r.b, l.a ~), a l.a)
767+ $(r.b $(b r.b, l.a ~), a l.a)
767− --
768+ --
768```
769```
769
770
770−
771#### Examples
771#### Examples
772
772
773```
773```
774− > (~(uni in `(set @t)`(sy "ac")) `(set @)`(sy "ha"))
774+> =a (silt ~[1 2 3 4 5])
775− [n='c' l={'a'} r={'h'}]
775+> =b (silt ~[4 5 6 7 8])
776
776
777− > (~(uni in `(set @t)`(sy "acmo")) ~)
777+> `(set @)`(~(uni in a) b)
778− [n='c' l={'a'} r={'m' 'o'}]
778+{8 5 7 6 1 2 3 4}
779
779
780− > (~(uni in `(set @t)`(sy "acmo")) `(set @t)`(sy "ham"))
780+> `(set @)`(~(uni in a) ~)
781− [n='c' l={'a'} r={'m' 'o' 'h'}]
781+{5 1 2 3 4}
782
782
783− > (~(uni in `(set @t)`(sy "acmo")) `(set @t)`(sy "lep"))
783+> `(set @)`(~(uni in `(set @)`~) b)
784− [n='e' l={} r={'a' 'c' 'm' 'l' 'o' 'p'}]
784+{8 5 7 6 4}
785```
785```
786
786
787---
787---
788+
788### `++wyt:in`
789### `++wyt:in`
789
790
790Set size
791Set size
@@ -802,25 +803,24 @@ An atom.
802#### Source
803#### Source
803
804
804```hoon
805```hoon
805− ++ wyt :: size of set
806+++ wyt
806− =< $
807+ =< $
807− ~% %wyt + ~
808+ ~% %wyt + ~
808− |. ^- @
809+ |. ^- @
809− ?~(a 0 +((add $(a l.a) $(a r.a))))
810+ ?~(a 0 +((add $(a l.a) $(a r.a))))
810− --
811+--
811```
812```
812
813
813−
814#### Examples
814#### Examples
815
815
816```
816```
817− > =a (~(put in (~(put in (sy)) 'a')) 'b')
818− > ~(wyt in a)
817+> ~(wyt in (silt ~[1 2 3 4]))
819− 2
818+4
819+```
820
820
821− > =b (sy `(list @t)`['john' 'bonita' 'daniel' 'madeleine' ~])
821+```
822− > ~(wyt in b)
822+> ~(wyt in `(set @)`~)
823− 4
823+0
824```
824```
825
825
826---
826---
content/docs/hoon/reference/stdlib/2i.md+720−436

This diff is too big to show here.

content/docs/hoon/reference/stdlib/2j.md+263−155

This diff is too big to show here.

content/docs/hoon/reference/stdlib/2k.md+191−135

This diff is too big to show here.

content/docs/hoon/reference/stdlib/2l.md+5−3

This diff is too big to show here.

content/docs/hoon/reference/stdlib/2m.md+40−32

This diff is too big to show here.

content/docs/hoon/reference/stdlib/2n.md+152−138

This diff is too big to show here.

content/docs/hoon/reference/stdlib/2o.md+99−86

This diff is too big to show here.

content/docs/hoon/reference/stdlib/2p.md+125−119

This diff is too big to show here.

content/docs/hoon/reference/stdlib/2q.md+350−139

This diff is too big to show here.

content/docs/hoon/reference/stdlib/3a.md+259−237

This diff is too big to show here.

content/docs/hoon/reference/stdlib/3b.md+1583−1418

This diff is too big to show here.

content/docs/hoon/reference/stdlib/3c.md+260−245

This diff is too big to show here.

content/docs/hoon/reference/stdlib/3d.md+455−456

This diff is too big to show here.

content/docs/hoon/reference/stdlib/3f.md+463−317

This diff is too big to show here.

content/docs/hoon/reference/stdlib/3g.md+136−165

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4a.md+5−1

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4b.md+36−37

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4c.md+12−16

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4d.md+4−4

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4e.md+20−33

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4f.md+49−53

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4g.md+8−8

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4h.md+66−64

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4i.md+70−72

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4j.md+62−64

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4k.md+5−5

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4l.md+11−13

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4m.md+20−18

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4n.md+15−13

This diff is too big to show here.

content/docs/hoon/reference/stdlib/4o.md+31−127

This diff is too big to show here.

content/docs/hoon/reference/stdlib/5c.md+77−1

This diff is too big to show here.

content/docs/hoon/reference/stdlib/5f.md+18−23

This diff is too big to show here.

content/docs/hoon/reference/stdlib/table-of-contents.md+134−97

This diff is too big to show here.

content/docs/hoon/reference/zuse/2d_1-5.mdnew file+587

This diff is too big to show here.

content/docs/hoon/reference/zuse/2d_6.mdnew file+1551

This diff is too big to show here.

content/docs/hoon/reference/zuse/2d_7.mdnew file+1307

This diff is too big to show here.

content/docs/hoon/reference/zuse/2e_2-3.mdnew file+67

This diff is too big to show here.

content/docs/hoon/reference/zuse/_index.mdnew file+31

This diff is too big to show here.

content/docs/hoon/reference/zuse/table-of-contents.mdnew file+247

This diff is too big to show here.

content/docs/system-overview/arvo.md+1−1

This diff is too big to show here.

content/docs/userspace/_index.md+5−2

This diff is too big to show here.

content/docs/userspace/dist/_index.mdnew file+29

This diff is too big to show here.

content/docs/userspace/dist/dist.mdnew file+105

This diff is too big to show here.

content/docs/userspace/dist/docket.mdnew file+296

This diff is too big to show here.

content/docs/userspace/dist/glob.mdnew file+102

This diff is too big to show here.

content/docs/userspace/dist/guide.mdnew file+269

This diff is too big to show here.

content/docs/userspace/dist/tools.mdnew file+342

This diff is too big to show here.

content/docs/userspace/gall/tutorial.md → content/docs/userspace/gall-guide.mdrenamed+1−1

This diff is too big to show here.

content/docs/userspace/gall/_index.mddeleted−21

This diff is too big to show here.

content/docs/userspace/graph-store/overview.md+15−21

This diff is too big to show here.

content/docs/userspace/graph-store/sample-application-overview.md+58−58

This diff is too big to show here.

content/docs/userspace/graph-store/validator-walkthrough.md+38−49

This diff is too big to show here.

content/docs/userspace/landscape/overview.md+5−14

This diff is too big to show here.

content/docs/userspace/overview.md+7−2

This diff is too big to show here.

content/docs/userspace/threads/basics/bind.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/basics/fundamentals.md+16−17

This diff is too big to show here.

content/docs/userspace/threads/examples/child-thread.md+6−5

This diff is too big to show here.

content/docs/userspace/threads/examples/get-json.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/examples/main-loop.md+2−2

This diff is too big to show here.

content/docs/userspace/threads/examples/poke-agent.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/examples/scry.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/examples/take-fact.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/gall/poke-thread.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/gall/start-thread.md+3−3

This diff is too big to show here.

content/docs/userspace/threads/gall/stop-thread.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/gall/take-facts.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/gall/take-result.md+1−1

This diff is too big to show here.

content/docs/userspace/threads/http-api.md+6−6

This diff is too big to show here.

content/docs/userspace/threads/overview.md+13−12

This diff is too big to show here.

content/docs/userspace/threads/reference.md+11−2

This diff is too big to show here.

content/events/2021-09-16-developer-call-azimuth-scaled.mdnew file+46

This diff is too big to show here.

content/events/2021-10-16-assembly-keynote.mdnew file+14

This diff is too big to show here.

content/events/2021-10-16-assembly-sw-dist-qa.mdnew file+14

This diff is too big to show here.

content/events/2021-11-26-meetup-brisbane.mdnew file+30

This diff is too big to show here.

content/events/20211007-developer-call-visor.mdnew file+38

This diff is too big to show here.

content/events/20211028-developer-call-hosting.mdnew file+33

This diff is too big to show here.

content/faq.md+10−155

This diff is too big to show here.

content/getting-started/_index.md+54−4

This diff is too big to show here.

content/getting-started/cli.md+15−24

This diff is too big to show here.

content/getting-started/planet.md+167−83

This diff is too big to show here.

content/grant-submission-guide.md+1−1

This diff is too big to show here.

content/grants/a-collaborative-web-mapping-system-for-urbit.md → content/grants/a-network-enabled-spatial-database-and-demonstration-app.mdrenamed+26−21

This diff is too big to show here.

content/grants/analytics-script.md+2−1

This diff is too big to show here.

content/grants/art-by-urbit.md+1

This diff is too big to show here.

content/grants/authenticate-with-urbit.mdnew file+36

This diff is too big to show here.

content/grants/azimuth-cli.mdnew file+164

This diff is too big to show here.

content/grants/bridge-l2-revamp.md+1

This diff is too big to show here.

content/grants/calendar-ui.md+1

This diff is too big to show here.

content/grants/clojure-urbit-client.mdnew file+111

This diff is too big to show here.

content/grants/comprehensive-local-server-and-mum-explanation-video.md+2−1

This diff is too big to show here.

content/grants/contacts.md+1

This diff is too big to show here.

content/grants/content-producer.md+1

This diff is too big to show here.

content/grants/cross-platform-desktop-urbit-app.md+2−1

This diff is too big to show here.

content/grants/cypherscope-bot.mdnew file+80

This diff is too big to show here.

content/grants/educational-guide-todomvc-urbit-edition.md+1

This diff is too big to show here.

content/grants/feed-aggregator.md+1

This diff is too big to show here.

content/grants/graph-store-documentation-guide.md+1

This diff is too big to show here.

content/grants/guide-to-s3.md+1

This diff is too big to show here.

content/grants/host-two-urbit-meetups-12.md+2−1

This diff is too big to show here.

content/grants/host-two-urbit-meetups-13.mdnew file+59

This diff is too big to show here.

content/grants/host-two-urbit-meetups-14.mdnew file+59

This diff is too big to show here.

content/grants/host-two-urbit-meetups-15.mdnew file+59

This diff is too big to show here.

content/grants/host-two-urbit-meetups-16.mdnew file+59

This diff is too big to show here.

content/grants/json-jet.md+1

This diff is too big to show here.

content/grants/links-in-urbit-reference-docs.md+2−1

This diff is too big to show here.

content/grants/login-with-urbit.md+3−8

This diff is too big to show here.

content/grants/machine-learning.md+1

This diff is too big to show here.

content/grants/market-interface.mdnew file+61

This diff is too big to show here.

content/grants/meetup-bom.mdnew file+118

This diff is too big to show here.

content/grants/minimal-urbit-os.md+1

This diff is too big to show here.

content/grants/native-urbit.mdnew file+30

This diff is too big to show here.

content/grants/network-explorer-data-pipeline-http-api.md+2−1

This diff is too big to show here.

content/grants/network-explorer.mddeleted−233

This diff is too big to show here.

content/grants/nuck-jet.md+1

This diff is too big to show here.

content/grants/overhaul-the-urbitorg-website.md+3−2

This diff is too big to show here.

content/grants/planet-sales.md+1

This diff is too big to show here.

content/grants/pokur.mdnew file+90

This diff is too big to show here.

content/grants/ra-page-tracking.md+2−2

This diff is too big to show here.

content/grants/search-in-groups.md+1−1

This diff is too big to show here.

content/grants/send-emails-to-a-mailing-list.mdnew file+78

This diff is too big to show here.

content/grants/slaw-scot-jets.md+1−1

This diff is too big to show here.

content/grants/-smol-future-sustained-knowledge-sharing-and-marketing.md → content/grants/smol-future-sustained-knowledge-sharing-and-marketing.mdrenamed

The content is the same.

content/grants/speech-recognition.md+1

This diff is too big to show here.

content/grants/static-site-generation.mdnew file+80

This diff is too big to show here.

content/grants/translate-key-parts-of-urbitorg-into-german.md+1

This diff is too big to show here.

content/grants/translate-key-parts-of-urbitorg-into-korean.md+1

This diff is too big to show here.

content/grants/translate-key-parts-of-urbitorg-into-spanish.md+1

This diff is too big to show here.

content/grants/try-urbit-website.md+2−1

This diff is too big to show here.

content/grants/twitter-uv-extension.mdnew file+67

This diff is too big to show here.

content/grants/ua-collaborative-text-editor.md+2−2

This diff is too big to show here.

content/grants/ua-filesharer.md+1−1

This diff is too big to show here.

content/grants/ua-heads-up-poker.md+1−1

This diff is too big to show here.

content/grants/ua-invoice-system.md+1−1

This diff is too big to show here.

content/grants/ua-marketplace.md+1−1

This diff is too big to show here.

content/grants/ucal-google-and-outlook-integration.md+1

This diff is too big to show here.

content/grants/urbian-a-customized-linux-distribution-for-urbit-appliances.md+1

This diff is too big to show here.

content/grants/urbit-community-concierge-east-coast-2q2021.md+2−1

This diff is too big to show here.

content/grants/urbit-community-concierge-east-coast.md+2−1

This diff is too big to show here.

content/grants/urbit-community-concierge-west-coast-2q2021.md+2−1

This diff is too big to show here.

content/grants/urbit-community-concierge-west-coast.md+2−1

This diff is too big to show here.

content/grants/urbit-event-series.md+2−1

This diff is too big to show here.

content/grants/urbit-explainer-video.md+1

This diff is too big to show here.

content/grants/urbit-http-api-for-emacs-elisp.md+1

This diff is too big to show here.

content/grants/urbit-http-api-for-kotlin.md+1

This diff is too big to show here.

content/grants/urbit-http-api-for-python.md+1

This diff is too big to show here.

content/grants/urbit-http-api-for-rust.md+1

This diff is too big to show here.

content/grants/urbit-http-interface-java-edition.md+1

This diff is too big to show here.

content/grants/urbit-http-library-for-ruby.md+1

This diff is too big to show here.

content/grants/urbit-irc-bridge.md+1

This diff is too big to show here.

content/grants/urbit-lfs-filehosting.md+1

This diff is too big to show here.

content/grants/urbit-react-cookbook.md+2−1

This diff is too big to show here.

content/grants/uturn.mdnew file+37

This diff is too big to show here.

content/grants/uv-extension-library.mdnew file+44

This diff is too big to show here.

content/grants/video-content-manager.md+1

This diff is too big to show here.

content/grants/volt-lightning-on-urbit.md+39−9

This diff is too big to show here.

content/grants/webrtc-gall-agent-and-external-app.md+16−18

This diff is too big to show here.

content/grants/webrtc.mddeleted−80

This diff is too big to show here.

content/grants/~home-urbit.mdnew file+120

This diff is too big to show here.

content/using/_index.md+3−3

This diff is too big to show here.

content/using/id/_index.md+26

This diff is too big to show here.

content/using/id/guide-to-breaches.md+1−3

This diff is too big to show here.

content/using/id/hd-wallet.mdnew file+164

This diff is too big to show here.

content/using/id/l2-star.mdnew file+41

This diff is too big to show here.

content/using/id/overview.md+187−55

This diff is too big to show here.

content/using/id/proxies.mdnew file+56

This diff is too big to show here.

content/using/id/using-bridge.md+1−1

This diff is too big to show here.

content/using/os/_index.md+1−1

This diff is too big to show here.

content/using/os/basics.mdnew file+236

This diff is too big to show here.

content/using/os/dist-faq.mdnew file+162

This diff is too big to show here.

content/using/os/filesystem.md+29−47

This diff is too big to show here.

content/using/os/getting-started.mddeleted−335

This diff is too big to show here.

content/using/os/shell.md+20−90

This diff is too big to show here.

content/using/os/ship-troubleshooting.md+2−2

This diff is too big to show here.

content/using/running/_index.md+4

This diff is too big to show here.

content/using/running/port.mdnew file+157

This diff is too big to show here.

lib/constants.js−1

This diff is too big to show here.

lib/glossary.js+1301−551

This diff is too big to show here.

next.config.js+46−10

This diff is too big to show here.

package-lock.json+2313−3335

This diff is too big to show here.

package.json+8−6

This diff is too big to show here.

pages/bitcoin-wallet.jsnew file+21

This diff is too big to show here.

pages/events.js+15−4

This diff is too big to show here.

pages/events/[slug].js+2−2

This diff is too big to show here.

pages/grants.js+1−1

This diff is too big to show here.

pages/index.js+75−23

This diff is too big to show here.

pages/using/[[...slug]].js+3−3

This diff is too big to show here.

patches/prismjs+1.24.1.patchdeleted−42

This diff is too big to show here.

public/images/developers-guide-logo.pngnew file

Binary file not shown.

public/images/network-explorer-logo.pngnew file

Binary file not shown.

public/images/operators-guide-logo.pngnew file

Binary file not shown.

public/images/star-market-logo.pngnew file

Binary file not shown.

public/rss.xmlnew file+17611

This diff is too big to show here.

styles/markdown.css+2−6

This diff is too big to show here.

vercel.json+5

This diff is too big to show here.

yarn.lockdeleted−1865

This diff is too big to show here.