on 424cd14 help sign in
321 lines 10 kB history raw
1---
2sort: 1
3next: true
4title: Hoon refresher / crash course
5---
7# Basic Hoon
9This recapitulates material you've already learned in Core Hoon.
10It will be a very abrupt tutorial if you don't know Hoon already,
11but it may be enough in and of itself. If you don't find it obvious at first
12glance, read it over again.
14Our goal is to get you programming interesting and useful things
15as soon as possible. To get there, we have to quickly cover some
16of the fundamentals of hoon. To do this, we'll walk through two
17simple programs: the first [Project
18Euler](https://projecteuler.net/) problem and
19[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
21To run this code, you'll need an urbit, and will have to copy the [examples repo](https://github.com/urbit/examples) into it.
23If you haven't installed
24urbit yet, check out the [installation
25instructions](/docs/user/install). Once urbit is
26installed, take a look at the [basic
27operation](/docs/user/basic) of your urbit.
29If you haven't copied in the examples repo, running the following commands from your urbit directory should do the trick:
31`cp -r {wherever-you've-pulled-to}/examples/gall/*/ arvo/`
32`cp -r {wherever-you've-pulled-to}/examples/dojo/*/ arvo/`
34Run an example to ensure it worked:
36 ~fintud-macrep:dojo> +examples-euler1
37 233.168
39## Euler 1
41Let's check out the code for Euler 1. First, the problem:
43```
44If we list all the natural numbers below 10 that are multiples of
453 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
47Find the sum of all the multiples of 3 or 5 below 1000.
48```
50Here is the hoon solution (which should be in your pier directory
51under `/gen/examples/euler1`):
53```
54:: project euler 1
55:: https://projecteuler.net/problem=1
56:: run in dojo with +examples-euler1
57::
58:::: /hoon/euler1/examples/gen
59 ::
60:- %say |= *
61:- %noun
62=< (sum 1.000)
63::
64:::: ~sivtyv-barnel
65 ::
66|%
67++ three
68 |= a/@
69 =| b/@
70 |- ^- @u
71 ?: (lth a b)
72 0
73 (add b $(b (add 3 b)))
75++ five
76 |= a/@
77 =| b/@
78 |- ^- @
79 ?: (lte a b)
80 0
81 ?: =((mod b 3) 0)
82 $(b (add b 5))
83 (add b $(b (add b 5)))
85++ sum
86 |= a/@u
87 (add (five a) (three a))
88--
89```
92<blockquote class="blockquote">
93Hoon is not generally whitespace sensitive, but we do have two
94different kinds of whitespace: a single space and a gap, which
95is two or more spaces or a linebreak. Tabs are taboo. Do not
96use them. Really. For a more detailed explanation of when to
97use spaces vs. gaps, see the syntax section before the first
98excercises.
99</blockquote>
102### Lines 1-11:
104Any line that begins with `::` is a comment.
106 :- %say |= *
107 :- %noun
108 =< (sum 1.000)
110All you need to know about the lines above is that they call the
111`++sum` function with an argument of `1.000`. We'll cover them in
112more detail later.
114### How to form expressions
116Hoon does not typically use reserved words to form expressions. Instead,
117expressions are formed with runes--diagraphs of two
118ascii symbols. Each rune takes a specific number of
119children--either expressions formed by other runes or literals
120that produce their own value (some runes take n children, and are usually closed with `==`).
122For example, the rune `?:` from line 17 is the classic
123'if-then-else' statement, and thus takes three children:
125 ?: (lth a b) :: if first child evals to true
126 0 :: then produce result of second
127 (add b $(b (add 3 b))) :: else, produce result of third
129Since runes are such a fundamental structure in Hoon, we found
130ourselves speaking them out loud frequently. It quickly grew
131cumbersome to have to say "question mark, colon" to describe
132`?:`. To alleviate this problem, we came up with our own naming
133scheme: each ascii glyph has a single syllable pronunciation
134phonetically designed to be both easily remembered and easily
135pronounced in conjunction with the other glyphs (when forming a
136rune).
138See the entire naming schema below/or link to it:
140```
141 ace [1 space] gal < pel (
142 bar | gap [>1 space, nl] per )
143 bas \ gar > sel [
144 buc $ hax # sem ;
145 cab _ hep - ser ]
146 cen % kel { soq '
147 col : ker } tar *
148 com , ket ^ tec `
149 doq " lus + tis =
150 dot . pam & wut ?
151 fas / pat @ zap !
152```
154Using our naming scheme `?:` is said 'wut col'.
156For those that would prefer to use reserved words to form expressions, you can substitute a rune's keyword--which you can find in `++twig` in `/arvo/hoon.hoon`--for the rune. For example, here's the code for `?:` in `++twig`:
158`{$if p/twig q/twig r/twig} :: ?: if/then/else`
160Instead of:
162```
163?:(=(1 2) 'this is true' 'this is false')
164'this is false'`
165```
166You can write:
168```
169if(=(1 2) 'this is true' 'this is false')
170'this is false'
171```
173### Lines 12-34
175Now let's quickly walk through this code line-by-line. Lines
17612-34 are wrapped in a `|%` (pronounced 'bar cen'), which
177produces a core, a fundamental datatype in hoon similar to a
178struct, class, or object. A core is just a map of names
179to any kind of code, whether it be functions or data. Each
180element in this map begins with a `++` followed by the name and
181the corresponding code. Since `|%` takes an arbitrary number of
182children, it needs to be closed with a `--`.
184<blockquote class="blockquote">
185`++` is not technically a rune, since it is only used in core
186syntax as shown above
187</blockquote>
189Let's step into each of the three arms within our core.
191### `++ sum`
193 ++ sum
194 |= a/@
195 (add (five a) (three a))
196 --
198`|=` produces a function, much like a lambda in lisp. It takes two children:
200- A set of argument(s). In this case our argument set only
201 contains one: `a`, which is required to be an atom or natural
202 number, denoted by `@`.
204- The body of the function itself, which is executed when the
205 function is called (in this case, with `(sum 1.000)`). This
206 particular function adds the results of evaluating the gates `++
207 five` and `++three` with each of their respective input
208 parameters set to `a`.
210### ++ three
212 ++ three
213 |= a/@
214 =| b/@
215 |- ^- @u
216 ?: (lth a b)
217 0
218 (add b $(b (add 3 b)))
220As above, `++three` takes an integer argument, `a`, and then
221executes the remainder of the code with `a` set to the actual
222arguments.
224Similarly, `=|` pushes its first child, `b` into our context (in
225other words, it declares a variable `b`) and executes the
226remainder of the code. However, `b` is not an argument; `=|`
227sets `b` to the default value of whatever type it is declared as.
228Since the default value of an atom is `0`, b is set to `0`.
230So now we have two variables: `a` is set to our input, and `b` is
231initialized to `0`.
233The easiest way to think about `|-` that it lays down a recursion
234point. More on this later.
236`^-` is just a cast that sets the result of the remainder of the
237code to an unsigned integer, `@u`.
239In pseudocode, the last three lines read like this: if `a` is
240less than `b`, produce zero. Else, add `b` to the result of
241rerunning the segment of the function following the `|-` with the
242value of `b` changed to `b` plus three.
244The only thing that should look completely unfamiliar to you here
245is the `$(b (add 3 b))`, which causes us to recurse back to our
246last recursion point with the value of `b` set to `(add 3 b)`.
247Note that we only specify what changes (`b` in this case). If
248you recurse by an actual function call, then you have to specify
249every argument.
251<blockquote class="blockquote">
252If you're familiar with Clojure, `|-` is `loop` and `$()` is
253recur.
254</blockquote>
256**Exercises**:
258Please tweak your code to complete the following excercises.
260There are a few runes and some syntaxes that we have yet to cover that
261you will need to complete the excercises below. For these, please
262refer to our cheatsheat at the bottom.
264- Read and understand `++five` line by line.
266- Change `++sum` to accept two variables, `a` and `b`. Pass `a`
267 to three and `b` to five. Then run the code with `a` set to
268 `1.000` and ` q` set to `2.000`.
270- Check if this new result is under one thousand. If it is,
271 return the string 'result is less than one thousand'. If not,
272 return 'result is greater than or equal to one thousand'.
274```
275Review
277|% start core (collection of named ++ arms; an "object")
278|= define function
279=| define variable from type with default value
280|- drop a recursion point
281^- cast
282?: if-then-else
283=(a b) test equality
284(function args ...) call function
286New material
288- There are two syntaxes for writing Hoon: tall form and wide
289 form.
291 In tall form, expressions are formed with either two spaces or
292 a line break separating both a rune from its children and each
293 of its children from one another. We use tall form when writing
294 multiline expressions.
296 For more concise expressions, we use wideform, which is always
297 a single line. Wideform can be used inside tall form
298 expressions, but not vice versa.
300 Wideform expressions are formed with a rune followed by ()
301 containing its children, all of which are separated by a
302 single space. For example to make a cell of two elements:
304 :-(a b)
306 We've already seen wideform in action, for example with
307 =((mod b 3) 0). In this case = is actually an irregular form
308 of .=, which tests its two children for equality.
310 Surrounding a function with () is an irregular wide form
311 syntax for calling a function with n arguments. More on this later.
313- :- makes a cell of values. The irregular wide form of this is
314 [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])
316- Cords are one datatype for text in hoon. They're just a big
317 atom formed from adjacent unicode bytes -- a "c string". To
318 produce a cord enclose text within single quotes. To set the type
319 of an argument to a cord, use @t.
321```