on 005ec77 help sign in
504 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`.
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```
173The fragment retains the type it had when we built it.
175Another (equivalent) way to think of tree addressing involves
176binary. As before, the root of the tree is at address `1`. For
177the node of a tree at some address `b`, where `b` is binary,
178you get the address of the head by concatenating a `0` to
179the end of `b`; and to get the tail, concatenate a `1` at the
180end. For example, the head of the node at binary address `111`
181is at `1110`, and the tail is at `1111`.
183## Labeled surfaces
185We can obviously get anything we want out of the subject by tree
186geometry. But that's not really how we'd like to program. We'd
187much rather *label* subtrees with convenient, memorable symbols.
189For example, suppose our tree looked like:
191```
192 1
193 / \
194 x=2 3
195 / \
196 y=6 z=7
197 / \
198 p=14 15
199 / \
200 q=30 r=31
201```
203Then instead of writing `+2`, we could write `x`, and so on.
205Let's replace our test subject `a` with a new noun built around
206this tree of *labeled surfaces*.
208```
209> =a [x=42 y=[p=%foo q=.6.28 r=~m45] z=0xdead.beef]
211> ? x:a
212 @ud
21342
215> ? y:a
216 {p/$foo q/@rs r/@dr}
217[p=%foo q=.6.28 r=~m45]
219> ? q.y:a
220 @rs
221.6.28
222```
224Surfaces might remind you of attributes in an object. But again,
225attributes in an object are a symbol table. There is no symbol
226table here -- just a tree search.
228An expression like the label `x` or the axis `+2`, which
229designates a fragment or feature of the subject, is called a
230*limb*. A list of limbs connected with `.` is a *wing*.
232To remind you that you're not in Kansas anymore, the syntax for a
233wing, like `q.y` above, means means "q inside y." In a classic
234object-oriented system, of course, this would be written `y.q`,
235that is, attribute `q` within object `y`. In Hoon, `q.y` means
236"find limb `y`, then find limb `q` inside that."
238## Surfaces versus fragments
240Once again, Hoon has no symbol tables. When we put a surface
241on a noun, the surface label is part of that noun's type. It's
242not part of the cell or other structure that contains the noun.
243This will take a little getting used to:
245```
246> ? x:a
247 @ud
24842
250> ? +2:a
251 x/@ud
252x=42
254? x.+2:a
255 @ud
25642
257```
259When we take fragment 2 of the labeled subject, the *surface
260comes with it*. `+2` is not `42` but rather `x=42`. We can
261take the surface off with `x.+2`.
263## The search algorithm
265In resolving a label to a fragment axis, we search the subject
266type in a depth-first traverse.
268If we find a surface that matches the limb, we succeed. If we
269find a surface that doesn't match the limb, we fail. If we find
270a cell, we search first head, then tail.
272## Skipping
274What if the same label appears twice in one noun? Let's modify
275our subject slightly as a test case:
277```
278> ? +7:a
279 z/@ux
280z=0xdead.beef
282> =a a(+7 x=z:a)
284> ? a
285 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
286[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
288> ? x:a
289 @ud
29042
292> ? ^x:a
293 @ux
2940xdead.beef
295```
297We don't want to hide any part of the noun from an expression.
298So the modified limb `^x` *skips* the first match with a surface
299`x`, getting us to our `0xdead.beef`. This is a unary notation:
300`^^x` would skip the first two matches.
302## Editing
304Above, we mutated our first noun with the flashy `a(+7 x=z:a)`.
306Of course we are not really "modifying" a noun. Hoon is a pure
307language. We are making an edited copy. `a(+7 x=z:a)` means "a
308copy of `a`, with limb `+7` replaced by the product of `x=z:a`."
310We can edit multiple (disjoint) wings in one expression:
312```
313> ? a(+7 [%hello %world], q.y .3.14)
314 {x/@ud y/{p/$foo q/@rs r/@dr} $hello $world}
315[x=42 y=[p=%foo q=.3.14 r=~m45] %hello %world]
316```
318Notice that nothing stopped us from changing `+7` from
319`x=0xdead.beef` to `[%hello %world]`. Since the mutated
320copy is a different noun, it has a different type.
322(And remember that since `[x y z]` means `[x [y z]]`,
323`[x y [%hello %world]]` means `[x y %hello %world]`.)
325## Cores and arms
327It should be reasonably clear how Hoon's system of fragments and
328surfaces parallels variables, records or structures in a
329classical language. But where is Hoon's equivalent of objects:
330values which bind code to data?
332The Hoon equivalent of an object is a *core*. As usual in Hoon,
333the resemblance is inexact. A core has a set of computed
334attributes, or *arms*. Each arm is an expression whose subject
335is the core. There is no argument, so an arm is not a method.
337Physically, a core is always a cell `[battery payload]`, where
338the *payload* is any noun, and the *battery* is a tree of
339formulas in Nock (Hoon's functional assembly language) that
340implements the arms. (A battery is like a C++ vtable, sort of.)
342## The search algorithm
344As you'd expect with a computed attribute, there is only one
345namespace and one search algorithm. We just extend the algorithm
346described above. And an expression which uses a label can't know
347whether the subject will resolve it to a surface fragment (a
348*leg*) or to an arm.
350If we're searching a core and the label matches one of the core's
351arms, we compute the arm against the core. If the label is not
352found, we search into the payload of the core.
354## Some core examples
356When you type these examples, make sure you get the number of
357spaces exactly right. Hoon syntax is not whitespace-sensitive
358in general, except that "one space" is always a different token
359from "two or more spaces."
361```
362> ? x:a
363 @ud
36442
366> ? => a x
367 @ud
36842
370> =b => a |% ++ foo x ++ bar [q.y foo] --
371```
373We're seeing some Hoon regular forms for the first time. `x:a`
374turns out to be an irregular relative of the regular `=>`
375(["tisgar"](../../hoon/rune/tis/gar)) form.
377We'll get more into syntax in a later Urbyte. If some of these
378examples seem syntactically a little funky, this isn't usually
379way we'd do them in "real life." We don't normally write cores
380on a single command line. In a file this would be:
382```
383 => a
384 |%
385 ++ foo x
386 ++ bar [q.y foo]
387 --
388```
390which is much more readable, at least once you get used to it.
391Let's look at the core itself:
393```
394> b
395<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
397> ? +2:b
398 *
399[[0 6] [0 58] 9 4 0 1]
401> ? +3:b
402 {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}
403[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
404```
406When we print `b`, or any core, we see that typed noun printing
407can't be an invertible function in Hoon.
409We actually can read the battery (with `+2:b` above), but it's
410just Nock code, not typed data. `<2.spy>` tells us the battery
411has two arms and hashes to the three-letter code `spy`.
413When printing a full core, we don't even print the payload data,
414just its type. But our `+3:b` confirms the `[battery payload]`
415structure of the core. Remember, `+2` is the head and `+3` is
416the tail.
418Finally, let's use this thing:
420```
421> ? foo:b
422 @ud
42342
425> ? bar:b
426 {@rs @ud}
427[.6.28 42]
429> ? x:b
430 @ud
43142
432```
434Seems legit.
436## The dojo subject
438Now that we've made a test subject which is a core, we can look
439directly at the real dojo subject:
441```
442> +1
443[ [ [ a=[x=42 y=[p=%foo q=.6.28 r=~m45] x=0xdead.beef]
444 b=<2.spy {x/@ud y/{p/$foo q/@rs r/@dr} x/@ux}>
445 ]
446 now=~2016.7.18..08.05.15..0b5c
447 eny=0vl.hsfrh.tg642.g5o21.1n80b.0h141.0vuan.pm8o4.77ovg.96rk0.n26nn
448 our=~palnul-wolmev-bonfex-danred--tilwen-midlux-bolfus-nocser
449 ]
450 ~
451 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
453```
455We see a bunch of surfaces: our custom `a` and `b`; standard
456surfaces for identity, date, and entropy; and a ginormous core
457stack with *over eight hundred* total arms.
459To be exact, the syntax `<283.xzp 42.ajz 407.xtr 110.xht 1.ztu
460$151>` denotes a stack of six cores, each of whose payload is
461another core, until the innermost payload `%151` (the Hoon
462version number). This stack is our standard library, from which
463comes `add` and other fine functions. (We don't know how to
464write a Hoon function yet, but we're getting way closer.)
466Let's clean up our subject, just to be hygienic:
468```
469> =a
470> =b
472> +1
473 now=~2016.7.18..08.10.42..36a0
474 eny=0vf.8j71j.hlqim.k340u.q0ual.v2cd8.cfa65.vkbte.e733g.ehihg.e8aog
475[ [ our=~palnul-wolmev-bonfex-danred--tilwen-midlux-bolfus-nocser
476 ]
477 ~
478 <283.xzp 42.ajz 407.xtr 110.xht 1.ztu $151>
480```
482Again, remember that `=a` is not Hoon syntax, but `:dojo` syntax.
483How the dojo assembles this subject remains a mystery. But it's
484not a particularly interesting mystery.
486## And we're done
488And we're done! Type `|exit` to exit:
490```
491~palnul_nocser:dojo> |exit
492%drum-exit
494```
496## Questions and/or exercises
498As always, these questions are optional and only for fun.
500What's the best way to construct a core which acts as a function?
501What do you do to call the function?
503Why don't any other languages use subject-oriented programming?
504Which languages are most similar to it?