@@ -1,6 +1,6 @@
11---
22next: true
3−sort: 7
3+sort: 8
44title: Using Generators with Apps
55---
66
@@ -12,7 +12,7 @@ the "plumbing" way to interact with apps. Generators are the
1212`|merge`, there are no marks in sight.
1313
1414We've used generators before, back in [Basic
15−Operation](basic). At that point, we just used the generators
15+Operation](http://urbit.org/docs/user/basic). At that point, we just used the generators
1616to produce values -- we didn't pipe their results into apps. In
1717the dojo cast, the role of a generator is to take a list of
1818arguments and produce a value, which is often, though not always,
@@ -52,10 +52,8 @@ abbreviated to `:my-app|my-generator <args>`. Because most
5252built-in commands are generators for the `:hood` app,
5353`:hood|generator <args>` can be shortened to `|generator <args>`.
5454
55−XXThe paragraph above is too long and confusing
56−
5755Let's write a generator for a modified version of `:pong` from
58−the chapter on [Network Messages](network). Recall that `:pong`
56+the chapter on [Network Messages](http://urbit.org/docs/user/network). Recall that `:pong`
5957takes an urbit address, which is of mark `urbit`, and sends that
6058urbit the message `'howdy'`. First--without a generator--let's
6159make `:ping` that does the same, except that it lets the user
@@ -64,44 +62,117 @@ optionally specify the message as well.
6462We'll need a new mark for our arguments. Let's call it
6563`ping-message`.
6664
67−> For app-specific marks, it's good style to prefix the name of
68−> the mark with the name of the app. Since many apps have
69−> several such marks, subdirectories in `/mar` are rendered as
70−> `-`, so that `ping-message` is written in
71−> (`/mar/ping/message.hoon`).
65+<blockquote class="blockquote">
66+For app-specific marks, it's good style to prefix the name of
67+the mark with the name of the app. Since many apps have
68+several such marks, subdirectories in `/mar` are rendered as
69+`-`, so that `ping-message` is written in
70+(`/mar/ping/message.hoon`).
71+</blockquote>
7272
7373```
74−|_ [to=@p message=@t]
75−++ grab
76− |%
77− ++ noun ,[@p @t]
78− --
74+:: Up-ness monitor. Accepts atom url, 'on', or 'off'
75+::
76+:::: /hoon/up/examples/app
77+ ::
78+/? 314
79+|%
80+++ move {bone card}
81+++ card
82+ $% {$hiss wire $~ $httr {$purl p/purl}}
83+ {$wait wire @da}
84+ ==
85+++ action
86+ $% {$on $~} :: enable polling('on')
87+ {$off $~} :: disable polling('off)
88+ {$target p/cord} :: set poll target('http://...')
89+ ==
90+--
91+|_ {hid/bowl on/_| in-progress/_| target/@t}
92+++ poke-atom
93+ |= url-or-command/@t ^- (quip move +>)
94+ =+ ^- act/action
95+ ?: ?=($on url-or-command) [%on ~]
96+ ?: ?=($off url-or-command) [%off ~]
97+ [%target url-or-command]
98+ ?- -.act
99+ $target [~ +>.$(target p.act)]
100+ $off [~ +>.$(on |)]
101+ $on
102+ :- ?: |(on in-progress) ~
103+ [ost.hid %hiss /request ~ %httr %purl (need (epur target))]~
104+ +>.$(on &, in-progress &)
105+ ==
106+::
107+
108+:: ~& 'i get here'
109+:: ^- {(list move) _+>.$}
110+:: ?: =('off' url)
111+:: [~ +>.$(on |)]
112+:: ?: =('on' url)
113+:: :_ +>.$(on &, in-progress &)
114+:: ?: |(on in-progress)
115+:: ~
116+:: [ost.hid %them /request ~ (need (epur target)) %get ~ ~]~
117+:: [~ +>.$(target url)]
118+++ sigh-httr
119+ |= {wir/wire code/@ud headers/mess body/(unit octs)}
120+ ~& 'arrive here'
121+ ^- {(list move) _+>.$}
122+ ?: &((gte code 200) (lth code 300))
123+ ~& [%all-is-well code]
124+ :_ +>.$
125+ [ost.hid %wait /timer (add ~s10 now.hid)]~
126+ ~& [%we-have-a-problem code]
127+ ~& [%headers headers]
128+ ~& [%body body]
129+ :_ +>.$
130+ [ost.hid %wait /timer (add ~s10 now.hid)]~
131+++ wake-timer
132+ |= {wir/wire $~} ^- (quip move +>)
133+ ?: on
134+ :_ +>.$
135+ [ost.hid %hiss /request ~ %httr %purl (need (epur target))]~
136+ [~ +>.$(in-progress |)]
137+::
138+++ prep ~& target _`. ::
79139--
80140```
81141
82−The app can easily be modified to use this (`/ape/ping.hoon`):
142+The app can easily be modified to use this (`/app/ping.hoon`):
83143
84144```
85−/? 314
145+::
146+:::: /hoon/ping/examples/app
147+ ::
148+/? 151
86149|%
87− ++ move ,[bone term wire *]
150+ ++ move {bone term wire *}
88151--
89152!:
90−|_ [bowl state=~]
153+|_ {bowl state/$~}
91154::
92−++ poke-ping-message
93− |= [to=@p message=@t]
94− ^- [(list move) _+>.$]
95− [[[ost %poke /sending [to dap] %atom message] ~] +>.$]
155+++ poke-examples-ping-message
156+ |= {to/@p message/@t}
157+ ~& 'sent'
158+ ^- {(list move) _+>.$}
159+ :- ^- (list move)
160+ :~ `move`[ost %poke /sending [to dap] %atom message]
161+ ==
162+ +>.$
96163::
97164++ poke-atom
98− |= arg=@
99− ^- [(list move) _+>.$]
100− ~& [%receiving (,@t arg)]
165+ |= arg/@
166+ ~& 'received'
167+ ^- {(list move) _+>.$}
168+ ::
169+ ~& [%receiving (@t arg)]
101170 [~ +>.$]
102171::
103172++ coup |=(* `+>)
104173--
174+
175+
105176```
106177
107178Now we can run this with:
@@ -123,11 +194,11 @@ to `:ping`, let's put it in `/gen/ping/send.hoon`:
123194
124195```
125196:- %say
126−|= [^ [[to=@p message=?(~ [text=@t ~])] ~]]
197+|= {^ {{to/@p message/?($~ {text/@t $~})} $~}
127198[%ping-message to ?~(message 'howdy' text.message)]
128199```
129200
130−A couple of new things here. Firstly, `message=?(~ [text=@t ~])`
201+A couple of new things here. Firstly, `message/?($~ {text=@t $~})`
131202should be read as "the message is either null or a pair of text
132203and null". Generator argument lists are always null-terminated,
133204which makes it convenient to accept lists in tail position (which
@@ -140,21 +211,23 @@ text and null.
140211Secondly, `?~(a b c)` is a rune which means "if the `a` is null,
141212do `b`, else `c`". It is roughly equivalent to `?:(=(~ a) b c)`.
142213
143−> `?~(a b c)` is actually equivalent to `?:=(?=(~ a) b c)`,
144−> which, although identical at run time, is subtly different at
145−> compile time. Specifically, using `?=` rather than `=` means
146−> that we're checking whether `a` is in the *type* of `~`, and so
147−> the compiler knows that in the `b` case `a` is null, and in the
148−> `c` case `a` is not null. Since `=` is purely a runtime value
149−> check with no type implications, the compiler doesn't gain any
150−> information.
151−>
152−> At any rate, this is the reason why we can refer to
153−> `text.message` in the `c` clause. The compiler knows that
154−> `message` is not null, so it must have `text` within it. If
155−> you used `?:(=(~ message) 'howdy' text.message)` the compiler
156−> would complain that it doesn't know whether `message` has
157−> `text` within it.
214+<blockquote class="blockquote">
215+`?~(a b c)` is actually equivalent to `?:=(?=(~ a) b c)`,
216+which, although identical at run time, is subtly different at
217+compile time. Specifically, using `?=` rather than `=` means
218+that we're checking whether `a` is in the *type* of `~`, and so
219+the compiler knows that in the `b` case `a` is null, and in the
220+`c` case `a` is not null. Since `=` is purely a runtime value
221+check with no type implications, the compiler doesn't gain any
222+information.
223+
224+At any rate, this is the reason why we can refer to
225+`text.message` in the `c` clause. The compiler knows that
226+`message` is not null, so it must have `text` within it. If
227+you used `?:(=(~ message) 'howdy' text.message)` the compiler
228+would complain that it doesn't know whether `message` has
229+`text` within it.
230+</blockquote>
158231
159232This is run as follows:
160233