Merge branches 'top-down', 'claydoc-rebase', 'curtis-url-fix' and 'curtis-tutorial-3-4'

Conflicts:
	urb/zod/pub/docs/dev/hoon/tutorial/2-syntax.mdy

added urbit.pill

fixes #563
fixes #574
This commit is contained in:
Philip C Monk 2015-11-20 18:56:19 -05:00
28 changed files with 1573 additions and 709 deletions

View File

@ -4,10 +4,7 @@
/? 314
/- talk, sole
/+ talk, sole
/= seed /~ !>(.)
/= talk-doc
/; |=(a=wain (turn a |=(b=cord [%txt "? {(trip b)}"])))
/: /===/pub/doc/talk/help /txt/
/= seed /~ !>(.)
::
::::
::
@ -913,7 +910,7 @@
%unset (unset +.job)
%target (target +.job)
%probe (probe +.job)
%help (help)
%help help
%say (say +.job)
==
::
@ -921,10 +918,12 @@
|= gam=telegram
^+ ..sh-work
=+ tay=~(. tr man.she (~(has in settings.she) %noob) gam)
=. ..sh-work (sh-fact %tan tr-tang:tay)
=. ..sh-work (sh-fact tr-fact:tay)
sh-prod(active.she `tr-pals:tay)
::
++ help |=(~ (sh-fact %mor talk-doc)) :: %help
++ help
(sh-fact %txt "see http://urbit.org/docs/user/talk")
::
++ glyph
|= idx=@
=< cha.ole
@ -1597,7 +1596,7 @@
pa-report-cabal
::
++ pa-cancel :: unsubscribe from
~& [%pa-cancel ost.hid]
:: ~& [%pa-cancel ost.hid]
%_ .
gramsers (~(del by gramsers) ost.hid)
groupers (~(del in groupers) ost.hid)
@ -1932,6 +1931,9 @@
bou=bouquet
sep=speech
==
++ tr-fact ^- sole-effect :: activate effect
~[%mor [%tan tr-meta] tr-body]
::
++ tr-line ^- tape :: one-line print
=+ txt=(tr-text =(who our.hid))
?: =(~ txt) ""
@ -1943,8 +1945,7 @@
(~(sn-nick sn man [who (main who)]))
(weld baw txt)
::
++ tr-tang ^- tang
%+ welp tr-sep-tang
++ tr-meta ^- tang
=. wen (sub wen (mod wen (div wen ~s0..0001))) :: round
=+ hed=leaf/"{(scow %uv sen)} at {(scow %da wen)}"
=+ =< paz=(turn (~(tap by aud)) .)
@ -1952,18 +1953,17 @@
=+ bok=(turn (sort (~(tap in bou)) aor) smyt)
[%rose [" " ~ ~] [hed >who< [%rose [", " "to " ~] paz] bok]]~
::
++ tr-sep-tang
|- ^- tang
=< ?+(. . [@ *] [.]~) ^- ?(tank tang) :: wrap single tanks
?+ -.sep [>sep<]~
%exp palm/[~ "#" " " ~]^~[leaf/(trip p.sep)]
%lin leaf/"{?:(p.sep "" "@ ")}{(trip q.sep)}"
%non ~
%app rose/[": " ~ ~]^~[leaf/"[{(trip p.sep)}]" leaf/(trip q.sep)]
%tax leaf/(rend-work-duty p.sep)
%url palm/[~ "/" " " ~]^~[leaf/(earf p.sep)]
%mor ?~(p.sep ~ (weld $(p.sep t.p.sep) $(sep i.p.sep)))
%fat (welp (tr-rend-tors p.sep) $(sep q.sep))
++ tr-body
|- ^- sole-effect
?+ -.sep tan/[>sep<]~
%exp tan/~[leaf/"# {(trip p.sep)}"]
%lin tan/~[leaf/"{?:(p.sep "" "@ ")}{(trip q.sep)}"]
%non tan/~
%app tan/~[rose/[": " ~ ~]^~[leaf/"[{(trip p.sep)}]" leaf/(trip q.sep)]]
%tax tan/~[leaf/(rend-work-duty p.sep)]
%url url/(crip (earf p.sep))
%mor mor/(turn p.sep |=(speech ^$(sep +<)))
%fat [%mor tan/(tr-rend-tors p.sep) $(sep q.sep) ~]
==
::
++ tr-rend-tors
@ -2111,7 +2111,7 @@
++ pull ::
|= [pax=path]
^- [(list move) _+>]
~& [%talk-pull src.hid ost.hid pax]
:: ~& [%talk-pull src.hid ost.hid pax]
=^ moz +>.$ ra-abet:(ra-cancel:ra src.hid pax)
[moz +>.$(shells (~(del by shells) ost.hid))]
::

View File

@ -132,7 +132,7 @@
ins=(unit (list (pair path cage))) :: inserts
dig=(map path cage) :: store diffs
dif=(unit (list (trel path lobe cage))) :: changes
muc=(map path cage) :: store miso
muc=(map path cage) :: store mutations
muh=(map path lobe) :: store hashes
mut=(unit (list (trel path lobe cage))) :: mutations
mim=(map path mime) :: mime cache
@ -492,6 +492,60 @@
$(p.lem t.p.lem)
==
::
:: This is the entry point to the commit flow. It deserves some
:: explaining, since it's rather long and convoluted.
::
:: We take a `++nori`, which is either a label-add request or a `++soba`,
:: which is a list of changes. If it's a label, it's easy and we just pass
:: it to `++edit:ze`.
::
:: If the given `++nori` is a list of file changes, then we our goal is to
:: convert the list of `++miso` changes to `++misu` changes. In other
:: words, turn the `++nori` into a `++nuri`. Then, we pass it to
:: `++edit:ze`, which applies the changes to our state, and then we
:: check out the new revision. XX reword
::
:: Anyhow, enough of high-level wishy-washy talk. It's time to get down to
:: the nitty-gritty.
::
:: When we get a list of `++miso` changes, we split them into four types:
:: deletions, insertions, diffs (i.e. change from diff), and mutations
:: (i.e. change from new data). We do four different things with them.
::
:: For deletions, we just fill in `del` in `++dork` with a list of the
:: deleted files.
::
:: For insertions, we distinguish bewtween `%hoon` files and all other
:: files. For `%hoon` files, we just store them to `ink` in `++dork` so
:: that we add diff them directly. `%hoon` files have to be treated
:: specially to make the bootstrapping sequence work, since the mark
:: definitions are themselves `%hoon` files.
::
:: For the other files, we make a `%tabl` compound ford request to convert
:: the data for the new file to the the mark indicated by the last span in
:: the path.
::
:: For diffs, we make a `%tabl` compound ford request to apply the diff to
:: the existing content. We also store the diffs in `dig` in `++dork`.
::
:: For mutations, we make a `%tabl` compound ford request to convert the
:: given new data to the mark of the already-existing file. Later on in
:: `++take-castify` we'll create the ford request to actually perform the
:: diff. We also store the mutations in `muc` in `++dork`. I'm pretty
:: sure that's useless because who cares about the original data.
:: XX delete `muc`.
::
:: Finally, for performance reasons we cache any of the data that came in
:: as a `%mime` cage. We do this because many commits come from unix,
:: where they're passed in as `%mime` and need to be turned back into it
:: for the ergo. We cache both `%hoon` and non-`%hoon` inserts and
:: mutations.
::
:: At this point, the flow of control goes through the three ford requests
:: back to `++take-inserting`, `++take-diffing`, and `++take-castifying`,
:: which itself leads to `++take-mutating`. Once each of those has
:: completed, we end up at `++apply-edit`, where our unified story picks up
:: again.
++ edit :: apply changes
|= [wen=@da lem=nori]
^+ +>
@ -608,31 +662,7 @@
==
==
::
++ silkify
|= [wen=@da pax=path mis=miso]
^- [duct path note]
~| [%silkifying pax -.mis]
:- hen
?+ -.mis !!
%mut
:- [%diffing (scot %p her) syd (scot %da wen) pax]
:^ %f %exec our :+ ~ [her syd %da wen]
^- silk
:+ %diff
(lobe-to-silk:ze pax (~(got by q:(aeon-to-yaki:ze let.dom)) pax))
=+ (slag (dec (lent pax)) pax)
=+ ?~(- %$ i.-)
[%cast - [%$ p.mis]]
::
%ins
:- [%casting (scot %p her) syd (scot %da wen) pax]
:^ %f %exec our :+ ~ [her syd %da wen]
^- silk
=+ (slag (dec (lent pax)) pax)
=+ ?~(- %$ i.-)
[%cast - [%$ p.mis]]
==
::
:: See ++edit for a description of the commit flow.
++ apply-edit
|= wen=@da
^+ +>
@ -664,6 +694,7 @@
([echo(dok ~)]:.(+>.$ +.hat) wen %& sim)
(checkout-ankh(lat.ran lat.ran.+.hat) u.-.hat)
::
:: See ++edit for a description of the commit flow.
++ take-inserting
|= [wen=@da res=gage]
^+ +>
@ -684,6 +715,7 @@
~|(%clay-take-inserting-strange-path-mark !!)
[((hard path) q.q.pax) cay]
::
:: See ++edit for a description of the commit flow.
++ take-diffing
|= [wen=@da res=gage]
^+ +>
@ -706,6 +738,7 @@
=+ paf=((hard path) q.q.pax)
[paf (page-to-lobe:ze [p q.q]:cay) (~(got by dig.u.dok) paf)]
::
:: See ++edit for a description of the commit flow.
++ take-castify
|= [wen=@da res=gage]
^+ +>
@ -736,6 +769,7 @@
[%diff - [%$ cay]]
==
::
:: See ++edit for a description of the commit flow.
++ take-mutating
|= [wen=@da res=gage]
^+ +>
@ -760,6 +794,7 @@
=+ paf=((hard path) q.q.pax)
`[paf (~(got by muh.u.dok) paf) cay]
::
:: See ++edit for a description of the commit flow.
++ take-patch
|= res=gage
^+ +>
@ -844,6 +879,7 @@
(lobe-to-silk:ze a p.-)
==
::
:: See ++edit for a description of the commit flow.
++ take-ergo
|= res=gage
^+ +>
@ -870,6 +906,7 @@
[(slag len pax) (~(got by can) pax)]
==
::
:: See ++edit for a description of the commit flow.
++ checkout-ankh
|= hat=(map path lobe)
^+ +>
@ -2692,7 +2729,6 @@
..^$(ruf ruf.old)
::
++ scry :: inspect
:: Make a request
|= [fur=(unit (set monk)) ren=@tas his=ship syd=desk lot=coin tyl=path]
^- (unit (unit cage))
:: ~& scry/[ren `path`[(scot %p his) syd ~(rent co lot) tyl]]

View File

@ -1388,7 +1388,7 @@
%plan (cope (abut:(meow p.kas q.kas) cof r.kas) faun)
%reef (faun cof pit)
%ride
%+ cool |.(leaf/"ford: ride {<`@p`(mug kas)>}")
%+ cool |.(leaf/"ford: build failed}")
%+ cope $(kas q.kas)
%- tabl-run
|= [cof=cafe cay=cage]

View File

@ -673,7 +673,7 @@
?. (~(has by sup.ged) ost) .
=+ soy=(~(get by qel.ged) ost)
?: |(?=(~ soy) =(0 u.soy))
~& [%ap-fill-under [our dap] q.q.pry ost]
:: ~& [%ap-fill-under [our dap] q.q.pry ost]
+
=. u.soy (dec u.soy)
:: ~& [%ap-fill-sub [[our dap] q.q.pry ost] u.soy]
@ -1049,7 +1049,7 @@
::
++ ap-pull :: load delete
=+ wim=(~(get by sup.ged) ost)
?~ wim ~&(%ap-pull-none +)
?~ wim + :: ~&(%ap-pull-none +)
=: sup.ged (~(del by sup.ged) ost)
qel.ged (~(del by qel.ged) ost)
==
@ -1062,7 +1062,7 @@
+>+
::
++ ap-kill :: queue kill
~& [%ap-kill dap ost]
:: ~& [%ap-kill dap ost]
(ap-give:ap-pull %quit ~)
::
++ ap-take :: non-diff gall take
@ -1070,7 +1070,7 @@
^+ +>
=+ cug=(ap-find cog pax)
?~ cug
~& [%ap-take-none cog pax]
:: ~& [%ap-take-none cog pax]
+>.$
=^ cam +>.$
%+ ap-call q.u.cug

View File

@ -2389,6 +2389,7 @@
[%mor ~] :: newline
[%sag p=path q=*] :: save to jamfile
[%sav p=path q=@] :: save to file
[%url p=@t] :: activate url
== ::
++ dill-belt :: new belt
$% [%aro p=?(%d %l %r %u)] :: arrow key
@ -2413,6 +2414,7 @@
[%out p=(list ,@c)] :: send output line
[%sag p=path q=*] :: save to jamfile
[%sav p=path q=@] :: save to file
[%url p=@t] :: activate url
== ::
++ flog :: sent to %dill
$% [%crud p=@tas q=(list tank)] ::
@ -2427,6 +2429,7 @@
++ gift-dill :: out result <-$
$% [%bbye ~] :: reset prompt
[%blit p=(list blit)] :: terminal output
[%burl p=@t] :: activate url
[%init p=@p] :: set owner
[%logo ~] :: logout
[%mass p=mass] :: memory usage

View File

@ -663,6 +663,7 @@
%sag +>(+> (se-blit fec))
%sav +>(+> (se-blit fec))
%txt $(fec [%tan [%leaf p.fec]~])
%url +>(+> (se-blit fec))
==
::
++ ta-dog :: change cursor

View File

@ -1,17 +1,24 @@
---
logo: black
title: Hoon
sort: 2
title: Hoon
---
<div class="short">
# Hoon
Hoon is a strict, typed, pure functional language. This site is served by an
urbit written in Hoon.
Hoon is a strict, typed, pure functional language. This site is
served by an urbit written in Hoon.
We're still developing the documentation; start with the
bottom-up tutorial, ["Hoon 101"](hoon/tutorial).
If you're interested in learning the fundamentals of Hoon from
the bottom up, start with [Principles of
Hoon](hoon/tutorial).
If you want to jump into building things right away and prefer to
learn from the top down, check out [Leap into
Hoon](hoon/jump-in/1-basic).
Both of these are under active development.
</div>

View File

@ -0,0 +1,420 @@
---
logo: black
sort: 1
title: Basic Hoon
---
# Basic Hoon
Our goal is to get you programming interesting and useful things
as soon as possible. To get there we have to quickly cover some
of the fundamentals of hoon. To do this we'll walk through two
simple programs: the first [Project
Euler](https://projecteuler.net/) problem and
[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
To run this code, you'll need an urbit, and you'll need the
`%examples` desk from `~wactex-ribmex`. If you haven't installed
urbit yet, check out the [installation
instructions](http://urbit.org/docs/user/install). Once urbit is
intalled, take a look at the [basic
operation](http://urbit.org/docs/user/basic) of your urbit.
If you haven't pulled the examples desk from `~wactex-ribmex`, do
so now:
~fintud-macrep:dojo> |merge %examples ~wactex-ribmex %examples
>=
; ~wactex-ribmex is your neighbor
; ~wactex-ribmex is your neighbor
[time passes...]
merged with strategy %init
The merge could take several minutes; you'll know it's done when
"merged with strategy %init" is printed. Mount the new files to
your Unix pier directory:
~fintud-macrep:dojo> |mount /=examples=
Switch desks to run commands from the `%examples` desk:
~fintud-macrep:dojo> =dir /=examples
=% /~fintud-macrep/examples/~2015.11.13..02.25.00..41e9/
Run an example:
~fintud-macrep:dojo> +euler1
233.168
## Euler 1
Let's check out the code for Euler 1. First, the problem:
```
If we list all the natural numbers below 10 that are multiples of
3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
```
Here is the hoon solution (which should be in your pier directory
under `/examples/gen/euler1.hoon`):
```
:: project euler 1
:: https://projecteuler.net/problem=1
:: run in dojo with +euler1
::
:::: /hoon/euler1/gen
::
:- %say |= *
:- %noun
=< (sum 1.000)
::
:::: ~fintud-macrep
::
|%
++ three
|= a=@
=| b=@
|- ^- @u
?: (lth a b)
0
(add b $(b (add 3 b)))
++ five
|= a=@
=| b=@
|- ^- @
?: (lte a b)
0
?: =((mod b 3) 0)
$(b (add b 5))
(add b $(b (add b 5)))
++ sum
|= a=@u
(add (five a) (three a))
--
```
> Hoon is not generally whitespace sensitive, but we do have two
> different kinds of whitespace: a single space and a gap, which
> is two or more spaces or a linebreak. Tabs are taboo. Do not
> use them. Really. For a more detailed explanation of when to
> use spaces vs. gaps, see the syntax section before the first
> excercises.
### Lines 1-11:
Any line that begins with `::` is a comment.
:- %say |= *
:- %noun
=< (sum 1.000)
All you need to know about the lines above is that they call the
`++sum` function with an argument of `1.000`. We'll cover them in
more detail later.
### How to form expressions
Hoon does not use reserved words to form expressions. Instead,
expressions are formed with runes, which are diagraphs of two
ascii symbols. Each rune takes a specific number of
children--either expressions formed by other runes or literals
that produce their own value.
For example, the rune `?:` from line 17 is the classic
'if-then-else' statement, and thus takes three children:
?: (lth a b) :: if first child evals to true
0 :: then produce result of second
(add b $(b (add 3 b))) :: else, produce result of third
Since runes are such a fundamental structure in Hoon, we found
ourselves speaking them out loud frequently. It quickly grew
cumbersome to have to say "question mark, colon" to describe
`?:`. To alleviate this problem, we came up with our own naming
scheme: each ascii glyph has a single syllable pronunciation
phonetically designed to be both easily remembered and easily
pronounced in conjunction with the other glyphs (when forming a
rune).
See the entire naming schema below/or link to it:
```
ace [1 space] gal < pel (
bar | gap [>1 space, nl] per )
bas \ gar > sel [
buc $ hax # sem ;
cab _ hep - ser ]
cen % kel { soq '
col : ker } tar *
com , ket ^ tec `
doq " lus + tis =
dot . pam & wut ?
fas / pat @ zap !
```
Using our naming scheme `?:` is said 'wut col'.
### Lines 12-34
Now let's quickly walk through this code line-by-line. Lines
12-34 are wrapped in a `|%` (pronounced 'bar cen'), which
produces a core, a fundamental datatype in hoon similar to a
struct, class, or object. A core is just a map of names
to any kind of code, whether it be functions or data. Each
element in this map begins with a `++` followed by the name and
the corresponding code. Since `|%` takes an arbitrary number of
children, it needs to be closed with a `--`.
> `++` is not technically a rune, since it is only used in core
> syntax as shown above
Let's step into each of the three arms within our core.
### `++ sum`
++ sum
|= a=@
(add (five a) (three a))
--
`|=` produces a function, much like a lambda in lisp. It takes two children:
- A set of argument(s). In this case our argument set only
contains one: `a` which is required to be an atom or natural
number, denoted by `@`.
- The body of the function itself, which is executed when the
function is called (in this case, with `(sum 1.000)`). This
particular function adds the results of evaluating the gates `++
five` and `++three` with each of their respective input
parameters set to `a`.
### ++ three
++ three
|= a=@
=| b=@
|- ^- @u
?: (lth a b)
0
(add b $(b (add 3 b)))
As above, `++three` takes an integer argument, `a`, and then
executes the remainder of the code with `a` set to the actual
arguments.
Similarly, `=|` pushes its first child, `b` into our context (in
other words, it declares a variable `b`) and executes the
remainder of the code. However, `b` is not an argument; `=|`
sets `b` to the default value of whatever type it is declared as.
Since the default value of an atom is `0`, b is set to `0`.
So now we have two variables: `a` is set to our input, and `b` is
initialized to `0`.
The easiest way to think about `|-` that it lays down a recursion
point. More on this later.
`^-` is just a cast that sets the result of the remainder of the
code to an unsigned integer, `@u`.
In pseudocode, the last three lines read like this: if `a` is
less than `b`, produce zero. Else, add `b` to the result of
rerunning the segment of the function following the `|-` with the
value of `b` changed to `b` plus three.
The only thing that should look completely unfamiliar to you here
is the `$(b (add 3 b))`, which causes us to recurse back to our
last recursion point with the value of `b` set to `(add 3 b)`.
Note that we only specify what changes (`b` in this case). If
you recurse by an actual function call, then you have to specify
every argument.
> If you're familiar with Clojure, `|-` is `loop` and `$()` is
> recur.
## Excercises
Please tweak your code to complete the following excercises.
There are a few runes and some syntax that we have yet to cover that
you will need to complete the excercises below. For these, please
refer to our cheatsheat at the bottom.
1. Read and understand `++five` line by line.
2. Change `++sum` to accept two variables, `a` and `b`. Pass `a`
to three and `b` to five. Then run the code with `a` set to
`1.000` and b set to `2.000`.
3. Check if this new result is under one thousand. If it is,
return the string 'result is less than one thousand'. If not,
return 'result is greater than or equal to one thousand'.
```
Review
|% start core (collection of named ++ arms)
|= define function
=| define variable from type with default value
|- drop a recursion point
^- cast
?: if-then-else
=(a b) test equality
(function args ...) call function
New material
- :- make a cell of values. The irregular wide form of this is
[a b] with two expressions separated by a single space.
- Cords are one datatype for text in hoon. They're just a big
atom formed from adjacent unicode bytes -- a "c string". To
produce a cord enclose text within single quotes. To set the type
of an argument to a cord, use @t.
- There are two syntaxes for writing Hoon: tall form and wide
form.
In tall form, expressions are formed with either two spaces or
a line break separating both a rune from its children and each
of its children from one another. We use tall form when writing
multiline expressions.
For more concise expressions, we use wideform, which is always
a single line. Wideform can be used inside tall form
expressions, but not vice versa.
Wideform expressions are formed with a rune followed by ()
containing its children, all of which are separated by a
single space. For example to make a cell of two elements:
:-(a b)
We've already seen wideform in action, for example with
=((mod b 3) 0). In this case = is actually an irregular form
of .=, which tests its two children for equality.
Another irregular form is [a b] for :-(a b)
Surrounding a function with () is an irregular wide form
syntax for calling a function with n arguments.
```
## The subject
Now we're going to cover the boiler plate that we skimmed over
earlier.
:- %say |= *
:- %noun
=< (sum [1.000 2.000])
This program is a cell of two elements: the first, `%say`, tells
the interpreter what to produce--in this case a value.
The second element is `|=`, which we know produces a function.
`|=`'s first child is its argument(s), which in this case is any
noun (`*`). Its second child is the remainder of the program.
Similarly, the rest of the program is a cell of the literal
`%noun`, which tells the shell that we're producing a value of
type `noun`, and the second child contains the code that we run
to actually produce our value of the type `noun`.
`=<` is a rune that takes two children. The second child is the
context against which we run the first child. So in this case, we
are running the expression `(sum 1.000)` against everything
contained within the `|%`. In Hoon, we call the code executed the
"formula" and its context the "subject".
```
::::::::::::::::::::::::::::::
=< (sum 1.000) :: formula
::::::::::::::::::::::::::::::
|% ::
++ three ::
|= a=@ ::
=| b=@ ::
|- ^- @u ::
?: (lth a b) ::
0 ::
(add b $(b (add 3 b))) ::
::
++ five ::
|= a=@ :: subject
=| b=@ ::
|- ^- @ ::
?: (lte a b) ::
0 ::
?: =((mod b 3) 0) ::
$(b (add b 5)) ::
(add b $(b (add b 5))) ::
::
++ sum ::
|= a=@u ::
(add (five a) (three a)) ::
-- ::
::::::::::::::::::::::::::::::
```
In nearly every language there is a similar concept of a
"context" in which expressions are executed. For example, in C
this includes things like the call stack, stack variables, and so
on.
Hoon is unique in that this context is a first-class value.
Scheme allows a sort of reification of the context through
continutations, and some may see a parallel to Forth's stack, but
Hoon takes takes the concept one step further.
Our starting subject is the standard library, which is defined in
`/arvo/hoon.hoon` and `/arvo/zuse.hoon`. This is where functions
like `add` are defined. When we define a core with `|%`, we
don't throw away the subject (i.e. the standard library); rather,
we stack the new core on top of the old subject so that both are
accessible.
## Exercises:
4. Pass `++sum` its arguments (`2000` and `3000`) from the
commandline.
5. Comment out all of the arms of the `|%`. Now add another arm
and call it `++add`, have it accept two arguments and procduce
42 (regardless of input). Change the `=<` line to `[(add 5 7)
(^add 5 7)]`. Can you recognize what's happening?
6. Write fizbuzz:
Write a program that prints the numbers from 1 to 100
(entered from the command line). But for multiples of three
print 'Fizz' instead of the number and for the multiples of
five print 'Buzz'. For numbers which are multiples of both
three and five print 'FizzBuzz'.
Cheatsheet:
- To pass arguments from the command line to a program, you
replace the `*` in the first line of the boiler plate to
`[^ [[arg=TYPE ~] ~]]` where `TYPE` is replaced with the
type of argument you're expecting. Then `+euler1 a` from
the dojo sets `arg` to `a`.
- A list of strings is of type `(list ,@t)`, so the result of
the fizzbuzz function is of this type (hint: you'll need to
use `^-`)
- The empty list is `~`
- Lisp-style cons (construct a cell/prepend an element) is
`[new-element list]`
- For example, the first three positive integers are `[1 2 3
~]`
- `gte` tests whether `a` is greater than or equal to `b`.
- `mod` runs the modulo operation on two atoms.
- See the [basic math section]() for more info.

View File

@ -0,0 +1,188 @@
---
hide: true
next: false
sort: 3
title: Network Messages
---
Enough of pure hoonery. Let's get to the good stuff. Let's get
our planets to talk to each other.
Of course, for talking to be of any use, we need someone
listening. What we've written up until now are just shell
commands that produce a value and then disappear. We need an
actual app to listen for messages from another planet. Let's
take a look at a very basic one.
```
:: There is no love that is not an echo
::
:::: /hoon/echo/ape
::
/? 314
|%
++ move ,*
--
!:
|_ [bowl state=~]
++ poke-noun
|= arg=*
^- [(list move) _+>.$]
~& [%argument arg]
[~ +>.$]
--
```
This is a very simple app that does only one thing. If you poke
it with a value it prints that out. You have to start the app,
then you can poke it from the command line.
```
> |start %echo
>=
> :echo 5
[%argument 5]
> :echo [1 2]
[%argument [1 2]]
```
Most of the app code should be simple enough to guess its
function. The important part of this code is the definition of
`++poke-noun`.
Once an app starts, it's always on in the background, and you
interact with it by sending it messages. The most
straightforward way to do that is to poke it from the command
line. When you do that, `++poke-noun` is called from your app.
In our case, `++poke-noun` takes an argument `arg` and prints it
out with `~&`. This is an unusual rune that formally "does
nothing", but the interpreter detects it and printfs the first
child. This is a slightly hacky way of printing to the console,
and we'll get to the correct way later on.
But what does `++poke-noun` produce? The phrase to remember is
"a list of moves and our state". Urbit is a message passing
system, so whenver we want to do something that interacts with
the rest of the system we send a message. Thus, the first thing
that `++poke-noun` produces is a list of messages, called
"moves". In this case, we don't actually want the system to do
anything, so we produce the empty list, `~`.
The second thing `++poke-noun` produces is our state. `+>.$`
refers to a particular address in our subject where our formal
app state is stored. It'll become clear why this is later on,
but for now pretend that `+>.$` is a magic invocation that means
"app state".
---
But what is our app state, exactly? In Unix systems, application
state is just a block of memory, which you need to serialize to
disk if you want to keep it around for very long.
In urbit, app state is a single (usually complex) value. In our
example, we don't have any special state, so we defined
`state=~`, meaning that our state is null. Of course, `state` is
just a name we're assigning to it, and you're free to use
whatever name you want.
Since urbit is purely functional, we can't just implicitly "have"
and "change" our state. Rather, it's explicitly passed to us, in
the `|_ [bowl state=~]` line, and we produce the new state with
`+>.$` in the `[~ +>.$]` line.
Two points you may be wondering about. Firstly, `bowl` is a set
of general global state that is managed by the system. It
includes things like `now` (current time), `our` (our urbit
identity), and `eny` (256 bits of guaranteed-fresh entropy). For
the full list of things in `++bowl`, search for `++ bowl` (note
the double space) in `/arvo/zuse.hoon`.
> This is a very common technique in learning hoon. While some
> documentation exists, often the easiest way to learn about an
> identifier you see in code is to search in `/arvo/zuse.hoon`
> and `/arvo/hoon.hoon` for it. These are our two "standard
> libraries", and they're usually not hard to read. Since
> urbit's codebase is relatively small (those two files are less
> than 15000 lines of code combined, and besides the standard
> library they include the hoon parser and compiler, plus the
> /arvo microkernel), you can usually use the code and the
> comments as reference doc.
Second point is that urbit needs no "serialize to disk" step.
Everything you produce in the app state is persistent across
calls to the app, restarts of the urbit, and even power failure.
If you want to write to the filesystem, you can, but it's not
needed for persistence. Urbit has transactional events, which
makes it an ACID operating system. Persistence is just another
one of those things you don't have to worry about when
programming in urbit.
As fascinating as state is, we don't actually need any state to
accomplish our immediate goal, which is to get apps on two urbits
talking to each other. We'll discuss state more in a later
chapter.
---
Anyway, that's a lot of theory, let's get back to coding. Let's
say we want to only accept a number, and then print out the
square of that number.
```
/? 314
|%
++ move ,*
--
!:
|_ [bowl state=~]
::
++ poke-atom
|= arg=@
^- [(list move) _+>.$]
~& [%square (mul arg arg)]
[~ +>.$]
--
```
A few things have changed. Firstly, we no longer accept
arbitrary nouns because we can only square atoms. Thus, our
argument is now `arg=@`. Secondly, it's `++poke-atom` rather
than `++poke-noun`.
Are there other `++poke`s? Definitely. In fact, `noun` and
`atom` are just two of arbitrarily many "marks". A mark is
fundamentally a type definition, and each mark is defined in the
`/mar` directory. Some marks have conversion routines to other
marks, and some have diff, path, and merge algorithms. None of
these are required for a mark to exist, though.
`noun` and `atom` are two of dozens of predefined marks, and the
user may add more at will. The type associated with `noun` is
`*`, and the type associated with `atom` is `@`.
Data constructed on the command line is by default marked with
`noun`. In this case, the app is expecting an atom, so we have
to explicitly mark the data with `atom`.
```
> |start %square
> :square 6
gall: %square: no poke arm for noun
> :square &atom 6
[%square 36]
```
Marks are powerful, and they're the backbone of urbit's data
pipeline, so we'll be getting quite used to them.
Let's write our first network message!
-don't forget to explain new hoon concepts ([])
-excercises
-then walk through more in depth
-move app state section to somewhere later
-put in interactive code snippets and explain a lil (bowl)

View File

@ -281,6 +281,6 @@ Can we use mutation to build a cyclical noun? Nice try, but no:
## Progress
Now, not only can we build a noun, we can get data out of it and
Now, not only can you build a noun, you can get data out of it and
even evolve new, related nouns. We've still seen only two very
restricted kinds of twigs: constants and legs. In the [next chapter](2-syntax), we'll actually write some interesting expressions.

View File

@ -244,6 +244,16 @@ ever. In Hoon it's called a *kelp*.
The head of a kelp (like `%dtzy` above) is called the *stem*.
The tail (like `[%ux 42]`) is the *bulb*.
> Think about how to encode tagged data in a noun. It seems
obvious that the noun is a cell, where the head of the cell is
the tag (stem) and the tail is the data (bulb). Then, all these
nouns are cells whose head is an atom. This leaves two noun
shapes "out of band": atoms, and cells whose head is a cell.
> Since no twig is an atom, a cell `[twig twig]` is always a cell
whose head is a cell. So we can distinguish "autocons" from all
stem-bulb nouns, and assign it specific semantics.
#### Runes and stems
A *rune* is a digraph - a sequence of two ASCII glyphs. If you
@ -359,7 +369,7 @@ there are no fixed rules for doing it right.
> Keep lines under 80 characters, though. The parser doesn't
enforce this yet. But it will, so watch out!
##### Backstep indentation
#### Backstep indentation
Note that the "variable declaration" metaphor of `=+` works
perfectly here. Because `[%hello planet]` -- despite being a
@ -462,4 +472,4 @@ Or with a gratuitous use of tall form:
Now you know how to read Hoon! For fun, try to pronounce more of
the code on this page. Please don't laugh too hard at yourself.
In the next chapter, we'll actually write a real program...
In the [next chapter](3-program), we'll actually write a real program...

View File

@ -0,0 +1,350 @@
---
title: Hoon 101.3: an algorithm
sort: 3
hide: true
next: false
---
# Hoon 101.3: an algorithm
In [chapter 0](0-nouns), we read about nouns. In [chapter 1](1-twigs),
we discovered twigs and legs. In [chapter 2](2-syntax), we learned
Hoon syntax and created our first source file.
Now it's time for an actual, meaningful *algorithm*.
## How to use this tutorial
Ideally, you've installed an Urbit planet (if you have a ticket)
or comet (if you don't). See the [user doc](../../../user).
We recommend opening up the dojo and just typing the examples;
you don't know a language until you know it in your fingers.
Also, make sure you've worked through the chapters in order.
## Goal: a decrement generator
Our algorithm is the classic Urbit example: decrement.
If you learned [Nock](../../nock) before Hoon, you've already
written decrement. If not, all you need to know is that the only
built-in arithmetic operator in Nock is increment. To decrement,
we need to count up to the result with a simple loop.
## A practical subject
As we've seen, Hoon works by running a twig against a subject.
In chapter 1, we made a simple test subject that was just a few
constants, and applied some simple twigs to it.
This time, we'll actually put useful working data in the subject,
building up more and more complex subjects as we go.
## Subject: nil
We'll start with the empty subject `~`:
```
:- %say |= * :- %noun
=> ~
[%hello %world]
```
The `=>` rune ("tisgar", `%tsgr`)), for `=>(p q)` executes `p`
against the subject, then uses that product as the subject of
`q`.
> We've already used an irregular form of `=>`, or to be more
precise its mirror `=<` ("tisgal", `%tsgl`). In chapter 1, when we wrote
`+3:test`, we meant `=>(test +3)` or `=<(+3 test)`.
What is `~`? It's Hoon `nil`, a zero atom:
```
~tasfyn-partyv:dojo/sandbox> ?? ~
[%cube 0 [%atom %n]]
~
```
We use `~` for list terminators and the like. Obviously, since
`[%hello %world]` is just a constant, a nil subject works as
well as any:
```
~tasfyn-partyv:dojo/sandbox> +test
[%hello %world]
```
## Subject: `arg=@`
Above, we used an empty subject to avoid the very complex,
interesting subject your generator twig gets by default.
But a decrement generator needs to get an argument from the
command line -- the number we're trying to decrement.
This involves changing the `test.hoon` boilerplate a little.
Again, don't worry about the boilerplate line just yet:
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
[%hello arg]
~tasfyn-partyv:dojo/sandbox> +test 42
[%hello 42]
```
> `=> arg=arg` looks a little odd. We wouldn't ordinarily do
this; we're just trying to keep the subject simple.
In case there's any doubt about the subject (remember from
chapter 1 that `.` means `+1`, the whole subject):
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
.
~tasfyn-partyv:dojo/sandbox> +test 42
arg=42
```
## An increment generator
We can even write a trivial increment generator using `.+`,
or even better its irregular form `+`:
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
+(arg)
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
We'll assume these same first two lines for the rest of the
examples in this chapter.
## Cores: one more kind of span
To decrement, we need a loop. To write a loop, we need yet
another kind of noun: the *core*. Briefly, a core is a `[code
data]` pair. Our new `span` mold:
```
++ span
$% [%atom p=@tas]
[%cell p=span p=span]
[%core p=span q=(map ,@tas twig)]
[%cube p=* q=span]
[%face p=@tas q=span]
==
```
### Structure of a core
The core is a cell `[battery payload]`. The payload is data, the
battery is code -- a tree of Nock formulas.
In the `%core` span, the payload is described by an arbitrary
span. The battery is described by a map of symbol to twig.
> Yes, the span contains the complete AST of the whole core.
This is a very different approach from most typed languages,
which compute function signatures. To infer the product of an
arm, we retrace the code in theory, but cache in practice.
### Arms are computed attributes
How do we use a core? Remember that Nock is a function
```
Nock(subject formula) -> product
```
To activate a core, we pull one formula from the battery, and
execute with the whole core as the subject. Coincidentally,
Nock has one macro instruction, `9`, that does just this.
So the formula defines an arbitrary function on the core. The
name of this function (as defined in the twig map) is a computed
attribute, or *arm*.
> Is a core an object? Not quite, because an arm is not a method.
Methods in an OO language have arguments. Arms are functions
only of the payload. (A method in Hoon is an arm that produces a
gate, which is another core -- but we're getting too far ahead.)
However, the battery does look a lot like a classic "vtable."
### Arms and wing resolution
It might be a good time to brush up on your [chapter 1](1-twigs).
The wing resolution algorithm gets a little more complicated.
Hoon overloads computed attributes (arms) and literal attributes
(legs) in the same namespace. A label in a wing may refer to
either. when searching a core, we look for a matching arm. If
we find it we're done. If we don't, or if a `^` mark makes us
skip, we search into the payload.
Only the last limb in the wing can activate an arm. If a name
resolves to a core arm, but it's not the last limb in the wing,
the arm produces the core itself. Similarly, when the wing is
not an access but a mutation, the arm refers to the core. Only
the end of the wing is activated.
> Suppose `foo` is a core. `bar` is an arm on foo. Then `bar.foo`
computes the `bar` arm. Perhaps the product is another core.
Even if `moo` is an arm in this new core, `bar.foo`, the wing
`moo.bar.foo` does not compute `moo` on the core `bar.foo`.
Instead, it looks for `moo` within the payload of the core `foo`.
(You're looking for `moo:bar.foo`, ie, `=>(bar.foo moo)`.)
Does this sound too tricky? Hopefully not, but it's about the
most complicated semantic rule you'll find in Hoon.
## Increment with a core
Keeping our two-line boilerplate, let's increment with a core:
```
=< inc
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
What's going on? We used the `|%` rune ("barcen") to produce a
core. (There are a lot of runes which create cores; they all
start with `|`, and are basically macros that turn into `|%`.)
The payload of a core produced with `|%` is the subject with
which `|%` is compiled. We might say that `|%` wraps a core
around its subject. In this case, the subject of the `|%`,
and thus payload, is our `arg=@ud` argument.
Then we used this core as the subject of the simple wing `inc`.
> Remember that `=<(a b)` is just `=>(b a)`. The core is heavy
and `inc` is light, so we use `=<` to put the heavy part last.
The prettyprinter can even print a core, sort of. Take out the
`=< inc`:
```
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
<1.bgq arg=42>
~tasfyn-partyv:dojo/sandbox> ? +test 42
<1.bgq arg=@ud>
<1.bgq arg=42>
```
In this notation, `1` means the number of arms in the core, `bgq`
is a very short fingerprint, and `arg=42` is the payload (and
`arg=@ud` is the payload span).
> Cores can be large and complex, and we obviously can't render all
the data in them, either when printing a type or a value. At
some point, you'll probably make the mistake of printing a big
core, maybe even the whole kernel, as an untyped noun. Just
press ^C.
## Adding a counter
To decrement, we need to count up to the argument. So we need a
counter in our subject, because where else would it go?
Let's change the subject to add a counter, `pre`:
```
=> [pre=0 .]
=< inc
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
Once again, `.` is the whole subject, so we're wrapping it in a
cell whose head is `pre=0`. This doesn't change the way we use
`arg`, even though it's one level deeper in the subject tree.
Let's look at the subject again:
```
=> [pre=0 .]
.
~tasfyn-partyv:dojo/sandbox> +test 42
[pre=0 arg=42]
~tasfyn-partyv:dojo/sandbox> ? +test 42
[pre=@ud arg=@ud]
[pre=0 arg=42]
```
There's a less cluttered way to write `=>([a .] b)`. In wide
mode, `=+(a b)`. A tall example:
```
=+ pre=0
.
~tasfyn-partyv:dojo/sandbox> +test 42
[pre=0 arg=42]
```
This rune `=+`, "tislus", `%tsls`, is of course the "variable
declaration" we saw in chapter 2.
## We actually decrement
Now we can write our actual decrement program, combining the
features we've explored above:
```
=+ pre=0
=< dec
|%
++ dec
?: =(arg +(pre))
pre
dec(pre +(pre))
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
`=(a b)` is an irregular form of `.=(a b)`, ie, "dottis" or the
noun `[%dtts a b]`. Likewise, `+(a)` is `.+(a)`, ie, "dotlus"
or `[%dtls a]`.
`?:`, "wuttis", `%wtts`, does exactly what it does in C.
The real action is in `dec(pre +(pre))`. We saw this same
mutation form in chapter 1. It's an irregular form of the `%=`
rune, "centis", `%cnts`.
Here, of course, we're computing an arm of a mutated core. We're
recomputing the loop arm, `dec`, against a new core with an
incremented `pre` leg. Basically, everything interesting in Hoon
happens when you compute an arm of a mutated core.
The whole program, using only regular forms, wide and tall:
```
=+ ^=(pre 0)
=< dec
|%
++ dec
?: .=(arg .+(pre))
pre
%= dec
pre .+(pre)
==
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
A good illustration of why we need irregular forms.
## Progress
Now we've actually done something useful. Well, if you count
O(n) decrement as something useful.
We've actually seen most of the major tools in Hoon's toolbox,
just in a super-minimalist selection. But we'll need a few more
runes to get to something that looks like real programming.
For instance, we have a decrement algorithm, but we don't have a
decrement *function* - in the Hoon sense of the word, anyway. We
don't see `(dec arg)` in this code. That'll be the next chapter.

View File

@ -0,0 +1,327 @@
---
title: Hoon 101.4: functions
sort: 4
hide: true
next: false
---
# Hoon 4: toward actual functions
In [chapter 0](0-nouns), we read about nouns. In [chapter 1](1-twigs),
we discovered twigs and legs. In [chapter 2](2-syntax), we learned
Hoon syntax and created our first source file. In [chapter 3](3-algorithm)
we wrote an actual algorithm.
Now we'll go a step farther and actually define a *function*.
## Goal: `(decrement arg)`
Of course, Hoon is a functional language and every twig defines a
function of the subject. But we haven't seen the Hoon equivalent
of a function *declaration*. Where is Lisp `defun`?
Also, the Hoon equivalent of a normal function call can't just
involve compiling the function into a Nock formula, whose subject
is the function's argument. As Einstein said, everything must be
as simple as possible, but no simpler.
A function that worked this way would, by definition, have no
access to data or code other than the argument. Where would the
standard library go? Would we have to pass it in the argument?
## Form of the solution
Let's get the boilerplate out of the way. We'll keep the same
external generator interface, but our solution will look like:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
(decrement arg)
=> ~
!!
```
In place of the `!!`, we'll put a core, effectively a library,
that exports a function `decrement`. We'll then call that
function with `(decrement arg)`, an irregular form of
`%-(decrement arg)`. Again, this core uses `=> ~` to clear
the subject, so we can't cheat and call `(dec arg)`.
> `!!`, or "zapzap" or `[%zpzp ~]`, is a twig that
always crashes. Because it produces the empty span (`%void`), it
doesn't cause type inference problems.
## Not quite a function call
As usual, we'll get to our goal gradually. A first try:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<(run gat(sam arg))
=> ~
|%
++ decrement
=+ sam=0
=+ pre=0
|%
++ run
?: =(sam +(pre))
pre
run(pre +(pre))
--
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
This works, but it's hardly concise or pretty. We'll get there.
We replaced the `!!` with a `|%` twig that produces a library
core. The payload of our library core is `~`, because that's the
subject we sent in. The battery contains one arm, `decrement`.
The `decrement` arm produces an inner core. The payload of this
inner core is `[pre=0 sam=0 +>]`, where `+>` is the library core.
The battery of the inner core has one arm, `run`, which computes
our algorithm from the last chapter.
To run our algorithm, we put the core that `decrement` produces
into a new leg, `gat`. Mutating this core to set `sam` to our
argument `arg`, we evaluate the `run` arm.
> Why do we need this `gat` leg? Why can't we just write `=<(run
decrement(sam arg))`? Remember our `moo:bar.foo` problem from
the previous chapter. `decrement(sam arg)` mutates not the
*product* of the decrement arm, but the core that computes it.
There's no `sam` in that subject, so the twig won't compile.
## Better is worse
To make this code look simpler, we need to make it more complex.
Our next try uses not two nested cores, but *three*:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<(run gat(sam arg))
=> ~
|%
++ decrement
=+ sam=0
|%
++ run
=+ pre=0
=< loop
|%
++ loop
?: =(sam +(pre))
pre
loop(pre +(pre))
--
--
--
```
This is actually the final structure of our function, but uses
none of the syntactic tricks we'll use to make it pretty.
> Why do we need to make the code more complex? Because we need
it to use the regular form that our synthetic runes, ie macros,
use to express function definitions and calls.
## Loop sugar
Look at little `loop`. It works just like our old `run`. But
there's something nice about it: we don't use the symbol `loop`
anywhere outside these 7 lines of code. It's not exported.
Therefore, the `loop` name is useless and redundant. Making up
names is one of the hard problems in computer science, so why
solve it for no reason?
So Hoon has an *empty name*: `$`. As a constant, `$` is a
zero-length symbol (`%$` instead of `%foo`) As a limb is the
`buc` symbol (`$`).
Replacing `loop` with `$`, our loop becomes:
```
=< $
|%
++ $
?: =(sam +(pre))
pre
$(sam +(run))
--
```
This may not seem like a huge improvement. It's not. But it
lets us match and move to the synthetic rune `|-`, "barhep":
```
|- ?: =(sam +(pre))
pre
$(pre +(pre))
```
`|-` is simply the canonical Hoon loop. All we've done to use a
core as a loop is to name our arm `$`, and evaluate it on the
core we just made.
Our program now:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<(run gat(sam arg))
=> ~
|%
++ decrement
=+ sam=0
|%
++ run
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
--
```
## Almost to lambda
Could we use `$` for `++run`? It certainly sounds like the same
kind of thing as `++loop`. The word "run" just means "do it".
Why should we be saying "do it" all the time?
Our third try, with this change:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<($ gat(sam arg))
=> ~
|%
++ decrement
=| sam=@ud
|%
++ $
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
> Besides `run` to `$`, we changed `=+ sam=0` to `=| sam=@ud`.
This is some mold magic we'll explain in the next chapter, but
it basically does the same thing: pushes a leg named `sam`, whose
value is a number we'll later overwrite.
This use of `$` in a core, very similar to the way we used `$` in
our `|-` loop, smells like it too should have a rune. It does:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<($ gat(sam arg))
=> ~
|%
++ decrement
|= sam=@ud
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
Doesn't `decrement` look like a function? Indeed, we're done with
the `decrement` arm. This is what it should look like.
> If you squint a little, `|=` ("bartis") might even be a strange,
deformed ASCII-art lambda.
Since it's doing something simple, we might well even compress
the whole body of `decrement` into one wide-form line:
```
=+(pre=0 |-(?:(=(sam +(pre)) pre $(pre +(pre)))))
```
This is a bit tight for most. But we can get really compact by
dropping the labels and going to full geometry:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<($ gat(sam arg))
=> ~
|%
++ decrement |=(@ud =+(0 |-(?:(=(+>+< +<) +< $(+< +(+<))))))
--
```
> It's not a good idea to actually program this way. But it does
strengthen your Hoon tree-geometry muscles. To use tree
geometry, you have to really know the shape of your subject.
## Structure of a gate
What is the noun produced by `decrement`? In true Hoonese it's
a *gate*, but nobody will hate you for saying "function." And
while we *slam* our gates, you can feel free to just "call" them.
Every gate is a core; not every core is a gate. All cores are
shaped like `[battery payload]`. A core is a gate if its payload
is a cell, and its battery has one arm, `$`. So a gate is shaped
like `[formula [sample context]]`.
To slam (call) a gate, you replace its sample (`+6` or `+<`,
"lusgal" or "dish") with your argument. "Multiple arguments" are
a single sample that's a tuple. So our code should actually read
```
=+ gat=decrement
=<($ gat(+< arg))
```
This `=+` sequence remains ugly. Once again, `decrement(+< arg)`
is not a mutation to the product of `decrement`, but a mutation
to the core that produces `decrement`. Fortunately, there's a
sugary rune that combines the semantics of both these lines:
```
%*($ decrement +< arg))
```
This mutates the product of `decrement` as specified. (`+< arg`
in the wide form of `$*` is just the first of n comma-separated
pairs; we could write `%*($ decrement +< arg, +> foo, moo 42)`.
> Arguably, %* is oversweetened; $:(decrement +< arg)
would be simpler and better. Hoon isn't perfect.
## Slamming the gate
Anyway, it shouldn't come as a surprise that a synonym for
`%*($ function +< argument)` is `%-(function argument)`. And an
irregular form of this is just `(function argument)`.
The irregular syntax constructs multiple-argument syntax as a
tuple; `(add 2 2)` is `(add [2 2])`, `(rsh 3 1 5)` is `(rsh [3 1 5])`.
If there are no arguments, `(function)`, this means `$:function`,
ie, `=>(function $)`.
We can also take the `=> ~` out, since we now know what we're
doing. The final program:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
(decrement arg)
|%
++ decrement
|= sam=@ud
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
```
## Progress
In most functional languages, a function is a primitive. In Hoon
it's a macro, and a pretty complex macro at that. We spent four
chapters building the concept up out of much smaller pieces.
Fortunately, once you have functions you can do anything. We
still have a fair bit to learn, but we've now seen all the
fundamental building blocks of programming in Hoon. In the next
chapter, we'll get back into molds and spans.

View File

@ -1,322 +0,0 @@
---
title: Hoon 101.3: our first program
sort: 3
hide: true
next: false
---
# Hoon 101.3: our first program
It's time for us to do some actual programming. In this section,
we'll work through that classic Urbit pons asinorum, decrement.
If you learned Nock before Hoon, you've already done decrement.
If not, all you need to know is that the only arithmetic
intrinsic in Nock is increment -- in Hoon, the unary `.+` rune.
So an actual decrement function is required.
In chapter 3, we write a decrement builder: more or less the
simplest nontrivial Urbit program. We should be able to run this
example:
```
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
## What's in that subject?
As we've seen, Hoon works by running a twig against a subject.
We've been cheerfully running twigs through three chapters while
avoiding the question: what's in the subject? To avoid the issue
we've built a lot of constants, etc.
Of course your twig's subject comes from whoever runs it. There
is no one true subject. Our twigs on the command line are not
run against the same subject as our generator code, even though
they are both run by the same `:dojo` appliance.
But the short answer is that both command-line and builder get
*basically* the same subject: some ginormous noun containing all
kinds of bells and whistles and slicers and dicers, including a
kernel library which can needless to say decrement in its sleep.
As yet you have only faced human-sized nouns. We need not yet
acquaint you with this mighty Yggdrasil, Mother of Trees. First
we need to figure out what she could even be made of.
## Clearing the subject
We'll start by clearing the subject:
```
:- %say |= * :- %noun
=> ~
[%hello %world]
```
The `=>` rune ("tisgar"), for `=>(p q)` executes `p` against
the subject, then uses that product as the subject of `q`.
(We've already used an irregular form of `=>`, or to be more
precise its mirror `=<` ("tisgal"). In chapter 1, when we wrote
`+3:test`, we meant `=>(test +3)` or `=<(+3 test)`.)
What is this `~`? It's Hoon `nil`, a zero atom with this span:
```
~tasfyn-partyv:dojo/sandbox> ?? ~
[%cube 0 %atom %n]
~
```
We use it for list terminators and the like. Obviously, since
our old test code is just a constant, a null subject works fine:
```
~tasfyn-partyv:dojo/sandbox> +test
[%hello %world]
```
## Getting an argument
Obviously, if we want to write a decrement builder, we'll have to
get an argument from the command line. This involves changing
the `test.hoon` boilerplate a little:
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
[%hello arg]
~tasfyn-partyv:dojo/sandbox> +test 42
[%hello 42]
```
`=> arg=arg` looks a little odd. We wouldn't ordinarily do
this. We're just replacing a very interesting subject that
contains `arg` with a very boring one that contains only `arg`,
for the same reason we cleared the subject with `~`.
In case there's any doubt about the subject (`.` is limb syntax
for `+1`, ie, the whole noun):
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
.
~tasfyn-partyv:dojo/sandbox> +test 42
arg=42
```
We can even write a trivial increment function using `.+`:
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
+(arg)
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
Below we'll skip both boilerplate lines in our examples.
## A core is a code-data cell
But how do we actually, like, code? The algorithm for decrement
is clear. We need to count up to 41. (How do we run useful
programs on a computer with O(n) decrement? That's an
implementation detail.)
We'll need another kind of noun: the *core*. Briefly, the core
is always a cell `[battery payload]`. The payload is data, the
battery is code -- one or more Nock formulas, to be exact.
Consider a simple core with a one-formula battery. Remember, we
create Nock formulas by compiling a twig against a subject. The
subject is dynamic data, but its span is static. What span do we
give the compiler, and what noun do we give the formula?
A core formula always has the core as its subject. The formula
is essentially a computed attribute on the payload. But if the
subject was just the payload, the formula couldn't recurse.
Of course, there is no need to restrict ourselves to one computed
attribute. We can just stick a bunch of formulas together and
call them a battery. The source twigs in this core are called
"arms," which have labels just like the faces we saw earlier.
Hoon overloads computed attributes (arms) and literal attributes
(legs) in the same namespace. A label in a wing may refer to
either. To extend the name-resolution tree search described in
chapter 1, when searching a core, we look for a matching arm.
If we find it we're done. If we don't, or if a `^` mark makes us
skip, we search into the payload.
If a name resolves to a core arm, but it's not the last limb in the
wing, the arm produces the core itself. Similarly, when the
wing is not an access but a mutation, the arm refers to the core.
This demands an example: if `foo` produces some core `c`, and
`bar` is an arm in that `c` (which may be `foo` itself, or some
leg within `foo`), `bar.foo` runs the arm formula with `c` as the
subject. You might think that `moo.bar.foo` would compute
`bar.foo`, then search for `moo` within that result. Instead, it
searches for `moo` within `c`. (You can get the other result
with `moo:bar.foo`.)
Does this sound too tricky? It should - it's about the most
complicated feature of Hoon. It's all downhill once you
understand cores.
Let's again extend our `++span` mold:
```
++ span
$% [%atom @tas]
[%cell span span]
[%core span (map ,@tas twig)]
[%cube * span]
[%face @tas span]
==
```
This definition of `%core` is somewhat simplified from the
reality, but basically conveys it. (Moreover, this version of
`span` describes every kind of noun we build.) In our `%core` we
see a payload span and a name-to-twig arm table, as expected.
Is a core an object? Not quite, because an arm is not a method.
Methods in an OO language have arguments. Arms are functions
only of the payload. (A method in Hoon is an arm that produces a
gate, which is another core -- but we're getting too far ahead.)
However, the battery does look a lot like a classic "vtable."
## Increment with a core
Let's increment with a core:
```
=< inc
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
What's going on? We used the `|%` rune ("barcen") to produce a
core. (There are a lot of runes which create cores; they all
start with `|`, and are basically macros that turn into `|%`.)
The payload of a core produced with `|%` is the subject with
which `|%` is compiled. We might say that `|%` wraps a core
around its subject. In this case, the subject of the `|%`,
and thus payload, is our `arg=@ud` argument.
Then we used this core as the subject of the simple wing `inc`.
(Remember that `=<(a b)` is just `=>(b a)`.)
We can actually print out a core. Take out the `=< inc`:
```
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
!!!
~tasfyn-partyv:dojo/sandbox> ? +test 42
!!!
```
Cores can be large and complex, and we obviously can't render all
the data in them, either when printing a type or a value. At
some point, you'll probably make the mistake of printing a big
core, maybe even the whole kernel, as an untyped noun. Just
press ^C.
## Adding a counter
To decrement, we need to count up to the argument. So we need a
counter in our subject, because where else would it go? Let's
change the subject to add a counter, `pre`:
```
=> [pre=0 .]
=< inc
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
Once again, `.` is the whole subject, so we're wrapping it in a
cell whose head is `pre=0`. Through the magic of labels, this
doesn't change the way we use `arg`, even though it's one level
deeper in the subject tree. Let's look at the subject again:
```
=> [pre=0 .]
.
~tasfyn-partyv:dojo/sandbox> +test 42
[pre=0 arg=42]
~tasfyn-partyv:dojo/sandbox> ? +test 42
[pre=@ud arg=@ud]
[pre=0 arg=42]
```
There's actually a simpler way to write this. We've seen it
already. It's not exactly a variable declaration:
```
=+ pre=0
.
~tasfyn-partyv:dojo/sandbox> +test 42
[pre=0 arg=42]
```
## We actually decrement
Now we can write our actual decrement program:
```
=+ pre=0
=< dec
|%
++ dec
?: =(arg +(pre))
pre
dec(pre +(pre))
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
`=(a b)` is an irregular form of `.=(a b)`, ie, "dottis" or the
noun `[%dtts a b]`. Likewise, `+(a)` is `.+(a)`, ie, "dotlus"
or `[%dtls a]`.
`?:` is a regular rune which does exactly what you think it does.
Bear in mind, though, that in Hoon 0 (`&`, "pam") is true and 1
(`|`, "bar") is false.
The real action is in `dec(pre +(pre))`. This is obviously an
irregular form -- it's the same mutation form we saw before.
Writing it out in full regular form:
```
=+ pre=0
=< dec
|%
++ dec
?: =(arg +(pre))
pre
%= dec
pre +(pre)
==
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
`%=`, "centis", is the rune which almost every use of a wing
resolves to. It might be called "evaluate with changes."
When we evaluate with changes, we take a wing (`dec`) here and
evaluate it as described above. Searching in the subject, which
is of course our core, we find an arm called `dec` and run it.
The changes (replacing `pre` with `+(pre)`) are always applied
relative to the core we landed on (or the leg we landed on).
The change wing is relative to this target; the subject of the
replacement (`+(pre)`) is the original subject.
So, in English, we compute the `dec` arm again, against a new
core with a new payload that contains an incremented `pre`.
And thus, we decrement. Doesn't seem so hard, does it?

View File

@ -1,267 +0,0 @@
---
title: Hoon 101.4: functions
sort: 4
hide: true
next: false
---
# Hoon 4: toward actual functions
Okay, we've programmed. We've achieved decrement. We've written
what is in some sense a loop. What next?
Well... we're still feeling vaguely disappointed. Because we're
supposed to be doing *functional programming*. And we haven't
yet written any *functions*.
After all, in Hoon we don't really write a command-line utility
to decrement `42`. We write `(dec 42)`. You probably realize
that on the inside, this is not the same thing as a function in a
normal functional language. The Tasmanian tiger is not a tiger.
On the other hand, it certainly *looks* like a function call.
So how do we write the function?
In this chapter, we'll modify `+test` to extend the subject so
that we can write our result as `(dec arg)`. Or rather, `(duck
arg)`, because we want to get out of training wheels and stop
clearing the subject soon.
## Form of the solution
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
(duck arg)
!! :: some interesting core
```
`!!`, or "zapzap" or `[%zpzp ~]`, can go anywhere a twig can and
always crashes. Because its span is the empty set (`%void`), it
doesn't cause type inference problems.
In place of the `!!`, we'll put a core, effectively a library,
that provides our new, improved decrement function `duck`. We'll
then call it with the irregular form, `(duck arg)`, which looks
like a function call but is in fact some mysterious macro.
## Some interesting core
Translated into imperative programming, what we did in chapter 3
was more like computing a function of a global variable. Now,
we have to actually pass an argument to a function.
Here's our first try:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=duck
=<(run gat(sam arg))
=> ~
|%
++ duck
=+ sam=0
=+ pre=0
|%
++ run
?: =(sam +(pre))
pre
run(pre +(pre))
--
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
We step back and contemplate our handiwork. Is it good? Well...
it works. Reading programs written without syntactic sugar is
about as fun as eating raw chocolate nibs.
What did we do? In the `duck` arm (we often write `++duck`, for
obvious reasons) we produce a core whose payload is `[pre=0 num=0
~]`, and whose battery contains `++run`.
In the result twig, we first use `++duck` to extend our subject
with a core named `gat`. We then use `run` on that gate. Why do
we need this `gat`? Why can't we just write `=<(run duck(sam
arg))`?
Because the arm is computed *after* the mutation. But here we
need the mutated *result* of `++duck`. Instead, what this code
is doing is trying to mutate `sam` within the core that contains
`++duck`. Where it doesn't exist, so your code won't compile.
And note that with `=<`, we've placed our library structurally
between the original subject and the program we're writing,
but lexically at the bottom with zero left margin. We also
clear the subject to keep things simple.
## A more regular structure
It actually gets worse. To make this code look simpler, we need
to make it more complex. While "function calls" actually fit
quite well into the Hoon architecture, they're also a nontrivial
synthetic construction. We'll build the desugared form the hard
way, then show you where we put the sugar in.
The desugared canonical decrement:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=duck
=<(run gat(sam arg))
=> ~
|%
++ duck
=+ sam=0
|%
++ run
=+ pre=0
=< loop
|%
++ loop
?: =(sam +(pre))
pre
loop(pre +(pre))
--
--
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
Yuck. Okay, let's fix this.
## Art of the loop
First, look at our little `++loop`. It works just like our old
`++run` loop. We notice that there's actually something nice
about it: we don't use the symbol `loop` anywhere outside these 7
lines of code. It's not exported at all.
Actually, the symbol `loop` name is useless and redundant.
Making up names is one of the hard problems in computer science,
so why solve it? For just this reason, Hoon has an *empty name*,
which as a constant is a zero-length symbol (`%$` instead of
`%foo`), and as a limb is the `buc` symbol (`$`). With `$`,
our loop becomes:
```
=< $
|%
++ $
?: =(sam +(pre))
pre
$(sam +(run))
--
```
This may not seem like a huge improvement. It's not. But it's
exactly equivalent to the synthetic rune `|-`, "bardas":
```
|- ?: =(sam +(pre))
pre
$(pre +(pre))
```
This is obviously the canonical Hoon loop. It leaves us with
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=duck
=<(run gat(sam arg))
=> ~
|%
++ duck
=+ sam=0
|%
++ run
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
## Is this a lambda?
Could we use `$` for `++run`? It certainly sounds like the same
kind of thing as `++loop` -- just a word we invented to mean "do
it." Should the programmer have to invent these kinds of words?
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=duck
=<($ gat(sam arg))
=> ~
|%
++ duck
=| sam=@ud
|%
=+ pre=0
++ $
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
(Besides `run` to `$`, we changed `=+ sam=0` to `=| sam=@ud`.
Let's just remember that there's some magic here. We'll come
back and explain it later.)
This is still kind of ugly -- but it's exactly equivalent to
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=duck
=<($ gat(sam arg))
=> ~
|%
++ duck
|= sam=@ud
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
Doesn't that look like a function? Indeed, we're done with
`++duck` -- that's what a Hoon decrement should look like.
If you squint a little, `|=` ("bartis") might even be a strange,
deformed lambda rune.
Since it's doing something simple, we might well even compress
the whole body of the function into one wide-form line:
```
=+(pre=0 |-(?:(=(sam +(pre)) pre $(pre +(pre)))))
```
(According, of course, to taste -- this is a bit tight for some.)
## Gates and how to call them
Our call site remains a disaster, though. We'll need moar sugar.
But first, let's look at this lambda-thing we've made. What is
the noun produced by `++duck`? Our term for it is a "gate," but
nobody will hate you for saying "function." And while we "slam"
our gates, you can feel free to just "call" them.
A gate is a core, of course, but a special kind of core. All
cores are shaped like `[battery payload]`. A gate is shaped like
`[formula [sample context]]`. A gate has one arm, `$`, so its
battery is just a formula. To slam a gate, you replace its
sample (`+6` or `+<`, "luslit" or "lust") with your own noun,
and apply the formula to the mutated gate.
As we explained earlier, `duck(sam arg)` is not the right way to
mutate the gate we make with `duck`, because it's actually
trying to mutate the core we used to make `duck`. But there has
to be some sugar to do this, and there is: `%*`, "centar". We
can replace our call site with `%*($ duck sam arg)`.
This is also not quite orthodox, because the whole point of a
gate is the canonical shape that defines a calling convention.
We can and should say: `%*($ duck +< arg)`.
Unsurprisingly, this in turn is `%-(duck arg)` in regular form,
or `(duck arg)`

View File

@ -1,7 +1,7 @@
---
logo: black
title: User doc
sort: 1
title: User doc
---
<div class="short">
@ -10,9 +10,9 @@ sort: 1
Read the [introduction](user/intro) for a summary of Urbit.
The [installation guide](user/install) gets you ready to run.
The [launch procedure](user/launch) holds your hand as you create
your server image. Once your urbit is live, the [quickstart
page](user/start) is all you need if in a hurry.
Launch with [basic operation](user/basic) and get a feel for the
system. Once your urbit is live, the [walking tour](user/tour)
shows how to do some common tasks.
For power users, the [appliance handbook](user/appliance) explains
your apps and how to control them. The [filesystem handbook](user/clay)

View File

@ -1,7 +1,7 @@
---
title: Appliance handbook
sort: 5
next: true
sort: 5
title: Appliance handbook
---
# Appliance handbook

143
pub/docs/user/basic.mdy Normal file
View File

@ -0,0 +1,143 @@
---
next: true
sort: 3
title: Basic Operation
---
# Basic Operation
Once urbit is installed, if you have an invitation, it's a planet
like `~fintud-macrep` and a ticket like
`~fortyv-tombyt-tabsen-sonres`. Run
bin/urbit -w fintud-macrep -t fortyv-tombyt-tabsen-sonres
(You can leave the `~` on, but it annoys some Unix shells.)
If you don't have an invitation, pick a nickname for your comet,
like `mycomet`. Urbit will randomly generate a 128-bit plot:
bin/urbit -c mycomet
Either way, creating your urbit will take some time. Some of
this time involves generating keys; some of it involves
downloading code over Urbit itself.
If you turn off your pier at any time (either "nicely" with `^D`
from talk or the dojo or by power-failure, oom-killer, or other
calamity), then you can start it up again with the path to your
pier directory (your planet name if you have an invitation,
otherwise the name you chose after `-c`):
bin/urbit fintud-macrep
or
bin/urbit mycomet
## Basic operation
Out of the box, your urbit is running two default appliances,
`:dojo` (a shell or REPL) and `:talk`. Switch between them with
`^X`. Note that all apps share an output log, but `^X` switches
the prompt.
`^D` from either default appliance exits the urbit process.
If your plot is `~fintud-macrep`, the dojo prompt is
~fintud-macrep:dojo>
Type any Hoon expression at the command line and see the result:
~fintud-macrep:dojo> (add 2 2)
You'll see:
> (add 2 2)
4
~fintud-macrep:dojo>
While there are some tools for interacting with urbit's
filesystem direclty, often it's useful to edit urbit files from
Unix. Use `|mount` to set up a Dropbox-style sync directory in
your pier directory:
~fintud-macrep:dojo> |mount %
>=
~fintud-macrep:dojo> |unmount %
>=
Look inside your pier directory to find your files, and edit them
with your favorite Unix text editor.
Sometimes you want to get files from another urbit. There's two
main commands to do this.
~fintud-macrep:dojo> |merge %examples ~wactex-ribmex %examples
>=
; ~wactex-ribmex is your neighbor
; ~wactex-ribmex is your neighbor
[time passes...]
merged with strategy %init
This pulls a bunch of examples from `~wactex-ribmex`'s `%examples`
desk and puts them in our `%examples` desk. A desk is a
branch (in the git branch sense) of our filesystem.
You can, of course, merge the examples into your `%home`
(default) desk if you wish. Merging into a new desk creates it,
while merging into an existing desk does an intelligent git-style
merge, with conflict resolution and stuff.
~fintud-macrep:dojo> |sync %examples ~wactex-ribmex %examples
>=
activated sync from %examples on ~wactex-ribmex to %examples
sync succeeded from %examples on ~wactex-ribmex to %examples
~fintud-macrep:dojo> |unsync %examples ~wactex-ribmex %examples
ended autosync from %examples on ~wactex-ribmex to %examples
`|sync` does an initial `|merge`, then listens for changes on the
foreign desk and runs `|merge` automatically whenever it changes.
By default your `%home` desk is synced to your parent's `%kids`
desk, so the entire network is upgraded at once. You may, of
course, unsync it, but this voids your warranty.
You can change which desk is your current working directory with:
~fintud-macrep:dojo> =dir /=examples
> `dir` is a special dojo variable, but you can also create your
> own variables with the same syntax. `=my-var (add 2 3)` allows
> you to use `my-var` for `5` anywhere later on.
When you change your desk all commands will use the files from
that desk. Unfortunately, changing your working directory to
anywhere but the top directory is currently
[broken](http://github.com/urbit/urbit/issues/565). If this is
fixed when you're reading this, please submit a pull request for
this document explaining how to do it!
The last command we'll discuss in this quickstart is `+moon`,
which only works on planets.
~fintud-macrep:dojo> +moon
"moon: ~ramnec-rossug-fintud-macrep; ticket: ~holtyl-mognyl-dostyp-moslud"
This generates a random moon and ticket. A moon is a subidentity
of your planet, so it's a separate urbit that's associated with
your planet. If your planet is off, then your moon won't
function very well over the network (it'll work just fine
locally, of coures).
You can start up your moon with `bin/urbit -w moon-name -t
ticket`. We recommend doing this for development because there
are still some instabilities that have the potential to explode
your planet if you develop on it. If this happens, then your
planet will be unusable until the next continuity breach. If you
tell us how you exploded your planet, we may give you a
replacement, but it's still a hassle for you.
Don't worry too much about exploding your moons -- you have four
billion of them, and they get replenished after every continuity
breach. Still do file a bug, though.

View File

@ -1,7 +1,7 @@
---
title: Filesystem handbook
sort: 6
next: true
sort: 6
title: Filesystem handbook
---
# Filesystem handbook

View File

@ -1,6 +1,6 @@
---
title: Dojo manual
sort: 8
title: Dojo manual
---
# `:dojo` manual

View File

@ -1,7 +1,7 @@
---
title: Install
sort: 2
next: true
sort: 2
title: Install
---
# Installation guide

View File

@ -1,7 +1,7 @@
---
title: Introduction
sort: 1
next: true
sort: 1
title: Introduction
---
# Introduction

View File

@ -1,7 +1,8 @@
---
title: Launch
sort: 3
hide: true
next: true
sort: 10
title: Launch
---
# Launch procedure

View File

@ -1,7 +1,7 @@
---
title: Talk manual
sort: 7
next: true
sort: 7
title: Talk manual
---
# `:talk` manual

View File

@ -1,20 +1,10 @@
---
title: Quickstart
sort: 4
next: true
sort: 4
title: Walking Tour
---
# Quickstart
To start your already-launched urbit, just run `urbit` with one
argument, which is the pier directory (`$PIER`). This is your
planet name if you have a planet, or the name you used with `-c`
if you have a comet:
bin/urbit fintud-macrep
or
bin/urbit mycomet
# Walking Tour
Piers are portable. You can move a pier anywhere. But never,
*ever* run the same urbit in two places at once. (If you try to
@ -24,31 +14,6 @@ pier, Urbit will kill the old process.)
(Also, don't let the Unix filesystem it's on run out of disk.
This is a known way to corrupt your urbit! Sorry.)
## Basic operation
Out of the box, your urbit is running two default appliances,
`:dojo` (a shell or REPL) and `:talk`. Switch between them with
`^X`. Note that all apps share an output log, but `^X` switches
the prompt.
`^D` from any default appliance exits the urbit process.
## Compute: your `:dojo` appliance
If your plot is `~fintud-macrep`, the dojo prompt is
~fintud-macrep:dojo>
Type any Hoon expression at the command line and see the result:
~fintud-macrep:dojo> (add 2 2)
You'll see:
> (add 2 2)
4
~fintud-macrep:dojo>
### Dojo expressions, generators and operators
`:dojo` is of course a command-line REPL or shell. But it
@ -96,7 +61,8 @@ You're on the air! You should see some backlog to give you
context. Please remember our code of conduct: don't be rude.
Also, `urbit-meta` is politically correct and safe for work.
For more instructions on how to use `:talk`, see the [`:talk` manual](http://urbit.org/docs/user/talk)
For more instructions on how to use `:talk`, see the [`:talk`
manual](http://urbit.org/docs/user/talk)
## Using the filesystem

View File

@ -1,4 +1,4 @@
::
::
:::: /hoon/sole/sur
!:
|%
@ -36,6 +36,7 @@
[%tan p=(list tank)] :: classic tank
:: [%taq p=tanq] :: modern tank
[%txt p=tape] :: text line
[%url p=@t] :: activate url
== ::
++ sole-command :: command state
$: pos=@ud :: cursor position