@@ -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)