on master help sign in
spacing issues
commit752a7ac52c886e5817bee9f9178f033df44408fd authorjoshuareagan <joshuareagan@gmail.com> dateMon 24 Sep 2018, 18:32 (8 years ago) parentad975b2
4 files changed+313−312
docs/tutorials/gall/network.umd+98−98 docs/tutorials/gall/state.umd+51−57 docs/tutorials/gall/subscriptions.umd+155−148 docs/tutorials/sail.umd+9−9
docs/tutorials/gall/network.umd+98−98
@@ -13,24 +13,24 @@ In the following we assume that you have some knowledge of Hoon. If you don't,
1313Let's get our planets to talk to each other. To listen for and receive messages from other planets, we'll need an app. Let's look at a very simple one, `echo.hoon`:
1414
1515```
16− :: Accepts any noun from dojo and prints it out
17− ::
18− :::: /===/app/echo/hoon
19− ::
20− !: :: enables debug printfs
21− |% :: forms a core with subject as payload
22− +$ move [bone card] :: defines echo app's arvo move mold
23− +$ card $% $~ :: defines card (data) mold as null tagged union
24− == :: end of mold definition; see $%
25− -- :: end of card arm definition
26− :: ::
27− |_ [bow=bowl:gall $~] :: forms a core with bowl (app state) as sample
28− ++ poke-noun :: begin definition of poke-noun arm
29− |= non=* :: forms a gate which accepts any noun
30− ^- [(list move) _+>.$] :: casts product to mold of moves and context
31− ~& echo+noun+non :: debug printf, i.e. '[%echo %noun *]'
32− [~ +>.$] :: produce a cell of empty list and our state
33− -- :: end of poke-noun arm definition
16+:: Accepts any noun from dojo and prints it out
17+::
18+:::: /===/app/echo/hoon
19+ ::
20+!: :: enables debug printfs
21+|% :: forms a core with subject as payload
22++$ move [bone card] :: defines echo app's arvo move mold
23++$ card $% $~ :: defines card (data) mold as null tagged union
24+ == :: end of mold definition; see $%
25+-- :: end of card arm definition
26+:: ::
27+|_ [bow=bowl:gall $~] :: forms a core with bowl (app state) as sample
28+++ poke-noun :: begin definition of poke-noun arm
29+ |= non=* :: forms a gate which accepts any noun
30+ ^- [(list move) _+>.$] :: casts product to mold of moves and context
31+ ~& echo+noun+non :: debug printf, i.e. '[%echo %noun *]'
32+ [~ +>.$] :: produce a cell of empty list and our state
33+-- :: end of poke-noun arm definition
3434```
3535
3636This is a very simple app that does only one thing. If you poke it with
@@ -39,19 +39,19 @@ the app, then you can poke it from the command line with the following
3939commands:
4040
4141```
42− ~fintud-macrep:dojo> |start %echo
43− >=
44− ~fintud-macrep:dojo> :echo 5
45− [%echo %noun 5]
46− >=
47− ~fintud-macrep:dojo> :echo [1 2]
48− [%echo %noun [1 2]]
49− >=
42+~fintud-macrep:dojo> |start %echo
43+>=
44+
45+~fintud-macrep:dojo> :echo 5
46+[%echo %noun 5]
47+>=
48+
49+~fintud-macrep:dojo> :echo [1 2]
50+[%echo %noun [1 2]]
51+>=
5052```
5153
52−> There is currently a bug where the `[%echo %noun *]` lines are printed *above*
53−> the line you entered, so your output may not look exactly like this. `>=`
54−> means that a command was successfully received and executed.
54+> There is currently a bug where the `[%echo %noun *]` lines are printed *above* the line you entered, so your output may not look exactly like this. `>=` means that a command was successfully received and executed.
5555
5656Most of the app code should be simple enough to guess its function. The
5757important part of this code is the definition of `++poke-noun`.
@@ -90,29 +90,29 @@ Let's look at another example (edit your code in
9090only accept a number, and then print out the square of that number.
9191
9292```
93− :: Accepts an atom from the dojo and squares it.
94− ::
95− :::: /===/app/square/hoon
96− ::
97− !:
98− |% :: no moves in :square
99− +$ move [bone card] :: no cards in :square
100− +$ card $% $~
101− ==
102− --
103− :: :: stateless
104− |_ [bow=bowl:gall $~]
105− ++ poke-atom
106− |= tom=@
107− ^- [(list move) _+>.$]
108− ~& square+(mul tom tom)
109− [~ +>.$]
110− --
93+:: Accepts an atom from the dojo and squares it.
94+::
95+:::: /===/app/square/hoon
96+ ::
97+!:
98+|% :: no moves in :square
99++$ move [bone card] :: no cards in :square
100++$ card $% $~
101+ ==
102+--
103+:: :: stateless
104+|_ [bow=bowl:gall $~]
105+++ poke-atom
106+ |= tom=@
107+ ^- [(list move) _+>.$]
108+ ~& square+(mul tom tom)
109+ [~ +>.$]
110+--
111111```
112112
113113A few things have changed. Firstly, we no longer accept arbitrary nouns because
114114we can only square atoms (integers, in this case an unsigned one). Thus, our
115−argument is now `tom/@`. Secondly, it's `++poke-atom` rather than `++poke-noun`.
115+argument is now `tom=@`. Secondly, it's `++poke-atom` rather than `++poke-noun`.
116116
117117## Intro to marks
118118
@@ -135,13 +135,15 @@ expecting an atom, so we have to explicitly mark the data with `atom`
135135using `&[mark]`. Try the following commands:
136136
137137```
138− ~fintud-macrep:dojo> |start %square
139− >=
140− ~fintud-macrep:dojo> :square 6
141− gall: %square: no poke arm for noun
142− ~fintud-macrep:dojo> :square &atom 6
143− [%square 36]
144− >=
138+~fintud-macrep:dojo> |start %square
139+>=
140+
141+~fintud-macrep:dojo> :square 6
142+gall: %square: no poke arm for noun
143+
144+~fintud-macrep:dojo> :square &atom 6
145+[%square 36]
146+>=
145147```
146148
147149> Recall the bug where `%square` may get printed above the input line.
@@ -158,48 +160,49 @@ so we'll be getting quite used to them.
158160Let's write our first network message! Here's `examples/app/pong.hoon`:
159161
160162```
161− :: Allows one urbit to send the string 'Pong' to
162− :: another urbit.
163− ::
164− :::: /===/app/pong/hoon
165− ::
166− !:
167− |%
168− +$ move [bone card]
169− +$ card $% [$poke wire dock poke-contents]
170− ==
171− +$ poke-contents $% [$atom @]
172− ==
173− --
174− |_ [bow=bowl:gall $~] :: stateless
175− ::
176− ++ poke-urbit
177− |= to=ship
178− ^- [(list move) _+>.$]
179− ~& pong+'Outgoing pong!'
180− :_ +>.$
181− ~[[ost.bow %poke /sending [to dap.bow] %atom 'Pong']]
182− ::
183− ++ poke-atom
184− |= tom=@
185− ^- [(list move) _+>.$]
186− ~& pong+'Incoming pong!'
187− ~& pong+received+`@t`tom
188− [~ +>.$]
189− ::
190− ++ coup |=(* [~ +>.$])
191− ::
192− --
163+:: Allows one urbit to send the string 'Pong' to
164+:: another urbit.
165+::
166+:::: /===/app/pong/hoon
167+ ::
168+!:
169+|%
170++$ move [bone card]
171++$ card $% [$poke wire dock poke-contents]
172+ ==
173++$ poke-contents $% [$atom @]
174+ ==
175+--
176+|_ [bow=bowl:gall $~] :: stateless
177+::
178+++ poke-urbit
179+ |= to=ship
180+ ^- [(list move) _+>.$]
181+ ~& pong+'Outgoing pong!'
182+ :_ +>.$
183+ ~[[ost.bow %poke /sending [to dap.bow] %atom 'Pong']]
184+::
185+++ poke-atom
186+ |= tom=@
187+ ^- [(list move) _+>.$]
188+ ~& pong+'Incoming pong!'
189+ ~& pong+received+`@t`tom
190+ [~ +>.$]
191+::
192+++ coup |=(* [~ +>.$])
193+::
194+--
193195```
194196
195197
196198Run it with these commands:
197199
198200```
199− ~fintud-macrep:dojo> |start %pong
200− >=
201− ~fintud-macrep:dojo> :pong &urbit ~sampel-sipnym
202− >=
201+~fintud-macrep:dojo> |start %pong
202+>=
203+
204+~fintud-macrep:dojo> :pong &urbit ~sampel-sipnym
205+>=
203206```
204207
205208Replace `~sampel-sipnym` with another urbit. The easiest thing to do is to start
@@ -209,8 +212,8 @@ the `%pong` app on that urbit, too. You should see, on the foreign
209212urbit, this output:
210213
211214```
212− [%pong 'Incoming pong!']
213− [%pong %received 'Pong']
215+[%pong 'Incoming pong!']
216+[%pong %received 'Pong']
214217```
215218
216219Most of the code should be straightforward. In `++poke-atom`, the only new thing
@@ -227,7 +230,7 @@ do anything in particular. Now we want to send a message to another urbit. Thus,
227230we produce a list with one element:
228231
229232```
230− ~[[ost.bow %poke /sending [to dap.bow] %atom 'Pong]]
233+~[[ost.bow %poke /sending [to dap.bow] %atom 'Pong]]
231234```
232235
233236### Moves
@@ -309,10 +312,7 @@ When Arvo receives a `%poke` move, it calls the appropriate `++poke`.
309312The same mechanism is used for sending messages between apps on the same
310313urbit as for sending messages between apps on different urbits.
311314
312−> We said earlier that we're not expecting a response. This is not
313−> entirely true: the `++coup` is called when we receive acknowledgment
314−> that the `++poke` was called. We don't do anything with this
315−> information right now, but we could.
315+> We said earlier that we're not expecting a response. This is not entirely true: the `++coup` is called when we receive acknowledgment that the `++poke` was called. We don't do anything with this information right now, but we could.
316316
317317*Exercises*:
318318
docs/tutorials/gall/state.umd+51−57
@@ -14,50 +14,52 @@ Let's build a trivial stateful app. It'll keep a running the sum of all the
1414atoms we poke it with. Here's `examples/app/sum.hoon`:
1515
1616```
17− :: Keeps track of the sum of all the atoms it has been
18− :: poked with and prints the sum out
19− ::
20− :::: /===/app/sum/hoon
21− ::
22− !:
23− |%
24− +$ move [bone card]
25− +$ card $% $~
26− ==
27− --
28− |_ [bow=bowl:gall sum=@]
29− ::
30− ++ poke-atom
31− |= tom=@
32− ^- [(list move) _+>.$]
33− ~& sum+(add sum tom)
34− [~ +>.$(sum (add sum tom))]
35− ::
36− ++ coup
37− |= [wir=wire err=(unit tang)]
38− ^- [(list move) _+>.$]
39− ?~ err
40− ~& sum+success+'Poke succeeded!'
17+:: Keeps track of the sum of all the atoms it has been
18+:: poked with and prints the sum out
19+::
20+:::: /===/app/sum/hoon
21+ ::
22+!:
23+|%
24++$ move [bone card]
25++$ card $% $~
26+ ==
27+--
28+|_ [bow=bowl:gall sum=@]
29+::
30+++ poke-atom
31+ |= tom=@
32+ ^- [(list move) _+>.$]
33+ ~& sum+(add sum tom)
34+ [~ +>.$(sum (add sum tom))]
35+::
36+++ coup
37+ |= [wir=wire err=(unit tang)]
38+ ^- [(list move) _+>.$]
39+ ?~ err
40+ ~& sum+success+'Poke succeeded!'
41+ [~ +>.$]
42+ ~& sum+error+'Poke failed. Error:'
43+ ~& sum+error+err
4144 [~ +>.$]
42− ~& sum+error+'Poke failed. Error:'
43− ~& sum+error+err
44− [~ +>.$]
45− ::
46− --
45+::
46+--
4747```
4848
4949We can start it with `|start %sum`, and then run it:
5050
5151```
52− ~fintud-macrep:dojo> :sum &atom 5
53− [%sum 5]
54− >=
55− ~fintud-macrep:dojo> :sum &atom 2
56− [%sum 7]
57− >=
58− ~fintud-macrep:dojo> :sum &atom 15
59− [%sum 22]
60− >=
52+~fintud-macrep:dojo> :sum &atom 5
53+[%sum 5]
54+>=
55+
56+~fintud-macrep:dojo> :sum &atom 2
57+[%sum 7]
58+>=
59+
60+~fintud-macrep:dojo> :sum &atom 15
61+[%sum 22]
62+>=
6163```
6264
6365We can see that app state is being saved, but when, where, and how?
@@ -88,17 +90,7 @@ identity), and `eny` (256 bits of guaranteed-fresh entropy). For the full list
8890of things in `++bowl`, search for `++ bowl` (note: two spaces) in
8991`/arvo/zuse.hoon`.
9092
91−> This is, perhaps, the most common way to learn Hoon. The easiest way to learn
92−> about an identifier you see in code is to search in `/arvo/zuse.hoon` and
93−> `/arvo/hoon.hoon` for it.\\ Urbit's codebase is less than 30000 lines of code
94−> combined,
95−> including the hoon parser, the compiler, and the `/arvo` microkernel, so you
96−> can
97−> usually use the code and its comments as a reference doc.
98−> You can also read
99−> [zuse.hoon](https://github.com/urbit/arvo/blob/master/arvo/zuse.hoon) and
100−> [hoon.hoon](https://github.com/urbit/arvo/blob/master/arvo/hoon.hoon) in your
101−> browser.
93+> This is, perhaps, the most common way to learn Hoon. The easiest way to learn about an identifier you see in code is to search in `/arvo/zuse.hoon` and `/arvo/hoon.hoon` for it.\\ Urbit's codebase is less than 30000 lines of code combined, including the hoon parser, the compiler, and the `/arvo` microkernel, so you can usually use the code and its comments as a reference doc. 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.
10294
10395The second thing we should clear up is this: Urbit needs no "serialize to disk"
10496step. Everything you produce in the app state is persistent across calls to the
@@ -118,12 +110,14 @@ to set up and write to a database.
118110Sample output:
119111
120112```
121− ~fintud-macrep:dojo> :last 7
122− [%last 0]
123− >=
124− ~fintud-macrep:dojo> :last [1 2 3]
125− [%last 7]
126− >=
127− ~fintud-macrep:dojo> :last 'howdy'
128− [%last [1 2 3]]
113+~fintud-macrep:dojo> :last 7
114+[%last 0]
115+>=
116+
117+~fintud-macrep:dojo> :last [1 2 3]
118+[%last 7]
119+>=
120+
121+~fintud-macrep:dojo> :last 'howdy'
122+[%last [1 2 3]]
129123```
docs/tutorials/gall/subscriptions.umd+155−148
@@ -18,124 +18,124 @@ Let's take a look at two apps, `:source` and `:sink`. First,
1818`:source`:
1919
2020```
21− :: Sends subscription updates to sink.hoon
22− ::
23− :::: /===/app/source/hoon
24− ::
25− !:
26− ::
27− |%
28− +$ move [bone card]
29− +$ card $% [%diff diff-contents]
30− ==
31− +$ diff-contents $% [%noun *]
32− ==
33− --
34− ::
35− |_ [bow=bowl:gall $~]
36− ::
37− ++ poke-noun
38− |= non=*
39− ^- [(list move) _+>.$]
40− :_ +>.$
41− %+ turn (prey /example-path bow)
42− |=({o=bone *} [o %diff %noun non])
43− ::
44− ++ peer-example-path
45− |= pax/path
46− ^- [(list move) _+>.$]
47− ~& source+peer-notify+'Someone subscribed to you!'
48− ~& source+[ship+src.bow path+pax]
49− [~ +>.$]
50− ::
51− ++ coup
52− |= {wir=wire err=(unit tang)}
53− ^- [(list move) _+>.$]
54− ?~ err
55− ~& source+success+'Poke succeeded!'
21+:: Sends subscription updates to sink.hoon
22+::
23+:::: /===/app/source/hoon
24+ ::
25+!:
26+::
27+|%
28+ +$ move [bone card]
29+ +$ card $% [%diff diff-contents]
30+ ==
31++$ diff-contents $% [%noun *]
32+ ==
33+--
34+::
35+|_ [bow=bowl:gall $~]
36+::
37+++ poke-noun
38+ |= non=*
39+ ^- [(list move) _+>.$]
40+ :_ +>.$
41+ %+ turn (prey /example-path bow)
42+ |=({o=bone *} [o %diff %noun non])
43+::
44+++ peer-example-path
45+ |= pax/path
46+ ^- [(list move) _+>.$]
47+ ~& source+peer-notify+'Someone subscribed to you!'
48+ ~& source+[ship+src.bow path+pax]
5649 [~ +>.$]
57− ~& source+error+'Poke failed. Error:'
58− ~& source+error+err
59− [~ +>.$]
60− ::
61− ++ reap
62− |= [wir=wire err=(unit tang)]
63− ^- [(list move) _+>.$]
64− ?~ err
65− ~& source+success+'Peer succeeded!'
50+::
51+++ coup
52+ |= {wir=wire err=(unit tang)}
53+ ^- [(list move) _+>.$]
54+ ?~ err
55+ ~& source+success+'Poke succeeded!'
56+ [~ +>.$]
57+ ~& source+error+'Poke failed. Error:'
58+ ~& source+error+err
59+ [~ +>.$]
60+::
61+++ reap
62+ |= [wir=wire err=(unit tang)]
63+ ^- [(list move) _+>.$]
64+ ?~ err
65+ ~& source+success+'Peer succeeded!'
66+ [~ +>.$]
67+ ~& source+error+'Peer failed. Error:'
68+ ~& source+error+err
6669 [~ +>.$]
67− ~& source+error+'Peer failed. Error:'
68− ~& source+error+err
69− [~ +>.$]
70− ::
71− --
70+::
71+--
7272```
7373
7474And secondly, `:sink`:
7575
7676```
77− :: Sets up a simple subscription to source.hoon
78− ::
79− :::: /===/app/sink/hoon
80− ::
81− !:
82− |%
83− +$ move [bone card]
84− +$ card $% [%peer wire dock path]
85− [%pull wire dock $~]
86− ==
87− --
88− ::
89− |_ [bow=bowl:gall val=?]
90− ::
91− ++ poke-noun
92− |= non=*
93− ^- [(list move) _+>.$]
94− ?: &(=(%on non) val)
95− :_ +>.$(val |)
96− :~ :* ost.bow
77+:: Sets up a simple subscription to source.hoon
78+::
79+:::: /===/app/sink/hoon
80+ ::
81+!:
82+|%
83++$ move [bone card]
84++$ card $% [%peer wire dock path]
85+ [%pull wire dock $~]
86+ ==
87+--
88+::
89+|_ [bow=bowl:gall val=?]
90+::
91+++ poke-noun
92+ |= non=*
93+ ^- [(list move) _+>.$]
94+ ?: &(=(%on non) val)
95+ :_ +>.$(val |)
96+ :~ :* ost.bow
9797 %peer
9898 /subscribe
9999 [our.bow %source]
100100 /example-path
101101 ==
102− ==
103− ?: &(=(%off non) !val)
104− :_ +>.$(val &)
105− ~[[ost.bow %pull /subscribe [our.bow %source] ~]]
106− ~& ?: val
107− sink+unsubscribed+'You are now unsubscribed!'
108− sink+subscribed+'You are now subscribed!'
109− [~ +>.$]
110− ::
111− ++ diff-noun
112− |= [wir=wire non=*]
113− ^- [(list move) _+>.$]
114− ~& sink+received-data+'You got something!'
115− ~& sink+data+non
116− [~ +>.$]
117− ::
118− ++ coup
119− |= [wir=wire err=(unit tang)]
120− ^- [(list move) _+>.$]
121− ?~ err
122− ~& sink+success+'Poke succeeded!'
102+ ==
103+ ?: &(=(%off non) !val)
104+ :_ +>.$(val &)
105+ ~[[ost.bow %pull /subscribe [our.bow %source] ~]]
106+ ~& ?: val
107+ sink+unsubscribed+'You are now unsubscribed!'
108+ sink+subscribed+'You are now subscribed!'
123109 [~ +>.$]
124− ~& sink+error+'Poke failed. Error:'
125− ~& sink+error+err
126− [~ +>.$]
127− ::
128− ++ reap
129− |= [wir=wire err=(unit tang)]
130− ^- [(list move) _+>.$]
131− ?~ err
132− ~& sink+success+'Peer succeeded!'
110+::
111+++ diff-noun
112+ |= [wir=wire non=*]
113+ ^- [(list move) _+>.$]
114+ ~& sink+received-data+'You got something!'
115+ ~& sink+data+non
133116 [~ +>.$]
134− ~& sink+error+'Peer failed. Error:'
135− ~& sink+error+err
136− [~ +>.$]
137− ::
138− --
117+::
118+++ coup
119+ |= [wir=wire err=(unit tang)]
120+ ^- [(list move) _+>.$]
121+ ?~ err
122+ ~& sink+success+'Poke succeeded!'
123+ [~ +>.$]
124+ ~& sink+error+'Poke failed. Error:'
125+ ~& sink+error+err
126+ [~ +>.$]
127+::
128+++ reap
129+ |= [wir=wire err=(unit tang)]
130+ ^- [(list move) _+>.$]
131+ ?~ err
132+ ~& sink+success+'Peer succeeded!'
133+ [~ +>.$]
134+ ~& sink+error+'Peer failed. Error:'
135+ ~& sink+error+err
136+ [~ +>.$]
137+::
138+--
139139```
140140
141141Two notes:
@@ -147,32 +147,39 @@ Two notes:
147147Here's some sample output of the two working together:
148148
149149```
150− ~fintud-macrep:dojo> |start %source
151− >=
152− ~fintud-macrep:dojo> |start %sink
153− >=
154− ~fintud-macrep:dojo> :sink %on
155− [%source %peer-notify 'Someone subscribed to you!']
156− [%source [%ship ~fintud-macrep] %path /]
157− [%sink %success 'Peer succeeded!']
158− >=
159− ~fintud-macrep:dojo> :source 5
160− [%sink %received-data 'You got something!']
161− [%sink %data 5]
162− >=
163− ~fintud-macrep:dojo> :sink %off
164− >=
165− ~fintud-macrep:dojo> :source 6
166− >=
167− ~fintud-macrep:dojo> :sink %on
168− [%source %peer-notify 'Someone subscribed to you!']
169− [%source [%ship ~fintud-macrep] %path /]
170− [%sink %success 'Peer succeeded!']
171− >=
172− ~fintud-macrep:dojo> :source 7
173− [%sink %received-data 'You got something!']
174− [%sink %data 7]
175− >=
150+~fintud-macrep:dojo> |start %source
151+>=
152+
153+~fintud-macrep:dojo> |start %sink
154+>=
155+
156+~fintud-macrep:dojo> :sink %on
157+[%source %peer-notify 'Someone subscribed to you!']
158+[%source [%ship ~fintud-macrep] %path /]
159+[%sink %success 'Peer succeeded!']
160+>=
161+
162+~fintud-macrep:dojo> :source 5
163+[%sink %received-data 'You got something!']
164+[%sink %data 5]
165+>=
166+
167+~fintud-macrep:dojo> :sink %off
168+>=
169+
170+~fintud-macrep:dojo> :source 6
171+>=
172+
173+~fintud-macrep:dojo> :sink %on
174+[%source %peer-notify 'Someone subscribed to you!']
175+[%source [%ship ~fintud-macrep] %path /]
176+[%sink %success 'Peer succeeded!']
177+>=
178+
179+~fintud-macrep:dojo> :source 7
180+[%sink %received-data 'You got something!']
181+[%sink %data 7]
182+>=
176183```
177184
178185### :source
@@ -190,8 +197,8 @@ Our definition of `move` is fairly specific, since we're only going to
190197sending one kind of move. The `%diff` move is a subscription update, and
191198its content is marked data which gall routes to our subscribers.
192199
193−This is a slightly different kind of move than [we've dealt with so
194−far](/arvo/network). It's producing a result rather than calling other
200+This is a slightly different kind of move than we've dealt with so
201+far. It's producing a result rather than calling other
195202code (i.e. it's a return rather than a function call), so if you recall
196203the discussion of ducts, a layer gets popped off the duct rather than
197204added to it. This is why no wire is needed for the move -- we won't
@@ -227,7 +234,7 @@ that begins with the given path. "Prey" is short for "prefix".
227234Now we have the list of relevant subscribers. This a list of triples,
228235`{bone @p path}`, where the only thing we really need is the bone, because we
229236don't need to know their urbit or what exact path they subscribed on. Thus, our
230−transformer function takes `{o/bone *}` and produces `[o %diff %noun non]`,
237+transformer function takes `[o=bone *]` and produces `[o %diff %noun non]`,
231238which is a move that provides bone `o` with this subscription update:
232239`[%noun non]`". This is fairly dense code, but what it's doing is
233240straightforward!
@@ -251,7 +258,7 @@ your bone and wire are the same as when you subscribed, then the cancellation
251258will happen correctly.
252259
253260The only state we need for `:sink` is a boolean to indicate whether
254−we're already subscribed to `:source`. We use `val/?`, where `?`
261+we're already subscribed to `:source`. We use `val=?`, where `?`
255262is the sign of type boolean (similar to `*`, `@`), which defaults to true (that
256263is, `0`).
257264
@@ -260,13 +267,13 @@ available (`val` is true). If so, we produce the move to subscribe to
260267`:source`:
261268
262269```
263− :~ :* ost.bow
264− %peer
265− /subscribe
266− [our.bow %source]
267− /example-path
268− ==
270+:~ :* ost.bow
271+ %peer
272+ /subscribe
273+ [our.bow %source]
274+ /example-path
269275 ==
276+==
270277```
271278
272279Also, in the preceding lines, we set `val` to false (`|`) with `+>.$(val |)`.
@@ -281,8 +288,8 @@ is false), then we unsubscribe from `:source` and set `val` back to true (`&`),
281288again using our handy inverted cell constructor mold `:_`:
282289
283290```
284− :_ +>.$(val &)
285− ~[[ost.bow %pull /subscribe [our.bow %source] ~]]
291+:_ +>.$(val &)
292+~[[ost.bow %pull /subscribe [our.bow %source] ~]]
286293```
287294
288295It's important to send over the same bone and wire (`/subscribe`) as the
@@ -293,10 +300,10 @@ state, based on whether `val` is true or false, and return a cell containing
293300a null list of moves and our unchanged app state:
294301
295302```
296− ~& ?: val
297− sink+unsubscribed+'You are now unsubscribed!'
298− sink+subscribed+'You are now subscribed!'
299− [~ +>.$]
303+~& ?: val
304+ sink+unsubscribed+'You are now unsubscribed!'
305+ sink+subscribed+'You are now subscribed!'
306+[~ +>.$]
300307```
301308
302309`++diff-noun` is called when we get a `%diff` update along a subscription with a
@@ -305,8 +312,8 @@ the `%peer` subscription request along and the data we got back. In our case we
305312just print out the data:
306313
307314```
308− ~& sink+received-data+'You got something!'
309− ~& sink+data+non
315+~& sink+received-data+'You got something!'
316+~& sink+data+non
310317```
311318
312319`++reap` is called when we receive an acknowledgment as to whether the
docs/tutorials/sail.umd+9−9
@@ -312,8 +312,8 @@ is done by wrapping the code to be inserted in `{}`. In your Dojo prompt, try
312312the command below (without the `>`):
313313
314314```
315− > "I am a l{(mul 3 11)}t Urbit user."
316− ! exit
315+> "I am a l{(mul 3 11)}t Urbit user."
316+! exit
317317```
318318
319319Oh no! That command produced a nest-fail error, which indicates that there was
@@ -325,8 +325,8 @@ Trying the `mul` function on its own will help answer this question. Try the
325325following command in your Dojo:
326326
327327```
328− > (mul 3 11)
329− 33
328+> (mul 3 11)
329+33
330330```
331331
332332This should work, producing `33`, an atom. That’s our problem. The
@@ -334,16 +334,16 @@ interpolation expression expects a tape, but our first command tried to
334334interpolate with something that results in an atom. Try this now:
335335
336336```
337− > <(mul 3 11)>
338− "33"
337+> <(mul 3 11)>
338+"33"
339339```
340340
341341We get a similar result, but we know that it’s a tape because it’s wrapped in
342342`""`. Bingo! With this knowledge, let’s perform a successful interpolation:
343343
344344```
345− > "I am a l{<(mul 3 11)>}t Urbit user."
346− "I am a l33t Urbit user."
345+> "I am a l{<(mul 3 11)>}t Urbit user."
346+"I am a l33t Urbit user."
347347```
348348
349349Great!
@@ -369,7 +369,7 @@ To see this difference, first save the code below to a file at
369369Then enter the following command in the Dojo:
370370
371371```
372− > .
372+> .
373373```
374374
375375You'll notice that the Sail subject is like a stripped-down version of the Dojo