@@ -1,200 +0,0 @@
1−:- :~ navhome/'/docs/'
2− next/'true'
3− sort/'3'
4− title/'Recursion'
5− ==
6−;>
7−
8−# Recursion
9−
10−Recursion is a common pattern for solving certain problems in most programming
11−languages, and Hoon is no exception. One of the classically recursive problems
12−is that of factorial. The factorial of _n_ is the product of all positive
13−integers less than or equal to N. Thus the factorial of 5, denoted as _5!_,
14−would be:
15−
16−```
17−5 * 4 * 3 * 2 * 1 = 120
18−```
19−
20−### Factorial In Hoon
21−
22−Let's implement a factorial calculator in Hoon. To do so, we'll write a
23−recursive `gate` (Hoon's equivalent of a function) to perform the relevant
24−computation. Save the code below as `factorial.hoon` in your ship's `/gen`
25−directory.
26−
27−```
28−|= n=@ud
29−?: =(n 1)
30− 1
31−(mul n $(n (dec n)))
32−```
33−
34−Our `gate` takes one sample (argument) `n` that must nest inside `@ud`, the
35−unsigned-integer type.
36−
37−Next we check to see if `n` is `1`. If so, the result is just `1`, since
38−`1 * 1 = 1`.
39−
40−If, however, `n` is _not_ `1`, then we branch to the final line of the code,
41−`(mul n $(n (dec n)))`, where the recursion logic lives. Here, we multiply `n`
42−by the recursion of `n` minus `1`. `$` initiates recursion: it calls the gate
43−that we're already in, but replaces its sample.
44−
45−In our example, we multiply `n` with the product of this _entire gate
46−all over again_ with `$(n (dec n))`, except when that new gate has its sample
47−decremented by one. This works recursively because each new gate will, of
48−course, itself contain the code to call a further-decremented gate. Gates will
49−continue to call new, further-decremented gates until `n` is `1`, and that `1`
50−will be the final number to be multiplied by.
51−
52−Let's run the program in the Dojo:
53−
54−```
55−> +factorial 5
56−120
57−```
58−
59−It may help to visualize the operation of our example gate. The pseudo-Hoon below
60−illustrates what happens when we use it to find the factorial of 5:
61−
62−```
63−(factorial 5)
64−(mul 5 (factorial 4))
65−(mul 5 (mul 4 (factorial 3)))
66−(mul 5 (mul 4 (mul 3 (factorial 2))))
67−(mul 5 (mul 4 (mul 3 (mul 2 (factorial 1)))))
68−(mul 5 (mul 4 (mul 3 (mul 2 1))))
69−(mul 5 (mul 4 (mul 3 2)))
70−(mul 5 (mul 4 6))
71−(mul 5 24)
72−120
73−```
74−
75−It's easy to see how we're "floating" gate calls until we reach the final
76−iteration of such calls that only produces a value. The `mul n` component of the
77−gate leaves something like `mul 5`, waiting for the final series of terms
78−to be operated upon. The `$(n (dec n))` component is what expands out the
79−expression, as illustrated by `(factorial 4)`. Once the expression cannot be
80−expanded out further, the operations work backwards, successively feeding values
81−into the `mul` functions behind them.
82−
83−##### Tail-Call Optimization
84−
85−Our last example isn't a very efficient use computing resources. The
86−pyramid-shaped illustration approximates what's happening on the *call stack*, a
87−memory structure that tracks the instructions of the program. In our example
88−code, every time a parent gate calls another gate, the gate being called is
89−"pushed" to the top of the stack in the form of a frame. This process continues
90−until a value is produced instead of a function, completing the stack.
91−
92−```
93− Push order Pop order
94−(fifth frame) ^ |
95−(fourth frame) | |
96−(third frame) | |
97−(second frame) | |
98−(first frame) | V
99−```
100−
101−Once this stack of frames is completed, frames "pop" off the stack starting at
102−the top. When a frame is popped, it executes the contained gate and passes
103−produced data to the frame below it. This process continues until the stack
104−is empty, giving us the gate's output.
105−
106−When a program's final expression uses the stack in this way, it's considered to
107−be *not tail-recursive*. This usually happens when the last line of executable
108−code calls more than one gate, our example code's `(mul n $(n (dec n)))` being
109−such a case. That's because such an expression needs to hold each iteration of
110−`$(n (dec n)` in memory so that it can know what to run against the `mul`
111−function every time.
112−
113−To reiterate: if you have to manipulate the result of a recursion as the last
114−expression of your gate, as we did in our example, the function is not
115−tail-recursive, and therefore not very efficient with memory. A problem arises
116−when we try to recurse more times that we have space on the stack. This will
117−result in our computation failing and producing a stack overflow. If we tried
118−to find the factorial of `5.000.000`, for example, we would almost certainly
119−run out of stack space.
120−
121−But the Hoon compiler, like most compilers, is smart enough to notice when the
122−last statement of a parent can reuse the same frame instead of needing to
123−add new ones onto the stack. If we write our code properly, we can use a single
124−frame that simply has its values replaced with each recursion.
125−
126−##### A Tail-Recursive Gate
127−
128−With a bit of refactoring, we can write a version of our factorial gate that
129−_is_ tail-recursive and can take advantage of this feature:
130−
131−```
132−|= n=@ud
133−=/ t=@ud 1
134−|-
135−?: =(n 1)
136− t
137−$(n (dec n), t (mul t n))
138−```
139−
140−The above code should look familiar. We are still building a gate that
141−takes one argument `n`. This time, however, we are also putting a face on a
142−`@ud` and setting it's initial value to 1. The `|-` here is used to create a new
143−gate with one arm `$` and immediately call it. Think of `|-` as the recursion
144−point.
145−
146−We then evaluate `n` to see if it is 1. If it is we return the value of `t`. In
147−the case that `n` is anything other than 1, we perform our recursion:
148−
149−```
150−$(n (dec n), t (mul t n))
151−```
152−
153−All we are doing here is recursing our new gate and modifying the values of `n`
154−and `t`. `t` is used as an accumulator variable that we use to keep a running
155−total for the factorial computation.
156−
157−Let's use pseudo-Hoon to illustrate how the stack is working in this example for
158−factorial 5.
159−
160−```
161−(factorial 5)
162−(|- 5 1)
163−(|- 4 5)
164−(|- 3 20)
165−(|- 2 60)
166−(|- 1 120)
167−120
168−```
169−
170−We simply multiply `t` and `n` to produce the new value of `t`, and then
171−decrement `n` before repeating. Since this `$` call is the final and solitary
172−thing that is run in the default case and since we are doing all computation
173−before the call, this version is properly tail-recursive. We don't need to do
174−anything to the result of the recursion except recurse it again. That means that
175−each iteration can be replaced instead of held in memory.
176−
177−##### A Note on `$`
178−
179−`$` (pronounced "buc") is, in its use with recursion, a reference to the gate that we are inside
180−of. That's because a gate is just a core with a single arm named `$`. The
181−subject is searched depth-first, head before tail, with faces skipped, and
182−stopping on the first result. In other words, the first match found in the head
183−will be returned. If you wished to refer to the outer `$` in this context, the
184−idiomatic way would be to use [`^$`](/docs/reference/rune/ket). The `^` operator
185−skips the first match of a name.
186−
187−The syntax used is also the irregular form of the `%=` rune.
188−
189−### Exercises
190−
191−1. Write a recursive gate that produces the first _n_
192−[Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number)
193−
194−2. Write a recursive gate that produces a list of moves to solve the
195−[Tower of Hanoi problem](https://en.wikipedia.org/wiki/Tower_of_Hanoi).
196−Disks are stacked on a pole by decreasing order of size. Move all of the
197−disks from one pole to another with a third pole as a spare, moving one
198−disc at a time, without putting a larger disk on top of a smaller disk.
199−
200−### [Next Lesson: Multi-gate Cores and Doors](../multi-gate-cores-and-doors)