on master help sign in
Merge pull request #334 from baudtack/master
0abf751David Kerschner
learn/arvo/arvo-internals/generators.udon+55−56
@@ -10,17 +10,17 @@
10Generators are the most straightforward way to write programs for Urbit. They
10Generators are the most straightforward way to write programs for Urbit. They
11are used for doing computations that do not require persistence: they take an
11are used for doing computations that do not require persistence: they take an
12input and produce an output, then disappear. Generators might make sense for
12input and produce an output, then disappear. Generators might make sense for
13−for listing directory contents, or running unit tests, or fetching the
13+listing directory contents, or running unit tests, or fetching the contents of a
14−contents of a URL.
14+URL.
15
15
16There are four kinds of generators: naked, `%say`, `%get`, and `%ask`.
16There are four kinds of generators: naked, `%say`, `%get`, and `%ask`.
17
17
18### Naked Generators
18### Naked Generators
19
19
20−A naked generator is simply a `gate`; that is, an is an anonymous function that
20+A naked generator is simply a `gate`; that is, it is an anonymous function that
21−takes a `sample` (argument) and produces a noun. All you need to do is to write a
21+takes a `sample` (argument) and produces a noun. All you need to do is write a
22−`gate` and put it into file in the `/gen` directory. Let's take a look at a very
22+`gate` and put it into a file in the `/gen` directory. Let's take a look at a
23−simple one:
23+very simple one:
24
24
25```
25```
26|= a=*
26|= a=*
@@ -59,7 +59,7 @@ as part of a `tape`, the `cord` is only a single character. So each atom in the
59is terminated with.
59is terminated with.
60
60
61We can tell the Dojo to cast -- apply a specific type to -- the output of our
61We can tell the Dojo to cast -- apply a specific type to -- the output of our
62−generator see something more familiar:
62+generator to see something more familiar:
63
63
64```
64```
65> _tape +echo "asdf"
65> _tape +echo "asdf"
@@ -95,11 +95,11 @@ useful when a generator is needed to pipe data to another program, a frequent
95occurrence.
95occurrence.
96
96
97To that end, `%say` generators use `mark`s to make it clear, to other Arvo
97To that end, `%say` generators use `mark`s to make it clear, to other Arvo
98−computations, what exactly their kind of data their output is. A `mark` is akin
98+computations, exactly what kind of data their output is. A `mark` is akin
99to a MIME type on the Arvo level. A `mark` describes the data in
99to a MIME type on the Arvo level. A `mark` describes the data in
100some way, indicating that it's an `%atom`, or that it's a standard such as
100some way, indicating that it's an `%atom`, or that it's a standard such as
101`%json`, or even that it's an application-specific data structure like
101`%json`, or even that it's an application-specific data structure like
102−`%talk-command`. `mark`s are not specific to `%say` generators; any time data
102+`%talk-command`. `mark`s are not specific to `%say` generators; whenever data
103moves between programs in Arvo, that data is marked.
103moves between programs in Arvo, that data is marked.
104
104
105So, more formally, a `%say` generator is a `cell`. The head of that cell is the
105So, more formally, a `%say` generator is a `cell`. The head of that cell is the
@@ -146,9 +146,9 @@ the `|= *` expression on the line that follows.
146
146
147`|= *` constructs a gate that takes a noun. This gate will itself produce a
147`|= *` constructs a gate that takes a noun. This gate will itself produce a
148`cask`, which is cell formed by the prepending `:-`. The head of that `cask` is
148`cask`, which is cell formed by the prepending `:-`. The head of that `cask` is
149−`%noun` and the tail is rest of the program, `(add 40 2)`. The tail of the
149+`%noun` and the tail is the rest of the program, `(add 40 2)`. The tail of the
150−`cask` will be our actual data produced by body of the program: in this case
150+`cask` will be our actual data produced by the body of the program: in this
151−just adding 40 and 2 together.
151+case, just adding 40 and 2 together.
152
152
153#### `%say` generators with arguments
153#### `%say` generators with arguments
154
154
@@ -163,7 +163,7 @@ in the gate's sample, which we only specified as `*` in the previous few
163examples. But we can do more with `%say` generators if we do more with that
163examples. But we can do more with `%say` generators if we do more with that
164sample. Any valid sample will follow this 3-tuple scheme:
164sample. Any valid sample will follow this 3-tuple scheme:
165
165
166−`[[datetime, entropy, beak] [list of unnamed arguments] [list of named arguments]]`
166+`[[now, eny, beak] [list of unnamed arguments] [list of named arguments]]`
167
167
168This entire structure is a noun, which is why `*` is a valid sample if we
168This entire structure is a noun, which is why `*` is a valid sample if we
169wish to not use any of the information here in a generator. But let's look at
169wish to not use any of the information here in a generator. But let's look at
@@ -177,8 +177,8 @@ atoms:
177`beak` contains the current ship, desk, and case.
177`beak` contains the current ship, desk, and case.
178
178
179You can access each of those pieces of data by typing their names into the Dojo.
179You can access each of those pieces of data by typing their names into the Dojo.
180−But in a generator, we need put faces (variable names) onto that data so we can
180+But in a generator, we need to put faces (variable names) onto that data so we
181−easily use it in the program. We can do that like below:
181+can easily use it in the program. We can do so like this:
182
182
183```
183```
184|= [[now=@da eny=@uvJ bec=beak] ~ ~]
184|= [[now=@da eny=@uvJ bec=beak] ~ ~]
@@ -189,18 +189,18 @@ Any of those pieces of data could be omitted by replacing part of the noun with
189didn't want `eny`, or `[* * bec=beak]` if we only wanted `beak`.
189didn't want `eny`, or `[* * bec=beak]` if we only wanted `beak`.
190
190
191The *second part* of the sample is a `list` of arguments that _must_ be passed
191The *second part* of the sample is a `list` of arguments that _must_ be passed
192−to the generator as it's run. Because it's a `list`, this element needs to be
192+to the generator as it is run. Because it's a `list`, this element needs to be
193terminated with a `~`. In the example above, we used `~`, the empty list, to
193terminated with a `~`. In the example above, we used `~`, the empty list, to
194represent this second part. But that would mean we don't want to use any new
194represent this second part. But that would mean we don't want to use any new
195faces for our generator. So a sample where we want to declare a single required
195faces for our generator. So a sample where we want to declare a single required
196−argument would look like this.
196+argument would look like this:
197
197
198```
198```
199|= [* [n=@ud ~] ~]
199|= [* [n=@ud ~] ~]
200```
200```
201
201
202In the above code, we use a `*` to ignore any of the information that would go
202In the above code, we use a `*` to ignore any of the information that would go
203−first part of the sample, kind of in the same way that we use a `~` to say
203+in the first part of the sample, somewhat similar to how we use a `~` to say
204"nothing here" for the second or third parts of the sample.
204"nothing here" for the second or third parts of the sample.
205
205
206But to use both parts together, our gate and sample would look like this:
206But to use both parts together, our gate and sample would look like this:
@@ -210,7 +210,7 @@ But to use both parts together, our gate and sample would look like this:
210```
210```
211
211
212The *third part* of the sample is a list of _optional_ arguments. These
212The *third part* of the sample is a list of _optional_ arguments. These
213−arguments may be passed to the program as its being run, but the program doesn't
213+arguments may be passed to the program as it's being run, but the program doesn't
214require them. The syntax for the third part is just like the syntax for the
214require them. The syntax for the third part is just like the syntax for the
215second part, besides its position:
215second part, besides its position:
216
216
@@ -229,15 +229,15 @@ file called `dice.hoon` in your `/gen` directory.
229```
229```
230
230
231This is a very simple dice program with an optional betting functionality.
231This is a very simple dice program with an optional betting functionality.
232−In the code, our sample specifies faces on all the all of the Arvo data, meaning
232+In the code, our sample specifies faces on all of the Arvo data, meaning that we
233−that we can can easily access them. We also require the argument `[n=@ud ~]`,
233+can easily access them. We also require the argument `[n=@ud ~]`, and allow the
234−and allow the _optional_ argument `[bet=@ud ~]`.
234+_optional_ argument `[bet=@ud ~]`.
235
235
236But there's something new: `(~(rad og eny) n)`. This code pulls the `rad` arm
236But there's something new: `(~(rad og eny) n)`. This code pulls the `rad` arm
237out of the `og` core with the subject of `eny`. Recall that `eny` is our entropy
237out of the `og` core with the subject of `eny`. Recall that `eny` is our entropy
238value, so this is used to seed the generator. The `rad` arm will give us a
238value, so this is used to seed the generator. The `rad` arm will give us a
239−pseudorandom number between 0 and `n`, and the `bet` that it's in a cell with
239+pseudorandom number between 0 and `n`. Then we form a cell with the result and
240−will just return the argument that we might choose to give it.
240+`bet`, the optional named argument specified previously.
241
241
242We can run this generator like so:
242We can run this generator like so:
243
243
@@ -294,7 +294,7 @@ We use the `%ask` generator when we want to create an interactive program
294that prompts for inputs as it runs, rather than expecting arguments to be passed
294that prompts for inputs as it runs, rather than expecting arguments to be passed
295in at the time of initiation.
295in at the time of initiation.
296
296
297−Code-wise, you need two things to create a useful `%ask` generator.
297+Code-wise, two things are needed to create a useful `%ask` generator.
298
298
299The first is *`sole-result`*, which lives in `/sur/sole.hoon`. It's a
299The first is *`sole-result`*, which lives in `/sur/sole.hoon`. It's a
300mold-builder that's required by any part of Arvo, such as the Dojo, that wants
300mold-builder that's required by any part of Arvo, such as the Dojo, that wants
@@ -305,7 +305,7 @@ molds and digests them into a type for the operating system. The simplest way to
305use `sole-result` is by calling the `produce` gate from `/lib/generators.hoon`.
305use `sole-result` is by calling the `produce` gate from `/lib/generators.hoon`.
306
306
307The second is *`prompt`*, a gate that lives in `lib/generators.hoon`. `prompt`
307The second is *`prompt`*, a gate that lives in `lib/generators.hoon`. `prompt`
308−allows you to get get information back from the user, which is essential to the
308+allows you to get information back from the user, which is essential to the
309typical desired operation of an `%ask` generator.
309typical desired operation of an `%ask` generator.
310
310
311Since this isn't easy to digest in the abstract, we'll use an example generator
311Since this isn't easy to digest in the abstract, we'll use an example generator
@@ -346,7 +346,7 @@ What is your favorite color?
346
346
347Something new happened. Instead of simply returning something, your Dojo's
347Something new happened. Instead of simply returning something, your Dojo's
348prompt changed from `~your-urbit:dojo>` to `~your-urbit:dojo: color:`, and
348prompt changed from `~your-urbit:dojo>` to `~your-urbit:dojo: color:`, and
349−expects additional input. Let's give it an input:
349+now expects additional input. Let's give it an input:
350
350
351```
351```
352: color: red
352: color: red
@@ -397,19 +397,18 @@ We use the `^-` rune to constrain the generator's output to such a
397A `cask` is a pair of a `mark` name and a noun. Recall that a `mark` can be
397A `cask` is a pair of a `mark` name and a noun. Recall that a `mark` can be
398thought of as an Arvo-level MIME type for data.
398thought of as an Arvo-level MIME type for data.
399
399
400−A `tang` is a `list` of `tank` and a `tank` is a structure for printing data
400+A `tang` is a `list` of `tank`, and a `tank` is a structure for printing data.
401−that there are three types of: `leaf`, `palm`, and `rose`. A `leaf` is for
401+There are three types of `tank`: `leaf`, `palm`, and `rose`. A `leaf` is for
402printing a single noun, a `rose` is for printing rows of data, and a `palm` is
402printing a single noun, a `rose` is for printing rows of data, and a `palm` is
403−printing backstep-indented lists.
403+for printing backstep-indented lists.
404
404
405```
405```
406%+ print leaf+"What is your favorite color?"
406%+ print leaf+"What is your favorite color?"
407%+ prompt [%& %prompt "color: "]
407%+ prompt [%& %prompt "color: "]
408−|= t=tape :: we will come to this later
408+|= t=tape
409%+ produce %tang
409%+ produce %tang
410```
410```
411
411
412−
413Because we imported `generators`, we can access its contained gates, three of
412Because we imported `generators`, we can access its contained gates, three of
414which we use in `axe.hoon`: `print`, `prompt`, and `produce`.
413which we use in `axe.hoon`: `print`, `prompt`, and `produce`.
415
414
@@ -423,39 +422,38 @@ argument which is a `tank` to print. The `+` here is syntactic sugar for
423It takes a single argument that is a tuple. Most `%ask` generators will want to
422It takes a single argument that is a tuple. Most `%ask` generators will want to
424use the `prompt` gate.
423use the `prompt` gate.
425
424
426−The first element of the `prompt` sample is a flag that indicates what the
425+The first element of the `prompt` sample is a flag that indicates whether what
427−user typed should be echoed out to them or hidden. `%&` will produce echoed
426+the user typed should be echoed out to them or hidden. `%&` will produce echoed
428output and `%|` will hide the output (for use in passwords or other secret
427output and `%|` will hide the output (for use in passwords or other secret
429text).
428text).
430
429
431−The second element of the `prompt` sample is a `%term` used The second argument
430+The second element of the `prompt` sample is intended to be information for use
432−is intended to be information to use to create autocomplete options for the
431+in creating autocomplete options for the prompt. This functionality is not yet
433−prompt this is not yet implemented.
432+implemented.
434
433
435The third element of the `prompt` sample is the `tape` that we would like to
434The third element of the `prompt` sample is the `tape` that we would like to
436use to prompt the user. In the case of our example, we use `"color: "`.
435use to prompt the user. In the case of our example, we use `"color: "`.
437
436
438−*`produce`* is is used to construct the output of the generator. In our
437+*`produce`* is used to construct the output of the generator. In our example,
439−example, we produce a `tang`.
438+we produce a `tang`.
440
439
441
440
442```
441```
443|= t=tape
442|= t=tape
444```
443```
445
444
446−Our gate here takes a `tape` that was produced by `prompt` if we needed another
445+Our gate here takes a `tape` that was produced by `prompt`. If we needed
447−type of data we could use `parse` to obtain it.
446+another type of data we could use `parse` to obtain it.
448
447
449The rest of this generator should be intelligible to those with Hoon knowledge
448The rest of this generator should be intelligible to those with Hoon knowledge
450at this point.
449at this point.
451
450
452One quirk that you should be aware of, though, is that `tang` prints in reverse
451One quirk that you should be aware of, though, is that `tang` prints in reverse
453order from how it is created. The reason for this is that `tang` was originally
452order from how it is created. The reason for this is that `tang` was originally
454−created to display stack trace information, which should be produced in
453+created to display stack trace information, which should be produced in reverse
455−in reverse order. This leads to an annoyance: we either have to specify our
454+order. This leads to an annoyance: we either have to specify our messages
456−messages backwards or construct them in the order we want and then `flop` the
455+backwards or construct them in the order we want and then `flop` the `list`.
457−`list` This is a [known issue](https://github.com/urbit/arvo/issues/840) to be
456+This is a [known issue](https://github.com/urbit/arvo/issues/840) to be resolved.
458−resolved.
459
457
460### `%get` generators
458### `%get` generators
461
459
@@ -484,8 +482,8 @@ u.my-json
484```
482```
485
483
486The above generator was written with the
484The above generator was written with the
487−[Studio Ghibli API](https://ghibliapi.herokuapp.com/). The generator below was
485+[Studio Ghibli API](https://ghibliapi.herokuapp.com/). It uses this API to
488−designed to use the this API to print the title of a Studio Ghibli film.
486+print the title of a Studio Ghibli film.
489
487
490```
488```
491/- sole
489/- sole
@@ -494,7 +492,7 @@ designed to use the this API to print the title of a Studio Ghibli film.
494```
492```
495
493
496Here we import types from `/sur/sole.hoon` and gates from
494Here we import types from `/sur/sole.hoon` and gates from
497−`/lib/generators.hoon`. We also use `=,` to exposes the namespace of
495+`/lib/generators.hoon`. We also use `=,` to expose the namespace of
498`generators` that we just imported.
496`generators` that we just imported.
499
497
500```
498```
@@ -502,9 +500,9 @@ Here we import types from `/sur/sole.hoon` and gates from
502|= [* [url=tape ~] ~]
500|= [* [url=tape ~] ~]
503```
501```
504
502
505−Like with `%say` and `%ask` generators, we must have include the "boilerplate":
503+Like with `%say` and `%ask` generators, we must include the "boilerplate":
506−code that produces a generator-specific `cell`. At the head of that cell is
504+code that produces a generator-specific `cell`. The head of that cell is `%get`,
507−`%get`, and the tail is a gate that takes a `tape` of the URL that we are trying
505+and the tail is a gate that takes a `tape` of the URL that we are trying
508to access.
506to access.
509
507
510```
508```
@@ -550,8 +548,9 @@ for us that we can then use to inspect the data.
550```
548```
551
549
552After parsing the JSON structure we want to make sure we got back a valid `json`
550After parsing the JSON structure we want to make sure we got back a valid `json`
553−type. To do that, we test for null and crash that test passes. If not, we use
551+type. To do that, we test for null and crash if that test passes. If it doesn't
554−`=,` on the `dejs:format` core so that we can more easily pull arms out of it.
552+pass, we use `=,` on the `dejs:format` core so that we can more easily pull arms
553+out of it.
555
554
556```
555```
557%+ produce %json
556%+ produce %json
@@ -600,5 +599,5 @@ the arguments of that function come first. It's used here to keep with the
600principle that heaviest, or most complex, expressions should go to the bottom.
599principle that heaviest, or most complex, expressions should go to the bottom.
601
600
602The key we are looking up in our new `map` we've created from `my-json` is
601The key we are looking up in our new `map` we've created from `my-json` is
603−`%title` which is an element in the original source to print out to produce as
602+`%title`, which is an element in the original source, to produce the final
604−the final result of the generator.
603+result of the generator.