Previous: layout intro immediate, Up: layout intro [Contents][Index]
They are values represented pointers to a structure that contains a header and a variable–length data block.
The data block is a pointer which can conceptually be one of two types. In case of a string or SRFI-4 object, the data block is simply an opaque “blob” or bytevector. In most other cases, the block is a compound value consisting of other Scheme objects. Typical examples are pairs, vectors and records.
Because these values are heap–allocated, two distinct objects are not stored at the same memory
address, even if they store the same value. That’s why comparing their values is a complex
operation. This operation is either equal?
for deep structural comparison, or eqv?
for value comparisons of numbers and symbols.
The R5RS specification explains that the difference between eq?
and eqv?
is not
necessarily the same across Scheme implementations. For example, in CHICKEN, eq?
can be
used to compare characters and fixnums, because they are stored as immediate values. Portable
programs should not rely on that. If we use eq?
on block objects, their pointers will be
compared: eq?
checks whether they are one and the same object. This can be a useful
operation in its own right.
Objects represented by data blocks also have to be tracked by the garbage collector: if there are still references to the block, its data must be copied (recursively) to keep it alive across garbage collection events.
Here are some “high level” examples of block objects:
-------------------------- | pair 2 slots | #\a | #\b | -------------------------- ------------------------------------------- | vector 5 slots | #f | 123 | 456 | #f | 42 | ------------------------------------------- -------------------------- ----------------------- | string 5 bytes | "hello" | | flonum 8 bytes | 12.5 | -------------------------- ----------------------- ^ ^ | | --------- --------- | | -----------------+----- -----------------+------ | pair 2 slots | O | O-|-->| pair 2 slots | O | () | ----------------------- ------------------------
every block object starts with a header which indicates the type of object and the object’s size. It also determines whether the object’s data block is a byte block or a block containing Scheme objects: if it contains Scheme objects, the header tells us how many slots (locations for storing Scheme objects) the object has. Byte blocks, on the other hand, are opaque and can contain any data. Their size is stored as a byte count.
From top to bottom, left to right, these represent the following values:
(#\a . #\b)
is a pair containing the character a
in its car and b
in its cdr.
#(#f 123 456 #f 42)
is a regular Scheme vector containing fixnums and false values.
"hello"
is a string consisting of 5 characters (strings are treated as byte vectors in
CHICKEN).
12.5
is an inexact representation of the number twelve and a half (a “flonum”). This is a
byte block storing the raw byte value of a C double
.
("hello" . (12.5 . ()))
is the first pair of a proper list which contains a string and a
flonum.
(12.5 . ())
is the cdr of that list; a pair containing a number and the end–of–list marker.
The final two pair objects show that slots (like any C_word
) can hold not only immediate
values, but also pointers to block objects. This leads us to the question: how to differentiate
between a pointer to an object and an immediate object?
Previous: layout intro immediate, Up: layout intro [Contents][Index]