on fc8a545 help sign in
505 lines 13 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 mycomet
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~palnul_nocser: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 `ctrl-x`,
40it will put you into `:talk`; press `ctrl-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`, the address of its head is `2n` and the
144address of its tail is `2n+1`.
148A picture might help:
149```
150 1
151 / \
152 2 3
153 / \ / \
154 4 5 6 7
155 / \
156 14 15
157```
159The syntax for a fragment of the subject at a tree address, or
160*axis*, is just `+axis`. So:
162```
163> +3:a
164[[%foo .3.14 ~m45] 0xdead.beef]
166> ? +7:a
167 @ux
1680xdead.beef
170> ? +13:a
171 {@rs @dr}
172[.3.14 ~m45]
173```
175The fragment retains the type it had when we built it.
177Another (equivalent) way to think of tree addressing involves
178binary. As before, the root of the tree is at address `1`. For
179the node of a tree at some address `b`, where `b` is binary,
180you get the address of the head by concatenating a `0` to
181the end of `b`; and to get the tail, concatenate a `1` at the
182end. For example, the head of the node at binary address `111`
183is at `1110`, and the tail is at `1111`.
185## Labeled surfaces
187We can obviously get anything we want out of the subject by tree
188geometry. But that's not really how we'd like to program. We'd
189much rather *label* subtrees with convenient, memorable symbols.
191For example, suppose our tree looked like:
193```
194 1
195 / \
196 x=2 3
197 / \
198 y=6 z=7
199 / \
200 p=14 15
201 / \
202 q=30 r=31
203```
205Then instead of writing `+2`, we could write `x`, and so on.
207Let's replace our test subject `a` with a new noun built around
208this tree of *labeled surfaces*.
210```
211> =a [x=42 y=[p=%foo q=.6.28 r=~m45] z=0xdead.beef]
213> ? x:a
214 @ud
21542
217> ? y:a
218 {p/$foo q/@rs r/@dr}
219[p=%foo q=.6.28 r=~m45]
221> ? q.y:a
222 @rs
223.6.28
224```
226Surfaces might remind you of attributes in an object. But again,
227attributes in an object are a symbol table. There is no symbol
228table here -- just a tree search.
230An expression like the label `x` or the axis `+2`, which
231designates a fragment or feature of the subject, is called a
232*limb*. A list of limbs connected with `.` is a *wing*.
234To remind you that you're not in Kansas anymore, the syntax for a
235wing, like `q.y` above, means means "q inside y." In a classic
236object-oriented system, of course, this would be written `y.q`,
237that is, attribute `q` within object `y`. In Hoon, `q.y` means
238"find limb `y`, then find limb `q` inside that."
240## Surfaces versus fragments
242Once again, Hoon has no symbol tables. When we put a surface
243on a noun, the surface label is part of that noun's type. It's
244not part of the cell or other structure that contains the noun.
245This will take a little getting used to:
247```
248> ? x:a
249 @ud
25042
252> ? +2:a
253 x/@ud
254x=42
256? x.+2:a
257 @ud
25842
259```
261When we take fragment 2 of the labeled subject, the *surface
262comes with it*. `+2` is not `42` but rather `x=42`. We can
263take the surface off with `x.+2`.
265## The search algorithm
267In resolving a label to a fragment axis, we search the subject
268type in a depth-first traverse.
270If we find a surface that matches the limb, we succeed. If we
271find a surface that doesn't match the limb, we fail. If we find
272a cell, we search first head, then tail.
274## Skipping
276What if the same label appears twice in one noun? Let's modify
277our subject slightly as a test case:
279```
280> ? +7:a
281 z/@ux
282z=0xdead.beef
284> =a a(+7 x=z:a)
286> ? a
287 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
288[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
290> ? x:a
291 @ud
29242
294> ? ^x:a
295 @ux
2960xdead.beef
297```
299We don't want to hide any part of the noun from an expression.
300So the modified limb `^x` *skips* the first match with a surface
301`x`, getting us to our `0xdead.beef`. This is a unary notation:
302`^^x` would skip the first two matches.
304## Editing
306Above, we mutated our first noun with the flashy `a(+7 x=z:a)`.
308Of course we are not really "modifying" a noun. Hoon is a pure
309language. We are making an edited copy. `a(+7 x=z:a)` means "a
310copy of `a`, with limb `+7` replaced by the product of `x=z:a`."
312We can edit multiple (disjoint) wings in one expression:
314```
315> ? a(+7 [%hello %world], q.y .3.14)
316 {x/@ud y/{p/$foo q/@rs r/@dr} $hello $world}
317[x=42 y=[p=%foo q=.3.14 r=~m45] %hello %world]
318```
320Notice that nothing stopped us from changing `+7` from
321`x=0xdead.beef` to `[%hello %world]`. Since the mutated
322copy is a different noun, it has a different type.
324(And remember that since `[x y z]` means `[x [y z]]`,
325`[x y [%hello %world]]` means `[x y %hello %world]`.)
327## Cores and arms
329It should be reasonably clear how Hoon's system of fragments and
330surfaces parallels variables, records or structures in a
331classical language. But where is Hoon's equivalent of objects:
332values which bind code to data?
334The Hoon equivalent of an object is a *core*. As usual in Hoon,
335the resemblance is inexact. A core has a set of computed
336attributes, or *arms*. Each arm is an expression whose subject
337is the core. There is no argument, so an arm is not a method.
339Physically, a core is always a cell `[battery payload]`, where
340the *payload* is any noun, and the *battery* is a tree of
341formulas in Nock (Hoon's functional assembly language) that
342implements the arms. (A battery is like a C++ vtable, sort of.)
344## The search algorithm
346As you'd expect with a computed attribute, there is only one
347namespace and one search algorithm. We just extend the algorithm
348described above. And an expression which uses a label can't know
349whether the subject will resolve it to a surface fragment (a
350*leg*) or to an arm.
352If we're searching a core and the label matches one of the core's
353arms, we compute the arm against the core. If the label is not
354found, we search into the payload of the core.
356## Some core examples
358When you type these examples, make sure you get the number of
359spaces exactly right. Hoon syntax is not whitespace-sensitive
360in general, except that "one space" is always a different token
361from "two or more spaces."
363```
364> ? x:a
365 @ud
36642
368> ? :per a x
369 @ud
37042
372> =b :per a :core ++ foo x ++ bar [q.y foo] --
373```
375We're seeing some Hoon regular forms for the first time. `x:a`
376turns out to be an irregular relative of the regular `:per` form.
378We'll get more into syntax in a later Urbyte. If some of these
379examples seem syntactically a little funky, this isn't usually
380way we'd do them in "real life." We don't normally write cores
381on a single command line. In a file this would be:
383```
384 :per a
385 :core
386 ++ foo x
387 ++ bar [q.y foo]
388 --
389```
391which is much more readable, at least once you get used to it.
392Let's look at the core itself:
394```
395> b
396<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
398> ? +2:b
399 *
400[[0 6] [0 58] 9 4 0 1]
402> ? +3:b
403 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
404[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
405```
407When we print `b`, or any core, we see that typed noun printing
408can't be an invertible function in Hoon.
410We actually can read the battery (with `+2:b` above), but it's
411just Nock code, not typed data. `<2.spy>` tells us the battery
412has two arms and hashes to the three-letter code `spy`.
414When printing a full core, we don't even print the payload data,
415just its type. But our `+3:b` confirms the `[battery payload]`
416structure of the core. Remember, `+2` is the head and `+3` is
417the tail.
419Finally, let's use this thing:
421```
422> ? foo:b
423 @ud
42442
426> ? bar:b
427 {@rs @ud}
428[.6.28 42]
430> ? x:b
431 @ud
43242
433```
435Seems legit.
437## The dojo subject
439Now that we've made a test subject which is a core, we can look
440directly at the real dojo subject:
442```
443> +1
444[ [ [ a=[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
445 b=<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
446 ]
447 now=~2016.7.18..08.05.15..0b5c
448 eny=0vl.hsfrh.tg642.g5o21.1n80b.0h141.0vuan.pm8o4.77ovg.96rk0.n26nn
449 our=~palnul-wolmev-bonfex-danred--tilwen-midlux-bolfus-nocser
450 ]
451 ~
452 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
454```
456We see a bunch of surfaces: our custom `a` and `b`; standard
457surfaces for identity, date, and entropy; and a ginormous core
458stack with *over eight hundred* total arms.
460To be exact, the syntax `<283.xzp 42.ajz 407.xtr 110.xht 1.ztu
461$151>` denotes a stack of six cores, each of whose payload is
462another core, until the innermost payload `%151` (the Hoon
463version number). This stack is our standard library, from which
464comes `add` and other fine functions. (We don't know how to
465write a Hoon function yet, but we're getting way closer.)
467Let's clean up our subject, just to be hygienic:
469```
470> =a
471> =b
473> +1
474 now=~2016.7.18..08.10.42..36a0
475 eny=0vf.8j71j.hlqim.k340u.q0ual.v2cd8.cfa65.vkbte.e733g.ehihg.e8aog
476[ [ our=~palnul-wolmev-bonfex-danred--tilwen-midlux-bolfus-nocser
477 ]
478 ~
479 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
481```
483Again, remember that `=a` is not Hoon syntax, but `:dojo` syntax.
484How the dojo assembles this subject remains a mystery. But it's
485not a particularly interesting mystery.
487## And we're done
489And we're done! Type `|exit` to exit:
491```
492~palnul_nocser:dojo> |exit
493%drum-exit
495```
497## Questions and/or exercises
499As always, these questions are optional and only for fun.
501What's the best way to construct a core which acts as a function?
502What do you do to call the function?
504Why don't any other languages use subject-oriented programming?
505Which languages are most similar to it?