on master help sign in
Merge pull request #566 from urbit/david-draft

Merge all the things

commit257e8ead7cd308f30b4a9c6007c787e291db476e authorrmariani <robert@tlon.io> dateThu 18 Jul 2019, 13:54 (7 years ago) parentcf6019833496ef
5 files changed+317−1
learn/hoon/hoon-tutorial/arms-and-cores.md+69 learn/hoon/hoon-tutorial/iron-polymorphism.md+90 learn/hoon/hoon-tutorial/lead-polymorphism.md+156 learn/hoon/hoon-tutorial/libraries.md+1 reference/hoon-expressions/rune/ket.md+1−1
learn/hoon/hoon-tutorial/arms-and-cores.md+69
@@ -404,6 +404,75 @@ Assume `this.is.a.wing` is a wing that resolves to an arm. You can use the `thi
404404
405405This almost looks like a function call of sorts.
406406
407+
408+### Cores, Gates, and Traps
409+
410+Let's take a quick look at the battery of one core in the dojo to show that this is true by inputting one into the dojo.
411+
412+```
413+> =dec |%
414+ ++ dec
415+ |= a=@
416+ ?< =(0 a)
417+ =+ b=0
418+ |- ^- @
419+ ?: =(a +(b)) b
420+ $(b +(b))
421+ --
422+
423+```
424+
425+This core has one arm `dec` which implements decrement. If we look at the head of the core we'll see the Nock.
426+
427+```
428+> -:dec
429+[ 8
430+ [1 0]
431+ [ 1
432+ 6
433+ [5 [1 0] 0 6]
434+ [0 0]
435+ 8
436+ [1 0]
437+ 8
438+ [1 6 [5 [0 30] 4 0 6] [0 6] 9 2 10 [6 4 0 6] 0 1]
439+ 9
440+ 2
441+ 0
442+ 1
443+ ]
444+ 0
445+ 1
446+]
447+```
448+
449+Again, being able to read Nock is not essential to understanding Hoon.
450+
451+Let's take a quick look at how cores can be combined to build up larger structures.
452+
453+```
454+=>
455+|%
456+++ dec
457+ |= a=@
458+ ?< =(0 a)
459+ =+ b=0
460+ |- ^- @
461+ ?: =(a +(b)) b
462+ $(b +(b))
463+--
464+|%
465+++ add
466+ |= [a=@ b=@]
467+ ^- @
468+ ?: =(0 a) b
469+ $(a (dec a), b +(b))
470+--
471+```
472+
473+Here you can see the style of wrapping one core in another. This technique is used frequently in Hoon, particularly in the standard library. `dec` is used in the subsequent core. This can be a useful code organization technique. Gates and Traps are both special kinds of cores, as you will see in later lessons.
474+
475+
407476## Summary
408477
409478At this point you should have a pretty good understanding of what an arm is, and how wing resolution to an arm works. But so far the arms you've created have been fairly simple. In the next lesson you'll learn about Hoon functions, and how to create your own.
learn/hoon/hoon-tutorial/iron-polymorphism.mdnew file+90
@@ -0,0 +1,90 @@
1++++
2+title = "2.5.1 Walkthrough: Iron Polymorphism and Wet Polymorphism"
3+weight = 32
4+template = "doc.html"
5++++
6+
7+Polymorphism is a programming concept that allows a a piece of code to use different types at different times. It's a common technique in most languages to make code that can be reused for many different situations, and Hoon is no exception. Let's take a look at a gate from the Hoon standard library as an example; we'll be passing a few different types in. The code below is an excerpt from `hoon.hoon` and, as such, will not run as-is by itself.
8+
9+`fold` is a _wet_ gate that takes two arguments and produces a _dry_ gate. But what are wet and dry gates?
10+
11+A dry gate (also simply a _gate_) is the kind that you're already familiar with by now: a one-armed core with a sample. A wet gate is also a one-armed core with a sample, but there is a difference. With a dry gate, when you pass in an argument and the code gets compiled, the type system will try to cast to the type specified by the gate; if you pass something that does not fit in the specified type, for example a `cord` instead of a `cell` you will get a nest failure. On the other hand, when you pass arguments to a wet gate, their types are preserved and type analysis is done at the definition site of the gate -- in our case, `fold` in `hoon.hoon` -- rather than the call site.
12+
13+```
14+++ fold
15+ |* [state=mold elem=mold]
16+ |= [[st=state xs=(list elem)] f=$-([state elem] state)]
17+ ^- state
18+ |-
19+ ?~ xs st
20+ $(xs t.xs, st (f st i.xs))
21+```
22+
23+On the first line of the arm, we use `|*` to create a wet gate, with two arguments: `state` and `elem`. These arguments are both `mold`s; that is to say, they are type definitions. We use this to define the types used in the dry gate.
24+
25+```
26+|= [[st=state xs=(list elem)] f=$-([state elem] state)]
27+```
28+
29+Here we begin to define our dry gate. The first thing the dry gate takes is a cell, `[st=state xs=(list elem)]`. `state` is the type we passed in first to our wet gate, and will be the type that is produced by the dry gate. `st` is a value of type `state` that will be used as an accumulator, and will be the final value returned when the dry gate is called.
30+
31+The second argument is `f=$-([state elem] state)`. `$-` is a rune that takes two type arguments, `[state elem]` and `state` in this case, and produces a `mold` of a gate that maps from the first type operand to the second. This will match a gate we provide `fold` for how to map from both the `state`.
32+
33+The rest of the dry gate is straightforward:
34+
35+```
36+ ^- state
37+ |-
38+ ?~ xs st
39+ $(xs t.xs, st (f st i.xs))
40+```
41+
42+We ensure the output is of type `state`. Then we check if `xs`, the list, is empty. If it is, we return `st`. Otherwise, we call `f` on `i.xs`, the head of the list, and set `xs` to be the tail of the list and repeat.
43+
44+Lets look at two examples of using `fold`.
45+
46+```
47+%+ (fold (list @) @)
48+ :- ~
49+ ~[1 2 3 4]
50+|= [s=(list @) e=@]
51+:_ s
52+(add 2 e)
53+```
54+
55+Here we have a call to `fold` that we can see will produce a `(list @)` from a list of `@`. The first argument is a cell of `~` and `~[1 2 3 4]`.
56+
57+
58+The gate will simply add two to each element `e` and append that to the front of `s`. Let's run this in the `dojo`:
59+
60+```
61+> %+ (fold (list @) @)
62+ :- ~
63+ ~[1 2 3 4]
64+ |= [s=(list @) e=@]
65+ :_ s
66+ (add 2 e)
67+~[6 5 4 3]
68+
69+~zod:dojo>
70+```
71+
72+The list is in reverse order simply because it's easier to add to the front of a list than the end. If you needed it in the same order, you could just `flop` it.
73+
74+But `fold` does not have to produce a `list`. Let's look at another example:
75+
76+
77+```
78+%+ (fold @ @)
79+ [0 ~[1 2 3 4]]
80+|= [s=@ e=@]
81+(add e s)
82+```
83+
84+
85+Here `fold` will produce a gate that takes an `atom` and applies a gate to a `list` of `atoms`. The difference here is that this call will produce a sum of the elements of the list, rather than the list itself.
86+
87+The key takeaway from both of these examples is that the gates provided are _iron polymorphic_ with respect to the definition of the type in `fold`. They are iron polymorphic because samples `s` and `e` nest under the types `state` and `elem`. In second case case, that's because when we provided those to `fold`, it was was stated they were `@` and `@`. In the first case, we stated that `state` was `(list @)` and `elem` was `@`. In both cases, the sample of each gate nest inside the types defined when we called the wet gate `fold`.
88+
89+
90+[Next Up: Walkthrough -- Lead Polymorphism](../lead-polymorphism)
learn/hoon/hoon-tutorial/lead-polymorphism.mdnew file+156
@@ -0,0 +1,156 @@
1++++
2+title = "2.5.2 Walkthrough: Lead Polymorphism"
3+weight = 33
4+template = "doc.html"
5++++
6+
7+There are four kinds of cores: gold, iron, zinc, and lead. You are able to use core-variance rules to create programs which take other programs as arguments. Which particular rules depends on which kind of core your program needs to complete.
8+
9+Lead cores have opaque payloads. That is, the payload can not be written to or read from. Below is an example of using lead cores. The program produces a list populated by the first 10 elements of `fib`.
10+
11+```
12+=< (to-list (take fib 10))
13+|%
14+++ stream
15+ |* of=mold
16+ $_ ^? |.
17+ ^- $@(~ [item=of more=^$])
18+ ~
19+++ stream-type
20+ |* s=(stream)
21+ $_ => (s)
22+ ?~ . !!
23+ item
24+++ to-list
25+ |* s=(stream)
26+ %- flop
27+ =| r=(list (stream-type s))
28+ |- ^+ r
29+ =+ (s)
30+ ?~ - r
31+ %= $
32+ r [item r]
33+ s more
34+ ==
35+++ take
36+ |* [s=(stream) n=@]
37+ =| i=@
38+ ^+ s
39+ |.
40+ ?: =(i n) ~
41+ =+ (s)
42+ ?~ - ~
43+ :- item
44+ %= ..$
45+ i +(i)
46+ s more
47+ ==
48+++ fib
49+ ^- (stream @ud)
50+ =+ [p=0 q=1]
51+ |. :- q
52+ %= .
53+ p q
54+ q (add p q)
55+ ==
56+--
57+```
58+
59+There are five arms in this core: `stream`, `stream-type`, `to-list`, `take`, and `fib`.
60+
61+
62+```
63+++ stream
64+ |* of=mold
65+ $_ ^? |.
66+ ^- $@(~ [item=of more=^$])
67+ ~
68+```
69+
70+`stream` is a mold-builder. It's a wet gate that takes one argument, `of`, which is a `mold`, and produces a trap -- a function with no argument.
71+
72+`$_` is a rune that produces a type from an example; `^?` converts (casts) a core to lead; `|.` forms the trap. So to follow this sequence we read it backwards: we create a trap, convert it to a lead trap (making its payload inaccessible), and then use that lead trap as an example to produce a type from.
73+
74+With the line `^- $@(~ [item=of more=^$])`, the output of the trap will be cast into a new type. `$@` is the rune to describe a data structure that can either be an atom or a cell. The first part describes the atom, which here is going to be `~`. The second part describes a cell, which we define to have the head of type `of` with the face `item`, and a tail with a face of `more`. The expression `^$` is not a rune, but rather a reference to the enclosing wet gate, so the tail of this cell will be of the same type produced by this wet gate.
75+
76+The final `~` here is used as the type produced when initially calling this wet gate. This is valid because it nests within the type we defined on the previous line.
77+
78+Now you can see that a `stream` is either `~` or a pair of a value of some type and a `stream`. This type represents an infinite series.
79+
80+```
81+++ stream-type
82+ |* s=(stream)
83+ $_ => (s)
84+ ?~ . !!
85+ item
86+```
87+
88+`stream-type` is a wet gate that produces the type of items stored in the `stream` arm. The `(stream)` syntax is a shortcut for `(stream *)`; a stream of some type.
89+
90+Calling a `stream`, which is a trap, will either produce `item` and `more` or it will produce `~`. If it does produce `~`, the `stream` is empty and we can't find what type it is, so we simply crash with `!!`.
91+
92+```
93+++ take
94+ |* [s=(stream) n=@]
95+ =| i=@
96+ ^+ s
97+ |.
98+ ?: =(i n) ~
99+ =+ (s)
100+ ?~ - ~
101+ :- item
102+ %= ..$
103+ i +(i)
104+ s more
105+ ==
106+```
107+
108+We're going to skip over `to-list` and examine `take` first. `take` is another wet gate. This time it takes a `stream` `s` and an atom `n`. We add an atom to the subject and then make sure that the trap we are creating is going to be of the same type as `s`, the `stream` we passed in.
109+
110+If `i` and `n` are equal, the trap will produce `~`. Otherwise, `s` is called and has its result put on the front of the subject. If its value is `~`, then the trap again produces `~`. Otherwise the trap produces a cell of `item`, the first part of the value of `s`, and a new trap that increments `i`, and sets `s` to be the `more` trap which produces the next value of the `stream`. The result here is a `stream` that will only ever produce `n` items, even if the stream otherwise would have been infinite.
111+
112+```
113+++ to-list
114+ |* s=(stream)
115+ %- flop
116+ =| r=(list (stream-type s))
117+ |- ^+ r
118+ =+ (s)
119+ ?~ - r
120+ %= $
121+ r [item r]
122+ s more
123+ ==
124+```
125+
126+Now with that in hand, let's go back to `to-list`. It's also a wet gate that takes `s`, a `stream`, only here it will, as you might expect, produce a `list`. The rest of this wet gate is straightforward, but we can examine it quickly anyway. As is the proper style, this list that is produced will be reversed, so `flop` is used to put it in the order it is in the stream. Recall that adding to the front of a list is cheap, while adding to the back is expensive.
127+
128+`r` is added to the subject as an empty `list` of whatever type is produced by `s`. A new trap is formed and called, and it will produce the same type as `r`. Then `s` is called and has its value added to the subject. If the result is `~`, the trap produces `r`. Otherwise, we want to call the trap again, adding `item` to the front of `r` and changing `s` to `more`. Now the utility of `take` should be clear. We don't want to feed `to-list` an infinite stream as it would never terminate.
129+
130+```
131+++ fib
132+ ^- (stream @ud)
133+ =+ [p=0 q=1]
134+ |. :- q
135+ %= .
136+ p q
137+ q (add p q)
138+ ==
139+```
140+
141+The final arm in our core is `fib`, which is a `stream` of `@ud` and therefore an iron core. It's subject contains `p` and `q`, which will not be accessible outside of this trap. The product of the trap is a pair of an `@ud` and the trap that will produce the next `@ud` in the Fibonacci series.
142+
143+
144+```
145+=< (to-list (take fib 10))
146+```
147+
148+Finally, the first line of our program will take the first 10 elements of `fib` and produce them as a list.
149+
150+```
151+~[1 1 2 3 5 8 13 21 34 55]
152+```
153+
154+This example is a bit overkill for simply calculating the Fibonacci series, but it nicely illustrates how you might use iron cores. Instead of `fib`, you could have any `stream` that produces some stream of values and you'd still be able to use the `take`, `to-list`, and `stream-type` arms.
155+
156+[Next Up: Reading -- Gall](../gall)
learn/hoon/hoon-tutorial/libraries.md+1
@@ -166,6 +166,7 @@ This is a very naive shuffling algorithm, and you could imagine a better one. Im
166166
167167## Using the Library
168168
169+
169170So now that we have this library, how do we actually use it? Let's look at a very simple `say` generator that takes advantage of what we built.
170171
171172```
reference/hoon-expressions/rune/ket.md+1−1
@@ -139,7 +139,7 @@ mint-vain
139139
140140Regular: **2-fixed**.
141141
142−Irregular: `` `foo`baz`` is `^-(foo baz)`.
142+Irregular: `` `foo`baz`` is `^-(foo ^-(@ baz))`.
143143
144144##### Discussion
145145