on 932d391 help sign in
318 lines 10 kB history raw
1---
2logo: black
3sort: 1
4next: true
5title: Hoon refresher / crash course
6---
8# Basic Hoon
10This recapitulates material you've already learned in Core Hoon.
11It will be a very abrupt tutorial if you don't know Hoon already,
12but it may be enough in and of itself. If you don't find it obvious at first
13glance, read it over again.
15Our goal is to get you programming interesting and useful things
16as soon as possible. To get there, we have to quickly cover some
17of the fundamentals of hoon. To do this, we'll walk through two
18simple programs: the first [Project
19Euler](https://projecteuler.net/) problem and
20[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
22To run this code, you'll need an urbit, and you'll need the
23`%examples` desk from `~zod`. If you haven't installed
24urbit yet, check out the [installation
25instructions](http://urbit.org/docs/user/install). Once urbit is
26installed, take a look at the [basic
27operation](http://urbit.org/docs/user/basic) of your urbit.
29If you haven't pulled the examples desk from `~zod`, do
30so now:
32 ~fintud-macrep:dojo> |merge %examples ~zod %examples
33 >=
34 [time passes...]
35 merged with strategy %init
37This merge could take several minutes; you'll know it's done when
38"merged with strategy %init" is printed. Next, mount the new files to
39your Unix pier directory:
41 ~fintud-macrep:dojo> |mount /=examples=
43Switch desks to run commands from the `%examples` desk:
45 ~fintud-macrep:dojo> =dir /=examples=
46 =% /~fintud-macrep/examples/~2015.11.13..02.25.00..41e9/
48Run an example:
50 ~fintud-macrep:dojo> +euler1
51 233.168
53## Euler 1
55Let's check out the code for Euler 1. First, the problem:
57```
58If we list all the natural numbers below 10 that are multiples of
593 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
61Find the sum of all the multiples of 3 or 5 below 1000.
62```
64Here is the hoon solution (which should be in your pier directory
65under `/examples/gen/euler1.hoon`):
67```
68:: project euler 1
69:: https://projecteuler.net/problem=1
70:: run in dojo with +euler1
71::
72:::: /hoon/euler1/gen
73 ::
74:- %say |= *
75:- %noun
76=< (sum 1.000)
77::
78:::: ~sivtyv-barnel
79 ::
80|%
81++ three
82 |= a/@
83 =| b/@
84 |- ^- @u
85 ?: (lth a b)
86 0
87 (add b $(b (add 3 b)))
89++ five
90 |= a/@
91 =| b/@
92 |- ^- @
93 ?: (lte a b)
94 0
95 ?: =((mod b 3) 0)
96 $(b (add b 5))
97 (add b $(b (add b 5)))
99++ sum
100 |= a/@u
101 (add (five a) (three a))
102--
103```
106<blockquote class="blockquote">
107Hoon is not generally whitespace sensitive, but we do have two
108different kinds of whitespace: a single space and a gap, which
109is two or more spaces or a linebreak. Tabs are taboo. Do not
110use them. Really. For a more detailed explanation of when to
111use spaces vs. gaps, see the [syntax section](docs/programming/core/twig/syntax) before the first
112excercises.
113</blockquote>
116### Lines 1-11:
118Any line that begins with `::` is a comment.
120 :- %say |= *
121 :- %noun
122 =< (sum 1.000)
124All you need to know about the lines above is that they call the
125`++sum` function with an argument of `1.000`. We'll cover them in
126more detail later.
128### How to form expressions
130Hoon does not use reserved words to form expressions. (We did recently implement an alternative keyword syntax, which is not covered here. For more information, see the [syntax section](docs/programming/core/twig/syntax)). Instead,
131expressions are formed with runes--diagraphs of two
132ascii symbols. Each rune takes a specific number of
133children--either expressions formed by other runes or literals
134that produce their own value (some runes take n children, and are usually closed with `==`).
136For example, the rune `?:` from line 17 is the classic
137'if-then-else' statement, and thus takes three children:
139 ?: (lth a b) :: if first child evals to true
140 0 :: then produce result of second
141 (add b $(b (add 3 b))) :: else, produce result of third
143Since runes are such a fundamental structure in Hoon, we found
144ourselves speaking them out loud frequently. It quickly grew
145cumbersome to have to say "question mark, colon" to describe
146`?:`. To alleviate this problem, we came up with our own naming
147scheme: each ascii glyph has a single syllable pronunciation
148phonetically designed to be both easily remembered and easily
149pronounced in conjunction with the other glyphs (when forming a
150rune).
152See the entire naming schema below/or link to it:
154```
155 ace [1 space] gal < pel (
156 bar | gap [>1 space, nl] per )
157 bas \ gar > sel [
158 buc $ hax # sem ;
159 cab _ hep - ser ]
160 cen % kel { soq '
161 col : ker } tar *
162 com , ket ^ tec `
163 doq " lus + tis =
164 dot . pam & wut ?
165 fas / pat @ zap !
166```
168Using our naming scheme `?:` is said 'wut col'.
170### Lines 12-34
172Now let's quickly walk through this code line-by-line. Lines
17312-34 are wrapped in a `|%` (pronounced 'bar cen'), which
174produces a core, a fundamental datatype in hoon similar to a
175struct, class, or object. A core is just a map of names
176to any kind of code, whether it be functions or data. Each
177element in this map begins with a `++` followed by the name and
178the corresponding code. Since `|%` takes an arbitrary number of
179children, it needs to be closed with a `--`.
181<blockquote class="blockquote">
182`++` is not technically a rune, since it is only used in core
183syntax as shown above
184</blockquote>
186Let's step into each of the three arms within our core.
188### `++ sum`
190 ++ sum
191 |= a/@
192 (add (five a) (three a))
193 --
195`|=` produces a function, much like a lambda in lisp. It takes two children:
197- A set of argument(s). In this case our argument set only
198 contains one: `a` which is required to be an atom or natural
199 number, denoted by `@`.
201- The body of the function itself, which is executed when the
202 function is called (in this case, with `(sum 1.000)`). This
203 particular function adds the results of evaluating the gates `++
204 five` and `++three` with each of their respective input
205 parameters set to `a`.
207### ++ three
209 ++ three
210 |= a/@
211 =| b/@
212 |- ^- @u
213 ?: (lth a b)
214 0
215 (add b $(b (add 3 b)))
217As above, `++three` takes an integer argument, `a`, and then
218executes the remainder of the code with `a` set to the actual
219arguments.
221Similarly, `=|` pushes its first child, `b` into our context (in
222other words, it declares a variable `b`) and executes the
223remainder of the code. However, `b` is not an argument; `=|`
224sets `b` to the default value of whatever type it is declared as.
225Since the default value of an atom is `0`, b is set to `0`.
227So now we have two variables: `a` is set to our input, and `b` is
228initialized to `0`.
230The easiest way to think about `|-` that it lays down a recursion
231point. More on this later.
233`^-` is just a cast that sets the result of the remainder of the
234code to an unsigned integer, `@u`.
236In pseudocode, the last three lines read like this: if `a` is
237less than `b`, produce zero. Else, add `b` to the result of
238rerunning the segment of the function following the `|-` with the
239value of `b` changed to `b` plus three.
241The only thing that should look completely unfamiliar to you here
242is the `$(b (add 3 b))`, which causes us to recurse back to our
243last recursion point with the value of `b` set to `(add 3 b)`.
244Note that we only specify what changes (`b` in this case). If
245you recurse by an actual function call, then you have to specify
246every argument.
248<blockquote class="blockquote">
249If you're familiar with Clojure, `|-` is `loop` and `$()` is
250recur.
251</blockquote>
253**Exercises**:
255Please tweak your code to complete the following excercises.
257There are a few runes and some syntax that we have yet to cover that
258you will need to complete the excercises below. For these, please
259refer to our cheatsheat at the bottom.
261- Read and understand `++five` line by line.
263- Change `++sum` to accept two variables, `a` and `b`. Pass `a`
264 to three and `b` to five. Then run the code with `a` set to
265 `1.000` and b set to `2.000`.
267- Check if this new result is under one thousand. If it is,
268 return the string 'result is less than one thousand'. If not,
269 return 'result is greater than or equal to one thousand'.
271```
272Review
274|% start core (collection of named ++ arms; an "object")
275|= define function
276=| define variable from type with default value
277|- drop a recursion point
278^- cast
279?: if-then-else
280=(a b) test equality
281(function args ...) call function
283New material
285- There are two syntaxes for writing Hoon: tall form and wide
286 form.
288 In tall form, expressions are formed with either two spaces or
289 a line break separating both a rune from its children and each
290 of its children from one another. We use tall form when writing
291 multiline expressions.
293 For more concise expressions, we use wideform, which is always
294 a single line. Wideform can be used inside tall form
295 expressions, but not vice versa.
297 Wideform expressions are formed with a rune followed by ()
298 containing its children, all of which are separated by a
299 single space. For example to make a cell of two elements:
301 :-(a b)
303 We've already seen wideform in action, for example with
304 =((mod b 3) 0). In this case = is actually an irregular form
305 of .=, which tests its two children for equality.
307 Surrounding a function with () is an irregular wide form
308 syntax for calling a function with n arguments. More on this later.
310- :- makes a cell of values. The irregular wide form of this is
311 [a b], with two expressions separated by a single space. (While the regular form of this rune takes a fixed number of children--2--its irregular wide form can accept n expressions:[a1..an])
313- Cords are one datatype for text in hoon. They're just a big
314 atom formed from adjacent unicode bytes -- a "c string". To
315 produce a cord enclose text within single quotes. To set the type
316 of an argument to a cord, use @t.
318```