on 4290670 help sign in
urbit.org/docs/arvo/basic.md
328 lines 10 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> Hoon is not generally whitespace sensitive, but we do have two
94> different kinds of whitespace: a single space and a gap, which
95> is two or more spaces or a linebreak. Tabs are taboo. Do not
96> use them. Really. For a more detailed explanation of when to
97> use spaces vs. gaps, see the syntax section before the first
98> exercises.
101### Lines 1-11:
103Any line that begins with `::` is a comment.
105 :- %say |= *
106 :- %noun
107 =< (sum 1.000)
109All you need to know about the lines above is that they call the
110`++sum` function with an argument of `1.000`. We'll cover them in
111more detail later.
113### How to form expressions
115Hoon does not typically use reserved words to form expressions. Instead,
116expressions are formed with _runes_: digraphs of two
117ASCII symbols. Each rune takes a specific number of
118children, either expressions formed by other runes or literals
119that produce their own value (some runes take _N_ children, and are usually closed with `==`).
121For example, the rune `?:` from line 17 is the classic
122'if-then-else' statement, and thus takes three children:
124 ?: (lth a b) :: if first child evals to true
125 0 :: then produce result of second
126 (add b $(b (add 3 b))) :: else, produce result of third
128Since runes are such a fundamental structure in Hoon, we found
129ourselves speaking them out loud frequently. It quickly grew
130cumbersome to have to say "question mark, colon" to describe
131`?:`. To alleviate this problem, we came up with our own naming
132scheme: each ASCII glyph has a single-syllable pronunciation
133phonetically designed to be both easily remembered and easily
134pronounced in conjunction with the other glyphs (when forming a
135rune).
137See the entire naming scheme below.
139```
140 ace [1 space] gal < pel (
141 bar | gap [>1 space, \n] per )
142 bas \ gar > sel [
143 buc $ hax # sem ;
144 cab _ hep - ser ]
145 cen % kel { soq '
146 col : ker } tar *
147 com , ket ^ tec `
148 doq " lus + tis =
149 dot . pam & wut ?
150 fas / pat @ zap !
151```
153Using this scheme, we would pronounce `?:` as 'wutcol'.
155For 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`:
157`{$if p/twig q/twig r/twig} :: ?: if/then/else`
159Instead of:
161```
162?:(=(1 2) 'this is true' 'this is false')
163'this is false'`
164```
165You can write:
167```
168if(=(1 2) 'this is true' 'this is false')
169'this is false'
170```
172### Lines 12-34
174Now let's quickly walk through this code line-by-line. Lines
17512-34 are wrapped in a `|%` ('barcen'), which produces a core.
176Cores are a fundamental datatype in Hoon, similar to a
177struct, class, or object. A core is just a map of names
178to any kind of code, whether it be functions or data. Each
179element in this map begins with a `++` followed by the name and
180the corresponding code. Since `|%` takes an arbitrary number of
181children, it needs to be closed with a `--`.
183> `++` ('luslus') is not technically a rune, since it is only used
184> in core syntax, as shown above.
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`|=` ('bartis') produces a function, much like a lambda in lisp. It takes two children:
1971. 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 `@`.
2011. 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, `=|` ('tisbar') pushes its first child, `b` into our
222context (in other words, it declares a variable `b`) and executes
223the remainder 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`.
227> To produce the default value of any given type, use `$*` ('buctar') followed by the type.
228> Alternatively, use the irregular form `*`.
229>
230> ```
231> > *@ :: produce the default value of atom @
232> 0
233>
234> > *@p :: produce the phonemic base of atom @
235> ~zod
236>
237> ```
239So now we have two variables: `a` is set to our input, and `b` is
240initialized to `0`.
242One way to think about `|-` ('barhep') is that it lays down a recursion
243point. More on this later.
245`^-` ('kethep') is just a cast that sets the result of the remainder of
246the code to an unsigned integer, `@u`.
248In pseudocode, the last three lines read like this: if `a` is
249less than `b`, produce zero. Else, add `b` to the result of
250rerunning the segment of the function following the `|-` with the
251value of `b` changed to `b` plus three.
253The only thing that should look completely unfamiliar to you here
254is the `$(b (add 3 b))`, which causes us to recurse back to our
255last recursion point with the value of `b` set to `(add 3 b)`.
256Note that we only specify what changes (`b` in this case). If
257you recurse by an actual function call, then you have to specify
258every argument.
260> If you're familiar with Clojure, `|-` is `loop` and `$()` is `recur`.
262**Exercises**:
264Tweak your code to complete the following excercises.
266There are a few runes and some syntax that we have yet to cover that
267you will need to complete the excercises below. For these, please
268refer to our cheatsheat at the bottom.
2701. Read and understand `++five` line by line.
2721. Change `++sum` to accept two variables, `a` and `b`. Pass `a`
273 to `three` and `b` to `five`. Then run the code with `a` set to
274 `1.000` and `q` set to `2.000`.
2761. Check if this new result is under one thousand. If it is,
277 return the string `'result < 1.000'`. If not,
278 return `'result >= 1.000'`.
280### Review
282 |% ('barcen') start core (collection of named ++ arms; an "object")
283 |= ('bartis') define function
284 =| ('tisbar') define variable from type with default value
285 |- ('barhep') drop a recursion point
286 ^- ('kethep') cast
287 ?: ('wutcol') if-then-else
288 =(a b) test equality
289 (function args ...) call function with args
291### New material
2931. There are two syntaxes for writing Hoon: tallform and wideform.
295 In tallform, expressions are formed with either two spaces or
296 a line break separating both a rune from its children and each
297 of its children from one another. We use tallform when writing
298 multiline expressions.
300 For more concise expressions, we use wideform, which is always
301 a single line. Wideform can be used inside tallform
302 expressions, but not vice versa.
304 Wideform expressions are formed with a rune followed by `()`
305 containing its children, all of which are separated by a
306 single space. For example, to make a cell of two elements:
308 :-(a b)
310 We've already seen wideform in action, for example with
311 `=((mod b 3) 0)`. In this case, `=` is actually an irregular form
312 of `.=`, which tests its two children for equality.
314 Surrounding a function with `()` is an irregular wide form
315 syntax for calling a function with _N_ arguments. More on this later.
3171. `:-` makes a cell of values. The irregular wide form of this is
318 `[a b]`, with two expressions separated by a single space.
319 While the regular form of this rune takes a fixed number of
320 children (two), its irregular wide form can accept _N_ expressions:
321 `[a1..an]`
3232. Cords are one datatype for text in Hoon. They're just a big
324 atom formed from adjacent unicode bytes -- a "c string". To
325 produce a cord, enclose text within single quotes. To set the type
326 of an argument to a cord, use `@t`.