--- navhome: /docs sort: 3 title: Subject-oriented programming --- # Urbyte 2: subject-oriented programming Thanks for reading Urbytes 0 and 1! In Urbyte 2, we'll take nouns for granted and have some real fun with them. Let's restart our engines: ``` $ urbit -FI ~zod myship [...] ames: on localhost, UDP 31337. http: live (insecure, public) on 8080 http: live ("secure", public) on 8443 http: live (insecure, loopback) on 12321 ~zod:dojo> ``` ## Welcome to the dojo Wait, where are we? We're playing in the Urbit `:dojo`. The dojo is sort of like a cross between a Lisp REPL and the Unix shell. (If you know the Unix shell, the Urbit command line has the same history model and Emacs editing commands.) The dojo has its own command language, which is a superset of Hoon. Any Hoon expression is a command. But not all commands are expressions. (The dojo is not the only command-line app on your Urbit. By default there is one other, `:talk`. Since you're on a fakezod, you can only talk to yourself. If you accidentally press `^X`, it will put you into `:talk`; press `^X` again to switch back.) ### Dojo variables Like the Unix shell, the dojo has command variables. Type ``` > =a 42 ``` You've set the dojo variable `a` to the value `42`. The dojo puts this binding in the Hoon subject for expressions to use. So you can write: ``` > a 42 > [4 a] [4 42] > ? [4 a] {@ud @ud} [4 42] ``` To unbind `a`, just omit the value: ``` > =a ``` You removed `a` from the subject. (We can bind it again later, or bind over it without removing it.) ``` > [4 a] -find.a ``` Now trying to use `a` is an error. ## Subject-oriented programming What is this *subject* thing, anyway? We put `a` in what? Most programming languages have something called a *scope* or an *environment* or a *context*. This is a data structure that contains the variables and functions an expression can use. In a normal language, the environment is not a first-class value. You cannot save an environment in a variable, compute an expression against the environment in the variable, etc, etc. In Hoon or any "subject-oriented" language, an expression is executed against one normal value, the *subject*. In Hoon, of course, the subject is a noun. ## First experiments Up to now, we've only built constants. By definition, a constant doesn't use the subject. It would be nice to start with the subject every dojo expression gets. But that subject is pretty complex. Instead, let's make a simple noun from the kinds of atoms we've already learned about: ``` > =a [42 [%foo .6.28 ~m45] 0xdead.beef] > ? a {@ud {$foo @rs @dr} @ux} [42 [%foo .3.14 ~m45] 0xdead.beef] > 420:a 420 ``` The syntax `expression:expression` uses the product of the second expression as the subject of the first. So we're using `a` as the subject of the expression `420`. Of course, `420` is a constant expression. It doesn't care what the subject is. But: ``` > (add 2 2):a -find.add ``` We can't use `a` as the subject of even a simple addition. How could we? There's no `add` function in our `a`. It sometimes takes new Hoon programmers a little while before they realize that there really isn't a scope or environment in Hoon. ## Tree geometry So what can we do with this subject? How can we get data out of it? Let's keep working with our little test subject `a`. The most basic way to access the subject is *tree geometry*. Every noun is a binary tree; every noun in the tree has a number which is its address. The root of the tree is `1`; if the address of a cell is `n`, its head is `2n` and its tail is `2n+1`. A picture might help:: ``` 1 / \ 2 3 / \ / \ 4 5 6 7 / \ 14 15 ``` The syntax for a fragment of the subject at a tree address, or *axis*, is just `+axis`. So: ``` > +3:a [[%foo .3.14 ~m45] 0xdead.beef] > ? +7:a @ux 0xdead.beef > ? +13:a {@rs @dr} [.3.14 ~m45] ``` Of course, the fragment retains the type it had when we built it. ## Labeled surfaces We can obviously get anything we want out of the subject by tree geometry. But that's not really how we'd like to program. We'd much rather *label* subtrees with convenient, memorable symbols. For example, suppose our tree looked like: ``` 1 / \ x=2 3 / \ y=6 z=7 / \ p=14 15 / \ q=30 r=31 ``` Then instead of writing `+2`, we could write `x`, and so on. Let's replace our test subject `a` with a new noun built around this tree of *labeled surfaces*. ``` > =a [x=42 y=[p=%foo q=.6.28 r=~m45] z=0xdead.beef] > ? x:a @ud 42 > ? y:a {p/$foo q/@rs r/@dr} [p=%foo q=.6.28 r=~m45] > ? q.y:a @rs .6.28 ``` Surfaces might remind you of attributes in an object. But again, attributes in an object are a symbol table. There is no symbol table here -- just a tree search. An expression like the label `x` or the axis `+2`, which designates a fragment or feature of the subject, is called a *limb*. A list of limbs connected with `.`, is a *wing*. To remind you that you're not in Kansas anymore, the syntax for a wing, like `q.y` above, means means "q inside y." In a classic object-oriented system, of course, this would be written `y.q`, that is, attribute `q` within object `y`. In Hoon, `q.y` means "find limb `y`, then find limb `q` inside that." ## Surfaces versus fragments Once again, Hoon has no symbol tables. When we put a surface on a noun, the surface label is part of that noun's type. It's not part of the cell or other structure that contains the noun. This will take a little getting used to: ``` > ? x:a @ud 42 > ? +2:a x/@ud x=42 ? x.+2:a @ud 42 ``` When we take fragment 2 of the labeled subject, the *surface comes with it*. `+2` is not `42` but rather `x=42`. We can take the surface off with `x.+2`. ## The search algorithm In resolving a label to a fragment axis, we search the subject type in a depth-first traverse. If we find a surface that matches the limb, we succeed. If we find a surface that doesn't match the limb, we fail. If we find a cell, we search first head, then tail. ## Skipping What if the same label appears twice in one noun? Let's modify our subject slightly as a test case: ``` > ? +7:a z/@ux z=0xdead.beef > =a a(+7 x=z:a) > ? a {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux} [x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef] > ? x:a @ud 42 > ? ^x:a @ux 0xdead.beef ``` We don't want to hide any part of the noun from an expression. So the modified limb `^x` *skips* the first match with a surface `x`, getting us to our `0xdead.beef`. This is a unary notation: `^^x` would skip the first two matches. ## Editing Above, we mutated our first noun with the flashy `a(+7 x=z:a)`. Of course we are not really "modifying" a noun. Hoon is a pure language. We are making an edited copy. `a(+7 x=z:a)` means "a copy of `a`, with limb `+7` replaced by the product of `x=z:a`." We can edit multiple (disjoint) wings in one expression: ``` > ? a(+7 [%hello %world], q.y .3.14) {x/@ud y/{p/$foo q/@rs r/@dr} $hello $world} [x=42 y=[p=%foo q=.3.14 r=~m45] %hello %world] ``` Notice that nothing stopped us from changing `+7` from `x=0xdead.beef` to `[%hello %world]`. Since the mutated copy is a different noun, it has a different type. (And remember that since `[x y z]` means `[x [y z]]`, `[x y [%hello %world]]` means `[x y %hello %world]`.) ## Cores and arms It should be reasonably clear how Hoon's system of fragments and surfaces parallels variables, records or structures in a classical language. But where is Hoon's equivalent of objects: values which bind code to data? The Hoon equivalent of an object is a *core*. As usual in Hoon, the resemblance is inexact. A core has a set of computed attributes, or *arms*. Each arm is an expression whose subject is the core. There is no argument, so an arm is not a method. Physically, a core is always a cell `[battery payload]`, where the *payload* is any noun, and the *battery* is a tree of formulas in Nock (Hoon's functional assembly language) that implements the arms. (A battery is like a C++ vtable, sort of.) ## The search algorithm As you'd expect with a computed attribute, there is only one namespace and one search algorithm. We just extend the algorithm described above. And an expression which uses a label can't know whether the subject will resolve it to a surface fragment (a *leg*) or to an arm. If we're searching a core and the label matches one of the core's arms, we compute the arm against the core. If the label is not found, we search into the payload of the core. ## Some core examples When you type these examples, make sure you get the number of spaces exactly right. Hoon syntax is not whitespace-sensitive in general, except that "one space" is always a different token from "two or more spaces." ``` > ? x:a @ud 42 > ? :per a x @ud 42 > =b :per a :core ++ foo x ++ bar [q.y foo] -- ``` We're seeing some Hoon regular forms for the first time. `x:a` turns out to be an irregular relative of the regular `:per` form. We'll get more into syntax in a later Urbyte. If some of these examples seem syntactically a little funky, this isn't usually way we'd do them in "real life." We don't normally write cores on a single command line. In a file this would be: ``` :per a :core ++ foo x ++ bar [q.y foo] -- ``` which is much more readable, at least once you get used to it. Let's look at the core itself: ``` > b <2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}> > ? +2:b * [[0 6] [0 58] 9 4 0 1] > ? +3:b {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux} [x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef] ``` When we print `b`, or any core, we see that typed noun printing can't be an invertible function in Hoon. We actually can read the battery (with `+2:b` above), but it's just Nock code, not typed data. `<2.spy>` tells us the battery has two arms and hashes to the three-letter code `spy`. When printing a full core, we don't even print the payload data, just its type. But our `+3:b` confirms the `[battery payload]` structure of the core. Remember, `+2` is the head and `+3` is the tail. Finally, let's use this thing: ``` > ? foo:b @ud 42 > ? bar:b {@rs @ud} [.6.28 42] ? x:b @ud 42 ``` Seems legit. ## The dojo subject Now that we've made a test subject which is a core, we can look directly at the real dojo subject: ``` > +1 [ [ [ a=[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef] b=<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}> ] our=~zod now=~2016.7.18..08.05.15..0b5c eny=0vl.hsfrh.tg642.g5o21.1n80b.0h141.0vuan.pm8o4.77ovg.96rk0.n26nn ] ~ <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151> ] ``` We see a bunch of surfaces: our custom `a` and `b`; standard surfaces for identity, date, and entropy; and a ginormous core stack with *over eight hundred* total arms. To be exact, the syntax `<283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>` denotes a stack of six cores, each of whose payload is another core, until the innermost payload `%151` (the Hoon version number). This stack is our standard library, from which comes `add` and other fine functions. (We don't know how to write a Hoon function yet, but we're getting way closer.) Let's clean up our subject, just to be hygienic: ``` > =a > =b > +1 [ [ our=~zod now=~2016.7.18..08.10.42..36a0 eny=0vf.8j71j.hlqim.k340u.q0ual.v2cd8.cfa65.vkbte.e733g.ehihg.e8aog ] ~ <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151> ] ``` Again, remember that `=a` is not Hoon syntax, but `:dojo` syntax. How the dojo assembles this subject remains a mystery. But it's not a particularly interesting mystery. ## And we're done And we're done! Press `^D` to exit: ``` ~zod:dojo> ^D $ ``` ## Questions and/or exercises As always, these questions are optional and only for fun. What's the best way to construct a core which acts as a function? What do you do to call the function? Why don't any other languages use subject-oriented programming? Which languages are most similar to it?