on 021ce99 help sign in
494 lines 12 kB history raw
1---
2navhome: /docs
3sort: 3
4title: Subject-oriented programming
5---
7# Urbyte 2: subject-oriented programming
9Thanks for reading Urbytes 0 and 1! In Urbyte 2, we'll take
10nouns for granted and have some real fun with them.
12Let's restart our engines:
14```
15$ urbit -FI ~zod myship
16[...]
17ames: on localhost, UDP 31337.
18http: live (insecure, public) on 8080
19http: live ("secure", public) on 8443
20http: live (insecure, loopback) on 12321
21~zod:dojo>
22```
24## Welcome to the dojo
26Wait, where are we?
28We're playing in the Urbit `:dojo`. The dojo is sort of like a
29cross between a Lisp REPL and the Unix shell. (If you know the
30Unix shell, the Urbit command line has the same history model and
31Emacs editing commands.)
33The dojo has its own command language, which is a superset of
34Hoon. Any Hoon expression is a command. But not all commands
35are expressions.
37(The dojo is not the only command-line app on your Urbit. By
38default there is one other, `:talk`. Since you're on a fakezod,
39you can only talk to yourself. If you accidentally press `^X`,
40it will put you into `:talk`; press `^X` again to switch back.)
42### Dojo variables
44Like the Unix shell, the dojo has command variables. Type
46```
47> =a 42
48```
50You've set the dojo variable `a` to the value `42`. The dojo
51puts this binding in the Hoon subject for expressions to use.
52So you can write:
54```
55> a
5642
58> [4 a]
59[4 42]
61> ? [4 a]
62 {@ud @ud}
63[4 42]
64```
66To unbind `a`, just omit the value:
68```
69> =a
70```
72You removed `a` from the subject. (We can bind it again later, or
73bind over it without removing it.)
75```
76> [4 a]
77-find.a
78```
80Now trying to use `a` is an error.
82## Subject-oriented programming
84What is this *subject* thing, anyway? We put `a` in what?
86Most programming languages have something called a *scope* or an
87*environment* or a *context*. This is a data structure that
88contains the variables and functions an expression can use.
90In a normal language, the environment is not a first-class value.
91You cannot save an environment in a variable, compute an
92expression against the environment in the variable, etc, etc.
94In Hoon or any "subject-oriented" language, an expression is
95executed against one normal value, the *subject*. In Hoon, of
96course, the subject is a noun.
98## First experiments
100Up to now, we've only built constants. By definition, a constant
101doesn't use the subject.
103It would be nice to start with the subject every dojo expression
104gets. But that subject is pretty complex. Instead, let's make a
105simple noun from the kinds of atoms we've already learned about:
107```
108> =a [42 [%foo .6.28 ~m45] 0xdead.beef]
110> ? a
111 {@ud {$foo @rs @dr} @ux}
112[42 [%foo .3.14 ~m45] 0xdead.beef]
114> 420:a
115420
116```
118The syntax `expression:expression` uses the product of the second
119expression as the subject of the first. So we're using `a` as
120the subject of the expression `420`.
122Of course, `420` is a constant expression. It doesn't care what
123the subject is. But:
125```
126> (add 2 2):a
127-find.add
128```
130We can't use `a` as the subject of even a simple addition. How
131could we? There's no `add` function in our `a`. It sometimes
132takes new Hoon programmers a little while before they realize
133that there really isn't a scope or environment in Hoon.
135## Tree geometry
137So what can we do with this subject? How can we get data out of
138it? Let's keep working with our little test subject `a`.
140The most basic way to access the subject is *tree geometry*.
141Every noun is a binary tree; every noun in the tree has a number
142which is its address. The root of the tree is `1`; if the
143address of a cell is `n`, its head is `2n` and its tail is
144`2n+1`.
146A picture might help::
147```
148 1
149 / \
150 2 3
151 / \ / \
152 4 5 6 7
153 / \
154 14 15
155```
157The syntax for a fragment of the subject at a tree address, or
158*axis*, is just `+axis`. So:
160```
161> +3:a
162[[%foo .3.14 ~m45] 0xdead.beef]
164> ? +7:a
165 @ux
1660xdead.beef
168> ? +13:a
169 {@rs @dr}
170[.3.14 ~m45]
171```
173Of course, the fragment retains the type it had when we built it.
175## Labeled surfaces
177We can obviously get anything we want out of the subject by tree
178geometry. But that's not really how we'd like to program. We'd
179much rather *label* subtrees with convenient, memorable symbols.
181For example, suppose our tree looked like:
183```
184 1
185 / \
186 x=2 3
187 / \
188 y=6 z=7
189 / \
190 p=14 15
191 / \
192 q=30 r=31
193```
195Then instead of writing `+2`, we could write `x`, and so on.
197Let's replace our test subject `a` with a new noun built around
198this tree of *labeled surfaces*.
200```
201> =a [x=42 y=[p=%foo q=.6.28 r=~m45] z=0xdead.beef]
203> ? x:a
204 @ud
20542
207> ? y:a
208 {p/$foo q/@rs r/@dr}
209[p=%foo q=.6.28 r=~m45]
211> ? q.y:a
212 @rs
213.6.28
214```
216Surfaces might remind you of attributes in an object. But again,
217attributes in an object are a symbol table. There is no symbol
218table here -- just a tree search.
220An expression like the label `x` or the axis `+2`, which
221designates a fragment or feature of the subject, is called a
222*limb*. A list of limbs connected with `.`, is a *wing*.
224To remind you that you're not in Kansas anymore, the syntax for a
225wing, like `q.y` above, means means "q inside y." In a classic
226object-oriented system, of course, this would be written `y.q`,
227that is, attribute `q` within object `y`. In Hoon, `q.y` means
228"find limb `y`, then find limb `q` inside that."
230## Surfaces versus fragments
232Once again, Hoon has no symbol tables. When we put a surface
233on a noun, the surface label is part of that noun's type. It's
234not part of the cell or other structure that contains the noun.
235This will take a little getting used to:
237```
238> ? x:a
239 @ud
24042
242> ? +2:a
243 x/@ud
244x=42
246? x.+2:a
247 @ud
24842
249```
251When we take fragment 2 of the labeled subject, the *surface
252comes with it*. `+2` is not `42` but rather `x=42`. We can
253take the surface off with `x.+2`.
255## The search algorithm
257In resolving a label to a fragment axis, we search the subject
258type in a depth-first traverse.
260If we find a surface that matches the limb, we succeed. If we
261find a surface that doesn't match the limb, we fail. If we find
262a cell, we search first head, then tail.
264## Skipping
266What if the same label appears twice in one noun? Let's modify
267our subject slightly as a test case:
269```
270> ? +7:a
271 z/@ux
272z=0xdead.beef
274> =a a(+7 x=z:a)
276> ? a
277 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
278[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
280> ? x:a
281 @ud
28242
284> ? ^x:a
285 @ux
2860xdead.beef
287```
289We don't want to hide any part of the noun from an expression.
290So the modified limb `^x` *skips* the first match with a surface
291`x`, getting us to our `0xdead.beef`. This is a unary notation:
292`^^x` would skip the first two matches.
294## Editing
296Above, we mutated our first noun with the flashy `a(+7 x=z:a)`.
298Of course we are not really "modifying" a noun. Hoon is a pure
299language. We are making an edited copy. `a(+7 x=z:a)` means "a
300copy of `a`, with limb `+7` replaced by the product of `x=z:a`."
302We can edit multiple (disjoint) wings in one expression:
304```
305> ? a(+7 [%hello %world], q.y .3.14)
306 {x/@ud y/{p/$foo q/@rs r/@dr} $hello $world}
307[x=42 y=[p=%foo q=.3.14 r=~m45] %hello %world]
308```
310Notice that nothing stopped us from changing `+7` from
311`x=0xdead.beef` to `[%hello %world]`. Since the mutated
312copy is a different noun, it has a different type.
314(And remember that since `[x y z]` means `[x [y z]]`,
315`[x y [%hello %world]]` means `[x y %hello %world]`.)
317## Cores and arms
319It should be reasonably clear how Hoon's system of fragments and
320surfaces parallels variables, records or structures in a
321classical language. But where is Hoon's equivalent of objects:
322values which bind code to data?
324The Hoon equivalent of an object is a *core*. As usual in Hoon,
325the resemblance is inexact. A core has a set of computed
326attributes, or *arms*. Each arm is an expression whose subject
327is the core. There is no argument, so an arm is not a method.
329Physically, a core is always a cell `[battery payload]`, where
330the *payload* is any noun, and the *battery* is a tree of
331formulas in Nock (Hoon's functional assembly language) that
332implements the arms. (A battery is like a C++ vtable, sort of.)
334## The search algorithm
336As you'd expect with a computed attribute, there is only one
337namespace and one search algorithm. We just extend the algorithm
338described above. And an expression which uses a label can't know
339whether the subject will resolve it to a surface fragment (a
340*leg*) or to an arm.
342If we're searching a core and the label matches one of the core's
343arms, we compute the arm against the core. If the label is not
344found, we search into the payload of the core.
346## Some core examples
348When you type these examples, make sure you get the number of
349spaces exactly right. Hoon syntax is not whitespace-sensitive
350in general, except that "one space" is always a different token
351from "two or more spaces."
353```
354> ? x:a
355 @ud
35642
358> ? :per a x
359 @ud
36042
362> =b :per a :core ++ foo x ++ bar [q.y foo] --
363```
365We're seeing some Hoon regular forms for the first time. `x:a`
366turns out to be an irregular relative of the regular `:per` form.
368We'll get more into syntax in a later Urbyte. If some of these
369examples seem syntactically a little funky, this isn't usually
370way we'd do them in "real life." We don't normally write cores
371on a single command line. In a file this would be:
373```
374 :per a
375 :core
376 ++ foo x
377 ++ bar [q.y foo]
378 --
379```
381which is much more readable, at least once you get used to it.
382Let's look at the core itself:
384```
385> b
386<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
388> ? +2:b
389 *
390[[0 6] [0 58] 9 4 0 1]
392> ? +3:b
393 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
394[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
395```
397When we print `b`, or any core, we see that typed noun printing
398can't be an invertible function in Hoon.
400We actually can read the battery (with `+2:b` above), but it's
401just Nock code, not typed data. `<2.spy>` tells us the battery
402has two arms and hashes to the three-letter code `spy`.
404When printing a full core, we don't even print the payload data,
405just its type. But our `+3:b` confirms the `[battery payload]`
406structure of the core. Remember, `+2` is the head and `+3` is
407the tail.
409Finally, let's use this thing:
411```
412> ? foo:b
413 @ud
41442
416> ? bar:b
417 {@rs @ud}
418[.6.28 42]
420? x:b
421 @ud
42242
423```
425Seems legit.
427## The dojo subject
429Now that we've made a test subject which is a core, we can look
430directly at the real dojo subject:
432```
433> +1
434[ [ [ a=[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
435 b=<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
436 ]
437 our=~zod
438 now=~2016.7.18..08.05.15..0b5c
439 eny=0vl.hsfrh.tg642.g5o21.1n80b.0h141.0vuan.pm8o4.77ovg.96rk0.n26nn
440 ]
441 ~
442 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
444```
446We see a bunch of surfaces: our custom `a` and `b`; standard
447surfaces for identity, date, and entropy; and a ginormous core
448stack with *over eight hundred* total arms.
450To be exact, the syntax `<283.xzp 42.ajz 407.xtr 110.xht 1.ztu
451$151>` denotes a stack of six cores, each of whose payload is
452another core, until the innermost payload `%151` (the Hoon
453version number). This stack is our standard library, from which
454comes `add` and other fine functions. (We don't know how to
455write a Hoon function yet, but we're getting way closer.)
457Let's clean up our subject, just to be hygienic:
459```
460> =a
461> =b
463> +1
464[ [ our=~zod
465 now=~2016.7.18..08.10.42..36a0
466 eny=0vf.8j71j.hlqim.k340u.q0ual.v2cd8.cfa65.vkbte.e733g.ehihg.e8aog
467 ]
468 ~
469 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
471```
473Again, remember that `=a` is not Hoon syntax, but `:dojo` syntax.
474How the dojo assembles this subject remains a mystery. But it's
475not a particularly interesting mystery.
477## And we're done
479And we're done! Press `^D` to exit:
481```
482~zod:dojo> ^D
484```
486## Questions and/or exercises
488As always, these questions are optional and only for fun.
490What's the best way to construct a core which acts as a function?
491What do you do to call the function?
493Why don't any other languages use subject-oriented programming?
494Which languages are most similar to it?