on 6d45ede help sign in
urbit.org/docs/arvo/state.md
109 lines 3.9 kB history raw
1---
2navhome: /docs
3next: true
4sort: 4
5title: State
6---
8State
9=====
11In the last section we built a few small apps that sent moves. These
12apps were entirely stateless, however. Most useful apps require some
13amount of state. Let's build a trivial stateful app. It'll keep a
14running the sum of all the atoms we poke it with. Here's
15`app/examples/sum.hoon`:
17 /? 314
18 !:
19 |_ {bowl state/@}
20 ++ poke-atom
21 |= arg/@
22 ^- {(list) _+>.$}
23 ~& [%so-far (add state arg)]
24 [~ +>.$(state (add state arg))]
25 --
27We can start it with `|start %examples-sum`, and then run it:
29 ~fintud-macrep:dojo> :examples-sum &atom 5
30 [%so-far 5]
31 >=
32 ~fintud-macrep:dojo> :examples-sum &atom 2
33 [%so-far 7]
34 >=
35 ~fintud-macrep:dojo> :examples-sum &atom 15
36 [%so-far 22]
37 >=
39We can see that app state is being saved, but when, where, and how?
41The state is stored as the second thing in the `|_` line. In our case,
42it's simply an atom named `state`. We change it by producing as our
43state not with `+>.$` (as before), but with
44`+>.$(state (add state arg))`. We've seen all these parts before, but
45you might not recognize them.
47Recall in the first chapter that we recursed with the expression
48`$(b (add 3 b))`. This meant "produce `$` with `b` changed to
49`(add 3 b)`. Similarly, `+>.$(state (add state arg))` means "produce
50`+>.$` (i.e. our context, which contains our state) with `state` changed
51to `(add state arg)`.
53At a high level, then, when we handle state, we do it explicitly. It's
54passed in and produced explicitly. In Unix systems, application state is
55just a block of memory, which you need to serialize to disk if you want
56to keep it around for very long.
58In Urbit, app state is a single (usually complex) value. In our example,
59we have very simple state, so we defined `state=@`, meaning that our
60state is an atom. Of course, `state` is just a name, and you're free to
61name your state whatever you like. But let's clarify a couple other
62things before we continue.
64First, `bowl` is a set of general global states. This set is managed by
65the system. It includes things like `now` (the current time), `our` (our
66urbit identity), and `eny` (256 bits of guaranteed-fresh entropy). For
67the full list of things in `++bowl`, search for `++ bowl` (note: two
68spaces) in `/arvo/zuse.hoon`.
70> This is, perhaps, the most common way to learn Hoon. The easiest way
71> to learn about an identifier you see in code is to search in
72> `/arvo/zuse.hoon` and `/arvo/hoon.hoon` for it.\
73> These "standard libraries" are usually simple to read. Since Urbit's
74> codebase is less than 15000 lines of code combined, including the hoon
75> parser, the compiler, and the `/arvo` microkernel, you can usually use
76> the code and its comments as a reference doc.
78> You can also read
79> [zuse.hoon](https://github.com/urbit/arvo/blob/master/arvo/zuse.hoon)
80> and
81> [hoon.hoon](https://github.com/urbit/arvo/blob/master/arvo/hoon.hoon)
82> in your browser.
84The second thing we should clear up is this: Urbit needs no "serialize
85to disk" step. Everything you produce in the app state is persistent
86across calls to the app, restarts of the urbit, and even power failure.
87If you want to write to the Unix filesystem, you can, but it's not
88needed for persistence. Urbit has transactional events, which makes it
89an [ACID operating system](https://en.wikipedia.org/wiki/ACID). Thus,
90you don't have to worry about persistence when programming in Urbit, or
91ever go through the hassle of having to set up and write to a database.
93**Exercises**:
95- Modify `:examples-sum` to reset the counter when you poke it with 0.
97- Write an app that prints out the previous value you poked it with.
98 Sample output:
100```
101~fintud-macrep:dojo> :examples-last 7
102[%last 0]
103>=
104~fintud-macrep:dojo> :examples-last [1 2 3]
105[%last 7]
106>=
107~fintud-macrep:dojo> :examples-last 'howdy'
108[%last [1 2 3]]
109```