On Hierarchies
Going larger while keeping separate.
We’ve mentioned tethers as one of the four main motifs, as well as the fact that tethers are the supporting structure for building hierarchies. The use of tethers for hierarchies has to do with the fact that tethers are dependent on their “parent” but points away from it, in turn creating something that seems like a knot from the outside.
If we delete “p” from the diagram above, “t” would be deleted as well, as it can’t “survive”. That might mean it gets deleted, but let's consider a less destructive perspective. If it isn’t deleted, we’d be left with a hole in our entity: “t = ? → t”.
We’d have to “pinch” it and turn “t = p → t” into “t = t → t” by being maximally conservative about our choices. This means that an orphaned tether becomes a knot! The same happens to marks as well, while arrows devolve into a mark or tether, depending on the missing endpoint. There’s a manifold of dependency growth and reduction here and it’s quite an interesting tool, especially if we’re viewing weave in a mutable context, where sources and targets can be changed over time.
Back from our detour, let’s now actually assume all dependents are deleted when their “parents” disappear. This gives us an incentive: if we can build using tethers, deleting the top-most parent deletes everything below it. This is great! In a way, we can build things with hierarchical structure and get cleanup for free. However…
Having a tether represent a child in a hierarchy is somewhat limiting: the fact it is a child or extension of something else is a defining trait for it. The identity of the parent is tied into it as well making tethers very similar to unique pointers: uniquely owned and held by some entity. This is only somewhat problematic: if you’re building a binary tree, it’s all good - all your “nodes” in the tree can easily be represented by tethers instead of knots.

Deleting a node high up the tree deletes the whole branch, and that’s good. However, if you want more loose hierarchies, tethers are only a part of the solution…
Before talking about the solution, however, let's look at one more problem because of which tethers are nicer for hierarchies than just, say, arrows with a “Parent” tag on them. Having tagged arrows be part of the meta-structure, informing us that some part of the graph is representing hierarchy instead of, say, transitions within a FSM, feels like lowering structure to data again. We can do it, we know we can, but it seems like having a chance to do something at compile time and then doing it at runtime anyway. Tethers aren’t arrows, they won’t be used for standard graph representation, opening up their use alongside knots (for nodes) arrows (for edges) and marks (for descriptors, eg. labels), as carriers of direct hierarchy.
So, if we have a graph whose bulk is represented using arrows and knots, to even add hierarchy, those knots that are “below” in the hierarchy need to become tethered to something above. If they should have two “parents”, tethers aren’t enough. We could make a single tether from the parent per node and add an arrow from that tether to the node itself, but we’re back to the issue of having “special” arrows. The solution is one step further: we extend a tether from the parent, and create a mark on the child. Both of these are “virtual” from the perspective of the graph, so we're cool! The only problem is that they're disconnected and nodelike on the ends that should meet. We need a way to bridge this, and in this case, an arrow would do the job quite well!
To recap, our parent entity p has a piece of itself extended towards some hierarchical entity c below it. This piece is its tether t. There's a unique relation r between this tether t and a piece of an entity below denoting that it is parented from above — a mark m. I call the tuple (t, r, m) a hoist because we've technically hoisted an arrow q = p → c that says “p parents c” into a layer of abstraction by saying q = t(p) → m(c). You reach out from p to c in a limited way. In other words, the between these two objects isn’t a defining feature of them, just a piece of what they are.

These three might seem excessive, but I’d wager that once it's setup in this way, this is the most general setup for hierarchies and will be sufficient without structural change for any number of further requests and design changes. Traversing a hoist is natural: every bit of it is oriented from the parent to the children, so just consistently moving towards the target of the current entity we’re “on” works in a way similar to the small (single arrow) and big (tether-arrow-mark) moves of a Turing machine. In Turing machines, big moves jump over a whole series of consecutive same symbols while small jump over a single one. In weave, hoists jump over levels of hierarchy while arrows traverse within a level. I'm pretty sure it’s a pointless simile in construction, but I can’t get over the fact Turing machines are in fact fully linear machines for which we need to plan and map out all the structures and moves in our ideaspace.
One of the most important long-term results of weave is to reduce ideaspace capacity, to create an environment in which one can almost geometrically construct ideas without the need to imagine all the scaffolding. Hoisting is an example where things seem to be much more complicated than they “need” to be — if a programmer was to mark a parent, they could just call the field or variable parent and have it all work by evening. What it does, how it relates to other things, etc. are important to hold in one’s head as one works, and then to hold in runtime memory as the program happens. In-between is what currently makes a programmer good in practice: if there’s a problem, how fast can it be solved and how much will the research take beforehand. Both of these are direct consequences of “how well is the problem mapped out in the programmer’s ideaspace?”. If we can even attempt to externalize that notion, we have a chance at lowering its upper bound, and ultimately, that upper bound is, in my mind, the source of most our problems.




