on 4a847c9 help sign in
418 lines 14 kB history raw
1---
2logo: black
3sort: 1
4next: true
5title: Basic Hoon
6---
8# Basic Hoon
10Our goal is to get you programming interesting and useful things
11as soon as possible. To get there we have to quickly cover some
12of the fundamentals of hoon. To do this we'll walk through two
13simple programs: the first [Project
14Euler](https://projecteuler.net/) problem and
15[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
17To run this code, you'll need an urbit, and you'll need the
18`%examples` desk from `~wactex-ribmex`. If you haven't installed
19urbit yet, check out the [installation
20instructions](http://urbit.org/docs/user/install). Once urbit is
21intalled, take a look at the [basic
22operation](http://urbit.org/docs/user/basic) of your urbit.
24If you haven't pulled the examples desk from `~wactex-ribmex`, do
25so now:
27 ~fintud-macrep:dojo> |merge %examples ~wactex-ribmex %examples
28 >=
29 ; ~wactex-ribmex is your neighbor
30 ; ~wactex-ribmex is your neighbor
31 [time passes...]
32 merged with strategy %init
34The merge could take several minutes; you'll know it's done when
35"merged with strategy %init" is printed. Mount the new files to
36your Unix pier directory:
38 ~fintud-macrep:dojo> |mount /=examples=
40Switch desks to run commands from the `%examples` desk:
42 ~fintud-macrep:dojo> =dir /=examples=
43 =% /~fintud-macrep/examples/~2015.11.13..02.25.00..41e9/
45Run an example:
47 ~fintud-macrep:dojo> +euler1
48 233.168
50## Euler 1
52Let's check out the code for Euler 1. First, the problem:
54```
55If we list all the natural numbers below 10 that are multiples of
563 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
58Find the sum of all the multiples of 3 or 5 below 1000.
59```
61Here is the hoon solution (which should be in your pier directory
62under `/examples/gen/euler1.hoon`):
64```
65:: project euler 1
66:: https://projecteuler.net/problem=1
67:: run in dojo with +euler1
68::
69:::: /hoon/euler1/gen
70 ::
71:- %say |= *
72:- %noun
73=< (sum 1.000)
74::
75:::: ~fintud-macrep
76 ::
77|%
78++ three
79 |= a=@
80 =| b=@
81 |- ^- @u
82 ?: (lth a b)
83 0
84 (add b $(b (add 3 b)))
86++ five
87 |= a=@
88 =| b=@
89 |- ^- @
90 ?: (lte a b)
91 0
92 ?: =((mod b 3) 0)
93 $(b (add b 5))
94 (add b $(b (add b 5)))
96++ sum
97 |= a=@u
98 (add (five a) (three a))
99--
100```
102> Hoon is not generally whitespace sensitive, but we do have two
103> different kinds of whitespace: a single space and a gap, which
104> is two or more spaces or a linebreak. Tabs are taboo. Do not
105> use them. Really. For a more detailed explanation of when to
106> use spaces vs. gaps, see the syntax section before the first
107> excercises.
109### Lines 1-11:
111Any line that begins with `::` is a comment.
113 :- %say |= *
114 :- %noun
115 =< (sum 1.000)
117All you need to know about the lines above is that they call the
118`++sum` function with an argument of `1.000`. We'll cover them in
119more detail later.
121### How to form expressions
123Hoon does not use reserved words to form expressions. Instead,
124expressions are formed with runes, which are diagraphs of two
125ascii symbols. Each rune takes a specific number of
126children--either expressions formed by other runes or literals
127that produce their own value.
129For example, the rune `?:` from line 17 is the classic
130'if-then-else' statement, and thus takes three children:
132 ?: (lth a b) :: if first child evals to true
133 0 :: then produce result of second
134 (add b $(b (add 3 b))) :: else, produce result of third
136Since runes are such a fundamental structure in Hoon, we found
137ourselves speaking them out loud frequently. It quickly grew
138cumbersome to have to say "question mark, colon" to describe
139`?:`. To alleviate this problem, we came up with our own naming
140scheme: each ascii glyph has a single syllable pronunciation
141phonetically designed to be both easily remembered and easily
142pronounced in conjunction with the other glyphs (when forming a
143rune).
145See the entire naming schema below/or link to it:
147```
148 ace [1 space] gal < pel (
149 bar | gap [>1 space, nl] per )
150 bas \ gar > sel [
151 buc $ hax # sem ;
152 cab _ hep - ser ]
153 cen % kel { soq '
154 col : ker } tar *
155 com , ket ^ tec `
156 doq " lus + tis =
157 dot . pam & wut ?
158 fas / pat @ zap !
159```
161Using our naming scheme `?:` is said 'wut col'.
163### Lines 12-34
165Now let's quickly walk through this code line-by-line. Lines
16612-34 are wrapped in a `|%` (pronounced 'bar cen'), which
167produces a core, a fundamental datatype in hoon similar to a
168struct, class, or object. A core is just a map of names
169to any kind of code, whether it be functions or data. Each
170element in this map begins with a `++` followed by the name and
171the corresponding code. Since `|%` takes an arbitrary number of
172children, it needs to be closed with a `--`.
174> `++` is not technically a rune, since it is only used in core
175> syntax as shown above
177Let's step into each of the three arms within our core.
179### `++ sum`
181 ++ sum
182 |= a=@
183 (add (five a) (three a))
184 --
186`|=` produces a function, much like a lambda in lisp. It takes two children:
188- A set of argument(s). In this case our argument set only
189 contains one: `a` which is required to be an atom or natural
190 number, denoted by `@`.
192- The body of the function itself, which is executed when the
193 function is called (in this case, with `(sum 1.000)`). This
194 particular function adds the results of evaluating the gates `++
195 five` and `++three` with each of their respective input
196 parameters set to `a`.
198### ++ three
200 ++ three
201 |= a=@
202 =| b=@
203 |- ^- @u
204 ?: (lth a b)
205 0
206 (add b $(b (add 3 b)))
208As above, `++three` takes an integer argument, `a`, and then
209executes the remainder of the code with `a` set to the actual
210arguments.
212Similarly, `=|` pushes its first child, `b` into our context (in
213other words, it declares a variable `b`) and executes the
214remainder of the code. However, `b` is not an argument; `=|`
215sets `b` to the default value of whatever type it is declared as.
216Since the default value of an atom is `0`, b is set to `0`.
218So now we have two variables: `a` is set to our input, and `b` is
219initialized to `0`.
221The easiest way to think about `|-` that it lays down a recursion
222point. More on this later.
224`^-` is just a cast that sets the result of the remainder of the
225code to an unsigned integer, `@u`.
227In pseudocode, the last three lines read like this: if `a` is
228less than `b`, produce zero. Else, add `b` to the result of
229rerunning the segment of the function following the `|-` with the
230value of `b` changed to `b` plus three.
232The only thing that should look completely unfamiliar to you here
233is the `$(b (add 3 b))`, which causes us to recurse back to our
234last recursion point with the value of `b` set to `(add 3 b)`.
235Note that we only specify what changes (`b` in this case). If
236you recurse by an actual function call, then you have to specify
237every argument.
239> If you're familiar with Clojure, `|-` is `loop` and `$()` is
240> recur.
242**Exercises**:
244Please tweak your code to complete the following excercises.
246There are a few runes and some syntax that we have yet to cover that
247you will need to complete the excercises below. For these, please
248refer to our cheatsheat at the bottom.
250- Read and understand `++five` line by line.
252- Change `++sum` to accept two variables, `a` and `b`. Pass `a`
253 to three and `b` to five. Then run the code with `a` set to
254 `1.000` and b set to `2.000`.
256- Check if this new result is under one thousand. If it is,
257 return the string 'result is less than one thousand'. If not,
258 return 'result is greater than or equal to one thousand'.
260```
261Review
263|% start core (collection of named ++ arms)
264|= define function
265=| define variable from type with default value
266|- drop a recursion point
267^- cast
268?: if-then-else
269=(a b) test equality
270(function args ...) call function
272New material
274- :- make a cell of values. The irregular wide form of this is
275 [a b] with two expressions separated by a single space.
277- Cords are one datatype for text in hoon. They're just a big
278 atom formed from adjacent unicode bytes -- a "c string". To
279 produce a cord enclose text within single quotes. To set the type
280 of an argument to a cord, use @t.
282- There are two syntaxes for writing Hoon: tall form and wide
283 form.
285 In tall form, expressions are formed with either two spaces or
286 a line break separating both a rune from its children and each
287 of its children from one another. We use tall form when writing
288 multiline expressions.
290 For more concise expressions, we use wideform, which is always
291 a single line. Wideform can be used inside tall form
292 expressions, but not vice versa.
294 Wideform expressions are formed with a rune followed by ()
295 containing its children, all of which are separated by a
296 single space. For example to make a cell of two elements:
298 :-(a b)
300 We've already seen wideform in action, for example with
301 =((mod b 3) 0). In this case = is actually an irregular form
302 of .=, which tests its two children for equality.
304 Another irregular form is [a b] for :-(a b)
306 Surrounding a function with () is an irregular wide form
307 syntax for calling a function with n arguments.
308```
311## The subject
313Now we're going to cover the boiler plate that we skimmed over
314earlier.
316 :- %say |= *
317 :- %noun
318 =< (sum [1.000 2.000])
320This program is a cell of two elements: the first, `%say`, tells
321the interpreter what to produce--in this case a value.
323The second element is `|=`, which we know produces a function.
324`|=`'s first child is its argument(s), which in this case is any
325noun (`*`). Its second child is the remainder of the program.
327Similarly, the rest of the program is a cell of the literal
328`%noun`, which tells the shell that we're producing a value of
329type `noun`, and the second child contains the code that we run
330to actually produce our value of the type `noun`.
332`=<` is a rune that takes two children. The second child is the
333context against which we run the first child. So in this case, we
334are running the expression `(sum 1.000)` against everything
335contained within the `|%`. In Hoon, we call the code executed the
336"formula" and its context the "subject".
338```
339::::::::::::::::::::::::::::::
340=< (sum 1.000) :: formula
341::::::::::::::::::::::::::::::
342|% ::
343++ three ::
344 |= a=@ ::
345 =| b=@ ::
346 |- ^- @u ::
347 ?: (lth a b) ::
348 0 ::
349 (add b $(b (add 3 b))) ::
350 ::
351++ five ::
352 |= a=@ :: subject
353 =| b=@ ::
354 |- ^- @ ::
355 ?: (lte a b) ::
356 0 ::
357 ?: =((mod b 3) 0) ::
358 $(b (add b 5)) ::
359 (add b $(b (add b 5))) ::
360 ::
361++ sum ::
362 |= a=@u ::
363 (add (five a) (three a)) ::
364-- ::
365::::::::::::::::::::::::::::::
366```
368In nearly every language there is a similar concept of a
369"context" in which expressions are executed. For example, in C
370this includes things like the call stack, stack variables, and so
371on.
373Hoon is unique in that this context is a first-class value.
374Scheme allows a sort of reification of the context through
375continutations, and some may see a parallel to Forth's stack, but
376Hoon takes takes the concept one step further.
378Our starting subject is the standard library, which is defined in
379`/arvo/hoon.hoon` and `/arvo/zuse.hoon`. This is where functions
380like `add` are defined. When we define a core with `|%`, we
381don't throw away the subject (i.e. the standard library); rather,
382we stack the new core on top of the old subject so that both are
383accessible.
385**Exercises**:
387- Pass `++sum` its arguments (`2000` and `3000`) from the
388 commandline.
390- Comment out all of the arms of the `|%`. Now add another arm
391 and call it `++add`, have it accept two arguments and procduce
392 42 (regardless of input). Change the `=<` line to `[(add 5 7)
393 (^add 5 7)]`. Can you recognize what's happening?
395- Write a program that prints the numbers from 1 to 100 (entered
396 from the command line), except that for multiples of three
397 print 'Fizz' instead of the number and for the multiples of
398 five print 'Buzz'. For numbers which are multiples of both
399 three and five print 'FizzBuzz'.
401Cheatsheet:
403- To pass arguments from the command line to a program, you
404 replace the `*` in the first line of the boiler plate to
405 `[^ [[arg=TYPE ~] ~]]` where `TYPE` is replaced with the
406 type of argument you're expecting. Then `+euler1 a` from
407 the dojo sets `arg` to `a`.
408- A list of strings is of type `(list ,@t)`, so the result of
409 the fizzbuzz function is of this type (hint: you'll need to
410 use `^-`)
411- The empty list is `~`
412- Lisp-style cons (construct a cell/prepend an element) is
413 `[new-element list]`
414- For example, the first three positive integers are `[1 2 3
415 ~]`
416- `gte` tests whether `a` is greater than or equal to `b`.
417- `mod` runs the modulo operation on two atoms.
418- See the [basic math section]() for more info.