on master help sign in
Merge pull request #80 from asgardiator/master

rogue links in arvo/generators.md

commitfd3b22b169e01d0798a401f36b111551ffa1e149 authorGalen Wolfe-Pauly <galen@office-for.com> dateMon 25 Jul 2016, 17:05 (10 years ago) parent0ba2661d71083c
2 files changed+143−156
docs/arvo/generators.md+139−153 docs/arvo/subscriptions.md+4−3
docs/arvo/generators.md+139−153
@@ -1,192 +1,178 @@
11---
2−navhome: /docs
3−next: true
2+navhome: '/docs'
3+next: True
44sort: 8
55title: Using Generators with Apps
66---
77
88# Generators
99
10−Up until now we've poked apps directly. This requires the user
11−to specify the mark, and it requires the app to accept the
12−arguments in a way that's convenient for users to input. This is
13−the "plumbing" way to interact with apps. Generators are the
14−"porcelain" layer. This is why when you run a command like `+ls` or
15−`|merge`, there are no marks in sight.
10+Up until now we've poked apps directly. This requires the user to
11+specify the mark, and it requires the app to accept the arguments in a
12+way that's convenient for users to input. This is the "plumbing" way to
13+interact with apps. Generators are the "porcelain" layer. This is why
14+when you run a command like `+ls` or `|merge`, there are no marks in
15+sight.
1616
1717We've used generators before, back in [Basic
18−Operation](/docs/using/admin). At that point, we just used the generators
19−to produce values -- we didn't pipe their results into apps. In
20−the dojo cast, the role of a generator is to take a list of
21−arguments and produce a value, which is often, though not always,
22−piped into an app. Generators are pure, stateless functions, and
23−they cannot send moves.
18+Operation](/docs/using/admin). At that point, we just used the
19+generators to produce values -- we didn't pipe their results into apps.
20+In the dojo cast, the role of a generator is to take a list of arguments
21+and produce a value, which is often, though not always, piped into an
22+app. Generators are pure, stateless functions, and they cannot send
23+moves.
2424
2525`+ls` and `+cat` are commonly-used generators that produce a directory
26−listing and print out a file, respectively. These are useful in
26+listing and print out a file, respectively. These are useful in
2727themselves, so we generally don't pipe the results into an app.
2828
29−Another generator is `+hood/merge`. Try running `+hood/merge`
30−with the normal arguments for `|merge`:
31−
32−```
33−~fintud-macrep:dojo> +hood/merge %home our %they
34−[syd=%home her=~fintud-macrep sud=%they gem=%auto]
35−~fintud-macrep:dojo> +hood/merge %home our %they, =gem %this
36−[syd=%home her=~fintud-macrep sud=%they gem=%auto]
37−```
38−
39−This didn't run any merge, it just constructed the command that,
40−if sent to `:hood`, would run it. Note first that, even though
41−it's not printed, this value has mark `kiln-merge`. Also, the
42−merge strategy `gem=%auto` was added automatically. Optional
43−arguments are straightforward with generators.
44−
45−In general, generators are prepended by either `+` or `|`. The
46−general form is `+generator`, but often generators are created
47−specifically to work with a single app, they're usually placed in
48−a subdirectory of gen and run with `|`. Thus, if `my-generator`
49−generator is made for use with `:my-app`, then `my-generator` is
50−put in `/gen/my-app/my-generator.hoon`, and can be run directly
51−with `+my-app/my-generator <args>`. If you want to pipe the
52−result into `:my-app`, then run `:my-app +my-app/my-generator
53−<args>`. Because this pattern is so common, this can be
54−abbreviated to `:my-app|my-generator <args>`. Because most
55−built-in commands are generators for the `:hood` app,
56−`:hood|generator <args>` can be shortened to `|generator <args>`.
29+Another generator is `+hood/merge`. Try running `+hood/merge` with the
30+normal arguments for `|merge`:
31+
32+ ~fintud-macrep:dojo> +hood/merge %home our %they
33+ [syd=%home her=~fintud-macrep sud=%they gem=%auto]
34+ ~fintud-macrep:dojo> +hood/merge %home our %they, =gem %this
35+ [syd=%home her=~fintud-macrep sud=%they gem=%auto]
36+
37+This didn't run any merge, it just constructed the command that, if sent
38+to `:hood`, would run it. Note first that, even though it's not printed,
39+this value has mark `kiln-merge`. Also, the merge strategy `gem=%auto`
40+was added automatically. Optional arguments are straightforward with
41+generators.
42+
43+In general, generators are prepended by either `+` or `|`. The general
44+form is `+generator`, but often generators are created specifically to
45+work with a single app, they're usually placed in a subdirectory of gen
46+and run with `|`. Thus, if `my-generator` generator is made for use with
47+`:my-app`, then `my-generator` is put in
48+`/gen/my-app/my-generator.hoon`, and can be run directly with
49+`+my-app/my-generator <args>`. If you want to pipe the result into
50+`:my-app`, then run `:my-app +my-app/my-generator <args>`. Because this
51+pattern is so common, this can be abbreviated to
52+`:my-app|my-generator <args>`. Because most built-in commands are
53+generators for the `:hood` app, `:hood|generator <args>` can be
54+shortened to `|generator <args>`.
5755
5856Let's write a generator for a modified version of `:examples-pong` from
59−the chapter on [Network Messages](/docs/programming/system/network). Recall that `:examples-pong`
60−takes an urbit address, which is of mark `urbit`, and sends that
61−urbit the message `'howdy'`. First--without a generator--let's
62−make `:examples-ping` that does the same, except that it lets the user
63−optionally specify the message as well.
57+the chapter on [Network Messages](/docs/arvo/system/network). Recall
58+that `:examples-pong` takes an urbit address, which is of mark `urbit`,
59+and sends that urbit the message `'howdy'`. First--without a
60+generator--let's make `:examples-ping` that does the same, except that
61+it lets the user optionally specify the message as well.
6462
65−We'll need a new mark for our arguments. Let's call it
63+We'll need a new mark for our arguments. Let's call it
6664`examples-ping-message`.
6765
68−> For app-specific marks, it's good style to prefix the name of
69−> the mark with the name of the app. Since many apps have
70−> several such marks, subdirectories in `/mar` are rendered as
71−> `-`, so that `ping-message` is written in
72−> (/mar/examples/ping/message.hoon).
73−
74−```
75−::
76−:::: /hoon/message/ping/examples/app
77− ::
78−/? 314
79−|_ {to/@p message/@t}
80−++ grab
81− |%
82− ++ noun {@p @t}
83− --
84−--
85−```
66+> For app-specific marks, it's good style to prefix the name of the mark
67+> with the name of the app. Since many apps have several such marks,
68+> subdirectories in `/mar` are rendered as `-`, so that `ping-message`
69+> is written in (/mar/examples/ping/message.hoon).
70+
71+ ::
72+ :::: /hoon/message/ping/examples/app
73+ ::
74+ /? 314
75+ |_ {to/@p message/@t}
76+ ++ grab
77+ |%
78+ ++ noun {@p @t}
79+ --
80+ --
8681
8782The app can easily be modified to use this (`/app/examples/ping.hoon`):
8883
89−```
90−:: Allows one ship to ping another with a string of text
91−::
92−:::: /hoon/ping/examples/app
93− ::
94−/? 314
95−|%
96− ++ move {bone term wire *}
97−--
98−!:
99−|_ {bowl state/$~}
100−::
101−++ poke-examples-ping-message
102− |= {to/@p message/@t}
103− ~& 'sent'
104− ^- {(list move) _+>.$}
105− :- ^- (list move)
106− :~ `move`[ost %poke /sending [to dap] %atom message]
107− ==
108− +>.$
109−::
110−++ poke-atom
111− |= arg/@
112− ~& 'received'
113− ^- {(list move) _+>.$}
114− ::
115− ~& [%receiving (@t arg)]
116− [~ +>.$]
117−::
118−++ coup |=(* `+>)
119−--
120−```
84+ :: Allows one ship to ping another with a string of text
85+ ::
86+ :::: /hoon/ping/examples/app
87+ ::
88+ /? 314
89+ |%
90+ ++ move {bone term wire *}
91+ --
92+ !:
93+ |_ {bowl state/$~}
94+ ::
95+ ++ poke-examples-ping-message
96+ |= {to/@p message/@t}
97+ ~& 'sent'
98+ ^- {(list move) _+>.$}
99+ :- ^- (list move)
100+ :~ `move`[ost %poke /sending [to dap] %atom message]
101+ ==
102+ +>.$
103+ ::
104+ ++ poke-atom
105+ |= arg/@
106+ ~& 'received'
107+ ^- {(list move) _+>.$}
108+ ::
109+ ~& [%receiving (@t arg)]
110+ [~ +>.$]
111+ ::
112+ ++ coup |=(* `+>)
113+ --
121114
122115Now we can run this with:
123116
124−```
125−~fintud-macrep:dojo> |start %examples-ping
126−>=
127−~fintud-macrep:dojo> :examples-ping &examples-ping-message [~sampel-sipnym 'heyya']
128−>=
129−```
117+ ~fintud-macrep:dojo> |start %examples-ping
118+ >=
119+ ~fintud-macrep:dojo> :examples-ping &examples-ping-message [~sampel-sipnym 'heyya']
120+ >=
130121
131122And on `~sampel-sipnym`, assuming it's running `:examples-ping` as well,
132123we see `[%receiving 'heyya']`.
133124
134−This is an annoying way to invoke the app, though. The `[]` are
135−mandatory, and optional arguments are hard. Let's make a
136−generator, `+examples-send` to make everything nicer. Since it's specific
137−to `:examples-ping`, let's put it in `/gen/examples/ping/send.hoon`:
138−
139−```
140−:- %say
141−|= {^ {to/@p message/?($~ {text/@t $~})} $~}
142−[%examples-ping-message to ?~(message 'howdy' text.message)]
143−```
144−
145−A couple of new things here. Firstly, `message/?($~ {text/@t $~})`
146−should be read as "the message is either null or a pair of text
147−and null". Generator argument lists are always null-terminated,
148−which makes it convenient to accept lists in tail position (which
149−are particularly annoying without generators). `?(a b)` is the
150−irregular form of `$?(a b)`, which is a union type. Thus, `?(a
151−b)` means the type of anything that's in either `a` or `b`.
152−Thus, in our case, `?(~ [text=@t ~])` is either null or a pair of
153−text and null.
154−
155−Secondly, `?~(a b c)` is a rune which means "if the `a` is null,
156−do `b`, else `c`". It is roughly equivalent to `?:(=(~ a) b c)`.
157−
158−> `?~(a b c)` is actually equivalent to `?:=(?=(~ a) b c)`,
159−> which, although identical at run time, is subtly different at
160−> compile time. Specifically, using `?=` rather than `=` means
161−> that we're checking whether `a` is in the *type* of `~`, and so
162−> the compiler knows that in the `b` case `a` is null, and in the
163−> `c` case `a` is not null. Since `=` is purely a runtime value
164−> check with no type implications, the compiler doesn't gain any
165−> information.
125+This is an annoying way to invoke the app, though. The `[]` are
126+mandatory, and optional arguments are hard. Let's make a generator,
127+`+examples-send` to make everything nicer. Since it's specific to
128+`:examples-ping`, let's put it in `/gen/examples/ping/send.hoon`:
129+
130+ :- %say
131+ |= {^ {to/@p message/?($~ {text/@t $~})} $~}
132+ [%examples-ping-message to ?~(message 'howdy' text.message)]
133+
134+A couple of new things here. Firstly, `message/?($~ {text/@t $~})`
135+should be read as "the message is either null or a pair of text and
136+null". Generator argument lists are always null-terminated, which makes
137+it convenient to accept lists in tail position (which are particularly
138+annoying without generators). `?(a b)` is the irregular form of
139+`$?(a b)`, which is a union type. Thus, `?(a b)` means the type of
140+anything that's in either `a` or `b`. Thus, in our case,
141+`?(~ [text=@t ~])` is either null or a pair of text and null.
142+
143+Secondly, `?~(a b c)` is a rune which means "if the `a` is null, do `b`,
144+else `c`". It is roughly equivalent to `?:(=(~ a) b c)`.
145+
146+> `?~(a b c)` is actually equivalent to `?:=(?=(~ a) b c)`, which,
147+> although identical at run time, is subtly different at compile time.
148+> Specifically, using `?=` rather than `=` means that we're checking
149+> whether `a` is in the *type* of `~`, and so the compiler knows that in
150+> the `b` case `a` is null, and in the `c` case `a` is not null. Since
151+> `=` is purely a runtime value check with no type implications, the
152+> compiler doesn't gain any information.
166153>
167−> At any rate, this is the reason why we can refer to
168−> `text.message` in the `c` clause. The compiler knows that
169−> `message` is not null, so it must have `text` within it. If
170−> you used `?:(=(~ message) 'howdy' text.message)` the compiler
171−> would complain that it doesn't know whether `message` has
172−> `text` within it.
154+> At any rate, this is the reason why we can refer to `text.message` in
155+> the `c` clause. The compiler knows that `message` is not null, so it
156+> must have `text` within it. If you used
157+> `?:(=(~ message) 'howdy' text.message)` the compiler would complain
158+> that it doesn't know whether `message` has `text` within it.
173159
174160This is run as follows:
175161
176−```
177−~fintud-macrep:dojo> :examples-ping|send ~sampel-sipnym
178−>=
179−~fintud-macrep:dojo> :examples-ping|send ~sampel-sipnym 'how do you do'
180−>=
181−```
162+ ~fintud-macrep:dojo> :examples-ping|send ~sampel-sipnym
163+ >=
164+ ~fintud-macrep:dojo> :examples-ping|send ~sampel-sipnym 'how do you do'
165+ >=
182166
183167Which causes `~sampel-sipnym` to print `[%receiving 'howdy']` and
184168`[%receiving 'how do you do']`.
185169
186170**Exercises**:
187171
188−- Create a generator for `:examples-sum` from [State](state) so that
189− you can run `:examples-sum|add 5` to add numbers to it.
172+- Create a generator for `:examples-sum` from
173+ [State](/docs/arvo/state) so that you can run `:examples-sum|add 5`
174+ to add numbers to it.
190175
191−- Create a generator for `:examples-click` from [Web Apps](web-apps) so
192− that you can run `:examplesclick|poke` to poke it.
176+- Create a generator for `:examples-click` from [Web
177+ Apps](/docs/arvo/web-apps) so that you can run
178+ `:examples-click|poke` to poke it.
docs/arvo/subscriptions.md+4−3
@@ -93,8 +93,8 @@ Cheat sheet:
9393 `?:($=(%type value) %tru %false)`. `$=`
9494 ([buctis](../../hoon/twig/buc-mold/tis-coat/)) tests whether value `q` is
9595 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-->
96+<!-- One thing to watch out for in hoon: if you do `?~`, it
97+ affects the type of the conditional value: XXexample -->
9898
9999- `:_` ([colcab](../../hoon/twig/col-cell/cab-scon/)) is inverted `:-`: it
100100 accepts `p` and `q`, and produces `[q p]`.
@@ -106,7 +106,8 @@ Cheat sheet:
106106- `$%` ([buccen](../../hoon/twig/buc-mold/cen-book/)) is a type
107107 constructor: it defines a new type, composed of `n` types that it is
108108 passed. For example `$% @ * ^ ==` is the type of either `@`,
109− `*`, or a cell `^`. <!--XX this is a union, right?-->
109+ `*`, or a cell `^`.
110+<!-- XX this is a union, right? -->
110111
111112- You may have noticed the separate `|%`
112113 ([barcen](../../hoon/twig/bar-core/cen-core/)) above the application core