This is mit-scheme-ref.info, produced by texi2any version 6.7 from
scheme.texinfo.

This manual documents MIT/GNU Scheme 11.0.90.

   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, 2020 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: Searching and Matching Strings,  Next: Regular Expressions,  Prev: Strings,  Up: Strings

6.1 Searching and Matching Strings
==================================

This section describes procedures for searching a string, either for a
character or a substring, and matching two strings to one another.

 -- procedure: string-search-forward pattern string [start [end]]
     The arguments PATTERN and STRING must satisfy 'string-in-nfc?'.

     Searches STRING for the leftmost occurrence of the substring
     PATTERN.  If successful, the index of the first character of the
     matched substring is returned; otherwise, '#f' is returned.

          (string-search-forward "rat" "pirate")
              => 2
          (string-search-forward "rat" "pirate rating")
              => 2
          (string-search-forward "rat" "pirate rating" 4 13)
              => 7
          (string-search-forward "rat" "pirate rating" 9 13)
              => #f

 -- procedure: string-search-backward pattern string [start [end]]
     The arguments PATTERN and STRING must satisfy 'string-in-nfc?'.

     Searches STRING for the rightmost occurrence of the substring
     PATTERN.  If successful, the index to the right of the last
     character of the matched substring is returned; otherwise, '#f' is
     returned.

          (string-search-backward "rat" "pirate")
              => 5
          (string-search-backward "rat" "pirate rating")
              => 10
          (string-search-backward "rat" "pirate rating" 1 8)
              => 5
          (string-search-backward "rat" "pirate rating" 9 13)
              => #f

 -- procedure: string-search-all pattern string [start [end]]
     The arguments PATTERN and STRING must satisfy 'string-in-nfc?'.

     Searches STRING to find all occurrences of the substring PATTERN.
     Returns a list of the occurrences; each element of the list is an
     index pointing to the first character of an occurrence.

          (string-search-all "rat" "pirate")
              => (2)
          (string-search-all "rat" "pirate rating")
              => (2 7)
          (string-search-all "rat" "pirate rating" 4 13)
              => (7)
          (string-search-all "rat" "pirate rating" 9 13)
              => ()

 -- procedure: substring? pattern string
     Searches STRING to see if it contains the substring PATTERN.
     Returns '#t' if PATTERN is a substring of STRING, otherwise returns
     '#f'.

          (substring? "rat" "pirate")             =>  #t
          (substring? "rat" "outrage")            =>  #f
          (substring? "" any-string)              =>  #t
          (if (substring? "moon" text)
              (process-lunar text)
              'no-moon)

 -- procedure: string-find-first-index proc string string ...
 -- procedure: string-find-last-index proc string string ...
     Each STRING must satisfy 'string-in-nfc?', and PROC must accept as
     many arguments as there are STRINGs.

     These procedures apply PROC element-wise to the elements of the
     STRINGs and return the first or last index for which PROC returns a
     true value.  If there is no such index, then '#f' is returned.

     If more than one STRING is given and not all strings have the same
     length, then only the indexes of the shortest string are tested.

 -- procedure: string-find-next-char string char [start [end]]
 -- procedure: string-find-next-char-ci string char [start [end]]
 -- procedure: string-find-next-char-in-set string char-set [start
          [end]]
     The argument STRING must satisfy 'string-in-nfc?'.

     These procedures search STRING for a matching character, starting
     from START and moving forwards to END.  If there is a matching
     character, the procedures stop the search and return the index of
     that character.  If there is no matching character, the procedures
     return '#f'.

     The procedures differ only in how they match characters:
     'string-find-next-char' matches a character that is 'char=?' to
     CHAR; 'string-find-next-char-ci' matches a character that is
     'char-ci=?' to CHAR; and 'string-find-next-char-in-set' matches a
     character that's a member of CHAR-SET.

          (string-find-next-char "Adam" #\A)           =>  0
          (string-find-next-char "Adam" #\A 1 4)       =>  #f
          (string-find-next-char-ci "Adam" #\A 1 4)    =>  2
          (string-find-next-char-in-set my-string char-set:alphabetic)
              =>  start position of the first word in my-string
          ; Can be used as a predicate:
          (if (string-find-next-char-in-set my-string
                                            (char-set #\( #\) ))
              'contains-parentheses
              'no-parentheses)

 -- procedure: string-find-previous-char string char [start [end]]
 -- procedure: string-find-previous-char-ci string char [start [end]]
 -- procedure: string-find-previous-char-in-set string char-set [start
          [end]]
     The argument STRING must satisfy 'string-in-nfc?'.

     These procedures search STRING for a matching character, starting
     from END and moving backwards to START.  If there is a matching
     character, the procedures stop the search and return the index of
     that character.  If there is no matching character, the procedures
     return '#f'.

     The procedures differ only in how they match characters:
     'string-find-previous-char' matches a character that is 'char=?' to
     CHAR; 'string-find-previous-char-ci' matches a character that is
     'char-ci=?' to CHAR; and 'string-find-previous-char-in-set' matches
     a character that's a member of CHAR-SET.

 -- procedure: string-match-forward string1 string2
     The arguments STRING1 and STRING2 must satisfy 'string-in-nfc?'.

     Compares the two strings, starting from the beginning, and returns
     the number of characters that are the same.  If the two strings
     start differently, returns 0.

          (string-match-forward "mirror" "micro") =>  2  ; matches "mi"
          (string-match-forward "a" "b")          =>  0  ; no match

 -- procedure: string-match-backward string1 string2
     The arguments STRING1 and STRING2 must satisfy 'string-in-nfc?'.

     Compares the two strings, starting from the end and matching toward
     the front, returning the number of characters that are the same.
     If the two strings end differently, returns 0.

          (string-match-backward "bulbous" "fractious")
                                                  =>  3  ; matches "ous"

 -- procedure: string-prefix? string1 string2
 -- procedure: string-prefix-ci? string1 string2
     These procedures return '#t' if the first string forms the prefix
     of the second; otherwise returns '#f'.  The '-ci' procedures don't
     distinguish uppercase and lowercase letters.

          (string-prefix? "abc" "abcdef")         =>  #t
          (string-prefix? "" any-string)          =>  #t

 -- procedure: string-suffix? string1 string2
 -- procedure: string-suffix-ci? string1 string2
     These procedures return '#t' if the first string forms the suffix
     of the second; otherwise returns '#f'.  The '-ci' procedures don't
     distinguish uppercase and lowercase letters.

          (string-suffix? "ous" "bulbous")        =>  #t
          (string-suffix? "" any-string)          =>  #t


File: mit-scheme-ref.info,  Node: Regular Expressions,  Prev: Searching and Matching Strings,  Up: Strings

6.2 Regular Expressions
=======================

MIT/GNU Scheme provides support for matching and searching strings
against regular expressions.  This is considerably more flexible than
ordinary string matching and searching, but potentially much slower.  On
the other hand it is less powerful than the mechanism described in *note
Parser Language::.

   Traditional regular expressions are defined with string patterns in
which characters like '[' and '*' have special meanings.  Unfortunately,
the syntax of these patterns is not only baroque but also comes in many
different and mutually-incompatible varieties.  As a consequence we have
chosen to specify regular expressions using an s-expression syntax,
which we call a "regular s-expression", abbreviated as "regsexp".

   Previous releases of MIT/GNU Scheme provided a regular-expression
implementation nearly identical to that of GNU Emacs version 18.  This
implementation supported only 8-bit strings, which made it unsuitable
for use with Unicode strings.  This implementation still exists but is
deprecated and will be removed in a future release.

* Menu:

* Regular S-Expressions::
* Regsexp Procedures::


File: mit-scheme-ref.info,  Node: Regular S-Expressions,  Next: Regsexp Procedures,  Prev: Regular Expressions,  Up: Regular Expressions

6.2.1 Regular S-Expressions
---------------------------

A regular s-expression is either a character or a string, which matches
itself, or one of the following forms.

   Examples in this section use the following definitions for brevity:

     (define (try-match pattern string)
       (regsexp-match-string (compile-regsexp pattern) string))

     (define (try-search pattern string)
       (regsexp-search-string-forward (compile-regsexp pattern) string))

   These forms match one or more characters literally:

 -- regsexp: char-ci char
     Matches CHAR without considering case.

 -- regsexp: string-ci string
     Matches STRING without considering case.

 -- regsexp: any-char
     Matches one character other than '#\newline'.

          (try-match '(any-char) "") => #f
          (try-match '(any-char) "a") => (0 1)
          (try-match '(any-char) "\n") => #f
          (try-search '(any-char) "") => #f
          (try-search '(any-char) "ab") => (0 1)
          (try-search '(any-char) "\na") => (1 2)

 -- regsexp: char-in datum ...
 -- regsexp: char-not-in datum ...
     Matches one character in (not in) the character set specified by
     '(char-set DATUM ...)'.

          (try-match '(seq "a" (char-in "ab") "c") "abc") => (0 3)
          (try-match '(seq "a" (char-not-in "ab") "c") "abc") => #f
          (try-match '(seq "a" (char-not-in "ab") "c") "adc") => (0 3)
          (try-match '(seq "a" (+ (char-in numeric)) "c") "a019c") => (0 5)

   These forms match no characters, but only at specific locations in
the input string:

 -- regsexp: line-start
 -- regsexp: line-end
     Matches no characters at the start (end) of a line.

          (try-match '(seq (line-start)
                           (* (any-char))
                           (line-end))
                     "abc") => (0 3)
          (try-match '(seq (line-start)
                           (* (any-char))
                           (line-end))
                     "ab\nc") => (0 2)
          (try-search '(seq (line-start)
                            (* (char-in alphabetic))
                            (line-end))
                      "1abc") => #f
          (try-search '(seq (line-start)
                            (* (char-in alphabetic))
                            (line-end))
                      "1\nabc") => (2 5)

 -- regsexp: string-start
 -- regsexp: string-end
     Matches no characters at the start (end) of the string.

          (try-match '(seq (string-start)
                           (* (any-char))
                           (string-end))
                     "abc") => (0 3)
          (try-match '(seq (string-start)
                           (* (any-char))
                           (string-end))
                     "ab\nc") => #f
          (try-search '(seq (string-start)
                            (* (char-in alphabetic))
                            (string-end))
                      "1abc") => #f
          (try-search '(seq (string-start)
                            (* (char-in alphabetic))
                            (string-end))
                      "1\nabc") => #f

   These forms match repetitions of a given regsexp.  Most of them come
in two forms, one of which is "greedy" and the other "shy".  The greedy
form matches as many repetitions as it can, then uses failure
backtracking to reduce the number of repetitions one at a time.  The shy
form matches the minimum number of repetitions, then uses failure
backtracking to increase the number of repetitions one at a time.  The
shy form is similar to the greedy form except that a '?' is added at the
end of the form's keyword.

 -- regsexp: ? regsexp
 -- regsexp: ?? regsexp
     Matches REGSEXP zero or one time.

          (try-search '(seq (char-in alphabetic)
                            (? (char-in numeric)))
                      "a") => (0 1)
          (try-search '(seq (char-in alphabetic)
                            (?? (char-in numeric)))
                      "a") => (0 1)
          (try-search '(seq (char-in alphabetic)
                            (? (char-in numeric)))
                      "a1") => (0 2)
          (try-search '(seq (char-in alphabetic)
                            (?? (char-in numeric)))
                      "a1") => (0 1)
          (try-search '(seq (char-in alphabetic)
                            (? (char-in numeric)))
                      "1a2") => (1 3)
          (try-search '(seq (char-in alphabetic)
                            (?? (char-in numeric)))
                      "1a2") => (1 2)

 -- regsexp: * regsexp
 -- regsexp: *? regsexp
     Matches REGSEXP zero or more times.

          (try-match '(seq (char-in alphabetic)
                           (* (char-in numeric))
                           (any-char))
                     "aa") => (0 2)
          (try-match '(seq (char-in alphabetic)
                           (*? (char-in numeric))
                           (any-char))
                     "aa") => (0 2)
          (try-match '(seq (char-in alphabetic)
                           (* (char-in numeric))
                           (any-char))
                     "a123a") => (0 5)
          (try-match '(seq (char-in alphabetic)
                           (*? (char-in numeric))
                           (any-char))
                     "a123a") => (0 2)

 -- regsexp: + regsexp
 -- regsexp: +? regsexp
     Matches REGSEXP one or more times.

          (try-match '(seq (char-in alphabetic)
                           (+ (char-in numeric))
                           (any-char))
                     "aa") => #f
          (try-match '(seq (char-in alphabetic)
                           (+? (char-in numeric))
                           (any-char))
                     "aa") => #f
          (try-match '(seq (char-in alphabetic)
                           (+ (char-in numeric))
                           (any-char))
                     "a123a") => (0 5)
          (try-match '(seq (char-in alphabetic)
                           (+? (char-in numeric))
                           (any-char))
                     "a123a") => (0 3)

 -- regsexp: ** n m regsexp
 -- regsexp: **? n m regsexp
     The N argument must be an exact nonnegative integer.  The M
     argument must be either an exact integer greater than or equal to
     N, or else '#f'.

     Matches REGSEXP at least N times and at most M times; if M is '#f'
     then there is no upper limit.

          (try-match '(seq (char-in alphabetic)
                           (** 0 2 (char-in numeric))
                           (any-char))
                     "aa") => (0 2)
          (try-match '(seq (char-in alphabetic)
                           (**? 0 2 (char-in numeric))
                           (any-char))
                     "aa") => (0 2)
          (try-match '(seq (char-in alphabetic)
                           (** 0 2 (char-in numeric))
                           (any-char))
                     "a123a") => (0 4)
          (try-match '(seq (char-in alphabetic)
                           (**? 0 2 (char-in numeric))
                           (any-char))
                     "a123a") => (0 2)

 -- regsexp: ** n regsexp
     This is an abbreviation for '(** N N REGSEXP)'.  This matcher is
     neither greedy nor shy since it matches a fixed number of
     repetitions.

   These forms implement alternatives and sequencing:

 -- regsexp: alt regsexp ...
     Matches one of the REGSEXP arguments, trying each in order from
     left to right.

          (try-match '(alt #\a (char-in numeric)) "a") => (0 1)
          (try-match '(alt #\a (char-in numeric)) "b") => #f
          (try-match '(alt #\a (char-in numeric)) "1") => (0 1)

 -- regsexp: seq regsexp ...
     Matches the first REGSEXP, then continues the match with the next
     REGSEXP, and so on until all of the arguments are matched.

          (try-match '(seq #\a #\b) "a") => #f
          (try-match '(seq #\a #\b) "aa") => #f
          (try-match '(seq #\a #\b) "ab") => (0 2)

   These forms implement named "registers", which store matched segments
of the input string:

 -- regsexp: group key regsexp
     The KEY argument must be a fixnum, a character, or a symbol.

     Matches REGSEXP.  If the match succeeds, the matched segment is
     stored in the register named KEY.

          (try-match '(seq (group a (any-char))
                           (group b (any-char))
                           (any-char))
                     "radar") => (0 3 (a . "r") (b . "a"))

 -- regsexp: group-ref key
     The KEY argument must be a fixnum, a character, or a symbol.

     Matches the characters stored in the register named KEY.  It is an
     error if that register has not been initialized with a
     corresponding 'group' expression.

          (try-match '(seq (group a (any-char))
                           (group b (any-char))
                           (any-char)
                           (group-ref b)
                           (group-ref a))
                     "radar") => (0 5 (a . "r") (b . "a"))


File: mit-scheme-ref.info,  Node: Regsexp Procedures,  Prev: Regular S-Expressions,  Up: Regular Expressions

6.2.2 Regsexp Procedures
------------------------

The regular s-expression implementation has two parts, like many other
regular-expression implementations: a compiler that translates the
pattern into an efficient form, and one or more procedures that use that
pattern to match or search inputs.

 -- procedure: compile-regsexp regsexp
     Compiles REGSEXP by translating it into a procedure that implements
     the specified matcher.

   The match and search procedures each return a list when they are
successful, and '#f' when they fail.  The returned list is of the form
'(S E REGISTER ...)', where S is the index at which the match starts, E
is the index at which the match ends, and each REGISTER is a pair '(KEY
. CONTENTS)' where KEY is the register's name and CONTENTS is the
contents of that register as a string.

   In order to get reliable results, the string arguments to these
procedures must be in Unicode Normalization Form C. The string
implementation keeps most strings in this form by default; in other
cases the caller must convert the string using 'string->nfc'.

 -- procedure: regsexp-match-string crse string [start [end]]
     The CRSE argument must be a value returned by 'compile-regsexp'.
     The STRING argument must satisfy 'string-in-nfc?'.

     Matches STRING against CRSE and returns the result.

 -- procedure: regsexp-search-string-forward crse string [start [end]]
     The CRSE argument must be a value returned by 'compile-regsexp'.
     The STRING argument must satisfy 'string-in-nfc?'.

     Searches STRING from left to right for a match against CRSE and
     returns the result.


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

7 Lists
*******

A "pair" (sometimes called a "dotted pair") is a data structure with two
fields called the "car" and "cdr" fields (for historical reasons).
Pairs are created by the procedure 'cons'.  The car and cdr fields are
accessed by the procedures 'car' and 'cdr'.  The car and cdr fields are
assigned by the procedures 'set-car!' and 'set-cdr!'.

   Pairs are used primarily to represent "lists".  A list can be defined
recursively as either the empty list or a pair whose cdr is a list.
More precisely, the set of lists is defined as the smallest set X such
that

   * The empty list is in X.

   * If LIST is in X, then any pair whose cdr field contains LIST is
     also in X.

   The objects in the car fields of successive pairs of a list are the
"elements" of the list.  For example, a two-element list is a pair whose
car is the first element and whose cdr is a pair whose car is the second
element and whose cdr is the empty list.  The "length" of a list is the
number of elements, which is the same as the number of pairs.  The
"empty list" is a special object of its own type (it is not a pair); it
has no elements and its length is zero.(1)

   The most general notation (external representation) for Scheme pairs
is the "dotted" notation '(C1 . C2)' where C1 is the value of the car
field and C2 is the value of the cdr field.  For example, '(4 . 5)' is a
pair whose car is '4' and whose cdr is '5'.  Note that '(4 . 5)' is the
external representation of a pair, not an expression that evaluates to a
pair.

   A more streamlined notation can be used for lists: the elements of
the list are simply enclosed in parentheses and separated by spaces.
The empty list is written '()'.  For example, the following are
equivalent notations for a list of symbols:

     (a b c d e)
     (a . (b . (c . (d . (e . ())))))

   Whether a given pair is a list depends upon what is stored in the cdr
field.  When the 'set-cdr!' procedure is used, an object can be a list
one moment and not the next:

     (define x (list 'a 'b 'c))
     (define y x)
     y                                       => (a b c)
     (list? y)                               => #t
     (set-cdr! x 4)                          => unspecified
     x                                       => (a . 4)
     (eqv? x y)                              => #t
     y                                       => (a . 4)
     (list? y)                               => #f
     (set-cdr! x x)                          => unspecified
     (list? y)                               => #f

   A chain of pairs that doesn't end in the empty list is called an
"improper list".  Note that an improper list is not a list.  The list
and dotted notations can be combined to represent improper lists, as the
following equivalent notations show:

     (a b c . d)
     (a . (b . (c . d)))

   Within literal expressions and representations of objects read by the
'read' procedure, the forms ''DATUM', '`DATUM', ',DATUM', and ',@DATUM'
denote two-element lists whose first elements are the symbols 'quote',
'quasiquote', 'unquote', and 'unquote-splicing', respectively.  The
second element in each case is DATUM.  This convention is supported so
that arbitrary Scheme programs may be represented as lists.  Among other
things, this permits the use of the 'read' procedure to parse Scheme
programs.

* Menu:

* Pairs::
* Construction of Lists::
* Selecting List Components::
* Cutting and Pasting Lists::
* Filtering Lists::
* Searching Lists::
* Mapping of Lists::
* Folding of Lists::
* Miscellaneous List Operations::

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

   (1) The above definitions imply that all lists have finite length and
are terminated by the empty list.


File: mit-scheme-ref.info,  Node: Pairs,  Next: Construction of Lists,  Prev: Lists,  Up: Lists

7.1 Pairs
=========

This section describes the simple operations that are available for
constructing and manipulating arbitrary graphs constructed from pairs.

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

          (pair? '(a . b))                        => #t
          (pair? '(a b c))                        => #t
          (pair? '())                             => #f
          (pair? '#(a b))                         => #f

 -- standard procedure: cons obj1 obj2
     Returns a newly allocated pair whose car is OBJ1 and whose cdr is
     OBJ2.  The pair is guaranteed to be different (in the sense of
     'eqv?') from every previously existing object.

          (cons 'a '())                           => (a)
          (cons '(a) '(b c d))                    => ((a) b c d)
          (cons "a" '(b c))                       => ("a" b c)
          (cons 'a 3)                             => (a . 3)
          (cons '(a b) 'c)                        => ((a b) . c)

 -- SRFI 1 procedure: xcons obj1 obj2
     Returns a newly allocated pair whose car is OBJ2 and whose cdr is
     OBJ1.

          (xcons '(b c) 'a)                       => (a b c)

 -- standard procedure: car pair
     Returns the contents of the car field of PAIR.  Note that it is an
     error to take the 'car' of the empty list.

          (car '(a b c))                          => a
          (car '((a) b c d))                      => (a)
          (car '(1 . 2))                          => 1
          (car '())                               error-> Illegal datum

 -- standard procedure: cdr pair
     Returns the contents of the cdr field of PAIR.  Note that it is an
     error to take the 'cdr' of the empty list.

          (cdr '((a) b c d))                      => (b c d)
          (cdr '(1 . 2))                          => 2
          (cdr '())                               error-> Illegal datum

 -- SRFI 1 procedure: car+cdr pair
     The fundamental pair deconstructor:

          (lambda (p) (values (car p) (cdr p)))

          (receive (a b) (car+cdr (cons 1 2))
            (write-line a)
            (write-line b))
          -| 1
          -| 2

 -- standard procedure: set-car! pair object
     Stores OBJECT in the car field of PAIR.  The value returned by
     'set-car!' is unspecified.

          (define (f) (list 'not-a-constant-list))
          (define (g) '(constant-list))
          (set-car! (f) 3)                        => unspecified
          (set-car! (g) 3)                        error-> Illegal datum

 -- standard procedure: set-cdr! pair object
     Stores OBJECT in the cdr field of PAIR.  The value returned by
     'set-cdr!' is unspecified.

 -- standard procedure: caar pair
 -- standard procedure: cadr pair
 -- standard procedure: cdar pair
 -- standard procedure: cddr pair
 -- standard procedure: caaar pair
 -- standard procedure: caadr pair
 -- standard procedure: cadar pair
 -- standard procedure: caddr pair
 -- standard procedure: cdaar pair
 -- standard procedure: cdadr pair
 -- standard procedure: cddar pair
 -- standard procedure: cdddr pair
 -- standard procedure: caaaar pair
 -- standard procedure: caaadr pair
 -- standard procedure: caadar pair
 -- standard procedure: caaddr pair
 -- standard procedure: cadaar pair
 -- standard procedure: cadadr pair
 -- standard procedure: caddar pair
 -- standard procedure: cadddr pair
 -- standard procedure: cdaaar pair
 -- standard procedure: cdaadr pair
 -- standard procedure: cdadar pair
 -- standard procedure: cdaddr pair
 -- standard procedure: cddaar pair
 -- standard procedure: cddadr pair
 -- standard procedure: cdddar pair
 -- standard procedure: cddddr pair
     These procedures are compositions of 'car' and 'cdr'; for example,
     'caddr' could be defined by

          (define caddr (lambda (x) (car (cdr (cdr x)))))

 -- procedure: general-car-cdr object path
     This procedure is a generalization of 'car' and 'cdr'.  PATH
     encodes a particular sequence of 'car' and 'cdr' operations, which
     'general-car-cdr' executes on OBJECT.  PATH is an exact
     non-negative integer that encodes the operations in a bitwise
     fashion: a zero bit represents a 'cdr' operation, and a one bit
     represents a 'car'.  The bits are executed LSB to MSB, and the most
     significant one bit, rather than being interpreted as an operation,
     signals the end of the sequence.(1)

     For example, the following are equivalent:
          (general-car-cdr OBJECT #b1011)
          (cdr (car (car OBJECT)))

     Here is a partial table of path/operation equivalents:

          #b10    cdr
          #b11    car
          #b100   cddr
          #b101   cdar
          #b110   cadr
          #b111   caar
          #b1000  cdddr

 -- SRFI 1 procedure: tree-copy tree
     This copies an arbitrary TREE constructed from pairs, copying both
     the car and cdr elements of every pair.  This could have been
     defined by

          (define (tree-copy tree)
            (let loop ((tree tree))
              (if (pair? tree)
                  (cons (loop (car tree)) (loop (cdr tree)))
                  tree)))

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

   (1) Note that PATH is restricted to a machine-dependent range,
usually the size of a machine word.  On many machines, this means that
the maximum length of PATH will be 30 operations (32 bits, less the sign
bit and the "end-of-sequence" bit).


File: mit-scheme-ref.info,  Node: Construction of Lists,  Next: Selecting List Components,  Prev: Pairs,  Up: Lists

7.2 Construction of Lists
=========================

 -- standard procedure: list object ...
     Returns a list of its arguments.

          (list 'a (+ 3 4) 'c)                    => (a 7 c)
          (list)                                  => ()

     These expressions are equivalent:

          (list OBJ1 OBJ2 ... OBJN)
          (cons OBJ1 (cons OBJ2 ... (cons OBJN '()) ...))

 -- SRFI 1 procedure: make-list n [fill]
     Returns an N-element list, whose elements are all the value FILL.
     If the FILL argument is not given, the elements of the list may be
     arbitrary values.

          (make-list 4 'c)                        => (c c c c)

 -- SRFI 1 procedure: cons* object object ...
     'cons*' is similar to 'list', except that 'cons*' conses together
     the last two arguments rather than consing the last argument with
     the empty list.  If the last argument is not a list the result is
     an improper list.  If the last argument is a list, the result is a
     list consisting of the initial arguments and all of the items in
     the final argument.  If there is only one argument, the result is
     the argument.

          (cons* 'a 'b 'c)                        => (a b . c)
          (cons* 'a 'b '(c d))                    => (a b c d)
          (cons* 'a)                              => a

     These expressions are equivalent:

          (cons* OBJ1 OBJ2 ... OBJN-1 OBJN)
          (cons OBJ1 (cons OBJ2 ... (cons OBJN-1 OBJN) ...))

 -- SRFI 1 procedure: list-tabulate k init-proc
 -- obsolete procedure: make-initialized-list k init-proc
     Returns a K-element list.  Element I of the list, where 0 <= I < K,
     is produced by (INIT-PROC I).  No guarantee is made about the
     dynamic order in which INIT-PROC is applied to these indices.

          (list-tabulate 4 values) => (0 1 2 3)

 -- SRFI 1 procedure: list-copy list
     Returns a newly allocated copy of LIST.  This copies each of the
     pairs comprising LIST.  This could have been defined by

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

 -- SRFI 1 procedure: iota count [start [step]]
     Returns a list containing the elements

          (START START+STEP ... START+(COUNT-1)*STEP)

     COUNT must be an exact non-negative integer, while START and STEP
     can be any numbers.  The START and STEP parameters default to 0 and
     1, respectively.

          (iota 5) => (0 1 2 3 4)
          (iota 5 0 -0.1) => (0 -0.1 -0.2 -0.3 -0.4)

 -- standard procedure: vector->list vector [start [end]]
 -- obsolete procedure: subvector->list vector start end
     Returns a newly allocated list of the elements of VECTOR between
     START inclusive and END exclusive.  The inverse of 'vector->list'
     is 'list->vector'.

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


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

7.3 Selecting List Components
=============================

 -- standard procedure: list? object
 -- SRFI 1 procedure: proper-list? object
     Returns '#t' if OBJECT is a proper list, otherwise returns '#f'.
     By definition, all proper lists have finite length and are
     terminated by the empty list.  If OBJECT is a circular list,
     returns '#f'.

     Any OBJECT satisfying this predicate will also satisfy exactly one
     of 'pair?' or 'null?'.

          (list? (list 'a 'b 'c))                 => #t
          (list? (cons* 'a 'b 'c))                error->
          (list? (circular-list 'a 'b 'c))        => #f

 -- SRFI 1 procedure: circular-list? object
     Returns '#t' if OBJECT is a circular list, otherwise returns '#f'.

          (circular-list? (list 'a 'b 'c))        => #f
          (circular-list? (cons* 'a 'b 'c))       => #f
          (circular-list? (circular-list 'a 'b 'c)) => #t

 -- SRFI 1 procedure: dotted-list? object
     Returns '#t' if OBJECT is an improper list, otherwise returns '#f'.

          (dotted-list? (list 'a 'b 'c))          => #f
          (dotted-list? (cons* 'a 'b 'c))         => #t
          (dotted-list? (circular-list 'a 'b 'c)) => #f

 -- standard procedure: length list
     Returns the length of LIST.  Signals an error if LIST isn't a
     proper list.

          (length (list 'a 'b 'c))                => 3
          (length (cons* 'a 'b 'c))               error->
          (length (circular-list 'a 'b 'c))       error->

 -- SRFI 1 procedure: length+ clist
     CLIST must be a proper, dotted, or circular list.  If CLIST is a
     circular list, returns '#f', otherwise returns the number of pairs
     comprising the list (which is the same as the length for a proper
     list).

          (length+ (list 'a 'b 'c))               => 3
          (length+ (cons* 'a 'b 'c))              => 2
          (length+ (circular-list 'a 'b 'c))      => #f

 -- standard procedure: null? object
     Returns '#t' if OBJECT is the empty list; otherwise returns '#f'.

          (null? '())                             => #t
          (null? (list 'a 'b 'c))                 => #f
          (null? (cons* 'a 'b 'c))                => #f
          (null? (circular-list 'a 'b 'c))        => #f

 -- SRFI 1 procedure: null-list? list
     LIST is a proper or circular list.  This procedure returns '#t' if
     the argument is the empty list '()', and '#f' if the argument is a
     pair.  It is an error to pass this procedure any other value.  This
     procedure is recommended as the termination condition for
     list-processing procedures that are not defined on dotted lists.

 -- standard procedure: list-ref list k
     Returns the Kth element of LIST, using zero-origin indexing.  The
     "valid indexes" of a list are the exact non-negative integers less
     than the length of the list.  The first element of a list has index
     '0', the second has index '1', and so on.

          (list-ref '(a b c d) 2)                 => c
          (list-ref '(a b c d)
                    (exact (round 1.8)))
               => c

     '(list-ref LIST K)' is equivalent to '(car (drop LIST K))'.

 -- SRFI 1 procedure: first list
 -- SRFI 1 procedure: second list
 -- SRFI 1 procedure: third list
 -- SRFI 1 procedure: fourth list
 -- SRFI 1 procedure: fifth list
 -- SRFI 1 procedure: sixth list
 -- SRFI 1 procedure: seventh list
 -- SRFI 1 procedure: eighth list
 -- SRFI 1 procedure: ninth list
 -- SRFI 1 procedure: tenth list
     Returns the specified element of LIST.  It is an error if LIST is
     not long enough to contain the specified element (for example, if
     the argument to 'seventh' is a list that contains only six
     elements).


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

7.4 Cutting and Pasting Lists
=============================

 -- SRFI 1 procedure: take x i
 -- SRFI 1 procedure: drop x i
     'take' returns the first I elements of list X.  'drop' returns all
     but the first I elements of list X.
          (take '(a b c d e)  2) => (a b)
          (drop '(a b c d e)  2) => (c d e)

     X may be any value--a proper, circular, or dotted list:
          (take '(1 2 3 . d) 2) => (1 2)
          (drop '(1 2 3 . d) 2) => (3 . d)
          (take '(1 2 3 . d) 3) => (1 2 3)
          (drop '(1 2 3 . d) 3) => d

     For a legal I, 'take' and 'drop' partition the list in a manner
     which can be inverted with 'append':
          (append (take X I) (drop X I)) = X

     'drop' is exactly equivalent to performing I 'cdr' operations on X;
     the returned value shares a common tail with X.  If the argument is
     a list of non-zero length, 'take' is guaranteed to return a
     freshly-allocated list, even in the case where the entire list is
     taken, e.g.  '(take lis (length lis))'.

 -- obsolete procedure: list-head x i
 -- standard procedure: list-tail x i
     Equivalent to 'take' and 'drop', respectively.  'list-head' is
     deprecated and should not be used.  'list-tail' is defined by R7RS.

 -- procedure: sublist list start end
     START and END must be exact integers satisfying

          0 <= START <= END <= (length LIST)

     'sublist' returns a newly allocated list formed from the elements
     of LIST beginning at index START (inclusive) and ending at END
     (exclusive).

 -- standard procedure: append list ...
     Returns a list consisting of the elements of the first LIST
     followed by the elements of the other LISTs.

          (append '(x) '(y))                      => (x y)
          (append '(a) '(b c d))                  => (a b c d)
          (append '(a (b)) '((c)))                => (a (b) (c))
          (append)                                => ()

     The resulting list is always newly allocated, except that it shares
     structure with the last LIST argument.  The last argument may
     actually be any object; an improper list results if the last
     argument is not a proper list.

          (append '(a b) '(c . d))                => (a b c . d)
          (append '() 'a)                         => a

 -- SRFI 1 procedure: append! list ...
     Returns a list that is the argument LISTs concatenated together.
     The arguments are changed rather than copied.  (Compare this with
     'append', which copies arguments rather than destroying them.)  For
     example:

          (define x (list 'a 'b 'c))
          (define y (list 'd 'e 'f))
          (define z (list 'g 'h))
          (append! x y z)                         => (a b c d e f g h)
          x                                       => (a b c d e f g h)
          y                                       => (d e f g h)
          z                                       => (g h)

 -- SRFI 1 procedure: last pair
 -- SRFI 1 procedure: last-pair pair
     'last' returns the last element of the non-empty, finite list PAIR.
     'last-pair' returns the last pair in the non-empty, finite list
     PAIR.

          (last '(a b c)) => c
          (last-pair '(a b c)) => (c)

 -- obsolete procedure: except-last-pair list
 -- obsolete procedure: except-last-pair! list
     These procedures are deprecated.  Instead use 'drop-right' or
     'drop-right!', respectively, with a second argument of '1'.


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

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

 -- SRFI 1 procedure: filter predicate list
     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)

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

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

 -- SRFI 1 procedure: partition predicate list
     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)

 -- SRFI 1 procedure: filter! predicate list
 -- SRFI 1 procedure: remove! predicate list
 -- SRFI 1 procedure: partition! predicate list
     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.

 -- SRFI 1 procedure: delete x list [compare]
 -- SRFI 1 procedure: delete! x list [compare]
     'delete' uses the comparison procedure COMPARE, which defaults to
     'equal?', to find all elements of LIST that are equal to X, and
     deletes them from LIST.  The dynamic order in which the various
     applications of COMPARE are made is not specified.

     The list is not disordered--elements that appear in the result list
     occur in the same order as they occur in the argument list.  The
     result may share a common tail with the argument list.

     Note that fully general element deletion can be performed with the
     'remove' and 'remove!' procedures, e.g.:
          ;; Delete all the even elements from LIS:
          (remove even? lis)

     The comparison procedure is used in this way: '(COMPARE X E_{I})'.
     That is, X is always the first argument, and a list element is
     always the second argument.  The comparison procedure will be used
     to compare each element of LIST exactly once; the order in which it
     is applied to the various E_{I} is not specified.  Thus, one can
     reliably remove all the numbers greater than five from a list with
     '(delete 5 list <)'.

     'delete!' is the linear-update variant of 'delete'.  It is allowed,
     but not required, to alter the cons cells in its argument list to
     construct the result.

 -- procedure: delq x list
 -- procedure: delq! x list
 -- procedure: delv x list
 -- procedure: delv! x list
     Equivalent to '(delete X LIST eq?)', '(delete! X LIST eq?)',
     '(delete X LIST eqv?)', and '(delete! X LIST eqv?)', respectively.

 -- 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
===================

 -- SRFI 1 procedure: find predicate list
     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.

 -- SRFI 1 procedure: find-tail predicate list
     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.

 -- standard procedure: memq object list
 -- standard procedure: memv object list
 -- standard procedure: member object list [compare]
     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 COMPARE, or
     'equal?' if COMPARE is not supplied.(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: Folding of Lists,  Prev: Searching Lists,  Up: Lists

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

 -- standard 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

 -- obsolete procedure: map* knil proc list_{1} list_{2} ...
     Deprecated, use 'fold-right' instead.  Equivalent to

          (fold-right (lambda (e_{1} e_{2} ... acc)
                        (cons* (PROC e_{1})
                               (PROC e_{2})
                               ...
                               acc))
                      KNIL
                      LIST_{1}
                      LIST_{2}
                      ...)

 -- SRFI 1 procedure: append-map procedure list list ...
     Similar to 'map' 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_{1} LIST_{2} ...)
          (apply append (map PROCEDURE LIST_{1} LIST_{2} ...))

 -- obsolete procedure: append-map* knil proc list_{1} list_{2} ...
     Deprecated, use 'fold-right' instead.  Equivalent to

          (fold-right (lambda (e_{1} e_{2} ... acc)
                        (append (PROC e_{1})
                                (PROC e_{2})
                                ...
                                acc))
                      KNIL
                      LIST_{1}
                      LIST_{2}
                      ...)

 -- SRFI 1 procedure: append-map! proc list list ...
     Similar to 'map' except that the results of applying PROC 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! PROC LIST LIST ...)
          (apply append! (map PROC LIST LIST ...))

 -- obsolete procedure: append-map*! knil proc list_{1} list_{2} ...
     Deprecated, use 'fold-right' instead.  Equivalent to

          (fold-right (lambda (e_{1} e_{2} ... acc)
                        (append! (PROC e_{1})
                                 (PROC e_{2})
                                 ...
                                 acc))
                      KNIL
                      LIST_{1}
                      LIST_{2}
                      ...)

 -- standard 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)

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

     If there are n list arguments LIST_{1} ... LIST_{N}, 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

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

     If there are n list arguments LIST_{1} ... LIST_{N}, 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.


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

7.8 Folding of Lists
====================

 -- SRFI 1 procedure: fold kons knil clist_{1} clist_{2} ...
     The fundamental list iterator.

     First, consider the single list-parameter case.  If CLIST_{1} =
     '(E_{1} E_{2} ... E_{N})', then this procedure returns
          (KONS E_{N} ... (KONS E_{2} (KONS E_{1} KNIL)) ...)

     That is, it obeys the (tail) recursion

          (fold KONS KNIL LIS) = (fold KONS (KONS (car LIS) KNIL) (cdr LIS))
          (fold KONS KNIL '()) = KNIL

     Examples:

          (fold + 0 lis)                  ; Add up the elements of LIS.

          (fold cons '() lis)             ; Reverse LIS.

          (fold cons tail rev-head)       ; See APPEND-REVERSE.

          ;; How many symbols in LIS?
          (fold (lambda (x count) (if (symbol? x) (+ count 1) count))
                0
                lis)

          ;; Length of the longest string in LIS:
          (fold (lambda (s max-len) (max max-len (string-length s)))
                0
                lis)

     If N list arguments are provided, then the KONS procedure must take
     N+1 parameters: one element from each list, and the "seed" or fold
     state, which is initially KNIL.  The fold operation terminates when
     the shortest list runs out of values:

          (fold cons* '() '(a b c) '(1 2 3 4 5)) => (c 3 b 2 a 1)

     At least one of the list arguments must be finite.

 -- SRFI 1 procedure: fold-right kons knil clist_{1} clist_{2} ...
     The fundamental list recursion operator.

     First, consider the single list-parameter case.  If CLIST_{1} =
     '(E_{1} E_{2} ... E_{N})', then this procedure returns

          (KONS E_{1} (KONS E_{2} ... (KONS E_{N} KNIL)))

     That is, it obeys the recursion

          (fold-right KONS KNIL LIS) = (KONS (car LIS) (fold-right KONS KNIL (cdr LIS)))
          (fold-right KONS KNIL '()) = KNIL

     Examples:

          (fold-right cons '() lis)               ; Copy LIS.

          ;; Filter the even numbers out of LIS.
          (fold-right (lambda (x l) (if (even? x) (cons x l) l)) '() lis))

     If N list arguments are provided, then the KONS function must take
     N+1 parameters: one element from each list, and the "seed" or fold
     state, which is initially KNIL.  The fold operation terminates when
     the shortest list runs out of values:
          (fold-right cons* '() '(a b c) '(1 2 3 4 5)) => (a 1 b 2 c 3)

     At least one of the list arguments must be finite.

 -- obsolete procedure: fold-left proc knil list
     Deprecated, use 'fold' instead.  Equivalent to

          (fold (lambda (acc elt) (PROC elt acc)) KNIL LIST)

 -- SRFI 1 procedure: reduce f ridentity list
     'reduce' is a variant of 'fold'.

     RIDENTITY should be a "right identity" of the procedure F--that is,
     for any value X acceptable to F,
          '(F X RIDENTITY)' = X

     'reduce' has the following definition:
          If LIST = '()', return RIDENTITY;
          Otherwise, return '(FOLD F (car LIST) (cdr LIST))'.
     ...in other words, we compute '(fold F RIDENTITY LIST)'.

     Note that RIDENTITY is used only in the empty-list case.  You
     typically use 'reduce' when applying F is expensive and you'd like
     to avoid the extra application incurred when 'fold' applies F to
     the head of list and the identity value, redundantly producing the
     same value passed in to F.  For example, if F involves searching a
     file directory or performing a database query, this can be
     significant.  In general, however, 'fold' is useful in many
     contexts where 'reduce' is not (consider the examples given in the
     'fold' definition--only one of the five 'fold's uses a function
     with a right identity.  The other four may not be performed with
     'reduce').

          ;; Take the max of a list of non-negative integers.
          (reduce max 0 nums) ; i.e., (apply max 0 nums)

 -- SRFI 1 procedure: reduce-right kons knil list
     'reduce-right' is the 'fold-right' variant of 'reduce'.  It obeys
     the following definition:
          '(reduce-right F RIDENTITY '())' = RIDENTITY
          '(reduce-right F RIDENTITY '(E_{1}))' = '(F E_{1} RIDENTITY)' = E_{1}
          '(reduce-right F RIDENTITY '(E_{1} E_{2} ...))' =
              '(F E_{1} (reduce F RIDENTITY '(E_{2} ...)))'
     ...in other words, we compute '(fold-right F RIDENTITY LIST)'.

          ;; Append a bunch of lists together.
          ;; I.e., (apply append list-of-lists)
          (reduce-right append '() list-of-lists)

 -- obsolete procedure: reduce-left f ridentity list
     Deprecated, use 'reduce' instead.  Equivalent to

          (reduce (lambda (acc elt) (F elt acc)) RIDENTITY LIST)


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

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

 -- SRFI 1 procedure: circular-list object ...
 -- procedure: make-circular-list k [element]
     'circular-list' returns a circular list containing the given
     OBJECTs.  'make-circular-list' returns a circular list of length K;
     if ELEMENT is given, the returned list is filled with it, otherwise
     the elements are unspecified.

     This procedure is like 'list' except that the returned list is
     circular.  'circular-list' could have been defined like this:

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

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

 -- standard 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)

 -- SRFI 1 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
     (https://srfi.schemers.org/srfi-39/srfi-39.html) and by R7RS
     (https://small.r7rs.org/attachment/r7rs.pdf), 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,
and the original value replaced with a unique "reclaimed object".

   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: gc-reclaimed-object? object
     Returns '#t' if OBJECT is the reclaimed object, and '#f' otherwise.

 -- procedure: gc-reclaimed-object
     Returns the reclaimed object.

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

     This is equivalent to
          (not (gc-reclaimed-object? (weak-car WEAK-PAIR)))

     This predicate has been deprecated; instead use
     'gc-reclaimed-object?'.  Please note that the previously
     recommended way to use 'weak-pair/car?' will no longer work, so any
     code using it should be rewritten.

 -- procedure: weak-car weak-pair
     Returns the car component of WEAK-PAIR.  If the car component has
     been garbage-collected, this operation returns the reclaimed
     object.

 -- 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::
* Associative Maps::


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
(https://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 comparator arg ...
 -- procedure: make-hash-table [key=? [hash-function arg ...]]
 -- procedure: alist->hash-table alist comparator arg ...
 -- procedure: alist->hash-table alist [key=? [hash-function arg ...]]
     These are the standard constructors for making hash tables.  The
     behavior of each differs depending on its arguments: if the first
     argument is a comparator, then it behaves like a SRFI 125
     procedure, otherwise it behaves like a SRFI 69 procedure.

     For SRFI 125 behavior the COMPARATOR must be a comparator that
     satisfies 'comparator-hashable?'.  The remaining ARGS are optional,
     and may include the following symbols:
     'weak-keys'
          Specifies that the table will have weak keys.

     'weak-values'
          Specifies that the table will have weak values.

     'ephemeral-keys'
          Specifies that the table will have ephemeral keys.

     'ephemeral-values'
          Specifies that the table will have ephemeral values.
     The symbols 'weak-keys' and 'weak-values' can be specified together
     or separately, likewise for 'ephemeral-keys' and
     'ephemeral-values'.  But weak and ephemeral symbols can't be mixed.
     If none of these symbols are present, then the keys and values are
     strongly held.

     Additionally ARGS may contain an exact non-negative integer, which
     specifies an initial size for the table; otherwise a default size
     is used.

     For SRFI 69 behavior 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.

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

 -- procedure: hash-table-constructor comparator arg ...
 -- obsolete procedure: hash-table-constructor type
     Returns a procedure that, when called, constructs a new hash table
     using the specified parameters.  The returned procedure accepts an
     optional INITIAL-SIZE.

     If its first argument is a comparator, it uses the COMPARATOR and
     ARGS as in 'make-hash-table', except that any initial size
     specified in ARGS can be overridden by the INITIAL-SIZE argument to
     the returned procedure.

     If its first argument is a type, returns a procedure that, when
     called, constructs a new hash table using the hashing parameters in
     TYPE.  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.

 -- obsolete 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:'.

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

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

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

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

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

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

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

 -- obsolete 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 eq? #t
           hash-table-entry-type:key-weak)))

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

     (define make-string-hash-table
       (hash-table-constructor
         (make-hash-table-type string-hash 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.

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

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

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

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

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

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

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

 -- 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,  Next: Associative Maps,  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?'.

* 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: Associative Maps,  Prev: Weight-Balanced Trees,  Up: Associations

11.8 Associative Maps
=====================

Starting with version 11.1, MIT/GNU Scheme provides an abstract
associative-map interface that can be backed by any kind of association
mechanism.  The interface is similar to that of SRFI 125.  Associative
maps can be mutable or immutable, depending on the backing
implementation.  As of this writing we support the following
implementations: alists, weak alists, red/black trees, hash tables, and
tries, all of which are mutable.

* Menu:

* Amap constructors::
* Amap predicates::
* Amap accessors::
* Amap mutators::
* Amap mapping and folding::
* Amap contents::
* Amap copying and conversion::
* Amaps as sets::


File: mit-scheme-ref.info,  Node: Amap constructors,  Next: Amap predicates,  Prev: Associative Maps,  Up: Associative Maps

11.8.1 Amap constructors
------------------------

All associative-map constructors take a comparator argument followed by
a list of additional specification arguments.  In all cases, the
comparator is used to compare keys in the map, while the additional
arguments specify the implementation and/or features of the map being
created.

 -- procedure: make-amap comparator arg ...
     Creates a new mutable associative map as specified by COMPARATOR
     and ARGs.

 -- procedure: alist->amap alist comparator arg ...
     Creates a new associative map as specified by COMPARATOR and ARGs,
     and which contains the associations in ALIST.

 -- procedure: amap-unfold stop? mapper successor seed comparator arg
          ...
     Creates a new associative map as specified by COMPARATOR and ARGs.
     The associations in the resulting map are generated using the
     additional arguments.

     The STOP? argument is a unary predicate that takes a state value
     and returns '#t' if generation is complete, otherwise '#f'.  The
     MAPPER argument is a unary procedure that takes a state value and
     returns two values: a key and a value.  The SUCCESSOR argument is a
     unary procedure that takes a state value and returns a new state
     value.  And SEED is the initial state value.

     The process by which the generator adds associations to the map is
     this:

          (let loop ((state SEED))
            (if (STOP? state)
                result
                (let-values (((key value) (MAPPER state)))
                  (amap-set! result key value)
                  (loop (SUCCESSOR state)))))

   The arguments passed to a constructor can be divided into categories:

   * Each backing implementation has an associated name, which can be
     passed as one of the arguments.  At present this includes 'alist',
     'hash-table', 'red/black-tree', etc.

     There must be at most one such name; it is an error to pass two or
     more implementation names.  If an implementation name is given,
     then the remaining arguments must be supported by that
     implementation.

   * The arguments 'weak-keys', 'weak-values', 'ephemeral-keys', and
     'ephemeral-values' specify how associations interact with garbage
     collection.  Not all implementations support these arguments, and
     those that do may support only some of them.  Some combinations are
     not allowed: for example, 'weak-keys' and 'ephemeral-keys' are
     mutually exclusive.

   * Additional arguments are used to guide the choice of implementation
     when it is not explicitly specified.  The desired time complexity
     can be specified: 'linear-time', 'log-time',
     'amortized-constant-time', and 'sublinear-time'.  The argument
     'ordered-by-key' specifies that the map keeps its associations
     ordered.

   * The argument 'thread-safe' specifies that the implementation is
     safe to use in a multi-threaded environment.  At present none of
     the implementations are thread-safe.

   * Finally, an exact non-negative integer argument specifies the
     initial size of the map.

   This is a complex set of possible arguments.  In order to help
explore what arguments can be used, and in what combinations, we provide
some utility procedures:

 -- procedure: amap-implementation-names
     Returns a list of the supported implementation names.

 -- procedure: amap-implementation-supported-args name
     Returns a list of the arguments supported by the implementation
     specified by NAME.  This list can include the procedure
     'exact-nonnegative-integer?' if the implementation supports an
     initial size.

 -- procedure: amap-implementation-supports-args? name args
     Returns '#t' if the implementation specified by NAME supports ARGS,
     otherwise returns '#f'.

   An implementation may support a limited set of comparators.  For
example, a hash table requires a comparator that satisfies
'comparator-hashable?', while a binary tree requires one satisfying
'comparator-ordered?'.

 -- procedure: amap-implementation-supports-comparator? name comparator
     Returns '#t' if the implementation specified by NAME supports
     COMPARATOR, otherwise returns '#f'.


File: mit-scheme-ref.info,  Node: Amap predicates,  Next: Amap accessors,  Prev: Amap constructors,  Up: Associative Maps

11.8.2 Amap predicates
----------------------

 -- procedure: amap? object
     True iff OBJECT is an associative map.

 -- procedure: amap-contains? amap key
     True iff AMAP contains an association for KEY.

 -- procedure: amap-empty? amap
     True iff AMAP has no associations.

 -- procedure: amap=? value-comparator amap1 amap2
     True iff the associations in AMAP1 are the same as the associations
     in AMAP2.  This means that AMAP1 and AMAP2 have the same keys (in
     the sense of their shared equality predicate), and that for each
     key they have the same value (in the sense of VALUE-COMPARATOR).

 -- procedure: amap-mutable? amap
     True iff AMAP is mutable.


File: mit-scheme-ref.info,  Node: Amap accessors,  Next: Amap mutators,  Prev: Amap predicates,  Up: Associative Maps

11.8.3 Amap accessors
---------------------

 -- procedure: amap-ref amap key [fail [succeed]]
     Looks up the value associated to KEY in AMAP, invokes the procedure
     SUCCEED on it, and returns its result; if SUCCEED is not provided,
     then the value itself is returned.  If KEY is not contained in AMAP
     and FAIL is supplied, then FAIL is invoked on no arguments and its
     result is returned.  Otherwise an error is signaled.

 -- procedure: amap-ref/default amap key default
     Semantically equivalent to, but may be more efficient than, the
     following code:

          (amap-ref AMAP KEY (lambda () DEFAULT))

 -- procedure: amap-comparator amap
     Returns the comparator that was used to create AMAP.

 -- procedure: amap-args amap
     Returns the extra arguments that were used to create AMAP.

 -- procedure: amap-implementation-name amap
     Returns the name of AMAP's backing implementation.


File: mit-scheme-ref.info,  Node: Amap mutators,  Next: Amap mapping and folding,  Prev: Amap accessors,  Up: Associative Maps

11.8.4 Amap mutators
--------------------

 -- procedure: amap-set! amap [key value] ...
     Repeatedly mutates AMAP, creating new associations in it by
     processing the arguments from left to right.  The args alternate
     between keys and values.  Whenever there is a previous association
     for a key, it is deleted.  It is an error if a key does not satisfy
     the type check procedure of the comparator of AMAP.  Likewise, it
     is an error if a key is not a valid argument to the equality
     predicate of AMAP.  Returns an unspecified value.

 -- procedure: amap-delete! amap key ...
     Deletes any association to each KEY in AMAP and returns the number
     of keys that had associations.

 -- procedure: amap-intern! amap key fail
     Effectively invokes 'amap-ref' with the given arguments and returns
     what it returns.  If KEY was not found in AMAP, its value is set to
     the result of calling FAIL.

 -- procedure: amap-update! amap key updater [fail [succeed]]
     Semantically equivalent to, but may be more efficient than, the
     following code:

          (amap-set! AMAP KEY (UPDATER (amap-ref AMAP KEY FAIL SUCCEED)))

 -- procedure: amap-update!/default amap key updater default
     Semantically equivalent to, but may be more efficient than, the
     following code:

          (amap-set! AMAP KEY (UPDATER (amap-ref/default AMAP KEY DEFAULT)))

 -- procedure: amap-pop! amap
     Chooses an arbitrary association from AMAP and removes it,
     returning the key and value as two values.  Signals an error if
     AMAP is empty.

 -- procedure: amap-clear! amap
     Delete all the associations from AMAP.

 -- procedure: amap-clean! amap
     If AMAP has weak or ephemeral associations, cleans up any storage
     for associations whose key and/or value has been reclaimed by the
     garbage collector.  Otherwise does nothing.

     This procedure does not have any visible effect, since the
     associations it cleans up are ignored by all other parts of the
     interface.  Additionally, most implementations clean up their
     storage incrementally as they are used.  But this procedure
     provides for edge cases where the reclaimed storage might matter.


File: mit-scheme-ref.info,  Node: Amap mapping and folding,  Next: Amap contents,  Prev: Amap mutators,  Up: Associative Maps

11.8.5 Amap mapping and folding
-------------------------------

 -- procedure: amap-map procedure amap [comparator arg ...]
     Returns a newly allocated associative map as if by '(make-amap
     COMPARATOR ARG ...)'.  Calls PROCEDURE for every association in
     AMAP with the value of the association.  The key of the association
     and the result of invoking PROCEDURE are entered into the new map.

     If COMPARATOR recognizes multiple keys in AMAP as equivalent, any
     one of such associations is taken.

 -- procedure: amap-for-each procedure amap
     Calls PROCEDURE for every association in AMAP with two arguments:
     the key of the association and the value of the association.  The
     value returned by PROCEDURE is discarded.  Returns an unspecified
     value.

 -- procedure: amap-map! procedure amap
     Calls PROCEDURE for every association in AMAP with two arguments:
     the key of the association and the value of the association.  The
     value returned by PROCEDURE is used to update the value of the
     association.  Returns an unspecified value.

 -- procedure: amap-map->list procedure amap
     Calls PROCEDURE for every association in AMAP with two arguments:
     the key of the association and the value of the association.  The
     values returned by the invocations of PROCEDURE are accumulated
     into a list, which is returned.

 -- procedure: amap-fold kons knil amap
     Calls KONS for every association in AMAP with three arguments: the
     key of the association, the value of the association, and an
     accumulated value VAL.  The argument KNIL is seed for the first
     invocation of KONS, and for subsequent invocations of KONS, the
     returned value of the previous invocation.  The value returned by
     'amap-fold' is the return value of the last invocation of KONS.

 -- procedure: amap-prune! predicate amap
     Calls PREDICATE for every association in AMAP with two arguments,
     the key and the value of the association, and removes all
     associations from AMAP for which PREDICATE returns true.  Returns
     an unspecified value.


File: mit-scheme-ref.info,  Node: Amap contents,  Next: Amap copying and conversion,  Prev: Amap mapping and folding,  Up: Associative Maps

11.8.6 Amap contents
--------------------

 -- procedure: amap-size amap
     Returns the number of associations in AMAP as an exact integer.

 -- procedure: amap-keys amap
     Returns a newly allocated list of all the keys in AMAP.

 -- procedure: amap-values amap
     Returns a newly allocated list of all the values in AMAP.

 -- procedure: amap-entries amap
     Returns two values, a newly allocated list of all the keys in AMAP
     and a newly allocated list of all the values in AMAP in the
     corresponding order.

 -- procedure: amap-find procedure amap fail
     For each association of AMAP, invoke PROCEDURE on its key and
     value.  If PROCEDURE returns true, then 'amap-find' returns what
     PROCEDURE returns.  If all the calls to PROCEDURE return '#f',
     returns the result of invoking the thunk FAIL.

 -- procedure: amap-count predicate amap
     For each association of AMAP, invoke PREDICATE on its key and
     value.  Returns the number of calls to PREDICATE that returned
     true.


File: mit-scheme-ref.info,  Node: Amap copying and conversion,  Next: Amaps as sets,  Prev: Amap contents,  Up: Associative Maps

11.8.7 Amap copying and conversion
----------------------------------

 -- procedure: amap-copy amap [mutable?]
     Returns a newly allocated associative map with the same properties
     and associations as AMAP.  If MUTABLE? is given and is true, the
     new associative map is mutable.  Otherwise it is immutable provided
     that the implementation supports immutable maps.

 -- procedure: amap-empty-copy amap
     Returns a newly allocated mutable associative map with the same
     properties as AMAP, but with no associations.

 -- procedure: amap->alist amap
     Returns an alist with the same associations as AMAP in an
     unspecified order.


File: mit-scheme-ref.info,  Node: Amaps as sets,  Prev: Amap copying and conversion,  Up: Associative Maps

11.8.8 Amaps as sets
--------------------

 -- procedure: amap-union! amap1 amap2
     Adds the associations of AMAP2 to AMAP1 and returns AMAP1.  If a
     key appears in both maps, its value is set to the value appearing
     in AMAP1.

 -- procedure: amap-intersection! amap1 amap2
     Deletes the associations from AMAP1 whose keys don't also appear in
     AMAP2 and returns AMAP1.

 -- procedure: amap-difference! amap1 amap2
     Deletes the associations of AMAP1 whose keys are also present in
     AMAP2 and returns AMAP1.

 -- procedure: amap-xor! amap1 amap2
     Deletes the associations of AMAP1 whose keys are also present in
     AMAP2, and then adds the associations of AMAP2 whose keys are not
     present in AMAP1 to AMAP1.  Returns AMAP1.


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))
            (write-to-string '(a b c d)))
                                          => "(a b c d)"
          (parameterize ((param:printer-list-breadth-limit 4))
            (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))
            (write-to-string '((((a))) b c d)))
                                          => "((((a))) b c d)"
          (parameterize ((param:printer-list-depth-limit 4))
            (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))
            (write-to-string "abcd"))
                                          => "\"abcd\""
          (parameterize ((param:printer-string-length-limit 4))
            (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.

