#### 3.3Hypertees: The Shape of a Hypersnippet of Text

 (require punctaffy/hypersnippet/hypertee) package: punctaffy-lib

##### 3.3.1Hypertee Coils

 syntax
 syntax
 match expander
 procedure v : any/c
Struct-like operations which construct and deconstruct a hypertee-coil/c value that represents one layer of recursion in a hypertee of degree 0 (in the sense of dim-sys-dim-zero).

Every two hypertee-coil-zero values are equal?.

 syntax
 syntax(hypertee-coil-hole overall-degree hole data tails)
 match expander(hypertee-coil-hole overall-degree hole data tails)
 procedure v : any/c
 procedure coil : hypertee-coil-hole?
 procedure(hypertee-coil-hole-hole coil) → any/c coil : hypertee-coil-hole?
 procedure(hypertee-coil-hole-data coil) → any/c coil : hypertee-coil-hole?
 procedure coil : hypertee-coil-hole?
Struct-like operations which construct and deconstruct a hypertee-coil/c value that represents one layer of recursion in a hypertee that would start with a hole in its bracket representation. Every hypertee of nonzero degree (in the sense of dim-sys-dim-zero) has at least one hole, and there’s nothing it can begin with other than a hole, so this is the most common case.

This has four parts: The overall-degree is the degree of the hypertee, the hole is the shape of the hole (carrying trivial? data in its own holes), the data is the data value carried in the hole, and the tails is a hypertee of the same shape as hole, but where the data values are hypertees representing the rest of the structure. The tail hypertee carried in a hole of degree N is expected to have trivial? data in its holes of degree less than N. Its holes of degree not less than N can carry any data; they represent additional holes in the overall hypertee.

Note that the hole is basically redundant here; it’s just the same as tails but with the data values trivialized. Most of our traversal operations make use of values of this form, and some of the places we would construct a typertee already have values of this form readily available, so we save ourselves some redundant computation by keeping it separate. (TODO: Offer an alternative way to create a hypertee-coil-hole without specifying its hole shape.)

On the other hand, we save ourselves some verbosity and some repetitive contract-checking by leaving out the dimension system. If we stored a dimension system alongside the rest of the fields in a hypertee-coil-hole, we could enforce far more precise contracts on the field values, but instead we allow any value to be stored in any of the fields and rely on hypertee-coil/c in the contract of any operation that needs to enforce the structure. (TODO: Reconsider this choice. In most places, we pass a coil to something that associates it with a dimension system as soon as we create it, so we’re effectively passing in the dimension system at the same time anyway. But for the sake of people doing a lot of computation at the coil level, perhaps enforcing contracts is too costly. We’ll probably need more practical experience before we understand the tradeoffs.)

A hypertee based on this kind of coil is essentially created from a snippet-sys-snippet-done in the shape of the hole, concatenated with the tail hypertees using snippet-sys-snippet-join. Considering this, it might be tempting to work with hypertees using only the generic snippet system operations, but even though that interface supplies a way to put together this kind of hypertee, it doesn’t supply a way to take it apart again to work with its details. Pattern-matching on the coils allows the details to be traversed.

Two hypertee-coil-hole values are equal? if they contain equal? elements.

 procedure ds : dim-sys?
Returns a flat contract that recognizes a well-formed hypertee coil for the given dimension system. For a value to be suitable, it must either be a hypertee-coil-zero? value or be a hypertee-coil-hole? value which abides by stricter expectations.

Namely: The overall degree (hypertee-coil-hole-overall-degree) must be a nonzero dimension number in the given dimension system. The hole shape must be a hypertee (of any degree) with the given dimension system and with trivial? values in its holes. The tails hypertee must be a hypertee similar to the hole shape, but with hypertees (the tails) in its holes. If a tail appears in a hole of degree N, each of its own holes of degree lower than N must have a trivial? value in it, and those holes must be in the same arrangement as the hole’s holes.

##### 3.3.2Hypertee Brackets

 syntax
 syntax(htb-labeled degree data)
 match expander(htb-labeled degree data)
 procedure v : any/c
 procedure b : htb-labeled?
 procedure b : htb-labeled?
Struct-like operations which construct and deconstruct a hypertee-bracket? value that represents one of the brackets of a hole in a hypertee, and in particular the bracket that appears first in the hypertee’s bracket representation.

The given degree is the degree of the hole, and the given data is the data value to be carried in the hole.

The data has to be placed somewhere among the hole’s brackets, and we place it at the first bracket as a stylistic choice for readability: This way, the placement of data values is comparable to the placement of section headings in a document or prefix operators in a Racket program.

Two htb-labeled values are equal? if they contain equal? elements.

 syntax
 syntax(htb-unlabeled degree)
 match expander(htb-unlabeled degree)
 procedure v : any/c
 procedure b : htb-unlabeled?
Struct-like operations which construct and deconstruct a hypertee-bracket? value that represents any non-first bracket of a hole in a hypertee, as it appears in the hypertee’s bracket representation.

The given degree is the degree of the hole that’s being initiated by this bracket. Even though this bracket isn’t the first bracket of a hole of the hypertee, it’s still the first bracket of some hole. It could be the first bracket of a hole of a hole of the hypertee; the first bracket of a hole of a hole of a hole of the hypertee; etc.

Two htb-unlabeled values are equal? if they contain equal? elements.

 procedure v : any/c
Returns whether the given value is a hypertee bracket. That is, it checks that the value is either an htb-labeled? value or an htb-unlabeled? value.

 procedure(hypertee-bracket/c dim/c) → contract? dim/c : contract?
Returns a contract that recognizes a hypertee-bracket? value where the degree abides by the given contract.

The resulting contract has the same contract obstinacy as the given one.

##### 3.3.3Hypertee Constructors and Operations

 procedure v : any/c
Returns whether the given value is a hypertee. A hypertee is a specific data structure representing hypersnippets of a content-free stream. While a hypertee does not have content, it does still have a multidimensional boundary. Hypertees tend to arise as the description of the shape of another kind of hypersnippet.

 procedure ht : hypertee?
Returns the dimension system the given hypertee’s degrees abide by.

 syntax

syntax

(hypertee-furl dim-sys coil)

 dim-sys : dim-sys?
 coil : (hypertee-coil/c dim-sys)
 match expander(hypertee-furl dim-sys coil)
Constructs or deconstructs a hypertee value, regarding it as being made up of a dimension system and a hypertee-coil/c value.

Two hypertees are equal? if they contain equal? elements when seen this way. Note that this isn’t the only way to understand their representation; they can also be seen as being constructed by hypertee-from-brackets.

 procedure → (hypertee-coil/c (hypertee-get-dim-sys ht)) ht : hypertee?
Given a hypertee, computes the hypertee-coil/c value that would need to be passed to hypertee-furl to construct it.

 procedure(hypertee-from-brackets ds degree brackets) → (hypertee/c ds) ds : dim-sys? degree : (dim-sys-dim/c ds) brackets : (listof (hypertee-bracket/c (dim-sys-dim/c ds)))
Constructs a hypertee value, regarding it as being made up of a dimension system, a degree, and a properly nested sequence of hypertee-bracket? values.

If the brackets aren’t properly nested, the exn:fail:contract exception is raised.

Proper nesting of hypertee brackets is a rather intricate matter which is probably easiest to approach by thinking of it as a series of hyperstack pop operations. The hyperstack starts out with a dimension of degree and data of #t at every dimension, and each bracket in the list performs a hyperstack-pop with data of #f. (A hyperstack-pop in some sense simultaneously "pushes" that data value onto every lower dimension. See the hyperstack documentation for more information.) If the pop reveals the data #t, the bracket should have been htb-labeled?; otherwise, it should have been htb-unlabeled?. Once we reach the end of the list, the hyperstack should have a dimension of 0 (in the sense of dim-sys-dim-zero).

Two hypertees are equal? if they’re constructed with equal? elements this way. Note that this isn’t the only way to understand their representation; they can also be seen as being constructed by hypertee-furl.

(TODO: Write some examples.)

procedure

(ht-bracs ds degree bracket ...)  (hypertee/c ds)

ds : dim-sys?
degree : (dim-sys-dim/c ds)
bracket :
 (let ([dim/c (dim-sys-dim/c ds)]) (or/c (hypertee-bracket/c dim/c) dim/c))
Constructs a hypertee value, regarding it as being made up of a dimension system, a degree, and a properly nested sequence of hypertee-bracket? values (some of which may be expressed as raw dimension numbers, which are understood as being implicitly wrapped in htb-unlabeled).

If the brackets aren’t properly nested, the exn:fail:contract exception is raised.

Rarely, some dimension system might represent its dimension numbers as hypertee-bracket? values. If that’s the case, then those values must be explicitly wrapped in htb-unlabeled. Otherwise, this will understand them as brackets instead of as dimension numbers.

This is simply a more concise alternative to hypertee-from-brackets. See that documentation for more information about what it takes for hypertee brackets to be "properly nested."

(TODO: Write some examples.)

 procedure → (listof (hypertee-bracket/c (dim-sys-dim/c ds))) ht : hypertee?
Given a hypertee, computes the list of hypertee-bracket? values that would need to be passed to hypertee-from-brackets to construct it.

 procedure ds : dim-sys?
Returns a contract that recognizes a hypertee? value where the dimension system is an ok/c match for the given one.

 syntax

syntax

(hypertee-snippet-sys dim-sys)

 dim-sys : dim-sys?
 match expander(hypertee-snippet-sys dim-sys)
 procedure v : any/c
 procedure ss : hypertee-snippet-sys?
Struct-like operations which construct and deconstruct a snippet system (snippet-sys?) where the dimension numbers are those of the given dimension system and the hypersnippet shapes and hypersnippets are hypertees which use that dimension system.

The resulting snippet system’s operations have behavior which corresponds to the sense in which we’ve described hypertees as being higher-dimensional snippets snipped out of content-free streams. Consider the snippet-sys-snippet-splice and snippet-sys-snippet-zip-map-selective operations, which iterate over all the holes of a hypersnippet. In the case of a hypertee, they iterate over each of the hypertee-coil-hole/htb-labeled nodes exactly once (notwithstanding early exits and the skipping of unselected? data values), so indeed each of these nodes legitimately represents one of the hypertee’s holes. We’ve chosen to directly describe operations like hypertee-coil-hole in terms of hypersnippet holes, largely because the very purpose of hypertees is tied to the functionality they have as hypersnippets. Because of this, "hypertee-coil-hole nodes really do correspond to holes" may sound tautological, but in fact the behavior of this snippet system is the reason we’ve been able to describe those nodes in terms of holes in the first place.

(TODO: This isn’t really a complete specification of the behavior. A complete specification might get very exhaustive or technical, but let’s see if we can at least improve this description over time. Perhaps we should go through and hedge some of the ways we describe hypertees so that they specifically appeal to hypertee-snippet-sys as the basis for their use of terms like "hypersnippet," "degree," and "hole.")

Two hypertee-snippet-sys values are equal? if they contain equal? elements. One such value is an ok/c match for another if the first’s element is ok/c for the second’s.

 syntax
 syntax
 match expander
 procedure v : any/c
Struct-like operations which construct and deconstruct a snippet format system (snippet-format-sys?) where, given any particular dimension system, the hypersnippet shapes and hypersnippets are hypertees which use that dimension system.

The shapes and snippets are related according to the same behavior as hypertee-snippet-sys. In some sense, this is a generalization of hypertee-snippet-sys which puts the choice of dimension system in the user’s hands. Instead of merely generalizing by being more late-bound, this also generalizes by having slightly more functionality: The combination of functor-from-dim-sys-sys-apply-to-morphism with snippet-format-sys-functor allows for transforming just the degrees of a hypertee while leaving the rest of the structure alone.

Every two hypertee-snippet-format-sys values are equal?. One such value is always an ok/c match for another.

 procedure ht : (and/c hypertee? (hypertee/c (hypertee-get-dim-sys ht)))
Given a hypertee, returns a maybe? value containing the value associated with its hole of degree 0, if such a hole exists.

(TODO: Not all snippet systems necessarily support an operation like this, but all the ones we’ve defined so far do. It may turn out that we’ll want to add this to the snippet system interface.)