Guile’s structures have a facility whereby each instance of a vtable can contain a variable-length tail array of values. The length of the tail array is stored in the structure. This facility was originally intended to allow C code to expose raw C structures with word-sized tail arrays to Scheme.
However, the tail array facility is confusing and doesn’t work very
well. It is very rarely used, but it insinuates itself into all
make-struct. For this reason the clumsily-named
make-struct/no-tail procedure can actually be more elegant in
actual use, because it doesn’t have a random
0 argument stuck in
Tail arrays also inhibit optimization by allowing instances to affect their shapes. In the absence of tail arrays, all instances of a given vtable have the same number and kinds of fields. This uniformity can be exploited by the runtime and the optimizer. The presence of tail arrays make some of these optimizations more difficult.
Finally, the tail array facility is ad-hoc and does not compose with the rest of Guile. If a Guile user wants an array with user-specified length, it’s best to use a vector. It is more clear in the code, and the standard optimization techniques will do a good job with it.
That said, we should mention some details about the interface. A vtable
that has tail array has upper-case permission descriptors:
O, correspoding to tail arrays of writable,
read-only, or opaque elements. A tail array permission descriptor may
only appear in the last element of a vtable layout.
For exampple, ‘pW’ indicates a tail of writable Scheme-valued fields. The ‘pW’ field itself holds the tail size, and the tail fields come after it.
(define v (make-vtable "prpW")) ;; one fixed then a tail array (define s (make-struct v 6 "fixed field" 'x 'y)) (struct-ref s 0) ⇒ "fixed field" (struct-ref s 1) ⇒ 2 ;; tail size (struct-ref s 2) ⇒ x ;; tail array ... (struct-ref s 3) ⇒ y (struct-ref s 4) ⇒ #f