on master help sign in
Merge pull request #526 from urbit/david-draft
c8b6466rmariani
learn/hoon/hoon-tutorial/egg-timer.mdnew file+120
@@ -0,0 +1,120 @@
1++++
2+title = "2.7.1 Walkthrough: Egg Timer"
3+weight = 36
4+template = "doc.html"
5++++
6+
7+The Arvo operating system is divided up into modules called vanes. Gall is the vane responsible for providing an API for building stateful applications in Urbit. Gall is a complex system that takes a lot of getting used to, so let's dip our toes in with a simple egg-timer app.
8+
9+
10+```
11+|%
12++$ effect (pair bone syscall)
13++$ syscall [%wait path @da]
14+--
15+|_ [bowl:gall ~]
16+++ poke-noun
17+ |= t=@dr
18+ ^+ [*(list effect) +>.$]
19+ :_ +>.$ :_ ~
20+ [ost %wait /(scot %da now) (add now t)]
21+++ wake
22+ |= [=wire error=(unit tang)]
23+ ^+ [*(list effect) +>.$]
24+ ~& "Timer went off!"
25+ [~ +>.$]
26+--
27+```
28+
29+The first thing to notice is that we are creating a `core` (`|%`) and a `door` (`|_`). This is a typical style of Gall programming where your types are defined in the first `core` and your application is defined in the following `door`.
30+
31+```
32+|%
33++$ effect (pair bone syscall)
34++$ syscall [%wait path @da]
35+--
36+```
37+
38+The `core` here defines two types: `effect` and `syscall`. An `effect` is a `pair` of `bone` and `syscall`. A `bone` is a Gall-only type that identifies app event chains by mapping atoms to them. We define `syscall` to be a request to Arvo to do something for us. In this case, the only valid `syscall` will be `%wait` which we'll discuss in a bit.
39+
40+It's important to note that the names `effect` and `syscall` are arbitrary; you can call them whatever you'd like. Commonly you will see them called `move` and `card`, respectively, but we've changed the names here to try to introduce some clarity that that older convention lacks.
41+
42+The sample of the `door` is:
43+
44+```
45+[bowl:gall ~]
46+```
47+
48+You can find the full definition of `bowl` in `sys/zuse.hoon`, but for now it's enough to know that this is the default app state and includes various faces for information. Below are some important such faces:
49+
50+`our` The current ship
51+`src` The ship the request originated with
52+`ost` A reference to a chain of events
53+`eny` Entropy
54+`now` The current time of the event
55+
56+The `door` we've made has two arms `poke-noun` and `wake`. Gall is capable of dispatching `pokes`, or requests, to an app based on the mark of the data given along with that poke. These are sent to the arm with the name that matches the mark of the data. Here we use the generic `noun` mark:
57+
58+```
59+++ poke-noun
60+ |= t=@dr
61+ ^+ [*(list effect) +>.$]
62+ :_ +>.$ :_ ~
63+ [ost %wait /(scot %da now) (add now t)]
64+```
65+
66+In the above code, we create a gate that takes a single `@dr` argument. `@dr` is an aura for a 128-bit relative date. Here are a few examples.
67+
68+`~s17` 17 seconds
69+`~m20` 20 minutes
70+`~d42` 42 days
71+
72+As a matter of good type hygiene, we explicitly cast the output of this gate with `^+` to ensure we are producing the correct thing for Gall to handle. `^+` is the rune for casting by example. Our example is a cell: `list` of `effect`, which we `bunt` with `*`, is the head; `+>.$`, the enclosing core which is our `door`, is the tail.
73+
74+Next we're going to use the `:_` rune which is just the inverted form a `:-` the cell construction rune. We use it twice so the actual data will end up looking something like:
75+
76+```
77+[[[ost %wait /(scot %da now) (add now t)] ~] +>.$]
78+```
79+
80+`ost` is the `bone`, the opaque reference to a chain of events, that comes from `bowl`, so we're going to continue to use it here. `%wait` is the name of the `syscall`, in this case a request to the Behn vain to start a timer for us.
81+
82+After `%wait`, we have the `path`, a `list` of `cords` that serves as the unique identifier for this `syscall`:
83+
84+```
85+/(scot %da now)
86+```
87+
88+The `/` here is an irregular syntax to make a `path`, and `scot` is going to transform `now`, the current time as given to us by `bowl`, from a `@da` to a `cord`.
89+
90+The final part of this `syscall` is:
91+
92+```
93+(add now t)
94+```
95+
96+`now` is the current time of type `@da`, and `t` was declared as `@dr`. Because they are both atoms, we can add `now` and `t` these two to get an atom that is `t` units of time into the future from `now`. That produced atom can be interpreted as a `@da`.
97+
98+That's all for our `poke-noun` arm. But what about when the timer goes off? Behn will create a `move` similar to how we created one with `effect`, only this time it will end up being dispatched back to us in the `++wake` arm. Behn always looks for an arm named `++wake` when a timer goes off; it is defined this way in the vane's code. So any So any app that wants to use a timer trigger needs to have an arm called `++wake`.
99+
100+```
101+++ wake
102+ |= [=wire error=(unit tang)]
103+ ^+ [*(list effect) +>.$]
104+ ~& "Timer went off!"
105+ [~ +>.$]
106+```
107+
108+`wake` is a `gate` that has two arguments: a `wire`, and a `(unit tang)` with the face `error`. The syntax of `=wire` is a shortcut for `wire=wire`; it's a common pattern to shadow the name of a type when you only have one instance of the type and are not going to refer to the type itself. A `wire` is just an alias for `path`. Our `wire` will be the `path` that we gave original `syscall`. If we needed to do something based on which request caused this gate to be called, we could use the wire to do so. In this case, we don't do perform such a dispatch.
109+
110+Next we have the same cast we used in `++poke-noun` to make sure we are producing the correct thing for Gall. These casts are not strictly necessary, as the type system can infer what the type will be, but they can be very useful both for debugging our own code and for someone else trying to determine what our code should be producing.
111+
112+```
113+~& "Timer went off!"
114+```
115+
116+`~&` is the debugging printf rune. Here we're using it to output a message. We could, however, modify this line of code to do any other computation we would want to happen when `++wait` gets called.
117+
118+Finally, we need to produce our `effect`. Here the effect is simply `[~ +>.$]`, since we have no `syscall` to make and we are not changing the state of our app. We just use the `door` without changing its sample.
119+
120+### [Next Up: Reading -- Ford](../ford)
learn/hoon/hoon-tutorial/libraries.mdnew file+181
@@ -0,0 +1,181 @@
1++++
2+title = "2.3.1 Walkthrough: Libraries"
3+weight = 28
4+template = "doc.html"
5++++
6+
7+In Hoon, like in other languages, it's often useful to create a library for other code to access. In this example, we look at one example of a library that can be used to represent a deck of 52 playing cards. The core below builds such a library, and can be accessed by programs.
8+
9+```
10+|%
11++$ suit ?(%hearts %spades %clubs %diamonds)
12++$ darc [sut=suit val=@ud]
13++$ deck (list darc)
14+++ make-deck
15+ ^- deck
16+ =| mydeck=deck
17+ =/ i 1
18+ |-
19+ ?: (gth i 4)
20+ mydeck
21+ =/ j 1
22+ |-
23+ ?. (lte j 13)
24+ ^$(i +(i))
25+ %= $
26+ j +(j)
27+ mydeck [(num-to-suit i) j]^mydeck
28+ ==
29+++ num-to-suit
30+ |= val=@ud
31+ ^- suit
32+ ?+ val !!
33+ %1 %hearts
34+ %2 %spades
35+ %3 %clubs
36+ %4 %diamonds
37+ ==
38+++ shuffle-deck
39+ |= [unshuffled=deck entropy=@]
40+ ^- deck
41+ =| shuffled=deck
42+ =/ random ~(. og entropy)
43+ =/ remaining (lent unshuffled)
44+ |-
45+ ?: =(remaining 1)
46+ :_ shuffled
47+ (snag 0 unshuffled)
48+ =^ index random (rads:random remaining)
49+ %^ $
50+ shuffled (snag index unshuffled)^shuffled
51+ remaining (dec remaining)
52+ unshuffled (oust [index 1] unshuffled)
53+++ draw
54+ |= [n=@ud d=deck]
55+ ^- [hand=deck rest=deck]
56+ :- (scag n d)
57+ (slag n d)
58+--
59+```
60+
61+On the very first line, we create a core with `|%`. This core contains all of our library code, and is closed by the `--` on the final line.
62+
63+To create three types we're going to need, we use `+$`, which is an arm used to define a type.
64+
65+
66+```
67++$ suit ?(%hearts %spades %clubs %diamonds)
68++$ darc [sut=suit val=@ud]
69++$ deck (list darc)
70+```
71+
72+The first is `suit`, which can be either `%hearts`, `%spades`, `%clubs`, or `%diamonds`.
73+
74+Next is a `darc`, which which is a pair of `suit` and a `@ud`. By pairing a suit and a number, it forms a particular card, such as "nine of hearts." Why do we call it `darc` and not `card`? Because `card` already has a meaning in gall, the Arvo app module, where one would likely to use this (or any) library. It's worthwhile to avoid any confusion over names.
75+
76+Our final type is `deck`, which is simply a `list` of `darc`.
77+
78+One way to get a feel for how a library works is to skim the `++` arm-names before diving into any specific arm. In this library, the arms are `make-deck`, `num-to-suit`, `shuffle-deck`, and `draw`. These names should be very clear, with the exception of `num-to-suit` though you could probably hazard a guess at what it does. Let's take a closer look at that one first.
79+
80+```
81+++ num-to-suit
82+ |= val=@ud
83+ ^- suit
84+ ?+ val !!
85+ %1 %hearts
86+ %2 %spades
87+ %3 %clubs
88+ %4 %diamonds
89+ ==
90+```
91+
92+We can see this is a gate that takes a single `@ud` and produces a `suit`.
93+
94+The `?+` rune is the rune to switch against a value with a default. The default here is to crash with `!!`. Then we have the four options of 1 through 4, based on the value of `val`, which each resulting in a different suit.
95+
96+```
97+++ make-deck
98+ ^- deck
99+ =| mydeck=deck
100+ =/ i 1
101+ |-
102+ ?: (gth i 4)
103+ mydeck
104+ =/ j 1
105+ |-
106+ ?. (lte j 13)
107+ ^$(i +(i))
108+ %= $
109+ j +(j)
110+ mydeck [(num-to-suit i) j]^mydeck
111+ ==
112+```
113+
114+`num-to-suit` is used in the `make-deck` arm shown above. This arm should be quite readable to you at this point. Here we simply have two loops where we use counters to build up the full set of 52 cards, by cycling through every possible suit and number and combining them. Once we have reached the point where `j` is greater than 13, we're going to jump back out to the "suit" outer-loop and increment `i`. `?.` may be an unfamiliar rune; it is simply the inverted version of `?:`, so the first branch is actually the "no" branch and the second is the "yes" branch. This is done to keep the "heaviest" branch at the bottom.
115+
116+
117+```
118+++ draw
119+ |= [n=@ud d=deck]
120+ ^- [hand=deck rest=deck]
121+ :- (scag n d)
122+ (slag n d)
123+```
124+
125+`draw` takes two arguments: `n`, a number; and `d`, a `deck`. It's going to produce a cell of two `decks`. The cell is created using `scag` and `slag`. [`scag`](https://urbit.org/docs/reference/library/2b/#scag) is a standard-library gate produces the first `n` elements from a list, and [`slag`](https://urbit.org/docs/reference/library/2b/#slag) is a standard-library gate that produces the remaining elements of a list starting after the `n`th element. So we use `scag` to produce the drawn hand of `n` cards in the head of the cell as `hand`, and `slag` to produce the remaining deck in the tail of the cell as `rest`.
126+
127+```
128+++ shuffle-deck
129+ |= [unshuffled=deck entropy=@]
130+ ^- deck
131+ =| shuffled=deck
132+ =/ random ~(. og entropy)
133+ =/ remaining (lent unshuffled)
134+ |-
135+ ?: =(remaining 1)
136+ :_ shuffled
137+ (snag 0 unshuffled)
138+ =^ index random (rads:random remaining)
139+ %^ $
140+ shuffled (snag index unshuffled)^shuffled
141+ remaining (dec remaining)
142+ unshuffled (oust [index 1] unshuffled)
143+```
144+
145+Finally, in the code above, we come to `shuffle-deck`. This gate takes two arguments: a `deck`, and a `@` as a bit of `entropy` to seed the `og` core. It's going to produce a `deck`.
146+
147+`=|` adds a default-valued `deck` to the subject.
148+
149+Next, with `=/ random ~(. og entropy)`, we feed the `og` core the entropy it needs in preparation for using it. Then, with `=/ remaining (lent unshuffled)`, we get the length of the unshuffled deck with `lent`.
150+
151+`?: =(remaining 1)` checks if have only one card remaining. If that's true, we produce a cell of `shuffled` and the one card left in `unshuffled`. We use the `:_` rune here, so that the "heavier" hoon is at the bottom of the expression.
152+
153+If the above conditional evaluates to false, we are going to do a little work. `=^` is a rune that pins the head of a pair and changes the leg with a tail. It's useful for interacting with the `og` core arms, as many of them produce a pair of a random numbers and the next state of the core. We're going to put the random number in the subject with the face `index` and change `random` to be the next core.
154+
155+With completed, we use `%^` to call `$` to recurse back up to `|-` with a few changes.
156+
157+`shuffled` gets the `darc` from `unshuffled` at `index` added to the front of it.
158+
159+`remaining` gets decremented. Why are we using a counter here instead of just checking the length of `unshuffled` on each loop? `lent` traverses the entire list every time it's called so maintaining a counter in this fashion is much faster.
160+
161+`unshuffled` becomes the result of using `oust` to remove 1 `darc` at `index` on `unshuffled`.
162+
163+This is a very naive shuffling algorithm, and you could imagine a better one. Implementation of a better algorithm is left as an exercise for the reader.
164+
165+## Using the Library
166+
167+So now that we have this library, how do we actually use it? Let's look at a very simple `say` generator that takes advantage of what we built.
168+
169+```
170+/+ playing-cards
171+:- %say
172+|= [[* eny=@uv *] *]
173+:- %noun
174+(shuffle-deck:playing-cards make-deck:playing-cards eny)
175+```
176+
177+If you save our the library as `playing-cards.hoon` in the `lib` directory, you can import the library with the `/+` rune. Our above `say` -- let's call it `cards.hoon` -- imports our library in this way. It should be noted that `/+` is not a Hoon rune, but instead a rune used by Ford, the Urbit build-system. When `cards.hoon` gets built, Ford will pull in the requested library and also build that. It will also create a dependency so that if `playing-cards.hoon` changes, this file will also get rebuilt.
178+
179+Below `/+ playing-cards`, you have the standard `say` generator boilerplate that allows us to get a bit of entropy from `arvo` when the generator is run. Then we feed the entropy and a `deck` created by `make-deck` into `shuffle-deck` to get back a shuffled `deck`.
180+
181+### [Next Up: Reading -- Trees, Sets, and Maps](../trees-sets-and-maps)