This is mit-scheme-ref.info, produced by makeinfo version 6.5 from
scheme.texinfo.

This manual documents MIT/GNU Scheme 10.1.8.

   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
2019 Massachusetts Institute of Technology

     Permission is granted to copy, distribute and/or modify this
     document under the terms of the GNU Free Documentation License,
     Version 1.2 or any later version published by the Free Software
     Foundation; with no Invariant Sections, with no Front-Cover Texts
     and no Back-Cover Texts.  A copy of the license is included in the
     section entitled "GNU Free Documentation License."
INFO-DIR-SECTION Programming Languages
START-INFO-DIR-ENTRY
* MIT/GNU Scheme Reference: (mit-scheme-ref).
                                Reference Manual
END-INFO-DIR-ENTRY


File: mit-scheme-ref.info,  Node: Filtering Lists,  Next: Searching Lists,  Prev: Cutting and Pasting Lists,  Up: Lists

7.5 Filtering Lists
===================

 -- procedure: filter predicate list
     (SRFI 1) Returns a newly allocated copy of LIST containing only the
     elements satisfying PREDICATE.  PREDICATE must be a procedure of
     one argument.

          (filter odd? '(1 2 3 4 5)) => (1 3 5)

     The non-standard procedure 'keep-matching-items' (and its alias
     'list-transform-positive') are the same except that its arguments
     are reversed.

 -- procedure: remove predicate list
     (SRFI 1) Like 'filter', except that the returned list contains only
     those elements _not_ satisfying PREDICATE.

          (remove odd? '(1 2 3 4 5)) => (2 4)

     The non-standard procedure 'delete-matching-items' (and its alias
     'list-transform-negative') are the same except that its arguments
     are reversed.

 -- procedure: partition predicate list
     (SRFI 1) Partitions the elements of LIST with PREDICATE, and
     returns two values: the list of in-elements and the list of
     out-elements.  The LIST is not disordered--elements occur in the
     result lists in the same order as they occur in the argument LIST.
     The dynamic order in which the various applications of 'predicate'
     are made is not specified.  One of the returned lists may share a
     common tail with the argument LIST.

          (partition symbol? '(one 2 3 four five 6)) =>
              (one four five)
              (2 3 6)

 -- procedure: filter! predicate list
 -- procedure: remove! predicate list
 -- procedure: partition! predicate list
     (SRFI 1) Linear-update variants of 'filter', 'remove' and
     'partition'.  These procedures are allowed, but not required, to
     alter the cons cells in the argument 'list' to construct the result
     lists.

     The non-standard procedures 'keep-matching-items!' and
     'delete-matching-items!' bear a similar relationship to
     'keep-matching-items' and 'delete-matching-items', respectively.

 -- procedure: delq element list
 -- procedure: delv element list
 -- procedure: delete element list
     Returns a newly allocated copy of LIST with all entries equal to
     ELEMENT removed.  'delq' uses 'eq?' to compare ELEMENT with the
     entries in LIST, 'delv' uses 'eqv?', and 'delete' uses 'equal?'.

 -- procedure: delq! element list
 -- procedure: delv! element list
 -- procedure: delete! element list
     Returns a list consisting of the top-level elements of LIST with
     all entries equal to ELEMENT removed.  These procedures are like
     'delq', 'delv', and 'delete' except that they destructively modify
     LIST.  'delq!' uses 'eq?' to compare element with the entries in
     LIST, 'delv!' uses 'eqv?', and 'delete!' uses 'equal?'.  Because
     the result may not be 'eq?' to LIST, it is desirable to do
     something like '(set! x (delete! x))'.

          (define x '(a b c b))
          (delete 'b x)                           => (a c)
          x                                       => (a b c b)

          (define x '(a b c b))
          (delete! 'b x)                          => (a c)
          x                                       => (a c)
          ;; Returns correct result:
          (delete! 'a x)                          => (c)

          ;; Didn't modify what x points to:
          x                                       => (a c)

 -- procedure: delete-member-procedure deletor predicate
     Returns a deletion procedure similar to 'delv' or 'delete!'.
     DELETOR should be one of the procedures 'list-deletor' or
     'list-deletor!'.  PREDICATE must be an equivalence predicate.  The
     returned procedure accepts exactly two arguments: first, an object
     to be deleted, and second, a list of objects from which it is to be
     deleted.  If DELETOR is 'list-deletor', the procedure returns a
     newly allocated copy of the given list in which all entries equal
     to the given object have been removed.  If DELETOR is
     'list-deletor!', the procedure returns a list consisting of the
     top-level elements of the given list with all entries equal to the
     given object removed; the given list is destructively modified to
     produce the result.  In either case PREDICATE is used to compare
     the given object to the elements of the given list.

     Here are some examples that demonstrate how
     'delete-member-procedure' could have been used to implement 'delv'
     and 'delete!':

          (define delv
            (delete-member-procedure list-deletor eqv?))
          (define delete!
            (delete-member-procedure list-deletor! equal?))

 -- procedure: list-deletor predicate
 -- procedure: list-deletor! predicate
     These procedures each return a procedure that deletes elements from
     lists.  PREDICATE must be a procedure of one argument.  The
     returned procedure accepts exactly one argument, which must be a
     proper list, and applies PREDICATE to each of the elements of the
     argument, deleting those for which it is true.

     The procedure returned by 'list-deletor' deletes elements
     non-destructively, by returning a newly allocated copy of the
     argument with the appropriate elements removed.  The procedure
     returned by 'list-deletor!' performs a destructive deletion.


File: mit-scheme-ref.info,  Node: Searching Lists,  Next: Mapping of Lists,  Prev: Filtering Lists,  Up: Lists

7.6 Searching Lists
===================

 -- procedure: find predicate list
     (SRFI 1) Returns the first element in LIST for which PREDICATE is
     true; returns '#f' if it doesn't find such an element.  PREDICATE
     must be a procedure of one argument.

          (find even? '(3 1 4 1 5 9)) => 4

     Note that 'find' has an ambiguity in its lookup semantics--if
     'find' returns '#f', you cannot tell (in general) if it found a
     '#f' element that satisfied PREDICATE, or if it did not find any
     element at all.  In many situations, this ambiguity cannot
     arise--either the list being searched is known not to contain any
     '#f' elements, or the list is guaranteed to have an element
     satisfying PREDICATE.  However, in cases where this ambiguity can
     arise, you should use 'find-tail' instead of 'find'--'find-tail'
     has no such ambiguity:

          (cond ((find-tail pred lis)
                  => (lambda (pair) ...)) ; Handle (CAR PAIR)
                (else ...)) ; Search failed.

     The non-standard 'find-matching-item' procedure (and its alias
     'list-search-positive') works identically except that its argument
     order is reversed.  'list-search-negative' is similar to
     'list-search-positive' but the sense of the predicate is reversed.

 -- procedure: find-tail predicate list
     (SRFI 1) Returns the first pair of LIST whose car satisfies
     PREDICATE; returns '#f' if there's no such pair.  'find-tail' can
     be viewed as a general-predicate variant of MEMV.

 -- procedure: memq object list
 -- procedure: memv object list
 -- procedure: member object list
     These procedures return the first pair of LIST whose car is OBJECT;
     the returned pair is always one from which LIST is composed.  If
     OBJECT does not occur in LIST, '#f' (n.b.: not the empty list) is
     returned.  'memq' uses 'eq?' to compare OBJECT with the elements of
     LIST, while 'memv' uses 'eqv?' and 'member' uses 'equal?'.(1)

          (memq 'a '(a b c))                      => (a b c)
          (memq 'b '(a b c))                      => (b c)
          (memq 'a '(b c d))                      => #f
          (memq (list 'a) '(b (a) c))             => #f
          (member (list 'a) '(b (a) c))           => ((a) c)
          (memq 101 '(100 101 102))               => unspecified
          (memv 101 '(100 101 102))               => (101 102)

 -- procedure: member-procedure predicate
     Returns a procedure similar to 'memq', except that PREDICATE, which
     must be an equivalence predicate, is used instead of 'eq?'.  This
     could be used to define 'memv' as follows:

          (define memv (member-procedure eqv?))

   ---------- Footnotes ----------

   (1) Although they are often used as predicates, 'memq', 'memv', and
'member' do not have question marks in their names because they return
useful values rather than just '#t' or '#f'.


File: mit-scheme-ref.info,  Node: Mapping of Lists,  Next: Reduction of Lists,  Prev: Searching Lists,  Up: Lists

7.7 Mapping of Lists
====================

 -- procedure: map procedure list list ...
     PROCEDURE must be a procedure taking as many arguments as there are
     LISTs.  If more than one LIST is given, then they must all be the
     same length.  'map' applies PROCEDURE element-wise to the elements
     of the LISTs and returns a list of the results, in order from left
     to right.  The dynamic order in which PROCEDURE is applied to the
     elements of the LISTs is unspecified; use 'for-each' to sequence
     side effects.

          (map cadr '((a b) (d e) (g h)))           => (b e h)
          (map (lambda (n) (expt n n)) '(1 2 3 4))  => (1 4 27 256)
          (map + '(1 2 3) '(4 5 6))                 => (5 7 9)
          (let ((count 0))
            (map (lambda (ignored)
                   (set! count (+ count 1))
                   count)
                 '(a b c)))                         => unspecified

 -- procedure: map* initial-value procedure list1 list2 ...
     Similar to 'map', except that the resulting list is terminated by
     INITIAL-VALUE rather than the empty list.  The following are
     equivalent:

          (map PROCEDURE LIST LIST ...)
          (map* '() PROCEDURE LIST LIST ...)

 -- procedure: append-map procedure list list ...
 -- procedure: append-map* initial-value procedure list list ...
     Similar to 'map' and 'map*', respectively, except that the results
     of applying PROCEDURE to the elements of LISTs are concatenated
     together by 'append' rather than by 'cons'.  The following are
     equivalent, except that the former is more efficient:

          (append-map PROCEDURE LIST LIST ...)
          (apply append (map PROCEDURE LIST LIST ...))

 -- procedure: append-map! procedure list list ...
 -- procedure: append-map*! initial-value procedure list list ...
     Similar to 'map' and 'map*', respectively, except that the results
     of applying PROCEDURE to the elements of LISTs are concatenated
     together by 'append!' rather than by 'cons'.  The following are
     equivalent, except that the former is more efficient:

          (append-map! PROCEDURE LIST LIST ...)
          (apply append! (map PROCEDURE LIST LIST ...))

 -- procedure: for-each procedure list list ...
     The arguments to 'for-each' are like the arguments to 'map', but
     'for-each' calls PROCEDURE for its side effects rather than for its
     values.  Unlike 'map', 'for-each' is guaranteed to call PROCEDURE
     on the elements of the LISTs in order from the first element to the
     last, and the value returned by 'for-each' is unspecified.

          (let ((v (make-vector 5)))
            (for-each (lambda (i)
                        (vector-set! v i (* i i)))
                      '(0 1 2 3 4))
            v)                            => #(0 1 4 9 16)


File: mit-scheme-ref.info,  Node: Reduction of Lists,  Next: Miscellaneous List Operations,  Prev: Mapping of Lists,  Up: Lists

7.8 Reduction of Lists
======================

 -- procedure: reduce-left procedure initial list
     Combines all the elements of LIST using the binary operation
     PROCEDURE.  For example, using '+' one can add up all the elements:

          (reduce-left + 0 list-of-numbers)

     The argument INITIAL is used only if LIST is empty; in this case
     INITIAL is the result of the call to 'reduce-left'.  If LIST has a
     single argument, it is returned.  Otherwise, the arguments are
     reduced in a left-associative fashion.  For example:

          (reduce-left + 0 '(1 2 3 4))            => 10
          (reduce-left + 0 '(1 2))                => 3
          (reduce-left + 0 '(1))                  => 1
          (reduce-left + 0 '())                   => 0
          (reduce-left + 0 '(foo))                => foo
          (reduce-left list '() '(1 2 3 4))       => (((1 2) 3) 4)

 -- procedure: reduce-right procedure initial list
     Like 'reduce-left' except that it is right-associative.

          (reduce-right list '() '(1 2 3 4))      => (1 (2 (3 4)))

 -- procedure: fold-right procedure initial list
     Combines all of the elements of LIST using the binary operation
     PROCEDURE.  Unlike 'reduce-left' and 'reduce-right', INITIAL is
     always used:

          (fold-right + 0 '(1 2 3 4))             => 10
          (fold-right + 0 '(foo))                 error-> Illegal datum
          (fold-right list '() '(1 2 3 4))        => (1 (2 (3 (4 ()))))

     'Fold-right' has interesting properties because it establishes a
     homomorphism between ('cons', '()') and (PROCEDURE, INITIAL).  It
     can be thought of as replacing the pairs in the spine of the list
     with PROCEDURE and replacing the '()' at the end with INITIAL.
     Many of the classical list-processing procedures can be expressed
     in terms of 'fold-right', at least for the simple versions that
     take a fixed number of arguments:

          (define (copy-list list)
            (fold-right cons '() list))

          (define (append list1 list2)
            (fold-right cons list2 list1))

          (define (map p list)
            (fold-right (lambda (x r) (cons (p x) r)) '() list))

          (define (reverse items)
            (fold-right (lambda (x r) (append r (list x))) '() items))

 -- procedure: fold-left procedure initial list
     Combines all the elements of LIST using the binary operation
     PROCEDURE.  Elements are combined starting with INITIAL and then
     the elements of LIST from left to right.  Whereas 'fold-right' is
     recursive in nature, capturing the essence of 'cdr'-ing down a list
     and then computing a result, FOLD-LEFT is iterative in nature,
     combining the elements as the list is traversed.

          (fold-left list '() '(1 2 3 4))         => ((((() 1) 2) 3) 4)

          (define (length list)
            (fold-left (lambda (sum element) (+ sum 1)) 0 list))

          (define (reverse items)
            (fold-left (lambda (x y) (cons y x)) () items))

 -- procedure: any predicate list list ...
     (SRFI 1) Applies PREDICATE across the LISTs, returning true if
     PREDICATE returns true on any application.

     If there are n list arguments LIST1 ... LISTN, then PREDICATE must
     be a procedure taking n arguments and returning a boolean result.

     'any' applies PREDICATE to the first elements of the LIST
     parameters.  If this application returns a true value, 'any'
     immediately returns that value.  Otherwise, it iterates, applying
     PREDICATE to the second elements of the LIST parameters, then the
     third, and so forth.  The iteration stops when a true value is
     produced or one of the lists runs out of values; in the latter
     case, 'any' returns '#f'.  The application of PREDICATE to the last
     element of the LISTs is a tail call.

     Note the difference between 'find' and 'any'--'find' returns the
     element that satisfied the predicate; 'any' returns the true value
     that the PREDICATE produced.

     Like 'every', 'any''s name does not end with a question mark--this
     is to indicate that it does not return a simple boolean ('#t' or
     '#f'), but a general value.

          (any integer? '(a 3 b 2.7))   => #t
          (any integer? '(a 3.1 b 2.7)) => #f
          (any < '(3 1 4 1 5)
                 '(2 7 1 8 2)) => #t

     The non-standard procedure 'there-exists?' is similar, except that
     it takes a single list and a predicate argument, in that order.

 -- procedure: every predicate list list ...
     (SRFI 1) Applies PREDICATE across the LISTs, returning true if
     PREDICATE returns true on every application.

     If there are n list arguments LIST1 ... LISTN, then PREDICATE must
     be a procedure taking n arguments and returning a boolean result.

     'every' applies PREDICATE to the first elements of the LIST
     parameters.  If this application returns false, 'every' immediately
     returns false.  Otherwise, it iterates, applying PREDICATE to the
     second elements of the LIST parameters, then the third, and so
     forth.  The iteration stops when a false value is produced or one
     of the LISTs runs out of values.  In the latter case, 'every'
     returns the true value produced by its final application of
     PREDICATE.  The application of PREDICATE to the last element of the
     LISTs is a tail call.

     If one of the LISTs has no elements, 'every' simply returns '#t'.

     Like 'any', 'every''s name does not end with a question mark--this
     is to indicate that it does not return a simple boolean ('#t' or
     '#f'), but a general value.

     The non-standard procedure 'for-all?' is similar, except that it
     takes a single list and a predicate argument, in that order.


File: mit-scheme-ref.info,  Node: Miscellaneous List Operations,  Prev: Reduction of Lists,  Up: Lists

7.9 Miscellaneous List Operations
=================================

 -- procedure: circular-list object ...
 -- procedure: make-circular-list k [element]
     These procedures are like 'list' and 'make-list', respectively,
     except that the returned lists are circular.  'circular-list' could
     have been defined like this:

          (define (circular-list . objects)
            (append! objects objects))

     'circular-list' is compatible with SRFI 1
     (http://srfi.schemers.org/srfi-1/srfi-1.html), but extended so that
     it can be called with no arguments.

 -- procedure: reverse list
     Returns a newly allocated list consisting of the top-level elements
     of LIST in reverse order.

          (reverse '(a b c))                  => (c b a)
          (reverse '(a (b c) d (e (f))))      => ((e (f)) d (b c) a)

 -- procedure: reverse! list
     Returns a list consisting of the top-level elements of LIST in
     reverse order.  'reverse!' is like 'reverse', except that it
     destructively modifies LIST.  Because the result may not be 'eqv?'
     to LIST, it is desirable to do something like '(set! x (reverse!
     x))'.

 -- procedure: sort sequence procedure
 -- procedure: merge-sort sequence procedure
 -- procedure: quick-sort sequence procedure
     SEQUENCE must be either a list or a vector.  PROCEDURE must be a
     procedure of two arguments that defines a "total ordering" on the
     elements of SEQUENCE.  In other words, if X and Y are two distinct
     elements of SEQUENCE, then it must be the case that

          (and (PROCEDURE X Y)
               (PROCEDURE Y X))
               => #f

     If SEQUENCE is a list (vector), 'sort' returns a newly allocated
     list (vector) whose elements are those of SEQUENCE, except that
     they are rearranged to be sorted in the order defined by PROCEDURE.
     So, for example, if the elements of SEQUENCE are numbers, and
     PROCEDURE is '<', then the resulting elements are sorted in
     monotonically nondecreasing order.  Likewise, if PROCEDURE is '>',
     the resulting elements are sorted in monotonically nonincreasing
     order.  To be precise, if X and Y are any two adjacent elements in
     the result, where X precedes Y, it is the case that

          (PROCEDURE Y X)
               => #f

     Two sorting algorithms are implemented: 'merge-sort' and
     'quick-sort'.  The procedure 'sort' is an alias for 'merge-sort'.

     See also the definition of 'sort!'.


File: mit-scheme-ref.info,  Node: Vectors,  Next: Bit Strings,  Prev: Lists,  Up: Top

8 Vectors
*********

"Vectors" are heterogenous structures whose elements are indexed by
exact non-negative integers.  A vector typically occupies less space
than a list of the same length, and the average time required to access
a randomly chosen element is typically less for the vector than for the
list.

   The "length" of a vector is the number of elements that it contains.
This number is an exact non-negative integer that is fixed when the
vector is created.  The "valid indexes" of a vector are the exact
non-negative integers less than the length of the vector.  The first
element in a vector is indexed by zero, and the last element is indexed
by one less than the length of the vector.

   Vectors are written using the notation '#(OBJECT ...)'.  For example,
a vector of length 3 containing the number zero in element 0, the list
'(2 2 2 2)' in element 1, and the string '"Anna"' in element 2 can be
written as

     #(0 (2 2 2 2) "Anna")

Note that this is the external representation of a vector, not an
expression evaluating to a vector.  Like list constants, vector
constants must be quoted:

     '#(0 (2 2 2 2) "Anna")          =>  #(0 (2 2 2 2) "Anna")

   A number of the vector procedures operate on subvectors.  A
"subvector" is a segment of a vector that is specified by two exact
non-negative integers, START and END.  START is the index of the first
element that is included in the subvector, and END is one greater than
the index of the last element that is included in the subvector.  Thus
if START and END are the same, they refer to a null subvector, and if
START is zero and END is the length of the vector, they refer to the
entire vector.  The "valid indexes" of a subvector are the exact
integers between START inclusive and END exclusive.

* Menu:

* Construction of Vectors::
* Selecting Vector Components::
* Cutting Vectors::
* Modifying Vectors::


File: mit-scheme-ref.info,  Node: Construction of Vectors,  Next: Selecting Vector Components,  Prev: Vectors,  Up: Vectors

8.1 Construction of Vectors
===========================

 -- procedure: make-vector k [object]
     Returns a newly allocated vector of K elements.  If OBJECT is
     specified, 'make-vector' initializes each element of the vector to
     OBJECT.  Otherwise the initial elements of the result are
     unspecified.

 -- procedure: vector object ...
     Returns a newly allocated vector whose elements are the given
     arguments.  'vector' is analogous to 'list'.

          (vector 'a 'b 'c)                       =>  #(a b c)

 -- procedure: vector-copy vector
     Returns a newly allocated vector that is a copy of VECTOR.

 -- procedure: list->vector list
     Returns a newly allocated vector initialized to the elements of
     LIST.  The inverse of 'list->vector' is 'vector->list'.

          (list->vector '(dididit dah))           =>  #(dididit dah)

 -- standard procedure: string->vector string [start [end]]
 -- standard procedure: vector->string vector [start [end]]
     It is an error if any element of VECTOR is not a character.

     The 'vector->string' procedure returns a newly allocated string of
     the objects contained in the elements of VECTOR between START and
     END.  The 'string->vector' procedure returns a newly created vector
     initialized to the elements of the string STRING between START and
     END.

     In both procedures, order is preserved.

          (string->vector "ABC")                  =>  #(#\A #\B #\C)
          (vector->string #(#\1 #\2 #\3)          =>  "123"

 -- procedure: make-initialized-vector k initialization
     Similar to 'make-vector', except that the elements of the result
     are determined by calling the procedure INITIALIZATION on the
     indices.  For example:

          (make-initialized-vector 5 (lambda (x) (* x x)))
               =>  #(0 1 4 9 16)

 -- procedure: vector-grow vector k
     K must be greater than or equal to the length of VECTOR.  Returns a
     newly allocated vector of length K.  The first '(vector-length
     VECTOR)' elements of the result are initialized from the
     corresponding elements of VECTOR.  The remaining elements of the
     result are unspecified.

 -- procedure: vector-map procedure vector
     PROCEDURE must be a procedure of one argument.  'vector-map'
     applies PROCEDURE element-wise to the elements of VECTOR and
     returns a newly allocated vector of the results, in order from left
     to right.  The dynamic order in which PROCEDURE is applied to the
     elements of VECTOR is unspecified.

          (vector-map cadr '#((a b) (d e) (g h)))     =>  #(b e h)
          (vector-map (lambda (n) (expt n n)) '#(1 2 3 4))
                                                      =>  #(1 4 27 256)
          (vector-map + '#(5 7 9))                    =>  #(5 7 9)


File: mit-scheme-ref.info,  Node: Selecting Vector Components,  Next: Cutting Vectors,  Prev: Construction of Vectors,  Up: Vectors

8.2 Selecting Vector Components
===============================

 -- procedure: vector? object
     Returns '#t' if OBJECT is a vector; otherwise returns '#f'.

 -- procedure: vector-length vector
     Returns the number of elements in VECTOR.

 -- procedure: vector-ref vector k
     Returns the contents of element K of VECTOR.  K must be a valid
     index of VECTOR.

          (vector-ref '#(1 1 2 3 5 8 13 21) 5)    =>  8

 -- procedure: vector-set! vector k object
     Stores OBJECT in element K of VECTOR and returns an unspecified
     value.  K must be a valid index of VECTOR.

          (let ((vec (vector 0 '(2 2 2 2) "Anna")))
            (vector-set! vec 1 '("Sue" "Sue"))
            vec)
               =>  #(0 ("Sue" "Sue") "Anna")

 -- procedure: vector-first vector
 -- procedure: vector-second vector
 -- procedure: vector-third vector
 -- procedure: vector-fourth vector
 -- procedure: vector-fifth vector
 -- procedure: vector-sixth vector
 -- procedure: vector-seventh vector
 -- procedure: vector-eighth vector
     These procedures access the first several elements of VECTOR in the
     obvious way.  It is an error if the implicit index of one of these
     procedurs is not a valid index of VECTOR.

 -- procedure: vector-binary-search vector key<? unwrap-key key
     Searches VECTOR for an element with a key matching KEY, returning
     the element if one is found or '#f' if none.  The search operation
     takes time proportional to the logarithm of the length of VECTOR.
     UNWRAP-KEY must be a procedure that maps each element of VECTOR to
     a key.  KEY<? must be a procedure that implements a total ordering
     on the keys of the elements.

          (define (translate number)
            (vector-binary-search '#((1 . i)
                                     (2 . ii)
                                     (3 . iii)
                                     (6 . vi))
                                  < car number))
          (translate 2)  =>  (2 . ii)
          (translate 4)  =>  #F


File: mit-scheme-ref.info,  Node: Cutting Vectors,  Next: Modifying Vectors,  Prev: Selecting Vector Components,  Up: Vectors

8.3 Cutting Vectors
===================

 -- procedure: subvector vector start end
     Returns a newly allocated vector that contains the elements of
     VECTOR between index START (inclusive) and END (exclusive).

 -- procedure: vector-head vector end
     Equivalent to

          (subvector VECTOR 0 END)

 -- procedure: vector-tail vector start
     Equivalent to

          (subvector VECTOR START (vector-length VECTOR))


File: mit-scheme-ref.info,  Node: Modifying Vectors,  Prev: Cutting Vectors,  Up: Vectors

8.4 Modifying Vectors
=====================

 -- procedure: vector-fill! vector object
 -- procedure: subvector-fill! vector start end object
     Stores OBJECT in every element of the vector (subvector) and
     returns an unspecified value.

 -- procedure: subvector-move-left! vector1 start1 end1 vector2 start2
 -- procedure: subvector-move-right! vector1 start1 end1 vector2 start2
     Destructively copies the elements of VECTOR1, starting with index
     START1 (inclusive) and ending with END1 (exclusive), into VECTOR2
     starting at index START2 (inclusive).  VECTOR1, START1, and END1
     must specify a valid subvector, and START2 must be a valid index
     for VECTOR2.  The length of the source subvector must not exceed
     the length of VECTOR2 minus the index START2.

     The elements are copied as follows (note that this is only
     important when VECTOR1 and VECTOR2 are 'eqv?'):

     'subvector-move-left!'
          The copy starts at the left end and moves toward the right
          (from smaller indices to larger).  Thus if VECTOR1 and VECTOR2
          are the same, this procedure moves the elements toward the
          left inside the vector.

     'subvector-move-right!'
          The copy starts at the right end and moves toward the left
          (from larger indices to smaller).  Thus if VECTOR1 and VECTOR2
          are the same, this procedure moves the elements toward the
          right inside the vector.

 -- procedure: sort! vector procedure
 -- procedure: merge-sort! vector procedure
 -- procedure: quick-sort! vector procedure
     PROCEDURE must be a procedure of two arguments that defines a
     "total ordering" on the elements of VECTOR.  The elements of VECTOR
     are rearranged so that they are sorted in the order defined by
     PROCEDURE.  The elements are rearranged in place, that is, VECTOR
     is destructively modified so that its elements are in the new
     order.

     'sort!' returns VECTOR as its value.

     Two sorting algorithms are implemented: 'merge-sort!' and
     'quick-sort!'.  The procedure 'sort!' is an alias for
     'merge-sort!'.

     See also the definition of 'sort'.


File: mit-scheme-ref.info,  Node: Bit Strings,  Next: Miscellaneous Datatypes,  Prev: Vectors,  Up: Top

9 Bit Strings
*************

A "bit string" is a sequence of bits.  Bit strings can be used to
represent sets or to manipulate binary data.  The elements of a bit
string are numbered from zero up to the number of bits in the string
less one, in _right to left order_, (the rightmost bit is numbered
zero).  When you convert from a bit string to an integer, the zero-th
bit is associated with the zero-th power of two, the first bit is
associated with the first power, and so on.

   Bit strings are encoded very densely in memory.  Each bit occupies
exactly one bit of storage, and the overhead for the entire bit string
is bounded by a small constant.  However, accessing a bit in a bit
string is slow compared to accessing an element of a vector or character
string.  If performance is of overriding concern, it is better to use
character strings to store sets of boolean values even though they
occupy more space.

   The "length" of a bit string is the number of bits that it contains.
This number is an exact non-negative integer that is fixed when the bit
string is created.  The "valid indexes" of a bit string are the exact
non-negative integers less than the length of the bit string.

   Bit strings may contain zero or more bits.  They are not limited by
the length of a machine word.  In the printed representation of a bit
string, the contents of the bit string are preceded by '#*'.  The
contents are printed starting with the most significant bit (highest
index).

   Note that the external representation of bit strings uses a bit
ordering that is the reverse of the representation for bit strings in
Common Lisp.  It is likely that MIT/GNU Scheme's representation will be
changed in the future, to be compatible with Common Lisp.  For the time
being this representation should be considered a convenience for viewing
bit strings rather than a means of entering them as data.

     #*11111
     #*1010
     #*00000000
     #*

   All of the bit-string procedures are MIT/GNU Scheme extensions.

* Menu:

* Construction of Bit Strings::
* Selecting Bit String Components::
* Cutting and Pasting Bit Strings::
* Bitwise Operations on Bit Strings::
* Modification of Bit Strings::
* Integer Conversions of Bit Strings::


File: mit-scheme-ref.info,  Node: Construction of Bit Strings,  Next: Selecting Bit String Components,  Prev: Bit Strings,  Up: Bit Strings

9.1 Construction of Bit Strings
===============================

 -- procedure: make-bit-string k initialization
     Returns a newly allocated bit string of length K.  If
     INITIALIZATION is '#f', the bit string is filled with 0 bits;
     otherwise, the bit string is filled with 1 bits.

          (make-bit-string 7 #f)                  =>  #*0000000

 -- procedure: bit-string-allocate k
     Returns a newly allocated bit string of length K, but does not
     initialize it.

 -- procedure: bit-string-copy bit-string
     Returns a newly allocated copy of BIT-STRING.


File: mit-scheme-ref.info,  Node: Selecting Bit String Components,  Next: Cutting and Pasting Bit Strings,  Prev: Construction of Bit Strings,  Up: Bit Strings

9.2 Selecting Bit String Components
===================================

 -- procedure: bit-string? object
     Returns '#t' if OBJECT is a bit string; otherwise returns '#f'.

 -- procedure: bit-string-length bit-string
     Returns the length of BIT-STRING.

 -- procedure: bit-string-ref bit-string k
     Returns '#t' if the Kth bit is 1; otherwise returns '#f'.  K must
     be a valid index of BIT-STRING.

 -- procedure: bit-string-set! bit-string k
     Sets the Kth bit in BIT-STRING to 1 and returns an unspecified
     value.  K must be a valid index of BIT-STRING.

 -- procedure: bit-string-clear! bit-string k
     Sets the Kth bit in BIT-STRING to 0 and returns an unspecified
     value.  K must be a valid index of BIT-STRING.

 -- procedure: bit-substring-find-next-set-bit bit-string start end
     Returns the index of the first occurrence of a set bit in the
     substring of BIT-STRING from START (inclusive) to END (exclusive).
     If none of the bits in the substring are set '#f' is returned.  The
     index returned is relative to the whole bit string, not substring.

     The following procedure uses 'bit-substring-find-next-set-bit' to
     find all the set bits and display their indexes:

          (define (scan-bitstring bs)
            (let ((end (bit-string-length bs)))
              (let loop ((start 0))
                (let ((next
                       (bit-substring-find-next-set-bit bs start end)))
                  (if next
                      (begin
                        (write-line next)
                        (if (< next end)
                            (loop (+ next 1)))))))))


File: mit-scheme-ref.info,  Node: Cutting and Pasting Bit Strings,  Next: Bitwise Operations on Bit Strings,  Prev: Selecting Bit String Components,  Up: Bit Strings

9.3 Cutting and Pasting Bit Strings
===================================

 -- procedure: bit-string-append bit-string-1 bit-string-2
     Appends the two bit string arguments, returning a newly allocated
     bit string as its result.  In the result, the bits copied from
     BIT-STRING-1 are less significant (smaller indices) than those
     copied from BIT-STRING-2.

 -- procedure: bit-substring bit-string start end
     Returns a newly allocated bit string whose bits are copied from
     BIT-STRING, starting at index START (inclusive) and ending at END
     (exclusive).


File: mit-scheme-ref.info,  Node: Bitwise Operations on Bit Strings,  Next: Modification of Bit Strings,  Prev: Cutting and Pasting Bit Strings,  Up: Bit Strings

9.4 Bitwise Operations on Bit Strings
=====================================

 -- procedure: bit-string-zero? bit-string
     Returns '#t' if BIT-STRING contains only 0 bits; otherwise returns
     '#f'.

 -- procedure: bit-string=? bit-string-1 bit-string-2
     Compares the two bit string arguments and returns '#t' if they are
     the same length and contain the same bits; otherwise returns '#f'.

 -- procedure: bit-string-not bit-string
     Returns a newly allocated bit string that is the bitwise-logical
     negation of BIT-STRING.

 -- procedure: bit-string-movec! target-bit-string bit-string
     The destructive version of 'bit-string-not'.  The arguments
     TARGET-BIT-STRING and BIT-STRING must be bit strings of the same
     length.  The bitwise-logical negation of BIT-STRING is computed and
     the result placed in TARGET-BIT-STRING.  The value of this
     procedure is unspecified.

 -- procedure: bit-string-and bit-string-1 bit-string-2
     Returns a newly allocated bit string that is the bitwise-logical
     "and" of the arguments.  The arguments must be bit strings of
     identical length.

 -- procedure: bit-string-andc bit-string-1 bit-string-2
     Returns a newly allocated bit string that is the bitwise-logical
     "and" of BIT-STRING-1 with the bitwise-logical negation of
     BIT-STRING-2.  The arguments must be bit strings of identical
     length.

 -- procedure: bit-string-or bit-string-1 bit-string-2
     Returns a newly allocated bit string that is the bitwise-logical
     "inclusive or" of the arguments.  The arguments must be bit strings
     of identical length.

 -- procedure: bit-string-xor bit-string-1 bit-string-2
     Returns a newly allocated bit string that is the bitwise-logical
     "exclusive or" of the arguments.  The arguments must be bit strings
     of identical length.

 -- procedure: bit-string-and! target-bit-string bit-string
 -- procedure: bit-string-or! target-bit-string bit-string
 -- procedure: bit-string-xor! target-bit-string bit-string
 -- procedure: bit-string-andc! target-bit-string bit-string
     These are destructive versions of the above operations.  The
     arguments TARGET-BIT-STRING and BIT-STRING must be bit strings of
     the same length.  Each of these procedures performs the
     corresponding bitwise-logical operation on its arguments, places
     the result into TARGET-BIT-STRING, and returns an unspecified
     result.


File: mit-scheme-ref.info,  Node: Modification of Bit Strings,  Next: Integer Conversions of Bit Strings,  Prev: Bitwise Operations on Bit Strings,  Up: Bit Strings

9.5 Modification of Bit Strings
===============================

 -- procedure: bit-string-fill! bit-string initialization
     Fills BIT-STRING with zeroes if INITIALIZATION is '#f'; otherwise
     fills BIT-STRING with ones.  Returns an unspecified value.

 -- procedure: bit-string-move! target-bit-string bit-string
     Moves the contents of BIT-STRING into TARGET-BIT-STRING.  Both
     arguments must be bit strings of the same length.  The results of
     the operation are undefined if the arguments are the same bit
     string.

 -- procedure: bit-substring-move-right! bit-string-1 start1 end1
          bit-string-2 start2
     Destructively copies the bits of BIT-STRING-1, starting at index
     START1 (inclusive) and ending at END1 (exclusive), into
     BIT-STRING-2 starting at index START2 (inclusive).  START1 and END1
     must be valid substring indices for BIT-STRING-1, and START2 must
     be a valid index for BIT-STRING-2.  The length of the source
     substring must not exceed the length of BIT-STRING-2 minus the
     index START2.

     The bits are copied starting from the MSB and working towards the
     LSB; the direction of copying only matters when BIT-STRING-1 and
     BIT-STRING-2 are 'eqv?'.


File: mit-scheme-ref.info,  Node: Integer Conversions of Bit Strings,  Prev: Modification of Bit Strings,  Up: Bit Strings

9.6 Integer Conversions of Bit Strings
======================================

 -- procedure: unsigned-integer->bit-string length integer
     Both LENGTH and INTEGER must be exact non-negative integers.
     Converts INTEGER into a newly allocated bit string of LENGTH bits.
     Signals an error of type 'condition-type:bad-range-argument' if
     INTEGER is too large to be represented in LENGTH bits.

 -- procedure: signed-integer->bit-string length integer
     LENGTH must be an exact non-negative integer, and INTEGER may be
     any exact integer.  Converts INTEGER into a newly allocated bit
     string of LENGTH bits, using two's complement encoding for negative
     numbers.  Signals an error of type
     'condition-type:bad-range-argument' if INTEGER is too large to be
     represented in LENGTH bits.

 -- procedure: bit-string->unsigned-integer bit-string
 -- procedure: bit-string->signed-integer bit-string
     Converts BIT-STRING into an exact integer.
     'bit-string->signed-integer' regards BIT-STRING as a two's
     complement representation of a signed integer, and produces an
     integer of like sign and absolute value.
     'bit-string->unsigned-integer' regards BIT-STRING as an unsigned
     quantity and converts to an integer accordingly.


File: mit-scheme-ref.info,  Node: Miscellaneous Datatypes,  Next: Associations,  Prev: Bit Strings,  Up: Top

10 Miscellaneous Datatypes
**************************

* Menu:

* Booleans::
* Symbols::
* Parameters::
* Records::
* Promises::
* Streams::
* Weak References::


File: mit-scheme-ref.info,  Node: Booleans,  Next: Symbols,  Prev: Miscellaneous Datatypes,  Up: Miscellaneous Datatypes

10.1 Booleans
=============

The "boolean objects" are "true" and "false".  The boolean constant true
is written as '#t', and the boolean constant false is written as '#f'.

   The primary use for boolean objects is in the conditional expressions
'if', 'cond', 'and', and 'or'; the behavior of these expressions is
determined by whether objects are true or false.  These expressions
count only '#f' as false.  They count everything else, including '#t',
pairs, symbols, numbers, strings, vectors, and procedures as true (but
*note True and False::).

   Programmers accustomed to other dialects of Lisp should note that
Scheme distinguishes '#f' and the empty list from the symbol 'nil'.
Similarly, '#t' is distinguished from the symbol 't'.  In fact, the
boolean objects (and the empty list) are not symbols at all.

   Boolean constants evaluate to themselves, so you don't need to quote
them.

     #t                                      =>  #t
     #f                                      =>  #f
     '#f                                     =>  #f
     t                                       error-> Unbound variable

 -- variable: false
 -- variable: true
     These variables are bound to the objects '#f' and '#t'
     respectively.  The compiler, given the 'usual-integrations'
     declaration, replaces references to these variables with their
     respective values.

     Note that the symbol 'true' is not equivalent to '#t', and the
     symbol 'false' is not equivalent to '#f'.

 -- standard procedure: boolean? object
     Returns '#t' if OBJECT is either '#t' or '#f'; otherwise returns
     '#f'.

          (boolean? #f)                           =>  #t
          (boolean? 0)                            =>  #f

 -- standard procedure: not object
 -- procedure: false? object
     These procedures return '#t' if OBJECT is false; otherwise they
     return '#f'.  In other words they _invert_ boolean values.  These
     two procedures have identical semantics; their names are different
     to give different connotations to the test.

          (not #t)                                =>  #f
          (not 3)                                 =>  #f
          (not (list 3))                          =>  #f
          (not #f)                                =>  #t

 -- extended standard procedure: procedure boolean=? boolean1 boolean2
          boolean3 ...
     This predicate is true iff the BOOLEAN args are either all true or
     all false.

     Implementation note: The standard requires this procedure's
     arguments to satisfy 'boolean?', but MIT/GNU Scheme allows any
     object to be an argument.

 -- procedure: boolean/and object ...
     This procedure returns '#t' if none of its arguments are '#f'.
     Otherwise it returns '#f'.

 -- procedure: boolean/or object ...
     This procedure returns '#f' if all of its arguments are '#f'.
     Otherwise it returns '#t'.


File: mit-scheme-ref.info,  Node: Symbols,  Next: Parameters,  Prev: Booleans,  Up: Miscellaneous Datatypes

10.2 Symbols
============

MIT/GNU Scheme provides two types of symbols: "interned" and
"uninterned".  Interned symbols are far more common than uninterned
symbols, and there are more ways to create them.  Interned symbols have
an external representation that is recognized by the procedure 'read';
uninterned symbols do not.(1)

   Interned symbols have an extremely useful property: any two interned
symbols whose names are the same, in the sense of 'string=?', are the
same object (i.e. they are 'eq?' to one another).  The term "interned"
refers to the process of "interning" by which this is accomplished.
Uninterned symbols do not share this property.

   The names of interned symbols are not distinguished by their
alphabetic case.  Because of this, MIT/GNU Scheme converts all
alphabetic characters in the name of an interned symbol to a specific
case (lower case) when the symbol is created.  When the name of an
interned symbol is referenced (using 'symbol->string') or written (using
'write') it appears in this case.  It is a bad idea to depend on the
name being lower case.  In fact, it is preferable to take this one step
further: don't depend on the name of a symbol being in a uniform case.

   The rules for writing an interned symbol are the same as the rules
for writing an identifier (*note Identifiers::).  Any interned symbol
that has been returned as part of a literal expression, or read using
the 'read' procedure and subsequently written out using the 'write'
procedure, will read back in as the identical symbol (in the sense of
'eq?').

   Usually it is also true that reading in an interned symbol that was
previously written out produces the same symbol.  An exception are
symbols created by the procedures 'string->symbol' and 'intern'; they
can create symbols for which this write/read invariance may not hold
because the symbols' names contain special characters or letters in the
non-standard case.(2)

   The external representation for uninterned symbols is special, to
distinguish them from interned symbols and prevent them from being
recognized by the 'read' procedure:

     (string->uninterned-symbol "foo")
          =>  #[uninterned-symbol 30 foo]

   In this section, the procedures that return symbols as values will
either always return interned symbols, or always return uninterned
symbols.  The procedures that accept symbols as arguments will always
accept either interned or uninterned symbols, and do not distinguish the
two.

 -- procedure: symbol? object
     Returns '#t' if OBJECT is a symbol, otherwise returns '#f'.

          (symbol? 'foo)                                  =>  #t
          (symbol? (car '(a b)))                          =>  #t
          (symbol? "bar")                                 =>  #f

 -- procedure: symbol->string symbol
     Returns the name of SYMBOL as a string.  If SYMBOL was returned by
     'string->symbol', the value of this procedure will be identical (in
     the sense of 'string=?') to the string that was passed to
     'string->symbol'.  It is an error to apply mutation procedures such
     as 'string-set!' to strings returned by this procedure.

          (symbol->string 'flying-fish)           =>  "flying-fish"
          (symbol->string 'Martin)                =>  "martin"
          (symbol->string (string->symbol "Malvina"))
                                                  =>  "Malvina"

     Note that two distinct uninterned symbols can have the same name.

 -- procedure: intern string
     Returns the interned symbol whose name is STRING.  Converts STRING
     to the standard alphabetic case before generating the symbol.  This
     is the preferred way to create interned symbols, as it guarantees
     the following independent of which case the implementation uses for
     symbols' names:

          (eq? 'bitBlt (intern "bitBlt")) =>     #t

     The user should take care that STRING obeys the rules for
     identifiers (*note Identifiers::), otherwise the resulting symbol
     cannot be read as itself.

 -- procedure: intern-soft string
     Returns the interned symbol whose name is STRING.  Converts STRING
     to the standard alphabetic case before generating the symbol.  If
     no such interned symbol exists, returns '#f'.

     This is exactly like 'intern', except that it will not create an
     interned symbol, but only returns symbols that already exist.

 -- procedure: string->symbol string
     Returns the interned symbol whose name is STRING.  Although you can
     use this procedure to create symbols with names containing special
     characters or lowercase letters, it's usually a bad idea to create
     such symbols because they cannot be read as themselves.  See
     'symbol->string'.

          (eq? 'mISSISSIppi 'mississippi)         =>  #t
          (string->symbol "mISSISSIppi")
               =>  the symbol with the name "mISSISSIppi"
          (eq? 'bitBlt (string->symbol "bitBlt")) =>  #f
          (eq? 'JollyWog
                (string->symbol
                  (symbol->string 'JollyWog)))    =>  #t
          (string=? "K. Harper, M.D."
                     (symbol->string
                       (string->symbol
                         "K. Harper, M.D.")))     =>  #t

 -- procedure: string->uninterned-symbol string
     Returns a newly allocated uninterned symbol whose name is STRING.
     It is unimportant what case or characters are used in STRING.

     Note: this is the fastest way to make a symbol.

 -- procedure: generate-uninterned-symbol [object]
     Returns a newly allocated uninterned symbol that is guaranteed to
     be different from any other object.  The symbol's name consists of
     a prefix string followed by the (exact non-negative integer) value
     of an internal counter.  The counter is initially zero, and is
     incremented after each call to this procedure.

     The optional argument OBJECT is used to control how the symbol is
     generated.  It may take one of the following values:

        * If OBJECT is omitted or '#f', the prefix is '"G"'.

        * If OBJECT is an exact non-negative integer, the internal
          counter is set to that integer prior to generating the result.

        * If OBJECT is a string, it is used as the prefix.

        * If OBJECT is a symbol, its name is used as the prefix.

          (generate-uninterned-symbol)
               =>  #[uninterned-symbol 31 G0]
          (generate-uninterned-symbol)
               =>  #[uninterned-symbol 32 G1]
          (generate-uninterned-symbol 'this)
               =>  #[uninterned-symbol 33 this2]
          (generate-uninterned-symbol)
               =>  #[uninterned-symbol 34 G3]
          (generate-uninterned-symbol 100)
               =>  #[uninterned-symbol 35 G100]
          (generate-uninterned-symbol)
               =>  #[uninterned-symbol 36 G101]

 -- procedure: symbol-append symbol ...
     Returns the interned symbol whose name is formed by concatenating
     the names of the given symbols.  This procedure preserves the case
     of the names of its arguments, so if one or more of the arguments'
     names has non-standard case, the result will also have non-standard
     case.

          (symbol-append 'foo- 'bar)              =>  foo-bar
          ;; the arguments may be uninterned:
          (symbol-append 'foo- (string->uninterned-symbol "baz"))
                                                  =>  foo-baz
          ;; the result has the same case as the arguments:
          (symbol-append 'foo- (string->symbol "BAZ"))    =>  foo-BAZ

 -- procedure: symbol-hash symbol
     Returns a hash number for SYMBOL, which is computed by calling
     'string-hash' on SYMBOL's name.  The hash number is an exact
     non-negative integer.

 -- procedure: symbol-hash-mod symbol modulus
     MODULUS must be an exact positive integer.  Equivalent to

          (modulo (symbol-hash SYMBOL) MODULUS)

     This procedure is provided for convenience in constructing hash
     tables.  However, it is normally preferable to use
     'make-strong-eq-hash-table' to build hash tables keyed by symbols,
     because 'eq?' hash tables are much faster.

 -- procedure: symbol<? symbol1 symbol2
     This procedure computes a total order on symbols.  It is equivalent
     to

          (string<? (symbol->string SYMBOL1)
                    (symbol->string SYMBOL2))

   ---------- Footnotes ----------

   (1) In older dialects of Lisp, uninterned symbols were fairly
important.  This was true because symbols were complicated data
structures: in addition to having value cells (and sometimes, function
cells), these structures contained "property lists".  Because of this,
uninterned symbols were often used merely for their property lists --
sometimes an uninterned symbol used this way was referred to as a
"disembodied property list".  In MIT/GNU Scheme, symbols do not have
property lists, or any other components besides their names.  There is a
different data structure similar to disembodied property lists:
one-dimensional tables (*note 1D Tables::).  For these reasons,
uninterned symbols are not very useful in MIT/GNU Scheme.  In fact,
their primary purpose is to simplify the generation of unique variable
names in programs that generate Scheme code.

   (2) MIT/GNU Scheme reserves a specific set of interned symbols for
its own use.  If you use these reserved symbols it is possible that you
could break specific pieces of software that depend on them.  The
reserved symbols all have names beginning with the characters '#[' and
ending with the character ']'; thus none of these symbols can be read by
the procedure 'read' and hence are not likely to be used by accident.
For example, '(intern "#[unnamed-procedure]")' produces a reserved
symbol.


File: mit-scheme-ref.info,  Node: Parameters,  Next: Records,  Prev: Symbols,  Up: Miscellaneous Datatypes

10.3 Parameters
===============

"Parameters" are objects that can be bound to new values for the
duration of a dynamic extent.  *Note Dynamic Binding::.

 -- procedure: make-parameter init [converter]
 -- procedure: make-unsettable-parameter init [converter]
     Returns a newly allocated parameter object, which is a procedure
     that accepts zero arguments and returns the value associated with
     the parameter object.  Initially this value is the value of
     '(converter init)', or of INIT if the conversion procedure
     CONVERTER is not specified.  The associated value can be
     temporarily changed using the 'parameterize' special form (*note
     parameterize::).

     The 'make-parameter' procedure is standardized by SRFI 39
     (http://srfi.schemers.org/srfi-39/srfi-39.html) and by R7RS
     (http://r7rs.org/), while 'make-unsettable-parameter' is an MIT/GNU
     Scheme extension.

 -- procedure: make-settable-parameter init [converter]
     This procedure is like 'make-parameter', except that the returned
     parameter object may also be assigned by passing it an argument.
     Note that an assignment to a settable parameter affects only the
     extent of its current binding.

     'make-settable-parameter' is an MIT/GNU Scheme extension.

 -- procedure: parameterize* bindings thunk
     BINDINGS should be an alist associating parameter objects with new
     values.  Returns the value of THUNK while the parameters are
     dynamically bound to the values.

     Note that the 'parameterize' special form expands into a call to
     this procedure.  'parameterize*' is an MIT/GNU Scheme extension.

10.3.1 Cells
------------

A "cell" object is very similar to a parameter but is not implemented in
multi-processing worlds and thus is *deprecated*.  Parameters should be
used instead.

 -- procedure: cell? object
     Returns '#t' if OBJECT is a cell; otherwise returns '#f'.

 -- procedure: make-cell object
     Returns a newly allocated cell whose contents is OBJECT.

 -- procedure: cell-contents cell
     Returns the current contents of CELL.

 -- procedure: set-cell-contents! cell object
     Alters the contents of CELL to be OBJECT.  Returns an unspecified
     value.

 -- procedure: bind-cell-contents! cell object thunk
     Alters the contents of CELL to be OBJECT, calls THUNK with no
     arguments, then restores the original contents of CELL and returns
     the value returned by THUNK.  This is completely equivalent to
     dynamic binding of a variable, including the behavior when
     continuations are used (*note Dynamic Binding::).


File: mit-scheme-ref.info,  Node: Records,  Next: Promises,  Prev: Parameters,  Up: Miscellaneous Datatypes

10.4 Records
============

MIT/GNU Scheme provides a "record" abstraction, which is a simple and
flexible mechanism for building structures with named components.
Records can be defined and accessed using the procedures defined in this
section.  A less flexible but more concise way to manipulate records is
to use the 'define-structure' special form (*note Structure
Definitions::).

 -- procedure: make-record-type type-name field-names
     Returns a "record-type descriptor", a value representing a new data
     type, disjoint from all others.  The TYPE-NAME argument must be a
     string, but is only used for debugging purposes (such as the
     printed representation of a record of the new type).  The
     FIELD-NAMES argument is a list of symbols naming the "fields" of a
     record of the new type.  It is an error if the list contains any
     duplicates.  It is unspecified how record-type descriptors are
     represented.

 -- procedure: record-constructor record-type [field-names]
     Returns a procedure for constructing new members of the type
     represented by RECORD-TYPE.  The returned procedure accepts exactly
     as many arguments as there are symbols in the given list,
     FIELD-NAMES; these are used, in order, as the initial values of
     those fields in a new record, which is returned by the constructor
     procedure.  The values of any fields not named in the list of
     FIELD-NAMES are unspecified.  The FIELD-NAMES argument defaults to
     the list of field-names in the call to 'make-record-type' that
     created the type represented by RECORD-TYPE; if the FIELD-NAMES
     argument is provided, it is an error if it contains any duplicates
     or any symbols not in the default list.

 -- procedure: record-keyword-constructor record-type
     Returns a procedure for constructing new members of the type
     represented by RECORD-TYPE.  The returned procedure accepts
     arguments in a "keyword list", which is an alternating sequence of
     names and values.  In other words, the number of arguments must be
     a multiple of two, and every other argument, starting with the
     first argument, must be a symbol that is one of the field names for
     RECORD-TYPE.

     The returned procedure may be called with a keyword list that
     contains multiple instances of the same keyword.  In this case, the
     leftmost instance is used and the other instances are ignored.
     This allows keyword lists to be accumulated using 'cons' or
     'cons*', and new bindings added to the front of the list override
     old bindings at the end.

 -- procedure: record-predicate record-type
     Returns a procedure for testing membership in the type represented
     by RECORD-TYPE.  The returned procedure accepts exactly one
     argument and returns '#t' if the argument is a member of the
     indicated record type; it returns '#f' otherwise.

 -- procedure: record-accessor record-type field-name
     Returns a procedure for reading the value of a particular field of
     a member of the type represented by RECORD-TYPE.  The returned
     procedure accepts exactly one argument which must be a record of
     the appropriate type; it returns the current value of the field
     named by the symbol FIELD-NAME in that record.  The symbol
     FIELD-NAME must be a member of the list of field names in the call
     to 'make-record-type' that created the type represented by
     RECORD-TYPE.

 -- procedure: record-modifier record-type field-name
     Returns a procedure for writing the value of a particular field of
     a member of the type represented by RECORD-TYPE.  The returned
     procedure accepts exactly two arguments: first, a record of the
     appropriate type, and second, an arbitrary Scheme value; it
     modifies the field named by the symbol FIELD-NAME in that record to
     contain the given value.  The returned value of the modifier
     procedure is unspecified.  The symbol FIELD-NAME must be a member
     of the list of field names in the call to 'make-record-type' that
     created the type represented by RECORD-TYPE.

 -- procedure: record? object
     Returns '#t' if OBJECT is a record of any type and '#f' otherwise.
     Note that 'record?' may be true of any Scheme value; of course, if
     it returns '#t' for some particular value, then
     'record-type-descriptor' is applicable to that value and returns an
     appropriate descriptor.

 -- procedure: record-type-descriptor record
     Returns the record-type descriptor representing the type of RECORD.
     That is, for example, if the returned descriptor were passed to
     'record-predicate', the resulting predicate would return '#t' when
     passed RECORD.  Note that it is not necessarily the case that the
     returned descriptor is the one that was passed to
     'record-constructor' in the call that created the constructor
     procedure that created RECORD.

 -- procedure: record-type? object
     Returns '#t' if OBJECT is a record-type descriptor; otherwise
     returns '#f'.

 -- procedure: record-type-name record-type
     Returns the type name associated with the type represented by
     RECORD-TYPE.  The returned value is 'eqv?' to the TYPE-NAME
     argument given in the call to 'make-record-type' that created the
     type represented by RECORD-TYPE.

 -- procedure: record-type-field-names record-type
     Returns a list of the symbols naming the fields in members of the
     type represented by RECORD-TYPE.  The returned value is 'equal?' to
     the FIELD-NAMES argument given in the call to 'make-record-type'
     that created the type represented by RECORD-TYPE.(1)

   ---------- Footnotes ----------

   (1) In MIT/GNU Scheme, the returned list is always newly allocated.


File: mit-scheme-ref.info,  Node: Promises,  Next: Streams,  Prev: Records,  Up: Miscellaneous Datatypes

10.5 Promises
=============

 -- special form: delay expression
     The 'delay' construct is used together with the procedure 'force'
     to implement "lazy evaluation" or "call by need".  '(delay
     EXPRESSION)' returns an object called a "promise" which at some
     point in the future may be asked (by the 'force' procedure) to
     evaluate EXPRESSION and deliver the resulting value.

 -- procedure: force promise
     Forces the value of _promise_.  If no value has been computed for
     the promise, then a value is computed and returned.  The value of
     the promise is cached (or "memoized") so that if it is forced a
     second time, the previously computed value is returned without any
     recomputation.

          (force (delay (+ 1 2)))                 =>  3

          (let ((p (delay (+ 1 2))))
            (list (force p) (force p)))           =>  (3 3)

          (define head car)

          (define tail
            (lambda (stream)
              (force (cdr stream))))

          (define a-stream
            (letrec ((next
                      (lambda (n)
                        (cons n (delay (next (+ n 1)))))))
              (next 0)))

          (head (tail (tail a-stream)))           =>  2

 -- procedure: promise? object
     Returns '#t' if OBJECT is a promise; otherwise returns '#f'.

 -- procedure: promise-forced? promise
     Returns '#t' if PROMISE has been forced and its value cached;
     otherwise returns '#f'.

 -- procedure: promise-value promise
     If PROMISE has been forced and its value cached, this procedure
     returns the cached value.  Otherwise, an error is signalled.

   'force' and 'delay' are mainly intended for programs written in
functional style.  The following examples should not be considered to
illustrate good programming style, but they illustrate the property that
the value of a promise is computed at most once.

     (define count 0)

     (define p
       (delay
        (begin
          (set! count (+ count 1))
          (* x 3))))

     (define x 5)

     count                                   =>  0
     p                                       =>  #[promise 54]
     (force p)                               =>  15
     p                                       =>  #[promise 54]
     count                                   =>  1
     (force p)                               =>  15
     count                                   =>  1

   Here is a possible implementation of 'delay' and 'force'.  We define
the expression

     (delay EXPRESSION)

to have the same meaning as the procedure call

     (make-promise (lambda () EXPRESSION))

where 'make-promise' is defined as follows:

     (define make-promise
       (lambda (proc)
         (let ((already-run? #f)
               (result #f))
           (lambda ()
             (cond ((not already-run?)
                    (set! result (proc))
                    (set! already-run? #t)))
             result))))

   Promises are implemented here as procedures of no arguments, and
'force' simply calls its argument.

     (define force
       (lambda (promise)
         (promise)))

   Various extensions to this semantics of 'delay' and 'force' are
supported in some implementations (none of these are currently supported
in MIT/GNU Scheme):

   * Calling 'force' on an object that is not a promise may simply
     return the object.

   * It may be the case that there is no means by which a promise can be
     operationally distinguished from its forced value.  That is,
     expressions like the following may evaluate to either '#t' or '#f',
     depending on the implementation:

          (eqv? (delay 1) 1)              =>  unspecified
          (pair? (delay (cons 1 2)))      =>  unspecified

   * Some implementations will implement "implicit forcing", where the
     value of a promise is forced by primitive procedures like 'car' and
     '+':

          (+ (delay (* 3 7)) 13)          =>  34


File: mit-scheme-ref.info,  Node: Streams,  Next: Weak References,  Prev: Promises,  Up: Miscellaneous Datatypes

10.6 Streams
============

In addition to promises, MIT/GNU Scheme supports a higher-level
abstraction called "streams".  Streams are similar to lists, except that
the tail of a stream is not computed until it is referred to.  This
allows streams to be used to represent infinitely long lists.

 -- procedure: stream object ...
     Returns a newly allocated stream whose elements are the arguments.
     Note that the expression '(stream)' returns the empty stream, or
     end-of-stream marker.

 -- procedure: list->stream list
     Returns a newly allocated stream whose elements are the elements of
     LIST.  Equivalent to '(apply stream LIST)'.

 -- procedure: stream->list stream
     Returns a newly allocated list whose elements are the elements of
     STREAM.  If STREAM has infinite length this procedure will not
     terminate.  This could have been defined by

          (define (stream->list stream)
            (if (stream-null? stream)
                '()
                (cons (stream-car stream)
                      (stream->list (stream-cdr stream)))))

 -- special form: cons-stream object expression
     Returns a newly allocated stream pair.  Equivalent to '(cons OBJECT
     (delay EXPRESSION))'.

 -- procedure: stream-pair? object
     Returns '#t' if OBJECT is a pair whose cdr contains a promise.
     Otherwise returns '#f'.  This could have been defined by

          (define (stream-pair? object)
            (and (pair? object)
                 (promise? (cdr object))))

 -- procedure: stream-car stream
 -- procedure: stream-first stream
     Returns the first element in STREAM.  'stream-car' is equivalent to
     'car'.  'stream-first' is a synonym for 'stream-car'.

 -- procedure: stream-cdr stream
 -- procedure: stream-rest stream
     Returns the first tail of STREAM.  Equivalent to '(force (cdr
     STREAM))'.  'stream-rest' is a synonym for 'stream-cdr'.

 -- procedure: stream-null? stream
     Returns '#t' if STREAM is the end-of-stream marker; otherwise
     returns '#f'.  This is equivalent to 'null?', but should be used
     whenever testing for the end of a stream.

 -- procedure: stream-length stream
     Returns the number of elements in STREAM.  If STREAM has an
     infinite number of elements this procedure will not terminate.
     Note that this procedure forces all of the promises that comprise
     STREAM.

 -- procedure: stream-ref stream k
     Returns the element of STREAM that is indexed by K; that is, the
     Kth element.  K must be an exact non-negative integer strictly less
     than the length of STREAM.

 -- procedure: stream-head stream k
     Returns the first K elements of STREAM as a list.  K must be an
     exact non-negative integer strictly less than the length of STREAM.

 -- procedure: stream-tail stream k
     Returns the tail of STREAM that is indexed by K; that is, the Kth
     tail.  This is equivalent to performing 'stream-cdr' K times.  K
     must be an exact non-negative integer strictly less than the length
     of STREAM.

 -- procedure: stream-map procedure stream stream ...
     Returns a newly allocated stream, each element being the result of
     invoking PROCEDURE with the corresponding elements of the STREAMs
     as its arguments.


File: mit-scheme-ref.info,  Node: Weak References,  Prev: Streams,  Up: Miscellaneous Datatypes

10.7 Weak References
====================

Weak references are a mechanism for building data structures that point
at objects without protecting them from garbage collection.  An example
of such a data structure might be an entry in a lookup table that should
be removed if the rest of the program does not reference its key.  Such
an entry must still point at its key to carry out comparisons, but
should not in itself prevent its key from being garbage collected.

   A "weak reference" is a reference that points at an object without
preventing it from being garbage collected.  The term "strong reference"
is used to distinguish normal references from weak ones.  If there is no
path of strong references to some object, the garbage collector will
reclaim that object and mark any weak references to it to indicate that
it has been reclaimed.

   If there is a path of strong references from an object A to an object
B, A is said to hold B "strongly".  If there is a path of references
from an object A to an object B, but every such path traverses at least
one weak reference, A is said to hold B "weakly".

   MIT Scheme provides two mechanisms for using weak references.  "Weak
pairs" are like normal pairs, except that their car slot is a weak
reference (but the cdr is still strong).  The heavier-weight
"ephemerons" additionally arrange that the ephemeron does not count as
holding the object in its key field strongly even if the object in its
datum field does.

   *Warning*: Working with weak references is subtle and requires
careful analysis; most programs should avoid working with them directly.
The most common use cases for weak references ought to be served by hash
tables (*note Hash Tables::), which can employ various flavors of weak
entry types, 1d tables (*note 1D Tables::), which hold their keys
weakly, and the association table (*note The Association Table::), which
also holds its keys weakly.

* Menu:

* Weak Pairs::
* Ephemerons::
* Reference barriers::


File: mit-scheme-ref.info,  Node: Weak Pairs,  Next: Ephemerons,  Prev: Weak References,  Up: Weak References

10.7.1 Weak Pairs
-----------------

The car of a "weak pair" holds its pointer weakly, while the cdr holds
its pointer strongly.  If the object in the car of a weak pair is not
held strongly by any other data structure, it will be garbage-collected.

   Note: weak pairs can be defeated by cross references among their
slots.  Consider a weak pair P holding an object A in its car and an
object D in its cdr.  P points to A weakly and to D strongly.  If D
holds A strongly, however, then P ends up holding A strongly after all.
If avoiding this is worth a heavier-weight structure, *Note
Ephemerons::.

   Note: weak pairs are _not_ pairs; that is, they do not satisfy the
predicate 'pair?'.

 -- procedure: weak-pair? object
     Returns '#t' if OBJECT is a weak pair; otherwise returns '#f'.

 -- procedure: weak-cons car cdr
     Allocates and returns a new weak pair, with components CAR and CDR.
     The CAR component is held weakly.

 -- procedure: weak-pair/car? weak-pair
     This predicate returns '#f' if the car of WEAK-PAIR has been
     garbage-collected; otherwise returns '#t'.  In other words, it is
     true if WEAK-PAIR has a valid car component.

 -- procedure: weak-car weak-pair
     Returns the car component of WEAK-PAIR.  If the car component has
     been garbage-collected, this operation returns '#f', but it can
     also return '#f' if that is the value that was stored in the car.

   Normally, 'weak-pair/car?' is used to determine if 'weak-car' would
return a valid value.  An obvious way of doing this would be:

     (if (weak-pair/car? x)
         (weak-car x)
         ...)

However, since a garbage collection could occur between the call to
'weak-pair/car?' and 'weak-car', this would not always work correctly.
Instead, the following should be used, which always works:

     (or (weak-car x)
         (and (not (weak-pair/car? x))
              ...))

   The reason that the latter expression works is that 'weak-car'
returns '#f' in just two instances: when the car component is '#f', and
when the car component has been garbage-collected.  In the former case,
if a garbage collection happens between the two calls, it won't matter,
because '#f' will never be garbage-collected.  And in the latter case,
it also won't matter, because the car component no longer exists and
cannot be affected by the garbage collector.

 -- procedure: weak-set-car! weak-pair object
     Sets the car component of WEAK-PAIR to OBJECT and returns an
     unspecified result.

 -- procedure: weak-cdr weak-pair
     Returns the cdr component of WEAK-PAIR.

 -- procedure: weak-set-cdr! weak-pair object
     Sets the cdr component of WEAK-PAIR to OBJECT and returns an
     unspecified result.


File: mit-scheme-ref.info,  Node: Ephemerons,  Next: Reference barriers,  Prev: Weak Pairs,  Up: Weak References

10.7.2 Ephemerons
-----------------

An "ephemeron" is an object with two weakly referenced components called
its "key" and "datum".  The garbage collector drops an ephemeron's
references to both key and datum, rendering the ephemeron "broken", if
and only if the garbage collector can prove that there are no strong
references to the key.  In other words, an ephemeron is broken when
nobody else cares about its key.  In particular, the datum holding a
reference to the key will not in itself prevent the ephemeron from
becoming broken; in contrast, *Note Weak Pairs::.  Once broken,
ephemerons never cease to be broken; setting the key or datum of a
broken ephemeron with 'set-ephemeron-key!' or 'set-ephemeron-datum!' has
no effect.  Note that an ephemeron's reference to its datum may be
dropped even if the datum is still reachable; all that matters is
whether the key is reachable.

   Ephemerons are considerably heavier-weight than weak pairs, because
garbage-collecting ephemerons is more complicated than
garbage-collecting weak pairs.  Each ephemeron needs five words of
storage, rather than the two words needed by a weak pair.  However,
while the garbage collector spends more time on ephemerons than on other
objects, the amount of time it spends on ephemerons scales linearly with
the number of live ephemerons, which is how its running time scales with
the total number of live objects anyway.

 -- procedure: ephemeron? object
     Returns '#t' if OBJECT is a ephemeron; otherwise returns '#f'.

 -- procedure: make-ephemeron key datum
     Allocates and returns a new ephemeron, with components KEY and
     DATUM.

 -- procedure: ephemeron-broken? ephemeron
     Returns '#t' if the garbage collector has dropped EPHEMERON's
     references to its key and datum; otherwise returns '#f'.

 -- procedure: ephemeron-key ephemeron
 -- procedure: ephemeron-datum ephemeron
     These return the key or datum component, respectively, of
     EPHEMERON.  If EPHEMERON has been broken, these operations return
     '#f', but they can also return '#f' if that is the value that was
     stored in the key or value component.

 -- procedure: set-ephemeron-key! ephemeron object
 -- procedure: set-ephemeron-datum! ephemeron object
     These set the key or datum component, respectively, of EPHEMERON to
     OBJECT and return an unspecified result.  If EPHEMERON is broken,
     neither of these operations has any effect.

   Like 'weak-pair/car?', 'ephemeron-broken?' must be used with care.
If '(ephemeron-broken? EPHEMERON)' yields false, it guarantees only that
prior evaluations of '(ephemeron-key EPHEMERON)' or '(ephemeron-datum
EPHEMERON)' yielded the key or datum that was stored in the ephemeron,
but it makes no guarantees about subsequent calls to 'ephemeron-key' or
'ephemeron-datum': the garbage collector may run and break the ephemeron
immediately after 'ephemeron-broken?' returns.  Thus, the correct idiom
to fetch an ephemeron's key and datum and use them if the ephemeron is
not broken is

     (let ((key (ephemeron-key ephemeron))
           (datum (ephemeron-datum ephemeron)))
       (if (ephemeron-broken? ephemeron)
           ... broken case ...
           ... code using KEY and DATUM ...))


File: mit-scheme-ref.info,  Node: Reference barriers,  Prev: Ephemerons,  Up: Weak References

10.7.3 Reference barriers
-------------------------

The garbage collector may break an ephemeron if it can prove that the
key is not strongly reachable.  To ensure that it does not do so before
a certain point in a program, the program can invoke a "reference
barrier" on the key by calling the 'reference-barrier' procedure, which
guarantees that even if the program does not use the key, it will be
considered strongly reachable until after 'reference-barrier' returns.

 -- procedure: reference-barrier object
     Guarantee that OBJECT is strongly reachable until after
     'reference-barrier' returns.


File: mit-scheme-ref.info,  Node: Associations,  Next: Procedures,  Prev: Miscellaneous Datatypes,  Up: Top

11 Associations
***************

MIT/GNU Scheme provides several mechanisms for associating objects with
one another.  Each of these mechanisms creates a link between one or
more objects, called "keys", and some other object, called a "datum".
Beyond this common idea, however, each of the mechanisms has various
different properties that make it appropriate in different situations:

   * "Association lists" are one of Lisp's oldest association
     mechanisms.  Because they are made from ordinary pairs, they are
     easy to build and manipulate, and very flexible in use.  However,
     the average lookup time for an association list is linear in the
     number of associations.

   * "1D tables" have a very simple interface, making them easy to use,
     and offer the feature that they do not prevent their keys from
     being reclaimed by the garbage collector.  Like association lists,
     their average lookup time is linear in the number of associations;
     but 1D tables aren't as flexible.

   * "The association table" is MIT/GNU Scheme's equivalent to the
     "property lists" of Lisp.  It has the advantages that the keys may
     be any type of object and that it does not prevent the keys from
     being reclaimed by the garbage collector.  However, two linear-time
     lookups must be performed, one for each key, whereas for
     traditional property lists only one lookup is required for both
     keys.

   * "Hash tables" are a powerful mechanism with constant-time access to
     large amounts of data.  Hash tables are not as flexible as
     association lists, but because their access times are independent
     of the number of associations in the table, for most applications
     they are the mechanism of choice.

   * "Balanced binary trees" are another association mechanism that is
     useful for applications in which the keys are ordered.  Binary
     trees have access times that are proportional to the logarithm of
     the number of associations in the tree.  While they aren't as fast
     as hash tables, they offer the advantage that the contents of the
     tree can be converted to a sorted alist in linear time.
     Additionally, two trees can be compared for equality in worst-case
     linear time.

   * "Red-Black trees" are a kind of balanced binary tree.  The
     implementation supports destructive insertion and deletion
     operations with a good constant factor.

   * "Weight-Balanced trees" are a kind of balanced binary tree.  The
     implementation provides non-destructive operations.  There is a
     comprehensive set of operations, including: a constant-time size
     operation; many high-level operations such as the set operations
     union, intersection and difference; and indexing of elements by
     position.

* Menu:

* Association Lists::
* 1D Tables::
* The Association Table::
* Hash Tables::
* Object Hashing::
* Red-Black Trees::
* Weight-Balanced Trees::


File: mit-scheme-ref.info,  Node: Association Lists,  Next: 1D Tables,  Prev: Associations,  Up: Associations

11.1 Association Lists
======================

An "association list", or "alist", is a data structure used very
frequently in Scheme.  An alist is a list of pairs, each of which is
called an "association".  The car of an association is called the "key".

   An advantage of the alist representation is that an alist can be
incrementally augmented simply by adding new entries to the front.
Moreover, because the searching procedures 'assv' et al. search the
alist in order, new entries can "shadow" old entries.  If an alist is
viewed as a mapping from keys to data, then the mapping can be not only
augmented but also altered in a non-destructive manner by adding new
entries to the front of the alist.(1)

 -- procedure: alist? object
     Returns '#t' if OBJECT is an association list (including the empty
     list); otherwise returns '#f'.  Any OBJECT satisfying this
     predicate also satisfies 'list?'.

 -- procedure: assq object alist
 -- procedure: assv object alist
 -- procedure: assoc object alist
     These procedures find the first pair in ALIST whose car field is
     OBJECT, and return that pair; the returned pair is always an
     _element_ of ALIST, _not_ one of the pairs from which ALIST is
     composed.  If no pair in ALIST has OBJECT as its car, '#f' (n.b.:
     not the empty list) is returned.  'assq' uses 'eq?' to compare
     OBJECT with the car fields of the pairs in ALIST, while 'assv' uses
     'eqv?' and 'assoc' uses 'equal?'.(2)

          (define e '((a 1) (b 2) (c 3)))
          (assq 'a e)                             =>  (a 1)
          (assq 'b e)                             =>  (b 2)
          (assq 'd e)                             =>  #f
          (assq (list 'a) '(((a)) ((b)) ((c))))   =>  #f
          (assoc (list 'a) '(((a)) ((b)) ((c))))  =>  ((a))
          (assq 5 '((2 3) (5 7) (11 13)))         =>  unspecified
          (assv 5 '((2 3) (5 7) (11 13)))         =>  (5 7)

 -- procedure: association-procedure predicate selector
     Returns an association procedure that is similar to 'assv', except
     that SELECTOR (a procedure of one argument) is used to select the
     key from the association, and PREDICATE (an equivalence predicate)
     is used to compare the key to the given item.  This can be used to
     make association lists whose elements are, say, vectors instead of
     pairs (also *note Searching Lists::).

     For example, here is how 'assv' could be implemented:

          (define assv (association-procedure eqv? car))

     Another example is a "reverse association" procedure:

          (define rassv (association-procedure eqv? cdr))

 -- procedure: del-assq object alist
 -- procedure: del-assv object alist
 -- procedure: del-assoc object alist
     These procedures return a newly allocated copy of ALIST in which
     all associations with keys equal to OBJECT have been removed.  Note
     that while the returned copy is a newly allocated list, the
     association pairs that are the elements of the list are shared with
     ALIST, not copied.  'del-assq' uses 'eq?' to compare OBJECT with
     the keys, while 'del-assv' uses 'eqv?' and 'del-assoc' uses
     'equal?'.

          (define a
            '((butcher . "231 e22nd St.")
              (baker . "515 w23rd St.")
              (hardware . "988 Lexington Ave.")))

          (del-assq 'baker a)
               =>
               ((butcher . "231 e22nd St.")
                (hardware . "988 Lexington Ave."))

 -- procedure: del-assq! object alist
 -- procedure: del-assv! object alist
 -- procedure: del-assoc! object alist
     These procedures remove from ALIST all associations with keys equal
     to OBJECT.  They return the resulting list.  'del-assq!' uses 'eq?'
     to compare OBJECT with the keys, while 'del-assv!' uses 'eqv?' and
     'del-assoc!' uses 'equal?'.  These procedures are like 'del-assq',
     'del-assv', and 'del-assoc', respectively, except that they
     destructively modify ALIST.

 -- procedure: delete-association-procedure deletor predicate selector
     This returns a deletion procedure similar to 'del-assv' or
     'del-assq!'.  The PREDICATE and SELECTOR arguments are the same as
     those for 'association-procedure', while the DELETOR argument
     should be either the procedure 'list-deletor' (for non-destructive
     deletions), or the procedure 'list-deletor!' (for destructive
     deletions).

     For example, here is a possible implementation of 'del-assv':

          (define del-assv
            (delete-association-procedure list-deletor eqv? car))

 -- procedure: alist-copy alist
     Returns a newly allocated copy of ALIST.  This is similar to
     'list-copy' except that the "association" pairs, i.e. the elements
     of the list ALIST, are also copied.  'alist-copy' could have been
     implemented like this:

          (define (alist-copy alist)
            (if (null? alist)
                '()
                (cons (cons (car (car alist)) (cdr (car alist)))
                      (alist-copy (cdr alist)))))

   ---------- Footnotes ----------

   (1) This introduction is taken from 'Common Lisp, The Language',
second edition, p. 431.

   (2) Although they are often used as predicates, 'assq', 'assv', and
'assoc' do not have question marks in their names because they return
useful values rather than just '#t' or '#f'.


File: mit-scheme-ref.info,  Node: 1D Tables,  Next: The Association Table,  Prev: Association Lists,  Up: Associations

11.2 1D Tables
==============

"1D tables" ("one-dimensional" tables) are similar to association lists.
In a 1D table, unlike an association list, the keys of the table are
held "weakly": if a key is garbage-collected, its associated value in
the table is removed.  1D tables compare their keys for equality using
'eq?'.

   1D tables can often be used as a higher-performance alternative to
the two-dimensional association table (*note The Association Table::).
If one of the keys being associated is a compound object such as a
vector, a 1D table can be stored in one of the vector's slots.  Under
these circumstances, accessing items in a 1D table will be comparable in
performance to using a property list in a conventional Lisp.

 -- procedure: make-1d-table
     Returns a newly allocated empty 1D table.

 -- procedure: 1d-table? object
     Returns '#t' if OBJECT is a 1D table, otherwise returns '#f'.  Any
     object that satisfies this predicate also satisfies 'list?'.

 -- procedure: 1d-table/put! 1d-table key datum
     Creates an association between KEY and DATUM in 1D-TABLE.  Returns
     an unspecified value.

 -- procedure: 1d-table/remove! 1d-table key
     Removes any association for KEY in 1D-TABLE and returns an
     unspecified value.

 -- procedure: 1d-table/get 1d-table key default
     Returns the DATUM associated with KEY in 1D-TABLE.  If there is no
     association for KEY, DEFAULT is returned.

 -- procedure: 1d-table/lookup 1d-table key if-found if-not-found
     IF-FOUND must be a procedure of one argument, and IF-NOT-FOUND must
     be a procedure of no arguments.  If 1D-TABLE contains an
     association for KEY, IF-FOUND is invoked on the DATUM of the
     association.  Otherwise, IF-NOT-FOUND is invoked with no arguments.
     In either case, the result of the invoked procedure is returned as
     the result of '1d-table/lookup'.

 -- procedure: 1d-table/alist 1d-table
     Returns a newly allocated association list that contains the same
     information as 1D-TABLE.


File: mit-scheme-ref.info,  Node: The Association Table,  Next: Hash Tables,  Prev: 1D Tables,  Up: Associations

11.3 The Association Table
==========================

MIT/GNU Scheme provides a generalization of the property-list mechanism
found in most other implementations of Lisp: a global two-dimensional
"association table".  This table is indexed by two keys, called X-KEY
and Y-KEY in the following procedure descriptions.  These keys and the
datum associated with them can be arbitrary objects.  'eq?' is used to
discriminate keys.

   Think of the association table as a matrix: a single datum can be
accessed using both keys, a column using X-KEY only, and a row using
Y-KEY only.

 -- procedure: 2d-put! x-key y-key datum
     Makes an entry in the association table that associates DATUM with
     X-KEY and Y-KEY.  Returns an unspecified result.

 -- procedure: 2d-remove! x-key y-key
     If the association table has an entry for X-KEY and Y-KEY, it is
     removed.  Returns an unspecified result.

 -- procedure: 2d-get x-key y-key
     Returns the DATUM associated with X-KEY and Y-KEY.  Returns '#f' if
     no such association exists.

 -- procedure: 2d-get-alist-x x-key
     Returns an association list of all entries in the association table
     that are associated with X-KEY.  The result is a list of '(Y-KEY .
     DATUM)' pairs.  Returns the empty list if no entries for X-KEY
     exist.

          (2d-put! 'foo 'bar 5)
          (2d-put! 'foo 'baz 6)
          (2d-get-alist-x 'foo)           =>  ((baz . 6) (bar . 5))

 -- procedure: 2d-get-alist-y y-key
     Returns an association list of all entries in the association table
     that are associated with Y-KEY.  The result is a list of '(X-KEY .
     DATUM)' pairs.  Returns the empty list if no entries for Y-KEY
     exist.

          (2d-put! 'bar 'foo 5)
          (2d-put! 'baz 'foo 6)
          (2d-get-alist-y 'foo)           =>  ((baz . 6) (bar . 5))


File: mit-scheme-ref.info,  Node: Hash Tables,  Next: Object Hashing,  Prev: The Association Table,  Up: Associations

11.4 Hash Tables
================

Hash tables are a fast, powerful mechanism for storing large numbers of
associations.  MIT/GNU Scheme's hash tables feature automatic resizing,
customizable growth parameters, customizable hash procedures, and many
options for weak references to keys or data.

   The average times for the insertion, deletion, and lookup operations
on a hash table are bounded by a constant.  The space required by the
table is proportional to the number of associations in the table; the
constant of proportionality is described below (*note Resizing of Hash
Tables::).

   The hash table interface described below is a superset of SRFI 69
(http://srfi.schemers.org/srfi-69/srfi-69.html): "Basic hash tables".
The reason for supporting the extra functionality is that SRFI 69 fails
to specify certain optimization-enabling exceptions to its semantics,
forcing a correct implementation to pay the non-negligible performance
cost of completely safe behavior.  (1) The MIT/GNU Scheme native hash
table interface, in contrast, specifies the minor exceptions it needs,
and is therefore implemented more efficiently.

   We do not describe the SRFI 69-compliant interface here, as that
would be redundant with the SRFI document.

* Menu:

* Construction of Hash Tables::
* Basic Hash Table Operations::
* Resizing of Hash Tables::
* Address Hashing::

   ---------- Footnotes ----------

   (1) SRFI 69 does not give hash functions the flexibility to return
new hash values after a garbage collection, which prevents a system
whose garbage collector may relocate objects from hashing based on the
addresses of objects in memory (*note Address Hashing::).  SRFI 69 also
does not specify circumstances when procedures passed as arguments to
hash table operations may not themselves modify the hash table, which
requires defensive copying and defensive repetitions of lookups.


File: mit-scheme-ref.info,  Node: Construction of Hash Tables,  Next: Basic Hash Table Operations,  Prev: Hash Tables,  Up: Hash Tables

11.4.1 Construction of Hash Tables
----------------------------------

The next few procedures are hash-table constructors.  All hash table
constructors are procedures that accept one optional argument,
INITIAL-SIZE, and return a newly allocated hash table.  If INITIAL-SIZE
is given, it must be an exact non-negative integer or '#f'.  The meaning
of INITIAL-SIZE is discussed below (*note Resizing of Hash Tables::).

   Hash tables are normally characterized by two things: the equivalence
predicate that is used to compare keys, and how the table allows its
keys and data to be reclaimed by the garbage collector.  If a table
prevents its keys and data from being reclaimed by the garbage
collector, it is said to hold its keys and data "strongly"; other
arrangements are possible, where a table may hold keys or data "weakly"
or "ephemerally" (*note Weak References::).

 -- procedure: make-strong-eq-hash-table [initial-size]
 -- obsolete procedure: make-symbol-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'eq?'.  The keys and data are
     held strongly.  These are the fastest of the standard hash tables.

 -- procedure: make-key-weak-eq-hash-table [initial-size]
 -- obsolete procedure: make-weak-eq-hash-table [initial-size]
 -- obsolete procedure: make-eq-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'eq?'.  The keys are held
     weakly and the data are held strongly.  Note that if a datum holds
     a key strongly, the table will effectively hold that key strongly.

 -- procedure: make-datum-weak-eq-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'eq?'.  The keys are held
     strongly and the data are held weakly.  Note that if a key holds a
     datum strongly, the table will effectively hold that datum
     strongly.

 -- procedure: make-key-ephemeral-eq-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'eq?'.  The keys are held
     weakly, even if some of the data should hold some of the keys
     strongly.

 -- procedure: make-strong-eqv-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'eqv?'.  The keys and data
     are held strongly.  These hash tables are a little slower than
     those made by 'make-strong-eq-hash-table'.

 -- procedure: make-key-weak-eqv-hash-table [initial-size]
 -- obsolete procedure: make-weak-eqv-hash-table [initial-size]
 -- obsolete procedure: make-eqv-hash-table [initial-size]
 -- obsolete procedure: make-object-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'eqv?'.  The keys are held
     weakly, except that booleans, characters, numbers, and interned
     symbols are held strongly.  The data are held strongly.  Note that
     if a datum holds a key strongly, the table will effectively hold
     that key strongly.

 -- procedure: make-datum-weak-eqv-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'eqv?'.  The keys are held
     strongly and the data are held weakly.  Note that if a key holds a
     datum strongly, the table will effectively hold that datum
     strongly.

 -- procedure: make-key-ephemeral-eqv-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'eqv?'.  The keys are held
     weakly, except that booleans, characters, numbers, and interned
     symbols are held strongly.  The keys are effectively held weakly
     even if some of the data should hold some of the keys strongly.

 -- procedure: make-equal-hash-table [initial-size]
     Returns a newly allocated hash table that accepts arbitrary objects
     as keys, and compares those keys with 'equal?'.  The keys and data
     are held strongly.  These hash tables are quite a bit slower than
     those made by 'make-strong-eq-hash-table'.

 -- procedure: make-string-hash-table [initial-size]
     Returns a newly allocated hash table that accepts character strings
     as keys, and compares them with 'string=?'.  The keys and data are
     held strongly.

   All of the above are highly optimized table implementations.  Next
are some general constructors that allow for more flexible table
definitions.

 -- procedure: make-hash-table [key=? [hash-function [arg ...]]]
 -- procedure: alist->hash-table alist [key=? [hash-function [arg ...]]]
     These are the SRFI 69 constructors.  The KEY=? argument specifies
     how keys are compared and defaults to 'equal?'.  The HASH-FUNCTION
     argument specifies the hash function to use.  If HASH-FUNCTION is
     not specified, it defaults to a standard value that depends on
     KEY=?; an error is signaled if there's no standard value.  The ARG
     arguments are allowed but are implementation dependent; do not
     provide them.

     The procedure 'alist->hash-table' creates a new hash table, as with
     'make-hash-table', and then fills it with the contents of ALIST.

   The remaining constructors use "hash-table types" to encapsulate the
hashing parameters.

 -- procedure: make-hash-table* type [initial-size]
     Constructs a new hash table using the hashing parameters in TYPE.

 -- procedure: hash-table-constructor type
     Returns a procedure that, when called, constructs a new hash table
     using the hashing parameters in TYPE.  The returned procedure
     accepts an optional INITIAL-SIZE.

     This is equivalent to
          (lambda (#!optional initial-size)
            (make-hash-table* TYPE initial-size))

   The next two procedures are used to create hash-table types.  The
procedures are equivalent in power; they differ only in how the types
are described.

 -- procedure: make-hash-table-type hash-function key=? rehash-after-gc?
          entry-type
     This procedure accepts four arguments and returns a hash-table
     type, which can be used to make hash tables of that type.  The
     KEY=? argument is an equivalence predicate for the keys of the hash
     table.  The HASH-FUNCTION argument is a procedure that computes a
     hash number.  Specifically, HASH-FUNCTION accepts two arguments, a
     key and an exact positive integer (the "modulus"), and returns an
     exact non-negative integer that is less than the modulus.

     The argument REHASH-AFTER-GC?, if true, says that the values
     returned by HASH-FUNCTION might change after a garbage collection.
     If so, the hash-table implementation arranges for the table to be
     rehashed when necessary.  (*Note Address Hashing::, for information
     about hash procedures that have this property.)  Otherwise, it is
     assumed that HASH-FUNCTION always returns the same value for the
     same arguments.

     The argument ENTRY-TYPE determines the strength with which the hash
     table will hold its keys and values.  It must be one of the
     entry-type variables described below, which all start with
     'hash-table-entry-type:'.

 -- procedure: make-hash-table-type* key=? hash-function
          rehash-after-gc? entry-type
     This procedure's arguments, except for KEY=?, are keyword
     arguments; that is, each argument is a symbol of the same name
     followed by its value.  Aside from how they are passed, the
     arguments have the same meaning as those for
     'make-hash-table-type'.  Note that all of the keyword arguments are
     optional, while KEY=? is required.

     The argument ENTRY-TYPE specifies _the name of_ an entry type.  It
     must be a symbol corresponding to one of the entry-type variables
     described below.  The name of an entry type is the symbol composed
     of the suffix of the corresponding variable; for example the type
     'hash-table-entry-type:key-weak' has the name 'key-weak'.

     The default values for the keyword arguments are as follows.  The
     arguments HASH-FUNCTION and REHASH-AFTER-GC? default to standard
     values that depend on KEY=?; an error is signaled if KEY=? has no
     standard values.  The argument ENTRY-TYPE defaults to STRONG.

 -- variable: hash-table-entry-type:strong
     The entry type for hash tables that hold both keys and data
     strongly.

 -- variable: hash-table-entry-type:key-weak
     An entry type for hash tables that hold keys weakly and data
     strongly.  An entry of this type is a weak pair (*note Weak
     Pairs::) whose weak (car) slot holds the key of the entry and whose
     strong (cdr) slot holds the datum of the entry.  If a key of such a
     hash table is garbage collected, the corresponding entry will be
     removed.  Note that if some datum holds some key strongly, the
     table will effectively hold that key strongly.

 -- variable: hash-table-entry-type:datum-weak
     An entry type for hash tables that hold keys strongly and data
     weakly.  An entry of this type is a weak pair (*note Weak Pairs::)
     whose weak (car) slot holds the datum of the entry and whose strong
     (cdr) slot holds the key of the entry.  If a datum of such a hash
     table is garbage collected, all corresponding entries will be
     removed.  Note that if some key holds some datum strongly, the
     table will effectively hold that datum strongly.

 -- variable: hash-table-entry-type:key&datum-weak
 -- obsolete variable: hash-table-entry-type:key/datum-weak
     The entry type for hash tables that hold both keys and data weakly.
     An entry of this type is a weak list, holding both the key and the
     datum in the weak (car) slot of weak pairs (*note Weak Pairs::).
     If either a key or datum of such a hash table is garbage collected,
     all corresponding entries will be removed.

 -- variable: hash-table-entry-type:key-ephemeral
     An entry type for hash tables that hold data ephemerally, keyed by
     the keys.  An entry of this type is an ephemeron (*note
     Ephemerons::) whose key is the key of the entry and whose datum is
     the datum of the entry.  If a key of such a hash table is garbage
     collected, the corresponding entry will be removed.  Note that the
     table holds all its keys weakly even if some data should hold some
     keys strongly.

 -- variable: hash-table-entry-type:datum-ephemeral
     An entry type for hash tables that hold keys ephemerally, keyed by
     the data.  An entry of this type is an ephemeron (*note
     Ephemerons::) whose key is the datum of the entry and whose datum
     is the key of the entry.  If a datum of such a hash table is
     garbage collected, all corresponding entries will be removed.  Note
     that the table holds all its data weakly even if some keys should
     hold some data strongly.

 -- variable: hash-table-entry-type:key&datum-ephemeral
     The entry type for hash tables that hold both keys and data
     ephemerally keyed on each other.  An entry of this type is a pair
     of ephemerons (*note Ephemerons::), one holding the datum keyed by
     the key and the other holding the key keyed by the datum.  If both
     the key and the datum of any entry of such a hash table are garbage
     collected, the entry will be removed.  The table holds all its keys
     and data weakly itself, but will prevent any key or datum from
     being garbage collected if there are strong references to its datum
     or key, respectively.

   Some examples showing how some standard hash-table constructors could
have been defined:

     (define make-weak-eq-hash-table
       (hash-table-constructor
         (make-hash-table-type eq-hash-mod eq? #t
           hash-table-entry-type:key-weak)))

     (define make-equal-hash-table
       (hash-table-constructor
         (make-hash-table-type equal-hash-mod equal? #t
           hash-table-entry-type:strong)))

     (define make-string-hash-table
       (hash-table-constructor
         (make-hash-table-type string-hash-mod string=? #f
           hash-table-entry-type:strong)))

   The following procedures are provided only for backward
compatibility.  They should be considered *deprecated* and should not be
used in new programs.

 -- obsolete procedure: hash-table/constructor hash-function key=?
          rehash-after-gc? entry-type
     This procedure is *deprecated*.  Instead use the equivalent
          (hash-table-constructor
            (make-hash-table-type HASH-FUNCTION KEY=? REHASH-AFTER-GC?
                                  ENTRY-TYPE))

 -- obsolete procedure: strong-hash-table/constructor hash-function
          key=? [rehash-after-gc?]
     Like 'hash-table/constructor' but always uses
     'hash-table-entry-type:strong'.  If REHASH-AFTER-GC? is omitted, it
     defaults to '#f'.

 -- obsolete procedure: weak-hash-table/constructor hash-function key=?
          [rehash-after-gc?]
     Like 'hash-table/constructor' but always uses
     'hash-table-entry-type:key-weak'.  If REHASH-AFTER-GC? is omitted,
     it defaults to '#f'.


File: mit-scheme-ref.info,  Node: Basic Hash Table Operations,  Next: Resizing of Hash Tables,  Prev: Construction of Hash Tables,  Up: Hash Tables

11.4.2 Basic Hash Table Operations
----------------------------------

The procedures described in this section are the basic operations on
hash tables.  They provide the functionality most often needed by
programmers.  Subsequent sections describe other operations that provide
additional functionality needed by some applications.

 -- procedure: hash-table? object
     Returns '#t' if OBJECT is a hash table, otherwise returns '#f'.

 -- procedure: hash-table-set! hash-table key datum
 -- obsolete procedure: hash-table/put! hash-table key datum
     Associates DATUM with KEY in HASH-TABLE and returns an unspecified
     result.

     The average time required by this operation is bounded by a
     constant.

 -- procedure: hash-table-ref hash-table key [get-default]
     Returns the datum associated with KEY in HASH-TABLE.  If there is
     no association for KEY, and GET-DEFAULT is provided, it is called
     with no arguments and the value it yields is returned; if
     GET-DEFAULT is not provided, an error is signaled.

     The average time required by this operation is bounded by a
     constant.

 -- procedure: hash-table-ref/default hash-table key default
 -- obsolete procedure: hash-table/get hash-table key default
     Equivalent to
          (hash-table-ref HASH-TABLE KEY (lambda () DEFAULT))

 -- procedure: hash-table-delete! hash-table key
 -- obsolete procedure: hash-table/remove! hash-table key
     If HASH-TABLE has an association for KEY, removes it.  Returns an
     unspecified result.

     The average time required by this operation is bounded by a
     constant.

 -- procedure: hash-table-clear! hash-table
 -- obsolete procedure: hash-table/clear! hash-table
     Removes all associations in HASH-TABLE and returns an unspecified
     result.

     The average and worst-case times required by this operation are
     bounded by a constant.

 -- procedure: hash-table-size hash-table
 -- obsolete procedure: hash-table/count hash-table
     Returns the number of associations in HASH-TABLE as an exact
     non-negative integer.  If HASH-TABLE does not hold its keys and
     data strongly, this is a conservative upper bound that may count
     some associations whose keys or data have recently been reclaimed
     by the garbage collector.

     The average and worst-case times required by this operation are
     bounded by a constant.

 -- procedure: hash-table->alist hash-table
     Returns the contents of HASH-TABLE as a newly allocated alist.
     Each element of the alist is a pair '(KEY . DATUM)' where KEY is
     one of the keys of HASH-TABLE, and DATUM is its associated datum.

     The average and worst-case times required by this operation are
     linear in the number of associations in the table.

 -- procedure: hash-table-keys hash-table
 -- obsolete procedure: hash-table/key-list hash-table
     Returns a newly allocated list of the keys in HASH-TABLE.

     The average and worst-case times required by this operation are
     linear in the number of associations in the table.

 -- procedure: hash-table-values hash-table
 -- obsolete procedure: hash-table/datum-list hash-table
     Returns a newly allocated list of the datums in HASH-TABLE.  Each
     element of the list corresponds to one of the associations in
     HASH-TABLE; if the table contains multiple associations with the
     same datum, so will this list.

     The average and worst-case times required by this operation are
     linear in the number of associations in the table.

 -- procedure: hash-table-walk hash-table procedure
 -- obsolete procedure: hash-table/for-each hash-table procedure
     PROCEDURE must be a procedure of two arguments.  Invokes PROCEDURE
     once for each association in HASH-TABLE, passing the association's
     KEY and DATUM as arguments, in that order.  Returns an unspecified
     result.  PROCEDURE must not modify HASH-TABLE, with one exception:
     it is permitted to call 'hash-table-delete!' to remove the
     association being processed.

   The following procedure is useful when there is no sensible default
value for 'hash-table-ref' and the caller must choose between different
actions depending on whether there is a datum associated with the key.

 -- procedure: hash-table/lookup hash-table key if-found if-not-found
     IF-FOUND must be a procedure of one argument, and IF-NOT-FOUND must
     be a procedure of no arguments.  If HASH-TABLE contains an
     association for KEY, IF-FOUND is invoked on the datum of the
     association.  Otherwise, IF-NOT-FOUND is invoked with no arguments.
     In either case, the result yielded by the invoked procedure is
     returned as the result of 'hash-table/lookup' ('hash-table/lookup'
     _reduces_ into the invoked procedure, i.e. calls it
     tail-recursively).

     The average time required by this operation is bounded by a
     constant.

 -- procedure: hash-table-update! hash-table key procedure [get-default]
     PROCEDURE must be a procedure of one argument and GET-DEFAULT, if
     supplied, must be a procedure of zero arguments.  Applies PROCEDURE
     to the datum associated with KEY in HASH-TABLE or to the value of
     calling GET-DEFAULT if there is no association for KEY, associates
     the result with KEY, and returns an unspecified value.  If
     GET-DEFAULT is not supplied and there's no association for KEY, an
     error is signaled.

     The average time required by this operation is bounded by a
     constant.

 -- procedure: hash-table-update!/default hash-table key procedure
          default
 -- obsolete procedure: hash-table/modify! hash-table key default
          procedure
     Equivalent to
          (hash-table-update! HASH-TABLE KEY PROCEDURE (lambda () DEFAULT))

 -- procedure: hash-table-intern! hash-table key get-default
 -- obsolete procedure: hash-table/intern! hash-table key get-default
     GET-DEFAULT must be a procedure of zero arguments.  Ensures that
     HASH-TABLE has an association for KEY and returns the associated
     datum.  If HASH-TABLE did not have a datum associated with KEY,
     GET-DEFAULT is called and its value is used to create a new
     association for KEY.

     The average time required by this operation is bounded by a
     constant.

   The following procedure is sometimes useful in conjunction with weak
and ephemeral hash tables.  Normally it is not needed, because such hash
tables clean themselves automatically as they are used.

 -- procedure: hash-table-clean! hash-table
 -- obsolete procedure: hash-table/clean! hash-table
     If HASH-TABLE is a type of hash table that holds its keys or data
     weakly or ephemerally, this procedure recovers any space that was
     being used to record associations for objects that have been
     reclaimed by the garbage collector.  Otherwise, this procedure does
     nothing.  In either case, it returns an unspecified result.


File: mit-scheme-ref.info,  Node: Resizing of Hash Tables,  Next: Address Hashing,  Prev: Basic Hash Table Operations,  Up: Hash Tables

11.4.3 Resizing of Hash Tables
------------------------------

Normally, hash tables automatically resize themselves according to need.
Because of this, the programmer need not be concerned with management of
the table's size.  However, some limited control over the table's size
is provided, which will be discussed below.  This discussion involves
two concepts, "usable size" and "physical size", which we will now
define.

   The "usable size" of a hash table is the number of associations that
the table can hold at a given time.  If the number of associations in
the table exceeds the usable size, the table will automatically grow,
increasing the usable size to a new value that is sufficient to hold the
associations.

   The "physical size" is an abstract measure of a hash table that
specifies how much space is allocated to hold the associations of the
table.  The physical size is always greater than or equal to the usable
size.  The physical size is not interesting in itself; it is interesting
only for its effect on the performance of the hash table.  While the
average performance of a hash-table lookup is bounded by a constant, the
worst-case performance is not.  For a table containing a given number of
associations, increasing the physical size of the table decreases the
probability that worse-than-average performance will occur.

   The physical size of a hash table is statistically related to the
number of associations.  However, it is possible to place bounds on the
physical size, and from this to estimate the amount of space used by the
table:

     (define (hash-table-space-bounds count rehash-size rehash-threshold)
       (let ((tf (/ 1 rehash-threshold)))
         (values (if (exact-integer? rehash-size)
                     (- (* count (+ 4 tf))
                        (* tf (+ rehash-size rehash-size)))
                     (* count (+ 4 (/ tf (* rehash-size rehash-size)))))
                 (* count (+ 4 tf)))))

What this formula shows is that, for a "normal" rehash size (that is,
not an exact integer), the amount of space used by the hash table is
proportional to the number of associations in the table.  The constant
of proportionality varies statistically, with the low bound being

     (+ 4 (/ (/ 1 rehash-threshold) (* rehash-size rehash-size)))

and the high bound being

     (+ 4 (/ 1 rehash-threshold))

which, for the default values of these parameters, are '4.25' and '5',
respectively.  Reducing the rehash size will tighten these bounds, but
increases the amount of time spent resizing, so you can see that the
rehash size gives some control over the time-space tradeoff of the
table.

   The programmer can control the size of a hash table by means of three
parameters:

   * Each table's INITIAL-SIZE may be specified when the table is
     created.

   * Each table has a "rehash size" that specifies how the size of the
     table is changed when it is necessary to grow or shrink the table.

   * Each table has a "rehash threshold" that specifies the relationship
     of the table's physical size to its usable size.

   If the programmer knows that the table will initially contain a
specific number of items, INITIAL-SIZE can be given when the table is
created.  If INITIAL-SIZE is an exact non-negative integer, it specifies
the initial usable size of the hash table; the table will not change
size until the number of items in the table exceeds INITIAL-SIZE, after
which automatic resizing is enabled and INITIAL-SIZE no longer has any
effect.  Otherwise, if INITIAL-SIZE is not given or is '#f', the table
is initialized to an unspecified size and automatic resizing is
immediately enabled.

   The "rehash size" specifies how much to increase the usable size of
the hash table when it becomes full.  It is either an exact positive
integer, or a real number greater than one.  If it is an integer, the
new size is the sum of the old size and the rehash size.  Otherwise, it
is a real number, and the new size is the product of the old size and
the rehash size.  Increasing the rehash size decreases the average cost
of an insertion, but increases the average amount of space used by the
table.  The rehash size of a table may be altered dynamically by the
application in order to optimize the resizing of the table; for example,
if the table will grow quickly for a known period and afterwards will
not change size, performance might be improved by using a large rehash
size during the growth phase and a small one during the static phase.
The default rehash size of a newly constructed hash table is '2.0'.

   *Warning*: The use of an exact positive integer for a rehash size is
almost always undesirable; this option is provided solely for
compatibility with the Common Lisp hash-table mechanism.  The reason for
this has to do with the time penalty for resizing the hash table.  The
time needed to resize a hash table is proportional to the number of
associations in the table.  This resizing cost is "amortized" across the
insertions required to fill the table to the point where it needs to
grow again.  If the table grows by an amount proportional to the number
of associations, then the cost of resizing and the increase in size are
both proportional to the number of associations, so the "amortized cost"
of an insertion operation is still bounded by a constant.  However, if
the table grows by a constant amount, this is not true: the amortized
cost of an insertion is not bounded by a constant.  Thus, using a
constant rehash size means that the average cost of an insertion
increases proportionally to the number of associations in the hash
table.

   The "rehash threshold" is a real number, between zero exclusive and
one inclusive, that specifies the ratio between a hash table's usable
size and its physical size.  Decreasing the rehash threshold decreases
the probability of worse-than-average insertion, deletion, and lookup
times, but increases the physical size of the table for a given usable
size.  The default rehash threshold of a newly constructed hash table is
'1'.

 -- procedure: hash-table-grow-size hash-table
 -- obsolete procedure: hash-table/size hash-table
     Returns the usable size of HASH-TABLE as an exact positive integer.
     This is the maximum number of associations that HASH-TABLE can hold
     before it will grow.

 -- procedure: hash-table-shrink-size hash-table
     Returns the minimum number of associations that HASH-TABLE can hold
     before it will shrink.

 -- procedure: hash-table-rehash-size hash-table
 -- obsolete procedure: hash-table/rehash-size hash-table
     Returns the rehash size of HASH-TABLE.

 -- procedure: set-hash-table-rehash-size! hash-table x
 -- obsolete procedure: set-hash-table/rehash-size! hash-table x
     X must be either an exact positive integer, or a real number that
     is greater than one.  Sets the rehash size of HASH-TABLE to X and
     returns an unspecified result.  This operation adjusts the "shrink
     threshold" of the table; the table might shrink if the number of
     associations is less than the new threshold.

 -- procedure: hash-table-rehash-threshold hash-table
 -- obsolete procedure: hash-table/rehash-threshold hash-table
     Returns the rehash threshold of HASH-TABLE.

 -- procedure: set-hash-table-rehash-threshold! hash-table x
 -- obsolete procedure: set-hash-table/rehash-threshold! hash-table x
     X must be a real number between zero exclusive and one inclusive.
     Sets the rehash threshold of HASH-TABLE to X and returns an
     unspecified result.  This operation does not change the usable size
     of the table, but it usually changes the physical size of the
     table, which causes the table to be rehashed.


File: mit-scheme-ref.info,  Node: Address Hashing,  Prev: Resizing of Hash Tables,  Up: Hash Tables

11.4.4 Address Hashing
----------------------

The procedures described in this section may be used to make very
efficient key-hashing procedures for arbitrary objects.  All of these
procedures are based on "address hashing", which uses the address of an
object as its hash number.  The great advantage of address hashing is
that converting an arbitrary object to a hash number is extremely fast
and takes the same amount of time for any object.

   The disadvantage of address hashing is that the garbage collector
changes the addresses of most objects.  The hash-table implementation
compensates for this disadvantage by automatically rehashing tables that
use address hashing when garbage collections occur.  Thus, in order to
use these procedures for key hashing, it is necessary to tell the
hash-table implementation (by means of the REHASH-AFTER-GC? argument to
the hash-table type constructors) that the hash numbers computed by your
key-hashing procedure must be recomputed after a garbage collection.

 -- procedure: eq-hash object
 -- procedure: eqv-hash object
 -- procedure: equal-hash object
     These procedures return a hash number for OBJECT.  The result is
     always a non-negative integer, and in the case of 'eq-hash', a
     non-negative fixnum.  Two objects that are equivalent according to
     'eq?', 'eqv?', or 'equal?', respectively, will produce the same
     hash number when passed as arguments to these procedures, provided
     that the garbage collector does not run during or between the two
     calls.

   The following procedures are the hash functions specified by SRFI 69.

 -- procedure: hash-by-identity key [modulus]
     This procedure returns the same value as 'eq-hash', optionally
     limited by MODULUS.

 -- procedure: hash-by-eqv key [modulus]
     This procedure returns the same value as 'eqv-hash', optionally
     limited by MODULUS.

     This procedure is not specified by SRFI 69.

 -- procedure: hash-by-equal key [modulus]
     This procedure returns the same value as 'equal-hash', optionally
     limited by MODULUS.

     This procedure is called 'hash' by SRFI 69, but that name was used
     for a different purpose by MIT/GNU Scheme long before SRFI 69 was
     written.  The previous use of 'hash' has been deprecated, but it
     will be some time until it can be removed.

   The following procedures are the key-hashing procedures used by the
standard address-hash-based hash tables.  They are

 -- procedure: eq-hash-mod object modulus
     This procedure is the key-hashing procedure used by
     'make-strong-eq-hash-table'.

 -- procedure: eqv-hash-mod object modulus
     This procedure is the key-hashing procedure used by
     'make-strong-eqv-hash-table'.

 -- procedure: equal-hash-mod object modulus
     This procedure is the key-hashing procedure used by
     'make-equal-hash-table'.


File: mit-scheme-ref.info,  Node: Object Hashing,  Next: Red-Black Trees,  Prev: Hash Tables,  Up: Associations

11.5 Object Hashing
===================

The MIT/GNU Scheme object-hashing facility provides a mechanism for
generating a unique hash number for an arbitrary object.  This hash
number, unlike an object's address, is unchanged by garbage collection.
The object-hashing facility is used in the generation of the written
representation for many objects (*note Custom Output::), but it can be
used for anything that needs a stable identifier for an arbitrary
object.

   All of these procedures accept an optional argument called HASHER
which contains the object-integer associations.  If given, this argument
must be an object hasher as constructed by 'make-object-hasher' (see
below).  If not given, a default hasher is used.

 -- procedure: hash-object object [hasher]
 -- obsolete procedure: hash object [hasher]
 -- obsolete procedure: object-hash object [hasher]
     'hash-object' associates an exact non-negative integer with OBJECT
     and returns that integer.  If 'hash-object' was previously called
     with OBJECT as its argument, the integer returned is the same as
     was returned by the previous call.  'hash-object' guarantees that
     distinct objects (in the sense of 'eqv?') are associated with
     distinct integers.

 -- procedure: unhash-object k [hasher]
 -- obsolete procedure: unhash k [hasher]
 -- obsolete procedure: object-unhash k [hasher]
     'unhash-object' takes an exact non-negative integer K and returns
     the object associated with that integer.  If there is no object
     associated with K, or if the object previously associated with K
     has been reclaimed by the garbage collector, an error of type
     'condition-type:bad-range-argument' is signalled.  In other words,
     if 'hash-object' previously returned K for some object, and that
     object has not been reclaimed, it is the value of the call to
     'unhash-object'.

   An object that is passed to 'hash-object' as an argument is not
protected from being reclaimed by the garbage collector.  If all other
references to that object are eliminated, the object will be reclaimed.
Subsequently calling 'unhash-object' with the hash number of the (now
reclaimed) object will signal an error.

     (define x (cons 0 0))           =>  unspecified
     (hash-object x)                 =>  77
     (eqv? (hash-object x)
           (hash-object x))          =>  #t
     (define x 0)                    =>  unspecified
     (gc-flip)                       ;force a garbage collection
     (unhash-object 77)              error->

 -- procedure: object-hashed? object [hasher]
     This predicate is true iff OBJECT has an associated hash number.

 -- procedure: valid-object-hash? k [hasher]
 -- obsolete procedure: valid-hash-number? k [hasher]
     This predicate is true iff K is the hash number associated with
     some object.

   Finally, this procedure makes new object hashers:

 -- procedure: make-object-hasher
 -- obsolete procedure: hash-table/make
     This procedure creates and returns a new, empty object hasher that
     is suitable for use as the optional HASHER argument to the above
     procedures.  The returned hasher contains no associations.


File: mit-scheme-ref.info,  Node: Red-Black Trees,  Next: Weight-Balanced Trees,  Prev: Object Hashing,  Up: Associations

11.6 Red-Black Trees
====================

Balanced binary trees are a useful data structure for maintaining large
sets of associations whose keys are ordered.  While most applications
involving large association sets should use hash tables, some
applications can benefit from the use of binary trees.  Binary trees
have two advantages over hash tables:

   * The contents of a binary tree can be converted to an alist, sorted
     by key, in time proportional to the number of associations in the
     tree.  A hash table can be converted into an unsorted alist in
     linear time; sorting it requires additional time.

   * Two binary trees can be compared for equality in linear time.  Hash
     tables, on the other hand, cannot be compared at all; they must be
     converted to alists before comparison can be done, and alist
     comparison is quadratic unless the alists are sorted.

   MIT/GNU Scheme provides an implementation of "red-black" trees.  The
red-black tree-balancing algorithm provides generally good performance
because it doesn't try to keep the tree very closely balanced.  At any
given node in the tree, one side of the node can be twice as high as the
other in the worst case.  With typical data the tree will remain fairly
well balanced anyway.

   A red-black tree takes space that is proportional to the number of
associations in the tree.  For the current implementation, the constant
of proportionality is eight words per association.

   Red-black trees hold their keys "strongly".  In other words, if a
red-black tree contains an association for a given key, that key cannot
be reclaimed by the garbage collector.

   The red-black tree implementation is a run-time-loadable option.  To
use red-black trees, execute

     (load-option 'rb-tree)

once before calling any of the procedures defined here.

 -- procedure: make-rb-tree key=? key<?
     This procedure creates and returns a newly allocated red-black
     tree.  The tree contains no associations.  KEY=? and KEY<? are
     predicates that compare two keys and determine whether they are
     equal to or less than one another, respectively.  For any two keys,
     at most one of these predicates is true.

 -- procedure: rb-tree? object
     Returns '#t' if OBJECT is a red-black tree, otherwise returns '#f'.

 -- procedure: rb-tree/insert! rb-tree key datum
     Associates DATUM with KEY in RB-TREE and returns an unspecified
     value.  If RB-TREE already has an association for KEY, that
     association is replaced.  The average and worst-case times required
     by this operation are proportional to the logarithm of the number
     of assocations in RB-TREE.

 -- procedure: rb-tree/lookup rb-tree key default
     Returns the datum associated with KEY in RB-TREE.  If RB-TREE
     doesn't contain an association for KEY, DEFAULT is returned.  The
     average and worst-case times required by this operation are
     proportional to the logarithm of the number of assocations in
     RB-TREE.

 -- procedure: rb-tree/delete! rb-tree key
     If RB-TREE contains an association for KEY, removes it.  Returns an
     unspecified value.  The average and worst-case times required by
     this operation are proportional to the logarithm of the number of
     assocations in RB-TREE.

 -- procedure: rb-tree->alist rb-tree
     Returns the contents of RB-TREE as a newly allocated alist.  Each
     element of the alist is a pair '(KEY . DATUM)' where KEY is one of
     the keys of RB-TREE, and DATUM is its associated datum.  The alist
     is sorted by key according to the KEY<? argument used to construct
     RB-TREE.  The time required by this operation is proportional to
     the number of associations in the tree.

 -- procedure: rb-tree/key-list rb-tree
     Returns a newly allocated list of the keys in RB-TREE.  The list is
     sorted by key according to the KEY<? argument used to construct
     RB-TREE.  The time required by this operation is proportional to
     the number of associations in the tree.

 -- procedure: rb-tree/datum-list rb-tree
     Returns a newly allocated list of the datums in RB-TREE.  Each
     element of the list corresponds to one of the associations in
     RB-TREE, so if the tree contains multiple associations with the
     same datum, so will this list.  The list is sorted by the keys of
     the associations, even though they do not appear in the result.
     The time required by this operation is proportional to the number
     of associations in the tree.

     This procedure is equivalent to:

          (lambda (rb-tree) (map cdr (rb-tree->alist rb-tree)))

 -- procedure: rb-tree/equal? rb-tree-1 rb-tree-2 datum=?
     Compares RB-TREE-1 and RB-TREE-2 for equality, returning '#t' iff
     they are equal and '#f' otherwise.  The trees must have been
     constructed with the same equality and order predicates (same in
     the sense of 'eq?').  The keys of the trees are compared using the
     KEY=? predicate used to build the trees, while the datums of the
     trees are compared using the equivalence predicate DATUM=?.  The
     worst-case time required by this operation is proportional to the
     number of associations in the tree.

 -- procedure: rb-tree/empty? rb-tree
     Returns '#t' iff RB-TREE contains no associations.  Otherwise
     returns '#f'.

 -- procedure: rb-tree/size rb-tree
     Returns the number of associations in RB-TREE, an exact
     non-negative integer.  The average and worst-case times required by
     this operation are proportional to the number of associations in
     the tree.

 -- procedure: rb-tree/height rb-tree
     Returns the height of RB-TREE, an exact non-negative integer.  This
     is the length of the longest path from a leaf of the tree to the
     root.  The average and worst-case times required by this operation
     are proportional to the number of associations in the tree.

     The returned value satisfies the following:

          (lambda (rb-tree)
            (let ((size (rb-tree/size rb-tree))
                  (lg (lambda (x) (/ (log x) (log 2)))))
              (<= (lg size)
                  (rb-tree/height rb-tree)
                  (* 2 (lg (+ size 1))))))

 -- procedure: rb-tree/copy rb-tree
     Returns a newly allocated copy of RB-TREE.  The copy is identical
     to RB-TREE in all respects, except that changes to RB-TREE do not
     affect the copy, and vice versa.  The time required by this
     operation is proportional to the number of associations in the
     tree.

 -- procedure: alist->rb-tree alist key=? key<?
     Returns a newly allocated red-black tree that contains the same
     associations as ALIST.  This procedure is equivalent to:

          (lambda (alist key=? key<?)
            (let ((tree (make-rb-tree key=? key<?)))
              (for-each (lambda (association)
                          (rb-tree/insert! tree
                                           (car association)
                                           (cdr association)))
                        alist)
              tree))

   The following operations provide access to the smallest and largest
members in a red/black tree.  They are useful for implementing priority
queues.

 -- procedure: rb-tree/min rb-tree default
     Returns the smallest key in RB-TREE, or DEFAULT if the tree is
     empty.

 -- procedure: rb-tree/min-datum rb-tree default
     Returns the datum associated with the smallest key in RB-TREE, or
     DEFAULT if the tree is empty.

 -- procedure: rb-tree/min-pair rb-tree
     Finds the smallest key in RB-TREE and returns a pair containing
     that key and its associated datum.  If the tree is empty, returns
     '#f'.

 -- procedure: rb-tree/max rb-tree default
     Returns the largest key in RB-TREE, or DEFAULT if the tree is
     empty.

 -- procedure: rb-tree/max-datum rb-tree default
     Returns the datum associated with the largest key in RB-TREE, or
     DEFAULT if the tree is empty.

 -- procedure: rb-tree/max-pair rb-tree
     Finds the largest key in RB-TREE and returns a pair containing that
     key and its associated datum.  If the tree is empty, returns '#f'.

 -- procedure: rb-tree/delete-min! rb-tree default
 -- procedure: rb-tree/delete-min-datum! rb-tree default
 -- procedure: rb-tree/delete-min-pair! rb-tree
 -- procedure: rb-tree/delete-max! rb-tree default
 -- procedure: rb-tree/delete-max-datum! rb-tree default
 -- procedure: rb-tree/delete-max-pair! rb-tree
     These operations are exactly like the accessors above, in that they
     return information associated with the smallest or largest key,
     except that they simultaneously delete that key.


File: mit-scheme-ref.info,  Node: Weight-Balanced Trees,  Prev: Red-Black Trees,  Up: Associations

11.7 Weight-Balanced Trees
==========================

Balanced binary trees are a useful data structure for maintaining large
sets of ordered objects or sets of associations whose keys are ordered.
MIT/GNU Scheme has a comprehensive implementation of weight-balanced
binary trees which has several advantages over the other data structures
for large aggregates:

   * In addition to the usual element-level operations like insertion,
     deletion and lookup, there is a full complement of collection-level
     operations, like set intersection, set union and subset test, all
     of which are implemented with good orders of growth in time and
     space.  This makes weight-balanced trees ideal for rapid
     prototyping of functionally derived specifications.

   * An element in a tree may be indexed by its position under the
     ordering of the keys, and the ordinal position of an element may be
     determined, both with reasonable efficiency.

   * Operations to find and remove minimum element make weight-balanced
     trees simple to use for priority queues.

   * The implementation is _functional_ rather than _imperative_.  This
     means that operations like 'inserting' an association in a tree do
     not destroy the old tree, in much the same way that '(+ 1 x)'
     modifies neither the constant 1 nor the value bound to 'x'.  The
     trees are referentially transparent thus the programmer need not
     worry about copying the trees.  Referential transparency allows
     space efficiency to be achieved by sharing subtrees.

   These features make weight-balanced trees suitable for a wide range
of applications, especially those that require large numbers of sets or
discrete maps.  Applications that have a few global databases and/or
concentrate on element-level operations like insertion and lookup are
probably better off using hash tables or red-black trees.

   The _size_ of a tree is the number of associations that it contains.
Weight-balanced binary trees are balanced to keep the sizes of the
subtrees of each node within a constant factor of each other.  This
ensures logarithmic times for single-path operations (like lookup and
insertion).  A weight-balanced tree takes space that is proportional to
the number of associations in the tree.  For the current implementation,
the constant of proportionality is six words per association.

   Weight-balanced trees can be used as an implementation for either
discrete sets or discrete maps (associations).  Sets are implemented by
ignoring the datum that is associated with the key.  Under this scheme
if an association exists in the tree this indicates that the key of the
association is a member of the set.  Typically a value such as '()',
'#t' or '#f' is associated with the key.

   Many operations can be viewed as computing a result that, depending
on whether the tree arguments are thought of as sets or maps, is known
by two different names.  An example is 'wt-tree/member?', which, when
regarding the tree argument as a set, computes the set membership
operation, but, when regarding the tree as a discrete map,
'wt-tree/member?' is the predicate testing if the map is defined at an
element in its domain.  Most names in this package have been chosen
based on interpreting the trees as sets, hence the name
'wt-tree/member?' rather than 'wt-tree/defined-at?'.

   The weight-balanced tree implementation is a run-time-loadable
option.  To use weight-balanced trees, execute

     (load-option 'wt-tree)

once before calling any of the procedures defined here.

* Menu:

* Construction of Weight-Balanced Trees::
* Basic Operations on Weight-Balanced Trees::
* Advanced Operations on Weight-Balanced Trees::
* Indexing Operations on Weight-Balanced Trees::


File: mit-scheme-ref.info,  Node: Construction of Weight-Balanced Trees,  Next: Basic Operations on Weight-Balanced Trees,  Prev: Weight-Balanced Trees,  Up: Weight-Balanced Trees

11.7.1 Construction of Weight-Balanced Trees
--------------------------------------------

Binary trees require there to be a total order on the keys used to
arrange the elements in the tree.  Weight-balanced trees are organized
by _types_, where the type is an object encapsulating the ordering
relation.  Creating a tree is a two-stage process.  First a tree type
must be created from the predicate that gives the ordering.  The tree
type is then used for making trees, either empty or singleton trees or
trees from other aggregate structures like association lists.  Once
created, a tree 'knows' its type and the type is used to test
compatibility between trees in operations taking two trees.  Usually a
small number of tree types are created at the beginning of a program and
used many times throughout the program's execution.

 -- procedure: make-wt-tree-type key<?
     This procedure creates and returns a new tree type based on the
     ordering predicate KEY<?.  KEY<? must be a total ordering, having
     the property that for all key values 'a', 'b' and 'c':

          (key<? a a)                         => #f
          (and (key<? a b) (key<? b a))       => #f
          (if (and (key<? a b) (key<? b c))
              (key<? a c)
              #t)                             => #t

     Two key values are assumed to be equal if neither is less than the
     other by KEY<?.

     Each call to 'make-wt-tree-type' returns a distinct value, and
     trees are only compatible if their tree types are 'eq?'.  A
     consequence is that trees that are intended to be used in
     binary-tree operations must all be created with a tree type
     originating from the same call to 'make-wt-tree-type'.

 -- variable: number-wt-type
     A standard tree type for trees with numeric keys.  'Number-wt-type'
     could have been defined by

          (define number-wt-type (make-wt-tree-type  <))

 -- variable: string-wt-type
     A standard tree type for trees with string keys.  'String-wt-type'
     could have been defined by

          (define string-wt-type (make-wt-tree-type  string<?))

 -- procedure: make-wt-tree wt-tree-type
     This procedure creates and returns a newly allocated
     weight-balanced tree.  The tree is empty, i.e.  it contains no
     associations.  WT-TREE-TYPE is a weight-balanced tree type obtained
     by calling 'make-wt-tree-type'; the returned tree has this type.

 -- procedure: singleton-wt-tree wt-tree-type key datum
     This procedure creates and returns a newly allocated
     weight-balanced tree.  The tree contains a single association, that
     of DATUM with KEY.  WT-TREE-TYPE is a weight-balanced tree type
     obtained by calling 'make-wt-tree-type'; the returned tree has this
     type.

 -- procedure: alist->wt-tree tree-type alist
     Returns a newly allocated weight-balanced tree that contains the
     same associations as ALIST.  This procedure is equivalent to:

          (lambda (type alist)
            (let ((tree (make-wt-tree type)))
              (for-each (lambda (association)
                          (wt-tree/add! tree
                                        (car association)
                                        (cdr association)))
                        alist)
              tree))


File: mit-scheme-ref.info,  Node: Basic Operations on Weight-Balanced Trees,  Next: Advanced Operations on Weight-Balanced Trees,  Prev: Construction of Weight-Balanced Trees,  Up: Weight-Balanced Trees

11.7.2 Basic Operations on Weight-Balanced Trees
------------------------------------------------

This section describes the basic tree operations on weight-balanced
trees.  These operations are the usual tree operations for insertion,
deletion and lookup, some predicates and a procedure for determining the
number of associations in a tree.

 -- procedure: wt-tree? object
     Returns '#t' if OBJECT is a weight-balanced tree, otherwise returns
     '#f'.

 -- procedure: wt-tree/empty? wt-tree
     Returns '#t' if WT-TREE contains no associations, otherwise returns
     '#f'.

 -- procedure: wt-tree/size wt-tree
     Returns the number of associations in WT-TREE, an exact
     non-negative integer.  This operation takes constant time.

 -- procedure: wt-tree/add wt-tree key datum
     Returns a new tree containing all the associations in WT-TREE and
     the association of DATUM with KEY.  If WT-TREE already had an
     association for KEY, the new association overrides the old.  The
     average and worst-case times required by this operation are
     proportional to the logarithm of the number of associations in
     WT-TREE.

 -- procedure: wt-tree/add! wt-tree key datum
     Associates DATUM with KEY in WT-TREE and returns an unspecified
     value.  If WT-TREE already has an association for KEY, that
     association is replaced.  The average and worst-case times required
     by this operation are proportional to the logarithm of the number
     of associations in WT-TREE.

 -- procedure: wt-tree/member? key wt-tree
     Returns '#t' if WT-TREE contains an association for KEY, otherwise
     returns '#f'.  The average and worst-case times required by this
     operation are proportional to the logarithm of the number of
     associations in WT-TREE.

 -- procedure: wt-tree/lookup wt-tree key default
     Returns the datum associated with KEY in WT-TREE.  If WT-TREE
     doesn't contain an association for KEY, DEFAULT is returned.  The
     average and worst-case times required by this operation are
     proportional to the logarithm of the number of associations in
     WT-TREE.

 -- procedure: wt-tree/delete wt-tree key
     Returns a new tree containing all the associations in WT-TREE,
     except that if WT-TREE contains an association for KEY, it is
     removed from the result.  The average and worst-case times required
     by this operation are proportional to the logarithm of the number
     of associations in WT-TREE.

 -- procedure: wt-tree/delete! wt-tree key
     If WT-TREE contains an association for KEY the association is
     removed.  Returns an unspecified value.  The average and worst-case
     times required by this operation are proportional to the logarithm
     of the number of associations in WT-TREE.


File: mit-scheme-ref.info,  Node: Advanced Operations on Weight-Balanced Trees,  Next: Indexing Operations on Weight-Balanced Trees,  Prev: Basic Operations on Weight-Balanced Trees,  Up: Weight-Balanced Trees

11.7.3 Advanced Operations on Weight-Balanced Trees
---------------------------------------------------

In the following the _size_ of a tree is the number of associations that
the tree contains, and a _smaller_ tree contains fewer associations.

 -- procedure: wt-tree/split< wt-tree bound
     Returns a new tree containing all and only the associations in
     WT-TREE that have a key that is less than BOUND in the ordering
     relation of the tree type of WT-TREE.  The average and worst-case
     times required by this operation are proportional to the logarithm
     of the size of WT-TREE.

 -- procedure: wt-tree/split> wt-tree bound
     Returns a new tree containing all and only the associations in
     WT-TREE that have a key that is greater than BOUND in the ordering
     relation of the tree type of WT-TREE.  The average and worst-case
     times required by this operation are proportional to the logarithm
     of the size of WT-TREE.

 -- procedure: wt-tree/union wt-tree-1 wt-tree-2
     Returns a new tree containing all the associations from both trees.
     This operation is asymmetric: when both trees have an association
     for the same key, the returned tree associates the datum from
     WT-TREE-2 with the key.  Thus if the trees are viewed as discrete
     maps then 'wt-tree/union' computes the map override of WT-TREE-1 by
     WT-TREE-2.  If the trees are viewed as sets the result is the set
     union of the arguments.  The worst-case time required by this
     operation is proportional to the sum of the sizes of both trees.
     If the minimum key of one tree is greater than the maximum key of
     the other tree then the worst-case time required is proportional to
     the logarithm of the size of the larger tree.

 -- procedure: wt-tree/intersection wt-tree-1 wt-tree-2
     Returns a new tree containing all and only those associations from
     WT-TREE-1 that have keys appearing as the key of an association in
     WT-TREE-2.  Thus the associated data in the result are those from
     WT-TREE-1.  If the trees are being used as sets the result is the
     set intersection of the arguments.  As a discrete map operation,
     'wt-tree/intersection' computes the domain restriction of WT-TREE-1
     to (the domain of) WT-TREE-2.  The worst-case time required by this
     operation is proportional to the sum of the sizes of the trees.

 -- procedure: wt-tree/difference wt-tree-1 wt-tree-2
     Returns a new tree containing all and only those associations from
     WT-TREE-1 that have keys that _do not_ appear as the key of an
     association in WT-TREE-2.  If the trees are viewed as sets the
     result is the asymmetric set difference of the arguments.  As a
     discrete map operation, it computes the domain restriction of
     WT-TREE-1 to the complement of (the domain of) WT-TREE-2.  The
     worst-case time required by this operation is proportional to the
     sum of the sizes of the trees.

 -- procedure: wt-tree/subset? wt-tree-1 wt-tree-2
     Returns '#t' iff the key of each association in WT-TREE-1 is the
     key of some association in WT-TREE-2, otherwise returns '#f'.
     Viewed as a set operation, 'wt-tree/subset?' is the improper subset
     predicate.  A proper subset predicate can be constructed:

          (define (proper-subset? s1 s2)
            (and (wt-tree/subset? s1 s2)
                 (< (wt-tree/size s1) (wt-tree/size s2))))

     As a discrete map operation, 'wt-tree/subset?' is the subset test
     on the domain(s) of the map(s).  In the worst-case the time
     required by this operation is proportional to the size of
     WT-TREE-1.

 -- procedure: wt-tree/set-equal? wt-tree-1 wt-tree-2
     Returns '#t' iff for every association in WT-TREE-1 there is an
     association in WT-TREE-2 that has the same key, and _vice versa_.

     Viewing the arguments as sets, 'wt-tree/set-equal?' is the set
     equality predicate.  As a map operation it determines if two maps
     are defined on the same domain.

     This procedure is equivalent to

          (lambda (wt-tree-1 wt-tree-2)
            (and (wt-tree/subset? wt-tree-1 wt-tree-2
                 (wt-tree/subset? wt-tree-2 wt-tree-1)))

     In the worst case the time required by this operation is
     proportional to the size of the smaller tree.

 -- procedure: wt-tree/fold combiner initial wt-tree
     This procedure reduces WT-TREE by combining all the associations,
     using an reverse in-order traversal, so the associations are
     visited in reverse order.  COMBINER is a procedure of three
     arguments: a key, a datum and the accumulated result so far.
     Provided COMBINER takes time bounded by a constant, 'wt-tree/fold'
     takes time proportional to the size of WT-TREE.

     A sorted association list can be derived simply:

          (wt-tree/fold (lambda (key datum list)
                          (cons (cons key datum) list))
                        '()
                        WT-TREE))

     The data in the associations can be summed like this:

          (wt-tree/fold (lambda (key datum sum) (+ sum datum))
                        0
                        WT-TREE)

 -- procedure: wt-tree/for-each action wt-tree
     This procedure traverses WT-TREE in order, applying ACTION to each
     association.  The associations are processed in increasing order of
     their keys.  ACTION is a procedure of two arguments that takes the
     key and datum respectively of the association.  Provided ACTION
     takes time bounded by a constant, 'wt-tree/for-each' takes time
     proportional to the size of WT-TREE.  The example prints the tree:

          (wt-tree/for-each (lambda (key value)
                              (display (list key value)))
                            WT-TREE))

 -- procedure: wt-tree/union-merge wt-tree-1 wt-tree-2 merge
     Returns a new tree containing all the associations from both trees.
     If both trees have an association for the same key, the datum
     associated with that key in the result tree is computed by applying
     the procedure MERGE to the key, the value from WT-TREE-1 and the
     value from WT-TREE-2.  MERGE is of the form

          (lambda (KEY DATUM-1 DATUM-2) ...)

     If some key occurs only in one tree, that association will appear
     in the result tree without being processed by MERGE, so for this
     operation to make sense, either MERGE must have both a right and
     left identity that correspond to the association being absent in
     one of the trees, or some guarantee must be made, for example, all
     the keys in one tree are known to occur in the other.

     These are all reasonable procedures for MERGE

          (lambda (key val1 val2) (+ val1 val2))
          (lambda (key val1 val2) (append val1 val2))
          (lambda (key val1 val2) (wt-tree/union val1 val2))

     However, a procedure like

          (lambda (key val1 val2) (- val1 val2))

     would result in a subtraction of the data for all associations with
     keys occuring in both trees but associations with keys occuring in
     only the second tree would be copied, not negated, as is presumably
     be intent.  The programmer might ensure that this never happens.

     This procedure has the same time behavior as 'wt-tree/union' but
     with a slightly worse constant factor.  Indeed, 'wt-tree/union'
     might have been defined like this:

          (define (wt-tree/union tree1 tree2)
            (wt-tree/union-merge tree1 tree2
                                 (lambda (key val1 val2) val2)))

   The MERGE procedure takes the KEY as a parameter in case the data are
not independent of the key.


File: mit-scheme-ref.info,  Node: Indexing Operations on Weight-Balanced Trees,  Prev: Advanced Operations on Weight-Balanced Trees,  Up: Weight-Balanced Trees

11.7.4 Indexing Operations on Weight-Balanced Trees
---------------------------------------------------

Weight-balanced trees support operations that view the tree as sorted
sequence of associations.  Elements of the sequence can be accessed by
position, and the position of an element in the sequence can be
determined, both in logarthmic time.

 -- procedure: wt-tree/index wt-tree index
 -- procedure: wt-tree/index-datum wt-tree index
 -- procedure: wt-tree/index-pair wt-tree index
     Returns the 0-based INDEXth association of WT-TREE in the sorted
     sequence under the tree's ordering relation on the keys.
     'wt-tree/index' returns the INDEXth key, 'wt-tree/index-datum'
     returns the datum associated with the INDEXth key and
     'wt-tree/index-pair' returns a new pair '(KEY . DATUM)' which is
     the 'cons' of the INDEXth key and its datum.  The average and
     worst-case times required by this operation are proportional to the
     logarithm of the number of associations in the tree.

     These operations signal a condition of type
     'condition-type:bad-range-argument' if INDEX'<0' or if INDEX is
     greater than or equal to the number of associations in the tree.
     If the tree is empty, they signal an anonymous error.

     Indexing can be used to find the median and maximum keys in the
     tree as follows:

          median:   (wt-tree/index WT-TREE
                                   (quotient (wt-tree/size WT-TREE)
                                             2))
          maximum:  (wt-tree/index WT-TREE
                                   (- (wt-tree/size WT-TREE)
                                      1))

 -- procedure: wt-tree/rank wt-tree key
     Determines the 0-based position of KEY in the sorted sequence of
     the keys under the tree's ordering relation, or '#f' if the tree
     has no association with for KEY.  This procedure returns either an
     exact non-negative integer or '#f'.  The average and worst-case
     times required by this operation are proportional to the logarithm
     of the number of associations in the tree.

 -- procedure: wt-tree/min wt-tree
 -- procedure: wt-tree/min-datum wt-tree
 -- procedure: wt-tree/min-pair wt-tree
     Returns the association of WT-TREE that has the least key under the
     tree's ordering relation.  'wt-tree/min' returns the least key,
     'wt-tree/min-datum' returns the datum associated with the least key
     and 'wt-tree/min-pair' returns a new pair '(key . datum)' which is
     the 'cons' of the minimum key and its datum.  The average and
     worst-case times required by this operation are proportional to the
     logarithm of the number of associations in the tree.

     These operations signal an error if the tree is empty.  They could
     have been written

          (define (wt-tree/min tree)
            (wt-tree/index tree 0))
          (define (wt-tree/min-datum tree)
            (wt-tree/index-datum tree 0))
          (define (wt-tree/min-pair tree)
            (wt-tree/index-pair tree 0))

 -- procedure: wt-tree/delete-min wt-tree
     Returns a new tree containing all of the associations in WT-TREE
     except the association with the least key under the WT-TREE's
     ordering relation.  An error is signalled if the tree is empty.
     The average and worst-case times required by this operation are
     proportional to the logarithm of the number of associations in the
     tree.  This operation is equivalent to

          (wt-tree/delete WT-TREE (wt-tree/min WT-TREE))

 -- procedure: wt-tree/delete-min! wt-tree
     Removes the association with the least key under the WT-TREE's
     ordering relation.  An error is signalled if the tree is empty.
     The average and worst-case times required by this operation are
     proportional to the logarithm of the number of associations in the
     tree.  This operation is equivalent to

          (wt-tree/delete! WT-TREE (wt-tree/min WT-TREE))


File: mit-scheme-ref.info,  Node: Procedures,  Next: Environments,  Prev: Associations,  Up: Top

12 Procedures
*************

Procedures are created by evaluating 'lambda' expressions (*note Lambda
Expressions::); the 'lambda' may either be explicit or may be implicit
as in a "procedure 'define'" (*note Definitions::).  Also there are
special built-in procedures, called "primitive procedures", such as
'car'; these procedures are not written in Scheme but in the language
used to implement the Scheme system.  MIT/GNU Scheme also provides
"application hooks", which support the construction of data structures
that act like procedures.

   In MIT/GNU Scheme, the written representation of a procedure tells
you the type of the procedure (compiled, interpreted, or primitive):

     pp
          =>  #[compiled-procedure 56 ("pp" #x2) #x10 #x307578]
     (lambda (x) x)
          =>  #[compound-procedure 57]
     (define (foo x) x)
     foo
          =>  #[compound-procedure 58 foo]
     car
          =>  #[primitive-procedure car]
     (call-with-current-continuation (lambda (x) x))
          =>  #[continuation 59]

Note that interpreted procedures are called "compound" procedures
(strictly speaking, compiled procedures are also compound procedures).
The written representation makes this distinction for historical
reasons, and may eventually change.

* Menu:

* Procedure Operations::
* Arity::
* Primitive Procedures::
* Continuations::
* Application Hooks::


File: mit-scheme-ref.info,  Node: Procedure Operations,  Next: Arity,  Prev: Procedures,  Up: Procedures

12.1 Procedure Operations
=========================

 -- procedure: apply procedure object object ...
     Calls PROCEDURE with the elements of the following list as
     arguments:

          (cons* OBJECT OBJECT ...)

     The initial OBJECTs may be any objects, but the last OBJECT (there
     must be at least one OBJECT) must be a list.

          (apply + (list 3 4 5 6))                =>  18
          (apply + 3 4 '(5 6))                    =>  18

          (define compose
            (lambda (f g)
              (lambda args
                (f (apply g args)))))
          ((compose sqrt *) 12 75)                =>  30

 -- procedure: procedure? object
     Returns '#t' if OBJECT is a procedure; otherwise returns '#f'.  If
     '#t' is returned, exactly one of the following predicates is
     satisfied by OBJECT: 'compiled-procedure?', 'compound-procedure?',
     or 'primitive-procedure?'.

 -- procedure: compiled-procedure? object
     Returns '#t' if OBJECT is a compiled procedure; otherwise returns
     '#f'.

 -- procedure: compound-procedure? object
     Returns '#t' if OBJECT is a compound (i.e. interpreted) procedure;
     otherwise returns '#f'.

 -- procedure: primitive-procedure? object
     Returns '#t' if OBJECT is a primitive procedure; otherwise returns
     '#f'.

 -- procedure: procedure-environment procedure
     Returns the closing environment of PROCEDURE.  Signals an error if
     PROCEDURE is a primitive procedure, or if PROCEDURE is a compiled
     procedure for which the debugging information is unavailable.


File: mit-scheme-ref.info,  Node: Arity,  Next: Primitive Procedures,  Prev: Procedure Operations,  Up: Procedures

12.2 Arity
==========

Each procedure has an "arity", which is the minimum and (optionally)
maximum number of arguments that it will accept.  MIT/GNU Scheme
provides an abstraction that represents arity, and tests for the
apparent arity of a procedure.

   Arity objects come in two forms: the simple form, an exact
non-negative integer, represents a fixed number of arguments.  The
general form is a pair whose 'car' represents the minimum number of
arguments and whose 'cdr' is the maximum number of arguments.

 -- procedure: make-procedure-arity min [max [simple-ok?]]
     Returns an arity object made from MIN and MAX.  MIN must be an
     exact non-negative integer.  MAX must be an exact non-negative
     integer at least as large as MIN.  Alternatively, MAX may be
     omitted or given as '#f', which represents an arity with no upper
     bound.

     If SIMPLE-OK? is true, the returned arity is in the simple form (an
     exact non-negative integer) when possible, and otherwise is always
     in the general form.  SIMPLE-OK? defaults to '#f'.

 -- procedure: procedure-arity? object
     Returns '#t' if OBJECT is an arity object, and '#f' otherwise.

 -- procedure: procedure-arity-min arity
 -- procedure: procedure-arity-max arity
     Return the lower and upper bounds of ARITY, respectively.

   The following procedures test for the apparent arity of a procedure.
The results of the test may be less restrictive than the effect of
calling the procedure.  In other words, these procedures may indicate
that the procedure will accept a given number of arguments, but if you
call the procedure it may signal a
'condition-type:wrong-number-of-arguments' error.  For example, here is
a procedure that appears to accept any number of arguments, but when
called will signal an error if the number of arguments is not one:

     (lambda arguments (apply car arguments))

 -- procedure: procedure-arity procedure
     Returns the arity that PROCEDURE accepts.  The result may be in
     either simple or general form.

          (procedure-arity (lambda () 3))         =>  (0 . 0)
          (procedure-arity (lambda (x) x))        =>  (1 . 1)
          (procedure-arity car)                   =>  (1 . 1)
          (procedure-arity (lambda x x))          =>  (0 . #f)
          (procedure-arity (lambda (x . y) x))    =>  (1 . #f)
          (procedure-arity (lambda (x #!optional y) x))
                                                  =>  (1 . 2)

 -- procedure: procedure-arity-valid? procedure arity
     Returns '#t' if PROCEDURE accepts ARITY, and '#f' otherwise.

 -- procedure: procedure-of-arity? object arity
     Returns '#t' if OBJECT is a procedure that accepts ARITY, and '#f'
     otherwise.  Equivalent to:

          (and (procedure? OBJECT)
               (procedure-arity-valid? OBJECT ARITY))

 -- procedure: guarantee-procedure-of-arity object arity caller
     Signals an error if OBJECT is not a procedure accepting ARITY.
     CALLER is a symbol that is printed as part of the error message and
     is intended to be the name of the procedure where the error occurs.

 -- procedure: thunk? object
     Returns '#t' if OBJECT is a procedure that accepts zero arguments,
     and '#f' otherwise.  Equivalent to:

          (procedure-of-arity? OBJECT 0)


File: mit-scheme-ref.info,  Node: Primitive Procedures,  Next: Continuations,  Prev: Arity,  Up: Procedures

12.3 Primitive Procedures
=========================

 -- procedure: make-primitive-procedure name [arity]
     NAME must be a symbol.  ARITY must be an exact non-negative
     integer, '-1', '#f', or '#t'; if not supplied it defaults to '#f'.
     Returns the primitive procedure called NAME.  May perform further
     actions depending on ARITY:

     '#f'
          If the primitive procedure is not implemented, signals an
          error.

     '#t'
          If the primitive procedure is not implemented, returns '#f'.

     integer
          If the primitive procedure is implemented, signals an error if
          its arity is not equal to ARITY.  If the primitive procedure
          is not implemented, returns an unimplemented primitive
          procedure object that accepts ARITY arguments.  An ARITY of
          '-1' means it accepts any number of arguments.

 -- procedure: primitive-procedure-name primitive-procedure
     Returns the name of PRIMITIVE-PROCEDURE, a symbol.

          (primitive-procedure-name car)          =>  car

 -- procedure: implemented-primitive-procedure? primitive-procedure
     Returns '#t' if PRIMITIVE-PROCEDURE is implemented; otherwise
     returns '#f'.  Useful because the code that implements a particular
     primitive procedure is not necessarily linked into the executable
     Scheme program.


File: mit-scheme-ref.info,  Node: Continuations,  Next: Application Hooks,  Prev: Primitive Procedures,  Up: Procedures

12.4 Continuations
==================

 -- procedure: call-with-current-continuation procedure
     PROCEDURE must be a procedure of one argument.  Packages up the
     current continuation (see below) as an "escape procedure" and
     passes it as an argument to PROCEDURE.  The escape procedure is a
     Scheme procedure of one argument that, if it is later passed a
     value, will ignore whatever continuation is in effect at that later
     time and will give the value instead to the continuation that was
     in effect when the escape procedure was created.  The escape
     procedure created by 'call-with-current-continuation' has unlimited
     extent just like any other procedure in Scheme.  It may be stored
     in variables or data structures and may be called as many times as
     desired.

     The following examples show only the most common uses of this
     procedure.  If all real programs were as simple as these examples,
     there would be no need for a procedure with the power of
     'call-with-current-continuation'.

          (call-with-current-continuation
            (lambda (exit)
              (for-each (lambda (x)
                          (if (negative? x)
                              (exit x)))
                        '(54 0 37 -3 245 19))
              #t))                                =>  -3

          (define list-length
            (lambda (obj)
              (call-with-current-continuation
                (lambda (return)
                  (letrec ((r
                            (lambda (obj)
                              (cond ((null? obj) 0)
                                    ((pair? obj) (+ (r (cdr obj)) 1))
                                    (else (return #f))))))
                    (r obj))))))
          (list-length '(1 2 3 4))                =>  4
          (list-length '(a b . c))                =>  #f

     A common use of 'call-with-current-continuation' is for structured,
     non-local exits from loops or procedure bodies, but in fact
     'call-with-current-continuation' is quite useful for implementing a
     wide variety of advanced control structures.

     Whenever a Scheme expression is evaluated a continuation exists
     that wants the result of the expression.  The continuation
     represents an entire (default) future for the computation.  If the
     expression is evaluated at top level, for example, the continuation
     will take the result, print it on the screen, prompt for the next
     input, evaluate it, and so on forever.  Most of the time the
     continuation includes actions specified by user code, as in a
     continuation that will take the result, multiply it by the value
     stored in a local variable, add seven, and give the answer to the
     top-level continuation to be printed.  Normally these ubiquitous
     continuations are hidden behind the scenes and programmers don't
     think much about them.  On the rare occasions that you may need to
     deal explicitly with continuations,
     'call-with-current-continuation' lets you do so by creating a
     procedure that acts just like the current continuation.

 -- procedure: continuation? object
     Returns '#t' if OBJECT is a continuation; otherwise returns '#f'.

 -- procedure: within-continuation continuation thunk
     THUNK must be a procedure of no arguments.  Conceptually,
     'within-continuation' invokes CONTINUATION on the result of
     invoking THUNK, but THUNK is executed in the dynamic state of
     CONTINUATION.  In other words, the "current" continuation is
     abandoned before THUNK is invoked.

 -- procedure: dynamic-wind before thunk after
     Calls THUNK without arguments, returning the result(s) of this
     call.  BEFORE and AFTER are called, also without arguments, as
     required by the following rules.  Note that in the absence of calls
     to continuations captured using 'call-with-current-continuation'
     the three arguments are called once each, in order.  BEFORE is
     called whenever execution enters the dynamic extent of the call to
     THUNK and AFTER is called whenever it exits that dynamic extent.
     The dynamic extent of a procedure call is the period between when
     the call is initiated and when it returns.  In Scheme, because of
     'call-with-current-continuation', the dynamic extent of a call may
     not be a single, connected time period.  It is defined as follows:

        * The dynamic extent is entered when execution of the body of
          the called procedure begins.

        * The dynamic extent is also entered when execution is not
          within the dynamic extent and a continuation is invoked that
          was captured (using 'call-with-current-continuation') during
          the dynamic extent.

        * It is exited when the called procedure returns.

        * It is also exited when execution is within the dynamic extent
          and a continuation is invoked that was captured while not
          within the dynamic extent.

     If a second call to 'dynamic-wind' occurs within the dynamic extent
     of the call to THUNK and then a continuation is invoked in such a
     way that the AFTERs from these two invocations of 'dynamic-wind'
     are both to be called, then the AFTER associated with the second
     (inner) call to 'dynamic-wind' is called first.

     If a second call to 'dynamic-wind' occurs within the dynamic extent
     of the call to THUNK and then a continuation is invoked in such a
     way that the BEFOREs from these two invocations of 'dynamic-wind'
     are both to be called, then the BEFORE associated with the first
     (outer) call to 'dynamic-wind' is called first.

     If invoking a continuation requires calling the BEFORE from one
     call to 'dynamic-wind' and the AFTER from another, then the AFTER
     is called first.

     The effect of using a captured continuation to enter or exit the
     dynamic extent of a call to BEFORE or AFTER is undefined.

          (let ((path '())
                (c #f))
            (let ((add (lambda (s)
                         (set! path (cons s path)))))
              (dynamic-wind
                (lambda () (add 'connect))
                (lambda ()
                  (add (call-with-current-continuation
                         (lambda (c0)
                           (set! c c0)
                           'talk1))))
                (lambda () (add 'disconnect)))
              (if (< (length path) 4)
                  (c 'talk2)
                  (reverse path))))

          => (connect talk1 disconnect connect talk2 disconnect)

   The following two procedures support multiple values.

 -- procedure: call-with-values thunk procedure
     THUNK must be a procedure of no arguments, and PROCEDURE must be a
     procedure.  THUNK is invoked with a continuation that expects to
     receive multiple values; specifically, the continuation expects to
     receive the same number of values that PROCEDURE accepts as
     arguments.  THUNK must return multiple values using the 'values'
     procedure.  Then PROCEDURE is called with the multiple values as
     its arguments.  The result yielded by PROCEDURE is returned as the
     result of 'call-with-values'.

 -- procedure: values object ...
     Returns multiple values.  The continuation in effect when this
     procedure is called must be a multiple-value continuation that was
     created by 'call-with-values'.  Furthermore it must accept as many
     values as there are OBJECTs.


File: mit-scheme-ref.info,  Node: Application Hooks,  Prev: Continuations,  Up: Procedures

12.5 Application Hooks
======================

"Application hooks" are objects that can be applied like procedures.
Each application hook has two parts: a "procedure" that specifies what
to do when the application hook is applied, and an arbitrary object,
called "extra".  Often the procedure uses the extra object to determine
what to do.

   There are two kinds of application hooks, which differ in what
arguments are passed to the procedure.  When an "apply hook" is applied,
the procedure is passed exactly the same arguments that were passed to
the apply hook.  When an "entity" is applied, the entity itself is
passed as the first argument, followed by the other arguments that were
passed to the entity.

   Both apply hooks and entities satisfy the predicate 'procedure?'.
Each satisfies either 'compiled-procedure?', 'compound-procedure?', or
'primitive-procedure?', depending on its procedure component.  An apply
hook is considered to accept the same number of arguments as its
procedure, while an entity is considered to accept one less argument
than its procedure.

 -- procedure: make-apply-hook procedure object
     Returns a newly allocated apply hook with a procedure component of
     PROCEDURE and an extra component of OBJECT.

 -- procedure: apply-hook? object
     Returns '#t' if OBJECT is an apply hook; otherwise returns '#f'.

 -- procedure: apply-hook-procedure apply-hook
     Returns the procedure component of APPLY-HOOK.

 -- procedure: set-apply-hook-procedure! apply-hook procedure
     Changes the procedure component of APPLY-HOOK to be PROCEDURE.
     Returns an unspecified value.

 -- procedure: apply-hook-extra apply-hook
     Returns the extra component of APPLY-HOOK.

 -- procedure: set-apply-hook-extra! apply-hook object
     Changes the extra component of APPLY-HOOK to be OBJECT.  Returns an
     unspecified value.

 -- procedure: make-entity procedure object
     Returns a newly allocated entity with a procedure component of
     PROCEDURE and an extra component of OBJECT.

 -- procedure: entity? object
     Returns '#t' if OBJECT is an entity; otherwise returns '#f'.

 -- procedure: entity-procedure entity
     Returns the procedure component of ENTITY.

 -- procedure: set-entity-procedure! entity procedure
     Changes the procedure component of ENTITY to be PROCEDURE.  Returns
     an unspecified value.

 -- procedure: entity-extra entity
     Returns the extra component of ENTITY.

 -- procedure: set-entity-extra! entity object
     Changes the extra component of ENTITY to be OBJECT.  Returns an
     unspecified value.


File: mit-scheme-ref.info,  Node: Environments,  Next: Input/Output,  Prev: Procedures,  Up: Top

13 Environments
***************

* Menu:

* Environment Operations::
* Environment Variables::
* REPL Environment::
* Top-level Environments::


File: mit-scheme-ref.info,  Node: Environment Operations,  Next: Environment Variables,  Prev: Environments,  Up: Environments

13.1 Environment Operations
===========================

Environments are first-class objects in MIT/GNU Scheme.  An environment
consists of some bindings and possibly a parent environment, from which
other bindings are inherited.  The operations in this section reveal the
frame-like structure of environments by permitting you to examine the
bindings of a particular environment separately from those of its
parent.

   There are several types of bindings that can occur in an environment.
The most common is the simple variable binding, which associates a value
(any Scheme object) with an identifier (a symbol).  A variable binding
can also be "unassigned", which means that it has no value.  An
unassigned variable is bound, in that is will shadow other bindings of
the same name in ancestor environments, but a reference to that variable
will signal an error of type 'condition-type:unassigned-variable'.  An
unassigned variable can be "assigned" (using 'set!' or
'environment-assign!') to give it a value.

   In addition to variable bindings, an environment can also have
"keyword bindings".  A keyword binding associates a syntactic keyword
(usually a macro transformer) with an identifier.  Keyword bindings are
special in that they are considered "bound", but ordinary variable
references don't work on them.  So an attempt to reference or assign a
keyword binding results in an error of type
'condition-type:macro-binding'.  However, keyword bindings can be
redefined using 'define' or 'environment-define'.

 -- procedure: environment? object
     Returns '#t' if OBJECT is an environment; otherwise returns '#f'.

 -- procedure: environment-has-parent? environment
     Returns '#t' if ENVIRONMENT has a parent environment; otherwise
     returns '#f'.

 -- procedure: environment-parent environment
     Returns the parent environment of ENVIRONMENT.  It is an error if
     ENVIRONMENT has no parent.

 -- procedure: environment-bound-names environment
     Returns a newly allocated list of the names (symbols) that are
     bound by ENVIRONMENT.  This does not include the names that are
     bound by the parent environment of ENVIRONMENT.  It does include
     names that are unassigned or keywords in ENVIRONMENT.

 -- procedure: environment-macro-names environment
     Returns a newly allocated list of the names (symbols) that are
     bound to syntactic keywords in ENVIRONMENT.

 -- procedure: environment-bindings environment
     Returns a newly allocated list of the bindings of ENVIRONMENT; does
     not include the bindings of the parent environment.  Each element
     of this list takes one of two forms: '(SYMBOL)' indicates that
     SYMBOL is bound but unassigned, while '(SYMBOL OBJECT)' indicates
     that SYMBOL is bound, and its value is OBJECT.

 -- procedure: environment-reference-type environment symbol
     Returns a symbol describing the "reference type" of SYMBOL in
     ENVIRONMENT or one of its ancestor environments.  The result is one
     of the following:

     'normal'
          means SYMBOL is a variable binding with a normal value.

     'unassigned'
          means SYMBOL is a variable binding with no value.

     'macro'
          means SYMBOL is a keyword binding.

     'unbound'
          means SYMBOL has no associated binding.

 -- procedure: environment-bound? environment symbol
     Returns '#t' if SYMBOL is bound in ENVIRONMENT or one of its
     ancestor environments; otherwise returns '#f'.  This is equivalent
     to

          (not (eq? 'unbound
                    (environment-reference-type ENVIRONMENT SYMBOL)))

 -- procedure: environment-assigned? environment symbol
     Returns '#t' if SYMBOL is bound in ENVIRONMENT or one of its
     ancestor environments, and has a normal value.  Returns '#f' if it
     is bound but unassigned.  Signals an error if it is unbound or is
     bound to a keyword.

 -- procedure: environment-lookup environment symbol
     SYMBOL must be bound to a normal value in ENVIRONMENT or one of its
     ancestor environments.  Returns the value to which it is bound.
     Signals an error if unbound, unassigned, or a keyword.

 -- procedure: environment-lookup-macro environment symbol
     If SYMBOL is a keyword binding in ENVIRONMENT or one of its
     ancestor environments, returns the value of the binding.
     Otherwise, returns '#f'.  Does not signal any errors other than
     argument-type errors.

 -- procedure: environment-assignable? environment symbol
     SYMBOL must be bound in ENVIRONMENT or one of its ancestor
     environments.  Returns '#t' if the binding may be modified by side
     effect.

 -- procedure: environment-assign! environment symbol object
     SYMBOL must be bound in ENVIRONMENT or one of its ancestor
     environments, and must be assignable.  Modifies the binding to have
     OBJECT as its value, and returns an unspecified result.

 -- procedure: environment-definable? environment symbol
     Returns '#t' if SYMBOL is definable in ENVIRONMENT, and '#f'
     otherwise.  At present, this is false for environments generated by
     application of compiled procedures, and true for all other
     environments.

 -- procedure: environment-define environment symbol object
     Defines SYMBOL to be bound to OBJECT in ENVIRONMENT, and returns an
     unspecified value.  Signals an error if SYMBOL isn't definable in
     ENVIRONMENT.

 -- procedure: environment-define-macro environment symbol transformer
     Defines SYMBOL to be a keyword bound to TRANSFORMER in ENVIRONMENT,
     and returns an unspecified value.  Signals an error if SYMBOL isn't
     definable in ENVIRONMENT.  The type of TRANSFORMER is defined by
     the syntax engine and is not checked by this procedure.  If the
     type is incorrect this will subsequently signal an error during
     syntax expansion.

 -- procedure: eval expression environment
     Evaluates EXPRESSION, a list-structure representation (sometimes
     called s-expression representation) of a Scheme expression, in
     ENVIRONMENT.  You rarely need 'eval' in ordinary programs; it is
     useful mostly for evaluating expressions that have been created "on
     the fly" by a program.  'eval' is relatively expensive because it
     must convert EXPRESSION to an internal form before it is executed.

          (define foo (list '+ 1 2))
          (eval foo (the-environment))            =>  3


File: mit-scheme-ref.info,  Node: Environment Variables,  Next: REPL Environment,  Prev: Environment Operations,  Up: Environments

13.2 Environment Variables
==========================

The 'user-initial-environment' is where the top-level read-eval-print
(REP) loop evaluates expressions and binds definitions.  It is a child
of 'system-global-environment', which is where all of the Scheme system
definitions are bound.  All of the bindings in
'system-global-environment' are available when the current environment
is 'user-initial-environment'.  However, any new bindings that you
create in the REP loop (with 'define' forms or by loading files
containing 'define' forms) occur in 'user-initial-environment'.

 -- variable: system-global-environment
     The variable 'system-global-environment' is bound to the
     distinguished environment that's the ancestor of most other
     environments (except for those created by
     'make-root-top-level-environment').  It is the parent environment
     of 'user-initial-environment'.  Primitives, system procedures, and
     most syntactic keywords are bound (and sometimes closed) in this
     environment.

 -- variable: user-initial-environment
     The variable 'user-initial-environment' is bound to the default
     environment in which typed expressions are evaluated by the
     top-level REP loop.

     Although all bindings in 'system-global-environment' are visible to
     the REP loop, definitions that are typed at, or loaded by, the REP
     loop occur in the 'user-initial-environment'.  This is partly a
     safety measure: if you enter a definition that happens to have the
     same name as a critical system procedure, your definition will be
     visible only to the procedures you define in the
     'user-initial-environment'; the MIT/GNU Scheme system procedures,
     which are defined in 'system-global-environment', will continue to
     see the original definition.


File: mit-scheme-ref.info,  Node: REPL Environment,  Next: Top-level Environments,  Prev: Environment Variables,  Up: Environments

13.3 REPL Environment
=====================

 -- procedure: nearest-repl/environment
     Returns the current REP loop environment (i.e. the current
     environment of the closest enclosing REP loop).  When Scheme first
     starts up, this is the same as 'user-initial-environment'.

 -- procedure: ge environment
     Changes the current REP loop environment to ENVIRONMENT.
     ENVIRONMENT can be either an environment or a procedure object.  If
     it's a procedure, the environment in which that procedure was
     closed is the new environment.


File: mit-scheme-ref.info,  Node: Top-level Environments,  Prev: REPL Environment,  Up: Environments

13.4 Top-level Environments
===========================

The operations in this section manipulate "top-level environments", as
opposed to environments created by the application of procedures.  For
historical reasons, top-level environments are referred to as
"interpreter environments".

 -- special form: the-environment
     Returns the current environment.  This form may only be evaluated
     in a top-level environment.  An error is signalled if it appears
     elsewhere.

 -- procedure: top-level-environment? object
 -- procedure: interpreter-environment? object
     Returns '#t' if OBJECT is an top-level environment; otherwise
     returns '#f'.

     'interpreter-environment?' is an alias for
     'top-level-environment?'.

 -- procedure: extend-top-level-environment environment [names [values]]
 -- procedure: make-top-level-environment [names [values]]
 -- procedure: make-root-top-level-environment [names [values]]
     Returns a newly allocated top-level environment.
     'extend-top-level-environment' creates an environment that has
     parent ENVIRONMENT, 'make-top-level-environment' creates an
     environment that has parent 'system-global-environment', and
     'make-root-top-level-environment' creates an environment that has
     no parent.

     The optional arguments NAMES and VALUES are used to specify initial
     bindings in the new environment.  If specified, NAMES must be a
     list of symbols, and VALUES must be a list of objects.  If only
     NAMES is specified, each name in NAMES will be bound in the
     environment, but unassigned.  If NAMES and VALUES are both
     specified, they must be the same length, and each name in NAMES
     will be bound to the corresponding value in VALUES.  If neither
     NAMES nor VALUES is specified, the environment will have no initial
     bindings.

 -- procedure: link-variables environment1 symbol1 environment2 symbol2
     Defines SYMBOL1 in ENVIRONMENT1 to have the same binding as SYMBOL2
     in ENVIRONMENT2, and returns an unspecified value.  Prior to the
     call, SYMBOL2 must be bound in ENVIRONMENT2, but the type of
     binding is irrelevant; it may be a normal binding, an unassigned
     binding, or a keyword binding.  Signals an error if SYMBOL1 isn't
     definable in ENVIRONMENT1, or if SYMBOL2 is unbound in
     ENVIRONMENT2.

     By "the same binding", we mean that the value cell is shared
     between the two environments.  If a value is assigned to SYMBOL1 in
     ENVIRONMENT1, a subsequent reference to SYMBOL2 in ENVIRONMENT2
     will see that value, and vice versa.

 -- procedure: unbind-variable environment symbol
     If SYMBOL is bound in ENVIRONMENT or one of its ancestor
     environments, removes the binding, so that subsequent accesses to
     that symbol behave as if the binding never existed.  Returns '#t'
     if there was a binding prior to the call, and '#f' if there wasn't.


File: mit-scheme-ref.info,  Node: Input/Output,  Next: Operating-System Interface,  Prev: Environments,  Up: Top

14 Input/Output
***************

This chapter describes the procedures that are used for input and output
(I/O).  The chapter first describes "ports" and how they are
manipulated, then describes the I/O operations.  Finally, some low-level
procedures are described that permit the implementation of custom ports
and high-performance I/O.

* Menu:

* Ports::
* File Ports::
* String Ports::
* Bytevector Ports::
* Input Procedures::
* Output Procedures::
* Blocking Mode::
* Terminal Mode::
* Format::
* Custom Output::
* Prompting::
* Textual Port Primitives::
* Parser Buffers::
* Parser Language::
* XML Support::


File: mit-scheme-ref.info,  Node: Ports,  Next: File Ports,  Prev: Input/Output,  Up: Input/Output

14.1 Ports
==========

Ports represent input and output devices.  To Scheme, an "input port" is
a Scheme object that can deliver data upon command, while an "output
port" is a Scheme object that can accept data.  Whether the input and
output port types are disjoint is implementation-dependent.  (In MIT/GNU
Scheme, there are input ports, output ports, and input/output ports.)

   Different port types operate on different data.  Scheme
implementations are required to support textual ports and binary ports,
but may also provide other port types.

   A "textual port" supports reading or writing of individual characters
from or to a backing store containing characters using 'read-char' and
'write-char' below, and it supports operations defined in terms of
characters, such as 'read' and 'write'.

   A "binary port" supports reading or writing of individual bytes from
or to a backing store containing bytes using 'read-u8' and 'write-u8'
below, as well as operations defined in terms of bytes.  Whether the
textual and binary port types are disjoint is implementation-dependent.
(In MIT/GNU Scheme, textual ports and binary ports are distinct.)

   Ports can be used to access files, devices, and similar things on the
host system on which the Scheme program is running.

 -- standard procedure: call-with-port port procedure
     It is an error if PROCEDURE does not accept one argument.

     The 'call-with-port' procedure calls PROCEDURE with PORT as an
     argument.  If PROCEDURE returns, then the port is closed
     automatically and the values yielded by PROCEDURE are returned.  If
     PROCEDURE does not return, then the port must not be closed
     automatically unless it is possible to prove that the port will
     never again be used for a read or write operation.

     _Rationale_: Because Scheme’s escape procedures have unlimited
     extent, it is possible to escape from the current continuation but
     later to resume it.  If implementations were permitted to close the
     port on any escape from the current continuation, then it would be
     impossible to write portable code using both
     'call-with-current-continuation' and 'call-with-port'.

 -- procedure: call-with-truncated-output-port limit output-port
          procedure
     The LIMIT argument must be a nonnegative integer.  It is an error
     if PROCEDURE does not accept one argument.

     This procedure uses a continuation to escape from PROCEDURE if it
     tries to write more than LIMIT characters.

     It calls PROCEDURE with a special output port as an argument.  Up
     to LIMIT characters may be written to that output port, and those
     characters are transparently written through to OUTPUT-PORT.

     If the number of characters written to that port exceeds LIMIT,
     then the escape continuation is invoked and '#t' is returned.
     Otherwise, PROCEDURE returns normally and '#f' is returned.

     Note that if PROCEDURE writes exactly LIMIT characters, then the
     escape continuation is _not_ invoked, and '#f' is returned.

     In no case does 'call-with-truncated-output-port' close
     OUTPUT-PORT.

 -- standard procedure: input-port? object
 -- standard procedure: output-port? object
 -- procedure: i/o-port? object
 -- standard procedure: textual-port? object
 -- standard procedure: binary-port? object
 -- standard procedure: port? object
     These procedures return '#t' if OBJECT is an input port, output
     port, input/output port, textual port, binary port, or any kind of
     port, respectively.  Otherwise they return '#f'.

 -- standard procedure: input-port-open? port
 -- standard procedure: output-port-open? port
     Returns '#t' if PORT is still open and capable of performing input
     or output, respectively, and '#f' otherwise.

 -- standard parameter: current-input-port [input-port]
 -- standard parameter: current-output-port [output-port]
 -- standard parameter: current-error-port [output-port]
     Returns the current default input port, output port, or error port
     (an output port), respectively.  These procedures are parameter
     objects, which can be overridden with 'parameterize'.  The initial
     bindings for these are implementation-defined textual ports.

 -- parameter: notification-output-port [output-port]
     Returns an output port suitable for generating "notifications",
     that is, messages to the user that supply interesting information
     about the execution of a program.  For example, the 'load'
     procedure writes messages to this port informing the user that a
     file is being loaded.

     This procedure is a parameter object, which can be overridden with
     'parameterize'.

 -- parameter: trace-output-port [output-port]
     Returns an output port suitable for generating "tracing"
     information about a program's execution.  The output generated by
     the 'trace' procedure is sent to this port.

     This procedure is a parameter object, which can be overridden with
     'parameterize'.

 -- parameter: interaction-i/o-port [i/o-port]
     Returns an I/O port suitable for querying or prompting the user.
     The standard prompting procedures use this port by default (*note
     Prompting::).

     This procedure is a parameter object, which can be overridden with
     'parameterize'.

 -- standard procedure: close-port port
 -- standard procedure: close-input-port port
 -- standard procedure: close-output-port port
     Closes the resource associated with PORT, rendering the port
     incapable of delivering or accepting data.  It is an error to apply
     the last two procedures to a port which is not an input or output
     port, respectively.  Scheme implementations may provide ports which
     are simultaneously input and output ports, such as sockets; the
     close-input-port and close-output-port procedures can then be used
     to close the input and output sides of the port independently.

     These routines have no effect if the port has already been closed.

 -- obsolete procedure: set-current-input-port! input-port
 -- obsolete procedure: set-current-output-port! output-port
 -- obsolete procedure: set-notification-output-port! output-port
 -- obsolete procedure: set-trace-output-port! output-port
 -- obsolete procedure: set-interaction-i/o-port! i/o-port
     These procedures are *deprecated*; instead call the corresponding
     parameters with an argument.

 -- obsolete procedure: with-input-from-port input-port thunk
 -- obsolete procedure: with-output-to-port output-port thunk
 -- obsolete procedure: with-notification-output-port output-port thunk
 -- obsolete procedure: with-trace-output-port output-port thunk
 -- obsolete procedure: with-interaction-i/o-port i/o-port thunk
     These procedures are *deprecated*; instead use 'parameterize' on
     the corresponding parameters.

 -- variable: console-i/o-port
     'console-i/o-port' is an I/O port that communicates with the
     "console".  Under unix, the console is the controlling terminal of
     the Scheme process.  Under Windows, the console is the window that
     is created when Scheme starts up.

     This variable is rarely used; instead programs should use one of
     the standard ports defined above.  This variable should not be
     modified.


File: mit-scheme-ref.info,  Node: File Ports,  Next: String Ports,  Prev: Ports,  Up: Input/Output

14.2 File Ports
===============

Before Scheme can access a file for reading or writing, it is necessary
to open a port to the file.  This section describes procedures used to
open ports to files.  Such ports are closed (like any other port) by
'close-port'.  File ports are automatically closed if and when they are
reclaimed by the garbage collector.

   Before opening a file for input or output, by whatever method, the
FILENAME argument is converted to canonical form by calling the
procedure 'merge-pathnames' with FILENAME as its sole argument.  Thus,
FILENAME can be either a string or a pathname, and it is merged with the
current pathname defaults to produce the pathname that is then opened.

 -- standard procedure: call-with-input-file filename procedure
 -- standard procedure: call-with-output-file filename procedure
     It is an error if PROCEDURE does not accept one argument.

     These procedures obtain a textual port obtained by opening the
     named file for input or output as if by 'open-input-file' or
     'open-output-file'.  The port and PROCEDURE are then passed to a
     procedure equivalent to 'call-with-port'.

 -- procedure: call-with-binary-input-file filename procedure
 -- procedure: call-with-binary-output-file filename procedure
     It is an error if PROCEDURE does not accept one argument.

     These procedures obtain a binary port obtained by opening the named
     file for input or output as if by 'open-binary-input-file' or
     'open-binary-output-file'.  The port and PROCEDURE are then passed
     to a procedure equivalent to 'call-with-port'.

 -- standard procedure: with-input-from-file filename thunk
 -- standard procedure: with-output-to-file filename thunk
     The file named by FILENAME is opened for input or output as if by
     'open-input-file' or 'open-output-file', and the new port is made
     to be the value returned by 'current-input-port' or
     'current-output-port' (as used by '(read)', '(write obj)', and so
     forth).  The THUNK is then called with no arguments.  When the
     THUNK returns, the port is closed and the previous default is
     restored.  It is an error if THUNK does not accept zero arguments.
     Both procedures return the values yielded by THUNK.  If an escape
     procedure is used to escape from the continuation of these
     procedures, they behave exactly as if the current input or output
     port had been bound dynamically with 'parameterize'.

 -- obsolete procedure: with-input-from-binary-file filename thunk
 -- obsolete procedure: with-output-to-binary-file filename thunk
     These procedures are *deprecated*; instead use 'parameterize' along
     with 'call-with-binary-input-file' or
     'call-with-binary-output-file'.

 -- procedure: open-input-file filename
 -- procedure: open-binary-input-file filename
     Takes a FILENAME for an existing file and returns a textual input
     port or binary input port that is capable of delivering data from
     the file.  If the file does not exist or cannot be opened, an error
     an error that satisfies 'file-error?' is signaled.

 -- standard procedure: open-output-file filename [append?]
 -- standard procedure: open-binary-output-file filename [append?]
     Takes a FILENAME naming an output file to be created and returns a
     textual output port or binary output port that is capable of
     writing data to a new file by that name.  If a file with the given
     name already exists, the effect is unspecified.  (In that case,
     MIT/GNU Scheme overwrites an existing file.)  If the file cannot be
     opened, an error that satisfies 'file-error?' is signalled.

     The optional argument APPEND? is an MIT/GNU Scheme extension.  If
     APPEND? is given and not '#f', the file is opened in "append" mode.
     In this mode, the contents of the file are not overwritten; instead
     any characters written to the file are appended to the end of the
     existing contents.  If the file does not exist, append mode creates
     the file and writes to it in the normal way.

 -- procedure: open-i/o-file filename
 -- procedure: open-binary-i/o-file filename
     Takes a FILENAME referring to an existing file and returns an I/O
     port that is capable of both reading from and writing to the file.
     If the file cannot be opened, an error that satisfies 'file-error?'
     is signalled.

     This procedure is often used to open special files.  For example,
     under unix this procedure can be used to open terminal device
     files, PTY device files, and named pipes.

 -- procedure: close-all-open-files
     This procedure closes all file ports that are open at the time that
     it is called, and returns an unspecified value.


File: mit-scheme-ref.info,  Node: String Ports,  Next: Bytevector Ports,  Prev: File Ports,  Up: Input/Output

14.3 String Ports
=================

This section describes textual input ports that read their input from
given strings, and textual output ports that accumulate their output and
return it as a string.

 -- standard procedure: open-input-string string [start [end]]
     Takes a string and returns a textual input port that delivers
     characters from the string.  If the string is modified, the effect
     is unspecified.

     The optional arguments START and END may be used to specify that
     the string port delivers characters from a substring of STRING; if
     not given, START defaults to '0' and END defaults to
     '(string-length STRING)'.

 -- standard procedure: open-output-string
     Returns a textual output port that will accumulate characters for
     retrieval by 'get-output-string'.

 -- standard procedure: get-output-string port
     It is an error if PORT was not created with OPEN-OUTPUT-STRING.

     Returns a string consisting of the characters that have been output
     to the port so far in the order they were output.  If the result
     string is modified, the effect is unspecified.

          (parameterize ((current-output-port (open-output-string)))
            (display "piece")
            (display " by piece ")
            (display "by piece.")
            (newline)
            (get-output-string (current-output-port)))

              => "piece by piece by piece.\n"

 -- procedure: call-with-output-string procedure
     The PROCEDURE is called with one argument, a textual output port.
     The values yielded by PROCEDURE are ignored.  When PROCEDURE
     returns, 'call-with-output-string' returns the port's accumulated
     output as a string.  If the result string is modified, the effect
     is unspecified.

     This procedure could have been defined as follows:
          (define (call-with-output-string procedure)
            (let ((port (open-output-string)))
              (procedure port)
              (get-output-string port)))

 -- procedure: call-with-truncated-output-string limit procedure
     Similar to 'call-with-output-string', except that the output is
     limited to at most LIMIT characters.  The returned value is a pair;
     the car of the pair is '#t' if PROCEDURE attempted to write more
     than LIMIT characters, and '#f' otherwise.  The cdr of the pair is
     a newly allocated string containing the accumulated output.

     This procedure could have been defined as follows:
          (define (call-with-truncated-output-string limit procedure)
            (let ((port (open-output-string)))
              (let ((truncated?
                     (call-with-truncated-output-port limit port
                                                      procedure)))
                (cons truncated? (get-output-string port)))))

     This procedure is helpful for displaying circular lists, as shown
     in this example:
          (define inf (list 'inf))
          (call-with-truncated-output-string 40
            (lambda (port)
              (write inf port)))                  =>  (#f . "(inf)")
          (set-cdr! inf inf)
          (call-with-truncated-output-string 40
            (lambda (port)
              (write inf port)))
                  =>  (#t . "(inf inf inf inf inf inf inf inf inf inf")

 -- procedure: write-to-string object [limit]
     Writes OBJECT to a string output port, and returns the resulting
     string.

     If LIMIT is supplied and not '#f', then this procedure is
     equivalent to the following and returns a pair instead of just a
     string:
          (call-with-truncated-output-string limit
            (lambda (port)
              (write object port)))

 -- obsolete procedure: with-input-from-string string thunk
 -- obsolete procedure: with-output-to-string thunk
 -- obsolete procedure: with-output-to-truncated-string limit thunk
     These procedures are *deprecated*; instead use 'open-input-string',
     'call-with-output-string', or 'call-with-truncated-output-string'
     along with 'parameterize'.


File: mit-scheme-ref.info,  Node: Bytevector Ports,  Next: Input Procedures,  Prev: String Ports,  Up: Input/Output

14.4 Bytevector Ports
=====================

This section describes binary input ports that read their input from
given bytevectors, and binary output ports that accumulate their output
and return it as a bytevector.

 -- standard procedure: open-input-bytevector bytevector [start [end]]
     Takes a bytevector and returns a binary input port that delivers
     bytes from the bytevector.  If the bytevector is modified, the
     effect is unspecified.

     The optional arguments START and END may be used to specify that
     the bytevector port delivers bytes from a portion of BYTEVECTOR; if
     not given, START defaults to '0' and END defaults to
     '(bytevector-length BYTEVECTOR)'.

 -- standard procedure: open-output-bytevector
     Returns a binary output port that will accumulate bytes for
     retrieval by 'get-output-bytevector'.

 -- standard procedure: get-output-bytevector port
     It is an error if PORT was not created with OPEN-OUTPUT-BYTEVECTOR.

     Returns a bytevector consisting of the bytes that have been output
     to the port so far in the order they were output.  If the result
     bytevector is modified, the effect is unspecified.

 -- procedure: call-with-output-bytevector procedure
     The PROCEDURE is called with one argument, a binary output port.
     The values yielded by PROCEDURE are ignored.  When PROCEDURE
     returns, 'call-with-output-bytevector' returns the port's
     accumulated output as a newly allocated bytevector.

     This procedure could have been defined as follows:
          (define (call-with-output-bytevector procedure)
            (let ((port (open-output-bytevector)))
              (procedure port)
              (get-output-bytevector port)))


File: mit-scheme-ref.info,  Node: Input Procedures,  Next: Output Procedures,  Prev: Bytevector Ports,  Up: Input/Output

14.5 Input Procedures
=====================

This section describes the procedures that read input.  Input procedures
can read either from the current input port or from a given port.
Remember that to read from a file, you must first open a port to the
file.

   Input ports can be divided into two types, called "interactive" and
"non-interactive".  Interactive input ports are ports that read input
from a source that is time-dependent; for example, a port that reads
input from a terminal or from another program.  Non-interactive input
ports read input from a time-independent source, such as an ordinary
file or a character string.

   In this section, all optional arguments called PORT default to the
current input port.

 -- standard procedure: read [port]
     The 'read' procedure converts external representations of Scheme
     objects into the objects themselves.  It returns the next object
     parsable from the given textual input PORT, updating PORT to point
     to the first character past the end of the external representation
     of the object.

     Implementations may support extended syntax to represent record
     types or other types that do not have datum representations.

     If an end of file is encountered in the input before any characters
     are found that can begin an object, then an end-of-file object is
     returned.  The port remains open, and further attempts to read will
     also return an end-of-file object.  If an end of file is
     encountered after the beginning of an object’s external
     representation, but the external representation is incomplete and
     therefore not parsable, an error that satisfies 'read-error?' is
     signaled.

     The PORT remains open, and further attempts to read will also
     return an end-of-file object.  If an end of file is encountered
     after the beginning of an object's written representation, but the
     written representation is incomplete and therefore not parsable, an
     error is signalled.

 -- standard procedure: read-char [port]
     Returns the next character available from the textual input PORT,
     updating PORT to point to the following character.  If no more
     characters are available, an end-of-file object is returned.

     In MIT/GNU Scheme, if PORT is an interactive input port and no
     characters are immediately available, 'read-char' will hang waiting
     for input, even if the port is in non-blocking mode.

 -- procedure: read-char-no-hang [port]
     This procedure behaves exactly like 'read-char' except when PORT is
     an interactive port in non-blocking mode, and there are no
     characters immediately available.  In that case this procedure
     returns '#f' without blocking.

 -- procedure: unread-char char [port]
     The given CHAR must be the most-recently read character from the
     textual input PORT.  This procedure "unreads" the character,
     updating PORT as if the character had never been read.

     Note that this only works with characters returned by 'read-char'
     or 'read-char-no-hang'.

 -- standard procedure: peek-char [port]
     Returns the next character available from the textual input PORT,
     _without_ updating PORT to point to the following character.  If no
     more characters are available, an end-of-file object is returned.

     _Note_: The value returned by a call to 'peek-char' is the same as
     the value that would have been returned by a call to 'read-char' on
     the same port.  The only difference is that the very next call to
     'read-char' or 'peek-char' on that PORT will return the value
     returned by the preceding call to 'peek-char'.  In particular, a
     call to 'peek-char' on an interactive port will hang waiting for
     input whenever a call to 'read-char' would have hung.

 -- standard procedure: read-line [port]
     Returns the next line of text available from the textual input
     PORT, updating the PORT to point to the following character.  If an
     end of line is read, a string containing all of the text up to (but
     not including) the end of line is returned, and the port is updated
     to point just past the end of line.  If an end of file is
     encountered before any end of line is read, but some characters
     have been read, a string containing those characters is returned.
     If an end of file is encountered before any characters are read, an
     end-of-file object is returned.  For the purpose of this procedure,
     an end of line consists of either a linefeed character, a carriage
     return character, or a sequence of a carriage return character
     followed by a linefeed character.  Implementations may also
     recognize other end of line characters or sequences.

     In MIT/GNU Scheme, if PORT is an interactive input port and no
     characters are immediately available, 'read-line' will hang waiting
     for input, even if the port is in non-blocking mode.

 -- standard procedure: eof-object? object
     Returns '#t' if OBJECT is an end-of-file object, otherwise returns
     '#f'.  The precise set of end-of-file objects will vary among
     implementations, but in any case no end-of-file object will ever be
     an object that can be read in using 'read'.

 -- standard procedure: eof-object
     Returns an end-of-file object, not necessarily unique.

 -- standard procedure: char-ready? [port]
     Returns '#t' if a character is ready on the textual input PORT and
     returns '#f' otherwise.  If 'char-ready?' returns '#t' then the
     next 'read-char' operation on the given PORT is guaranteed not to
     hang.  If the PORT is at end of file then 'char-ready?' returns
     '#t'.

     Rationale: The 'char-ready?' procedure exists to make it possible
     for a program to accept characters from interactive ports without
     getting stuck waiting for input.  Any input editors associated with
     such ports must ensure that characters whose existence has been
     asserted by 'char-ready?' cannot be removed from the input.  If
     'char-ready?' were to return '#f' at end of file, a port at end of
     file would be indistinguishable from an interactive port that has
     no ready characters.

 -- standard procedure: read-string k [port]
     Reads the next K characters, or as many as are available before the
     end of file, from the textual input PORT into a newly allocated
     string in left-to-right order and returns the string.  If no
     characters are available before the end of file, an end-of-file
     object is returned.

     _Note_: MIT/GNU Scheme previously defined this procedure
     differently, and this alternate usage is *deprecated*; please use
     'read-delimited-string' instead.  For now, 'read-string' will
     redirect to 'read-delimited-string' as needed, but this redirection
     will be eliminated in a future release.

 -- procedure: read-string! string [port [start [end]]]
     Reads the next end-start characters, or as many as are available
     before the end of file, from the textual input PORT into STRING in
     left-to-right order beginning at the START position.  If END is not
     supplied, reads until the end of STRING has been reached.  If START
     is not supplied, reads beginning at position '0'.  Returns the
     number of characters read.  If no characters are available, an
     end-of-file object is returned.

     In MIT/GNU Scheme, if PORT is an interactive port in non-blocking
     mode and no characters are immediately available, '#f' is returned
     without any modification of STRING.

     However, if one or more characters are immediately available, the
     region is filled using the available characters.  The procedure
     then returns the number of characters filled in, without waiting
     for further characters, even if the number of filled characters is
     less than the size of the region.

 -- obsolete procedure: read-substring! string start end [port]
     This procedure is *deprecated*; use 'read-string!' instead.

 -- standard procedure: read-u8 [port]
     Returns the next byte available from the binary input PORT,
     updating the PORT to point to the following byte.  If no more bytes
     are available, an end-of-file object is returned.

     In MIT/GNU Scheme, if PORT is an interactive input port in
     non-blocking mode and no characters are immediately available,
     'read-u8' will return '#f'.

 -- standard procedure: peek-u8 [port]
     Returns the next byte available from the binary input PORT, but
     _without_ updating the PORT to point to the following byte.  If no
     more bytes are available, an end-of-file object is returned.

     In MIT/GNU Scheme, if PORT is an interactive input port in
     non-blocking mode and no characters are immediately available,
     'peek-u8' will return '#f'.

 -- standard procedure: u8-ready? [port]
     Returns '#t' if a byte is ready on the binary input 'port' and
     returns '#f' otherwise.  If 'u8-ready?' returns '#t' then the next
     'read-u8' operation on the given PORT is guaranteed not to hang.
     If the PORT is at end of file then 'u8-ready?' returns '#t'.

 -- standard procedure: read-bytevector k [port]
     Reads the next K bytes, or as many as are available before the end
     of file, from the binary input PORT into a newly allocated
     bytevector in left-to-right order and returns the bytevector.  If
     no bytes are available before the end of file, an end-of-file
     object is returned.

     In MIT/GNU Scheme, if PORT is an interactive input port in
     non-blocking mode and no characters are immediately available,
     'read-bytevector' will return '#f'.

     However, if one or more bytes are immediately available, they are
     read and returned as a bytevector, without waiting for further
     bytes, even if the number of bytes is less than K.

 -- standard procedure: read-bytevector! bytevector [port [start [end]]]
     Reads the next end-start bytes, or as many as are available before
     the end of file, from the binary input PORT into BYTEVECTOR in
     left-to-right order beginning at the START position.  If END is not
     supplied, reads until the end of BYTEVECTOR has been reached.  If
     START is not supplied, reads beginning at position '0'.  Returns
     the number of bytes read.  If no bytes are available, an
     end-of-file object is returned.

     In MIT/GNU Scheme, if PORT is an interactive input port in
     non-blocking mode and no characters are immediately available,
     'read-bytevector!' will return '#f'.

     However, if one or more bytes are immediately available, the region
     is filled using the available bytes.  The procedure then returns
     the number of bytes filled in, without waiting for further bytes,
     even if the number of filled bytes is less than the size of the
     region.

 -- procedure: read-delimited-string char-set [port]
     Reads characters from PORT until it finds a terminating character
     that is a member of CHAR-SET (*note Character Sets::) or encounters
     end of file.  The port is updated to point to the terminating
     character, or to end of file if no terminating character was found.
     'read-delimited-string' returns the characters, up to but excluding
     the terminating character, as a newly allocated string.

     This procedure ignores the blocking mode of the port, blocking
     unconditionally until it sees either a delimiter or end of file.
     If end of file is encountered before any characters are read, an
     end-of-file object is returned.

     On many input ports, this operation is significantly faster than
     the following equivalent code using 'peek-char' and 'read-char':

          (define (read-delimited-string char-set port)
            (let ((char (peek-char port)))
              (if (eof-object? char)
                  char
                  (list->string
                   (let loop ((char char))
                     (if (or (eof-object? char)
                             (char-in-set? char char-set))
                         '()
                         (begin
                           (read-char port)
                           (cons char
                                 (loop (peek-char port))))))))))

14.5.1 Reader Controls
----------------------

The following parameters control the behavior of the 'read' procedure.

 -- parameter: param:reader-radix
     This parameter defines the radix used by the reader when it parses
     numbers.  This is similar to passing a radix argument to
     'string->number'.  The value of the parameter must be one of '2',
     '8', '10', or '16'; an error is signaled if the parameter is bound
     to any other value.

     Note that much of the number syntax is invalid for radixes other
     than '10'.  The reader detects cases where such invalid syntax is
     used and signals an error.  However, problems can still occur when
     'param:reader-radix' is bound to '16', because syntax that normally
     denotes symbols can now denote numbers (e.g. 'abc').  Because of
     this, it is usually undesirable to bind this parameter to anything
     other than the default.

     The default value of this parameter is '10'.

 -- parameter: param:reader-fold-case?
     This parameter controls whether the parser folds the case of
     symbols, character names, and certain other syntax.  If it is bound
     to its default value of '#t', symbols read by the parser are
     case-folded prior to being interned.  Otherwise, symbols are
     interned without folding.

     At present, it is a bad idea to use this feature, as it doesn't
     really make Scheme case-sensitive, and therefore can break features
     of the Scheme runtime that depend on case-folded symbols.  Instead,
     use the '#!fold-case' or '#!no-fold-case' markers in your code.

 -- obsolete variable: *parser-radix*
 -- obsolete variable: *parser-canonicalize-symbols?*
     These variables are *deprecated*; instead use the corresponding
     parameter objects.


File: mit-scheme-ref.info,  Node: Output Procedures,  Next: Blocking Mode,  Prev: Input Procedures,  Up: Input/Output

14.6 Output Procedures
======================

Output ports may or may not support "buffering" of output, in which
output characters are collected together in a buffer and then sent to
the output device all at once.  (Most of the output ports implemented by
the runtime system support buffering.)  Sending all of the characters in
the buffer to the output device is called "flushing" the buffer.  In
general, output procedures do not flush the buffer of an output port
unless the buffer is full.

   However, the standard output procedures described in this section
perform what is called "discretionary" flushing of the buffer.
Discretionary output flushing works as follows.  After a procedure
performs its output (writing characters to the output buffer), it checks
to see if the port implements an operation called
'discretionary-flush-output'.  If so, then that operation is invoked to
flush the buffer.  At present, only the console port defines
'discretionary-flush-output'; this is used to guarantee that output to
the console appears immediately after it is written, without requiring
calls to 'flush-output-port'.

   In this section, all optional arguments called PORT default to the
current output port.

   *Note*: MIT/GNU Scheme doesn't support datum labels, so any behavior
in 'write', 'write-shared', or 'write-simple' that depends on datum
labels is not implemented.  At present all three of these procedures are
equivalent.  This will be remedied in a future release.

 -- standard procedure: write object [port]
     Writes a representation of OBJECT to the given textual output PORT.
     Strings that appear in the written representation are enclosed in
     quotation marks, and within those strings backslash and quotation
     mark characters are escaped by backslashes.  Symbols that contain
     non-ASCII characters are escaped with vertical lines.  Character
     objects are written using the '#\' notation.

     If OBJECT contains cycles which would cause an infinite loop using
     the normal written representation, then at least the objects that
     form part of the cycle must be represented using datum labels.
     Datum labels must not be used if there are no cycles.

     Implementations may support extended syntax to represent record
     types or other types that do not have datum representations.

     The 'write' procedure returns an unspecified value.

     On MIT/GNU Scheme 'write' performs discretionary output flushing.

 -- standard procedure: write-shared object [port]
     The 'write-shared' procedure is the same as 'write', except that
     shared structure must be represented using datum labels for all
     pairs and vectors that appear more than once in the output.

 -- standard procedure: write-simple object [port]
     The 'write-simple' procedure is the same as 'write', except that
     shared structure is never represented using datum labels.  This can
     cause 'write-simple' not to terminate if OBJECT contains circular
     structure.

 -- standard procedure: display object [port]
     Writes a representation of OBJECT to the given textual output PORT.
     Strings that appear in the written representation are output as if
     by write-string instead of by write.  Symbols are not escaped.
     Character objects appear in the representation as if written by
     'write-char' instead of by 'write'.  The display representation of
     other objects is unspecified.  However, 'display' must not loop
     forever on self-referencing pairs, vectors, or records.  Thus if
     the normal 'write' representation is used, datum labels are needed
     to represent cycles as in 'write'.

     Implementations may support extended syntax to represent record
     types or other types that do not have datum representations.

     The 'display' procedure returns an unspecified value.

     _Rationale_: The 'write' procedure is intended for producing
     machine-readable output and 'display' for producing human-readable
     output.

 -- standard procedure: newline [port]
     Writes an end of line to textual output PORT.  Exactly how this is
     done differs from one operating system to another.  Returns an
     unspecified value.

 -- standard procedure: write-char char [port]
     Writes the character CHAR (not an external representation of the
     character) to the given textual output PORT and returns an
     unspecified value.

 -- standard procedure: write-string string [port [start [end]]]
     Writes the characters of STRING from START to END in left-to-right
     order to the textual output PORT.

 -- obsolete procedure: write-substring string start end [port]
     This procedure is *deprecated*; use 'write-string' instead.

 -- standard procedure: write-u8 byte [port]
     Writes the BYTE to the given binary output PORT and returns an
     unspecified value.

     In MIT/GNU Scheme, if PORT is an interactive output port in
     non-blocking mode and writing a byte would block, 'write-u8'
     immediately returns '#f' without writing anything.  Otherwise BYTE
     is written and '1' is returned.

 -- standard procedure: write-bytevector bytevector [port [start [end]]]
     Writes the bytes of BYTEVECTOR from START to END in left-to-right
     order to the binary output PORT.

     In MIT/GNU Scheme, if PORT is an interactive output port in
     non-blocking mode 'write-bytevector' will write as many bytes as it
     can without blocking, then returns the number of bytes written; if
     no bytes can be written without blocking, returns '#f' without
     writing anything.  Otherwise 'write-bytevector' returns the number
     of bytes actually written, which may be less than the number
     requested if unable to write all the bytes.  (For example, if
     writing to a file and the file system is full.)

 -- standard procedure: flush-output-port [port]
     Flushes any buffered output from the buffer of PORT to the
     underlying file or device and returns an unspecified value.

 -- obsolete procedure: flush-output [port]
     This procedure is *deprecated*; use 'flush-output-port' instead.

 -- procedure: fresh-line [port]
     Most output ports are able to tell whether or not they are at the
     beginning of a line of output.  If PORT is such a port, this
     procedure writes an end-of-line to the port only if the port is not
     already at the beginning of a line.  If PORT is not such a port,
     this procedure is identical to 'newline'.  In either case,
     'fresh-line' performs discretionary output flushing and returns an
     unspecified value.

 -- procedure: write-line object [port]
     Like 'write', except that it writes an end-of-line to PORT after
     writing OBJECT's representation.  This procedure performs
     discretionary output flushing and returns an unspecified value.

 -- procedure: beep [port]
     Performs a "beep" operation on PORT, performs discretionary output
     flushing, and returns an unspecified value.  On the console port,
     this usually causes the console bell to beep, but more
     sophisticated interactive ports may take other actions, such as
     flashing the screen.  On most output ports, e.g. file and string
     output ports, this does nothing.

 -- procedure: clear [port]
     "Clears the screen" of PORT, performs discretionary output
     flushing, and returns an unspecified value.  On a terminal or
     window, this has a well-defined effect.  On other output ports,
     e.g. file and string output ports, this does nothing.

 -- procedure: pp object [port [as-code?]]
     'pp' prints OBJECT in a visually appealing and structurally
     revealing manner on PORT.  If object is a procedure, 'pp' attempts
     to print the source text.  If the optional argument AS-CODE? is
     true, 'pp' prints lists as Scheme code, providing appropriate
     indentation; by default this argument is false.  'pp' performs
     discretionary output flushing and returns an unspecified value.

   The following parameters may be used with 'parameterize' to change
the behavior of the 'write' and 'display' procedures.

 -- parameter: param:printer-radix
     This parameter specifies the default radix used to print numbers.
     Its value must be one of the exact integers '2', '8', '10', or
     '16'; the default is '10'.  For values other than '10', numbers are
     prefixed to indicate their radix.

 -- parameter: param:printer-list-breadth-limit
     This parameter specifies a limit on the length of the printed
     representation of a list or vector; for example, if the limit is
     '4', only the first four elements of any list are printed, followed
     by ellipses to indicate any additional elements.  The value of this
     parameter must be an exact non-negative integer, or '#f' meaning no
     limit; the default is '#f'.

          (parameterize ((param:printer-list-breadth-limit 4))
            (lambda ()
              (write-to-string '(a b c d))))
                                          => "(a b c d)"
          (parameterize ((param:printer-list-breadth-limit 4))
            (lambda ()
              (write-to-string '(a b c d e))))
                                          => "(a b c d ...)"

 -- parameter: param:printer-list-depth-limit
     This parameter specifies a limit on the nesting of lists and
     vectors in the printed representation.  If lists (or vectors) are
     more deeply nested than the limit, the part of the representation
     that exceeds the limit is replaced by ellipses.  The value of this
     parameter must be an exact non-negative integer, or '#f' meaning no
     limit; the default is '#f'.

          (parameterize ((param:printer-list-depth-limit 4))
            (lambda ()
              (write-to-string '((((a))) b c d))))
                                          => "((((a))) b c d)"
          (parameterize ((param:printer-list-depth-limit 4))
            (lambda ()
              (write-to-string '(((((a)))) b c d))))
                                          => "((((...))) b c d)"

 -- parameter: param:printer-string-length-limit
     This parameter specifies a limit on the length of the printed
     representation of strings.  If a string's length exceeds this
     limit, the part of the printed representation for the characters
     exceeding the limit is replaced by ellipses.  The value of this
     parameter must be an exact non-negative integer, or '#f' meaning no
     limit; the default is '#f'.

          (parameterize ((param:printer-string-length-limit 4))
            (lambda ()
              (write-to-string "abcd")))
                                          => "\"abcd\""
          (parameterize ((param:printer-string-length-limit 4))
            (lambda ()
              (write-to-string "abcde")))
                                          => "\"abcd...\""

 -- parameter: param:print-with-maximum-readability?
     This parameter, which takes a boolean value, tells the printer to
     use a special printed representation for objects that normally
     print in a form that cannot be recognized by 'read'.  These objects
     are printed using the representation '#@N', where N is the result
     of calling 'hash' on the object to be printed.  The reader
     recognizes this syntax, calling 'unhash' on N to get back the
     original object.  Note that this printed representation can only be
     recognized by the Scheme program in which it was generated, because
     these hash numbers are different for each invocation of Scheme.

 -- obsolete variable: *unparser-radix*
 -- obsolete variable: *unparser-list-breadth-limit*
 -- obsolete variable: *unparser-list-depth-limit*
 -- obsolete variable: *unparser-string-length-limit*
 -- obsolete variable: *unparse-with-maximum-readability?*
     These variables are *deprecated*; instead use the corresponding
     parameter objects.


File: mit-scheme-ref.info,  Node: Blocking Mode,  Next: Terminal Mode,  Prev: Output Procedures,  Up: Input/Output

14.7 Blocking Mode
==================

An interactive port is always in one of two modes: "blocking" or
"non-blocking".  This mode is independent of the terminal mode: each can
be changed independently of the other.  Furthermore, if it is an
interactive I/O port, there are separate blocking modes for input and
for output.

   If an input port is in blocking mode, attempting to read from it when
no input is available will cause Scheme to "block", i.e. suspend itself,
until input is available.  If an input port is in non-blocking mode,
attempting to read from it when no input is available will cause the
reading procedure to return immediately, indicating the lack of input in
some way (exactly how this situation is indicated is separately
specified for each procedure or operation).

   An output port in blocking mode will block if the output device is
not ready to accept output.  In non-blocking mode it will return
immediately after performing as much output as the device will allow
(again, each procedure or operation reports this situation in its own
way).

   Interactive ports are initially in blocking mode; this can be changed
at any time with the procedures defined in this section.

   These procedures represent blocking mode by the symbol 'blocking',
and non-blocking mode by the symbol 'nonblocking'.  An argument called
MODE must be one of these symbols.  A PORT argument to any of these
procedures may be any port, even if that port does not support blocking
mode; in that case, the port is not modified in any way.

 -- procedure: input-port-blocking-mode input-port
 -- procedure: output-port-blocking-mode output-port
     Returns the blocking mode of INPUT-PORT or OUTPUT-PORT.  Returns
     '#f' if the given port doesn't support blocking mode.

 -- procedure: set-input-port-blocking-mode! input-port mode
 -- procedure: set-output-port-blocking-mode output-port mode
     Changes the blocking mode of INPUT-PORT or OUTPUT-PORT to be MODE
     and returns an unspecified value.

 -- procedure: with-input-port-blocking-mode input-port mode thunk
 -- procedure: with-output-port-blocking-mode output-port mode thunk
     THUNK must be a procedure of no arguments.

     Binds the blocking mode of INPUT-PORT or OUTPUT-PORT to be MODE,
     and calls THUNK.  When THUNK returns, the original blocking mode is
     restored and the values yielded by THUNK are returned.

 -- obsolete procedure: port/input-blocking-mode input-port
 -- obsolete procedure: port/set-input-blocking-mode input-port mode
 -- obsolete procedure: port/with-input-blocking-mode input-port mode
          thunk
 -- obsolete procedure: port/output-blocking-mode output-port
 -- obsolete procedure: port/set-output-blocking-mode output-port mode
 -- obsolete procedure: port/with-output-blocking-mode output-port mode
          thunk
     These procedures are *deprecated*; instead use the corresponding
     procedures above.


File: mit-scheme-ref.info,  Node: Terminal Mode,  Next: Format,  Prev: Blocking Mode,  Up: Input/Output

14.8 Terminal Mode
==================

A port that reads from or writes to a terminal has a "terminal mode";
this is either "cooked" or "raw".  This mode is independent of the
blocking mode: each can be changed independently of the other.
Furthermore, a terminal I/O port has independent terminal modes both for
input and for output.

   A terminal port in cooked mode provides some standard processing to
make the terminal easy to communicate with.  For example, under unix,
cooked mode on input reads from the terminal a line at a time and
provides editing within the line, while cooked mode on output might
translate linefeeds to carriage-return/linefeed pairs.  In general, the
precise meaning of cooked mode is operating-system dependent, and
furthermore might be customizable by means of operating-system
utilities.  The basic idea is that cooked mode does whatever is
necessary to make the terminal handle all of the usual user-interface
conventions for the operating system, while keeping the program's
interaction with the port as normal as possible.

   A terminal port in raw mode disables all of that processing.  In raw
mode, characters are directly read from and written to the device
without any translation or interpretation by the operating system.  On
input, characters are available as soon as they are typed, and are not
echoed on the terminal by the operating system.  In general, programs
that put ports in raw mode have to know the details of interacting with
the terminal.  In particular, raw mode is used for writing programs such
as text editors.

   Terminal ports are initially in cooked mode; this can be changed at
any time with the procedures defined in this section.

   These procedures represent cooked mode by the symbol 'cooked', and
raw mode by the symbol 'raw'.  An argument called MODE must be one of
these symbols.  A PORT argument to any of these procedures may be any
port, even if that port does not support terminal mode; in that case,
the port is not modified in any way.

 -- procedure: input-port-terminal-mode input-port
 -- procedure: output-port-terminal-mode output-port
     Returns the terminal mode of INPUT-PORT or OUTPUT-PORT.  Returns
     '#f' if the given port is not a terminal port.

 -- procedure: set-input-port-terminal-mode! input-port mode
 -- procedure: set-output-port-terminal-mode! output-port mode
     Changes the terminal mode of INPUT-PORT or OUTPUT-PORT to be MODE
     and returns an unspecified value.

 -- procedure: with-input-port-terminal-mode input-port mode thunk
 -- procedure: with-output-port-terminal-mode output-port mode thunk
     THUNK must be a procedure of no arguments.

     Binds the terminal mode of INPUT-PORT or OUTPUT-PORT to be MODE,
     and calls THUNK.  When THUNK returns, the original terminal mode is
     restored and the values yielded by THUNK are returned.

 -- obsolete procedure: port/input-terminal-mode input-port
 -- obsolete procedure: port/set-input-terminal-mode input-port mode
 -- obsolete procedure: port/with-input-terminal-mode input-port mode
          thunk
 -- obsolete procedure: port/output-terminal-mode output-port
 -- obsolete procedure: port/set-output-terminal-mode output-port mode
 -- obsolete procedure: port/with-output-terminal-mode output-port mode
          thunk
     These procedures are *deprecated*; instead use the corresponding
     procedures above.


File: mit-scheme-ref.info,  Node: Format,  Next: Custom Output,  Prev: Terminal Mode,  Up: Input/Output

14.9 Format
===========

The procedure 'format' is very useful for producing nicely formatted
text, producing good-looking messages, and so on.  MIT/GNU Scheme's
implementation of 'format' is similar to that of Common Lisp, except
that Common Lisp defines many more directives.(1)

   'format' is a run-time-loadable option.  To use it, execute

     (load-option 'format)

once before calling it.

 -- procedure: format destination control-string argument ...
     Writes the characters of CONTROL-STRING to DESTINATION, except that
     a tilde ('~') introduces a "format directive".  The character after
     the tilde, possibly preceded by prefix parameters and modifiers,
     specifies what kind of formatting is desired.  Most directives use
     one or more ARGUMENTs to create their output; the typical directive
     puts the next ARGUMENT into the output, formatted in some special
     way.  It is an error if no argument remains for a directive
     requiring an argument, but it is not an error if one or more
     arguments remain unprocessed by a directive.

     The output is sent to DESTINATION.  If DESTINATION is '#f', a
     string is created that contains the output; this string is returned
     as the value of the call to 'format'.  In all other cases 'format'
     returns an unspecified value.  If DESTINATION is '#t', the output
     is sent to the current output port.  Otherwise, DESTINATION must be
     an output port, and the output is sent there.

     This procedure performs discretionary output flushing (*note Output
     Procedures::).

     A 'format' directive consists of a tilde ('~'), optional prefix
     parameters separated by commas, optional colon (':') and at-sign
     ('@') modifiers, and a single character indicating what kind of
     directive this is.  The alphabetic case of the directive character
     is ignored.  The prefix parameters are generally integers, notated
     as optionally signed decimal numbers.  If both the colon and
     at-sign modifiers are given, they may appear in either order.

     In place of a prefix parameter to a directive, you can put the
     letter 'V' (or 'v'), which takes an ARGUMENT for use as a parameter
     to the directive.  Normally this should be an exact integer.  This
     feature allows variable-width fields and the like.  You can also
     use the character '#' in place of a parameter; it represents the
     number of arguments remaining to be processed.

     It is an error to give a format directive more parameters than it
     is described here as accepting.  It is also an error to give colon
     or at-sign modifiers to a directive in a combination not
     specifically described here as being meaningful.

     '~A'
          The next ARGUMENT, which may be any object, is printed as if
          by 'display'.  '~MINCOLA' inserts spaces on the right, if
          necessary, to make the width at least MINCOL columns.  The '@'
          modifier causes the spaces to be inserted on the left rather
          than the right.

     '~S'
          The next ARGUMENT, which may be any object, is printed as if
          by 'write'.  '~MINCOLS' inserts spaces on the right, if
          necessary, to make the width at least MINCOL columns.  The '@'
          modifier causes the spaces to be inserted on the left rather
          than the right.

     '~%'
          This outputs a '#\newline' character.  '~N%' outputs N
          newlines.  No ARGUMENT is used.  Simply putting a newline in
          CONTROL-STRING would work, but '~%' is often used because it
          makes the control string look nicer in the middle of a
          program.

     '~~'
          This outputs a tilde.  '~N~' outputs N tildes.

     '~NEWLINE'
          Tilde immediately followed by a newline ignores the newline
          and any following non-newline whitespace characters.  With an
          '@', the newline is left in place, but any following
          whitespace is ignored.  This directive is typically used when
          CONTROL-STRING is too long to fit nicely into one line of the
          program:

               (define (type-clash-error procedure arg spec actual)
                 (format
                  #t
                  "~%Procedure ~S~%requires its %A argument ~
                   to be of type ~S,~%but it was called with ~
                   an argument of type ~S.~%"
                  procedure arg spec actual))

               (type-clash-error 'vector-ref
                                 "first"
                                 'integer
                                 'vector)

               prints

               Procedure vector-ref
               requires its first argument to be of type integer,
               but it was called with an argument of type vector.

          Note that in this example newlines appear in the output only
          as specified by the '~%' directives; the actual newline
          characters in the control string are suppressed because each
          is preceded by a tilde.

   ---------- Footnotes ----------

   (1) This description of 'format' is adapted from 'Common Lisp, The
Language', second edition, section 22.3.3.


File: mit-scheme-ref.info,  Node: Custom Output,  Next: Prompting,  Prev: Format,  Up: Input/Output

14.10 Custom Output
===================

MIT/GNU Scheme provides hooks for specifying that specified objects have
special written representations.  There are no restrictions on the
written representations.

 -- procedure: define-print-method predicate print-method
     Defines the print method for objects satisfying PREDICATE to be
     PRINT-METHOD.  The PREDICATE argument must be a unary procedure
     that returns true for the objects to print specially, and
     PRINT-METHOD must be a binary procedure that accepts one of those
     objects and a textual output port.

     Although PRINT-METHOD can print the object in any way, we strongly
     recomment using one of the following special printers.

 -- procedure: standard-print-method name [get-parts]
     The NAME argument may be a unary procedure, a string, or a symbol;
     if it is a procedure it is called with the object to be printed as
     its argument and should return a string or a symbol.  The GET-PARTS
     argument, if provided, must be a unary procedure that is called
     with the object to be printed and must return a list of objects.
     If GET-PARTS is not provided, it defaults to a procedure that
     returns an empty list.

     The output generated by this method is in a standard format:
          #[<name> <hash> <part>...]
     where '<name>' is the string or symbol from NAME as printed by
     'display', '<hash>' is a unique nonnegative integer generated by
     calling 'hash-object' on the object, and the '<part>'s are the
     result of calling GET-PARTS as printed by 'write' and separated by
     spaces.

     One significant advantage of print methods generated by
     'standard-print-method' is that the parts returned by GET-PARTS are
     examined when searching for circular structure (as by 'write') or
     shared structure (as by 'write-shared').  In effect the printer
     sees one of these objects as a compound object containing those
     parts.

 -- procedure: bracketed-print-method name printer
     The NAME argument may be a unary procedure, a string, or a symbol;
     if it is a procedure it is called with the object to be printed as
     its argument and should return a string or a symbol.  The PRINTER
     argument must be a binary procedure, which is called with the
     object to print and a textual output port as its arguments.

     Similar to 'standard-print-method', this procedure prints an object
          #[<name> <hash><output>]
     where '<name>' is the string or symbol from NAME as printed by
     'display', '<hash>' is a unique nonnegative integer generated by
     calling 'hash-object' on the object, and '<output>' is the text
     written by PRINTER.

     This procedure has the benefit of printing objects using the
     standard bracketed form, but because its OUTPUT is unstructured can
     not be examined for sharing or circularity.  Generally speaking
     it's preferable to use 'standard-print-method' instead.

   The following are deprecated procedures that have been replaced by
the above.

 -- obsolete procedure: set-record-type-unparser-method! record-type
          unparser-method
     This procedure is *deprecated*; instead use
          (define-print-method (record-constructor RECORD-TYPE)
            UNPARSER-METHOD)
     provided that UNPARSER-METHOD is really a print method.

 -- obsolete procedure: unparser/set-tagged-vector-method! tag
          unparser-method
 -- obsolete procedure: unparser/set-tagged-pair-method! tag
          unparser-method
     These procedures arg *deprecated*.  There is no direct replacement
     for them.

     These were primarily used by 'define-structure', which now
     generates new-style print methods.  If you have other uses of
     these, it should be possible to translate them to use
     'define-print-method' with hand-written predicates.

 -- obsolete procedure: standard-unparser-method name procedure
     This procedure is *deprecated*; it is currently an alias for
     'bracketed-print-method'.

 -- obsolete procedure: with-current-unparser-state unparser-state
          procedure
     This procedure is *deprecated*, with no direct replacement.  In
     general just use PROCEDURE without wrapping it.


File: mit-scheme-ref.info,  Node: Prompting,  Next: Textual Port Primitives,  Prev: Custom Output,  Up: Input/Output

14.11 Prompting
===============

This section describes procedures that prompt the user for input.  Why
should the programmer use these procedures when it is possible to do
prompting using ordinary input and output procedures?  One reason is
that the prompting procedures are more succinct.  However, a second and
better reason is that the prompting procedures can be separately
customized for each user interface, providing more natural interaction.
The interfaces for Edwin and for GNU Emacs have already been customized
in this fashion; because Edwin and Emacs are very similar editors, their
customizations provide very similar behavior.

   Each of these procedure accepts an optional argument called PORT,
which if given must be an I/O port.  If not given, this port defaults to
the value of '(interaction-i/o-port)'; this is initially the console I/O
port.

 -- procedure: prompt-for-command-expression prompt [port]
     Prompts the user for an expression that is to be executed as a
     command.  This is the procedure called by the REP loop to read the
     user's expressions.

     If PROMPT is a string, it is used verbatim as the prompt string.
     Otherwise, it must be a pair whose car is the symbol 'standard' and
     whose cdr is a string; in this case the prompt string is formed by
     prepending to the string the current REP loop "level number" and a
     space.  Also, a space is appended to the string, unless it already
     ends in a space or is an empty string.

     The default behavior of this procedure is to print a fresh line, a
     newline, and the prompt string; flush the output buffer; then read
     an object and return it.  v Under Edwin and Emacs, before the
     object is read, the interaction buffer is put into a mode that
     allows expressions to be edited and submitted for input using
     specific editor commands.  The first expression that is submitted
     is returned as the value of this procedure.

 -- procedure: prompt-for-command-char prompt [port]
     Prompts the user for a single character that is to be executed as a
     command; the returned character is guaranteed to satisfy
     'char-graphic?'.  If at all possible, the character is read from
     the user interface using a mode that reads the character as a
     single keystroke; in other words, it should not be necessary for
     the user to follow the character with a carriage return or
     something similar.

     This is the procedure called by 'debug' and 'where' to read the
     user's commands.

     If PROMPT is a string, it is used verbatim as the prompt string.
     Otherwise, it must be a pair whose car is 'standard' and whose cdr
     is a string; in this case the prompt string is formed by prepending
     to the string the current REP loop "level number" and a space.
     Also, a space is appended to the string, unless it already ends in
     a space or is an empty string.

     The default behavior of this procedure is to print a fresh line, a
     newline, and the prompt string; flush the output buffer; read a
     character in raw mode, echo that character, and return it.

     Under Edwin and Emacs, instead of reading a character, the
     interaction buffer is put into a mode in which graphic characters
     submit themselves as input.  After this mode change, the first such
     character submitted is returned as the value of this procedure.

 -- procedure: prompt-for-expression prompt [port]
     Prompts the user for an expression.

     The prompt string is formed by appending a colon and a space to
     PROMPT, unless PROMPT already ends in a space or is the null
     string.

     The default behavior of this procedure is to print a fresh line, a
     newline, and the prompt string; flush the output buffer; then read
     an object and return it.

     Under Edwin and Emacs, the expression is read in the minibuffer.

 -- procedure: prompt-for-evaluated-expression prompt [environment
          [port]]
     Prompts the user for an evaluated expression.  Calls
     'prompt-for-expression' to read an expression, then evaluates the
     expression using ENVIRONMENT; if ENVIRONMENT is not given, the REP
     loop environment is used.

 -- procedure: prompt-for-confirmation prompt [port]
     Prompts the user for confirmation.  The result yielded by this
     procedure is a boolean.

     The prompt string is formed by appending the string '" (y or n)? "'
     to PROMPT, unless PROMPT already ends in a space or is the null
     string.

     The default behavior of this procedure is to print a fresh line, a
     newline, and the prompt string; flush the output buffer; then read
     a character in raw mode.  If the character is '#\y', '#\Y', or
     '#\space', the procedure returns '#t'; If the character is '#\n',
     '#\N', or '#\rubout', the procedure returns '#f'.  Otherwise the
     prompt is repeated.

     Under Edwin or Emacs, the confirmation is read in the minibuffer.


File: mit-scheme-ref.info,  Node: Textual Port Primitives,  Next: Parser Buffers,  Prev: Prompting,  Up: Input/Output

14.12 Textual Port Primitives
=============================

This section describes the low-level operations that can be used to
build and manipulate textual I/O ports.  The purpose of these operations
is to allow programmers to construct new kinds of textual I/O ports.

   The mechanisms described in this section are exclusively for textual
ports; binary ports can't be customized.  In this section, any reference
to a "port" that isn't modified by "textual" or "binary" is assumed to
be a textual port.

   The abstract model of a textual I/O port, as implemented here, is a
combination of a set of named operations and a state.  The state is an
arbitrary object, the meaning of which is determined by the operations.
The operations are defined by a mapping from names to procedures.

   The set of named operations is represented by an object called a
"textual port type".  A port type is constructed from a set of named
operations, and is subsequently used to construct a port.  The port type
completely specifies the behavior of the port.  Port types also support
a simple form of inheritance, allowing you to create new ports that are
similar to existing ports.

   The port operations are divided into two classes:

Standard operations
     There is a specific set of standard operations for input ports, and
     a different set for output ports.  Applications can assume that the
     standard input operations are implemented for all input ports, and
     likewise the standard output operations are implemented for all
     output ports.

Custom operations
     Some ports support additional operations.  For example, ports that
     implement output to terminals (or windows) may define an operation
     named 'y-size' that returns the height of the terminal in
     characters.  Because only some ports will implement these
     operations, programs that use custom operations must test each port
     for their existence, and be prepared to deal with ports that do not
     implement them.

* Menu:

* Textual Port Types::
* Constructors and Accessors for Textual Ports::
* Textual Input Port Operations::
* Textual Output Port Operations::


File: mit-scheme-ref.info,  Node: Textual Port Types,  Next: Constructors and Accessors for Textual Ports,  Prev: Textual Port Primitives,  Up: Textual Port Primitives

14.12.1 Textual Port Types
--------------------------

The procedures in this section provide means for constructing port types
with standard and custom operations, and accessing their operations.

 -- procedure: make-textual-port-type operations port-type
     Creates and returns a new port type.  OPERATIONS must be a list;
     each element is a list of two elements, the name of the operation
     (a symbol) and the procedure that implements it.  PORT-TYPE is
     either '#f' or a port type; if it is a port type, any operations
     implemented by PORT-TYPE but not specified in OPERATIONS will be
     implemented by the resulting port type.

     OPERATIONS need not contain definitions for all of the standard
     operations; the procedure will provide defaults for any standard
     operations that are not defined.  At a minimum, the following
     operations must be defined: for input ports, 'read-char' and
     'peek-char'; for output ports, either 'write-char' or
     'write-substring'.  I/O ports must supply the minimum operations
     for both input and output.

     If an operation in OPERATIONS is defined to be '#f', then the
     corresponding operation in PORT-TYPE is _not_ inherited.

     If 'read-char' is defined in OPERATIONS, then any standard input
     operations defined in PORT-TYPE are ignored.  Likewise, if
     'write-char' or 'write-substring' is defined in OPERATIONS, then
     any standard output operations defined in PORT-TYPE are ignored.
     This feature allows overriding the standard operations without
     having to enumerate them.

 -- procedure: textual-port-type? object
 -- procedure: textual-input-port-type? object
 -- procedure: textual-output-port-type? object
 -- procedure: textual-i/o-port-type? object
     These predicates return '#t' if OBJECT is a port type, input-port
     type, output-port type, or I/O-port type, respectively.  Otherwise,
     they return '#f'.

 -- obsolete procedure: make-port-type operations port-type
 -- obsolete procedure: port-type? object
 -- obsolete procedure: input-port-type? object
 -- obsolete procedure: output-port-type? object
 -- obsolete procedure: i/o-port-type? object
     These procedures are *deprecated*; use the procedures defined
     above.

 -- obsolete procedure: port-type/operations port-type
 -- obsolete procedure: port-type/operation-names port-type
 -- obsolete procedure: port-type/operation port-type symbol
     These procedures are *deprecated* and will be removed in the near
     future.  There are no replacements planned.


File: mit-scheme-ref.info,  Node: Constructors and Accessors for Textual Ports,  Next: Textual Input Port Operations,  Prev: Textual Port Types,  Up: Textual Port Primitives

14.12.2 Constructors and Accessors for Textual Ports
----------------------------------------------------

The procedures in this section provide means for constructing ports,
accessing the type of a port, and manipulating the state of a port.

 -- procedure: make-textual-port port-type state
     Returns a new port with type PORT-TYPE and the given STATE.  The
     port will be an input, output, or I/O port according to PORT-TYPE.

 -- procedure: textual-port-type textual-port
     Returns the port type of TEXTUAL-PORT.

 -- procedure: textual-port-state textual-port
     Returns the state component of TEXTUAL-PORT.

 -- procedure: set-textual-port-state! textual-port object
     Changes the state component of TEXTUAL-PORT to be OBJECT.  Returns
     an unspecified value.

 -- procedure: textual-port-operation textual-port symbol
     Returns the operation named SYMBOL for TEXTUAL-PORT.  If
     TEXTUAL-PORT has no such operation, returns '#f'.

 -- procedure: textual-port-operation-names textual-port
     Returns a newly allocated list whose elements are the names of the
     operations implemented by TEXTUAL-PORT.

 -- obsolete procedure: make-port port-type state
 -- obsolete procedure: port/type textual-port
 -- obsolete procedure: port/state textual-port
 -- obsolete procedure: set-port/state! textual-port object
 -- obsolete procedure: port/operation textual-port symbol
 -- obsolete procedure: port/operation-names port
     These procedures are *deprecated*; use the procedures defined
     above.


File: mit-scheme-ref.info,  Node: Textual Input Port Operations,  Next: Textual Output Port Operations,  Prev: Constructors and Accessors for Textual Ports,  Up: Textual Port Primitives

14.12.3 Textual Input Port Operations
-------------------------------------

This section describes the standard operations on textual input ports.
Following that, some useful custom operations are described.

 -- operation on textual input port: read-char port
     Removes the next character available from PORT and returns it.  If
     PORT has no more characters and will never have any (e.g. at the
     end of an input file), this operation returns an end-of-file
     object.  If PORT has no more characters but will eventually have
     some more (e.g. a terminal where nothing has been typed recently),
     and it is in non-blocking mode, '#f' is returned; otherwise the
     operation hangs until input is available.

 -- operation on textual input port: peek-char port
     Reads the next character available from PORT and returns it.  The
     character is _not_ removed from PORT, and a subsequent attempt to
     read from the port will get that character again.  In other
     respects this operation behaves like 'read-char'.

 -- operation on textual input port: char-ready? port k
     'char-ready?' returns '#t' if at least one character is available
     to be read from PORT.  If no characters are available, the
     operation waits up to K milliseconds before returning '#f',
     returning immediately if any characters become available while it
     is waiting.

 -- operation on textual input port: read-string port char-set
 -- operation on textual input port: discard-chars port char-set
     These operations are like 'read-char', except that they read or
     discard multiple characters at once.  All characters up to, but
     excluding, the first character in CHAR-SET (or end of file) are
     read from PORT.  'read-string' returns these characters as a newly
     allocated string, while 'discard-chars' discards them and returns
     an unspecified value.  These operations hang until sufficient input
     is available, even if PORT is in non-blocking mode.  If end of file
     is encountered before any input characters, 'read-string' returns
     an end-of-file object.

 -- operation on textual input port: read-substring port string start
          end
     Reads characters from PORT into the substring defined by STRING,
     START, and END until either the substring has been filled or there
     are no more characters available.  Returns the number of characters
     written to the substring.

     If PORT is an interactive port, and at least one character is
     immediately available, the available characters are written to the
     substring and this operation returns immediately.  If no characters
     are available, and PORT is in blocking mode, the operation blocks
     until at least one character is available.  Otherwise, the
     operation returns '#f' immediately.

     This is an extremely fast way to read characters from a port.

 -- procedure: input-port/read-char textual-input-port
 -- procedure: input-port/peek-char textual-input-port
 -- procedure: input-port/char-ready? textual-input-port k
 -- procedure: input-port/read-string textual-input-port char-set
 -- procedure: input-port/discard-chars textual-input-port char-set
 -- procedure: input-port/read-substring textual-input-port string start
          end
     Each of these procedures invokes the respective operation on
     TEXTUAL-INPUT-PORT.  For example, the following are equivalent:

          (input-port/read-char TEXTUAL-INPUT-PORT)
          ((textual-port-operation TEXTUAL-INPUT-PORT 'read-char)
           TEXTUAL-INPUT-PORT)

   The following custom operations are implemented for input ports to
files, and will also work with some other kinds of input ports:

 -- operation on textual input port: eof? port
     Returns '#t' if PORT is known to be at end of file, otherwise it
     returns '#f'.

 -- operation on textual input port: chars-remaining port
     Returns an estimate of the number of characters remaining to be
     read from PORT.  This is useful only when PORT is a file port in
     binary mode; in other cases, it returns '#f'.

 -- operation on textual input port: buffered-input-chars port
     Returns the number of unread characters that are stored in PORT's
     buffer.  This will always be less than or equal to the buffer's
     size.

 -- operation on textual input port: input-buffer-size port
     Returns the maximum number of characters that PORT's buffer can
     hold.

 -- operation on textual input port: set-input-buffer-size port size
     Resizes PORT's buffer so that it can hold at most SIZE characters.
     Characters in the buffer are discarded.  SIZE must be an exact
     non-negative integer.


File: mit-scheme-ref.info,  Node: Textual Output Port Operations,  Prev: Textual Input Port Operations,  Up: Textual Port Primitives

14.12.4 Textual Output Port Operations
--------------------------------------

This section describes the standard operations on output ports.
Following that, some useful custom operations are described.

 -- operation on textual output port: write-char port char
     Writes CHAR to PORT and returns an unspecified value.

 -- operation on textual output port: write-substring port string start
          end
     Writes the substring specified by STRING, START, and END to PORT
     and returns an unspecified value.  Equivalent to writing the
     characters of the substring, one by one, to PORT, but is
     implemented very efficiently.

 -- operation on textual output port: fresh-line port
     Most output ports are able to tell whether or not they are at the
     beginning of a line of output.  If PORT is such a port, end-of-line
     is written to the port only if the port is not already at the
     beginning of a line.  If PORT is not such a port, an end-of-line is
     unconditionally written to the port.  Returns an unspecified value.

 -- operation on textual output port: flush-output port
     If PORT is buffered, this causes its buffer to be written out.
     Otherwise it has no effect.  Returns an unspecified value.

 -- operation on textual output port: discretionary-flush-output port
     Normally, this operation does nothing.  However, ports that support
     discretionary output flushing implement this operation identically
     to 'flush-output'.

 -- procedure: output-port/write-char textual-output-port char
 -- procedure: output-port/write-substring textual-output-port string
          start end
 -- procedure: output-port/fresh-line textual-output-port
 -- procedure: output-port/flush-output textual-output-port
 -- procedure: output-port/discretionary-flush-output
          textual-output-port
     Each of these procedures invokes the respective operation on
     TEXTUAL-OUTPUT-PORT.  For example, the following are equivalent:

          (output-port/write-char TEXTUAL-OUTPUT-PORT CHAR)
          ((textual-port-operation TEXTUAL-OUTPUT-PORT 'write-char)
           TEXTUAL-OUTPUT-PORT CHAR)

 -- procedure: output-port/write-string textual-output-port string
     Writes STRING to TEXTUAL-OUTPUT-PORT.  Equivalent to

          (output-port/write-substring TEXTUAL-OUTPUT-PORT
                                       STRING
                                       0
                                       (string-length STRING))

   The following custom operations are generally useful.

 -- operation on textual output port: buffered-output-chars port
     Returns the number of unwritten characters that are stored in
     PORT's buffer.  This will always be less than or equal to the
     buffer's size.

 -- operation on textual output port: output-buffer-size port
     Returns the maximum number of characters that PORT's buffer can
     hold.

 -- operation on textual output port: set-output-buffer-size port size
     Resizes PORT's buffer so that it can hold at most SIZE characters.
     Characters in the buffer are discarded.  SIZE must be an exact
     non-negative integer.

 -- operation on textual output port: x-size port
     Returns an exact positive integer that is the width of PORT in
     characters.  If PORT has no natural width, e.g. if it is a file
     port, '#f' is returned.

 -- operation on textual output port: y-size port
     Returns an exact positive integer that is the height of PORT in
     characters.  If PORT has no natural height, e.g. if it is a file
     port, '#f' is returned.

 -- procedure: output-port/x-size textual-output-port
     This procedure invokes the custom operation whose name is the
     symbol 'x-size', if it exists.  If the 'x-size' operation is both
     defined and returns a value other than '#f', that value is returned
     as the result of this procedure.  Otherwise, 'output-port/x-size'
     returns a default value (currently '80').

     'output-port/x-size' is useful for programs that tailor their
     output to the width of the display (a fairly common practice).  If
     the output device is not a display, such programs normally want
     some reasonable default width to work with, and this procedure
     provides exactly that.

 -- procedure: output-port/y-size textual-output-port
     This procedure invokes the custom operation whose name is the
     symbol 'y-size', if it exists.  If the 'y-size' operation is
     defined, the value it returns is returned as the result of this
     procedure; otherwise, '#f' is returned.


File: mit-scheme-ref.info,  Node: Parser Buffers,  Next: Parser Language,  Prev: Textual Port Primitives,  Up: Input/Output

14.13 Parser Buffers
====================

The "parser buffer" mechanism facilitates construction of parsers for
complex grammars.  It does this by providing an input stream with
unbounded buffering and backtracking.  The amount of buffering is under
program control.  The stream can backtrack to any position in the
buffer.

   The mechanism defines two data types: the "parser buffer" and the
"parser-buffer pointer".  A parser buffer is like an input port with
buffering and backtracking.  A parser-buffer pointer is a pointer into
the stream of characters provided by a parser buffer.

   Note that all of the procedures defined here consider a parser buffer
to contain a stream of Unicode characters.

   There are several constructors for parser buffers:

 -- procedure: textual-input-port->parser-buffer textual-input-port
 -- obsolete procedure: input-port->parser-buffer textual-input-port
     Returns a parser buffer that buffers characters read from
     TEXTUAL-INPUT-PORT.

 -- procedure: substring->parser-buffer string start end
     Returns a parser buffer that buffers the characters in the argument
     substring.  This is equivalent to creating a string input port and
     calling 'textual-input-port->parser-buffer', but it runs faster and
     uses less memory.

 -- procedure: string->parser-buffer string
     Like 'substring->parser-buffer' but buffers the entire string.

 -- procedure: source->parser-buffer source
     Returns a parser buffer that buffers the characters returned by
     calling SOURCE.  SOURCE is a procedure of three arguments: a
     string, a start index, and an end index (in other words, a
     substring specifier).  Each time SOURCE is called, it writes some
     characters in the substring, and returns the number of characters
     written.  When there are no more characters available, it returns
     zero.  It must not return zero in any other circumstance.

   Parser buffers and parser-buffer pointers may be distinguished from
other objects:

 -- procedure: parser-buffer? object
     Returns '#t' if OBJECT is a parser buffer, otherwise returns '#f'.

 -- procedure: parser-buffer-pointer? object
     Returns '#t' if OBJECT is a parser-buffer pointer, otherwise
     returns '#f'.

   Characters can be read from a parser buffer much as they can be read
from an input port.  The parser buffer maintains an internal pointer
indicating its current position in the input stream.  Additionally, the
buffer remembers all characters that were previously read, and can look
at characters arbitrarily far ahead in the stream.  It is this buffering
capability that facilitates complex matching and backtracking.

 -- procedure: read-parser-buffer-char buffer
     Returns the next character in BUFFER, advancing the internal
     pointer past that character.  If there are no more characters
     available, returns '#f' and leaves the internal pointer unchanged.

 -- procedure: peek-parser-buffer-char buffer
     Returns the next character in BUFFER, or '#f' if no characters are
     available.  Leaves the internal pointer unchanged.

 -- procedure: parser-buffer-ref buffer index
     Returns a character in BUFFER.  INDEX is a non-negative integer
     specifying the character to be returned.  If INDEX is zero, returns
     the next available character; if it is one, returns the character
     after that, and so on.  If INDEX specifies a position after the
     last character in BUFFER, returns '#f'.  Leaves the internal
     pointer unchanged.

   The internal pointer of a parser buffer can be read or written:

 -- procedure: get-parser-buffer-pointer buffer
     Returns a parser-buffer pointer object corresponding to the
     internal pointer of BUFFER.

 -- procedure: set-parser-buffer-pointer! buffer pointer
     Sets the internal pointer of BUFFER to the position specified by
     POINTER.  POINTER must have been returned from a previous call of
     'get-parser-buffer-pointer' on BUFFER.  Additionally, if some of
     BUFFER's characters have been discarded by
     'discard-parser-buffer-head!', POINTER must be outside the range
     that was discarded.

 -- procedure: get-parser-buffer-tail buffer pointer
     Returns a newly-allocated string consisting of all of the
     characters in BUFFER that fall between POINTER and BUFFER's
     internal pointer.  POINTER must have been returned from a previous
     call of 'get-parser-buffer-pointer' on BUFFER.  Additionally, if
     some of BUFFER's characters have been discarded by
     'discard-parser-buffer-head!', POINTER must be outside the range
     that was discarded.

 -- procedure: discard-parser-buffer-head! buffer
     Discards all characters in BUFFER that have already been read; in
     other words, all characters prior to the internal pointer.  After
     this operation has completed, it is no longer possible to move the
     internal pointer backwards past the current position by calling
     'set-parser-buffer-pointer!'.

   The next rather large set of procedures does conditional matching
against the contents of a parser buffer.  All matching is performed
relative to the buffer's internal pointer, so the first character to be
matched against is the next character that would be returned by
'peek-parser-buffer-char'.  The returned value is always '#t' for a
successful match, and '#f' otherwise.  For procedures whose names do not
end in '-no-advance', a successful match also moves the internal pointer
of the buffer forward to the end of the matched text; otherwise the
internal pointer is unchanged.

 -- procedure: match-parser-buffer-char buffer char
 -- procedure: match-parser-buffer-char-ci buffer char
 -- procedure: match-parser-buffer-not-char buffer char
 -- procedure: match-parser-buffer-not-char-ci buffer char
 -- procedure: match-parser-buffer-char-no-advance buffer char
 -- procedure: match-parser-buffer-char-ci-no-advance buffer char
 -- procedure: match-parser-buffer-not-char-no-advance buffer char
 -- procedure: match-parser-buffer-not-char-ci-no-advance buffer char
     Each of these procedures compares a single character in BUFFER to
     CHAR.  The basic comparison 'match-parser-buffer-char' compares the
     character to CHAR using 'char=?'.  The procedures whose names
     contain the '-ci' modifier do case-insensitive comparison (i.e.
     they use 'char-ci=?').  The procedures whose names contain the
     'not-' modifier are successful if the character _doesn't_ match
     CHAR.

 -- procedure: match-parser-buffer-char-in-set buffer char-set
 -- procedure: match-parser-buffer-char-in-set-no-advance buffer
          char-set
     These procedures compare the next character in BUFFER against
     CHAR-SET using 'char-in-set?'.

 -- procedure: match-parser-buffer-string buffer string
 -- procedure: match-parser-buffer-string-ci buffer string
 -- procedure: match-parser-buffer-string-no-advance buffer string
 -- procedure: match-parser-buffer-string-ci-no-advance buffer string
     These procedures match STRING against BUFFER's contents.  The '-ci'
     procedures do case-insensitive matching.

 -- procedure: match-parser-buffer-substring buffer string start end
 -- procedure: match-parser-buffer-substring-ci buffer string start end
 -- procedure: match-parser-buffer-substring-no-advance buffer string
          start end
 -- procedure: match-parser-buffer-substring-ci-no-advance buffer string
          start end
     These procedures match the specified substring against BUFFER's
     contents.  The '-ci' procedures do case-insensitive matching.

   The remaining procedures provide information that can be used to
identify locations in a parser buffer's stream.

 -- procedure: parser-buffer-position-string pointer
     Returns a string describing the location of POINTER in terms of its
     character and line indexes.  This resulting string is meant to be
     presented to an end user in order to direct their attention to a
     feature in the input stream.  In this string, the indexes are
     presented as one-based numbers.

     POINTER may alternatively be a parser buffer, in which case it is
     equivalent to having specified the buffer's internal pointer.

 -- procedure: parser-buffer-pointer-index pointer
 -- procedure: parser-buffer-pointer-line pointer
     Returns the character or line index, respectively, of POINTER.
     Both indexes are zero-based.


File: mit-scheme-ref.info,  Node: Parser Language,  Next: XML Support,  Prev: Parser Buffers,  Up: Input/Output

14.14 Parser Language
=====================

Although it is possible to write parsers using the parser-buffer
abstraction (*note Parser Buffers::), it is tedious.  The problem is
that the abstraction isn't closely matched to the way that people think
about syntactic structures.  In this section, we introduce a
higher-level mechanism that greatly simplifies the implementation of a
parser.

   The "parser language" described here allows the programmer to write
BNF-like specifications that are translated into efficient Scheme code
at compile time.  The language is declarative, but it can be freely
mixed with Scheme code; this allows the parsing of grammars that aren't
conveniently described in the language.

   The language also provides backtracking.  For example, this
expression matches any sequence of alphanumeric characters followed by a
single alphabetic character:

     (*matcher
      (seq (* (char-set char-set:alphanumeric))
           (char-set char-set:alphabetic)))

The way that this works is that the matcher matches alphanumeric
characters in the input stream until it finds a non-alphanumeric
character.  It then tries to match an alphabetic character, which of
course fails.  At this point, if it matched at least one alphanumeric
character, it _backtracks_: the last matched alphanumeric is
"unmatched", and it again attempts to match an alphabetic character.
The backtracking can be arbitrarily deep; the matcher will continue to
back up until it finds a way to match the remainder of the expression.

   So far, this sounds a lot like regular-expression matching (*note
Regular Expressions::).  However, there are some important differences.

   * The parser language uses a Scheme-like syntax that is easier to
     read and write than regular-expression notation.

   * The language provides macros so that common syntactic constructs
     can be abstracted.

   * The language mixes easily with Scheme code, allowing the full power
     of Scheme to be applied to program around limitations in the parser
     language.

   * The language provides expressive facilities for converting syntax
     into parsed structure.  It also makes it easy to convert parsed
     strings into meaningful objects (e.g. numbers).

   * The language is compiled into machine language; regular expressions
     are usually interpreted.

   Here is an example that shows off several of the features of the
parser language.  The example is a parser for XML start tags:

     (*parser
      (with-pointer p
        (seq "<"
             parse-name
             parse-attribute-list
             (alt (match ">")
                  (match "/>")
                  (sexp
                   (lambda (b)
                     (error
                      (string-append
                       "Unterminated start tag at "
                       (parser-buffer-position-string p)))))))))

This shows that the basic description of a start tag is very similar to
its BNF.  Non-terminal symbols 'parse-name' and 'parse-attribute-list'
do most of the work, and the noise strings '"<"' and '">"' are the
syntactic markers delimiting the form.  There are two alternate endings
for start tags, and if the parser doesn't find either of the endings,
the Scheme code (wrapped in 'sexp') is run to signal an error.  The
error procedure 'perror' takes a pointer 'p', which it uses to indicate
the position in the input stream at which the error occurred.  In this
case, that is the beginning of the start tag, i.e. the position of the
leading '"<"' marker.

   This example still looks pretty complicated, mostly due to the
error-signalling code.  In practice, this is abstracted into a macro,
after which the expression is quite succinct:

     (*parser
      (bracket "start tag"
          (seq (noise (string "<")) parse-name)
          (match (alt (string ">") (string "/>")))
        parse-attribute-list))

The 'bracket' macro captures the pattern of a bracketed item, and hides
much of the detail.

   The parser language actually consists of two languages: one for
defining matchers, and one for defining parsers.  The languages are
intentionally very similar, and are meant to be used together.  Each
sub-language is described below in its own section.

   The parser language is a run-time-loadable option; to use it, execute

     (load-option '*parser)

once before compiling any code that uses the language.

* Menu:

* *Matcher::
* *Parser::
* Parser-language Macros::


File: mit-scheme-ref.info,  Node: *Matcher,  Next: *Parser,  Prev: Parser Language,  Up: Parser Language

14.14.1 *Matcher
----------------

The "matcher language" is a declarative language for specifying a
"matcher procedure".  A matcher procedure is a procedure that accepts a
single parser-buffer argument and returns a boolean value indicating
whether the match it performs was successful.  If the match succeeds,
the internal pointer of the parser buffer is moved forward over the
matched text.  If the match fails, the internal pointer is unchanged.

   For example, here is a matcher procedure that matches the character
'a':

     (lambda (b) (match-parser-buffer-char b #\a))

Here is another example that matches two given characters, C1 and C2, in
sequence:

     (lambda (b)
       (let ((p (get-parser-buffer-pointer b)))
         (if (match-parser-buffer-char b C1)
             (if (match-parser-buffer-char b C2)
                 #t
                 (begin
                   (set-parser-buffer-pointer! b p)
                   #f))
             #f)))

This is code is clear, but has lots of details that get in the way of
understanding what it is doing.  Here is the same example in the matcher
language:

     (*matcher (seq (char C1) (char C2)))

This is much simpler and more intuitive.  And it generates virtually the
same code:

     (pp (*matcher (seq (char c1) (char c2))))
     -| (lambda (#[b1])
     -|   (let ((#[p1] (get-parser-buffer-pointer #[b1])))
     -|     (and (match-parser-buffer-char #[b1] c1)
     -|          (if (match-parser-buffer-char #[b1] c2)
     -|              #t
     -|              (begin
     -|                (set-parser-buffer-pointer! #[b1] #[p1])
     -|                #f)))))

   Now that we have seen an example of the language, it's time to look
at the detail.  The '*matcher' special form is the interface between the
matcher language and Scheme.

 -- special form: *matcher mexp
     The operand MEXP is an expression in the matcher language.  The
     '*matcher' expression expands into Scheme code that implements a
     matcher procedure.

   Here are the predefined matcher expressions.  New matcher expressions
can be defined using the macro facility (*note Parser-language
Macros::).  We will start with the primitive expressions.

 -- matcher expression: char expression
 -- matcher expression: char-ci expression
 -- matcher expression: not-char expression
 -- matcher expression: not-char-ci expression
     These expressions match a given character.  In each case, the
     EXPRESSION operand is a Scheme expression that must evaluate to a
     character at run time.  The '-ci' expressions do case-insensitive
     matching.  The 'not-' expressions match any character other than
     the given one.

 -- matcher expression: string expression
 -- matcher expression: string-ci expression
     These expressions match a given string.  The EXPRESSION operand is
     a Scheme expression that must evaluate to a string at run time.
     The 'string-ci' expression does case-insensitive matching.

 -- matcher expression: char-set expression
     These expressions match a single character that is a member of a
     given character set.  The EXPRESSION operand is a Scheme expression
     that must evaluate to a character set at run time.

 -- matcher expression: end-of-input
     The 'end-of-input' expression is successful only when there are no
     more characters available to be matched.

 -- matcher expression: discard-matched
     The 'discard-matched' expression always successfully matches the
     null string.  However, it isn't meant to be used as a matching
     expression; it is used for its effect.  'discard-matched' causes
     all of the buffered text prior to this point to be discarded (i.e.
     it calls 'discard-parser-buffer-head!' on the parser buffer).

     Note that 'discard-matched' may not be used in certain places in a
     matcher expression.  The reason for this is that it deliberately
     discards information needed for backtracking, so it may not be used
     in a place where subsequent backtracking will need to back over it.
     As a rule of thumb, use 'discard-matched' only in the last operand
     of a 'seq' or 'alt' expression (including any 'seq' or 'alt'
     expressions in which it is indirectly contained).

   In addition to the above primitive expressions, there are two
convenient abbreviations.  A character literal (e.g. '#\A') is a legal
primitive expression, and is equivalent to a 'char' expression with that
literal as its operand (e.g. '(char #\A)').  Likewise, a string literal
is equivalent to a 'string' expression (e.g. '(string "abc")').

   Next there are several combinator expressions.  These closely
correspond to similar combinators in regular expressions.  Parameters
named MEXP are arbitrary expressions in the matcher language.

 -- matcher expression: seq mexp ...
     This matches each MEXP operand in sequence.  For example,

          (seq (char-set char-set:alphabetic)
               (char-set char-set:numeric))

     matches an alphabetic character followed by a numeric character,
     such as 'H4'.

     Note that if there are no MEXP operands, the 'seq' expression
     successfully matches the null string.

 -- matcher expression: alt mexp ...
     This attempts to match each MEXP operand in order from left to
     right.  The first one that successfully matches becomes the match
     for the entire 'alt' expression.

     The 'alt' expression participates in backtracking.  If one of the
     MEXP operands matches, but the overall match in which this
     expression is embedded fails, the backtracking mechanism will cause
     the 'alt' expression to try the remaining MEXP operands.  For
     example, if the expression

          (seq (alt "ab" "a") "b")

     is matched against the text 'abc', the 'alt' expression will
     initially match its first operand.  But it will then fail to match
     the second operand of the 'seq' expression.  This will cause the
     'alt' to be restarted, at which time it will match 'a', and the
     overall match will succeed.

     Note that if there are no MEXP operands, the 'alt' match will
     always fail.

 -- matcher expression: * mexp
     This matches zero or more occurrences of the MEXP operand.
     (Consequently this match always succeeds.)

     The '*' expression participates in backtracking; if it matches N
     occurrences of MEXP, but the overall match fails, it will backtrack
     to N-1 occurrences and continue.  If the overall match continues to
     fail, the '*' expression will continue to backtrack until there are
     no occurrences left.

 -- matcher expression: + mexp
     This matches one or more occurrences of the MEXP operand.  It is
     equivalent to

          (seq MEXP (* MEXP))

 -- matcher expression: ? mexp
     This matches zero or one occurrences of the MEXP operand.  It is
     equivalent to

          (alt MEXP (seq))

 -- matcher expression: sexp expression
     The 'sexp' expression allows arbitrary Scheme code to be embedded
     inside a matcher.  The EXPRESSION operand must evaluate to a
     matcher procedure at run time; the procedure is called to match the
     parser buffer.  For example,

          (*matcher
           (seq "a"
                (sexp parse-foo)
                "b"))

     expands to

          (lambda (#[b1])
            (let ((#[p1] (get-parser-buffer-pointer #[b1])))
              (and (match-parser-buffer-char #[b1] #\a)
                   (if (parse-foo #[b1])
                       (if (match-parser-buffer-char #[b1] #\b)
                           #t
                           (begin
                             (set-parser-buffer-pointer! #[b1] #[p1])
                             #f))
                       (begin
                         (set-parser-buffer-pointer! #[b1] #[p1])
                         #f)))))

     The case in which EXPRESSION is a symbol is so common that it has
     an abbreviation: '(sexp SYMBOL)' may be abbreviated as just SYMBOL.

 -- matcher expression: with-pointer identifier mexp
     The 'with-pointer' expression fetches the parser buffer's internal
     pointer (using 'get-parser-buffer-pointer'), binds it to
     IDENTIFIER, and then matches the pattern specified by MEXP.
     IDENTIFIER must be a symbol.

     This is meant to be used on conjunction with 'sexp', as a way to
     capture a pointer to a part of the input stream that is outside the
     'sexp' expression.  An example of the use of 'with-pointer' appears
     above (*note with-pointer example::).


File: mit-scheme-ref.info,  Node: *Parser,  Next: Parser-language Macros,  Prev: *Matcher,  Up: Parser Language

14.14.2 *Parser
---------------

The "parser language" is a declarative language for specifying a "parser
procedure".  A parser procedure is a procedure that accepts a single
parser-buffer argument and parses some of the input from the buffer.  If
the parse is successful, the procedure returns a vector of objects that
are the result of the parse, and the internal pointer of the parser
buffer is advanced past the input that was parsed.  If the parse fails,
the procedure returns '#f' and the internal pointer is unchanged.  This
interface is much like that of a matcher procedure, except that on
success the parser procedure returns a vector of values rather than
'#t'.

   The '*parser' special form is the interface between the parser
language and Scheme.

 -- special form: *parser pexp
     The operand PEXP is an expression in the parser language.  The
     '*parser' expression expands into Scheme code that implements a
     parser procedure.

   There are several primitive expressions in the parser language.  The
first two provide a bridge to the matcher language (*note *Matcher::):

 -- parser expression: match mexp
     The 'match' expression performs a match on the parser buffer.  The
     match to be performed is specified by MEXP, which is an expression
     in the matcher language.  If the match is successful, the result of
     the 'match' expression is a vector of one element: a string
     containing that text.

 -- parser expression: noise mexp
     The 'noise' expression performs a match on the parser buffer.  The
     match to be performed is specified by MEXP, which is an expression
     in the matcher language.  If the match is successful, the result of
     the 'noise' expression is a vector of zero elements.  (In other
     words, the text is matched and then thrown away.)

     The MEXP operand is often a known character or string, so in the
     case that MEXP is a character or string literal, the 'noise'
     expression can be abbreviated as the literal.  In other words,
     '(noise "foo")' can be abbreviated just '"foo"'.

 -- parser expression: values expression ...
     Sometimes it is useful to be able to insert arbitrary values into
     the parser result.  The 'values' expression supports this.  The
     EXPRESSION arguments are arbitrary Scheme expressions that are
     evaluated at run time and returned in a vector.  The 'values'
     expression always succeeds and never modifies the internal pointer
     of the parser buffer.

 -- parser expression: discard-matched
     The 'discard-matched' expression always succeeds, returning a
     vector of zero elements.  In all other respects it is identical to
     the 'discard-matched' expression in the matcher language.

   Next there are several combinator expressions.  Parameters named PEXP
are arbitrary expressions in the parser language.  The first few
combinators are direct equivalents of those in the matcher language.

 -- parser expression: seq pexp ...
     The 'seq' expression parses each of the PEXP operands in order.  If
     all of the PEXP operands successfully match, the result is the
     concatenation of their values (by 'vector-append').

 -- parser expression: alt pexp ...
     The 'alt' expression attempts to parse each PEXP operand in order
     from left to right.  The first one that successfully parses
     produces the result for the entire 'alt' expression.

     Like the 'alt' expression in the matcher language, this expression
     participates in backtracking.

 -- parser expression: * pexp
     The '*' expression parses zero or more occurrences of PEXP.  The
     results of the parsed occurrences are concatenated together (by
     'vector-append') to produce the expression's result.

     Like the '*' expression in the matcher language, this expression
     participates in backtracking.

 -- parser expression: + pexp
     The '*' expression parses one or more occurrences of PEXP.  It is
     equivalent to

          (seq PEXP (* PEXP))

 -- parser expression: ? pexp
     The '*' expression parses zero or one occurrences of PEXP.  It is
     equivalent to

          (alt PEXP (seq))

   The next three expressions do not have equivalents in the matcher
language.  Each accepts a single PEXP argument, which is parsed in the
usual way.  These expressions perform transformations on the returned
values of a successful match.

 -- parser expression: transform expression pexp
     The 'transform' expression performs an arbitrary transformation of
     the values returned by parsing PEXP.  EXPRESSION is a Scheme
     expression that must evaluate to a procedure at run time.  If PEXP
     is successfully parsed, the procedure is called with the vector of
     values as its argument, and must return a vector or '#f'.  If it
     returns a vector, the parse is successful, and those are the
     resulting values.  If it returns '#f', the parse fails and the
     internal pointer of the parser buffer is returned to what it was
     before PEXP was parsed.

     For example:

          (transform (lambda (v) (if (= 0 (vector-length v)) #f v)) ...)

 -- parser expression: encapsulate expression pexp
     The 'encapsulate' expression transforms the values returned by
     parsing PEXP into a single value.  EXPRESSION is a Scheme
     expression that must evaluate to a procedure at run time.  If PEXP
     is successfully parsed, the procedure is called with the vector of
     values as its argument, and may return any Scheme object.  The
     result of the 'encapsulate' expression is a vector of length one
     containing that object.  (And consequently 'encapsulate' doesn't
     change the success or failure of PEXP, only its value.)

     For example:

          (encapsulate vector->list ...)

 -- parser expression: map expression pexp
     The 'map' expression performs a per-element transform on the values
     returned by parsing PEXP.  EXPRESSION is a Scheme expression that
     must evaluate to a procedure at run time.  If PEXP is successfully
     parsed, the procedure is mapped (by 'vector-map') over the values
     returned from the parse.  The mapped values are returned as the
     result of the 'map' expression.  (And consequently 'map' doesn't
     change the success or failure of PEXP, nor the number of values
     returned.)

     For example:

          (map string->symbol ...)

   Finally, as in the matcher language, we have 'sexp' and
'with-pointer' to support embedding Scheme code in the parser.

 -- parser expression: sexp expression
     The 'sexp' expression allows arbitrary Scheme code to be embedded
     inside a parser.  The EXPRESSION operand must evaluate to a parser
     procedure at run time; the procedure is called to parse the parser
     buffer.  This is the parser-language equivalent of the 'sexp'
     expression in the matcher language.

     The case in which EXPRESSION is a symbol is so common that it has
     an abbreviation: '(sexp SYMBOL)' may be abbreviated as just SYMBOL.

 -- parser expression: with-pointer identifier pexp
     The 'with-pointer' expression fetches the parser buffer's internal
     pointer (using 'get-parser-buffer-pointer'), binds it to
     IDENTIFIER, and then parses the pattern specified by PEXP.
     IDENTIFIER must be a symbol.  This is the parser-language
     equivalent of the 'with-pointer' expression in the matcher
     language.

