@@ -5,369 +5,339 @@ sort: 3
5title: Network messages
5title: Network messages
8−# Network messages
8+Network messages
10−Now we've learned enough hoon to do more interesting things.
11+Now we've learned enough Hoon to do more interesting things. Let's get
11−Let's get our planets to talk to each other.
12+our planets to talk to each other.
13−All we've written up until now are just shell
14+All we've written up until now are just shell commands that produce a
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+value and then disappear. To listen for and receive messages from other
15−
16+planets, we'll need an app. Let's look at a very simple one:
17−:: There is no love that is not an echo
18+ :: There is no love that is not an echo
19−:::: /hoon/echo/examples/app
20+ :::: /hoon/echo/examples/app
23−|_ {bowl state/$~}
24+ |_ {bowl state/$~}
24−++ poke-noun
25+ ++ poke-noun
26− ^- {(list) _+>.$}
27+ ^- {(list) _+>.$}
27− ~& [%argument arg]
28+ ~& [%argument arg]
33−This is a very simple app that does only one thing. If you poke
32+This is a very simple app that does only one thing. If you poke it with
34−it with a value, it prints that value out. To try this out, you
33+a value, it prints that value out. To try this out, you have to start
35−have to start the app, then you can poke it from the command line
34+the app, then you can poke it from the command line with the following
36−with the following commands:
35+commands:
39−~fintud-macrep:dojo> |start %echo
37+ ~fintud-macrep:dojo> |start %echo
41−~fintud-macrep:dojo> :examples-echo 5
39+ ~fintud-macrep:dojo> :examples-echo 5
42−[%argument 5]
40+ [%argument 5]
44−~fintud-macrep:dojo> :examples-echo [1 2]
42+ ~fintud-macrep:dojo> :examples-echo [1 2]
45−[%argument [1 2]]
43+ [%argument [1 2]]
49−<blockquote class="blockquote">
50−There is currently a bug where the `%argument` lines are
46+> There is currently a bug where the `%argument` lines are printed
51−printed *above* the line you entered, so your output may not
47+> *above* the line you entered, so your output may not look exactly like
52−look exactly like this.
53−`>=` means that a command was successfully received and
48+> this. `>=` means that a command was successfully received and
54−executed.
49+> executed.
57−Most of the app code should be simple enough to guess its
51+Most of the app code should be simple enough to guess its function. The
58−function. The important part of this code is the definition of
52+important part of this code is the definition of `++poke-noun`.
61Once an app starts, it's always running in the background and you
54Once an app starts, it's always running in the background and you
62−interact with it by sending it messages. The most
55+interact with it by sending it messages. The most straightforward way to
63−straightforward way to do that is to poke it from the command
56+do that is to poke it from the command line, which we we did with
64−line, which we we did with `:echo 5` (`:[app-name]
65−[argument(s)]).
57+`:echo 5` (`:[app-name] [argument(s)]`).
67−In this case, `++poke-noun` takes an argument `arg` and prints it
59+In this case, `++poke-noun` takes an argument `arg` and prints it out
68−out with `~&`. This is an unusual rune that formally "does
60+with `~&` ([sigpam](/hoon/twig/sig-hint/pam-dump/)). This is an unusual
69−nothing", but the interpreter detects it and printfs the first
61+rune that formally "does nothing", but the interpreter detects it and
70−child, before executing the second as if the first didn't exist.
62+printfs the first child, before executing the second as if the first
71−This is a slightly hacky way of printing to the console, but
63+didn't exist. This is a slightly hacky way of printing to the console,
72−we'll get to the correct way later on.
64+but we'll get to the correct way later on.
74−But what does `++poke-noun` produce? Recall that `^-` casts to a
66+But what does `++poke-noun` produce? Recall that `^-` casts to a type.
75−type. In this case, it's declaring that end result of the
67+In this case, it's declaring that end result of the function will be of
76−function will be of type `{(list) _+>.$}`. But what does this
68+type `{(list) _+>.$}`. But what does this mean?
79−The phrase to remember is "a list of moves and our state". Urbit
70+The phrase to remember is "a list of moves and our state". Urbit is a
80−is a message passing system, so whenever we want to do something that
71+message passing system, so whenever we want to do something that
81−interacts with the rest of the system, we send a message. Thus, a
72+interacts with the rest of the system, we send a message. Thus, a move
82−move is arvo's equivalent of a syscall. The first thing that
73+is arvo's equivalent of a syscall. The first thing that `++poke-noun`
83−`++poke-noun` produces is a list of messages, called
74+produces is a list of messages, called "moves". In this case, we don't
84−"moves". In this case, we don't actually want the system to do
85−anything, so we produce the empty list, `~` (in the `[~ +>.$]`
75+actually want the system to do anything, so we produce the empty list,
86−line).
76+`~` (in the `[~ +>.$]` line).
88−The second thing `++poke-noun` produces is our state. `+>.$`
78+The second thing `++poke-noun` produces is our state. `+>.$` refers to a
89−refers to a particular address in our subject where our formal
79+particular address in our subject where our formal app state is stored.
90−app state is stored. It'll become clear why this is later on,
80+It'll become clear why this is later on, but for now pretend that `+>.$`
91−but for now pretend that `+>.$` is a magic invocation that means
81+is a magic invocation that means "app state".
93−
83+Let's look at another example (edit your code in
94−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
84+`/app/examples/echo/hoon` to reflect the code below). Say we want to
95−number, and then print out the square of that number.
85+only accept a number, and then print out the square of that number.
100−|_ {bowl state=~}
89+ |_ {bowl state=~}
102−++ poke-atom
91+ ++ poke-atom
103− |= arg/@
92+ |= arg/@
104− ^- {(list) _+>.$}
93+ ^- {(list) _+>.$}
105− ~& [%square (mul arg arg)]
94+ ~& [%square (mul arg arg)]
106− [~ +>.$]
95+ [~ +>.$]
110−A few things have changed. Firstly, we no longer accept
98+A few things have changed. Firstly, we no longer accept arbitrary nouns
111−arbitrary nouns because we can only square atoms (integers, in
99+because we can only square atoms (integers, in this case an unsigned
112−this case an unsigned one). Thus, our argument is now `arg/@`.
100+one). Thus, our argument is now `arg/@`. Secondly, it's `++poke-atom`
113−Secondly, it's `++poke-atom` rather than `++poke-noun`.
101+rather than `++poke-noun`.
115−# Intro to marks
103+Intro to marks
117−Are there other `++poke`s? Yes. In fact, `noun` and
106+Are there other `++poke`s? Yes. In fact, `noun` and `atom` are just two
118−`atom` are just two of arbitrarily many "marks". A mark is
107+of arbitrarily many "marks". A mark is fundamentally a type definition,
119−fundamentally a type definition, but accessible at the arvo
120−level. Each mark is defined in the `/mar` directory. Some marks
108+but accessible at the arvo level. Each mark is defined in the `/mar`
121−have conversion routines to other marks, and some have diff,
109+directory. Some marks have conversion routines to other marks, and some
122−patch, and merge algorithms. None of these are required for a
110+have diff, patch, and merge algorithms. None of these are required for a
123mark to exist, however.
111mark to exist, however.
125−`noun` and `atom` are two of dozens of predefined marks (that will
113+`noun` and `atom` are two predefined marks. In your `/mar` directory,
126−already be in your `/mar` directory), and the
127−user may add more at will. The type associated with `noun` is
114+there are already many more, and you may add more at will. The type
128−`*`, and the type associated with `atom` is `@`.
115+associated with `noun` is `*`, and the type associated with `atom` is
130−When we poke an app from anywhere, we do so with a mark that
118+When we poke an app from anywhere, we do so with a mark that searches
131−searches for the corresponding (`++poke-[mark]`) arm. Data
119+for the corresponding (`++poke-[mark]`) arm. Data constructed on the
132−constructed on the command line is by default marked with `noun`.
120+command line is by default marked with `noun`. In this case, the app is
133−In this case, the app is expecting an atom, so we have to
121+expecting an atom, so we have to explicitly mark the data with `atom`
134−explicitly mark the data with `atom` using `&[mark]`. Try the following
122+using `&[mark]`. Try the following commands:
138−~fintud-macrep:dojo> |start %square
124+ ~fintud-macrep:dojo> |start %square
140−~fintud-macrep:dojo> :examples-square 6
126+ ~fintud-macrep:dojo> :examples-square 6
141−gall: %square: no poke arm for noun
127+ gall: %square: no poke arm for noun
142−~fintud-macrep:dojo> :examples-square &atom 6
128+ ~fintud-macrep:dojo> :examples-square &atom 6
143−[%square 36]
129+ [%square 36]
147−> Recall the bug where `%square` may get printed above the input
132+> Recall the bug where `%square` may get printed above the input line.
150−Marks are powerful, and they're the backbone of urbit's data
134+Marks are powerful, and they're the backbone of Urbit's data pipeline,
151−pipeline, so we'll be getting quite used to them.
135+so we'll be getting quite used to them.
153**Exercise**:
137**Exercise**:
155−- Write an app that computes fizzbuzz on its input (as in the
139+- Write an app that computes fizzbuzz on its input (as in the previous
156− previous section).
140+ section).
158−# Sending a message to another ship
142+Sending a message to another urbit
159−
143+==================================
160−Let's write our first network message! Here's `/app/examples/pong.hoon`:
145+Let's write our first network message! Here's `/app/examples/pong.hoon`:
165− ++ move {bone term wire *}
149+ ++ move {bone term wire *}
168−|_ {bowl state=$~}
152+ |_ {bowl state=$~}
170−++ poke-urbit
154+ ++ poke-urbit
171− |= to/@p
155+ |= to/@p
172− ^- [(list move) _+>.$]
156+ ^- [(list move) _+>.$]
173− [[[ost %poke /sending [to %pong] %atom 'howdy'] ~] +>.$]
157+ [[[ost %poke /sending [to %pong] %atom 'howdy'] ~] +>.$]
175−++ poke-atom
159+ ++ poke-atom
176− |= arg/@
160+ |= arg/@
177− ^- (list move) _+>.$}
161+ ^- (list move) _+>.$}
178− ~& [%receiving (@t arg)]
162+ ~& [%receiving (@t arg)]
179− [~ +>.$]
163+ [~ +>.$]
181−++ coup |=(* [~ +>.$])
165+ ++ coup |=(* [~ +>.$])
185Run it with these commands:
168Run it with these commands:
188−~fintud-macrep:dojo> |start %examples-pong
170+ ~fintud-macrep:dojo> |start %examples-pong
190−~fintud-macrep:dojo> :pong &examples-urbit ~sampel-sipnym
172+ ~fintud-macrep:dojo> :pong &examples-urbit ~sampel-sipnym
194−Replace `~sampel-sipnym` with another urbit. The easiest thing to
175+Replace `~sampel-sipnym` with another urbit. The easiest thing to do is
195−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
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
196−forget to start the `%examples-pong` app on that urbit too. You should
178+forget to start the `%examples-pong` app on that urbit, too. You should
197see, on the foreign urbit, this output:
179see, on the foreign urbit, this output:
200−[%receiving 'howdy']
181+ [%receiving 'howdy']
203−Most of the code should be straightforward. In `++poke-atom`,
183+Most of the code should be straightforward. In `++poke-atom`, the only
204−the only new thing is the expression `(@t arg)`. As we already
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
205−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" in hoon) -- that is, a function whose domain is all nouns and range is the given type.
188+is, a function whose domain is all nouns, and range is the given type
189+(in this case, `@t`).
207−In simpler terms, if a validator function is passed a value that
191+In simpler terms, if a clam is passed a value of its own type, it
208−falls within its type, that value is produced. Otherwise, it
209−produces the default value (aka the "bunt") of its type. Here we call
192+produces that value. Otherwise, it produces the default value (aka the
210−this `@t` function on the argument. This coerces the argument
193+"bunt") of its type. Here we call this `@t` function on the argument.
211−to text, so that we can print it out prettily no matter what
194+This coerces the argument to text, so that we can print it out prettily
212−we're passed.
195+no matter what we're passed.
214−The more interesting part is in `++poke-urbit`. The `urbit` mark
197+The more interesting part is in `++poke-urbit`. The `urbit` mark is an
215−is an urbit identity, and the hoon type associated with it is
198+urbit identity, and the Hoon type associated with it is `@p` (the "p"
216−`@p` (the "p" stands for "phonetic base").
199+stands for "phonetic base").
218Recall that in a `++poke` arm we produce "a list of moves and our
201Recall that in a `++poke` arm we produce "a list of moves and our
219−state". Until now, we've left the list of moves empty, since we
202+state". Until now, we've left the list of moves empty, since we haven't
220−haven't wanted to tell arvo to do anything in particular. Now we
203+wanted to tell arvo to do anything in particular. Now we want to send a
221−want to send a message to another urbit. Thus, we produce a list
204+message to another urbit. Thus, we produce a list with one element:
225−[ost %poke /sending [to-urbit-address %pong] %atom 'howdy']
206+ [ost %poke /sending [to-urbit-address %pong] %atom 'howdy']
230−The general form of a move is
210+The general form of a move is `[bone term wire *]`.
235−------------------------->app/vane-specific part of move
237Or, in pseudo-code:
212Or, in pseudo-code:
239−`["cause" sys-call/action tack-new-layer-on-cause action-specific
214+`["cause" sys-call/action tack-new-layer-on-cause action-specific information]`
242Let's walk through each of these elements step by step.
216Let's walk through each of these elements step by step.
244#### Bones ("cause")
218#### Bones ("cause")
246−If you look up `++bone` in `hoon.hoon`, you'll see that it's a
220+If you look up `++bone` in `hoon.hoon`, you'll see that it's a number
247−number (`@ud`), and that it's an opaque reference to a duct.
221+(`@ud`), and that it's an opaque reference to a duct. `++duct` in
248−`++duct` in hoon.hoon is a list of `wire`s, where `++wire` is an
222+hoon.hoon is a list of `wire`s, where `++wire` is an alias for `++path`.
249−alias for `++path`. `++path` is a list of `++span`s, which are ASCII
223+`++path` is a list of `++span`s, which are ASCII text. Thus, a duct is a
250−text. Thus, a duct is a list of paths, and a bone is an opaque
224+list of paths, and a bone is an opaque reference to it (in the same way
251−reference to it (in the same way that a Unix file
252−descriptor is an opaque reference to a file structure). Thus, to
225+that a Unix file descriptor is an opaque reference to a file structure).
253−truly understand bones, we must understand ducts.
226+Thus, to truly understand bones, we must understand ducts.
255−A duct is stack of causes, again, represented as paths, which are
228+A duct is stack of causes, again, represented as paths, which are called
256−called wires. At the bottom of every duct is a unix event, such
229+wires. At the bottom of every duct is a unix event, such as a keystroke,
257−as a keystroke, network packet, file change, or timer event.
230+network packet, file change, or timer event. When arvo is given this
258−When arvo is given this event, it routes the event to appropriate
231+event, it routes the event to appropriate kernel module for handling.
259−kernel module for handling.
232+
261−Sometimes, the module can immediately handle the event and
233+Sometimes, the module can immediately handle the event and produce any
262−produce any necessary results. For example, when we poked the
234+necessary results. For example, when we poked the `++poke-atom` arm
263−`++poke-atom` arm above, we poked %gall, our application server,
235+above, we poked %gall, our application server, which was able to respond
264−which was able to respond to our poke directly. When the module
236+to our poke directly. When the module cannot service the request itself,
265−cannot service the request itself, it sends instructions to another kernel
237+it sends instructions to another kernel module or application (the the
266−module or application (the the %gall module) to do a specified action, and produces the result from that.
238+%gall module) to do a specified action, and produces the result from
268−Furthermore, when one module sends a message to another kernel module or application, it also sends along the duct it was given
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
269−with its new wire tacked onto the end. Now the duct has two entries,
243+tacked onto the end. Now the duct has two entries, with the unix even on
270−with the unix even on the bottom and the kernel module that
244+the bottom and the kernel module that handled it next. This process can
271−handled it next. This process can continue indefinitely, adding
272−more and more layers onto the duct. When an entity finally
245+continue indefinitely, adding more and more layers onto the duct. When
273−produces a result, a layer is popped off the duct, and the result
246+an entity finally produces a result, a layer is popped off the duct, and
274−is passed all the way back down.
247+the result is passed all the way back down.
276−In effect, a duct is an arvo-level call stack. It's worth noting
249+In effect, a duct is an arvo-level call stack. It's worth noting that
277−that while in traditional call stacks a function call happens
250+while in traditional call stacks a function call happens synchronously
278−synchronously and returns exactly once. In arvo, multiple moves
251+and returns exactly once. In arvo, multiple moves can be sent at once,
279−can be sent at once, are evaluated asynchronously, and each
252+are evaluated asynchronously, and each one may be responded to zero or
280−one may be responded to zero or more times.
253+more times.
282The point to take home is that whatever caused `++poke-urbit` to be
255The point to take home is that whatever caused `++poke-urbit` to be
283−called is also the root cause for the network message we're
256+called is also the root cause for the network message we're trying to
284−trying to send. Thus, we say to send the network message along the given bone
257+send. Thus, we say to send the network message along the given bone
287##### Wire ('tack on new layer to duct')
260##### Wire ('tack on new layer to duct')
289−Of course, we have to push a new layer onto our duct
262+Of course, we have to push a new layer onto our duct before passing it
290−before passing it along (or responding to it directly) anywhere. This
263+along (or responding to it directly) anywhere. This layer can have any
291−layer can have any data we want in it, but we don't need anything
264+data we want in it, but we don't need anything specific here, so we just
292−specific here, so we just use the wire `/sending`
293−(`/elem1/elem2/elem n` is one syntax used to create `++path`s and
265+use the wire `/sending` (`/elem1/elem2/elemN` is one syntax used to
294−`++wire`s of n elements). If we were expecting a response (which
266+create `++path`s and `++wire`s of N elements). If we were expecting a
295−we're not), it would come back along the `/sending` wire, meaning
267+response (which we're not), it would come back along the `/sending`
296−that the path `/sending` will be passed back to the response
268+wire, meaning that the path `/sending` will be passed back to the
297−handler as an argument. Although it's not required, it's
269+response handler as an argument. Although it's not required, it's
298−generally a good idea to make the wire human-readable for
270+generally a good idea to make the wire human-readable for bug-handling
299−bug-handling purposes.
271+purposes.
301##### Term (sys-call)
273##### Term (sys-call)
303−Looking back at the general form of a move, there is a
304−`term`--which is text composed lowercase ascii and `-`, and has
275+Each move also has a `term`, composed of lowercase ASCII and/or `-`.
305−the sign of `@tas`-- which in this case is `%poke`. This is the
276+This `term` has the sign `@tas`. In this case, out `term` is `%poke`,
306−name of the particular kind of move we're sending. If you think
277+which is the name of the particular kind of move we're sending. You can
307−of a move as a syscall (which you should), then this `term` is
278+always use `%poke` to message an app. Other common names include
308−the name of the syscall. Common ones include: `%poke`, to
309−message an app; `%warp`, to read from the filesystem; `%wait`, to
279+`%warp`, to read from the filesystem; `%wait`, to set a timer; and
310−set a timer; and `%them`, to send an http request.
280+`%them`, to send an http request.
312−The general form ends with `*` (a noun) since each type of move takes
282+The move ends with `*` (that is, any noun) since each type of move takes
313−different data. In our case, a `%poke` move takes a target
283+different data. In our case, a `%poke` move takes a target (urbit and
314−(urbit and app) and marked data and pokes the arm of the
284+app) and marked data, then pokes the arm of the corresponding mark on
315−corresponding mark on that app on that urbit
316−with that data. `[to-urbit-address %pong]` is the target urbit and app,
285+that app on that urbit with that data. `[to-urbit-address %pong]` is the
317−`%atom` is the mark`, and `'howdy'` is the data.
286+target urbit and app, `%atom` is the mark`, and`'howdy'\` is the data.
319−When arvo receives a `%poke` move, it calls the appropriate
288+When arvo receives a `%poke` move, it calls the appropriate `++poke`.
320−`++poke`. The same mechanism is used for sending messages
289+The same mechanism is used for sending messages between apps on the same
321−between apps on the same urbit as for sending messages between
290+urbit as for sending messages between apps on different urbits.
322−apps on different urbits.
291+
324−<blockquote class="blockquote">
325−We said earlier that we're not expecting a response. This is
292+> We said earlier that we're not expecting a response. This is not
326−not entirely true: the `++coup` is called when we receive
293+> entirely true: the `++coup` is called when we receive acknowledgment
327−acknowledgment that the `++poke` was called. We don't do
294+> that the `++poke` was called. We don't do anything with this
328−anything with this information right now, but we could.
295+> information right now, but we could.
331**Exercises**:
297**Exercises**:
333−- Extend either of the apps in the first two exercises to accept
299+- Extend either of the apps in the first two exercises to accept input
334− input over the network in the same way as `pong`.
300+ over the network in the same way as `pong`.
336−- Modify `examples-pong` to print out a message when it receives acknowledgement.
302+- Modify `examples-pong` to print out a message when it receives
337−
303+ acknowledgement.
338−- Write two apps, `even` and `odd`. When you pass an atom to
305+- Write two apps, `even` and `odd`. When you pass an atom to `even`,
339− `even`, check whether it's even. If so, divide it by two and
306+ check whether it's even. If so, divide it by two and recurse;
340− recurse; otherwise, poke `odd` with it. When `odd` recieves
307+ otherwise, poke `odd` with it. When `odd` recieves an atom, check
341− an atom, check whether it's equal to one. If so, terminate,
308+ whether it's equal to one. If so, terminate, printing "%success".
342− printing "%success". Otherwise, check whether it's odd. If
309+ Otherwise, check whether it's odd. If so, multiply it by three, add
343− so, multiply it by three, add one, and recurse; otherwise, poke
310+ one, and recurse; otherwise, poke `even` with it. When either app
344− `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
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
345− conjecture play out between the two apps. Sample output:
313+ between the two apps. Sample output:
348−~fintud-macrep:dojo> :even &atom 18
317+ ~fintud-macrep:dojo> :even &atom 18
349−[%even 18]
318+ [%even 18]
350−[%odd 9]
319+ [%odd 9]
351−[%even 28]
320+ [%even 28]
352−[%even 14]
321+ [%even 14]
353−[%odd 7]
322+ [%odd 7]
354−[%even 22]
323+ [%even 22]
355−[%odd 11]
324+ [%odd 11]
356−[%even 34]
325+ [%even 34]
357−[%odd 17]
326+ [%odd 17]
358−[%even 52]
327+ [%even 52]
359−[%even 26]
328+ [%even 26]
360−[%odd 13]
329+ [%odd 13]
361−[%even 40]
330+ [%even 40]
362−[%even 20]
331+ [%even 20]
363−[%even 10]
332+ [%even 10]
364−[%odd 5]
333+ [%odd 5]
365−[%even 16]
334+ [%even 16]
366−[%even 8]
335+ [%even 8]
367−[%even 4]
336+ [%even 4]
368−[%even 2]
337+ [%even 2]
369−%success
338+ %success
372−- Put `even` and `odd` on two separate ships and pass the
340+- Put `even` and `odd` on two separate urbits and pass the messages
373− messages over the network.
341+ over the network. Post a link to a working solution in :talk to