@@ -1,888 +0,0 @@
1−+++
2−title = "Simple One-Gate Programs"
3−weight = 23
4−template = "doc.html"
5−+++
6−In this lesson we'll try to cover enough basic Hoon so that you can write (and understand) your own simple programs. Each of the programs given in this lesson produces a gate. (Gates are one-armed cores of Hoon that can be used as functions -- this is covered in [lesson 1.5](../gates).)
7−
8−For each program we encourage you to: (1) write out the program yourself, (2) save it to the `/home/gen` directory of your urbit's pier, and (3) run it from the dojo. The best way to learn to program in Hoon is by getting your hands dirty.
9−
10−We will also continue to run one-line snippets of code in the dojo. We encourage you to enter these for yourself as well.
11−
12−## Writing Gates: A Review
13−
14−Let's look at a really simple gate: `|=(a=@ 15)`. This gate takes any atom as input and returns the value `15`.
15−
16−The `|=` rune takes two subexpressions. The first must indicate a type, and the second may evaluate to any value. The first defines the gate's sample type and possibly binds a face to it, and the second defines the output of the gate. In the example `|=(a=@ 15)` the `|=` subexpressions are `a=@` and `15`.
17−
18−The following characters represent basic Hoon types: `@` for atoms, `^` for cells, `?` for flags, and `*` for nouns. You should already know what atoms, cells, and nouns are. (See [lesson 1.2](../nouns) if you need a reminder.) There are two values for the `?` type: `%.y` for yes, and `%.n` for no. In other words, `?` is for the [Boolean values](https://en.wikipedia.org/wiki/Boolean_data_type) of Hoon.
19−
20−You could have picked a different type for the first subexpression of `|=(a=@ 15)` and left off the face. To illustrate this let's call different versions of the gate with the `(gate arg)` function call syntax:
21−
22−```
23−> (|=(@ 15) 11)
24−15
25−
26−> (|=(@ 15) 22)
27−15
28−
29−> (|=(* 15) 22)
30−15
31−
32−> (|=(^ 15) 11)
33−nest-fail [crash message]
34−```
35−
36−The argument for each of these function calls is either `11` or `22`. These are atoms, `@`, and hence also nouns, `*`. So when you define the sample to be either `@` or `*` the evaluation works as desired.
37−
38−In the last function call, however, the gate's sample is defined to be a cell, `^`, and `11` isn't a cell. This is why, when that gate is called with `11`, the result is a `nest-fail` crash message. For all function calls, Hoon's type system checks whether the type of the argument matches the type of the sample. If not, the the function will not be evaluated and you get the `nest-fail`. (What counts as "nesting" will be covered more carefully in the next few lessons.)
39−
40−Ordinarily a face is included in the first subexpression after the `|=` rune. This makes it easier to refer to the sample in the second `|=` subexpression. Usually you'll want the gate product to depend on the arguments passed.
41−
42−```
43−> (|=(a=@ (add 2 a)) 12)
44−14
45−
46−> (|=(a=@ (add 2 a)) 14)
47−16
48−```
49−
50−### Checking the Gate's Output
51−
52−You are probably fallible. A fallible person will, at least occasionally, write code that produces output of the wrong type. Hoon's type system is designed to help you avoid this problem, but to take full advantage of this help you have to ask. You can do this with a 'cast' expression. It is good practice to include a cast in every gate expression you write in Hoon.
53−
54−A cast is a test that the value produced by an expression is provably of the desired type. When the code is compiled, the compiler does type inference on the expression in question. (We'll talk in more detail about how Hoon's type inference works later in the chapter.) If the inferred type 'nests' under the desired type then the cast succeeds and the program is compiled. Otherwise, the compile halts with a `nest-fail` crash. In the latter case the program -- at least potentially -- produces the wrong kind of value and needs to be debugged.
55−
56−There are different ways to cast, but for now we'll just use the `^-` rune. Consider the even number checker given in the last lesson:
57−
58−```
59−|= a=@ :: even number checker
60−^- ? :: output is a flag
61−=(0 (mod a 2)) :: if remainder=0 'yes'
62−```
63−
64−The first subexpression after `|=` is `a=@`, and the second is the rather more complex:
65−
66−```
67−^- ?
68−=(0 (mod a 2))
69−```
70−
71−This latter subexpression begins with the `^-` rune, which itself takes two subexpressions. The first `^-` subexpression must indicate a type, `?`, and the second is to be evaluated, `=(0 (mod a 2))`. The value of the second subexpression is the value produced by the whole `^-` expression.
72−
73−The inferred type of `=(0 (mod a 2))` is compared against `?`. If the former type fits under the latter, the type-check passes. Otherwise the program will fail to compile, `nest-fail`.
74−
75−Save the even number checker to the `/home/gen` directory of your pier as `even.hoon` and run it from the dojo:
76−
77−```
78−> +even 11
79−%.n
80−
81−> +even 22
82−%.y
83−```
84−
85−Now replace the `=(0 (mod a 2))` in the third line with just `15`. The result:
86−
87−```
88−|= a=@ :: even number checker
89−^- ? :: output is a flag
90−15 :: return 15
91−```
92−
93−Save this and try to run it from the dojo again:
94−
95−```
96−> +even 22
97−nest-fail
98−```
99−
100−You changed the gate so that the output is `15`, which is an atom, `@`. But you're casting for a flag, `?` -- either `%.y` or `%.n`. Because `@` doesn't nest under `?` the program fails to compile.
101−
102−### Multiple Inputs and Outputs
103−
104−A gate is a one-armed core with a sample:
105−
106−```
107− [gate]
108− / \
109− [$ arm] [payload]
110− / \
111− [sample] [context]
112−```
113−
114−When a function call to a gate occurs, the `$` arm is evaluated with the gate itself as the subject. But the gate's payload is usually modified. The modification in question is to the sample: the default gate sample is replaced with the argument(s) of the function call. This is how the `$` arm 'knows' what the argument(s) of the function are.
115−
116−The sample is just the noun in that slot of the gate, `+6`. The product of the arm evaluation is just another noun. Thus, gates always have a single noun for input and a single noun for output.
117−
118−But we would like to use functions that take multiple inputs as well as functions with multiple outputs. How? The obvious solution is to use cells.
119−
120−Let's write a program that checks two numbers at a time and tells us if each is even:
121−
122−```
123−::
124−:: even2.hoon
125−::
126−:: this gate takes a pair of atoms, tests whether each is even, and then
127−:: returns two flags.
128−::
129−|= [a=@ b=@] :: check two numbers
130−^- [? ?] :: output is two flags
131−:- =(0 (mod a 2)) :: :-(x y) makes [x y]
132−=(0 (mod b 2)) ::
133−```
134−
135−The first `|=` subexpression is now `[a=@ b=@]`. This indicates a complex type for the gate's sample. The gate takes a pair of atoms, labeling the first `a` and the second `b`.
136−
137−The second `|=` subexpression is:
138−
139−```
140−^- [? ?]
141−:- =(0 (mod a 2))
142−=(0 (mod b 2))
143−```
144−
145−The first of two `^-` subexpressions is `[? ?]`, indicating another complex type. The inferred type of the second `^-` subexpression must be a cell of two flags, or else the program will fail to compile. The second `^-` subexpression:
146−
147−```
148−:- =(0 (mod a 2))
149−=(0 (mod b 2))
150−```
151−
152−The `:-` rune takes two subexpressions and makes them into a cell. Each of these, `=(0 (mod a 2))` and `=(0 (mod b 2))`, evaluates to a flag value, `?`.
153−
154−Save the whole program in your pier as `even2.hoon` (or as something else if you like) and test it in the dojo. Remembering to pass the two arguments as a cell:
155−
156−```
157−> +even2 [2 2]
158−[%.y %.y]
159−
160−> +even2 [2 3]
161−[%.y %.n]
162−
163−> +even2 [3 3]
164−[%.n %.n]
165−
166−> +even2 [22 33]
167−[%.y %.n]
168−```
169−
170−A gate may take as input or produce as output arbitrarily complex cells. For example, one could write a gate that takes a cell of five different things:
171−
172−```
173−|= [a=* b=@ud c=^ d=? e=@sb]
174−...
175−```
176−
177−## Basic Tools
178−
179−### `.+` and `.=`
180−
181−The `.+` rune is for 'incrementing'; it takes an atom and adds `1` to it. That's it! Here it is in action:
182−
183−```
184−> .+ 22
185−23
186−
187−> .+(22)
188−23
189−
190−> .+(101)
191−102
192−```
193−
194−But it's nearly always used in its irregular form, which lacks the `.`:
195−
196−```
197−> +(22)
198−23
199−
200−> +(101)
201−102
202−```
203−
204−You've already used the `.=` rune in its irregular form, `=( )`. This rune takes two subexpressions, evaluates them, and then does a simple test of equality on the resulting values.
205−
206−```
207−> =(22 11)
208−%.n
209−
210−> =(22 (add 11 11))
211−%.y
212−```
213−
214−But there's one more quirk that you should know about: `.=(a b)` includes a type check. Of the inferred types of `a` and `b`, one must nest in the other or else the code won't compile:
215−
216−```
217−> =(12 [12 14])
218−nest-fail
219−```
220−
221−The inferred type of `12` is `@ud`, and the inferred type of `[12 14]` is `[@ud @ud]`. Neither type nests under the other, so the code fails to compile. There is a way to get around this type check, which we'll explain later in this chapter. The best policy is to avoid wiggling out of type safety checks, however.
222−
223−### Introduction to Conditionals: The `?` Rune Family
224−
225−We won't cover all the `?` runes here -- we'll save some for the upcoming lesson on types. But we'll cover enough to get you writing simple Hoon programs.
226−
227−#### `?:` if-then-else
228−
229−The `?:` rune indicates an 'if-then-else' expression and takes three subexpressions: (1) the condition, which must evaluate to a flag, (2) an expression to be evaluated if the condition evaluates to `%.y`, and (3) an expression to be evaluated if the condition evaluates to `%.n`.
230−
231−```
232−> ?:(%.y 11 22)
233−11
234−
235−> ?: %.y
236− 11
237− 22
238−11
239−
240−> ?:(%.n 11 22)
241−22
242−```
243−
244−#### `?.` ifnot-then-else
245−
246−The `?.` rune does precisely the same thing as `?:`, except reversed: if the condition evaluates to `%.n` then the second subexpression is evaluated, otherwise the third is evaluated.
247−
248−```
249−> ?.(%.y 11 22)
250−22
251−
252−> ?. %.y
253− 11
254− 22
255−22
256−
257−> ?.(%.n 11 22)
258−11
259−```
260−
261−The reasons for Hoon's having both `?:` and `?.` involve code neatness and clarity. Use whichever makes your code better.
262−
263−#### `?&` logical 'AND'
264−
265−The `?&` rune is for logical 'AND'. It takes two or more subexpressions, each of which must evaluate to a flag, `?`; and if all of them evaluate to `%.y` then the result of the `?&` expression is `%.y`. Otherwise it's `%.n`. In tall form the expression is terminated with `==`.
266−
267−```
268−> ?& %.y %.y %.y ==
269−%.y
270−
271−> ?& & | & ==
272−%.n
273−
274−> ?&(%.y %.y %.y)
275−%.y
276−
277−> ?&(& =(1 2) &)
278−%.n
279−```
280−
281−You may be confused about the lone `&` and `|` characters in the second and fourth examples above. The `&` character (used by itself) is another alias for 'yes', and `|` (used by itself) is another alias for 'no':
282−
283−```
284−> &
285−%.y
286−
287−> |
288−%.n
289−```
290−
291−The irregular form of `?&` allows you to drop the `?` symbol:
292−
293−```
294−> &(& & &)
295−%.y
296−
297−> &(| & &)
298−%.n
299−
300−> &(& | &)
301−%.n
302−
303−> &(& & |)
304−%.n
305−```
306−
307−To be clear, in `&(blah-1 blah-2)` the `&()` is the irregular `?&` rune; and anywhere else in the code `&` by itself means 'yes', `%.y`.
308−
309−#### `?|` logical 'OR'
310−
311−The `?|` rune is for logical 'OR'. It takes two or more subexpressions, each of which must evaluate to a flag, `?`. If at least one evaluates to `%.y` then the whole `?|` expression evals to `%.y`; otherwise it's `%.n`:
312−
313−```
314−> ?| %.n %.n %.n ==
315−%.n
316−
317−> ?| | | & ==
318−%.y
319−
320−> ?|(=(12 12) | |)
321−%.y
322−```
323−
324−The irregular form drops the `?` symbol:
325−
326−```
327−> |(=(12 12) | |)
328−%.y
329−
330−> |(=(12 13) | |)
331−%.n
332−```
333−
334−#### `?!` logical 'NOT'
335−
336−The `?!` rune is for logical 'NOT'. It takes one subexpression that evaluates to a flag and returns the opposite value.
337−
338−```
339−> ?! &
340−%.n
341−
342−> ?!(|)
343−%.y
344−```
345−
346−The irregular form drops the `?` symbol and uses no parentheses:
347−
348−```
349−> !|
350−%.y
351−
352−> =(22 33)
353−%.n
354−
355−> !=(22 33)
356−%.y
357−```
358−
359−#### Are All Three Even?
360−
361−Let's write a program that takes three atoms, `@`, and returns `%.y` if they're all even, otherwise `%.n`.
362−
363−```
364−|= [a=@ b=@ c=@] :: check three @
365−^- ? :: output is a flag
366−?& =(0 (mod a 2)) :: `a` is even AND
367− =(0 (mod b 2)) :: `b` is even AND
368− =(0 (mod c 2)) :: `c` is even
369−==
370−```
371−
372−Save this in your urbit's pier as `even3.hoon` and run it from the dojo:
373−
374−```
375−> +even3 [12 13 14]
376−%.n
377−
378−> +even3 [12 16 14]
379−%.y
380−```
381−
382−#### If So, Multiply -- Otherwise Add
383−
384−Let's write a slightly more complicated program. The gate takes three atoms, `@`, and if all three are even it multiplies all of them together. Otherwise, it adds them all together.
385−
386−```
387−|= [a=@ b=@ c=@] :: take three @
388−^- @ :: output is an @
389−?: ?& =(0 (mod a 2)) :: if `a` is even AND
390− =(0 (mod b 2)) :: `b` is even AND
391− =(0 (mod c 2)) :: `c` is even
392− ==
393− (mul a (mul b c)) :: then multiply
394−(add a (add b c)) :: otherwise add
395−```
396−
397−Save this as `addmul.hoon` and try it from the dojo:
398−
399−```
400−> +addmul [2 2 2]
401−8
402−
403−> +addmul [2 2 3]
404−7
405−
406−> +addmul [4 4 4]
407−64
408−
409−> +addmul [4 4 5]
410−13
411−```
412−
413−### Subject Modification: The `=` Rune Family
414−
415−As with the `?` family, we won't explain all the runes of the `=` family -- just a few to get you started.
416−
417−#### `=>` Evaluate a Hoon Against a Subject
418−
419−The `=>` rune takes two subexpressions. The first is evaluated, with the result becoming the new subject; the second subexpression is evaluated against that subject.
420−
421−A few examples:
422−
423−```
424−> => [[a=12 b=14] [c=16 d=18]] +
425−[c=16 d=18]
426−
427−> => [[a=12 b=14] [c=16 d=18]] -
428−[a=12 b=14]
429−
430−> => [[a=12 b=14] [c=16 d=18]] +>
431−d=18
432−
433−> => [[a=12 b=14] [c=16 d=18]] a
434−12
435−
436−> => [[a=12 b=14] [c=16 d=18]] d
437−18
438−```
439−
440−#### `=<` Evaluate a Hoon Against a Subject, Reversed
441−
442−The `=<` rune is just like `=>` but reversed. The second subexpression is evaluated, with the result becoming the new subject; the first subexpression is evaluated against that subject.
443−
444−A few examples:
445−
446−```
447−> =< + [[a=12 b=14] [c=16 d=18]]
448−[c=16 d=18]
449−
450−> =< - [[a=12 b=14] [c=16 d=18]]
451−[a=12 b=14]
452−
453−> =< +> [[a=12 b=14] [c=16 d=18]]
454−d=18
455−
456−> =< a.- [[a=12 b=14] [c=16 d=18]]
457−12
458−
459−> =< d.+ [[a=12 b=14] [c=16 d=18]]
460−18
461−```
462−
463−The `=>` and `=<` runes should seem vaguely familiar, in spirit if not otherwise. You've already used the irregular version of `=<`, with the `:` character:
464−
465−```
466−> +:[[a=12 b=14] [c=16 d=18]]
467−[c=16 d=18]
468−
469−> -:[[a=12 b=14] [c=16 d=18]]
470−[a=12 b=14]
471−
472−> +>:[[a=12 b=14] [c=16 d=18]]
473−d=18
474−
475−> a:[[a=12 b=14] [c=16 d=18]]
476−12
477−
478−> d:[[a=12 b=14] [c=16 d=18]]
479−18
480−```
481−
482−#### `=+` 'Pin' a Noun to the Subject
483−
484−The `=+` rune takes two subexpressions. The first is evaluated and then the resulting value is 'pinned' to the head of the subject -- that is, the old subject becomes the tail of the new subject, and the value produced by the first `=+` subexpression becomes the head of the new subject. The second `=+` subexpression is evaluated against the new subject. Examples:
485−
486−```
487−> => [22 33 44] =+(101 -)
488−101
489−
490−> => [22 33 44] =+(101 +)
491−[22 33 44]
492−
493−> => [22 33 44] =+(101 +1)
494−[101 22 33 44]
495−
496−> => [b=22 c=33 d=44] a
497−-find.a
498−
499−> => [b=22 c=33 d=44] =+(a=101 a)
500−101
501−```
502−
503−#### `=/` Pin a Faced (and Possibly Typed) Noun To the Subject
504−
505−The `=/` rune is a more powerful variation of `=+`. `=/` takes three subexpressions: (1) the first is the face for the noun to be pinned (e.g., `a`), and possibly includes a type (e.g., `a=@`); (2) the second is the noun to be pinned; and (3) the third is the expression to be evaluated on the modified subject.
506−
507−Some examples:
508−
509−```
510−> =/(b=@ 22 [b b b])
511−[22 22 22]
512−
513−> =/(b=@ 22 (add b b))
514−44
515−```
516−
517−The `=/` rune is the closest thing Hoon has to an instruction for 'initializing a variable' while giving it an initial value. What actually occurs in Hoon is that the value is pinned to the head of the subject, and the indicated face is bound to that value.
518−
519−#### `=|` Pin a Faced, Typed Default Noun to the Subject
520−
521−The `=|` is a lot like the `=/` rune except that (1) you must include type information when you use it, and (2) the programmer doesn't set the initial value of the face -- it's a default value for the type in question, sometimes called a 'bunt' value. The `=|` rune takes two subexpressions. The first is a face names (e.g., `a`), followed by `=`, followed by a type (e.g., `@`). The second is to be evaluated against the modified subject.
522−
523−```
524−> =| a=@ a
525−0
526−
527−> =| a=^ a
528−[0 0]
529−
530−> =| a=? a
531−%.y
532−```
533−
534−The `=|` rune is a lot like 'initializing a variable' but for faces, without giving the face an interesting initial value (a default value for the type is used instead, i.e., the 'bunt' value).
535−
536−#### `=.` Change a Leg of the Subject
537−
538−The `=.` rune takes three subexpression. The first is a wing expression, indicating the leg of the subject whose value is to be changed. The second is the new value for the indicated leg. The third is the expression to be evaluated against the modified subject.
539−
540−```
541−> =/ a=@ 22 =.(a 99 a)
542−99
543−
544−> =/ a=@ 22 [a =.(a 99 a)]
545−[22 99]
546−
547−> => [12 14] =.(+2 22 .)
548−[22 14]
549−```
550−
551−This rune is often used for modifying the value of a face whose value was set beforehand.
552−
553−## Recursion
554−
555−How do we do loops in Hoon? Like other functional programming languages Hoon uses [recursion](https://en.wikipedia.org/wiki/Recursion_%28computer_science%29). In rough terms, a recursive function solves a problem in part by calling on itself to solve a slightly easier or smaller case of the same problem. The self-calling loop continues until the simplified problem is so simple that it has a trivial solution.
556−
557−Seeing an example will make this process easier to understand.
558−
559−### Addition
560−
561−Let's write a gate that takes a pair of atoms, `@`, and which returns the sum of these atoms. There is a cheap solution to this problem, of course. The Hoon standard library has `add` in it:
562−
563−```
564−> (add 22 33)
565−55
566−```
567−
568−But let's solve the problem without using `add` from the Hoon standard library. We have the `.+` rune for adding `1` and the `.=` rune for testing equality. We'll also use `dec` from the standard library and some recursion. That's it!
569−
570−What's `dec`? It takes some atom, `@`, and returns the decrement -- i.e., it takes some number `a` and returns `a - 1`:
571−
572−```
573−> (dec 101)
574−100
575−
576−> (dec 51)
577−50
578−
579−> (dec 11)
580−10
581−```
582−
583−For adding two atoms together, the algorithm we'll use is very simple. We start with two numbers, `a` and `b`. If `b` is `0`, then the answer is `a`. (This is the trivial case of addition for our algorithm, sometimes also called the 'base' case.) Otherwise, the answer is the sum of `a + 1` and `b - 1` -- now do **that** addition. (This is the **recursive** case.)
584−
585−Do you see how this process calls for a loop of sorts? If you want to sum `7` and `2`, check to see whether the second number is `0`. It isn't, so now figure out the sum of `8` and `1`. Is the second number `0`? No, so do the sum of `9` and `0`. Now the second number is `0` -- the answer is `9`.
586−
587−Here's the program:
588−
589−```
590−|= [a=@ b=@] :: take two @
591−^- @ :: output is one @
592−?: =(b 0) :: if b is 0
593− a :: return a, else
594−$(a +(a), b (dec b)) :: add a+1 and b-1
595−```
596−
597−Save it as `add.hoon` in your urbit's pier and run it from the dojo:
598−
599−```
600−> +add [22 33]
601−55
602−
603−> +add [122 33]
604−155
605−```
606−
607−It works!
608−
609−Every line of `add.hoon` should be clear up to the last one. What's going on there? The `$( )` is used for recursive function calls. That is, it's a way for a function to call itself, but with certain values modified according to the instructions inside the parentheses. Two values are being modified for the call: `a` is modified to `+(a)`, and `b` is modified to `(dec b)`. A comma is used to separate the two modification instructions. (Of course, in programs that call for it, more than two modifications may be made here.)
610−
611−### `%=` Resolve to a Wing with Changes
612−
613−The `$( )` syntax is an irregular form of the the `%=` rune. We can rewrite that part of `add.hoon` in regular form:
614−
615−```
616−|= [a=@ b=@] :: take two @
617−^- @ :: output is one @
618−?: =(b 0) :: if b is 0
619− a :: return a, else
620−%= $ :: resolve to $
621− a +(a) :: but change a to +(a)
622− b (dec b) :: and b to (dec b)
623−==
624−```
625−
626−This version is precisely equivalent to the old one. The first `%=` subexpression is for a wing. In the program above, this is just `$`. The other subexpressions of `%=` indicate the changes to be made upon resolution to the wing. You can make as many of these changes as desired when using `%=`, so the expression is ended with `==`.
627−
628−Remember from lessons [1.4](../arms-and-cores) and [1.5](../gates) that wing resolution works in two different ways. If the wing resolves to a leg, that fragment of the subject is returned. If the wing resolves to an arm, the arm is evaluated with its parent core as the subject. In [lesson 1.5](../gates) you learned that `$` is the special name of the arm of a gate. (Remember, a gate is a one-armed core with a sample.) Because we wrote `add.hoon` with `|=` it produces a gate. The `%=` expression above thus evaluates the `$` arm of the gate, but only after having made changes to the parent core: `a` is incremented, and `b` is decremented.
629−
630−### Decrement
631−
632−We've used `dec`, but now let's write our own version. That is, let's write a gate that takes some atom, `@`, and returns the 'decrement' of that value. There is a cheap solution to this problem too. The Hoon standard library has the `sub` function in it for subtraction:
633−
634−```
635−> (sub 100 50)
636−50
637−
638−> (sub 100 1)
639−99
640−```
641−
642−But let's solve the problem without using the Hoon standard library. We have the `.+` rune for adding `1`, the `.=` rune for testing equality, and various runes of the `=` family for manipulating the subject. And we'll again use recursion.
643−
644−How do we decrement using only those tools? The algorithm is pretty simple. We'll start by defining a counter value, `0`, and binding it to `c`.
645−
646−If `c + 1` equals the value to be decremented, then `c` is the answer. (This is the trivial case.) Otherwise, we increment `c` by `1` and try again. (This is the recursive case.)
647−
648−There's one quirk about this algorithm that makes it different from the addition algorithm. We didn't set any initial values in the addition program, and so calling the whole function at the end was an acceptable option. If we do the same thing with decrement -- call the whole function at the end -- we'll end up setting the same face, `c`, to the same initial value again, `0`. We don't want that. We want the counter to increase in value for each loop! There should be a recursion start point that comes after `c` is set initially. For that you can use the `|-` rune.
649−
650−Here's the program:
651−
652−```
653−|= a=@ :: take one @
654−=/ c=@ 0 :: set c to 0
655−|- :: recursion start
656−^- @ :: output is @
657−?: =(a +(c)) :: if a = c+1
658− c :: return c, else
659−$(c +(c)) :: add 1 to c, recurse
660− :: back to the |-
661−```
662−
663−Save it as `dec.hoon` and try it from the dojo:
664−
665−```
666−> +dec 101
667−100
668−
669−> +dec 97
670−96
671−
672−> +dec 11
673−10
674−```
675−
676−At an intuitive level this code should make sense. The `$( )` at the end effectively serves as a loop going back to the `|-` rune, with a modification to the value of `c`. But isn't `$` the name of the gate's single arm? What's going on? Let's take a moment to understand how `|-` works at a deeper level.
677−
678−### `|-` Make and Call a One-armed Core
679−
680−The `|-` rune makes a one-armed core whose arm has the name `$`, and then it calls `$`. The `|-` rune takes one subexpression, which determines what `$` does:
681−
682−```
683−> |- 2
684−2
685−
686−> |- (add 22 33)
687−55
688−```
689−
690−Let's look at the decrement program again, this time using the regular version of the `%=` rune.
691−
692−```
693−|= a=@ :: take one @
694−=/ c=@ 0 :: set c to 0
695−|- :: recursion start
696−^- @ :: output is @
697−?: =(a +(c)) :: if a = c+1
698− c :: return c, else
699−%= $ :: resolve to $
700− c +(c) :: add 1 to c
701−==
702−```
703−
704−Strictly speaking, when you use `$( )` or `%= $` you're asking for a resolution to `$` (with changes indicated in parentheses). And because `$` is an arm, that means evaluating it with its parent core as the subject.
705−
706−When you use `|-` in the decrement program, you're defining a _new_ core whose arm name is `$`, in addition to the one created by `|=`. So the subject ends up having two arms named `$` in it: one for the gate defined by `|=`, and one for the core defined by `|-`.
707−
708−When `$( )` or `%= $` is executed, the subject is searched for the `$` arm. The `|-` `$` arm is found first because it was defined later than the `|=` arm. You can skip the first name match for `$` by using `^`, if you like. That is, if you like, you can recurse all the way to the beginning of the function using `^$( )` or `%= ^$`.
709−
710−### Exercises
711−
712−You should know enough at this point to write some basic Hoon programs. Practice with some of these exercises. Solutions are provided at the bottom of the page.
713−
714−#### Exercise 2.3.1: Subtraction
715−
716−Write a program that takes two numbers and returns the difference. You may use `dec`, but don't use anything else from the Hoon standard library.
717−
718−#### Exercise 2.3.2: Factorial
719−
720−Write a program that takes a number `n` and returns the factorial of `n`, `n!`. `1!` is `1`, `2!` is `2 x 1`, `3!` is `3 x 2 x 1`, `4!` is `4 x 3 x 2 x 1`, and so on. You may use the Hoon standard library.
721−
722−#### Exercise 2.3.3: Prime Number Checker
723−
724−Write a program that takes a number `n` and returns `%.y` if it's prime, and `%.n` if it isn't. You may use the Hoon standard library.
725−
726−## Fizzbuzz
727−
728−Let's write a Hoon implementation of [FizzBuzz](https://en.wikipedia.org/wiki/Fizz_buzz). Fizzbuzz takes some number `n` and then makes a list of numbers from `1` to `n`, except that numbers evenly divisible by `3` are replaced with 'Fizz', numbers evenly divisible by `5` are replaced with 'Buzz', and numbers evenly divisible by both are replaced with 'FizzBuzz'.
729−
730−You already saw a program that produces a list of atoms from `1` to `n` in [lesson 2.1](../hoon-programs), `listnum.hoon`:
731−
732−```
733−|= end=@ :: 1
734−=/ count=@ 1 :: 2
735−|- :: 3
736−^- (list @) :: 4
737−?: =(end count) :: 5
738− ~ :: 6
739−:- count :: 7
740−$(count (add 1 count)) :: 8
741−```
742−
743−The difference for FizzBuzz is that certain items of the product list must be replaced with strings: `"Fizz"`, `"Buzz"`, and `"FizzBuzz"`.
744−
745−Below is our implementation of FizzBuzz. Each line is commented with a number for convenient line reference:
746−
747−```
748−|= end=@ :: 1
749−=/ count=@ 1 :: 2
750−|- :: 3
751−^- (list tape) :: 4
752−?: =(end count) :: 5
753− ~ :: 6
754−:- :: 7
755− ?: =(0 (mod count 15)) :: 8
756− "FizzBuzz" :: 9
757− ?: =(0 (mod count 3)) :: 10
758− "Fizz" :: 11
759− ?: =(0 (mod count 5)) :: 12
760− "Buzz" :: 13
761− <count> :: 14
762−$(count (add 1 count)) :: 15
763−```
764−
765−Save this as 'fizzbuzz.hoon' in `/home/gen` of your urbit's pier. To run it enter `+fizzbuzz 25` in the dojo:
766−
767−```
768−> +fizzbuzz 25
769−<<
770− "1"
771− "2"
772− "Fizz"
773− "4"
774− "Buzz"
775− "Fizz"
776− "7"
777− "8"
778− "Fizz"
779− "Buzz"
780− "11"
781− "Fizz"
782− "13"
783− "14"
784− "FizzBuzz"
785− "16"
786− "17"
787− "Fizz"
788− "19"
789− "Buzz"
790− "Fizz"
791− "22"
792− "23"
793− "Fizz"
794−>>
795−```
796−
797−### Explaining Fizzbuzz
798−
799−```
800−|= end=@ :: 1
801−=/ count=@ 1 :: 2
802−|- :: 3
803−^- (list tape) :: 4
804−```
805−
806−This gate takes an atom, `end`, for its sample. The initial value of `count`, an atom, is `1`. Line `3` uses `|-` for a recursion (or loop) starting point, so that `count` is only set to `1` once.
807−
808−The gate output is cast to `(list tape)`, i.e., to a list of `tape`s. A `tape` is one of Hoon's two string types and is pretty-printed as a string in double quotes.
809−
810−```
811−> "This is a tape."
812−"This is a tape."
813−
814−> "So is this!"
815−"So is this!"
816−```
817−
818−Moving on:
819−
820−```
821−?: =(end count) :: 5
822− ~ :: 6
823−```
824−
825−If `end` and `count` are the same value, then the list is finished. The null character, `~`, is returned. (Reminder: Hoon lists are null-terminated.)
826−
827−Otherwise...
828−
829−```
830−:- :: 7
831− ?: =(0 (mod count 15)) :: 8
832− "FizzBuzz" :: 9
833− ?: =(0 (mod count 3)) :: 10
834− "Fizz" :: 11
835− ?: =(0 (mod count 5)) :: 12
836− "Buzz" :: 13
837− <count> :: 14
838−$(count (add 1 count)) :: 15
839−```
840−
841−If not, line 7 uses the rune `:-` to produce a cell. This cell is the FizzBuzz list, in which the head is the first list item and the tail is the rest of the list, itself another list.
842−
843−The head of this cell is produced by lines 8-14, and the tail by line 15.
844−
845−For value of the head there are two possibilities . First, the value is "FizzBuzz", or "Fizz", or "Buzz", if any of the respective conditional tests hit. For example, if `=(0 (mod count 15))` is true -- i.e., if `count` is evenly divisible by 15 -- then the value returned is "FizzBuzz". Second, if none of the three test conditions is true, then the value is the number in question, `count`. In the latter case, line 14 uses the `< >` syntax to convert `count` from an `@` to a `tape`. Remember that the cast is for a list of `tape`s, so each list item must be a `tape`.
846−
847−For the value of the cell's tail: the rest of the output list is produced by line 15. This line uses `$( )` to loop back to the `|-` in line 3, but only after modifying the value of `count`: `count` is increased in value by `1`.
848−
849−The product of the `$( )` call on line 15 is another list. Either the modified `count` equals `end`, in which case the null list, `~`, is returned on line 6; or a new cell is produced in which case the head is an item determined by lines 7-14 and the tail is determined by line 15. The process repeats until `count` equals `end`.
850−
851−## Exercise Answers
852−
853−There are many possible solutions so yours may look a bit different from the ones we have below. These solutions aren't optimized for performance. Instead, clarity and simplicity have been prioritized.
854−
855−#### Exercise 2.3.1 Solution: Subtraction
856−
857−```
858−|= [x=@ y=@]
859−^- @
860−?: =(y 0)
861− x
862−$(x (dec x), y (dec y))
863−```
864−
865−#### Exercise 2.3.2 Solution: Factorial
866−
867−```
868−|= n=@
869−^- @
870−?: (lte n 1)
871− 1
872−(mul n $(n (dec n)))
873−```
874−
875−#### Exercise 2.3.3 Solution: Prime
876−
877−```
878−|= a=@
879−?: (lth a 2) |
880−?: =(a 2) &
881−=/ c 2
882−|- ^- ?
883−?: =(0 (mod a c)) |
884−?: (gth (mul c 2) a) &
885−$(c +(c))
886−```
887−
888−### [Next Lesson: Atoms, Auras, and Simple Cell Types](../atoms-auras-and-simple-cell-types)