on 0304485 help sign in
urbit.org/docs/arvo/basic.md
336 lines 11 kB history raw
1---
2navhome: /docs
3sort: 1
4next: true
5title: Hoon refresher / crash course
6---
8# Basic Hoon
10This recapitulates material you've already learned in [Hoon](/docs/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, try working up from Hoon.
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 will have to copy the [examples repo](https://github.com/urbit/examples) into it.
24If you haven't installed
25urbit yet, check out the [installation
26instructions](/docs/user/install). Once urbit is
27installed, take a look at the [basic
28operation](/docs/user/basic) of your urbit.
30If you haven't copied in the examples repo, running the following commands from your urbit directory should do the trick:
32`$ cp -r {wherever-you've-pulled-to}/examples/gall/*/ arvo/`
33`$ cp -r {wherever-you've-pulled-to}/examples/dojo/*/ arvo/`
35Run an example to ensure it worked:
37 ~fintud-macrep:dojo> +examples-euler1
38 233.168
40## Euler 1
42Let's check out the code for Euler 1. First, the problem:
44```
45If we list all the natural numbers below 10 that are multiples of
463 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
48Find the sum of all the multiples of 3 or 5 below 1000.
49```
51Here is the hoon solution (which should be in your pier directory
52under `/gen/examples/euler1`):
54```
55:: project euler 1
56:: https://projecteuler.net/problem=1
57:: run in dojo with +examples-euler1
58::
59:::: /hoon/euler1/examples/gen
60 ::
61:- %say |= *
62:- %noun
63=< (sum 1.000)
64::
65:::: ~sivtyv-barnel
66 ::
67|%
68++ three
69 |= a/@
70 =| b/@
71 |- ^- @u
72 ?: (lth a b)
73 0
74 (add b $(b (add 3 b)))
76++ five
77 |= a/@
78 =| b/@
79 |- ^- @
80 ?: (lte a b)
81 0
82 ?: =((mod b 3) 0)
83 $(b (add b 5))
84 (add b $(b (add b 5)))
86++ sum
87 |= a/@u
88 (add (five a) (three a))
89--
90```
93<blockquote class="blockquote">
94Hoon is not generally whitespace sensitive, but we do have two
95different kinds of whitespace: a single space and a gap, which
96is two or more spaces or a linebreak. Tabs are taboo. Do not
97use them. Really. For a more detailed explanation of when to
98use spaces vs. gaps, see the syntax section before the first
99excercises.
100</blockquote>
103### Lines 1-11:
105Any line that begins with `::` is a comment.
107 :- %say |= *
108 :- %noun
109 =< (sum 1.000)
111All you need to know about the lines above is that they call the
112`++sum` function with an argument of `1.000`. We'll cover them in
113more detail later.
115### How to form expressions
117Hoon does not typically use reserved words to form expressions. Instead,
118expressions are formed with _runes_: digraphs of two
119ASCII symbols. Each rune takes a specific number of
120children, either expressions formed by other runes or literals
121that produce their own value (some runes take _N_ children, and are usually closed with `==`).
123For example, the rune `?:` from line 17 is the classic
124'if-then-else' statement, and thus takes three children:
126 ?: (lth a b) :: if first child evals to true
127 0 :: then produce result of second
128 (add b $(b (add 3 b))) :: else, produce result of third
130Since runes are such a fundamental structure in Hoon, we found
131ourselves speaking them out loud frequently. It quickly grew
132cumbersome to have to say "question mark, colon" to describe
133`?:`. To alleviate this problem, we came up with our own naming
134scheme: each ASCII glyph has a single-syllable pronunciation
135phonetically designed to be both easily remembered and easily
136pronounced in conjunction with the other glyphs (when forming a
137rune).
139See the entire naming scheme below.
141```
142 ace [1 space] gal < pel (
143 bar | gap [>1 space, \n] per )
144 bas \ gar > sel [
145 buc $ hax # sem ;
146 cab _ hep - ser ]
147 cen % kel { soq '
148 col : ker } tar *
149 com , ket ^ tec `
150 doq " lus + tis =
151 dot . pam & wut ?
152 fas / pat @ zap !
153```
155Using this scheme, we would pronounce `?:` as 'wutcol'.
157For those who prefer to use reserved words to form expressions, you can substitute any rune with that rune's keyword, which you can find in `++twig` in `/arvo/hoon.hoon`. For example, here's the code for `?:` in `++twig`:
159`{$if p/twig q/twig r/twig} :: ?: if/then/else`
161Instead of:
163```
164?:(=(1 2) 'this is true' 'this is false')
165'this is false'`
166```
167You can write:
169```
170if(=(1 2) 'this is true' 'this is false')
171'this is false'
172```
174### Lines 12-34
176Now let's quickly walk through this code line-by-line. Lines
17712-34 are wrapped in a `|%` ('barcen'), which produces a core.
178Cores are a fundamental datatype in Hoon, similar to a
179struct, class, or object. A core is just a map of names
180to any kind of code, whether it be functions or data. Each
181element in this map begins with a `++` followed by the name and
182the corresponding code. Since `|%` takes an arbitrary number of
183children, it needs to be closed with a `--`.
185<blockquote class="blockquote">
186`++` ('luslus') is not technically a rune, since it is only used
187in core syntax, as shown above.
188</blockquote>
190Let's step into each of the three arms within our core.
192### `++ sum`
194 ++ sum
195 |= a/@
196 (add (five a) (three a))
197 --
199`|=` ('bartis') produces a function, much like a lambda in lisp. It takes two children:
2011. A set of argument(s). In this case our argument set only
202 contains one: `a`, which is required to be an atom or natural
203 number, denoted by `@`.
2051. The body of the function itself, which is executed when the
206 function is called (in this case, with `(sum 1.000)`). This
207 particular function adds the results of evaluating the gates `++
208 five` and `++three` with each of their respective input
209 parameters set to `a`.
211### ++ three
213 ++ three
214 |= a/@
215 =| b/@
216 |- ^- @u
217 ?: (lth a b)
218 0
219 (add b $(b (add 3 b)))
221As above, `++three` takes an integer argument, `a`, and then
222executes the remainder of the code with `a` set to the actual
223arguments.
225Similarly, `=|` ('tisbar') pushes its first child, `b` into our
226context (in other words, it declares a variable `b`) and executes
227the remainder of the code. However, `b` is not an argument; `=|`
228sets `b` to the default value of whatever type it is declared as.
229Since the default value of an atom is `0`, b is set to `0`.
231<blockquote class="blockquote">
232To produce the default value of any given type, use `$*` ('buctar') followed by the type.
233Alternatively, use the irregular form `*`.
235```
236 > *@ :: produce the default value of atom @
237 0
239 > *@p :: produce the phonemic base of atom @
240 ~zod
242```
243</blockquote>
245So now we have two variables: `a` is set to our input, and `b` is
246initialized to `0`.
248One way to think about `|-` ('barhep') is that it lays down a recursion
249point. More on this later.
251`^-` ('kethep') is just a cast that sets the result of the remainder of
252the code to an unsigned integer, `@u`.
254In pseudocode, the last three lines read like this: if `a` is
255less than `b`, produce zero. Else, add `b` to the result of
256rerunning the segment of the function following the `|-` with the
257value of `b` changed to `b` plus three.
259The only thing that should look completely unfamiliar to you here
260is the `$(b (add 3 b))`, which causes us to recurse back to our
261last recursion point with the value of `b` set to `(add 3 b)`.
262Note that we only specify what changes (`b` in this case). If
263you recurse by an actual function call, then you have to specify
264every argument.
266<blockquote class="blockquote">
267If you're familiar with Clojure, `|-` is `loop` and `$()` is `recur`.
268</blockquote>
270**Exercises**:
272Tweak your code to complete the following excercises.
274There are a few runes and some syntax that we have yet to cover that
275you will need to complete the excercises below. For these, please
276refer to our cheatsheat at the bottom.
2781. Read and understand `++five` line by line.
2801. Change `++sum` to accept two variables, `a` and `b`. Pass `a`
281 to `three` and `b` to `five`. Then run the code with `a` set to
282 `1.000` and `q` set to `2.000`.
2841. Check if this new result is under one thousand. If it is,
285 return the string `'result < 1.000'`. If not,
286 return `'result >= 1.000'`.
288### Review
290 |% ('barcen') start core (collection of named ++ arms; an "object")
291 |= ('bartis') define function
292 =| ('tisbar') define variable from type with default value
293 |- ('barhep') drop a recursion point
294 ^- ('kethep') cast
295 ?: ('wutcol') if-then-else
296 =(a b) test equality
297 (function args ...) call function with args
299### New material
3011. There are two syntaxes for writing Hoon: tallform and wideform.
303 In tallform, expressions are formed with either two spaces or
304 a line break separating both a rune from its children and each
305 of its children from one another. We use tallform when writing
306 multiline expressions.
308 For more concise expressions, we use wideform, which is always
309 a single line. Wideform can be used inside tallform
310 expressions, but not vice versa.
312 Wideform expressions are formed with a rune followed by `()`
313 containing its children, all of which are separated by a
314 single space. For example, to make a cell of two elements:
316 :-(a b)
318 We've already seen wideform in action, for example with
319 `=((mod b 3) 0)`. In this case, `=` is actually an irregular form
320 of `.=`, which tests its two children for equality.
322 Surrounding a function with `()` is an irregular wide form
323 syntax for calling a function with _N_ arguments. More on this later.
3251. `:-` makes a cell of values. The irregular wide form of this is
326 `[a b]`, with two expressions separated by a single space.
327 While the regular form of this rune takes a fixed number of
328 children (two), its irregular wide form can accept _N_ expressions:
329 `[a1..an]`
3312. Cords are one datatype for text in Hoon. They're just a big
332 atom formed from adjacent unicode bytes -- a "c string". To
333 produce a cord, enclose text within single quotes. To set the type
334 of an argument to a cord, use `@t`.