4title: 'Subject-oriented programming'
7# Urbyte 2: Subject-oriented programming
9Thanks for reading Urbytes 0 and 1! In Urbyte 2, we'll take nouns for granted
10and have some real fun with them.
12Let's restart our engines:
16 ames: on localhost, UDP 31337.
17 http: live (insecure, public) on 8080
18 http: live ("secure", public) on 8443
19 http: live (insecure, loopback) on 12321
26We're playing in the Urbit `:dojo`. The dojo is sort of like a cross between a
27Lisp REPL and the Unix shell. (If you know the Unix shell, the Urbit command
28line has the same history model and Emacs editing commands.)
30The dojo has its own command language, which is a superset of Hoon. Any Hoon
31expression is a command. But not all commands are expressions.
33(The dojo is not the only command-line app on your Urbit. By default there is
34one other, `:talk`. Since you're on a fakezod, you can only talk to yourself. If
35you accidentally press `ctrl-x`, it will put you into `:talk`; press `ctrl-x`
40Like the Unix shell, the dojo has command variables. Type
44You've set the dojo variable `a` to the value `42`. The dojo puts this binding
45in the Hoon subject for expressions to use. So you can write:
57To unbind `a`, just omit the value:
61You removed `a` from the subject. (We can bind it again later, or bind over it
67Now trying to use `a` is an error.
69## Subject-oriented programming
71What is this *subject* thing, anyway? We put `a` in what?
73Most programming languages have something called a *scope* or an *environment*
74or a *context*. This is a data structure that contains the variables and
75functions an expression can use.
77In a normal language, the environment is not a first-class value. You cannot
78save an environment in a variable, compute an expression against the environment
79in the variable, etc, etc.
81In Hoon or any "subject-oriented" language, an expression is executed against
82one normal value, the *subject*. In Hoon, of course, the subject is a noun.
86Up to now, we've only built constants. By definition, a constant doesn't use the
89It would be nice to start with the subject every dojo expression gets. But that
90subject is pretty complex. Instead, let's make a simple noun from the kinds of
91atoms we've already learned about:
93 > =a [42 [%foo .6.28 ~m45] 0xdead.beef]
96 {@ud {$foo @rs @dr} @ux}
97 [42 [%foo .3.14 ~m45] 0xdead.beef]
102The syntax `expression:expression` uses the product of the second expression as
103the subject of the first. So we're using `a` as the subject of the expression
106Of course, `420` is a constant expression. It doesn't care what the subject is.
112We can't use `a` as the subject of even a simple addition. How could we? There's
113no `add` function in our `a`. It sometimes takes new Hoon programmers a little
114while before they realize that there really isn't a scope or environment in
119So what can we do with this subject? How can we get data out of it? Let's keep
120working with our little test subject `a`.
122The most basic way to access the subject is *tree geometry*. Every noun is a
123binary tree; every noun in the tree has a number which is its address. The root
124of the tree is `1`; if the address of a cell is `n`, its head is `2n` and its
137The syntax for a fragment of the subject at a tree address, or *axis*, is just
141 [[%foo .3.14 ~m45] 0xdead.beef]
151Of course, the fragment retains the type it had when we built it.
155We can obviously get anything we want out of the subject by tree geometry. But
156that's not really how we'd like to program. We'd much rather *label* subtrees
157with convenient, memorable symbols.
159For example, suppose our tree looked like:
171Then instead of writing `+2`, we could write `x`, and so on.
173Let's replace our test subject `a` with a new noun built around this tree of
176 > =a [x=42 y=[p=%foo q=.6.28 r=~m45] z=0xdead.beef]
184 [p=%foo q=.6.28 r=~m45]
190Surfaces might remind you of attributes in an object. But again, attributes in
191an object are a symbol table. There is no symbol table here -- just a tree
194An expression like the label `x` or the axis `+2`, which designates a fragment
195or feature of the subject, is called a *limb*. A list of limbs connected with
198To remind you that you're not in Kansas anymore, the syntax for a wing, like
199`q.y` above, means means "q inside y." In a classic object-oriented system, of
200course, this would be written `y.q`, that is, attribute `q` within object `y`.
201In Hoon, `q.y` means "find limb `y`, then find limb `q` inside that."
203## Surfaces versus fragments
205Once again, Hoon has no symbol tables. When we put a surface on a noun, the
206surface label is part of that noun's type. It's not part of the cell or other
207structure that contains the noun. This will take a little getting used to:
221When we take fragment 2 of the labeled subject, the *surface comes with it*.
222`+2` is not `42` but rather `x=42`. We can take the surface off with `x.+2`.
224## The search algorithm
226In resolving a label to a fragment axis, we search the subject type in a
229If we find a surface that matches the limb, we succeed. If we find a surface
230that doesn't match the limb, we fail. If we find a cell, we search first head,
235What if the same label appears twice in one noun? Let's modify our subject
236slightly as a test case:
245 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
246 [x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
256We don't want to hide any part of the noun from an expression. So the modified
257limb `^x` *skips* the first match with a surface `x`, getting us to our
258`0xdead.beef`. This is a unary notation: `^^x` would skip the first two matches.
262Above, we mutated our first noun with the flashy `a(+7 x=z:a)`.
264Of course we are not really "modifying" a noun. Hoon is a pure language. We are
265making an edited copy. `a(+7 x=z:a)` means "a copy of `a`, with limb `+7`
266replaced by the product of `x=z:a`."
268We can edit multiple (disjoint) wings in one expression:
270 > ? a(+7 [%hello %world], q.y .3.14)
271 {x/@ud y/{p/$foo q/@rs r/@dr} $hello $world}
272 [x=42 y=[p=%foo q=.3.14 r=~m45] %hello %world]
274Notice that nothing stopped us from changing `+7` from `x=0xdead.beef` to
275`[%hello %world]`. Since the mutated copy is a different noun, it has a
278(And remember that since `[x y z]` means `[x [y z]]`, `[x y [%hello %world]]`
279means `[x y %hello %world]`.)
283It should be reasonably clear how Hoon's system of fragments and surfaces
284parallels variables, records or structures in a classical language. But where is
285Hoon's equivalent of objects: values which bind code to data?
287The Hoon equivalent of an object is a *core*. As usual in Hoon, the resemblance
288is inexact. A core has a set of computed attributes, or *arms*. Each arm is an
289expression whose subject is the core. There is no argument, so an arm is not a
292Physically, a core is always a cell `[battery payload]`, where the *payload* is
293any noun, and the *battery* is a tree of formulas in Nock (Hoon's functional
294assembly language) that implements the arms. (A battery is like a C++ vtable,
297## The search algorithm
299As you'd expect with a computed attribute, there is only one namespace and one
300search algorithm. We just extend the algorithm described above. And an
301expression which uses a label can't know whether the subject will resolve it to
302a surface fragment (a *leg*) or to an arm.
304If we're searching a core and the label matches one of the core's arms, we
305compute the arm against the core. If the label is not found, we search into the
310When you type these examples, make sure you get the number of spaces exactly
311right. Hoon syntax is not whitespace-sensitive in general, except that "one
312space" is always a different token from "two or more spaces."
322 > =b :per a :core ++ foo x ++ bar [q.y foo] --
324We're seeing some Hoon regular forms for the first time. `x:a` turns out to be
325an irregular relative of the regular `:per` form.
327We'll get more into syntax in a later Urbyte. If some of these examples seem
328syntactically a little funky, this isn't usually way we'd do them in "real
329life." We don't normally write cores on a single command line. In a file this
338which is much more readable, at least once you get used to it. Let's look at the
342 <2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
346 [[0 6] [0 58] 9 4 0 1]
349 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
350 [x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
352When we print `b`, or any core, we see that typed noun printing can't be an
353invertible function in Hoon.
355We actually can read the battery (with `+2:b` above), but it's just Nock code,
356not typed data. `<2.spy>` tells us the battery has two arms and hashes to the
357three-letter code `spy`.
359When printing a full core, we don't even print the payload data, just its type.
360But our `+3:b` confirms the `[battery payload]` structure of the core. Remember,
361`+2` is the head and `+3` is the tail.
363Finally, let's use this thing:
381Now that we've made a test subject which is a core, we can look directly at the
385 [ [ [ a=[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
386 b=<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
388 now=~2016.7.18..08.05.15..0b5c
389 eny=0vl.hsfrh.tg642.g5o21.1n80b.0h141.0vuan.pm8o4.77ovg.96rk0.n26nn
390 our=~palnul-wolmev-bonfex-danred--tilwen-midlux-bolfus-nocser
393 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
396We see a bunch of surfaces: our custom `a` and `b`; standard surfaces for
397identity, date, and entropy; and a ginormous core stack with *over eight
400To be exact, the syntax `<283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>` denotes a
401stack of six cores, each of whose payload is another core, until the innermost
402payload `%151` (the Hoon version number). This stack is our standard library,
403from which comes `add` and other fine functions. (We don't know how to write a
404Hoon function yet, but we're getting way closer.)
406Let's clean up our subject, just to be hygienic:
412 now=~2016.7.18..08.10.42..36a0
413 eny=0vf.8j71j.hlqim.k340u.q0ual.v2cd8.cfa65.vkbte.e733g.ehihg.e8aog
414 [ [ our=~palnul-wolmev-bonfex-danred--tilwen-midlux-bolfus-nocser
417 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
420Again, remember that `=a` is not Hoon syntax, but `:dojo` syntax. How the dojo
421assembles this subject remains a mystery. But it's not a particularly
426And we're done! Type `|exit` to exit:
428 ~palnul_nocser:dojo> |exit
432## Questions and/or exercises
434As always, these questions are optional and only for fun.
436What's the best way to construct a core which acts as a function? What do you do
439Why don't any other languages use subject-oriented programming? Which languages
440are most similar to it?
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