@@ -86,31 +86,28 @@ Let's look at another example (edit your code in `/app/examples/echo/hoon` to
86reflect the code below). Say we want to only accept a number, and then print out
86reflect the code below). Say we want to only accept a number, and then print out
87the square of that number.
87the square of that number.
89− :: Accepts any atom from dojo and prints its square
89+ :: Accepts an atom from the dojo and squares it.
91− :::: /===/app/echo/hoon
91+ :::: /===/app/square/hoon
94− |%
94+ |% ::> no moves in :square
95− ++ move {bone card}
95+ ++ move {bone card} ::> no cards in :square
96 ++ card $% $~
96 ++ card $% $~
99− ::
99+ :: ::< stateless
100 |_ {bow/bowl $~}
100 |_ {bow/bowl $~}
101 ++ poke-atom
101 ++ poke-atom
102− |= atm/@
102+ |= tom/@
103 ^- {(list move) _+>.$}
103 ^- {(list move) _+>.$}
104− ~& [%square atm (mul atm atm)]
104+ ~& square+(mul tom tom)
105 [~ +>.$]
105 [~ +>.$]
108A few things have changed. Firstly, we no longer accept arbitrary nouns because
108A few things have changed. Firstly, we no longer accept arbitrary nouns because
109we can only square atoms (integers, in this case an unsigned one). Thus, our
109we can only square atoms (integers, in this case an unsigned one). Thus, our
110−argument is now `atm/@`. Secondly, it's `++poke-atom` rather than `++poke-noun`.
110+argument is now `tom/@`. Secondly, it's `++poke-atom` rather than `++poke-noun`.
111−Also note how the format of the sample we send to the debug printf rune `~&`
112−has moved from irregular (`echo+noun+non`) to regular
113−(`[%square atm (mul atm atm)]`).
115# Intro to marks
112# Intro to marks
@@ -132,9 +129,9 @@ commands:
133 ~fintud-macrep:dojo> |start %square
130 ~fintud-macrep:dojo> |start %square
135− ~fintud-macrep:dojo> :examples-square 6
132+ ~fintud-macrep:dojo> :square 6
136 gall: %square: no poke arm for noun
133 gall: %square: no poke arm for noun
137− ~fintud-macrep:dojo> :examples-square &atom 6
134+ ~fintud-macrep:dojo> :square &atom 6
138 [%square 36]
135 [%square 36]
@@ -150,49 +147,62 @@ be getting quite used to them.
151# Sending a message to another urbit
148# Sending a message to another urbit
153−Let's write our first network message! Here's `/app/examples/pong.hoon`:
150+Let's write our first network message! Here's `examples/app/pong.hoon`:
155− /? 314
152+ :: Allows one urbit to send the string 'Pong' to
155+ :::: /===/app/pong/hoon
157− ++ move {bone term wire *}
159+ ++ move {bone card}
160+ ++ card $% {$poke wire dock poke-contents}
162+ ++ poke-contents $% {$atom @}
159− !:
165+ |_ {bow/bowl $~} ::< stateless
162 ++ poke-urbit
167 ++ poke-urbit
163− |= to/@p
168+ |= to/ship
164 ^- {(list move) _+>.$}
169 ^- {(list move) _+>.$}
170+ ~& pong+'Outgoing pong!'
165− [[[ost %poke /sending [to dap] %atom 'howdy'] ~] +>.$]
172+ ~[[ost.bow %poke /sending [to dap.bow] %atom 'Pong']]
167 ++ poke-atom
174 ++ poke-atom
168− |= arg/@
175+ |= tom/@
169 ^- {(list move) _+>.$}
176 ^- {(list move) _+>.$}
170− ~& [%receiving (@t arg)]
177+ ~& pong+'Incoming pong!'
178+ ~& pong+received+`@t`tom
173 ++ coup |=(* [~ +>.$])
181 ++ coup |=(* [~ +>.$])
176Run it with these commands:
185Run it with these commands:
178− ~fintud-macrep:dojo> |start %examples-pong
187+ ~fintud-macrep:dojo> |start %pong
180− ~fintud-macrep:dojo> :examples-pong &urbit ~sampel-sipnym
189+ ~fintud-macrep:dojo> :pong &urbit ~sampel-sipnym
183Replace `~sampel-sipnym` with another urbit. The easiest thing to do is to start
192Replace `~sampel-sipnym` with another urbit. The easiest thing to do is to start
184a comet, a free and disposable Urbit identity. If you don't know how to start a
193a comet, a free and disposable Urbit identity. If you don't know how to start a
185comet, see [the user setup section](/docs/using/setup/). Don't forget to start
194comet, see [the user setup section](/docs/using/setup/). Don't forget to start
186−the `%examples-pong` app on that urbit, too. You should see, on the foreign
195+the `%pong` app on that urbit, too. You should see, on the foreign
187urbit, this output:
196urbit, this output:
189− [%receiving 'howdy']
198+ [%pong 'Incoming pong!']
199+ [%pong %received 'Pong']
191Most of the code should be straightforward. In `++poke-atom`, the only new thing
201Most of the code should be straightforward. In `++poke-atom`, the only new thing
192−is the expression `(@t arg)`, which is the type `@t` being called as a function
202+is the expression `` `@t`tom ``, which is casting the argument `tom` to type
193−with argument `arg`. As we already know, `@t` is the type of "cord" text
203+`@t`. As we already know, `@t` is the type of "cord" text strings. In Hoon,
194−strings. In Hoon, when types are called as functions, they serve as a validator
204+when types are called using tick marks, they serve as a validator function
195−function called a "clam" -- that is, a function whose domain is all nouns, and
205+called a "clam" -- that is, a function whose domain is all nouns, and
196range is the given type (in this case, `@t`).
206range is the given type (in this case, `@t`).
198In simpler terms, if a clam is passed a value of its own type, it produces that
208In simpler terms, if a clam is passed a value of its own type, it produces that
@@ -201,15 +211,15 @@ Here we call this `@t` function on the argument. This coerces the argument to
201text, so that we can print it out prettily no matter what we're passed.
211text, so that we can print it out prettily no matter what we're passed.
203The more interesting part is in `++poke-urbit`. The `urbit` mark is an urbit
213The more interesting part is in `++poke-urbit`. The `urbit` mark is an urbit
204−identity, and the Hoon type associated with it is `@p` (the "p" stands for
214+identity, and the Hoon type associated with it is `ship` or `@p` (the "p"
205−"phonetic base").
215+stands for "phonetic base").
207Recall that in a `++poke` arm we produce "a list of moves and our state". Until
217Recall that in a `++poke` arm we produce "a list of moves and our state". Until
208now, we've left the list of moves empty, since we haven't wanted to tell Arvo to
218now, we've left the list of moves empty, since we haven't wanted to tell Arvo to
209do anything in particular. Now we want to send a message to another urbit. Thus,
219do anything in particular. Now we want to send a message to another urbit. Thus,
210we produce a list with one element:
220we produce a list with one element:
212− [ost %poke /sending [to-urbit-address %pong] %atom 'howdy']
222+ ~[[ost.bow %poke /sending [to dap.bow] %atom 'Pong]]
@@ -224,14 +234,14 @@ Let's walk through each of these elements step by step.
224#### Bones ("cause")
234#### Bones ("cause")
226If you look up `++bone` in `hoon.hoon`, you'll see that it's a number (`@ud`),
236If you look up `++bone` in `hoon.hoon`, you'll see that it's a number (`@ud`),
227−and that it's an opaque reference to a duct. `++duct` in hoon.hoon is a list of
237+and that it's an opaque reference to a duct. `++duct` in `hoon.hoon` is a list
228−`wire`s, where `++wire` is an alias for `++path`. `++path` is a list of
238+of `wire`s, where `++wire` is an alias for `++path`. `++path` is a list of
229`++knot`s, which are ASCII text. Thus, a duct is a list of paths, and a bone is
239`++knot`s, which are ASCII text. Thus, a duct is a list of paths, and a bone is
230an opaque reference to it (in the same way that a Unix file descriptor is an
240an opaque reference to it (in the same way that a Unix file descriptor is an
231opaque reference to a file structure). Thus, to truly understand bones, we must
241opaque reference to a file structure). Thus, to truly understand bones, we must
232understand ducts.
242understand ducts.
234−A duct is stack of causes, again, represented as paths, which are called wires.
244+A duct is a stack of causes, again, represented as paths, which are called wires.
235At the bottom of every duct is a unix event, such as a keystroke, network
245At the bottom of every duct is a unix event, such as a keystroke, network
236packet, file change, or timer event. When Arvo is given this event, it routes
246packet, file change, or timer event. When Arvo is given this event, it routes
237the event to appropriate kernel module for handling.
247the event to appropriate kernel module for handling.
@@ -245,11 +255,12 @@ action, and produces the result from that.
246Furthermore, when one module sends a message to another kernel module or
256Furthermore, when one module sends a message to another kernel module or
247application, it also sends along the duct it was given with its new wire tacked
257application, it also sends along the duct it was given with its new wire tacked
248−onto the end. Now the duct has two entries, with the unix event on the bottom
258+onto the top. Now the duct has two entries, with the unix event on the bottom
249−and the kernel module that handled it next. This process can continue
259+and the kernel module that handled it on top. This process can continue
250−indefinitely, adding more and more layers onto the duct. When an entity finally
260+indefinitely, pushing more and more wires onto the top of the duct. When an
251−produces a result, a layer is popped off the duct, and the result is passed all
261+entity finally produces a result, a wire is popped off the duct, and the result
252−the way back down.
262+is passed all the way back down, repeating the process of wire popping
263+sequentially until the bottom of the duct is reached.
254In effect, a duct is an Arvo-level call stack. It's worth noting that while in
265In effect, a duct is an Arvo-level call stack. It's worth noting that while in
255traditional call stacks a function call happens synchronously and returns
266traditional call stacks a function call happens synchronously and returns
@@ -262,8 +273,8 @@ to send the network message along the given bone `ost`.
263##### Wire ('tack on new layer to duct')
274##### Wire ('tack on new layer to duct')
265−Of course, we have to push a new layer onto our duct before passing it along (or
276+Of course, we have to push a new wire onto our duct before passing it along (or
266−responding to it directly) anywhere. This layer can have any data we want in it,
277+responding to it directly) anywhere. This wire can have any data we want in it,
267but we don't need anything specific here, so we just use the wire `/sending`
278but we don't need anything specific here, so we just use the wire `/sending`
268(`/elem1/elem2/elemN` is one syntax used to create `++path`s and `++wire`s of N
279(`/elem1/elem2/elemN` is one syntax used to create `++path`s and `++wire`s of N
269elements). If we were expecting a response (which we're not), it would come back
280elements). If we were expecting a response (which we're not), it would come back
@@ -274,7 +285,7 @@ generally a good idea to make the wire human-readable for bug-handling purposes.
274##### Term (sys-call)
285##### Term (sys-call)
276Each move also has a `term`, composed of lowercase ASCII and/or `-`. This `term`
287Each move also has a `term`, composed of lowercase ASCII and/or `-`. This `term`
277−has the sign `@tas`. In this case, out `term` is `%poke`, which is the name of
288+has the sign `@tas`. In this case, our `term` is `%poke`, which is the name of
278the particular kind of move we're sending. You can always use `%poke` to message
289the particular kind of move we're sending. You can always use `%poke` to message
279an app. Other common names include `%warp`, to read from the filesystem;
290an app. Other common names include `%warp`, to read from the filesystem;
280`%wait`, to set a timer; and `%them`, to send an http request.
291`%wait`, to set a timer; and `%them`, to send an http request.