on d659381 help sign in
urbit.org/docs/arvo/basic.md
316 lines 11 kB history raw
1---
2navhome: /docs/
3sort: 11
4next: true
5title: Basic Hoon
6---
8Basic Hoon
9==========
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:
29```
30~fintud-macrep:dojo> |mount %
31```
33Then, copy the example into it
35```
36$ cp -r {urbit-examples}/gall/*/* {your-pier}/home/
37$ cp -r {urbit-examples}/dojo/*/* {your-pier}/home/
38```
40Run an example to ensure it worked:
42 ~fintud-macrep:dojo> +examples-euler1
43 233.168
45Euler 1
46-------
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`):
58 :: project euler 1
59 :: https://projecteuler.net/problem=1
60 :: run in dojo with +examples-euler1
61 ::
62 :::: /hoon/euler1/examples/gen
63 ::
64 :- %say |= *
65 :- %noun
66 =< (sum 1.000)
67 ::
68 :::: ~sivtyv-barnel
69 ::
70 |%
71 ++ three
72 |= a/@
73 =| b/@
74 |- ^- @u
75 ?: (lth a b)
76 0
77 (add b $(b (add 3 b)))
78 ::
79 ++ five
80 |= a/@
81 =| b/@
82 |- ^- @
83 ?: (lte a b)
84 0
85 ?: =((mod b 3) 0)
86 $(b (add b 5))
87 (add b $(b (add b 5)))
88 ::
89 ++ sum
90 |= a/@u
91 (add (five a) (three a))
92 --
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.
100### Lines 1-11:
102Any line that begins with `::` is a comment.
104 :- %say |= *
105 :- %noun
106 =< (sum 1.000)
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
110later.
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 18 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 < pal (
138 bar | gap [>1 space, nl] par )
139 bas \ gar > sel [
140 buc $ hax # sem ;
141 cab _ hep - ser ]
142 cen % kel { sig ~
143 col : ker } soq '
144 com , ket ^ tar *
145 doq " lus + tec `
146 dot . pam & tis =
147 fas / pat @ wut ?
148 zap !
150Using this scheme, we would pronounce `?:` as 'wutcol'.
152For those who prefer to use reserved words to form expressions, you can
153substitute any rune with that rune's keyword, which you can find in
154`++twig` in `/arvo/hoon.hoon`. For example, here's the code for `?:` in
155`++twig`:
157`{$if p/twig q/twig r/twig} :: ?: if/then/else`
159Instead of:
161 ?:(=(1 2) 'this is true' 'this is false')
162 'this is false'`
164You can write:
166 :if(=(1 2) 'this is true' 'this is false')
167 'this is false'
169### Lines 13-35
171Now let's quickly walk through this code line-by-line. Lines 13-35 are
172wrapped in a `|%` ('[barcen](../../hoon/twig/bar-core/cen-core/)'), which produces a core. Cores are a
173fundamental datatype in Hoon, similar to a struct, class, or object. A
174core is just a map of names to any kind of code, whether it be functions
175or data. Each element in this map begins with a `++` followed by the
176name and the corresponding code. Since `|%` takes an arbitrary number of
177children, it needs to be closed with a `--`.
179> `++` ('luslus') is not technically a rune, since it is only used in
180> core syntax, as shown above.
182Let's step into each of the three arms within our core.
184### `++ sum`
186 ++ sum
187 |= a/@
188 (add (five a) (three a))
189 --
191`|=` ('[bartis](../../hoon/twig/bar-core/tis-gate/)') produces a function, much like a lambda in lisp. It
192takes two children:
1941. A set of argument(s). In this case our argument set only contains
195 one: `a`, which is required to be an atom or natural number, denoted
196 by `@`.
1982. The body of the function itself, which is executed when the function
199 is called (in this case, with `(sum 1.000)`). This particular
200 function adds the results of evaluating the gates `++ five` and
201 `++three` with each of their respective input parameters set to `a`.
203### ++ three
205 ++ three
206 |= a/@
207 =| b/@
208 |- ^- @u
209 ?: (lth a b)
210 0
211 (add b $(b (add 3 b)))
213As above, `++three` takes an integer argument, `a`, and then executes
214the remainder of the code with `a` set to the actual arguments.
216Similarly, `=|` ('[tisbar](../../hoon/twig/tis-flow/bar-new/)') pushes its first child, `b` into our context
217(in other words, it declares a variable `b`) and executes the remainder
218of the code. However, `b` is not an argument; `=|` sets `b` to the
219default value of whatever type it is declared as. Since the default
220value of an atom is `0`, b is set to `0`.
222> To produce the default value of any given type, use `*` ('tar')
223> followed by the type. This operaction is called *bunt*.
225> > *@ :: produce the default value of atom @
226> 0
227>
228> > *@p :: produce the phonemic base of atom @
229> ~zod
231So now we have two variables: `a` is set to our input, and `b` is
232initialized to `0`.
234One way to think about `|-` ('[barhep](../../hoon/twig/bar-core/hep-loop/)') is that it lays down a recursion
235point. More on this later.
237`^-` ('[kethep](../../hoon/core/ket-cast/hep-cast/)') is just a cast that sets the result of the remainder of
238the code to an unsigned integer, `@u`.
240In pseudocode, the last three lines read like this: if `a` is less than
241`b`, produce zero. Else, add `b` to the result of rerunning the segment
242of the function following the `|-` with the value of `b` changed to `b`
243plus three.
245The only thing that should look completely unfamiliar to you here is the
246`$(b (add 3 b))`, which causes us to recurse back to our last recursion
247point with the value of `b` set to `(add 3 b)`. Note that we only
248specify what changes (`b` in this case). If you recurse by an actual
249function call, then you have to specify every argument.
251> If you're familiar with Clojure, `|-` is `loop` and `$()` is `recur`.
253**Exercises**:
255Tweak your code to complete the following exercises.
257There are a few runes and some syntax that we have yet to cover that you
258will need to complete the exercises below. For these, please refer to
259our cheatsheat at the bottom.
2611. Read and understand `++five` line by line.
2632. Change `++sum` to accept two variables, `a` and `b`. Pass `a` to
264 `three` and `b` to `five`. Then run the code with `a` set to `1.000`
265 and `b` set to `2.000`.
2673. Check if this new result is under one thousand. If it is, return the
268 string `'result < 1.000'`. If not, return `'result >= 1.000'`.
270### Review
272 |% ('barcen') start core (collection of named ++ arms; an "object")
273 |= ('bartis') define function
274 =| ('tisbar') define variable from type with default value
275 |- ('barhep') drop a recursion point
276 ^- ('kethep') cast
277 ?: ('wutcol') if-then-else
278 =(a b) test equality
279 (function args ...) call function with args
281Lookup each of these expressions (and all others!) in the [Twig Expressions](../../hoon/twig/) definition.
283### New material
2851. There are two syntaxes for writing Hoon: tallform and wideform.
287 In tallform, expressions are formed with either two spaces or a line
288 break separating both a rune from its children and each of its children
289 from one another. We use tallform when writing multiline expressions.
291 For more concise expressions, we use wideform, which is always a single
292 line. Wideform can be used inside tallform expressions, but not vice
293 versa.
295 Wideform expressions are formed with a rune followed by `()` containing
296 its children, all of which are separated by a single space. For example,
297 to make a cell of two elements, use `:-(a b)`.
299 We've already seen wideform in action, for example with
300 `=((mod b 3) 0)`. In this case, `=` is actually an irregular form of
301 `.=`, which tests its two children for equality.
303 Surrounding a function with `()` is an irregular wide form syntax for
304 calling a function with *N* arguments. More on this later.
3062. For a set of multiple arguments following `|=` ('[bartis](../../hoon/twig/bar-core/tis-gate/)'), use `{` 'kel' and `}` 'ker.' For example: `{a/@u b/@u}`.
3083. `:-` makes a cell of values. The irregular wide form of this is
309 `[a b]`, with two expressions separated by a single space. While the
310 regular form of this rune takes a fixed number of children (two),
311 its irregular wide form can accept *N* expressions: `[a1..an]`.
3134. Cords are one datatype for text in Hoon. They're just a big atom
314 formed from adjacent unicode bytes -- a "c string". To produce a
315 cord, enclose text within single quotes. To set the type of an
316 argument to a cord, use `@t`.