on master help sign in
Merge pull request #1211 from tinnus-napbus/update-hoon-school-wrt-dist
d15e4d1tinnus-napbus
content/docs/hoon/hoon-school/caesar.md+25−25
@@ -27,7 +27,7 @@ information. Implementing it in a program is just a fun exercise.
27Below is a generator that performs a Caesar cipher on a tape. This example
27Below is a generator that performs a Caesar cipher on a tape. This example
28isn't the most compact implementation of such a cipher in Hoon, but it
28isn't the most compact implementation of such a cipher in Hoon, but it
29demonstrates important principles that more laconic code would not. Save it as
29demonstrates important principles that more laconic code would not. Save it as
30−`caesar.hoon` in your `/gen` directory.
30+`caesar.hoon` in the `/gen` directory of your `%base` desk.
31
31
32```hoon
32```hoon
33!:
33!:
@@ -131,7 +131,7 @@ itself before reading the explanation.
131The `!:` in the first line of the above code enables a full stack trace in the
131The `!:` in the first line of the above code enables a full stack trace in the
132event of an error.
132event of an error.
133
133
134−`|= [msg=tape steps=@ud]` creates a [gate](/docs/glossary/gate/) that takes a cell. The head of this cell
134+`|= [msg=tape steps=@ud]` creates a [gate](/docs/glossary/gate/) that takes a cell. The head of this cell
135is a `tape`, which is a string type that's a list of `cord`s. Tapes are represented
135is a `tape`, which is a string type that's a list of `cord`s. Tapes are represented
136as text surrounded by double-quotes, such as this: `"a tape"`. We give this input
136as text surrounded by double-quotes, such as this: `"a tape"`. We give this input
137tape the face `msg`. The tail of our cell is a `@ud` -- an unsigned decimal [atom](/docs/glossary/atom/)
137tape the face `msg`. The tail of our cell is a `@ud` -- an unsigned decimal [atom](/docs/glossary/atom/)
@@ -141,7 +141,7 @@ tape the face `msg`. The tail of our cell is a `@ud` -- an unsigned decimal [ato
141second child expression as the subject. In this case, we evaluate the
141second child expression as the subject. In this case, we evaluate the
142expressions in the code chunk below against the [core](/docs/glossary/core/) declared later, which
142expressions in the code chunk below against the [core](/docs/glossary/core/) declared later, which
143allows us reference the core's contained [arms](/docs/glossary/arm/) before they are defined. Without
143allows us reference the core's contained [arms](/docs/glossary/arm/) before they are defined. Without
144−`=<`, we would need to put the code chunk below at the bottom of our program. In Hoon, as previously
144+`=<`, we would need to put the code chunk below at the bottom of our program. In Hoon, as previously
145stated, we always want to keep the longer code towards the bottom of our programs - `=<` helps us do that.
145stated, we always want to keep the longer code towards the bottom of our programs - `=<` helps us do that.
146
146
147```hoon
147```hoon
@@ -150,19 +150,19 @@ stated, we always want to keep the longer code towards the bottom of our program
150(unshift msg steps)
150(unshift msg steps)
151```
151```
152
152
153−`=. msg (cass msg)` changes the input string `msg` to lowercases. `=.` changes
153+`=. msg (cass msg)` changes the input string `msg` to lowercases. `=.` changes
154the leg of the subject to something else. In our case, the leg to be changed is
154the leg of the subject to something else. In our case, the leg to be changed is
155`msg`, and the thing to replace it is `(cass msg)`. `cass` is a standard-library
155`msg`, and the thing to replace it is `(cass msg)`. `cass` is a standard-library
156gate that converts uppercase letters to lowercase.
156gate that converts uppercase letters to lowercase.
157
157
158−`:- (shift msg steps)` and `(unshift msg steps)` simply composes a
158+`:- (shift msg steps)` and `(unshift msg steps)` simply composes a
159cell of a right-shifted cipher and a left-shifted cipher of our original message.
159cell of a right-shifted cipher and a left-shifted cipher of our original message.
160We will see how this is done using the core described below, but this is the final
160We will see how this is done using the core described below, but this is the final
161output of our generator.
161output of our generator.
162
162
163`|%` creates a `core`, the second child of `=<`. Everything after `|%` is part of that
163`|%` creates a `core`, the second child of `=<`. Everything after `|%` is part of that
164second child `core`, and will be used as the subject of the first child of `=<`, described
164second child `core`, and will be used as the subject of the first child of `=<`, described
165−above. The various parts, or `arm`s, of the `core` are denoted by `++` beneath it, for
165+above. The various parts, or `arm`s, of the `core` are denoted by `++` beneath it, for
166instance:
166instance:
167
167
168```hoon
168```hoon
@@ -174,21 +174,21 @@ instance:
174```
174```
175
175
176The `rotation` arm takes takes a specified number of characters off of a tape and
176The `rotation` arm takes takes a specified number of characters off of a tape and
177−puts them on the end of the tape. We're going to use this to create our shifted alphabet,
177+puts them on the end of the tape. We're going to use this to create our shifted alphabet,
178based on the number of `steps` given as an argument to our gate.
178based on the number of `steps` given as an argument to our gate.
179
179
180−`|= [my-alphabet=tape my-steps=@ud]` creates a gate that takes two arguments: `my-alphabet`, a `tape`,
180+`|= [my-alphabet=tape my-steps=@ud]` creates a gate that takes two arguments: `my-alphabet`, a `tape`,
181and `my-steps`, a `@ud`.
181and `my-steps`, a `@ud`.
182
182
183−`=/ length=@ud (lent my-alphabet)` stores the length of `my-alphabet` to make the following
183+`=/ length=@ud (lent my-alphabet)` stores the length of `my-alphabet` to make the following
184code a little clearer.
184code a little clearer.
185
185
186`trim` is a a gate from the standard library that splits a tape at into two
186`trim` is a a gate from the standard library that splits a tape at into two
187−parts at a specified position. So `=+ (trim (mod my-steps length) my-alphabet)` splits the
187+parts at a specified position. So `=+ (trim (mod my-steps length) my-alphabet)` splits the
188tape `my-alphabet` into two parts, `p` and `q`, which are now directly available in the subject.
188tape `my-alphabet` into two parts, `p` and `q`, which are now directly available in the subject.
189We call the modulus operation `mod` to make sure that the point at which we split our `tape` is
189We call the modulus operation `mod` to make sure that the point at which we split our `tape` is
190a valid point inside of `my-alphabet` even if `my-steps` is greater than `length`, the length of
190a valid point inside of `my-alphabet` even if `my-steps` is greater than `length`, the length of
191−`my-alphabet`. Try trim in the dojo:
191+`my-alphabet`. Try trim in the dojo:
192
192
193```
193```
194> (trim 2 "abcdefg")
194> (trim 2 "abcdefg")
@@ -221,42 +221,42 @@ A `map` is a type equivalent to a dictionary in other languages: it's a data str
221associates a key with a value. If, for example, we wanted to have an association
221associates a key with a value. If, for example, we wanted to have an association
222between `a` and 1 and `b` and 2, we could use a `map`.
222between `a` and 1 and `b` and 2, we could use a `map`.
223
223
224−`|= [a=tape b=tape]` builds a gate that takes two tapes, `a` and `b`, as its
224+`|= [a=tape b=tape]` builds a gate that takes two tapes, `a` and `b`, as its
225sample.
225sample.
226
226
227−`^- (map @t @t)` casts the gate to a `map` with a `cord` (or `@t`) key and a `cord`
227+`^- (map @t @t)` casts the gate to a `map` with a `cord` (or `@t`) key and a `cord`
228value.
228value.
229
229
230You might wonder, if our gate in this arm takes `tape`s, why then are we producing
230You might wonder, if our gate in this arm takes `tape`s, why then are we producing
231a map of `cord` keys and values?
231a map of `cord` keys and values?
232
232
233−As we discussed earlier, a `tape` is a list of `cord`s. In this case what we are going to do
233+As we discussed earlier, a `tape` is a list of `cord`s. In this case what we are going to do
234is map a single element of a `tape` (either our alphabet or shifted-alphabet) to an element of
234is map a single element of a `tape` (either our alphabet or shifted-alphabet) to an element of
235−a different `tape` (either our shifted-alphabet or our alphabet). This pair will therefore be
235+a different `tape` (either our shifted-alphabet or our alphabet). This pair will therefore be
236−a pair of `cord`s. When we go to use this `map` to convert our incoming `msg`, we will take
236+a pair of `cord`s. When we go to use this `map` to convert our incoming `msg`, we will take
237each element (`cord`) of our `msg` `tape`, use it as a `key` when accessing our `map` and get
237each element (`cord`) of our `msg` `tape`, use it as a `key` when accessing our `map` and get
238the corresponding `value` from that position in the `map`. This is how we're going to encode
238the corresponding `value` from that position in the `map`. This is how we're going to encode
239or decode our `msg` `tape`.
239or decode our `msg` `tape`.
240
240
241−`=| chart=(map @t @t)` adds a [noun](/docs/glossary/noun/) to the subject with the default value of
241+`=| chart=(map @t @t)` adds a [noun](/docs/glossary/noun/) to the subject with the default value of
242the `(map @t @t)` type, and gives that noun the face `chart`.
242the `(map @t @t)` type, and gives that noun the face `chart`.
243
243
244−`?. =((lent key-position) (lent value-result))` checks if the two `tape`s are the same length. If not,
244+`?. =((lent key-position) (lent value-result))` checks if the two `tape`s are the same length. If not,
245−the program crashes with an error message of `%uneven-lengths`, using `|~ %uneven-lengths !!`.
245+the program crashes with an error message of `%uneven-lengths`, using `|~ %uneven-lengths !!`.
246
246
247If the two `tape`s are of the same length, we continue on to create a trap.
247If the two `tape`s are of the same length, we continue on to create a trap.
248`|-` creates a [trap](/docs/glossary/trap/), a gate that is called immediately.
248`|-` creates a [trap](/docs/glossary/trap/), a gate that is called immediately.
249
249
250−`?: |(?=(~ key-position) ?=(~ value-result))` checks if either `tape` is empty. If this is true, the
250+`?: |(?=(~ key-position) ?=(~ value-result))` checks if either `tape` is empty. If this is true, the
251`map-maker` arm is finished and can return `chart`, the `map` that we have been
251`map-maker` arm is finished and can return `chart`, the `map` that we have been
252creating.
252creating.
253
253
254If the above test finds that the `tape`s are not empty, we trigger a recursion
254If the above test finds that the `tape`s are not empty, we trigger a recursion
255that constructs our `map`: `$(chart (~(put by chart) i.a i.b), a t.a, b t.b)`.
255that constructs our `map`: `$(chart (~(put by chart) i.a i.b), a t.a, b t.b)`.
256This code recursively adds an entry in our `map` where the head of the `tape` `a`
256This code recursively adds an entry in our `map` where the head of the `tape` `a`
257−maps to the value of the head of `tape` `b` with `~(put by chart)`, our calling
257+maps to the value of the head of `tape` `b` with `~(put by chart)`, our calling
258of the `put` arm of the `by` map-engine core (note that `~(<wing> <door> <sample>`) is
258of the `put` arm of the `by` map-engine core (note that `~(<wing> <door> <sample>`) is
259−a shorthand for `%~ <wing> <door> <sample>` (see the [Calls % ('cen')](/docs/hoon/reference/rune/cen#censig)
259+a shorthand for `%~ <wing> <door> <sample>` (see the [Calls % ('cen')](/docs/hoon/reference/rune/cen#censig)
260documentation for more information). The recursion also "consumes"
260documentation for more information). The recursion also "consumes"
261those heads with every iteration by changing `a` and `b` to their tails using `a t.a, b t.b`.
261those heads with every iteration by changing `a` and `b` to their tails using `a t.a, b t.b`.
262
262
@@ -271,7 +271,7 @@ first.
271 (~(put by (map-maker key-position value-result)) ' ' ' ')
271 (~(put by (map-maker key-position value-result)) ' ' ' ')
272```
272```
273
273
274−`|= [key-position=tape value-result=tape]` creates a gate that takes two `tapes`.
274+`|= [key-position=tape value-result=tape]` creates a gate that takes two `tapes`.
275
275
276We use the `put` arm of the `by` core on the next line, giving it a `map` produced
276We use the `put` arm of the `by` core on the next line, giving it a `map` produced
277by the `map-maker` arm that we created before as its sample. This adds an entry to the
277by the `map-maker` arm that we created before as its sample. This adds an entry to the
@@ -300,12 +300,12 @@ that we can use to encode and decode messages.
300In both cases, we create a gate that accepts a `@ud` named `steps`.
300In both cases, we create a gate that accepts a `@ud` named `steps`.
301
301
302In `encoder`:
302In `encoder`:
303−`=/ value-tape=tape (rotation alpha steps)` creates a `value-tape` noun by calling `rotation`
303+`=/ value-tape=tape (rotation alpha steps)` creates a `value-tape` noun by calling `rotation`
304on `alpha`. `alpha` is our arm which contains a `tape` of the entire alphabet. The
304on `alpha`. `alpha` is our arm which contains a `tape` of the entire alphabet. The
305`value-tape` will be the list of `value`s in our `map`.
305`value-tape` will be the list of `value`s in our `map`.
306
306
307In `decoder`:
307In `decoder`:
308−`=/ key-tape (rotation alpha steps)` does the same work, but when passed to `space-adder`
308+`=/ key-tape (rotation alpha steps)` does the same work, but when passed to `space-adder`
309it will be the list of `key`s in our `map`.
309it will be the list of `key`s in our `map`.
310
310
311`(space-adder alpha value-tape)`, for `encoder`, and `(space-adder key-tape alpha)`, for
311`(space-adder alpha value-tape)`, for `encoder`, and `(space-adder key-tape alpha)`, for
content/docs/hoon/hoon-school/egg-timer.md+33−28
@@ -5,10 +5,10 @@ template = "doc.html"
5aliases = ["/docs/learn/hoon/hoon-tutorial/egg-timer/"]
5aliases = ["/docs/learn/hoon/hoon-tutorial/egg-timer/"]
6+++
6+++
7
7
8−The Arvo operating system is divided up into modules called vanes. Gall is the vane responsible for providing an API for building stateful applications in Urbit. Gall is a complex system that takes a lot of getting used to, so let's dip our toes in with a simple egg-timer app.
8+The Arvo operating system is divided up into modules called vanes. Gall is the vane responsible for providing an API for building stateful applications in Urbit. Gall is a complex system that takes a lot of getting used to, so let's dip our toes in with a simple egg-timer app.
9
9
10−The following code sample should be saved as `/home/app/egg-timer.hoon`
10+The following code sample should be saved as `/base/app/egg-timer.hoon`
11−After committing: `|start %egg-timer` and poke with `:egg-timer ~s10`
11+After committing: `|rein %base [& %egg-timer]` and poke with `:egg-timer ~s10`
12
12
13```hoon
13```hoon
14/+ default-agent
14/+ default-agent
@@ -46,7 +46,7 @@ After committing: `|start %egg-timer` and poke with `:egg-timer ~s10`
46--
46--
47```
47```
48
48
49−The first thing to notice is that we are creating a core (`|%`) and a door (`|_`). This is a typical style for Gall programming wherein types are defined in the first core and your application is defined in the following door.
49+The first thing to notice is that we are creating a core (`|%`) and a door (`|_`). This is a typical style for Gall programming wherein types are defined in the first core and your application is defined in the following door.
50Our door will have type `agent:gall` as specified in `sys/zuse.hoon`
50Our door will have type `agent:gall` as specified in `sys/zuse.hoon`
51
51
52```hoon
52```hoon
@@ -55,10 +55,10 @@ Our door will have type `agent:gall` as specified in `sys/zuse.hoon`
55--
55--
56```
56```
57
57
58−The core here defines only one type: `card`.
58+The core here defines only one type: `card`.
59−A `card` is a request to Arvo to do something for us. In this case, the only card used will be a `%wait` request to Behn which we'll discuss later.
59+A `card` is a request to Arvo to do something for us. In this case, the only card used will be a `%wait` request to Behn which we'll discuss later.
60
60
61−It's important to note that the name `card` is technically arbitrary. By convention, however, you will see it called `card` practically everywhere.
61+It's important to note that the name `card` is technically arbitrary. By convention, however, you will see it called `card` practically everywhere.
62
62
63The sample of the door(`|_`) is:
63The sample of the door(`|_`) is:
64
64
@@ -66,12 +66,12 @@ The sample of the door(`|_`) is:
66=bowl:gall
66=bowl:gall
67```
67```
68
68
69−You can find the full definition of `bowl` in `sys/zuse.hoon`, but for now it's enough to know that includes contextual data used by Gall with particular faces. Below are some important such faces:
69+You can find the full definition of `bowl` in `sys/zuse.hoon`, but for now it's enough to know that includes contextual data used by Gall with particular faces. Below are some important such faces:
70
70
71−- `our` The ship this code is running on
71+- `our` The ship this code is running on
72−- `src` The ship the current event originated from
72+- `src` The ship the current event originated from
73−- `eny` Guaranteed-fresh entropy
73+- `eny` Guaranteed-fresh entropy
74−- `now` The current time
74+- `now` The current time
75
75
76We give `bowl:gall` the face `bowl`.
76We give `bowl:gall` the face `bowl`.
77Additionally, we use `+*` to create two structures for future use:
77Additionally, we use `+*` to create two structures for future use:
@@ -80,10 +80,11 @@ Additionally, we use `+*` to create two structures for future use:
80+* this .
80+* this .
81 def ~(. (default-agent this %.n) bowl)
81 def ~(. (default-agent this %.n) bowl)
82```
82```
83+
83`this` is our current context(the door).
84`this` is our current context(the door).
84`def` uses `default-agent` to produce a standard `gall:agent` door, from which we will instance default definitions for our unused arms.
85`def` uses `default-agent` to produce a standard `gall:agent` door, from which we will instance default definitions for our unused arms.
85
86
86−All Gall agents have a fixed set of 10 arms. In this trivial case, we will specify only two and use the default definitions from `default-agent` for the remaining arms.
87+All Gall agents have a fixed set of 10 arms. In this trivial case, we will specify only two and use the default definitions from `default-agent` for the remaining arms.
87
88
88```hoon
89```hoon
89++ on-poke
90++ on-poke
@@ -94,33 +95,34 @@ All Gall agents have a fixed set of 10 arms. In this trivial case, we will spec
94 [%pass /egg-timer %arvo %b %wait (add now.bowl t)]~
95 [%pass /egg-timer %arvo %b %wait (add now.bowl t)]~
95```
96```
96
97
97−The `++on-poke` arm evaluates to a gate which takes a sample `[mark vase]`. `mark` is a type specification and `vase` is a cell of `[specification value]`
98+The `++on-poke` arm evaluates to a gate which takes a sample `[mark vase]`. `mark` is a type specification and `vase` is a cell of `[specification value]`
98Note: since `++on-poke` may take many different samples, it would be prudent to add a `%noun` mark check here.
99Note: since `++on-poke` may take many different samples, it would be prudent to add a `%noun` mark check here.
99−In this example, we assume that our sample will contain a `@dr` and pull it from the `vase` with `=/ t !<(@dr vase)`
100+In this example, we assume that our sample will contain a `@dr` and pull it from the `vase` with `=/ t !<(@dr vase)`
100`@dr` is an aura for a 128-bit relative date. Here are a few examples.
101`@dr` is an aura for a 128-bit relative date. Here are a few examples.
101
102
102−- `~s17` 17 seconds
103+- `~s17` 17 seconds
103−- `~m20` 20 minutes
104+- `~m20` 20 minutes
104- `~m13s37` 13 minutes, 37 seconds
105- `~m13s37` 13 minutes, 37 seconds
105−- `~d42` 42 days
106+- `~d42` 42 days
106
107
107As a matter of good type hygiene, we explicitly cast the output of this gate with `^-` to ensure we are producing the correct structure for Gall to handle.
108As a matter of good type hygiene, we explicitly cast the output of this gate with `^-` to ensure we are producing the correct structure for Gall to handle.
108−Our specification is `(quip card _this)` which produces a type, `[(list card) _this]`. Note that `_this` is irregular form of `$_(this)` which normalizes to the type of `this`, our door.
109+Our specification is `(quip card _this)` which produces a type, `[(list card) _this]`. Note that `_this` is irregular form of `$_(this)` which normalizes to the type of `this`, our door.
109
110
110−Next we use the `:_` rune which is the inverted form of `:-`, the cell construction rune.
111+Next we use the `:_` rune which is the inverted form of `:-`, the cell construction rune.
111
112
112```hoon
113```hoon
113:_ this
114:_ this
114 [%pass /egg-timer %arvo %b %wait (add now.bowl t)]~
115 [%pass /egg-timer %arvo %b %wait (add now.bowl t)]~
115```
116```
117+
116Our card should follow the basic form `[%pass /my/wire a-note]`
118Our card should follow the basic form `[%pass /my/wire a-note]`
117In this case, our card will ask Arvo to `%pass` a note along the wire `/egg-timer` to Behn(`%b`) containing a `%wait` request.
119In this case, our card will ask Arvo to `%pass` a note along the wire `/egg-timer` to Behn(`%b`) containing a `%wait` request.
118Behn will start a timer for us, and will respond along our wire, `/egg-timer`.
120Behn will start a timer for us, and will respond along our wire, `/egg-timer`.
119
121
120−`now.bowl` is the current time of type `@da`, and `t` was declared as `@dr`. Because they are both atoms, we can add `now` and `t` to produce an atom that is `t` units of time into the future from `now`. That produced atom can be interpreted as a `@da`.
122+`now.bowl` is the current time of type `@da`, and `t` was declared as `@dr`. Because they are both atoms, we can add `now` and `t` to produce an atom that is `t` units of time into the future from `now`. That produced atom can be interpreted as a `@da`.
121The calculated time will be passed via Arvo to Behn with instruction to `%wait @da`, i.e., to set a timer.
123The calculated time will be passed via Arvo to Behn with instruction to `%wait @da`, i.e., to set a timer.
122
124
123−That's all for our `++on-poke` arm. But what about when the timer goes off? Behn will create a `gift`, a similar construct to our `card` which will be dispatched back to us via Gall in the `++on-arvo` arm.
125+That's all for our `++on-poke` arm. But what about when the timer goes off? Behn will create a `gift`, a similar construct to our `card` which will be dispatched back to us via Gall in the `++on-arvo` arm.
124
126
125```hoon
127```hoon
126++ on-arvo
128++ on-arvo
@@ -130,20 +132,22 @@ That's all for our `++on-poke` arm. But what about when the timer goes off? Be
130 ~& "Timer went off!"
132 ~& "Timer went off!"
131 [~ this]
133 [~ this]
132```
134```
133−`++on-arvo` evaluates to a gate whose sample is a cell of `wire` and `sign-arvo` here given default faces. The syntax of `=wire` is a shortcut for `wire=wire`; it's a common pattern to shadow the name of a type when you only have one instance of the type and are not going to refer to the type itself.
134−A `wire` is an alias for a path. Our `wire` will be the path we provided in our `++on-poke` card. If we needed to do something particular depending on which request triggered this Arvo card, we could use the wire to do so.
135
135
136+`++on-arvo` evaluates to a gate whose sample is a cell of `wire` and `sign-arvo` here given default faces. The syntax of `=wire` is a shortcut for `wire=wire`; it's a common pattern to shadow the name of a type when you only have one instance of the type and are not going to refer to the type itself.
137+A `wire` is an alias for a path. Our `wire` will be the path we provided in our `++on-poke` card. If we needed to do something particular depending on which request triggered this Arvo card, we could use the wire to do so.
138+
136−Note: since multiple vanes can send many sorts of cards via `++on-arvo`, it would be prudent to check if `sign-arvo` is `[%b %wake *]`. Since our trivial example assumes the card is `%wake` from Behn, we will forgo that better practice here.
139+Note: since multiple vanes can send many sorts of cards via `++on-arvo`, it would be prudent to check if `sign-arvo` is `[%b %wake *]`. Since our trivial example assumes the card is `%wake` from Behn, we will forgo that better practice here.
140+
141+Next we have the same cast we used in `++on-poke` to make sure we produce the correct type for Gall. `(quip card _this)` resolves to a type `[(list card) _this]`
137
142
138−Next we have the same cast we used in `++on-poke` to make sure we produce the correct type for Gall. `(quip card _this)` resolves to a type `[(list card) _this]`
139```
143```
140~& "Timer went off!"
144~& "Timer went off!"
141```
145```
142
146
143−`~&` is the debugging printf rune. Here we're using it to output a message. We could, however, modify this line of code to do any other computation when `++on-arvo` is called.
147+`~&` is the debugging printf rune. Here we're using it to output a message. We could, however, modify this line of code to do any other computation when `++on-arvo` is called.
144
148
145We need to produce a noun of type `(quip card _this)` i.e., `[(list card) _this]`.
149We need to produce a noun of type `(quip card _this)` i.e., `[(list card) _this]`.
146−In this case, we will not produce any card or change application state. Therefore we simply produce a cell of a null list and our original context, `[~ this]`.
150+In this case, we will not produce any card or change application state. Therefore we simply produce a cell of a null list and our original context, `[~ this]`.
147
151
148```hoon
152```hoon
149++ on-init on-init:def
153++ on-init on-init:def
@@ -156,4 +160,5 @@ In this case, we will not produce any card or change application state. Therefo
156++ on-fail on-fail:def
160++ on-fail on-fail:def
157--
161--
158```
162```
163+
159Finally, we define the remaining 8 unused but required Gall Agent armsas instances of the default arms provided in `/lib/default-agent.hoon`.
164Finally, we define the remaining 8 unused but required Gall Agent armsas instances of the default arms provided in `/lib/default-agent.hoon`.
content/docs/hoon/hoon-school/generators.md+13−14
@@ -16,9 +16,8 @@ There are three kinds of generators: naked, `%say`, and `%ask`. There also used
16### Naked Generators
16### Naked Generators
17
17
18A naked generator is simply a `gate`; that is, it is an anonymous function that
18A naked generator is simply a `gate`; that is, it is an anonymous function that
19−takes a `sample` (argument) and produces a [noun](/docs/glossary/noun/). All you need to do is write a
19+takes a `sample` (argument) and produces a [noun](/docs/glossary/noun/). All you
20−`gate` and put it into a file in the `/gen` directory. Let's take a look at a
20+need to do is write a `gate` and put it into a file in the `/gen` directory of a desk on your ship. Let's take a look at a very simple one:
21−very simple one:
22
21
23```hoon
22```hoon
24|= a=*
23|= a=*
@@ -26,7 +25,8 @@ a
26```
25```
27
26
28This generator takes one argument of any noun and produces it without any
27This generator takes one argument of any noun and produces it without any
28+changes. Put this into a file named `echo.hoon` in the `/gen` directory of your
29−changes. Once you put this into a file named `echo.hoon` in the `/gen` directory, you must make your ship recognize the change by inputting `|commit %home` in the dojo. You can then run it from the dojo:
29+`%base` desk. You must make your ship recognize the change by inputting `|commit %base` in the dojo. You can then run it from the dojo:
30
30
31```
31```
32> +echo 42
32> +echo 42
@@ -64,7 +64,7 @@ generator to see something more familiar:
64```
64```
65
65
66Now let's create a generator with two arguments instead of one. Save the code
66Now let's create a generator with two arguments instead of one. Save the code
67−below as `add.hoon` in the `/gen` directory.
67+below as `add.hoon` in the `/gen` directory of your `%base` desk.
68
68
69```hoon
69```hoon
70|= [a=@ud b=@ud]
70|= [a=@ud b=@ud]
@@ -104,7 +104,7 @@ So, more formally, a `%say` generator is a `cell`. The head of that cell is the
104output data and the `mark` describing that data.
104output data and the `mark` describing that data.
105
105
106Below is an example of a `%say` generator. Save it to `add.hoon` in the `/gen`
106Below is an example of a `%say` generator. Save it to `add.hoon` in the `/gen`
107−directory.
107+directory of your `%base` desk.
108
108
109```hoon
109```hoon
110:- %say
110:- %say
@@ -133,7 +133,7 @@ Recall that the rune `:-` produces a cell, with the first following expression
133as its head and the second following expression as its tail.
133as its head and the second following expression as its tail.
134
134
135The expression above creates a cell with `%say` as the head. The tail is
135The expression above creates a cell with `%say` as the head. The tail is
136−the `|= *` expression on the line that follows.
136+the `|= *` expression on the line that follows.
137
137
138```hoon
138```hoon
139|= *
139|= *
@@ -141,10 +141,10 @@ the `|= *` expression on the line that follows.
141(add 40 2)
141(add 40 2)
142```
142```
143
143
144−`|= *` constructs a [gate](/docs/glossary/gate/) that takes a noun. This [gate](/docs/glossary/gate/) will itself produce a
144+`|= *` constructs a [gate](/docs/glossary/gate/) that takes a noun. This [gate](/docs/glossary/gate/) will itself produce a
145`cask`, which is cell formed by the prepending `:-`. The head of that `cask` is
145`cask`, which is cell formed by the prepending `:-`. The head of that `cask` is
146`%noun` and the tail is the rest of the program, `(add 40 2)`. The tail of the
146`%noun` and the tail is the rest of the program, `(add 40 2)`. The tail of the
147−`cask` will be our actual data produced by the body of the program: in this
147+`cask` will be our actual data produced by the body of the program: in this
148case, just adding 40 and 2 together.
148case, just adding 40 and 2 together.
149
149
150#### `%say` generators with arguments
150#### `%say` generators with arguments
@@ -216,7 +216,7 @@ second part, besides its position:
216```
216```
217
217
218Let's look at an example that uses all three parts. Save the code below in a
218Let's look at an example that uses all three parts. Save the code below in a
219−file called `dice.hoon` in your `/gen` directory.
219+file called `dice.hoon` in the `/gen` directory of your `%base` desk.
220
220
221```hoon
221```hoon
222:- %say
222:- %say
@@ -311,7 +311,7 @@ to explain how this kind of generator works.
311##### `%ask` example
311##### `%ask` example
312
312
313The code below is an `%ask` generator that checks if the user inputs "blue" when
313The code below is an `%ask` generator that checks if the user inputs "blue" when
314−prompted. Save it as `axe.hoon` in `/gen`.
314+prompted. Save it as `axe.hoon` in the `/gen` directory of your `%base` desk.
315
315
316```hoon
316```hoon
317/- sole
317/- sole
@@ -379,7 +379,7 @@ This code might be familiar. Just as with their `%say` cousins, `%ask`
379generators need to produce a `cell`, the head of which specifies what kind of
379generators need to produce a `cell`, the head of which specifies what kind of
380generator we are running.
380generator we are running.
381
381
382−With `|= *`, we create a gate and ignore the standard arguments we are given,
382+With `|= *`, we create a gate and ignore the standard arguments we are given,
383because we're not using them.
383because we're not using them.
384
384
385```hoon
385```hoon
@@ -434,7 +434,6 @@ use to prompt the user. In the case of our example, we use `"color: "`.
434**`produce`** is used to construct the output of the generator. In our example,
434**`produce`** is used to construct the output of the generator. In our example,
435we produce a `tang`.
435we produce a `tang`.
436
436
437−
438```hoon
437```hoon
439|= t=tape
438|= t=tape
440```
439```
@@ -458,4 +457,4 @@ This is a [known issue](https://github.com/urbit/arvo/issues/840) to be resolved
458
457
459## Conclusion
458## Conclusion
460
459
461−You've now reached the end of Chapter 1 of the Hoon tutorial. Ideally you should have a fair understanding of the fundamental concepts of subject-oriented programming: limbs, legs, faces, wings, arms, cores, gates, and [doors](/docs/glossary/door/). If you can master these concepts you should have little or no trouble learning to write substantial Hoon programs.
460+You've now reached the end of Chapter 1 of the Hoon tutorial. Ideally you should have a fair understanding of the fundamental concepts of subject-oriented programming: limbs, legs, faces, wings, arms, cores, gates, and [doors](/docs/glossary/door/). If you can master these concepts you should have little or no trouble learning to write substantial Hoon programs.
content/docs/hoon/hoon-school/list-of-numbers.md+3−3
@@ -20,7 +20,7 @@ Below is a simple Hoon program that takes a single number `n` from the user as i
20$(count (add 1 count)) :: 8
20$(count (add 1 count)) :: 8
21```
21```
22
22
23−As we mentioned in the previous lesson, the easiest way to use such a program is to run it as a _generator_. Mount your desk `|mount %` (if you didn't do it before), saving a file in the `/home/gen` directory of your ship and commiting these changes `|commit %home` allows you to run it from your ship's Dojo (command line) as a generator. Save the above code there as `list.hoon`. Now you can run it in the Dojo with the command below (remember, without the `>`):
23+As we mentioned in the previous lesson, the easiest way to use such a program is to run it as a _generator_. Mount your `%base` desk with `|mount %base` (if you didn't do it before), saving a file in the `base/gen` directory of your ship and commiting these changes `|commit %base` allows you to run it from your ship's Dojo (command line) as a generator. Save the above code there as `list.hoon`. Now you can run it in the Dojo with the command below (remember, without the `>`):
24
24
25`> +list 5`
25`> +list 5`
26
26
@@ -89,7 +89,7 @@ In this case, the rune specifies that our gate's output must be `(list @)` -- th
89
89
90`?:` is a rune that evaluates whether its first child is `true` or `false`. If that child is `true`, the program branches to the second child. If it's `false`, it branches to the third child. `?:` takes three children.
90`?:` is a rune that evaluates whether its first child is `true` or `false`. If that child is `true`, the program branches to the second child. If it's `false`, it branches to the third child. `?:` takes three children.
91
91
92−`=(end count)` checks if the user's input equals to the `count` value that we're incrementing to build the list. If these values are equal, we want to end the program, because our list has been built out to where it needs to be. Note that this expression is, in fact, a rune expression, just written a different way than you've seen so far. `=(end count)` is an _irregular form_ of `.= end count`, different in looks but identical in operation. `.=` is a rune that checks for the equality of its two children, and produces a `true` or `false` based on what it finds.
92+`=(end count)` checks if the user's input equals to the `count` value that we're incrementing to build the list. If these values are equal, we want to end the program, because our list has been built out to where it needs to be. Note that this expression is, in fact, a rune expression, just written a different way than you've seen so far. `=(end count)` is an _irregular form_ of `.= end count`, different in looks but identical in operation. `.=` is a rune that checks for the equality of its two children, and produces a `true` or `false` based on what it finds.
93
93
94`~` simply represents the `null` value. The program branches here if on line 5 it finds that `end` equals `count`. Lists in Hoon always end with `~`, so we need this to be the last thing we put in our list.
94`~` simply represents the `null` value. The program branches here if on line 5 it finds that `end` equals `count`. Lists in Hoon always end with `~`, so we need this to be the last thing we put in our list.
95
95
@@ -97,7 +97,7 @@ In this case, the rune specifies that our gate's output must be `(list @)` -- th
97
97
98`:-` is a rune that creates a **cell**, an ordered pair of two values, such as `[1 2]`. It takes two children.
98`:-` is a rune that creates a **cell**, an ordered pair of two values, such as `[1 2]`. It takes two children.
99
99
100−In our case, `:- count` creates a cell out of whatever value is stored in `count`, and then with the product of line 8.
100+In our case, `:- count` creates a cell out of whatever value is stored in `count`, and then with the product of line 8.
101
101
102## Line 8
102## Line 8
103
103
content/docs/hoon/hoon-school/recursion.md+7−8
@@ -19,8 +19,8 @@ would be:
19
19
20Let's implement a factorial calculator in Hoon. To do so, we'll write a
20Let's implement a factorial calculator in Hoon. To do so, we'll write a
21recursive `gate` (Hoon's equivalent of a function) to perform the relevant
21recursive `gate` (Hoon's equivalent of a function) to perform the relevant
22−computation. Save the code below as `factorial.hoon` in your ship's `/gen`
22+computation. Save the code below as `factorial.hoon` in the `/gen` directory of
23−directory.
23+the `%base` desk on your ship.
24
24
25```hoon
25```hoon
26|= n=@ud
26|= n=@ud
@@ -185,11 +185,10 @@ skips the first match of a name.
185### Exercises
185### Exercises
186
186
1871. Write a recursive gate that produces the first _n_
1871. Write a recursive gate that produces the first _n_
188−[Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number)
188+ [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number)
189
189
1902. Write a recursive gate that produces a list of moves to solve the
1902. Write a recursive gate that produces a list of moves to solve the
191−[Tower of Hanoi problem](https://en.wikipedia.org/wiki/Tower_of_Hanoi).
191+ [Tower of Hanoi problem](https://en.wikipedia.org/wiki/Tower_of_Hanoi).
192−Disks are stacked on a pole by decreasing order of size. Move all of the
192+ Disks are stacked on a pole by decreasing order of size. Move all of the
193−disks from one pole to another with a third pole as a spare, moving one
193+ disks from one pole to another with a third pole as a spare, moving one
194−disc at a time, without putting a larger disk on top of a smaller disk.
194+ disc at a time, without putting a larger disk on top of a smaller disk.
195−
content/docs/hoon/hoon-school/setup.md+6−1
@@ -67,7 +67,9 @@ You asked Dojo to evaluate `17` and it echoed the number back at you. This value
67
67
68Generators are the most straightforward way to write Hoon programs. They are a concept in Arvo, and involve saving Hoon code in a `.hoon` text file. While they aren't strictly part of the Hoon language, we'll be dealing with generators throughout this tutorial.
68Generators are the most straightforward way to write Hoon programs. They are a concept in Arvo, and involve saving Hoon code in a `.hoon` text file. While they aren't strictly part of the Hoon language, we'll be dealing with generators throughout this tutorial.
69
69
70−The simplest type of generator is the **naked generator**. All naked generators are `gates`: functions that take an argument and produce an output. Before creating a generator you need to [mount](/getting-started/) your `desk` to Unix. To create a generator, all you need to do is write a `gate` and put it into a file in the `/home/gen/` directory of your ship as a `.hoon` file. (Assuming you've already mounted with `|mount /=home=`.) After this, you need to run `|commit %home` in Dojo and the new file will be recognized by your ship. To run a generator named `mygen.hoon`, you would type `+mygen <argument>` in your ship's Dojo.
70+The simplest type of generator is the **naked generator**. All naked generators are `gates`: functions that take an argument and produce an output. To create a generator, all you need to do is write a `gate`, save it in a `.hoon` file, and add it to the `/gen` directory of a desk on your ship.
71+
72+To be able to add files easily, you'll need to mount a desk to the Unix filesystem. We'll use the `%base` desk in this case, but you might like to use a different one if you're not on a fake ship. To mount `%base`, just run `|mount %base` in the dojo. If you look in your [pier](/glossary/pier), you should now see a `base` folder. Once you've added the `.hoon` file in `base/gen/`, you'll need to run `|commit %base` in the dojo so the new file is recognised by your ship. To run a generator named `mygen.hoon`, you would type `+mygen <argument>` in your ship's dojo. If you added it to a desk other than `%base`, you can run `+desk!mygen <argument>` where `desk` is the desk you put it in.
71
73
72If this doesn't make sense yet, that's okay. In the [next lesson](/docs/hoon/hoon-school/list-of-numbers), we will walk you through an example `gate` that is run as a generator.
74If this doesn't make sense yet, that's okay. In the [next lesson](/docs/hoon/hoon-school/list-of-numbers), we will walk you through an example `gate` that is run as a generator.
73
75
@@ -84,12 +86,15 @@ If you are brand new to programming, don't think too much about which editor to
84These editors are easy to use for first-time coders.
86These editors are easy to use for first-time coders.
85
87
86#### Atom
88#### Atom
89+
87Atom is free and open-source and runs on all major operating systems. It is available [here](https://atom.io/). A package for Hoon support is maintained by Tlon and may be obtained using the package manager within the editor by searching for `Hoon`.
90Atom is free and open-source and runs on all major operating systems. It is available [here](https://atom.io/). A package for Hoon support is maintained by Tlon and may be obtained using the package manager within the editor by searching for `Hoon`.
88
91
89#### Sublime
92#### Sublime
93+
90Sublime is closed-source, but may be downloaded for free and there is no enforced time limit for evaluation. It runs on all major operating systems. It is available [here](https://www.sublimetext.com/).
94Sublime is closed-source, but may be downloaded for free and there is no enforced time limit for evaluation. It runs on all major operating systems. It is available [here](https://www.sublimetext.com/).
91
95
92#### Visual Studio Code
96#### Visual Studio Code
97+
93Visual Studio Code is free and open-source and runs on all major operating systems. It is available [here](https://code.visualstudio.com/). Hoon support may be acquired in the Extensions menu within the editor by searching for `Hoon`.
98Visual Studio Code is free and open-source and runs on all major operating systems. It is available [here](https://code.visualstudio.com/). Hoon support may be acquired in the Extensions menu within the editor by searching for `Hoon`.
94
99
95### Advanced text editors
100### Advanced text editors
content/docs/hoon/hoon-school/type-polymorphism.md+81−81
@@ -5,9 +5,9 @@ template = "doc.html"
5aliases = ["/docs/learn/hoon/hoon-tutorial/type-polymorphism/"]
5aliases = ["/docs/learn/hoon/hoon-tutorial/type-polymorphism/"]
6+++
6+++
7
7
8−There are many cases in which one may want to write a function that accepts as input various different types of data. Such a function is said to be [polymorphic](https://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29). ("Polymorphism" = "many forms"; so polymorphic functions accept many forms of data as input.)
8+There are many cases in which one may want to write a function that accepts as input various different types of data. Such a function is said to be [polymorphic](https://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29). ("Polymorphism" = "many forms"; so polymorphic functions accept many forms of data as input.)
9
9
10−One relatively trivial form of polymorphism involves sub-typing. A [gate](/docs/glossary/gate/) whose sample is a raw `noun` can accept any Hoon data structure as input -- it's just that the sample will only be treated as a raw [noun](/docs/glossary/noun/). For example, consider the `copy` gate below:
10+One relatively trivial form of polymorphism involves sub-typing. A [gate](/docs/glossary/gate/) whose sample is a raw `noun` can accept any Hoon data structure as input -- it's just that the sample will only be treated as a raw [noun](/docs/glossary/noun/). For example, consider the `copy` gate below:
11
11
12```
12```
13> =copy |=(a=* [a a])
13> =copy |=(a=* [a a])
@@ -22,39 +22,39 @@ One relatively trivial form of polymorphism involves sub-typing. A [gate](/docs
22[[72 101 108 108 111 33 0] [72 101 108 108 111 33 0]]
22[[72 101 108 108 111 33 0] [72 101 108 108 111 33 0]]
23```
23```
24
24
25−`copy` takes the input, `a`, and returns a cell of `[a a]`. Because every piece of Hoon data is a noun, anything can be taken as input. Every other type in Hoon is a sub-type of `noun`. But the output of `copy` is always going to be just a cell of nouns; the type information of the original input value is not preserved by the gate. Consider the `tape` in the last example: `"Hello!"` was pretty-printed in the dojo as a raw noun, not as a string. So `copy` is a relatively uninteresting polymorphic function.
25+`copy` takes the input, `a`, and returns a cell of `[a a]`. Because every piece of Hoon data is a noun, anything can be taken as input. Every other type in Hoon is a sub-type of `noun`. But the output of `copy` is always going to be just a cell of nouns; the type information of the original input value is not preserved by the gate. Consider the `tape` in the last example: `"Hello!"` was pretty-printed in the dojo as a raw noun, not as a string. So `copy` is a relatively uninteresting polymorphic function.
26
26
27In this lesson we'll go over Hoon's support for more interesting polymorphic functions.
27In this lesson we'll go over Hoon's support for more interesting polymorphic functions.
28
28
29## Polymorphic Properties of Cores
29## Polymorphic Properties of Cores
30
30
31−Hoon supports type polymorphism at the [core](/docs/glossary/core/) level. That is, each core has certain polymorphic properties that are tracked and maintained as metadata by Hoon's type system. (See `+$ type` of `hoon.hoon`.) These properties determine the extent to which a core can be used as an interface for values of various types.
31+Hoon supports type polymorphism at the [core](/docs/glossary/core/) level. That is, each core has certain polymorphic properties that are tracked and maintained as metadata by Hoon's type system. (See `+$ type` of `hoon.hoon`.) These properties determine the extent to which a core can be used as an interface for values of various types.
32
32
33−This is rather vaguely put so far. We can clarify by talking more specifically about the kinds of polymorphism supported in Hoon. There are two kinds of type polymorphism for cores: [genericity](https://en.wikipedia.org/wiki/Generic_programming), to include certain kinds of [parametric polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism); and [variance polymorphism](https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29), which involves making use of special sub-typing rules for cores.
33+This is rather vaguely put so far. We can clarify by talking more specifically about the kinds of polymorphism supported in Hoon. There are two kinds of type polymorphism for cores: [genericity](https://en.wikipedia.org/wiki/Generic_programming), to include certain kinds of [parametric polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism); and [variance polymorphism](https://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29), which involves making use of special sub-typing rules for cores.
34
34
35−If you don't understand these very well, that's okay. We'll explain them. Let's begin with the former.
35+If you don't understand these very well, that's okay. We'll explain them. Let's begin with the former.
36
36
37## Dry vs. Wet Cores
37## Dry vs. Wet Cores
38
38
39−To review briefly, a **core** is a pair of `[battery payload]`. The **battery** contains the various [arms](/docs/glossary/arm/) of the core (code), and the **payload** contains all the data needed to evaluate those arms correctly (data). Every arm is evaluated with its parent core as the subject. A **gate** (i.e., a Hoon function) is a core with exactly one arm named `$` and with a [payload](/docs/glossary/payload/) of the form: `[sample context]`. The **sample** is reserved for the function's argument value, and the **context** is any other data needed to evaluate `$` correctly.
39+To review briefly, a **core** is a pair of `[battery payload]`. The **battery** contains the various [arms](/docs/glossary/arm/) of the core (code), and the **payload** contains all the data needed to evaluate those arms correctly (data). Every arm is evaluated with its parent core as the subject. A **gate** (i.e., a Hoon function) is a core with exactly one arm named `$` and with a [payload](/docs/glossary/payload/) of the form: `[sample context]`. The **sample** is reserved for the function's argument value, and the **context** is any other data needed to evaluate `$` correctly.
40
40
41−There are two kinds of cores: **dry** and **wet**. Dry cores, which are more typical, _don't_ make use of **genericity**. Wet cores do. In order to understand generic functions in Hoon, you have to understand the difference between dry and wet cores.
41+There are two kinds of cores: **dry** and **wet**. Dry cores, which are more typical, _don't_ make use of **genericity**. Wet cores do. In order to understand generic functions in Hoon, you have to understand the difference between dry and wet cores.
42
42
43−The cores produced with the `|=`, `|-`, `|%`, and `|_` runes, among others, are all dry. The cores produced with the `|*` and `|@` runes are wet. (`|*` and `|@` are the wet versions of `|=` and `|%`, respectively.)
43+The cores produced with the `|=`, `|-`, `|%`, and `|_` runes, among others, are all dry. The cores produced with the `|*` and `|@` runes are wet. (`|*` and `|@` are the wet versions of `|=` and `|%`, respectively.)
44
44
45−Briefly, the difference between dry and wet cores has to do with how they're treated at compile time, for type inference and type checking. During the type check, the product type of each arm is inferred. For computing a dry arm type, it's assumed that the arm's subject type is of the original parent core. For computing a wet arm type, the parent core type is used, except that the payload value may vary from the original type.
45+Briefly, the difference between dry and wet cores has to do with how they're treated at compile time, for type inference and type checking. During the type check, the product type of each arm is inferred. For computing a dry arm type, it's assumed that the arm's subject type is of the original parent core. For computing a wet arm type, the parent core type is used, except that the payload value may vary from the original type.
46
46
47−Because of this, wet gates can be used as functions that take different input types at different call sites. We'll go over the dry/wet distinction in more detail below and explain why it matters.
47+Because of this, wet gates can be used as functions that take different input types at different call sites. We'll go over the dry/wet distinction in more detail below and explain why it matters.
48
48
49### Dry Cores
49### Dry Cores
50
50
51−A core's payload can change from its original value. In fact, this happens in the typical function call -- the default sample is replaced with an input value. How can we ensure that the core's arms are able to run correctly, that the payload type is still appropriate despite whatever changes it has undergone?
51+A core's payload can change from its original value. In fact, this happens in the typical function call -- the default sample is replaced with an input value. How can we ensure that the core's arms are able to run correctly, that the payload type is still appropriate despite whatever changes it has undergone?
52
52
53−There is a type check for each arm of a dry core, intended to verify that the arm's parent core has a payload of the correct type. In this section we'll describe that type check, starting with typical gate usage.
53+There is a type check for each arm of a dry core, intended to verify that the arm's parent core has a payload of the correct type. In this section we'll describe that type check, starting with typical gate usage.
54
54
55−When the `$` arm of a dry gate is evaluated it takes its parent core -- the dry gate itself -- as the subject, often with a modified sample _value_. But any change in sample _type_ should be conservative; the modified sample value must be of the same type as the default sample value (or possibly a subtype). When the `$` arm is evaluated it should have a subject of a type it knows how to use.
55+When the `$` arm of a dry gate is evaluated it takes its parent core -- the dry gate itself -- as the subject, often with a modified sample _value_. But any change in sample _type_ should be conservative; the modified sample value must be of the same type as the default sample value (or possibly a subtype). When the `$` arm is evaluated it should have a subject of a type it knows how to use.
56
56
57−For illustration, consider the gate created by `add`, a function in the Hoon standard library. The structure of the `add` gate is as follows:
57+For illustration, consider the gate created by `add`, a function in the Hoon standard library. The structure of the `add` gate is as follows:
58
58
59```
59```
60 add
60 add
@@ -64,7 +64,7 @@ For illustration, consider the gate created by `add`, a function in the Hoon sta
64 sample context
64 sample context
65```
65```
66
66
67−The `add` code depends on the fact that there are two [atoms](/docs/glossary/atom/) in the sample: the numbers to be added together. Hence, it is appropriate that only a cell of atoms is permitted for the sample. We can look at the default sample of `add` at address `+6`:
67+The `add` code depends on the fact that there are two [atoms](/docs/glossary/atom/) in the sample: the numbers to be added together. Hence, it is appropriate that only a cell of atoms is permitted for the sample. We can look at the default sample of `add` at address `+6`:
68
68
69```
69```
70> +6:add
70> +6:add
@@ -85,28 +85,28 @@ Any other type of value in the sample results in a `nest-fail` crash:
85nest-fail
85nest-fail
86```
86```
87
87
88−This function call attempts to create a modified copy of the `add` gate, replacing the original sample `[0 0]` with `[12 "hello"]`, then evaluate the `$` arm of this modified core. (We ignore the `a` and `b` faces for now.) But this piece of code failed to compile; the type system knew to reject it.
88+This function call attempts to create a modified copy of the `add` gate, replacing the original sample `[0 0]` with `[12 "hello"]`, then evaluate the `$` arm of this modified core. (We ignore the `a` and `b` faces for now.) But this piece of code failed to compile; the type system knew to reject it.
89
89
90−How does it know? The type system keeps track of two copies of the payload type for each core:
90+How does it know? The type system keeps track of two copies of the payload type for each core:
91
91
92−+ The original payload type, i.e., the type of the payload when the core was first created. In the case of `add`, the original sample type is a cell of atoms, `[@ @]`. This original type information is always preserved, regardless of the argument values used to call `add`.
92+- The original payload type, i.e., the type of the payload when the core was first created. In the case of `add`, the original sample type is a cell of atoms, `[@ @]`. This original type information is always preserved, regardless of the argument values used to call `add`.
93−+ The current payload type, i.e., the type of the payload after any substitutions or other changes have been made. In the last `add` call, `(add 12 "hello")`, the sample would be a cell whose head is an `@ud`, and whose tail is a `tape`.
93+- The current payload type, i.e., the type of the payload after any substitutions or other changes have been made. In the last `add` call, `(add 12 "hello")`, the sample would be a cell whose head is an `@ud`, and whose tail is a `tape`.
94
94
95−The type check at compile time compares these two types, and if the current payload type doesn't nest under the original payload, the compile fails with a `nest-fail` crash. (E.g., a cell of type `[@ud tape]` doesn't nest under `[@ @]`.) Otherwise, the original payload _type_ is used for evaluation, even though the original sample _value_ has been replaced. So the arm of a dry core is guaranteed to run with exactly the same subject type each time it is evaluated.
95+The type check at compile time compares these two types, and if the current payload type doesn't nest under the original payload, the compile fails with a `nest-fail` crash. (E.g., a cell of type `[@ud tape]` doesn't nest under `[@ @]`.) Otherwise, the original payload _type_ is used for evaluation, even though the original sample _value_ has been replaced. So the arm of a dry core is guaranteed to run with exactly the same subject type each time it is evaluated.
96
96
97−The type check for each arm in a dry core can be understood as implementing a version of the ["Liskov substitution principle"](https://en.wikipedia.org/wiki/Liskov_substitution_principle). The arm works for some (originally defined) payload type `P`. Payload type `Q` nests under `P`. Therefore the arm works for `Q` as well, though for type inference purposes the payload is treated as a `P`. The inferred type of the arm is based on the assumption that it's evaluated with a subject type exactly like that of its original parent core -- i.e., whose payload is of type `P`.
97+The type check for each arm in a dry core can be understood as implementing a version of the ["Liskov substitution principle"](https://en.wikipedia.org/wiki/Liskov_substitution_principle). The arm works for some (originally defined) payload type `P`. Payload type `Q` nests under `P`. Therefore the arm works for `Q` as well, though for type inference purposes the payload is treated as a `P`. The inferred type of the arm is based on the assumption that it's evaluated with a subject type exactly like that of its original parent core -- i.e., whose payload is of type `P`.
98
98
99### Wet Cores (Genericity)
99### Wet Cores (Genericity)
100
100
101−The type checking and inference rules for arms are a bit different for wet cores. Whereas the dry arm is understood as having _exactly_ its parent core type for its subject, wet arms can be evaluated with payloads of various types.
101+The type checking and inference rules for arms are a bit different for wet cores. Whereas the dry arm is understood as having _exactly_ its parent core type for its subject, wet arms can be evaluated with payloads of various types.
102
102
103Let's start again with a typical function call.
103Let's start again with a typical function call.
104
104
105−When a function call occurs on a wet arm, the [call site](https://en.wikipedia.org/wiki/Call_site) argument value type is used as the sample type -- not the original parent core sample type. Correspondingly, the inferred type of a wet arm depends, among other things, on the type of the argument value -- i.e., the modified sample value type of the core, not the original sample. Thus, the inferred product type typically varies from one call site to another.
105+When a function call occurs on a wet arm, the [call site](https://en.wikipedia.org/wiki/Call_site) argument value type is used as the sample type -- not the original parent core sample type. Correspondingly, the inferred type of a wet arm depends, among other things, on the type of the argument value -- i.e., the modified sample value type of the core, not the original sample. Thus, the inferred product type typically varies from one call site to another.
106
106
107−The arms of wet cores must be able to handle subjects of various types -- they are interestingly polymorphic in a way that dry cores cannot be. The Hoon code that defines each wet arm must be [generic](https://en.wikipedia.org/wiki/Generic_programming) with respect to the sample type.
107+The arms of wet cores must be able to handle subjects of various types -- they are interestingly polymorphic in a way that dry cores cannot be. The Hoon code that defines each wet arm must be [generic](https://en.wikipedia.org/wiki/Generic_programming) with respect to the sample type.
108
108
109−An example will clarify how wet gates work. Recall the `copy` gate from earlier in the lesson:
109+An example will clarify how wet gates work. Recall the `copy` gate from earlier in the lesson:
110
110
111```
111```
112> =copy |=(a=* [a a])
112> =copy |=(a=* [a a])
@@ -121,7 +121,7 @@ An example will clarify how wet gates work. Recall the `copy` gate from earlier
121[[72 101 108 108 111 33 0] [72 101 108 108 111 33 0]]
121[[72 101 108 108 111 33 0] [72 101 108 108 111 33 0]]
122```
122```
123
123
124−This gate is dry (as are all cores produced with `|=`), and so the inferred type of the product is determined based on the original core sample type. In this case, that's a raw noun, `*`. The dojo pretty-printer therefore has no way of knowing that the product of the last `copy` call should be printed as a pair of `tape`s -- it just sees a pair of nouns. If we want the original type information preserved, we must use a wet gate, which can be produced with `|*`:
124+This gate is dry (as are all cores produced with `|=`), and so the inferred type of the product is determined based on the original core sample type. In this case, that's a raw noun, `*`. The dojo pretty-printer therefore has no way of knowing that the product of the last `copy` call should be printed as a pair of `tape`s -- it just sees a pair of nouns. If we want the original type information preserved, we must use a wet gate, which can be produced with `|*`:
125
125
126```
126```
127> =wet-copy |*(a=* [a a])
127> =wet-copy |*(a=* [a a])
@@ -136,7 +136,7 @@ This gate is dry (as are all cores produced with `|=`), and so the inferred type
136["Hello!" "Hello!"]
136["Hello!" "Hello!"]
137```
137```
138
138
139−We see that the type information about the `tape` literal `"Hello!"` is preserved in the last function call, as desired. The original sample value of `wet-copy` is replaced with `"Hello!"`, and the original sample type is ignored in favor of the new sample type, `tape`. So the inferred arm type is a cell of `tape`s, which the dojo pretty-printer handles appropriately.
139+We see that the type information about the `tape` literal `"Hello!"` is preserved in the last function call, as desired. The original sample value of `wet-copy` is replaced with `"Hello!"`, and the original sample type is ignored in favor of the new sample type, `tape`. So the inferred arm type is a cell of `tape`s, which the dojo pretty-printer handles appropriately.
140
140
141In fact, `wet-copy` can take a Hoon value of any type you like.
141In fact, `wet-copy` can take a Hoon value of any type you like.
142
142
@@ -155,7 +155,7 @@ For another example, consider the following gate that switches the order of the
155[0b1101 0xbeef]
155[0b1101 0xbeef]
156```
156```
157
157
158−Not only does `switch` reverse the order of the values, it also reverses their respective types, as desired. The dry version of switch is not as useful:
158+Not only does `switch` reverse the order of the values, it also reverses their respective types, as desired. The dry version of switch is not as useful:
159
159
160```
160```
161> =dry-switch |=([a=* b=*] [b a])
161> =dry-switch |=([a=* b=*] [b a])
@@ -176,9 +176,9 @@ But `switch` can't take just any input:
176-find.b
176-find.b
177```
177```
178
178
179−It must take a cell, not an atom. So it's certainly possible to write a wet gate that doesn't take all possible input types.
179+It must take a cell, not an atom. So it's certainly possible to write a wet gate that doesn't take all possible input types.
180
180
181−It is good practice to include a cast in all gates, even wet gates. But in many cases the desired output type depends on the input type. How can we cast appropriately? Often we can cast by example, using the input values themselves. For example, we can rewrite `switch` as:
181+It is good practice to include a cast in all gates, even wet gates. But in many cases the desired output type depends on the input type. How can we cast appropriately? Often we can cast by example, using the input values themselves. For example, we can rewrite `switch` as:
182
182
183```
183```
184> =switch |*([a=* b=*] ^+([b a] [b a]))
184> =switch |*([a=* b=*] ^+([b a] [b a]))
@@ -187,7 +187,7 @@ It is good practice to include a cast in all gates, even wet gates. But in many
187[0xbeef "Hello"]
187[0xbeef "Hello"]
188```
188```
189
189
190−As is the case with dry arms, there is a type-check associated with each wet arm. Or, rather, there are potentially many checks for each wet arm, one for each wing in the code that resolves to a wet arm. The product type of that arm is inferred at each call site, using the argument value type given at that site. If the type inference doesn't go through -- e.g., if there is a cast that doesn't succeed relative to the call site argument value -- then the compile will crash with a `nest-fail`. Otherwise the type check goes through with the inferred type of the wet arm at that call site. So the product type of a wet gate can differ from one call site to another, as we saw with `switch` above.
190+As is the case with dry arms, there is a type-check associated with each wet arm. Or, rather, there are potentially many checks for each wet arm, one for each wing in the code that resolves to a wet arm. The product type of that arm is inferred at each call site, using the argument value type given at that site. If the type inference doesn't go through -- e.g., if there is a cast that doesn't succeed relative to the call site argument value -- then the compile will crash with a `nest-fail`. Otherwise the type check goes through with the inferred type of the wet arm at that call site. So the product type of a wet gate can differ from one call site to another, as we saw with `switch` above.
191
191
192### Parametric Polymorphism and `|$`
192### Parametric Polymorphism and `|$`
193
193
@@ -197,10 +197,10 @@ list of molds and produces a new mold. Here we take another look at this rune as
197an implementation of **parametric polymorphism** in Hoon.
197an implementation of **parametric polymorphism** in Hoon.
198
198
199For example, we have `list`s, `tree`s, and `set`s in Hoon, which are each
199For example, we have `list`s, `tree`s, and `set`s in Hoon, which are each
200−defined in `hoon.hoon` as wet gate mold builders. Take a moment to see for
200+defined in `hoon.hoon` as wet gate mold builders. Take a moment to see for
201−yourself. Each `++` arm is followed by `|$` and a list of labels for input
201+yourself. Each `++` arm is followed by `|$` and a list of labels for input
202−types inside brackets `[ ]`. After that subexpression comes another that
202+types inside brackets `[ ]`. After that subexpression comes another that
203−defines a type that is parametrically polymorphic with respect to the input values. For example, here is the definition of `list` from `hoon.hoon`:
203+defines a type that is parametrically polymorphic with respect to the input values. For example, here is the definition of `list` from `hoon.hoon`:
204
204
205```hoon
205```hoon
206++ list
206++ list
@@ -213,9 +213,9 @@ defines a type that is parametrically polymorphic with respect to the input valu
213 $@(~ [i=item t=(list item)])
213 $@(~ [i=item t=(list item)])
214```
214```
215
215
216−The `|$` rune is especially useful for defining [containers](https://en.wikipedia.org/wiki/Container_%28abstract_data_type%29) of various kinds. Indeed, `list`s, `tree`s, and `set`s are all examples of containers. You can have a `(list @)`, a `(list ^)`, a `(list *)`, and so on. Or a `(tree @)`, a `(tree ^)`, a `(tree *)`, etc. And the same for `set`.
216+The `|$` rune is especially useful for defining [containers](https://en.wikipedia.org/wiki/Container_%28abstract_data_type%29) of various kinds. Indeed, `list`s, `tree`s, and `set`s are all examples of containers. You can have a `(list @)`, a `(list ^)`, a `(list *)`, and so on. Or a `(tree @)`, a `(tree ^)`, a `(tree *)`, etc. And the same for `set`.
217
217
218−One nice thing about containers defined by `|$` is that they nest in the expected way. Intuitively a `(list @)` should nest under `(list *)`, because `@` nests under `*`. And so it does:
218+One nice thing about containers defined by `|$` is that they nest in the expected way. Intuitively a `(list @)` should nest under `(list *)`, because `@` nests under `*`. And so it does:
219
219
220```
220```
221> =a `(list @)`~[11 22 33]
221> =a `(list @)`~[11 22 33]
@@ -251,7 +251,7 @@ Let's clear the dojo subject by unbinding the faces we've used up to now in the
251
251
252## Core Variance
252## Core Variance
253
253
254−Let's say you want to write a function that takes a gate as one (or more) of its arguments. It's not hard to imagine useful cases of this. Consider `turn` from the Hoon standard library, which applies an arbitrary function to each item in a list and returns a modified list:
254+Let's say you want to write a function that takes a gate as one (or more) of its arguments. It's not hard to imagine useful cases of this. Consider `turn` from the Hoon standard library, which applies an arbitrary function to each item in a list and returns a modified list:
255
255
256```
256```
257> =b `(list @)`~[2 3 4 5]
257> =b `(list @)`~[2 3 4 5]
@@ -265,9 +265,9 @@ Let's say you want to write a function that takes a gate as one (or more) of its
265=b
265=b
266```
266```
267
267
268−It's quite useful to be able to pass cores as arguments. But let's think about how to write a function that accepts a core as input. How do we define a sample so that it accepts a core?
268+It's quite useful to be able to pass cores as arguments. But let's think about how to write a function that accepts a core as input. How do we define a sample so that it accepts a core?
269
269
270−We _could_ define the sample by example -- i.e., with `$_`, or `_` for short -- using a core. Consider the following, in which `mycore` is the example core and `apply` is function that accepts gates:
270+We _could_ define the sample by example -- i.e., with `$_`, or `_` for short -- using a core. Consider the following, in which `mycore` is the example core and `apply` is function that accepts gates:
271
271
272```
272```
273> =mycore =>([12 13] |=(a=@ +(a)))
273> =mycore =>([12 13] |=(a=@ +(a)))
@@ -284,47 +284,47 @@ We _could_ define the sample by example -- i.e., with `$_`, or `_` for short --
284123
284123
285```
285```
286
286
287−This works, but in fact `apply` is a very brittle function. It can only take as input a core whose payload is exactly like, or a subtype of, the payload of `mycore`:
287+This works, but in fact `apply` is a very brittle function. It can only take as input a core whose payload is exactly like, or a subtype of, the payload of `mycore`:
288
288
289```
289```
290> (apply 15 |=(a=@ (mul 2 a)))
290> (apply 15 |=(a=@ (mul 2 a)))
291nest-fail
291nest-fail
292```
292```
293
293
294−A core created in one place of your code isn't likely to have the same payload as a core produced elsewhere, unless you intentionally define it so that it does. This generally isn't practical, so we need another way to indicate that we want a core as input.
294+A core created in one place of your code isn't likely to have the same payload as a core produced elsewhere, unless you intentionally define it so that it does. This generally isn't practical, so we need another way to indicate that we want a core as input.
295
295
296−Why did the last example crash? To understand this, you need to understand the the different variance properties a core can have. These properties determine the nesting and type inference rules associated with each core.
296+Why did the last example crash? To understand this, you need to understand the the different variance properties a core can have. These properties determine the nesting and type inference rules associated with each core.
297
297
298The basic question to be answered is: when does one core type nest under another?
298The basic question to be answered is: when does one core type nest under another?
299
299
300−The battery nesting rules for dry cores are relatively straightforward, and they're the same for all cores, regardless of variance properties. Let `A` and `B` be two cores. The type of `B` nests under the type of `A` only if two conditions are met: (i) the batteries of `A` and `B` have exactly the same tree shape, and (ii) the product type of each `B` arm nests under the product type of the corresponding `A` arm.
300+The battery nesting rules for dry cores are relatively straightforward, and they're the same for all cores, regardless of variance properties. Let `A` and `B` be two cores. The type of `B` nests under the type of `A` only if two conditions are met: (i) the batteries of `A` and `B` have exactly the same tree shape, and (ii) the product type of each `B` arm nests under the product type of the corresponding `A` arm.
301
301
302−The payload types of `A` and `B` must also be checked. Certain payload nesting rules apply to all cores, if `B` is to nest under `A`: (i) if `A` is wet then `B` must also be wet; (ii) the original payload type of `A` must mutually nest with the current payload type of `A` (i.e., these types nest under each other); and (iii) the current payload type of `B` must nest under the original payload type of `B`.
302+The payload types of `A` and `B` must also be checked. Certain payload nesting rules apply to all cores, if `B` is to nest under `A`: (i) if `A` is wet then `B` must also be wet; (ii) the original payload type of `A` must mutually nest with the current payload type of `A` (i.e., these types nest under each other); and (iii) the current payload type of `B` must nest under the original payload type of `B`.
303
303
304### The Four Kinds of Cores: Gold, Iron, Zinc, and Lead
304### The Four Kinds of Cores: Gold, Iron, Zinc, and Lead
305
305
306But there are different sets of nesting rules for finishing the payload type check, depending on the variance properties of the core.
306But there are different sets of nesting rules for finishing the payload type check, depending on the variance properties of the core.
307
307
308−There are four kinds of cores: **gold** (invariant payload), **iron** (contravariant sample), **zinc** (covariant sample), and **lead** (bivariant sample). Information about the kind of core is tracked by the Hoon type system.
308+There are four kinds of cores: **gold** (invariant payload), **iron** (contravariant sample), **zinc** (covariant sample), and **lead** (bivariant sample). Information about the kind of core is tracked by the Hoon type system.
309
309
310Their nesting rules in brief:
310Their nesting rules in brief:
311
311
312−+ If `A` is a gold core, then core `B` nests under it only if `B` is gold and the payload of `B` doesn't vary in type from the payload of `A`. The payload `B` is **invariant** (i.e., neither co- nor contravariant) relative to the payload of an `A` it nests under. Gold cores have a read-write payload.
312+- If `A` is a gold core, then core `B` nests under it only if `B` is gold and the payload of `B` doesn't vary in type from the payload of `A`. The payload `B` is **invariant** (i.e., neither co- nor contravariant) relative to the payload of an `A` it nests under. Gold cores have a read-write payload.
313−+ If `A` is an iron core, then core `B` nests under it only if `B` is gold or iron and the sample of `A` nests under the sample of `B`. Notice that the nesting direction of the samples is the opposite of the nesting direction of the cores. I.e., the sample types are **contravariant** with respect to the iron core types. Iron cores have a write-only sample and an opaque context. ("Opaque" means neither read nor write.)
313+- If `A` is an iron core, then core `B` nests under it only if `B` is gold or iron and the sample of `A` nests under the sample of `B`. Notice that the nesting direction of the samples is the opposite of the nesting direction of the cores. I.e., the sample types are **contravariant** with respect to the iron core types. Iron cores have a write-only sample and an opaque context. ("Opaque" means neither read nor write.)
314−+ If `A` is a zinc core, then core `B` nests under it only if `B` is gold or zinc and the sample of `B` nests under the sample of `A`. Notice that the nesting direction of the samples is the same as the nesting direction of the cores. I.e., the sample types are **covariant** with respect to the zinc core types. Zinc cores have a read-only sample and an opaque context.
314+- If `A` is a zinc core, then core `B` nests under it only if `B` is gold or zinc and the sample of `B` nests under the sample of `A`. Notice that the nesting direction of the samples is the same as the nesting direction of the cores. I.e., the sample types are **covariant** with respect to the zinc core types. Zinc cores have a read-only sample and an opaque context.
315−+ If `A` is a lead core, then core `B` nests under it without any additional payload check beyond those described in the previous section. It trivially follows that the payload type both co- and contravaries with respect to the lead core types (hence lead cores are **bivariant**). Lead cores have an opaque payload.
315+- If `A` is a lead core, then core `B` nests under it without any additional payload check beyond those described in the previous section. It trivially follows that the payload type both co- and contravaries with respect to the lead core types (hence lead cores are **bivariant**). Lead cores have an opaque payload.
316
316
317Let's go through each kind more carefully.
317Let's go through each kind more carefully.
318
318
319#### Gold Cores (Invariant)
319#### Gold Cores (Invariant)
320
320
321−By default, most cores are gold. This includes the cores produced with the `|%`, `|=`, `|_`, and `|-` runes, among others.
321+By default, most cores are gold. This includes the cores produced with the `|%`, `|=`, `|_`, and `|-` runes, among others.
322
322
323−Assume that `A` is a gold core and that `B` is some other core. The type of `B` nests under the type of `A` only if the original payload types of each mutually nest -- i.e., the original payload type of `A` nests under the original payload type of `B`, and _vice versa_. Furthermore, only gold cores nest under other gold cores; so `B` must be gold to nest under `A`.
323+Assume that `A` is a gold core and that `B` is some other core. The type of `B` nests under the type of `A` only if the original payload types of each mutually nest -- i.e., the original payload type of `A` nests under the original payload type of `B`, and _vice versa_. Furthermore, only gold cores nest under other gold cores; so `B` must be gold to nest under `A`.
324
324
325−These payload nesting rules are the strictest ones for cores. The payload type is neither covariant nor contravariant; when type-checking against a gold core, the target payload cannot vary at all in type. Consequently, it is type-safe to modify every part of the payload: gold cores have a read-write payload.
325+These payload nesting rules are the strictest ones for cores. The payload type is neither covariant nor contravariant; when type-checking against a gold core, the target payload cannot vary at all in type. Consequently, it is type-safe to modify every part of the payload: gold cores have a read-write payload.
326
326
327−Usually it makes sense to cast for a gold core type when you're treating a core as a state machine. The check ensures that the payload, which includes the relevant state, doesn't vary in type. To see state machines that involve casts for gold cores, see Chapter 2 of the Hoon tutorial.
327+Usually it makes sense to cast for a gold core type when you're treating a core as a state machine. The check ensures that the payload, which includes the relevant state, doesn't vary in type. To see state machines that involve casts for gold cores, see Chapter 2 of the Hoon tutorial.
328
328
329Let's look at simpler examples here, using the `^+` rune:
329Let's look at simpler examples here, using the `^+` rune:
330
330
@@ -344,7 +344,7 @@ nest-fail
344nest-fail
344nest-fail
345```
345```
346
346
347−The first cast goes through because the right-hand gold core has the same sample type as the left-hand gold core. The sample types mutually nest. The second cast fails because the right-hand sample type is more specific than the left-hand sample type. (Not all cells, `^`, are pairs of atoms, `[@ @]`.) And the third cast fails because the right-hand sample type is broader than the left-hand sample type. (Not all nouns, `*`, are cells, `^`.)
347+The first cast goes through because the right-hand gold core has the same sample type as the left-hand gold core. The sample types mutually nest. The second cast fails because the right-hand sample type is more specific than the left-hand sample type. (Not all cells, `^`, are pairs of atoms, `[@ @]`.) And the third cast fails because the right-hand sample type is broader than the left-hand sample type. (Not all nouns, `*`, are cells, `^`.)
348
348
349Two more examples:
349Two more examples:
350
350
@@ -356,15 +356,15 @@ Two more examples:
356nest-fail
356nest-fail
357```
357```
358
358
359−In these examples, the `=>` rune is used to give each core a simple context. The context of the left-hand core in each case is a pair of atoms, `[@ @]`. The first cast goes through because the right-hand core also has a pair of atoms as its context. The second cast fails because the right-hand core has the wrong type of context -- three atoms, `[@ @ @]`.
359+In these examples, the `=>` rune is used to give each core a simple context. The context of the left-hand core in each case is a pair of atoms, `[@ @]`. The first cast goes through because the right-hand core also has a pair of atoms as its context. The second cast fails because the right-hand core has the wrong type of context -- three atoms, `[@ @ @]`.
360
360
361#### Iron Cores (Contravariant)
361#### Iron Cores (Contravariant)
362
362
363−Assume that `A` is an iron core and `B` is some other core. The type of `B` nests under the type of `A` only if the original sample type of `A` nests under the original sample type of `B`. That is, `B`'s sample type must be equivalent or more general than the sample type of `A`. Furthermore, `B` must be either iron or gold to nest under `A`.
363+Assume that `A` is an iron core and `B` is some other core. The type of `B` nests under the type of `A` only if the original sample type of `A` nests under the original sample type of `B`. That is, `B`'s sample type must be equivalent or more general than the sample type of `A`. Furthermore, `B` must be either iron or gold to nest under `A`.
364
364
365−The context type of `B` isn't checked at all; and because of the nesting rules it isn't type-safe to do type-inference on the sample of an iron gate. Thus, there are certain restrictions on iron cores that preserve type safety: (i) the context of an iron core is opaque, meaning that it cannot be written-to or read-from; and (ii) the iron core payload is write-only.
365+The context type of `B` isn't checked at all; and because of the nesting rules it isn't type-safe to do type-inference on the sample of an iron gate. Thus, there are certain restrictions on iron cores that preserve type safety: (i) the context of an iron core is opaque, meaning that it cannot be written-to or read-from; and (ii) the iron core payload is write-only.
366
366
367−Iron gates are particularly useful when you want to pass gates (having various payload types) to other gates. We can illustrate this use with a very simple example. Save the following as `gatepass.hoon` in the `gen` directory of your urbit's pier:
367+Iron gates are particularly useful when you want to pass gates (having various payload types) to other gates. We can illustrate this use with a very simple example. Save the following as `gatepass.hoon` in the `gen` directory of your `%base` desk:
368
368
369```hoon
369```hoon
370|= a=_^|(|=(@ 15))
370|= a=_^|(|=(@ 15))
@@ -373,9 +373,9 @@ Iron gates are particularly useful when you want to pass gates (having various p
373(add b 20)
373(add b 20)
374```
374```
375
375
376−This generator is mostly very simple. Everything about it should be clear except possibly the first line.
376+This generator is mostly very simple. Everything about it should be clear except possibly the first line.
377
377
378−The first line defines the sample as an iron gate and gives it the face `a`. The function as a whole is for taking some gate as input, calling it by passing it the value `10`, adding `20` to it, and returning the result. Let's try it out in the dojo:
378+The first line defines the sample as an iron gate and gives it the face `a`. The function as a whole is for taking some gate as input, calling it by passing it the value `10`, adding `20` to it, and returning the result. Let's try it out in the dojo:
379
379
380```
380```
381> +gatepass |=(a=@ +(a))
381> +gatepass |=(a=@ +(a))
@@ -388,16 +388,16 @@ The first line defines the sample as an iron gate and gives it the face `a`. Th
38850
38850
389```
389```
390
390
391−But we still haven't fully explained the first line of the code. What does `_^|(|=(@ 15))` mean? The inside portion is clear enough -- `|=(@ 15)` produces a normal (i.e., gold) gate that takes an atom and returns `15`. The `^|` rune is used to turn gold gates to iron. (Reverse alchemy!) And the `_` character turns that iron gate value into a structure, i.e. a type. So the whole subexpression means, roughly: "the same type as an iron gate whose sample is an atom, `@`, and whose product is another atom, `@`". The context isn't checked at all. This is good, because that allows us to accept gates defined and produced in drastically different environments. Let's try passing a gate with a different context:
391+But we still haven't fully explained the first line of the code. What does `_^|(|=(@ 15))` mean? The inside portion is clear enough -- `|=(@ 15)` produces a normal (i.e., gold) gate that takes an atom and returns `15`. The `^|` rune is used to turn gold gates to iron. (Reverse alchemy!) And the `_` character turns that iron gate value into a structure, i.e. a type. So the whole subexpression means, roughly: "the same type as an iron gate whose sample is an atom, `@`, and whose product is another atom, `@`". The context isn't checked at all. This is good, because that allows us to accept gates defined and produced in drastically different environments. Let's try passing a gate with a different context:
392
392
393```
393```
394> +gatepass =>([22 33] |=(a=@ +(a)))
394> +gatepass =>([22 33] |=(a=@ +(a)))
39531
39531
396```
396```
397
397
398−Yup, it still works. You can't do that with a gold core sample!
398+Yup, it still works. You can't do that with a gold core sample!
399
399
400−There's a simpler way to define an iron sample. Revise the first line of `gatepass.hoon` to the following:
400+There's a simpler way to define an iron sample. Revise the first line of `gatepass.hoon` to the following:
401
401
402```hoon
402```hoon
403|= a=$-(@ @)
403|= a=$-(@ @)
@@ -406,15 +406,15 @@ There's a simpler way to define an iron sample. Revise the first line of `gatep
406(add b 20)
406(add b 20)
407```
407```
408
408
409−If you test it you'll find that the generator behaves the same as it did before the edits. The `$-` rune is used to create an iron gate structure, i.e., an iron gate type. The first expression defines the desired sample type, and the second subexpression defines the gate's desired output type.
409+If you test it you'll find that the generator behaves the same as it did before the edits. The `$-` rune is used to create an iron gate structure, i.e., an iron gate type. The first expression defines the desired sample type, and the second subexpression defines the gate's desired output type.
410
410
411−The sample type of an iron gate is contravariant. This means that, when doing a cast with some iron gate, the desired gate must have either the same sample type or a superset.
411+The sample type of an iron gate is contravariant. This means that, when doing a cast with some iron gate, the desired gate must have either the same sample type or a superset.
412
412
413Why is this a useful nesting rule for passing gates?
413Why is this a useful nesting rule for passing gates?
414
414
415−Let's say you're writing a function `F` that takes as input some gate `G`. Let's also say you want `G` to be able to take as input any **mammal**. The code of `F` is going to pass arbitrary **mammals** to `G`, so that `G` needs to know how to handle all **mammals** correctly. You can't pass `F` a gate that only takes **dogs** as input, because `F` might call it with a **cat**. But `F` can accept a gate that takes all **animals** as input, because a gate that can handle any **animal** can handle **any mammal**.
415+Let's say you're writing a function `F` that takes as input some gate `G`. Let's also say you want `G` to be able to take as input any **mammal**. The code of `F` is going to pass arbitrary **mammals** to `G`, so that `G` needs to know how to handle all **mammals** correctly. You can't pass `F` a gate that only takes **dogs** as input, because `F` might call it with a **cat**. But `F` can accept a gate that takes all **animals** as input, because a gate that can handle any **animal** can handle **any mammal**.
416
416
417−Iron cores are designed precisely with this purpose in mind. The reason that the sample is write-only is that we want to be able to assume, within function `F`, that the sample of `G` is a **mammal**. But that might not be true when `G` is first passed into `F` -- the default value of `G` could be another **animal**, say, a **lizard**. So we restrict looking into the sample of `G` by making the sample write-only. The illusion is maintained and type safety secured.
417+Iron cores are designed precisely with this purpose in mind. The reason that the sample is write-only is that we want to be able to assume, within function `F`, that the sample of `G` is a **mammal**. But that might not be true when `G` is first passed into `F` -- the default value of `G` could be another **animal**, say, a **lizard**. So we restrict looking into the sample of `G` by making the sample write-only. The illusion is maintained and type safety secured.
418
418
419Let's illustrate iron core nesting properties:
419Let's illustrate iron core nesting properties:
420
420
@@ -441,9 +441,9 @@ nest-fail
441
441
442(As before, we use the `^|` rune to turn gold gates iron.)
442(As before, we use the `^|` rune to turn gold gates iron.)
443
443
444−The first cast goes through because the two gates have the same sample type. The second cast fails because the right-hand gate has a more specific sample type than the left-hand gate does. If you're casting for a gate that accepts any cell, `^`, it's because we want to be able to pass any cell to it. A gate that is only designed for pairs of atoms, `[@ @]`, can't handle all such cases, naturally. The third cast goes through because the right-hand gate sample type is broader than the left-hand gate sample type. A gate that can take any noun as its sample, `*`, works just fine if we choose only to pass it cells, `^`.
444+The first cast goes through because the two gates have the same sample type. The second cast fails because the right-hand gate has a more specific sample type than the left-hand gate does. If you're casting for a gate that accepts any cell, `^`, it's because we want to be able to pass any cell to it. A gate that is only designed for pairs of atoms, `[@ @]`, can't handle all such cases, naturally. The third cast goes through because the right-hand gate sample type is broader than the left-hand gate sample type. A gate that can take any noun as its sample, `*`, works just fine if we choose only to pass it cells, `^`.
445
445
446−We mentioned previously that an iron core has a write-only sample and an opaque core. Let's prove it.
446+We mentioned previously that an iron core has a write-only sample and an opaque core. Let's prove it.
447
447
448Let's define a trivial gate with a context of `[g=22 h=44 .]`, convert it to iron with `^|`, and bind it to `iron-gate` in the dojo:
448Let's define a trivial gate with a context of `[g=22 h=44 .]`, convert it to iron with `^|`, and bind it to `iron-gate` in the dojo:
449
449
@@ -457,14 +457,14 @@ Let's define a trivial gate with a context of `[g=22 h=44 .]`, convert it to iro
45733
45733
458```
458```
459
459
460−Not a complicated function, but it serves our purposes. Normally (i.e., with gold cores) we can look at a context value `p` of some gate `q` with a wing expression: `p.q`. Not so with the iron gate:
460+Not a complicated function, but it serves our purposes. Normally (i.e., with gold cores) we can look at a context value `p` of some gate `q` with a wing expression: `p.q`. Not so with the iron gate:
461
461
462```
462```
463> g.iron-gate
463> g.iron-gate
464-find.g.iron-gate
464-find.g.iron-gate
465```
465```
466
466
467−And usually we can look at the sample value using the face given in the gate definition. Not in this case:
467+And usually we can look at the sample value using the face given in the gate definition. Not in this case:
468
468
469```
469```
470> a.iron-gate
470> a.iron-gate
@@ -505,11 +505,11 @@ Let's clear up the dojo subject by unbinding `iron-gate`:
505
505
506Zinc cores are mirror versions of iron cores.
506Zinc cores are mirror versions of iron cores.
507
507
508−Assume that `A` is a zinc core and `B` is some other core. The type of `B` nests under the type of `A` only if the original sample type of `B` nests under the original sample type of `A`. That is, the target core sample type must be equivalent or a subset of the cast core sample type. Furthermore, `B` must be either zinc or gold to nest under `A`.
508+Assume that `A` is a zinc core and `B` is some other core. The type of `B` nests under the type of `A` only if the original sample type of `B` nests under the original sample type of `A`. That is, the target core sample type must be equivalent or a subset of the cast core sample type. Furthermore, `B` must be either zinc or gold to nest under `A`.
509
509
510−As with iron cores, the context of zinc cores is opaque -- they cannot be written-to or read-from. The sample of a zinc core is read-only. That means, among other things, that zinc cores cannot be used for function calls. Function calls in Hoon involve a change to the sample (the default sample is replaced with the argument value), which is disallowed as type-unsafe for zinc cores.
510+As with iron cores, the context of zinc cores is opaque -- they cannot be written-to or read-from. The sample of a zinc core is read-only. That means, among other things, that zinc cores cannot be used for function calls. Function calls in Hoon involve a change to the sample (the default sample is replaced with the argument value), which is disallowed as type-unsafe for zinc cores.
511
511
512−We can illustrate the casting properties of zinc cores with a few examples. The `^&` rune is used to convert gold cores to zinc:
512+We can illustrate the casting properties of zinc cores with a few examples. The `^&` rune is used to convert gold cores to zinc:
513
513
514```
514```
515> ^+(^&(|=(^ 15)) |=(^ 16))
515> ^+(^&(|=(^ 15)) |=(^ 16))
@@ -532,9 +532,9 @@ We can illustrate the casting properties of zinc cores with a few examples. The
532nest-fail
532nest-fail
533```
533```
534
534
535−The first two casts succeed because the right-hand core sample type is either the same or a subset of the left-hand core sample type. The last one fails because the right-hand sample type is a superset.
535+The first two casts succeed because the right-hand core sample type is either the same or a subset of the left-hand core sample type. The last one fails because the right-hand sample type is a superset.
536
536
537−Even though you can't function call a zinc core, the arms of a zinc core can be computed and the sample can be read. Let's test this with a zinc gate of our own:
537+Even though you can't function call a zinc core, the arms of a zinc core can be computed and the sample can be read. Let's test this with a zinc gate of our own:
538
538
539```
539```
540> =zinc-gate ^& |=(a=_22 (add 10 a))
540> =zinc-gate ^& |=(a=_22 (add 10 a))
@@ -557,11 +557,11 @@ Let's clear up the dojo subject again:
557
557
558#### Lead Cores (Bivariant)
558#### Lead Cores (Bivariant)
559
559
560−Lead cores have more permissive nesting rules than either iron or zinc cores. There is no restriction on which payload types nest. That means, among other things, that the payload type of a lead core is both covariant and contravariant ('bivariant').
560+Lead cores have more permissive nesting rules than either iron or zinc cores. There is no restriction on which payload types nest. That means, among other things, that the payload type of a lead core is both covariant and contravariant ('bivariant').
561
561
562−In order to preserve type safety when working with lead cores, a severe restriction is needed. The whole payload of a lead core is opaque -- the payload can neither be written-to or read-from. For this reason, as was the case with zinc cores, lead cores cannot be called as functions.
562+In order to preserve type safety when working with lead cores, a severe restriction is needed. The whole payload of a lead core is opaque -- the payload can neither be written-to or read-from. For this reason, as was the case with zinc cores, lead cores cannot be called as functions.
563
563
564−The arms of a lead core can still be evaluated, however. We can use the `^?` rune to convert a gold, iron, or zinc core to lead:
564+The arms of a lead core can still be evaluated, however. We can use the `^?` rune to convert a gold, iron, or zinc core to lead:
565
565
566```
566```
567> =lead-gate ^? |=(a=_22 (add 10 a))
567> =lead-gate ^? |=(a=_22 (add 10 a))