on 7d27c45 help sign in
105 lines 3.7 kB history raw
1---
2next: true
3sort: 3
4title: State
5---
7In the last section we built a few small apps that sent moves.
8These apps were entirely stateless, however. Most useful apps
9require some amount of state. Let's build a trivial stateful
10app. It'll keep a running the sum of all the atoms we poke it with.
11Here's `ape/sum.hoon`:
13```
14/? 314
15!:
16|_ [bowl state/@]
17++ poke-atom
18 |= arg/@
19 ^- {(list) _+>.$}
20 ~& [%so-far (add state arg)]
21 [~ +>.$(state (add state arg))]
22--
23```
25We can start it with `|start %sum`, and then run it:
27```
28~fintud-macrep:dojo> :sum &atom 5
29[%so-far 5]
30>=
31~fintud-macrep:dojo> :sum &atom 2
32[%so-far 7]
33>=
34~fintud-macrep:dojo> :sum &atom 15
35[%so-far 22]
36>=
37```
39We can see that app state is being saved, but when, where, and
40how?
42The state is stored as the second thing in the `|_` line. In our
43case, it's simply an atom named `state`. We change it by
44producing as our state not with `+>.$` (as before), but with `+>.$(state (add state arg))`. We've seen all these parts before, but you might not
45recognize 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
50"produce `+>.$` (i.e. our context, which contains our state) with
51`state` changed to `(add state arg)`.
53At a high level, then, when we handle state, we do it explicitly.
54It's passed in and produced explicitly. In Unix systems,
55application state is just a block of memory, which you need to
56serialize to disk if you want to keep it around for very long.
58In urbit, app state is a single (usually complex) value. In our
59example, we have very simple state, so we defined `state=@`,
60meaning that our state is an atom. Of course, `state` is just a
61name we're assigning to it, and you're free to use whatever name
62you want.
64There are at least two points you may be wondering about. First, `bowl` is a set of general global state that is managed by the system. It
65includes things like `now` (current time), `our` (our urbit
66identity), and `eny` (256 bits of guaranteed-fresh entropy). For
67the full list of things in `++bowl`, search for `++ bowl` (note
68the double space) in `/arvo/zuse.hoon`.
70> This is a very common technique in learning hoon. While
71> documentation exists, often the easiest way to learn about an
72> identifier you see in code is to search in `/arvo/zuse.hoon`
73> and `/arvo/hoon.hoon` for it. These are our two "standard
74> libraries", and they're usually not hard to read. Since
75> urbit's codebase is relatively small (those two files are less
76> than 15000 lines of code combined, and besides the standard
77> library they include the hoon parser and compiler, plus the
78> /arvo microkernel), you can usually use the code and the
79> comments as reference doc.
81The second thing is that urbit needs no "serialize to disk" step.
82Everything you produce in the app state is persistent across
83calls to the app, restarts of the urbit, and even power failure.
84If you want to write to the filesystem, you can, but it's not
85needed for persistence. Urbit has transactional events, which
86makes it an [ACID operating system](https://en.wikipedia.org/wiki/ACID). Thus, you don't have to
87worry about persistence when programming in urbit or to ever go
88through the hassle of having to set up and write to a database.
90**Exercises**:
92- Modify `:sum` to reset the counter when you poke it with zero.
94- Write an app that prints out the previous value you poked it
95 with. Sample output:
97```
98~fintud-macrep:dojo> :last 7
99[%last 0]
100>=
101~fintud-macrep:dojo> :last [1 2 3]
102[%last 7]
103>=
104~fintud-macrep:dojo> :last 'howdy'
105[%last [1 2 3]]