This manual documents Guile version 3.0.10.

   Copyright (C) 1996-1997, 2000-2005, 2009-2023 Free Software
Foundation, Inc.
Copyright (C) 2021 Maxime Devos
Copyright (C) 2024 Tomas Volf

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
copy of the license is included in the section entitled "GNU Free
Documentation License."

7.5.35 SRFI-61 - A more general ‘cond’ clause
---------------------------------------------

This SRFI extends RnRS ‘cond’ to support test expressions that return
multiple values, as well as arbitrary definitions of test success.  SRFI
61 is implemented in the Guile core; there's no module needed to get
SRFI-61 itself.  Extended ‘cond’ is documented in Simple Conditional Evaluation.

7.5.36 SRFI-62 - S-expression comments.
---------------------------------------

Starting from version 2.0, Guile's ‘read’ supports SRFI-62/R7RS
S-expression comments by default.

7.5.37 SRFI-64 - A Scheme API for test suites.
----------------------------------------------

See the specification of SRFI-64
(http://srfi.schemers.org/srfi-64/srfi-64.html).

7.5.38 SRFI-67 - Compare procedures
-----------------------------------

See the specification of SRFI-67
(http://srfi.schemers.org/srfi-67/srfi-67.html).

7.5.39 SRFI-69 - Basic hash tables
----------------------------------

This is a portable wrapper around Guile's built-in hash table and weak
table support.  See Hash Tables, for information on that built-in
support.  Above that, this hash-table interface provides association of
equality and hash functions with tables at creation time, so variants of
each function are not required, as well as a procedure that takes care
of most uses for Guile hash table handles, which this SRFI does not
provide as such.

   Access it with:

     (use-modules (srfi srfi-69))

7.5.39.1 Creating hash tables
.............................

 -- Scheme Procedure: make-hash-table [equal-proc hash-proc #:weak
          weakness start-size]
     Create and answer a new hash table with EQUAL-PROC as the equality
     function and HASH-PROC as the hashing function.

     By default, EQUAL-PROC is ‘equal?’.  It can be any two-argument
     procedure, and should answer whether two keys are the same for this
     table's purposes.

     By default HASH-PROC assumes that ‘equal-proc’ is no coarser than
     ‘equal?’ unless it is literally ‘string-ci=?’.  If provided,
     HASH-PROC should be a two-argument procedure that takes a key and
     the current table size, and answers a reasonably good hash integer
     between 0 (inclusive) and the size (exclusive).

     WEAKNESS should be ‘#f’ or a symbol indicating how "weak" the hash
     table is:

     ‘#f’
          An ordinary non-weak hash table.  This is the default.

     ‘key’
          When the key has no more non-weak references at GC, remove
          that entry.

     ‘value’
          When the value has no more non-weak references at GC, remove
          that entry.

     ‘key-or-value’
          When either has no more non-weak references at GC, remove the
          association.

     As a legacy of the time when Guile couldn't grow hash tables,
     START-SIZE is an optional integer argument that specifies the
     approximate starting size for the hash table, which will be rounded
     to an algorithmically-sounder number.

   By “coarser” than ‘equal?’, we mean that for all X and Y values where
‘(EQUAL-PROC X Y)’, ‘(equal? X Y)’ as well.  If that does not hold for
your EQUAL-PROC, you must provide a HASH-PROC.

   In the case of weak tables, remember that “references” above always
refers to ‘eq?’-wise references.  Just because you have a reference to
some string ‘"foo"’ doesn't mean that an association with key ‘"foo"’ in
a weak-key table _won't_ be collected; it only counts as a reference if
the two ‘"foo"’s are ‘eq?’, regardless of EQUAL-PROC.  As such, it is
usually only sensible to use ‘eq?’ and ‘hashq’ as the equivalence and
hash functions for a weak table.  See Weak References, for more
information on Guile's built-in weak table support.

 -- Scheme Procedure: alist->hash-table alist [equal-proc hash-proc
          #:weak weakness start-size]
     As with ‘make-hash-table’, but initialize it with the associations
     in ALIST.  Where keys are repeated in ALIST, the leftmost
     association takes precedence.

7.5.39.2 Accessing table items
..............................

 -- Scheme Procedure: hash-table-ref table key [default-thunk]
 -- Scheme Procedure: hash-table-ref/default table key default
     Answer the value associated with KEY in TABLE.  If KEY is not
     present, answer the result of invoking the thunk DEFAULT-THUNK,
     which signals an error instead by default.

     ‘hash-table-ref/default’ is a variant that requires a third
     argument, DEFAULT, and answers DEFAULT itself instead of invoking
     it.

 -- Scheme Procedure: hash-table-set! table key new-value
     Set KEY to NEW-VALUE in TABLE.

 -- Scheme Procedure: hash-table-delete! table key
     Remove the association of KEY in TABLE, if present.  If absent, do
     nothing.

 -- Scheme Procedure: hash-table-exists? table key
     Answer whether KEY has an association in TABLE.

 -- Scheme Procedure: hash-table-update! table key modifier
          [default-thunk]
 -- Scheme Procedure: hash-table-update!/default table key modifier
          default
     Replace KEY's associated value in TABLE by invoking MODIFIER with
     one argument, the old value.

     If KEY is not present, and DEFAULT-THUNK is provided, invoke it
     with no arguments to get the "old value" to be passed to MODIFIER
     as above.  If DEFAULT-THUNK is not provided in such a case, signal
     an error.

     ‘hash-table-update!/default’ is a variant that requires the fourth
     argument, which is used directly as the "old value" rather than as
     a thunk to be invoked to retrieve the "old value".

7.5.39.3 Table properties
.........................

 -- Scheme Procedure: hash-table-size table
     Answer the number of associations in TABLE.  This is guaranteed to
     run in constant time for non-weak tables.

 -- Scheme Procedure: hash-table-keys table
     Answer an unordered list of the keys in TABLE.

 -- Scheme Procedure: hash-table-values table
     Answer an unordered list of the values in TABLE.

 -- Scheme Procedure: hash-table-walk table proc
     Invoke PROC once for each association in TABLE, passing the key and
     value as arguments.

 -- Scheme Procedure: hash-table-fold table proc init
     Invoke ‘(PROC KEY VALUE PREVIOUS)’ for each KEY and VALUE in TABLE,
     where PREVIOUS is the result of the previous invocation, using INIT
     as the first PREVIOUS value.  Answer the final PROC result.

 -- Scheme Procedure: hash-table->alist table
     Answer an alist where each association in TABLE is an association
     in the result.

7.5.39.4 Hash table algorithms
..............................

Each hash table carries an “equivalence function” and a “hash function”,
used to implement key lookups.  Beginning users should follow the rules
for consistency of the default HASH-PROC specified above.  Advanced
users can use these to implement their own equivalence and hash
functions for specialized lookup semantics.

 -- Scheme Procedure: hash-table-equivalence-function hash-table
 -- Scheme Procedure: hash-table-hash-function hash-table
     Answer the equivalence and hash function of HASH-TABLE,
     respectively.

 -- Scheme Procedure: hash obj [size]
 -- Scheme Procedure: string-hash obj [size]
 -- Scheme Procedure: string-ci-hash obj [size]
 -- Scheme Procedure: hash-by-identity obj [size]
     Answer a hash value appropriate for equality predicate ‘equal?’,
     ‘string=?’, ‘string-ci=?’, and ‘eq?’, respectively.

   ‘hash’ is a backwards-compatible replacement for Guile's built-in
‘hash’.

7.5.40 SRFI-71 - Extended let-syntax for multiple values
--------------------------------------------------------

This SRFI shadows the forms for ‘let’, ‘let*’, and ‘letrec’ so that they
may accept multiple values.  For example:

     (use-modules (srfi srfi-71))

     (let* ((x y (values 1 2))
            (z (+ x y)))
       (* z 2))
     ⇒ 6

   See the specification of SRFI-71
(http://srfi.schemers.org/srfi-71/srfi-71.html).

7.5.41 SRFI-87 => in case clauses
---------------------------------

Starting from version 2.0.6, Guile's core ‘case’ syntax supports ‘=>’ in
clauses, as specified by SRFI-87/R7RS. See Conditionals.

7.5.42 SRFI-88 Keyword Objects
------------------------------

SRFI-88 (http://srfi.schemers.org/srfi-88/srfi-88.html) provides
“keyword objects”, which are equivalent to Guile's keywords (see
Keywords).  SRFI-88 keywords can be entered using the “postfix keyword
syntax”, which consists of an identifier followed by ‘:’ (see
‘postfix’ keyword syntax).  SRFI-88 can be made available
with:

     (use-modules (srfi srfi-88))

   Doing so installs the right reader option for keyword syntax, using
‘(read-set! keywords 'postfix)’.  It also provides the procedures
described below.

 -- Scheme Procedure: keyword? obj
     Return ‘#t’ if OBJ is a keyword.  This is the same procedure as the
     same-named built-in procedure (see ‘keyword?’).

          (keyword? foo:)         ⇒ #t
          (keyword? 'foo:)        ⇒ #t
          (keyword? "foo")        ⇒ #f

 -- Scheme Procedure: keyword->string kw
     Return the name of KW as a string, i.e., without the trailing
     colon.  The returned string may not be modified, e.g., with
     ‘string-set!’.

          (keyword->string foo:)  ⇒ "foo"

 -- Scheme Procedure: string->keyword str
     Return the keyword object whose name is STR.

          (keyword->string (string->keyword "a b c"))     ⇒ "a b c"

7.5.43 SRFI-98 Accessing environment variables.
-----------------------------------------------

This is a portable wrapper around Guile's built-in support for
interacting with the current environment, see Runtime Environment.

 -- Scheme Procedure: get-environment-variable name
     Returns a string containing the value of the environment variable
     given by the string ‘name’, or ‘#f’ if the named environment
     variable is not found.  This is equivalent to ‘(getenv name)’.

 -- Scheme Procedure: get-environment-variables
     Returns the names and values of all the environment variables as an
     association list in which both the keys and the values are strings.

7.5.44 SRFI-105 Curly-infix expressions.
----------------------------------------

Guile's built-in reader includes support for SRFI-105 curly-infix
expressions.  See the specification of SRFI-105
(http://srfi.schemers.org/srfi-105/srfi-105.html).  Some examples:

     {n <= 5}                ⇒  (<= n 5)
     {a + b + c}             ⇒  (+ a b c)
     {a * {b + c}}           ⇒  (* a (+ b c))
     {(- a) / b}             ⇒  (/ (- a) b)
     {-(a) / b}              ⇒  (/ (- a) b) as well
     {(f a b) + (g h)}       ⇒  (+ (f a b) (g h))
     {f(a b) + g(h)}         ⇒  (+ (f a b) (g h)) as well
     {f[a b] + g(h)}         ⇒  (+ ($bracket-apply$ f a b) (g h))
     '{a + f(b) + x}         ⇒  '(+ a (f b) x)
     {length(x) >= 6}        ⇒  (>= (length x) 6)
     {n-1 + n-2}             ⇒  (+ n-1 n-2)
     {n * factorial{n - 1}}  ⇒  (* n (factorial (- n 1)))
     {{a > 0} and {b >= 1}}  ⇒  (and (> a 0) (>= b 1))
     {f{n - 1}(x)}           ⇒  ((f (- n 1)) x)
     {a . z}                 ⇒  ($nfx$ a . z)
     {a + b - c}             ⇒  ($nfx$ a + b - c)

   To enable curly-infix expressions within a file, place the reader
directive ‘#!curly-infix’ before the first use of curly-infix notation.
To globally enable curly-infix expressions in Guile's reader, set the
‘curly-infix’ read option.

   Guile also implements the following non-standard extension to
SRFI-105: if ‘curly-infix’ is enabled and there is no other meaning
assigned to square brackets (i.e.  the ‘square-brackets’ read option is
turned off), then lists within square brackets are read as normal lists
but with the special symbol ‘$bracket-list$’ added to the front.  To
enable this combination of read options within a file, use the reader
directive ‘#!curly-infix-and-bracket-lists’.  For example:

     [a b]    ⇒  ($bracket-list$ a b)
     [a . b]  ⇒  ($bracket-list$ a . b)

   For more information on reader options, see Scheme Read.

7.5.45 SRFI-111 Boxes.
----------------------

SRFI-111 (http://srfi.schemers.org/srfi-111/srfi-111.html) provides
boxes: objects with a single mutable cell.

 -- Scheme Procedure: box value
     Return a newly allocated box whose contents is initialized to
     VALUE.

 -- Scheme Procedure: box? obj
     Return true if OBJ is a box, otherwise return false.

 -- Scheme Procedure: unbox box
     Return the current contents of BOX.

 -- Scheme Procedure: set-box! box value
     Set the contents of BOX to VALUE.

7.5.46 SRFI-119 Wisp: simpler indentation-sensitive Scheme.
-----------------------------------------------------------

The languages shipped in Guile include SRFI-119, also referred to as
“Wisp” (for "Whitespace to Lisp"), an encoding of Scheme that allows
replacing parentheses with equivalent indentation and inline colons.
See the specification of SRFI-119
(http://srfi.schemers.org/srfi-119/srfi-119.html).  Some examples:

     display "Hello World!"         ⇒  (display "Hello World!")

     define : factorial n           ⇒  (define (factorial n)
         if : zero? n               ⇒      (if (zero? n)
            . 1                     ⇒          1
            * n : factorial {n - 1} ⇒    (* n (factorial {n - 1}))))

   To execute a file with Wisp code, select the language and filename
extension ‘.w’ vie ‘guile --language=wisp -x .w’.

   In files using Wisp, see SRFI-105 (Curly Infix) is always
activated.

7.5.47 Transducers
------------------

Some of the most common operations used in the Scheme language are those
transforming lists: map, filter, take and so on.  They work well, are
well understood, and are used daily by most Scheme programmers.  They
are however not general because they only work on lists, and they do not
compose very well since combining N of them builds ‘(- N 1)’
intermediate lists.

   Transducers are oblivious to what kind of process they are used in,
and are composable without building intermediate collections.  This
means we can create a transducer that squares all odd numbers:

     (compose (tfilter odd?) (tmap (lambda (x) (* x x))))

   and reuse it with lists, vectors, or in just about any context where
data flows in one direction.  We could use it as a processing step for
asynchronous channels, with an event framework as a pre-processing step,
or even in lazy contexts where you pass a lazy collection and a
transducer to a function and get a new lazy collection back.

   The traditional Scheme approach of having collection-specific
procedures is not changed.  We instead specify a general form of
transformations that complement these procedures.  The benefits are
obvious: a clear, well-understood way of describing common
transformations in a way that is faster than just chaining the
collection-specific counterparts.  For guile in particular this means a
lot better GC performance.

   Notice however that ‘(compose ...)’ composes transducers
left-to-right, due to how transducers are initiated.

7.5.47.1 SRFI-171 General Discussion
....................................

The concept of reducers
-----------------------

The central part of transducers are 3-arity reducing procedures.

   • no arguments: Produces the identity of the reducer.

   • (result-so-far): completion.  Returns ‘result-so-far’ either with
     or without transforming it first.

   • (result-so-far input) combines ‘result-so-far’ and ‘input’ to
     produce a new ‘result-so-far’.

   In the case of a summing ‘+’ reducer, the reducer would produce, in
arity order: ‘0’, ‘result-so-far’, ‘(+ result-so-far input)’.  This
happens to be exactly what the regular ‘+’ does.

The concept of transducers
--------------------------

A transducer is a one-arity procedure that takes a reducer and produces
a reducing function that behaves as follows:

   • no arguments: calls reducer with no arguments (producing its
     identity)

   • (result-so-far): Maybe transform the result-so-far and call reducer
     with it.

   • (result-so-far input) Maybe do something to input and maybe call
     the reducer with result-so-far and the maybe-transformed input.

   A simple example is as following:

     (list-transduce (tfilter odd?) + '(1 2 3 4 5))

   This first returns a transducer filtering all odd elements, then it
runs ‘+’ without arguments to retrieve its identity.  It then starts the
transduction by passing ‘+’ to the transducer returned by ‘(tfilter
odd?)’ which returns a reducing function.  It works not unlike reduce
from SRFI 1, but also checks whether one of the intermediate transducers
returns a "reduced" value (implemented as a SRFI 9 record), which means
the reduction finished early.

   Because transducers compose and the final reduction is only executed
in the last step, composed transducers will not build any intermediate
result or collections.  Although the normal way of thinking about
application of composed functions is right to left, due to how the
transduction is built it is applied left to right.  ‘(compose (tfilter
odd?) (tmap sqrt))’ will create a transducer that first filters out any
odd values and then computes the square root of the rest.

State
-----

Even though transducers appear to be somewhat of a generalisation of
‘map’ and friends, this is not really true.  Since transducers don't
know in which context they are being used, some transducers must keep
state where their collection-specific counterparts do not.  The
transducers that keep state do so using hidden mutable state, and as
such all the caveats of mutation, parallelism, and multi-shot
continuations apply.  Each transducer keeping state is clearly described
as doing so in the documentation.

Naming
------

Reducers exported from the transducers module are named as in their
SRFI-1 counterpart, but prepended with an r.  Transducers also follow
that naming, but are prepended with a t.

7.5.47.2 Applying Transducers
.............................

 -- Scheme Procedure: list-transduce xform f lst
 -- Scheme Procedure: list-transduce xform f identity lst
     Initialize the transducer XFORM by passing the reducer F to it.  If
     no identity is provided, F runs without arguments to return the
     reducer identity.  It then reduces over LST using the identity as
     the seed.

     If one of the transducers finishes early (such as ‘ttake’ or
     ‘tdrop’), it communicates this by returning a reduced value, which
     in the guile implementation is just a value wrapped in a SRFI 9
     record type named "reduced".  If such a value is returned by the
     transducer, ‘list-transduce’ must stop execution and return an
     unreduced value immediately.

 -- Scheme Procedure: vector-transduce xform f vec
 -- Scheme Procedure: vector-transduce xform f identity vec
 -- Scheme Procedure: string-transduce xform f str
 -- Scheme Procedure: string-transduce xform f identity str
 -- Scheme Procedure: bytevector-u8-transduce xform f bv
 -- Scheme Procedure: bytevector-u8-transduce xform f identity bv
 -- Scheme Procedure: generator-transduce xform f gen
 -- Scheme Procedure: generator-transduce xform f identity gen

     Same as ‘list-transduce’, but for vectors, strings, u8-bytevectors
     and SRFI-158-styled generators respectively.

 -- Scheme Procedure: port-transduce xform f reader
 -- Scheme Procedure: port-transduce xform f reader port
 -- Scheme Procedure: port-transduce xform f identity reader port

     Same as ‘list-transduce’ but for ports.  Called without a port, it
     reduces over the results of applying READER until the EOF-object is
     returned, presumably to read from ‘current-input-port’.  With a
     port READER is applied to PORT instead of without any arguments.
     If IDENTITY is provided, that is used as the initial identity in
     the reduction.

7.5.47.3 Reducers
.................

 -- Scheme Procedure: rcons
     a simple consing reducer.  When called without values, it returns
     its identity, ‘'()’.  With one value, which will be a list, it
     reverses the list (using ‘reverse!’).  When called with two values,
     it conses the second value to the first.

          (list-transduce (tmap (lambda (x) (+ x 1)) rcons (list 0 1 2 3))
          ⇒ (1 2 3 4)

 -- Scheme Procedure: reverse-rcons
     same as rcons, but leaves the values in their reversed order.
          (list-transduce (tmap (lambda (x) (+ x 1))) reverse-rcons (list 0 1 2 3))
          ⇒ (4 3 2 1)

 -- Scheme Procedure: rany pred?
     The reducer version of any.  Returns ‘(reduced (pred? value))’ if
     any ‘(pred? value)’ returns non-#f.  The identity is #f.

          (list-transduce (tmap (lambda (x) (+ x 1))) (rany odd?) (list 1 3 5))
          ⇒ #f

          (list-transduce (tmap (lambda (x) (+ x 1))) (rany odd?) (list 1 3 4 5))
          ⇒ #t

 -- Scheme Procedure: revery pred?
     The reducer version of every.  Stops the transduction and returns
     ‘(reduced #f)’ if any ‘(pred? value)’ returns #f.  If every ‘(pred?
     value)’ returns true, it returns the result of the last invocation
     of ‘(pred? value)’.  The identity is #t.

          (list-transduce
            (tmap (lambda (x) (+ x 1)))
            (revery (lambda (v) (if (odd? v) v #f)))
            (list 2 4 6))
            ⇒ 7

          (list-transduce (tmap (lambda (x) (+ x 1)) (revery odd?) (list 2 4 5 6))
          ⇒ #f

 -- Scheme Procedure: rcount
     A simple counting reducer.  Counts the values that pass through the
     transduction.
          (list-transduce (tfilter odd?) rcount (list 1 2 3 4)) ⇒ 2.

7.5.47.4 Transducers
....................

 -- Scheme Procedure: tmap proc
     Returns a transducer that applies PROC to all values.  Stateless.

 -- Scheme Procedure: tfilter pred?
     Returns a transducer that removes values for which PRED? returns
     #f.

     Stateless.

 -- Scheme Procedure: tremove pred?
     Returns a transducer that removes values for which PRED? returns
     non-#f.

     Stateless

 -- Scheme Procedure: tfilter-map proc
     The same as ‘(compose (tmap proc) (tfilter values))’.  Stateless.

 -- Scheme Procedure: treplace mapping
     The argument MAPPING is an association list (using ‘equal?’ to
     compare keys), a hash-table, a one-argument procedure taking one
     argument and either producing that same argument or a replacement
     value.

     Returns a transducer which checks for the presence of any value
     passed through it in mapping.  If a mapping is found, the value of
     that mapping is returned, otherwise it just returns the original
     value.

     Does not keep internal state, but modifying the mapping while it's
     in use by treplace is an error.

 -- Scheme Procedure: tdrop n
     Returns a transducer that discards the first N values.

     Stateful.

 -- Scheme Procedure: ttake n
     Returns a transducer that discards all values and stops the
     transduction after the first N values have been let through.  Any
     subsequent values are ignored.

     Stateful.

 -- Scheme Procedure: tdrop-while pred?
     Returns a transducer that discards the first values for which PRED?
     returns true.

     Stateful.

 -- Scheme Procedure: ttake-while pred?
 -- Scheme Procedure: ttake-while pred? retf
     Returns a transducer that stops the transduction after PRED? has
     returned #f.  Any subsequent values are ignored and the last
     successful value is returned.  RETF is a function that gets called
     whenever PRED? returns false.  The arguments passed are the result
     so far and the input for which pred?  returns ‘#f’.  The default
     function is ‘(lambda (result input) result)’.

     Stateful.

 -- Scheme Procedure: tconcatenate
     tconcatenate _is_ a transducer that concatenates the content of
     each value (that must be a list) into the reduction.
          (list-transduce tconcatenate rcons '((1 2) (3 4 5) (6 (7 8) 9)))
          ⇒ (1 2 3 4 5 6 (7 8) 9)

 -- Scheme Procedure: tappend-map proc
     The same as ‘(compose (tmap proc) tconcatenate)’.

 -- Scheme Procedure: tflatten
     tflatten _is_ a transducer that flattens an input consisting of
     lists.

          (list-transduce tflatten rcons '((1 2) 3 (4 (5 6) 7 8) 9)
          ⇒ (1 2 3 4 5 6 7 8 9)

 -- Scheme Procedure: tdelete-neighbor-duplicates
 -- Scheme Procedure: tdelete-neighbor-duplicates equality-predicate
     Returns a transducer that removes any directly following duplicate
     elements.  The default EQUALITY-PREDICATE is ‘equal?’.

     Stateful.

 -- Scheme Procedure: tdelete-duplicates
 -- Scheme Procedure: tdelete-duplicates equality-predicate
     Returns a transducer that removes any subsequent duplicate elements
     compared using EQUALITY-PREDICATE.  The default EQUALITY-PREDICATE
     is ‘equal?’.

     Stateful.

 -- Scheme Procedure: tsegment n
     Returns a transducer that groups inputs into lists of N elements.
     When the transduction stops, it flushes any remaining collection,
     even if it contains fewer than N elements.

     Stateful.

 -- Scheme Procedure: tpartition pred?
     Returns a transducer that groups inputs in lists by whenever
     ‘(pred? input)’ changes value.

     Stateful.

 -- Scheme Procedure: tadd-between value
     Returns a transducer which interposes VALUE between each value and
     the next.  This does not compose gracefully with transducers like
     ‘ttake’, as you might end up ending the transduction on ‘value’.

     Stateful.

 -- Scheme Procedure: tenumerate
 -- Scheme Procedure: tenumerate start
     Returns a transducer that indexes values passed through it,
     starting at START, which defaults to 0.  The indexing is done
     through cons pairs like ‘(index . input)’.

          (list-transduce (tenumerate 1) rcons (list 'first 'second 'third))
          ⇒ ((1 . first) (2 . second) (3 . third))

     Stateful.

 -- Scheme Procedure: tlog
 -- Scheme Procedure: tlog logger
     Returns a transducer that can be used to log or print values and
     results.  The result of the LOGGER procedure is discarded.  The
     default LOGGER is ‘(lambda (result input) (write input)
     (newline))’.

     Stateless.

Guile-specific transducers
--------------------------

These transducers are available in the ‘(srfi srfi-171 gnu)’ library,
and are provided outside the standard described by the SRFI-171
document.

 -- Scheme Procedure: tbatch reducer
 -- Scheme Procedure: tbatch transducer reducer
     A batching transducer that accumulates results using REDUCER or
     ‘((transducer) reducer)’ until it returns a reduced value.  This
     can be used to generalize something like ‘tsegment’:

          ;; This behaves exactly like (tsegment 4).
          (list-transduce (tbatch (ttake 4) rcons) rcons (iota 10))
          ⇒ ((0 1 2 3) (4 5 6 7) (8 9))

 -- Scheme Procedure: tfold reducer
 -- Scheme Procedure: tfold reducer seed

     A folding transducer that yields the result of ‘(reducer seed
     value)’, saving its result between iterations.

          (list-transduce (tfold +) rcons (iota 10))
          ⇒ (0 1 3 6 10 15 21 28 36 45)

7.5.47.5 Helper functions for writing transducers
.................................................

These functions are in the ‘(srfi srfi-171 meta)’ module and are only
usable when you want to write your own transducers.

 -- Scheme Procedure: reduced value
     Wraps a value in a ‘<reduced>’ container, signaling that the
     reduction should stop.

 -- Scheme Procedure: reduced? value
     Returns #t if value is a ‘<reduced>’ record.

 -- Scheme Procedure: unreduce reduced-container
     Returns the value in reduced-container.

 -- Scheme Procedure: ensure-reduced value
     Wraps value in a ‘<reduced>’ container if it is not already
     reduced.

 -- Scheme Procedure: preserving-reduced reducer
     Wraps ‘reducer’ in another reducer that encapsulates any returned
     reduced value in another reduced container.  This is useful in
     places where you re-use a reducer with [collection]-reduce.  If the
     reducer returns a reduced value, [collection]-reduce unwraps it.
     Unless handled, this leads to the reduction continuing.

 -- Scheme Procedure: list-reduce f identity lst
     The reducing function used internally by ‘list-transduce’.  F is a
     reducer as returned by a transducer.  IDENTITY is the identity
     (sometimes called "seed") of the reduction.  LST is a list.  If F
     returns a reduced value, the reduction stops immediately and the
     unreduced value is returned.

 -- Scheme Procedure: vector-reduce f identity vec
     The vector version of list-reduce.

 -- Scheme Procedure: string-reduce f identity str
     The string version of list-reduce.

 -- Scheme Procedure: bytevector-u8-reduce f identity bv
     The bytevector-u8 version of list-reduce.

 -- Scheme Procedure: port-reduce f identity reader port
     The port version of list-reduce.  It reduces over port using reader
     until reader returns the EOF object.

 -- Scheme Procedure: generator-reduce f identity gen
     The generator version of list-reduce.  It reduces over ‘gen’ until
     it returns the EOF object

7.6 R6RS Support
================

See R6RS Libraries, for more information on how to define R6RS
libraries, and their integration with Guile modules.

7.6.1 Incompatibilities with the R6RS
-------------------------------------

There are some incompatibilities between Guile and the R6RS. Some of
them are intentional, some of them are bugs, and some are simply
unimplemented features.  Please let the Guile developers know if you
find one that is not on this list.

   • The R6RS specifies many situations in which a conforming
     implementation must signal a specific error.  Guile doesn't really
     care about that too much--if a correct R6RS program would not hit
     that error, we don't bother checking for it.

   • Multiple ‘library’ forms in one file are not yet supported.  This
     is because the expansion of ‘library’ sets the current module, but
     does not restore it.  This is a bug.

   • R6RS unicode escapes within strings are disabled by default,
     because they conflict with Guile's already-existing escapes.  The
     same is the case for R6RS treatment of escaped newlines in strings.

     R6RS behavior can be turned on via a reader option.  See String Syntax,
     for more information.

   • Guile does not yet support Unicode escapes in symbols, such as
     ‘H\x65;llo’ (the same as ‘Hello’), or ‘\x3BB;’ (the same as ‘λ’).

   • A ‘set!’ to a variable transformer may only expand to an
     expression, not a definition--even if the original ‘set!’
     expression was in definition context.

   • Instead of using the algorithm detailed in chapter 10 of the R6RS,
     expansion of toplevel forms happens sequentially.

     For example, while the expansion of the following set of toplevel
     definitions does the correct thing:

          (begin
           (define even?
             (lambda (x)
               (or (= x 0) (odd? (- x 1)))))
           (define-syntax odd?
             (syntax-rules ()
               ((odd? x) (not (even? x)))))
           (even? 10))
          ⇒ #t

     The same definitions outside of the ‘begin’ wrapper do not:

          (define even?
            (lambda (x)
              (or (= x 0) (odd? (- x 1)))))
          (define-syntax odd?
            (syntax-rules ()
              ((odd? x) (not (even? x)))))
          (even? 10)
          <unnamed port>:4:18: In procedure even?:
          <unnamed port>:4:18: Wrong type to apply: #<syntax-transformer odd?>

     This is because when expanding the right-hand-side of ‘even?’, the
     reference to ‘odd?’ is not yet marked as a syntax transformer, so
     it is assumed to be a function.

     This bug will only affect top-level programs, not code in ‘library’
     forms.  Fixing it for toplevel forms seems doable, but tricky to
     implement in a backward-compatible way.  Suggestions and/or patches
     would be appreciated.

   • The ‘(rnrs io ports)’ module is incomplete.  Work is ongoing to fix
     this.

   • Guile does not prevent use of textual I/O procedures on binary
     ports, or vice versa.  All ports in Guile support both binary and
     textual I/O. See Encoding, for full details.

   • Guile's implementation of ‘equal?’ may fail to terminate when
     applied to arguments containing cycles.

   Guile exposes a procedure in the root module to choose R6RS defaults
over Guile's historical defaults.

 -- Scheme Procedure: install-r6rs!
     Alter Guile's default settings to better conform to the R6RS.

     While Guile's defaults may evolve over time, the current changes
     that this procedure imposes are to add ‘.sls’ and ‘.guile.sls’ to
     the set of supported ‘%load-extensions’, to better support R6RS
     conventions.  See Load Paths.  Also, enable R6RS unicode
     escapes in strings; see the discussion above.

   Finally, note that the ‘--r6rs’ command-line argument will call
‘install-r6rs!’ before calling user code.  R6RS users probably want to
pass this argument to their Guile.

7.6.2 R6RS Standard Libraries
-----------------------------

In contrast with earlier versions of the Revised Report, the R6RS
organizes the procedures and syntactic forms required of conforming
implementations into a set of "standard libraries" which can be imported
as necessary by user programs and libraries.  Here we briefly list the
libraries that have been implemented for Guile.

   We do not attempt to document these libraries fully here, as most of
their functionality is already available in Guile itself.  The
expectation is that most Guile users will use the well-known and
well-documented Guile modules.  These R6RS libraries are mostly useful
to users who want to port their code to other R6RS systems.

   The documentation in the following sections reproduces some of the
content of the library section of the Report, but is mostly intended to
provide supplementary information about Guile's implementation of the
R6RS standard libraries.  For complete documentation, design rationales
and further examples, we advise you to consult the "Standard Libraries"
section of the Report (see R6RS Standard Libraries (r6rs)).

7.6.2.1 Library Usage
.....................

Guile implements the R6RS 'library' form as a transformation to a native
Guile module definition.  As a consequence of this, all of the libraries
described in the following subsections, in addition to being available
for use by R6RS libraries and top-level programs, can also be imported
as if they were normal Guile modules--via a ‘use-modules’ form, say.
For example, the R6RS "composite" library can be imported by:

       (import (rnrs (6)))

       (use-modules ((rnrs) :version (6)))

   For more information on Guile's library implementation, see (see
R6RS Libraries).

7.6.2.2 rnrs base
.................

The ‘(rnrs base (6))’ library exports the procedures and syntactic forms
described in the main section of the Report (see R6RS Base library (r6rs)).
They are grouped below by the existing manual
sections to which they correspond.

 -- Scheme Procedure: boolean? obj
 -- Scheme Procedure: not x
     See Booleans, for documentation.

 -- Scheme Procedure: symbol? obj
 -- Scheme Procedure: symbol->string sym
 -- Scheme Procedure: string->symbol str
     See Symbol Primitives, for documentation.

 -- Scheme Procedure: char? obj
 -- Scheme Procedure: char=?
 -- Scheme Procedure: char<?
 -- Scheme Procedure: char>?
 -- Scheme Procedure: char<=?
 -- Scheme Procedure: char>=?
 -- Scheme Procedure: integer->char n
 -- Scheme Procedure: char->integer chr
     See Characters, for documentation.

 -- Scheme Procedure: list? x
 -- Scheme Procedure: null? x
     See List Predicates, for documentation.

 -- Scheme Procedure: pair? x
 -- Scheme Procedure: cons x y
 -- Scheme Procedure: car pair
 -- Scheme Procedure: cdr pair
 -- Scheme Procedure: caar pair
 -- Scheme Procedure: cadr pair
 -- Scheme Procedure: cdar pair
 -- Scheme Procedure: cddr pair
 -- Scheme Procedure: caaar pair
 -- Scheme Procedure: caadr pair
 -- Scheme Procedure: cadar pair
 -- Scheme Procedure: cdaar pair
 -- Scheme Procedure: caddr pair
 -- Scheme Procedure: cdadr pair
 -- Scheme Procedure: cddar pair
 -- Scheme Procedure: cdddr pair
 -- Scheme Procedure: caaaar pair
 -- Scheme Procedure: caaadr pair
 -- Scheme Procedure: caadar pair
 -- Scheme Procedure: cadaar pair
 -- Scheme Procedure: cdaaar pair
 -- Scheme Procedure: cddaar pair
 -- Scheme Procedure: cdadar pair
 -- Scheme Procedure: cdaadr pair
 -- Scheme Procedure: cadadr pair
 -- Scheme Procedure: caaddr pair
 -- Scheme Procedure: caddar pair
 -- Scheme Procedure: cadddr pair
 -- Scheme Procedure: cdaddr pair
 -- Scheme Procedure: cddadr pair
 -- Scheme Procedure: cdddar pair
 -- Scheme Procedure: cddddr pair
     See Pairs, for documentation.

 -- Scheme Procedure: number? obj
     See Numerical Tower, for documentation.

 -- Scheme Procedure: string? obj
     See String Predicates, for documentation.

 -- Scheme Procedure: procedure? obj
     See Procedure Properties, for documentation.

 -- Scheme Syntax: define name value
 -- Scheme Syntax: set! variable-name value
     See Definition, for documentation.

 -- Scheme Syntax: define-syntax keyword expression
 -- Scheme Syntax: let-syntax ((keyword transformer) ...) exp1 exp2 ...
 -- Scheme Syntax: letrec-syntax ((keyword transformer) ...) exp1 exp2
          ...
     See Defining Macros, for documentation.

 -- Scheme Syntax: identifier-syntax exp
     See Identifier Macros, for documentation.

 -- Scheme Syntax: syntax-rules literals (pattern template) ...
     See Syntax Rules, for documentation.

 -- Scheme Syntax: lambda formals body
     See Lambda, for documentation.

 -- Scheme Syntax: let bindings body
 -- Scheme Syntax: let* bindings body
 -- Scheme Syntax: letrec bindings body
 -- Scheme Syntax: letrec* bindings body
     See Local Bindings, for documentation.

 -- Scheme Syntax: let-values bindings body
 -- Scheme Syntax: let*-values bindings body
     See SRFI-11, for documentation.

 -- Scheme Syntax: begin expr1 expr2 ...
     See begin, for documentation.

 -- Scheme Syntax: quote expr
 -- Scheme Syntax: quasiquote expr
 -- Scheme Syntax: unquote expr
 -- Scheme Syntax: unquote-splicing expr
     See Expression Syntax, for documentation.

 -- Scheme Syntax: if test consequence [alternate]
 -- Scheme Syntax: cond clause1 clause2 ...
 -- Scheme Syntax: case key clause1 clause2 ...
     See Conditionals, for documentation.

 -- Scheme Syntax: and expr ...
 -- Scheme Syntax: or expr ...
     See and or, for documentation.

 -- Scheme Procedure: eq? x y
 -- Scheme Procedure: eqv? x y
 -- Scheme Procedure: equal? x y
 -- Scheme Procedure: symbol=? symbol1 symbol2 ...
     See Equality, for documentation.

     ‘symbol=?’ is identical to ‘eq?’.

 -- Scheme Procedure: complex? z
     See Complex Numbers, for documentation.

 -- Scheme Procedure: real-part z
 -- Scheme Procedure: imag-part z
 -- Scheme Procedure: make-rectangular real_part imaginary_part
 -- Scheme Procedure: make-polar x y
 -- Scheme Procedure: magnitude z
 -- Scheme Procedure: angle z
     See Complex, for documentation.

 -- Scheme Procedure: sqrt z
 -- Scheme Procedure: exp z
 -- Scheme Procedure: expt z1 z2
 -- Scheme Procedure: log z
 -- Scheme Procedure: sin z
 -- Scheme Procedure: cos z
 -- Scheme Procedure: tan z
 -- Scheme Procedure: asin z
 -- Scheme Procedure: acos z
 -- Scheme Procedure: atan z
     See Scientific, for documentation.

 -- Scheme Procedure: real? x
 -- Scheme Procedure: rational? x
 -- Scheme Procedure: numerator x
 -- Scheme Procedure: denominator x
 -- Scheme Procedure: rationalize x eps
     See Reals and Rationals, for documentation.

 -- Scheme Procedure: exact? x
 -- Scheme Procedure: inexact? x
 -- Scheme Procedure: exact z
 -- Scheme Procedure: inexact z
     See Exactness, for documentation.  The ‘exact’ and ‘inexact’
     procedures are identical to the ‘inexact->exact’ and
     ‘exact->inexact’ procedures provided by Guile's code library.

 -- Scheme Procedure: integer? x
     See Integers, for documentation.

 -- Scheme Procedure: odd? n
 -- Scheme Procedure: even? n
 -- Scheme Procedure: gcd x ...
 -- Scheme Procedure: lcm x ...
 -- Scheme Procedure: exact-integer-sqrt k
     See Integer Operations, for documentation.

 -- Scheme Procedure: =
 -- Scheme Procedure: <
 -- Scheme Procedure: >
 -- Scheme Procedure: <=
 -- Scheme Procedure: >=
 -- Scheme Procedure: zero? x
 -- Scheme Procedure: positive? x
 -- Scheme Procedure: negative? x
     See Comparison, for documentation.

 -- Scheme Procedure: for-each f lst1 lst2 ...
     See SRFI-1 Fold and Map, for documentation.

 -- Scheme Procedure: list elem ...
     See List Constructors, for documentation.

 -- Scheme Procedure: length lst
 -- Scheme Procedure: list-ref lst k
 -- Scheme Procedure: list-tail lst k
     See List Selection, for documentation.

 -- Scheme Procedure: append lst ... obj
 -- Scheme Procedure: append
 -- Scheme Procedure: reverse lst
     See Append/Reverse, for documentation.

 -- Scheme Procedure: number->string n [radix]
 -- Scheme Procedure: string->number str [radix]
     See Conversion, for documentation.

 -- Scheme Procedure: string char ...
 -- Scheme Procedure: make-string k [chr]
 -- Scheme Procedure: list->string lst
     See String Constructors, for documentation.

 -- Scheme Procedure: string->list str [start [end]]
     See List/String Conversion, for documentation.

 -- Scheme Procedure: string-length str
 -- Scheme Procedure: string-ref str k
 -- Scheme Procedure: string-copy str [start [end]]
 -- Scheme Procedure: substring str start [end]
     See String Selection, for documentation.

 -- Scheme Procedure: string=? s1 s2 s3 ...
 -- Scheme Procedure: string<? s1 s2 s3 ...
 -- Scheme Procedure: string>? s1 s2 s3 ...
 -- Scheme Procedure: string<=? s1 s2 s3 ...
 -- Scheme Procedure: string>=? s1 s2 s3 ...
     See String Comparison, for documentation.

 -- Scheme Procedure: string-append arg ...
     See Reversing and Appending Strings, for documentation.

 -- Scheme Procedure: string-for-each proc s [start [end]]
     See Mapping Folding and Unfolding, for documentation.

 -- Scheme Procedure: + z1 ...
 -- Scheme Procedure: - z1 z2 ...
 -- Scheme Procedure: * z1 ...
 -- Scheme Procedure: / z1 z2 ...
 -- Scheme Procedure: max x1 x2 ...
 -- Scheme Procedure: min x1 x2 ...
 -- Scheme Procedure: abs x
 -- Scheme Procedure: truncate x
 -- Scheme Procedure: floor x
 -- Scheme Procedure: ceiling x
 -- Scheme Procedure: round x
     See Arithmetic, for documentation.

 -- Scheme Procedure: div x y
 -- Scheme Procedure: mod x y
 -- Scheme Procedure: div-and-mod x y
     These procedures accept two real numbers X and Y, where the divisor
     Y must be non-zero.  ‘div’ returns the integer Q and ‘mod’ returns
     the real number R such that X = Q*Y + R and 0 <= R < abs(Y).
     ‘div-and-mod’ returns both Q and R, and is more efficient than
     computing each separately.  Note that when Y > 0, ‘div’ returns
     floor(X/Y), otherwise it returns ceiling(X/Y).

          (div 123 10) ⇒ 12
          (mod 123 10) ⇒ 3
          (div-and-mod 123 10) ⇒ 12 and 3
          (div-and-mod 123 -10) ⇒ -12 and 3
          (div-and-mod -123 10) ⇒ -13 and 7
          (div-and-mod -123 -10) ⇒ 13 and 7
          (div-and-mod -123.2 -63.5) ⇒ 2.0 and 3.8
          (div-and-mod 16/3 -10/7) ⇒ -3 and 22/21

 -- Scheme Procedure: div0 x y
 -- Scheme Procedure: mod0 x y
 -- Scheme Procedure: div0-and-mod0 x y
     These procedures accept two real numbers X and Y, where the divisor
     Y must be non-zero.  ‘div0’ returns the integer Q and ‘mod0’
     returns the real number R such that X = Q*Y + R and -abs(Y/2) <= R
     < abs(Y/2).  ‘div0-and-mod0’ returns both Q and R, and is more
     efficient than computing each separately.

     Note that ‘div0’ returns X/Y rounded to the nearest integer.  When
     X/Y lies exactly half-way between two integers, the tie is broken
     according to the sign of Y.  If Y > 0, ties are rounded toward
     positive infinity, otherwise they are rounded toward negative
     infinity.  This is a consequence of the requirement that -abs(Y/2)
     <= R < abs(Y/2).

          (div0 123 10) ⇒ 12
          (mod0 123 10) ⇒ 3
          (div0-and-mod0 123 10) ⇒ 12 and 3
          (div0-and-mod0 123 -10) ⇒ -12 and 3
          (div0-and-mod0 -123 10) ⇒ -12 and -3
          (div0-and-mod0 -123 -10) ⇒ 12 and -3
          (div0-and-mod0 -123.2 -63.5) ⇒ 2.0 and 3.8
          (div0-and-mod0 16/3 -10/7) ⇒ -4 and -8/21

 -- Scheme Procedure: real-valued? obj
 -- Scheme Procedure: rational-valued? obj
 -- Scheme Procedure: integer-valued? obj
     These procedures return ‘#t’ if and only if their arguments can,
     respectively, be coerced to a real, rational, or integer value
     without a loss of numerical precision.

     ‘real-valued?’ will return ‘#t’ for complex numbers whose imaginary
     parts are zero.

 -- Scheme Procedure: nan? x
 -- Scheme Procedure: infinite? x
 -- Scheme Procedure: finite? x
     ‘nan?’ returns ‘#t’ if X is a NaN value, ‘#f’ otherwise.
     ‘infinite?’ returns ‘#t’ if X is an infinite value, ‘#f’ otherwise.
     ‘finite?’ returns ‘#t’ if X is neither infinite nor a NaN value,
     otherwise it returns ‘#f’.  Every real number satisfies exactly one
     of these predicates.  An exception is raised if X is not real.

 -- Scheme Syntax: assert expr
     Raises an ‘&assertion’ condition if EXPR evaluates to ‘#f’;
     otherwise evaluates to the value of EXPR.

 -- Scheme Procedure: error who message irritant1 ...
 -- Scheme Procedure: assertion-violation who message irritant1 ...
     These procedures raise compound conditions based on their
     arguments: If WHO is not ‘#f’, the condition will include a ‘&who’
     condition whose ‘who’ field is set to WHO; a ‘&message’ condition
     will be included with a ‘message’ field equal to MESSAGE; an
     ‘&irritants’ condition will be included with its ‘irritants’ list
     given by ‘irritant1 ...’.

     ‘error’ produces a compound condition with the simple conditions
     described above, as well as an ‘&error’ condition;
     ‘assertion-violation’ produces one that includes an ‘&assertion’
     condition.

 -- Scheme Procedure: vector-map proc v
 -- Scheme Procedure: vector-for-each proc v
     These procedures implement the ‘map’ and ‘for-each’ contracts over
     vectors.

 -- Scheme Procedure: vector arg ...
 -- Scheme Procedure: vector? obj
 -- Scheme Procedure: make-vector len
 -- Scheme Procedure: make-vector len fill
 -- Scheme Procedure: list->vector l
 -- Scheme Procedure: vector->list v
     See Vector Creation, for documentation.

 -- Scheme Procedure: vector-length vector
 -- Scheme Procedure: vector-ref vector k
 -- Scheme Procedure: vector-set! vector k obj
 -- Scheme Procedure: vector-fill! v fill
     See Vector Accessors, for documentation.

 -- Scheme Procedure: call-with-current-continuation proc
 -- Scheme Procedure: call/cc proc
     See Continuations, for documentation.

 -- Scheme Procedure: values arg ...
 -- Scheme Procedure: call-with-values producer consumer
     See Multiple Values, for documentation.

 -- Scheme Procedure: dynamic-wind in_guard thunk out_guard
     See Dynamic Wind, for documentation.

 -- Scheme Procedure: apply proc arg ... arglst
     See Fly Evaluation, for documentation.

7.6.2.3 rnrs unicode
....................

The ‘(rnrs unicode (6))’ library provides procedures for manipulating
Unicode characters and strings.

 -- Scheme Procedure: char-upcase char
 -- Scheme Procedure: char-downcase char
 -- Scheme Procedure: char-titlecase char
 -- Scheme Procedure: char-foldcase char
     These procedures translate their arguments from one Unicode
     character set to another.  ‘char-upcase’, ‘char-downcase’, and
     ‘char-titlecase’ are identical to their counterparts in the Guile
     core library; see Characters, for documentation.

     ‘char-foldcase’ returns the result of applying ‘char-upcase’ to its
     argument, followed by ‘char-downcase’--except in the case of the
     Turkic characters ‘U+0130’ and ‘U+0131’, for which the procedure
     acts as the identity function.

 -- Scheme Procedure: char-ci=? char1 char2 char3 ...
 -- Scheme Procedure: char-ci<? char1 char2 char3 ...
 -- Scheme Procedure: char-ci>? char1 char2 char3 ...
 -- Scheme Procedure: char-ci<=? char1 char2 char3 ...
 -- Scheme Procedure: char-ci>=? char1 char2 char3 ...
     These procedures facilitate case-insensitive comparison of Unicode
     characters.  They are identical to the procedures provided by
     Guile's core library.  See Characters, for documentation.

 -- Scheme Procedure: char-alphabetic? char
 -- Scheme Procedure: char-numeric? char
 -- Scheme Procedure: char-whitespace? char
 -- Scheme Procedure: char-upper-case? char
 -- Scheme Procedure: char-lower-case? char
 -- Scheme Procedure: char-title-case? char
     These procedures implement various Unicode character set
     predicates.  They are identical to the procedures provided by
     Guile's core library.  See Characters, for documentation.

 -- Scheme Procedure: char-general-category char
     See Characters, for documentation.

 -- Scheme Procedure: string-upcase string
 -- Scheme Procedure: string-downcase string
 -- Scheme Procedure: string-titlecase string
 -- Scheme Procedure: string-foldcase string
     These procedures perform Unicode case folding operations on their
     input.  See Alphabetic Case Mapping, for documentation.

 -- Scheme Procedure: string-ci=? string1 string2 string3 ...
 -- Scheme Procedure: string-ci<? string1 string2 string3 ...
 -- Scheme Procedure: string-ci>? string1 string2 string3 ...
 -- Scheme Procedure: string-ci<=? string1 string2 string3 ...
 -- Scheme Procedure: string-ci>=? string1 string2 string3 ...
     These procedures perform case-insensitive comparison on their
     input.  See String Comparison, for documentation.

 -- Scheme Procedure: string-normalize-nfd string
 -- Scheme Procedure: string-normalize-nfkd string
 -- Scheme Procedure: string-normalize-nfc string
 -- Scheme Procedure: string-normalize-nfkc string
     These procedures perform Unicode string normalization operations on
     their input.  See String Comparison, for documentation.

7.6.2.4 rnrs bytevectors
........................

The ‘(rnrs bytevectors (6))’ library provides procedures for working
with blocks of binary data.  This functionality is documented in its own
section of the manual; see Bytevectors.

7.6.2.5 rnrs lists
..................

The ‘(rnrs lists (6))’ library provides procedures additional procedures
for working with lists.

 -- Scheme Procedure: find proc list
     This procedure is identical to the one defined in Guile's SRFI-1
     implementation.  See SRFI-1 Searching, for documentation.

 -- Scheme Procedure: for-all proc list1 list2 ...
 -- Scheme Procedure: exists proc list1 list2 ...

     The ‘for-all’ procedure is identical to the ‘every’ procedure
     defined by SRFI-1; the ‘exists’ procedure is identical to SRFI-1's
     ‘any’.  See SRFI-1 Searching, for documentation.

 -- Scheme Procedure: filter proc list
 -- Scheme Procedure: partition proc list
     These procedures are identical to the ones provided by SRFI-1.
     See List Modification, for a description of ‘filter’; see
     SRFI-1 Filtering and Partitioning, for ‘partition’.

 -- Scheme Procedure: fold-right combine nil list1 list2 ...
     This procedure is identical the ‘fold-right’ procedure provided by
     SRFI-1.  See SRFI-1 Fold and Map, for documentation.

 -- Scheme Procedure: fold-left combine nil list1 list2 ...
     This procedure is like ‘fold’ from SRFI-1, but COMBINE is called
     with the seed as the first argument.  See SRFI-1 Fold and Map,
     for documentation.

 -- Scheme Procedure: remp proc list
 -- Scheme Procedure: remove obj list
 -- Scheme Procedure: remv obj list
 -- Scheme Procedure: remq obj list
     ‘remove’, ‘remv’, and ‘remq’ are identical to the ‘delete’, ‘delv’,
     and ‘delq’ procedures provided by Guile's core library, (see List Modification).
     ‘remp’ is identical to the alternate ‘remove’
     procedure provided by SRFI-1; see SRFI-1 Deleting.

 -- Scheme Procedure: memp proc list
 -- Scheme Procedure: member obj list
 -- Scheme Procedure: memv obj list
 -- Scheme Procedure: memq obj list
     ‘member’, ‘memv’, and ‘memq’ are identical to the procedures
     provided by Guile's core library; see List Searching, for their
     documentation.  ‘memp’ uses the specified predicate function ‘proc’
     to test elements of the list LIST--it behaves similarly to ‘find’,
     except that it returns the first sublist of LIST whose ‘car’
     satisfies PROC.

 -- Scheme Procedure: assp proc alist
 -- Scheme Procedure: assoc obj alist
 -- Scheme Procedure: assv obj alist
 -- Scheme Procedure: assq obj alist
     ‘assoc’, ‘assv’, and ‘assq’ are identical to the procedures
     provided by Guile's core library; see Alist Key Equality, for
     their documentation.  ‘assp’ uses the specified predicate function
     ‘proc’ to test keys in the association list ALIST.

 -- Scheme Procedure: cons* obj1 ... obj
 -- Scheme Procedure: cons* obj
     This procedure is identical to the one exported by Guile's core
     library.  See List Constructors, for documentation.

7.6.2.6 rnrs sorting
....................

The ‘(rnrs sorting (6))’ library provides procedures for sorting lists
and vectors.

 -- Scheme Procedure: list-sort proc list
 -- Scheme Procedure: vector-sort proc vector
     These procedures return their input sorted in ascending order,
     without modifying the original data.  PROC must be a procedure that
     takes two elements from the input list or vector as arguments, and
     returns a true value if the first is "less" than the second, ‘#f’
     otherwise.  ‘list-sort’ returns a list; ‘vector-sort’ returns a
     vector.

     Both ‘list-sort’ and ‘vector-sort’ are implemented in terms of the
     ‘stable-sort’ procedure from Guile's core library.  See
     Sorting, for a discussion of the behavior of that procedure.

 -- Scheme Procedure: vector-sort! proc vector
     Performs a destructive, "in-place" sort of VECTOR, using PROC as
     described above to determine an ascending ordering of elements.
     ‘vector-sort!’ returns an unspecified value.

     This procedure is implemented in terms of the ‘sort!’ procedure
     from Guile's core library.  See Sorting, for more information.

7.6.2.7 rnrs control
....................

The ‘(rnrs control (6))’ library provides syntactic forms useful for
constructing conditional expressions and controlling the flow of
execution.

 -- Scheme Syntax: when test expression1 expression2 ...
 -- Scheme Syntax: unless test expression1 expression2 ...
     The ‘when’ form is evaluated by evaluating the specified TEST
     expression; if the result is a true value, the EXPRESSIONs that
     follow it are evaluated in order, and the value of the final
     EXPRESSION becomes the value of the entire ‘when’ expression.

     The ‘unless’ form behaves similarly, with the exception that the
     specified EXPRESSIONs are only evaluated if the value of TEST is
     false.

 -- Scheme Syntax: do ((variable init step) ...) (test expression ...)
          command ...
     This form is identical to the one provided by Guile's core library.
     See while do, for documentation.

 -- Scheme Syntax: case-lambda clause ...
     This form is identical to the one provided by Guile's core library.
     See Case-lambda, for documentation.

7.6.2.8 R6RS Records
....................

The manual sections below describe Guile's implementation of R6RS
records, which provide support for user-defined data types.  The R6RS
records API provides a superset of the features provided by Guile's
"native" records, as well as those of the SRFI-9 records API; see
Records, and SRFI-9 Records, for a description of those
interfaces.

   As with SRFI-9 and Guile's native records, R6RS records are
constructed using a record-type descriptor that specifies attributes
like the record's name, its fields, and the mutability of those fields.

   R6RS records extend this framework to support single inheritance via
the specification of a "parent" type for a record type at definition
time.  Accessors and mutator procedures for the fields of a parent type
may be applied to records of a subtype of this parent.  A record type
may be “sealed”, in which case it cannot be used as the parent of
another record type.

   The inheritance mechanism for record types also informs the process
of initializing the fields of a record and its parents.  Constructor
procedures that generate new instances of a record type are obtained
from a record constructor descriptor, which encapsulates the record-type
descriptor of the record to be constructed along with a “protocol”
procedure that defines how constructors for record subtypes delegate to
the constructors of their parent types.

   A protocol is a procedure used by the record system at construction
time to bind arguments to the fields of the record being constructed.
The protocol procedure is passed a procedure N that accepts the
arguments required to construct the record's parent type; this
procedure, when invoked, will return a procedure P that accepts the
arguments required to construct a new instance of the record type itself
and returns a new instance of the record type.

   The protocol should in turn return a procedure that uses N and P to
initialize the fields of the record type and its parent type(s).  This
procedure will be the constructor returned by

   As a trivial example, consider the hypothetical record type ‘pixel’,
which encapsulates an x-y location on a screen, and ‘voxel’, which has
‘pixel’ as its parent type and stores an additional coordinate.  The
following protocol produces a constructor procedure that accepts all
three coordinates, uses the first two to initialize the fields of
‘pixel’, and binds the third to the single field of ‘voxel’.

       (lambda (n)
         (lambda (x y z)
           (let ((p (n x y)))
             (p z))))

   It may be helpful to think of protocols as "constructor factories"
that produce chains of delegating constructors glued together by the
helper procedure N.

   An R6RS record type may be declared to be “nongenerative” via the use
of a unique generated or user-supplied symbol--or “uid”--such that
subsequent record type declarations with the same uid and attributes
will return the previously-declared record-type descriptor.

   R6RS record types may also be declared to be “opaque”, in which case
the various predicates and introspection procedures defined in ‘(rnrs
records introspection)’ will behave as if records of this type are not
records at all.

   Note that while the R6RS records API shares much of its namespace
with both the SRFI-9 and native Guile records APIs, it is not currently
compatible with either.

7.6.2.9 rnrs records syntactic
..............................

The ‘(rnrs records syntactic (6))’ library exports the syntactic API for
working with R6RS records.

 -- Scheme Syntax: define-record-type name-spec record-clause ...
     Defines a new record type, introducing bindings for a record-type
     descriptor, a record constructor descriptor, a constructor
     procedure, a record predicate, and accessor and mutator procedures
     for the new record type's fields.

     NAME-SPEC must either be an identifier or must take the form
     ‘(record-name constructor-name predicate-name)’, where RECORD-NAME,
     CONSTRUCTOR-NAME, and PREDICATE-NAME are all identifiers and
     specify the names to which, respectively, the record-type
     descriptor, constructor, and predicate procedures will be bound.
     If NAME-SPEC is only an identifier, it specifies the name to which
     the generated record-type descriptor will be bound.

     Each RECORD-CLAUSE must be one of the following:

        • ‘(fields field-spec*)’, where each FIELD-SPEC specifies a
          field of the new record type and takes one of the following
          forms:
             • ‘(immutable field-name accessor-name)’, which specifies
               an immutable field with the name FIELD-NAME and binds an
               accessor procedure for it to the name given by
               ACCESSOR-NAME
             • ‘(mutable field-name accessor-name mutator-name)’, which
               specifies a mutable field with the name FIELD-NAME and
               binds accessor and mutator procedures to ACCESSOR-NAME
               and MUTATOR-NAME, respectively
             • ‘(immutable field-name)’, which specifies an immutable
               field with the name FIELD-NAME; an accessor procedure for
               it will be created and named by appending record name and
               FIELD-NAME with a hyphen separator
             • ‘(mutable field-name’), which specifies a mutable field
               with the name FIELD-NAME; an accessor procedure for it
               will be created and named as described above; a mutator
               procedure will also be created and named by appending
               ‘-set!’ to the accessor name
             • ‘field-name’, which specifies an immutable field with the
               name FIELD-NAME; an access procedure for it will be
               created and named as described above
        • ‘(parent parent-name)’, where PARENT-NAME is a symbol giving
          the name of the record type to be used as the parent of the
          new record type
        • ‘(protocol expression)’, where EXPRESSION evaluates to a
          protocol procedure which behaves as described above, and is
          used to create a record constructor descriptor for the new
          record type
        • ‘(sealed sealed?)’, where SEALED? is a boolean value that
          specifies whether or not the new record type is sealed
        • ‘(opaque opaque?)’, where OPAQUE? is a boolean value that
          specifies whether or not the new record type is opaque
        • ‘(nongenerative [uid])’, which specifies that the record type
          is nongenerative via the optional uid UID.  If UID is not
          specified, a unique uid will be generated at expansion time
        • ‘(parent-rtd parent-rtd parent-cd)’, a more explicit form of
          the ‘parent’ form above; PARENT-RTD and PARENT-CD should
          evaluate to a record-type descriptor and a record constructor
          descriptor, respectively

 -- Scheme Syntax: record-type-descriptor record-name
     Evaluates to the record-type descriptor associated with the type
     specified by RECORD-NAME.

 -- Scheme Syntax: record-constructor-descriptor record-name
     Evaluates to the record-constructor descriptor associated with the
     type specified by RECORD-NAME.

7.6.2.10 rnrs records procedural
................................

The ‘(rnrs records procedural (6))’ library exports the procedural API
for working with R6RS records.

 -- Scheme Procedure: make-record-type-descriptor name parent uid
          sealed? opaque? fields
     Returns a new record-type descriptor with the specified
     characteristics: NAME must be a symbol giving the name of the new
     record type; PARENT must be either ‘#f’ or a non-sealed record-type
     descriptor for the returned record type to extend; UID must be
     either ‘#f’, indicating that the record type is generative, or a
     symbol giving the type's nongenerative uid; SEALED? and OPAQUE?
     must be boolean values that specify the sealedness and opaqueness
     of the record type; FIELDS must be a vector of zero or more field
     specifiers of the form ‘(mutable name)’ or ‘(immutable name)’,
     where name is a symbol giving a name for the field.

     If UID is not ‘#f’, it must be a symbol

 -- Scheme Procedure: record-type-descriptor? obj
     Returns ‘#t’ if OBJ is a record-type descriptor, ‘#f’ otherwise.

 -- Scheme Procedure: make-record-constructor-descriptor rtd
          parent-constructor-descriptor protocol
     Returns a new record constructor descriptor that can be used to
     produce constructors for the record type specified by the
     record-type descriptor RTD and whose delegation and binding
     behavior are specified by the protocol procedure PROTOCOL.

     PARENT-CONSTRUCTOR-DESCRIPTOR specifies a record constructor
     descriptor for the parent type of RTD, if one exists.  If RTD
     represents a base type, then PARENT-CONSTRUCTOR-DESCRIPTOR must be
     ‘#f’.  If RTD is an extension of another type,
     PARENT-CONSTRUCTOR-DESCRIPTOR may still be ‘#f’, but protocol must
     also be ‘#f’ in this case.

 -- Scheme Procedure: record-constructor rcd
     Returns a record constructor procedure by invoking the protocol
     defined by the record-constructor descriptor RCD.

 -- Scheme Procedure: record-predicate rtd
     Returns the record predicate procedure for the record-type
     descriptor RTD.

 -- Scheme Procedure: record-accessor rtd k
     Returns the record field accessor procedure for the Kth field of
     the record-type descriptor RTD.

 -- Scheme Procedure: record-mutator rtd k
     Returns the record field mutator procedure for the Kth field of the
     record-type descriptor RTD.  An ‘&assertion’ condition will be
     raised if this field is not mutable.

7.6.2.11 rnrs records inspection
................................

The ‘(rnrs records inspection (6))’ library provides procedures useful
for accessing metadata about R6RS records.

 -- Scheme Procedure: record? obj
     Return ‘#t’ if the specified object is a non-opaque R6RS record,
     ‘#f’ otherwise.

 -- Scheme Procedure: record-rtd record
     Returns the record-type descriptor for RECORD.  An ‘&assertion’ is
     raised if RECORD is opaque.

 -- Scheme Procedure: record-type-name rtd
     Returns the name of the record-type descriptor RTD.

 -- Scheme Procedure: record-type-parent rtd
     Returns the parent of the record-type descriptor RTD, or ‘#f’ if it
     has none.

 -- Scheme Procedure: record-type-uid rtd
     Returns the uid of the record-type descriptor RTD, or ‘#f’ if it
     has none.

 -- Scheme Procedure: record-type-generative? rtd
     Returns ‘#t’ if the record-type descriptor RTD is generative, ‘#f’
     otherwise.

 -- Scheme Procedure: record-type-sealed? rtd
     Returns ‘#t’ if the record-type descriptor RTD is sealed, ‘#f’
     otherwise.

 -- Scheme Procedure: record-type-opaque? rtd
     Returns ‘#t’ if the record-type descriptor RTD is opaque, ‘#f’
     otherwise.

 -- Scheme Procedure: record-type-field-names rtd
     Returns a vector of symbols giving the names of the fields defined
     by the record-type descriptor RTD (and not any of its sub- or
     supertypes).

 -- Scheme Procedure: record-field-mutable? rtd k
     Returns ‘#t’ if the field at index K of the record-type descriptor
     RTD (and not any of its sub- or supertypes) is mutable.

7.6.2.12 rnrs exceptions
........................

The ‘(rnrs exceptions (6))’ library provides functionality related to
signaling and handling exceptional situations.  This functionality
re-exports Guile's core exception-handling primitives.  See
Exceptions, for a full discussion.  See SRFI-34, for a similar
pre-R6RS facility.  In Guile, SRFI-34, SRFI-35, and R6RS exception
handling are all built on the same core facilities, and so are
interoperable.

 -- Scheme Procedure: with-exception-handler handler thunk
     See Raising and Handling Exceptions, for more information on
     ‘with-exception-handler’.

 -- Scheme Syntax: guard (variable clause1 clause2 ...) body
     Evaluates the expression given by BODY, first creating an ad hoc
     exception handler that binds a raised exception to VARIABLE and
     then evaluates the specified CLAUSEs as if they were part of a
     ‘cond’ expression, with the value of the first matching clause
     becoming the value of the ‘guard’ expression (see
     Conditionals).  If none of the clause's test expressions
     evaluates to ‘#t’, the exception is re-raised, with the exception
     handler that was current before the evaluation of the ‘guard’ form.

     For example, the expression

          (guard (ex ((eq? ex 'foo) 'bar) ((eq? ex 'bar) 'baz))
            (raise 'bar))

     evaluates to ‘baz’.

 -- Scheme Procedure: raise obj
     Equivalent to core Guile ‘(raise-exception OBJ)’.  See Raising and Handling Exceptions.
     (Unfortunately, ‘raise’ is already
     bound to a different function in core Guile.  See Signals.)

 -- Scheme Procedure: raise-continuable obj
     Equivalent to core Guile ‘(raise-exception OBJ #:continuable? #t)’.
     See Raising and Handling Exceptions.

7.6.2.13 rnrs conditions
........................

The ‘(rnrs condition (6))’ library provides forms and procedures for
constructing new condition types, as well as a library of pre-defined
condition types that represent a variety of common exceptional
situations.  Conditions are records of a subtype of the ‘&condition’
record type, which is neither sealed nor opaque.  See R6RS Records.

   Conditions may be manipulated singly, as “simple conditions”, or when
composed with other conditions to form “compound conditions”.  Compound
conditions do not "nest"--constructing a new compound condition out of
existing compound conditions will "flatten" them into their component
simple conditions.  For example, making a new condition out of a
‘&message’ condition and a compound condition that contains an
‘&assertion’ condition and another ‘&message’ condition will produce a
compound condition that contains two ‘&message’ conditions and one
‘&assertion’ condition.

   The record type predicates and field accessors described below can
operate on either simple or compound conditions.  In the latter case,
the predicate returns ‘#t’ if the compound condition contains a
component simple condition of the appropriate type; the field accessors
return the requisite fields from the first component simple condition
found to be of the appropriate type.

   Guile's R6RS layer uses core exception types from the ‘(ice-9
exceptions)’ module as the basis for its R6RS condition system.  Guile
prefers to use the term "exception object" and "exception type" rather
than "condition" or "condition type", but that's just a naming
difference.  Guile also has different names for the types in the
condition hierarchy.  See Exception Objects, for full details.

   This library is quite similar to the SRFI-35 conditions module (see
SRFI-35).  Among other minor differences, the ‘(rnrs conditions)’
library features slightly different semantics around condition field
accessors, and comes with a larger number of pre-defined condition
types.  The two APIs are compatible; the ‘condition?’ predicate from one
API will return ‘#t’ when applied to a condition object created in the
other.  of the condition types are the same, also.

 -- Condition Type: &condition
 -- Scheme Procedure: condition? obj
     The base record type for conditions.  Known as ‘&exception’ in core
     Guile.

 -- Scheme Procedure: condition condition1 ...
 -- Scheme Procedure: simple-conditions condition
     The ‘condition’ procedure creates a new compound condition out of
     its condition arguments, flattening any specified compound
     conditions into their component simple conditions as described
     above.

     ‘simple-conditions’ returns a list of the component simple
     conditions of the compound condition ‘condition’, in the order in
     which they were specified at construction time.

 -- Scheme Procedure: condition-predicate rtd
 -- Scheme Procedure: condition-accessor rtd proc
     These procedures return condition predicate and accessor procedures
     for the specified condition record type RTD.

 -- Scheme Syntax: define-condition-type condition-type supertype
          constructor predicate field-spec ...
     Evaluates to a new record type definition for a condition type with
     the name CONDITION-TYPE that has the condition type SUPERTYPE as
     its parent.  A default constructor, which binds its arguments to
     the fields of this type and its parent types, will be bound to the
     identifier CONSTRUCTOR; a condition predicate will be bound to
     PREDICATE.  The fields of the new type, which are immutable, are
     specified by the FIELD-SPECs, each of which must be of the form:
          (field accessor)
     where FIELD gives the name of the field and ACCESSOR gives the name
     for a binding to an accessor procedure created for this field.

 -- Condition Type: &message
 -- Scheme Procedure: make-message-condition message
 -- Scheme Procedure: message-condition? obj
 -- Scheme Procedure: condition-message condition
     A type that includes a message describing the condition that
     occurred.

 -- Condition Type: &warning
 -- Scheme Procedure: make-warning
 -- Scheme Procedure: warning? obj
     A base type for representing non-fatal conditions during execution.

 -- Condition Type: &serious
 -- Scheme Procedure: make-serious-condition
 -- Scheme Procedure: serious-condition? obj
     A base type for conditions representing errors serious enough that
     cannot be ignored.  Known as ‘&error’ in core Guile.

 -- Condition Type: &error
 -- Scheme Procedure: make-error
 -- Scheme Procedure: error? obj
     A base type for conditions representing errors.  Known as
     ‘&external-error’ in core Guile.

 -- Condition Type: &violation
 -- Scheme Procedure: make-violation
 -- Scheme Procedure: violation?
     A subtype of ‘&serious’ that can be used to represent violations of
     a language or library standard.  Known as ‘&programming-error’ in
     core Guile.

 -- Condition Type: &assertion
 -- Scheme Procedure: make-assertion-violation
 -- Scheme Procedure: assertion-violation? obj
     A subtype of ‘&violation’ that indicates an invalid call to a
     procedure.  Known as ‘&assertion-failure’ in core Guile.

 -- Condition Type: &irritants
 -- Scheme Procedure: make-irritants-condition irritants
 -- Scheme Procedure: irritants-condition? obj
 -- Scheme Procedure: condition-irritants condition
     A base type used for storing information about the causes of
     another condition in a compound condition.

 -- Condition Type: &who
 -- Scheme Procedure: make-who-condition who
 -- Scheme Procedure: who-condition? obj
 -- Scheme Procedure: condition-who condition
     A base type used for storing the identity, a string or symbol, of
     the entity responsible for another condition in a compound
     condition.

 -- Condition Type: &non-continuable
 -- Scheme Procedure: make-non-continuable-violation
 -- Scheme Procedure: non-continuable-violation? obj
     A subtype of ‘&violation’ used to indicate that an exception
     handler invoked by ‘raise’ has returned locally.

 -- Condition Type: &implementation-restriction
 -- Scheme Procedure: make-implementation-restriction-violation
 -- Scheme Procedure: implementation-restriction-violation? obj
     A subtype of ‘&violation’ used to indicate a violation of an
     implementation restriction.

 -- Condition Type: &lexical
 -- Scheme Procedure: make-lexical-violation
 -- Scheme Procedure: lexical-violation? obj
     A subtype of ‘&violation’ used to indicate a syntax violation at
     the level of the datum syntax.

 -- Condition Type: &syntax
 -- Scheme Procedure: make-syntax-violation form subform
 -- Scheme Procedure: syntax-violation? obj
 -- Scheme Procedure: syntax-violation-form condition
 -- Scheme Procedure: syntax-violation-subform condition
     A subtype of ‘&violation’ that indicates a syntax violation.  The
     FORM and SUBFORM fields, which must be datum values, indicate the
     syntactic form responsible for the condition.

 -- Condition Type: &undefined
 -- Scheme Procedure: make-undefined-violation
 -- Scheme Procedure: undefined-violation? obj
     A subtype of ‘&violation’ that indicates a reference to an unbound
     identifier.  Known as ‘&undefined-variable’ in core Guile.

7.6.2.14 I/O Conditions
.......................

These condition types are exported by both the ‘(rnrs io ports (6))’ and
‘(rnrs io simple (6))’ libraries.

 -- Condition Type: &i/o
 -- Scheme Procedure: make-i/o-error
 -- Scheme Procedure: i/o-error? obj
     A condition supertype for more specific I/O errors.

 -- Condition Type: &i/o-read
 -- Scheme Procedure: make-i/o-read-error
 -- Scheme Procedure: i/o-read-error? obj
     A subtype of ‘&i/o’; represents read-related I/O errors.

 -- Condition Type: &i/o-write
 -- Scheme Procedure: make-i/o-write-error
 -- Scheme Procedure: i/o-write-error? obj
     A subtype of ‘&i/o’; represents write-related I/O errors.

 -- Condition Type: &i/o-invalid-position
 -- Scheme Procedure: make-i/o-invalid-position-error position
 -- Scheme Procedure: i/o-invalid-position-error? obj
 -- Scheme Procedure: i/o-error-position condition
     A subtype of ‘&i/o’; represents an error related to an attempt to
     set the file position to an invalid position.

 -- Condition Type: &i/o-filename
 -- Scheme Procedure: make-io-filename-error filename
 -- Scheme Procedure: i/o-filename-error? obj
 -- Scheme Procedure: i/o-error-filename condition
     A subtype of ‘&i/o’; represents an error related to an operation on
     a named file.

 -- Condition Type: &i/o-file-protection
 -- Scheme Procedure: make-i/o-file-protection-error filename
 -- Scheme Procedure: i/o-file-protection-error? obj
     A subtype of ‘&i/o-filename’; represents an error resulting from an
     attempt to access a named file for which the caller had
     insufficient permissions.

 -- Condition Type: &i/o-file-is-read-only
 -- Scheme Procedure: make-i/o-file-is-read-only-error filename
 -- Scheme Procedure: i/o-file-is-read-only-error? obj
     A subtype of ‘&i/o-file-protection’; represents an error related to
     an attempt to write to a read-only file.

 -- Condition Type: &i/o-file-already-exists
 -- Scheme Procedure: make-i/o-file-already-exists-error filename
 -- Scheme Procedure: i/o-file-already-exists-error? obj
     A subtype of ‘&i/o-filename’; represents an error related to an
     operation on an existing file that was assumed not to exist.

 -- Condition Type: &i/o-file-does-not-exist
 -- Scheme Procedure: make-i/o-file-does-not-exist-error
 -- Scheme Procedure: i/o-file-does-not-exist-error? obj
     A subtype of ‘&i/o-filename’; represents an error related to an
     operation on a non-existent file that was assumed to exist.

 -- Condition Type: &i/o-port
 -- Scheme Procedure: make-i/o-port-error port
 -- Scheme Procedure: i/o-port-error? obj
 -- Scheme Procedure: i/o-error-port condition
     A subtype of ‘&i/o’; represents an error related to an operation on
     the port PORT.

7.6.2.15 Transcoders
....................

The transcoder facilities are exported by ‘(rnrs io ports)’.

   Several different Unicode encoding schemes describe standard ways to
encode characters and strings as byte sequences and to decode those
sequences.  Within this document, a “codec” is an immutable Scheme
object that represents a Unicode or similar encoding scheme.

   An “end-of-line style” is a symbol that, if it is not ‘none’,
describes how a textual port transcodes representations of line endings.

   A “transcoder” is an immutable Scheme object that combines a codec
with an end-of-line style and a method for handling decoding errors.
Each transcoder represents some specific bidirectional (but not
necessarily lossless), possibly stateful translation between byte
sequences and Unicode characters and strings.  Every transcoder can
operate in the input direction (bytes to characters) or in the output
direction (characters to bytes).  A TRANSCODER parameter name means that
the corresponding argument must be a transcoder.

   A “binary port” is a port that supports binary I/O, does not have an
associated transcoder and does not support textual I/O. A “textual port”
is a port that supports textual I/O, and does not support binary I/O. A
textual port may or may not have an associated transcoder.

 -- Scheme Procedure: latin-1-codec
 -- Scheme Procedure: utf-8-codec
 -- Scheme Procedure: utf-16-codec

     These are predefined codecs for the ISO 8859-1, UTF-8, and UTF-16
     encoding schemes.

     A call to any of these procedures returns a value that is equal in
     the sense of ‘eqv?’ to the result of any other call to the same
     procedure.

 -- Scheme Syntax: eol-style EOL-STYLE-SYMBOL

     EOL-STYLE-SYMBOL should be a symbol whose name is one of ‘lf’,
     ‘cr’, ‘crlf’, ‘nel’, ‘crnel’, ‘ls’, and ‘none’.

     The form evaluates to the corresponding symbol.  If the name of
     EOL-STYLE-SYMBOL is not one of these symbols, the effect and result
     are implementation-dependent; in particular, the result may be an
     eol-style symbol acceptable as an EOL-STYLE argument to
     ‘make-transcoder’.  Otherwise, an exception is raised.

     All eol-style symbols except ‘none’ describe a specific line-ending
     encoding:

     ‘lf’
          linefeed
     ‘cr’
          carriage return
     ‘crlf’
          carriage return, linefeed
     ‘nel’
          next line
     ‘crnel’
          carriage return, next line
     ‘ls’
          line separator

     For a textual port with a transcoder, and whose transcoder has an
     eol-style symbol ‘none’, no conversion occurs.  For a textual input
     port, any eol-style symbol other than ‘none’ means that all of the
     above line-ending encodings are recognized and are translated into
     a single linefeed.  For a textual output port, ‘none’ and ‘lf’ are
     equivalent.  Linefeed characters are encoded according to the
     specified eol-style symbol, and all other characters that
     participate in possible line endings are encoded as is.

          Note: Only the name of EOL-STYLE-SYMBOL is significant.

 -- Scheme Procedure: native-eol-style
     Returns the default end-of-line style of the underlying platform,
     e.g., ‘lf’ on Unix and ‘crlf’ on Windows.

 -- Condition Type: &i/o-decoding
 -- Scheme Procedure: make-i/o-decoding-error port
 -- Scheme Procedure: i/o-decoding-error? obj
     This condition type could be defined by

          (define-condition-type &i/o-decoding &i/o-port
            make-i/o-decoding-error i/o-decoding-error?)

     An exception with this type is raised when one of the operations
     for textual input from a port encounters a sequence of bytes that
     cannot be translated into a character or string by the input
     direction of the port's transcoder.

     When such an exception is raised, the port's position is past the
     invalid encoding.

 -- Condition Type: &i/o-encoding
 -- Scheme Procedure: make-i/o-encoding-error port char
 -- Scheme Procedure: i/o-encoding-error? obj
 -- Scheme Procedure: i/o-encoding-error-char condition
     This condition type could be defined by

          (define-condition-type &i/o-encoding &i/o-port
            make-i/o-encoding-error i/o-encoding-error?
            (char i/o-encoding-error-char))

     An exception with this type is raised when one of the operations
     for textual output to a port encounters a character that cannot be
     translated into bytes by the output direction of the port's
     transcoder.  CHAR is the character that could not be encoded.

 -- Scheme Syntax: error-handling-mode ERROR-HANDLING-MODE-SYMBOL
     ERROR-HANDLING-MODE-SYMBOL should be a symbol whose name is one of
     ‘ignore’, ‘raise’, and ‘replace’.  The form evaluates to the
     corresponding symbol.  If ERROR-HANDLING-MODE-SYMBOL is not one of
     these identifiers, effect and result are implementation-dependent:
     The result may be an error-handling-mode symbol acceptable as a
     HANDLING-MODE argument to ‘make-transcoder’.  If it is not
     acceptable as a HANDLING-MODE argument to ‘make-transcoder’, an
     exception is raised.

          Note: Only the name of ERROR-HANDLING-MODE-SYMBOL is
          significant.

     The error-handling mode of a transcoder specifies the behavior of
     textual I/O operations in the presence of encoding or decoding
     errors.

     If a textual input operation encounters an invalid or incomplete
     character encoding, and the error-handling mode is ‘ignore’, an
     appropriate number of bytes of the invalid encoding are ignored and
     decoding continues with the following bytes.

     If the error-handling mode is ‘replace’, the replacement character
     U+FFFD is injected into the data stream, an appropriate number of
     bytes are ignored, and decoding continues with the following bytes.

     If the error-handling mode is ‘raise’, an exception with condition
     type ‘&i/o-decoding’ is raised.

     If a textual output operation encounters a character it cannot
     encode, and the error-handling mode is ‘ignore’, the character is
     ignored and encoding continues with the next character.  If the
     error-handling mode is ‘replace’, a codec-specific replacement
     character is emitted by the transcoder, and encoding continues with
     the next character.  The replacement character is U+FFFD for
     transcoders whose codec is one of the Unicode encodings, but is the
     ‘?’ character for the Latin-1 encoding.  If the error-handling mode
     is ‘raise’, an exception with condition type ‘&i/o-encoding’ is
     raised.

 -- Scheme Procedure: make-transcoder codec
 -- Scheme Procedure: make-transcoder codec eol-style
 -- Scheme Procedure: make-transcoder codec eol-style handling-mode
     CODEC must be a codec; EOL-STYLE, if present, an eol-style symbol;
     and HANDLING-MODE, if present, an error-handling-mode symbol.

     EOL-STYLE may be omitted, in which case it defaults to the native
     end-of-line style of the underlying platform.  HANDLING-MODE may be
     omitted, in which case it defaults to ‘replace’.  The result is a
     transcoder with the behavior specified by its arguments.

 -- Scheme procedure: native-transcoder
     Returns an implementation-dependent transcoder that represents a
     possibly locale-dependent "native" transcoding.

 -- Scheme Procedure: transcoder-codec transcoder
 -- Scheme Procedure: transcoder-eol-style transcoder
 -- Scheme Procedure: transcoder-error-handling-mode transcoder
     These are accessors for transcoder objects; when applied to a
     transcoder returned by ‘make-transcoder’, they return the CODEC,
     EOL-STYLE, and HANDLING-MODE arguments, respectively.

 -- Scheme Procedure: bytevector->string bytevector transcoder
     Returns the string that results from transcoding the BYTEVECTOR
     according to the input direction of the transcoder.

 -- Scheme Procedure: string->bytevector string transcoder
     Returns the bytevector that results from transcoding the STRING
     according to the output direction of the transcoder.

7.6.2.16 rnrs io ports
......................

Guile's binary and textual port interface was heavily inspired by R6RS,
so many R6RS port interfaces are documented elsewhere.  Note that R6RS
ports are not disjoint from Guile's native ports, so Guile-specific
procedures will work on ports created using the R6RS API, and vice
versa.  Also note that in Guile, all ports are both textual and binary.
See Input and Output, for more on Guile's core port API. The R6RS
ports module wraps Guile's I/O routines in a helper that will translate
native Guile exceptions to R6RS conditions; see R6RS I/O Conditions,
for more.  See R6RS File Ports, for documentation on the R6RS file
port interface.

   _Note_: The implementation of this R6RS API is not complete yet.

 -- Scheme Procedure: eof-object? obj
     See Binary I/O, for documentation.

 -- Scheme Procedure: eof-object
     Return the end-of-file (EOF) object.

          (eof-object? (eof-object))
          ⇒ #t

 -- Scheme Procedure: port? obj
 -- Scheme Procedure: input-port? obj
 -- Scheme Procedure: output-port? obj
 -- Scheme Procedure: call-with-port port proc
     See Ports, for documentation.

 -- Scheme Procedure: port-transcoder port
     Return a transcoder associated with the encoding of PORT.  See
     Encoding, and R6RS Transcoders.

 -- Scheme Procedure: binary-port? port
     Return ‘#t’ if PORT appears to be a binary port, else return ‘#f’.
     Note that Guile does not currently distinguish between binary and
     textual ports, so this predicate is not a reliable indicator of
     whether the port was created as a binary port.  Currently, it
     returns ‘#t’ if and only if the port encoding is "ISO-8859-1",
     because Guile uses this encoding when creating a binary port.
     See Encoding, for more details.

 -- Scheme Procedure: textual-port? port
     Return ‘#t’ if PORT appears to be a textual port, else return ‘#f’.
     Note that Guile does not currently distinguish between binary and
     textual ports, so this predicate is not a reliable indicator of
     whether the port was created as a textual port.  Currently, it
     always returns ‘#t’, because all ports can be used for textual I/O
     in Guile.  See Encoding, for more details.

 -- Scheme Procedure: transcoded-port binary-port transcoder
     The ‘transcoded-port’ procedure returns a new textual port with the
     specified TRANSCODER.  Otherwise the new textual port's state is
     largely the same as that of BINARY-PORT.  If BINARY-PORT is an
     input port, the new textual port will be an input port and will
     transcode the bytes that have not yet been read from BINARY-PORT.
     If BINARY-PORT is an output port, the new textual port will be an
     output port and will transcode output characters into bytes that
     are written to the byte sink represented by BINARY-PORT.

     As a side effect, however, ‘transcoded-port’ closes BINARY-PORT in
     a special way that allows the new textual port to continue to use
     the byte source or sink represented by BINARY-PORT, even though
     BINARY-PORT itself is closed and cannot be used by the input and
     output operations described in this chapter.

 -- Scheme Procedure: port-position port
     Equivalent to ‘(seek PORT 0 SEEK_CUR)’.  See Random Access.

 -- Scheme Procedure: port-has-port-position? port
     Return ‘#t’ is PORT supports ‘port-position’.

 -- Scheme Procedure: set-port-position! port offset
     Equivalent to ‘(seek PORT OFFSET SEEK_SET)’.  See Random Access.

 -- Scheme Procedure: port-has-set-port-position!? port
     Return ‘#t’ is PORT supports ‘set-port-position!’.

 -- Scheme Procedure: port-eof? input-port
     Equivalent to ‘(eof-object? (lookahead-u8 INPUT-PORT))’.

 -- Scheme Procedure: standard-input-port
 -- Scheme Procedure: standard-output-port
 -- Scheme Procedure: standard-error-port
     Returns a fresh binary input port connected to standard input, or a
     binary output port connected to the standard output or standard
     error, respectively.  Whether the port supports the ‘port-position’
     and ‘set-port-position!’ operations is implementation-dependent.

 -- Scheme Procedure: current-input-port
 -- Scheme Procedure: current-output-port
 -- Scheme Procedure: current-error-port
     See Default Ports.

 -- Scheme Procedure: open-bytevector-input-port bv [transcoder]
 -- Scheme Procedure: open-bytevector-output-port [transcoder]
     See Bytevector Ports.

 -- Scheme Procedure: make-custom-binary-input-port id read!
          get-position set-position! close
 -- Scheme Procedure: make-custom-binary-output-port id write!
          get-position set-position! close
 -- Scheme Procedure: make-custom-binary-input/output-port id read!
          write! get-position set-position! close
     Custom Ports.

 -- Scheme Procedure: make-custom-textual-input-port id read!
          get-position set-position! close
 -- Scheme Procedure: make-custom-textual-output-port id write!
          get-position set-position! close
 -- Scheme Procedure: make-custom-textual-input/output-port id read!
          write! get-position set-position! close
     Custom Ports.

 -- Scheme Procedure: get-u8 port
 -- Scheme Procedure: lookahead-u8 port
 -- Scheme Procedure: get-bytevector-n port count
 -- Scheme Procedure: get-bytevector-n! port bv start count
 -- Scheme Procedure: get-bytevector-some port
 -- Scheme Procedure: get-bytevector-all port
 -- Scheme Procedure: put-u8 port octet
 -- Scheme Procedure: put-bytevector port bv [start [count]]
     See Binary I/O.

 -- Scheme Procedure: get-char textual-input-port
 -- Scheme Procedure: lookahead-char textual-input-port
 -- Scheme Procedure: get-string-n textual-input-port count
 -- Scheme Procedure: get-string-n! textual-input-port string start
          count
 -- Scheme Procedure: get-string-all textual-input-port
 -- Scheme Procedure: get-line textual-input-port
 -- Scheme Procedure: put-char port char
 -- Scheme Procedure: put-string port string [start [count]]
     See Textual I/O.

 -- Scheme Procedure: get-datum textual-input-port count
     Reads an external representation from TEXTUAL-INPUT-PORT and
     returns the datum it represents.  The ‘get-datum’ procedure returns
     the next datum that can be parsed from the given
     TEXTUAL-INPUT-PORT, updating TEXTUAL-INPUT-PORT to point exactly
     past the end of the external representation of the object.

     Any _interlexeme space_ (comment or whitespace, see Scheme Syntax)
     in the input is first skipped.  If an end of file occurs
     after the interlexeme space, the end-of-file object is returned.

     If a character inconsistent with an external representation is
     encountered in the input, an exception with condition types
     ‘&lexical’ and ‘&i/o-read’ is raised.  Also, if the end of file is
     encountered after the beginning of an external representation, but
     the external representation is incomplete and therefore cannot be
     parsed, an exception with condition types ‘&lexical’ and
     ‘&i/o-read’ is raised.

 -- Scheme Procedure: put-datum textual-output-port datum
     DATUM should be a datum value.  The ‘put-datum’ procedure writes an
     external representation of DATUM to TEXTUAL-OUTPUT-PORT.  The
     specific external representation is implementation-dependent.
     However, whenever possible, an implementation should produce a
     representation for which ‘get-datum’, when reading the
     representation, will return an object equal (in the sense of
     ‘equal?’) to DATUM.

          Note: Not all datums may allow producing an external
          representation for which ‘get-datum’ will produce an object
          that is equal to the original.  Specifically, NaNs contained
          in DATUM may make this impossible.

          Note: The ‘put-datum’ procedure merely writes the external
          representation, but no trailing delimiter.  If ‘put-datum’ is
          used to write several subsequent external representations to
          an output port, care should be taken to delimit them properly
          so they can be read back in by subsequent calls to
          ‘get-datum’.

 -- Scheme Procedure: flush-output-port port
     See Buffering, for documentation on ‘force-output’.

7.6.2.17 R6RS File Ports
........................

The facilities described in this section are exported by the ‘(rnrs io
ports)’ module.

 -- Scheme Syntax: buffer-mode BUFFER-MODE-SYMBOL
     BUFFER-MODE-SYMBOL must be a symbol whose name is one of ‘none’,
     ‘line’, and ‘block’.  The result is the corresponding symbol, and
     specifies the associated buffer mode.  See Buffering, for a
     discussion of these different buffer modes.  To control the amount
     of buffering, use ‘setvbuf’ instead.  Note that only the name of
     BUFFER-MODE-SYMBOL is significant.

     See Buffering, for a discussion of port buffering.

 -- Scheme Procedure: buffer-mode? obj
     Returns ‘#t’ if the argument is a valid buffer-mode symbol, and
     returns ‘#f’ otherwise.

   When opening a file, the various procedures accept a ‘file-options’
object that encapsulates flags to specify how the file is to be opened.
A ‘file-options’ object is an enum-set (see rnrs enums) over the
symbols constituting valid file options.

   A FILE-OPTIONS parameter name means that the corresponding argument
must be a file-options object.

 -- Scheme Syntax: file-options FILE-OPTIONS-SYMBOL ...

     Each FILE-OPTIONS-SYMBOL must be a symbol.

     The ‘file-options’ syntax returns a file-options object that
     encapsulates the specified options.

     When supplied to an operation that opens a file for output, the
     file-options object returned by ‘(file-options)’ specifies that the
     file is created if it does not exist and an exception with
     condition type ‘&i/o-file-already-exists’ is raised if it does
     exist.  The following standard options can be included to modify
     the default behavior.

     ‘no-create’
          If the file does not already exist, it is not created;
          instead, an exception with condition type
          ‘&i/o-file-does-not-exist’ is raised.  If the file already
          exists, the exception with condition type
          ‘&i/o-file-already-exists’ is not raised and the file is
          truncated to zero length.
     ‘no-fail’
          If the file already exists, the exception with condition type
          ‘&i/o-file-already-exists’ is not raised, even if ‘no-create’
          is not included, and the file is truncated to zero length.
     ‘no-truncate’
          If the file already exists and the exception with condition
          type ‘&i/o-file-already-exists’ has been inhibited by
          inclusion of ‘no-create’ or ‘no-fail’, the file is not
          truncated, but the port's current position is still set to the
          beginning of the file.

     These options have no effect when a file is opened only for input.
     Symbols other than those listed above may be used as
     FILE-OPTIONS-SYMBOLs; they have implementation-specific meaning, if
     any.

          Note: Only the name of FILE-OPTIONS-SYMBOL is significant.

 -- Scheme Procedure: open-file-input-port filename
 -- Scheme Procedure: open-file-input-port filename file-options
 -- Scheme Procedure: open-file-input-port filename file-options
          buffer-mode
 -- Scheme Procedure: open-file-input-port filename file-options
          buffer-mode maybe-transcoder
     MAYBE-TRANSCODER must be either a transcoder or ‘#f’.

     The ‘open-file-input-port’ procedure returns an input port for the
     named file.  The FILE-OPTIONS and MAYBE-TRANSCODER arguments are
     optional.

     The FILE-OPTIONS argument, which may determine various aspects of
     the returned port, defaults to the value of ‘(file-options)’.

     The BUFFER-MODE argument, if supplied, must be one of the symbols
     that name a buffer mode.  The BUFFER-MODE argument defaults to
     ‘block’.

     If MAYBE-TRANSCODER is a transcoder, it becomes the transcoder
     associated with the returned port.

     If MAYBE-TRANSCODER is ‘#f’ or absent, the port will be a binary
     port and will support the ‘port-position’ and ‘set-port-position!’
     operations.  Otherwise the port will be a textual port, and whether
     it supports the ‘port-position’ and ‘set-port-position!’ operations
     is implementation-dependent (and possibly transcoder-dependent).

 -- Scheme Procedure: open-file-output-port filename
 -- Scheme Procedure: open-file-output-port filename file-options
 -- Scheme Procedure: open-file-output-port filename file-options
          buffer-mode
 -- Scheme Procedure: open-file-output-port filename file-options
          buffer-mode maybe-transcoder
     MAYBE-TRANSCODER must be either a transcoder or ‘#f’.

     The ‘open-file-output-port’ procedure returns an output port for
     the named file.

     The FILE-OPTIONS argument, which may determine various aspects of
     the returned port, defaults to the value of ‘(file-options)’.

     The BUFFER-MODE argument, if supplied, must be one of the symbols
     that name a buffer mode.  The BUFFER-MODE argument defaults to
     ‘block’.

     If MAYBE-TRANSCODER is a transcoder, it becomes the transcoder
     associated with the port.

     If MAYBE-TRANSCODER is ‘#f’ or absent, the port will be a binary
     port and will support the ‘port-position’ and ‘set-port-position!’
     operations.  Otherwise the port will be a textual port, and whether
     it supports the ‘port-position’ and ‘set-port-position!’ operations
     is implementation-dependent (and possibly transcoder-dependent).

7.6.2.18 rnrs io simple
.......................

The ‘(rnrs io simple (6))’ library provides convenience functions for
performing textual I/O on ports.  This library also exports all of the
condition types and associated procedures described in (see R6RS I/O Conditions).
In the context of this section, when stating that a
procedure behaves "identically" to the corresponding procedure in
Guile's core library, this is modulo the behavior wrt.  conditions: such
procedures raise the appropriate R6RS conditions in case of error, but
otherwise behave identically.

     Note: There are still known issues regarding condition-correctness;
     some errors may still be thrown as native Guile exceptions instead
     of the appropriate R6RS conditions.

 -- Scheme Procedure: eof-object
 -- Scheme Procedure: eof-object? obj
     These procedures are identical to the ones provided by the ‘(rnrs
     io ports (6))’ library.  See rnrs io ports, for documentation.

 -- Scheme Procedure: input-port? obj
 -- Scheme Procedure: output-port? obj
     These procedures are identical to the ones provided by Guile's core
     library.  See Ports, for documentation.

 -- Scheme Procedure: call-with-input-file filename proc
 -- Scheme Procedure: call-with-output-file filename proc
 -- Scheme Procedure: open-input-file filename
 -- Scheme Procedure: open-output-file filename
 -- Scheme Procedure: with-input-from-file filename thunk
 -- Scheme Procedure: with-output-to-file filename thunk
     These procedures are identical to the ones provided by Guile's core
     library.  See File Ports, for documentation.

 -- Scheme Procedure: close-input-port input-port
 -- Scheme Procedure: close-output-port output-port
     Closes the given INPUT-PORT or OUTPUT-PORT.  These are legacy
     interfaces; just use ‘close-port’.

 -- Scheme Procedure: peek-char
 -- Scheme Procedure: peek-char textual-input-port
 -- Scheme Procedure: read-char
 -- Scheme Procedure: read-char textual-input-port
     These procedures are identical to the ones provided by Guile's core
     library.  See Venerable Port Interfaces, for documentation.

 -- Scheme Procedure: read
 -- Scheme Procedure: read textual-input-port
     This procedure is identical to the one provided by Guile's core
     library.  See Scheme Read, for documentation.

 -- Scheme Procedure: display obj
 -- Scheme Procedure: display obj textual-output-port
 -- Scheme Procedure: newline
 -- Scheme Procedure: newline textual-output-port
 -- Scheme Procedure: write obj
 -- Scheme Procedure: write obj textual-output-port
 -- Scheme Procedure: write-char char
 -- Scheme Procedure: write-char char textual-output-port
     These procedures are identical to the ones provided by Guile's core
     library.  See Venerable Port Interfaces, and Scheme Write,
     for documentation.

7.6.2.19 rnrs files
...................

The ‘(rnrs files (6))’ library provides the ‘file-exists?’ and
‘delete-file’ procedures, which test for the existence of a file and
allow the deletion of files from the file system, respectively.

   These procedures are identical to the ones provided by Guile's core
library.  See File System, for documentation.

7.6.2.20 rnrs programs
......................

The ‘(rnrs programs (6))’ library provides procedures for process
management and introspection.

 -- Scheme Procedure: command-line
     This procedure is identical to the one provided by Guile's core
     library.  See Runtime Environment, for documentation.

 -- Scheme Procedure: exit [status]
     This procedure is identical to the one provided by Guile's core
     library.  See Processes, for documentation.

7.6.2.21 rnrs arithmetic fixnums
................................

The ‘(rnrs arithmetic fixnums (6))’ library provides procedures for
performing arithmetic operations on an implementation-dependent range of
exact integer values, which R6RS refers to as “fixnums”.  In Guile, the
size of a fixnum is determined by the size of the ‘SCM’ type; a single
SCM struct is guaranteed to be able to hold an entire fixnum, making
fixnum computations particularly efficient--(see The SCM Type).  On
32-bit systems, the most negative and most positive fixnum values are,
respectively, -536870912 and 536870911.

   Unless otherwise specified, all of the procedures below take fixnums
as arguments, and will raise an ‘&assertion’ condition if passed a
non-fixnum argument or an ‘&implementation-restriction’ condition if
their result is not itself a fixnum.

 -- Scheme Procedure: fixnum? obj
     Returns ‘#t’ if OBJ is a fixnum, ‘#f’ otherwise.

 -- Scheme Procedure: fixnum-width
 -- Scheme Procedure: least-fixnum
 -- Scheme Procedure: greatest-fixnum
     These procedures return, respectively, the maximum number of bits
     necessary to represent a fixnum value in Guile, the minimum fixnum
     value, and the maximum fixnum value.

 -- Scheme Procedure: fx=? fx1 fx2 fx3 ...
 -- Scheme Procedure: fx>? fx1 fx2 fx3 ...
 -- Scheme Procedure: fx<? fx1 fx2 fx3 ...
 -- Scheme Procedure: fx>=? fx1 fx2 fx3 ...
 -- Scheme Procedure: fx<=? fx1 fx2 fx3 ...
     These procedures return ‘#t’ if their fixnum arguments are
     (respectively): equal, monotonically increasing, monotonically
     decreasing, monotonically nondecreasing, or monotonically
     nonincreasing; ‘#f’ otherwise.

 -- Scheme Procedure: fxzero? fx
 -- Scheme Procedure: fxpositive? fx
 -- Scheme Procedure: fxnegative? fx
 -- Scheme Procedure: fxodd? fx
 -- Scheme Procedure: fxeven? fx
     These numerical predicates return ‘#t’ if FX is, respectively,
     zero, greater than zero, less than zero, odd, or even; ‘#f’
     otherwise.

 -- Scheme Procedure: fxmax fx1 fx2 ...
 -- Scheme Procedure: fxmin fx1 fx2 ...
     These procedures return the maximum or minimum of their arguments.

 -- Scheme Procedure: fx+ fx1 fx2
 -- Scheme Procedure: fx* fx1 fx2
     These procedures return the sum or product of their arguments.

 -- Scheme Procedure: fx- fx1 fx2
 -- Scheme Procedure: fx- fx
     Returns the difference of FX1 and FX2, or the negation of FX, if
     called with a single argument.

     An ‘&assertion’ condition is raised if the result is not itself a
     fixnum.

 -- Scheme Procedure: fxdiv-and-mod fx1 fx2
 -- Scheme Procedure: fxdiv fx1 fx2
 -- Scheme Procedure: fxmod fx1 fx2
 -- Scheme Procedure: fxdiv0-and-mod0 fx1 fx2
 -- Scheme Procedure: fxdiv0 fx1 fx2
 -- Scheme Procedure: fxmod0 fx1 fx2
     These procedures implement number-theoretic division on fixnums;
     see (rnrs base), for a description of their semantics.

 -- Scheme Procedure: fx+/carry fx1 fx2 fx3
     Returns the two fixnum results of the following computation:
          (let* ((s (+ fx1 fx2 fx3))
                 (s0 (mod0 s (expt 2 (fixnum-width))))
                 (s1 (div0 s (expt 2 (fixnum-width)))))
            (values s0 s1))

 -- Scheme Procedure: fx-/carry fx1 fx2 fx3
     Returns the two fixnum results of the following computation:
          (let* ((d (- fx1 fx2 fx3))
                 (d0 (mod0 d (expt 2 (fixnum-width))))
                 (d1 (div0 d (expt 2 (fixnum-width)))))
            (values d0 d1))

 -- Scheme Procedure: fx*/carry fx1 fx2 fx3
          Returns the two fixnum results of the following computation:
          (let* ((s (+ (* fx1 fx2) fx3))
                 (s0 (mod0 s (expt 2 (fixnum-width))))
                 (s1 (div0 s (expt 2 (fixnum-width)))))
            (values s0 s1))

 -- Scheme Procedure: fxnot fx
 -- Scheme Procedure: fxand fx1 ...
 -- Scheme Procedure: fxior fx1 ...
 -- Scheme Procedure: fxxor fx1 ...
     These procedures are identical to the ‘lognot’, ‘logand’, ‘logior’,
     and ‘logxor’ procedures provided by Guile's core library.  See
     Bitwise Operations, for documentation.

 -- Scheme Procedure: fxif fx1 fx2 fx3
     Returns the bitwise "if" of its fixnum arguments.  The bit at
     position ‘i’ in the return value will be the ‘i’th bit from FX2 if
     the ‘i’th bit of FX1 is 1, the ‘i’th bit from FX3.

 -- Scheme Procedure: fxbit-count fx
     Returns the number of 1 bits in the two's complement representation
     of FX.

 -- Scheme Procedure: fxlength fx
     Returns the number of bits necessary to represent FX.

 -- Scheme Procedure: fxfirst-bit-set fx
     Returns the index of the least significant 1 bit in the two's
     complement representation of FX.

 -- Scheme Procedure: fxbit-set? fx1 fx2
     Returns ‘#t’ if the FX2th bit in the two's complement
     representation of FX1 is 1, ‘#f’ otherwise.

 -- Scheme Procedure: fxcopy-bit fx1 fx2 fx3
     Returns the result of setting the FX2th bit of FX1 to the FX2th bit
     of FX3.

 -- Scheme Procedure: fxbit-field fx1 fx2 fx3
     Returns the integer representation of the contiguous sequence of
     bits in FX1 that starts at position FX2 (inclusive) and ends at
     position FX3 (exclusive).

 -- Scheme Procedure: fxcopy-bit-field fx1 fx2 fx3 fx4
     Returns the result of replacing the bit field in FX1 with start and
     end positions FX2 and FX3 with the corresponding bit field from
     FX4.

 -- Scheme Procedure: fxarithmetic-shift fx1 fx2
 -- Scheme Procedure: fxarithmetic-shift-left fx1 fx2
 -- Scheme Procedure: fxarithmetic-shift-right fx1 fx2
     Returns the result of shifting the bits of FX1 right or left by the
     FX2 positions.  ‘fxarithmetic-shift’ is identical to
     ‘fxarithmetic-shift-left’.

 -- Scheme Procedure: fxrotate-bit-field fx1 fx2 fx3 fx4
     Returns the result of cyclically permuting the bit field in FX1
     with start and end positions FX2 and FX3 by FX4 bits in the
     direction of more significant bits.

 -- Scheme Procedure: fxreverse-bit-field fx1 fx2 fx3
     Returns the result of reversing the order of the bits of FX1
     between position FX2 (inclusive) and position FX3 (exclusive).

7.6.2.22 rnrs arithmetic flonums
................................

The ‘(rnrs arithmetic flonums (6))’ library provides procedures for
performing arithmetic operations on inexact representations of real
numbers, which R6RS refers to as “flonums”.

   Unless otherwise specified, all of the procedures below take flonums
as arguments, and will raise an ‘&assertion’ condition if passed a
non-flonum argument.

 -- Scheme Procedure: flonum? obj
     Returns ‘#t’ if OBJ is a flonum, ‘#f’ otherwise.

 -- Scheme Procedure: real->flonum x
     Returns the flonum that is numerically closest to the real number
     X.

 -- Scheme Procedure: fl=? fl1 fl2 fl3 ...
 -- Scheme Procedure: fl<? fl1 fl2 fl3 ...
 -- Scheme Procedure: fl<=? fl1 fl2 fl3 ...
 -- Scheme Procedure: fl>? fl1 fl2 fl3 ...
 -- Scheme Procedure: fl>=? fl1 fl2 fl3 ...
     These procedures return ‘#t’ if their flonum arguments are
     (respectively): equal, monotonically increasing, monotonically
     decreasing, monotonically nondecreasing, or monotonically
     nonincreasing; ‘#f’ otherwise.

 -- Scheme Procedure: flinteger? fl
 -- Scheme Procedure: flzero? fl
 -- Scheme Procedure: flpositive? fl
 -- Scheme Procedure: flnegative? fl
 -- Scheme Procedure: flodd? fl
 -- Scheme Procedure: fleven? fl
     These numerical predicates return ‘#t’ if FL is, respectively, an
     integer, zero, greater than zero, less than zero, odd, even, ‘#f’
     otherwise.  In the case of ‘flodd?’ and ‘fleven?’, FL must be an
     integer-valued flonum.

 -- Scheme Procedure: flfinite? fl
 -- Scheme Procedure: flinfinite? fl
 -- Scheme Procedure: flnan? fl
     These numerical predicates return ‘#t’ if FL is, respectively, not
     infinite, infinite, or a ‘NaN’ value.

 -- Scheme Procedure: flmax fl1 fl2 ...
 -- Scheme Procedure: flmin fl1 fl2 ...
     These procedures return the maximum or minimum of their arguments.

 -- Scheme Procedure: fl+ fl1 ...
 -- Scheme Procedure: fl* fl ...
     These procedures return the sum or product of their arguments.

 -- Scheme Procedure: fl- fl1 fl2 ...
 -- Scheme Procedure: fl- fl
 -- Scheme Procedure: fl/ fl1 fl2 ...
 -- Scheme Procedure: fl/ fl
     These procedures return, respectively, the difference or quotient
     of their arguments when called with two arguments; when called with
     a single argument, they return the additive or multiplicative
     inverse of FL.

 -- Scheme Procedure: flabs fl
     Returns the absolute value of FL.

 -- Scheme Procedure: fldiv-and-mod fl1 fl2
 -- Scheme Procedure: fldiv fl1 fl2
 -- Scheme Procedure: fldmod fl1 fl2
 -- Scheme Procedure: fldiv0-and-mod0 fl1 fl2
 -- Scheme Procedure: fldiv0 fl1 fl2
 -- Scheme Procedure: flmod0 fl1 fl2
     These procedures implement number-theoretic division on flonums;
     see (rnrs base), for a description for their semantics.

 -- Scheme Procedure: flnumerator fl
 -- Scheme Procedure: fldenominator fl
     These procedures return the numerator or denominator of FL as a
     flonum.

 -- Scheme Procedure: flfloor fl1
 -- Scheme Procedure: flceiling fl
 -- Scheme Procedure: fltruncate fl
 -- Scheme Procedure: flround fl
     These procedures are identical to the ‘floor’, ‘ceiling’,
     ‘truncate’, and ‘round’ procedures provided by Guile's core
     library.  See Arithmetic, for documentation.

 -- Scheme Procedure: flexp fl
 -- Scheme Procedure: fllog fl
 -- Scheme Procedure: fllog fl1 fl2
 -- Scheme Procedure: flsin fl
 -- Scheme Procedure: flcos fl
 -- Scheme Procedure: fltan fl
 -- Scheme Procedure: flasin fl
 -- Scheme Procedure: flacos fl
 -- Scheme Procedure: flatan fl
 -- Scheme Procedure: flatan fl1 fl2
     These procedures, which compute the usual transcendental functions,
     are the flonum variants of the procedures provided by the R6RS base
     library (see (rnrs base)).

 -- Scheme Procedure: flsqrt fl
     Returns the square root of FL.  If FL is ‘-0.0’, -0.0 is returned;
     for other negative values, a ‘NaN’ value is returned.

 -- Scheme Procedure: flexpt fl1 fl2
     Returns the value of FL1 raised to the power of FL2.

   The following condition types are provided to allow Scheme
implementations that do not support infinities or ‘NaN’ values to
indicate that a computation resulted in such a value.  Guile supports
both of these, so these conditions will never be raised by Guile's
standard libraries implementation.

 -- Condition Type: &no-infinities
 -- Scheme Procedure: make-no-infinities-violation obj
 -- Scheme Procedure: no-infinities-violation?
     A condition type indicating that a computation resulted in an
     infinite value on a Scheme implementation incapable of representing
     infinities.

 -- Condition Type: &no-nans
 -- Scheme Procedure: make-no-nans-violation obj
 -- Scheme Procedure: no-nans-violation? obj
     A condition type indicating that a computation resulted in a ‘NaN’
     value on a Scheme implementation incapable of representing ‘NaN’s.

 -- Scheme Procedure: fixnum->flonum fx
     Returns the flonum that is numerically closest to the fixnum FX.

7.6.2.23 rnrs arithmetic bitwise
................................

The ‘(rnrs arithmetic bitwise (6))’ library provides procedures for
performing bitwise arithmetic operations on the two's complement
representations of fixnums.

   This library and the procedures it exports share functionality with
SRFI-60, which provides support for bitwise manipulation of integers
(see SRFI-60).

 -- Scheme Procedure: bitwise-not ei
 -- Scheme Procedure: bitwise-and ei1 ...
 -- Scheme Procedure: bitwise-ior ei1 ...
 -- Scheme Procedure: bitwise-xor ei1 ...
     These procedures are identical to the ‘lognot’, ‘logand’, ‘logior’,
     and ‘logxor’ procedures provided by Guile's core library.  See
     Bitwise Operations, for documentation.

 -- Scheme Procedure: bitwise-if ei1 ei2 ei3
     Returns the bitwise "if" of its arguments.  The bit at position ‘i’
     in the return value will be the ‘i’th bit from EI2 if the ‘i’th bit
     of EI1 is 1, the ‘i’th bit from EI3.

 -- Scheme Procedure: bitwise-bit-count ei
     Returns the number of 1 bits in the two's complement representation
     of EI.

 -- Scheme Procedure: bitwise-length ei
     Returns the number of bits necessary to represent EI.

 -- Scheme Procedure: bitwise-first-bit-set ei
     Returns the index of the least significant 1 bit in the two's
     complement representation of EI.

 -- Scheme Procedure: bitwise-bit-set? ei1 ei2
     Returns ‘#t’ if the EI2th bit in the two's complement
     representation of EI1 is 1, ‘#f’ otherwise.

 -- Scheme Procedure: bitwise-copy-bit ei1 ei2 ei3
     Returns the result of setting the EI2th bit of EI1 to the EI2th bit
     of EI3.

 -- Scheme Procedure: bitwise-bit-field ei1 ei2 ei3
     Returns the integer representation of the contiguous sequence of
     bits in EI1 that starts at position EI2 (inclusive) and ends at
     position EI3 (exclusive).

 -- Scheme Procedure: bitwise-copy-bit-field ei1 ei2 ei3 ei4
     Returns the result of replacing the bit field in EI1 with start and
     end positions EI2 and EI3 with the corresponding bit field from
     EI4.

 -- Scheme Procedure: bitwise-arithmetic-shift ei1 ei2
 -- Scheme Procedure: bitwise-arithmetic-shift-left ei1 ei2
 -- Scheme Procedure: bitwise-arithmetic-shift-right ei1 ei2
     Returns the result of shifting the bits of EI1 right or left by the
     EI2 positions.  ‘bitwise-arithmetic-shift’ is identical to
     ‘bitwise-arithmetic-shift-left’.

 -- Scheme Procedure: bitwise-rotate-bit-field ei1 ei2 ei3 ei4
     Returns the result of cyclically permuting the bit field in EI1
     with start and end positions EI2 and EI3 by EI4 bits in the
     direction of more significant bits.

 -- Scheme Procedure: bitwise-reverse-bit-field ei1 ei2 ei3
     Returns the result of reversing the order of the bits of EI1
     between position EI2 (inclusive) and position EI3 (exclusive).

7.6.2.24 rnrs syntax-case
.........................

The ‘(rnrs syntax-case (6))’ library provides access to the
‘syntax-case’ system for writing hygienic macros.  With one exception,
all of the forms and procedures exported by this library are
"re-exports" of Guile's native support for ‘syntax-case’; see Syntax Case,
for documentation, examples, and rationale.

 -- Scheme Procedure: make-variable-transformer proc
     Creates a new variable transformer out of PROC, a procedure that
     takes a syntax object as input and returns a syntax object.  If an
     identifier to which the result of this procedure is bound appears
     on the left-hand side of a ‘set!’ expression, PROC will be called
     with a syntax object representing the entire ‘set!’ expression, and
     its return value will replace that ‘set!’ expression.

 -- Scheme Syntax: syntax-case expression (literal ...) clause ...
     The ‘syntax-case’ pattern matching form.

 -- Scheme Syntax: syntax template
 -- Scheme Syntax: quasisyntax template
 -- Scheme Syntax: unsyntax template
 -- Scheme Syntax: unsyntax-splicing template
     These forms allow references to be made in the body of a
     syntax-case output expression subform to datum and non-datum
     values.  They are identical to the forms provided by Guile's core
     library; see Syntax Case, for documentation.

 -- Scheme Procedure: identifier? obj
 -- Scheme Procedure: bound-identifier=? id1 id2
 -- Scheme Procedure: free-identifier=? id1 id2
     These predicate procedures operate on syntax objects representing
     Scheme identifiers.  ‘identifier?’ returns ‘#t’ if OBJ represents
     an identifier, ‘#f’ otherwise.  ‘bound-identifier=?’ returns ‘#t’
     if and only if a binding for ID1 would capture a reference to ID2
     in the transformer's output, or vice-versa.  ‘free-identifier=?’
     returns ‘#t’ if and only ID1 and ID2 would refer to the same
     binding in the output of the transformer, independent of any
     bindings introduced by the transformer.

 -- Scheme Procedure: generate-temporaries l
     Returns a list, of the same length as L, which must be a list or a
     syntax object representing a list, of globally unique symbols.

 -- Scheme Procedure: syntax->datum syntax-object
 -- Scheme Procedure: datum->syntax template-id datum
     These procedures convert wrapped syntax objects to and from Scheme
     datum values.  The syntax object returned by ‘datum->syntax’ shares
     contextual information with the syntax object TEMPLATE-ID.

 -- Scheme Procedure: syntax-violation whom message form
 -- Scheme Procedure: syntax-violation whom message form subform
     Constructs a new compound condition that includes the following
     simple conditions:
        • If WHOM is not ‘#f’, a ‘&who’ condition with the WHOM as its
          field
        • A ‘&message’ condition with the specified MESSAGE
        • A ‘&syntax’ condition with the specified FORM and optional
          SUBFORM fields

7.6.2.25 rnrs hashtables
........................

The ‘(rnrs hashtables (6))’ library provides structures and procedures
for creating and accessing hash tables.  The hash tables API defined by
R6RS is substantially similar to both Guile's native hash tables
implementation as well as the one provided by SRFI-69; see Hash Tables,
and SRFI-69, respectively.  Note that you can write
portable R6RS library code that manipulates SRFI-69 hash tables (by
importing the ‘(srfi :69)’ library); however, hash tables created by one
API cannot be used by another.

   Like SRFI-69 hash tables--and unlike Guile's native ones--R6RS hash
tables associate hash and equality functions with a hash table at the
time of its creation.  Additionally, R6RS allows for the creation (via
‘hashtable-copy’; see below) of immutable hash tables.

 -- Scheme Procedure: make-eq-hashtable
 -- Scheme Procedure: make-eq-hashtable k
     Returns a new hash table that uses ‘eq?’ to compare keys and
     Guile's ‘hashq’ procedure as a hash function.  If K is given, it
     specifies the initial capacity of the hash table.

 -- Scheme Procedure: make-eqv-hashtable
 -- Scheme Procedure: make-eqv-hashtable k
     Returns a new hash table that uses ‘eqv?’ to compare keys and
     Guile's ‘hashv’ procedure as a hash function.  If K is given, it
     specifies the initial capacity of the hash table.

 -- Scheme Procedure: make-hashtable hash-function equiv
 -- Scheme Procedure: make-hashtable hash-function equiv k
     Returns a new hash table that uses EQUIV to compare keys and
     HASH-FUNCTION as a hash function.  EQUIV must be a procedure that
     accepts two arguments and returns a true value if they are
     equivalent, ‘#f’ otherwise; HASH-FUNCTION must be a procedure that
     accepts one argument and returns a non-negative integer.

     If K is given, it specifies the initial capacity of the hash table.

 -- Scheme Procedure: hashtable? obj
     Returns ‘#t’ if OBJ is an R6RS hash table, ‘#f’ otherwise.

 -- Scheme Procedure: hashtable-size hashtable
     Returns the number of keys currently in the hash table HASHTABLE.

 -- Scheme Procedure: hashtable-ref hashtable key default
     Returns the value associated with KEY in the hash table HASHTABLE,
     or DEFAULT if none is found.

 -- Scheme Procedure: hashtable-set! hashtable key obj
     Associates the key KEY with the value OBJ in the hash table
     HASHTABLE, and returns an unspecified value.  An ‘&assertion’
     condition is raised if HASHTABLE is immutable.

 -- Scheme Procedure: hashtable-delete! hashtable key
     Removes any association found for the key KEY in the hash table
     HASHTABLE, and returns an unspecified value.  An ‘&assertion’
     condition is raised if HASHTABLE is immutable.

 -- Scheme Procedure: hashtable-contains? hashtable key
     Returns ‘#t’ if the hash table HASHTABLE contains an association
     for the key KEY, ‘#f’ otherwise.

 -- Scheme Procedure: hashtable-update! hashtable key proc default
     Associates with KEY in the hash table HASHTABLE the result of
     calling PROC, which must be a procedure that takes one argument, on
     the value currently associated KEY in HASHTABLE--or on DEFAULT if
     no such association exists.  An ‘&assertion’ condition is raised if
     HASHTABLE is immutable.

 -- Scheme Procedure: hashtable-copy hashtable
 -- Scheme Procedure: hashtable-copy hashtable mutable
     Returns a copy of the hash table HASHTABLE.  If the optional
     argument MUTABLE is provided and is a true value, the new hash
     table will be mutable.

 -- Scheme Procedure: hashtable-clear! hashtable
 -- Scheme Procedure: hashtable-clear! hashtable k
     Removes all of the associations from the hash table HASHTABLE.  The
     optional argument K, which specifies a new capacity for the hash
     table, is accepted by Guile's ‘(rnrs hashtables)’ implementation,
     but is ignored.

 -- Scheme Procedure: hashtable-keys hashtable
     Returns a vector of the keys with associations in the hash table
     HASHTABLE, in an unspecified order.

 -- Scheme Procedure: hashtable-entries hashtable
     Return two values--a vector of the keys with associations in the
     hash table HASHTABLE, and a vector of the values to which these
     keys are mapped, in corresponding but unspecified order.

 -- Scheme Procedure: hashtable-equivalence-function hashtable
     Returns the equivalence predicated use by HASHTABLE.  This
     procedure returns ‘eq?’ and ‘eqv?’, respectively, for hash tables
     created by ‘make-eq-hashtable’ and ‘make-eqv-hashtable’.

 -- Scheme Procedure: hashtable-hash-function hashtable
     Returns the hash function used by HASHTABLE.  For hash tables
     created by ‘make-eq-hashtable’ or ‘make-eqv-hashtable’, ‘#f’ is
     returned.

 -- Scheme Procedure: hashtable-mutable? hashtable
     Returns ‘#t’ if HASHTABLE is mutable, ‘#f’ otherwise.

   A number of hash functions are provided for convenience:

 -- Scheme Procedure: equal-hash obj
     Returns an integer hash value for OBJ, based on its structure and
     current contents.  This hash function is suitable for use with
     ‘equal?’ as an equivalence function.

 -- Scheme Procedure: string-hash string
 -- Scheme Procedure: symbol-hash symbol
     These procedures are identical to the ones provided by Guile's core
     library.  See Hash Table Reference, for documentation.

 -- Scheme Procedure: string-ci-hash string
     Returns an integer hash value for STRING based on its contents,
     ignoring case.  This hash function is suitable for use with
     ‘string-ci=?’ as an equivalence function.

7.6.2.26 rnrs enums
...................

The ‘(rnrs enums (6))’ library provides structures and procedures for
working with enumerable sets of symbols.  Guile's implementation defines
an “enum-set” record type that encapsulates a finite set of distinct
symbols, the “universe”, and a subset of these symbols, which define the
enumeration set.

   The SRFI-1 list library provides a number of procedures for
performing set operations on lists; Guile's ‘(rnrs enums)’
implementation makes use of several of them.  See SRFI-1 Set Operations,
for more information.

 -- Scheme Procedure: make-enumeration symbol-list
     Returns a new enum-set whose universe and enumeration set are both
     equal to SYMBOL-LIST, a list of symbols.

 -- Scheme Procedure: enum-set-universe enum-set
     Returns an enum-set representing the universe of ENUM-SET, an
     enum-set.

 -- Scheme Procedure: enum-set-indexer enum-set
     Returns a procedure that takes a single argument and returns the
     zero-indexed position of that argument in the universe of ENUM-SET,
     or ‘#f’ if its argument is not a member of that universe.

 -- Scheme Procedure: enum-set-constructor enum-set
     Returns a procedure that takes a single argument, a list of symbols
     from the universe of ENUM-SET, an enum-set, and returns a new
     enum-set with the same universe that represents a subset containing
     the specified symbols.

 -- Scheme Procedure: enum-set->list enum-set
     Returns a list containing the symbols of the set represented by
     ENUM-SET, an enum-set, in the order that they appear in the
     universe of ENUM-SET.

 -- Scheme Procedure: enum-set-member? symbol enum-set
 -- Scheme Procedure: enum-set-subset? enum-set1 enum-set2
 -- Scheme Procedure: enum-set=? enum-set1 enum-set2
     These procedures test for membership of symbols and enum-sets in
     other enum-sets.  ‘enum-set-member?’ returns ‘#t’ if and only if
     SYMBOL is a member of the subset specified by ENUM-SET.
     ‘enum-set-subset?’ returns ‘#t’ if and only if the universe of
     ENUM-SET1 is a subset of the universe of ENUM-SET2 and every symbol
     in ENUM-SET1 is present in ENUM-SET2.  ‘enum-set=?’ returns ‘#t’ if
     and only if ENUM-SET1 is a subset, as per ‘enum-set-subset?’ of
     ENUM-SET2 and vice versa.

 -- Scheme Procedure: enum-set-union enum-set1 enum-set2
 -- Scheme Procedure: enum-set-intersection enum-set1 enum-set2
 -- Scheme Procedure: enum-set-difference enum-set1 enum-set2
     These procedures return, respectively, the union, intersection, and
     difference of their enum-set arguments.

 -- Scheme Procedure: enum-set-complement enum-set
     Returns ENUM-SET's complement (an enum-set), with regard to its
     universe.

 -- Scheme Procedure: enum-set-projection enum-set1 enum-set2
     Returns the projection of the enum-set ENUM-SET1 onto the universe
     of the enum-set ENUM-SET2.

 -- Scheme Syntax: define-enumeration type-name (symbol ...)
          constructor-syntax
     Evaluates to two new definitions: A constructor bound to
     CONSTRUCTOR-SYNTAX that behaves similarly to constructors created
     by ‘enum-set-constructor’, above, and creates new ENUM-SETs in the
     universe specified by ‘(symbol ...)’; and a "predicate macro" bound
     to TYPE-NAME, which has the following form:

          (TYPE-NAME sym)

     If SYM is a member of the universe specified by the SYMBOLs above,
     this form evaluates to SYM.  Otherwise, a ‘&syntax’ condition is
     raised.

7.6.2.27 rnrs
.............

The ‘(rnrs (6))’ library is a composite of all of the other R6RS
standard libraries--it imports and re-exports all of their exported
procedures and syntactic forms--with the exception of the following
libraries:

   • ‘(rnrs eval (6))’
   • ‘(rnrs mutable-pairs (6))’
   • ‘(rnrs mutable-strings (6))’
   • ‘(rnrs r5rs (6))’

7.6.2.28 rnrs eval
..................

The ‘(rnrs eval (6)’ library provides procedures for performing
"on-the-fly" evaluation of expressions.

 -- Scheme Procedure: eval expression environment
     Evaluates EXPRESSION, which must be a datum representation of a
     valid Scheme expression, in the environment specified by
     ENVIRONMENT.  This procedure is identical to the one provided by
     Guile's code library; see Fly Evaluation, for documentation.

 -- Scheme Procedure: environment import-spec ...
     Constructs and returns a new environment based on the specified
     IMPORT-SPECs, which must be datum representations of the import
     specifications used with the ‘import’ form.  See R6RS Libraries,
     for documentation.

7.6.2.29 rnrs mutable-pairs
...........................

The ‘(rnrs mutable-pairs (6))’ library provides the ‘set-car!’ and
‘set-cdr!’ procedures, which allow the ‘car’ and ‘cdr’ fields of a pair
to be modified.

   These procedures are identical to the ones provide by Guile's core
library.  See Pairs, for documentation.  All pairs in Guile are
mutable; consequently, these procedures will never throw the
‘&assertion’ condition described in the R6RS libraries specification.

7.6.2.30 rnrs mutable-strings
.............................

The ‘(rnrs mutable-strings (6))’ library provides the ‘string-set!’ and
‘string-fill!’ procedures, which allow the content of strings to be
modified "in-place."

   These procedures are identical to the ones provided by Guile's core
library.  See String Modification, for documentation.  All strings
in Guile are mutable; consequently, these procedures will never throw
the ‘&assertion’ condition described in the R6RS libraries
specification.

7.6.2.31 rnrs r5rs
..................

The ‘(rnrs r5rs (6))’ library exports bindings for some procedures
present in R5RS but omitted from the R6RS base library specification.

 -- Scheme Procedure: exact->inexact z
 -- Scheme Procedure: inexact->exact z
     These procedures are identical to the ones provided by Guile's core
     library.  See Exactness, for documentation.

 -- Scheme Procedure: quotient n1 n2
 -- Scheme Procedure: remainder n1 n2
 -- Scheme Procedure: modulo n1 n2
     These procedures are identical to the ones provided by Guile's core
     library.  See Integer Operations, for documentation.

 -- Scheme Syntax: delay expr
 -- Scheme Procedure: force promise
     The ‘delay’ form and the ‘force’ procedure are identical to their
     counterparts in Guile's core library.  See Delayed Evaluation,
     for documentation.

 -- Scheme Procedure: null-environment n
 -- Scheme Procedure: scheme-report-environment n
     These procedures are identical to the ones provided by the ‘(ice-9
     r5rs)’ Guile module.  See Environments, for documentation.

7.7 R7RS Support
================

The R7RS (https://small.r7rs.org/) standard is essentially R5RS
(directly supported by Guile), plus a module facility, plus an
organization of bindings into a standard set of modules.

   Happily, the syntax for R7RS modules was chosen to be compatible with
R6RS, and so Guile's documentation there applies.  See R6RS Libraries,
for more information on how to define R6RS libraries, and
their integration with Guile modules.  See Library Usage, also.

7.7.1 Incompatibilities with the R7RS
-------------------------------------

As the R7RS is a much less ambitious standard than the R6RS (see Guile and Scheme),
it is very easy for Guile to support.  As such, Guile is
a fully conforming implementation of R7RS, with the exception of the
occasional bug and a couple of unimplemented features:

   • The R7RS specifies a syntax for reading circular data structures
     using “datum labels”, such as ‘#0=(1 2 3 . #0#)’.  Guile's reader
     does not support this syntax currently;
     <https://bugs.gnu.org/38236>.

   • As with R6RS, a number of lexical features of R7RS conflict with
     Guile's historical syntax.  In addition to ‘r6rs-hex-escapes’ and
     ‘hungry-eol-escapes’ (see R6RS Incompatibilities), the
     ‘r7rs-symbols’ reader feature needs to be explicitly enabled.

   Guile exposes a procedure in the root module to choose R7RS defaults
over Guile's historical defaults.

 -- Scheme Procedure: install-r7rs!
     Alter Guile's default settings to better conform to the R7RS.

     While Guile's defaults may evolve over time, the current changes
     that this procedure imposes are to add ‘.sls’ and ‘.guile.sls’ to
     the set of supported ‘%load-extensions’, to better support R7RS
     conventions.  See Load Paths.  ‘install-r7rs!’ will also enable
     the reader options mentioned above.

   Finally, note that the ‘--r7rs’ command-line argument will call
‘install-r7rs!’ before calling user code.  R7RS users probably want to
pass this argument to their Guile.

7.7.2 R7RS Standard Libraries
-----------------------------

The R7RS organizes the definitions from R5RS into modules, and also adds
a few new definitions.

   We do not attempt to document these libraries fully here, as unlike
R6RS, there are few new definitions in R7RS relative to R5RS. Most of
their functionality is already in Guile's standard environment.  Again,
the expectation is that most Guile users will use the well-known and
well-documented Guile modules; these R7RS libraries are mostly useful to
users who want to port their code to other R7RS systems.

   As a brief overview, we note that the libraries defined by the R7RS
are as follows:

‘(scheme base)’
     The core functions, mostly corresponding to R5RS minus the elements
     listed separately below, but plus SRFI-34 error handling (see
     SRFI-34), bytevectors and bytevector ports (see Bytevectors),
     and some miscellaneous other new procedures.
‘(scheme case-lambda)’
     ‘case-lambda’.
‘(scheme char)’
     Converting strings and characters to upper or lower case,
     predicates for if a characer is numeric, and so on.
‘(scheme complex)’
     Constructors and accessors for complex numbers.
‘(scheme cxr)’
     ‘cddr’, ‘cadadr’, and all that.
‘(scheme eval)’
     ‘eval’, but also an ‘environment’ routine allowing a user to
     specify an environment using a module import set.
‘(scheme file)’
     ‘call-with-input-file’ and so on.
‘(scheme inexact)’
     Routines that operate on inexact numbers: ‘sin’, ‘finite?’, and so
     on.
‘(scheme lazy)’
     Promises.
‘(scheme load)’
     The ‘load’ procedure.
‘(scheme process-context)’
     Environment variables.  See SRFI-98.  Also, ‘commmand-line’,
     ‘emergency-exit’ (like Guile's ‘primitive-_exit’), and ‘exit’.
‘(scheme r5rs)’
     The precise set of bindings exported by ‘r5rs’, but without
     ‘transcript-off’ / ‘transcript-on’, and also with the auxiliary
     syntax definitions like ‘_’ or ‘else’.  See Syntax Rules, for
     more on auxiliary syntax.
‘(scheme read)’
     The ‘read’ procedure.
‘(scheme repl)’
     The ‘interaction-environment’ procedure.
‘(scheme time)’
     ‘current-second’, as well as ‘current-jiffy’ and
     ‘jiffies-per-second’.  Guile uses the term "internal time unit" for
     what R7RS calls "jiffies".
‘(scheme write)’
     ‘display’, ‘write’, as well as ‘write-shared’ and ‘write-simple’.

   For complete documentation, we advise the interested user to consult
the R7RS directly (see R7RS (r7rs)).

7.8 Pattern Matching
====================

The ‘(ice-9 match)’ module provides a “pattern matcher”, written by Alex
Shinn, and compatible with Andrew K. Wright's pattern matcher found in
many Scheme implementations.

   A pattern matcher can match an object against several patterns and
extract the elements that make it up.  Patterns can represent any Scheme
object: lists, strings, symbols, records, etc.  They can optionally
contain “pattern variables”.  When a matching pattern is found, an
expression associated with the pattern is evaluated, optionally with all
pattern variables bound to the corresponding elements of the object:

     (let ((l '(hello (world))))
       (match l           ;; <- the input object
         (('hello (who))  ;; <- the pattern
          who)))          ;; <- the expression evaluated upon matching
     ⇒ world

   In this example, list L matches the pattern ‘('hello (who))’, because
it is a two-element list whose first element is the symbol ‘hello’ and
whose second element is a one-element list.  Here WHO is a pattern
variable.  ‘match’, the pattern matcher, locally binds WHO to the value
contained in this one-element list--i.e., the symbol ‘world’.  An error
would be raised if L did not match the pattern.

   The same object can be matched against a simpler pattern:

     (let ((l '(hello (world))))
       (match l
         ((x y)
          (values x y))))
     ⇒ hello
     ⇒ (world)

   Here pattern ‘(x y)’ matches any two-element list, regardless of the
types of these elements.  Pattern variables X and Y are bound to,
respectively, the first and second element of L.

   Patterns can be composed, and nested.  For instance, ‘...’ (ellipsis)
means that the previous pattern may be matched zero or more times in a
list:

     (match lst
       (((heads tails ...) ...)
        heads))

This expression returns the first element of each list within LST.  For
proper lists of proper lists, it is equivalent to ‘(map car lst)’.
However, it performs additional checks to make sure that LST and the
lists therein are proper lists, as prescribed by the pattern, raising an
error if they are not.

   Compared to hand-written code, pattern matching noticeably improves
clarity and conciseness--no need to resort to series of ‘car’ and ‘cdr’
calls when matching lists, for instance.  It also improves robustness,
by making sure the input _completely_ matches the pattern--conversely,
hand-written code often trades robustness for conciseness.  And of
course, ‘match’ is a macro, and the code it expands to is just as
efficient as equivalent hand-written code.

   The pattern matcher is defined as follows:

 -- Scheme Syntax: match exp clause1 clause2 ...
     Match object EXP against the patterns in CLAUSE1 CLAUSE2 ... in the
     order in which they appear.  Return the value produced by the first
     matching clause.  If no clause matches, throw an exception with key
     ‘match-error’.

     Each clause has the form ‘(pattern body1 body2 ...)’.  Each PATTERN
     must follow the syntax described below.  Each body is an arbitrary
     Scheme expression, possibly referring to pattern variables of
     PATTERN.

   The syntax and interpretation of patterns is as follows:

        patterns:                       matches:

pat ::= identifier                      anything, and binds identifier
      | _                               anything
      | ()                              the empty list
      | #t                              #t
      | #f                              #f
      | string                          a string
      | number                          a number
      | character                       a character
      | 'sexp                           an s-expression
      | 'symbol                         a symbol (special case of s-expr)
      | (pat_1 ... pat_n)               list of n elements
      | (pat_1 ... pat_n . pat_{n+1})   list of n or more
      | (pat_1 ... pat_n pat_n+1 ooo)   list of n or more, each element
                                          of remainder must match pat_n+1
      | #(pat_1 ... pat_n)              vector of n elements
      | #(pat_1 ... pat_n pat_n+1 ooo)  vector of n or more, each element
                                          of remainder must match pat_n+1
      | #&pat                           box
      | ($ record-name pat_1 ... pat_n) a record
      | (= field pat)                   a ``field'' of an object
      | (and pat_1 ... pat_n)           if all of pat_1 thru pat_n match
      | (or pat_1 ... pat_n)            if any of pat_1 thru pat_n match
      | (not pat_1 ... pat_n)           if all pat_1 thru pat_n don't match
      | (? predicate pat_1 ... pat_n)   if predicate true and all of
                                          pat_1 thru pat_n match
      | (set! identifier)               anything, and binds setter
      | (get! identifier)               anything, and binds getter
      | `qp                             a quasi-pattern
      | (identifier *** pat)            matches pat in a tree and binds
                                        identifier to the path leading
                                        to the object that matches pat

ooo ::= ...                             zero or more
      | ___                             zero or more
      | ..1                             1 or more

        quasi-patterns:                 matches:

qp  ::= ()                              the empty list
      | #t                              #t
      | #f                              #f
      | string                          a string
      | number                          a number
      | character                       a character
      | identifier                      a symbol
      | (qp_1 ... qp_n)                 list of n elements
      | (qp_1 ... qp_n . qp_{n+1})      list of n or more
      | (qp_1 ... qp_n qp_n+1 ooo)      list of n or more, each element
                                          of remainder must match qp_n+1
      | #(qp_1 ... qp_n)                vector of n elements
      | #(qp_1 ... qp_n qp_n+1 ooo)     vector of n or more, each element
                                          of remainder must match qp_n+1
      | #&qp                            box
      | ,pat                            a pattern
      | ,@pat                           a pattern

   The names ‘quote’, ‘quasiquote’, ‘unquote’, ‘unquote-splicing’, ‘?’,
‘_’, ‘$’, ‘and’, ‘or’, ‘not’, ‘set!’, ‘get!’, ‘...’, and ‘___’ cannot be
used as pattern variables.

   Here is a more complex example:

     (use-modules (srfi srfi-9))

     (let ()
       (define-record-type person
         (make-person name friends)
         person?
         (name    person-name)
         (friends person-friends))

       (letrec ((alice (make-person "Alice" (delay (list bob))))
                (bob   (make-person "Bob" (delay (list alice)))))
         (match alice
           (($ person name (= force (($ person "Bob"))))
            (list 'friend-of-bob name))
           (_ #f))))

     ⇒ (friend-of-bob "Alice")

Here the ‘$’ pattern is used to match a SRFI-9 record of type PERSON
containing two or more slots.  The value of the first slot is bound to
NAME.  The ‘=’ pattern is used to apply ‘force’ on the second slot, and
then checking that the result matches the given pattern.  In other
words, the complete pattern matches any PERSON whose second slot is a
promise that evaluates to a one-element list containing a PERSON whose
first slot is ‘"Bob"’.

   The ‘(ice-9 match)’ module also provides the following convenient
syntactic sugar macros wrapping around ‘match’.

 -- Scheme Syntax: match-lambda clause1 clause2 ...
     Create a procedure of one argument that matches its argument
     against each clause, and returns the result of evaluating the
     corresponding expressions.

          (match-lambda clause1 clause2 ...)
          ≡
          (lambda (arg) (match arg clause1 clause2 ...))

     ((match-lambda
        (('hello (who))
         who))
      '(hello (world)))
     ⇒ world

 -- Scheme Syntax: match-lambda* clause1 clause2 ...
     Create a procedure of any number of arguments that matches its
     argument list against each clause, and returns the result of
     evaluating the corresponding expressions.

          (match-lambda* clause1 clause2 ...)
          ≡
          (lambda args (match args clause1 clause2 ...))

     ((match-lambda*
        (('hello (who))
         who))
      'hello '(world))
     ⇒ world

 -- Scheme Syntax: match-let ((pattern expression) ...) body
     Match each pattern to the corresponding expression, and evaluate
     the body with all matched variables in scope.  Raise an error if
     any of the expressions fail to match.  ‘match-let’ is analogous to
     named let and can also be used for recursive functions which match
     on their arguments as in ‘match-lambda*’.

          (match-let (((x y) (list 1 2))
                      ((a b) (list 3 4)))
            (list a b x y))
          ⇒
          (3 4 1 2)

 -- Scheme Syntax: match-let variable ((pattern init) ...) body
     Similar to ‘match-let’, but analogously to “named let”, locally
     bind VARIABLE to a new procedure which accepts as many arguments as
     there are INIT expressions.  The procedure is initially applied to
     the results of evaluating the INIT expressions.  When called, the
     procedure matches each argument against the corresponding PATTERN,
     and returns the result(s) of evaluating the BODY expressions.
     See Iteration, for more on “named let”.

 -- Scheme Syntax: match-let* ((variable expression) ...) body
     Similar to ‘match-let’, but analogously to ‘let*’, match and bind
     the variables in sequence, with preceding match variables in scope.

          (match-let* (((x y) (list 1 2))
                       ((a b) (list x 4)))
            (list a b x y))
          ≡
          (match-let (((x y) (list 1 2)))
            (match-let (((a b) (list x 4)))
              (list a b x y)))
          ⇒
          (1 4 1 2)

 -- Scheme Syntax: match-letrec ((variable expression) ...) body
     Similar to ‘match-let’, but analogously to ‘letrec’, match and bind
     the variables with all match variables in scope.

   Guile also comes with a pattern matcher specifically tailored to SXML
trees, see sxml-match.

7.9 Readline Support
====================

Guile comes with an interface module to the readline library (see
readline).  This makes interactive use much more convenient,
because of the command-line editing features of readline.  Using ‘(ice-9
readline)’, you can navigate through the current input line with the
cursor keys, retrieve older command lines from the input history and
even search through the history entries.

7.9.1 Loading Readline Support
------------------------------

The module is not loaded by default and so has to be loaded and
activated explicitly.  This is done with two simple lines of code:

     (use-modules (ice-9 readline))
     (activate-readline)

   The first line will load the necessary code, and the second will
activate readline's features for the REPL. If you plan to use this
module often, you should save these to lines to your ‘.guile’ personal
startup file.

   You will notice that the REPL's behavior changes a bit when you have
loaded the readline module.  For example, when you press Enter before
typing in the closing parentheses of a list, you will see the
“continuation” prompt, three dots: ‘...’ This gives you a nice visual
feedback when trying to match parentheses.  To make this even easier,
“bouncing parentheses” are implemented.  That means that when you type
in a closing parentheses, the cursor will jump to the corresponding
opening parenthesis for a short time, making it trivial to make them
match.

   Once the readline module is activated, all lines entered
interactively will be stored in a history and can be recalled later
using the cursor-up and -down keys.  Readline also understands the Emacs
keys for navigating through the command line and history.

   When you quit your Guile session by evaluating ‘(quit)’ or pressing
Ctrl-D, the history will be saved to the file ‘.guile_history’ and read
in when you start Guile for the next time.  Thus you can start a new
Guile session and still have the (probably long-winded) definition
expressions available.

   You can specify a different history file by setting the environment
variable ‘GUILE_HISTORY’.  And you can make Guile specific
customizations to your ‘.inputrc’ by testing for application ‘Guile’
(see Conditional Init Constructs (readline)).  For instance to define
a key inserting a matched pair of parentheses,

     $if Guile
       "\C-o": "()\C-b"
     $endif

7.9.2 Readline Options
----------------------

The readline interface module can be tweaked in a few ways to better
suit the user's needs.  Configuration is done via the readline module's
options interface, in a similar way to the evaluator and debugging
options (see Runtime Options).

 -- Scheme Procedure: readline-options
 -- Scheme Procedure: readline-enable option-name
 -- Scheme Procedure: readline-disable option-name
 -- Scheme Syntax: readline-set! option-name value
     Accessors for the readline options.  Note that unlike the
     enable/disable procedures, ‘readline-set!’ is syntax, which expects
     an unquoted option name.

   Here is the list of readline options generated by typing
‘(readline-options 'help)’ in Guile.  You can also see the default
values.

     history-file    yes     Use history file.
     history-length  200     History length.
     bounce-parens   500     Time (ms) to show matching opening parenthesis
                             (0 = off).
     bracketed-paste yes     Disable interpretation of control characters
                             in pastes.

   The readline options interface can only be used _after_ loading the
readline module, because it is defined in that module.

7.9.3 Readline Functions
------------------------

The following functions are provided by

     (use-modules (ice-9 readline))

   There are two ways to use readline from Scheme code, either make
calls to ‘readline’ directly to get line by line input, or use the
readline port below with all the usual reading functions.

 -- Function: readline [prompt]
     Read a line of input from the user and return it as a string
     (without a newline at the end).  PROMPT is the prompt to show, or
     the default is the string set in ‘set-readline-prompt!’ below.

          (readline "Type something: ") ⇒ "hello"

 -- Function: set-readline-input-port! port
 -- Function: set-readline-output-port! port
     Set the input and output port the readline function should read
     from and write to.  PORT must be a file port (see File Ports),
     and should usually be a terminal.

     The default is the ‘current-input-port’ and ‘current-output-port’
     (see Default Ports) when ‘(ice-9 readline)’ loads, which in an
     interactive user session means the Unix "standard input" and
     "standard output".

7.9.3.1 Readline Port
.....................

 -- Function: readline-port
     Return a buffered input port (see Buffered Input) which calls
     the ‘readline’ function above to get input.  This port can be used
     with all the usual reading functions (‘read’, ‘read-char’, etc),
     and the user gets the interactive editing features of readline.

     There's only a single readline port created.  ‘readline-port’
     creates it when first called, and on subsequent calls just returns
     what it previously made.

 -- Function: activate-readline
     If the ‘current-input-port’ is a terminal (see ‘isatty?’)
     then enable readline for all reading from
     ‘current-input-port’ (see Default Ports) and enable readline
     features in the interactive REPL (see The REPL).

          (activate-readline)
          (read-char)

     ‘activate-readline’ enables readline on ‘current-input-port’ simply
     by a ‘set-current-input-port’ to the ‘readline-port’ above.  An
     application can do that directly if the extra REPL features that
     ‘activate-readline’ adds are not wanted.

 -- Function: set-readline-prompt! prompt1 [prompt2]
     Set the prompt string to print when reading input.  This is used
     when reading through ‘readline-port’, and is also the default
     prompt for the ‘readline’ function above.

     PROMPT1 is the initial prompt shown.  If a user might enter an
     expression across multiple lines, then PROMPT2 is a different
     prompt to show further input required.  In the Guile REPL for
     instance this is an ellipsis (‘...’).

     See ‘set-buffered-input-continuation?!’ (see Buffered Input)
     for an application to indicate the boundaries of logical
     expressions (assuming of course an application has such a notion).

7.9.3.2 Completion
..................

 -- Function: with-readline-completion-function completer thunk
     Call ‘(THUNK)’ with COMPLETER as the readline tab completion
     function to be used in any readline calls within that THUNK.
     COMPLETER can be ‘#f’ for no completion.

     COMPLETER will be called as ‘(COMPLETER text state)’, as described
     in (see How Completing Works (readline)).  TEXT is a partial
     word to be completed, and each COMPLETER call should return a
     possible completion string or ‘#f’ when no more.  STATE is ‘#f’ for
     the first call asking about a new TEXT then ‘#t’ while getting
     further completions of that TEXT.

     Here's an example COMPLETER for user login names from the password
     file (see User Information), much like readline's own
     ‘rl_username_completion_function’,

          (define (username-completer-function text state)
            (if (not state)
                (setpwent))  ;; new, go to start of database
            (let more ((pw (getpwent)))
              (if pw
                  (if (string-prefix? text (passwd:name pw))
                      (passwd:name pw)     ;; this name matches, return it
                      (more (getpwent)))   ;; doesn't match, look at next
                  (begin
                    ;; end of database, close it and return #f
                    (endpwent)
                    #f))))

 -- Function: apropos-completion-function text state
     A completion function offering completions for Guile functions and
     variables (all ‘define’s).  This is the default completion
     function.

 -- Function: filename-completion-function text state
     A completion function offering filename completions.  This is
     readline's ‘rl_filename_completion_function’ (see
     Completion Functions (readline)).

 -- Function: make-completion-function string-list
     Return a completion function which offers completions from the
     possibilities in STRING-LIST.  Matching is case-sensitive.

7.10 Pretty Printing
====================

The module ‘(ice-9 pretty-print)’ provides the procedure ‘pretty-print’,
which provides nicely formatted output of Scheme objects.  This is
especially useful for deeply nested or complex data structures, such as
lists and vectors.

   The module is loaded by entering the following:

     (use-modules (ice-9 pretty-print))

   This makes the procedure ‘pretty-print’ available.  As an example how
‘pretty-print’ will format the output, see the following:

     (pretty-print '(define (foo) (lambda (x)
     (cond ((zero? x) #t) ((negative? x) -x) (else
     (if (= x 1) 2 (* x x x)))))))
     ⊣
     (define (foo)
       (lambda (x)
         (cond ((zero? x) #t)
               ((negative? x) -x)
               (else (if (= x 1) 2 (* x x x))))))

 -- Scheme Procedure: pretty-print obj [port] [keyword-options]
     Print the textual representation of the Scheme object OBJ to PORT.
     PORT defaults to the current output port, if not given.

     The further KEYWORD-OPTIONS are keywords and parameters as follows,

     #:display? FLAG
          If FLAG is true then print using ‘display’.  The default is
          ‘#f’ which means use ‘write’ style.  See Scheme Write.

     #:per-line-prefix STRING
          Print the given STRING as a prefix on each line.  The default
          is no prefix.

     #:width COLUMNS
          Print within the given COLUMNS.  The default is 79.

     #:max-expr-width COLUMNS
          The maximum width of an expression.  The default is 50.

   Also exported by the ‘(ice-9 pretty-print)’ module is
‘truncated-print’, a procedure to print Scheme datums, truncating the
output to a certain number of characters.  This is useful when you need
to present an arbitrary datum to the user, but you only have one line in
which to do so.

     (define exp '(a b #(c d e) f . g))
     (truncated-print exp #:width 10) (newline)
     ⊣ (a b . #)
     (truncated-print exp #:width 15) (newline)
     ⊣ (a b # f . g)
     (truncated-print exp #:width 18) (newline)
     ⊣ (a b #(c ...) . #)
     (truncated-print exp #:width 20) (newline)
     ⊣ (a b #(c d e) f . g)
     (truncated-print "The quick brown fox" #:width 20) (newline)
     ⊣ "The quick brown..."
     (truncated-print (current-module) #:width 20) (newline)
     ⊣ #<directory (gui...>

   ‘truncated-print’ will not output a trailing newline.  If an
expression does not fit in the given width, it will be truncated -
possibly ellipsized(1), or in the worst case, displayed as #.

 -- Scheme Procedure: truncated-print obj [port] [keyword-options]
     Print OBJ, truncating the output, if necessary, to make it fit into
     WIDTH characters.  By default, OBJ will be printed using ‘write’,
     though that behavior can be overridden via the DISPLAY? keyword
     argument.

     The default behavior is to print depth-first, meaning that the
     entire remaining width will be available to each sub-expression of
     OBJ - e.g., if OBJ is a vector, each member of OBJ.  One can
     attempt to "ration" the available width, trying to allocate it
     equally to each sub-expression, via the BREADTH-FIRST? keyword
     argument.

     The further KEYWORD-OPTIONS are keywords and parameters as follows,

     #:display? FLAG
          If FLAG is true then print using ‘display’.  The default is
          ‘#f’ which means use ‘write’ style.  See Scheme Write.

     #:width COLUMNS
          Print within the given COLUMNS.  The default is 79.

     #:breadth-first? FLAG
          If FLAG is true, then allocate the available width
          breadth-first among elements of a compound data structure
          (list, vector, pair, etc.).  The default is ‘#f’ which means
          that any element is allowed to consume all of the available
          width.

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

   (1) On Unicode-capable ports, the ellipsis is represented by
character 'HORIZONTAL ELLIPSIS' (U+2026), otherwise it is represented by
three dots.

7.11 Formatted Output
=====================

The ‘format’ function is a powerful way to print numbers, strings and
other objects together with literal text under the control of a format
string.  This function is available from

     (use-modules (ice-9 format))

   A format string is generally more compact and easier than using just
the standard procedures like ‘display’, ‘write’ and ‘newline’.
Parameters in the output string allow various output styles, and
parameters can be taken from the arguments for runtime flexibility.

   ‘format’ is similar to the Common Lisp procedure of the same name,
but it's not identical and doesn't have quite all the features found in
Common Lisp.

   C programmers will note the similarity between ‘format’ and ‘printf’,
though escape sequences are marked with ~ instead of %, and are more
powerful.

 -- Scheme Procedure: format dest fmt arg ...
     Write output specified by the FMT string to DEST.  DEST can be an
     output port, ‘#t’ for ‘current-output-port’ (see Default Ports),
     or ‘#f’ to return the output as a string.

     FMT can contain literal text to be output, and ~ escapes.  Each
     escape has the form

          ~ [param [, param...] [:] [@] code

     code is a character determining the escape sequence.  The : and @
     characters are optional modifiers, one or both of which change the
     way various codes operate.  Optional parameters are accepted by
     some codes too.  Parameters have the following forms,

     [+/-]number
          An integer, with optional + or -.
     ' (apostrophe)
          The following character in the format string, for instance 'z
          for z.
     v
          The next function argument as the parameter.  v stands for
          "variable", a parameter can be calculated at runtime and
          included in the arguments.  Upper case V can be used too.
     #
          The number of arguments remaining.  (See ~* below for some
          usages.)

     Parameters are separated by commas (,).  A parameter can be left
     empty to keep its default value when supplying later parameters.

     The following escapes are available.  The code letters are not
     case-sensitive, upper and lower case are the same.

     ~a
     ~s
          Object output.  Parameters: MINWIDTH, PADINC, MINPAD, PADCHAR.

          ~a outputs an argument like ‘display’, ~s outputs an argument
          like ‘write’ (see Scheme Write).

               (format #t "~a" "foo") ⊣ foo
               (format #t "~s" "foo") ⊣ "foo"

          ~:a and ~:s put objects that don't have an external
          representation in quotes like a string.

               (format #t "~:a" car) ⊣ "#<primitive-procedure car>"

          If the output is less than MINWIDTH characters (default 0),
          it's padded on the right with PADCHAR (default space).  ~@a
          and ~@s put the padding on the left instead.

               (format #f "~5a" 'abc)       ⇒ "abc  "
               (format #f "~5,,,'-@a" 'abc) ⇒ "--abc"

          MINPAD is a minimum for the padding then plus a multiple of
          PADINC.  Ie. the padding is MINPAD + N * PADINC, where N is
          the smallest integer making the total object plus padding
          greater than or equal to MINWIDTH.  The default MINPAD is 0
          and the default PADINC is 1 (imposing no minimum or multiple).

               (format #f "~5,1,4a" 'abc) ⇒ "abc    "

     ~c
          Character.  Parameter: CHARNUM.

          Output a character.  The default is to simply output, as per
          ‘write-char’ (see Venerable Port Interfaces).  ~@c prints
          in ‘write’ style.  ~:c prints control characters (ASCII 0 to
          31) in ^X form.

               (format #t "~c" #\z)        ⊣ z
               (format #t "~@c" #\z)       ⊣ #\z
               (format #t "~:c" #\newline) ⊣ ^J

          If the CHARNUM parameter is given then an argument is not
          taken but instead the character is ‘(integer->char CHARNUM)’
          (see Characters).  This can be used for instance to output
          characters given by their ASCII code.

               (format #t "~65c")  ⊣ A

     ~d
     ~x
     ~o
     ~b
          Integer.  Parameters: MINWIDTH, PADCHAR, COMMACHAR,
          COMMAWIDTH.

          Output an integer argument as a decimal, hexadecimal, octal or
          binary integer (respectively), in a locale-independent way.

               (format #t "~d" 123) ⊣ 123

          ~@d etc shows a + sign is shown on positive numbers.

               (format #t "~@b" 12) ⊣ +1100

          If the output is less than the MINWIDTH parameter (default no
          minimum), it's padded on the left with the PADCHAR parameter
          (default space).

               (format #t "~5,'*d" 12)   ⊣ ***12
               (format #t "~5,'0d" 12)   ⊣ 00012
               (format #t "~3d"    1234) ⊣ 1234

          ~:d adds commas (or the COMMACHAR parameter) every three
          digits (or the COMMAWIDTH parameter many).  However, when your
          intent is to write numbers in a way that follows typographical
          conventions, using ~h is recommended.

               (format #t "~:d" 1234567)         ⊣ 1,234,567
               (format #t "~10,'*,'/,2:d" 12345) ⊣ ***1/23/45

          Hexadecimal ~x output is in lower case, but the ~( and ~) case
          conversion directives described below can be used to get upper
          case.

               (format #t "~x"       65261) ⊣ feed
               (format #t "~:@(~x~)" 65261) ⊣ FEED

     ~r
          Integer in words, roman numerals, or a specified radix.
          Parameters: RADIX, MINWIDTH, PADCHAR, COMMACHAR, COMMAWIDTH.

          With no parameters output is in words as a cardinal like
          "ten", or ~:r prints an ordinal like "tenth".

               (format #t "~r" 9)  ⊣ nine        ;; cardinal
               (format #t "~r" -9) ⊣ minus nine  ;; cardinal
               (format #t "~:r" 9) ⊣ ninth       ;; ordinal

          And also with no parameters, ~@r gives roman numerals and ~:@r
          gives old roman numerals.  In old roman numerals there's no
          "subtraction", so 9 is VIIII instead of IX. In both cases only
          positive numbers can be output.

               (format #t "~@r" 89)  ⊣ LXXXIX     ;; roman
               (format #t "~:@r" 89) ⊣ LXXXVIIII  ;; old roman

          When a parameter is given it means numeric output in the
          specified RADIX.  The modifiers and parameters following the
          radix are the same as described for ~d etc above.

               (format #f "~3r" 27)   ⇒ "1000"    ;; base 3
               (format #f "~3,5r" 26) ⇒ "  222"   ;; base 3 width 5

     ~f
          Fixed-point float.  Parameters: WIDTH, DECIMALS, SCALE,
          OVERFLOWCHAR, PADCHAR.

          Output a number or number string in fixed-point format, ie.
          with a decimal point.

               (format #t "~f" 5)      ⊣ 5.0
               (format #t "~f" "123")  ⊣ 123.0
               (format #t "~f" "1e-1") ⊣ 0.1

          ~@f prints a + sign on positive numbers (including zero).

               (format #t "~@f" 0) ⊣ +0.0

          If the output is less than WIDTH characters it's padded on the
          left with PADCHAR (space by default).  If the output equals or
          exceeds WIDTH then there's no padding.  The default for WIDTH
          is no padding.

               (format #f "~6f" -1.5)      ⇒ "  -1.5"
               (format #f "~6,,,,'*f" 23)  ⇒ "**23.0"
               (format #f "~6f" 1234567.0) ⇒ "1234567.0"

          DECIMALS is how many digits to print after the decimal point,
          with the value rounded or padded with zeros as necessary.
          (The default is to output as many decimals as required.)

               (format #t "~1,2f" 3.125) ⊣ 3.13
               (format #t "~1,2f" 1.5)   ⊣ 1.50

          SCALE is a power of 10 applied to the value, moving the
          decimal point that many places.  A positive SCALE increases
          the value shown, a negative decreases it.

               (format #t "~,,2f" 1234)  ⊣ 123400.0
               (format #t "~,,-2f" 1234) ⊣ 12.34

          If OVERFLOWCHAR and WIDTH are both given and if the output
          would exceed WIDTH, then that many OVERFLOWCHARs are printed
          instead of the value.

               (format #t "~6,,,'xf" 12345) ⊣ 12345.
               (format #t "~5,,,'xf" 12345) ⊣ xxxxx

     ~h
          Localized number(1).  Parameters: WIDTH, DECIMALS, PADCHAR.

          Like ~f, output an exact or floating point number, but do so
          according to the current locale, or according to the given
          locale object when the ‘:’ modifier is used (see
          ‘number->locale-string’).

               (format #t "~h" 12345.5678)  ; with "C" as the current locale
               ⊣ 12345.5678

               (format #t "~14,,'*:h" 12345.5678
                       (make-locale LC_ALL "en_US"))
               ⊣ ***12,345.5678

               (format #t "~,2:h" 12345.5678
                       (make-locale LC_NUMERIC "fr_FR"))
               ⊣ 12 345,56

     ~e
          Exponential float.  Parameters: WIDTH, MANTDIGITS, EXPDIGITS,
          INTDIGITS, OVERFLOWCHAR, PADCHAR, EXPCHAR.

          Output a number or number string in exponential notation.

               (format #t "~e" 5000.25) ⊣ 5.00025E+3
               (format #t "~e" "123.4") ⊣ 1.234E+2
               (format #t "~e" "1e4")   ⊣ 1.0E+4

          ~@e prints a + sign on positive numbers (including zero).
          (This is for the mantissa, a + or - sign is always shown on
          the exponent.)

               (format #t "~@e" 5000.0) ⊣ +5.0E+3

          If the output is less than WIDTH characters it's padded on the
          left with PADCHAR (space by default).  The default for WIDTH
          is to output with no padding.

               (format #f "~10e" 1234.0)     ⇒ "  1.234E+3"
               (format #f "~10,,,,,'*e" 0.5) ⇒ "****5.0E-1"

          MANTDIGITS is the number of digits shown in the mantissa after
          the decimal point.  The value is rounded or trailing zeros are
          added as necessary.  The default MANTDIGITS is to show as much
          as needed by the value.

               (format #f "~,3e" 11111.0) ⇒ "1.111E+4"
               (format #f "~,8e" 123.0)   ⇒ "1.23000000E+2"

          EXPDIGITS is the minimum number of digits shown for the
          exponent, with leading zeros added if necessary.  The default
          for EXPDIGITS is to show only as many digits as required.  At
          least 1 digit is always shown.

               (format #f "~,,1e" 1.0e99) ⇒ "1.0E+99"
               (format #f "~,,6e" 1.0e99) ⇒ "1.0E+000099"

          INTDIGITS (default 1) is the number of digits to show before
          the decimal point in the mantissa.  INTDIGITS can be zero, in
          which case the integer part is a single 0, or it can be
          negative, in which case leading zeros are shown after the
          decimal point.

               (format #t "~,,,3e" 12345.0)  ⊣ 123.45E+2
               (format #t "~,,,0e" 12345.0)  ⊣ 0.12345E+5
               (format #t "~,,,-3e" 12345.0) ⊣ 0.00012345E+8

          If OVERFLOWCHAR is given then WIDTH is a hard limit.  If the
          output would exceed WIDTH then instead that many OVERFLOWCHARs
          are printed.

               (format #f "~6,,,,'xe" 100.0) ⇒ "1.0E+2"
               (format #f "~3,,,,'xe" 100.0) ⇒ "xxx"

          EXPCHAR is the exponent marker character (default E).

               (format #t "~,,,,,,'ee" 100.0) ⊣ 1.0e+2

     ~g
          General float.  Parameters: WIDTH, MANTDIGITS, EXPDIGITS,
          INTDIGITS, OVERFLOWCHAR, PADCHAR, EXPCHAR.

          Output a number or number string in either exponential format
          the same as ~e, or fixed-point format like ~f but aligned
          where the mantissa would have been and followed by padding
          where the exponent would have been.

          Fixed-point is used when the absolute value is 0.1 or more and
          it takes no more space than the mantissa in exponential
          format, ie. basically up to MANTDIGITS digits.

               (format #f "~12,4,2g" 999.0)    ⇒ "   999.0    "
               (format #f "~12,4,2g" "100000") ⇒ "  1.0000E+05"

          The parameters are interpreted as per ~e above.  When
          fixed-point is used, the DECIMALS parameter to ~f is
          established from MANTDIGITS, so as to give a total
          MANTDIGITS+1 figures.

     ~$
          Monetary style fixed-point float.  Parameters: DECIMALS,
          INTDIGITS, WIDTH, PADCHAR.

          Output a number or number string in fixed-point format, ie.
          with a decimal point.  DECIMALS is the number of decimal
          places to show, default 2.

               (format #t "~$" 5)       ⊣ 5.00
               (format #t "~4$" "2.25") ⊣ 2.2500
               (format #t "~4$" "1e-2") ⊣ 0.0100

          ~@$ prints a + sign on positive numbers (including zero).

               (format #t "~@$" 0) ⊣ +0.00

          INTDIGITS is a minimum number of digits to show in the integer
          part of the value (default 1).

               (format #t "~,3$" 9.5)   ⊣ 009.50
               (format #t "~,0$" 0.125) ⊣ .13

          If the output is less than WIDTH characters (default 0), it's
          padded on the left with PADCHAR (default space).  ~:$ puts the
          padding after the sign.

               (format #f "~,,8$" -1.5)   ⇒ "   -1.50"
               (format #f "~,,8:$" -1.5)  ⇒ "-   1.50"
               (format #f "~,,8,'.:@$" 3) ⇒ "+...3.00"

          Note that floating point for dollar amounts is generally not a
          good idea, because a cent 0.01 cannot be represented exactly
          in the binary floating point Guile uses, which leads to slowly
          accumulating rounding errors.  Keeping values as cents (or
          fractions of a cent) in integers then printing with the scale
          option in ~f may be a better approach.

     ~i
          Complex fixed-point float.  Parameters: WIDTH, DECIMALS,
          SCALE, OVERFLOWCHAR, PADCHAR.

          Output the argument as a complex number, with both real and
          imaginary part shown (even if one or both are zero).

          The parameters and modifiers are the same as for fixed-point
          ~f described above.  The real and imaginary parts are both
          output with the same given parameters and modifiers, except
          that for the imaginary part the @ modifier is always enabled,
          so as to print a + sign between the real and imaginary parts.

               (format #t "~i" 1)  ⊣ 1.0+0.0i

     ~p
          Plural.  No parameters.

          Output nothing if the argument is 1, or ‘s’ for any other
          value.

               (format #t "enter name~p" 1) ⊣ enter name
               (format #t "enter name~p" 2) ⊣ enter names

          ~@p prints ‘y’ for 1 or ‘ies’ otherwise.

               (format #t "pupp~@p" 1) ⊣ puppy
               (format #t "pupp~@p" 2) ⊣ puppies

          ~:p re-uses the preceding argument instead of taking a new
          one, which can be convenient when printing some sort of count.

               (format #t "~d cat~:p" 9)   ⊣ 9 cats
               (format #t "~d pupp~:@p" 5) ⊣ 5 puppies

          ~p is designed for English plurals and there's no attempt to
          support other languages.  ~[ conditionals (below) may be able
          to help.  When using ‘gettext’ to translate messages
          ‘ngettext’ is probably best though (see
          Internationalization).

     ~y
          Structured printing.  Parameters: WIDTH.

          ~y outputs an argument using ‘pretty-print’ (see Pretty Printing).
          The result will be formatted to fit within WIDTH
          columns (79 by default), consuming multiple lines if
          necessary.

          ~@y outputs an argument using ‘truncated-print’ (see Pretty Printing).
          The resulting code will be formatted to fit
          within WIDTH columns (79 by default), on a single line.  The
          output will be truncated if necessary.

          ~:@y is like ~@y, except the WIDTH parameter is interpreted to
          be the maximum column to which to output.  That is to say, if
          you are at column 10, and ~60:@y is seen, the datum will be
          truncated to 50 columns.

     ~?
     ~k
          Sub-format.  No parameters.

          Take a format string argument and a second argument which is a
          list of arguments for that string, and output the result.

               (format #t "~?" "~d ~d" '(1 2))    ⊣ 1 2

          ~@?  takes arguments for the sub-format directly rather than
          in a list.

               (format #t "~@? ~s" "~d ~d" 1 2 "foo") ⊣ 1 2 "foo"

          ~?  and ~k are the same, ~k is provided for T-Scheme
          compatibility.

     ~*
          Argument jumping.  Parameter: N.

          Move forward N arguments (default 1) in the argument list.
          ~:* moves backwards.  (N cannot be negative.)

               (format #f "~d ~2*~d" 1 2 3 4) ⇒ "1 4"
               (format #f "~d ~:*~d" 6)       ⇒ "6 6"

          ~@* moves to argument number N.  The first argument is number
          0 (and that's the default for N).

               (format #f "~d~d again ~@*~d~d" 1 2) ⇒ "12 again 12"
               (format #f "~d~d~d ~1@*~d~d" 1 2 3)  ⇒ "123 23"

          A # move to the end followed by a : modifier move back can be
          used for an absolute position relative to the end of the
          argument list, a reverse of what the @ modifier does.

               (format #t "~#*~2:*~a" 'a 'b 'c 'd)   ⊣ c

          At the end of the format string the current argument position
          doesn't matter, any further arguments are ignored.

     ~t
          Advance to a column position.  Parameters: COLNUM, COLINC,
          PADCHAR.

          Output PADCHAR (space by default) to move to the given COLNUM
          column.  The start of the line is column 0, the default for
          COLNUM is 1.

               (format #f "~tX")  ⇒ " X"
               (format #f "~3tX") ⇒ "   X"

          If the current column is already past COLNUM, then the move is
          to there plus a multiple of COLINC, ie. column COLNUM + N *
          COLINC for the smallest N which makes that value greater than
          or equal to the current column.  The default COLINC is 1
          (which means no further move).

               (format #f "abcd~2,5,'.tx") ⇒ "abcd...x"

          ~@t takes COLNUM as an offset from the current column.  COLNUM
          many pad characters are output, then further padding to make
          the current column a multiple of COLINC, if it isn't already
          so.

               (format #f "a~3,5'*@tx") ⇒ "a****x"

          ~t is implemented using ‘port-column’ (see Textual I/O),
          so it works even there has been other output before ‘format’.

     ~~
          Tilde character.  Parameter: N.

          Output a tilde character ~, or N many if a parameter is given.
          Normally ~ introduces an escape sequence, ~~ is the way to
          output a literal tilde.

     ~%
          Newline.  Parameter: N.

          Output a newline character, or N many if a parameter is given.
          A newline (or a few newlines) can of course be output just by
          including them in the format string.

     ~&
          Start a new line.  Parameter: N.

          Output a newline if not already at the start of a line.  With
          a parameter, output that many newlines, but with the first
          only if not already at the start of a line.  So for instance 3
          would be a newline if not already at the start of a line, and
          2 further newlines.

     ~_
          Space character.  Parameter: N.

          Output a space character, or N many if a parameter is given.

          With a variable parameter this is one way to insert runtime
          calculated padding (~t or the various field widths can do
          similar things).

               (format #f "~v_foo" 4) ⇒ "    foo"

     ~/
          Tab character.  Parameter: N.

          Output a tab character, or N many if a parameter is given.

     ~|
          Formfeed character.  Parameter: N.

          Output a formfeed character, or N many if a parameter is
          given.

     ~!
          Force output.  No parameters.

          At the end of output, call ‘force-output’ to flush any buffers
          on the destination (see Buffering).  ~!  can occur
          anywhere in the format string, but the force is done at the
          end of output.

          When output is to a string (destination ‘#f’), ~!  does
          nothing.

     ~newline (ie. newline character)
          Continuation line.  No parameters.

          Skip this newline and any following whitespace in the format
          string, ie. don't send it to the output.  This can be used to
          break up a long format string for readability, but not print
          the extra whitespace.

               (format #f "abc~
                           ~d def~
                           ~d" 1 2) ⇒ "abc1 def2"

          ~:newline skips the newline but leaves any further whitespace
          to be printed normally.

          ~@newline prints the newline then skips following whitespace.

     ~( ~)
          Case conversion.  No parameters.

          Between ~( and ~) the case of all output is changed.  The
          modifiers on ~( control the conversion.

               ~( -- lower case.
               ~:@( -- upper case.

          For example,

               (format #t "~(Hello~)")   ⊣ hello
               (format #t "~:@(Hello~)") ⊣ HELLO

          In the future it's intended the modifiers : and @ alone will
          capitalize the first letters of words, as per Common Lisp
          ‘format’, but the current implementation of this is flawed and
          not recommended for use.

          Case conversions do not nest, currently.  This might change in
          the future, but if it does then it will be to Common Lisp
          style where the outermost conversion has priority, overriding
          inner ones (making those fairly pointless).

     ~{ ~}
          Iteration.  Parameter: MAXREPS (for ~{).

          The format between ~{ and ~} is iterated.  The modifiers to ~{
          determine how arguments are taken.  The default is a list
          argument with each iteration successively consuming elements
          from it.  This is a convenient way to output a whole list.

               (format #t "~{~d~}"     '(1 2 3))       ⊣ 123
               (format #t "~{~s=~d ~}" '("x" 1 "y" 2)) ⊣ "x"=1 "y"=2

          ~:{ takes a single argument which is a list of lists, each of
          those contained lists gives the arguments for the iterated
          format.

               (format #t "~:{~dx~d ~}" '((1 2) (3 4) (5 6)))
               ⊣ 1x2 3x4 5x6

          ~@{ takes arguments directly, with each iteration successively
          consuming arguments.

               (format #t "~@{~d~}"     1 2 3)       ⊣ 123
               (format #t "~@{~s=~d ~}" "x" 1 "y" 2) ⊣ "x"=1 "y"=2

          ~:@{ takes list arguments, one argument for each iteration,
          using that list for the format.

               (format #t "~:@{~dx~d ~}" '(1 2) '(3 4) '(5 6))
               ⊣ 1x2 3x4 5x6

          Iterating stops when there are no more arguments or when the
          MAXREPS parameter to ~{ is reached (default no maximum).

               (format #t "~2{~d~}" '(1 2 3 4)) ⊣ 12

          If the format between ~{ and ~} is empty, then a format string
          argument is taken (before iteration argument(s)) and used
          instead.  This allows a sub-format (like ~?  above) to be
          iterated.

               (format #t "~{~}" "~d" '(1 2 3)) ⊣ 123

          Iterations can be nested, an inner iteration operates in the
          same way as described, but of course on the arguments the
          outer iteration provides it.  This can be used to work into
          nested list structures.  For example in the following the
          inner ~{~d~}x is applied to ‘(1 2)’ then ‘(3 4 5)’ etc.

               (format #t "~{~{~d~}x~}" '((1 2) (3 4 5))) ⊣ 12x345x

          See also ~^ below for escaping from iteration.

     ~[ ~; ~]
          Conditional.  Parameter: SELECTOR.

          A conditional block is delimited by ~[ and ~], and ~;
          separates clauses within the block.  ~[ takes an integer
          argument and that number clause is used.  The first clause is
          number 0.

               (format #f "~[peach~;banana~;mango~]" 1)  ⇒ "banana"

          The SELECTOR parameter can be used for the clause number,
          instead of taking an argument.

               (format #f "~2[peach~;banana~;mango~]") ⇒ "mango"

          If the clause number is out of range then nothing is output.
          Or the last clause can be ~:; to use that for a number out of
          range.

               (format #f "~[banana~;mango~]"         99) ⇒ ""
               (format #f "~[banana~;mango~:;fruit~]" 99) ⇒ "fruit"

          ~:[ treats the argument as a flag, and expects two clauses.
          The first is used if the argument is ‘#f’ or the second
          otherwise.

               (format #f "~:[false~;not false~]" #f)   ⇒ "false"
               (format #f "~:[false~;not false~]" 'abc) ⇒ "not false"

               (let ((n 3))
                 (format #t "~d gnu~:[s are~; is~] here" n (= 1 n)))
               ⊣ 3 gnus are here

          ~@[ also treats the argument as a flag, and expects one
          clause.  If the argument is ‘#f’ then no output is produced
          and the argument is consumed, otherwise the clause is used and
          the argument is not consumed, it's left for the clause.  This
          can be used for instance to suppress output if ‘#f’ means
          something not available.

               (format #f "~@[temperature=~d~]" 27) ⇒ "temperature=27"
               (format #f "~@[temperature=~d~]" #f) ⇒ ""

     ~^
          Escape.  Parameters: VAL1, VAL2, VAL3.

          Stop formatting if there are no more arguments.  This can be
          used for instance to have a format string adapt to a variable
          number of arguments.

               (format #t "~d~^ ~d" 1)   ⊣ 1
               (format #t "~d~^ ~d" 1 2) ⊣ 1 2

          Within a ~{ ~} iteration, ~^ stops the current iteration step
          if there are no more arguments to that step, but continuing
          with possible further steps and the rest of the format.  This
          can be used for instance to avoid a separator on the last
          iteration, or to adapt to variable length argument lists.

               (format #f "~{~d~^/~} go"    '(1 2 3))     ⇒ "1/2/3 go"
               (format #f "~:{ ~d~^~d~} go" '((1) (2 3))) ⇒ " 1 23 go"

          Within a ~?  sub-format, ~^ operates just on that sub-format.
          If it terminates the sub-format then the originating format
          will still continue.

               (format #t "~? items" "~d~^ ~d" '(1))   ⊣ 1 items
               (format #t "~? items" "~d~^ ~d" '(1 2)) ⊣ 1 2 items

          The parameters to ~^ (which are numbers) change the condition
          used to terminate.  For a single parameter, termination is
          when that value is zero (notice this makes plain ~^ equivalent
          to ~#^).  For two parameters, termination is when those two
          are equal.  For three parameters, termination is when VAL1 <=
          VAL2 and VAL2 <= VAL3.

     ~q
          Inquiry message.  Insert a copyright message into the output.

          ~:q inserts the format implementation version.

     It's an error if there are not enough arguments for the escapes in
     the format string, but any excess arguments are ignored.

     Iterations ~{ ~} and conditionals ~[ ~; ~] can be nested, but must
     be properly nested, meaning the inner form must be entirely within
     the outer form.  So it's not possible, for instance, to try to
     conditionalize the endpoint of an iteration.

          (format #t "~{ ~[ ... ~] ~}" ...)       ;; good
          (format #t "~{ ~[ ... ~} ... ~]" ...)   ;; bad

     The same applies to case conversions ~( ~), they must properly nest
     with respect to iterations and conditionals (though currently a
     case conversion cannot nest within another case conversion).

     When a sub-format (~?)  is used, that sub-format string must be
     self-contained.  It cannot for instance give a ~{ to begin an
     iteration form and have the ~} up in the originating format, or
     similar.

   Guile contains a ‘format’ procedure even when the module ‘(ice-9
format)’ is not loaded.  The default ‘format’ is ‘simple-format’ (see
Simple Output), it doesn't support all escape sequences documented in
this section, and will signal an error if you try to use one of them.
The reason for two versions is that the full ‘format’ is fairly large
and requires some time to load.  ‘simple-format’ is often adequate too.

     Note: Beware that when ‘(ice-9 format)’ is loaded, it replaces the
     binding for ‘format’ on the toplevel.  If your module loads another
     module that loads ‘(ice-9 format)’, then your module will see the
     ‘format’ function from ‘(ice-9 format)’, even if it does not itself
     import ‘(ice-9 format)’.

     _This is legacy behavior and may be removed in a future Guile
     version._

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

   (1) The ~h format specifier first appeared in Guile version 2.0.6.

7.12 File Tree Walk
===================

The functions in this section traverse a tree of files and directories.
They come in two flavors: the first one is a high-level functional
interface, and the second one is similar to the C ‘ftw’ and ‘nftw’
routines (see Working with Directory Trees (libc)).

     (use-modules (ice-9 ftw))

 -- Scheme Procedure: file-system-tree file-name [enter? [stat]]
     Return a tree of the form ‘(FILE-NAME STAT CHILDREN ...)’ where
     STAT is the result of ‘(STAT FILE-NAME)’ and CHILDREN are similar
     structures for each file contained in FILE-NAME when it designates
     a directory.

     The optional ENTER? predicate is invoked as ‘(ENTER? NAME STAT)’
     and should return true to allow recursion into directory NAME; the
     default value is a procedure that always returns ‘#t’.  When a
     directory does not match ENTER?, it nonetheless appears in the
     resulting tree, only with zero children.

     The STAT argument is optional and defaults to ‘lstat’, as for
     ‘file-system-fold’ (see below.)

     The example below shows how to obtain a hierarchical listing of the
     files under the ‘module/language’ directory in the Guile source
     tree, discarding their ‘stat’ info:

          (use-modules (ice-9 match))

          (define remove-stat
            ;; Remove the `stat' object the `file-system-tree' provides
            ;; for each file in the tree.
            (match-lambda
              ((name stat)              ; flat file
               name)
              ((name stat children ...) ; directory
               (list name (map remove-stat children)))))

          (let ((dir (string-append (assq-ref %guile-build-info 'top_srcdir)
                                    "/module/language")))
            (remove-stat (file-system-tree dir)))

          ⇒
          ("language"
           (("value" ("spec.go" "spec.scm"))
            ("scheme"
             ("spec.go"
              "spec.scm"
              "compile-tree-il.scm"
              "decompile-tree-il.scm"
              "decompile-tree-il.go"
              "compile-tree-il.go"))
            ("tree-il"
             ("spec.go"
              "fix-letrec.go"
              "inline.go"
              "fix-letrec.scm"
              "compile-glil.go"
              "spec.scm"
              "optimize.scm"
              "primitives.scm"
              ...))
            ...))

   It is often desirable to process directories entries directly, rather
than building up a tree of entries in memory, like ‘file-system-tree’
does.  The following procedure, a “combinator”, is designed to allow
directory entries to be processed directly as a directory tree is
traversed; in fact, ‘file-system-tree’ is implemented in terms of it.

 -- Scheme Procedure: file-system-fold enter? leaf down up skip error
          init file-name [stat]
     Traverse the directory at FILE-NAME, recursively, and return the
     result of the successive applications of the LEAF, DOWN, UP, and
     SKIP procedures as described below.

     Enter sub-directories only when ‘(ENTER? PATH STAT RESULT)’ returns
     true.  When a sub-directory is entered, call ‘(DOWN PATH STAT
     RESULT)’, where PATH is the path of the sub-directory and STAT the
     result of ‘(false-if-exception (STAT PATH))’; when it is left, call
     ‘(UP PATH STAT RESULT)’.

     For each file in a directory, call ‘(LEAF PATH STAT RESULT)’.

     When ENTER? returns ‘#f’, or when an unreadable directory is
     encountered, call ‘(SKIP PATH STAT RESULT)’.

     When FILE-NAME names a flat file, ‘(LEAF PATH STAT INIT)’ is
     returned.

     When an ‘opendir’ or STAT call fails, call ‘(ERROR PATH STAT ERRNO
     RESULT)’, with ERRNO being the operating system error number that
     was raised--e.g., ‘EACCES’--and STAT either ‘#f’ or the result of
     the STAT call for that entry, when available.

     The special ‘.’ and ‘..’ entries are not passed to these
     procedures.  The PATH argument to the procedures is a full file
     name--e.g., ‘"../foo/bar/gnu"’; if FILE-NAME is an absolute file
     name, then PATH is also an absolute file name.  Files and
     directories, as identified by their device/inode number pair, are
     traversed only once.

     The optional STAT argument defaults to ‘lstat’, which means that
     symbolic links are not followed; the ‘stat’ procedure can be used
     instead when symbolic links are to be followed (see stat).

     The example below illustrates the use of ‘file-system-fold’:

          (define (total-file-size file-name)
            "Return the size in bytes of the files under FILE-NAME (similar
          to `du --apparent-size' with GNU Coreutils.)"

            (define (enter? name stat result)
              ;; Skip version control directories.
              (not (member (basename name) '(".git" ".svn" "CVS"))))
            (define (leaf name stat result)
              ;; Return RESULT plus the size of the file at NAME.
              (+ result (stat:size stat)))

            ;; Count zero bytes for directories.
            (define (down name stat result) result)
            (define (up name stat result) result)

            ;; Likewise for skipped directories.
            (define (skip name stat result) result)

            ;; Ignore unreadable files/directories but warn the user.
            (define (error name stat errno result)
              (format (current-error-port) "warning: ~a: ~a~%"
                      name (strerror errno))
              result)

            (file-system-fold enter? leaf down up skip error
                                     0  ; initial counter is zero bytes
                                     file-name))

          (total-file-size ".")
          ⇒ 8217554

          (total-file-size "/dev/null")
          ⇒ 0

   The alternative C-like functions are described below.

 -- Scheme Procedure: scandir name [select? [entry<?]]
     Return the list of the names of files contained in directory NAME
     that match predicate SELECT? (by default, all files).  The returned
     list of file names is sorted according to ENTRY<?, which defaults
     to ‘string-locale<?’ such that file names are sorted in the
     locale's alphabetical order (see Text Collation).  Return ‘#f’
     when NAME is unreadable or is not a directory.

     This procedure is modeled after the C library function of the same
     name (see Scanning Directory Content (libc)).

 -- Scheme Procedure: ftw startname proc ['hash-size n]
     Walk the file system tree descending from STARTNAME, calling PROC
     for each file and directory.

     Hard links and symbolic links are followed.  A file or directory is
     reported to PROC only once, and skipped if seen again in another
     place.  One consequence of this is that ‘ftw’ is safe against
     circularly linked directory structures.

     Each PROC call is ‘(PROC filename statinfo flag)’ and it should
     return ‘#t’ to continue, or any other value to stop.

     FILENAME is the item visited, being STARTNAME plus a further path
     and the name of the item.  STATINFO is the return from ‘stat’
     (see File System) on FILENAME.  FLAG is one of the following
     symbols,

     ‘regular’
          FILENAME is a file, this includes special files like devices,
          named pipes, etc.

     ‘directory’
          FILENAME is a directory.

     ‘invalid-stat’
          An error occurred when calling ‘stat’, so nothing is known.
          STATINFO is ‘#f’ in this case.

     ‘directory-not-readable’
          FILENAME is a directory, but one which cannot be read and
          hence won't be recursed into.

     ‘symlink’
          FILENAME is a dangling symbolic link.  Symbolic links are
          normally followed and their target reported, the link itself
          is reported if the target does not exist.

     The return value from ‘ftw’ is ‘#t’ if it ran to completion, or
     otherwise the non-‘#t’ value from PROC which caused the stop.

     Optional argument symbol ‘hash-size’ and an integer can be given to
     set the size of the hash table used to track items already visited.
     (see Hash Table Reference)

     In the current implementation, returning non-‘#t’ from PROC is the
     only valid way to terminate ‘ftw’.  PROC must not use ‘throw’ or
     similar to escape.

 -- Scheme Procedure: nftw startname proc ['chdir] ['depth] ['hash-size
          n] ['mount] ['physical]
     Walk the file system tree starting at STARTNAME, calling PROC for
     each file and directory.  ‘nftw’ has extra features over the basic
     ‘ftw’ described above.

     Like ‘ftw’, hard links and symbolic links are followed.  A file or
     directory is reported to PROC only once, and skipped if seen again
     in another place.  One consequence of this is that ‘nftw’ is safe
     against circular linked directory structures.

     Each PROC call is ‘(PROC filename statinfo flag base level)’ and it
     should return ‘#t’ to continue, or any other value to stop.

     FILENAME is the item visited, being STARTNAME plus a further path
     and the name of the item.  STATINFO is the return from ‘stat’ on
     FILENAME (see File System).  BASE is an integer offset into
     FILENAME which is where the basename for this item begins.  LEVEL
     is an integer giving the directory nesting level, starting from 0
     for the contents of STARTNAME (or that item itself if it's a file).
     FLAG is one of the following symbols,

     ‘regular’
          FILENAME is a file, including special files like devices,
          named pipes, etc.

     ‘directory’
          FILENAME is a directory.

     ‘directory-processed’
          FILENAME is a directory, and its contents have all been
          visited.  This flag is given instead of ‘directory’ when the
          ‘depth’ option below is used.

     ‘invalid-stat’
          An error occurred when applying ‘stat’ to FILENAME, so nothing
          is known about it.  STATINFO is ‘#f’ in this case.

     ‘directory-not-readable’
          FILENAME is a directory, but one which cannot be read and
          hence won't be recursed into.

     ‘stale-symlink’
          FILENAME is a dangling symbolic link.  Links are normally
          followed and their target reported, the link itself is
          reported if its target does not exist.

     ‘symlink’
          When the ‘physical’ option described below is used, this
          indicates FILENAME is a symbolic link whose target exists (and
          is not being followed).

     The following optional arguments can be given to modify the way
     ‘nftw’ works.  Each is passed as a symbol (and ‘hash-size’ takes a
     following integer value).

     ‘chdir’
          Change to the directory containing the item before calling
          PROC.  When ‘nftw’ returns the original current directory is
          restored.

          Under this option, generally the BASE parameter to each PROC
          call should be used to pick out the base part of the FILENAME.
          The FILENAME is still a path but with a changed directory it
          won't be valid (unless the STARTNAME directory was absolute).

     ‘depth’
          Visit files "depth first", meaning PROC is called for the
          contents of each directory before it's called for the
          directory itself.  Normally a directory is reported first,
          then its contents.

          Under this option, the FLAG to PROC for a directory is
          ‘directory-processed’ instead of ‘directory’.

     ‘hash-size N’
          Set the size of the hash table used to track items already
          visited.  (see Hash Table Reference)

     ‘mount’
          Don't cross a mount point, meaning only visit items on the
          same file system as STARTNAME (ie. the same ‘stat:dev’).

     ‘physical’
          Don't follow symbolic links, instead report them to PROC as
          ‘symlink’.  Dangling links (those whose target doesn't exist)
          are still reported as ‘stale-symlink’.

     The return value from ‘nftw’ is ‘#t’ if it ran to completion, or
     otherwise the non-‘#t’ value from PROC which caused the stop.

     In the current implementation, returning non-‘#t’ from PROC is the
     only valid way to terminate ‘ftw’.  PROC must not use ‘throw’ or
     similar to escape.

7.13 Queues
===========

The functions in this section are provided by

     (use-modules (ice-9 q))

   This module implements queues holding arbitrary scheme objects and
designed for efficient first-in / first-out operations.

   ‘make-q’ creates a queue, and objects are entered and removed with
‘enq!’ and ‘deq!’.  ‘q-push!’ and ‘q-pop!’ can be used too, treating the
front of the queue like a stack.

 -- Scheme Procedure: make-q
     Return a new queue.

 -- Scheme Procedure: q? obj
     Return ‘#t’ if OBJ is a queue, or ‘#f’ if not.

     Note that queues are not a distinct class of objects but are
     implemented with cons cells.  For that reason certain list
     structures can get ‘#t’ from ‘q?’.

 -- Scheme Procedure: enq! q obj
     Add OBJ to the rear of Q, and return Q.

 -- Scheme Procedure: deq! q
 -- Scheme Procedure: q-pop! q
     Remove and return the front element from Q.  If Q is empty, a
     ‘q-empty’ exception is thrown.

     ‘deq!’ and ‘q-pop!’ are the same operation, the two names just let
     an application match ‘enq!’ with ‘deq!’, or ‘q-push!’ with
     ‘q-pop!’.

 -- Scheme Procedure: q-push! q obj
     Add OBJ to the front of Q, and return Q.

 -- Scheme Procedure: q-length q
     Return the number of elements in Q.

 -- Scheme Procedure: q-empty? q
     Return true if Q is empty.

 -- Scheme Procedure: q-empty-check q
     Throw a ‘q-empty’ exception if Q is empty.

 -- Scheme Procedure: q-front q
     Return the first element of Q (without removing it).  If Q is
     empty, a ‘q-empty’ exception is thrown.

 -- Scheme Procedure: q-rear q
     Return the last element of Q (without removing it).  If Q is empty,
     a ‘q-empty’ exception is thrown.

 -- Scheme Procedure: q-remove! q obj
     Remove all occurrences of OBJ from Q, and return Q.  OBJ is
     compared to queue elements using ‘eq?’.

   The ‘q-empty’ exceptions described above are thrown just as ‘(throw
'q-empty)’, there's no message etc like an error throw.

   A queue is implemented as a cons cell, the ‘car’ containing a list of
queued elements, and the ‘cdr’ being the last cell in that list (for
ease of enqueuing).

     (LIST . LAST-CELL)

If the queue is empty, LIST is the empty list and LAST-CELL is ‘#f’.

   An application can directly access the queue list if desired, for
instance to search the elements or to insert at a specific point.

 -- Scheme Procedure: sync-q! q
     Recompute the LAST-CELL field in Q.

     All the operations above maintain LAST-CELL as described, so
     normally there's no need for ‘sync-q!’.  But if an application
     modifies the queue LIST then it must either maintain LAST-CELL
     similarly, or call ‘sync-q!’ to recompute it.

7.14 Streams
============

This section documents Guile's legacy stream module.  For a more
complete and portable stream library, see SRFI-41.

   A stream represents a sequence of values, each of which is calculated
only when required.  This allows large or even infinite sequences to be
represented and manipulated with familiar operations like "car", "cdr",
"map" or "fold".  In such manipulations only as much as needed is
actually held in memory at any one time.  The functions in this section
are available from

     (use-modules (ice-9 streams))

   Streams are implemented using promises (see Delayed Evaluation),
which is how the underlying calculation of values is made only when
needed, and the values then retained so the calculation is not repeated.

Here is a simple example producing a stream of all odd numbers,

     (define odds (make-stream (lambda (state)
                                 (cons state (+ state 2)))
                               1))
     (stream-car odds)              ⇒ 1
     (stream-car (stream-cdr odds)) ⇒ 3

‘stream-map’ could be used to derive a stream of odd squares,

     (define (square n) (* n n))
     (define oddsquares (stream-map square odds))

   These are infinite sequences, so it's not possible to convert them to
a list, but they could be printed (infinitely) with for example

     (stream-for-each (lambda (n sq)
                        (format #t "~a squared is ~a\n" n sq))
                      odds oddsquares)
     ⊣
     1 squared is 1
     3 squared is 9
     5 squared is 25
     7 squared is 49
     ...

 -- Scheme Procedure: make-stream proc initial-state
     Return a new stream, formed by calling PROC successively.

     Each call is ‘(PROC STATE)’, it should return a pair, the ‘car’
     being the value for the stream, and the ‘cdr’ being the new STATE
     for the next call.  For the first call STATE is the given
     INITIAL-STATE.  At the end of the stream, PROC should return some
     non-pair object.

 -- Scheme Procedure: stream-car stream
     Return the first element from STREAM.  STREAM must not be empty.

 -- Scheme Procedure: stream-cdr stream
     Return a stream which is the second and subsequent elements of
     STREAM.  STREAM must not be empty.

 -- Scheme Procedure: stream-null? stream
     Return true if STREAM is empty.

 -- Scheme Procedure: list->stream list
 -- Scheme Procedure: vector->stream vector
     Return a stream with the contents of LIST or VECTOR.

     LIST or VECTOR should not be modified subsequently, since it's
     unspecified whether changes there will be reflected in the stream
     returned.

 -- Scheme Procedure: port->stream port readproc
     Return a stream which is the values obtained by reading from PORT
     using READPROC.  Each read call is ‘(READPROC PORT)’, and it should
     return an EOF object (see Binary I/O) at the end of input.

     For example a stream of characters from a file,

          (port->stream (open-input-file "/foo/bar.txt") read-char)

 -- Scheme Procedure: stream->list stream
     Return a list which is the entire contents of STREAM.

 -- Scheme Procedure: stream->reversed-list stream
     Return a list which is the entire contents of STREAM, but in
     reverse order.

 -- Scheme Procedure: stream->list&length stream
     Return two values (see Multiple Values), being firstly a list
     which is the entire contents of STREAM, and secondly the number of
     elements in that list.

 -- Scheme Procedure: stream->reversed-list&length stream
     Return two values (see Multiple Values) being firstly a list
     which is the entire contents of STREAM, but in reverse order, and
     secondly the number of elements in that list.

 -- Scheme Procedure: stream->vector stream
     Return a vector which is the entire contents of STREAM.

 -- Function: stream-fold proc init stream1 stream2 ...
     Apply PROC successively over the elements of the given streams,
     from first to last until the end of the shortest stream is reached.
     Return the result from the last PROC call.

     Each call is ‘(PROC elem1 elem2 ... prev)’, where each ELEM is from
     the corresponding STREAM.  PREV is the return from the previous
     PROC call, or the given INIT for the first call.

 -- Function: stream-for-each proc stream1 stream2 ...
     Call PROC on the elements from the given STREAMs.  The return value
     is unspecified.

     Each call is ‘(PROC elem1 elem2 ...)’, where each ELEM is from the
     corresponding STREAM.  ‘stream-for-each’ stops when it reaches the
     end of the shortest STREAM.

 -- Function: stream-map proc stream1 stream2 ...
     Return a new stream which is the results of applying PROC to the
     elements of the given STREAMs.

     Each call is ‘(PROC elem1 elem2 ...)’, where each ELEM is from the
     corresponding STREAM.  The new stream ends when the end of the
     shortest given STREAM is reached.

7.15 Buffered Input
===================

The following functions are provided by

     (use-modules (ice-9 buffered-input))

   A buffered input port allows a reader function to return chunks of
characters which are to be handed out on reading the port.  A notion of
further input for an application level logical expression is maintained
too, and passed through to the reader.

 -- Scheme Procedure: make-buffered-input-port reader
     Create an input port which returns characters obtained from the
     given READER function.  READER is called (READER cont), and should
     return a string or an EOF object.

     The new port gives precisely the characters returned by READER,
     nothing is added, so if any newline characters or other separators
     are desired they must come from the reader function.

     The CONT parameter to READER is ‘#f’ for initial input, or ‘#t’
     when continuing an expression.  This is an application level
     notion, set with ‘set-buffered-input-continuation?!’ below.  If the
     user has entered a partial expression then it allows READER for
     instance to give a different prompt to show more is required.

 -- Scheme Procedure: make-line-buffered-input-port reader
     Create an input port which returns characters obtained from the
     specified READER function, similar to ‘make-buffered-input-port’
     above, but where READER is expected to be a line-oriented.

     READER is called (READER cont), and should return a string or an
     EOF object as above.  Each string is a line of input without a
     newline character, the port code inserts a newline after each
     string.

 -- Scheme Procedure: set-buffered-input-continuation?! port cont
     Set the input continuation flag for a given buffered input PORT.

     An application uses this by calling with a CONT flag of ‘#f’ when
     beginning to read a new logical expression.  For example with the
     Scheme ‘read’ function (see Scheme Read),

          (define my-port (make-buffered-input-port my-reader))

          (set-buffered-input-continuation?! my-port #f)
          (let ((obj (read my-port)))
            ...

7.16 Expect
===========

The macros in this section are made available with:

     (use-modules (ice-9 expect))

   ‘expect’ is a macro for selecting actions based on the output from a
port.  The name comes from a tool of similar functionality by Don Libes.
Actions can be taken when a particular string is matched, when a timeout
occurs, or when end-of-file is seen on the port.  The ‘expect’ macro is
described below; ‘expect-strings’ is a front-end to ‘expect’ based on
regexec (see the regular expression documentation).

 -- Macro: expect-strings clause ...
     By default, ‘expect-strings’ will read from the current input port.
     The first term in each clause consists of an expression evaluating
     to a string pattern (regular expression).  As characters are read
     one-by-one from the port, they are accumulated in a buffer string
     which is matched against each of the patterns.  When a pattern
     matches, the remaining expression(s) in the clause are evaluated
     and the value of the last is returned.  For example:

          (with-input-from-file "/etc/passwd"
            (lambda ()
              (expect-strings
                ("^nobody" (display "Got a nobody user.\n")
                           (display "That's no problem.\n"))
                ("^daemon" (display "Got a daemon user.\n")))))

     The regular expression is compiled with the ‘REG_NEWLINE’ flag, so
     that the ^ and $ anchors will match at any newline, not just at the
     start and end of the string.

     There are two other ways to write a clause:

     The expression(s) to evaluate can be omitted, in which case the
     result of the regular expression match (converted to strings, as
     obtained from regexec with match-pick set to "") will be returned
     if the pattern matches.

     The symbol ‘=>’ can be used to indicate that the expression is a
     procedure which will accept the result of a successful regular
     expression match.  E.g.,

          ("^daemon" => write)
          ("^d(aemon)" => (lambda args (for-each write args)))
          ("^da(em)on" => (lambda (all sub)
                            (write all) (newline)
                            (write sub) (newline)))

     The order of the substrings corresponds to the order in which the
     opening brackets occur.

     A number of variables can be used to control the behavior of
     ‘expect’ (and ‘expect-strings’).  Most have default top-level
     bindings to the value ‘#f’, which produces the default behavior.
     They can be redefined at the top level or locally bound in a form
     enclosing the expect expression.

     ‘expect-port’
          A port to read characters from, instead of the current input
          port.
     ‘expect-timeout’
          ‘expect’ will terminate after this number of seconds,
          returning ‘#f’ or the value returned by expect-timeout-proc.
     ‘expect-timeout-proc’
          A procedure called if timeout occurs.  The procedure takes a
          single argument: the accumulated string.
     ‘expect-eof-proc’
          A procedure called if end-of-file is detected on the input
          port.  The procedure takes a single argument: the accumulated
          string.
     ‘expect-char-proc’
          A procedure to be called every time a character is read from
          the port.  The procedure takes a single argument: the
          character which was read.
     ‘expect-strings-compile-flags’
          Flags to be used when compiling a regular expression, which
          are passed to ‘make-regexp’ Regexp Functions.  The
          default value is ‘regexp/newline’.
     ‘expect-strings-exec-flags’
          Flags to be used when executing a regular expression, which
          are passed to regexp-exec Regexp Functions.  The
          default value is ‘regexp/noteol’, which prevents ‘$’ from
          matching the end of the string while it is still accumulating,
          but still allows it to match after a line break or at the end
          of file.

     Here's an example using all of the variables:

          (let ((expect-port (open-input-file "/etc/passwd"))
                (expect-timeout 1)
                (expect-timeout-proc
                  (lambda (s) (display "Times up!\n")))
                (expect-eof-proc
                  (lambda (s) (display "Reached the end of the file!\n")))
                (expect-char-proc display)
                (expect-strings-compile-flags (logior regexp/newline regexp/icase))
                (expect-strings-exec-flags 0))
             (expect-strings
               ("^nobody"  (display "Got a nobody user\n"))))

 -- Macro: expect clause ...
     ‘expect’ is used in the same way as ‘expect-strings’, but tests are
     specified not as patterns, but as procedures.  The procedures are
     called in turn after each character is read from the port, with two
     arguments: the value of the accumulated string and a flag to
     indicate whether end-of-file has been reached.  The flag will
     usually be ‘#f’, but if end-of-file is reached, the procedures are
     called an additional time with the final accumulated string and
     ‘#t’.

     The test is successful if the procedure returns a non-false value.

     If the ‘=>’ syntax is used, then if the test succeeds it must
     return a list containing the arguments to be provided to the
     corresponding expression.

     In the following example, a string will only be matched at the
     beginning of the file:

          (let ((expect-port (open-input-file "/etc/passwd")))
            (expect
               ((lambda (s eof?) (string=? s "fnord!"))
                  (display "Got a nobody user!\n"))))

     The control variables described for ‘expect-strings’ also influence
     the behavior of ‘expect’, with the exception of variables whose
     names begin with ‘expect-strings-’.

7.17 ‘sxml-match’: Pattern Matching of SXML
===========================================

The ‘(sxml match)’ module provides syntactic forms for pattern matching
of SXML trees, in a "by example" style reminiscent of the pattern
matching of the ‘syntax-rules’ and ‘syntax-case’ macro systems.  See
SXML, for more information on SXML.

   The following example(1) provides a brief illustration, transforming
a music album catalog language into HTML.

     (define (album->html x)
       (sxml-match x
         ((album (@ (title ,t)) (catalog (num ,n) (fmt ,f)) ...)
          `(ul (li ,t)
               (li (b ,n) (i ,f)) ...))))

   Three macros are provided: ‘sxml-match’, ‘sxml-match-let’, and
‘sxml-match-let*’.

   Compared to a standard s-expression pattern matcher (see Pattern Matching),
‘sxml-match’ provides the following benefits:

   • matching of SXML elements does not depend on any degree of
     normalization of the SXML;
   • matching of SXML attributes (within an element) is under-ordered;
     the order of the attributes specified within the pattern need not
     match the ordering with the element being matched;
   • all attributes specified in the pattern must be present in the
     element being matched; in the spirit that XML is 'extensible', the
     element being matched may include additional attributes not
     specified in the pattern.

   The present module is a descendant of WebIt!, and was inspired by an
s-expression pattern matcher developed by Erik Hilsdale, Dan Friedman,
and Kent Dybvig at Indiana University.

Syntax
------

‘sxml-match’ provides ‘case’-like form for pattern matching of XML
nodes.

 -- Scheme Syntax: sxml-match input-expression clause1 clause2 ...
     Match INPUT-EXPRESSION, an SXML tree, according to the given
     CLAUSEs (one or more), each consisting of a pattern and one or more
     expressions to be evaluated if the pattern match succeeds.
     Optionally, each CLAUSE within ‘sxml-match’ may include a “guard
     expression”.

   The pattern notation is based on that of Scheme's ‘syntax-rules’ and
‘syntax-case’ macro systems.  The grammar for the ‘sxml-match’ syntax is
given below:

match-form ::= (sxml-match input-expression
                 clause+)

clause ::= [node-pattern action-expression+]
         | [node-pattern (guard expression*) action-expression+]

node-pattern ::= literal-pattern
               | pat-var-or-cata
               | element-pattern
               | list-pattern

literal-pattern ::= string
                  | character
                  | number
                  | #t
                  | #f

attr-list-pattern ::= (@ attribute-pattern*)
                    | (@ attribute-pattern* . pat-var-or-cata)

attribute-pattern ::= (tag-symbol attr-val-pattern)

attr-val-pattern ::= literal-pattern
                   | pat-var-or-cata
                   | (pat-var-or-cata default-value-expr)

element-pattern ::= (tag-symbol attr-list-pattern?)
                  | (tag-symbol attr-list-pattern? nodeset-pattern)
                  | (tag-symbol attr-list-pattern?
                                nodeset-pattern? . pat-var-or-cata)

list-pattern ::= (list nodeset-pattern)
               | (list nodeset-pattern? . pat-var-or-cata)
               | (list)

nodeset-pattern ::= node-pattern
                  | node-pattern ...
                  | node-pattern nodeset-pattern
                  | node-pattern ... nodeset-pattern

pat-var-or-cata ::= (unquote var-symbol)
                  | (unquote [var-symbol*])
                  | (unquote [cata-expression -> var-symbol*])

   Within a list or element body pattern, ellipses may appear only once,
but may be followed by zero or more node patterns.

   Guard expressions cannot refer to the return values of catamorphisms.

   Ellipses in the output expressions must appear only in an expression
context; ellipses are not allowed in a syntactic form.

   The sections below illustrate specific aspects of the ‘sxml-match’
pattern matcher.

Matching XML Elements
---------------------

The example below illustrates the pattern matching of an XML element:

     (sxml-match '(e (@ (i 1)) 3 4 5)
       ((e (@ (i ,d)) ,a ,b ,c) (list d a b c))
       (,otherwise #f))

   Each clause in ‘sxml-match’ contains two parts: a pattern and one or
more expressions which are evaluated if the pattern is successfully
match.  The example above matches an element ‘e’ with an attribute ‘i’
and three children.

   Pattern variables must be "unquoted" in the pattern.  The above
expression binds D to ‘1’, A to ‘3’, B to ‘4’, and C to ‘5’.

Ellipses in Patterns
--------------------

As in ‘syntax-rules’, ellipses may be used to specify a repeated
pattern.  Note that the pattern ‘item ...’ specifies zero-or-more
matches of the pattern ‘item’.

   The use of ellipses in a pattern is illustrated in the code fragment
below, where nested ellipses are used to match the children of repeated
instances of an ‘a’ element, within an element ‘d’.

     (define x '(d (a 1 2 3) (a 4 5) (a 6 7 8) (a 9 10)))

     (sxml-match x
       ((d (a ,b ...) ...)
        (list (list b ...) ...)))

   The above expression returns a value of ‘((1 2 3) (4 5) (6 7 8) (9
10))’.

Ellipses in Quasiquote'd Output
-------------------------------

Within the body of an ‘sxml-match’ form, a slightly extended version of
quasiquote is provided, which allows the use of ellipses.  This is
illustrated in the example below.

     (sxml-match '(e 3 4 5 6 7)
       ((e ,i ... 6 7) `("start" ,(list 'wrap i) ... "end"))
       (,otherwise #f))

   The general pattern is that ‘`(something ,i ...)’ is rewritten as
‘`(something ,@i)’.

Matching Nodesets
-----------------

A nodeset pattern is designated by a list in the pattern, beginning the
identifier list.  The example below illustrates matching a nodeset.

     (sxml-match '("i" "j" "k" "l" "m")
       ((list ,a ,b ,c ,d ,e)
        `((p ,a) (p ,b) (p ,c) (p ,d) (p ,e))))

   This example wraps each nodeset item in an HTML paragraph element.
This example can be rewritten and simplified through using ellipsis:

     (sxml-match '("i" "j" "k" "l" "m")
       ((list ,i ...)
        `((p ,i) ...)))

   This version will match nodesets of any length, and wrap each item in
the nodeset in an HTML paragraph element.

Matching the "Rest" of a Nodeset
--------------------------------

Matching the "rest" of a nodeset is achieved by using a ‘. rest)’
pattern at the end of an element or nodeset pattern.

   This is illustrated in the example below:

     (sxml-match '(e 3 (f 4 5 6) 7)
       ((e ,a (f . ,y) ,d)
        (list a y d)))

   The above expression returns ‘(3 (4 5 6) 7)’.

Matching the Unmatched Attributes
---------------------------------

Sometimes it is useful to bind a list of attributes present in the
element being matched, but which do not appear in the pattern.  This is
achieved by using a ‘. rest)’ pattern at the end of the attribute list
pattern.  This is illustrated in the example below:

     (sxml-match '(a (@ (z 1) (y 2) (x 3)) 4 5 6)
       ((a (@ (y ,www) . ,qqq) ,t ,u ,v)
        (list www qqq t u v)))

   The above expression matches the attribute ‘y’ and binds a list of
the remaining attributes to the variable QQQ.  The result of the above
expression is ‘(2 ((z 1) (x 3)) 4 5 6)’.

   This type of pattern also allows the binding of all attributes:

     (sxml-match '(a (@ (z 1) (y 2) (x 3)))
       ((a (@ . ,qqq))
        qqq))

Default Values in Attribute Patterns
------------------------------------

It is possible to specify a default value for an attribute which is used
if the attribute is not present in the element being matched.  This is
illustrated in the following example:

     (sxml-match '(e 3 4 5)
       ((e (@ (z (,d 1))) ,a ,b ,c) (list d a b c)))

   The value ‘1’ is used when the attribute ‘z’ is absent from the
element ‘e’.

Guards in Patterns
------------------

Guards may be added to a pattern clause via the ‘guard’ keyword.  A
guard expression may include zero or more expressions which are
evaluated only if the pattern is matched.  The body of the clause is
only evaluated if the guard expressions evaluate to ‘#t’.

   The use of guard expressions is illustrated below:

     (sxml-match '(a 2 3)
       ((a ,n) (guard (number? n)) n)
       ((a ,m ,n) (guard (number? m) (number? n)) (+ m n)))

Catamorphisms
-------------

The example below illustrates the use of explicit recursion within an
‘sxml-match’ form.  This example implements a simple calculator for the
basic arithmetic operations, which are represented by the XML elements
‘plus’, ‘minus’, ‘times’, and ‘div’.

     (define simple-eval
       (lambda (x)
         (sxml-match x
           (,i (guard (integer? i)) i)
           ((plus ,x ,y) (+ (simple-eval x) (simple-eval y)))
           ((times ,x ,y) (* (simple-eval x) (simple-eval y)))
           ((minus ,x ,y) (- (simple-eval x) (simple-eval y)))
           ((div ,x ,y) (/ (simple-eval x) (simple-eval y)))
           (,otherwise (error "simple-eval: invalid expression" x)))))

   Using the catamorphism feature of ‘sxml-match’, a more concise
version of ‘simple-eval’ can be written.  The pattern ‘,(x)’ recursively
invokes the pattern matcher on the value bound in this position.

     (define simple-eval
       (lambda (x)
         (sxml-match x
           (,i (guard (integer? i)) i)
           ((plus ,(x) ,(y)) (+ x y))
           ((times ,(x) ,(y)) (* x y))
           ((minus ,(x) ,(y)) (- x y))
           ((div ,(x) ,(y)) (/ x y))
           (,otherwise (error "simple-eval: invalid expression" x)))))

Named-Catamorphisms
-------------------

It is also possible to explicitly name the operator in the "cata"
position.  Where ‘,(id*)’ recurs to the top of the current ‘sxml-match’,
‘,(cata -> id*)’ recurs to ‘cata’.  ‘cata’ must evaluate to a procedure
which takes one argument, and returns as many values as there are
identifiers following ‘->’.

   Named catamorphism patterns allow processing to be split into
multiple, mutually recursive procedures.  This is illustrated in the
example below: a transformation that formats a "TV Guide" into HTML.

     (define (tv-guide->html g)
       (define (cast-list cl)
         (sxml-match cl
           ((CastList (CastMember (Character (Name ,ch)) (Actor (Name ,a))) ...)
            `(div (ul (li ,ch ": " ,a) ...)))))
       (define (prog p)
         (sxml-match p
           ((Program (Start ,start-time) (Duration ,dur) (Series ,series-title)
                     (Description ,desc ...))
            `(div (p ,start-time
                     (br) ,series-title
                     (br) ,desc ...)))
           ((Program (Start ,start-time) (Duration ,dur) (Series ,series-title)
                     (Description ,desc ...)
                     ,(cast-list -> cl))
            `(div (p ,start-time
                     (br) ,series-title
                     (br) ,desc ...)
                  ,cl))))
       (sxml-match g
         ((TVGuide (@ (start ,start-date)
                      (end ,end-date))
                   (Channel (Name ,nm) ,(prog -> p) ...) ...)
          `(html (head (title "TV Guide"))
                 (body (h1 "TV Guide")
                       (div (h2 ,nm) ,p ...) ...)))))

‘sxml-match-let’ and ‘sxml-match-let*’
--------------------------------------

 -- Scheme Syntax: sxml-match-let ((pat expr) ...) expression0
          expression ...
 -- Scheme Syntax: sxml-match-let* ((pat expr) ...) expression0
          expression ...
     These forms generalize the ‘let’ and ‘let*’ forms of Scheme to
     allow an XML pattern in the binding position, rather than a simple
     variable.

   For example, the expression below:

     (sxml-match-let (((a ,i ,j) '(a 1 2)))
       (+ i j))

   binds the variables I and J to ‘1’ and ‘2’ in the XML value given.

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

   (1) This example is taken from a paper by Krishnamurthi et al.  Their
paper was the first to show the usefulness of the ‘syntax-rules’ style
of pattern matching for transformation of XML, though the language
described, XT3D, is an XML language.

7.18 The Scheme shell (scsh)
============================

An incomplete port of the Scheme shell (scsh) was once available for
Guile as a separate package.  However this code has bitrotten somewhat.
The pieces are available in Guile's legacy CVS repository, which may be
browsed at
<http://cvs.savannah.gnu.org/viewvc/guile/guile-scsh/?root=guile>.

   For information about scsh see <http://www.scsh.net/>.

   This bitrotting is a bit of a shame, as there is a good deal of
well-written Scheme code in scsh.  Adopting this code and porting it to
current Guile should be an educational experience, in addition to
providing something of value to Guile folks.

7.19 Curried Definitions
========================

The macros in this section are provided by
     (use-modules (ice-9 curried-definitions))
and replace those provided by default.

   Prior to Guile 2.0, Guile provided a type of definition known
colloquially as a "curried definition".  The idea is to extend the
syntax of ‘define’ so that you can conveniently define procedures that
return procedures, up to any desired depth.

   For example,
     (define ((foo x) y)
       (list x y))
   is a convenience form of
     (define foo
       (lambda (x)
         (lambda (y)
           (list x y))))

 -- Scheme Syntax: define (... (name args ...) ...) body ...
 -- Scheme Syntax: define* (... (name args ...) ...) body ...
 -- Scheme Syntax: define-public (... (name args ...) ...) body ...

     Create a top level variable NAME bound to the procedure with
     parameter list ARGS.  If NAME is itself a formal parameter list,
     then a higher order procedure is created using that
     formal-parameter list, and returning a procedure that has parameter
     list ARGS.  This nesting may occur to arbitrary depth.

     ‘define*’ is similar but the formal parameter lists take additional
     options as described in lambda* and define*.  For example,
          (define* ((foo #:keys (bar 'baz) (quux 'zot)) frotz #:rest rest)
            (list bar quux frotz rest))

          ((foo #:quux 'foo) 1 2 3 4 5)
          ⇒ (baz foo 1 (2 3 4 5))

     ‘define-public’ is similar to ‘define’ but it also adds NAME to the
     list of exported bindings of the current module.

7.20 Statprof
=============

Statprof is a statistical profiler for Guile.

   A simple use of statprof would look like this:

     (use-modules (statprof))
     (statprof (lambda ()
                 (map 1+ (iota 1000000))
                 #f))

   This would run the thunk with statistical profiling, finally
displaying a flat table of statistics which could look something like
this:

     %     cumulative   self
     time   seconds     seconds  procedure
      57.14  39769.73      0.07  ice-9/boot-9.scm:249:5:map1
      28.57      0.04      0.04  ice-9/boot-9.scm:1165:0:iota
      14.29      0.02      0.02  1+
       0.00      0.12      0.00  <current input>:2:10
     ---
     Sample count: 7
     Total time: 0.123490713 seconds (0.201983993 seconds in GC)

   All of the numerical data with the exception of the calls column is
statistically approximate.  In the following column descriptions, and in
all of statprof, "time" refers to execution time (both user and system),
not wall clock time.

   The ‘% time’ column indicates the percentage of the run-time time
spent inside the procedure itself (not counting children).  It is
calculated as ‘self seconds’, measuring the amount of time spent in the
procedure, divided by the total run-time.

   ‘cumulative seconds’ also counts time spent in children of a
function.  For recursive functions, this can exceed the total time, as
in our example above, because each activation on the stack adds to the
cumulative time.

   Finally, the GC time measures the time spent in the garbage
collector.  On systems with multiple cores, this time can be larger than
the run time, because it counts time spent in all threads, and will run
the "marking" phase of GC in parallel.  If GC time is a significant
fraction of the run time, that means that most time in your program is
spent allocating objects and cleaning up after those allocations.  To
speed up your program, one good place to start would be to look at how
to reduce the allocation rate.

   Statprof's main mode of operation is as a statistical profiler.
However statprof can also run in a "precise" mode as well.  Pass the
‘#:count-calls? #t’ keyword argument to ‘statprof’ to record all calls:

     (use-modules (statprof))
     (statprof (lambda ()
                 (map 1+ (iota 1000000))
                 #f)
               #:count-calls? #t)

   The result has an additional ‘calls’ column:

     %     cumulative   self
     time   seconds    seconds   calls   procedure
      82.26      0.73      0.73 1000000  1+
      11.29 420925.80      0.10 1000001  ice-9/boot-9.scm:249:5:map1
       4.84      0.06      0.04       1  ice-9/boot-9.scm:1165:0:iota
     [...]
     ---
     Sample count: 62
     Total time: 0.893098065 seconds (1.222796536 seconds in GC)

   As you can see, the profile is perturbed: ‘1+’ ends up on top,
whereas it was not marked as hot in the earlier profile.  This is
because the overhead of call-counting unfairly penalizes calls.  Still,
this precise mode can be useful at times to do algorithmic optimizations
based on the precise call counts.

Implementation notes
====================

The profiler works by setting the unix profiling signal ‘ITIMER_PROF’ to
go off after the interval you define in the call to ‘statprof-reset’.
When the signal fires, a sampling routine runs which crawls up the
stack, recording all instruction pointers into a buffer.  After the
sample is complete, the profiler resets profiling timer to fire again
after the appropriate interval.

   Later, when profiling stops, that log buffer is analyzed to produce
the "self seconds" and "cumulative seconds" statistics.  A procedure at
the top of the stack counts toward "self" samples, and everything on the
stack counts towards "cumulative" samples.

   While the profiler is running it measures how much CPU time (system
and user - which is also what ‘ITIMER_PROF’ tracks) has elapsed while
code has been executing within the profiler.  Only run time counts
towards the profile, not wall-clock time.  For example, sleeping and
waiting for input or output do not cause the timer clock to advance.

Usage
=====

 -- Scheme Procedure: statprof thunk [#:loop loop=1] [#:hz hz=100]
          [#:port port=(current-output-port)] [#:count-calls?
          count-calls?=#f] [#:display-style display-style='flat]
     Profile the execution of THUNK, and return its return values.

     The stack will be sampled HZ times per second, and the thunk itself
     will be called LOOP times.

     If COUNT-CALLS? is true, all procedure calls will be recorded.
     This operation is somewhat expensive.

     After the THUNK has been profiled, print out a profile to PORT.  If
     DISPLAY-STYLE is ‘flat’, the results will be printed as a flat
     profile.  Otherwise if DISPLAY-STYLE is ‘tree’, print the results
     as a tree profile.

     Note that ‘statprof’ requires a working profiling timer.  Some
     platforms do not support profiling timers.  ‘(provided?
     'ITIMER_PROF)’ can be used to check for support of profiling
     timers.

   Profiling can also be enabled and disabled manually.

 -- Scheme Procedure: statprof-active?
     Returns ‘#t’ if ‘statprof-start’ has been called more times than
     ‘statprof-stop’, ‘#f’ otherwise.

 -- Scheme Procedure: statprof-start
 -- Scheme Procedure: statprof-stop
     Start or stop the profiler.

 -- Scheme Procedure: statprof-reset sample-seconds sample-microseconds
          count-calls?
     Reset the profiling sample interval to SAMPLE-SECONDS and
     SAMPLE-MICROSECONDS.  If COUNT-CALLS? is true, arrange to
     instrument procedure calls as well as collecting statistical
     profiling data.

   If you use the manual ‘statprof-start’/‘statprof-stop’ interface, an
implicit statprof state will persist starting from the last call to
‘statprof-reset’, or the first call to ‘statprof-start’.  There are a
number of accessors to fetch statistics from this implicit state.

 -- Scheme Procedure: statprof-accumulated-time
     Returns the time accumulated during the last statprof run.

 -- Scheme Procedure: statprof-sample-count
     Returns the number of samples taken during the last statprof run.

 -- Scheme Procedure: statprof-fold-call-data proc init
     Fold PROC over the call-data accumulated by statprof.  This
     procedure cannot be called while statprof is active.

     PROC will be called with arguments, CALL-DATA and PRIOR-RESULT.

 -- Scheme Procedure: statprof-proc-call-data proc
     Returns the call-data associated with PROC, or ‘#f’ if none is
     available.

 -- Scheme Procedure: statprof-call-data-name cd
 -- Scheme Procedure: statprof-call-data-calls cd
 -- Scheme Procedure: statprof-call-data-cum-samples cd
 -- Scheme Procedure: statprof-call-data-self-samples cd
     Accessors for the fields in a statprof call-data object.

 -- Scheme Procedure: statprof-call-data->stats call-data
     Returns an object of type ‘statprof-stats’.

 -- Scheme Procedure: statprof-stats-proc-name stats
 -- Scheme Procedure: statprof-stats-%-time-in-proc stats
 -- Scheme Procedure: statprof-stats-cum-secs-in-proc stats
 -- Scheme Procedure: statprof-stats-self-secs-in-proc stats
 -- Scheme Procedure: statprof-stats-calls stats
 -- Scheme Procedure: statprof-stats-self-secs-per-call stats
 -- Scheme Procedure: statprof-stats-cum-secs-per-call stats
     Accessors for the fields in a ‘statprof-stats’ object.

 -- Scheme Procedure: statprof-display [port=(current-output-port)]
          [#:style style=flat]
     Displays a summary of the statistics collected.  Possible values
     for STYLE include:

     ‘flat’
          Display a traditional gprof-style flat profile.
     ‘anomalies’
          Find statistical anomalies in the data.
     ‘tree’
          Display a tree profile.

 -- Scheme Procedure: statprof-fetch-stacks
     Returns a list of stacks, as they were captured since the last call
     to ‘statprof-reset’.

 -- Scheme Procedure: statprof-fetch-call-tree [#:precise precise?=#f]
     Return a call tree for the previous statprof run.

     The return value is a list of nodes.  A node is a list of the form:
     @code
      node ::= (@var{proc} @var{count} . @var{nodes})
     @end code

     The @var{proc} is a printable representation of a procedure, as a
     string.  If @var{precise?} is false, which is the default, then a node
     corresponds to a procedure invocation.  If it is true, then a node
     corresponds to a return point in a procedure.  Passing @code{#:precise?
     #t} allows a user to distinguish different source lines in a procedure,
     but usually it is too much detail, so it is off by default.

 -- Scheme Procedure: gcprof thunk [#:loop]
     Like the ‘statprof’ procedure, but instead of profiling CPU time,
     we profile garbage collection.

     The stack will be sampled soon after every garbage collection
     during the evaluation of THUNK, yielding an approximate idea of
     what is causing allocation in your program.

     Since GC does not occur very frequently, you may need to use the
     LOOP parameter, to cause THUNK to be called LOOP times.

7.21 SXML
=========

SXML is a native representation of XML in terms of standard Scheme data
types: lists, symbols, and strings.  For example, the simple XML
fragment:

     <parrot type="African Grey"><name>Alfie</name></parrot>

   may be represented with the following SXML:

     (parrot (@ (type "African Grey")) (name "Alfie"))

   SXML is very general, and is capable of representing all of XML.
Formally, this means that SXML is a conforming implementation of the XML
Information Set (http://www.w3.org/TR/xml-infoset/) standard.

   Guile includes several facilities for working with XML and SXML:
parsers, serializers, and transformers.

7.21.1 SXML Overview
--------------------

(This section needs to be written; volunteers welcome.)

7.21.2 Reading and Writing XML
------------------------------

The ‘(sxml simple)’ module presents a basic interface for parsing XML
from a port into the Scheme SXML format, and for serializing it back to
text.

     (use-modules (sxml simple))

 -- Scheme Procedure: xml->sxml [string-or-port] [#:namespaces='()]
          [#:declare-namespaces?=#t] [#:trim-whitespace?=#f]
          [#:entities='()] [#:default-entity-handler=#f]
          [#:doctype-handler=#f]
     Use SSAX to parse an XML document into SXML. Takes one optional
     argument, STRING-OR-PORT, which defaults to the current input port.
     Returns the resulting SXML document.  If STRING-OR-PORT is a port,
     it will be left pointing at the next available character in the
     port.

   As is normal in SXML, XML elements parse as tagged lists.
Attributes, if any, are placed after the tag, within an ‘@’ element.
The root of the resulting XML will be contained in a special tag,
‘*TOP*’.  This tag will contain the root element of the XML, but also
any prior processing instructions.

     (xml->sxml "<foo/>")
     ⇒ (*TOP* (foo))
     (xml->sxml "<foo>text</foo>")
     ⇒ (*TOP* (foo "text"))
     (xml->sxml "<foo kind=\"bar\">text</foo>")
     ⇒ (*TOP* (foo (@ (kind "bar")) "text"))
     (xml->sxml "<?xml version=\"1.0\"?><foo/>")
     ⇒ (*TOP* (*PI* xml "version=\"1.0\"") (foo))

   All namespaces in the XML document must be declared, via ‘xmlns’
attributes.  SXML elements built from non-default namespaces will have
their tags prefixed with their URI. Users can specify custom prefixes
for certain namespaces with the ‘#:namespaces’ keyword argument to
‘xml->sxml’.

     (xml->sxml "<foo xmlns=\"http://example.org/ns1\">text</foo>")
     ⇒ (*TOP* (http://example.org/ns1:foo "text"))
     (xml->sxml "<foo xmlns=\"http://example.org/ns1\">text</foo>"
                #:namespaces '((ns1 . "http://example.org/ns1")))
     ⇒ (*TOP* (ns1:foo "text"))
     (xml->sxml "<foo xmlns:bar=\"http://example.org/ns2\"><bar:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2")))
     ⇒ (*TOP* (foo (ns2:baz)))

   By default, namespaces passed to ‘xml->sxml’ are treated as if they
were declared on the root element.  Passing a false
‘#:declare-namespaces?’ argument will disable this behavior, requiring
in-document declarations of namespaces before use..

     (xml->sxml "<foo><ns2:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2")))
     ⇒ (*TOP* (foo (ns2:baz)))
     (xml->sxml "<foo><ns2:baz/></foo>"
                #:namespaces '((ns2 . "http://example.org/ns2"))
                #:declare-namespaces? #f)
     ⇒ error: undeclared namespace: `bar'

   By default, all whitespace in XML is significant.  Passing the
‘#:trim-whitespace?’ keyword argument to ‘xml->sxml’ will trim
whitespace in front, behind and between elements, treating it as
"unsignificant".  Whitespace in text fragments is left alone.

     (xml->sxml "<foo>\n<bar> Alfie the parrot! </bar>\n</foo>")
     ⇒ (*TOP* (foo "\n" (bar " Alfie the parrot! ") "\n"))
     (xml->sxml "<foo>\n<bar> Alfie the parrot! </bar>\n</foo>"
                #:trim-whitespace? #t)
     ⇒ (*TOP* (foo (bar " Alfie the parrot! ")))

   Parsed entities may be declared with the ‘#:entities’ keyword
argument, or handled with the ‘#:default-entity-handler’.  By default,
only the standard ‘&lt;’, ‘&gt;’, ‘&amp;’, ‘&apos;’ and ‘&quot;’
entities are defined, as well as the ‘&#N;’ and ‘&#xN;’ (decimal and
hexadecimal) numeric character entities.

     (xml->sxml "<foo>&amp;</foo>")
     ⇒ (*TOP* (foo "&"))
     (xml->sxml "<foo>&nbsp;</foo>")
     ⇒ error: undefined entity: nbsp
     (xml->sxml "<foo>&#xA0;</foo>")
     ⇒ (*TOP* (foo "\xa0"))
     (xml->sxml "<foo>&nbsp;</foo>"
                #:entities '((nbsp . "\xa0")))
     ⇒ (*TOP* (foo "\xa0"))
     (xml->sxml "<foo>&nbsp; &foo;</foo>"
                #:default-entity-handler
                (lambda (port name)
                  (case name
                    ((nbsp) "\xa0")
                    (else
                     (format (current-warning-port)
                             "~a:~a:~a: undefined entitity: ~a\n"
                             (or (port-filename port) "<unknown file>")
                             (port-line port) (port-column port)
                             name)
                     (symbol->string name)))))
     ⊣ <unknown file>:0:17: undefined entitity: foo
     ⇒ (*TOP* (foo "\xa0 foo"))

   By default, ‘xml->sxml’ skips over the ‘<!DOCTYPE>’ declaration, if
any.  This behavior can be overridden with the ‘#:doctype-handler’
argument, which should be a procedure of three arguments: the “docname”
(a symbol), “systemid” (a string), and the internal doctype subset (as a
string or ‘#f’ if not present).

   The handler should return keyword arguments as multiple values, as if
it were calling its continuation with keyword arguments.  The
continuation accepts the ‘#:entities’ and ‘#:namespaces’ keyword
arguments, in the same format that ‘xml->sxml’ itself takes.  These
entities and namespaces will be prepended to those given to the
‘xml->sxml’ invocation.

     (define (handle-foo docname systemid internal-subset)
       (case docname
         ((foo)
          (values #:entities '((greets . "<i>Hello, world!</i>"))))
         (else
          (values))))

     (xml->sxml "<!DOCTYPE foo><p>&greets;</p>"
                #:doctype-handler handle-foo)
     ⇒ (*TOP* (p (i "Hello, world!")))

   If the document has no doctype declaration, the DOCTYPE-HANDLER is
invoked with ‘#f’ for the three arguments.

   In the future, the continuation may accept other keyword arguments,
for example to validate the parsed SXML against the doctype.

 -- Scheme Procedure: sxml->xml tree [port]
     Serialize the SXML tree TREE as XML. The output will be written to
     the current output port, unless the optional argument PORT is
     present.

 -- Scheme Procedure: sxml->string sxml
     Detag an sxml tree SXML into a string.  Does not perform any
     formatting.

7.21.3 SSAX: A Functional XML Parsing Toolkit
---------------------------------------------

Guile's XML parser is based on Oleg Kiselyov's powerful XML parsing
toolkit, SSAX.

7.21.3.1 History
................

Back in the 1990s, when the world was young again and XML was the
solution to all of its problems, there were basically two kinds of XML
parsers out there: DOM parsers and SAX parsers.

   A DOM parser reads through an entire XML document, building up a tree
of "DOM objects" representing the document structure.  They are very
easy to use, but sometimes you don't actually want all of the
information in a document; building an object tree is not necessary if
all you want to do is to count word frequencies in a document, for
example.

   SAX parsers were created to give the programmer more control on the
parsing process.  A programmer gives the SAX parser a number of
"callbacks": functions that will be called on various features of the
XML stream as they are encountered.  SAX parsers are more efficient, but
much harder to use, as users typically have to manually maintain a stack
of open elements.

   Kiselyov realized that the SAX programming model could be made much
simpler if the callbacks were formulated not as a linear fold across the
features of the XML stream, but as a _tree fold_ over the structure
implicit in the XML. In this way, the user has a very convenient,
functional-style interface that can still generate optimal parsers.

   The ‘xml->sxml’ interface from the ‘(sxml simple)’ module is a
DOM-style parser built using SSAX, though it returns SXML instead of DOM
objects.

7.21.3.2 Implementation
.......................

‘(sxml ssax)’ is a package of low-to-high level lexing and parsing
procedures that can be combined to yield a SAX, a DOM, a validating
parser, or a parser intended for a particular document type.  The
procedures in the package can be used separately to tokenize or parse
various pieces of XML documents.  The package supports XML Namespaces,
internal and external parsed entities, user-controlled handling of
whitespace, and validation.  This module therefore is intended to be a
framework, a set of "Lego blocks" you can use to build a parser
following any discipline and performing validation to any degree.  As an
example of the parser construction, the source file includes a
semi-validating SXML parser.

   SSAX has a "sequential" feel of SAX yet a "functional style" of DOM.
Like a SAX parser, the framework scans the document only once and
permits incremental processing.  An application that handles document
elements in order can run as efficiently as possible.  _Unlike_ a SAX
parser, the framework does not require an application register stateful
callbacks and surrender control to the parser.  Rather, it is the
application that can drive the framework - calling its functions to get
the current lexical or syntax element.  These functions do not maintain
or mutate any state save the input port.  Therefore, the framework
permits parsing of XML in a pure functional style, with the input port
being a monad (or a linear, read-once parameter).

   Besides the PORT, there is another monad - SEED.  Most of the middle-
and high-level parsers are single-threaded through the SEED.  The
functions of this framework do not process or affect the SEED in any
way: they simply pass it around as an instance of an opaque datatype.
User functions, on the other hand, can use the seed to maintain user's
state, to accumulate parsing results, etc.  A user can freely mix their
own functions with those of the framework.  On the other hand, the user
may wish to instantiate a high-level parser: ‘SSAX:make-elem-parser’ or
‘SSAX:make-parser’.  In the latter case, the user must provide functions
of specific signatures, which are called at predictable moments during
the parsing: to handle character data, element data, or processing
instructions (PI). The functions are always given the SEED, among other
parameters, and must return the new SEED.

   From a functional point of view, XML parsing is a combined
pre-post-order traversal of a "tree" that is the XML document itself.
This down-and-up traversal tells the user about an element when its
start tag is encountered.  The user is notified about the element once
more, after all element's children have been handled.  The process of
XML parsing therefore is a fold over the raw XML document.  Unlike a
fold over trees defined in [1], the parser is necessarily
single-threaded - obviously as elements in a text XML document are laid
down sequentially.  The parser therefore is a tree fold that has been
transformed to accept an accumulating parameter [1,2].

   Formally, the denotational semantics of the parser can be expressed
as

      parser:: (Start-tag -> Seed -> Seed) ->
     	   (Start-tag -> Seed -> Seed -> Seed) ->
     	   (Char-Data -> Seed -> Seed) ->
     	   XML-text-fragment -> Seed -> Seed
      parser fdown fup fchar "<elem attrs> content </elem>" seed
       = fup "<elem attrs>" seed
     	(parser fdown fup fchar "content" (fdown "<elem attrs>" seed))

      parser fdown fup fchar "char-data content" seed
       = parser fdown fup fchar "content" (fchar "char-data" seed)

      parser fdown fup fchar "elem-content content" seed
       = parser fdown fup fchar "content" (
     	parser fdown fup fchar "elem-content" seed)

   Compare the last two equations with the left fold

      fold-left kons elem:list seed = fold-left kons list (kons elem seed)

   The real parser created by ‘SSAX:make-parser’ is slightly more
complicated, to account for processing instructions, entity references,
namespaces, processing of document type declaration, etc.

   The XML standard document referred to in this module is
<http://www.w3.org/TR/1998/REC-xml-19980210.html>

   The present file also defines a procedure that parses the text of an
XML document or of a separate element into SXML, an S-expression-based
model of an XML Information Set.  SXML is also an Abstract Syntax Tree
of an XML document.  SXML is similar but not identical to DOM; SXML is
particularly suitable for Scheme-based XML/HTML authoring, SXPath
queries, and tree transformations.  See SXML.html for more details.
SXML is a term implementation of evaluation of the XML document [3].
The other implementation is context-passing.

   The present frameworks fully supports the XML Namespaces
Recommendation: <http://www.w3.org/TR/REC-xml-names/>.

   Other links:

[1]
     Jeremy Gibbons, Geraint Jones, "The Under-appreciated Unfold,"
     Proc.  ICFP'98, 1998, pp.  273-279.

[2]
     Richard S. Bird, The promotion and accumulation strategies in
     transformational programming, ACM Trans.  Progr.  Lang.  Systems,
     6(4):487-504, October 1984.

[3]
     Ralf Hinze, "Deriving Backtracking Monad Transformers," Functional
     Pearl.  Proc ICFP'00, pp.  186-197.

7.21.3.3 Usage
..............

 -- Scheme Procedure: current-ssax-error-port

 -- Scheme Procedure: with-ssax-error-to-port port thunk

 -- Scheme Procedure: xml-token? _
      -- Scheme Procedure: pair? x
          Return `#t' if X is a pair; otherwise return `#f'.

 -- Scheme Syntax: xml-token-kind token

 -- Scheme Syntax: xml-token-head token

 -- Scheme Procedure: make-empty-attlist

 -- Scheme Procedure: attlist-add attlist name-value

 -- Scheme Procedure: attlist-null? x
     Return ‘#t’ if X is the empty list, else ‘#f’.

 -- Scheme Procedure: attlist-remove-top attlist

 -- Scheme Procedure: attlist->alist attlist

 -- Scheme Procedure: attlist-fold kons knil lis1

 -- Scheme Procedure: define-parsed-entity! entity str
     Define a new parsed entity.  ENTITY should be a symbol.

     Instances of &ENTITY; in XML text will be replaced with the string
     STR, which will then be parsed.

 -- Scheme Procedure: reset-parsed-entity-definitions!
     Restore the set of parsed entity definitions to its initial state.

 -- Scheme Procedure: ssax:uri-string->symbol uri-str

 -- Scheme Procedure: ssax:skip-internal-dtd port

 -- Scheme Procedure: ssax:read-pi-body-as-string port

 -- Scheme Procedure: ssax:reverse-collect-str-drop-ws fragments

 -- Scheme Procedure: ssax:read-markup-token port

 -- Scheme Procedure: ssax:read-cdata-body port str-handler seed

 -- Scheme Procedure: ssax:read-char-ref port

 -- Scheme Procedure: ssax:read-attributes port entities

 -- Scheme Procedure: ssax:complete-start-tag tag-head port elems
          entities namespaces

 -- Scheme Procedure: ssax:read-external-id port

 -- Scheme Procedure: ssax:read-char-data port expect-eof? str-handler
          seed

 -- Scheme Procedure: ssax:xml->sxml port namespace-prefix-assig

 -- Scheme Syntax: ssax:make-parser . kw-val-pairs

 -- Scheme Syntax: ssax:make-pi-parser orig-handlers

 -- Scheme Syntax: ssax:make-elem-parser my-new-level-seed
          my-finish-element my-char-data-handler my-pi-handlers

7.21.4 Transforming SXML
------------------------

7.21.4.1 Overview
.................

SXML expression tree transformers
=================================

Pre-Post-order traversal of a tree and creation of a new tree
-------------------------------------------------------------

     pre-post-order:: <tree> x <bindings> -> <new-tree>

   where

      <bindings> ::= (<binding> ...)
      <binding> ::= (<trigger-symbol> *preorder* . <handler>) |
                    (<trigger-symbol> *macro* . <handler>) |
     		(<trigger-symbol> <new-bindings> . <handler>) |
     		(<trigger-symbol> . <handler>)
      <trigger-symbol> ::= XMLname | *text* | *default*
      <handler> :: <trigger-symbol> x [<tree>] -> <new-tree>

   The ‘pre-post-order’ function, in the ‘(sxml transform)’ module,
visits the nodes and nodelists pre-post-order (depth-first).  For each
‘<Node>’ of the form ‘(NAME <Node> ...)’, it looks up an association
with the given NAME among its <BINDINGS>.  If failed, ‘pre-post-order’
tries to locate a ‘*default*’ binding.  It's an error if the latter
attempt fails as well.  Having found a binding, the ‘pre-post-order’
function first checks to see if the binding is of the form

     	(<trigger-symbol> *preorder* . <handler>)

   If it is, the handler is 'applied' to the current node.  Otherwise,
the pre-post-order function first calls itself recursively for each
child of the current node, with <NEW-BINDINGS> prepended to the
<BINDINGS> in effect.  The result of these calls is passed to the
<HANDLER> (along with the head of the current <NODE>).  To be more
precise, the handler is _applied_ to the head of the current node and
its processed children.  The result of the handler, which should also be
a ‘<tree>’, replaces the current <NODE>.  If the current <NODE> is a
text string or other atom, a special binding with a symbol ‘*text*’ is
looked up.

   A binding can also be of a form

     	(<trigger-symbol> *macro* . <handler>)

   This is equivalent to ‘*preorder*’ described above.  However, the
result is re-processed again, with the current stylesheet.

7.21.4.2 Usage
..............

 -- Scheme Procedure: SRV:send-reply . fragments
     Output the FRAGMENTS to the current output port.

     The fragments are a list of strings, characters, numbers, thunks,
     ‘#f’, ‘#t’ - and other fragments.  The function traverses the tree
     depth-first, writes out strings and characters, executes thunks,
     and ignores ‘#f’ and ‘'()’.  The function returns ‘#t’ if anything
     was written at all; otherwise the result is ‘#f’ If ‘#t’ occurs
     among the fragments, it is not written out but causes the result of
     ‘SRV:send-reply’ to be ‘#t’.

 -- Scheme Procedure: foldts fdown fup fhere seed tree

 -- Scheme Procedure: post-order tree bindings

 -- Scheme Procedure: pre-post-order tree bindings

 -- Scheme Procedure: replace-range beg-pred end-pred forest

7.21.5 SXML Tree Fold
---------------------

7.21.5.1 Overview
.................

‘(sxml fold)’ defines a number of variants of the “fold” algorithm for
use in transforming SXML trees.  Additionally it defines the layout
operator, ‘fold-layout’, which might be described as a context-passing
variant of SSAX's ‘pre-post-order’.

7.21.5.2 Usage
..............

 -- Scheme Procedure: foldt fup fhere tree
     The standard multithreaded tree fold.

     FUP is of type [a] -> a.  FHERE is of type object -> a.

 -- Scheme Procedure: foldts fdown fup fhere seed tree
     The single-threaded tree fold originally defined in SSAX. See
     SSAX, for more information.

 -- Scheme Procedure: foldts* fdown fup fhere seed tree
     A variant of ‘foldts’ that allows pre-order tree rewrites.
     Originally defined in Andy Wingo's 2007 paper, _Applications of
     fold to XML transformation_.

 -- Scheme Procedure: fold-values proc list . seeds
     A variant of ‘fold’ that allows multi-valued seeds.  Note that the
     order of the arguments differs from that of ‘fold’.  See SRFI-1 Fold and Map.

 -- Scheme Procedure: foldts*-values fdown fup fhere tree . seeds
     A variant of ‘foldts*’ that allows multi-valued seeds.  Originally
     defined in Andy Wingo's 2007 paper, _Applications of fold to XML
     transformation_.

 -- Scheme Procedure: fold-layout tree bindings params layout stylesheet
     A traversal combinator in the spirit of ‘pre-post-order’.  See
     Transforming SXML.

     ‘fold-layout’ was originally presented in Andy Wingo's 2007 paper,
     _Applications of fold to XML transformation_.

          bindings := (<binding>...)
          binding  := (<tag> <handler-pair>...)
                    | (*default* . <post-handler>)
                    | (*text* . <text-handler>)
          tag      := <symbol>
          handler-pair := (pre-layout . <pre-layout-handler>)
                    | (post . <post-handler>)
                    | (bindings . <bindings>)
                    | (pre . <pre-handler>)
                    | (macro . <macro-handler>)

     PRE-LAYOUT-HANDLER
          A function of three arguments:

          KIDS
               the kids of the current node, before traversal

          PARAMS
               the params of the current node

          LAYOUT
               the layout coming into this node

          PRE-LAYOUT-HANDLER is expected to use this information to
          return a layout to pass to the kids.  The default
          implementation returns the layout given in the arguments.

     POST-HANDLER
          A function of five arguments:

          TAG
               the current tag being processed

          PARAMS
               the params of the current node

          LAYOUT
               the layout coming into the current node, before any kids
               were processed

          KLAYOUT
               the layout after processing all of the children

          KIDS
               the already-processed child nodes

          POST-HANDLER should return two values, the layout to pass to
          the next node and the final tree.

     TEXT-HANDLER
          TEXT-HANDLER is a function of three arguments:

          TEXT
               the string

          PARAMS
               the current params

          LAYOUT
               the current layout

          TEXT-HANDLER should return two values, the layout to pass to
          the next node and the value to which the string should
          transform.

7.21.6 SXPath
-------------

7.21.6.1 Overview
.................

SXPath: SXML Query Language
===========================

SXPath is a query language for SXML, an instance of XML Information set
(Infoset) in the form of s-expressions.  See ‘(sxml ssax)’ for the
definition of SXML and more details.  SXPath is also a translation into
Scheme of an XML Path Language, XPath (http://www.w3.org/TR/xpath).
XPath and SXPath describe means of selecting a set of Infoset's items or
their properties.

   To facilitate queries, XPath maps the XML Infoset into an explicit
tree, and introduces important notions of a location path and a current,
context node.  A location path denotes a selection of a set of nodes
relative to a context node.  Any XPath tree has a distinguished, root
node - which serves as the context node for absolute location paths.
Location path is recursively defined as a location step joined with a
location path.  A location step is a simple query of the database
relative to a context node.  A step may include expressions that further
filter the selected set.  Each node in the resulting set is used as a
context node for the adjoining location path.  The result of the step is
a union of the sets returned by the latter location paths.

   The SXML representation of the XML Infoset (see SSAX.scm) is rather
suitable for querying as it is.  Bowing to the XPath specification, we
will refer to SXML information items as 'Nodes':

      	<Node> ::= <Element> | <attributes-coll> | <attrib>
      		   | "text string" | <PI>

   This production can also be described as

     	<Node> ::= (name . <Nodeset>) | "text string"

   An (ordered) set of nodes is just a list of the constituent nodes:

      	<Nodeset> ::= (<Node> ...)

   Nodesets, and Nodes other than text strings are both lists.  A
<Nodeset> however is either an empty list, or a list whose head is not a
symbol.  A symbol at the head of a node is either an XML name (in which
case it's a tag of an XML element), or an administrative name such as
'@'.  This uniform list representation makes processing rather simple
and elegant, while avoiding confusion.  The multi-branch tree structure
formed by the mutually-recursive datatypes <Node> and <Nodeset> lends
itself well to processing by functional languages.

   A location path is in fact a composite query over an XPath tree or
its branch.  A singe step is a combination of a projection, selection or
a transitive closure.  Multiple steps are combined via join and union
operations.  This insight allows us to _elegantly_ implement XPath as a
sequence of projection and filtering primitives - converters - joined by
“combinators”.  Each converter takes a node and returns a nodeset which
is the result of the corresponding query relative to that node.  A
converter can also be called on a set of nodes.  In that case it returns
a union of the corresponding queries over each node in the set.  The
union is easily implemented as a list append operation as all nodes in a
SXML tree are considered distinct, by XPath conventions.  We also
preserve the order of the members in the union.  Query combinators are
high-order functions: they take converter(s) (which is a Node|Nodeset ->
Nodeset function) and compose or otherwise combine them.  We will be
concerned with only relative location paths [XPath]: an absolute
location path is a relative path applied to the root node.

   Similarly to XPath, SXPath defines full and abbreviated notations for
location paths.  In both cases, the abbreviated notation can be
mechanically expanded into the full form by simple rewriting rules.  In
the case of SXPath the corresponding rules are given in the
documentation of the ‘sxpath’ procedure.  See SXPath procedure documentation.

   The regression test suite at the end of the file ‘SXPATH-old.scm’
shows a representative sample of SXPaths in both notations, juxtaposed
with the corresponding XPath expressions.  Most of the samples are
borrowed literally from the XPath specification.

   Much of the following material is taken from the SXPath sources by
Oleg Kiselyov et al.

7.21.6.2 Basic Converters and Applicators
.........................................

A converter is a function mapping a nodeset (or a single node) to
another nodeset.  Its type can be represented like this:

     type Converter = Node|Nodeset -> Nodeset

   A converter can also play the role of a predicate: in that case, if a
converter, applied to a node or a nodeset, yields a non-empty nodeset,
the converter-predicate is deemed satisfied.  Likewise, an empty nodeset
is equivalent to ‘#f’ in denoting failure.

 -- Scheme Procedure: nodeset? x
     Return ‘#t’ if X is a nodeset.

 -- Scheme Procedure: node-typeof? crit
     This function implements a 'Node test' as defined in Sec.  2.3 of
     the XPath document.  A node test is one of the components of a
     location step.  It is also a converter-predicate in SXPath.

     The function ‘node-typeof?’ takes a type criterion and returns a
     function, which, when applied to a node, will tell if the node
     satisfies the test.

     The criterion CRIT is a symbol, one of the following:

     ‘id’
          tests if the node has the right name (id)

     ‘@’
          tests if the node is an <attributes-coll>

     ‘*’
          tests if the node is an <Element>

     ‘*text*’
          tests if the node is a text node

     ‘*PI*’
          tests if the node is a PI (processing instruction) node

     ‘*any*’
          ‘#t’ for any type of node

 -- Scheme Procedure: node-eq? other
     A curried equivalence converter predicate that takes a node OTHER
     and returns a function that takes another node.  The two nodes are
     compared using ‘eq?’.

 -- Scheme Procedure: node-equal? other
     A curried equivalence converter predicate that takes a node OTHER
     and returns a function that takes another node.  The two nodes are
     compared using ‘equal?’.

 -- Scheme Procedure: node-pos n
     Select the N'th element of a nodeset and return as a singular
     nodeset.  If the N'th element does not exist, return an empty
     nodeset.  If N is a negative number the node is picked from the
     tail of the list.

          ((node-pos 1) nodeset)  ; return the the head of the nodeset (if exists)
          ((node-pos 2) nodeset)  ; return the node after that (if exists)
          ((node-pos -1) nodeset) ; selects the last node of a non-empty nodeset
          ((node-pos -2) nodeset) ; selects the last but one node, if exists.

 -- Scheme Procedure: filter pred?
     A filter applicator, which introduces a filtering context.  The
     argument converter PRED? is considered a predicate, with either
     ‘#f’ or ‘nil’ meaning failure.

 -- Scheme Procedure: take-until pred?
          take-until:: Converter -> Converter, or
          take-until:: Pred -> Node|Nodeset -> Nodeset

     Given a converter-predicate PRED? and a nodeset, apply the
     predicate to each element of the nodeset, until the predicate
     yields anything but ‘#f’ or ‘nil’.  Return the elements of the
     input nodeset that have been processed until that moment (that is,
     which fail the predicate).

     ‘take-until’ is a variation of the ‘filter’ above: ‘take-until’
     passes elements of an ordered input set up to (but not including)
     the first element that satisfies the predicate.  The nodeset
     returned by ‘((take-until (not pred)) nset)’ is a subset - to be
     more precise, a prefix - of the nodeset returned by ‘((filter pred)
     nset)’.

 -- Scheme Procedure: take-after pred?
          take-after:: Converter -> Converter, or
          take-after:: Pred -> Node|Nodeset -> Nodeset

     Given a converter-predicate PRED? and a nodeset, apply the
     predicate to each element of the nodeset, until the predicate
     yields anything but ‘#f’ or ‘nil’.  Return the elements of the
     input nodeset that have not been processed: that is, return the
     elements of the input nodeset that follow the first element that
     satisfied the predicate.

     ‘take-after’ along with ‘take-until’ partition an input nodeset
     into three parts: the first element that satisfies a predicate, all
     preceding elements and all following elements.

 -- Scheme Procedure: map-union proc lst
     Apply PROC to each element of LST and return the list of results.
     If PROC returns a nodeset, splice it into the result

     From another point of view, ‘map-union’ is a function
     ‘Converter->Converter’, which places an argument-converter in a
     joining context.

 -- Scheme Procedure: node-reverse node-or-nodeset
          node-reverse :: Converter, or
          node-reverse:: Node|Nodeset -> Nodeset

     Reverses the order of nodes in the nodeset.  This basic converter
     is needed to implement a reverse document order (see the XPath
     Recommendation).

 -- Scheme Procedure: node-trace title
          node-trace:: String -> Converter

     ‘(node-trace title)’ is an identity converter.  In addition it
     prints out the node or nodeset it is applied to, prefixed with the
     TITLE.  This converter is very useful for debugging.

7.21.6.3 Converter Combinators
..............................

Combinators are higher-order functions that transmogrify a converter or
glue a sequence of converters into a single, non-trivial converter.  The
goal is to arrive at converters that correspond to XPath location paths.

   From a different point of view, a combinator is a fixed, named
“pattern” of applying converters.  Given below is a complete set of such
patterns that together implement XPath location path specification.  As
it turns out, all these combinators can be built from a small number of
basic blocks: regular functional composition, ‘map-union’ and ‘filter’
applicators, and the nodeset union.

 -- Scheme Procedure: select-kids test-pred?
     ‘select-kids’ takes a converter (or a predicate) as an argument and
     returns another converter.  The resulting converter applied to a
     nodeset returns an ordered subset of its children that satisfy the
     predicate TEST-PRED?.

 -- Scheme Procedure: node-self pred?
     Similar to ‘select-kids’ except that the predicate PRED? is applied
     to the node itself rather than to its children.  The resulting
     nodeset will contain either one component, or will be empty if the
     node failed the predicate.

 -- Scheme Procedure: node-join . selectors
          node-join:: [LocPath] -> Node|Nodeset -> Nodeset, or
          node-join:: [Converter] -> Converter

     Join the sequence of location steps or paths as described above.

 -- Scheme Procedure: node-reduce . converters
          node-reduce:: [LocPath] -> Node|Nodeset -> Nodeset, or
          node-reduce:: [Converter] -> Converter

     A regular functional composition of converters.  From a different
     point of view, ‘((apply node-reduce converters) nodeset)’ is
     equivalent to ‘(foldl apply nodeset converters)’, i.e., folding, or
     reducing, a list of converters with the nodeset as a seed.

 -- Scheme Procedure: node-or . converters
          node-or:: [Converter] -> Converter

     This combinator applies all converters to a given node and produces
     the union of their results.  This combinator corresponds to a union
     (‘|’ operation) for XPath location paths.

 -- Scheme Procedure: node-closure test-pred?
          node-closure:: Converter -> Converter

     Select all _descendants_ of a node that satisfy a
     converter-predicate TEST-PRED?.  This combinator is similar to
     ‘select-kids’ but applies to grand...  children as well.  This
     combinator implements the ‘descendant::’ XPath axis.  Conceptually,
     this combinator can be expressed as

          (define (node-closure f)
            (node-or
              (select-kids f)
              (node-reduce (select-kids (node-typeof? '*)) (node-closure f))))

     This definition, as written, looks somewhat like a fixpoint, and it
     will run forever.  It is obvious however that sooner or later
     ‘(select-kids (node-typeof? '*))’ will return an empty nodeset.  At
     this point further iterations will no longer affect the result and
     can be stopped.

 -- Scheme Procedure: node-parent rootnode
          node-parent:: RootNode -> Converter

     ‘(node-parent rootnode)’ yields a converter that returns a parent
     of a node it is applied to.  If applied to a nodeset, it returns
     the list of parents of nodes in the nodeset.  The ROOTNODE does not
     have to be the root node of the whole SXML tree - it may be a root
     node of a branch of interest.

     Given the notation of Philip Wadler's paper on semantics of XSLT,

       parent(x) = { y | y=subnode*(root), x=subnode(y) }

     Therefore, ‘node-parent’ is not the fundamental converter: it can
     be expressed through the existing ones.  Yet ‘node-parent’ is a
     rather convenient converter.  It corresponds to a ‘parent::’ axis
     of SXPath.  Note that the ‘parent::’ axis can be used with an
     attribute node as well.

 -- Scheme Procedure: sxpath path
     Evaluate an abbreviated SXPath.

          sxpath:: AbbrPath -> Converter, or
          sxpath:: AbbrPath -> Node|Nodeset -> Nodeset

     PATH is a list.  It is translated to the full SXPath according to
     the following rewriting rules:

          (sxpath '())
          ⇒ (node-join)

          (sxpath '(path-component ...))
          ⇒ (node-join (sxpath1 path-component) (sxpath '(...)))

          (sxpath1 '//)
          ⇒ (node-or
             (node-self (node-typeof? '*any*))
             (node-closure (node-typeof? '*any*)))

          (sxpath1 '(equal? x))
          ⇒ (select-kids (node-equal? x))

          (sxpath1 '(eq? x))
          ⇒ (select-kids (node-eq? x))

          (sxpath1 ?symbol)
          ⇒ (select-kids (node-typeof? ?symbol)

          (sxpath1 procedure)
          ⇒ procedure

          (sxpath1 '(?symbol ...))
          ⇒ (sxpath1 '((?symbol) ...))

          (sxpath1 '(path reducer ...))
          ⇒ (node-reduce (sxpath path) (sxpathr reducer) ...)

          (sxpathr number)
          ⇒ (node-pos number)

          (sxpathr path-filter)
          ⇒ (filter (sxpath path-filter))

7.21.7 (sxml ssax input-parse)
------------------------------

7.21.7.1 Overview
.................

A simple lexer.

   The procedures in this module surprisingly often suffice to parse an
input stream.  They either skip, or build and return tokens, according
to inclusion or delimiting semantics.  The list of characters to expect,
include, or to break at may vary from one invocation of a function to
another.  This allows the functions to easily parse even
context-sensitive languages.

   EOF is generally frowned on, and thrown up upon if encountered.
Exceptions are mentioned specifically.  The list of expected characters
(characters to skip until, or break-characters) may include an EOF
"character", which is to be coded as the symbol, ‘*eof*’.

   The input stream to parse is specified as a “port”, which is usually
the last (and optional) argument.  It defaults to the current input port
if omitted.

   If the parser encounters an error, it will throw an exception to the
key ‘parser-error’.  The arguments will be of the form ‘(PORT MESSAGE
SPECIALISING-MSG*)’.

   The first argument is a port, which typically points to the offending
character or its neighborhood.  You can then use ‘port-column’ and
‘port-line’ to query the current position.  MESSAGE is the description
of the error.  Other arguments supply more details about the problem.

7.21.7.2 Usage
..............

 -- Scheme Procedure: peek-next-char [port]

 -- Scheme Procedure: assert-curr-char expected-chars comment [port]

 -- Scheme Procedure: skip-until arg [port]

 -- Scheme Procedure: skip-while skip-chars [port]

 -- Scheme Procedure: next-token prefix-skipped-chars break-chars
          [comment] [port]

 -- Scheme Procedure: next-token-of incl-list/pred [port]

 -- Scheme Procedure: read-text-line [port]

 -- Scheme Procedure: read-string n [port]

 -- Scheme Procedure: find-string-from-port? _ _ . _
     Looks for STR in <INPUT-PORT>, optionally within the first
     MAX-NO-CHAR characters.