10In the last section we built a few small apps that sent moves.
11These apps were entirely stateless, however. Most useful apps
12require some amount of state. Let's build a trivial stateful
13app. It'll keep a running the sum of all the atoms we poke it with.
14Here's `app/examples/sum.hoon`:
25 ~& [%so-far (add state arg)]
26 [~ +>.$(state (add state arg))]
30We can start it with `|start %examples-sum`, and then run it:
33~fintud-macrep:dojo> :examples-sum &atom 5
36~fintud-macrep:dojo> :examples-sum &atom 2
39~fintud-macrep:dojo> :examples-sum &atom 15
44We can see that app state is being saved, but when, where, and
47The state is stored as the second thing in the `|_` line. In our
48case, it's simply an atom named `state`. We change it by
49producing as our state not with `+>.$` (as before), but with `+>.$(state (add state arg))`. We've seen all these parts before, but you might not
52Recall in the first chapter that we recursed with the expression
53`$(b (add 3 b))`. This meant "produce `$` with `b` changed to
54`(add 3 b)`. Similarly, `+>.$(state (add state arg))` means
55"produce `+>.$` (i.e. our context, which contains our state) with
56`state` changed to `(add state arg)`.
58At a high level, then, when we handle state, we do it explicitly.
59It's passed in and produced explicitly. In Unix systems,
60application state is just a block of memory, which you need to
61serialize to disk if you want to keep it around for very long.
63In urbit, app state is a single (usually complex) value. In our
64example, we have very simple state, so we defined `state=@`,
65meaning that our state is an atom. Of course, `state` is just a
66name we're assigning to it, and you're free to use whatever name
69There 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
70includes things like `now` (current time), `our` (our urbit
71identity), and `eny` (256 bits of guaranteed-fresh entropy). For
72the full list of things in `++bowl`, search for `++ bowl` (note
73the double space) in `/arvo/zuse.hoon`.
75<blockquote class="blockquote">
76This is a very common technique in learning hoon. While
77documentation exists, often the easiest way to learn about an
78identifier you see in code is to search in `/arvo/zuse.hoon`
79and `/arvo/hoon.hoon` for it. These are our two "standard
80libraries", and they're usually not hard to read. Since
81urbit's codebase is relatively small (those two files are less
82than 15000 lines of code combined, and besides the standard
83library they include the hoon parser and compiler, plus the
84/arvo microkernel), you can usually use the code and the
85comments as reference doc.
88The second thing is that urbit needs no "serialize to disk" step.
89Everything you produce in the app state is persistent across
90calls to the app, restarts of the urbit, and even power failure.
91If you want to write to the filesystem, you can, but it's not
92needed for persistence. Urbit has transactional events, which
93makes it an [ACID operating system](https://en.wikipedia.org/wiki/ACID). Thus, you don't have to
94worry about persistence when programming in urbit or to ever go
95through the hassle of having to set up and write to a database.
99- Modify `:examples-sum` to reset the counter when you poke it with zero.
101- Write an app that prints out the previous value you poked it
105~fintud-macrep:dojo> :examples-last 7
108~fintud-macrep:dojo> :examples-last [1 2 3]
111~fintud-macrep:dojo> :examples-last 'howdy'
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list