on master help sign in
pandocify
commit195cd2706b1a3382fc7ed84fbe5d1a6566cb1018 authorTobias Merkle <tgamerkle@gmail.com> dateThu 9 Jun 2016, 15:07 (10 years ago) parentc61dbda
5 files changed+874−937
docs/arvo/basic.md+184−202 docs/arvo/network.md+285−310 docs/arvo/state.md+85−93 docs/arvo/subject.md+86−87 docs/arvo/subscriptions.md+234−245
docs/arvo/basic.md+184−202
@@ -5,29 +5,29 @@ next: true
55title: Hoon refresher / crash course
66---
77
8−# Basic Hoon
8+Basic Hoon
9+==========
910
10−This recapitulates material you've already learned in [Hoon](/docs/hoon/).
11−It will be a very abrupt tutorial if you don't know Hoon already,
12−but it may be enough in and of itself. If you don't find it obvious at first
13−glance, try working up from Hoon.
11+This recapitulates material you've already learned in
12+[Hoon](/docs/hoon/). It will be a very abrupt tutorial if you don't know
13+Hoon already, but it may be enough in and of itself. If you don't find
14+it obvious at first glance, try working up from Hoon.
1415
15−Our goal is to get you programming interesting and useful things
16−as soon as possible. To get there, we have to quickly cover some
17−of the fundamentals of hoon. To do this, we'll walk through two
18−simple programs: the first [Project
19−Euler](https://projecteuler.net/) problem and
20−[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
16+Our goal is to get you programming interesting and useful things as soon
17+as possible. To get there, we have to quickly cover some of the
18+fundamentals of hoon. To do this, we'll walk through two simple
19+programs: the first [Project Euler](https://projecteuler.net/) problem
20+and [fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
2121
22−To run this code, you'll need an urbit, and will have to copy the [examples repo](https://github.com/urbit/examples) into it.
22+To run this code, you'll need an urbit, and will have to copy the
23+[examples repo](https://github.com/urbit/examples) into it.
2324
24−If you haven't installed
25−urbit yet, check out the [installation
26−instructions](/docs/user/install). Once urbit is
27−installed, take a look at the [basic
28−operation](/docs/user/basic) of your urbit.
25+If you haven't installed urbit yet, check out the [installation
26+instructions](/docs/user/install). Once urbit is installed, take a look
27+at the [basic operation](/docs/user/basic) of your urbit.
2928
30−If you haven't copied in the examples repo, running the following commands from your urbit directory should do the trick:
29+If you haven't copied in the examples repo, running the following
30+commands from your urbit directory should do the trick:
3131
3232`$ cp -r {wherever-you've-pulled-to}/examples/gall/*/ arvo/`
3333`$ cp -r {wherever-you've-pulled-to}/examples/dojo/*/ arvo/`
@@ -37,66 +37,60 @@ Run an example to ensure it worked:
3737 ~fintud-macrep:dojo> +examples-euler1
3838 233.168
3939
40−## Euler 1
41−
42−Let's check out the code for Euler 1. First, the problem:
43−
44−```
45−If we list all the natural numbers below 10 that are multiples of
46−3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
47−
48−Find the sum of all the multiples of 3 or 5 below 1000.
49−```
50−
51−Here is the hoon solution (which should be in your pier directory
52−under `/gen/examples/euler1`):
53−
54−```
55−:: project euler 1
56−:: https://projecteuler.net/problem=1
57−:: run in dojo with +examples-euler1
58−::
59−:::: /hoon/euler1/examples/gen
60− ::
61−:- %say |= *
62−:- %noun
63−=< (sum 1.000)
64−::
65−:::: ~sivtyv-barnel
66− ::
67−|%
68−++ three
69− |= a/@
70− =| b/@
71− |- ^- @u
72− ?: (lth a b)
73− 0
74− (add b $(b (add 3 b)))
75−
76−++ five
77− |= a/@
78− =| b/@
79− |- ^- @
80− ?: (lte a b)
81− 0
82− ?: =((mod b 3) 0)
83− $(b (add b 5))
84− (add b $(b (add b 5)))
85−
86−++ sum
87− |= a/@u
88− (add (five a) (three a))
89−--
90−```
40+Euler 1
41+-------
9142
43+Let's check out the code for Euler 1. First, the problem:
9244
93−> Hoon is not generally whitespace sensitive, but we do have two
94−> different kinds of whitespace: a single space and a gap, which
95−> is two or more spaces or a linebreak. Tabs are taboo. Do not
96−> use them. Really. For a more detailed explanation of when to
97−> use spaces vs. gaps, see the syntax section before the first
98−> exercises.
45+ If we list all the natural numbers below 10 that are multiples of
46+ 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
47+
48+ Find the sum of all the multiples of 3 or 5 below 1000.
9949
50+Here is the hoon solution (which should be in your pier directory under
51+`/gen/examples/euler1`):
52+
53+ :: project euler 1
54+ :: https://projecteuler.net/problem=1
55+ :: run in dojo with +examples-euler1
56+ ::
57+ :::: /hoon/euler1/examples/gen
58+ ::
59+ :- %say |= *
60+ :- %noun
61+ =< (sum 1.000)
62+ ::
63+ :::: ~sivtyv-barnel
64+ ::
65+ |%
66+ ++ three
67+ |= a/@
68+ =| b/@
69+ |- ^- @u
70+ ?: (lth a b)
71+ 0
72+ (add b $(b (add 3 b)))
73+
74+ ++ five
75+ |= a/@
76+ =| b/@
77+ |- ^- @
78+ ?: (lte a b)
79+ 0
80+ ?: =((mod b 3) 0)
81+ $(b (add b 5))
82+ (add b $(b (add b 5)))
83+
84+ ++ sum
85+ |= a/@u
86+ (add (five a) (three a))
87+ --
88+
89+> Hoon is not generally whitespace sensitive, but we do have two
90+> different kinds of whitespace: a single space and a gap, which is two
91+> or more spaces or a linebreak. Tabs are taboo. Do not use them.
92+> Really. For a more detailed explanation of when to use spaces vs.
93+> gaps, see the syntax section before the first exercises.
10094
10195### Lines 1-11:
10296
@@ -106,82 +100,78 @@ Any line that begins with `::` is a comment.
106100 :- %noun
107101 =< (sum 1.000)
108102
109−All you need to know about the lines above is that they call the
110−`++sum` function with an argument of `1.000`. We'll cover them in
111−more detail later.
103+All you need to know about the lines above is that they call the `++sum`
104+function with an argument of `1.000`. We'll cover them in more detail
105+later.
112106
113107### How to form expressions
114108
115109Hoon does not typically use reserved words to form expressions. Instead,
116−expressions are formed with _runes_: digraphs of two
117−ASCII symbols. Each rune takes a specific number of
118−children, either expressions formed by other runes or literals
119−that produce their own value (some runes take _N_ children, and are usually closed with `==`).
110+expressions are formed with *runes*: digraphs of two ASCII symbols. Each
111+rune takes a specific number of children, either expressions formed by
112+other runes or literals that produce their own value (some runes take
113+*N* children, and are usually closed with `==`).
120114
121−For example, the rune `?:` from line 17 is the classic
122−'if-then-else' statement, and thus takes three children:
115+For example, the rune `?:` from line 17 is the classic 'if-then-else'
116+statement, and thus takes three children:
123117
124118 ?: (lth a b) :: if first child evals to true
125119 0 :: then produce result of second
126120 (add b $(b (add 3 b))) :: else, produce result of third
127121
128−Since runes are such a fundamental structure in Hoon, we found
129−ourselves speaking them out loud frequently. It quickly grew
130−cumbersome to have to say "question mark, colon" to describe
131−`?:`. To alleviate this problem, we came up with our own naming
132−scheme: each ASCII glyph has a single-syllable pronunciation
133−phonetically designed to be both easily remembered and easily
134−pronounced in conjunction with the other glyphs (when forming a
135−rune).
122+Since runes are such a fundamental structure in Hoon, we found ourselves
123+speaking them out loud frequently. It quickly grew cumbersome to have to
124+say "question mark, colon" to describe `?:`. To alleviate this problem,
125+we came up with our own naming scheme: each ASCII glyph has a
126+single-syllable pronunciation phonetically designed to be both easily
127+remembered and easily pronounced in conjunction with the other glyphs
128+(when forming a rune).
136129
137130See the entire naming scheme below.
138131
139−```
140− ace [1 space] gal < pel (
141− bar | gap [>1 space, \n] per )
142− bas \ gar > sel [
143− buc $ hax # sem ;
144− cab _ hep - ser ]
145− cen % kel { soq '
146− col : ker } tar *
147− com , ket ^ tec `
148− doq " lus + tis =
149− dot . pam & wut ?
150− fas / pat @ zap !
151−```
132+ ace [1 space] gal < pel (
133+ bar | gap [>1 space, \n] per )
134+ bas \ gar > sel [
135+ buc $ hax # sem ;
136+ cab _ hep - ser ]
137+ cen % kel { soq '
138+ col : ker } tar *
139+ com , ket ^ tec `
140+ doq " lus + tis =
141+ dot . pam & wut ?
142+ fas / pat @ zap !
152143
153144Using this scheme, we would pronounce `?:` as 'wutcol'.
154145
155−For those who prefer to use reserved words to form expressions, you can substitute any rune with that rune's keyword, which you can find in `++twig` in `/arvo/hoon.hoon`. For example, here's the code for `?:` in `++twig`:
146+For those who prefer to use reserved words to form expressions, you can
147+substitute any rune with that rune's keyword, which you can find in
148+`++twig` in `/arvo/hoon.hoon`. For example, here's the code for `?:` in
149+`++twig`:
156150
157151`{$if p/twig q/twig r/twig} :: ?: if/then/else`
158152
159−Instead of:
153+Instead of:
154+
155+ ?:(=(1 2) 'this is true' 'this is false')
156+ 'this is false'`
160157
161−```
162−?:(=(1 2) 'this is true' 'this is false')
163−'this is false'`
164−```
165158You can write:
166159
167−```
168−if(=(1 2) 'this is true' 'this is false')
169−'this is false'
170−```
160+ if(=(1 2) 'this is true' 'this is false')
161+ 'this is false'
171162
172163### Lines 12-34
173164
174−Now let's quickly walk through this code line-by-line. Lines
175−12-34 are wrapped in a `|%` ('barcen'), which produces a core.
176−Cores are a fundamental datatype in Hoon, similar to a
177−struct, class, or object. A core is just a map of names
178−to any kind of code, whether it be functions or data. Each
179−element in this map begins with a `++` followed by the name and
180−the corresponding code. Since `|%` takes an arbitrary number of
165+Now let's quickly walk through this code line-by-line. Lines 12-34 are
166+wrapped in a `|%` ('barcen'), which produces a core. Cores are a
167+fundamental datatype in Hoon, similar to a struct, class, or object. A
168+core is just a map of names to any kind of code, whether it be functions
169+or data. Each element in this map begins with a `++` followed by the
170+name and the corresponding code. Since `|%` takes an arbitrary number of
181171children, it needs to be closed with a `--`.
182172
183−> `++` ('luslus') is not technically a rune, since it is only used
184−> in core syntax, as shown above.
173+> `++` ('luslus') is not technically a rune, since it is only used in
174+> core syntax, as shown above.
185175
186176Let's step into each of the three arms within our core.
187177
@@ -192,19 +182,19 @@ Let's step into each of the three arms within our core.
192182 (add (five a) (three a))
193183 --
194184
195−`|=` ('bartis') produces a function, much like a lambda in lisp. It takes two children:
185+`|=` ('bartis') produces a function, much like a lambda in lisp. It
186+takes two children:
196187
197−1. A set of argument(s). In this case our argument set only
198− contains one: `a`, which is required to be an atom or natural
199− number, denoted by `@`.
188+1. A set of argument(s). In this case our argument set only contains
189+ one: `a`, which is required to be an atom or natural number, denoted
190+ by `@`.
200191
201−1. The body of the function itself, which is executed when the
202− function is called (in this case, with `(sum 1.000)`). This
203− particular function adds the results of evaluating the gates `++
204− five` and `++three` with each of their respective input
205− parameters set to `a`.
192+2. The body of the function itself, which is executed when the function
193+ is called (in this case, with `(sum 1.000)`). This particular
194+ function adds the results of evaluating the gates `++ five` and
195+ `++three` with each of their respective input parameters set to `a`.
206196
207−### ++ three
197+### ++ three
208198
209199 ++ three
210200 |= a/@
@@ -214,27 +204,23 @@ Let's step into each of the three arms within our core.
214204 0
215205 (add b $(b (add 3 b)))
216206
217−As above, `++three` takes an integer argument, `a`, and then
218−executes the remainder of the code with `a` set to the actual
219−arguments.
220−
221−Similarly, `=|` ('tisbar') pushes its first child, `b` into our
222−context (in other words, it declares a variable `b`) and executes
223−the remainder of the code. However, `b` is not an argument; `=|`
224−sets `b` to the default value of whatever type it is declared as.
225−Since the default value of an atom is `0`, b is set to `0`.
226−
227−> To produce the default value of any given type, use `$*` ('buctar') followed by the type.
228−> Alternatively, use the irregular form `*`.
229−>
230−> ```
231−> > *@ :: produce the default value of atom @
232−> 0
233−>
234−> > *@p :: produce the phonemic base of atom @
235−> ~zod
236−>
237−> ```
207+As above, `++three` takes an integer argument, `a`, and then executes
208+the remainder of the code with `a` set to the actual arguments.
209+
210+Similarly, `=|` ('tisbar') pushes its first child, `b` into our context
211+(in other words, it declares a variable `b`) and executes the remainder
212+of the code. However, `b` is not an argument; `=|` sets `b` to the
213+default value of whatever type it is declared as. Since the default
214+value of an atom is `0`, b is set to `0`.
215+
216+> To produce the default value of any given type, use `$*` ('buctar')
217+> followed by the type. Alternatively, use the irregular form `*`.
218+>
219+> > *@ :: produce the default value of atom @
220+> 0
221+>
222+> > *@p :: produce the phonemic base of atom @
223+> ~zod
238224
239225So now we have two variables: `a` is set to our input, and `b` is
240226initialized to `0`.
@@ -242,20 +228,19 @@ initialized to `0`.
242228One way to think about `|-` ('barhep') is that it lays down a recursion
243229point. More on this later.
244230
245−`^-` ('kethep') is just a cast that sets the result of the remainder of
231+`^-` ('kethep') is just a cast that sets the result of the remainder of
246232the code to an unsigned integer, `@u`.
247233
248−In pseudocode, the last three lines read like this: if `a` is
249−less than `b`, produce zero. Else, add `b` to the result of
250−rerunning the segment of the function following the `|-` with the
251−value of `b` changed to `b` plus three.
234+In pseudocode, the last three lines read like this: if `a` is less than
235+`b`, produce zero. Else, add `b` to the result of rerunning the segment
236+of the function following the `|-` with the value of `b` changed to `b`
237+plus three.
252238
253−The only thing that should look completely unfamiliar to you here
254−is the `$(b (add 3 b))`, which causes us to recurse back to our
255−last recursion point with the value of `b` set to `(add 3 b)`.
256−Note that we only specify what changes (`b` in this case). If
257−you recurse by an actual function call, then you have to specify
258−every argument.
239+The only thing that should look completely unfamiliar to you here is the
240+`$(b (add 3 b))`, which causes us to recurse back to our last recursion
241+point with the value of `b` set to `(add 3 b)`. Note that we only
242+specify what changes (`b` in this case). If you recurse by an actual
243+function call, then you have to specify every argument.
259244
260245> If you're familiar with Clojure, `|-` is `loop` and `$()` is `recur`.
261246
@@ -263,19 +248,18 @@ every argument.
263248
264249Tweak your code to complete the following excercises.
265250
266−There are a few runes and some syntax that we have yet to cover that
267−you will need to complete the excercises below. For these, please
268−refer to our cheatsheat at the bottom.
251+There are a few runes and some syntax that we have yet to cover that you
252+will need to complete the excercises below. For these, please refer to
253+our cheatsheat at the bottom.
269254
270−1. Read and understand `++five` line by line.
255+1. Read and understand `++five` line by line.
271256
272−1. Change `++sum` to accept two variables, `a` and `b`. Pass `a`
273− to `three` and `b` to `five`. Then run the code with `a` set to
274− `1.000` and `q` set to `2.000`.
257+2. Change `++sum` to accept two variables, `a` and `b`. Pass `a` to
258+ `three` and `b` to `five`. Then run the code with `a` set to `1.000`
259+ and `q` set to `2.000`.
275260
276−1. Check if this new result is under one thousand. If it is,
277− return the string `'result < 1.000'`. If not,
278− return `'result >= 1.000'`.
261+3. Check if this new result is under one thousand. If it is, return the
262+ string `'result < 1.000'`. If not, return `'result >= 1.000'`.
279263
280264### Review
281265
@@ -290,39 +274,37 @@ refer to our cheatsheat at the bottom.
290274
291275### New material
292276
293−1. There are two syntaxes for writing Hoon: tallform and wideform.
277+1. There are two syntaxes for writing Hoon: tallform and wideform.
278+
279+In tallform, expressions are formed with either two spaces or a line
280+break separating both a rune from its children and each of its children
281+from one another. We use tallform when writing multiline expressions.
294282
295− In tallform, expressions are formed with either two spaces or
296− a line break separating both a rune from its children and each
297− of its children from one another. We use tallform when writing
298− multiline expressions.
283+For more concise expressions, we use wideform, which is always a single
284+line. Wideform can be used inside tallform expressions, but not vice
285+versa.
299286
300− For more concise expressions, we use wideform, which is always
301− a single line. Wideform can be used inside tallform
302− expressions, but not vice versa.
303−
304− Wideform expressions are formed with a rune followed by `()`
305− containing its children, all of which are separated by a
306− single space. For example, to make a cell of two elements:
287+Wideform expressions are formed with a rune followed by `()` containing
288+its children, all of which are separated by a single space. For example,
289+to make a cell of two elements:
307290
308291 :-(a b)
309292
310− We've already seen wideform in action, for example with
311− `=((mod b 3) 0)`. In this case, `=` is actually an irregular form
312− of `.=`, which tests its two children for equality.
293+We've already seen wideform in action, for example with
294+`=((mod b 3) 0)`. In this case, `=` is actually an irregular form of
295+`.=`, which tests its two children for equality.
313296
314− Surrounding a function with `()` is an irregular wide form
315− syntax for calling a function with _N_ arguments. More on this later.
297+Surrounding a function with `()` is an irregular wide form syntax for
298+calling a function with *N* arguments. More on this later.
316299
317−1. `:-` makes a cell of values. The irregular wide form of this is
318− `[a b]`, with two expressions separated by a single space.
319− While the regular form of this rune takes a fixed number of
320− children (two), its irregular wide form can accept _N_ expressions:
321− `[a1..an]`
300+1. `:-` makes a cell of values. The irregular wide form of this is
301+ `[a b]`, with two expressions separated by a single space. While the
302+ regular form of this rune takes a fixed number of children (two),
303+ its irregular wide form can accept *N* expressions: `[a1..an]`
322304
323−2. Cords are one datatype for text in Hoon. They're just a big
324− atom formed from adjacent unicode bytes -- a "c string". To
325− produce a cord, enclose text within single quotes. To set the type
326− of an argument to a cord, use `@t`.
305+2. Cords are one datatype for text in Hoon. They're just a big atom
306+ formed from adjacent unicode bytes -- a "c string". To produce a
307+ cord, enclose text within single quotes. To set the type of an
308+ argument to a cord, use `@t`.
327309
328310
docs/arvo/network.md+285−310
@@ -5,364 +5,339 @@ sort: 3
55title: Network messages
66---
77
8−# Network messages
9−
10−Now we've learned enough hoon to do more interesting things.
11−Let's get our planets to talk to each other.
12−
13−All we've written up until now are just shell
14−commands that produce a value and then disappear. To listen for and receive messages from other planets, we'll need an app. Let's look at a very simple one:
15−
16−```
17−:: There is no love that is not an echo
18−::
19−:::: /hoon/echo/examples/app
20− ::
21−/? 314
22−!:
23−|_ {bowl state/$~}
24−++ poke-noun
25− |= arg/*
26− ^- {(list) _+>.$}
27− ~& [%argument arg]
28− [~ +>.$]
29−--
30−```
31−
32−
33−This is a very simple app that does only one thing. If you poke
34−it with a value, it prints that value out. To try this out, you
35−have to start the app, then you can poke it from the command line
36−with the following commands:
37−
38−```
39−~fintud-macrep:dojo> |start %echo
40−>=
41−~fintud-macrep:dojo> :examples-echo 5
42−[%argument 5]
43−>=
44−~fintud-macrep:dojo> :examples-echo [1 2]
45−[%argument [1 2]]
46−>=
47−```
48−
49−> There is currently a bug where the `%argument` lines are
50−> printed *above* the line you entered, so your output may not
51−> look exactly like this.
52−> `>=` means that a command was successfully received and
8+Network messages
9+================
10+
11+Now we've learned enough Hoon to do more interesting things. Let's get
12+our planets to talk to each other.
13+
14+All we've written up until now are just shell commands that produce a
15+value and then disappear. To listen for and receive messages from other
16+planets, we'll need an app. Let's look at a very simple one:
17+
18+ :: There is no love that is not an echo
19+ ::
20+ :::: /hoon/echo/examples/app
21+ ::
22+ /? 314
23+ !:
24+ |_ {bowl state/$~}
25+ ++ poke-noun
26+ |= arg/*
27+ ^- {(list) _+>.$}
28+ ~& [%argument arg]
29+ [~ +>.$]
30+ --
31+
32+This is a very simple app that does only one thing. If you poke it with
33+a value, it prints that value out. To try this out, you have to start
34+the app, then you can poke it from the command line with the following
35+commands:
36+
37+ ~fintud-macrep:dojo> |start %echo
38+ >=
39+ ~fintud-macrep:dojo> :examples-echo 5
40+ [%argument 5]
41+ >=
42+ ~fintud-macrep:dojo> :examples-echo [1 2]
43+ [%argument [1 2]]
44+ >=
45+
46+> There is currently a bug where the `%argument` lines are printed
47+> *above* the line you entered, so your output may not look exactly like
48+> this. `>=` means that a command was successfully received and
5349> executed.
5450
55−Most of the app code should be simple enough to guess its
56−function. The important part of this code is the definition of
57−`++poke-noun`.
51+Most of the app code should be simple enough to guess its function. The
52+important part of this code is the definition of `++poke-noun`.
5853
5954Once an app starts, it's always running in the background and you
60−interact with it by sending it messages. The most
61−straightforward way to do that is to poke it from the command
62−line, which we we did with `:echo 5` (`:[app-name]
63−[argument(s)]`).
64−
65−In this case, `++poke-noun` takes an argument `arg` and prints it
66−out with `~&` (sigpam). This is an unusual rune that formally "does
67−nothing", but the interpreter detects it and printfs the first
68−child, before executing the second as if the first didn't exist.
69−This is a slightly hacky way of printing to the console, but
70−we'll get to the correct way later on.
71−
72−But what does `++poke-noun` produce? Recall that `^-` casts to a
73−type. In this case, it's declaring that end result of the
74−function will be of type `{(list) _+>.$}`. But what does this
75−mean?
76−
77−The phrase to remember is "a list of moves and our state". Urbit
78−is a message passing system, so whenever we want to do something that
79−interacts with the rest of the system, we send a message. Thus, a
80−move is arvo's equivalent of a syscall. The first thing that
81−`++poke-noun` produces is a list of messages, called
82−"moves". In this case, we don't actually want the system to do
83−anything, so we produce the empty list, `~` (in the `[~ +>.$]`
84−line).
85−
86−The second thing `++poke-noun` produces is our state. `+>.$`
87−refers to a particular address in our subject where our formal
88−app state is stored. It'll become clear why this is later on,
89−but for now pretend that `+>.$` is a magic invocation that means
90−"app state".
91−
92−Let's look at another example (edit your code in `/app/examples/echo/hoon` to reflect the code below). Say we want to only accept a
93−number, and then print out the square of that number.
94−
95−```
96−/? 314
97−!:
98−|_ {bowl state=~}
99−::
100−++ poke-atom
101− |= arg/@
102− ^- {(list) _+>.$}
103− ~& [%square (mul arg arg)]
104− [~ +>.$]
105−--
106−```
107−
108−A few things have changed. Firstly, we no longer accept
109−arbitrary nouns because we can only square atoms (integers, in
110−this case an unsigned one). Thus, our argument is now `arg/@`.
111−Secondly, it's `++poke-atom` rather than `++poke-noun`.
112−
113−# Intro to marks
114−
115−Are there other `++poke`s? Yes. In fact, `noun` and
116−`atom` are just two of arbitrarily many "marks". A mark is
117−fundamentally a type definition, but accessible at the arvo
118−level. Each mark is defined in the `/mar` directory. Some marks
119−have conversion routines to other marks, and some have diff,
120−patch, and merge algorithms. None of these are required for a
55+interact with it by sending it messages. The most straightforward way to
56+do that is to poke it from the command line, which we we did with
57+`:echo 5` (`:[app-name] [argument(s)]`).
58+
59+In this case, `++poke-noun` takes an argument `arg` and prints it out
60+with `~&` ([sigpam](/hoon/twig/sig-hint/pam-dump/)). This is an unusual
61+rune that formally "does nothing", but the interpreter detects it and
62+printfs the first child, before executing the second as if the first
63+didn't exist. This is a slightly hacky way of printing to the console,
64+but we'll get to the correct way later on.
65+
66+But what does `++poke-noun` produce? Recall that `^-` casts to a type.
67+In this case, it's declaring that end result of the function will be of
68+type `{(list) _+>.$}`. But what does this mean?
69+
70+The phrase to remember is "a list of moves and our state". Urbit is a
71+message passing system, so whenever we want to do something that
72+interacts with the rest of the system, we send a message. Thus, a move
73+is arvo's equivalent of a syscall. The first thing that `++poke-noun`
74+produces is a list of messages, called "moves". In this case, we don't
75+actually want the system to do anything, so we produce the empty list,
76+`~` (in the `[~ +>.$]` line).
77+
78+The second thing `++poke-noun` produces is our state. `+>.$` refers to a
79+particular address in our subject where our formal app state is stored.
80+It'll become clear why this is later on, but for now pretend that `+>.$`
81+is a magic invocation that means "app state".
82+
83+Let's look at another example (edit your code in
84+`/app/examples/echo/hoon` to reflect the code below). Say we want to
85+only accept a number, and then print out the square of that number.
86+
87+ /? 314
88+ !:
89+ |_ {bowl state=~}
90+ ::
91+ ++ poke-atom
92+ |= arg/@
93+ ^- {(list) _+>.$}
94+ ~& [%square (mul arg arg)]
95+ [~ +>.$]
96+ --
97+
98+A few things have changed. Firstly, we no longer accept arbitrary nouns
99+because we can only square atoms (integers, in this case an unsigned
100+one). Thus, our argument is now `arg/@`. Secondly, it's `++poke-atom`
101+rather than `++poke-noun`.
102+
103+Intro to marks
104+==============
105+
106+Are there other `++poke`s? Yes. In fact, `noun` and `atom` are just two
107+of arbitrarily many "marks". A mark is fundamentally a type definition,
108+but accessible at the arvo level. Each mark is defined in the `/mar`
109+directory. Some marks have conversion routines to other marks, and some
110+have diff, patch, and merge algorithms. None of these are required for a
121111mark to exist, however.
122112
123−`noun` and `atom` are two predefined marks. In your `/mar`
124−directory, there are already many more, and you may add more
125−at will. The type associated with `noun` is `*`, and the type
126−associated with `atom` is `@`.
113+`noun` and `atom` are two predefined marks. In your `/mar` directory,
114+there are already many more, and you may add more at will. The type
115+associated with `noun` is `*`, and the type associated with `atom` is
116+`@`.
127117
128−When we poke an app from anywhere, we do so with a mark that
129−searches for the corresponding (`++poke-[mark]`) arm. Data
130−constructed on the command line is by default marked with `noun`.
131−In this case, the app is expecting an atom, so we have to
132−explicitly mark the data with `atom` using `&[mark]`. Try the following
133−commands:
118+When we poke an app from anywhere, we do so with a mark that searches
119+for the corresponding (`++poke-[mark]`) arm. Data constructed on the
120+command line is by default marked with `noun`. In this case, the app is
121+expecting an atom, so we have to explicitly mark the data with `atom`
122+using `&[mark]`. Try the following commands:
134123
135−```
136−~fintud-macrep:dojo> |start %square
137−>=
138−~fintud-macrep:dojo> :examples-square 6
139−gall: %square: no poke arm for noun
140−~fintud-macrep:dojo> :examples-square &atom 6
141−[%square 36]
142−>=
143−```
124+ ~fintud-macrep:dojo> |start %square
125+ >=
126+ ~fintud-macrep:dojo> :examples-square 6
127+ gall: %square: no poke arm for noun
128+ ~fintud-macrep:dojo> :examples-square &atom 6
129+ [%square 36]
130+ >=
144131
145−> Recall the bug where `%square` may get printed above the input
146−> line.
132+> Recall the bug where `%square` may get printed above the input line.
147133
148−Marks are powerful, and they're the backbone of Urbit's data
149−pipeline, so we'll be getting quite used to them.
134+Marks are powerful, and they're the backbone of Urbit's data pipeline,
135+so we'll be getting quite used to them.
150136
151137**Exercise**:
152138
153−- Write an app that computes fizzbuzz on its input (as in the
154− previous section).
155−
156−# Sending a message to another urbit
157−
158−Let's write our first network message! Here's `/app/examples/pong.hoon`:
159−
160−```
161−/? 314
162−|%
163− ++ move {bone term wire *}
164−--
165−!:
166−|_ {bowl state=$~}
167−::
168−++ poke-urbit
169− |= to/@p
170− ^- [(list move) _+>.$]
171− [[[ost %poke /sending [to %pong] %atom 'howdy'] ~] +>.$]
172−::
173−++ poke-atom
174− |= arg/@
175− ^- (list move) _+>.$}
176− ~& [%receiving (@t arg)]
177− [~ +>.$]
178−::
179−++ coup |=(* [~ +>.$])
180−--
181−```
139+- Write an app that computes fizzbuzz on its input (as in the previous
140+ section).
141+
142+Sending a message to another urbit
143+==================================
144+
145+Let's write our first network message! Here's `/app/examples/pong.hoon`:
146+
147+ /? 314
148+ |%
149+ ++ move {bone term wire *}
150+ --
151+ !:
152+ |_ {bowl state=$~}
153+ ::
154+ ++ poke-urbit
155+ |= to/@p
156+ ^- [(list move) _+>.$]
157+ [[[ost %poke /sending [to %pong] %atom 'howdy'] ~] +>.$]
158+ ::
159+ ++ poke-atom
160+ |= arg/@
161+ ^- (list move) _+>.$}
162+ ~& [%receiving (@t arg)]
163+ [~ +>.$]
164+ ::
165+ ++ coup |=(* [~ +>.$])
166+ --
182167
183168Run it with these commands:
184169
185−```
186−~fintud-macrep:dojo> |start %examples-pong
187−>=
188−~fintud-macrep:dojo> :pong &examples-urbit ~sampel-sipnym
189−>=
190−```
170+ ~fintud-macrep:dojo> |start %examples-pong
171+ >=
172+ ~fintud-macrep:dojo> :pong &examples-urbit ~sampel-sipnym
173+ >=
191174
192−Replace `~sampel-sipnym` with another urbit. The easiest thing to
193−do is to start a moon, a sub-identity of your urbit. If you don't know how to start a moon, see [the user admin section](/docs/using/admin/). Don't
194−forget to start the `%examples-pong` app on that urbit, too. You should
175+Replace `~sampel-sipnym` with another urbit. The easiest thing to do is
176+to start a moon, a sub-identity of your urbit. If you don't know how to
177+start a moon, see [the user admin section](/docs/using/admin/). Don't
178+forget to start the `%examples-pong` app on that urbit, too. You should
195179see, on the foreign urbit, this output:
196180
197−```
198−[%receiving 'howdy']
199−```
181+ [%receiving 'howdy']
200182
201−Most of the code should be straightforward. In `++poke-atom`,
202−the only new thing is the expression `(@t arg)`, which is the type `@t` being called as a function with argument `arg`. As we already
203−know, `@t` is the type of "cord" text strings. In Hoon, when types are called as functions, they serve as a validator function called a "clam" -- that is, a function whose domain is all nouns, and range is the given type (in this case, `@t`).
183+Most of the code should be straightforward. In `++poke-atom`, the only
184+new thing is the expression `(@t arg)`, which is the type `@t` being
185+called as a function with argument `arg`. As we already know, `@t` is
186+the type of "cord" text strings. In Hoon, when types are called as
187+functions, they serve as a validator function called a "clam" -- that
188+is, a function whose domain is all nouns, and range is the given type
189+(in this case, `@t`).
204190
205−In simpler terms, if a clam is passed a value of its own
206−type, it produces that value. Otherwise, it
207−produces the default value (aka the "bunt") of its type. Here we call
208−this `@t` function on the argument. This coerces the argument
209−to text, so that we can print it out prettily no matter what
210−we're passed.
191+In simpler terms, if a clam is passed a value of its own type, it
192+produces that value. Otherwise, it produces the default value (aka the
193+"bunt") of its type. Here we call this `@t` function on the argument.
194+This coerces the argument to text, so that we can print it out prettily
195+no matter what we're passed.
211196
212−The more interesting part is in `++poke-urbit`. The `urbit` mark
213−is an urbit identity, and the hoon type associated with it is
214−`@p` (the "p" stands for "phonetic base").
197+The more interesting part is in `++poke-urbit`. The `urbit` mark is an
198+urbit identity, and the Hoon type associated with it is `@p` (the "p"
199+stands for "phonetic base").
215200
216201Recall that in a `++poke` arm we produce "a list of moves and our
217−state". Until now, we've left the list of moves empty, since we
218−haven't wanted to tell arvo to do anything in particular. Now we
219−want to send a message to another urbit. Thus, we produce a list
220−with one element:
202+state". Until now, we've left the list of moves empty, since we haven't
203+wanted to tell arvo to do anything in particular. Now we want to send a
204+message to another urbit. Thus, we produce a list with one element:
221205
222−```
223−[ost %poke /sending [to-urbit-address %pong] %atom 'howdy']
224−```
206+ [ost %poke /sending [to-urbit-address %pong] %atom 'howdy']
225207
226208### Moves
227209
228−The general form of a move is
229−
230−-arvo part---->
231−`[bone term wire *]`
232−
233−------------------------->app/vane-specific part of move
210+The general form of a move is `[bone term wire *]`.
234211
235212Or, in pseudo-code:
236213
237−`["cause" sys-call/action tack-new-layer-on-cause action-specific
238−information]`
214+`["cause" sys-call/action tack-new-layer-on-cause action-specific information]`
239215
240216Let's walk through each of these elements step by step.
241217
242218#### Bones ("cause")
243219
244−If you look up `++bone` in `hoon.hoon`, you'll see that it's a
245−number (`@ud`), and that it's an opaque reference to a duct.
246−`++duct` in hoon.hoon is a list of `wire`s, where `++wire` is an
247−alias for `++path`. `++path` is a list of `++span`s, which are ASCII
248−text. Thus, a duct is a list of paths, and a bone is an opaque
249−reference to it (in the same way that a Unix file
250−descriptor is an opaque reference to a file structure). Thus, to
251−truly understand bones, we must understand ducts.
252−
253−A duct is stack of causes, again, represented as paths, which are
254−called wires. At the bottom of every duct is a unix event, such
255−as a keystroke, network packet, file change, or timer event.
256−When arvo is given this event, it routes the event to appropriate
257−kernel module for handling.
258−
259−Sometimes, the module can immediately handle the event and
260−produce any necessary results. For example, when we poked the
261−`++poke-atom` arm above, we poked %gall, our application server,
262−which was able to respond to our poke directly. When the module
263−cannot service the request itself, it sends instructions to another kernel
264−module or application (the the %gall module) to do a specified action, and produces the result from that.
265−
266−Furthermore, when one module sends a message to another kernel module or application, it also sends along the duct it was given
267−with its new wire tacked onto the end. Now the duct has two entries,
268−with the unix even on the bottom and the kernel module that
269−handled it next. This process can continue indefinitely, adding
270−more and more layers onto the duct. When an entity finally
271−produces a result, a layer is popped off the duct, and the result
272−is passed all the way back down.
273−
274−In effect, a duct is an arvo-level call stack. It's worth noting
275−that while in traditional call stacks a function call happens
276−synchronously and returns exactly once. In arvo, multiple moves
277−can be sent at once, are evaluated asynchronously, and each
278−one may be responded to zero or more times.
220+If you look up `++bone` in `hoon.hoon`, you'll see that it's a number
221+(`@ud`), and that it's an opaque reference to a duct. `++duct` in
222+hoon.hoon is a list of `wire`s, where `++wire` is an alias for `++path`.
223+`++path` is a list of `++span`s, which are ASCII text. Thus, a duct is a
224+list of paths, and a bone is an opaque reference to it (in the same way
225+that a Unix file descriptor is an opaque reference to a file structure).
226+Thus, to truly understand bones, we must understand ducts.
227+
228+A duct is stack of causes, again, represented as paths, which are called
229+wires. At the bottom of every duct is a unix event, such as a keystroke,
230+network packet, file change, or timer event. When arvo is given this
231+event, it routes the event to appropriate kernel module for handling.
232+
233+Sometimes, the module can immediately handle the event and produce any
234+necessary results. For example, when we poked the `++poke-atom` arm
235+above, we poked %gall, our application server, which was able to respond
236+to our poke directly. When the module cannot service the request itself,
237+it sends instructions to another kernel module or application (the the
238+%gall module) to do a specified action, and produces the result from
239+that.
240+
241+Furthermore, when one module sends a message to another kernel module or
242+application, it also sends along the duct it was given with its new wire
243+tacked onto the end. Now the duct has two entries, with the unix even on
244+the bottom and the kernel module that handled it next. This process can
245+continue indefinitely, adding more and more layers onto the duct. When
246+an entity finally produces a result, a layer is popped off the duct, and
247+the result is passed all the way back down.
248+
249+In effect, a duct is an arvo-level call stack. It's worth noting that
250+while in traditional call stacks a function call happens synchronously
251+and returns exactly once. In arvo, multiple moves can be sent at once,
252+are evaluated asynchronously, and each one may be responded to zero or
253+more times.
279254
280255The point to take home is that whatever caused `++poke-urbit` to be
281−called is also the root cause for the network message we're
282−trying to send. Thus, we say to send the network message along the given bone
256+called is also the root cause for the network message we're trying to
257+send. Thus, we say to send the network message along the given bone
283258`ost`.
284259
285260##### Wire ('tack on new layer to duct')
286261
287−Of course, we have to push a new layer onto our duct
288−before passing it along (or responding to it directly) anywhere. This
289−layer can have any data we want in it, but we don't need anything
290−specific here, so we just use the wire `/sending`
291−(`/elem1/elem2/elemN` is one syntax used to create `++path`s and
292−`++wire`s of N elements). If we were expecting a response (which
293−we're not), it would come back along the `/sending` wire, meaning
294−that the path `/sending` will be passed back to the response
295−handler as an argument. Although it's not required, it's
296−generally a good idea to make the wire human-readable for
297−bug-handling purposes.
262+Of course, we have to push a new layer onto our duct before passing it
263+along (or responding to it directly) anywhere. This layer can have any
264+data we want in it, but we don't need anything specific here, so we just
265+use the wire `/sending` (`/elem1/elem2/elemN` is one syntax used to
266+create `++path`s and `++wire`s of N elements). If we were expecting a
267+response (which we're not), it would come back along the `/sending`
268+wire, meaning that the path `/sending` will be passed back to the
269+response handler as an argument. Although it's not required, it's
270+generally a good idea to make the wire human-readable for bug-handling
271+purposes.
298272
299273##### Term (sys-call)
300274
301275Each move also has a `term`, composed of lowercase ASCII and/or `-`.
302−This `term` has the sign `@tas`. In this case, out `term` is `%poke`,
303−which is the name of the particular kind of move we're sending.
304−You can always use `%poke` to message an app. Other common names
305−include `%warp`, to read from the filesystem; `%wait`, to
306−set a timer; and `%them`, to send an http request.
276+This `term` has the sign `@tas`. In this case, out `term` is `%poke`,
277+which is the name of the particular kind of move we're sending. You can
278+always use `%poke` to message an app. Other common names include
279+`%warp`, to read from the filesystem; `%wait`, to set a timer; and
280+`%them`, to send an http request.
307281
308282The move ends with `*` (that is, any noun) since each type of move takes
309−different data. In our case, a `%poke` move takes a target
310−(urbit and app) and marked data, then pokes the arm of the
311−corresponding mark on that app on that urbit
312−with that data. `[to-urbit-address %pong]` is the target urbit and app,
313−`%atom` is the mark`, and `'howdy'` is the data.
314−
315−When arvo receives a `%poke` move, it calls the appropriate
316−`++poke`. The same mechanism is used for sending messages
317−between apps on the same urbit as for sending messages between
318−apps on different urbits.
319−
320−> We said earlier that we're not expecting a response. This is
321−> not entirely true: the `++coup` is called when we receive
322−> acknowledgment that the `++poke` was called. We don't do
323−> anything with this information right now, but we could.
283+different data. In our case, a `%poke` move takes a target (urbit and
284+app) and marked data, then pokes the arm of the corresponding mark on
285+that app on that urbit with that data. `[to-urbit-address %pong]` is the
286+target urbit and app, `%atom` is the mark`, and`'howdy'\` is the data.
287+
288+When arvo receives a `%poke` move, it calls the appropriate `++poke`.
289+The same mechanism is used for sending messages between apps on the same
290+urbit as for sending messages between apps on different urbits.
291+
292+> We said earlier that we're not expecting a response. This is not
293+> entirely true: the `++coup` is called when we receive acknowledgment
294+> that the `++poke` was called. We don't do anything with this
295+> information right now, but we could.
324296
325297**Exercises**:
326298
327−- Extend either of the apps in the first two exercises to accept
328− input over the network in the same way as `pong`.
329−
330−- Modify `examples-pong` to print out a message when it receives acknowledgement.
331−
332−- Write two apps, `even` and `odd`. When you pass an atom to
333− `even`, check whether it's even. If so, divide it by two and
334− recurse; otherwise, poke `odd` with it. When `odd` recieves
335− an atom, check whether it's equal to one. If so, terminate,
336− printing "%success". Otherwise, check whether it's odd. If
337− so, multiply it by three, add one, and recurse; otherwise, poke
338− `even` with it. When either app receives a number, print it out along with the name of the app. In the end, you should be able to watch Collatz's
339− conjecture play out between the two apps. Sample output:
340−
341−```
342−~fintud-macrep:dojo> :even &atom 18
343−[%even 18]
344−[%odd 9]
345−[%even 28]
346−[%even 14]
347−[%odd 7]
348−[%even 22]
349−[%odd 11]
350−[%even 34]
351−[%odd 17]
352−[%even 52]
353−[%even 26]
354−[%odd 13]
355−[%even 40]
356−[%even 20]
357−[%even 10]
358−[%odd 5]
359−[%even 16]
360−[%even 8]
361−[%even 4]
362−[%even 2]
363−%success
364−```
365−
366−- Put `even` and `odd` on two separate urbits and pass the
367− messages over the network. Post a link to a working solution
368− in :talk to receive a cookie.
299+- Extend either of the apps in the first two exercises to accept input
300+ over the network in the same way as `pong`.
301+
302+- Modify `examples-pong` to print out a message when it receives
303+ acknowledgement.
304+
305+- Write two apps, `even` and `odd`. When you pass an atom to `even`,
306+ check whether it's even. If so, divide it by two and recurse;
307+ otherwise, poke `odd` with it. When `odd` recieves an atom, check
308+ whether it's equal to one. If so, terminate, printing "%success".
309+ Otherwise, check whether it's odd. If so, multiply it by three, add
310+ one, and recurse; otherwise, poke `even` with it. When either app
311+ receives a number, print it out along with the name of the app. In
312+ the end, you should be able to watch Collatz's conjecture play out
313+ between the two apps. Sample output:
314+
315+<!-- -->
316+
317+ ~fintud-macrep:dojo> :even &atom 18
318+ [%even 18]
319+ [%odd 9]
320+ [%even 28]
321+ [%even 14]
322+ [%odd 7]
323+ [%even 22]
324+ [%odd 11]
325+ [%even 34]
326+ [%odd 17]
327+ [%even 52]
328+ [%even 26]
329+ [%odd 13]
330+ [%even 40]
331+ [%even 20]
332+ [%even 10]
333+ [%odd 5]
334+ [%even 16]
335+ [%even 8]
336+ [%even 4]
337+ [%even 2]
338+ %success
339+
340+- Put `even` and `odd` on two separate urbits and pass the messages
341+ over the network. Post a link to a working solution in :talk to
342+ receive a cookie.
343+
docs/arvo/state.md+85−93
@@ -5,108 +5,100 @@ sort: 4
55title: State
66---
77
8−# State
9−
10−In the last section we built a few small apps that sent moves.
11−These apps were entirely stateless, however. Most useful apps
12−require some amount of state. Let's build a trivial stateful
13−app. It'll keep a running the sum of all the atoms we poke it with.
14−Here's `app/examples/sum.hoon`:
15−
16−```
17−/? 314
18−!:
19−|_ {bowl state/@}
20−++ poke-atom
21− |= arg/@
22− ^- {(list) _+>.$}
23− ?: =(arg 0)
24− [~ +>.$(state 0)]
25− ~& [%so-far (add state arg)]
26− [~ +>.$(state (add state arg))]
27−--
28−```
8+State
9+=====
10+
11+In the last section we built a few small apps that sent moves. These
12+apps were entirely stateless, however. Most useful apps require some
13+amount of state. Let's build a trivial stateful app. It'll keep a
14+running the sum of all the atoms we poke it with. Here's
15+`app/examples/sum.hoon`:
16+
17+ /? 314
18+ !:
19+ |_ {bowl state/@}
20+ ++ poke-atom
21+ |= arg/@
22+ ^- {(list) _+>.$}
23+ ?: =(arg 0)
24+ [~ +>.$(state 0)]
25+ ~& [%so-far (add state arg)]
26+ [~ +>.$(state (add state arg))]
27+ --
2928
3029We can start it with `|start %examples-sum`, and then run it:
3130
32−```
33−~fintud-macrep:dojo> :examples-sum &atom 5
34−[%so-far 5]
35−>=
36−~fintud-macrep:dojo> :examples-sum &atom 2
37−[%so-far 7]
38−>=
39−~fintud-macrep:dojo> :examples-sum &atom 15
40−[%so-far 22]
41−>=
42−```
43−
44−We can see that app state is being saved, but when, where, and
45−how?
46−
47−The state is stored as the second thing in the `|_` line. In our
48−case, it's simply an atom named `state`. We change it by
49−producing as our state not with `+>.$` (as before), but with `+>.$(state (add state arg))`. We've seen all these parts before, but you might not
50−recognize them.
31+ ~fintud-macrep:dojo> :examples-sum &atom 5
32+ [%so-far 5]
33+ >=
34+ ~fintud-macrep:dojo> :examples-sum &atom 2
35+ [%so-far 7]
36+ >=
37+ ~fintud-macrep:dojo> :examples-sum &atom 15
38+ [%so-far 22]
39+ >=
40+
41+We can see that app state is being saved, but when, where, and how?
42+
43+The state is stored as the second thing in the `|_` line. In our case,
44+it's simply an atom named `state`. We change it by producing as our
45+state not with `+>.$` (as before), but with
46+`+>.$(state (add state arg))`. We've seen all these parts before, but
47+you might not recognize them.
5148
5249Recall in the first chapter that we recursed with the expression
53−`$(b (add 3 b))`. This meant "produce `$` with `b` changed to
54−`(add 3 b)`. Similarly, `+>.$(state (add state arg))` means
55−"produce `+>.$` (i.e. our context, which contains our state) with
56−`state` changed to `(add state arg)`.
57−
58−At a high level, then, when we handle state, we do it explicitly.
59−It's passed in and produced explicitly. In Unix systems,
60−application state is just a block of memory, which you need to
61−serialize to disk if you want to keep it around for very long.
62−
63−In Urbit, app state is a single (usually complex) value. In our
64−example, we have very simple state, so we defined `state=@`,
65−meaning that our state is an atom. Of course, `state` is just a
66−name, and you're free to name your state whatever you like. But
67−let's clarify a couple other things before we continue.
68−
69−First, `bowl` is a set of general global states. This set is
70−managed by the system. It includes things like `now` (the
71−current time), `our` (our urbit identity), and `eny` (256 bits
72−of guaranteed-fresh entropy). For the full list of things in
73−`++bowl`, search for `++ bowl` (note: two spaces) in
74−`/arvo/zuse.hoon`.
75−
76−> This is, perhaps, the most common way to learn Hoon.
77−> The easiest way to learn about an identifier you see in code
78−> is to search in `/arvo/zuse.hoon` and `/arvo/hoon.hoon` for it.
79−> These "standard libraries" are usually simple to read. Since
80−> Urbit's codebase is less than 15000 lines of code combined,
81−> including the hoon parser, the compiler, and the
82−> `/arvo` microkernel, you can usually use the code and its
83−> comments as a reference doc.
50+`$(b (add 3 b))`. This meant "produce `$` with `b` changed to
51+`(add 3 b)`. Similarly, `+>.$(state (add state arg))` means "produce
52+`+>.$` (i.e. our context, which contains our state) with `state` changed
53+to `(add state arg)`.
54+
55+At a high level, then, when we handle state, we do it explicitly. It's
56+passed in and produced explicitly. In Unix systems, application state is
57+just a block of memory, which you need to serialize to disk if you want
58+to keep it around for very long.
59+
60+In Urbit, app state is a single (usually complex) value. In our example,
61+we have very simple state, so we defined `state=@`, meaning that our
62+state is an atom. Of course, `state` is just a name, and you're free to
63+name your state whatever you like. But let's clarify a couple other
64+things before we continue.
65+
66+First, `bowl` is a set of general global states. This set is managed by
67+the system. It includes things like `now` (the current time), `our` (our
68+urbit identity), and `eny` (256 bits of guaranteed-fresh entropy). For
69+the full list of things in `++bowl`, search for `++ bowl` (note: two
70+spaces) in `/arvo/zuse.hoon`.
71+
72+> This is, perhaps, the most common way to learn Hoon. The easiest way
73+> to learn about an identifier you see in code is to search in
74+> `/arvo/zuse.hoon` and `/arvo/hoon.hoon` for it.\
75+> These "standard libraries" are usually simple to read. Since Urbit's
76+> codebase is less than 15000 lines of code combined, including the hoon
77+> parser, the compiler, and the `/arvo` microkernel, you can usually use
78+> the code and its comments as a reference doc.
8479>
85−> You can also read [zuse.hoon](https://github.com/urbit/arvo/blob/master/arvo/zuse.hoon) and [hoon.hoon](https://github.com/urbit/arvo/blob/master/arvo/hoon.hoon) in your browser.
86−
87−The second thing we should clear up is this:
88−Urbit needs no "serialize to disk" step.
89−Everything you produce in the app state is persistent across
90−calls to the app, restarts of the urbit, and even power failure.
80+> You can also read
81+> [zuse.hoon](https://github.com/urbit/arvo/blob/master/arvo/zuse.hoon)
82+> and
83+> [hoon.hoon](https://github.com/urbit/arvo/blob/master/arvo/hoon.hoon)
84+> in your browser.
85+
86+The second thing we should clear up is this: Urbit needs no "serialize
87+to disk" step. Everything you produce in the app state is persistent
88+across calls to the app, restarts of the urbit, and even power failure.
9189If you want to write to the Unix filesystem, you can, but it's not
92−needed for persistence. Urbit has transactional events, which
93−makes it an [ACID operating system](https://en.wikipedia.org/wiki/ACID). Thus, you don't have to
94−worry about persistence when programming in Urbit, or ever go
95−through the hassle of having to set up and write to a database.
90+needed for persistence. Urbit has transactional events, which makes it
91+an [ACID operating system](https://en.wikipedia.org/wiki/ACID). Thus,
92+you don't have to worry about persistence when programming in Urbit, or
93+ever go through the hassle of having to set up and write to a database.
9694
9795**Exercises**:
9896
99−- Modify `:examples-sum` to reset the counter when you poke it with 0.
97+- Modify `:examples-sum` to reset the counter when you poke it with 0.
10098
101−- Write an app that prints out the previous value you poked it
102− with. Sample output:
99+- Write an app that prints out the previous value you poked it with.
100+ Sample output:
103101
104−```
105−~fintud-macrep:dojo> :examples-last 7
106−[%last 0]
107−>=
108−~fintud-macrep:dojo> :examples-last [1 2 3]
109−[%last 7]
110−>=
111−~fintud-macrep:dojo> :examples-last 'howdy'
112−[%last [1 2 3]]
102+\`\`\` \~fintud-macrep:dojo\> :examples-last 7 [%last 0] \>=
103+\~fintud-macrep:dojo\> :examples-last [1 2 3][%last 7] \>=
104+\~fintud-macrep:dojo\> :examples-last 'howdy' [%last [1 2 3]]
docs/arvo/subject.md+86−87
@@ -5,103 +5,102 @@ next: true
55title: The subject
66---
77
8−# The subject
8+The subject
9+===========
910
10−Now we're going to cover the boiler plate that we skimmed over
11−earlier.
11+Now we're going to cover the boiler plate that we skimmed over earlier.
1212
1313 :- %say |= *
1414 :- %noun
1515 =< (sum [1.000 2.000])
16−
17−The first rune, `:-` (colhep, aka [:cons](/hoon/twig/col-cell/hep-cons/)),
18−constructs the 2-element cell that will be our program. The first element,
19−`%say`, tells the interpreter what to produce--in this case a value.
20−
21−The second element is `|=`, which we know produces a function.
22−`|=`'s first child is its argument(s), which in this case is any
23−noun (`*`). Its second child is the remainder of the program.
24−
25−Similarly, the rest of the program (which we construct
26−with another `:-`) is a cell of the literal `%noun`, which tells
27−the shell that we're producing a value of type `noun`, and the
28−code that we run to actually produce our value of the type `noun`.
29−
30−`=<` (tisgal) is a rune that takes two children. The second child is the
31−context against which we run the first child. So in this case, we
32−are running the expression `(sum [1.000 2.000])` against everything
33−contained within the `|%`. In Hoon, we call the code executed the
34−"formula" and its context the "subject".
35−
36−```
37−::::::::::::::::::::::::::::::
38−=< (sum [1.000 2.000]) :: formula
39−::::::::::::::::::::::::::::::
40−|% ::
41−++ three ::
42− |= a/@ ::
43− =| b/@ ::
44− |- ^- @u ::
45− ?: (lth a b) ::
46− 0 ::
47− (add b $(b (add 3 b))) ::
48− ::
49−++ five ::
50− |= a/@ :: subject
51− =| b/@ ::
52− |- ^- @ ::
53− ?: (lte a b) ::
54− 0 ::
55− ?: =((mod b 3) 0) ::
56− $(b (add b 5)) ::
57− (add b $(b (add b 5))) ::
58− ::
59−++ sum ::
60− |= a/@u ::
61− (add (five a) (three a)) ::
62−-- ::
63−::::::::::::::::::::::::::::::
64−```
65−
66−In nearly every language there is a similar concept of a
67−"context" in which expressions are executed. For example, in C
68−this includes things like the call stack, stack variables, and so
69−on.
70−
71−Hoon is unique in that this context is a first-class value.
72−Scheme allows a sort of reification of the context through
73−continutations, and some may see a parallel to Forth's stack, but
74−Hoon takes takes the concept one step further.
75−
76−Our starting subject is the [standard library](/hoon/library), which is defined in
77−`/arvo/hoon.hoon` and `/arvo/zuse.hoon`. This is where functions
78−like `add` are defined. When we define a core with `|%`, we
79−don't throw away the subject (i.e. the standard library); rather,
80−we stack the new core on top of the old subject so that both are
16+
17+The first rune, `:-` (colhep, aka
18+[:cons](/hoon/twig/col-cell/hep-cons/)), constructs the 2-element cell
19+that will be our program. The first element, `%say`, tells the
20+interpreter what to produce--in this case a value.
21+
22+The second element is `|=`, which we know produces a function. `|=`'s
23+first child is its argument(s), which in this case is any noun (`*`).
24+Its second child is the remainder of the program.
25+
26+Similarly, the rest of the program (which we construct with another
27+`:-`) is a cell of the literal `%noun`, which tells the shell that we're
28+producing a value of type `noun`, and the code that we run to actually
29+produce our value of the type `noun`.
30+
31+`=<` ([tisgal](/hoon/twig/tis-flow/gal-rap/)) is a rune that takes two
32+children. The second child is the context against which we run the first
33+child. So in this case, we are running the expression
34+`(sum [1.000 2.000])` against everything contained within the `|%`. In
35+Hoon, we call the code executed the "formula" and its context the
36+"subject".
37+
38+ ::::::::::::::::::::::::::::::
39+ =< (sum [1.000 2.000]) :: formula
40+ ::::::::::::::::::::::::::::::
41+ |% ::
42+ ++ three ::
43+ |= a/@ ::
44+ =| b/@ ::
45+ |- ^- @u ::
46+ ?: (lth a b) ::
47+ 0 ::
48+ (add b $(b (add 3 b))) ::
49+ ::
50+ ++ five ::
51+ |= a/@ :: subject
52+ =| b/@ ::
53+ |- ^- @ ::
54+ ?: (lte a b) ::
55+ 0 ::
56+ ?: =((mod b 3) 0) ::
57+ $(b (add b 5)) ::
58+ (add b $(b (add b 5))) ::
59+ ::
60+ ++ sum ::
61+ |= a/@u ::
62+ (add (five a) (three a)) ::
63+ -- ::
64+ ::::::::::::::::::::::::::::::
65+
66+In nearly every language there is a similar concept of a "context" in
67+which expressions are executed. For example, in C this includes things
68+like the call stack, stack variables, and so on.
69+
70+Hoon is unique in that this context is a first-class value. Scheme
71+allows a sort of reification of the context through continutations, and
72+some may see a parallel to Forth's stack, but Hoon takes takes the
73+concept one step further.
74+
75+Our starting subject is the [standard library](/hoon/library), which is
76+defined in `/arvo/hoon.hoon` and `/arvo/zuse.hoon`. This is where
77+functions like `add` are defined. When we define a core with `|%`, we
78+don't throw away the subject (i.e. the standard library); rather, we
79+stack the new core on top of the old subject so that both are
8180accessible.
8281
8382**Exercises**:
8483
85−- Pass `++sum` its arguments (`2.000` and `3.000`) from the
86− commandline.
84+- Pass `++sum` its arguments (`2.000` and `3.000`) from the
85+ commandline.
8786
88−- Comment out all of the arms of the `|%`. Now add another arm
89− and call it `++add`, have it accept two arguments and procduce
90− 42 (regardless of input). Change the `=<` line to `[(add 5 7)
91− (^add 5 7)]`. Can you recognize what's happening?
87+- Comment out all of the arms of the `|%`. Now add another arm and
88+ call it `++add`, have it accept two arguments and procduce 42
89+ (regardless of input). Change the `=<` line to
90+ `[(add 5 7) (^add 5 7)]`. Can you recognize what's happening?
9291
9392Cheatsheet:
9493
95−- To pass arguments from the command line to a program, you
96− replace the `*` in the first line of the boiler plate to
97− `{^ {{arg/TYPE ~} ~}}` where `TYPE` is replaced with the
98− type of argument you're expecting. Then `+euler1 a` from
99− the dojo sets `arg` to `a`.
100−- The empty list is `~`
101−- Lisp-style cons (construct a cell/prepend an element) is
102− `[new-element list]`
103−- For example, the first three positive integers are `[1 2 3
104− ~]`
105−- `(gte a b)` tests whether `a` is greater than or equal to `b`.
106−- `(mod a b)` runs the modulo operation on two atoms.
107−- See the basic math section in `/arvo/hoon.hoon` for more info.
94+- To pass arguments from the command line to a program, you replace
95+ the `*` in the first line of the boiler plate to
96+ `{^ {{arg/TYPE ~} ~}}` where `TYPE` is replaced with the type of
97+ argument you're expecting. Then `+euler1 a` from the dojo sets `arg`
98+ to `a`.
99+- The empty list is `~`
100+- Lisp-style cons (construct a cell/prepend an element) is
101+ `[new-element list]`
102+- For example, the first three positive integers are `[1 2 3 ~]`
103+- `(gte a b)` tests whether `a` is greater than or equal to `b`.
104+- `(mod a b)` runs the modulo operation on two atoms.
105+- See the basic math section in `/arvo/hoon.hoon` for more info.
106+
docs/arvo/subscriptions.md+234−245
@@ -5,275 +5,264 @@ sort: 5
55title: Subscriptions
66---
77
8−# Subscriptions
9−
10−We've dealt fairly extensively with "poke" messages to an app,
11−but these are somewhat limited. A poke is a one-way message, but
12−more often we want to subscribe to updates from another app. You
13−could build a subscription model out of one-way pokes, but it's
14−such a common pattern that it's built into arvo.
15−
16−Let's take a look at two apps, `:examples-source` and `:examples-sink`. First,
17−`:examples-source`:
18−
19−```
20−/? 314
21−!:
22−|%
23−++ move {bone $diff mark *}
24−--
25−|_ {hid/bowl state/$~}
26−++ poke-noun
27− |= arg/*
28− ^- {(list move) _+>.$}
29− :_ +>.$
30− %+ turn (prey /the-path hid)
31− |=({o/bone *} `move`[o %diff %noun arg])
32−++ peer
33− |= pax/path
34− ^- {(list move) _+>.$}
35− ~& [%subscribed-to pax=pax]
36− [~ +>.$]
37−--
38−```
8+# Subscriptions
9+
10+We've dealt fairly extensively with "poke" messages to an app, but these
11+are somewhat limited. A poke is a one-way message, but more often we
12+want to subscribe to updates from another app. You could build a
13+subscription model out of one-way pokes, but it's such a common pattern
14+that it's built into arvo.
15+
16+Let's take a look at two apps, `:examples-source` and `:examples-sink`.
17+First, `:examples-source`:
18+
19+ /? 314
20+ !:
21+ |%
22+ ++ move {bone $diff mark *}
23+ --
24+ |_ {hid/bowl state/$~}
25+ ++ poke-noun
26+ |= arg/*
27+ ^- {(list move) _+>.$}
28+ :_ +>.$
29+ %+ turn (prey /the-path hid)
30+ |=({o/bone *} `move`[o %diff %noun arg])
31+ ++ peer
32+ |= pax/path
33+ ^- {(list move) _+>.$}
34+ ~& [%subscribed-to pax=pax]
35+ [~ +>.$]
36+ --
3937
4038And secondly, `:examples-sink`:
4139
42−```
43−/? 314
44−|%
45−++ move {bone card}
46−++ card
47− $% {$peer wire {@p term} path}
48− {$pull wire {@p term} $~}
49− ==
50−--
51−!:
52−|_ {bowl available/?}
53−++ poke-noun
54− |= arg/*
55− ^- {(list move) _+>.$}
56− ?: &(=(%on arg) available)
57− [[[ost %peer /subscribe [our %source] /the-path] ~] +>.$(available |)]
58− ?: &(=(%off arg) !available)
59− [[[ost %pull /subscribe [our %source] ~] ~] +>.$(available &)]
60− ~& ?:(available %not-subscribed %subscribed)
61− [~ +>.$]
62−++ diff-noun
63− |= {wir/wire arg/*}
64− ^- {(list move) _+>.$}
65− ~& [%recieved-data arg]
66− [~ +>.$]
67−++ reap
68− |= {wir/wire error/(unit tang)}
69− ^- {(list move) _+>.$}
70− ?~ error
71− ~& %successfully-subscribed
72− [~ +>.$]
73− ~& [%subscription-failed error]
74− [~ +>.$]
75−--
76−```
40+ /? 314
41+ |%
42+ ++ move {bone card}
43+ ++ card
44+ $% {$peer wire {@p term} path}
45+ {$pull wire {@p term} $~}
46+ ==
47+ --
48+ !:
49+ |_ {bowl available/?}
50+ ++ poke-noun
51+ |= arg/*
52+ ^- {(list move) _+>.$}
53+ ?: &(=(%on arg) available)
54+ [[[ost %peer /subscribe [our %source] /the-path] ~] +>.$(available |)]
55+ ?: &(=(%off arg) !available)
56+ [[[ost %pull /subscribe [our %source] ~] ~] +>.$(available &)]
57+ ~& ?:(available %not-subscribed %subscribed)
58+ [~ +>.$]
59+ ++ diff-noun
60+ |= {wir/wire arg/*}
61+ ^- {(list move) _+>.$}
62+ ~& [%recieved-data arg]
63+ [~ +>.$]
64+ ++ reap
65+ |= {wir/wire error/(unit tang)}
66+ ^- {(list move) _+>.$}
67+ ?~ error
68+ ~& %successfully-subscribed
69+ [~ +>.$]
70+ ~& [%subscription-failed error]
71+ [~ +>.$]
72+ --
7773
7874Cheat sheet:
7975
80−- `&` (pam) can either be the boolean true (along with `%.y`, `0`), or
81− the irregular wide form of the `?&` ([wutpam](/hoon/twig/wut-test/pam-and)) rune, which computes the
82− logical `AND` operation on its two children.
83−
84−- Similar to `&`,`|` is either the boolean false (along with `%.n` and `1`), or
85− the irregular short for of `?|` ([wutbar](/hoon/twig/wut-test/bar-or)), which computes logical `OR` on
86− its two children.
87−
88−- `!` is the irregular wide form of `?!` ([wutzap](/hoon/twig/wut-test/zap-not/)), which computes
89− logical `NOT` on its child.
90−
91−- `?~` ([wutsig](/hoon/twig/wut-test/sig-ifno/)) is basically an if-then-else that checks whether condition `p`
92− is `~` (null). `?~` is slightly different from `?:(~ %tru %fal)` in that `?~`
93− reduces to `?:($=(%type value) %tru %false)`. `$=` ([buctis](/hoon/twig/buc-mold/tis-coat/)) tests whether
94− value `q` is of type `p`.
95− <!--One thing to watch out for in hoon: if you do `?~`, it
96− affects the type of the conditional value: XXexample-->
76+- `&` (pam) can either be the boolean true (as can `%.y`, `0`), or
77+ the irregular wide form of the `?&`
78+ ([wutpam](/hoon/twig/wut-test/pam-and)) rune, which computes
79+ logical `AND` on its two children.
80+
81+- Similar to `&`,`|` is either the boolean false (along with `%.n` and
82+ `1`), or the irregular short for of `?|`
83+ ([wutbar](/hoon/twig/wut-test/bar-or)), which computes logical `OR`
84+ on its two children.
85+
86+- `!` is the irregular wide form of `?!`
87+ ([wutzap](/hoon/twig/wut-test/zap-not/)), which computes logical
88+ `NOT` on its child.
89+
90+- `?~` ([wutsig](/hoon/twig/wut-test/sig-ifno/)) is basically an
91+ if-then-else that checks whether condition `p` is `~` (null). `?~`
92+ is slightly different from `?:(~ %tru %fal)` in that `?~` reduces to
93+ `?:($=(%type value) %tru %false)`. `$=`
94+ ([buctis](/hoon/twig/buc-mold/tis-coat/)) tests whether value `q` is
95+ of type `p`.
96+ <!--One thing to watch out for in hoon: if you do `?~`, it
97+ affects the type of the conditional value: XXexample-->
98+
99+- `:_` ([colcab](/hoon/twig/col-cell/cab-scon/)) is inverted `:-`: it
100+ accepts `p` and `q`, and produces `[q p]`.
101+
102+- `++bowl` is the type of the system state within our app. For
103+ example, it includes things like `our`, the name of the host urbit,
104+ and `now`, the current time.
105+
106+- `$%` ([buccen](/hoon/twig/buc-mold/cen-book/)) is a type
107+ constructor: it defines a new type, composed of `n` types that it is
108+ passed. For example `$% @ * ^ ==` is the type of either `@`,
109+ `*`, or a cell `^`. <!--XX this is a union, right?-->
110+
111+- You may have noticed the separate `|%`
112+ ([barcen](/hoon/twig/bar-core/cen-core/)) above the application core
113+ `|_` ([barcab](/hoon/twig/bar-core/cab-door/). We usually put our
114+ types in another core on top of the application core. We can access
115+ these type from our `|_` because in `hoon.hoon` files, all cores are
116+ called against each other. (The shorthand for 'called' is `=>`.)
117+ Thus, the `|%` with the types is in the context of the `|_`, as it
118+ lies above it: `hoon.hoon` `=> |% w types => |_`
97119
98−- `:_` ([colcab](/hoon/twig/col-cell/cab-scon/)) is inverted `:-`: it accepts `p` and `q`, and produces `[q p]`.
99−
100−- `++bowl` is the type of the system state within our app. For example, it
101− includes things like `our`, the name of the host urbit, and `now`, the
102− current time.
103−
104−- `$%` ([buccen](/hoon/twig/buc-mold/cen-book/)) is a type constructor: it defines a new type, composed of `n`
105− types that it is passed. For example `$% @ * ^ ==` is the
106− type of either `@`, `*`, or a cell `^`. <!--XX this is a union, right?-->
107−
108−- You may have noticed the separate `|%` ([barcen](/hoon/twig/bar-core/cen-core/)) above the application
109− core `|_` ([barcab](/hoon/twig/bar-core/cab-door/). We usually put our types in another core on top of the
110− application core. We can access these type from our `|_`
111− because in `hoon.hoon` files, all cores are called against
112− each other. (The shorthand for 'called' is `=>`.) Thus, the
113− `|%` with the types is in the context of the `|_`, as it lies
114− above it: `hoon.hoon` `=> |% w types =>
115− |_`
116−
117−
118120Here's some sample output of the two working together:
119121
120−```
121−
122−~fintud-macrep:dojo> |start %examples-source
123−>=
124−~fintud-macrep:dojo> |start %examples-sink
125−>=
126−~fintud-macrep:dojo> :examples-sink %on
127−[%subscribed-to pax=/the-path]
128−%successfully-subscribed]
129−>=
130−~fintud-macrep:dojo> :examples-source 5
131−[%received-data 5]
132−>=
133−~fintud-macrep:dojo> :examples-sink %off
134−>=
135−~fintud-macrep:dojo> :examples-source 6
136−>=
137−~fintud-macrep:dojo> :examples-sink %on
138−[%subscribed-to pax=/the-path]
139−%successfully-subscribed]
140−>=
141−~fintud-macrep:dojo> :examples-source 7
142−[%received-data 7]
143−>=
144−
145−```
146−
147−###:examples-source
148−
149−Hopefully you can get a sense for what's happening here. When we
150−poke `:examples-sink` with `%on`, `:examples-sink` subscribes to `:examples-source`, and so
151−whenever we poke `:examples-source`, `:examples-sink` gets the update and prints it
152−out. Then we unsubscribe by poking `:examples-sink` with `%off`, and
153−`:examples-sink` stops getting updates. We then resubscribe.
122+
123+ ~fintud-macrep:dojo> |start %examples-source
124+ >=
125+ ~fintud-macrep:dojo> |start %examples-sink
126+ >=
127+ ~fintud-macrep:dojo> :examples-sink %on
128+ [%subscribed-to pax=/the-path]
129+ %successfully-subscribed]
130+ >=
131+ ~fintud-macrep:dojo> :examples-source 5
132+ [%received-data 5]
133+ >=
134+ ~fintud-macrep:dojo> :examples-sink %off
135+ >=
136+ ~fintud-macrep:dojo> :examples-source 6
137+ >=
138+ ~fintud-macrep:dojo> :examples-sink %on
139+ [%subscribed-to pax=/the-path]
140+ %successfully-subscribed]
141+ >=
142+ ~fintud-macrep:dojo> :examples-source 7
143+ [%received-data 7]
144+ >=
145+
146+### :examples-source
147+
148+Hopefully you can get a sense for what's happening here. When we poke
149+`:examples-sink` with `%on`, `:examples-sink` subscribes to
150+`:examples-source`, and so whenever we poke `:examples-source`,
151+`:examples-sink` gets the update and prints it out. Then we unsubscribe
152+by poking `:examples-sink` with `%off`, and `:examples-sink` stops
153+getting updates. We then resubscribe.
154154
155155There's a fair bit going on in this code. Let's look at
156156`:examples-source` first.
157157
158−Our definition of `move` is fairly specific, since we're only
159−going to sending one kind of move. The `%diff` move is a
160−subscription update, and its content is marked data which gall
161−routes to our subscribers.
162−
163−This is a slightly different kind of move than [we've dealt with
164−so far](/arvo/network). It's producing a result rather than calling other code
165−(i.e. it's a return rather than a function call), so if you
166−recall the discussion of ducts, a layer gets popped off the duct
167−rather than added to it. This is why no wire is needed for the
168−move -- we won't receive anything in response to it.
169−
170−Anyways, there're two functions inside the `|_`. We already know
171−when `++poke-noun` is called. `++peer` is called when someone
172−tries to subscribe to our app. Of course, you don't just
173−subscribe to an app; you subscribe to a path on that app. This
174−path comes in as the argument to `++peer`.
175−
176−In our case, we don't care what path you subscribed on, and all
177−we do is print out that you subscribed. Arvo keeps track of your
178−subscriptions, so you don't have to. You can access your
179−subscribers by looking at `sup` in the bowl that's passed in.
180−`sup` is of type `(map bone {@p path})`, which associates bones
181−with the urbit who subscribed, and which path they subscribed on.
182−If you want to communicate with your subscribers, send them messages along
183−their bone.
158+Our definition of `move` is fairly specific, since we're only going to
159+sending one kind of move. The `%diff` move is a subscription update, and
160+its content is marked data which gall routes to our subscribers.
161+
162+This is a slightly different kind of move than [we've dealt with so
163+far](/arvo/network). It's producing a result rather than calling other
164+code (i.e. it's a return rather than a function call), so if you recall
165+the discussion of ducts, a layer gets popped off the duct rather than
166+added to it. This is why no wire is needed for the move -- we won't
167+receive anything in response to it.
168+
169+Anyways, there're two functions inside the `|_`. We already know when
170+`++poke-noun` is called. `++peer` is called when someone tries to
171+subscribe to our app. Of course, you don't just subscribe to an app; you
172+subscribe to a path on that app. This path comes in as the argument to
173+`++peer`.
174+
175+In our case, we don't care what path you subscribed on, and all we do is
176+print out that you subscribed. Arvo keeps track of your subscriptions,
177+so you don't have to. You can access your subscribers by looking at
178+`sup` in the bowl that's passed in. `sup` is of type
179+`(map bone {@p path})`, which associates bones with the urbit who
180+subscribed, and which path they subscribed on. If you want to
181+communicate with your subscribers, send them messages along their bone.
184182
185183`++poke-noun` "spams" the given arguement to all our subscribers.
186−There's a few things we haven't seen before. Firstly, `:_(a b)`
187−is the same as `[b a]`. It's just a convenient way of formatting
188−things when the first thing in a cell is much more complicated
189−than the second. Thus, we're producing our state unchanged.
190−
191−Our list of moves is the result of a call to `++turn`. `++turn`
192−is what many languages call "map" -- it runs a function on every
193−item in a list and collects the results in a list. The list is
194−`(prey /the-path hid)` and the function is the `|=` line right
195−after it.
196−
197−`++prey` is a standard library function defined in `zuse`. It
198−takes a path and a bowl and gives you a list of the subscribers
199−who are subscribed on a path that begins with the given path.
200−"Prey" is short for "prefix".
201−
202−Now we have the list of relevant subscribers. This a list of
203−triples, `{bone @p path}`, where the only thing we really need is
204−the bone, because we don't need to know their urbit or what exact
205−path they subscribed on. Thus, our transformer function takes
206−`{o/bone *}` and produces `[o %diff %noun arg]`, which is a move
207−that provides bone `o` with this subscription update: `[%noun
208−arg]`". This is fairly dense code, but what it's doing is
209−straightforward.
210−
211−###:examples-sink
212−
213−`:examples-source` should now make sense. `:examples-sink` is a little longer,
214−but not much more complicated.
215−
216−In `:examples-sink`, our definition of of `++move` is different. All
217−moves start with a `bone`, and we conventionally refer to the
218−second half as the "card", so that we can say a move is an action
219−that sends a card along a bone.
220−
221−We have two kinds of cards here: we `%peer` to start a
222−subscription, and we `%pull` to stop it. Both of these are
223−"forward" moves that may receive a response, so they need a wire
224−to tack onto the duct before they pass it on. They also need a
225−target, which is a pair of an urbit and an app name. Additionally, `%peer`
226−needs a path on that app to subscribe too. `%pull` doesn't need
227−this, because its semantics are to cancel any subscriptions
228−coming over this duct. If your bone and wire are the same as
229−when you subscribed, then the cancellation will happen correctly.
230−
231−The only state we need for `:examples-sink` is a boolean to indicate whether
232−we're already subscribed to `:examples-source`. We use `available/?`,
233−where `?` is the sign of type boolean (similar to `*`, `@`), which defaults to true (that is, `0`).
234−
235−In `++poke-noun` we check our input to see both if it's `%on` and
236−we're available. If so, we produce the move to subscribe to
184+There's a few things we haven't seen before. Firstly, `:_(a b)` is the
185+same as `[b a]`. It's just a convenient way of formatting things when
186+the first thing in a cell is much more complicated than the second.
187+Thus, we're producing our state unchanged.
188+
189+Our list of moves is the result of a call to `++turn`. `++turn` is what
190+many languages call "map" -- it runs a function on every item in a list
191+and collects the results in a list. The list is `(prey /the-path hid)`
192+and the function is the `|=` line right after it.
193+
194+`++prey` is a standard library function defined in `zuse`. It takes a
195+path and a bowl and gives you a list of the subscribers who are
196+subscribed on a path that begins with the given path. "Prey" is short
197+for "prefix".
198+
199+Now we have the list of relevant subscribers. This a list of triples,
200+`{bone @p path}`, where the only thing we really need is the bone,
201+because we don't need to know their urbit or what exact path they
202+subscribed on. Thus, our transformer function takes `{o/bone *}` and
203+produces `[o %diff %noun arg]`, which is a move that provides bone `o`
204+with this subscription update: `[%noun arg]`". This is fairly dense
205+code, but what it's doing is straightforward.
206+
207+### :examples-sink
208+
209+`:examples-source` should now make sense. `:examples-sink` is a little
210+longer, but not much more complicated.
211+
212+In `:examples-sink`, our definition of of `++move` is different. All
213+moves start with a `bone`, and we conventionally refer to the second
214+half as the "card", so that we can say a move is an action that sends a
215+card along a bone.
216+
217+We have two kinds of cards here: we `%peer` to start a subscription, and
218+we `%pull` to stop it. Both of these are "forward" moves that may
219+receive a response, so they need a wire to tack onto the duct before
220+they pass it on. They also need a target, which is a pair of an urbit
221+and an app name. Additionally, `%peer` needs a path on that app to
222+subscribe too. `%pull` doesn't need this, because its semantics are to
223+cancel any subscriptions coming over this duct. If your bone and wire
224+are the same as when you subscribed, then the cancellation will happen
225+correctly.
226+
227+The only state we need for `:examples-sink` is a boolean to indicate
228+whether we're already subscribed to `:examples-source`. We use
229+`available/?`, where `?` is the sign of type boolean (similar to `*`,
230+`@`), which defaults to true (that is, `0`).
231+
232+In `++poke-noun` we check our input to see both if it's `%on` and we're
233+available. If so, we produce the move to subscribe to
237234`:examples-source`:
238235
239−```
240−[ost %peer /subscribe [our %source] /the-path]
241−```
236+ [ost %peer /subscribe [our %source] /the-path]
242237
243238Also, we set available to false (`|`) with `+>.$(available |)`.
244239
245−Otherwise, if our input is `%off` and we're already subscribed
246−(i.e. `available` is false), then we unsubscribe from
247−`:examples-source`:
240+Otherwise, if our input is `%off` and we're already subscribed (i.e.
241+`available` is false), then we unsubscribe from `:examples-source`:
248242
249−```
250−[ost %pull /subscribe [our %source] ~]
251−```
243+ [ost %pull /subscribe [our %source] ~]
252244
253−It's important to send over the same bone and wire (`/subscribe`)
254−as the one we originally subscribed on.
245+It's important to send over the same bone and wire (`/subscribe`) as the
246+one we originally subscribed on.
255247
256248We also set `available` to true (`&`).
257249
258−If neither of these cases are true, then we print our
259−current subscription state.
250+If neither of these cases are true, then we print our current
251+subscription state.
260252
261253`++diff-noun` is called when we get a `%diff` update along a
262−subscription with a mark of `noun`. `++diff-noun` is given the
263−wire that we originally passed with the `%peer` subscription
264−request along and the data we got back. In our case we just
265−print out the data.
266−
267−`++reap` is called when we receive an acknowledgment as to
268−whether the subscription was handled successfully. You can
269−remember that `++reap` is the counterpart to `++peer` as it's
270−pronounced like 'peer' backwards. Similarly, `coup` is
271−similar to 'poke' backwards.
272−
273−Moving forward, `++reap` is given the wire we attempted to
274−subscribe over, possibly along with an error message in cases of
275−failure. `(unit type)` means "either `~` or `[~ type]`, which
276−means it's used like Haskell's "maybe" or C's nullability. If
277−`error` is `~`, then the subscription was successful and we tell
278−that to the user. Otherwise, we print out the error message.
279−
254+subscription with a mark of `noun`. `++diff-noun` is given the wire that
255+we originally passed with the `%peer` subscription request along and the
256+data we got back. In our case we just print out the data.
257+
258+`++reap` is called when we receive an acknowledgment as to whether the
259+subscription was handled successfully. You can remember that `++reap` is
260+the counterpart to `++peer` as it's pronounced like 'peer' backwards.
261+Similarly, `coup` is similar to 'poke' backwards.
262+
263+Moving forward, `++reap` is given the wire we attempted to subscribe
264+over, possibly along with an error message in cases of failure.
265+`(unit type)` means "either `~` or `[~ type]`, which means it's used
266+like Haskell's "maybe" or C's nullability. If `error` is `~`, then the
267+subscription was successful and we tell that to the user. Otherwise, we
268+print out the error message.