General Utility Functions
*************************

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.

Equality
========

Three different kinds of sameness are defined in Scheme.

  * Two values can refer to exactly the same object.

  * Two objects can have the same value.

  * Two objects can be structurally equivalent.

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.

 -- Scheme Procedure: eq? x y
     Return #t iff 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?.

 -- Scheme Procedure: eqv? x y
     The eqv? procedure defines a useful equivalence relation on objects. Briefly, it returns #t if 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.

 -- Scheme Procedure: equal? x y
     Return #t iff X and Y are recursively eqv? equivalent. 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.

Property Lists
==============

Every object in the system can have a property list that may be used for information about that object.  For example, a function may have a property list that includes information about the source file in which it is defined.

Property lists are implemented as assq lists (see Association Lists).

Currently, property lists are implemented differently for procedures and closures than for other kinds of objects.  Therefore, when manipulating a property list associated with a procedure object, use the procedure functions; otherwise, use the object functions.

 -- Scheme Procedure: object-properties obj
 -- C Function: scm_object_properties (obj)
     Return OBJ's property list.

 -- Scheme Procedure: set-object-properties! obj alist
 -- C Function: scm_set_object_properties_x (obj, alist)
     Set OBJ's property list to ALIST.

 -- Scheme Procedure: object-property obj key
 -- C Function: scm_object_property (obj, key)
     Return the property of OBJ with name KEY.

 -- Scheme Procedure: set-object-property! obj key value
 -- C Function: scm_set_object_property_x (obj, key, value)
     In OBJ's property list, set the property named KEY to VALUE.

[Interface bug:  there should be a second level of interface in which the user provides a "property table" that is possibly private.]

Primitive Properties
====================

 -- Scheme Procedure: primitive-make-property not_found_proc
 -- C Function: scm_primitive_make_property (not_found_proc)
     Create a property token that can be used with primitive-property-ref and primitive-property-set!. See primitive-property-ref for the significance of NOT_FOUND_PROC.

 -- Scheme Procedure: primitive-property-ref prop obj
 -- C Function: scm_primitive_property_ref (prop, obj)
     Return the property PROP of OBJ.  When no value has yet been associated with PROP and OBJ, call NOT-FOUND-PROC instead (see primitive-make-property) and use its return value.  That value is also associated with OBJ via primitive-property-set!.  When NOT-FOUND-PROC is #f, use #f as the default value of PROP.

 -- Scheme Procedure: primitive-property-set! prop obj val
 -- C Function: scm_primitive_property_set_x (prop, obj, val)
     Associate CODE with PROP and OBJ.

 -- Scheme Procedure: primitive-property-del! prop obj
 -- C Function: scm_primitive_property_del_x (prop, obj)
     Remove any value associated with PROP and OBJ.

Sorting
=======

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.

 -- Scheme Procedure: merge alist blist less
 -- C Function: scm_merge (alist, blist, less)
     Merge two already sorted lists into one. Given two lists ALIST and BLIST, such that (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.

 -- Scheme Procedure: merge! alist blist less
 -- C Function: scm_merge_x (alist, blist, less)
     Takes two lists ALIST and BLIST such that (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 merge Note:  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 stable- are 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 input.

 -- Scheme Procedure: sorted? items less
 -- C Function: scm_sorted_p (items, less)
     Return #t iff 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

 -- Scheme Procedure: sort items less
 -- C Function: scm_sort (items, less)
     Sort the sequence ITEMS, which may be a list or a vector.  LESS is used for comparing the sequence elements.  This is not a stable sort.

 -- Scheme Procedure: sort! items less
 -- C Function: scm_sort_x (items, less)
     Sort the sequence ITEMS, which may be a list or a vector.  LESS is used for comparing the sequence elements.  The sorting is destructive, that means that the input sequence is modified to produce the sorted result. This is not a stable sort.

 -- Scheme Procedure: stable-sort items less
 -- C Function: scm_stable_sort (items, less)
     Sort the sequence ITEMS, which may be a list or a vector. LESS is used for comparing the sequence elements. This is a stable sort.

 -- Scheme Procedure: stable-sort! items less
 -- C Function: scm_stable_sort_x (items, less)
     Sort the sequence ITEMS, which may be a list or a vector. LESS is used for comparing the sequence elements. The sorting is destructive, that means that the input sequence is modified to produce the sorted result. This is a stable sort.

The procedures in the last group only accept lists or vectors as input, as their names indicate.

 -- Scheme Procedure: sort-list items less
 -- C Function: scm_sort_list (items, less)
     Sort the list ITEMS, using LESS for comparing the list elements. This is a stable sort.

 -- Scheme Procedure: sort-list! items less
 -- C Function: scm_sort_list_x (items, less)
     Sort the list ITEMS, using LESS for comparing the list elements. The sorting is destructive, that means that the input list is modified to produce the sorted result. This is a stable sort.

 -- Scheme Procedure: restricted-vector-sort! vec less startpos endpos
 -- C Function: scm_restricted_vector_sort_x (vec, less, startpos, endpos)
     Sort the vector VEC, using LESS for comparing the vector elements.  STARTPOS and ENDPOS delimit the range of the vector which gets sorted.  The return value is not specified.

Copying Deep Structures
=======================

The procedures for copying lists (see 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.

 -- Scheme Procedure: copy-tree obj
 -- C Function: scm_copy_tree (obj)
     Recursively copy the data tree that is bound to OBJ, and return a pointer to the new data structure.  copy-tree recurses 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.

General String Conversion
=========================

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 procedure.

 -- Scheme Procedure: object->string obj [printer]
 -- C Function: scm_object_to_string (obj, printer)
     Return a Scheme string obtained by printing OBJ. Printing function can be specified by the optional second argument PRINTER (default: write).

Hooks
=====

A hook is basically a list of procedures to be called at well defined points in time.  Hooks are used internally for several debugging facilities, but they can be used in user code, too.

Hooks are created with make-hook, then procedures can be added to a hook with add-hook! or removed with remove-hook! or reset-hook!.  The procedures stored in a hook can be invoked with run-hook.

Hook Examples
-------------

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 arguments.  When the procedures have been added, we can invoke them using run-hook.

     (add-hook! hook (lambda (x y)
                         (display "Foo: ")
                         (display (+ x y))
                         (newline)))
     (add-hook! hook (lambda (x y)
                         (display "Bar: ")
                         (display (* x y))
                         (newline)))
     (run-hook hook 3 4)
     -| Bar: 12
     -| Foo: 7

Note that the procedures are called in reverse order than they were added.  This can be changed by providing the optional third argument on the second call to add-hook!.

     (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

Hook Reference
--------------

When a hook is created with make-hook, you can supply the arity of the procedures which can be added to the hook.  The arity defaults to zero.  All procedures of a hook must have the same arity, and when the procedures are invoked using run-hook, the number of arguments must match the arity of the procedures.

The order in which procedures are added to a hook matters.  If the third parameter to ADD-HOOK! is omitted or is equal to #f, the 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 first to last when they are invoked via run-hook.

When calling hook->list, the procedures in the resulting list are in the same order as they would have been called by run-hook.

 -- Scheme Procedure: make-hook [n_args]
 -- C Function: scm_make_hook (n_args)
     Create a hook for storing procedure of arity N_ARGS. N_ARGS defaults to zero.  The returned value is a hook object to be used with the other hook procedures.

 -- Scheme Procedure: hook? x
 -- C Function: scm_hook_p (x)
     Return #t if X is a hook, #f otherwise.

 -- Scheme Procedure: hook-empty? hook
 -- C Function: scm_hook_empty_p (hook)
     Return #t if HOOK is an empty hook, #f otherwise.

 -- Scheme Procedure: add-hook! hook proc [append_p]
 -- C Function: scm_add_hook_x (hook, proc, append_p)
     Add the procedure PROC to the hook HOOK. The procedure is added to the end if APPEND_P is true, otherwise it is added to the front.  The return value of this procedure is not specified.

 -- Scheme Procedure: remove-hook! hook proc
 -- C Function: scm_remove_hook_x (hook, proc)
     Remove the procedure PROC from the hook HOOK.  The return value of this procedure is not specified.

 -- Scheme Procedure: reset-hook! hook
 -- C Function: scm_reset_hook_x (hook)
     Remove all procedures from the hook HOOK.  The return value of this procedure is not specified.

 -- Scheme Procedure: run-hook hook . args
 -- C Function: scm_run_hook (hook, args)
     Apply all procedures from the hook HOOK to the arguments ARGS.  The order of the procedure application is first to last.  The return value of this procedure is not specified.

 -- Scheme Procedure: hook->list hook
 -- C Function: scm_hook_to_list (hook)
     Convert the procedure list of HOOK to a list.