This chapter contains information about procedures which are not cleanly tied to a specific data type. Because of their wide range of applications, they are collected in a utility chapter.
Three different kinds of sameness are defined in Scheme.
The differentiation between these three kinds is important, because determining whether two values are the same objects is very efficient, while determining structural equivalence can be quite expensive (consider comparing two very long lists). Therefore, three different procedures for testing for equality are provided, which correspond to the three kinds of sameness defined above.
#tiff x references the same object as y.
eq?is similar to
eqv?except that in some cases it is capable of discerning distinctions finer than those detectable by
eqv?procedure defines a useful equivalence relation on objects. Briefly, it returns
#tif x and y should normally be regarded as the same object. This relation is left slightly open to interpretation, but works for comparing immediate integers, characters, and inexact numbers.
#tiff x and y are recursively
equal?recursively compares the contents of pairs, vectors, and strings, applying
eqv?on other objects such as numbers and symbols. A rule of thumb is that objects are generally
equal?if they print the same.
equal?may fail to terminate if its arguments are circular data structures.
It's often useful to associate a piece of additional information with a Scheme object even though that object does not have a dedicated slot available in which the additional information could be stored. Object properties allow you to do just that.
An object property is most commonly used to associate one kind of
additional information with each instance of a class of similar Scheme
objects. For example, all procedures have a `name' property, which
stores the name of the variable in which the procedure was stored by a
define expression, or
#f if the procedure wasn't created
by that kind of expression.
Guile's representation of an object property is a procedure-with-setter
(see section Procedures with Setters) that can be used with the generalized
set! (REFFIXME) to set and retrieve that property for any
Scheme object. So, setting a property looks like this:
(set! (my-property obj1) value-for-obj1) (set! (my-property obj2) value-for-obj2)
And retrieving values of the same property looks like this:
(my-property obj1) => value-for-obj1 (my-property obj2) => value-for-obj2
To create an object property in the first place, use the
(define my-property (make-object-property))
(set! (property obj) val)sets obj's property to val.
(property obj)returns the current setting of obj's property.
A single object property created by
associate distinct property values with all Scheme values that are
eq? (including, for example, integers).
Internally, object properties are implemented using a weak key hash table. This means that, as long as a Scheme value with property values is protected from garbage collection, its property values are also protected. When the Scheme value is collected, its entry in the property table is removed and so the (ex-) property values are no longer protected by the table.
primitive-property-reffor the significance of not_found_proc.
primitive-make-property) and use its return value. That value is also associated with obj via
primitive-property-set!. When not-found-proc is
#fas the default value of prop.
Traditionally, Lisp systems provide a different object property
interface to that provided by
make-object-property, in which the
object property that is being set or retrieved is indicated by a symbol.
Guile includes this older kind of interface as well, but it may well be
removed in a future release, as it is less powerful than
make-object-property and so increases the size of the Guile
library for no benefit. (And it is trivial to write a compatibility
layer in Scheme.)
Sorting is very important in computer programs. Therefore, Guile comes
with several sorting procedures built-in. As always, procedures with
names ending in
! are side-effecting, that means that they may
modify their parameters in order to produce their results.
The first group of procedures can be used to merge two lists (which must be already sorted on their own) and produce sorted lists containing all elements of the input lists.
(sorted? alist less?)and
(sorted? blist less?), return a new list in which the elements of alist and blist have been stably interleaved so that
(sorted? (merge alist blist less?) less?). Note: this does _not_ accept vectors.
(sorted? alist less?)and
(sorted? blist less?)and returns a new list in which the elements of alist and blist have been stably interleaved so that
(sorted? (merge alist blist less?) less?). This is the destructive variant of
mergeNote: this does _not_ accept vectors.
The following procedures can operate on sequences which are either
vectors or list. According to the given arguments, they return sorted
vectors or lists, respectively. The first of the following procedures
determines whether a sequence is already sorted, the other sort a given
sequence. The variants with names starting with
special in that they maintain a special property of the input sequences:
If two or more elements are the same according to the comparison
predicate, they are left in the same order as they appeared in the
#tiff items is a list or a vector such that for all 1 <= i <= m, the predicate less returns true when applied to all elements i - 1 and i
The procedures in the last group only accept lists or vectors as input, as their names indicate.
The procedures for copying lists (see section Lists) only produce a flat
copy of the input list, and currently Guile does not even contain
procedures for copying vectors.
copy-tree can be used for these
application, as it does not only copy the spine of a list, but also
copies any pairs in the cars of the input lists.
copy-treerecurses down the contents of both pairs and vectors (since both cons cells and vector cells may point to arbitrary objects), and stops recursing when it hits any other object.
When debugging Scheme programs, but also for providing a human-friendly interface, a procedure for converting any Scheme object into string format is very useful. Conversion from/to strings can of course be done with specialized procedures when the data type of the object to convert is known, but with this procedure, it is often more comfortable.
object->string converts an object by using a print procedure for
writing to a string port, and then returning the resulting string.
Converting an object back from the string is only possible if the object
type has a read syntax and the read syntax is preserved by the printing
A hook is a list of procedures to be called at well defined points in time. Typically, an application provides a hook h and promises its users that it will call all of the procedures in h at a defined point in the application's processing. By adding its own procedure to h, an application user can tap into or even influence the progress of the application.
Guile itself provides several such hooks for debugging and customization purposes: these are listed in a subsection below.
When an application first creates a hook, it needs to know how many arguments will be passed to the hook's procedures when the hook is run. The chosen number of arguments (which may be none) is declared when the hook is created, and all the procedures that are added to that hook must be capable of accepting that number of arguments.
A hook is created using
make-hook. A procedure can be added to
or removed from a hook using
and all of a hook's procedures can be removed together using
reset-hook!. When an application wants to run a hook, it does so
Hook usage is shown by some examples in this section. First, we will define a hook of arity 2 -- that is, the procedures stored in the hook will have to accept two arguments.
(define hook (make-hook 2)) hook => #<hook 2 40286c90>
Now we are ready to add some procedures to the newly created hook with
add-hook!. In the following example, two procedures are added,
which print different messages and do different things with their
(add-hook! hook (lambda (x y) (display "Foo: ") (display (+ x y)) (newline))) (add-hook! hook (lambda (x y) (display "Bar: ") (display (* x y)) (newline)))
Once the procedures have been added, we can invoke the hook using
(run-hook hook 3 4) -| Bar: 12 -| Foo: 7
Note that the procedures are called in the reverse of the order with
which they were added. This is because the default behaviour of
add-hook! is to add its procedure to the front of the
hook's procedure list. You can force
add-hook! to add its
procedure to the end of the list instead by providing a third
#t argument on the second call to
(add-hook! hook (lambda (x y) (display "Foo: ") (display (+ x y)) (newline))) (add-hook! hook (lambda (x y) (display "Bar: ") (display (* x y)) (newline)) #t) ; <- Change here! (run-hook hook 3 4) -| Foo: 7 -| Bar: 12
When you create a hook with
make-hook, you must specify the arity
of the procedures which can be added to the hook. If the arity is not
given explicitly as an argument to
make-hook, it defaults to
zero. All procedures of a given hook must have the same arity, and when
the procedures are invoked using
run-hook, the number of
arguments passed must match the arity specified at hook creation time.
The order in which procedures are added to a hook matters. If the third
add-hook! is omitted or is equal to
procedure is added in front of the procedures which might already be on
that hook, otherwise the procedure is added at the end. The procedures
are always called from the front to the end of the list when they are
The ordering of the list of procedures returned by
matches the order in which those procedures would be called if the hook
was run using
#tif x is a hook,
#tif hook is an empty hook,
If, in C code, you are certain that you have a hook object and well
formed argument list for that hook, you can also use
scm_c_run_hook, which is identical to
does no type checking.
scm_run_hookbut without any type checking to confirm that hook is actually a hook object and that args is a well-formed list matching the arity of the hook.
The hooks already described are intended to be populated by Scheme-level procedures. In addition to this, the Guile library provides an independent set of interfaces for the creation and manipulation of hooks that are designed to be populated by functions implemented in C.
The original motivation here was to provide a kind of hook that could safely be invoked at various points during garbage collection. Scheme-level hooks are unsuitable for this purpose as running them could itself require memory allocation, which would then invoke garbage collection recursively ... However, it is also the case that these hooks are easier to work with than the Scheme-level ones if you only want to register C functions with them. So if that is mainly what your code needs to do, you may prefer to use this interface.
To create a C hook, you should allocate storage for a structure of type
scm_t_c_hook and then initialize it using
scm_t_c_hook_typeenumeration, and controls how the hook functions will be called. hook_data is a closure parameter that will be passed to all registered hook functions when they are called.
To add or remove a C function from a C hook, use
scm_c_hook_remove. A hook function must expect three
void * parameters which are, respectively:
scm_c_hook_runcall that runs the hook.
void *parameters and returns a
scm_c_hook_removechecks both func and func_data so as to allow for the same func being registered multiple times with different closure data.
Finally, to invoke a C hook, call the
specifying the hook and the call closure data for this run:
scm_c_hook_runcalls hook's registered functions in turn, passing them the hook's closure data, each function's closure data, and the call closure data.
scm_c_hook_run's return value is the return value of the last
function to be called.
Whenever Guile performs a garbage collection, it calls the following hooks in the order shown.
scm_gc_running_pto 1, but before entering the GC critical section.
If garbage collection is blocked because
non-zero, GC exits early soon after calling this hook, and no further
hooks will be called.
All the C hooks listed here have type
initialized with hook closure data NULL, are are invoked by
scm_c_hook_run with call closure data NULL.
The Scheme hook
after-gc-hook is particularly useful in
conjunction with guardians (see section Guardians). Typically, if you are
using a guardian, you want to call the guardian after garbage collection
to see if any of the objects added to the guardian have been collected.
By adding a thunk that performs this call to
can ensure that your guardian is tested after every garbage collection
Go to the first, previous, next, last section, table of contents.