5title: Subject-oriented programming
8# Urbyte 2: subject-oriented programming
10Thanks for reading Urbytes 0 and 1! In Urbyte 2, we'll take
11nouns for granted and have some real fun with them.
13Let's restart our engines:
16$ urbit -FI ~zod myship
18ames: on localhost, UDP 31337.
19http: live (insecure, public) on 8080
20http: live ("secure", public) on 8443
21http: live (insecure, loopback) on 12321
29We're playing in the Urbit `:dojo`. The dojo is sort of like a
30cross between a Lisp REPL and the Unix shell. (If you know the
31Unix shell, the Urbit command line has the same history model and
32Emacs editing commands.)
34The dojo has its own command language, which is a superset of
35Hoon. Any Hoon expression is a command. But not all commands
38(The dojo is not the only command-line app on your Urbit. By
39default there is one other, `:talk`. Since you're on a fakezod,
40you can only talk to yourself. If you accidentally press `^X`,
41it will put you into `:talk`; press `^X` again to switch back.)
45Like the Unix shell, the dojo has command variables. Type
51You've set the dojo variable `a` to the value `42`. The dojo
52puts this binding in the Hoon subject for expressions to use.
67To unbind `a`, just omit the value:
73You removed `a` from the subject. (We can bind it again later, or
74bind over it without removing it.)
81Now trying to use `a` is an error.
83## Subject-oriented programming
85What is this *subject* thing, anyway? We put `a` in what?
87Most programming languages have something called a *scope* or an
88*environment* or a *context*. This is a data structure that
89contains the variables and functions an expression can use.
91In a normal language, the environment is not a first-class value.
92You cannot save an environment in a variable, compute an
93expression against the environment in the variable, etc, etc.
95In Hoon or any "subject-oriented" language, an expression is
96executed against one normal value, the *subject*. In Hoon, of
97course, the subject is a noun.
101Up to now, we've only built constants. By definition, a constant
102doesn't use the subject.
104It would be nice to start with the subject every dojo expression
105gets. But that subject is pretty complex. Instead, let's make a
106simple noun from the kinds of atoms we've already learned about:
109> =a [42 [%foo .6.28 ~m45] 0xdead.beef]
112 {@ud {$foo @rs @dr} @ux}
113[42 [%foo .3.14 ~m45] 0xdead.beef]
119The syntax `expression:expression` uses the product of the second
120expression as the subject of the first. So we're using `a` as
121the subject of the expression `420`.
123Of course, `420` is a constant expression. It doesn't care what
131We can't use `a` as the subject of even a simple addition. How
132could we? There's no `add` function in our `a`. It sometimes
133takes new Hoon programmers a little while before they realize
134that there really isn't a scope or environment in Hoon.
138So what can we do with this subject? How can we get data out of
139it? Let's keep working with our little test subject `a`.
141The most basic way to access the subject is *tree geometry*.
142Every noun is a binary tree; every noun in the tree has a number
143which is its address. The root of the tree is `1`; if the
144address of a cell is `n`, its head is `2n` and its tail is
147A picture might help::
158The syntax for a fragment of the subject at a tree address, or
159*axis*, is just `+axis`. So:
163[[%foo .3.14 ~m45] 0xdead.beef]
174Of course, the fragment retains the type it had when we built it.
178We can obviously get anything we want out of the subject by tree
179geometry. But it's not really how we'd like to program. We'd
180much rather *label* subtrees with convenient, memorable symbols.
182For example, suppose our tree looked like:
196Then instead of writing `+2`, we could write `x`, and so on.
198Let's replace our test subject `a` with a new noun built around
199this tree of *labeled surfaces*.
202> =a [x=42 y=[p=%foo q=.6.28 r=~m45] z=0xdead.beef]
210[p=%foo q=.6.28 r=~m45]
217Surfaces might remind you of attributes in an object. But again,
218attributes in an object are a symbol table. There is no symbol
219table here -- just a tree search.
221An expression like the label `x` or the axis `+2`, which
222designates a fragment or feature of the subject, is called a
223*limb*. Limbs can be connected with a `.`, making a *wing*.
225To remind you that you're not in Kansas anymore, the syntax for a
226wing, like `q.y` above, means means "q inside y." In a classic
227object-oriented system, of course, this would be written `y.q`,
228that is, attribute `q` within object `y`. In Hoon, `q.y` means
229"find limb `q`, then find limb `y` inside that."
231## Surfaces versus fragments
233Once again, Hoon has no symbol tables. When we put a surface
234on a noun, the surface label is part of that noun's type. It's
235not part of the cell or other structure that contains the noun.
252When we take fragment 2 of the labeled subject the *surface
253comes with it *. `+2` is not `42` but rather `x=42`. We can
254take the surface off with `x.+2`.
256## The search algorithm
258In resolving a label to a fragment axis, we search the subject
259type in a depth-first traverse.
261If we find a surface that matches the limb, we succeed. If we
262find a surface that doesn't match the limb, we fail. If we find
263a cell, we search first head, then tail.
267What if the same label appears twice in one noun? Let's modify
268our subject slightly as a test case:
278 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
279[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
290We don't want to hide any part of the noun from an expression.
291So the modified limb `^x` *skips* the first match with a surface
292`x`, getting us to our `0xdead.beef`. This is a unary notation:
293`^^x` would skip the first two matches.
297Above, we mutated our first noun with the flashy `a(+7 x=z:a)`.
299Of course we are not really "modifying" a noun. Hoon is a pure
300language. We are making an edited copy. `a(+7 x=z:a)` means "a
301copy of `a`, with limb `+7` replaced by the product of `x=z:a`."
303We can edit multiple (disjoint) wings in one expression:
306> ? a(+7 [%hello %world], q.y .3.14)
307 {x/@ud y/{p/$foo q/@rs r/@dr} $hello $world}
308[x=42 y=[p=%foo q=.3.14 r=~m45] %hello %world]
311Notice that nothing stopped us from changing `+7` from
312`x=0xdead.beef` to `[%hello %world]`. Since the mutated
313copy is a different noun, it has a different type.
315(And remember that since `[x y z]` means `[x [y z]]`,
316`[x y [%hello %world]]` means `[x y %hello %world]`.)
320It should be reasonably clear how Hoon's system of fragments and
321surfaces parallels variables, records or structures in a
322classical language. But where is Hoon's equivalent of objects:
323values which bind code to data?
325The Hoon equivalent of an object is a *core*. As usual in Hoon,
326the resemblance isn't exact. A core has a set of computed
327attributes, or *arms*. Each arm is an expression whose subject
328is the core. There is no argument, so an arm is not a method.
330Physically, a core is always a cell `[battery payload]`, where
331the *payload* is any noun, and the *battery* is a tree of
332formulas in Nock (Hoon's functional assembly language) that
335As you'd expect with a computed attribute, an expression which
336uses a label can't know whether the subject will resolve it to a
337surface fragment (a *leg*) or to an arm.
339If we're searching a core and the label matches one of the core's
340arms, we compute the arm against the core. If the label is not
341found, we search into the payload of the core.
345When you type these examples, make sure you get the number of
346spaces exactly right. Hoon syntax is not whitespace-sensitive
347in general, except that "one space" is always a different token
348from "two or more spaces."
359> =b :per a :core ++ foo x ++ bar [q.y foo] --
362<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
378[[0 6] [0 58] 9 4 0 1]
381We're seeing some Hoon regular forms for the first time. `x:a`
382turns out to be an irregular relative of the regular `:per` form.
384(We'll get more into syntax in a later Urbyte. If some of these
385examples seem syntactically a little funky, this isn't usually
386way we'd do them in "real life." We don't normally write cores
387on one line in the dojo, for instance.)
389And when we print `b`, or any core, we see that typed noun
390printing can't be an invertible function in Hoon.
392We actually can read the battery (with `+2:b` above), but it's
393just Nock code, not typed data. We don't even print the payload
394data, though we print the payload type. The `<2.spy>` just shows
395a core with two arms, for which `spy` is a hash code.
399Now that we've made a test subject which is a core, we can look
400directly at the real dojo subject:
404[ [ [ a=[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
405 b=<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
408 now=~2016.7.18..08.05.15..0b5c
409 eny=0vl.hsfrh.tg642.g5o21.1n80b.0h141.0vuan.pm8o4.77ovg.96rk0.n26nn
412 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
416We see a bunch of surfaces: our custom `a` and `b`; standard
417surfaces for identity, date, and entropy; and a ginormous core
418stack with almost a thousand total arms.
420To be exact, the syntax `<283.xzp 42.ajz 407.xtr 110.xht 1.ztu
421$151>` denotes a system of six cores, each of whose payload is
422another core, until the innermost payload `%151` (the Hoon
423version). This stack is our standard library, from which comes
424`add` and other fine functions. (We don't know how to define a
425Hoon function yet, but we're getting close.)
427Let's clean up our subject, just to be hygienic:
435 now=~2016.7.18..08.10.42..36a0
436 eny=0vf.8j71j.hlqim.k340u.q0ual.v2cd8.cfa65.vkbte.e733g.ehihg.e8aog
439 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
443Again, remember that `=a` is not Hoon syntax, but `:dojo` syntax.
444How the dojo assembles this subject remains a mystery. But it's
445not a particularly interesting mystery.
449And we're done! Press `^D` to exit:
456## Questions and/or exercises
458As always, these questions are optional and only for fun.
460What's the best way to construct a core which acts as a function?
461How do you call the function?
463Why don't any other languages use subject-oriented programming?
464Which languages are 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