Previous: Structure Basics, Up: Structures
Vtables are structures that are used to represent structure types. Each
vtable contains a layout specification in field
vtable-index-layout
– instances of the type are laid out
according to that specification. Vtables contain additional fields
which are used only internally to libguile. The variable
vtable-offset-user
is bound to a field number. Vtable fields
at that position or greater are user definable.
Return the vtable structure that describes the type of struct.
Return
#t
iff x is a vtable structure.
If you have a vtable structure, V
, you can create an instance of
the type it describes by using (make-struct V ...)
. But where
does V
itself come from? One possibility is that V
is an
instance of a user-defined vtable type, V'
, so that V
is
created by using (make-struct V' ...)
. Another possibility is
that V
is an instance of the type it itself describes. Vtable
structures of the second sort are created by this procedure:
Return a new, self-describing vtable structure.
user-fields is a string describing user defined fields of the vtable beginning at index
vtable-offset-user
(seemake-struct-layout
).tail-size specifies the size of the tail-array (if any) of this vtable.
init1, ... are the optional initializers for the fields of the vtable.
Vtables have one initializable system field—the struct printer. This field comes before the user fields in the initializers passed to
make-vtable-vtable
andmake-struct
, and thus works as a third optional argument tomake-vtable-vtable
and a fourth tomake-struct
when creating vtables:If the value is a procedure, it will be called instead of the standard printer whenever a struct described by this vtable is printed. The procedure will be called with arguments STRUCT and PORT.
The structure of a struct is described by a vtable, so the vtable is in essence the type of the struct. The vtable is itself a struct with a vtable. This could go on forever if it weren't for the vtable-vtables which are self-describing vtables, and thus terminate the chain.
There are several potential ways of using structs, but the standard one is to use three kinds of structs, together building up a type sub-system: one vtable-vtable working as the root and one or several "types", each with a set of "instances". (The vtable-vtable should be compared to the class <class> which is the class of itself.)
(define ball-root (make-vtable-vtable "pr" 0)) (define (make-ball-type ball-color) (make-struct ball-root 0 (make-struct-layout "pw") (lambda (ball port) (format port "#<a ~A ball owned by ~A>" (color ball) (owner ball))) ball-color)) (define (color ball) (struct-ref (struct-vtable ball) vtable-offset-user)) (define (owner ball) (struct-ref ball 0)) (define red (make-ball-type 'red)) (define green (make-ball-type 'green)) (define (make-ball type owner) (make-struct type 0 owner)) (define ball (make-ball green 'Nisse)) ball => #<a green ball owned by Nisse>
Return the name of the vtable vtable.