11Our goal is to get you programming interesting and useful things as soon
12as possible. To get there, we have to quickly cover some of the
13fundamentals of [Hoon](/docs/hoon/). To do this, we'll walk through two simple
14programs: the first [Project Euler](https://projecteuler.net/) problem
15and [fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
17To run this code, you'll need an urbit, and will have to copy the
18[examples repo](https://github.com/urbit/examples) into it.
20If you haven't installed urbit yet, check out the [installation
21instructions](/docs/using/install). Once urbit is installed, take a look
22at the [basic operation](/docs/using/admin) of your urbit.
24If you haven't copied in the examples repo, running the following
25commands from your urbit directory should do the trick:
27Make sure you've mounted your `%home` desk:
30~fintud-macrep:dojo> |mount %
33Then, copy the example into it
36$ cp -r {urbit-examples}/gall/*/* {your-pier}/home/
37$ cp -r {urbit-examples}/dojo/*/* {your-pier}/home/
40Run an example to ensure it worked:
42 ~fintud-macrep:dojo> +examples-euler1
48Let's check out the code for Euler 1. First, the problem:
50 If we list all the natural numbers below 10 that are multiples of
51 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
53 Find the sum of all the multiples of 3 or 5 below 1000.
55Here is the hoon solution (which should be in your pier directory under
56`/gen/examples/euler1`):
59 :: https://projecteuler.net/problem=1
60 :: run in dojo with +examples-euler1
62 :::: /hoon/euler1/examples/gen
77 (add b $(b (add 3 b)))
87 (add b $(b (add b 5)))
91 (add (five a) (three a))
94> Hoon is not generally whitespace sensitive, but we do have two
95> different kinds of whitespace: a single space and a gap, which is two
96> or more spaces or a linebreak. Tabs are taboo. Do not use them.
97> Really. For a more detailed explanation of when to use spaces vs.
98> gaps, see the syntax section before the first exercises.
102Any line that begins with `::` is a comment.
108All you need to know about the lines above is that they call the `++sum`
109function with an argument of `1.000`. We'll cover them in more detail
112### How to form expressions
114Hoon does not typically use reserved words to form expressions. Instead,
115expressions are formed with *runes*: digraphs of two ASCII symbols. Each
116rune takes a specific number of children, either expressions formed by
117other runes or literals that produce their own value (some runes take
118*N* children, and are usually closed with `==`).
120For example, the rune `?:` from line 17 is the classic 'if-then-else'
121statement, and thus takes three children:
123 ?: (lth a b) :: if first child evals to true
124 0 :: then produce result of second
125 (add b $(b (add 3 b))) :: else, produce result of third
127Since runes are such a fundamental structure in Hoon, we found ourselves
128speaking them out loud frequently. It quickly grew cumbersome to have to
129say "question mark, colon" to describe `?:`. To alleviate this problem,
130we came up with our own naming scheme: each ASCII glyph has a
131single-syllable pronunciation phonetically designed to be both easily
132remembered and easily pronounced in conjunction with the other glyphs
133(when forming a rune).
135See the entire naming scheme below.
137 ace [1 space] gal < pel (
138 bar | gap [>1 space, \n] per )
149Using this scheme, we would pronounce `?:` as 'wutcol'.
151For those who prefer to use reserved words to form expressions, you can
152substitute any rune with that rune's keyword, which you can find in
153`++twig` in `/arvo/hoon.hoon`. For example, here's the code for `?:` in
156`{$if p/twig q/twig r/twig} :: ?: if/then/else`
160 ?:(=(1 2) 'this is true' 'this is false')
165 :if(=(1 2) 'this is true' 'this is false')
170Now let's quickly walk through this code line-by-line. Lines 12-34 are
171wrapped in a `|%` ('[barcen](../../hoon/twig/bar-core/cen-core/)'), which produces a core. Cores are a
172fundamental datatype in Hoon, similar to a struct, class, or object. A
173core is just a map of names to any kind of code, whether it be functions
174or data. Each element in this map begins with a `++` followed by the
175name and the corresponding code. Since `|%` takes an arbitrary number of
176children, it needs to be closed with a `--`.
178> `++` ('luslus') is not technically a rune, since it is only used in
179> core syntax, as shown above.
181Let's step into each of the three arms within our core.
187 (add (five a) (three a))
190`|=` ('[bartis](../../hoon/twig/bar-core/tis-gate/)') produces a function, much like a lambda in lisp. It
1931. A set of argument(s). In this case our argument set only contains
194 one: `a`, which is required to be an atom or natural number, denoted
1972. The body of the function itself, which is executed when the function
198 is called (in this case, with `(sum 1.000)`). This particular
199 function adds the results of evaluating the gates `++ five` and
200 `++three` with each of their respective input parameters set to `a`.
210 (add b $(b (add 3 b)))
212As above, `++three` takes an integer argument, `a`, and then executes
213the remainder of the code with `a` set to the actual arguments.
215Similarly, `=|` ('[tisbar](../../hoon/twig/tis-flow/bar-new/)') pushes its first child, `b` into our context
216(in other words, it declares a variable `b`) and executes the remainder
217of the code. However, `b` is not an argument; `=|` sets `b` to the
218default value of whatever type it is declared as. Since the default
219value of an atom is `0`, b is set to `0`.
221> To produce the default value of any given type, use `*` ('tar')
222> followed by the type. This operaction is called *bunt*.
224> > *@ :: produce the default value of atom @
227> > *@p :: produce the phonemic base of atom @
230So now we have two variables: `a` is set to our input, and `b` is
233One way to think about `|-` ('[barhep](../../hoon/twig/bar-core/hep-loop/)') is that it lays down a recursion
234point. More on this later.
236`^-` ('[kethep](../../hoon/core/ket-cast/hep-cast/)') is just a cast that sets the result of the remainder of
237the code to an unsigned integer, `@u`.
239In pseudocode, the last three lines read like this: if `a` is less than
240`b`, produce zero. Else, add `b` to the result of rerunning the segment
241of the function following the `|-` with the value of `b` changed to `b`
244The only thing that should look completely unfamiliar to you here is the
245`$(b (add 3 b))`, which causes us to recurse back to our last recursion
246point with the value of `b` set to `(add 3 b)`. Note that we only
247specify what changes (`b` in this case). If you recurse by an actual
248function call, then you have to specify every argument.
250> If you're familiar with Clojure, `|-` is `loop` and `$()` is `recur`.
254Tweak your code to complete the following exercises.
256There are a few runes and some syntax that we have yet to cover that you
257will need to complete the exercises below. For these, please refer to
258our cheatsheat at the bottom.
2601. Read and understand `++five` line by line.
2622. Change `++sum` to accept two variables, `a` and `b`. Pass `a` to
263 `three` and `b` to `five`. Then run the code with `a` set to `1.000`
264 and `q` set to `2.000`.
2663. Check if this new result is under one thousand. If it is, return the
267 string `'result < 1.000'`. If not, return `'result >= 1.000'`.
271 |% ('barcen') start core (collection of named ++ arms; an "object")
272 |= ('bartis') define function
273 =| ('tisbar') define variable from type with default value
274 |- ('barhep') drop a recursion point
276 ?: ('wutcol') if-then-else
278 (function args ...) call function with args
280Lookup each of these expressions (and all others!) in the [Twig Expressions](../../hoon/twig/) definition.
2841. There are two syntaxes for writing Hoon: tallform and wideform.
286In tallform, expressions are formed with either two spaces or a line
287break separating both a rune from its children and each of its children
288from one another. We use tallform when writing multiline expressions.
290For more concise expressions, we use wideform, which is always a single
291line. Wideform can be used inside tallform expressions, but not vice
294Wideform expressions are formed with a rune followed by `()` containing
295its children, all of which are separated by a single space. For example,
296to make a cell of two elements:
300We've already seen wideform in action, for example with
301`=((mod b 3) 0)`. In this case, `=` is actually an irregular form of
302`.=`, which tests its two children for equality.
304Surrounding a function with `()` is an irregular wide form syntax for
305calling a function with *N* arguments. More on this later.
3071. `:-` makes a cell of values. The irregular wide form of this is
308 `[a b]`, with two expressions separated by a single space. While the
309 regular form of this rune takes a fixed number of children (two),
310 its irregular wide form can accept *N* expressions: `[a1..an]`
3122. Cords are one datatype for text in Hoon. They're just a big atom
313 formed from adjacent unicode bytes -- a "c string". To produce a
314 cord, enclose text within single quotes. To set the type of an
315 argument to a cord, use `@t`.
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list