A vtable is a structure type, specifying its layout, and other information. A vtable is actually itself a structure, but there’s no need to worry about that initially (see Vtable Contents.)

Scheme Procedure: make-vtable fields [print]

Create a new vtable.

fields is a string describing the fields in the structures to be created. Each field is represented by two characters, a type letter and a permissions letter, for example "pw". The types are as follows.

  • p – a Scheme value. “p” stands for “protected” meaning it’s protected against garbage collection.
  • u – an arbitrary word of data (an scm_t_bits). At the Scheme level it’s read and written as an unsigned integer. “u” stands for “unboxed”, as it’s stored as a raw value without additional type annotations.

It used to be that the second letter for each field was a permission code, such as w for writable or r for read-only. However over time structs have become more of a raw low-level facility; access control is better implemented as a layer on top. After all, struct-set! is a cross-cutting operator that can bypass abstractions made by higher-level record facilities; it’s not generally safe (in the sense of abstraction-preserving) to expose struct-set! to “untrusted” code, even if the fields happen to be writable. Additionally, permission checks added overhead to every structure access in a way that couldn’t be optimized out, hampering the ability of structs to act as a low-level building block. For all of these reasons, all fields in Guile structs are now writable; attempting to make a read-only field will now issue a deprecation warning, and the field will be writable regardless.

(make-vtable "pw")      ;; one scheme field
(make-vtable "pwuwuw")  ;; one scheme and two unboxed fields

The optional print argument is a function called by display and write (etc) to give a printed representation of a structure created from this vtable. It’s called (print struct port) and should look at struct and write to port. The default print merely gives a form like ‘#<struct ADDR:ADDR>’ with a pair of machine addresses.

The following print function for example shows the two fields of its structure.

(make-vtable "pwpw"
             (lambda (struct port)
               (format port "#<~a and ~a>"
                       (struct-ref struct 0)
                       (struct-ref struct 1))))