@@ -10,41 +10,62 @@ title: State
10In the last section we built a few small apps that sent moves. These apps were
10In the last section we built a few small apps that sent moves. These apps were
11entirely stateless, however. Most useful apps require some amount of state.
11entirely stateless, however. Most useful apps require some amount of state.
12Let's build a trivial stateful app. It'll keep a running the sum of all the
12Let's build a trivial stateful app. It'll keep a running the sum of all the
13−atoms we poke it with. Here's `app/examples/sum.hoon`:
13+atoms we poke it with. Here's `examples/app/sum.hoon`:
15− /? 314
15+ :: Keeps track of the sum of all the atoms it has been
16+ :: poked with and prints the sum out
18+ :::: /===/app/sum/hoon
17− |_ {bowl state/@}
26+ |_ {bow/bowl sum/@}
18− ++ poke-atom
28+ ++ poke-atom
20− ^- {(list) _+>.$}
30+ ^- {(list move) _+>.$}
21− ~& [%so-far (add state arg)]
31+ ~& sum+(add sum tom)
22− [~ +>.$(state (add state arg))]
32+ [~ +>.$(sum (add sum tom))]
35+ |= {wir/wire err/(unit tang)}
36+ ^- {(list move) _+>.$}
38+ ~& sum+success+'Poke succeeded!'
40+ ~& sum+error+'Poke failed. Error:'
25−We can start it with `|start %examples-sum`, and then run it:
46+We can start it with `|start %sum`, and then run it:
27− ~fintud-macrep:dojo> :examples-sum &atom 5
48+ ~fintud-macrep:dojo> :sum &atom 5
28− [%so-far 5]
49+ [%sum 5]
30− ~fintud-macrep:dojo> :examples-sum &atom 2
51+ ~fintud-macrep:dojo> :sum &atom 2
31− [%so-far 7]
52+ [%sum 7]
33− ~fintud-macrep:dojo> :examples-sum &atom 15
54+ ~fintud-macrep:dojo> :sum &atom 15
34− [%so-far 22]
55+ [%sum 22]
37We can see that app state is being saved, but when, where, and how?
58We can see that app state is being saved, but when, where, and how?
39The state is stored as the second thing in the `|_` line. In our case, it's
60The state is stored as the second thing in the `|_` line. In our case, it's
40−simply an atom named `state`. We change it by producing our state not with
61+simply an atom named `sum`. We change it by producing our state not with
41−`+>.$` (as before), but with `+>.$(state (add state arg))`. We've seen all these
62+`+>.$` (as before), but with `+>.$(sum (add sum tom))`. We've seen all these
42parts before, but you might not recognize them.
63parts before, but you might not recognize them.
44Recall in the first chapter that we recursed with the expression
65Recall in the first chapter that we recursed with the expression
45`$(b (add 3 b))`. This meant "produce `$` with `b` changed to `(add 3 b)`.
66`$(b (add 3 b))`. This meant "produce `$` with `b` changed to `(add 3 b)`.
46−Similarly, `+>.$(state (add state arg))` means "produce `+>.$` (i.e. our
67+Similarly, `+>.$(sum (add sum tom))` means "produce `+>.$` (i.e. our
47−context, which contains our state) with `state` changed to `(add state arg)`.
68+context, which contains our state) with `sum` changed to `(add sum tom)`.
49At a high level, then, when we handle state, we do it explicitly. It's passed in
70At a high level, then, when we handle state, we do it explicitly. It's passed in
50and produced explicitly. In Unix systems, application state is just a block of
71and produced explicitly. In Unix systems, application state is just a block of
@@ -52,8 +73,8 @@ memory, which you need to serialize to disk if you want to keep it around for
54In Urbit, app state is a single (usually complex) value. In our example, we have
75In Urbit, app state is a single (usually complex) value. In our example, we have
55−very simple state, so we defined `state/@`, meaning that our state is an atom.
76+very simple state, so we defined `sum/@`, meaning that our state is an atom.
56−Of course, `state` is just a name, and you're free to name your state whatever
77+Of course, `sum` is just a name, and you're free to name your state whatever
57you like. But let's clarify a couple other things before we continue.
78you like. But let's clarify a couple other things before we continue.
59First, `bowl` is a set of general global states. This set is managed by the
80First, `bowl` is a set of general global states. This set is managed by the
@@ -81,22 +102,22 @@ Unix filesystem, you can, but it's not needed for persistence. Urbit has
81transactional events, which makes it an [ACID operating
102transactional events, which makes it an [ACID operating
82system](https://en.wikipedia.org/wiki/ACID). Thus, you don't have to worry about
103system](https://en.wikipedia.org/wiki/ACID). Thus, you don't have to worry about
83persistence when programming in Urbit, or ever go through the hassle of having
104persistence when programming in Urbit, or ever go through the hassle of having
84−to set up and write to a database.
105+to set up and write to a database.
86**Exercises**:
107**Exercises**:
88−- Modify `:examples-sum` to reset the counter when you poke it with 0.
109+- Modify `:sum` to reset the counter when you poke it with 0.
90−- Write an app that prints out the previous value you poked it with. Sample
111+- Write an app called `last` that prints out the previous value you poked it with.
91− output:
112+ Sample output:
95− ~fintud-macrep:dojo> :examples-last 7
116+ ~fintud-macrep:dojo> :last 7
96 [%last 0]
117 [%last 0]
98− ~fintud-macrep:dojo> :examples-last [1 2 3]
119+ ~fintud-macrep:dojo> :last [1 2 3]
99 [%last 7]
120 [%last 7]
101− ~fintud-macrep:dojo> :examples-last 'howdy'
122+ ~fintud-macrep:dojo> :last 'howdy'
102 [%last [1 2 3]]
123 [%last [1 2 3]]