summaryrefslogtreecommitdiffstats
path: root/slib.info
diff options
context:
space:
mode:
Diffstat (limited to 'slib.info')
-rw-r--r--slib.info11240
1 files changed, 11240 insertions, 0 deletions
diff --git a/slib.info b/slib.info
new file mode 100644
index 0000000..8e62273
--- /dev/null
+++ b/slib.info
@@ -0,0 +1,11240 @@
+This is Info file slib.info, produced by Makeinfo version 1.68 from the
+input file slib.texi.
+
+INFO-DIR-SECTION The Algorithmic Language Scheme
+START-INFO-DIR-ENTRY
+* SLIB: (slib). Scheme Library
+END-INFO-DIR-ENTRY
+
+ This file documents SLIB, the portable Scheme library.
+
+ Copyright (C) 1993 Todd R. Eigenschink
+Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Aubrey Jaffer |
+
+ Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+ Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+ Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be stated in a
+translation approved by the author.
+
+
+File: slib.info, Node: Top, Next: The Library System, Prev: (dir), Up: (dir)
+
+"SLIB" is a portable library for the programming language "Scheme". It |
+provides a platform independent framework for using "packages" of |
+Scheme procedures and syntax. As distributed, SLIB contains useful
+packages for all Scheme implementations. Its catalog can be |
+transparently extended to accomodate packages specific to a site, |
+implementation, user, or directory. |
+
+* Menu:
+
+* The Library System:: How to use and customize.
+* Scheme Syntax Extension Packages::
+* Textual Conversion Packages::
+* Mathematical Packages::
+* Database Packages::
+* Other Packages::
+* About SLIB:: Install, etc.
+* Index::
+
+
+File: slib.info, Node: The Library System, Next: Scheme Syntax Extension Packages, Prev: Top, Up: Top
+
+The Library System
+******************
+
+* Menu:
+
+* Feature:: SLIB names.
+* Requesting Features::
+* Library Catalogs::
+* Catalog Compilation::
+* Built-in Support::
+* About this manual::
+
+
+File: slib.info, Node: Feature, Next: Requesting Features, Prev: The Library System, Up: The Library System
+
+Feature
+=======
+
+SLIB denotes "features" by symbols. SLIB maintains a list of features
+supported by the Scheme "session". The set of features provided by a
+session may change over time. Some features are properties of the
+Scheme implementation being used. The following features detail what
+sort of numbers are available from an implementation.
+
+ * 'inexact
+
+ * 'rational
+
+ * 'real
+
+ * 'complex
+
+ * 'bignum
+
+Other features correspond to the presence of sets of Scheme procedures
+or syntax (macros).
+
+ - Function: provided? FEATURE
+ Returns `#t' if FEATURE is supported by the current Scheme session.
+
+ - Procedure: provide FEATURE
+ Informs SLIB that FEATURE is supported. Henceforth `(provided?
+ FEATURE)' will return `#t'.
+
+ (provided? 'foo) => #f
+ (provide 'foo)
+ (provided? 'foo) => #t
+
+
+File: slib.info, Node: Requesting Features, Next: Library Catalogs, Prev: Feature, Up: The Library System
+
+Requesting Features
+===================
+
+SLIB creates and maintains a "catalog" mapping features to locations of
+files introducing procedures and syntax denoted by those features.
+
+At the beginning of each section of this manual, there is a line like
+`(require 'FEATURE)'. The Scheme files comprising SLIB are cataloged
+so that these feature names map to the corresponding files.
+
+SLIB provides a form, `require', which loads the files providing the
+requested feature.
+
+ - Procedure: require FEATURE
+ * If `(provided? FEATURE)' is true, then `require' just returns
+ an unspecified value.
+
+ * Otherwise, if FEATURE is found in the catalog, then the
+ corresponding files will be loaded and an unspecified value
+ returned.
+
+ Subsequently `(provided? FEATURE)' will return `#t'.
+
+ * Otherwise (FEATURE not found in the catalog), an error is
+ signaled.
+
+The catalog can also be queried using `require:feature->path'.
+
+ - Function: require:feature->path FEATURE
+ * If FEATURE is already provided, then returns `#t'.
+
+ * Otherwise, if FEATURE is in the catalog, the path or list of
+ paths associated with FEATURE is returned.
+
+ * Otherwise, returns `#f'.
+
+
+File: slib.info, Node: Library Catalogs, Next: Catalog Compilation, Prev: Requesting Features, Up: The Library System
+
+Library Catalogs
+================
+
+At the start of a session no catalog is present, but is created with the
+first catalog inquiry (such as `(require 'random)'). Several sources
+of catalog information are combined to produce the catalog:
+
+ * standard SLIB packages.
+
+ * additional packages of interest to this site.
+
+ * packages specifically for the variety of Scheme which this session
+ is running.
+
+ * packages this user wants to always have available. This catalog
+ is the file `homecat' in the user's "HOME" directory.
+
+ * packages germane to working in this (current working) directory.
+ This catalog is the file `usercat' in the directory to which it
+ applies. One would typically `cd' to this directory before
+ starting the Scheme session.
+
+Catalog files consist of one or more "association list"s. In the
+circumstance where a feature symbol appears in more than one list, the
+latter list's association is retrieved. Here are the supported formats
+for elements of catalog lists:
+
+`(FEATURE . <symbol>)'
+ Redirects to the feature named <symbol>.
+
+`(FEATURE . "<path>")'
+ Loads file <path>.
+
+`(FEATURE source "<path>")'
+ `slib:load's the Scheme source file <path>.
+
+`(FEATURE compiled "<path>" ...)'
+ `slib:load-compiled's the files <path> ....
+
+The various macro styles first `require' the named macro package, then
+just load <path> or load-and-macro-expand <path> as appropriate for the
+implementation.
+
+`(FEATURE defmacro "<path>")'
+ `defmacro:load's the Scheme source file <path>.
+
+`(FEATURE macro-by-example "<path>")'
+ `defmacro:load's the Scheme source file <path>.
+
+`(FEATURE macro "<path>")'
+ `macro:load's the Scheme source file <path>.
+
+`(FEATURE macros-that-work "<path>")'
+ `macro:load's the Scheme source file <path>.
+
+`(FEATURE syntax-case "<path>")'
+ `macro:load's the Scheme source file <path>.
+
+`(FEATURE syntactic-closures "<path>")'
+ `macro:load's the Scheme source file <path>.
+
+Here is an example of a `usercat' catalog. A Program in this directory
+can invoke the `run' feature with `(require 'run)'.
+
+ ;;; "usercat": SLIB catalog additions for SIMSYNCH. -*-scheme-*-
+
+ (
+ (simsynch . "../synch/simsynch.scm")
+ (run . "../synch/run.scm")
+ (schlep . "schlep.scm")
+ )
+
+
+File: slib.info, Node: Catalog Compilation, Next: Built-in Support, Prev: Library Catalogs, Up: The Library System
+
+Catalog Compilation
+===================
+
+SLIB combines the catalog information which doesn't vary per user into
+the file `slibcat' in the implementation-vicinity. Therefore `slibcat'
+needs change only when new software is installed or compiled. Because
+the actual pathnames of files can differ from installation to
+installation, SLIB builds a separate catalog for each implementation it
+is used with.
+
+The definition of `*SLIB-VERSION*' in SLIB file `require.scm' is
+checked against the catalog association of `*SLIB-VERSION*' to
+ascertain when versions have changed. I recommend that the definition
+of `*SLIB-VERSION*' be changed whenever the library is changed. If
+multiple implementations of Scheme use SLIB, remember that recompiling
+one `slibcat' will fix only that implementation's catalog.
+
+The compilation scripts of Scheme implementations which work with SLIB
+can automatically trigger catalog compilation by deleting `slibcat' or
+by invoking a special form of `require':
+
+ - Procedure: require 'new-catalog
+ This will load `mklibcat', which compiles and writes a new
+ `slibcat'.
+
+Another special form of `require' erases SLIB's catalog, forcing it to
+be reloaded the next time the catalog is queried.
+
+ - Procedure: require #f
+ Removes SLIB's catalog information. This should be done before
+ saving an executable image so that, when restored, its catalog
+ will be loaded afresh.
+
+Each file in the table below is descibed in terms of its file-system
+independent "vicinity" (*note Vicinity::.). The entries of a catalog
+in the table override those of catalogs above it in the table.
+
+`implementation-vicinity' `slibcat'
+ This file contains the associations for the packages comprising
+ SLIB, the `implcat' and the `sitecat's. The associations in the
+ other catalogs override those of the standard catalog.
+
+`library-vicinity' `mklibcat.scm'
+ creates `slibcat'.
+
+`library-vicinity' `sitecat'
+ This file contains the associations specific to an SLIB
+ installation.
+
+`implementation-vicinity' `implcat'
+ This file contains the associations specific to an implementation
+ of Scheme. Different implementations of Scheme should have
+ different `implementation-vicinity'.
+
+`implementation-vicinity' `mkimpcat.scm'
+ if present, creates `implcat'.
+
+`implementation-vicinity' `sitecat'
+ This file contains the associations specific to a Scheme
+ implementation installation.
+
+`home-vicinity' `homecat'
+ This file contains the associations specific to an SLIB user.
+
+`user-vicinity' `usercat'
+ This file contains associations effecting only those sessions whose
+ "working directory" is `user-vicinity'.
+
+
+File: slib.info, Node: Built-in Support, Next: About this manual, Prev: Catalog Compilation, Up: The Library System
+
+Built-in Support
+================
+
+The procedures described in these sections are supported by all
+implementations as part of the `*.init' files or by `require.scm'.
+
+* Menu:
+
+* Require:: Module Management
+* Vicinity:: Pathname Management
+* Configuration:: Characteristics of Scheme Implementation
+* Input/Output:: Things not provided by the Scheme specs.
+* Legacy::
+* System:: LOADing, EVALing, ERRORing, and EXITing
+
+
+File: slib.info, Node: Require, Next: Vicinity, Prev: Built-in Support, Up: Built-in Support
+
+Require
+-------
+
+ - Variable: *features*
+ Is a list of symbols denoting features supported in this
+ implementation. *FEATURES* can grow as modules are `require'd.
+ *FEATURES* must be defined by all implementations (*note
+ Porting::.).
+
+ Here are features which SLIB (`require.scm') adds to *FEATURES*
+ when appropriate.
+
+ * 'inexact
+
+ * 'rational
+
+ * 'real
+
+ * 'complex
+
+ * 'bignum
+
+ For each item, `(provided? 'FEATURE)' will return `#t' if that
+ feature is available, and `#f' if not.
+
+ - Variable: *modules*
+ Is a list of pathnames denoting files which have been loaded.
+
+ - Variable: *catalog*
+ Is an association list of features (symbols) and pathnames which
+ will supply those features. The pathname can be either a string
+ or a pair. If pathname is a pair then the first element should be
+ a macro feature symbol, `source', or `compiled'. The cdr of the
+ pathname should be either a string or a list.
+
+In the following functions if the argument FEATURE is not a symbol it
+is assumed to be a pathname.
+
+ - Function: provided? FEATURE
+ Returns `#t' if FEATURE is a member of `*features*' or `*modules*'
+ or if FEATURE is supported by a file already loaded and `#f'
+ otherwise.
+
+ - Procedure: require FEATURE
+ FEATURE is a symbol. If `(provided? FEATURE)' is true `require'
+ returns. Otherwise, if `(assq FEATURE *catalog*)' is not `#f',
+ the associated files will be loaded and `(provided? FEATURE)' will
+ henceforth return `#t'. An unspecified value is returned. If
+ FEATURE is not found in `*catalog*', then an error is signaled.
+
+ - Procedure: require PATHNAME
+ PATHNAME is a string. If PATHNAME has not already been given as
+ an argument to `require', PATHNAME is loaded. An unspecified
+ value is returned.
+
+ - Procedure: provide FEATURE
+ Assures that FEATURE is contained in `*features*' if FEATURE is a
+ symbol and `*modules*' otherwise.
+
+ - Function: require:feature->path FEATURE
+ Returns `#t' if FEATURE is a member of `*features*' or `*modules*'
+ or if FEATURE is supported by a file already loaded. Returns a
+ path if one was found in `*catalog*' under the feature name, and
+ `#f' otherwise. The path can either be a string suitable as an
+ argument to load or a pair as described above for *catalog*.
+
+
+File: slib.info, Node: Vicinity, Next: Configuration, Prev: Require, Up: Built-in Support
+
+Vicinity
+--------
+
+A vicinity is a descriptor for a place in the file system. Vicinities
+hide from the programmer the concepts of host, volume, directory, and
+version. Vicinities express only the concept of a file environment
+where a file name can be resolved to a file in a system independent
+manner. Vicinities can even be used on "flat" file systems (which have
+no directory structure) by having the vicinity express constraints on
+the file name. On most systems a vicinity would be a string. All of
+these procedures are file system dependent.
+
+These procedures are provided by all implementations.
+
+ - Function: make-vicinity PATH
+ Returns the vicinity of PATH for use by `in-vicinity'.
+
+ - Function: program-vicinity
+ Returns the vicinity of the currently loading Scheme code. For an
+ interpreter this would be the directory containing source code.
+ For a compiled system (with multiple files) this would be the
+ directory where the object or executable files are. If no file is
+ currently loading it the result is undefined. *Warning:*
+ `program-vicinity' can return incorrect values if your program
+ escapes back into a `load'.
+
+ - Function: library-vicinity
+ Returns the vicinity of the shared Scheme library.
+
+ - Function: implementation-vicinity
+ Returns the vicinity of the underlying Scheme implementation. This
+ vicinity will likely contain startup code and messages and a
+ compiler.
+
+ - Function: user-vicinity
+ Returns the vicinity of the current directory of the user. On most
+ systems this is `""' (the empty string).
+
+ - Function: home-vicinity
+ Returns the vicinity of the user's "HOME" directory, the directory
+ which typically contains files which customize a computer
+ environment for a user. If scheme is running without a user (eg.
+ a daemon) or if this concept is meaningless for the platform, then
+ `home-vicinity' returns `#f'.
+
+ - Function: in-vicinity VICINITY FILENAME
+ Returns a filename suitable for use by `slib:load',
+ `slib:load-source', `slib:load-compiled', `open-input-file',
+ `open-output-file', etc. The returned filename is FILENAME in
+ VICINITY. `in-vicinity' should allow FILENAME to override
+ VICINITY when FILENAME is an absolute pathname and VICINITY is
+ equal to the value of `(user-vicinity)'. The behavior of
+ `in-vicinity' when FILENAME is absolute and VICINITY is not equal
+ to the value of `(user-vicinity)' is unspecified. For most systems
+ `in-vicinity' can be `string-append'.
+
+ - Function: sub-vicinity VICINITY NAME
+ Returns the vicinity of VICINITY restricted to NAME. This is used
+ for large systems where names of files in subsystems could
+ conflict. On systems with directory structure `sub-vicinity' will
+ return a pathname of the subdirectory NAME of VICINITY.
+
+
+File: slib.info, Node: Configuration, Next: Input/Output, Prev: Vicinity, Up: Built-in Support
+
+Configuration
+-------------
+
+These constants and procedures describe characteristics of the Scheme
+and underlying operating system. They are provided by all
+implementations.
+
+ - Constant: char-code-limit
+ An integer 1 larger that the largest value which can be returned by
+ `char->integer'.
+
+ - Constant: most-positive-fixnum
+ In implementations which support integers of practically unlimited
+ size, MOST-POSITIVE-FIXNUM is a large exact integer within the
+ range of exact integers that may result from computing the length
+ of a list, vector, or string.
+
+ In implementations which do not support integers of practically
+ unlimited size, MOST-POSITIVE-FIXNUM is the largest exact integer
+ that may result from computing the length of a list, vector, or
+ string.
+
+ - Constant: slib:tab
+ The tab character.
+
+ - Constant: slib:form-feed
+ The form-feed character.
+
+ - Function: software-type
+ Returns a symbol denoting the generic operating system type. For
+ instance, `unix', `vms', `macos', `amiga', or `ms-dos'.
+
+ - Function: slib:report-version
+ Displays the versions of SLIB and the underlying Scheme
+ implementation and the name of the operating system. An
+ unspecified value is returned.
+
+ (slib:report-version) => slib "2c7" on scm "5b1" on unix |
+
+ - Function: slib:report
+ Displays the information of `(slib:report-version)' followed by
+ almost all the information neccessary for submitting a problem
+ report. An unspecified value is returned.
+
+ - Function: slib:report #T
+ provides a more verbose listing.
+
+ - Function: slib:report FILENAME
+ Writes the report to file `filename'.
+
+ (slib:report)
+ =>
+ slib "2c7" on scm "5b1" on unix |
+ (implementation-vicinity) is "/home/jaffer/scm/"
+ (library-vicinity) is "/home/jaffer/slib/"
+ (scheme-file-suffix) is ".scm"
+ loaded *features* :
+ trace alist qp sort
+ common-list-functions macro values getopt
+ compiled
+ implementation *features* :
+ bignum complex real rational
+ inexact vicinity ed getenv
+ tmpnam abort transcript with-file
+ ieee-p1178 rev4-report rev4-optional-procedures hash
+ object-hash delay eval dynamic-wind
+ multiarg-apply multiarg/and- logical defmacro
+ string-port source current-time record
+ rev3-procedures rev2-procedures sun-dl string-case
+ array dump char-ready? full-continuation
+ system
+ implementation *catalog* :
+ (i/o-extensions compiled "/home/jaffer/scm/ioext.so")
+ ...
+
+
+File: slib.info, Node: Input/Output, Next: Legacy, Prev: Configuration, Up: Built-in Support
+
+Input/Output
+------------
+
+These procedures are provided by all implementations.
+
+ - Procedure: file-exists? FILENAME
+ Returns `#t' if the specified file exists. Otherwise, returns
+ `#f'. If the underlying implementation does not support this
+ feature then `#f' is always returned.
+
+ - Procedure: delete-file FILENAME
+ Deletes the file specified by FILENAME. If FILENAME can not be
+ deleted, `#f' is returned. Otherwise, `#t' is returned.
+
+ - Procedure: tmpnam
+ Returns a pathname for a file which will likely not be used by any
+ other process. Successive calls to `(tmpnam)' will return
+ different pathnames.
+
+ - Procedure: current-error-port
+ Returns the current port to which diagnostic and error output is
+ directed.
+
+ - Procedure: force-output
+ - Procedure: force-output PORT
+ Forces any pending output on PORT to be delivered to the output
+ device and returns an unspecified value. The PORT argument may be
+ omitted, in which case it defaults to the value returned by
+ `(current-output-port)'.
+
+ - Procedure: output-port-width
+ - Procedure: output-port-width PORT
+ Returns the width of PORT, which defaults to
+ `(current-output-port)' if absent. If the width cannot be
+ determined 79 is returned.
+
+ - Procedure: output-port-height
+ - Procedure: output-port-height PORT
+ Returns the height of PORT, which defaults to
+ `(current-output-port)' if absent. If the height cannot be
+ determined 24 is returned.
+
+
+File: slib.info, Node: Legacy, Next: System, Prev: Input/Output, Up: Built-in Support
+
+Legacy
+------
+
+ These procedures are provided by all implementations.
+
+ - Function: identity X
+ IDENTITY returns its argument.
+
+ Example:
+ (identity 3)
+ => 3
+ (identity '(foo bar))
+ => (foo bar)
+ (map identity LST)
+ == (copy-list LST)
+
+The following procedures were present in Scheme until R4RS (*note
+Language changes: (r4rs)Notes.). They are provided by all SLIB
+implementations.
+
+ - Constant: t
+ Derfined as `#t'.
+
+ - Constant: nil
+ Defined as `#f'.
+
+ - Function: last-pair L
+ Returns the last pair in the list L. Example:
+ (last-pair (cons 1 2))
+ => (1 . 2)
+ (last-pair '(1 2))
+ => (2)
+ == (cons 2 '())
+
+
+File: slib.info, Node: System, Prev: Legacy, Up: Built-in Support
+
+System
+------
+
+These procedures are provided by all implementations.
+
+ - Procedure: slib:load-source NAME
+ Loads a file of Scheme source code from NAME with the default
+ filename extension used in SLIB. For instance if the filename
+ extension used in SLIB is `.scm' then `(slib:load-source "foo")'
+ will load from file `foo.scm'.
+
+ - Procedure: slib:load-compiled NAME
+ On implementations which support separtely loadable compiled
+ modules, loads a file of compiled code from NAME with the
+ implementation's filename extension for compiled code appended.
+
+ - Procedure: slib:load NAME
+ Loads a file of Scheme source or compiled code from NAME with the
+ appropriate suffixes appended. If both source and compiled code
+ are present with the appropriate names then the implementation
+ will load just one. It is up to the implementation to choose
+ which one will be loaded.
+
+ If an implementation does not support compiled code then
+ `slib:load' will be identical to `slib:load-source'.
+
+ - Procedure: slib:eval OBJ
+ `eval' returns the value of OBJ evaluated in the current top level
+ environment. *Note Eval:: provides a more general evaluation
+ facility.
+
+ - Procedure: slib:eval-load FILENAME EVAL
+ FILENAME should be a string. If filename names an existing file,
+ the Scheme source code expressions and definitions are read from
+ the file and EVAL called with them sequentially. The
+ `slib:eval-load' procedure does not affect the values returned by
+ `current-input-port' and `current-output-port'.
+
+ - Procedure: slib:warn ARG1 ARG2 ...
+ Outputs a warning message containing the arguments.
+
+ - Procedure: slib:error ARG1 ARG2 ...
+ Outputs an error message containing the arguments, aborts
+ evaluation of the current form and responds in a system dependent
+ way to the error. Typical responses are to abort the program or
+ to enter a read-eval-print loop.
+
+ - Procedure: slib:exit N
+ - Procedure: slib:exit
+ Exits from the Scheme session returning status N to the system.
+ If N is omitted or `#t', a success status is returned to the
+ system (if possible). If N is `#f' a failure is returned to the
+ system (if possible). If N is an integer, then N is returned to
+ the system (if possible). If the Scheme session cannot exit an
+ unspecified value is returned from `slib:exit'.
+
+
+File: slib.info, Node: About this manual, Prev: Built-in Support, Up: The Library System
+
+About this manual
+=================
+
+ * Entries that are labeled as Functions are called for their return
+ values. Entries that are labeled as Procedures are called
+ primarily for their side effects.
+
+ * Examples in this text were produced using the `scm' Scheme
+ implementation.
+
+ * At the beginning of each section, there is a line that looks like
+ `(require 'feature)'. Include this line in your code prior to
+ using the package.
+
+
+File: slib.info, Node: Scheme Syntax Extension Packages, Next: Textual Conversion Packages, Prev: The Library System, Up: Top
+
+Scheme Syntax Extension Packages
+********************************
+
+* Menu:
+
+* Defmacro:: Supported by all implementations
+
+* R4RS Macros:: 'macro
+* Macro by Example:: 'macro-by-example
+* Macros That Work:: 'macros-that-work
+* Syntactic Closures:: 'syntactic-closures
+* Syntax-Case Macros:: 'syntax-case
+
+Syntax extensions (macros) included with SLIB. Also *Note Structures::.
+
+* Fluid-Let:: 'fluid-let
+* Yasos:: 'yasos, 'oop, 'collect
+
+
+File: slib.info, Node: Defmacro, Next: R4RS Macros, Prev: Scheme Syntax Extension Packages, Up: Scheme Syntax Extension Packages
+
+Defmacro
+========
+
+ Defmacros are supported by all implementations.
+
+ - Function: gentemp
+ Returns a new (interned) symbol each time it is called. The symbol
+ names are implementation-dependent
+ (gentemp) => scm:G0
+ (gentemp) => scm:G1
+
+ - Function: defmacro:eval E
+ Returns the `slib:eval' of expanding all defmacros in scheme
+ expression E.
+
+ - Function: defmacro:load FILENAME
+ FILENAME should be a string. If filename names an existing file,
+ the `defmacro:load' procedure reads Scheme source code expressions
+ and definitions from the file and evaluates them sequentially.
+ These source code expressions and definitions may contain defmacro
+ definitions. The `macro:load' procedure does not affect the values
+ returned by `current-input-port' and `current-output-port'.
+
+ - Function: defmacro? SYM
+ Returns `#t' if SYM has been defined by `defmacro', `#f' otherwise.
+
+ - Function: macroexpand-1 FORM
+ - Function: macroexpand FORM
+ If FORM is a macro call, `macroexpand-1' will expand the macro
+ call once and return it. A FORM is considered to be a macro call
+ only if it is a cons whose `car' is a symbol for which a `defmacr'
+ has been defined.
+
+ `macroexpand' is similar to `macroexpand-1', but repeatedly
+ expands FORM until it is no longer a macro call.
+
+ - Macro: defmacro NAME LAMBDA-LIST FORM ...
+ When encountered by `defmacro:eval', `defmacro:macroexpand*', or
+ `defmacro:load' defines a new macro which will henceforth be
+ expanded when encountered by `defmacro:eval',
+ `defmacro:macroexpand*', or `defmacro:load'.
+
+Defmacroexpand
+--------------
+
+ `(require 'defmacroexpand)'
+
+ - Function: defmacro:expand* E
+ Returns the result of expanding all defmacros in scheme expression
+ E.
+
+
+File: slib.info, Node: R4RS Macros, Next: Macro by Example, Prev: Defmacro, Up: Scheme Syntax Extension Packages
+
+R4RS Macros
+===========
+
+ `(require 'macro)' is the appropriate call if you want R4RS
+high-level macros but don't care about the low level implementation. If
+an SLIB R4RS macro implementation is already loaded it will be used.
+Otherwise, one of the R4RS macros implemetations is loaded.
+
+ The SLIB R4RS macro implementations support the following uniform
+interface:
+
+ - Function: macro:expand SEXPRESSION
+ Takes an R4RS expression, macro-expands it, and returns the result
+ of the macro expansion.
+
+ - Function: macro:eval SEXPRESSION
+ Takes an R4RS expression, macro-expands it, evals the result of the
+ macro expansion, and returns the result of the evaluation.
+
+ - Procedure: macro:load FILENAME
+ FILENAME should be a string. If filename names an existing file,
+ the `macro:load' procedure reads Scheme source code expressions and
+ definitions from the file and evaluates them sequentially. These
+ source code expressions and definitions may contain macro
+ definitions. The `macro:load' procedure does not affect the
+ values returned by `current-input-port' and `current-output-port'.
+
+
+File: slib.info, Node: Macro by Example, Next: Macros That Work, Prev: R4RS Macros, Up: Scheme Syntax Extension Packages
+
+Macro by Example
+================
+
+ `(require 'macro-by-example)'
+
+ A vanilla implementation of `Macro by Example' (Eugene Kohlbecker,
+R4RS) by Dorai Sitaram, (dorai@cs.rice.edu) using `defmacro'.
+
+ * generating hygienic global `define-syntax' Macro-by-Example macros
+ *cheaply*.
+
+ * can define macros which use `...'.
+
+ * needn't worry about a lexical variable in a macro definition
+ clashing with a variable from the macro use context
+
+ * don't suffer the overhead of redefining the repl if `defmacro'
+ natively supported (most implementations)
+
+Caveat
+------
+
+ These macros are not referentially transparent (*note Macros:
+(r4rs)Macros.). Lexically scoped macros (i.e., `let-syntax' and
+`letrec-syntax') are not supported. In any case, the problem of
+referential transparency gains poignancy only when `let-syntax' and
+`letrec-syntax' are used. So you will not be courting large-scale
+disaster unless you're using system-function names as local variables
+with unintuitive bindings that the macro can't use. However, if you
+must have the full `r4rs' macro functionality, look to the more
+featureful (but also more expensive) versions of syntax-rules available
+in slib *Note Macros That Work::, *Note Syntactic Closures::, and *Note
+Syntax-Case Macros::.
+
+ - Macro: define-syntax KEYWORD TRANSFORMER-SPEC
+ The KEYWORD is an identifier, and the TRANSFORMER-SPEC should be
+ an instance of `syntax-rules'.
+
+ The top-level syntactic environment is extended by binding the
+ KEYWORD to the specified transformer.
+
+ (define-syntax let*
+ (syntax-rules ()
+ ((let* () body1 body2 ...)
+ (let () body1 body2 ...))
+ ((let* ((name1 val1) (name2 val2) ...)
+ body1 body2 ...)
+ (let ((name1 val1))
+ (let* (( name2 val2) ...)
+ body1 body2 ...)))))
+
+ - Macro: syntax-rules LITERALS SYNTAX-RULE ...
+ LITERALS is a list of identifiers, and each SYNTAX-RULE should be
+ of the form
+
+ `(PATTERN TEMPLATE)'
+
+ where the PATTERN and TEMPLATE are as in the grammar above.
+
+ An instance of `syntax-rules' produces a new macro transformer by
+ specifying a sequence of hygienic rewrite rules. A use of a macro
+ whose keyword is associated with a transformer specified by
+ `syntax-rules' is matched against the patterns contained in the
+ SYNTAX-RULEs, beginning with the leftmost SYNTAX-RULE. When a
+ match is found, the macro use is trancribed hygienically according
+ to the template.
+
+ Each pattern begins with the keyword for the macro. This keyword
+ is not involved in the matching and is not considered a pattern
+ variable or literal identifier.
+
+
+File: slib.info, Node: Macros That Work, Next: Syntactic Closures, Prev: Macro by Example, Up: Scheme Syntax Extension Packages
+
+Macros That Work
+================
+
+ `(require 'macros-that-work)'
+
+ `Macros That Work' differs from the other R4RS macro implementations
+in that it does not expand derived expression types to primitive
+expression types.
+
+ - Function: macro:expand EXPRESSION
+ - Function: macwork:expand EXPRESSION
+ Takes an R4RS expression, macro-expands it, and returns the result
+ of the macro expansion.
+
+ - Function: macro:eval EXPRESSION
+ - Function: macwork:eval EXPRESSION
+ `macro:eval' returns the value of EXPRESSION in the current top
+ level environment. EXPRESSION can contain macro definitions.
+ Side effects of EXPRESSION will affect the top level environment.
+
+ - Procedure: macro:load FILENAME
+ - Procedure: macwork:load FILENAME
+ FILENAME should be a string. If filename names an existing file,
+ the `macro:load' procedure reads Scheme source code expressions and
+ definitions from the file and evaluates them sequentially. These
+ source code expressions and definitions may contain macro
+ definitions. The `macro:load' procedure does not affect the
+ values returned by `current-input-port' and `current-output-port'.
+
+ References:
+
+ The `Revised^4 Report on the Algorithmic Language Scheme' Clinger and
+Rees [editors]. To appear in LISP Pointers. Also available as a
+technical report from the University of Oregon, MIT AI Lab, and Cornell.
+
+ Macros That Work. Clinger and Rees. POPL '91.
+
+ The supported syntax differs from the R4RS in that vectors are allowed
+as patterns and as templates and are not allowed as pattern or template
+data.
+
+ transformer spec ==> (syntax-rules literals rules)
+
+ rules ==> ()
+ | (rule . rules)
+
+ rule ==> (pattern template)
+
+ pattern ==> pattern_var ; a symbol not in literals
+ | symbol ; a symbol in literals
+ | ()
+ | (pattern . pattern)
+ | (ellipsis_pattern)
+ | #(pattern*) ; extends R4RS
+ | #(pattern* ellipsis_pattern) ; extends R4RS
+ | pattern_datum
+
+ template ==> pattern_var
+ | symbol
+ | ()
+ | (template2 . template2)
+ | #(template*) ; extends R4RS
+ | pattern_datum
+
+ template2 ==> template
+ | ellipsis_template
+
+ pattern_datum ==> string ; no vector
+ | character
+ | boolean
+ | number
+
+ ellipsis_pattern ==> pattern ...
+
+ ellipsis_template ==> template ...
+
+ pattern_var ==> symbol ; not in literals
+
+ literals ==> ()
+ | (symbol . literals)
+
+Definitions
+-----------
+
+Scope of an ellipsis
+ Within a pattern or template, the scope of an ellipsis (`...') is
+ the pattern or template that appears to its left.
+
+Rank of a pattern variable
+ The rank of a pattern variable is the number of ellipses within
+ whose scope it appears in the pattern.
+
+Rank of a subtemplate
+ The rank of a subtemplate is the number of ellipses within whose
+ scope it appears in the template.
+
+Template rank of an occurrence of a pattern variable
+ The template rank of an occurrence of a pattern variable within a
+ template is the rank of that occurrence, viewed as a subtemplate.
+
+Variables bound by a pattern
+ The variables bound by a pattern are the pattern variables that
+ appear within it.
+
+Referenced variables of a subtemplate
+ The referenced variables of a subtemplate are the pattern
+ variables that appear within it.
+
+Variables opened by an ellipsis template
+ The variables opened by an ellipsis template are the referenced
+ pattern variables whose rank is greater than the rank of the
+ ellipsis template.
+
+Restrictions
+------------
+
+ No pattern variable appears more than once within a pattern.
+
+ For every occurrence of a pattern variable within a template, the
+template rank of the occurrence must be greater than or equal to the
+pattern variable's rank.
+
+ Every ellipsis template must open at least one variable.
+
+ For every ellipsis template, the variables opened by an ellipsis
+template must all be bound to sequences of the same length.
+
+ The compiled form of a RULE is
+
+ rule ==> (pattern template inserted)
+
+ pattern ==> pattern_var
+ | symbol
+ | ()
+ | (pattern . pattern)
+ | ellipsis_pattern
+ | #(pattern)
+ | pattern_datum
+
+ template ==> pattern_var
+ | symbol
+ | ()
+ | (template2 . template2)
+ | #(pattern)
+ | pattern_datum
+
+ template2 ==> template
+ | ellipsis_template
+
+ pattern_datum ==> string
+ | character
+ | boolean
+ | number
+
+ pattern_var ==> #(V symbol rank)
+
+ ellipsis_pattern ==> #(E pattern pattern_vars)
+
+ ellipsis_template ==> #(E template pattern_vars)
+
+ inserted ==> ()
+ | (symbol . inserted)
+
+ pattern_vars ==> ()
+ | (pattern_var . pattern_vars)
+
+ rank ==> exact non-negative integer
+
+ where V and E are unforgeable values.
+
+ The pattern variables associated with an ellipsis pattern are the
+variables bound by the pattern, and the pattern variables associated
+with an ellipsis template are the variables opened by the ellipsis
+template.
+
+ If the template contains a big chunk that contains no pattern
+variables or inserted identifiers, then the big chunk will be copied
+unnecessarily. That shouldn't matter very often.
+
+
+File: slib.info, Node: Syntactic Closures, Next: Syntax-Case Macros, Prev: Macros That Work, Up: Scheme Syntax Extension Packages
+
+Syntactic Closures
+==================
+
+ `(require 'syntactic-closures)'
+
+ - Function: macro:expand EXPRESSION
+ - Function: synclo:expand EXPRESSION
+ Returns scheme code with the macros and derived expression types of
+ EXPRESSION expanded to primitive expression types.
+
+ - Function: macro:eval EXPRESSION
+ - Function: synclo:eval EXPRESSION
+ `macro:eval' returns the value of EXPRESSION in the current top
+ level environment. EXPRESSION can contain macro definitions.
+ Side effects of EXPRESSION will affect the top level environment.
+
+ - Procedure: macro:load FILENAME
+ - Procedure: synclo:load FILENAME
+ FILENAME should be a string. If filename names an existing file,
+ the `macro:load' procedure reads Scheme source code expressions and
+ definitions from the file and evaluates them sequentially. These
+ source code expressions and definitions may contain macro
+ definitions. The `macro:load' procedure does not affect the
+ values returned by `current-input-port' and `current-output-port'.
+
+Syntactic Closure Macro Facility
+--------------------------------
+
+ A Syntactic Closures Macro Facility
+
+ by Chris Hanson
+
+ 9 November 1991
+
+ This document describes "syntactic closures", a low-level macro
+facility for the Scheme programming language. The facility is an
+alternative to the low-level macro facility described in the `Revised^4
+Report on Scheme.' This document is an addendum to that report.
+
+ The syntactic closures facility extends the BNF rule for TRANSFORMER
+SPEC to allow a new keyword that introduces a low-level macro
+transformer:
+ TRANSFORMER SPEC := (transformer EXPRESSION)
+
+ Additionally, the following procedures are added:
+ make-syntactic-closure
+ capture-syntactic-environment
+ identifier?
+ identifier=?
+
+ The description of the facility is divided into three parts. The
+first part defines basic terminology. The second part describes how
+macro transformers are defined. The third part describes the use of
+"identifiers", which extend the syntactic closure mechanism to be
+compatible with `syntax-rules'.
+
+Terminology
+...........
+
+ This section defines the concepts and data types used by the syntactic
+closures facility.
+
+ * "Forms" are the syntactic entities out of which programs are
+ recursively constructed. A form is any expression, any
+ definition, any syntactic keyword, or any syntactic closure. The
+ variable name that appears in a `set!' special form is also a
+ form. Examples of forms:
+ 17
+ #t
+ car
+ (+ x 4)
+ (lambda (x) x)
+ (define pi 3.14159)
+ if
+ define
+
+ * An "alias" is an alternate name for a given symbol. It can appear
+ anywhere in a form that the symbol could be used, and when quoted
+ it is replaced by the symbol; however, it does not satisfy the
+ predicate `symbol?'. Macro transformers rarely distinguish
+ symbols from aliases, referring to both as identifiers.
+
+ * A "syntactic" environment maps identifiers to their meanings.
+ More precisely, it determines whether an identifier is a syntactic
+ keyword or a variable. If it is a keyword, the meaning is an
+ interpretation for the form in which that keyword appears. If it
+ is a variable, the meaning identifies which binding of that
+ variable is referenced. In short, syntactic environments contain
+ all of the contextual information necessary for interpreting the
+ meaning of a particular form.
+
+ * A "syntactic closure" consists of a form, a syntactic environment,
+ and a list of identifiers. All identifiers in the form take their
+ meaning from the syntactic environment, except those in the given
+ list. The identifiers in the list are to have their meanings
+ determined later. A syntactic closure may be used in any context
+ in which its form could have been used. Since a syntactic closure
+ is also a form, it may not be used in contexts where a form would
+ be illegal. For example, a form may not appear as a clause in the
+ cond special form. A syntactic closure appearing in a quoted
+ structure is replaced by its form.
+
+Transformer Definition
+......................
+
+ This section describes the `transformer' special form and the
+procedures `make-syntactic-closure' and `capture-syntactic-environment'.
+
+ - Syntax: transformer EXPRESSION
+ Syntax: It is an error if this syntax occurs except as a
+ TRANSFORMER SPEC.
+
+ Semantics: The EXPRESSION is evaluated in the standard transformer
+ environment to yield a macro transformer as described below. This
+ macro transformer is bound to a macro keyword by the special form
+ in which the `transformer' expression appears (for example,
+ `let-syntax').
+
+ A "macro transformer" is a procedure that takes two arguments, a
+ form and a syntactic environment, and returns a new form. The
+ first argument, the "input form", is the form in which the macro
+ keyword occurred. The second argument, the "usage environment",
+ is the syntactic environment in which the input form occurred.
+ The result of the transformer, the "output form", is automatically
+ closed in the "transformer environment", which is the syntactic
+ environment in which the `transformer' expression occurred.
+
+ For example, here is a definition of a push macro using
+ `syntax-rules':
+ (define-syntax push
+ (syntax-rules ()
+ ((push item list)
+ (set! list (cons item list)))))
+
+ Here is an equivalent definition using `transformer':
+ (define-syntax push
+ (transformer
+ (lambda (exp env)
+ (let ((item
+ (make-syntactic-closure env '() (cadr exp)))
+ (list
+ (make-syntactic-closure env '() (caddr exp))))
+ `(set! ,list (cons ,item ,list))))))
+
+ In this example, the identifiers `set!' and `cons' are closed in
+ the transformer environment, and thus will not be affected by the
+ meanings of those identifiers in the usage environment `env'.
+
+ Some macros may be non-hygienic by design. For example, the
+ following defines a loop macro that implicitly binds `exit' to an
+ escape procedure. The binding of `exit' is intended to capture
+ free references to `exit' in the body of the loop, so `exit' must
+ be left free when the body is closed:
+ (define-syntax loop
+ (transformer
+ (lambda (exp env)
+ (let ((body (cdr exp)))
+ `(call-with-current-continuation
+ (lambda (exit)
+ (let f ()
+ ,@(map (lambda (exp)
+ (make-syntactic-closure env '(exit)
+ exp))
+ body)
+ (f))))))))
+
+ To assign meanings to the identifiers in a form, use
+ `make-syntactic-closure' to close the form in a syntactic
+ environment.
+
+ - Function: make-syntactic-closure ENVIRONMENT FREE-NAMES FORM
+ ENVIRONMENT must be a syntactic environment, FREE-NAMES must be a
+ list of identifiers, and FORM must be a form.
+ `make-syntactic-closure' constructs and returns a syntactic closure
+ of FORM in ENVIRONMENT, which can be used anywhere that FORM could
+ have been used. All the identifiers used in FORM, except those
+ explicitly excepted by FREE-NAMES, obtain their meanings from
+ ENVIRONMENT.
+
+ Here is an example where FREE-NAMES is something other than the
+ empty list. It is instructive to compare the use of FREE-NAMES in
+ this example with its use in the `loop' example above: the examples
+ are similar except for the source of the identifier being left
+ free.
+ (define-syntax let1
+ (transformer
+ (lambda (exp env)
+ (let ((id (cadr exp))
+ (init (caddr exp))
+ (exp (cadddr exp)))
+ `((lambda (,id)
+ ,(make-syntactic-closure env (list id) exp))
+ ,(make-syntactic-closure env '() init))))))
+
+ `let1' is a simplified version of `let' that only binds a single
+ identifier, and whose body consists of a single expression. When
+ the body expression is syntactically closed in its original
+ syntactic environment, the identifier that is to be bound by
+ `let1' must be left free, so that it can be properly captured by
+ the `lambda' in the output form.
+
+ To obtain a syntactic environment other than the usage
+ environment, use `capture-syntactic-environment'.
+
+ - Function: capture-syntactic-environment PROCEDURE
+ `capture-syntactic-environment' returns a form that will, when
+ transformed, call PROCEDURE on the current syntactic environment.
+ PROCEDURE should compute and return a new form to be transformed,
+ in that same syntactic environment, in place of the form.
+
+ An example will make this clear. Suppose we wanted to define a
+ simple `loop-until' keyword equivalent to
+ (define-syntax loop-until
+ (syntax-rules ()
+ ((loop-until id init test return step)
+ (letrec ((loop
+ (lambda (id)
+ (if test return (loop step)))))
+ (loop init)))))
+
+ The following attempt at defining `loop-until' has a subtle bug:
+ (define-syntax loop-until
+ (transformer
+ (lambda (exp env)
+ (let ((id (cadr exp))
+ (init (caddr exp))
+ (test (cadddr exp))
+ (return (cadddr (cdr exp)))
+ (step (cadddr (cddr exp)))
+ (close
+ (lambda (exp free)
+ (make-syntactic-closure env free exp))))
+ `(letrec ((loop
+ (lambda (,id)
+ (if ,(close test (list id))
+ ,(close return (list id))
+ (loop ,(close step (list id)))))))
+ (loop ,(close init '())))))))
+
+ This definition appears to take all of the proper precautions to
+ prevent unintended captures. It carefully closes the
+ subexpressions in their original syntactic environment and it
+ leaves the `id' identifier free in the `test', `return', and
+ `step' expressions, so that it will be captured by the binding
+ introduced by the `lambda' expression. Unfortunately it uses the
+ identifiers `if' and `loop' within that `lambda' expression, so if
+ the user of `loop-until' just happens to use, say, `if' for the
+ identifier, it will be inadvertently captured.
+
+ The syntactic environment that `if' and `loop' want to be exposed
+ to is the one just outside the `lambda' expression: before the
+ user's identifier is added to the syntactic environment, but after
+ the identifier loop has been added.
+ `capture-syntactic-environment' captures exactly that environment
+ as follows:
+ (define-syntax loop-until
+ (transformer
+ (lambda (exp env)
+ (let ((id (cadr exp))
+ (init (caddr exp))
+ (test (cadddr exp))
+ (return (cadddr (cdr exp)))
+ (step (cadddr (cddr exp)))
+ (close
+ (lambda (exp free)
+ (make-syntactic-closure env free exp))))
+ `(letrec ((loop
+ ,(capture-syntactic-environment
+ (lambda (env)
+ `(lambda (,id)
+ (,(make-syntactic-closure env '() `if)
+ ,(close test (list id))
+ ,(close return (list id))
+ (,(make-syntactic-closure env '()
+ `loop)
+ ,(close step (list id)))))))))
+ (loop ,(close init '())))))))
+
+ In this case, having captured the desired syntactic environment,
+ it is convenient to construct syntactic closures of the
+ identifiers `if' and the `loop' and use them in the body of the
+ `lambda'.
+
+ A common use of `capture-syntactic-environment' is to get the
+ transformer environment of a macro transformer:
+ (transformer
+ (lambda (exp env)
+ (capture-syntactic-environment
+ (lambda (transformer-env)
+ ...))))
+
+Identifiers
+...........
+
+ This section describes the procedures that create and manipulate
+identifiers. Previous syntactic closure proposals did not have an
+identifier data type - they just used symbols. The identifier data
+type extends the syntactic closures facility to be compatible with the
+high-level `syntax-rules' facility.
+
+ As discussed earlier, an identifier is either a symbol or an "alias".
+An alias is implemented as a syntactic closure whose "form" is an
+identifier:
+ (make-syntactic-closure env '() 'a)
+ => an "alias"
+
+ Aliases are implemented as syntactic closures because they behave just
+like syntactic closures most of the time. The difference is that an
+alias may be bound to a new value (for example by `lambda' or
+`let-syntax'); other syntactic closures may not be used this way. If
+an alias is bound, then within the scope of that binding it is looked
+up in the syntactic environment just like any other identifier.
+
+ Aliases are used in the implementation of the high-level facility
+`syntax-rules'. A macro transformer created by `syntax-rules' uses a
+template to generate its output form, substituting subforms of the
+input form into the template. In a syntactic closures implementation,
+all of the symbols in the template are replaced by aliases closed in
+the transformer environment, while the output form itself is closed in
+the usage environment. This guarantees that the macro transformation
+is hygienic, without requiring the transformer to know the syntactic
+roles of the substituted input subforms.
+
+ - Function: identifier? OBJECT
+ Returns `#t' if OBJECT is an identifier, otherwise returns `#f'.
+ Examples:
+ (identifier? 'a)
+ => #t
+ (identifier? (make-syntactic-closure env '() 'a))
+ => #t
+ (identifier? "a")
+ => #f
+ (identifier? #\a)
+ => #f
+ (identifier? 97)
+ => #f
+ (identifier? #f)
+ => #f
+ (identifier? '(a))
+ => #f
+ (identifier? '#(a))
+ => #f
+
+ The predicate `eq?' is used to determine if two identifers are
+ "the same". Thus `eq?' can be used to compare identifiers exactly
+ as it would be used to compare symbols. Often, though, it is
+ useful to know whether two identifiers "mean the same thing". For
+ example, the `cond' macro uses the symbol `else' to identify the
+ final clause in the conditional. A macro transformer for `cond'
+ cannot just look for the symbol `else', because the `cond' form
+ might be the output of another macro transformer that replaced the
+ symbol `else' with an alias. Instead the transformer must look
+ for an identifier that "means the same thing" in the usage
+ environment as the symbol `else' means in the transformer
+ environment.
+
+ - Function: identifier=? ENVIRONMENT1 IDENTIFIER1 ENVIRONMENT2
+ IDENTIFIER2
+ ENVIRONMENT1 and ENVIRONMENT2 must be syntactic environments, and
+ IDENTIFIER1 and IDENTIFIER2 must be identifiers. `identifier=?'
+ returns `#t' if the meaning of IDENTIFIER1 in ENVIRONMENT1 is the
+ same as that of IDENTIFIER2 in ENVIRONMENT2, otherwise it returns
+ `#f'. Examples:
+
+ (let-syntax
+ ((foo
+ (transformer
+ (lambda (form env)
+ (capture-syntactic-environment
+ (lambda (transformer-env)
+ (identifier=? transformer-env 'x env 'x)))))))
+ (list (foo)
+ (let ((x 3))
+ (foo))))
+ => (#t #f)
+
+ (let-syntax ((bar foo))
+ (let-syntax
+ ((foo
+ (transformer
+ (lambda (form env)
+ (capture-syntactic-environment
+ (lambda (transformer-env)
+ (identifier=? transformer-env 'foo
+ env (cadr form))))))))
+ (list (foo foo)
+ (foobar))))
+ => (#f #t)
+
+Acknowledgements
+................
+
+ The syntactic closures facility was invented by Alan Bawden and
+Jonathan Rees. The use of aliases to implement `syntax-rules' was
+invented by Alan Bawden (who prefers to call them "synthetic names").
+Much of this proposal is derived from an earlier proposal by Alan
+Bawden.
+
+
+File: slib.info, Node: Syntax-Case Macros, Next: Fluid-Let, Prev: Syntactic Closures, Up: Scheme Syntax Extension Packages
+
+Syntax-Case Macros
+==================
+
+ `(require 'syntax-case)'
+
+ - Function: macro:expand EXPRESSION
+ - Function: syncase:expand EXPRESSION
+ Returns scheme code with the macros and derived expression types of
+ EXPRESSION expanded to primitive expression types.
+
+ - Function: macro:eval EXPRESSION
+ - Function: syncase:eval EXPRESSION
+ `macro:eval' returns the value of EXPRESSION in the current top
+ level environment. EXPRESSION can contain macro definitions.
+ Side effects of EXPRESSION will affect the top level environment.
+
+ - Procedure: macro:load FILENAME
+ - Procedure: syncase:load FILENAME
+ FILENAME should be a string. If filename names an existing file,
+ the `macro:load' procedure reads Scheme source code expressions and
+ definitions from the file and evaluates them sequentially. These
+ source code expressions and definitions may contain macro
+ definitions. The `macro:load' procedure does not affect the
+ values returned by `current-input-port' and `current-output-port'.
+
+ This is version 2.1 of `syntax-case', the low-level macro facility
+proposed and implemented by Robert Hieb and R. Kent Dybvig.
+
+ This version is further adapted by Harald Hanche-Olsen
+<hanche@imf.unit.no> to make it compatible with, and easily usable
+with, SLIB. Mainly, these adaptations consisted of:
+
+ * Removing white space from `expand.pp' to save space in the
+ distribution. This file is not meant for human readers anyway...
+
+ * Removed a couple of Chez scheme dependencies.
+
+ * Renamed global variables used to minimize the possibility of name
+ conflicts.
+
+ * Adding an SLIB-specific initialization file.
+
+ * Removing a couple extra files, most notably the documentation (but
+ see below).
+
+ If you wish, you can see exactly what changes were done by reading the
+shell script in the file `syncase.sh'.
+
+ The two PostScript files were omitted in order to not burden the SLIB
+distribution with them. If you do intend to use `syntax-case',
+however, you should get these files and print them out on a PostScript
+printer. They are available with the original `syntax-case'
+distribution by anonymous FTP in
+`cs.indiana.edu:/pub/scheme/syntax-case'.
+
+ In order to use syntax-case from an interactive top level, execute:
+ (require 'syntax-case)
+ (require 'repl)
+ (repl:top-level macro:eval)
+ See the section Repl (*note Repl::.) for more information.
+
+ To check operation of syntax-case get
+`cs.indiana.edu:/pub/scheme/syntax-case', and type
+ (require 'syntax-case)
+ (syncase:sanity-check)
+
+ Beware that `syntax-case' takes a long time to load - about 20s on a
+SPARCstation SLC (with SCM) and about 90s on a Macintosh SE/30 (with
+Gambit).
+
+Notes
+-----
+
+ All R4RS syntactic forms are defined, including `delay'. Along with
+`delay' are simple definitions for `make-promise' (into which `delay'
+expressions expand) and `force'.
+
+ `syntax-rules' and `with-syntax' (described in `TR356') are defined.
+
+ `syntax-case' is actually defined as a macro that expands into calls
+to the procedure `syntax-dispatch' and the core form `syntax-lambda';
+do not redefine these names.
+
+ Several other top-level bindings not documented in TR356 are created:
+ * the "hooks" in `hooks.ss'
+
+ * the `build-' procedures in `output.ss'
+
+ * `expand-syntax' (the expander)
+
+ The syntax of define has been extended to allow `(define ID)', which
+assigns ID to some unspecified value.
+
+ We have attempted to maintain R4RS compatibility where possible. The
+incompatibilities should be confined to `hooks.ss'. Please let us know
+if there is some incompatibility that is not flagged as such.
+
+ Send bug reports, comments, suggestions, and questions to Kent Dybvig
+(dyb@iuvax.cs.indiana.edu).
+
+Note from maintainer
+--------------------
+
+ Included with the `syntax-case' files was `structure.scm' which
+defines a macro `define-structure'. There is no documentation for this
+macro and it is not used by any code in SLIB.
+
+
+File: slib.info, Node: Fluid-Let, Next: Yasos, Prev: Syntax-Case Macros, Up: Scheme Syntax Extension Packages
+
+Fluid-Let
+=========
+
+ `(require 'fluid-let)'
+
+ - Syntax: fluid-let `(BINDINGS ...)' FORMS...
+
+ (fluid-let ((VARIABLE INIT) ...)
+ EXPRESSION EXPRESSION ...)
+
+ The INITs are evaluated in the current environment (in some
+unspecified order), the current values of the VARIABLEs are saved, the
+results are assigned to the VARIABLEs, the EXPRESSIONs are evaluated
+sequentially in the current environment, the VARIABLEs are restored to
+their original values, and the value of the last EXPRESSION is returned.
+
+ The syntax of this special form is similar to that of `let', but
+`fluid-let' temporarily rebinds existing VARIABLEs. Unlike `let',
+`fluid-let' creates no new bindings; instead it *assigns* the values of
+each INIT to the binding (determined by the rules of lexical scoping)
+of its corresponding VARIABLE.
+
+
+File: slib.info, Node: Yasos, Prev: Fluid-Let, Up: Scheme Syntax Extension Packages
+
+Yasos
+=====
+
+ `(require 'oop)' or `(require 'yasos)'
+
+ `Yet Another Scheme Object System' is a simple object system for
+Scheme based on the paper by Norman Adams and Jonathan Rees: `Object
+Oriented Programming in Scheme', Proceedings of the 1988 ACM Conference
+on LISP and Functional Programming, July 1988 [ACM #552880].
+
+ Another reference is:
+
+ Ken Dickey. Scheming with Objects `AI Expert' Volume 7, Number 10
+(October 1992), pp. 24-33.
+
+* Menu:
+
+* Yasos terms:: Definitions and disclaimer.
+* Yasos interface:: The Yasos macros and procedures.
+* Setters:: Dylan-like setters in Yasos.
+* Yasos examples:: Usage of Yasos and setters.
+
+
+File: slib.info, Node: Yasos terms, Next: Yasos interface, Prev: Yasos, Up: Yasos
+
+Terms
+-----
+
+"Object"
+ Any Scheme data object.
+
+"Instance"
+ An instance of the OO system; an "object".
+
+"Operation"
+ A METHOD.
+
+*Notes:*
+ The object system supports multiple inheritance. An instance can
+ inherit from 0 or more ancestors. In the case of multiple
+ inherited operations with the same identity, the operation used is
+ that from the first ancestor which contains it (in the ancestor
+ `let'). An operation may be applied to any Scheme data
+ object--not just instances. As code which creates instances is
+ just code, there are no "classes" and no meta-ANYTHING. Method
+ dispatch is by a procedure call a la CLOS rather than by `send'
+ syntax a la Smalltalk.
+
+*Disclaimer:*
+ There are a number of optimizations which can be made. This
+ implementation is expository (although performance should be quite
+ reasonable). See the L&FP paper for some suggestions.
+
+
+File: slib.info, Node: Yasos interface, Next: Setters, Prev: Yasos terms, Up: Yasos
+
+Interface
+---------
+
+ - Syntax: define-operation `('OPNAME SELF ARG ...`)' DEFAULT-BODY
+ Defines a default behavior for data objects which don't handle the
+ operation OPNAME. The default behavior (for an empty
+ DEFAULT-BODY) is to generate an error.
+
+ - Syntax: define-predicate OPNAME?
+ Defines a predicate OPNAME?, usually used for determining the
+ "type" of an object, such that `(OPNAME? OBJECT)' returns `#t' if
+ OBJECT has an operation OPNAME? and `#f' otherwise.
+
+ - Syntax: object `((NAME SELF ARG ...) BODY)' ...
+ Returns an object (an instance of the object system) with
+ operations. Invoking `(NAME OBJECT ARG ...' executes the BODY of
+ the OBJECT with SELF bound to OBJECT and with argument(s) ARG....
+
+ - Syntax: object-with-ancestors `(('ANCESTOR1 INIT1`)' ...`)'
+ OPERATION ...
+ A `let'-like form of `object' for multiple inheritance. It
+ returns an object inheriting the behaviour of ANCESTOR1 etc. An
+ operation will be invoked in an ancestor if the object itself does
+ not provide such a method. In the case of multiple inherited
+ operations with the same identity, the operation used is the one
+ found in the first ancestor in the ancestor list.
+
+ - Syntax: operate-as COMPONENT OPERATION SELF ARG ...
+ Used in an operation definition (of SELF) to invoke the OPERATION
+ in an ancestor COMPONENT but maintain the object's identity. Also
+ known as "send-to-super".
+
+ - Procedure: print OBJ PORT
+ A default `print' operation is provided which is just `(format
+ PORT OBJ)' (*note Format::.) for non-instances and prints OBJ
+ preceded by `#<INSTANCE>' for instances.
+
+ - Function: size OBJ
+ The default method returns the number of elements in OBJ if it is
+ a vector, string or list, `2' for a pair, `1' for a character and
+ by default id an error otherwise. Objects such as collections
+ (*note Collections::.) may override the default in an obvious way.
+
+
+File: slib.info, Node: Setters, Next: Yasos examples, Prev: Yasos interface, Up: Yasos
+
+Setters
+-------
+
+ "Setters" implement "generalized locations" for objects associated
+with some sort of mutable state. A "getter" operation retrieves a
+value from a generalized location and the corresponding setter
+operation stores a value into the location. Only the getter is named -
+the setter is specified by a procedure call as below. (Dylan uses
+special syntax.) Typically, but not necessarily, getters are access
+operations to extract values from Yasos objects (*note Yasos::.).
+Several setters are predefined, corresponding to getters `car', `cdr',
+`string-ref' and `vector-ref' e.g., `(setter car)' is equivalent to
+`set-car!'.
+
+ This implementation of setters is similar to that in Dylan(TM)
+(`Dylan: An object-oriented dynamic language', Apple Computer Eastern
+Research and Technology). Common LISP provides similar facilities
+through `setf'.
+
+ - Function: setter GETTER
+ Returns the setter for the procedure GETTER. E.g., since
+ `string-ref' is the getter corresponding to a setter which is
+ actually `string-set!':
+ (define foo "foo")
+ ((setter string-ref) foo 0 #\F) ; set element 0 of foo
+ foo => "Foo"
+
+ - Syntax: set PLACE NEW-VALUE
+ If PLACE is a variable name, `set' is equivalent to `set!'.
+ Otherwise, PLACE must have the form of a procedure call, where the
+ procedure name refers to a getter and the call indicates an
+ accessible generalized location, i.e., the call would return a
+ value. The return value of `set' is usually unspecified unless
+ used with a setter whose definition guarantees to return a useful
+ value.
+ (set (string-ref foo 2) #\O) ; generalized location with getter
+ foo => "FoO"
+ (set foo "foo") ; like set!
+ foo => "foo"
+
+ - Procedure: add-setter GETTER SETTER
+ Add procedures GETTER and SETTER to the (inaccessible) list of
+ valid setter/getter pairs. SETTER implements the store operation
+ corresponding to the GETTER access operation for the relevant
+ state. The return value is unspecified.
+
+ - Procedure: remove-setter-for GETTER
+ Removes the setter corresponding to the specified GETTER from the
+ list of valid setters. The return value is unspecified.
+
+ - Syntax: define-access-operation GETTER-NAME
+ Shorthand for a Yasos `define-operation' defining an operation
+ GETTER-NAME that objects may support to return the value of some
+ mutable state. The default operation is to signal an error. The
+ return value is unspecified.
+
+
+File: slib.info, Node: Yasos examples, Prev: Setters, Up: Yasos
+
+Examples
+--------
+
+ ;;; These definitions for PRINT and SIZE are
+ ;;; already supplied by
+ (require 'yasos)
+
+ (define-operation (print obj port)
+ (format port
+ (if (instance? obj) "#<instance>" "~s")
+ obj))
+
+ (define-operation (size obj)
+ (cond
+ ((vector? obj) (vector-length obj))
+ ((list? obj) (length obj))
+ ((pair? obj) 2)
+ ((string? obj) (string-length obj))
+ ((char? obj) 1)
+ (else
+ (error "Operation not supported: size" obj))))
+
+ (define-predicate cell?)
+ (define-operation (fetch obj))
+ (define-operation (store! obj newValue))
+
+ (define (make-cell value)
+ (object
+ ((cell? self) #t)
+ ((fetch self) value)
+ ((store! self newValue)
+ (set! value newValue)
+ newValue)
+ ((size self) 1)
+ ((print self port)
+ (format port "#<Cell: ~s>" (fetch self)))))
+
+ (define-operation (discard obj value)
+ (format #t "Discarding ~s~%" value))
+
+ (define (make-filtered-cell value filter)
+ (object-with-ancestors
+ ((cell (make-cell value)))
+ ((store! self newValue)
+ (if (filter newValue)
+ (store! cell newValue)
+ (discard self newValue)))))
+
+ (define-predicate array?)
+ (define-operation (array-ref array index))
+ (define-operation (array-set! array index value))
+
+ (define (make-array num-slots)
+ (let ((anArray (make-vector num-slots)))
+ (object
+ ((array? self) #t)
+ ((size self) num-slots)
+ ((array-ref self index)
+ (vector-ref anArray index))
+ ((array-set! self index newValue)
+ (vector-set! anArray index newValue))
+ ((print self port)
+ (format port "#<Array ~s>" (size self))))))
+
+ (define-operation (position obj))
+ (define-operation (discarded-value obj))
+
+ (define (make-cell-with-history value filter size)
+ (let ((pos 0) (most-recent-discard #f))
+ (object-with-ancestors
+ ((cell (make-filtered-call value filter))
+ (sequence (make-array size)))
+ ((array? self) #f)
+ ((position self) pos)
+ ((store! self newValue)
+ (operate-as cell store! self newValue)
+ (array-set! self pos newValue)
+ (set! pos (+ pos 1)))
+ ((discard self value)
+ (set! most-recent-discard value))
+ ((discarded-value self) most-recent-discard)
+ ((print self port)
+ (format port "#<Cell-with-history ~s>"
+ (fetch self))))))
+
+ (define-access-operation fetch)
+ (add-setter fetch store!)
+ (define foo (make-cell 1))
+ (print foo #f)
+ => "#<Cell: 1>"
+ (set (fetch foo) 2)
+ =>
+ (print foo #f)
+ => "#<Cell: 2>"
+ (fetch foo)
+ => 2
+
+
+File: slib.info, Node: Textual Conversion Packages, Next: Mathematical Packages, Prev: Scheme Syntax Extension Packages, Up: Top
+
+Textual Conversion Packages
+***************************
+
+* Menu:
+
+* Precedence Parsing::
+* Format:: Common-Lisp Format
+* Standard Formatted I/O:: Posix printf and scanf
+* Programs and Arguments::
+* HTML HTTP and CGI:: Generate pages and serve WWW sites
+* Printing Scheme:: Nicely
+* Time and Date::
+* Vector Graphics::
+* Schmooz:: Documentation markup for Scheme programs
+
+
+File: slib.info, Node: Precedence Parsing, Next: Format, Prev: Textual Conversion Packages, Up: Textual Conversion Packages
+
+Precedence Parsing
+==================
+
+ `(require 'precedence-parse)' or `(require 'parse)'
+
+This package implements:
+
+ * a Pratt style precedence parser;
+
+ * a "tokenizer" which congeals tokens according to assigned classes
+ of constituent characters;
+
+ * procedures giving direct control of parser rulesets;
+
+ * procedures for higher level specification of rulesets.
+
+* Menu:
+
+* Precedence Parsing Overview::
+* Ruleset Definition and Use::
+* Token definition::
+* Nud and Led Definition::
+* Grammar Rule Definition::
+
+
+File: slib.info, Node: Precedence Parsing Overview, Next: Ruleset Definition and Use, Prev: Precedence Parsing, Up: Precedence Parsing
+
+Precedence Parsing Overview
+---------------------------
+
+This package offers improvements over previous parsers.
+
+ * Common computer language constructs are concisely specified.
+
+ * Grammars can be changed dynamically. Operators can be assigned
+ different meanings within a lexical context.
+
+ * Rulesets don't need compilation. Grammars can be changed
+ incrementally.
+
+ * Operator precedence is specified by integers.
+
+ * All possibilities of bad input are handled (1) and return as much
+ structure as was parsed when the error occured; The symbol `?' is
+ substituted for missing input.
+
+Here are the higher-level syntax types and an example of each.
+Precedence considerations are omitted for clarity. See *Note Grammar
+Rule Definition:: for full details.
+
+ - Grammar: nofix bye exit
+ bye
+ calls the function `exit' with no arguments.
+
+ - Grammar: prefix - negate
+ - 42
+ Calls the function `negate' with the argument `42'.
+
+ - Grammar: infix - difference
+ x - y
+ Calls the function `difference' with arguments `x' and `y'.
+
+ - Grammar: nary + sum
+ x + y + z
+ Calls the function `sum' with arguments `x', `y', and `y'.
+
+ - Grammar: postfix ! factorial
+ 5 !
+ Calls the function `factorial' with the argument `5'.
+
+ - Grammar: prestfix set set!
+ set foo bar
+ Calls the function `set!' with the arguments `foo' and `bar'.
+
+ - Grammar: commentfix /* */
+ /* almost any text here */
+ Ignores the comment delimited by `/*' and `*/'.
+
+ - Grammar: matchfix { list }
+ {0, 1, 2}
+ Calls the function `list' with the arguments `0', `1', and `2'.
+
+ - Grammar: inmatchfix ( funcall )
+ f(x, y)
+ Calls the function `funcall' with the arguments `f', `x', and `y'.
+
+ - Grammar: delim ;
+ set foo bar;
+ delimits the extent of the restfix operator `set'.
+
+ ---------- Footnotes ----------
+
+ (1) How do I know this? I parsed 250kbyte of random input (an e-mail
+file) with a non-trivial grammar utilizing all constructs.
+
+
+File: slib.info, Node: Ruleset Definition and Use, Next: Token definition, Prev: Precedence Parsing Overview, Up: Precedence Parsing
+
+Ruleset Definition and Use
+--------------------------
+
+ - Variable: *syn-defs*
+ A grammar is built by one or more calls to `prec:define-grammar'.
+ The rules are appended to *SYN-DEFS*. The value of *SYN-DEFS* is
+ the grammar suitable for passing as an argument to `prec:parse'.
+
+ - Constant: *syn-ignore-whitespace*
+ Is a nearly empty grammar with whitespace characters set to group
+ 0, which means they will not be made into tokens. Most rulesets
+ will want to start with `*syn-ignore-whitespace*'
+
+In order to start defining a grammar, either
+
+ (set! *syn-defs* '())
+
+or
+
+ (set! *syn-defs* *syn-ignore-whitespace*)
+
+ - Function: prec:define-grammar RULE1 ...
+ Appends RULE1 ... to *SYN-DEFS*. `prec:define-grammar' is used to
+ define both the character classes and rules for tokens.
+
+Once your grammar is defined, save the value of `*syn-defs*' in a
+variable (for use when calling `prec:parse').
+
+ (define my-ruleset *syn-defs*)
+
+ - Function: prec:parse RULESET DELIM
+ - Function: prec:parse RULESET DELIM PORT
+ The RULESET argument must be a list of rules as constructed by
+ `prec:define-grammar' and extracted from *SYN-DEFS*.
+
+ The token DELIM may be a character, symbol, or string. A
+ character DELIM argument will match only a character token; i.e. a
+ character for which no token-group is assigned. A symbols or
+ string will match only a token string; i.e. a token resulting from
+ a token group.
+
+ `prec:parse' reads a RULESET grammar expression delimited by DELIM
+ from the given input PORT. `prec:parse' returns the next object
+ parsable from the given input PORT, updating PORT to point to the
+ first character past the end of the external representation of the
+ object.
+
+ If an end of file is encountered in the input before any
+ characters are found that can begin an object, then an end of file
+ object is returned. If a delimiter (such as DELIM) is found
+ before any characters are found that can begin an object, then
+ `#f' is returned.
+
+ The PORT argument may be omitted, in which case it defaults to the
+ value returned by `current-input-port'. It is an error to parse
+ from a closed port.
+
+
+File: slib.info, Node: Token definition, Next: Nud and Led Definition, Prev: Ruleset Definition and Use, Up: Precedence Parsing
+
+Token definition
+----------------
+
+ - Function: tok:char-group GROUP CHARS CHARS-PROC
+ The argument CHARS may be a single character, a list of
+ characters, or a string. Each character in CHARS is treated as
+ though `tok:char-group' was called with that character alone.
+
+ The argument CHARS-PROC must be a procedure of one argument, a
+ list of characters. After `tokenize' has finished accumulating
+ the characters for a token, it calls CHARS-PROC with the list of
+ characters. The value returned is the token which `tokenize'
+ returns.
+
+ The argument GROUP may be an exact integer or a procedure of one
+ character argument. The following discussion concerns the
+ treatment which the tokenizing routine, `tokenize', will accord to
+ characters on the basis of their groups.
+
+ When GROUP is a non-zero integer, characters whose group number is
+ equal to or exactly one less than GROUP will continue to
+ accumulate. Any other character causes the accumulation to stop
+ (until a new token is to be read).
+
+ The GROUP of zero is special. These characters are ignored when
+ parsed pending a token, and stop the accumulation of token
+ characters when the accumulation has already begun. Whitespace
+ characters are usually put in group 0.
+
+ If GROUP is a procedure, then, when triggerd by the occurence of
+ an initial (no accumulation) CHARS character, this procedure will
+ be repeatedly called with each successive character from the input
+ stream until the GROUP procedure returns a non-false value.
+
+The following convenient constants are provided for use with
+`tok:char-group'.
+
+ - Constant: tok:decimal-digits
+ Is the string `"0123456789"'.
+
+ - Constant: tok:upper-case
+ Is the string consisting of all upper-case letters
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZ").
+
+ - Constant: tok:lower-case
+ Is the string consisting of all lower-case letters
+ ("abcdefghijklmnopqrstuvwxyz").
+
+ - Constant: tok:whitespaces
+ Is the string consisting of all characters between 0 and 255 for
+ which `char-whitespace?' returns true.
+
+
+File: slib.info, Node: Nud and Led Definition, Next: Grammar Rule Definition, Prev: Token definition, Up: Precedence Parsing
+
+Nud and Led Definition
+----------------------
+
+ This section describes advanced features. You can skip this section
+on first reading.
+
+The "Null Denotation" (or "nud") of a token is the procedure and
+arguments applying for that token when "Left", an unclaimed parsed
+expression is not extant.
+
+The "Left Denotation" (or "led") of a token is the procedure,
+arguments, and lbp applying for that token when there is a "Left", an
+unclaimed parsed expression.
+
+In his paper,
+
+ Pratt, V. R. Top Down Operator Precendence. `SIGACT/SIGPLAN
+ Symposium on Principles of Programming Languages', Boston, 1973,
+ pages 41-51
+
+ the "left binding power" (or "lbp") was an independent property of
+tokens. I think this was done in order to allow tokens with NUDs but
+not LEDs to also be used as delimiters, which was a problem for
+statically defined syntaxes. It turns out that *dynamically binding*
+NUDs and LEDs allows them independence.
+
+For the rule-defining procedures that follow, the variable TK may be a
+character, string, or symbol, or a list composed of characters,
+strings, and symbols. Each element of TK is treated as though the
+procedure were called for each element.
+
+Character TK arguments will match only character tokens; i.e.
+characters for which no token-group is assigned. Symbols and strings
+will both match token strings; i.e. tokens resulting from token groups.
+
+ - Function: prec:make-nud TK SOP ARG1 ...
+ Returns a rule specifying that SOP be called when TK is parsed.
+ If SOP is a procedure, it is called with TK and ARG1 ... as its
+ arguments; the resulting value is incorporated into the expression
+ being built. Otherwise, `(list SOP ARG1 ...)' is incorporated.
+
+If no NUD has been defined for a token; then if that token is a string,
+it is converted to a symbol and returned; if not a string, the token is
+returned.
+
+ - Function: prec:make-led TK SOP ARG1 ...
+ Returns a rule specifying that SOP be called when TK is parsed and
+ LEFT has an unclaimed parsed expression. If SOP is a procedure,
+ it is called with LEFT, TK, and ARG1 ... as its arguments; the
+ resulting value is incorporated into the expression being built.
+ Otherwise, LEFT is incorporated.
+
+If no LED has been defined for a token, and LEFT is set, the parser
+issues a warning.
+
+
+File: slib.info, Node: Grammar Rule Definition, Prev: Nud and Led Definition, Up: Precedence Parsing
+
+Grammar Rule Definition
+-----------------------
+
+Here are procedures for defining rules for the syntax types introduced
+in *Note Precedence Parsing Overview::.
+
+For the rule-defining procedures that follow, the variable TK may be a
+character, string, or symbol, or a list composed of characters,
+strings, and symbols. Each element of TK is treated as though the
+procedure were called for each element.
+
+For procedures prec:delim, ..., prec:prestfix, if the SOP argument is
+`#f', then the token which triggered this rule is converted to a symbol
+and returned. A false SOP argument to the procedures prec:commentfix,
+prec:matchfix, or prec:inmatchfix has a different meaning.
+
+Character TK arguments will match only character tokens; i.e.
+characters for which no token-group is assigned. Symbols and strings
+will both match token strings; i.e. tokens resulting from token groups.
+
+ - Function: prec:delim TK
+ Returns a rule specifying that TK should not be returned from
+ parsing; i.e. TK's function is purely syntactic. The end-of-file
+ is always treated as a delimiter.
+
+ - Function: prec:nofix TK SOP
+ Returns a rule specifying the following actions take place when TK
+ is parsed:
+ * If SOP is a procedure, it is called with no arguments; the
+ resulting value is incorporated into the expression being
+ built. Otherwise, the list of SOP is incorporated.
+
+ - Function: prec:prefix TK SOP BP RULE1 ...
+ Returns a rule specifying the following actions take place when TK
+ is parsed:
+ * The rules RULE1 ... augment and, in case of conflict, override
+ rules currently in effect.
+
+ * `prec:parse1' is called with binding-power BP.
+
+ * If SOP is a procedure, it is called with the expression
+ returned from `prec:parse1'; the resulting value is
+ incorporated into the expression being built. Otherwise, the
+ list of SOP and the expression returned from `prec:parse1' is
+ incorporated.
+
+ * The ruleset in effect before TK was parsed is restored; RULE1
+ ... are forgotten.
+
+ - Function: prec:infix TK SOP LBP BP RULE1 ...
+ Returns a rule declaring the left-binding-precedence of the token
+ TK is LBP and specifying the following actions take place when TK
+ is parsed:
+ * The rules RULE1 ... augment and, in case of conflict, override
+ rules currently in effect.
+
+ * One expression is parsed with binding-power LBP. If instead a
+ delimiter is encountered, a warning is issued.
+
+ * If SOP is a procedure, it is applied to the list of LEFT and
+ the parsed expression; the resulting value is incorporated
+ into the expression being built. Otherwise, the list of SOP,
+ the LEFT expression, and the parsed expression is
+ incorporated.
+
+ * The ruleset in effect before TK was parsed is restored; RULE1
+ ... are forgotten.
+
+ - Function: prec:nary TK SOP BP
+ Returns a rule declaring the left-binding-precedence of the token
+ TK is BP and specifying the following actions take place when TK
+ is parsed:
+ * Expressions are parsed with binding-power BP as far as they
+ are interleaved with the token TK.
+
+ * If SOP is a procedure, it is applied to the list of LEFT and
+ the parsed expressions; the resulting value is incorporated
+ into the expression being built. Otherwise, the list of SOP,
+ the LEFT expression, and the parsed expressions is
+ incorporated.
+
+ - Function: prec:postfix TK SOP LBP
+ Returns a rule declaring the left-binding-precedence of the token
+ TK is LBP and specifying the following actions take place when TK
+ is parsed:
+ * If SOP is a procedure, it is called with the LEFT expression;
+ the resulting value is incorporated into the expression being
+ built. Otherwise, the list of SOP and the LEFT expression is
+ incorporated.
+
+ - Function: prec:prestfix TK SOP BP RULE1 ...
+ Returns a rule specifying the following actions take place when TK
+ is parsed:
+ * The rules RULE1 ... augment and, in case of conflict, override
+ rules currently in effect.
+
+ * Expressions are parsed with binding-power BP until a
+ delimiter is reached.
+
+ * If SOP is a procedure, it is applied to the list of parsed
+ expressions; the resulting value is incorporated into the
+ expression being built. Otherwise, the list of SOP and the
+ parsed expressions is incorporated.
+
+ * The ruleset in effect before TK was parsed is restored; RULE1
+ ... are forgotten.
+
+ - Function: prec:commentfix TK STP MATCH RULE1 ...
+ Returns rules specifying the following actions take place when TK
+ is parsed:
+ * The rules RULE1 ... augment and, in case of conflict, override
+ rules currently in effect.
+
+ * Characters are read until and end-of-file or a sequence of
+ characters is read which matches the *string* MATCH.
+
+ * If STP is a procedure, it is called with the string of all
+ that was read between the TK and MATCH (exclusive).
+
+ * The ruleset in effect before TK was parsed is restored; RULE1
+ ... are forgotten.
+
+ Parsing of commentfix syntax differs from the others in several
+ ways. It reads directly from input without tokenizing; It calls
+ STP but does not return its value; nay any value. I added the STP
+ argument so that comment text could be echoed.
+
+ - Function: prec:matchfix TK SOP SEP MATCH RULE1 ...
+ Returns a rule specifying the following actions take place when TK
+ is parsed:
+ * The rules RULE1 ... augment and, in case of conflict, override
+ rules currently in effect.
+
+ * A rule declaring the token MATCH a delimiter takes effect.
+
+ * Expressions are parsed with binding-power `0' until the token
+ MATCH is reached. If the token SEP does not appear between
+ each pair of expressions parsed, a warning is issued.
+
+ * If SOP is a procedure, it is applied to the list of parsed
+ expressions; the resulting value is incorporated into the
+ expression being built. Otherwise, the list of SOP and the
+ parsed expressions is incorporated.
+
+ * The ruleset in effect before TK was parsed is restored; RULE1
+ ... are forgotten.
+
+ - Function: prec:inmatchfix TK SOP SEP MATCH LBP RULE1 ...
+ Returns a rule declaring the left-binding-precedence of the token
+ TK is LBP and specifying the following actions take place when TK
+ is parsed:
+ * The rules RULE1 ... augment and, in case of conflict, override
+ rules currently in effect.
+
+ * A rule declaring the token MATCH a delimiter takes effect.
+
+ * Expressions are parsed with binding-power `0' until the token
+ MATCH is reached. If the token SEP does not appear between
+ each pair of expressions parsed, a warning is issued.
+
+ * If SOP is a procedure, it is applied to the list of LEFT and
+ the parsed expressions; the resulting value is incorporated
+ into the expression being built. Otherwise, the list of SOP,
+ the LEFT expression, and the parsed expressions is
+ incorporated.
+
+ * The ruleset in effect before TK was parsed is restored; RULE1
+ ... are forgotten.
+
+
+File: slib.info, Node: Format, Next: Standard Formatted I/O, Prev: Precedence Parsing, Up: Textual Conversion Packages
+
+Format (version 3.0)
+====================
+
+ `(require 'format)'
+
+* Menu:
+
+* Format Interface::
+* Format Specification::
+
+
+File: slib.info, Node: Format Interface, Next: Format Specification, Prev: Format, Up: Format
+
+Format Interface
+----------------
+
+ - Function: format DESTINATION FORMAT-STRING . ARGUMENTS
+ An almost complete implementation of Common LISP format description
+ according to the CL reference book `Common LISP' from Guy L.
+ Steele, Digital Press. Backward compatible to most of the
+ available Scheme format implementations.
+
+ Returns `#t', `#f' or a string; has side effect of printing
+ according to FORMAT-STRING. If DESTINATION is `#t', the output is
+ to the current output port and `#t' is returned. If DESTINATION
+ is `#f', a formatted string is returned as the result of the call.
+ NEW: If DESTINATION is a string, DESTINATION is regarded as the
+ format string; FORMAT-STRING is then the first argument and the
+ output is returned as a string. If DESTINATION is a number, the
+ output is to the current error port if available by the
+ implementation. Otherwise DESTINATION must be an output port and
+ `#t' is returned.
+
+ FORMAT-STRING must be a string. In case of a formatting error
+ format returns `#f' and prints a message on the current output or
+ error port. Characters are output as if the string were output by
+ the `display' function with the exception of those prefixed by a
+ tilde (~). For a detailed description of the FORMAT-STRING syntax
+ please consult a Common LISP format reference manual. For a test
+ suite to verify this format implementation load `formatst.scm'.
+ Please send bug reports to `lutzeb@cs.tu-berlin.de'.
+
+ Note: `format' is not reentrant, i.e. only one `format'-call may
+ be executed at a time.
+
+
+
+File: slib.info, Node: Format Specification, Prev: Format Interface, Up: Format
+
+Format Specification (Format version 3.0)
+-----------------------------------------
+
+ Please consult a Common LISP format reference manual for a detailed
+description of the format string syntax. For a demonstration of the
+implemented directives see `formatst.scm'.
+
+ This implementation supports directive parameters and modifiers (`:'
+and `@' characters). Multiple parameters must be separated by a comma
+(`,'). Parameters can be numerical parameters (positive or negative),
+character parameters (prefixed by a quote character (`''), variable
+parameters (`v'), number of rest arguments parameter (`#'), empty and
+default parameters. Directive characters are case independent. The
+general form of a directive is:
+
+DIRECTIVE ::= ~{DIRECTIVE-PARAMETER,}[:][@]DIRECTIVE-CHARACTER
+
+DIRECTIVE-PARAMETER ::= [ [-|+]{0-9}+ | 'CHARACTER | v | # ]
+
+Implemented CL Format Control Directives
+........................................
+
+ Documentation syntax: Uppercase characters represent the corresponding
+control directive characters. Lowercase characters represent control
+directive parameter descriptions.
+
+`~A'
+ Any (print as `display' does).
+ `~@A'
+ left pad.
+
+ `~MINCOL,COLINC,MINPAD,PADCHARA'
+ full padding.
+
+`~S'
+ S-expression (print as `write' does).
+ `~@S'
+ left pad.
+
+ `~MINCOL,COLINC,MINPAD,PADCHARS'
+ full padding.
+
+`~D'
+ Decimal.
+ `~@D'
+ print number sign always.
+
+ `~:D'
+ print comma separated.
+
+ `~MINCOL,PADCHAR,COMMACHARD'
+ padding.
+
+`~X'
+ Hexadecimal.
+ `~@X'
+ print number sign always.
+
+ `~:X'
+ print comma separated.
+
+ `~MINCOL,PADCHAR,COMMACHARX'
+ padding.
+
+`~O'
+ Octal.
+ `~@O'
+ print number sign always.
+
+ `~:O'
+ print comma separated.
+
+ `~MINCOL,PADCHAR,COMMACHARO'
+ padding.
+
+`~B'
+ Binary.
+ `~@B'
+ print number sign always.
+
+ `~:B'
+ print comma separated.
+
+ `~MINCOL,PADCHAR,COMMACHARB'
+ padding.
+
+`~NR'
+ Radix N.
+ `~N,MINCOL,PADCHAR,COMMACHARR'
+ padding.
+
+`~@R'
+ print a number as a Roman numeral.
+
+`~:@R'
+ print a number as an "old fashioned" Roman numeral.
+
+`~:R'
+ print a number as an ordinal English number.
+
+`~:@R'
+ print a number as a cardinal English number.
+
+`~P'
+ Plural.
+ `~@P'
+ prints `y' and `ies'.
+
+ `~:P'
+ as `~P but jumps 1 argument backward.'
+
+ `~:@P'
+ as `~@P but jumps 1 argument backward.'
+
+`~C'
+ Character.
+ `~@C'
+ prints a character as the reader can understand it (i.e. `#\'
+ prefixing).
+
+ `~:C'
+ prints a character as emacs does (eg. `^C' for ASCII 03).
+
+`~F'
+ Fixed-format floating-point (prints a flonum like MMM.NNN).
+ `~WIDTH,DIGITS,SCALE,OVERFLOWCHAR,PADCHARF'
+
+ `~@F'
+ If the number is positive a plus sign is printed.
+
+`~E'
+ Exponential floating-point (prints a flonum like MMM.NNN`E'EE).
+ `~WIDTH,DIGITS,EXPONENTDIGITS,SCALE,OVERFLOWCHAR,PADCHAR,EXPONENTCHARE'
+
+ `~@E'
+ If the number is positive a plus sign is printed.
+
+`~G'
+ General floating-point (prints a flonum either fixed or
+ exponential).
+ `~WIDTH,DIGITS,EXPONENTDIGITS,SCALE,OVERFLOWCHAR,PADCHAR,EXPONENTCHARG'
+
+ `~@G'
+ If the number is positive a plus sign is printed.
+
+`~$'
+ Dollars floating-point (prints a flonum in fixed with signs
+ separated).
+ `~DIGITS,SCALE,WIDTH,PADCHAR$'
+
+ `~@$'
+ If the number is positive a plus sign is printed.
+
+ `~:@$'
+ A sign is always printed and appears before the padding.
+
+ `~:$'
+ The sign appears before the padding.
+
+`~%'
+ Newline.
+ `~N%'
+ print N newlines.
+
+`~&'
+ print newline if not at the beginning of the output line.
+ `~N&'
+ prints `~&' and then N-1 newlines.
+
+`~|'
+ Page Separator.
+ `~N|'
+ print N page separators.
+
+`~~'
+ Tilde.
+ `~N~'
+ print N tildes.
+
+`~'<newline>
+ Continuation Line.
+ `~:'<newline>
+ newline is ignored, white space left.
+
+ `~@'<newline>
+ newline is left, white space ignored.
+
+`~T'
+ Tabulation.
+ `~@T'
+ relative tabulation.
+
+ `~COLNUM,COLINCT'
+ full tabulation.
+
+`~?'
+ Indirection (expects indirect arguments as a list).
+ `~@?'
+ extracts indirect arguments from format arguments.
+
+`~(STR~)'
+ Case conversion (converts by `string-downcase').
+ `~:(STR~)'
+ converts by `string-capitalize'.
+
+ `~@(STR~)'
+ converts by `string-capitalize-first'.
+
+ `~:@(STR~)'
+ converts by `string-upcase'.
+
+`~*'
+ Argument Jumping (jumps 1 argument forward).
+ `~N*'
+ jumps N arguments forward.
+
+ `~:*'
+ jumps 1 argument backward.
+
+ `~N:*'
+ jumps N arguments backward.
+
+ `~@*'
+ jumps to the 0th argument.
+
+ `~N@*'
+ jumps to the Nth argument (beginning from 0)
+
+`~[STR0~;STR1~;...~;STRN~]'
+ Conditional Expression (numerical clause conditional).
+ `~N['
+ take argument from N.
+
+ `~@['
+ true test conditional.
+
+ `~:['
+ if-else-then conditional.
+
+ `~;'
+ clause separator.
+
+ `~:;'
+ default clause follows.
+
+`~{STR~}'
+ Iteration (args come from the next argument (a list)).
+ `~N{'
+ at most N iterations.
+
+ `~:{'
+ args from next arg (a list of lists).
+
+ `~@{'
+ args from the rest of arguments.
+
+ `~:@{'
+ args from the rest args (lists).
+
+`~^'
+ Up and out.
+ `~N^'
+ aborts if N = 0
+
+ `~N,M^'
+ aborts if N = M
+
+ `~N,M,K^'
+ aborts if N <= M <= K
+
+Not Implemented CL Format Control Directives
+............................................
+
+`~:A'
+ print `#f' as an empty list (see below).
+
+`~:S'
+ print `#f' as an empty list (see below).
+
+`~<~>'
+ Justification.
+
+`~:^'
+ (sorry I don't understand its semantics completely)
+
+Extended, Replaced and Additional Control Directives
+....................................................
+
+`~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHD'
+
+`~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHX'
+
+`~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHO'
+
+`~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHB'
+
+`~N,MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHR'
+ COMMAWIDTH is the number of characters between two comma
+ characters.
+
+`~I'
+ print a R4RS complex number as `~F~@Fi' with passed parameters for
+ `~F'.
+
+`~Y'
+ Pretty print formatting of an argument for scheme code lists.
+
+`~K'
+ Same as `~?.'
+
+`~!'
+ Flushes the output if format DESTINATION is a port.
+
+`~_'
+ Print a `#\space' character
+ `~N_'
+ print N `#\space' characters.
+
+`~/'
+ Print a `#\tab' character
+ `~N/'
+ print N `#\tab' characters.
+
+`~NC'
+ Takes N as an integer representation for a character. No arguments
+ are consumed. N is converted to a character by `integer->char'. N
+ must be a positive decimal number.
+
+`~:S'
+ Print out readproof. Prints out internal objects represented as
+ `#<...>' as strings `"#<...>"' so that the format output can always
+ be processed by `read'.
+
+`~:A'
+ Print out readproof. Prints out internal objects represented as
+ `#<...>' as strings `"#<...>"' so that the format output can always
+ be processed by `read'.
+
+`~Q'
+ Prints information and a copyright notice on the format
+ implementation.
+ `~:Q'
+ prints format version.
+
+`~F, ~E, ~G, ~$'
+ may also print number strings, i.e. passing a number as a string
+ and format it accordingly.
+
+Configuration Variables
+.......................
+
+ Format has some configuration variables at the beginning of
+`format.scm' to suit the systems and users needs. There should be no
+modification necessary for the configuration that comes with SLIB. If
+modification is desired the variable should be set after the format
+code is loaded. Format detects automatically if the running scheme
+system implements floating point numbers and complex numbers.
+
+FORMAT:SYMBOL-CASE-CONV
+ Symbols are converted by `symbol->string' so the case type of the
+ printed symbols is implementation dependent.
+ `format:symbol-case-conv' is a one arg closure which is either
+ `#f' (no conversion), `string-upcase', `string-downcase' or
+ `string-capitalize'. (default `#f')
+
+FORMAT:IOBJ-CASE-CONV
+ As FORMAT:SYMBOL-CASE-CONV but applies for the representation of
+ implementation internal objects. (default `#f')
+
+FORMAT:EXPCH
+ The character prefixing the exponent value in `~E' printing.
+ (default `#\E')
+
+Compatibility With Other Format Implementations
+...............................................
+
+SLIB format 2.x:
+ See `format.doc'.
+
+SLIB format 1.4:
+ Downward compatible except for padding support and `~A', `~S',
+ `~P', `~X' uppercase printing. SLIB format 1.4 uses C-style
+ `printf' padding support which is completely replaced by the CL
+ `format' padding style.
+
+MIT C-Scheme 7.1:
+ Downward compatible except for `~', which is not documented
+ (ignores all characters inside the format string up to a newline
+ character). (7.1 implements `~a', `~s', ~NEWLINE, `~~', `~%',
+ numerical and variable parameters and `:/@' modifiers in the CL
+ sense).
+
+Elk 1.5/2.0:
+ Downward compatible except for `~A' and `~S' which print in
+ uppercase. (Elk implements `~a', `~s', `~~', and `~%' (no
+ directive parameters or modifiers)).
+
+Scheme->C 01nov91:
+ Downward compatible except for an optional destination parameter:
+ S2C accepts a format call without a destination which returns a
+ formatted string. This is equivalent to a #f destination in S2C.
+ (S2C implements `~a', `~s', `~c', `~%', and `~~' (no directive
+ parameters or modifiers)).
+
+ This implementation of format is solely useful in the SLIB context
+because it requires other components provided by SLIB.
+
+
+File: slib.info, Node: Standard Formatted I/O, Next: Programs and Arguments, Prev: Format, Up: Textual Conversion Packages
+
+Standard Formatted I/O
+======================
+
+* Menu:
+
+* Standard Formatted Output:: 'printf
+* Standard Formatted Input:: 'scanf
+
+stdio
+-----
+
+ `(require 'stdio)'
+
+ `require's `printf' and `scanf' and additionally defines the symbols:
+
+ - Variable: stdin
+ Defined to be `(current-input-port)'.
+
+ - Variable: stdout
+ Defined to be `(current-output-port)'.
+
+ - Variable: stderr
+ Defined to be `(current-error-port)'.
+
+
+File: slib.info, Node: Standard Formatted Output, Next: Standard Formatted Input, Prev: Standard Formatted I/O, Up: Standard Formatted I/O
+
+Standard Formatted Output
+-------------------------
+
+ `(require 'printf)'
+
+ - Procedure: printf FORMAT ARG1 ...
+ - Procedure: fprintf PORT FORMAT ARG1 ...
+ - Procedure: sprintf STR FORMAT ARG1 ...
+ - Procedure: sprintf #F FORMAT ARG1 ...
+ - Procedure: sprintf K FORMAT ARG1 ...
+ Each function converts, formats, and outputs its ARG1 ...
+ arguments according to the control string FORMAT argument and
+ returns the number of characters output.
+
+ `printf' sends its output to the port `(current-output-port)'.
+ `fprintf' sends its output to the port PORT. `sprintf'
+ `string-set!'s locations of the non-constant string argument STR
+ to the output characters.
+
+ Two extensions of `sprintf' return new strings. If the first
+ argument is `#f', then the returned string's length is as many
+ characters as specified by the FORMAT and data; if the first
+ argument is a non-negative integer K, then the length of the
+ returned string is also bounded by K.
+
+ The string FORMAT contains plain characters which are copied to
+ the output stream, and conversion specifications, each of which
+ results in fetching zero or more of the arguments ARG1 .... The
+ results are undefined if there are an insufficient number of
+ arguments for the format. If FORMAT is exhausted while some of the
+ ARG1 ... arguments remain unused, the excess ARG1 ... arguments
+ are ignored.
+
+ The conversion specifications in a format string have the form:
+
+ % [ FLAGS ] [ WIDTH ] [ . PRECISION ] [ TYPE ] CONVERSION
+
+ An output conversion specifications consist of an initial `%'
+ character followed in sequence by:
+
+ * Zero or more "flag characters" that modify the normal
+ behavior of the conversion specification.
+
+ `-'
+ Left-justify the result in the field. Normally the
+ result is right-justified.
+
+ `+'
+ For the signed `%d' and `%i' conversions and all inexact
+ conversions, prefix a plus sign if the value is positive.
+
+ ` '
+ For the signed `%d' and `%i' conversions, if the result
+ doesn't start with a plus or minus sign, prefix it with
+ a space character instead. Since the `+' flag ensures
+ that the result includes a sign, this flag is ignored if
+ both are specified.
+
+ `#'
+ For inexact conversions, `#' specifies that the result
+ should always include a decimal point, even if no digits
+ follow it. For the `%g' and `%G' conversions, this also
+ forces trailing zeros after the decimal point to be
+ printed where they would otherwise be elided.
+
+ For the `%o' conversion, force the leading digit to be
+ `0', as if by increasing the precision. For `%x' or
+ `%X', prefix a leading `0x' or `0X' (respectively) to
+ the result. This doesn't do anything useful for the
+ `%d', `%i', or `%u' conversions. Using this flag
+ produces output which can be parsed by the `scanf'
+ functions with the `%i' conversion (*note Standard
+ Formatted Input::.).
+
+ `0'
+ Pad the field with zeros instead of spaces. The zeros
+ are placed after any indication of sign or base. This
+ flag is ignored if the `-' flag is also specified, or if
+ a precision is specified for an exact converson.
+
+ * An optional decimal integer specifying the "minimum field
+ width". If the normal conversion produces fewer characters
+ than this, the field is padded (with spaces or zeros per the
+ `0' flag) to the specified width. This is a *minimum* width;
+ if the normal conversion produces more characters than this,
+ the field is *not* truncated.
+
+ Alternatively, if the field width is `*', the next argument
+ in the argument list (before the actual value to be printed)
+ is used as the field width. The width value must be an
+ integer. If the value is negative it is as though the `-'
+ flag is set (see above) and the absolute value is used as the
+ field width.
+
+ * An optional "precision" to specify the number of digits to be
+ written for numeric conversions and the maximum field width
+ for string conversions. The precision is specified by a
+ period (`.') followed optionally by a decimal integer (which
+ defaults to zero if omitted).
+
+ Alternatively, if the precision is `.*', the next argument in
+ the argument list (before the actual value to be printed) is
+ used as the precision. The value must be an integer, and is
+ ignored if negative. If you specify `*' for both the field
+ width and precision, the field width argument precedes the
+ precision argument. The `.*' precision is an enhancement. C
+ library versions may not accept this syntax.
+
+ For the `%f', `%e', and `%E' conversions, the precision
+ specifies how many digits follow the decimal-point character.
+ The default precision is `6'. If the precision is
+ explicitly `0', the decimal point character is suppressed.
+
+ For the `%g' and `%G' conversions, the precision specifies how
+ many significant digits to print. Significant digits are the
+ first digit before the decimal point, and all the digits
+ after it. If the precision is `0' or not specified for `%g'
+ or `%G', it is treated like a value of `1'. If the value
+ being printed cannot be expressed accurately in the specified
+ number of digits, the value is rounded to the nearest number
+ that fits.
+
+ For exact conversions, if a precision is supplied it
+ specifies the minimum number of digits to appear; leading
+ zeros are produced if necessary. If a precision is not
+ supplied, the number is printed with as many digits as
+ necessary. Converting an exact `0' with an explicit
+ precision of zero produces no characters.
+
+ * An optional one of `l', `h' or `L', which is ignored for
+ numeric conversions. It is an error to specify these
+ modifiers for non-numeric conversions.
+
+ * A character that specifies the conversion to be applied.
+
+Exact Conversions
+.................
+
+ `d', `i'
+ Print an integer as a signed decimal number. `%d' and `%i'
+ are synonymous for output, but are different when used with
+ `scanf' for input (*note Standard Formatted Input::.).
+
+ `o'
+ Print an integer as an unsigned octal number.
+
+ `u'
+ Print an integer as an unsigned decimal number.
+
+ `x', `X'
+ Print an integer as an unsigned hexadecimal number. `%x'
+ prints using the digits `0123456789abcdef'. `%X' prints
+ using the digits `0123456789ABCDEF'.
+
+Inexact Conversions
+...................
+
+ `f'
+ Print a floating-point number in fixed-point notation.
+
+ `e', `E'
+ Print a floating-point number in exponential notation. `%e'
+ prints `e' between mantissa and exponont. `%E' prints `E'
+ between mantissa and exponont.
+
+ `g', `G'
+ Print a floating-point number in either fixed or exponential |
+ notation, whichever is more appropriate for its magnitude.
+ Unless an `#' flag has been supplied trailing zeros after a
+ decimal point will be stripped off. `%g' prints `e' between
+ mantissa and exponont. `%G' prints `E' between mantissa and
+ exponent.
+
+Other Conversions
+.................
+
+ `c'
+ Print a single character. The `-' flag is the only one which
+ can be specified. It is an error to specify a precision.
+
+ `s'
+ Print a string. The `-' flag is the only one which can be
+ specified. A precision specifies the maximum number of
+ characters to output; otherwise all characters in the string
+ are output.
+
+ `a', `A'
+ Print a scheme expression. The `-' flag left-justifies the
+ output. The `#' flag specifies that strings and characters
+ should be quoted as by `write' (which can be read using
+ `read'); otherwise, output is as `display' prints. A
+ precision specifies the maximum number of characters to
+ output; otherwise as many characters as needed are output.
+
+ *Note:* `%a' and `%A' are SLIB extensions.
+
+ `%'
+ Print a literal `%' character. No argument is consumed. It
+ is an error to specifiy flags, field width, precision, or
+ type modifiers with `%%'.
+
+
+File: slib.info, Node: Standard Formatted Input, Prev: Standard Formatted Output, Up: Standard Formatted I/O
+
+Standard Formatted Input
+------------------------
+
+ `(require 'scanf)'
+
+ - Function: scanf-read-list FORMAT
+ - Function: scanf-read-list FORMAT PORT
+ - Function: scanf-read-list FORMAT STRING
+
+ - Macro: scanf FORMAT ARG1 ...
+ - Macro: fscanf PORT FORMAT ARG1 ...
+ - Macro: sscanf STR FORMAT ARG1 ...
+ Each function reads characters, interpreting them according to the
+ control string FORMAT argument.
+
+ `scanf-read-list' returns a list of the items specified as far as
+ the input matches FORMAT. `scanf', `fscanf', and `sscanf' return
+ the number of items successfully matched and stored. `scanf',
+ `fscanf', and `sscanf' also set the location corresponding to ARG1
+ ... using the methods:
+
+ symbol
+ `set!'
+
+ car expression
+ `set-car!'
+
+ cdr expression
+ `set-cdr!'
+
+ vector-ref expression
+ `vector-set!'
+
+ substring expression
+ `substring-move-left!'
+
+ The argument to a `substring' expression in ARG1 ... must be a
+ non-constant string. Characters will be stored starting at the
+ position specified by the second argument to `substring'. The
+ number of characters stored will be limited by either the position
+ specified by the third argument to `substring' or the length of the
+ matched string, whichever is less.
+
+ The control string, FORMAT, contains conversion specifications and
+ other characters used to direct interpretation of input sequences.
+ The control string contains:
+
+ * White-space characters (blanks, tabs, newlines, or formfeeds)
+ that cause input to be read (and discarded) up to the next
+ non-white-space character.
+
+ * An ordinary character (not `%') that must match the next
+ character of the input stream.
+
+ * Conversion specifications, consisting of the character `%', an
+ optional assignment suppressing character `*', an optional
+ numerical maximum-field width, an optional `l', `h' or `L'
+ which is ignored, and a conversion code.
+
+ Unless the specification contains the `n' conversion character
+ (described below), a conversion specification directs the
+ conversion of the next input field. The result of a conversion
+ specification is returned in the position of the corresponding
+ argument points, unless `*' indicates assignment suppression.
+ Assignment suppression provides a way to describe an input field
+ to be skipped. An input field is defined as a string of
+ characters; it extends to the next inappropriate character or
+ until the field width, if specified, is exhausted.
+
+ *Note:* This specification of format strings differs from the
+ `ANSI C' and `POSIX' specifications. In SLIB, white space
+ before an input field is not skipped unless white space
+ appears before the conversion specification in the format
+ string. In order to write format strings which work
+ identically with `ANSI C' and SLIB, prepend whitespace to all
+ conversion specifications except `[' and `c'.
+
+ The conversion code indicates the interpretation of the input
+ field; For a suppressed field, no value is returned. The
+ following conversion codes are legal:
+
+ `%'
+ A single % is expected in the input at this point; no value
+ is returned.
+
+ `d', `D'
+ A decimal integer is expected.
+
+ `u', `U'
+ An unsigned decimal integer is expected.
+
+ `o', `O'
+ An octal integer is expected.
+
+ `x', `X'
+ A hexadecimal integer is expected.
+
+ `i'
+ An integer is expected. Returns the value of the next input
+ item, interpreted according to C conventions; a leading `0'
+ implies octal, a leading `0x' implies hexadecimal; otherwise,
+ decimal is assumed.
+
+ `n'
+ Returns the total number of bytes (including white space)
+ read by `scanf'. No input is consumed by `%n'.
+
+ `f', `F', `e', `E', `g', `G'
+ A floating-point number is expected. The input format for
+ floating-point numbers is an optionally signed string of
+ digits, possibly containing a radix character `.', followed
+ by an optional exponent field consisting of an `E' or an `e',
+ followed by an optional `+', `-', or space, followed by an
+ integer.
+
+ `c', `C'
+ WIDTH characters are expected. The normal
+ skip-over-white-space is suppressed in this case; to read the
+ next non-space character, use `%1s'. If a field width is
+ given, a string is returned; up to the indicated number of
+ characters is read.
+
+ `s', `S'
+ A character string is expected The input field is terminated
+ by a white-space character. `scanf' cannot read a null
+ string.
+
+ `['
+ Indicates string data and the normal
+ skip-over-leading-white-space is suppressed. The left
+ bracket is followed by a set of characters, called the
+ scanset, and a right bracket; the input field is the maximal
+ sequence of input characters consisting entirely of
+ characters in the scanset. `^', when it appears as the first
+ character in the scanset, serves as a complement operator and
+ redefines the scanset as the set of all characters not
+ contained in the remainder of the scanset string.
+ Construction of the scanset follows certain conventions. A
+ range of characters may be represented by the construct
+ first-last, enabling `[0123456789]' to be expressed `[0-9]'.
+ Using this convention, first must be lexically less than or
+ equal to last; otherwise, the dash stands for itself. The
+ dash also stands for itself when it is the first or the last
+ character in the scanset. To include the right square
+ bracket as an element of the scanset, it must appear as the
+ first character (possibly preceded by a `^') of the scanset,
+ in which case it will not be interpreted syntactically as the
+ closing bracket. At least one character must match for this
+ conversion to succeed.
+
+ The `scanf' functions terminate their conversions at end-of-file,
+ at the end of the control string, or when an input character
+ conflicts with the control string. In the latter case, the
+ offending character is left unread in the input stream.
+
+
+File: slib.info, Node: Programs and Arguments, Next: HTML HTTP and CGI, Prev: Standard Formatted I/O, Up: Textual Conversion Packages
+
+Program and Arguments
+=====================
+
+* Menu:
+
+* Getopt:: Command Line option parsing
+* Command Line:: A command line reader for Scheme shells
+* Parameter lists:: 'parameters
+* Getopt Parameter lists:: 'getopt-parameters
+* Filenames:: 'glob or 'filename
+* Batch:: 'batch
+
+
+File: slib.info, Node: Getopt, Next: Command Line, Prev: Programs and Arguments, Up: Programs and Arguments
+
+Getopt
+------
+
+ `(require 'getopt)'
+
+ This routine implements Posix command line argument parsing. Notice
+that returning values through global variables means that `getopt' is
+*not* reentrant.
+
+ - Variable: *optind*
+ Is the index of the current element of the command line. It is
+ initially one. In order to parse a new command line or reparse an
+ old one, *OPTING* must be reset.
+
+ - Variable: *optarg*
+ Is set by getopt to the (string) option-argument of the current
+ option.
+
+ - Procedure: getopt ARGC ARGV OPTSTRING
+ Returns the next option letter in ARGV (starting from `(vector-ref
+ argv *optind*)') that matches a letter in OPTSTRING. ARGV is a
+ vector or list of strings, the 0th of which getopt usually
+ ignores. ARGC is the argument count, usually the length of ARGV.
+ OPTSTRING is a string of recognized option characters; if a
+ character is followed by a colon, the option takes an argument
+ which may be immediately following it in the string or in the next
+ element of ARGV.
+
+ *OPTIND* is the index of the next element of the ARGV vector to be
+ processed. It is initialized to 1 by `getopt.scm', and `getopt'
+ updates it when it finishes with each element of ARGV.
+
+ `getopt' returns the next option character from ARGV that matches
+ a character in OPTSTRING, if there is one that matches. If the
+ option takes an argument, `getopt' sets the variable *OPTARG* to
+ the option-argument as follows:
+
+ * If the option was the last character in the string pointed to
+ by an element of ARGV, then *OPTARG* contains the next
+ element of ARGV, and *OPTIND* is incremented by 2. If the
+ resulting value of *OPTIND* is greater than or equal to ARGC,
+ this indicates a missing option argument, and `getopt'
+ returns an error indication.
+
+ * Otherwise, *OPTARG* is set to the string following the option
+ character in that element of ARGV, and *OPTIND* is
+ incremented by 1.
+
+ If, when `getopt' is called, the string `(vector-ref argv
+ *optind*)' either does not begin with the character `#\-' or is
+ just `"-"', `getopt' returns `#f' without changing *OPTIND*. If
+ `(vector-ref argv *optind*)' is the string `"--"', `getopt'
+ returns `#f' after incrementing *OPTIND*.
+
+ If `getopt' encounters an option character that is not contained in
+ OPTSTRING, it returns the question-mark `#\?' character. If it
+ detects a missing option argument, it returns the colon character
+ `#\:' if the first character of OPTSTRING was a colon, or a
+ question-mark character otherwise. In either case, `getopt' sets
+ the variable GETOPT:OPT to the option character that caused the
+ error.
+
+ The special option `"--"' can be used to delimit the end of the
+ options; `#f' is returned, and `"--"' is skipped.
+
+ RETURN VALUE
+
+ `getopt' returns the next option character specified on the command
+ line. A colon `#\:' is returned if `getopt' detects a missing
+ argument and the first character of OPTSTRING was a colon `#\:'.
+
+ A question-mark `#\?' is returned if `getopt' encounters an option
+ character not in OPTSTRING or detects a missing argument and the
+ first character of OPTSTRING was not a colon `#\:'.
+
+ Otherwise, `getopt' returns `#f' when all command line options
+ have been parsed.
+
+ Example:
+ #! /usr/local/bin/scm
+ ;;;This code is SCM specific.
+ (define argv (program-arguments))
+ (require 'getopt)
+
+ (define opts ":a:b:cd")
+ (let loop ((opt (getopt (length argv) argv opts)))
+ (case opt
+ ((#\a) (print "option a: " *optarg*))
+ ((#\b) (print "option b: " *optarg*))
+ ((#\c) (print "option c"))
+ ((#\d) (print "option d"))
+ ((#\?) (print "error" getopt:opt))
+ ((#\:) (print "missing arg" getopt:opt))
+ ((#f) (if (< *optind* (length argv))
+ (print "argv[" *optind* "]="
+ (list-ref argv *optind*)))
+ (set! *optind* (+ *optind* 1))))
+ (if (< *optind* (length argv))
+ (loop (getopt (length argv) argv opts))))
+
+ (slib:exit)
+
+Getopt-
+-------
+
+ - Function: getopt- ARGC ARGV OPTSTRING
+ The procedure `getopt--' is an extended version of `getopt' which
+ parses "long option names" of the form `--hold-the-onions' and
+ `--verbosity-level=extreme'. `Getopt--' behaves as `getopt'
+ except for non-empty options beginning with `--'.
+
+ Options beginning with `--' are returned as strings rather than
+ characters. If a value is assigned (using `=') to a long option,
+ `*optarg*' is set to the value. The `=' and value are not
+ returned as part of the option string.
+
+ No information is passed to `getopt--' concerning which long
+ options should be accepted or whether such options can take
+ arguments. If a long option did not have an argument, `*optarg'
+ will be set to `#f'. The caller is responsible for detecting and
+ reporting errors.
+
+ (define opts ":-:b:")
+ (define argc 5)
+ (define argv '("foo" "-b9" "--f1" "--2=" "--g3=35234.342" "--"))
+ (define *optind* 1)
+ (define *optarg* #f)
+ (require 'qp)
+ (do ((i 5 (+ -1 i)))
+ ((zero? i))
+ (define opt (getopt-- argc argv opts))
+ (print *optind* opt *optarg*)))
+ -|
+ 2 #\b "9"
+ 3 "f1" #f
+ 4 "2" ""
+ 5 "g3" "35234.342"
+ 5 #f "35234.342"
+
+
+File: slib.info, Node: Command Line, Next: Parameter lists, Prev: Getopt, Up: Programs and Arguments
+
+Command Line
+------------
+
+ `(require 'read-command)'
+
+ - Function: read-command PORT
+ - Function: read-command
+ `read-command' converts a "command line" into a list of strings
+ suitable for parsing by `getopt'. The syntax of command lines
+ supported resembles that of popular "shell"s. `read-command'
+ updates PORT to point to the first character past the command
+ delimiter.
+
+ If an end of file is encountered in the input before any
+ characters are found that can begin an object or comment, then an
+ end of file object is returned.
+
+ The PORT argument may be omitted, in which case it defaults to the
+ value returned by `current-input-port'.
+
+ The fields into which the command line is split are delimited by
+ whitespace as defined by `char-whitespace?'. The end of a command
+ is delimited by end-of-file or unescaped semicolon (<;>) or
+ <newline>. Any character can be literally included in a field by
+ escaping it with a backslach (<\>).
+
+ The initial character and types of fields recognized are:
+ `\'
+ The next character has is taken literally and not interpreted
+ as a field delimiter. If <\> is the last character before a
+ <newline>, that <newline> is just ignored. Processing
+ continues from the characters after the <newline> as though
+ the backslash and <newline> were not there.
+
+ `"'
+ The characters up to the next unescaped <"> are taken
+ literally, according to [R4RS] rules for literal strings
+ (*note Strings: (r4rs)Strings.).
+
+ `(', `%''
+ One scheme expression is `read' starting with this character.
+ The `read' expression is evaluated, converted to a string
+ (using `display'), and replaces the expression in the returned
+ field.
+
+ `;'
+ Semicolon delimits a command. Using semicolons more than one
+ command can appear on a line. Escaped semicolons and
+ semicolons inside strings do not delimit commands.
+
+ The comment field differs from the previous fields in that it must
+ be the first character of a command or appear after whitespace in
+ order to be recognized. <#> can be part of fields if these
+ conditions are not met. For instance, `ab#c' is just the field
+ ab#c.
+
+ `#'
+ Introduces a comment. The comment continues to the end of
+ the line on which the semicolon appears. Comments are
+ treated as whitespace by `read-dommand-line' and backslashes
+ before <newline>s in comments are also ignored.
+
+ - Function: read-options-file FILENAME
+ `read-options-file' converts an "options file" into a list of
+ strings suitable for parsing by `getopt'. The syntax of options
+ files is the same as the syntax for command lines, except that
+ <newline>s do not terminate reading (only <;> or end of file).
+
+ If an end of file is encountered before any characters are found
+ that can begin an object or comment, then an end of file object is
+ returned.
+
+
+File: slib.info, Node: Parameter lists, Next: Getopt Parameter lists, Prev: Command Line, Up: Programs and Arguments
+
+Parameter lists
+---------------
+
+ `(require 'parameters)'
+
+Arguments to procedures in scheme are distinguished from each other by
+their position in the procedure call. This can be confusing when a
+procedure takes many arguments, many of which are not often used.
+
+A "parameter-list" is a way of passing named information to a
+procedure. Procedures are also defined to set unused parameters to
+default values, check parameters, and combine parameter lists.
+
+A PARAMETER has the form `(parameter-name value1 ...)'. This format
+allows for more than one value per parameter-name.
+
+A PARAMETER-LIST is a list of PARAMETERs, each with a different
+PARAMETER-NAME.
+
+ - Function: make-parameter-list PARAMETER-NAMES
+ Returns an empty parameter-list with slots for PARAMETER-NAMES.
+
+ - Function: parameter-list-ref PARAMETER-LIST PARAMETER-NAME
+ PARAMETER-NAME must name a valid slot of PARAMETER-LIST.
+ `parameter-list-ref' returns the value of parameter PARAMETER-NAME
+ of PARAMETER-LIST.
+
+ - Procedure: adjoin-parameters! PARAMETER-LIST PARAMETER1 ...
+ Returns PARAMETER-LIST with PARAMETER1 ... merged in.
+
+ - Procedure: parameter-list-expand EXPANDERS PARAMETER-LIST
+ EXPANDERS is a list of procedures whose order matches the order of
+ the PARAMETER-NAMEs in the call to `make-parameter-list' which
+ created PARAMETER-LIST. For each non-false element of EXPANDERS
+ that procedure is mapped over the corresponding parameter value
+ and the returned parameter lists are merged into PARAMETER-LIST.
+
+ This process is repeated until PARAMETER-LIST stops growing. The
+ value returned from `parameter-list-expand' is unspecified.
+
+ - Function: fill-empty-parameters DEFAULTERS PARAMETER-LIST
+ DEFAULTERS is a list of procedures whose order matches the order
+ of the PARAMETER-NAMEs in the call to `make-parameter-list' which
+ created PARAMETER-LIST. `fill-empty-parameters' returns a new
+ parameter-list with each empty parameter replaced with the list
+ returned by calling the corresponding DEFAULTER with
+ PARAMETER-LIST as its argument.
+
+ - Function: check-parameters CHECKS PARAMETER-LIST
+ CHECKS is a list of procedures whose order matches the order of
+ the PARAMETER-NAMEs in the call to `make-parameter-list' which
+ created PARAMETER-LIST.
+
+ `check-parameters' returns PARAMETER-LIST if each CHECK of the
+ corresponding PARAMETER-LIST returns non-false. If some CHECK
+ returns `#f' an error is signaled.
+
+In the following procedures ARITIES is a list of symbols. The elements
+of `arities' can be:
+
+`single'
+ Requires a single parameter.
+
+`optional'
+ A single parameter or no parameter is acceptable.
+
+`boolean'
+ A single boolean parameter or zero parameters is acceptable.
+
+`nary'
+ Any number of parameters are acceptable.
+
+`nary1'
+ One or more of parameters are acceptable.
+
+ - Function: parameter-list->arglist POSITIONS ARITIES TYPES
+ PARAMETER-LIST
+ Returns PARAMETER-LIST converted to an argument list. Parameters
+ of ARITY type `single' and `boolean' are converted to the single
+ value associated with them. The other ARITY types are converted
+ to lists of the value(s) of type TYPES.
+
+ POSITIONS is a list of positive integers whose order matches the
+ order of the PARAMETER-NAMEs in the call to `make-parameter-list'
+ which created PARAMETER-LIST. The integers specify in which
+ argument position the corresponding parameter should appear.
+
+
+File: slib.info, Node: Getopt Parameter lists, Next: Filenames, Prev: Parameter lists, Up: Programs and Arguments
+
+Getopt Parameter lists
+----------------------
+
+ `(require 'getopt-parameters)'
+
+ - Function: getopt->parameter-list ARGC ARGV OPTNAMES ARITIES TYPES
+ ALIASES
+ Returns ARGV converted to a parameter-list. OPTNAMES are the
+ parameter-names. ALIASES is a list of lists of strings and
+ elements of OPTNAMES. Each of these strings which have length of
+ 1 will be treated as a single <-> option by `getopt'. Longer
+ strings will be treated as long-named options (*note getopt-:
+ Getopt.).
+
+ - Function: getopt->arglist ARGC ARGV OPTNAMES POSITIONS ARITIES TYPES
+ DEFAULTERS CHECKS ALIASES
+ Like `getopt->parameter-list', but converts ARGV to an
+ argument-list as specified by OPTNAMES, POSITIONS, ARITIES, TYPES,
+ DEFAULTERS, CHECKS, and ALIASES.
+
+These `getopt' functions can be used with SLIB relational databases.
+For an example, *Note make-command-server: Database Utilities.
+
+If errors are encountered while processing options, directions for using
+the options are printed to `current-error-port'.
+
+ (begin
+ (set! *optind* 1)
+ (getopt->parameter-list
+ 2
+ '("cmd" "-?")
+ '(flag number symbols symbols string flag2 flag3 num2 num3)
+ '(boolean optional nary1 nary single boolean boolean nary nary)
+ '(boolean integer symbol symbol string boolean boolean integer integer)
+ '(("flag" flag)
+ ("f" flag)
+ ("Flag" flag2)
+ ("B" flag3)
+ ("optional" number)
+ ("o" number)
+ ("nary1" symbols)
+ ("N" symbols)
+ ("nary" symbols)
+ ("n" symbols)
+ ("single" string)
+ ("s" string)
+ ("a" num2)
+ ("Abs" num3))))
+ -|
+ Usage: cmd [OPTION ARGUMENT ...] ...
+
+ -f, --flag
+ -o, --optional=<number>
+ -n, --nary=<symbols> ...
+ -N, --nary1=<symbols> ...
+ -s, --single=<string>
+ --Flag
+ -B
+ -a <num2> ...
+ --Abs=<num3> ...
+
+ ERROR: getopt->parameter-list "unrecognized option" "-?"
+
+
+File: slib.info, Node: Filenames, Next: Batch, Prev: Getopt Parameter lists, Up: Programs and Arguments
+
+Filenames
+---------
+
+ `(require 'filename)' or `(require 'glob)'
+
+ - Function: filename:match?? PATTERN
+ - Function: filename:match-ci?? PATTERN
+ Returns a predicate which returns a non-false value if its string
+ argument matches (the string) PATTERN, false otherwise. Filename
+ matching is like "glob" expansion described the bash manpage,
+ except that names beginning with `.' are matched and `/'
+ characters are not treated specially.
+
+ These functions interpret the following characters specially in
+ PATTERN strings:
+ `*'
+ Matches any string, including the null string.
+
+ `?'
+ Matches any single character.
+
+ `[...]'
+ Matches any one of the enclosed characters. A pair of
+ characters separated by a minus sign (-) denotes a range; any
+ character lexically between those two characters, inclusive,
+ is matched. If the first character following the `[' is a
+ `!' or a `^' then any character not enclosed is matched. A
+ `-' or `]' may be matched by including it as the first or
+ last character in the set.
+
+
+ - Function: filename:substitute?? PATTERN TEMPLATE
+ - Function: filename:substitute-ci?? PATTERN TEMPLATE
+ Returns a function transforming a single string argument according
+ to glob patterns PATTERN and TEMPLATE. PATTERN and TEMPLATE must
+ have the same number of wildcard specifications, which need not be
+ identical. PATTERN and TEMPLATE may have a different number of
+ literal sections. If an argument to the function matches PATTERN
+ in the sense of `filename:match??' then it returns a copy of
+ TEMPLATE in which each wildcard specification is replaced by the
+ part of the argument matched by the corresponding wildcard
+ specification in PATTERN. A `*' wildcard matches the longest
+ leftmost string possible. If the argument does not match PATTERN
+ then false is returned.
+
+ TEMPLATE may be a function accepting the same number of string
+ arguments as there are wildcard specifications in PATTERN. In the
+ case of a match the result of applying TEMPLATE to a list of the
+ substrings matched by wildcard specifications will be returned,
+ otherwise TEMPLATE will not be called and `#f' will be returned.
+
+ ((filename:substitute?? "scm_[0-9]*.html" "scm5c4_??.htm")
+ "scm_10.html")
+ => "scm5c4_10.htm"
+ ((filename:substitute?? "??" "beg?mid?end") "AZ")
+ => "begAmidZend"
+ ((filename:substitute?? "*na*" "?NA?") "banana")
+ => "banaNA"
+ ((filename:substitute?? "?*?" (lambda (s1 s2 s3) (string-append s3 s1))) "ABZ")
+ => "ZA"
+
+ - Function: replace-suffix STR OLD NEW
+ STR can be a string or a list of strings. Returns a new string
+ (or strings) similar to `str' but with the suffix string OLD
+ removed and the suffix string NEW appended. If the end of STR
+ does not match OLD, an error is signaled.
+
+ (replace-suffix "/usr/local/lib/slib/batch.scm" ".scm" ".c")
+ => "/usr/local/lib/slib/batch.c"
+
+
+File: slib.info, Node: Batch, Prev: Filenames, Up: Programs and Arguments
+
+Batch
+-----
+
+ `(require 'batch)'
+
+The batch procedures provide a way to write and execute portable scripts
+for a variety of operating systems. Each `batch:' procedure takes as
+its first argument a parameter-list (*note Parameter lists::.). This
+parameter-list argument PARMS contains named associations. Batch
+currently uses 2 of these:
+
+`batch-port'
+ The port on which to write lines of the batch file.
+
+`batch-dialect'
+ The syntax of batch file to generate. Currently supported are:
+ * unix
+
+ * dos
+
+ * vms
+
+ * amigados
+
+ * system
+
+ * *unknown*
+
+`batch.scm' uses 2 enhanced relational tables (*note Database
+Utilities::.) to store information linking the names of
+`operating-system's to `batch-dialect'es.
+
+ - Function: batch:initialize! DATABASE
+ Defines `operating-system' and `batch-dialect' tables and adds the
+ domain `operating-system' to the enhanced relational database
+ DATABASE.
+
+ - Variable: batch:platform
+ Is batch's best guess as to which operating-system it is running
+ under. `batch:platform' is set to `(software-type)' (*note
+ Configuration::.) unless `(software-type)' is `unix', in which
+ case finer distinctions are made.
+
+ - Function: batch:call-with-output-script PARMS FILE PROC
+ PROC should be a procedure of one argument. If FILE is an
+ output-port, `batch:call-with-output-script' writes an appropriate
+ header to FILE and then calls PROC with FILE as the only argument.
+ If FILE is a string, `batch:call-with-output-script' opens a
+ output-file of name FILE, writes an appropriate header to FILE,
+ and then calls PROC with the newly opened port as the only
+ argument. Otherwise, `batch:call-with-output-script' acts as if
+ it was called with the result of `(current-output-port)' as its
+ third argument.
+ |
+The rest of the `batch:' procedures write (or execute if
+`batch-dialect' is `system') commands to the batch port which has been
+added to PARMS or `(copy-tree PARMS)' by the code:
+
+ (adjoin-parameters! PARMS (list 'batch-port PORT))
+
+ - Function: batch:command PARMS STRING1 STRING2 ... |
+ Calls `batch:try-command' (below) with arguments, but signals an |
+ error if `batch:try-command' returns `#f'. |
+
+These functions return a non-false value if the command was successfully
+translated into the batch dialect and `#f' if not. In the case of the
+`system' dialect, the value is non-false if the operation suceeded.
+
+ - Function: batch:try-command PARMS STRING1 STRING2 ... |
+ Writes a command to the `batch-port' in PARMS which executes the
+ program named STRING1 with arguments STRING2 ....
+
+ - Function: batch:try-chopped-command PARMS ARG1 ARG2 ... LIST |
+ breaks the last argument LIST into chunks small enough so that the |
+ command: |
+ |
+ ARG1 ARG2 ... CHUNK |
+ |
+ fits withing the platform's maximum command-line length. |
+ |
+ `batch:try-chopped-command' calls `batch:try-command' with the |
+ command and returns non-false only if the commands all fit and |
+ `batch:try-command' of each command line returned non-false. |
+ |
+ - Function: batch:run-script PARMS STRING1 STRING2 ...
+ Writes a command to the `batch-port' in PARMS which executes the
+ batch script named STRING1 with arguments STRING2 ....
+
+ *Note:* `batch:run-script' and `batch:try-command' are not the |
+ same for some operating systems (VMS). |
+
+ - Function: batch:comment PARMS LINE1 ...
+ Writes comment lines LINE1 ... to the `batch-port' in PARMS.
+
+ - Function: batch:lines->file PARMS FILE LINE1 ...
+ Writes commands to the `batch-port' in PARMS which create a file
+ named FILE with contents LINE1 ....
+
+ - Function: batch:delete-file PARMS FILE
+ Writes a command to the `batch-port' in PARMS which deletes the
+ file named FILE.
+
+ - Function: batch:rename-file PARMS OLD-NAME NEW-NAME
+ Writes a command to the `batch-port' in PARMS which renames the
+ file OLD-NAME to NEW-NAME.
+
+In addition, batch provides some small utilities very useful for writing
+scripts:
+
+ - Function: truncate-up-to PATH CHAR
+ - Function: truncate-up-to PATH STRING
+ - Function: truncate-up-to PATH CHARLIST
+ PATH can be a string or a list of strings. Returns PATH sans any
+ prefixes ending with a character of the second argument. This can
+ be used to derive a filename moved locally from elsewhere.
+
+ (truncate-up-to "/usr/local/lib/slib/batch.scm" "/")
+ => "batch.scm"
+
+ - Function: string-join JOINER STRING1 ...
+ Returns a new string consisting of all the strings STRING1 ... in
+ order appended together with the string JOINER between each
+ adjacent pair.
+
+ - Function: must-be-first LIST1 LIST2
+ Returns a new list consisting of the elements of LIST2 ordered so
+ that if some elements of LIST1 are `equal?' to elements of LIST2,
+ then those elements will appear first and in the order of LIST1.
+
+ - Function: must-be-last LIST1 LIST2
+ Returns a new list consisting of the elements of LIST1 ordered so
+ that if some elements of LIST2 are `equal?' to elements of LIST1,
+ then those elements will appear last and in the order of LIST2.
+
+ - Function: os->batch-dialect OSNAME
+ Returns its best guess for the `batch-dialect' to be used for the
+ operating-system named OSNAME. `os->batch-dialect' uses the
+ tables added to DATABASE by `batch:initialize!'.
+
+Here is an example of the use of most of batch's procedures:
+
+ (require 'database-utilities)
+ (require 'parameters)
+ (require 'batch)
+ (require 'glob)
+
+ (define batch (create-database #f 'alist-table))
+ (batch:initialize! batch)
+
+ (define my-parameters
+ (list (list 'batch-dialect (os->batch-dialect batch:platform))
+ (list 'platform batch:platform)
+ (list 'batch-port (current-output-port)))) ;gets filled in later
+
+ (batch:call-with-output-script
+ my-parameters
+ "my-batch"
+ (lambda (batch-port)
+ (adjoin-parameters! my-parameters (list 'batch-port batch-port))
+ (and
+ (batch:comment my-parameters
+ "================ Write file with C program.")
+ (batch:rename-file my-parameters "hello.c" "hello.c~")
+ (batch:lines->file my-parameters "hello.c"
+ "#include <stdio.h>"
+ "int main(int argc, char **argv)"
+ "{"
+ " printf(\"hello world\\n\");"
+ " return 0;"
+ "}" )
+ (batch:command my-parameters "cc" "-c" "hello.c") |
+ (batch:command my-parameters "cc" "-o" "hello" |
+ (replace-suffix "hello.c" ".c" ".o"))
+ (batch:command my-parameters "hello") |
+ (batch:delete-file my-parameters "hello")
+ (batch:delete-file my-parameters "hello.c")
+ (batch:delete-file my-parameters "hello.o")
+ (batch:delete-file my-parameters "my-batch")
+ )))
+
+Produces the file `my-batch':
+
+ #!/bin/sh
+ # "my-batch" script created by SLIB/batch Sun Oct 31 18:24:10 1999 |
+ # ================ Write file with C program.
+ mv -f hello.c hello.c~
+ rm -f hello.c
+ echo '#include <stdio.h>'>>hello.c
+ echo 'int main(int argc, char **argv)'>>hello.c
+ echo '{'>>hello.c
+ echo ' printf("hello world\n");'>>hello.c
+ echo ' return 0;'>>hello.c
+ echo '}'>>hello.c
+ cc -c hello.c
+ cc -o hello hello.o
+ hello
+ rm -f hello
+ rm -f hello.c
+ rm -f hello.o
+ rm -f my-batch
+
+When run, `my-batch' prints:
+
+ bash$ my-batch
+ mv: hello.c: No such file or directory
+ hello world
+
+
+File: slib.info, Node: HTML HTTP and CGI, Next: Printing Scheme, Prev: Programs and Arguments, Up: Textual Conversion Packages
+
+HTML Forms
+==========
+
+ `(require 'html-form)'
+
+ - Variable: *html:output-port*
+ Procedure names starting with `html:' send their output to the
+ port *HTML:OUTPUT-PORT*. *HTML:OUTPUT-PORT* is initially the
+ current output port.
+
+ - Function: make-atval TXT
+ Returns a string with character substitutions appropriate to send
+ TXT as an "attribute-value".
+
+ - Function: make-plain TXT
+ Returns a string with character substitutions appropriate to send
+ TXT as an "plain-text".
+
+ - Function: html:start-page TITLE BACKLINK TAGS ...
+ - Function: html:start-page TITLE BACKLINK
+ - Function: html:start-page TITLE
+ Outputs headers for an HTML page named TITLE. If string arguments
+ BACKLINK ... are supplied they are printed verbatim within the
+ <HEAD> section.
+
+ - Function: html:end-page
+ Outputs HTML codes to end a page.
+
+ - Function: html:pre LINE1 LINE ...
+ Writes (using `html:printf') the strings LINE1, LINES as
+ "PRE"formmated plain text (rendered in fixed-width font).
+ Newlines are inserted between LINE1, LINES. HTML tags (`<tag>')
+ within LINES will be visible verbatim.
+
+ - Function: html:comment LINE1 LINE ...
+ Writes (using `html:printf') the strings LINE1 as HTML comments.
+
+HTML Tables
+===========
+
+ - Function: html:start-table CAPTION
+
+ - Function: html:end-table
+
+ - Function: html:heading COLUMNS
+ Outputs a heading row for the currently-started table.
+
+ - Function: html:href-heading COLUMNS URLS
+ Outputs a heading row with column-names COLUMNS linked to URLs
+ URLS.
+
+ - Function: make-row-converter K FOREIGNS
+ The positive integer K is the primary-key-limit (number of
+ primary-keys) of the table. FOREIGNS is a list of the filenames of
+ foreign-key field pages and #f for non foreign-key fields.
+
+ `make-row-converter' returns a procedure taking a row for its
+ single argument. This returned procedure prints the table row to
+ *HTML:OUTPUT-PORT*.
+
+ - Function: table-name->filename TABLE-NAME
+ Returns the symbol TABLE-NAME converted to a filename.
+
+ - Function: table->html CAPTION DB TABLE-NAME MATCH-KEY1 ...
+ Writes HTML for DB table TABLE-NAME to *HTML:OUTPUT-PORT*.
+
+ The optional MATCH-KEY1 ... arguments restrict actions to a subset
+ of the table. *Note match-key: Table Operations.
+
+ - Function: table->page DB TABLE-NAME INDEX-FILENAME
+ Writes a complete HTML page to *HTML:OUTPUT-PORT*. The string
+ INDEX-FILENAME names the page which refers to this one.
+
+ - Function: catalog->html DB CAPTION
+ Writes HTML for the catalog table of DB to *HTML:OUTPUT-PORT*.
+
+ - Function: catalog->page DB CAPTION
+ Writes a complete HTML page for the catalog of DB to
+ *HTML:OUTPUT-PORT*.
+
+HTML Forms
+==========
+
+ - Function: html:start-form METHOD ACTION
+ The symbol METHOD is either `get', `head', `post', `put', or
+ `delete'. `html:start-form' prints the header for an HTML "form".
+
+ - Function: html:end-form PNAME SUBMIT-LABEL
+ `html:end-form' prints the footer for an HTML "form". The string
+ SUBMIT-LABEL appears on the button which submits the form.
+
+ - Function: command->html RDB COMMAND-TABLE COMMAND METHOD ACTION
+ The symbol COMMAND-TABLE names a command table in the RDB
+ relational database.
+
+ `command->html' writes an HTML-2.0 "form" for command COMMAND to
+ the current-output-port. The `SUBMIT' button, which is labeled
+ COMMAND, invokes the URI ACTION with method METHOD with a hidden
+ attribute `*command*' bound to the command symbol submitted.
+
+ An action may invoke a CGI script
+ (`http://www.my-site.edu/cgi-bin/search.cgi') or HTTP daemon
+ (`http://www.my-site.edu:8001').
+
+ This example demonstrates how to create a HTML-form for the `build'
+ command.
+
+ (require (in-vicinity (implementation-vicinity) "build.scm"))
+ (call-with-output-file "buildscm.html"
+ (lambda (port)
+ (fluid-let ((*html:output-port* port))
+ (html:start-page 'commands)
+ (command->html
+ build '*commands* 'build 'post
+ (or "/cgi-bin/build.cgi"
+ "http://localhost:8081/buildscm"))
+ html:end-page)))
+
+HTTP and CGI service
+====================
+
+ `(require 'html-form)'
+
+ - Function: cgi:serve-command RDB COMMAND-TABLE
+ Reads a `"POST"' or `"GET"' query from `(current-input-port)' and
+ executes the encoded command from COMMAND-TABLE in
+ relational-database RDB.
+
+ This example puts up a plain-text page in response to a CGI query.
+
+ (display "Content-Type: text/plain") (newline) (newline)
+ (require 'html-form)
+ (load (in-vicinity (implementation-vicinity) "build.scm"))
+ (cgi:serve-command build '*commands*)
+
+ - Function: serve-urlencoded-command RDB COMMAND-TABLE URLENCODED
+ Reads attribute-value pairs from URLENCODED, converts them to
+ parameters and invokes the RDB command named by the parameter
+ `*command*'.
+
+ - Function: http:serve-query INPUT-PORT OUTPUT-PORT SERVE-PROC
+ reads the "query-string" from INPUT-PORT. If this is a valid
+ `"POST"' or `"GET"' query, then `http:serve-query' calls
+ SERVE-PROC with two arguments, the query-string and the
+ header-alist.
+
+ Otherwise, `http:serve-query' replies (to OUTPUT-PORT) with
+ appropriate HTML describing the problem.
+
+ This example services HTTP queries from port 8081:
+
+ (define socket (make-stream-socket AF_INET 0))
+ (socket:bind socket 8081)
+ (socket:listen socket 10)
+ (dynamic-wind
+ (lambda () #f)
+ (lambda ()
+ (do ((port (socket:accept socket)
+ (socket:accept socket)))
+ (#f)
+ (dynamic-wind
+ (lambda () #f)
+ (lambda ()
+ (fluid-let ((*html:output-port* port))
+ (http:serve-query
+ port port
+ (lambda (query-string header)
+ (http:send-header
+ '(("Content-Type" . "text/plain")))
+ (with-output-to-port port
+ (lambda ()
+ (serve-urlencoded-command
+ build '*commands* query-string)))))))
+ (lambda () (close-port port)))))
+ (lambda () (close-port socket)))
+
+ - Function: http:read-request-line PORT
+ Reads the first non-blank line from PORT and, if successful,
+ returns a list of three itmes from the request-line:
+
+ 0. Method
+
+ Either one of the symbols `options', `get', `head', `post',
+ `put', `delete', or `trace'; Or a string.
+
+ 1. Request-URI
+
+ A string. At the minimum, it will be the string `"/"'.
+
+ 2. HTTP-Version
+
+ A string. For example, `HTTP/1.0'.
+
+ - Function: cgi:read-query-string
+ Reads the "query-string" from `(current-input-port)'.
+ `cgi:read-query-string' reads a `"POST"' or `"GET"' queries,
+ depending on the value of `(getenv "REQUEST_METHOD")'.
+
+
+File: slib.info, Node: Printing Scheme, Next: Time and Date, Prev: HTML HTTP and CGI, Up: Textual Conversion Packages
+
+Printing Scheme
+===============
+
+* Menu:
+
+* Generic-Write:: 'generic-write
+* Object-To-String:: 'object->string
+* Pretty-Print:: 'pretty-print, 'pprint-file
+
+
+File: slib.info, Node: Generic-Write, Next: Object-To-String, Prev: Printing Scheme, Up: Printing Scheme
+
+Generic-Write
+-------------
+
+ `(require 'generic-write)'
+
+ `generic-write' is a procedure that transforms a Scheme data value
+(or Scheme program expression) into its textual representation and
+prints it. The interface to the procedure is sufficiently general to
+easily implement other useful formatting procedures such as pretty
+printing, output to a string and truncated output.
+
+ - Procedure: generic-write OBJ DISPLAY? WIDTH OUTPUT
+ OBJ
+ Scheme data value to transform.
+
+ DISPLAY?
+ Boolean, controls whether characters and strings are quoted.
+
+ WIDTH
+ Extended boolean, selects format:
+ #f
+ single line format
+
+ integer > 0
+ pretty-print (value = max nb of chars per line)
+
+ OUTPUT
+ Procedure of 1 argument of string type, called repeatedly with
+ successive substrings of the textual representation. This
+ procedure can return `#f' to stop the transformation.
+
+ The value returned by `generic-write' is undefined.
+
+ Examples:
+ (write obj) == (generic-write obj #f #f DISPLAY-STRING)
+ (display obj) == (generic-write obj #t #f DISPLAY-STRING)
+
+ where
+ DISPLAY-STRING ==
+ (lambda (s) (for-each write-char (string->list s)) #t)
+
+
+File: slib.info, Node: Object-To-String, Next: Pretty-Print, Prev: Generic-Write, Up: Printing Scheme
+
+Object-To-String
+----------------
+
+ `(require 'object->string)'
+
+ - Function: object->string OBJ
+ Returns the textual representation of OBJ as a string.
+
+ - Function: object->limited-string OBJ LIMIT
+ Returns the textual representation of OBJ as a string of length at
+ most LIMIT.
+
+
+File: slib.info, Node: Pretty-Print, Prev: Object-To-String, Up: Printing Scheme
+
+Pretty-Print
+------------
+
+ `(require 'pretty-print)'
+
+ - Procedure: pretty-print OBJ
+ - Procedure: pretty-print OBJ PORT
+ `pretty-print's OBJ on PORT. If PORT is not specified,
+ `current-output-port' is used.
+
+ Example:
+ (pretty-print '((1 2 3 4 5) (6 7 8 9 10) (11 12 13 14 15)
+ (16 17 18 19 20) (21 22 23 24 25)))
+ -| ((1 2 3 4 5)
+ -| (6 7 8 9 10)
+ -| (11 12 13 14 15)
+ -| (16 17 18 19 20)
+ -| (21 22 23 24 25))
+
+ `(require 'pprint-file)'
+
+ - Procedure: pprint-file INFILE
+ - Procedure: pprint-file INFILE OUTFILE
+ Pretty-prints all the code in INFILE. If OUTFILE is specified,
+ the output goes to OUTFILE, otherwise it goes to
+ `(current-output-port)'.
+
+ - Function: pprint-filter-file INFILE PROC OUTFILE
+ - Function: pprint-filter-file INFILE PROC
+ INFILE is a port or a string naming an existing file. Scheme
+ source code expressions and definitions are read from the port (or
+ file) and PROC is applied to them sequentially.
+
+ OUTFILE is a port or a string. If no OUTFILE is specified then
+ `current-output-port' is assumed. These expanded expressions are
+ then `pretty-print'ed to this port.
+
+ Whitepsace and comments (introduced by `;') which are not part of
+ scheme expressions are reproduced in the output. This procedure
+ does not affect the values returned by `current-input-port' and
+ `current-output-port'.
+
+ `pprint-filter-file' can be used to pre-compile macro-expansion and
+thus can reduce loading time. The following will write into
+`exp-code.scm' the result of expanding all defmacros in `code.scm'.
+ (require 'pprint-file)
+ (require 'defmacroexpand)
+ (defmacro:load "my-macros.scm")
+ (pprint-filter-file "code.scm" defmacro:expand* "exp-code.scm")
+
+
+File: slib.info, Node: Time and Date, Next: Vector Graphics, Prev: Printing Scheme, Up: Textual Conversion Packages
+
+Time and Date
+=============
+
+* Menu:
+
+* Time Zone::
+* Posix Time:: 'posix-time
+* Common-Lisp Time:: 'common-lisp-time
+
+If `(provided? 'current-time)':
+
+The procedures `current-time', `difftime', and `offset-time' deal with
+a "calendar time" datatype which may or may not be disjoint from other
+Scheme datatypes.
+
+ - Function: current-time
+ Returns the time since 00:00:00 GMT, January 1, 1970, measured in
+ seconds. Note that the reference time is different from the
+ reference time for `get-universal-time' in *Note Common-Lisp
+ Time::.
+
+ - Function: difftime CALTIME1 CALTIME0
+ Returns the difference (number of seconds) between twe calendar
+ times: CALTIME1 - CALTIME0. CALTIME0 may also be a number.
+
+ - Function: offset-time CALTIME OFFSET
+ Returns the calendar time of CALTIME offset by OFFSET number of
+ seconds `(+ caltime offset)'.
+
+
+File: slib.info, Node: Time Zone, Next: Posix Time, Prev: Time and Date, Up: Time and Date
+
+Time Zone
+---------
+
+ (require 'time-zone)
+
+ - Data Format: TZ-string
+ POSIX standards specify several formats for encoding time-zone
+ rules.
+
+ :<pathname>
+ If the first character of <pathname> is `/', then <pathname>
+ specifies the absolute pathname of a tzfile(5) format
+ time-zone file. Otherwise, <pathname> is interpreted as a
+ pathname within TZFILE:VICINITY (/usr/lib/zoneinfo/) naming a
+ tzfile(5) format time-zone file.
+
+ <std><offset>
+ The string <std> consists of 3 or more alphabetic characters.
+ <offset> specifies the time difference from GMT. The <offset>
+ is positive if the local time zone is west of the Prime
+ Meridian and negative if it is east. <offset> can be the
+ number of hours or hours and minutes (and optionally seconds)
+ separated by `:'. For example, `-4:30'.
+
+ <std><offset><dst>
+ <dst> is the at least 3 alphabetic characters naming the local
+ daylight-savings-time.
+
+ <std><offset><dst><doffset>
+ <doffset> specifies the offset from the Prime Meridian when
+ daylight-savings-time is in effect.
+
+ The non-tzfile formats can optionally be followed by transition
+ times specifying the day and time when a zone changes from
+ standard to daylight-savings and back again.
+
+ ,<date>/<time>,<date>/<time>
+ The <time>s are specified like the <offset>s above, except
+ that leading `+' and `-' are not allowed.
+
+ Each <date> has one of the formats:
+
+ J<day>
+ specifies the Julian day with <day> between 1 and 365.
+ February 29 is never counted and cannot be referenced.
+
+ <day>
+ This specifies the Julian day with n between 0 and 365.
+ February 29 is counted in leap years and can be
+ specified.
+
+ M<month>.<week>.<day>
+ This specifies day <day> (0 <= <day> <= 6) of week
+ <week> (1 <= <week> <= 5) of month <month> (1 <= <month>
+ <= 12). Week 1 is the first week in which day d occurs
+ and week 5 is the last week in which day <day> occurs.
+ Day 0 is a Sunday.
+
+
+ - Data Type: time-zone
+ is a datatype encoding how many hours from Greenwich Mean Time the
+ local time is, and the "Daylight Savings Time" rules for changing
+ it.
+
+ - Function: time-zone TZ-STRING
+ Creates and returns a time-zone object specified by the string
+ TZ-STRING. If `time-zone' cannot interpret TZ-STRING, `#f' is
+ returned.
+
+ - Function: tz:params CALTIME TZ
+ TZ is a time-zone object. `tz:params' returns a list of three
+ items:
+ 0. An integer. 0 if standard time is in effect for timezone TZ
+ at CALTIME; 1 if daylight savings time is in effect for
+ timezone TZ at CALTIME.
+
+ 1. The number of seconds west of the Prime Meridian timezone TZ
+ is at CALTIME.
+
+ 2. The name for timezone TZ at CALTIME.
+
+ `tz:params' is unaffected by the default timezone; inquiries can be
+ made of any timezone at any calendar time.
+
+
+The rest of these procedures and variables are provided for POSIX
+compatability. Because of shared state they are not thread-safe.
+
+ - Function: tzset
+ Returns the default time-zone.
+
+ - Function: tzset TZ
+ Sets (and returns) the default time-zone to TZ.
+
+ - Function: tzset TZ-STRING
+ Sets (and returns) the default time-zone to that specified by
+ TZ-STRING.
+
+ `tzset' also sets the variables *TIMEZONE*, DAYLIGHT?, and TZNAME.
+ This function is automatically called by the time conversion
+ procedures which depend on the time zone (*note Time and Date::.).
+
+ - Variable: *timezone*
+ Contains the difference, in seconds, between Greenwich Mean Time
+ and local standard time (for example, in the U.S. Eastern time
+ zone (EST), timezone is 5*60*60). `*timezone*' is initialized by
+ `tzset'.
+
+ - Variable: daylight?
+ is `#t' if the default timezone has rules for "Daylight Savings
+ Time". *Note:* DAYLIGHT? does not tell you when Daylight Savings
+ Time is in effect, just that the default zone sometimes has
+ Daylight Savings Time.
+
+ - Variable: tzname
+ is a vector of strings. Index 0 has the abbreviation for the
+ standard timezone; If DAYLIGHT?, then index 1 has the abbreviation
+ for the Daylight Savings timezone.
+
+
+File: slib.info, Node: Posix Time, Next: Common-Lisp Time, Prev: Time Zone, Up: Time and Date
+
+Posix Time
+----------
+
+ (require 'posix-time)
+
+ - Data Type: Calendar-Time
+ is a datatype encapsulating time.
+
+ - Data Type: Coordinated Universal Time
+ (abbreviated "UTC") is a vector of integers representing time:
+
+ 0. seconds (0 - 61)
+
+ 1. minutes (0 - 59)
+
+ 2. hours since midnight (0 - 23)
+
+ 3. day of month (1 - 31)
+
+ 4. month (0 - 11). Note difference from
+ `decode-universal-time'.
+
+ 5. the number of years since 1900. Note difference from
+ `decode-universal-time'.
+
+ 6. day of week (0 - 6)
+
+ 7. day of year (0 - 365)
+
+ 8. 1 for daylight savings, 0 for regular time
+
+ - Function: gmtime CALTIME
+ Converts the calendar time CALTIME to UTC and returns it.
+
+ - Function: localtime CALTIME TZ
+ Returns CALTIME converted to UTC relative to timezone TZ.
+
+ - Function: localtime CALTIME
+ converts the calendar time CALTIME to a vector of integers
+ expressed relative to the user's time zone. `localtime' sets the
+ variable *TIMEZONE* with the difference between Coordinated
+ Universal Time (UTC) and local standard time in seconds (*note
+ tzset: Time Zone.).
+
+
+ - Function: gmktime UNIVTIME
+ Converts a vector of integers in GMT Coordinated Universal Time
+ (UTC) format to a calendar time.
+
+ - Function: mktime UNIVTIME
+ Converts a vector of integers in local Coordinated Universal Time
+ (UTC) format to a calendar time.
+
+ - Function: mktime UNIVTIME TZ
+ Converts a vector of integers in Coordinated Universal Time (UTC)
+ format (relative to time-zone TZ) to calendar time.
+
+ - Function: asctime UNIVTIME
+ Converts the vector of integers CALTIME in Coordinated Universal
+ Time (UTC) format into a string of the form `"Wed Jun 30 21:49:08
+ 1993"'.
+
+ - Function: gtime CALTIME
+ - Function: ctime CALTIME
+ - Function: ctime CALTIME TZ
+ Equivalent to `(asctime (gmtime CALTIME))', `(asctime (localtime
+ CALTIME))', and `(asctime (localtime CALTIME TZ))', respectively.
+
+
+File: slib.info, Node: Common-Lisp Time, Prev: Posix Time, Up: Time and Date
+
+Common-Lisp Time
+----------------
+
+ - Function: get-decoded-time
+ Equivalent to `(decode-universal-time (get-universal-time))'.
+
+ - Function: get-universal-time
+ Returns the current time as "Universal Time", number of seconds
+ since 00:00:00 Jan 1, 1900 GMT. Note that the reference time is
+ different from `current-time'.
+
+ - Function: decode-universal-time UNIVTIME
+ Converts UNIVTIME to "Decoded Time" format. Nine values are
+ returned:
+ 0. seconds (0 - 61)
+
+ 1. minutes (0 - 59)
+
+ 2. hours since midnight
+
+ 3. day of month
+
+ 4. month (1 - 12). Note difference from `gmtime' and
+ `localtime'.
+
+ 5. year (A.D.). Note difference from `gmtime' and `localtime'.
+
+ 6. day of week (0 - 6)
+
+ 7. #t for daylight savings, #f otherwise
+
+ 8. hours west of GMT (-24 - +24)
+
+ Notice that the values returned by `decode-universal-time' do not
+ match the arguments to `encode-universal-time'.
+
+ - Function: encode-universal-time SECOND MINUTE HOUR DATE MONTH YEAR
+ - Function: encode-universal-time SECOND MINUTE HOUR DATE MONTH YEAR
+ TIME-ZONE
+ Converts the arguments in Decoded Time format to Universal Time
+ format. If TIME-ZONE is not specified, the returned time is
+ adjusted for daylight saving time. Otherwise, no adjustment is
+ performed.
+
+ Notice that the values returned by `decode-universal-time' do not
+ match the arguments to `encode-universal-time'.
+
+
+File: slib.info, Node: Vector Graphics, Next: Schmooz, Prev: Time and Date, Up: Textual Conversion Packages
+
+Vector Graphics
+===============
+
+* Menu:
+
+* Tektronix Graphics Support::
+
+
+File: slib.info, Node: Tektronix Graphics Support, Prev: Vector Graphics, Up: Vector Graphics
+
+Tektronix Graphics Support
+--------------------------
+
+ *Note:* The Tektronix graphics support files need more work, and are
+not complete.
+
+Tektronix 4000 Series Graphics
+..............................
+
+ The Tektronix 4000 series graphics protocol gives the user a 1024 by
+1024 square drawing area. The origin is in the lower left corner of the
+screen. Increasing y is up and increasing x is to the right.
+
+ The graphics control codes are sent over the current-output-port and
+can be mixed with regular text and ANSI or other terminal control
+sequences.
+
+ - Procedure: tek40:init
+
+ - Procedure: tek40:graphics
+
+ - Procedure: tek40:text
+
+ - Procedure: tek40:linetype LINETYPE
+
+ - Procedure: tek40:move X Y
+
+ - Procedure: tek40:draw X Y
+
+ - Procedure: tek40:put-text X Y STR
+
+ - Procedure: tek40:reset
+
+Tektronix 4100 Series Graphics
+..............................
+
+ The graphics control codes are sent over the current-output-port and
+can be mixed with regular text and ANSI or other terminal control
+sequences.
+
+ - Procedure: tek41:init
+
+ - Procedure: tek41:reset
+
+ - Procedure: tek41:graphics
+
+ - Procedure: tek41:move X Y
+
+ - Procedure: tek41:draw X Y
+
+ - Procedure: tek41:point X Y NUMBER
+
+ - Procedure: tek41:encode-x-y X Y
+
+ - Procedure: tek41:encode-int NUMBER
+
+
+File: slib.info, Node: Schmooz, Prev: Vector Graphics, Up: Textual Conversion Packages
+
+Schmooz
+=======
+
+ "Schmooz" is a simple, lightweight markup language for interspersing
+Texinfo documentation with Scheme source code. Schmooz does not create
+the top level Texinfo file; it creates `txi' files which can be
+imported into the documentation using the Texinfo command `@include'.
+
+ `(require 'schmooz)' defines the function `schmooz', which is used to
+process files. Files containing schmooz documentation should not
+contain `(require 'schmooz)'.
+
+ - Procedure: schmooz FILENAMEscm ...
+ FILENAMEscm should be a string ending with `scm' naming an
+ existing file containing Scheme source code. `schmooz' extracts
+ top-level comments containing schmooz commands from FILENAMEscm
+ and writes the converted Texinfo source to a file named
+ FILENAMEtxi.
+
+ - Procedure: schmooz FILENAMEtexi ...
+ - Procedure: schmooz FILENAMEtex ...
+ - Procedure: schmooz FILENAMEtxi ...
+ FILENAME should be a string naming an existing file containing
+ Texinfo source code. For every occurrence of the string `@include
+ FILENAMEtxi' within that file, `schmooz' calls itself with the
+ argument `FILENAMEscm'.
+
+ Schmooz comments are distinguished (from non-schmooz comments) by
+their first line, which must start with an at-sign (@) preceded by one
+or more semicolons (;). A schmooz comment ends at the first subsequent
+line which does *not* start with a semicolon. Currently schmooz
+comments are recognized only at top level.
+
+ Schmooz comments are copied to the Texinfo output file with the
+leading contiguous semicolons removed. Certain character sequences
+starting with at-sign are treated specially. Others are copied
+unchanged.
+
+ A schmooz comment starting with `@body' must be followed by a Scheme
+definition. All comments between the `@body' line and the definition
+will be included in a Texinfo definition, either a `@defun' or a
+`@defvar', depending on whether a procedure or a variable is being
+defined.
+
+ Within the text of that schmooz comment, at-sign followed by `0' will
+be replaced by `@code{procedure-name}' if the following definition is
+of a procedure; or `@var{variable}' if defining a variable.
+
+ An at-sign followed by a non-zero digit will expand to the variable
+citation of that numbered argument: `@var{argument-name}'.
+
+ If more than one definition follows a `@body' comment line without an
+intervening blank or comment line, then those definitions will be
+included in the same Texinfo definition using `@defvarx' or `@defunx',
+depending on whether the first definition is of a variable or of a
+procedure.
+
+ Schmooz can figure out whether a definition is of a procedure if it
+is of the form:
+
+ `(define (<identifier> <arg> ...) <expression>)'
+
+or if the left hand side of the definition is some form ending in a
+lambda expression. Obviously, it can be fooled. In order to force
+recognition of a procedure definition, start the documentation with
+`@args' instead of `@body'. `@args' should be followed by the argument
+list of the function being defined, which may be enclosed in
+parentheses and delimited by whitespace, (as in Scheme), enclosed in
+braces and separated by commas, (as in Texinfo), or consist of the
+remainder of the line, separated by whitespace.
+
+ For example:
+
+ ;;@args arg1 args ...
+ ;;@0 takes argument @1 and any number of @2
+ (define myfun (some-function-returning-magic))
+
+ Will result in:
+
+ @defun myfun arg1 args @dots{}
+
+ @code{myfun} takes argument @var{arg1} and any number of @var{args}
+ @end defun
+
+ `@args' may also be useful for indicating optional arguments by name.
+If `@args' occurs inside a schmooz comment section, rather than at the
+beginning, then it will generate a `@defunx' line with the arguments
+supplied.
+
+ If the first at-sign in a schmooz comment is immediately followed by
+whitespace, then the comment will be expanded to whatever follows that
+whitespace. If the at-sign is followed by a non-whitespace character
+then the at-sign will be included as the first character of the
+expansion. This feature is intended to make it easy to include Texinfo
+directives in schmooz comments.
+
+
+File: slib.info, Node: Mathematical Packages, Next: Database Packages, Prev: Textual Conversion Packages, Up: Top
+
+Mathematical Packages
+*********************
+
+* Menu:
+
+* Bit-Twiddling:: 'logical
+* Modular Arithmetic:: 'modular
+* Prime Numbers:: 'factor
+* Random Numbers:: 'random
+* Fast Fourier Transform:: 'fft
+* Cyclic Checksum:: 'make-crc
+* Plotting:: 'charplot
+* Root Finding:: 'root
+* Commutative Rings:: 'commutative-ring
+* Determinant:: 'determinant
+
+
+File: slib.info, Node: Bit-Twiddling, Next: Modular Arithmetic, Prev: Mathematical Packages, Up: Mathematical Packages
+
+Bit-Twiddling
+=============
+
+ `(require 'logical)'
+
+ The bit-twiddling functions are made available through the use of the
+`logical' package. `logical' is loaded by inserting `(require
+'logical)' before the code that uses these functions. These functions
+behave as though operating on integers in two's-complement
+representation.
+
+Bitwise Operations
+------------------
+
+ - Function: logand N1 N1
+ Returns the integer which is the bit-wise AND of the two integer
+ arguments.
+
+ Example:
+ (number->string (logand #b1100 #b1010) 2)
+ => "1000"
+
+ - Function: logior N1 N2
+ Returns the integer which is the bit-wise OR of the two integer
+ arguments.
+
+ Example:
+ (number->string (logior #b1100 #b1010) 2)
+ => "1110"
+
+ - Function: logxor N1 N2
+ Returns the integer which is the bit-wise XOR of the two integer
+ arguments.
+
+ Example:
+ (number->string (logxor #b1100 #b1010) 2)
+ => "110"
+
+ - Function: lognot N
+ Returns the integer which is the 2s-complement of the integer
+ argument.
+
+ Example:
+ (number->string (lognot #b10000000) 2)
+ => "-10000001"
+ (number->string (lognot #b0) 2)
+ => "-1"
+
+ - Function: bitwise-if MASK N0 N1
+ Returns an integer composed of some bits from integer N0 and some
+ from integer N1. A bit of the result is taken from N0 if the
+ corresponding bit of integer MASK is 1 and from N1 if that bit of
+ MASK is 0.
+
+ - Function: logtest J K
+ (logtest j k) == (not (zero? (logand j k)))
+
+ (logtest #b0100 #b1011) => #f
+ (logtest #b0100 #b0111) => #t
+
+ - Function: logcount N
+ Returns the number of bits in integer N. If integer is positive,
+ the 1-bits in its binary representation are counted. If negative,
+ the 0-bits in its two's-complement binary representation are
+ counted. If 0, 0 is returned.
+
+ Example:
+ (logcount #b10101010)
+ => 4
+ (logcount 0)
+ => 0
+ (logcount -2)
+ => 1
+
+Bit Within Word
+---------------
+
+ - Function: logbit? INDEX J
+ (logbit? index j) == (logtest (integer-expt 2 index) j)
+
+ (logbit? 0 #b1101) => #t
+ (logbit? 1 #b1101) => #f
+ (logbit? 2 #b1101) => #t
+ (logbit? 3 #b1101) => #t
+ (logbit? 4 #b1101) => #f
+
+ - Function: copy-bit INDEX FROM BIT
+ Returns an integer the same as FROM except in the INDEXth bit,
+ which is 1 if BIT is `#t' and 0 if BIT is `#f'.
+
+ Example:
+ (number->string (copy-bit 0 0 #t) 2) => "1"
+ (number->string (copy-bit 2 0 #t) 2) => "100"
+ (number->string (copy-bit 2 #b1111 #f) 2) => "1011"
+
+Fields of Bits
+--------------
+
+ - Function: bit-field N START END
+ Returns the integer composed of the START (inclusive) through END
+ (exclusive) bits of N. The STARTth bit becomes the 0-th bit in
+ the result.
+
+ This function was called `bit-extract' in previous versions of
+ SLIB.
+
+ Example:
+ (number->string (bit-field #b1101101010 0 4) 2)
+ => "1010"
+ (number->string (bit-field #b1101101010 4 9) 2)
+ => "10110"
+
+ - Function: copy-bit-field TO START END FROM
+ Returns an integer the same as TO except possibly in the START
+ (inclusive) through END (exclusive) bits, which are the same as
+ those of FROM. The 0-th bit of FROM becomes the STARTth bit of
+ the result.
+
+ Example:
+ (number->string (copy-bit-field #b1101101010 0 4 0) 2)
+ => "1101100000"
+ (number->string (copy-bit-field #b1101101010 0 4 -1) 2)
+ => "1101101111"
+
+ - Function: ash INT COUNT
+ Returns an integer equivalent to `(inexact->exact (floor (* INT
+ (expt 2 COUNT))))'.
+
+ Example:
+ (number->string (ash #b1 3) 2)
+ => "1000"
+ (number->string (ash #b1010 -1) 2)
+ => "101"
+
+ - Function: integer-length N
+ Returns the number of bits neccessary to represent N.
+
+ Example:
+ (integer-length #b10101010)
+ => 8
+ (integer-length 0)
+ => 0
+ (integer-length #b1111)
+ => 4
+
+ - Function: integer-expt N K
+ Returns N raised to the non-negative integer exponent K.
+
+ Example:
+ (integer-expt 2 5)
+ => 32
+ (integer-expt -3 3)
+ => -27
+
+
+File: slib.info, Node: Modular Arithmetic, Next: Prime Numbers, Prev: Bit-Twiddling, Up: Mathematical Packages
+
+Modular Arithmetic
+==================
+
+ `(require 'modular)'
+
+ - Function: extended-euclid N1 N2
+ Returns a list of 3 integers `(d x y)' such that d = gcd(N1, N2) =
+ N1 * x + N2 * y.
+
+ - Function: symmetric:modulus N
+ Returns `(quotient (+ -1 n) -2)' for positive odd integer N.
+
+ - Function: modulus->integer MODULUS
+ Returns the non-negative integer characteristic of the ring formed
+ when MODULUS is used with `modular:' procedures.
+
+ - Function: modular:normalize MODULUS N
+ Returns the integer `(modulo N (modulus->integer MODULUS))' in the
+ representation specified by MODULUS.
+
+The rest of these functions assume normalized arguments; That is, the
+arguments are constrained by the following table:
+
+For all of these functions, if the first argument (MODULUS) is:
+`positive?'
+ Work as before. The result is between 0 and MODULUS.
+
+`zero?'
+ The arguments are treated as integers. An integer is returned.
+
+`negative?'
+ The arguments and result are treated as members of the integers
+ modulo `(+ 1 (* -2 MODULUS))', but with "symmetric"
+ representation; i.e. `(<= (- MODULUS) N MODULUS)'.
+
+If all the arguments are fixnums the computation will use only fixnums.
+
+ - Function: modular:invertable? MODULUS K
+ Returns `#t' if there exists an integer n such that K * n == 1 mod
+ MODULUS, and `#f' otherwise.
+
+ - Function: modular:invert MODULUS K2
+ Returns an integer n such that 1 = (n * K2) mod MODULUS. If K2
+ has no inverse mod MODULUS an error is signaled.
+
+ - Function: modular:negate MODULUS K2
+ Returns (-K2) mod MODULUS.
+
+ - Function: modular:+ MODULUS K2 K3
+ Returns (K2 + K3) mod MODULUS.
+
+ - Function: modular:- MODULUS K2 K3
+ Returns (K2 - K3) mod MODULUS.
+
+ - Function: modular:* MODULUS K2 K3
+ Returns (K2 * K3) mod MODULUS.
+
+ The Scheme code for `modular:*' with negative MODULUS is not
+ completed for fixnum-only implementations.
+
+ - Function: modular:expt MODULUS K2 K3
+ Returns (K2 ^ K3) mod MODULUS.
+
+
+File: slib.info, Node: Prime Numbers, Next: Random Numbers, Prev: Modular Arithmetic, Up: Mathematical Packages
+
+Prime Numbers
+=============
+
+ `(require 'factor)'
+
+ - Variable: prime:prngs
+ PRIME:PRNGS is the random-state (*note Random Numbers::.) used by
+ these procedures. If you call these procedures from more than one |
+ thread (or from interrupt), `random' may complain about reentrant |
+ calls. |
+ |
+ *Note:* The prime test and generation procedures implement (or use) |
+the Solovay-Strassen primality test. See |
+ |
+ * Robert Solovay and Volker Strassen, `A Fast Monte-Carlo Test for |
+ Primality', SIAM Journal on Computing, 1977, pp 84-85. |
+
+ - Function: jacobi-symbol P Q
+ Returns the value (+1, -1, or 0) of the Jacobi-Symbol of exact
+ non-negative integer P and exact positive odd integer Q.
+
+ - Variable: prime:trials
+ PRIME:TRIALS the maxinum number of iterations of Solovay-Strassen
+ that will be done to test a number for primality.
+
+ - Function: prime? N
+ Returns `#f' if N is composite; `#t' if N is prime. There is a
+ slight chance `(expt 2 (- prime:trials))' that a composite will
+ return `#t'.
+
+ - Function: primes< START COUNT
+ Returns a list of the first COUNT prime numbers less than START.
+ If there are fewer than COUNT prime numbers less than START, then
+ the returned list will have fewer than START elements.
+
+ - Function: primes> START COUNT
+ Returns a list of the first COUNT prime numbers greater than START.
+
+ - Function: factor K
+ Returns a list of the prime factors of K. The order of the
+ factors is unspecified. In order to obtain a sorted list do
+ `(sort! (factor K) <)'.
+
+
+File: slib.info, Node: Random Numbers, Next: Fast Fourier Transform, Prev: Prime Numbers, Up: Mathematical Packages
+
+Random Numbers
+==============
+
+ `(require 'random)'
+
+ A pseudo-random number generator is only as good as the tests it
+passes. George Marsaglia of Florida State University developed a
+battery of tests named "DIEHARD"
+(`http://stat.fsu.edu/~geo/diehard.html'). `diehard.c' has a bug which
+the patch |
+`http://swissnet.ai.mit.edu/ftpdir/users/jaffer/diehard.c.pat' corrects. |
+
+ SLIB's new PRNG generates 8 bits at a time. With the degenerate seed
+`0', the numbers generated pass DIEHARD; but when bits are combined
+from sequential bytes, tests fail. With the seed
+`http://swissnet.ai.mit.edu/~jaffer/SLIB.html', all of those tests pass.
+
+ - Function: random N
+ - Function: random N STATE
+ Accepts a positive integer or real N and returns a number of the
+ same type between zero (inclusive) and N (exclusive). The values
+ returned by `random' are uniformly distributed from 0 to N.
+
+ The optional argument STATE must be of the type returned by
+ `(seed->random-state)' or `(make-random-state)'. It defaults to
+ the value of the variable `*random-state*'. This object is used
+ to maintain the state of the pseudo-random-number generator and is
+ altered as a side effect of calls to `random'.
+
+ - Variable: *random-state*
+ Holds a data structure that encodes the internal state of the
+ random-number generator that `random' uses by default. The nature
+ of this data structure is implementation-dependent. It may be
+ printed out and successfully read back in, but may or may not
+ function correctly as a random-number state object in another
+ implementation.
+
+ - Function: copy-random-state STATE
+ Returns a new copy of argument STATE.
+
+ - Function: copy-random-state
+ Returns a new copy of `*random-state*'.
+
+ - Function: seed->random-state SEED
+ Returns a new object of type suitable for use as the value of the
+ variable `*random-state*' or as a second argument to `random'.
+ The number or string SEED is used to initialize the state. If
+ `seed->random-state' is called twice with arguments which are
+ `equal?', then the returned data structures will be `equal?'.
+ Calling `seed->random-state' with unequal arguments will nearly
+ always return unequal states.
+
+ - Function: make-random-state
+ - Function: make-random-state OBJ
+ Returns a new object of type suitable for use as the value of the
+ variable `*random-state*' or as a second argument to `random'. If
+ the optional argument OBJ is given, it should be a printable
+ Scheme object; the first 50 characters of its printed
+ representation will be used as the seed. Otherwise the value of
+ `*random-state*' is used as the seed.
+
+ If inexact numbers are supported by the Scheme implementation,
+`randinex.scm' will be loaded as well. `randinex.scm' contains
+procedures for generating inexact distributions.
+
+ - Function: random:uniform
+ - Function: random:uniform STATE
+ Returns an uniformly distributed inexact real random number in the
+ range between 0 and 1.
+
+ - Function: random:exp
+ - Function: random:exp STATE
+ Returns an inexact real in an exponential distribution with mean
+ 1. For an exponential distribution with mean U use
+ `(* U (random:exp))'.
+
+ - Function: random:normal
+ - Function: random:normal STATE
+ Returns an inexact real in a normal distribution with mean 0 and
+ standard deviation 1. For a normal distribution with mean M and
+ standard deviation D use `(+ M (* D (random:normal)))'.
+
+ - Function: random:normal-vector! VECT
+ - Function: random:normal-vector! VECT STATE
+ Fills VECT with inexact real random numbers which are independent
+ and standard normally distributed (i.e., with mean 0 and variance
+ 1).
+
+ - Function: random:hollow-sphere! VECT
+ - Function: random:hollow-sphere! VECT STATE
+ Fills VECT with inexact real random numbers the sum of whose
+ squares is less than 1.0. Thinking of VECT as coordinates in
+ space of dimension N = `(vector-length VECT)', the coordinates are
+ uniformly distributed within the unit N-shere. The sum of the
+ squares of the numbers is returned.
+
+ - Function: random:solid-sphere! VECT
+ - Function: random:solid-sphere! VECT STATE
+ Fills VECT with inexact real random numbers the sum of whose
+ squares is equal to 1.0. Thinking of VECT as coordinates in space
+ of dimension n = `(vector-length VECT)', the coordinates are
+ uniformly distributed over the surface of the unit n-shere.
+
+
+File: slib.info, Node: Fast Fourier Transform, Next: Cyclic Checksum, Prev: Random Numbers, Up: Mathematical Packages
+
+Fast Fourier Transform
+======================
+
+ `(require 'fft)'
+
+ - Function: fft ARRAY
+ ARRAY is an array of `(expt 2 n)' numbers. `fft' returns an array
+ of complex numbers comprising the "Discrete Fourier Transform" of
+ ARRAY.
+
+ - Function: fft-1 ARRAY
+ `fft-1' returns an array of complex numbers comprising the inverse
+ Discrete Fourier Transform of ARRAY.
+
+ `(fft-1 (fft ARRAY))' will return an array of values close to ARRAY.
+
+ (fft '#(1 0+i -1 0-i 1 0+i -1 0-i)) =>
+
+ #(0.0 0.0 0.0+628.0783185208527e-18i 0.0
+ 0.0 0.0 8.0-628.0783185208527e-18i 0.0)
+
+ (fft-1 '#(0 0 0 0 0 0 8 0)) =>
+
+ #(1.0 -61.23031769111886e-18+1.0i -1.0 61.23031769111886e-18-1.0i
+ 1.0 -61.23031769111886e-18+1.0i -1.0 61.23031769111886e-18-1.0i)
+
+
+File: slib.info, Node: Cyclic Checksum, Next: Plotting, Prev: Fast Fourier Transform, Up: Mathematical Packages
+
+Cyclic Checksum
+===============
+
+ `(require 'make-crc)'
+
+ - Function: make-port-crc
+ - Function: make-port-crc DEGREE
+ - Function: make-port-crc DEGREE GENERATOR
+ Returns an expression for a procedure of one argument, a port.
+ This procedure reads characters from the port until the end of
+ file and returns the integer checksum of the bytes read.
+
+ The integer DEGREE, if given, specifies the degree of the
+ polynomial being computed - which is also the number of bits
+ computed in the checksums. The default value is 32.
+
+ The integer GENERATOR specifies the polynomial being computed.
+ The power of 2 generating each 1 bit is the exponent of a term of
+ the polynomial. The bit at position DEGREE is implicit and should
+ not be part of GENERATOR. This allows systems with numbers
+ limited to 32 bits to calculate 32 bit checksums. The default
+ value of GENERATOR when DEGREE is 32 (its default) is:
+
+ (make-port-crc 32 #b00000100110000010001110110110111)
+
+ Creates a procedure to calculate the P1003.2/D11.2 (POSIX.2) 32-bit
+ checksum from the polynomial:
+
+ 32 26 23 22 16 12 11
+ ( x + x + x + x + x + x + x +
+
+ 10 8 7 5 4 2 1
+ x + x + x + x + x + x + x + 1 ) mod 2
+
+ (require 'make-crc)
+ (define crc32 (slib:eval (make-port-crc)))
+ (define (file-check-sum file) (call-with-input-file file crc32))
+ (file-check-sum (in-vicinity (library-vicinity) "ratize.scm"))
+
+ => 3553047446
+
+
+File: slib.info, Node: Plotting, Next: Root Finding, Prev: Cyclic Checksum, Up: Mathematical Packages
+
+Plotting on Character Devices
+=============================
+
+ `(require 'charplot)'
+
+ The plotting procedure is made available through the use of the
+`charplot' package. `charplot' is loaded by inserting `(require
+'charplot)' before the code that uses this procedure.
+
+ - Variable: charplot:height
+ The number of rows to make the plot vertically.
+
+ - Variable: charplot:width
+ The number of columns to make the plot horizontally.
+
+ - Procedure: plot! COORDS X-LABEL Y-LABEL
+ COORDS is a list of pairs of x and y coordinates. X-LABEL and
+ Y-LABEL are strings with which to label the x and y axes.
+
+ Example:
+ (require 'charplot)
+ (set! charplot:height 19)
+ (set! charplot:width 45)
+
+ (define (make-points n)
+ (if (zero? n)
+ '()
+ (cons (cons (/ n 6) (sin (/ n 6))) (make-points (1- n)))))
+
+ (plot! (make-points 37) "x" "Sin(x)")
+ -|
+ Sin(x) ______________________________________________
+ 1.25|- |
+ | |
+ 1|- **** |
+ | ** ** |
+ 750.0e-3|- * * |
+ | * * |
+ 500.0e-3|- * * |
+ | * |
+ 250.0e-3|- * |
+ | * * |
+ 0|-------------------*--------------------------|
+ | * |
+ -250.0e-3|- * * |
+ | * * |
+ -500.0e-3|- * |
+ | * * |
+ -750.0e-3|- * * |
+ | ** ** |
+ -1|- **** |
+ |____________:_____._____:_____._____:_________|
+ x 2 4
+
+
+File: slib.info, Node: Root Finding, Next: Commutative Rings, Prev: Plotting, Up: Mathematical Packages
+
+Root Finding
+============
+
+ `(require 'root)'
+
+ - Function: newtown:find-integer-root F DF/DX X0
+ Given integer valued procedure F, its derivative (with respect to
+ its argument) DF/DX, and initial integer value X0 for which
+ DF/DX(X0) is non-zero, returns an integer X for which F(X) is
+ closer to zero than either of the integers adjacent to X; or
+ returns `#f' if such an integer can't be found.
+
+ To find the closest integer to a given integers square root:
+
+ (define (integer-sqrt y)
+ (newton:find-integer-root
+ (lambda (x) (- (* x x) y))
+ (lambda (x) (* 2 x))
+ (ash 1 (quotient (integer-length y) 2))))
+
+ (integer-sqrt 15) => 4
+
+ - Function: integer-sqrt Y
+ Given a non-negative integer Y, returns the rounded square-root of
+ Y.
+
+ - Function: newton:find-root F DF/DX X0 PREC
+ Given real valued procedures F, DF/DX of one (real) argument,
+ initial real value X0 for which DF/DX(X0) is non-zero, and
+ positive real number PREC, returns a real X for which `abs'(F(X))
+ is less than PREC; or returns `#f' if such a real can't be found.
+
+ If PREC is instead a negative integer, `newton:find-root' returns
+ the result of -PREC iterations.
+
+H. J. Orchard, `The Laguerre Method for Finding the Zeros of
+Polynomials', IEEE Transactions on Circuits and Systems, Vol. 36, No.
+11, November 1989, pp 1377-1381.
+
+ There are 2 errors in Orchard's Table II. Line k=2 for starting
+ value of 1000+j0 should have Z_k of 1.0475 + j4.1036 and line k=2
+ for starting value of 0+j1000 should have Z_k of 1.0988 + j4.0833.
+
+ - Function: laguerre:find-root F DF/DZ DDF/DZ^2 Z0 PREC
+ Given complex valued procedure F of one (complex) argument, its
+ derivative (with respect to its argument) DF/DX, its second
+ derivative DDF/DZ^2, initial complex value Z0, and positive real
+ number PREC, returns a complex number Z for which
+ `magnitude'(F(Z)) is less than PREC; or returns `#f' if such a
+ number can't be found.
+
+ If PREC is instead a negative integer, `laguerre:find-root'
+ returns the result of -PREC iterations.
+
+ - Function: laguerre:find-polynomial-root DEG F DF/DZ DDF/DZ^2 Z0 PREC
+ Given polynomial procedure F of integer degree DEG of one
+ argument, its derivative (with respect to its argument) DF/DX, its
+ second derivative DDF/DZ^2, initial complex value Z0, and positive
+ real number PREC, returns a complex number Z for which
+ `magnitude'(F(Z)) is less than PREC; or returns `#f' if such a
+ number can't be found.
+
+ If PREC is instead a negative integer,
+ `laguerre:find-polynomial-root' returns the result of -PREC
+ iterations.
+
+ - Function: secant:find-root F X0 X1 PREC
+ - Function: secant:find-bracketed-root F X0 X1 PREC
+ Given a real valued procedure F and two real valued starting
+ points X0 and X1, returns a real X for which `(abs (f x))' is less
+ than PREC; or returns `#f' if such a real can't be found.
+
+ If X0 and X1 are chosen such that they bracket a root, that is
+ (or (< (f x0) 0 (f x1))
+ (< (f x1) 0 (f x0)))
+ then the root returned will be between X0 and X1, and F will not
+ be passed an argument outside of that interval.
+
+ `secant:find-bracketed-root' will return `#f' unless X0 and X1
+ bracket a root.
+
+ The secant method is used until a bracketing interval is found, at
+ which point a modified regula falsi method is used.
+
+ If PREC is instead a negative integer, `secant:find-root' returns
+ the result of -PREC iterations.
+
+ If PREC is a procedure it should accept 5 arguments: X0 F0 X1 F1
+ and COUNT, where F0 will be `(f x0)', F1 `(f x1)', and COUNT the
+ number of iterations performed so far. PREC should return
+ non-false if the iteration should be stopped.
+
+
+File: slib.info, Node: Commutative Rings, Next: Determinant, Prev: Root Finding, Up: Mathematical Packages
+
+Commutative Rings
+=================
+
+ Scheme provides a consistent and capable set of numeric functions.
+Inexacts implement a field; integers a commutative ring (and Euclidean
+domain). This package allows one to use basic Scheme numeric functions
+with symbols and non-numeric elements of commutative rings.
+
+ `(require 'commutative-ring)'
+
+ The "commutative-ring" package makes the procedures `+', `-', `*',
+`/', and `^' "careful" in the sense that any non-numeric arguments they
+do not reduce appear in the expression output. In order to see what
+working with this package is like, self-set all the single letter
+identifiers (to their corresponding symbols).
+
+ (define a 'a)
+ ...
+ (define z 'z)
+
+ Or just `(require 'self-set)'. Now try some sample expressions:
+
+ (+ (+ a b) (- a b)) => (* a 2)
+ (* (+ a b) (+ a b)) => (^ (+ a b) 2)
+ (* (+ a b) (- a b)) => (* (+ a b) (- a b))
+ (* (- a b) (- a b)) => (^ (- a b) 2)
+ (* (- a b) (+ a b)) => (* (+ a b) (- a b))
+ (/ (+ a b) (+ c d)) => (/ (+ a b) (+ c d))
+ (^ (+ a b) 3) => (^ (+ a b) 3)
+ (^ (+ a 2) 3) => (^ (+ 2 a) 3)
+
+ Associative rules have been applied and repeated addition and
+multiplication converted to multiplication and exponentiation.
+
+ We can enable distributive rules, thus expanding to sum of products
+form:
+ (set! *ruleset* (combined-rulesets distribute* distribute/))
+
+ (* (+ a b) (+ a b)) => (+ (* 2 a b) (^ a 2) (^ b 2))
+ (* (+ a b) (- a b)) => (- (^ a 2) (^ b 2))
+ (* (- a b) (- a b)) => (- (+ (^ a 2) (^ b 2)) (* 2 a b))
+ (* (- a b) (+ a b)) => (- (^ a 2) (^ b 2))
+ (/ (+ a b) (+ c d)) => (+ (/ a (+ c d)) (/ b (+ c d)))
+ (/ (+ a b) (- c d)) => (+ (/ a (- c d)) (/ b (- c d)))
+ (/ (- a b) (- c d)) => (- (/ a (- c d)) (/ b (- c d)))
+ (/ (- a b) (+ c d)) => (- (/ a (+ c d)) (/ b (+ c d)))
+ (^ (+ a b) 3) => (+ (* 3 a (^ b 2)) (* 3 b (^ a 2)) (^ a 3) (^ b 3))
+ (^ (+ a 2) 3) => (+ 8 (* a 12) (* (^ a 2) 6) (^ a 3))
+
+ Use of this package is not restricted to simple arithmetic
+expressions:
+
+ (require 'determinant)
+
+ (determinant '((a b c) (d e f) (g h i))) =>
+ (- (+ (* a e i) (* b f g) (* c d h)) (* a f h) (* b d i) (* c e g))
+
+ Currently, only `+', `-', `*', `/', and `^' support non-numeric
+elements. Expressions with `-' are converted to equivalent expressions
+without `-', so behavior for `-' is not defined separately. `/'
+expressions are handled similarly.
+
+ This list might be extended to include `quotient', `modulo',
+`remainder', `lcm', and `gcd'; but these work only for the more
+restrictive Euclidean (Unique Factorization) Domain.
+
+Rules and Rulesets
+==================
+
+ The "commutative-ring" package allows control of ring properties
+through the use of "rulesets".
+
+ - Variable: *ruleset*
+ Contains the set of rules currently in effect. Rules defined by
+ `cring:define-rule' are stored within the value of *ruleset* at the
+ time `cring:define-rule' is called. If *RULESET* is `#f', then no
+ rules apply.
+
+ - Function: make-ruleset RULE1 ...
+ - Function: make-ruleset NAME RULE1 ...
+ Returns a new ruleset containing the rules formed by applying
+ `cring:define-rule' to each 4-element list argument RULE. If the
+ first argument to `make-ruleset' is a symbol, then the database
+ table created for the new ruleset will be named NAME. Calling
+ `make-ruleset' with no rule arguments creates an empty ruleset.
+
+ - Function: combined-rulesets RULESET1 ...
+ - Function: combined-rulesets NAME RULESET1 ...
+ Returns a new ruleset containing the rules contained in each
+ ruleset argument RULESET. If the first argument to
+ `combined-ruleset' is a symbol, then the database table created for
+ the new ruleset will be named NAME. Calling `combined-ruleset'
+ with no ruleset arguments creates an empty ruleset.
+
+ Two rulesets are defined by this package.
+
+ - Constant: distribute*
+ Contain the ruleset to distribute multiplication over addition and
+ subtraction.
+
+ - Constant: distribute/
+ Contain the ruleset to distribute division over addition and
+ subtraction.
+
+ Take care when using both DISTRIBUTE* and DISTRIBUTE/
+ simultaneously. It is possible to put `/' into an infinite loop.
+
+ You can specify how sum and product expressions containing non-numeric
+elements simplify by specifying the rules for `+' or `*' for cases
+where expressions involving objects reduce to numbers or to expressions
+involving different non-numeric elements.
+
+ - Function: cring:define-rule OP SUB-OP1 SUB-OP2 REDUCTION
+ Defines a rule for the case when the operation represented by
+ symbol OP is applied to lists whose `car's are SUB-OP1 and
+ SUB-OP2, respectively. The argument REDUCTION is a procedure
+ accepting 2 arguments which will be lists whose `car's are SUB-OP1
+ and SUB-OP2.
+
+ - Function: cring:define-rule OP SUB-OP1 'IDENTITY REDUCTION
+ Defines a rule for the case when the operation represented by
+ symbol OP is applied to a list whose `car' is SUB-OP1, and some
+ other argument. REDUCTION will be called with the list whose
+ `car' is SUB-OP1 and some other argument.
+
+ If REDUCTION returns `#f', the reduction has failed and other
+ reductions will be tried. If REDUCTION returns a non-false value,
+ that value will replace the two arguments in arithmetic (`+', `-',
+ and `*') calculations involving non-numeric elements.
+
+ The operations `+' and `*' are assumed commutative; hence both
+ orders of arguments to REDUCTION will be tried if necessary.
+
+ The following rule is the definition for distributing `*' over `+'.
+
+ (cring:define-rule
+ '* '+ 'identity
+ (lambda (exp1 exp2)
+ (apply + (map (lambda (trm) (* trm exp2)) (cdr exp1))))))
+
+How to Create a Commutative Ring
+================================
+
+ The first step in creating your commutative ring is to write
+procedures to create elements of the ring. A non-numeric element of
+the ring must be represented as a list whose first element is a symbol
+or string. This first element identifies the type of the object. A
+convenient and clear convention is to make the type-identifying element
+be the same symbol whose top-level value is the procedure to create it.
+
+ (define (n . list1)
+ (cond ((and (= 2 (length list1))
+ (eq? (car list1) (cadr list1)))
+ 0)
+ ((not (term< (first list1) (last1 list1)))
+ (apply n (reverse list1)))
+ (else (cons 'n list1))))
+
+ (define (s x y) (n x y))
+
+ (define (m . list1)
+ (cond ((neq? (first list1) (term_min list1))
+ (apply m (cyclicrotate list1)))
+ ((term< (last1 list1) (cadr list1))
+ (apply m (reverse (cyclicrotate list1))))
+ (else (cons 'm list1))))
+
+ Define a procedure to multiply 2 non-numeric elements of the ring.
+Other multiplicatons are handled automatically. Objects for which rules
+have *not* been defined are not changed.
+
+ (define (n*n ni nj)
+ (let ((list1 (cdr ni)) (list2 (cdr nj)))
+ (cond ((null? (intersection list1 list2)) #f)
+ ((and (eq? (last1 list1) (first list2))
+ (neq? (first list1) (last1 list2)))
+ (apply n (splice list1 list2)))
+ ((and (eq? (first list1) (first list2))
+ (neq? (last1 list1) (last1 list2)))
+ (apply n (splice (reverse list1) list2)))
+ ((and (eq? (last1 list1) (last1 list2))
+ (neq? (first list1) (first list2)))
+ (apply n (splice list1 (reverse list2))))
+ ((and (eq? (last1 list1) (first list2))
+ (eq? (first list1) (last1 list2)))
+ (apply m (cyclicsplice list1 list2)))
+ ((and (eq? (first list1) (first list2))
+ (eq? (last1 list1) (last1 list2)))
+ (apply m (cyclicsplice (reverse list1) list2)))
+ (else #f))))
+
+ Test the procedures to see if they work.
+
+ ;;; where cyclicrotate(list) is cyclic rotation of the list one step
+ ;;; by putting the first element at the end
+ (define (cyclicrotate list1)
+ (append (rest list1) (list (first list1))))
+ ;;; and where term_min(list) is the element of the list which is
+ ;;; first in the term ordering.
+ (define (term_min list1)
+ (car (sort list1 term<)))
+ (define (term< sym1 sym2)
+ (string<? (symbol->string sym1) (symbol->string sym2)))
+ (define first car)
+ (define rest cdr)
+ (define (last1 list1) (car (last-pair list1)))
+ (define (neq? obj1 obj2) (not (eq? obj1 obj2)))
+ ;;; where splice is the concatenation of list1 and list2 except that their
+ ;;; common element is not repeated.
+ (define (splice list1 list2)
+ (cond ((eq? (last1 list1) (first list2))
+ (append list1 (cdr list2)))
+ (else (error 'splice list1 list2))))
+ ;;; where cyclicsplice is the result of leaving off the last element of
+ ;;; splice(list1,list2).
+ (define (cyclicsplice list1 list2)
+ (cond ((and (eq? (last1 list1) (first list2))
+ (eq? (first list1) (last1 list2)))
+ (butlast (splice list1 list2) 1))
+ (else (error 'cyclicsplice list1 list2))))
+
+ (N*N (S a b) (S a b)) => (m a b)
+
+ Then register the rule for multiplying type N objects by type N
+objects.
+
+ (cring:define-rule '* 'N 'N N*N))
+
+ Now we are ready to compute!
+
+ (define (t)
+ (define detM
+ (+ (* (S g b)
+ (+ (* (S f d)
+ (- (* (S a f) (S d g)) (* (S a g) (S d f))))
+ (* (S f f)
+ (- (* (S a g) (S d d)) (* (S a d) (S d g))))
+ (* (S f g)
+ (- (* (S a d) (S d f)) (* (S a f) (S d d))))))
+ (* (S g d)
+ (+ (* (S f b)
+ (- (* (S a g) (S d f)) (* (S a f) (S d g))))
+ (* (S f f)
+ (- (* (S a b) (S d g)) (* (S a g) (S d b))))
+ (* (S f g)
+ (- (* (S a f) (S d b)) (* (S a b) (S d f))))))
+ (* (S g f)
+ (+ (* (S f b)
+ (- (* (S a d) (S d g)) (* (S a g) (S d d))))
+ (* (S f d)
+ (- (* (S a g) (S d b)) (* (S a b) (S d g))))
+ (* (S f g)
+ (- (* (S a b) (S d d)) (* (S a d) (S d b))))))
+ (* (S g g)
+ (+ (* (S f b)
+ (- (* (S a f) (S d d)) (* (S a d) (S d f))))
+ (* (S f d)
+ (- (* (S a b) (S d f)) (* (S a f) (S d b))))
+ (* (S f f)
+ (- (* (S a d) (S d b)) (* (S a b) (S d d))))))))
+ (* (S b e) (S c a) (S e c)
+ detM
+ ))
+ (pretty-print (t))
+ -|
+ (- (+ (m a c e b d f g)
+ (m a c e b d g f)
+ (m a c e b f d g)
+ (m a c e b f g d)
+ (m a c e b g d f)
+ (m a c e b g f d))
+ (* 2 (m a b e c) (m d f g))
+ (* (m a c e b d) (m f g))
+ (* (m a c e b f) (m d g))
+ (* (m a c e b g) (m d f)))
+
+
+File: slib.info, Node: Determinant, Prev: Commutative Rings, Up: Mathematical Packages
+
+Determinant
+===========
+
+ (require 'determinant)
+ (determinant '((1 2) (3 4))) => -2
+ (determinant '((1 2 3) (4 5 6) (7 8 9))) => 0
+ (determinant '((1 2 3 4) (5 6 7 8) (9 10 11 12))) => 0
+
+
+File: slib.info, Node: Database Packages, Next: Other Packages, Prev: Mathematical Packages, Up: Top
+
+Database Packages
+*****************
+
+* Menu:
+
+* Base Table::
+* Relational Database:: 'relational-database
+* Weight-Balanced Trees:: 'wt-tree
+
+
+File: slib.info, Node: Base Table, Next: Relational Database, Prev: Database Packages, Up: Database Packages
+
+Base Table
+==========
+
+ A base table implementation using Scheme association lists is
+available as the value of the identifier `alist-table' after doing:
+
+ `(require 'alist-table)'
+
+ Association list base tables are suitable for small databases and
+support all Scheme types when temporary and readable/writeable Scheme
+types when saved. I hope support for other base table implementations
+will be added in the future.
+
+ This rest of this section documents the interface for a base table
+implementation from which the *Note Relational Database:: package
+constructs a Relational system. It will be of interest primarily to
+those wishing to port or write new base-table implementations.
+
+ All of these functions are accessed through a single procedure by
+calling that procedure with the symbol name of the operation. A
+procedure will be returned if that operation is supported and `#f'
+otherwise. For example:
+
+ (require 'alist-table)
+ (define open-base (alist-table 'make-base))
+ make-base => *a procedure*
+ (define foo (alist-table 'foo))
+ foo => #f
+
+ - Function: make-base FILENAME KEY-DIMENSION COLUMN-TYPES
+ Returns a new, open, low-level database (collection of tables)
+ associated with FILENAME. This returned database has an empty
+ table associated with CATALOG-ID. The positive integer
+ KEY-DIMENSION is the number of keys composed to make a PRIMARY-KEY
+ for the catalog table. The list of symbols COLUMN-TYPES describes
+ the types of each column for that table. If the database cannot
+ be created as specified, `#f' is returned.
+
+ Calling the `close-base' method on this database and possibly other
+ operations will cause FILENAME to be written to. If FILENAME is
+ `#f' a temporary, non-disk based database will be created if such
+ can be supported by the base table implelentation.
+
+ - Function: open-base FILENAME MUTABLE
+ Returns an open low-level database associated with FILENAME. If
+ MUTABLE? is `#t', this database will have methods capable of
+ effecting change to the database. If MUTABLE? is `#f', only
+ methods for inquiring the database will be available. If the
+ database cannot be opened as specified `#f' is returned.
+
+ Calling the `close-base' (and possibly other) method on a MUTABLE?
+ database will cause FILENAME to be written to.
+
+ - Function: write-base LLDB FILENAME
+ Causes the low-level database LLDB to be written to FILENAME. If
+ the write is successful, also causes LLDB to henceforth be
+ associated with FILENAME. Calling the `close-database' (and
+ possibly other) method on LLDB may cause FILENAME to be written
+ to. If FILENAME is `#f' this database will be changed to a
+ temporary, non-disk based database if such can be supported by the
+ underlying base table implelentation. If the operations completed
+ successfully, `#t' is returned. Otherwise, `#f' is returned.
+
+ - Function: sync-base LLDB
+ Causes the file associated with the low-level database LLDB to be
+ updated to reflect its current state. If the associated filename
+ is `#f', no action is taken and `#f' is returned. If this
+ operation completes successfully, `#t' is returned. Otherwise,
+ `#f' is returned.
+
+ - Function: close-base LLDB
+ Causes the low-level database LLDB to be written to its associated
+ file (if any). If the write is successful, subsequent operations
+ to LLDB will signal an error. If the operations complete
+ successfully, `#t' is returned. Otherwise, `#f' is returned.
+
+ - Function: make-table LLDB KEY-DIMENSION COLUMN-TYPES
+ Returns the BASE-ID for a new base table, otherwise returns `#f'.
+ The base table can then be opened using `(open-table LLDB
+ BASE-ID)'. The positive integer KEY-DIMENSION is the number of
+ keys composed to make a PRIMARY-KEY for this table. The list of
+ symbols COLUMN-TYPES describes the types of each column.
+
+ - Constant: catalog-id
+ A constant BASE-ID suitable for passing as a parameter to
+ `open-table'. CATALOG-ID will be used as the base table for the
+ system catalog.
+
+ - Function: open-table LLDB BASE-ID KEY-DIMENSION COLUMN-TYPES
+ Returns a HANDLE for an existing base table in the low-level
+ database LLDB if that table exists and can be opened in the mode
+ indicated by MUTABLE?, otherwise returns `#f'.
+
+ As with `make-table', the positive integer KEY-DIMENSION is the
+ number of keys composed to make a PRIMARY-KEY for this table. The
+ list of symbols COLUMN-TYPES describes the types of each column.
+
+ - Function: kill-table LLDB BASE-ID KEY-DIMENSION COLUMN-TYPES
+ Returns `#t' if the base table associated with BASE-ID was removed
+ from the low level database LLDB, and `#f' otherwise.
+
+ - Function: make-keyifier-1 TYPE
+ Returns a procedure which accepts a single argument which must be
+ of type TYPE. This returned procedure returns an object suitable
+ for being a KEY argument in the functions whose descriptions
+ follow.
+
+ Any 2 arguments of the supported type passed to the returned
+ function which are not `equal?' must result in returned values
+ which are not `equal?'.
+
+ - Function: make-list-keyifier KEY-DIMENSION TYPES
+ The list of symbols TYPES must have at least KEY-DIMENSION
+ elements. Returns a procedure which accepts a list of length
+ KEY-DIMENSION and whose types must corresopond to the types named
+ by TYPES. This returned procedure combines the elements of its
+ list argument into an object suitable for being a KEY argument in
+ the functions whose descriptions follow.
+
+ Any 2 lists of supported types (which must at least include
+ symbols and non-negative integers) passed to the returned function
+ which are not `equal?' must result in returned values which are not
+ `equal?'.
+
+ - Function: make-key-extractor KEY-DIMENSION TYPES COLUMN-NUMBER
+ Returns a procedure which accepts objects produced by application
+ of the result of `(make-list-keyifier KEY-DIMENSION TYPES)'. This
+ procedure returns a KEY which is `equal?' to the COLUMN-NUMBERth
+ element of the list which was passed to create COMBINED-KEY. The
+ list TYPES must have at least KEY-DIMENSION elements.
+
+ - Function: make-key->list KEY-DIMENSION TYPES
+ Returns a procedure which accepts objects produced by application
+ of the result of `(make-list-keyifier KEY-DIMENSION TYPES)'. This
+ procedure returns a list of KEYs which are elementwise `equal?' to
+ the list which was passed to create COMBINED-KEY.
+
+In the following functions, the KEY argument can always be assumed to
+be the value returned by a call to a *keyify* routine.
+
+In contrast, a MATCH-KEY argument is a list of length equal to the
+number of primary keys. The MATCH-KEY restricts the actions of the
+table command to those records whose primary keys all satisfy the
+corresponding element of the MATCH-KEY list. The elements and their
+actions are:
+
+ `#f'
+ The false value matches any key in the corresponding position.
+
+ an object of type procedure
+ This procedure must take a single argument, the key in the
+ corresponding position. Any key for which the procedure
+ returns a non-false value is a match; Any key for which the
+ procedure returns a `#f' is not.
+
+ other values
+ Any other value matches only those keys `equal?' to it.
+
+ - Function: for-each-key HANDLE PROCEDURE MATCH-KEY
+ Calls PROCEDURE once with each KEY in the table opened in HANDLE
+ which satisfies MATCH-KEY in an unspecified order. An unspecified
+ value is returned.
+
+ - Function: map-key HANDLE PROCEDURE MATCH-KEY
+ Returns a list of the values returned by calling PROCEDURE once
+ with each KEY in the table opened in HANDLE which satisfies
+ MATCH-KEY in an unspecified order.
+
+ - Function: ordered-for-each-key HANDLE PROCEDURE MATCH-KEY
+ Calls PROCEDURE once with each KEY in the table opened in HANDLE
+ which satisfies MATCH-KEY in the natural order for the types of
+ the primary key fields of that table. An unspecified value is
+ returned.
+
+ - Function: delete* HANDLE MATCH-KEY
+ Removes all rows which satisfy MATCH-KEY from the table opened in
+ HANDLE. An unspecified value is returned.
+
+ - Function: present? HANDLE KEY
+ Returns a non-`#f' value if there is a row associated with KEY in
+ the table opened in HANDLE and `#f' otherwise.
+
+ - Function: delete HANDLE KEY
+ Removes the row associated with KEY from the table opened in
+ HANDLE. An unspecified value is returned.
+
+ - Function: make-getter KEY-DIMENSION TYPES
+ Returns a procedure which takes arguments HANDLE and KEY. This
+ procedure returns a list of the non-primary values of the relation
+ (in the base table opened in HANDLE) whose primary key is KEY if
+ it exists, and `#f' otherwise.
+
+ - Function: make-putter KEY-DIMENSION TYPES
+ Returns a procedure which takes arguments HANDLE and KEY and
+ VALUE-LIST. This procedure associates the primary key KEY with
+ the values in VALUE-LIST (in the base table opened in HANDLE) and
+ returns an unspecified value.
+
+ - Function: supported-type? SYMBOL
+ Returns `#t' if SYMBOL names a type allowed as a column value by
+ the implementation, and `#f' otherwise. At a minimum, an
+ implementation must support the types `integer', `symbol',
+ `string', `boolean', and `base-id'.
+
+ - Function: supported-key-type? SYMBOL
+ Returns `#t' if SYMBOL names a type allowed as a key value by the
+ implementation, and `#f' otherwise. At a minimum, an
+ implementation must support the types `integer', and `symbol'.
+
+`integer'
+ Scheme exact integer.
+
+`symbol'
+ Scheme symbol.
+
+`boolean'
+ `#t' or `#f'.
+
+`base-id'
+ Objects suitable for passing as the BASE-ID parameter to
+ `open-table'. The value of CATALOG-ID must be an acceptable
+ `base-id'.
+
+
+File: slib.info, Node: Relational Database, Next: Weight-Balanced Trees, Prev: Base Table, Up: Database Packages
+
+Relational Database
+===================
+
+ `(require 'relational-database)'
+
+ This package implements a database system inspired by the Relational
+Model (`E. F. Codd, A Relational Model of Data for Large Shared Data
+Banks'). An SLIB relational database implementation can be created
+from any *Note Base Table:: implementation.
+
+* Menu:
+
+* Motivations:: Database Manifesto
+* Creating and Opening Relational Databases::
+* Relational Database Operations::
+* Table Operations::
+* Catalog Representation::
+* Unresolved Issues::
+* Database Utilities:: 'database-utilities
+* Database Reports::
+* Database Browser:: 'database-browse
+
+
+File: slib.info, Node: Motivations, Next: Creating and Opening Relational Databases, Prev: Relational Database, Up: Relational Database
+
+Motivations
+-----------
+
+ Most nontrivial programs contain databases: Makefiles, configure
+scripts, file backup, calendars, editors, source revision control, CAD
+systems, display managers, menu GUIs, games, parsers, debuggers,
+profilers, and even error reporting are all rife with databases. Coding
+databases is such a common activity in programming that many may not be
+aware of how often they do it.
+
+ A database often starts as a dispatch in a program. The author,
+perhaps because of the need to make the dispatch configurable, the need
+for correlating dispatch in other routines, or because of changes or
+growth, devises a data structure to contain the information, a routine
+for interpreting that data structure, and perhaps routines for
+augmenting and modifying the stored data. The dispatch must be
+converted into this form and tested.
+
+ The programmer may need to devise an interactive program for enabling
+easy examination and modification of the information contained in this
+database. Often, in an attempt to foster modularity and avoid delays in
+release, intermediate file formats for the database information are
+devised. It often turns out that users prefer modifying these
+intermediate files with a text editor to using the interactive program
+in order to do operations (such as global changes) not forseen by the
+program's author.
+
+ In order to address this need, the conscientious software engineer may
+even provide a scripting language to allow users to make repetitive
+database changes. Users will grumble that they need to read a large
+manual and learn yet another programming language (even if it *almost*
+has language "xyz" syntax) in order to do simple configuration.
+
+ All of these facilities need to be designed, coded, debugged,
+documented, and supported; often causing what was very simple in concept
+to become a major developement project.
+
+ This view of databases just outlined is somewhat the reverse of the
+view of the originators of the "Relational Model" of database
+abstraction. The relational model was devised to unify and allow
+interoperation of large multi-user databases running on diverse
+platforms. A fairly general purpose "Comprehensive Language" for
+database manipulations is mandated (but not specified) as part of the
+relational model for databases.
+
+ One aspect of the Relational Model of some importance is that the
+"Comprehensive Language" must be expressible in some form which can be
+stored in the database. This frees the programmer from having to make
+programs data-driven in order to use a database.
+
+ This package includes as one of its basic supported types Scheme
+"expression"s. This type allows expressions as defined by the Scheme
+standards to be stored in the database. Using `slib:eval' retrieved
+expressions can be evaluated (in the top-level environment). Scheme's
+`lambda' facilitates closure of environments, modularity, etc. so that
+procedures (which could not be stored directly most databases) can
+still be effectively retrieved. Since `slib:eval' evaluates
+expressions in the top-level environment, built-in and user defined
+procedures can be easily accessed by name.
+
+ This package's purpose is to standardize (through a common interface)
+database creation and usage in Scheme programs. The relational model's
+provision for inclusion of language expressions as data as well as the
+description (in tables, of course) of all of its tables assures that
+relational databases are powerful enough to assume the roles currently
+played by thousands of ad-hoc routines and data formats.
+
+Such standardization to a relational-like model brings many benefits:
+
+ * Tables, fields, domains, and types can be dealt with by name in
+ programs.
+
+ * The underlying database implementation can be changed (for
+ performance or other reasons) by changing a single line of code.
+
+ * The formats of tables can be easily extended or changed without
+ altering code.
+
+ * Consistency checks are specified as part of the table descriptions.
+ Changes in checks need only occur in one place.
+
+ * All the configuration information which the developer wishes to
+ group together is easily grouped, without needing to change
+ programs aware of only some of these tables.
+
+ * Generalized report generators, interactive entry programs, and
+ other database utilities can be part of a shared library. The
+ burden of adding configurability to a program is greatly reduced.
+
+ * Scheme is the "comprehensive language" for these databases.
+ Scripting for configuration no longer needs to be in a separate
+ language with additional documentation.
+
+ * Scheme's latent types mesh well with the strict typing and logical
+ requirements of the relational model.
+
+ * Portable formats allow easy interchange of data. The included
+ table descriptions help prevent misinterpretation of format.
+
+
+File: slib.info, Node: Creating and Opening Relational Databases, Next: Relational Database Operations, Prev: Motivations, Up: Relational Database
+
+Creating and Opening Relational Databases
+-----------------------------------------
+
+ - Function: make-relational-system BASE-TABLE-IMPLEMENTATION
+ Returns a procedure implementing a relational database using the
+ BASE-TABLE-IMPLEMENTATION.
+
+ All of the operations of a base table implementation are accessed
+ through a procedure defined by `require'ing that implementation.
+ Similarly, all of the operations of the relational database
+ implementation are accessed through the procedure returned by
+ `make-relational-system'. For instance, a new relational database
+ could be created from the procedure returned by
+ `make-relational-system' by:
+
+ (require 'alist-table)
+ (define relational-alist-system
+ (make-relational-system alist-table))
+ (define create-alist-database
+ (relational-alist-system 'create-database))
+ (define my-database
+ (create-alist-database "mydata.db"))
+
+What follows are the descriptions of the methods available from
+relational system returned by a call to `make-relational-system'.
+
+ - Function: create-database FILENAME
+ Returns an open, nearly empty relational database associated with
+ FILENAME. The only tables defined are the system catalog and
+ domain table. Calling the `close-database' method on this database
+ and possibly other operations will cause FILENAME to be written
+ to. If FILENAME is `#f' a temporary, non-disk based database will
+ be created if such can be supported by the underlying base table
+ implelentation. If the database cannot be created as specified
+ `#f' is returned. For the fields and layout of descriptor tables,
+ *Note Catalog Representation::
+
+ - Function: open-database FILENAME MUTABLE?
+ Returns an open relational database associated with FILENAME. If
+ MUTABLE? is `#t', this database will have methods capable of
+ effecting change to the database. If MUTABLE? is `#f', only
+ methods for inquiring the database will be available. Calling the
+ `close-database' (and possibly other) method on a MUTABLE?
+ database will cause FILENAME to be written to. If the database
+ cannot be opened as specified `#f' is returned.
+
+
+File: slib.info, Node: Relational Database Operations, Next: Table Operations, Prev: Creating and Opening Relational Databases, Up: Relational Database
+
+Relational Database Operations
+------------------------------
+
+These are the descriptions of the methods available from an open
+relational database. A method is retrieved from a database by calling
+the database with the symbol name of the operation. For example:
+
+ (define my-database
+ (create-alist-database "mydata.db"))
+ (define telephone-table-desc
+ ((my-database 'create-table) 'telephone-table-desc))
+
+ - Function: close-database
+ Causes the relational database to be written to its associated
+ file (if any). If the write is successful, subsequent operations
+ to this database will signal an error. If the operations completed
+ successfully, `#t' is returned. Otherwise, `#f' is returned.
+
+ - Function: write-database FILENAME
+ Causes the relational database to be written to FILENAME. If the
+ write is successful, also causes the database to henceforth be
+ associated with FILENAME. Calling the `close-database' (and
+ possibly other) method on this database will cause FILENAME to be
+ written to. If FILENAME is `#f' this database will be changed to
+ a temporary, non-disk based database if such can be supported by
+ the underlying base table implelentation. If the operations
+ completed successfully, `#t' is returned. Otherwise, `#f' is
+ returned.
+
+ - Function: table-exists? TABLE-NAME
+ Returns `#t' if TABLE-NAME exists in the system catalog, otherwise
+ returns `#f'.
+
+ - Function: open-table TABLE-NAME MUTABLE?
+ Returns a "methods" procedure for an existing relational table in
+ this database if it exists and can be opened in the mode indicated
+ by MUTABLE?, otherwise returns `#f'.
+
+These methods will be present only in databases which are MUTABLE?.
+
+ - Function: delete-table TABLE-NAME
+ Removes and returns the TABLE-NAME row from the system catalog if
+ the table or view associated with TABLE-NAME gets removed from the
+ database, and `#f' otherwise.
+
+ - Function: create-table TABLE-DESC-NAME
+ Returns a methods procedure for a new (open) relational table for
+ describing the columns of a new base table in this database,
+ otherwise returns `#f'. For the fields and layout of descriptor
+ tables, *Note Catalog Representation::.
+
+ - Function: create-table TABLE-NAME TABLE-DESC-NAME
+ Returns a methods procedure for a new (open) relational table with
+ columns as described by TABLE-DESC-NAME, otherwise returns `#f'.
+
+ - Function: create-view ??
+ - Function: project-table ??
+ - Function: restrict-table ??
+ - Function: cart-prod-tables ??
+ Not yet implemented.
+
+
+File: slib.info, Node: Table Operations, Next: Catalog Representation, Prev: Relational Database Operations, Up: Relational Database
+
+Table Operations
+----------------
+
+These are the descriptions of the methods available from an open
+relational table. A method is retrieved from a table by calling the
+table with the symbol name of the operation. For example:
+
+ (define telephone-table-desc
+ ((my-database 'create-table) 'telephone-table-desc))
+ (require 'common-list-functions)
+ (define ndrp (telephone-table-desc 'row:insert))
+ (ndrp '(1 #t name #f string))
+ (ndrp '(2 #f telephone
+ (lambda (d)
+ (and (string? d) (> (string-length d) 2)
+ (every
+ (lambda (c)
+ (memv c '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9
+ #\+ #\( #\ #\) #\-)))
+ (string->list d))))
+ string))
+
+Some operations described below require primary key arguments. Primary
+keys arguments are denoted KEY1 KEY2 .... It is an error to call an
+operation for a table which takes primary key arguments with the wrong
+number of primary keys for that table.
+
+The term "row" used below refers to a Scheme list of values (one for
+each column) in the order specified in the descriptor (table) for this
+table. Missing values appear as `#f'. Primary keys must not be
+missing.
+
+ - Function: get COLUMN-NAME
+ Returns a procedure of arguments KEY1 KEY2 ... which returns the
+ value for the COLUMN-NAME column of the row associated with
+ primary keys KEY1, KEY2 ... if that row exists in the table, or
+ `#f' otherwise.
+
+ ((plat 'get 'processor) 'djgpp) => i386
+ ((plat 'get 'processor) 'be-os) => #f
+
+ - Function: get* COLUMN-NAME
+ Returns a procedure of optional arguments MATCH-KEY1 ... which
+ returns a list of the values for the specified column for all rows
+ in this table. The optional MATCH-KEY1 ... arguments restrict
+ actions to a subset of the table. See the match-key description
+ below for details.
+
+ ((plat 'get* 'processor)) =>
+ (i386 8086 i386 8086 i386 i386 8086 m68000
+ m68000 m68000 m68000 m68000 powerpc)
+
+ ((plat 'get* 'processor) #f) =>
+ (i386 8086 i386 8086 i386 i386 8086 m68000
+ m68000 m68000 m68000 m68000 powerpc)
+
+ (define (a-key? key)
+ (char=? #\a (string-ref (symbol->string key) 0)))
+
+ ((plat 'get* 'processor) a-key?) =>
+ (m68000 m68000 m68000 m68000 m68000 powerpc)
+
+ ((plat 'get* 'name) a-key?) =>
+ (atari-st-turbo-c atari-st-gcc amiga-sas/c-5.10
+ amiga-aztec amiga-dice-c aix)
+
+ - Function: row:retrieve
+ Returns a procedure of arguments KEY1 KEY2 ... which returns the
+ row associated with primary keys KEY1, KEY2 ... if it exists, or
+ `#f' otherwise.
+
+ ((plat 'row:retrieve) 'linux) => (linux i386 linux gcc)
+ ((plat 'row:retrieve) 'multics) => #f
+
+ - Function: row:retrieve*
+ Returns a procedure of optional arguments MATCH-KEY1 ... which
+ returns a list of all rows in this table. The optional MATCH-KEY1
+ ... arguments restrict actions to a subset of the table. See the
+ match-key description below for details.
+
+ ((plat 'row:retrieve*) a-key?) =>
+ ((atari-st-turbo-c m68000 atari turbo-c)
+ (atari-st-gcc m68000 atari gcc)
+ (amiga-sas/c-5.10 m68000 amiga sas/c)
+ (amiga-aztec m68000 amiga aztec)
+ (amiga-dice-c m68000 amiga dice-c)
+ (aix powerpc aix -))
+
+ - Function: row:remove
+ Returns a procedure of arguments KEY1 KEY2 ... which removes and
+ returns the row associated with primary keys KEY1, KEY2 ... if it
+ exists, or `#f' otherwise.
+
+ - Function: row:remove*
+ Returns a procedure of optional arguments MATCH-KEY1 ... which
+ removes and returns a list of all rows in this table. The optional
+ MATCH-KEY1 ... arguments restrict actions to a subset of the
+ table. See the match-key description below for details.
+
+ - Function: row:delete
+ Returns a procedure of arguments KEY1 KEY2 ... which deletes the
+ row associated with primary keys KEY1, KEY2 ... if it exists. The
+ value returned is unspecified.
+
+ - Function: row:delete*
+ Returns a procedure of optional arguments MATCH-KEY1 ... which
+ Deletes all rows from this table. The optional MATCH-KEY1 ...
+ arguments restrict deletions to a subset of the table. See the
+ match-key description below for details. The value returned is
+ unspecified. The descriptor table and catalog entry for this
+ table are not affected.
+
+ - Function: row:update
+ Returns a procedure of one argument, ROW, which adds the row, ROW,
+ to this table. If a row for the primary key(s) specified by ROW
+ already exists in this table, it will be overwritten. The value
+ returned is unspecified.
+
+ - Function: row:update*
+ Returns a procedure of one argument, ROWS, which adds each row in
+ the list of rows, ROWS, to this table. If a row for the primary
+ key specified by an element of ROWS already exists in this table,
+ it will be overwritten. The value returned is unspecified.
+
+ - Function: row:insert
+ Adds the row ROW to this table. If a row for the primary key(s)
+ specified by ROW already exists in this table an error is
+ signaled. The value returned is unspecified.
+
+ - Function: row:insert*
+ Returns a procedure of one argument, ROWS, which adds each row in
+ the list of rows, ROWS, to this table. If a row for the primary
+ key specified by an element of ROWS already exists in this table,
+ an error is signaled. The value returned is unspecified.
+
+ - Function: for-each-row
+ Returns a procedure of arguments PROC MATCH-KEY1 ... which calls
+ PROC with each ROW in this table in the (implementation-dependent)
+ natural ordering for rows. The optional MATCH-KEY1 ... arguments
+ restrict actions to a subset of the table. See the match-key
+ description below for details.
+
+ *Real* relational programmers would use some least-upper-bound join
+ for every row to get them in order; But we don't have joins yet.
+
+The (optional) MATCH-KEY1 ... arguments are used to restrict actions of
+a whole-table operation to a subset of that table. Those procedures
+(returned by methods) which accept match-key arguments will accept any
+number of match-key arguments between zero and the number of primary
+keys in the table. Any unspecified MATCH-KEY arguments default to `#f'.
+
+The MATCH-KEY1 ... restrict the actions of the table command to those
+records whose primary keys each satisfy the corresponding MATCH-KEY
+argument. The arguments and their actions are:
+
+ `#f'
+ The false value matches any key in the corresponding position.
+
+ an object of type procedure
+ This procedure must take a single argument, the key in the
+ corresponding position. Any key for which the procedure
+ returns a non-false value is a match; Any key for which the
+ procedure returns a `#f' is not.
+
+ other values
+ Any other value matches only those keys `equal?' to it.
+
+ - Function: close-table
+ Subsequent operations to this table will signal an error.
+
+ - Constant: column-names
+ - Constant: column-foreigns
+ - Constant: column-domains
+ - Constant: column-types
+ Return a list of the column names, foreign-key table names, domain
+ names, or type names respectively for this table. These 4 methods
+ are different from the others in that the list is returned, rather
+ than a procedure to obtain the list.
+
+ - Constant: primary-limit
+ Returns the number of primary keys fields in the relations in this
+ table.
+
+
+File: slib.info, Node: Catalog Representation, Next: Unresolved Issues, Prev: Table Operations, Up: Relational Database
+
+Catalog Representation
+----------------------
+
+Each database (in an implementation) has a "system catalog" which
+describes all the user accessible tables in that database (including
+itself).
+
+The system catalog base table has the following fields. `PRI'
+indicates a primary key for that table.
+
+ PRI table-name
+ column-limit the highest column number
+ coltab-name descriptor table name
+ bastab-id data base table identifier
+ user-integrity-rule
+ view-procedure A scheme thunk which, when called,
+ produces a handle for the view. coltab
+ and bastab are specified if and only if
+ view-procedure is not.
+
+Descriptors for base tables (not views) are tables (pointed to by
+system catalog). Descriptor (base) tables have the fields:
+
+ PRI column-number sequential integers from 1
+ primary-key? boolean TRUE for primary key components
+ column-name
+ column-integrity-rule
+ domain-name
+
+A "primary key" is any column marked as `primary-key?' in the
+corresponding descriptor table. All the `primary-key?' columns must
+have lower column numbers than any non-`primary-key?' columns. Every
+table must have at least one primary key. Primary keys must be
+sufficient to distinguish all rows from each other in the table. All of
+the system defined tables have a single primary key.
+
+This package currently supports tables having from 1 to 4 primary keys
+if there are non-primary columns, and any (natural) number if *all*
+columns are primary keys. If you need more than 4 primary keys, I would
+like to hear what you are doing!
+
+A "domain" is a category describing the allowable values to occur in a
+column. It is described by a (base) table with the fields:
+
+ PRI domain-name
+ foreign-table
+ domain-integrity-rule
+ type-id
+ type-param
+
+The "type-id" field value is a symbol. This symbol may be used by the
+underlying base table implementation in storing that field.
+
+If the `foreign-table' field is non-`#f' then that field names a table
+from the catalog. The values for that domain must match a primary key
+of the table referenced by the TYPE-PARAM (or `#f', if allowed). This
+package currently does not support composite foreign-keys.
+
+The types for which support is planned are:
+ atom
+ symbol
+ string [<length>]
+ number [<base>]
+ money <currency>
+ date-time
+ boolean
+
+ foreign-key <table-name>
+ expression
+ virtual <expression>
+
+
+File: slib.info, Node: Unresolved Issues, Next: Database Utilities, Prev: Catalog Representation, Up: Relational Database
+
+Unresolved Issues
+-----------------
+
+ Although `rdms.scm' is not large, I found it very difficult to write
+(six rewrites). I am not aware of any other examples of a generalized
+relational system (although there is little new in CS). I left out
+several aspects of the Relational model in order to simplify the job.
+The major features lacking (which might be addressed portably) are
+views, transaction boundaries, and protection.
+
+ Protection needs a model for specifying priveledges. Given how
+operations are accessed from handles it should not be difficult to
+restrict table accesses to those allowed for that user.
+
+ The system catalog has a field called `view-procedure'. This should
+allow a purely functional implementation of views. This will work but
+is unsatisfying for views resulting from a "select"ion (subset of
+rows); for whole table operations it will not be possible to reduce the
+number of keys scanned over when the selection is specified only by an
+opaque procedure.
+
+ Transaction boundaries present the most intriguing area. Transaction
+boundaries are actually a feature of the "Comprehensive Language" of the
+Relational database and not of the database. Scheme would seem to
+provide the opportunity for an extremely clean semantics for transaction
+boundaries since the builtin procedures with side effects are small in
+number and easily identified.
+
+ These side-effect builtin procedures might all be portably redefined
+to versions which properly handled transactions. Compiled library
+routines would need to be recompiled as well. Many system extensions
+(delete-file, system, etc.) would also need to be redefined.
+
+There are 2 scope issues that must be resolved for multiprocess
+transaction boundaries:
+
+Process scope
+ The actions captured by a transaction should be only for the
+ process which invoked the start of transaction. Although standard
+ Scheme does not provide process primitives as such, `dynamic-wind'
+ would provide a workable hook into process switching for many
+ implementations.
+
+Shared utilities with state
+ Some shared utilities have state which should *not* be part of a
+ transaction. An example would be calling a pseudo-random number
+ generator. If the success of a transaction depended on the
+ pseudo-random number and failed, the state of the generator would
+ be set back. Subsequent calls would keep returning the same
+ number and keep failing.
+
+ Pseudo-random number generators are not reentrant; thus they would
+ require locks in order to operate properly in a multiprocess
+ environment. Are all examples of utilities whose state should not
+ be part of transactions also non-reentrant? If so, perhaps
+ suspending transaction capture for the duration of locks would
+ solve this problem.
+
+
+File: slib.info, Node: Database Utilities, Next: Database Reports, Prev: Unresolved Issues, Up: Relational Database
+
+Database Utilities
+------------------
+
+ `(require 'database-utilities)'
+
+This enhancement wraps a utility layer on `relational-database' which
+provides:
+ * Automatic loading of the appropriate base-table package when
+ opening a database.
+
+ * Automatic execution of initialization commands stored in database.
+
+ * Transparent execution of database commands stored in `*commands*'
+ table in database.
+
+Also included are utilities which provide:
+ * Data definition from Scheme lists and
+
+ * Report generation
+
+for any SLIB relational database.
+
+ - Function: create-database FILENAME BASE-TABLE-TYPE
+ Returns an open, nearly empty enhanced (with `*commands*' table)
+ relational database (with base-table type BASE-TABLE-TYPE)
+ associated with FILENAME.
+
+ - Function: open-database FILENAME
+ - Function: open-database FILENAME BASE-TABLE-TYPE
+ Returns an open enchanced relational database associated with
+ FILENAME. The database will be opened with base-table type
+ BASE-TABLE-TYPE) if supplied. If BASE-TABLE-TYPE is not supplied,
+ `open-database' will attempt to deduce the correct
+ base-table-type. If the database can not be opened or if it lacks
+ the `*commands*' table, `#f' is returned.
+
+ - Function: open-database! FILENAME
+ - Function: open-database! FILENAME BASE-TABLE-TYPE
+ Returns *mutable* open enchanced relational database ...
+
+The table `*commands*' in an "enhanced" relational-database has the
+fields (with domains):
+ PRI name symbol
+ parameters parameter-list
+ procedure expression
+ documentation string
+
+ The `parameters' field is a foreign key (domain `parameter-list') of
+the `*catalog-data*' table and should have the value of a table
+described by `*parameter-columns*'. This `parameter-list' table
+describes the arguments suitable for passing to the associated command.
+The intent of this table is to be of a form such that different
+user-interfaces (for instance, pull-down menus or plain-text queries)
+can operate from the same table. A `parameter-list' table has the
+following fields:
+ PRI index uint
+ name symbol
+ arity parameter-arity
+ domain domain
+ defaulter expression
+ expander expression
+ documentation string
+
+ The `arity' field can take the values:
+
+`single'
+ Requires a single parameter of the specified domain.
+
+`optional'
+ A single parameter of the specified domain or zero parameters is
+ acceptable.
+
+`boolean'
+ A single boolean parameter or zero parameters (in which case `#f'
+ is substituted) is acceptable.
+
+`nary'
+ Any number of parameters of the specified domain are acceptable.
+ The argument passed to the command function is always a list of the
+ parameters.
+
+`nary1'
+ One or more of parameters of the specified domain are acceptable.
+ The argument passed to the command function is always a list of the
+ parameters.
+
+ The `domain' field specifies the domain which a parameter or
+parameters in the `index'th field must satisfy.
+
+ The `defaulter' field is an expression whose value is either `#f' or
+a procedure of one argument (the parameter-list) which returns a *list*
+of the default value or values as appropriate. Note that since the
+`defaulter' procedure is called every time a default parameter is
+needed for this column, "sticky" defaults can be implemented using
+shared state with the domain-integrity-rule.
+
+Invoking Commands
+.................
+
+ When an enhanced relational-database is called with a symbol which
+matches a NAME in the `*commands*' table, the associated procedure
+expression is evaluated and applied to the enhanced
+relational-database. A procedure should then be returned which the user
+can invoke on (optional) arguments.
+
+ The command `*initialize*' is special. If present in the
+`*commands*' table, `open-database' or `open-database!' will return
+the value of the `*initialize*' command. Notice that arbitrary code
+can be run when the `*initialize*' procedure is automatically applied
+to the enhanced relational-database.
+
+ Note also that if you wish to shadow or hide from the user
+relational-database methods described in *Note Relational Database
+Operations::, this can be done by a dispatch in the closure returned by
+the `*initialize*' expression rather than by entries in the
+`*commands*' table if it is desired that the underlying methods remain
+accessible to code in the `*commands*' table.
+
+ - Function: make-command-server RDB TABLE-NAME
+ Returns a procedure of 2 arguments, a (symbol) command and a
+ call-back procedure. When this returned procedure is called, it
+ looks up COMMAND in table TABLE-NAME and calls the call-back
+ procedure with arguments:
+ COMMAND
+ The COMMAND
+
+ COMMAND-VALUE
+ The result of evaluating the expression in the PROCEDURE
+ field of TABLE-NAME and calling it with RDB.
+
+ PARAMETER-NAME
+ A list of the "official" name of each parameter. Corresponds
+ to the `name' field of the COMMAND's parameter-table.
+
+ POSITIONS
+ A list of the positive integer index of each parameter.
+ Corresponds to the `index' field of the COMMAND's
+ parameter-table.
+
+ ARITIES
+ A list of the arities of each parameter. Corresponds to the
+ `arity' field of the COMMAND's parameter-table. For a
+ description of `arity' see table above.
+
+ TYPES
+ A list of the type name of each parameter. Correspnds to the
+ `type-id' field of the contents of the `domain' of the
+ COMMAND's parameter-table.
+
+ DEFAULTERS
+ A list of the defaulters for each parameter. Corresponds to
+ the `defaulters' field of the COMMAND's parameter-table.
+
+ DOMAIN-INTEGRITY-RULES
+ A list of procedures (one for each parameter) which tests
+ whether a value for a parameter is acceptable for that
+ parameter. The procedure should be called with each datum in
+ the list for `nary' arity parameters.
+
+ ALIASES
+ A list of lists of `(alias parameter-name)'. There can be
+ more than one alias per PARAMETER-NAME.
+
+ For information about parameters, *Note Parameter lists::. Here is an
+example of setting up a command with arguments and parsing those
+arguments from a `getopt' style argument list (*note Getopt::.).
+
+ (require 'database-utilities)
+ (require 'fluid-let)
+ (require 'parameters)
+ (require 'getopt)
+
+ (define my-rdb (create-database #f 'alist-table))
+
+ (define-tables my-rdb
+ '(foo-params
+ *parameter-columns*
+ *parameter-columns*
+ ((1 single-string single string
+ (lambda (pl) '("str")) #f "single string")
+ (2 nary-symbols nary symbol
+ (lambda (pl) '()) #f "zero or more symbols")
+ (3 nary1-symbols nary1 symbol
+ (lambda (pl) '(symb)) #f "one or more symbols")
+ (4 optional-number optional uint
+ (lambda (pl) '()) #f "zero or one number")
+ (5 flag boolean boolean
+ (lambda (pl) '(#f)) #f "a boolean flag")))
+ '(foo-pnames
+ ((name string))
+ ((parameter-index uint))
+ (("s" 1)
+ ("single-string" 1)
+ ("n" 2)
+ ("nary-symbols" 2)
+ ("N" 3)
+ ("nary1-symbols" 3)
+ ("o" 4)
+ ("optional-number" 4)
+ ("f" 5)
+ ("flag" 5)))
+ '(my-commands
+ ((name symbol))
+ ((parameters parameter-list)
+ (parameter-names parameter-name-translation)
+ (procedure expression)
+ (documentation string))
+ ((foo
+ foo-params
+ foo-pnames
+ (lambda (rdb) (lambda args (print args)))
+ "test command arguments"))))
+
+ (define (dbutil:serve-command-line rdb command-table
+ command argc argv)
+ (set! argv (if (vector? argv) (vector->list argv) argv))
+ ((make-command-server rdb command-table)
+ command
+ (lambda (comname comval options positions
+ arities types defaulters dirs aliases)
+ (apply comval (getopt->arglist
+ argc argv options positions
+ arities types defaulters dirs aliases)))))
+
+ (define (cmd . opts)
+ (fluid-let ((*optind* 1))
+ (printf "%-34s => "
+ (call-with-output-string
+ (lambda (pt) (write (cons 'cmd opts) pt))))
+ (set! opts (cons "cmd" opts))
+ (force-output)
+ (dbutil:serve-command-line
+ my-rdb 'my-commands 'foo (length opts) opts)))
+
+ (cmd) => ("str" () (symb) () #f)
+ (cmd "-f") => ("str" () (symb) () #t)
+ (cmd "--flag") => ("str" () (symb) () #t)
+ (cmd "-o177") => ("str" () (symb) (177) #f)
+ (cmd "-o" "177") => ("str" () (symb) (177) #f)
+ (cmd "--optional" "621") => ("str" () (symb) (621) #f)
+ (cmd "--optional=621") => ("str" () (symb) (621) #f)
+ (cmd "-s" "speciality") => ("speciality" () (symb) () #f)
+ (cmd "-sspeciality") => ("speciality" () (symb) () #f)
+ (cmd "--single" "serendipity") => ("serendipity" () (symb) () #f)
+ (cmd "--single=serendipity") => ("serendipity" () (symb) () #f)
+ (cmd "-n" "gravity" "piety") => ("str" () (piety gravity) () #f)
+ (cmd "-ngravity" "piety") => ("str" () (piety gravity) () #f)
+ (cmd "--nary" "chastity") => ("str" () (chastity) () #f)
+ (cmd "--nary=chastity" "") => ("str" () ( chastity) () #f)
+ (cmd "-N" "calamity") => ("str" () (calamity) () #f)
+ (cmd "-Ncalamity") => ("str" () (calamity) () #f)
+ (cmd "--nary1" "surety") => ("str" () (surety) () #f)
+ (cmd "--nary1=surety") => ("str" () (surety) () #f)
+ (cmd "-N" "levity" "fealty") => ("str" () (fealty levity) () #f)
+ (cmd "-Nlevity" "fealty") => ("str" () (fealty levity) () #f)
+ (cmd "--nary1" "surety" "brevity") => ("str" () (brevity surety) () #f)
+ (cmd "--nary1=surety" "brevity") => ("str" () (brevity surety) () #f)
+ (cmd "-?")
+ -|
+ Usage: cmd [OPTION ARGUMENT ...] ...
+
+ -f, --flag
+ -o, --optional[=]<number>
+ -n, --nary[=]<symbols> ...
+ -N, --nary1[=]<symbols> ...
+ -s, --single[=]<string>
+
+ ERROR: getopt->parameter-list "unrecognized option" "-?"
+
+ Some commands are defined in all extended relational-databases. The
+are called just like *Note Relational Database Operations::.
+
+ - Function: add-domain DOMAIN-ROW
+ Adds DOMAIN-ROW to the "domains" table if there is no row in the
+ domains table associated with key `(car DOMAIN-ROW)' and returns
+ `#t'. Otherwise returns `#f'.
+
+ For the fields and layout of the domain table, *Note Catalog
+ Representation::. Currently, these fields are
+ * domain-name
+
+ * foreign-table
+
+ * domain-integrity-rule
+
+ * type-id
+
+ * type-param
+
+ The following example adds 3 domains to the `build' database.
+ `Optstring' is either a string or `#f'. `filename' is a string
+ and `build-whats' is a symbol.
+
+ (for-each (build 'add-domain)
+ '((optstring #f
+ (lambda (x) (or (not x) (string? x)))
+ string
+ #f)
+ (filename #f #f string #f)
+ (build-whats #f #f symbol #f)))
+
+ - Function: delete-domain DOMAIN-NAME
+ Removes and returns the DOMAIN-NAME row from the "domains" table.
+
+ - Function: domain-checker DOMAIN
+ Returns a procedure to check an argument for conformance to domain
+ DOMAIN.
+
+Defining Tables
+...............
+
+ - Procedure: define-tables RDB SPEC-0 ...
+ Adds tables as specified in SPEC-0 ... to the open
+ relational-database RDB. Each SPEC has the form:
+
+ (<name> <descriptor-name> <descriptor-name> <rows>)
+ or
+ (<name> <primary-key-fields> <other-fields> <rows>)
+
+ where <name> is the table name, <descriptor-name> is the symbol
+ name of a descriptor table, <primary-key-fields> and
+ <other-fields> describe the primary keys and other fields
+ respectively, and <rows> is a list of data rows to be added to the
+ table.
+
+ <primary-key-fields> and <other-fields> are lists of field
+ descriptors of the form:
+
+ (<column-name> <domain>)
+ or
+ (<column-name> <domain> <column-integrity-rule>)
+
+ where <column-name> is the column name, <domain> is the domain of
+ the column, and <column-integrity-rule> is an expression whose
+ value is a procedure of one argument (which returns `#f' to signal
+ an error).
+
+ If <domain> is not a defined domain name and it matches the name of
+ this table or an already defined (in one of SPEC-0 ...) single key
+ field table, a foriegn-key domain will be created for it.
+
+The following example shows a new database with the name of `foo.db'
+being created with tables describing processor families and
+processor/os/compiler combinations.
+
+The database command `define-tables' is defined to call `define-tables'
+with its arguments. The database is also configured to print `Welcome'
+when the database is opened. The database is then closed and reopened.
+
+ (require 'database-utilities)
+ (define my-rdb (create-database "foo.db" 'alist-table))
+
+ (define-tables my-rdb
+ '(*commands*
+ ((name symbol))
+ ((parameters parameter-list)
+ (procedure expression)
+ (documentation string))
+ ((define-tables
+ no-parameters
+ no-parameter-names
+ (lambda (rdb) (lambda specs (apply define-tables rdb specs)))
+ "Create or Augment tables from list of specs")
+ (*initialize*
+ no-parameters
+ no-parameter-names
+ (lambda (rdb) (display "Welcome") (newline) rdb)
+ "Print Welcome"))))
+
+ ((my-rdb 'define-tables)
+ '(processor-family
+ ((family atom))
+ ((also-ran processor-family))
+ ((m68000 #f)
+ (m68030 m68000)
+ (i386 8086)
+ (8086 #f)
+ (powerpc #f)))
+
+ '(platform
+ ((name symbol))
+ ((processor processor-family)
+ (os symbol)
+ (compiler symbol))
+ ((aix powerpc aix -)
+ (amiga-dice-c m68000 amiga dice-c)
+ (amiga-aztec m68000 amiga aztec)
+ (amiga-sas/c-5.10 m68000 amiga sas/c)
+ (atari-st-gcc m68000 atari gcc)
+ (atari-st-turbo-c m68000 atari turbo-c)
+ (borland-c-3.1 8086 ms-dos borland-c)
+ (djgpp i386 ms-dos gcc)
+ (linux i386 linux gcc)
+ (microsoft-c 8086 ms-dos microsoft-c)
+ (os/2-emx i386 os/2 gcc)
+ (turbo-c-2 8086 ms-dos turbo-c)
+ (watcom-9.0 i386 ms-dos watcom))))
+
+ ((my-rdb 'close-database))
+
+ (set! my-rdb (open-database "foo.db" 'alist-table))
+ -|
+ Welcome
+
+
+File: slib.info, Node: Database Reports, Next: Database Browser, Prev: Database Utilities, Up: Relational Database
+
+Database Reports
+----------------
+
+Code for generating database reports is in `report.scm'. After writing
+it using `format', I discovered that Common-Lisp `format' is not
+useable for this application because there is no mechanismm for
+truncating fields. `report.scm' needs to be rewritten using `printf'.
+
+ - Procedure: create-report RDB DESTINATION REPORT-NAME TABLE
+ - Procedure: create-report RDB DESTINATION REPORT-NAME
+ The symbol REPORT-NAME must be primary key in the table named
+ `*reports*' in the relational database RDB. DESTINATION is a
+ port, string, or symbol. If DESTINATION is a:
+
+ port
+ The table is created as ascii text and written to that port.
+
+ string
+ The table is created as ascii text and written to the file
+ named by DESTINATION.
+
+ symbol
+ DESTINATION is the primary key for a row in the table named
+ *printers*.
+
+ The report is prepared as follows:
+
+ * `Format' (*note Format::.) is called with the `header' field
+ and the (list of) `column-names' of the table.
+
+ * `Format' is called with the `reporter' field and (on
+ successive calls) each record in the natural order for the
+ table. A count is kept of the number of newlines output by
+ format. When the number of newlines to be output exceeds the
+ number of lines per page, the set of lines will be broken if
+ there are more than `minimum-break' left on this page and the
+ number of lines for this row is larger or equal to twice
+ `minimum-break'.
+
+ * `Format' is called with the `footer' field and the (list of)
+ `column-names' of the table. The footer field should not
+ output a newline.
+
+ * A new page is output.
+
+ * This entire process repeats until all the rows are output.
+
+ Each row in the table *reports* has the fields:
+
+name
+ The report name.
+
+default-table
+ The table to report on if none is specified.
+
+header, footer
+ A `format' string. At the beginning and end of each page
+ respectively, `format' is called with this string and the (list of)
+ column-names of this table.
+
+reporter
+ A `format' string. For each row in the table, `format' is called
+ with this string and the row.
+
+minimum-break
+ The minimum number of lines into which the report lines for a row
+ can be broken. Use `0' if a row's lines should not be broken over
+ page boundaries.
+
+ Each row in the table *printers* has the fields:
+
+name
+ The printer name.
+
+print-procedure
+ The procedure to call to actually print.
+
+
+File: slib.info, Node: Database Browser, Prev: Database Reports, Up: Relational Database
+
+Database Browser
+----------------
+
+ (require 'database-browse)
+
+ - Procedure: browse DATABASE
+ Prints the names of all the tables in DATABASE and sets browse's
+ default to DATABASE.
+
+ - Procedure: browse
+ Prints the names of all the tables in the default database.
+
+ - Procedure: browse TABLE-NAME
+ For each record of the table named by the symbol TABLE-NAME,
+ prints a line composed of all the field values.
+
+ - Procedure: browse PATHNAME
+ Opens the database named by the string PATHNAME, prints the names
+ of all its tables, and sets browse's default to the database.
+
+ - Procedure: browse DATABASE TABLE-NAME
+ Sets browse's default to DATABASE and prints the records of the
+ table named by the symbol TABLE-NAME.
+
+ - Procedure: browse PATHNAME TABLE-NAME
+ Opens the database named by the string PATHNAME and sets browse's
+ default to it; `browse' prints the records of the table named by
+ the symbol TABLE-NAME.
+
+
+
+File: slib.info, Node: Weight-Balanced Trees, Prev: Relational Database, Up: Database Packages
+
+Weight-Balanced Trees
+=====================
+
+ `(require 'wt-tree)'
+
+ Balanced binary trees are a useful data structure for maintaining
+large sets of ordered objects or sets of associations whose keys are
+ordered. MIT Scheme has an comprehensive implementation of
+weight-balanced binary trees which has several advantages over the
+other data structures for large aggregates:
+
+ * In addition to the usual element-level operations like insertion,
+ deletion and lookup, there is a full complement of collection-level
+ operations, like set intersection, set union and subset test, all
+ of which are implemented with good orders of growth in time and
+ space. This makes weight balanced trees ideal for rapid
+ prototyping of functionally derived specifications.
+
+ * An element in a tree may be indexed by its position under the
+ ordering of the keys, and the ordinal position of an element may
+ be determined, both with reasonable efficiency.
+
+ * Operations to find and remove minimum element make weight balanced
+ trees simple to use for priority queues.
+
+ * The implementation is *functional* rather than *imperative*. This
+ means that operations like `inserting' an association in a tree do
+ not destroy the old tree, in much the same way that `(+ 1 x)'
+ modifies neither the constant 1 nor the value bound to `x'. The
+ trees are referentially transparent thus the programmer need not
+ worry about copying the trees. Referential transparency allows
+ space efficiency to be achieved by sharing subtrees.
+
+ These features make weight-balanced trees suitable for a wide range of
+applications, especially those that require large numbers of sets or
+discrete maps. Applications that have a few global databases and/or
+concentrate on element-level operations like insertion and lookup are
+probably better off using hash-tables or red-black trees.
+
+ The *size* of a tree is the number of associations that it contains.
+Weight balanced binary trees are balanced to keep the sizes of the
+subtrees of each node within a constant factor of each other. This
+ensures logarithmic times for single-path operations (like lookup and
+insertion). A weight balanced tree takes space that is proportional to
+the number of associations in the tree. For the current
+implementation, the constant of proportionality is six words per
+association.
+
+ Weight balanced trees can be used as an implementation for either
+discrete sets or discrete maps (associations). Sets are implemented by
+ignoring the datum that is associated with the key. Under this scheme
+if an associations exists in the tree this indicates that the key of the
+association is a member of the set. Typically a value such as `()',
+`#t' or `#f' is associated with the key.
+
+ Many operations can be viewed as computing a result that, depending on
+whether the tree arguments are thought of as sets or maps, is known by
+two different names. An example is `wt-tree/member?', which, when
+regarding the tree argument as a set, computes the set membership
+operation, but, when regarding the tree as a discrete map,
+`wt-tree/member?' is the predicate testing if the map is defined at an
+element in its domain. Most names in this package have been chosen
+based on interpreting the trees as sets, hence the name
+`wt-tree/member?' rather than `wt-tree/defined-at?'.
+
+ The weight balanced tree implementation is a run-time-loadable option.
+To use weight balanced trees, execute
+
+ (load-option 'wt-tree)
+
+once before calling any of the procedures defined here.
+
+* Menu:
+
+* Construction of Weight-Balanced Trees::
+* Basic Operations on Weight-Balanced Trees::
+* Advanced Operations on Weight-Balanced Trees::
+* Indexing Operations on Weight-Balanced Trees::
+
+
+File: slib.info, Node: Construction of Weight-Balanced Trees, Next: Basic Operations on Weight-Balanced Trees, Prev: Weight-Balanced Trees, Up: Weight-Balanced Trees
+
+Construction of Weight-Balanced Trees
+-------------------------------------
+
+ Binary trees require there to be a total order on the keys used to
+arrange the elements in the tree. Weight balanced trees are organized
+by *types*, where the type is an object encapsulating the ordering
+relation. Creating a tree is a two-stage process. First a tree type
+must be created from the predicate which gives the ordering. The tree
+type is then used for making trees, either empty or singleton trees or
+trees from other aggregate structures like association lists. Once
+created, a tree `knows' its type and the type is used to test
+compatibility between trees in operations taking two trees. Usually a
+small number of tree types are created at the beginning of a program and
+used many times throughout the program's execution.
+
+ - procedure+: make-wt-tree-type KEY<?
+ This procedure creates and returns a new tree type based on the
+ ordering predicate KEY<?. KEY<? must be a total ordering, having
+ the property that for all key values `a', `b' and `c':
+
+ (key<? a a) => #f
+ (and (key<? a b) (key<? b a)) => #f
+ (if (and (key<? a b) (key<? b c))
+ (key<? a c)
+ #t) => #t
+
+ Two key values are assumed to be equal if neither is less than the
+ other by KEY<?.
+
+ Each call to `make-wt-tree-type' returns a distinct value, and
+ trees are only compatible if their tree types are `eq?'. A
+ consequence is that trees that are intended to be used in binary
+ tree operations must all be created with a tree type originating
+ from the same call to `make-wt-tree-type'.
+
+ - variable+: number-wt-type
+ A standard tree type for trees with numeric keys. `Number-wt-type'
+ could have been defined by
+
+ (define number-wt-type (make-wt-tree-type <))
+
+ - variable+: string-wt-type
+ A standard tree type for trees with string keys. `String-wt-type'
+ could have been defined by
+
+ (define string-wt-type (make-wt-tree-type string<?))
+
+ - procedure+: make-wt-tree WT-TREE-TYPE
+ This procedure creates and returns a newly allocated weight
+ balanced tree. The tree is empty, i.e. it contains no
+ associations. WT-TREE-TYPE is a weight balanced tree type
+ obtained by calling `make-wt-tree-type'; the returned tree has
+ this type.
+
+ - procedure+: singleton-wt-tree WT-TREE-TYPE KEY DATUM
+ This procedure creates and returns a newly allocated weight
+ balanced tree. The tree contains a single association, that of
+ DATUM with KEY. WT-TREE-TYPE is a weight balanced tree type
+ obtained by calling `make-wt-tree-type'; the returned tree has
+ this type.
+
+ - procedure+: alist->wt-tree TREE-TYPE ALIST
+ Returns a newly allocated weight-balanced tree that contains the
+ same associations as ALIST. This procedure is equivalent to:
+
+ (lambda (type alist)
+ (let ((tree (make-wt-tree type)))
+ (for-each (lambda (association)
+ (wt-tree/add! tree
+ (car association)
+ (cdr association)))
+ alist)
+ tree))
+
+
+File: slib.info, Node: Basic Operations on Weight-Balanced Trees, Next: Advanced Operations on Weight-Balanced Trees, Prev: Construction of Weight-Balanced Trees, Up: Weight-Balanced Trees
+
+Basic Operations on Weight-Balanced Trees
+-----------------------------------------
+
+ This section describes the basic tree operations on weight balanced
+trees. These operations are the usual tree operations for insertion,
+deletion and lookup, some predicates and a procedure for determining the
+number of associations in a tree.
+
+ - procedure+: wt-tree? OBJECT
+ Returns `#t' if OBJECT is a weight-balanced tree, otherwise
+ returns `#f'.
+
+ - procedure+: wt-tree/empty? WT-TREE
+ Returns `#t' if WT-TREE contains no associations, otherwise
+ returns `#f'.
+
+ - procedure+: wt-tree/size WT-TREE
+ Returns the number of associations in WT-TREE, an exact
+ non-negative integer. This operation takes constant time.
+
+ - procedure+: wt-tree/add WT-TREE KEY DATUM
+ Returns a new tree containing all the associations in WT-TREE and
+ the association of DATUM with KEY. If WT-TREE already had an
+ association for KEY, the new association overrides the old. The
+ average and worst-case times required by this operation are
+ proportional to the logarithm of the number of associations in
+ WT-TREE.
+
+ - procedure+: wt-tree/add! WT-TREE KEY DATUM
+ Associates DATUM with KEY in WT-TREE and returns an unspecified
+ value. If WT-TREE already has an association for KEY, that
+ association is replaced. The average and worst-case times
+ required by this operation are proportional to the logarithm of
+ the number of associations in WT-TREE.
+
+ - procedure+: wt-tree/member? KEY WT-TREE
+ Returns `#t' if WT-TREE contains an association for KEY, otherwise
+ returns `#f'. The average and worst-case times required by this
+ operation are proportional to the logarithm of the number of
+ associations in WT-TREE.
+
+ - procedure+: wt-tree/lookup WT-TREE KEY DEFAULT
+ Returns the datum associated with KEY in WT-TREE. If WT-TREE
+ doesn't contain an association for KEY, DEFAULT is returned. The
+ average and worst-case times required by this operation are
+ proportional to the logarithm of the number of associations in
+ WT-TREE.
+
+ - procedure+: wt-tree/delete WT-TREE KEY
+ Returns a new tree containing all the associations in WT-TREE,
+ except that if WT-TREE contains an association for KEY, it is
+ removed from the result. The average and worst-case times required
+ by this operation are proportional to the logarithm of the number
+ of associations in WT-TREE.
+
+ - procedure+: wt-tree/delete! WT-TREE KEY
+ If WT-TREE contains an association for KEY the association is
+ removed. Returns an unspecified value. The average and worst-case
+ times required by this operation are proportional to the logarithm
+ of the number of associations in WT-TREE.
+
+
+File: slib.info, Node: Advanced Operations on Weight-Balanced Trees, Next: Indexing Operations on Weight-Balanced Trees, Prev: Basic Operations on Weight-Balanced Trees, Up: Weight-Balanced Trees
+
+Advanced Operations on Weight-Balanced Trees
+--------------------------------------------
+
+ In the following the *size* of a tree is the number of associations
+that the tree contains, and a *smaller* tree contains fewer
+associations.
+
+ - procedure+: wt-tree/split< WT-TREE BOUND
+ Returns a new tree containing all and only the associations in
+ WT-TREE which have a key that is less than BOUND in the ordering
+ relation of the tree type of WT-TREE. The average and worst-case
+ times required by this operation are proportional to the logarithm
+ of the size of WT-TREE.
+
+ - procedure+: wt-tree/split> WT-TREE BOUND
+ Returns a new tree containing all and only the associations in
+ WT-TREE which have a key that is greater than BOUND in the
+ ordering relation of the tree type of WT-TREE. The average and
+ worst-case times required by this operation are proportional to the
+ logarithm of size of WT-TREE.
+
+ - procedure+: wt-tree/union WT-TREE-1 WT-TREE-2
+ Returns a new tree containing all the associations from both trees.
+ This operation is asymmetric: when both trees have an association
+ for the same key, the returned tree associates the datum from
+ WT-TREE-2 with the key. Thus if the trees are viewed as discrete
+ maps then `wt-tree/union' computes the map override of WT-TREE-1 by
+ WT-TREE-2. If the trees are viewed as sets the result is the set
+ union of the arguments. The worst-case time required by this
+ operation is proportional to the sum of the sizes of both trees.
+ If the minimum key of one tree is greater than the maximum key of
+ the other tree then the time required is at worst proportional to
+ the logarithm of the size of the larger tree.
+
+ - procedure+: wt-tree/intersection WT-TREE-1 WT-TREE-2
+ Returns a new tree containing all and only those associations from
+ WT-TREE-1 which have keys appearing as the key of an association
+ in WT-TREE-2. Thus the associated data in the result are those
+ from WT-TREE-1. If the trees are being used as sets the result is
+ the set intersection of the arguments. As a discrete map
+ operation, `wt-tree/intersection' computes the domain restriction
+ of WT-TREE-1 to (the domain of) WT-TREE-2. The time required by
+ this operation is never worse that proportional to the sum of the
+ sizes of the trees.
+
+ - procedure+: wt-tree/difference WT-TREE-1 WT-TREE-2
+ Returns a new tree containing all and only those associations from
+ WT-TREE-1 which have keys that *do not* appear as the key of an
+ association in WT-TREE-2. If the trees are viewed as sets the
+ result is the asymmetric set difference of the arguments. As a
+ discrete map operation, it computes the domain restriction of
+ WT-TREE-1 to the complement of (the domain of) WT-TREE-2. The
+ time required by this operation is never worse that proportional to
+ the sum of the sizes of the trees.
+
+ - procedure+: wt-tree/subset? WT-TREE-1 WT-TREE-2
+ Returns `#t' iff the key of each association in WT-TREE-1 is the
+ key of some association in WT-TREE-2, otherwise returns `#f'.
+ Viewed as a set operation, `wt-tree/subset?' is the improper subset
+ predicate. A proper subset predicate can be constructed:
+
+ (define (proper-subset? s1 s2)
+ (and (wt-tree/subset? s1 s2)
+ (< (wt-tree/size s1) (wt-tree/size s2))))
+
+ As a discrete map operation, `wt-tree/subset?' is the subset test
+ on the domain(s) of the map(s). In the worst-case the time
+ required by this operation is proportional to the size of
+ WT-TREE-1.
+
+ - procedure+: wt-tree/set-equal? WT-TREE-1 WT-TREE-2
+ Returns `#t' iff for every association in WT-TREE-1 there is an
+ association in WT-TREE-2 that has the same key, and *vice versa*.
+
+ Viewing the arguments as sets `wt-tree/set-equal?' is the set
+ equality predicate. As a map operation it determines if two maps
+ are defined on the same domain.
+
+ This procedure is equivalent to
+
+ (lambda (wt-tree-1 wt-tree-2)
+ (and (wt-tree/subset? wt-tree-1 wt-tree-2
+ (wt-tree/subset? wt-tree-2 wt-tree-1)))
+
+ In the worst-case the time required by this operation is
+ proportional to the size of the smaller tree.
+
+ - procedure+: wt-tree/fold COMBINER INITIAL WT-TREE
+ This procedure reduces WT-TREE by combining all the associations,
+ using an reverse in-order traversal, so the associations are
+ visited in reverse order. COMBINER is a procedure of three
+ arguments: a key, a datum and the accumulated result so far.
+ Provided COMBINER takes time bounded by a constant, `wt-tree/fold'
+ takes time proportional to the size of WT-TREE.
+
+ A sorted association list can be derived simply:
+
+ (wt-tree/fold (lambda (key datum list)
+ (cons (cons key datum) list))
+ '()
+ WT-TREE))
+
+ The data in the associations can be summed like this:
+
+ (wt-tree/fold (lambda (key datum sum) (+ sum datum))
+ 0
+ WT-TREE)
+
+ - procedure+: wt-tree/for-each ACTION WT-TREE
+ This procedure traverses the tree in-order, applying ACTION to
+ each association. The associations are processed in increasing
+ order of their keys. ACTION is a procedure of two arguments which
+ take the key and datum respectively of the association. Provided
+ ACTION takes time bounded by a constant, `wt-tree/for-each' takes
+ time proportional to in the size of WT-TREE. The example prints
+ the tree:
+
+ (wt-tree/for-each (lambda (key value)
+ (display (list key value)))
+ WT-TREE))
+
+
+File: slib.info, Node: Indexing Operations on Weight-Balanced Trees, Prev: Advanced Operations on Weight-Balanced Trees, Up: Weight-Balanced Trees
+
+Indexing Operations on Weight-Balanced Trees
+--------------------------------------------
+
+ Weight balanced trees support operations that view the tree as sorted
+sequence of associations. Elements of the sequence can be accessed by
+position, and the position of an element in the sequence can be
+determined, both in logarthmic time.
+
+ - procedure+: wt-tree/index WT-TREE INDEX
+ - procedure+: wt-tree/index-datum WT-TREE INDEX
+ - procedure+: wt-tree/index-pair WT-TREE INDEX
+ Returns the 0-based INDEXth association of WT-TREE in the sorted
+ sequence under the tree's ordering relation on the keys.
+ `wt-tree/index' returns the INDEXth key, `wt-tree/index-datum'
+ returns the datum associated with the INDEXth key and
+ `wt-tree/index-pair' returns a new pair `(KEY . DATUM)' which is
+ the `cons' of the INDEXth key and its datum. The average and
+ worst-case times required by this operation are proportional to
+ the logarithm of the number of associations in the tree.
+
+ These operations signal an error if the tree is empty, if
+ INDEX`<0', or if INDEX is greater than or equal to the number of
+ associations in the tree.
+
+ Indexing can be used to find the median and maximum keys in the
+ tree as follows:
+
+ median: (wt-tree/index WT-TREE
+ (quotient (wt-tree/size WT-TREE) 2))
+
+ maximum: (wt-tree/index WT-TREE
+ (-1+ (wt-tree/size WT-TREE)))
+
+ - procedure+: wt-tree/rank WT-TREE KEY
+ Determines the 0-based position of KEY in the sorted sequence of
+ the keys under the tree's ordering relation, or `#f' if the tree
+ has no association with for KEY. This procedure returns either an
+ exact non-negative integer or `#f'. The average and worst-case
+ times required by this operation are proportional to the logarithm
+ of the number of associations in the tree.
+
+ - procedure+: wt-tree/min WT-TREE
+ - procedure+: wt-tree/min-datum WT-TREE
+ - procedure+: wt-tree/min-pair WT-TREE
+ Returns the association of WT-TREE that has the least key under
+ the tree's ordering relation. `wt-tree/min' returns the least key,
+ `wt-tree/min-datum' returns the datum associated with the least key
+ and `wt-tree/min-pair' returns a new pair `(key . datum)' which is
+ the `cons' of the minimum key and its datum. The average and
+ worst-case times required by this operation are proportional to the
+ logarithm of the number of associations in the tree.
+
+ These operations signal an error if the tree is empty. They could
+ be written
+ (define (wt-tree/min tree) (wt-tree/index tree 0))
+ (define (wt-tree/min-datum tree) (wt-tree/index-datum tree 0))
+ (define (wt-tree/min-pair tree) (wt-tree/index-pair tree 0))
+
+ - procedure+: wt-tree/delete-min WT-TREE
+ Returns a new tree containing all of the associations in WT-TREE
+ except the association with the least key under the WT-TREE's
+ ordering relation. An error is signalled if the tree is empty.
+ The average and worst-case times required by this operation are
+ proportional to the logarithm of the number of associations in the
+ tree. This operation is equivalent to
+
+ (wt-tree/delete WT-TREE (wt-tree/min WT-TREE))
+
+ - procedure+: wt-tree/delete-min! WT-TREE
+ Removes the association with the least key under the WT-TREE's
+ ordering relation. An error is signalled if the tree is empty.
+ The average and worst-case times required by this operation are
+ proportional to the logarithm of the number of associations in the
+ tree. This operation is equivalent to
+
+ (wt-tree/delete! WT-TREE (wt-tree/min WT-TREE))
+
+
+File: slib.info, Node: Other Packages, Next: About SLIB, Prev: Database Packages, Up: Top
+
+Other Packages
+**************
+
+* Menu:
+
+* Data Structures:: Various data structures.
+* Procedures:: Miscellaneous utility procedures.
+* Standards Support:: Support for Scheme Standards.
+* Session Support:: REPL and Debugging.
+* Extra-SLIB Packages::
+
+
+File: slib.info, Node: Data Structures, Next: Procedures, Prev: Other Packages, Up: Other Packages
+
+Data Structures
+===============
+
+* Menu:
+
+* Arrays:: 'array
+* Array Mapping:: 'array-for-each
+* Association Lists:: 'alist
+* Byte:: 'byte
+* Collections:: 'collect
+* Dynamic Data Type:: 'dynamic
+* Hash Tables:: 'hash-table
+* Hashing:: 'hash, 'sierpinski, 'soundex
+* Object:: 'object
+* Priority Queues:: 'priority-queue
+* Queues:: 'queue
+* Records:: 'record
+* Structures:: 'struct, 'structure
+
+
+File: slib.info, Node: Arrays, Next: Array Mapping, Prev: Data Structures, Up: Data Structures
+
+Arrays
+------
+
+ `(require 'array)'
+
+ - Function: array? OBJ
+ Returns `#t' if the OBJ is an array, and `#f' if not.
+
+ - Function: make-array INITIAL-VALUE BOUND1 BOUND2 ...
+ Creates and returns an array that has as many dimensins as there
+ are BOUNDs and fills it with INITIAL-VALUE.
+
+ When constructing an array, BOUND is either an inclusive range of
+indices expressed as a two element list, or an upper bound expressed as
+a single integer. So
+ (make-array 'foo 3 3) == (make-array 'foo '(0 2) '(0 2))
+
+ - Function: make-shared-array ARRAY MAPPER BOUND1 BOUND2 ...
+ `make-shared-array' can be used to create shared subarrays of other
+ arrays. The MAPPER is a function that translates coordinates in
+ the new array into coordinates in the old array. A MAPPER must be
+ linear, and its range must stay within the bounds of the old
+ array, but it can be otherwise arbitrary. A simple example:
+ (define fred (make-array #f 8 8))
+ (define freds-diagonal
+ (make-shared-array fred (lambda (i) (list i i)) 8))
+ (array-set! freds-diagonal 'foo 3)
+ (array-ref fred 3 3)
+ => FOO
+ (define freds-center
+ (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j)))
+ 2 2))
+ (array-ref freds-center 0 0)
+ => FOO
+
+ - Function: array-rank OBJ
+ Returns the number of dimensions of OBJ. If OBJ is not an array,
+ 0 is returned.
+
+ - Function: array-shape ARRAY
+ `array-shape' returns a list of inclusive bounds. So:
+ (array-shape (make-array 'foo 3 5))
+ => ((0 2) (0 4))
+
+ - Function: array-dimensions ARRAY
+ `array-dimensions' is similar to `array-shape' but replaces
+ elements with a 0 minimum with one greater than the maximum. So:
+ (array-dimensions (make-array 'foo 3 5))
+ => (3 5)
+
+ - Procedure: array-in-bounds? ARRAY INDEX1 INDEX2 ...
+ Returns `#t' if its arguments would be acceptable to `array-ref'.
+
+ - Function: array-ref ARRAY INDEX1 INDEX2 ...
+ Returns the element at the `(INDEX1, INDEX2)' element in ARRAY.
+
+ - Procedure: array-set! ARRAY NEW-VALUE INDEX1 INDEX2 ...
+
+ - Function: array-1d-ref ARRAY INDEX
+ - Function: array-2d-ref ARRAY INDEX1 INDEX2
+ - Function: array-3d-ref ARRAY INDEX1 INDEX2 INDEX3
+
+ - Procedure: array-1d-set! ARRAY NEW-VALUE INDEX
+ - Procedure: array-2d-set! ARRAY NEW-VALUE INDEX1 INDEX2
+ - Procedure: array-3d-set! ARRAY NEW-VALUE INDEX1 INDEX2 INDEX3
+
+ The functions are just fast versions of `array-ref' and `array-set!'
+that take a fixed number of arguments, and perform no bounds checking.
+
+ If you comment out the bounds checking code, this is about as
+efficient as you could ask for without help from the compiler.
+
+ An exercise left to the reader: implement the rest of APL.
+
+
+File: slib.info, Node: Array Mapping, Next: Association Lists, Prev: Arrays, Up: Data Structures
+
+Array Mapping
+-------------
+
+ `(require 'array-for-each)'
+
+ - Function: array-map! ARRAY0 PROC ARRAY1 ...
+ ARRAY1, ... must have the same number of dimensions as ARRAY0 and
+ have a range for each index which includes the range for the
+ corresponding index in ARRAY0. PROC is applied to each tuple of
+ elements of ARRAY1 ... and the result is stored as the
+ corresponding element in ARRAY0. The value returned is
+ unspecified. The order of application is unspecified.
+
+ - Function: array-for-each PROC ARRAY0 ...
+ PROC is applied to each tuple of elements of ARRAY0 ... in
+ row-major order. The value returned is unspecified.
+
+ - Function: array-indexes ARRAY
+ Returns an array of lists of indexes for ARRAY such that, if LI is
+ a list of indexes for which ARRAY is defined, (equal? LI (apply
+ array-ref (array-indexes ARRAY) LI)).
+
+ - Function: array-index-map! ARRAY PROC
+ applies PROC to the indices of each element of ARRAY in turn,
+ storing the result in the corresponding element. The value
+ returned and the order of application are unspecified.
+
+ One can implement ARRAY-INDEXES as
+ (define (array-indexes array)
+ (let ((ra (apply make-array #f (array-shape array))))
+ (array-index-map! ra (lambda x x))
+ ra))
+ Another example:
+ (define (apl:index-generator n)
+ (let ((v (make-uniform-vector n 1)))
+ (array-index-map! v (lambda (i) i))
+ v))
+
+ - Function: array-copy! SOURCE DESTINATION
+ Copies every element from vector or array SOURCE to the
+ corresponding element of DESTINATION. DESTINATION must have the
+ same rank as SOURCE, and be at least as large in each dimension.
+ The order of copying is unspecified.
+
+
+File: slib.info, Node: Association Lists, Next: Byte, Prev: Array Mapping, Up: Data Structures
+
+Association Lists
+-----------------
+
+ `(require 'alist)'
+
+ Alist functions provide utilities for treating a list of key-value
+pairs as an associative database. These functions take an equality
+predicate, PRED, as an argument. This predicate should be repeatable,
+symmetric, and transitive.
+
+ Alist functions can be used with a secondary index method such as hash
+tables for improved performance.
+
+ - Function: predicate->asso PRED
+ Returns an "association function" (like `assq', `assv', or
+ `assoc') corresponding to PRED. The returned function returns a
+ key-value pair whose key is `pred'-equal to its first argument or
+ `#f' if no key in the alist is PRED-equal to the first argument.
+
+ - Function: alist-inquirer PRED
+ Returns a procedure of 2 arguments, ALIST and KEY, which returns
+ the value associated with KEY in ALIST or `#f' if KEY does not
+ appear in ALIST.
+
+ - Function: alist-associator PRED
+ Returns a procedure of 3 arguments, ALIST, KEY, and VALUE, which
+ returns an alist with KEY and VALUE associated. Any previous
+ value associated with KEY will be lost. This returned procedure
+ may or may not have side effects on its ALIST argument. An
+ example of correct usage is:
+ (define put (alist-associator string-ci=?))
+ (define alist '())
+ (set! alist (put alist "Foo" 9))
+
+ - Function: alist-remover PRED
+ Returns a procedure of 2 arguments, ALIST and KEY, which returns
+ an alist with an association whose KEY is key removed. This
+ returned procedure may or may not have side effects on its ALIST
+ argument. An example of correct usage is:
+ (define rem (alist-remover string-ci=?))
+ (set! alist (rem alist "foo"))
+
+ - Function: alist-map PROC ALIST
+ Returns a new association list formed by mapping PROC over the
+ keys and values of ALIST. PROC must be a function of 2 arguments
+ which returns the new value part.
+
+ - Function: alist-for-each PROC ALIST
+ Applies PROC to each pair of keys and values of ALIST. PROC must
+ be a function of 2 arguments. The returned value is unspecified.
+
+
+File: slib.info, Node: Byte, Next: Collections, Prev: Association Lists, Up: Data Structures
+
+Byte
+----
+
+ `(require 'byte)'
+
+ Some algorithms are expressed in terms of arrays of small integers.
+Using Scheme strings to implement these arrays is not portable vis-a-vis
+the correspondence between integers and characters and non-ascii
+character sets. These functions abstract the notion of a "byte".
+
+ - Function: byte-ref BYTES K
+ K must be a valid index of BYTES. `byte-ref' returns byte K of
+ BYTES using zero-origin indexing.
+
+ - Procedure: byte-set! BYTES K BYTE
+ K must be a valid index of BYTES%, and BYTE must be a small
+ integer. `Byte-set!' stores BYTE in element K of BYTES and
+ returns an unspecified value.
+
+ - Function: make-bytes K
+ - Function: make-bytes K BYTE
+ `Make-bytes' returns a newly allocated byte-array of length K. If
+ BYTE is given, then all elements of the byte-array are initialized
+ to BYTE, otherwise the contents of the byte-array are unspecified.
+
+
+ - Function: bytes-length BYTES
+ `bytes-length' returns length of byte-array BYTES.
+
+
+ - Function: write-byte BYTE
+ - Function: write-byte BYTE PORT
+ Writes the byte BYTE (not an external representation of the byte)
+ to the given PORT and returns an unspecified value. The PORT
+ argument may be omitted, in which case it defaults to the value
+ returned by `current-output-port'.
+
+
+ - Function: read-byte
+ - Function: read-byte PORT
+ Returns the next byte available from the input PORT, updating the
+ PORT to point to the following byte. If no more bytes are
+ available, an end of file object is returned. PORT may be
+ omitted, in which case it defaults to the value returned by
+ `current-input-port'.
+
+
+ - Function: bytes BYTE ...
+ Returns a newly allocated byte-array composed of the arguments.
+
+
+ - Function: bytes->list BYTES
+ - Function: list->bytes BYTES
+ `Bytes->list' returns a newly allocated list of the bytes that
+ make up the given byte-array. `List->bytes' returns a newly
+ allocated byte-array formed from the small integers in the list
+ BYTES. `Bytes->list' and `list->bytes' are inverses so far as
+ `equal?' is concerned.
+
+
+
+File: slib.info, Node: Collections, Next: Dynamic Data Type, Prev: Byte, Up: Data Structures
+
+Collections
+-----------
+
+ `(require 'collect)'
+
+ Routines for managing collections. Collections are aggregate data
+structures supporting iteration over their elements, similar to the
+Dylan(TM) language, but with a different interface. They have
+"elements" indexed by corresponding "keys", although the keys may be
+implicit (as with lists).
+
+ New types of collections may be defined as YASOS objects (*note
+Yasos::.). They must support the following operations:
+ * `(collection? SELF)' (always returns `#t');
+
+ * `(size SELF)' returns the number of elements in the collection;
+
+ * `(print SELF PORT)' is a specialized print operation for the
+ collection which prints a suitable representation on the given
+ PORT or returns it as a string if PORT is `#t';
+
+ * `(gen-elts SELF)' returns a thunk which on successive invocations
+ yields elements of SELF in order or gives an error if it is
+ invoked more than `(size SELF)' times;
+
+ * `(gen-keys SELF)' is like `gen-elts', but yields the collection's
+ keys in order.
+
+ They might support specialized `for-each-key' and `for-each-elt'
+operations.
+
+ - Function: collection? OBJ
+ A predicate, true initially of lists, vectors and strings. New
+ sorts of collections must answer `#t' to `collection?'.
+
+ - Procedure: map-elts PROC . COLLECTIONS
+ - Procedure: do-elts PROC . COLLECTIONS
+ PROC is a procedure taking as many arguments as there are
+ COLLECTIONS (at least one). The COLLECTIONS are iterated over in
+ their natural order and PROC is applied to the elements yielded by
+ each iteration in turn. The order in which the arguments are
+ supplied corresponds to te order in which the COLLECTIONS appear.
+ `do-elts' is used when only side-effects of PROC are of interest
+ and its return value is unspecified. `map-elts' returns a
+ collection (actually a vector) of the results of the applications
+ of PROC.
+
+ Example:
+ (map-elts + (list 1 2 3) (vector 1 2 3))
+ => #(2 4 6)
+
+ - Procedure: map-keys PROC . COLLECTIONS
+ - Procedure: do-keys PROC . COLLECTIONS
+ These are analogous to `map-elts' and `do-elts', but each
+ iteration is over the COLLECTIONS' *keys* rather than their
+ elements.
+
+ Example:
+ (map-keys + (list 1 2 3) (vector 1 2 3))
+ => #(0 2 4)
+
+ - Procedure: for-each-key COLLECTION PROC
+ - Procedure: for-each-elt COLLECTION PROC
+ These are like `do-keys' and `do-elts' but only for a single
+ collection; they are potentially more efficient.
+
+ - Function: reduce PROC SEED . COLLECTIONS
+ A generalization of the list-based `comlist:reduce-init' (*note
+ Lists as sequences::.) to collections which will shadow the
+ list-based version if `(require 'collect)' follows `(require
+ 'common-list-functions)' (*note Common List Functions::.).
+
+ Examples:
+ (reduce + 0 (vector 1 2 3))
+ => 6
+ (reduce union '() '((a b c) (b c d) (d a)))
+ => (c b d a).
+
+ - Function: any? PRED . COLLECTIONS
+ A generalization of the list-based `some' (*note Lists as
+ sequences::.) to collections.
+
+ Example:
+ (any? odd? (list 2 3 4 5))
+ => #t
+
+ - Function: every? PRED . COLLECTIONS
+ A generalization of the list-based `every' (*note Lists as
+ sequences::.) to collections.
+
+ Example:
+ (every? collection? '((1 2) #(1 2)))
+ => #t
+
+ - Function: empty? COLLECTION
+ Returns `#t' iff there are no elements in COLLECTION.
+
+ `(empty? COLLECTION) == (zero? (size COLLECTION))'
+
+ - Function: size COLLECTION
+ Returns the number of elements in COLLECTION.
+
+ - Function: Setter LIST-REF
+ See *Note Setters:: for a definition of "setter". N.B. `(setter
+ list-ref)' doesn't work properly for element 0 of a list.
+
+ Here is a sample collection: `simple-table' which is also a `table'.
+ (define-predicate TABLE?)
+ (define-operation (LOOKUP table key failure-object))
+ (define-operation (ASSOCIATE! table key value)) ;; returns key
+ (define-operation (REMOVE! table key)) ;; returns value
+
+ (define (MAKE-SIMPLE-TABLE)
+ (let ( (table (list)) )
+ (object
+ ;; table behaviors
+ ((TABLE? self) #t)
+ ((SIZE self) (size table))
+ ((PRINT self port) (format port "#<SIMPLE-TABLE>"))
+ ((LOOKUP self key failure-object)
+ (cond
+ ((assq key table) => cdr)
+ (else failure-object)
+ ))
+ ((ASSOCIATE! self key value)
+ (cond
+ ((assq key table)
+ => (lambda (bucket) (set-cdr! bucket value) key))
+ (else
+ (set! table (cons (cons key value) table))
+ key)
+ ))
+ ((REMOVE! self key);; returns old value
+ (cond
+ ((null? table) (slib:error "TABLE:REMOVE! Key not found: " key))
+ ((eq? key (caar table))
+ (let ( (value (cdar table)) )
+ (set! table (cdr table))
+ value)
+ )
+ (else
+ (let loop ( (last table) (this (cdr table)) )
+ (cond
+ ((null? this)
+ (slib:error "TABLE:REMOVE! Key not found: " key))
+ ((eq? key (caar this))
+ (let ( (value (cdar this)) )
+ (set-cdr! last (cdr this))
+ value)
+ )
+ (else
+ (loop (cdr last) (cdr this)))
+ ) ) )
+ ))
+ ;; collection behaviors
+ ((COLLECTION? self) #t)
+ ((GEN-KEYS self) (collect:list-gen-elts (map car table)))
+ ((GEN-ELTS self) (collect:list-gen-elts (map cdr table)))
+ ((FOR-EACH-KEY self proc)
+ (for-each (lambda (bucket) (proc (car bucket))) table)
+ )
+ ((FOR-EACH-ELT self proc)
+ (for-each (lambda (bucket) (proc (cdr bucket))) table)
+ )
+ ) ) )
+
+
+File: slib.info, Node: Dynamic Data Type, Next: Hash Tables, Prev: Collections, Up: Data Structures
+
+Dynamic Data Type
+-----------------
+
+ `(require 'dynamic)'
+
+ - Function: make-dynamic OBJ
+ Create and returns a new "dynamic" whose global value is OBJ.
+
+ - Function: dynamic? OBJ
+ Returns true if and only if OBJ is a dynamic. No object
+ satisfying `dynamic?' satisfies any of the other standard type
+ predicates.
+
+ - Function: dynamic-ref DYN
+ Return the value of the given dynamic in the current dynamic
+ environment.
+
+ - Procedure: dynamic-set! DYN OBJ
+ Change the value of the given dynamic to OBJ in the current
+ dynamic environment. The returned value is unspecified.
+
+ - Function: call-with-dynamic-binding DYN OBJ THUNK
+ Invoke and return the value of the given thunk in a new, nested
+ dynamic environment in which the given dynamic has been bound to a
+ new location whose initial contents are the value OBJ. This
+ dynamic environment has precisely the same extent as the
+ invocation of the thunk and is thus captured by continuations
+ created within that invocation and re-established by those
+ continuations when they are invoked.
+
+ The `dynamic-bind' macro is not implemented.
+
+
+File: slib.info, Node: Hash Tables, Next: Hashing, Prev: Dynamic Data Type, Up: Data Structures
+
+Hash Tables
+-----------
+
+ `(require 'hash-table)'
+
+ - Function: predicate->hash PRED
+ Returns a hash function (like `hashq', `hashv', or `hash')
+ corresponding to the equality predicate PRED. PRED should be
+ `eq?', `eqv?', `equal?', `=', `char=?', `char-ci=?', `string=?', or
+ `string-ci=?'.
+
+ A hash table is a vector of association lists.
+
+ - Function: make-hash-table K
+ Returns a vector of K empty (association) lists.
+
+ Hash table functions provide utilities for an associative database.
+These functions take an equality predicate, PRED, as an argument. PRED
+should be `eq?', `eqv?', `equal?', `=', `char=?', `char-ci=?',
+`string=?', or `string-ci=?'.
+
+ - Function: predicate->hash-asso PRED
+ Returns a hash association function of 2 arguments, KEY and
+ HASHTAB, corresponding to PRED. The returned function returns a
+ key-value pair whose key is PRED-equal to its first argument or
+ `#f' if no key in HASHTAB is PRED-equal to the first argument.
+
+ - Function: hash-inquirer PRED
+ Returns a procedure of 3 arguments, `hashtab' and `key', which
+ returns the value associated with `key' in `hashtab' or `#f' if
+ key does not appear in `hashtab'.
+
+ - Function: hash-associator PRED
+ Returns a procedure of 3 arguments, HASHTAB, KEY, and VALUE, which
+ modifies HASHTAB so that KEY and VALUE associated. Any previous
+ value associated with KEY will be lost.
+
+ - Function: hash-remover PRED
+ Returns a procedure of 2 arguments, HASHTAB and KEY, which
+ modifies HASHTAB so that the association whose key is KEY is
+ removed.
+
+ - Function: hash-map PROC HASH-TABLE
+ Returns a new hash table formed by mapping PROC over the keys and
+ values of HASH-TABLE. PROC must be a function of 2 arguments
+ which returns the new value part.
+
+ - Function: hash-for-each PROC HASH-TABLE
+ Applies PROC to each pair of keys and values of HASH-TABLE. PROC
+ must be a function of 2 arguments. The returned value is
+ unspecified.
+
+
+File: slib.info, Node: Hashing, Next: Object, Prev: Hash Tables, Up: Data Structures
+
+Hashing
+-------
+
+ `(require 'hash)'
+
+ These hashing functions are for use in quickly classifying objects.
+Hash tables use these functions.
+
+ - Function: hashq OBJ K
+ - Function: hashv OBJ K
+ - Function: hash OBJ K
+ Returns an exact non-negative integer less than K. For each
+ non-negative integer less than K there are arguments OBJ for which
+ the hashing functions applied to OBJ and K returns that integer.
+
+ For `hashq', `(eq? obj1 obj2)' implies `(= (hashq obj1 k) (hashq
+ obj2))'.
+
+ For `hashv', `(eqv? obj1 obj2)' implies `(= (hashv obj1 k) (hashv
+ obj2))'.
+
+ For `hash', `(equal? obj1 obj2)' implies `(= (hash obj1 k) (hash
+ obj2))'.
+
+ `hash', `hashv', and `hashq' return in time bounded by a constant.
+ Notice that items having the same `hash' implies the items have
+ the same `hashv' implies the items have the same `hashq'.
+
+ `(require 'sierpinski)'
+
+ - Function: make-sierpinski-indexer MAX-COORDINATE
+ Returns a procedure (eg hash-function) of 2 numeric arguments which
+ preserves *nearness* in its mapping from NxN to N.
+
+ MAX-COORDINATE is the maximum coordinate (a positive integer) of a
+ population of points. The returned procedures is a function that
+ takes the x and y coordinates of a point, (non-negative integers)
+ and returns an integer corresponding to the relative position of
+ that point along a Sierpinski curve. (You can think of this as
+ computing a (pseudo-) inverse of the Sierpinski spacefilling
+ curve.)
+
+ Example use: Make an indexer (hash-function) for integer points
+ lying in square of integer grid points [0,99]x[0,99]:
+ (define space-key (make-sierpinski-indexer 100))
+ Now let's compute the index of some points:
+ (space-key 24 78) => 9206
+ (space-key 23 80) => 9172
+
+ Note that locations (24, 78) and (23, 80) are near in index and
+ therefore, because the Sierpinski spacefilling curve is
+ continuous, we know they must also be near in the plane. Nearness
+ in the plane does not, however, necessarily correspond to nearness
+ in index, although it *tends* to be so.
+
+ Example applications:
+ * Sort points by Sierpinski index to get heuristic solution to
+ *travelling salesman problem*. For details of performance,
+ see L. Platzman and J. Bartholdi, "Spacefilling curves and the
+ Euclidean travelling salesman problem", JACM 36(4):719-737
+ (October 1989) and references therein.
+
+ * Use Sierpinski index as key by which to store 2-dimensional
+ data in a 1-dimensional data structure (such as a table).
+ Then locations that are near each other in 2-d space will
+ tend to be near each other in 1-d data structure; and
+ locations that are near in 1-d data structure will be near in
+ 2-d space. This can significantly speed retrieval from
+ secondary storage because contiguous regions in the plane
+ will tend to correspond to contiguous regions in secondary
+ storage. (This is a standard technique for managing CAD/CAM
+ or geographic data.)
+
+
+ `(require 'soundex)'
+
+ - Function: soundex NAME
+ Computes the *soundex* hash of NAME. Returns a string of an
+ initial letter and up to three digits between 0 and 6. Soundex
+ supposedly has the property that names that sound similar in normal
+ English pronunciation tend to map to the same key.
+
+ Soundex was a classic algorithm used for manual filing of personal
+ records before the advent of computers. It performs adequately for
+ English names but has trouble with other nationalities.
+
+ See Knuth, Vol. 3 `Sorting and searching', pp 391-2
+
+ To manage unusual inputs, `soundex' omits all non-alphabetic
+ characters. Consequently, in this implementation:
+
+ (soundex <string of blanks>) => ""
+ (soundex "") => ""
+
+ Examples from Knuth:
+
+ (map soundex '("Euler" "Gauss" "Hilbert" "Knuth"
+ "Lloyd" "Lukasiewicz"))
+ => ("E460" "G200" "H416" "K530" "L300" "L222")
+
+ (map soundex '("Ellery" "Ghosh" "Heilbronn" "Kant"
+ "Ladd" "Lissajous"))
+ => ("E460" "G200" "H416" "K530" "L300" "L222")
+
+ Some cases in which the algorithm fails (Knuth):
+
+ (map soundex '("Rogers" "Rodgers")) => ("R262" "R326")
+
+ (map soundex '("Sinclair" "St. Clair")) => ("S524" "S324")
+
+ (map soundex '("Tchebysheff" "Chebyshev")) => ("T212" "C121")
+
+
+File: slib.info, Node: Object, Next: Priority Queues, Prev: Hashing, Up: Data Structures
+
+Macroless Object System
+-----------------------
+
+ `(require 'object)'
+
+ This is the Macroless Object System written by Wade Humeniuk
+(whumeniu@datap.ca). Conceptual Tributes: *Note Yasos::, MacScheme's
+%object, CLOS, Lack of R4RS macros.
+
+Concepts
+--------
+
+OBJECT
+ An object is an ordered association-list (by `eq?') of methods
+ (procedures). Methods can be added (`make-method!'), deleted
+ (`unmake-method!') and retrieved (`get-method'). Objects may
+ inherit methods from other objects. The object binds to the
+ environment it was created in, allowing closures to be used to
+ hide private procedures and data.
+
+GENERIC-METHOD
+ A generic-method associates (in terms of `eq?') object's method.
+ This allows scheme function style to be used for objects. The
+ calling scheme for using a generic method is `(generic-method
+ object param1 param2 ...)'.
+
+METHOD
+ A method is a procedure that exists in the object. To use a method
+ get-method must be called to look-up the method. Generic methods
+ implement the get-method functionality. Methods may be added to an
+ object associated with any scheme obj in terms of eq?
+
+GENERIC-PREDICATE
+ A generic method that returns a boolean value for any scheme obj.
+
+PREDICATE
+ A object's method asscociated with a generic-predicate. Returns
+ `#t'.
+
+Procedures
+----------
+
+ - Function: make-object ANCESTOR ...
+ Returns an object. Current object implementation is a tagged
+ vector. ANCESTORs are optional and must be objects in terms of
+ object?. ANCESTORs methods are included in the object. Multiple
+ ANCESTORs might associate the same generic-method with a method.
+ In this case the method of the ANCESTOR first appearing in the
+ list is the one returned by `get-method'.
+
+ - Function: object? OBJ
+ Returns boolean value whether OBJ was created by make-object.
+
+ - Function: make-generic-method EXCEPTION-PROCEDURE
+ Returns a procedure which be associated with an object's methods.
+ If EXCEPTION-PROCEDURE is specified then it is used to process
+ non-objects.
+
+ - Function: make-generic-predicate
+ Returns a boolean procedure for any scheme object.
+
+ - Function: make-method! OBJECT GENERIC-METHOD METHOD
+ Associates METHOD to the GENERIC-METHOD in the object. The METHOD
+ overrides any previous association with the GENERIC-METHOD within
+ the object. Using `unmake-method!' will restore the object's
+ previous association with the GENERIC-METHOD. METHOD must be a
+ procedure.
+
+ - Function: make-predicate! OBJECT GENERIC-PRECIATE
+ Makes a predicate method associated with the GENERIC-PREDICATE.
+
+ - Function: unmake-method! OBJECT GENERIC-METHOD
+ Removes an object's association with a GENERIC-METHOD .
+
+ - Function: get-method OBJECT GENERIC-METHOD
+ Returns the object's method associated (if any) with the
+ GENERIC-METHOD. If no associated method exists an error is
+ flagged.
+
+Examples
+--------
+
+ (require 'object)
+
+ (define instantiate (make-generic-method))
+
+ (define (make-instance-object . ancestors)
+ (define self (apply make-object
+ (map (lambda (obj) (instantiate obj)) ancestors)))
+ (make-method! self instantiate (lambda (self) self))
+ self)
+
+ (define who (make-generic-method))
+ (define imigrate! (make-generic-method))
+ (define emigrate! (make-generic-method))
+ (define describe (make-generic-method))
+ (define name (make-generic-method))
+ (define address (make-generic-method))
+ (define members (make-generic-method))
+
+ (define society
+ (let ()
+ (define self (make-instance-object))
+ (define population '())
+ (make-method! self imigrate!
+ (lambda (new-person)
+ (if (not (eq? new-person self))
+ (set! population (cons new-person population)))))
+ (make-method! self emigrate!
+ (lambda (person)
+ (if (not (eq? person self))
+ (set! population
+ (comlist:remove-if (lambda (member)
+ (eq? member person))
+ population)))))
+ (make-method! self describe
+ (lambda (self)
+ (map (lambda (person) (describe person)) population)))
+ (make-method! self who
+ (lambda (self) (map (lambda (person) (name person))
+ population)))
+ (make-method! self members (lambda (self) population))
+ self))
+
+ (define (make-person %name %address)
+ (define self (make-instance-object society))
+ (make-method! self name (lambda (self) %name))
+ (make-method! self address (lambda (self) %address))
+ (make-method! self who (lambda (self) (name self)))
+ (make-method! self instantiate
+ (lambda (self)
+ (make-person (string-append (name self) "-son-of")
+ %address)))
+ (make-method! self describe
+ (lambda (self) (list (name self) (address self))))
+ (imigrate! self)
+ self)
+
+Inverter Documentation
+......................
+
+ Inheritance:
+ <inverter>::(<number> <description>)
+ Generic-methods
+ <inverter>::value => <number>::value
+ <inverter>::set-value! => <number>::set-value!
+ <inverter>::describe => <description>::describe
+ <inverter>::help
+ <inverter>::invert
+ <inverter>::inverter?
+
+Number Documention
+..................
+
+ Inheritance
+ <number>::()
+ Slots
+ <number>::<x>
+ Generic Methods
+ <number>::value
+ <number>::set-value!
+
+Inverter code
+.............
+
+ (require 'object)
+
+ (define value (make-generic-method (lambda (val) val)))
+ (define set-value! (make-generic-method))
+ (define invert (make-generic-method
+ (lambda (val)
+ (if (number? val)
+ (/ 1 val)
+ (error "Method not supported:" val)))))
+ (define noop (make-generic-method))
+ (define inverter? (make-generic-predicate))
+ (define describe (make-generic-method))
+ (define help (make-generic-method))
+
+ (define (make-number x)
+ (define self (make-object))
+ (make-method! self value (lambda (this) x))
+ (make-method! self set-value!
+ (lambda (this new-value) (set! x new-value)))
+ self)
+
+ (define (make-description str)
+ (define self (make-object))
+ (make-method! self describe (lambda (this) str))
+ (make-method! self help (lambda (this) "Help not available"))
+ self)
+
+ (define (make-inverter)
+ (let* ((self (make-object
+ (make-number 1)
+ (make-description "A number which can be inverted")))
+ (<value> (get-method self value)))
+ (make-method! self invert (lambda (self) (/ 1 (<value> self))))
+ (make-predicate! self inverter?)
+ (unmake-method! self help)
+ (make-method! self help
+ (lambda (self)
+ (display "Inverter Methods:") (newline)
+ (display " (value inverter) ==> n") (newline)))
+ self))
+
+ ;;;; Try it out
+
+ (define invert! (make-generic-method))
+
+ (define x (make-inverter))
+
+ (make-method! x invert! (lambda (x) (set-value! x (/ 1 (value x)))))
+
+ (value x) => 1
+ (set-value! x 33) => undefined
+ (invert! x) => undefined
+ (value x) => 1/33
+
+ (unmake-method! x invert!) => undefined
+
+ (invert! x) error--> ERROR: Method not supported: x
+
+
+File: slib.info, Node: Priority Queues, Next: Queues, Prev: Object, Up: Data Structures
+
+Priority Queues
+---------------
+
+ `(require 'priority-queue)'
+
+ - Function: make-heap PRED<?
+ Returns a binary heap suitable which can be used for priority queue
+ operations.
+
+ - Function: heap-length HEAP
+ Returns the number of elements in HEAP.
+
+ - Procedure: heap-insert! HEAP ITEM
+ Inserts ITEM into HEAP. ITEM can be inserted multiple times. The
+ value returned is unspecified.
+
+ - Function: heap-extract-max! HEAP
+ Returns the item which is larger than all others according to the
+ PRED<? argument to `make-heap'. If there are no items in HEAP, an
+ error is signaled.
+
+ The algorithm for priority queues was taken from `Introduction to
+Algorithms' by T. Cormen, C. Leiserson, R. Rivest. 1989 MIT Press.
+
+
+File: slib.info, Node: Queues, Next: Records, Prev: Priority Queues, Up: Data Structures
+
+Queues
+------
+
+ `(require 'queue)'
+
+ A "queue" is a list where elements can be added to both the front and
+rear, and removed from the front (i.e., they are what are often called
+"dequeues"). A queue may also be used like a stack.
+
+ - Function: make-queue
+ Returns a new, empty queue.
+
+ - Function: queue? OBJ
+ Returns `#t' if OBJ is a queue.
+
+ - Function: queue-empty? Q
+ Returns `#t' if the queue Q is empty.
+
+ - Procedure: queue-push! Q DATUM
+ Adds DATUM to the front of queue Q.
+
+ - Procedure: enquque! Q DATUM
+ Adds DATUM to the rear of queue Q.
+
+ All of the following functions raise an error if the queue Q is empty.
+
+ - Function: queue-front Q
+ Returns the datum at the front of the queue Q.
+
+ - Function: queue-rear Q
+ Returns the datum at the rear of the queue Q.
+
+ - Prcoedure: queue-pop! Q
+ - Procedure: dequeue! Q
+ Both of these procedures remove and return the datum at the front
+ of the queue. `queue-pop!' is used to suggest that the queue is
+ being used like a stack.
+
+
+File: slib.info, Node: Records, Next: Structures, Prev: Queues, Up: Data Structures
+
+Records
+-------
+
+ `(require 'record)'
+
+ The Record package provides a facility for user to define their own
+record data types.
+
+ - Function: make-record-type TYPE-NAME FIELD-NAMES
+ Returns a "record-type descriptor", a value representing a new data
+ type disjoint from all others. The TYPE-NAME argument must be a
+ string, but is only used for debugging purposes (such as the
+ printed representation of a record of the new type). The
+ FIELD-NAMES argument is a list of symbols naming the "fields" of a
+ record of the new type. It is an error if the list contains any
+ duplicates. It is unspecified how record-type descriptors are
+ represented.
+
+ - Function: record-constructor RTD [FIELD-NAMES]
+ Returns a procedure for constructing new members of the type
+ represented by RTD. The returned procedure accepts exactly as
+ many arguments as there are symbols in the given list,
+ FIELD-NAMES; these are used, in order, as the initial values of
+ those fields in a new record, which is returned by the constructor
+ procedure. The values of any fields not named in that list are
+ unspecified. The FIELD-NAMES argument defaults to the list of
+ field names in the call to `make-record-type' that created the
+ type represented by RTD; if the FIELD-NAMES argument is provided,
+ it is an error if it contains any duplicates or any symbols not in
+ the default list.
+
+ - Function: record-predicate RTD
+ Returns a procedure for testing membership in the type represented
+ by RTD. The returned procedure accepts exactly one argument and
+ returns a true value if the argument is a member of the indicated
+ record type; it returns a false value otherwise.
+
+ - Function: record-accessor RTD FIELD-NAME
+ Returns a procedure for reading the value of a particular field of
+ a member of the type represented by RTD. The returned procedure
+ accepts exactly one argument which must be a record of the
+ appropriate type; it returns the current value of the field named
+ by the symbol FIELD-NAME in that record. The symbol FIELD-NAME
+ must be a member of the list of field-names in the call to
+ `make-record-type' that created the type represented by RTD.
+
+ - Function: record-modifier RTD FIELD-NAME
+ Returns a procedure for writing the value of a particular field of
+ a member of the type represented by RTD. The returned procedure
+ accepts exactly two arguments: first, a record of the appropriate
+ type, and second, an arbitrary Scheme value; it modifies the field
+ named by the symbol FIELD-NAME in that record to contain the given
+ value. The returned value of the modifier procedure is
+ unspecified. The symbol FIELD-NAME must be a member of the list
+ of field-names in the call to `make-record-type' that created the
+ type represented by RTD.
+
+ In May of 1996, as a product of discussion on the `rrrs-authors'
+mailing list, I rewrote `record.scm' to portably implement type
+disjointness for record data types.
+
+ As long as an implementation's procedures are opaque and the `record'
+code is loaded before other programs, this will give disjoint record
+types which are unforgeable and incorruptible by R4RS procedures.
+
+ As a consequence, the procedures `record?', `record-type-descriptor',
+`record-type-name'.and `record-type-field-names' are no longer
+supported.
+
+
+File: slib.info, Node: Structures, Prev: Records, Up: Data Structures
+
+Structures
+----------
+
+ `(require 'struct)' (uses defmacros)
+
+ `defmacro's which implement "records" from the book `Essentials of
+Programming Languages' by Daniel P. Friedman, M. Wand and C.T. Haynes.
+Copyright 1992 Jeff Alexander, Shinnder Lee, and Lewis Patterson
+
+ Matthew McDonald <mafm@cs.uwa.edu.au> added field setters.
+
+ - Macro: define-record TAG (VAR1 VAR2 ...)
+ Defines several functions pertaining to record-name TAG:
+
+ - Function: make-TAG VAR1 VAR2 ...
+
+ - Function: TAG? OBJ
+
+ - Function: TAG->VAR1 OBJ
+
+ - Function: TAG->VAR2 OBJ
+ ...
+
+ - Function: set-TAG-VAR1! OBJ VAL
+
+ - Function: set-TAG-VAR2! OBJ VAL
+ ...
+
+ Here is an example of its use.
+
+ (define-record term (operator left right))
+ => #<unspecified>
+ (define foo (make-term 'plus 1 2))
+ => foo
+ (term->left foo)
+ => 1
+ (set-term-left! foo 2345)
+ => #<unspecified>
+ (term->left foo)
+ => 2345
+
+ - Macro: variant-case EXP (TAG (VAR1 VAR2 ...) BODY) ...
+ executes the following for the matching clause:
+
+ ((lambda (VAR1 VAR ...) BODY)
+ (TAG->VAR1 EXP)
+ (TAG->VAR2 EXP) ...)
+
+
+File: slib.info, Node: Procedures, Next: Standards Support, Prev: Data Structures, Up: Other Packages
+
+Procedures
+==========
+
+ Anything that doesn't fall neatly into any of the other categories
+winds up here.
+
+* Menu:
+
+* Common List Functions:: 'common-list-functions
+* Tree Operations:: 'tree
+* Chapter Ordering:: 'chapter-order
+* Sorting:: 'sort
+* Topological Sort:: Keep your socks on.
+* String-Case:: 'string-case
+* String Ports:: 'string-port
+* String Search:: Also Search from a Port.
+* Line I/O:: 'line-i/o
+* Multi-Processing:: 'process
+
+
+File: slib.info, Node: Common List Functions, Next: Tree Operations, Prev: Procedures, Up: Procedures
+
+Common List Functions
+---------------------
+
+ `(require 'common-list-functions)'
+
+ The procedures below follow the Common LISP equivalents apart from
+optional arguments in some cases.
+
+* Menu:
+
+* List construction::
+* Lists as sets::
+* Lists as sequences::
+* Destructive list operations::
+* Non-List functions::
+
+
+File: slib.info, Node: List construction, Next: Lists as sets, Prev: Common List Functions, Up: Common List Functions
+
+List construction
+.................
+
+ - Function: make-list K . INIT
+ `make-list' creates and returns a list of K elements. If INIT is
+ included, all elements in the list are initialized to INIT.
+
+ Example:
+ (make-list 3)
+ => (#<unspecified> #<unspecified> #<unspecified>)
+ (make-list 5 'foo)
+ => (foo foo foo foo foo)
+
+ - Function: list* X . Y
+ Works like `list' except that the cdr of the last pair is the last
+ argument unless there is only one argument, when the result is
+ just that argument. Sometimes called `cons*'. E.g.:
+ (list* 1)
+ => 1
+ (list* 1 2 3)
+ => (1 2 . 3)
+ (list* 1 2 '(3 4))
+ => (1 2 3 4)
+ (list* ARGS '())
+ == (list ARGS)
+
+ - Function: copy-list LST
+ `copy-list' makes a copy of LST using new pairs and returns it.
+ Only the top level of the list is copied, i.e., pairs forming
+ elements of the copied list remain `eq?' to the corresponding
+ elements of the original; the copy is, however, not `eq?' to the
+ original, but is `equal?' to it.
+
+ Example:
+ (copy-list '(foo foo foo))
+ => (foo foo foo)
+ (define q '(foo bar baz bang))
+ (define p q)
+ (eq? p q)
+ => #t
+ (define r (copy-list q))
+ (eq? q r)
+ => #f
+ (equal? q r)
+ => #t
+ (define bar '(bar))
+ (eq? bar (car (copy-list (list bar 'foo))))
+ => #t
+
+
+File: slib.info, Node: Lists as sets, Next: Lists as sequences, Prev: List construction, Up: Common List Functions
+
+Lists as sets
+.............
+
+ `eqv?' is used to test for membership by procedures which treat lists
+as sets.
+
+ - Function: adjoin E L
+ `adjoin' returns the adjoint of the element E and the list L.
+ That is, if E is in L, `adjoin' returns L, otherwise, it returns
+ `(cons E L)'.
+
+ Example:
+ (adjoin 'baz '(bar baz bang))
+ => (bar baz bang)
+ (adjoin 'foo '(bar baz bang))
+ => (foo bar baz bang)
+
+ - Function: union L1 L2
+ `union' returns the combination of L1 and L2. Duplicates between
+ L1 and L2 are culled. Duplicates within L1 or within L2 may or
+ may not be removed.
+
+ Example:
+ (union '(1 2 3 4) '(5 6 7 8))
+ => (4 3 2 1 5 6 7 8)
+ (union '(1 2 3 4) '(3 4 5 6))
+ => (2 1 3 4 5 6)
+
+ - Function: intersection L1 L2
+ `intersection' returns all elements that are in both L1 and L2.
+
+ Example:
+ (intersection '(1 2 3 4) '(3 4 5 6))
+ => (3 4)
+ (intersection '(1 2 3 4) '(5 6 7 8))
+ => ()
+
+ - Function: set-difference L1 L2
+ `set-difference' returns the union of all elements that are in L1
+ but not in L2.
+
+ Example:
+ (set-difference '(1 2 3 4) '(3 4 5 6))
+ => (1 2)
+ (set-difference '(1 2 3 4) '(1 2 3 4 5 6))
+ => ()
+
+ - Function: member-if PRED LST
+ `member-if' returns LST if `(PRED ELEMENT)' is `#t' for any
+ ELEMENT in LST. Returns `#f' if PRED does not apply to any
+ ELEMENT in LST.
+
+ Example:
+ (member-if vector? '(1 2 3 4))
+ => #f
+ (member-if number? '(1 2 3 4))
+ => (1 2 3 4)
+
+ - Function: some PRED LST . MORE-LSTS
+ PRED is a boolean function of as many arguments as there are list
+ arguments to `some' i.e., LST plus any optional arguments. PRED
+ is applied to successive elements of the list arguments in order.
+ `some' returns `#t' as soon as one of these applications returns
+ `#t', and is `#f' if none returns `#t'. All the lists should have
+ the same length.
+
+ Example:
+ (some odd? '(1 2 3 4))
+ => #t
+
+ (some odd? '(2 4 6 8))
+ => #f
+
+ (some > '(2 3) '(1 4))
+ => #f
+
+ - Function: every PRED LST . MORE-LSTS
+ `every' is analogous to `some' except it returns `#t' if every
+ application of PRED is `#t' and `#f' otherwise.
+
+ Example:
+ (every even? '(1 2 3 4))
+ => #f
+
+ (every even? '(2 4 6 8))
+ => #t
+
+ (every > '(2 3) '(1 4))
+ => #f
+
+ - Function: notany PRED . LST
+ `notany' is analogous to `some' but returns `#t' if no application
+ of PRED returns `#t' or `#f' as soon as any one does.
+
+ - Function: notevery PRED . LST
+ `notevery' is analogous to `some' but returns `#t' as soon as an
+ application of PRED returns `#f', and `#f' otherwise.
+
+ Example:
+ (notevery even? '(1 2 3 4))
+ => #t
+
+ (notevery even? '(2 4 6 8))
+ => #f
+
+ - Function: find-if PRED LST
+ `find-if' searches for the first ELEMENT in LST such that `(PRED
+ ELEMENT)' returns `#t'. If it finds any such ELEMENT in LST,
+ ELEMENT is returned. Otherwise, `#f' is returned.
+
+ Example:
+ (find-if number? '(foo 1 bar 2))
+ => 1
+
+ (find-if number? '(foo bar baz bang))
+ => #f
+
+ (find-if symbol? '(1 2 foo bar))
+ => foo
+
+ - Function: remove ELT LST
+ `remove' removes all occurrences of ELT from LST using `eqv?' to
+ test for equality and returns everything that's left. N.B.: other
+ implementations (Chez, Scheme->C and T, at least) use `equal?' as
+ the equality test.
+
+ Example:
+ (remove 1 '(1 2 1 3 1 4 1 5))
+ => (2 3 4 5)
+
+ (remove 'foo '(bar baz bang))
+ => (bar baz bang)
+
+ - Function: remove-if PRED LST
+ `remove-if' removes all ELEMENTs from LST where `(PRED ELEMENT)'
+ is `#t' and returns everything that's left.
+
+ Example:
+ (remove-if number? '(1 2 3 4))
+ => ()
+
+ (remove-if even? '(1 2 3 4 5 6 7 8))
+ => (1 3 5 7)
+
+ - Function: remove-if-not PRED LST
+ `remove-if-not' removes all ELEMENTs from LST for which `(PRED
+ ELEMENT)' is `#f' and returns everything that's left.
+
+ Example:
+ (remove-if-not number? '(foo bar baz))
+ => ()
+ (remove-if-not odd? '(1 2 3 4 5 6 7 8))
+ => (1 3 5 7)
+
+ - Function: has-duplicates? LST
+ returns `#t' if 2 members of LST are `equal?', `#f' otherwise.
+
+ Example:
+ (has-duplicates? '(1 2 3 4))
+ => #f
+
+ (has-duplicates? '(2 4 3 4))
+ => #t
+
+ The procedure `remove-duplicates' uses `member' (rather than `memv').
+
+ - Function: remove-duplicates LST
+ returns a copy of LST with its duplicate members removed.
+ Elements are considered duplicate if they are `equal?'.
+
+ Example:
+ (remove-duplicates '(1 2 3 4))
+ => (4 3 2 1)
+
+ (remove-duplicates '(2 4 3 4))
+ => (3 4 2)
+
+
+File: slib.info, Node: Lists as sequences, Next: Destructive list operations, Prev: Lists as sets, Up: Common List Functions
+
+Lists as sequences
+..................
+
+ - Function: position OBJ LST
+ `position' returns the 0-based position of OBJ in LST, or `#f' if
+ OBJ does not occur in LST.
+
+ Example:
+ (position 'foo '(foo bar baz bang))
+ => 0
+ (position 'baz '(foo bar baz bang))
+ => 2
+ (position 'oops '(foo bar baz bang))
+ => #f
+
+ - Function: reduce P LST
+ `reduce' combines all the elements of a sequence using a binary
+ operation (the combination is left-associative). For example,
+ using `+', one can add up all the elements. `reduce' allows you to
+ apply a function which accepts only two arguments to more than 2
+ objects. Functional programmers usually refer to this as "foldl".
+ `collect:reduce' (*note Collections::.) provides a version of
+ `collect' generalized to collections.
+
+ Example:
+ (reduce + '(1 2 3 4))
+ => 10
+ (define (bad-sum . l) (reduce + l))
+ (bad-sum 1 2 3 4)
+ == (reduce + (1 2 3 4))
+ == (+ (+ (+ 1 2) 3) 4)
+ => 10
+ (bad-sum)
+ == (reduce + ())
+ => ()
+ (reduce string-append '("hello" "cruel" "world"))
+ == (string-append (string-append "hello" "cruel") "world")
+ => "hellocruelworld"
+ (reduce anything '())
+ => ()
+ (reduce anything '(x))
+ => x
+
+ What follows is a rather non-standard implementation of `reverse'
+ in terms of `reduce' and a combinator elsewhere called "C".
+
+ ;;; Contributed by Jussi Piitulainen (jpiitula@ling.helsinki.fi)
+
+ (define commute
+ (lambda (f)
+ (lambda (x y)
+ (f y x))))
+
+ (define reverse
+ (lambda (args)
+ (reduce-init (commute cons) '() args)))
+
+ - Function: reduce-init P INIT LST
+ `reduce-init' is the same as reduce, except that it implicitly
+ inserts INIT at the start of the list. `reduce-init' is preferred
+ if you want to handle the null list, the one-element, and lists
+ with two or more elements consistently. It is common to use the
+ operator's idempotent as the initializer. Functional programmers
+ usually call this "foldl".
+
+ Example:
+ (define (sum . l) (reduce-init + 0 l))
+ (sum 1 2 3 4)
+ == (reduce-init + 0 (1 2 3 4))
+ == (+ (+ (+ (+ 0 1) 2) 3) 4)
+ => 10
+ (sum)
+ == (reduce-init + 0 '())
+ => 0
+
+ (reduce-init string-append "@" '("hello" "cruel" "world"))
+ ==
+ (string-append (string-append (string-append "@" "hello")
+ "cruel")
+ "world")
+ => "@hellocruelworld"
+
+ Given a differentiation of 2 arguments, `diff', the following will
+ differentiate by any number of variables.
+ (define (diff* exp . vars)
+ (reduce-init diff exp vars))
+
+ Example:
+ ;;; Real-world example: Insertion sort using reduce-init.
+
+ (define (insert l item)
+ (if (null? l)
+ (list item)
+ (if (< (car l) item)
+ (cons (car l) (insert (cdr l) item))
+ (cons item l))))
+ (define (insertion-sort l) (reduce-init insert '() l))
+
+ (insertion-sort '(3 1 4 1 5)
+ == (reduce-init insert () (3 1 4 1 5))
+ == (insert (insert (insert (insert (insert () 3) 1) 4) 1) 5)
+ == (insert (insert (insert (insert (3)) 1) 4) 1) 5)
+ == (insert (insert (insert (1 3) 4) 1) 5)
+ == (insert (insert (1 3 4) 1) 5)
+ == (insert (1 1 3 4) 5)
+ => (1 1 3 4 5)
+
+ - Function: last LST N
+ `last' returns the last N elements of LST. N must be a
+ non-negative integer.
+
+ Example:
+ (last '(foo bar baz bang) 2)
+ => (baz bang)
+ (last '(1 2 3) 0)
+ => 0
+
+ - Function: butlast LST N
+ `butlast' returns all but the last N elements of LST.
+
+ Example:
+ (butlast '(a b c d) 3)
+ => (a)
+ (butlast '(a b c d) 4)
+ => ()
+
+`last' and `butlast' split a list into two parts when given identical
+arugments.
+ (last '(a b c d e) 2)
+ => (d e)
+ (butlast '(a b c d e) 2)
+ => (a b c)
+
+ - Function: nthcdr N LST
+ `nthcdr' takes N `cdr's of LST and returns the result. Thus
+ `(nthcdr 3 LST)' == `(cdddr LST)'
+
+ Example:
+ (nthcdr 2 '(a b c d))
+ => (c d)
+ (nthcdr 0 '(a b c d))
+ => (a b c d)
+
+ - Function: butnthcdr N LST
+ `butnthcdr' returns all but the nthcdr N elements of LST.
+
+ Example:
+ (butnthcdr 3 '(a b c d))
+ => (a b c)
+ (butnthcdr 4 '(a b c d))
+ => ()
+
+`nthcdr' and `butnthcdr' split a list into two parts when given
+identical arugments.
+ (nthcdr 2 '(a b c d e))
+ => (c d e)
+ (butnthcdr 2 '(a b c d e))
+ => (a b)
+
+
+File: slib.info, Node: Destructive list operations, Next: Non-List functions, Prev: Lists as sequences, Up: Common List Functions
+
+Destructive list operations
+...........................
+
+ These procedures may mutate the list they operate on, but any such
+mutation is undefined.
+
+ - Procedure: nconc ARGS
+ `nconc' destructively concatenates its arguments. (Compare this
+ with `append', which copies arguments rather than destroying them.)
+ Sometimes called `append!' (*note Rev2 Procedures::.).
+
+ Example: You want to find the subsets of a set. Here's the
+ obvious way:
+
+ (define (subsets set)
+ (if (null? set)
+ '(())
+ (append (mapcar (lambda (sub) (cons (car set) sub))
+ (subsets (cdr set)))
+ (subsets (cdr set)))))
+ But that does way more consing than you need. Instead, you could
+ replace the `append' with `nconc', since you don't have any need
+ for all the intermediate results.
+
+ Example:
+ (define x '(a b c))
+ (define y '(d e f))
+ (nconc x y)
+ => (a b c d e f)
+ x
+ => (a b c d e f)
+
+ `nconc' is the same as `append!' in `sc2.scm'.
+
+ - Procedure: nreverse LST
+ `nreverse' reverses the order of elements in LST by mutating
+ `cdr's of the list. Sometimes called `reverse!'.
+
+ Example:
+ (define foo '(a b c))
+ (nreverse foo)
+ => (c b a)
+ foo
+ => (a)
+
+ Some people have been confused about how to use `nreverse',
+ thinking that it doesn't return a value. It needs to be pointed
+ out that
+ (set! lst (nreverse lst))
+
+ is the proper usage, not
+ (nreverse lst)
+ The example should suffice to show why this is the case.
+
+ - Procedure: delete ELT LST
+ - Procedure: delete-if PRED LST
+ - Procedure: delete-if-not PRED LST
+ Destructive versions of `remove' `remove-if', and `remove-if-not'.
+
+ Example:
+ (define lst '(foo bar baz bang))
+ (delete 'foo lst)
+ => (bar baz bang)
+ lst
+ => (foo bar baz bang)
+
+ (define lst '(1 2 3 4 5 6 7 8 9))
+ (delete-if odd? lst)
+ => (2 4 6 8)
+ lst
+ => (1 2 4 6 8)
+
+ Some people have been confused about how to use `delete',
+ `delete-if', and `delete-if', thinking that they dont' return a
+ value. It needs to be pointed out that
+ (set! lst (delete el lst))
+
+ is the proper usage, not
+ (delete el lst)
+ The examples should suffice to show why this is the case.
+
+
+File: slib.info, Node: Non-List functions, Prev: Destructive list operations, Up: Common List Functions
+
+Non-List functions
+..................
+
+ - Function: and? . ARGS
+ `and?' checks to see if all its arguments are true. If they are,
+ `and?' returns `#t', otherwise, `#f'. (In contrast to `and', this
+ is a function, so all arguments are always evaluated and in an
+ unspecified order.)
+
+ Example:
+ (and? 1 2 3)
+ => #t
+ (and #f 1 2)
+ => #f
+
+ - Function: or? . ARGS
+ `or?' checks to see if any of its arguments are true. If any is
+ true, `or?' returns `#t', and `#f' otherwise. (To `or' as `and?'
+ is to `and'.)
+
+ Example:
+ (or? 1 2 #f)
+ => #t
+ (or? #f #f #f)
+ => #f
+
+ - Function: atom? OBJECT
+ Returns `#t' if OBJECT is not a pair and `#f' if it is pair.
+ (Called `atom' in Common LISP.)
+ (atom? 1)
+ => #t
+ (atom? '(1 2))
+ => #f
+ (atom? #(1 2)) ; dubious!
+ => #t
+
+ - Function: type-of OBJECT
+ Returns a symbol name for the type of OBJECT.
+
+ - Function: coerce OBJECT RESULT-TYPE
+ Converts and returns OBJECT of type `char', `number', `string',
+ `symbol', `list', or `vector' to RESULT-TYPE (which must be one of
+ these symbols).
+
+
+File: slib.info, Node: Tree Operations, Next: Chapter Ordering, Prev: Common List Functions, Up: Procedures
+
+Tree operations
+---------------
+
+ `(require 'tree)'
+
+ These are operations that treat lists a representations of trees.
+
+ - Function: subst NEW OLD TREE
+ - Function: substq NEW OLD TREE
+ - Function: substv NEW OLD TREE
+ `subst' makes a copy of TREE, substituting NEW for every subtree
+ or leaf of TREE which is `equal?' to OLD and returns a modified
+ tree. The original TREE is unchanged, but may share parts with
+ the result.
+
+ `substq' and `substv' are similar, but test against OLD using
+ `eq?' and `eqv?' respectively.
+
+ Examples:
+ (substq 'tempest 'hurricane '(shakespeare wrote (the hurricane)))
+ => (shakespeare wrote (the tempest))
+ (substq 'foo '() '(shakespeare wrote (twelfth night)))
+ => (shakespeare wrote (twelfth night . foo) . foo)
+ (subst '(a . cons) '(old . pair)
+ '((old . spice) ((old . shoes) old . pair) (old . pair)))
+ => ((old . spice) ((old . shoes) a . cons) (a . cons))
+
+ - Function: copy-tree TREE
+ Makes a copy of the nested list structure TREE using new pairs and
+ returns it. All levels are copied, so that none of the pairs in
+ the tree are `eq?' to the original ones - only the leaves are.
+
+ Example:
+ (define bar '(bar))
+ (copy-tree (list bar 'foo))
+ => ((bar) foo)
+ (eq? bar (car (copy-tree (list bar 'foo))))
+ => #f
+
+
+File: slib.info, Node: Chapter Ordering, Next: Sorting, Prev: Tree Operations, Up: Procedures
+
+Chapter Ordering
+----------------
+
+ `(require 'chapter-order)'
+
+ The `chap:' functions deal with strings which are ordered like
+chapter numbers (or letters) in a book. Each section of the string
+consists of consecutive numeric or consecutive aphabetic characters of
+like case.
+
+ - Function: chap:string<? STRING1 STRING2
+ Returns #t if the first non-matching run of alphabetic upper-case
+ or the first non-matching run of alphabetic lower-case or the first
+ non-matching run of numeric characters of STRING1 is `string<?'
+ than the corresponding non-matching run of characters of STRING2.
+
+ (chap:string<? "a.9" "a.10") => #t
+ (chap:string<? "4c" "4aa") => #t
+ (chap:string<? "Revised^{3.99}" "Revised^{4}") => #t
+
+ - Function: chap:string>? STRING1 STRING2
+ - Function: chap:string<=? STRING1 STRING2
+ - Function: chap:string>=? STRING1 STRING2
+ Implement the corresponding chapter-order predicates.
+
+ - Function: chap:next-string STRING
+ Returns the next string in the *chapter order*. If STRING has no
+ alphabetic or numeric characters, `(string-append STRING "0")' is
+ returnd. The argument to chap:next-string will always be
+ `chap:string<?' than the result.
+
+ (chap:next-string "a.9") => "a.10"
+ (chap:next-string "4c") => "4d"
+ (chap:next-string "4z") => "4aa"
+ (chap:next-string "Revised^{4}") => "Revised^{5}"
+
+
+File: slib.info, Node: Sorting, Next: Topological Sort, Prev: Chapter Ordering, Up: Procedures
+
+Sorting
+-------
+
+ `(require 'sort)'
+
+ Many Scheme systems provide some kind of sorting functions. They do
+not, however, always provide the *same* sorting functions, and those
+that I have had the opportunity to test provided inefficient ones (a
+common blunder is to use quicksort which does not perform well).
+
+ Because `sort' and `sort!' are not in the standard, there is very
+little agreement about what these functions look like. For example,
+Dybvig says that Chez Scheme provides
+ (merge predicate list1 list2)
+ (merge! predicate list1 list2)
+ (sort predicate list)
+ (sort! predicate list)
+
+while MIT Scheme 7.1, following Common LISP, offers unstable
+ (sort list predicate)
+
+TI PC Scheme offers
+ (sort! list/vector predicate?)
+
+and Elk offers
+ (sort list/vector predicate?)
+ (sort! list/vector predicate?)
+
+ Here is a comprehensive catalogue of the variations I have found.
+
+ 1. Both `sort' and `sort!' may be provided.
+
+ 2. `sort' may be provided without `sort!'.
+
+ 3. `sort!' may be provided without `sort'.
+
+ 4. Neither may be provided.
+
+ 5. The sequence argument may be either a list or a vector.
+
+ 6. The sequence argument may only be a list.
+
+ 7. The sequence argument may only be a vector.
+
+ 8. The comparison function may be expected to behave like `<'.
+
+ 9. The comparison function may be expected to behave like `<='.
+
+ 10. The interface may be `(sort predicate? sequence)'.
+
+ 11. The interface may be `(sort sequence predicate?)'.
+
+ 12. The interface may be `(sort sequence &optional (predicate? <))'.
+
+ 13. The sort may be stable.
+
+ 14. The sort may be unstable.
+
+ All of this variation really does not help anybody. A nice simple
+merge sort is both stable and fast (quite a lot faster than *quick*
+sort).
+
+ I am providing this source code with no restrictions at all on its use
+(but please retain D.H.D.Warren's credit for the original idea). You
+may have to rename some of these functions in order to use them in a
+system which already provides incompatible or inferior sorts. For each
+of the functions, only the top-level define needs to be edited to do
+that.
+
+ I could have given these functions names which would not clash with
+any Scheme that I know of, but I would like to encourage implementors to
+converge on a single interface, and this may serve as a hint. The
+argument order for all functions has been chosen to be as close to
+Common LISP as made sense, in order to avoid NIH-itis.
+
+ Each of the five functions has a required *last* parameter which is a
+comparison function. A comparison function `f' is a function of 2
+arguments which acts like `<'. For example,
+
+ (not (f x x))
+ (and (f x y) (f y z)) == (f x z)
+
+ The standard functions `<', `>', `char<?', `char>?', `char-ci<?',
+`char-ci>?', `string<?', `string>?', `string-ci<?', and `string-ci>?'
+are suitable for use as comparison functions. Think of `(less? x y)'
+as saying when `x' must *not* precede `y'.
+
+ - Function: sorted? SEQUENCE LESS?
+ Returns `#t' when the sequence argument is in non-decreasing order
+ according to LESS? (that is, there is no adjacent pair `... x y
+ ...' for which `(less? y x)').
+
+ Returns `#f' when the sequence contains at least one out-of-order
+ pair. It is an error if the sequence is neither a list nor a
+ vector.
+
+ - Function: merge LIST1 LIST2 LESS?
+ This merges two lists, producing a completely new list as result.
+ I gave serious consideration to producing a Common-LISP-compatible
+ version. However, Common LISP's `sort' is our `sort!' (well, in
+ fact Common LISP's `stable-sort' is our `sort!', merge sort is
+ *fast* as well as stable!) so adapting CL code to Scheme takes a
+ bit of work anyway. I did, however, appeal to CL to determine the
+ *order* of the arguments.
+
+ - Procedure: merge! LIST1 LIST2 LESS?
+ Merges two lists, re-using the pairs of LIST1 and LIST2 to build
+ the result. If the code is compiled, and LESS? constructs no new
+ pairs, no pairs at all will be allocated. The first pair of the
+ result will be either the first pair of LIST1 or the first pair of
+ LIST2, but you can't predict which.
+
+ The code of `merge' and `merge!' could have been quite a bit
+ simpler, but they have been coded to reduce the amount of work
+ done per iteration. (For example, we only have one `null?' test
+ per iteration.)
+
+ - Function: sort SEQUENCE LESS?
+ Accepts either a list or a vector, and returns a new sequence
+ which is sorted. The new sequence is the same type as the input.
+ Always `(sorted? (sort sequence less?) less?)'. The original
+ sequence is not altered in any way. The new sequence shares its
+ *elements* with the old one; no elements are copied.
+
+ - Procedure: sort! SEQUENCE LESS?
+ Returns its sorted result in the original boxes. If the original
+ sequence is a list, no new storage is allocated at all. If the
+ original sequence is a vector, the sorted elements are put back in
+ the same vector.
+
+ Some people have been confused about how to use `sort!', thinking
+ that it doesn't return a value. It needs to be pointed out that
+ (set! slist (sort! slist <))
+
+ is the proper usage, not
+ (sort! slist <)
+
+ Note that these functions do *not* accept a CL-style `:key' argument.
+A simple device for obtaining the same expressiveness is to define
+ (define (keyed less? key)
+ (lambda (x y) (less? (key x) (key y))))
+
+and then, when you would have written
+ (sort a-sequence #'my-less :key #'my-key)
+
+in Common LISP, just write
+ (sort! a-sequence (keyed my-less? my-key))
+
+in Scheme.
+
+
+File: slib.info, Node: Topological Sort, Next: String-Case, Prev: Sorting, Up: Procedures
+
+Topological Sort
+----------------
+
+ `(require 'topological-sort)' or `(require 'tsort)'
+
+The algorithm is inspired by Cormen, Leiserson and Rivest (1990)
+`Introduction to Algorithms', chapter 23.
+
+ - Function: tsort DAG PRED
+ - Function: topological-sort DAG PRED
+ where
+ DAG
+ is a list of sublists. The car of each sublist is a vertex.
+ The cdr is the adjacency list of that vertex, i.e. a list of
+ all vertices to which there exists an edge from the car
+ vertex.
+
+ PRED
+ is one of `eq?', `eqv?', `equal?', `=', `char=?',
+ `char-ci=?', `string=?', or `string-ci=?'.
+
+ Sort the directed acyclic graph DAG so that for every edge from
+ vertex U to V, U will come before V in the resulting list of
+ vertices.
+
+ Time complexity: O (|V| + |E|)
+
+ Example (from Cormen):
+ Prof. Bumstead topologically sorts his clothing when getting
+ dressed. The first argument to `tsort' describes which
+ garments he needs to put on before others. (For example,
+ Prof Bumstead needs to put on his shirt before he puts on his
+ tie or his belt.) `tsort' gives the correct order of
+ dressing:
+
+ (require 'tsort)
+ (tsort '((shirt tie belt)
+ (tie jacket)
+ (belt jacket)
+ (watch)
+ (pants shoes belt)
+ (undershorts pants shoes)
+ (socks shoes))
+ eq?)
+ =>
+ (socks undershorts pants shoes watch shirt belt tie jacket)
+
+
+File: slib.info, Node: String-Case, Next: String Ports, Prev: Topological Sort, Up: Procedures
+
+String-Case
+-----------
+
+ `(require 'string-case)'
+
+ - Procedure: string-upcase STR
+ - Procedure: string-downcase STR
+ - Procedure: string-capitalize STR
+ The obvious string conversion routines. These are non-destructive.
+
+ - Function: string-upcase! STR
+ - Function: string-downcase! STR
+ - Function: string-captialize! STR
+ The destructive versions of the functions above.
+
+ - Function: string-ci->symbol STR
+ Converts string STR to a symbol having the same case as if the
+ symbol had been `read'.
+
+
+File: slib.info, Node: String Ports, Next: String Search, Prev: String-Case, Up: Procedures
+
+String Ports
+------------
+
+ `(require 'string-port)'
+
+ - Procedure: call-with-output-string PROC
+ PROC must be a procedure of one argument. This procedure calls
+ PROC with one argument: a (newly created) output port. When the
+ function returns, the string composed of the characters written
+ into the port is returned.
+
+ - Procedure: call-with-input-string STRING PROC
+ PROC must be a procedure of one argument. This procedure calls
+ PROC with one argument: an (newly created) input port from which
+ STRING's contents may be read. When PROC returns, the port is
+ closed and the value yielded by the procedure PROC is returned.
+
+
+File: slib.info, Node: String Search, Next: Line I/O, Prev: String Ports, Up: Procedures
+
+String Search
+-------------
+
+ `(require 'string-search)'
+
+ - Procedure: string-index STRING CHAR
+ - Procedure: string-index-ci STRING CHAR
+ Returns the index of the first occurence of CHAR within STRING, or
+ `#f' if the STRING does not contain a character CHAR.
+
+ - Procedure: string-reverse-index STRING CHAR
+ - Procedure: string-reverse-index-ci STRING CHAR
+ Returns the index of the last occurence of CHAR within STRING, or
+ `#f' if the STRING does not contain a character CHAR.
+
+ - procedure: substring? PATTERN STRING
+ - procedure: substring-ci? PATTERN STRING
+ Searches STRING to see if some substring of STRING is equal to
+ PATTERN. `substring?' returns the index of the first character of
+ the first substring of STRING that is equal to PATTERN; or `#f' if
+ STRING does not contain PATTERN.
+
+ (substring? "rat" "pirate") => 2
+ (substring? "rat" "outrage") => #f
+ (substring? "" any-string) => 0
+
+ - Procedure: find-string-from-port? STR IN-PORT MAX-NO-CHARS
+ Looks for a string STR within the first MAX-NO-CHARS chars of the
+ input port IN-PORT.
+
+ - Procedure: find-string-from-port? STR IN-PORT
+ When called with two arguments, the search span is limited by the
+ end of the input stream.
+
+ - Procedure: find-string-from-port? STR IN-PORT CHAR
+ Searches up to the first occurrence of character CHAR in STR.
+
+ - Procedure: find-string-from-port? STR IN-PORT PROC
+ Searches up to the first occurrence of the procedure PROC
+ returning non-false when called with a character (from IN-PORT)
+ argument.
+
+ When the STR is found, `find-string-from-port?' returns the number
+ of characters it has read from the port, and the port is set to
+ read the first char after that (that is, after the STR) The
+ function returns `#f' when the STR isn't found.
+
+ `find-string-from-port?' reads the port *strictly* sequentially,
+ and does not perform any buffering. So `find-string-from-port?'
+ can be used even if the IN-PORT is open to a pipe or other
+ communication channel.
+
+ - Function: string-subst TXT OLD1 NEW1 ...
+ Returns a copy of string TXT with all occurrences of string OLD1
+ in TXT replaced with NEW1, OLD2 replaced with NEW2 ....
+
+
+File: slib.info, Node: Line I/O, Next: Multi-Processing, Prev: String Search, Up: Procedures
+
+Line I/O
+--------
+
+ `(require 'line-i/o)'
+
+ - Function: read-line
+ - Function: read-line PORT
+ Returns a string of the characters up to, but not including a
+ newline or end of file, updating PORT to point to the character
+ following the newline. If no characters are available, an end of
+ file object is returned. The PORT argument may be omitted, in
+ which case it defaults to the value returned by
+ `current-input-port'.
+
+ - Function: read-line! STRING
+ - Function: read-line! STRING PORT
+ Fills STRING with characters up to, but not including a newline or
+ end of file, updating the PORT to point to the last character read
+ or following the newline if it was read. If no characters are
+ available, an end of file object is returned. If a newline or end
+ of file was found, the number of characters read is returned.
+ Otherwise, `#f' is returned. The PORT argument may be omitted, in
+ which case it defaults to the value returned by
+ `current-input-port'.
+
+ - Function: write-line STRING
+ - Function: write-line STRING PORT
+ Writes STRING followed by a newline to the given PORT and returns
+ an unspecified value. The PORT argument may be omited, in which
+ case it defaults to the value returned by `current-input-port'.
+
+ - Function: display-file PATH
+ - Function: display-file PATH PORT
+ Displays the contents of the file named by PATH to PORT. The PORT
+ argument may be ommited, in which case it defaults to the value
+ returned by `current-output-port'.
+
+
+File: slib.info, Node: Multi-Processing, Prev: Line I/O, Up: Procedures
+
+Multi-Processing
+----------------
+
+ `(require 'process)'
+
+ This module implements asynchronous (non-polled) time-sliced
+multi-processing in the SCM Scheme implementation using procedures
+`alarm' and `alarm-interrupt'. Until this is ported to another
+implementation, consider it an example of writing schedulers in Scheme.
+
+ - Procedure: add-process! PROC
+ Adds proc, which must be a procedure (or continuation) capable of
+ accepting accepting one argument, to the `process:queue'. The
+ value returned is unspecified. The argument to PROC should be
+ ignored. If PROC returns, the process is killed.
+
+ - Procedure: process:schedule!
+ Saves the current process on `process:queue' and runs the next
+ process from `process:queue'. The value returned is unspecified.
+
+ - Procedure: kill-process!
+ Kills the current process and runs the next process from
+ `process:queue'. If there are no more processes on
+ `process:queue', `(slib:exit)' is called (*note System::.).
+
+
+File: slib.info, Node: Standards Support, Next: Session Support, Prev: Procedures, Up: Other Packages
+
+Standards Support
+=================
+
+* Menu:
+
+* With-File:: 'with-file
+* Transcripts:: 'transcript
+* Rev2 Procedures:: 'rev2-procedures
+* Rev4 Optional Procedures:: 'rev4-optional-procedures
+* Multi-argument / and -:: 'multiarg/and-
+* Multi-argument Apply:: 'multiarg-apply
+* Rationalize:: 'rationalize
+* Promises:: 'promise
+* Dynamic-Wind:: 'dynamic-wind
+* Eval:: 'eval
+* Values:: 'values
+
+
+File: slib.info, Node: With-File, Next: Transcripts, Prev: Standards Support, Up: Standards Support
+
+With-File
+---------
+
+ `(require 'with-file)'
+
+ - Function: with-input-from-file FILE THUNK
+ - Function: with-output-to-file FILE THUNK
+ Description found in R4RS.
+
+
+File: slib.info, Node: Transcripts, Next: Rev2 Procedures, Prev: With-File, Up: Standards Support
+
+Transcripts
+-----------
+
+ `(require 'transcript)'
+
+ - Function: transcript-on FILENAME
+ - Function: transcript-off FILENAME
+ Redefines `read-char', `read', `write-char', `write', `display',
+ and `newline'.
+
+
+File: slib.info, Node: Rev2 Procedures, Next: Rev4 Optional Procedures, Prev: Transcripts, Up: Standards Support
+
+Rev2 Procedures
+---------------
+
+ `(require 'rev2-procedures)'
+
+ The procedures below were specified in the `Revised^2 Report on
+Scheme'. *N.B.*: The symbols `1+' and `-1+' are not `R4RS' syntax.
+Scheme->C, for instance, barfs on this module.
+
+ - Procedure: substring-move-left! STRING1 START1 END1 STRING2 START2
+ - Procedure: substring-move-right! STRING1 START1 END1 STRING2 START2
+ STRING1 and STRING2 must be a strings, and START1, START2 and END1
+ must be exact integers satisfying
+
+ 0 <= START1 <= END1 <= (string-length STRING1)
+ 0 <= START2 <= END1 - START1 + START2 <= (string-length STRING2)
+
+ `substring-move-left!' and `substring-move-right!' store
+ characters of STRING1 beginning with index START1 (inclusive) and
+ ending with index END1 (exclusive) into STRING2 beginning with
+ index START2 (inclusive).
+
+ `substring-move-left!' stores characters in time order of
+ increasing indices. `substring-move-right!' stores characters in
+ time order of increasing indeces.
+
+ - Procedure: substring-fill! STRING START END CHAR
+ Fills the elements START-END of STRING with the character CHAR.
+
+ - Function: string-null? STR
+ == `(= 0 (string-length STR))'
+
+ - Procedure: append! . PAIRS
+ Destructively appends its arguments. Equivalent to `nconc'.
+
+ - Function: 1+ N
+ Adds 1 to N.
+
+ - Function: -1+ N
+ Subtracts 1 from N.
+
+ - Function: <?
+ - Function: <=?
+ - Function: =?
+ - Function: >?
+ - Function: >=?
+ These are equivalent to the procedures of the same name but
+ without the trailing `?'.
+
+
+File: slib.info, Node: Rev4 Optional Procedures, Next: Multi-argument / and -, Prev: Rev2 Procedures, Up: Standards Support
+
+Rev4 Optional Procedures
+------------------------
+
+ `(require 'rev4-optional-procedures)'
+
+ For the specification of these optional procedures, *Note Standard
+procedures: (r4rs)Standard procedures.
+
+ - Function: list-tail L P
+
+ - Function: string->list S
+
+ - Function: list->string L
+
+ - Function: string-copy
+
+ - Procedure: string-fill! S OBJ
+
+ - Function: list->vector L
+
+ - Function: vector->list S
+
+ - Procedure: vector-fill! S OBJ
+
+
+File: slib.info, Node: Multi-argument / and -, Next: Multi-argument Apply, Prev: Rev4 Optional Procedures, Up: Standards Support
+
+Multi-argument / and -
+----------------------
+
+ `(require 'mutliarg/and-)'
+
+ For the specification of these optional forms, *Note Numerical
+operations: (r4rs)Numerical operations. The `two-arg:'* forms are only
+defined if the implementation does not support the many-argument forms.
+
+ - Function: two-arg:/ N1 N2
+ The original two-argument version of `/'.
+
+ - Function: / DIVIDENT . DIVISORS
+
+ - Function: two-arg:- N1 N2
+ The original two-argument version of `-'.
+
+ - Function: - MINUEND . SUBTRAHENDS
+
+
+File: slib.info, Node: Multi-argument Apply, Next: Rationalize, Prev: Multi-argument / and -, Up: Standards Support
+
+Multi-argument Apply
+--------------------
+
+ `(require 'multiarg-apply)'
+
+For the specification of this optional form, *Note Control features:
+(r4rs)Control features.
+
+ - Function: two-arg:apply PROC L
+ The implementation's native `apply'. Only defined for
+ implementations which don't support the many-argument version.
+
+ - Function: apply PROC . ARGS
+
+
+File: slib.info, Node: Rationalize, Next: Promises, Prev: Multi-argument Apply, Up: Standards Support
+
+Rationalize
+-----------
+
+ `(require 'rationalize)'
+
+ The procedure rationalize is interesting because most programming
+languages do not provide anything analogous to it. For simplicity, we
+present an algorithm which computes the correct result for exact
+arguments (provided the implementation supports exact rational numbers
+of unlimited precision), and produces a reasonable answer for inexact
+arguments when inexact arithmetic is implemented using floating-point.
+We thank Alan Bawden for contributing this algorithm.
+
+ - Function: rationalize X E
+
+
+File: slib.info, Node: Promises, Next: Dynamic-Wind, Prev: Rationalize, Up: Standards Support
+
+Promises
+--------
+
+ `(require 'promise)'
+
+ - Function: make-promise PROC
+
+ Change occurrences of `(delay EXPRESSION)' to `(make-promise (lambda
+() EXPRESSION))' and `(define force promise:force)' to implement
+promises if your implementation doesn't support them (*note Control
+features: (r4rs)Control features.).
+
+
+File: slib.info, Node: Dynamic-Wind, Next: Eval, Prev: Promises, Up: Standards Support
+
+Dynamic-Wind
+------------
+
+ `(require 'dynamic-wind)'
+
+ This facility is a generalization of Common LISP `unwind-protect',
+designed to take into account the fact that continuations produced by
+`call-with-current-continuation' may be reentered.
+
+ - Procedure: dynamic-wind THUNK1 THUNK2 THUNK3
+ The arguments THUNK1, THUNK2, and THUNK3 must all be procedures of
+ no arguments (thunks).
+
+ `dynamic-wind' calls THUNK1, THUNK2, and then THUNK3. The value
+ returned by THUNK2 is returned as the result of `dynamic-wind'.
+ THUNK3 is also called just before control leaves the dynamic
+ context of THUNK2 by calling a continuation created outside that
+ context. Furthermore, THUNK1 is called before reentering the
+ dynamic context of THUNK2 by calling a continuation created inside
+ that context. (Control is inside the context of THUNK2 if THUNK2
+ is on the current return stack).
+
+ *Warning:* There is no provision for dealing with errors or
+ interrupts. If an error or interrupt occurs while using
+ `dynamic-wind', the dynamic environment will be that in effect at
+ the time of the error or interrupt.
+
+
+File: slib.info, Node: Eval, Next: Values, Prev: Dynamic-Wind, Up: Standards Support
+
+Eval
+----
+
+ `(require 'eval)'
+
+ - Function: eval EXPRESSION ENVIRONMENT-SPECIFIER
+ Evaluates EXPRESSION in the specified environment and returns its
+ value. EXPRESSION must be a valid Scheme expression represented
+ as data, and ENVIRONMENT-SPECIFIER must be a value returned by one
+ of the three procedures described below. Implementations may
+ extend `eval' to allow non-expression programs (definitions) as
+ the first argument and to allow other values as environments, with
+ the restriction that `eval' is not allowed to create new bindings
+ in the environments associated with `null-environment' or
+ `scheme-report-environment'.
+
+ (eval '(* 7 3) (scheme-report-environment 5))
+ => 21
+
+ (let ((f (eval '(lambda (f x) (f x x))
+ (null-environment))))
+ (f + 10))
+ => 20
+
+ - Function: scheme-report-environment VERSION
+ - Function: null-environment VERSION
+ - Function: null-environment
+ VERSION must be an exact non-negative integer N corresponding to a
+ version of one of the Revised^N Reports on Scheme.
+ `Scheme-report-environment' returns a specifier for an environment
+ that contains the set of bindings specified in the corresponding
+ report that the implementation supports. `Null-environment'
+ returns a specifier for an environment that contains only the
+ (syntactic) bindings for all the syntactic keywords defined in the
+ given version of the report.
+
+ Not all versions may be available in all implementations at all
+ times. However, an implementation that conforms to version N of
+ the Revised^N Reports on Scheme must accept version N. An error
+ is signalled if the specified version is not available.
+
+ The effect of assigning (through the use of `eval') a variable
+ bound in a `scheme-report-environment' (for example `car') is
+ unspecified. Thus the environments specified by
+ `scheme-report-environment' may be immutable.
+
+
+ - Function: interaction-environment
+ This optional procedure returns a specifier for the environment
+ that contains implementation-defined bindings, typically a
+ superset of those listed in the report. The intent is that this
+ procedure will return the environment in which the implementation
+ would evaluate expressions dynamically typed by the user.
+
+Here are some more `eval' examples:
+
+ (require 'eval)
+ => #<unspecified>
+ (define car 'volvo)
+ => #<unspecified>
+ car
+ => volvo
+ (eval 'car (interaction-environment))
+ => volvo
+ (eval 'car (scheme-report-environment 5))
+ => #<primitive-procedure car>
+ (eval '(eval 'car (interaction-environment))
+ (scheme-report-environment 5))
+ => volvo
+ (eval '(eval '(set! car 'buick) (interaction-environment))
+ (scheme-report-environment 5))
+ => #<unspecified>
+ car
+ => buick
+ (eval 'car (scheme-report-environment 5))
+ => #<primitive-procedure car>
+ (eval '(eval 'car (interaction-environment))
+ (scheme-report-environment 5))
+ => buick
+
+
+File: slib.info, Node: Values, Prev: Eval, Up: Standards Support
+
+Values
+------
+
+ `(require 'values)'
+
+ - Function: values OBJ ...
+ `values' takes any number of arguments, and passes (returns) them
+ to its continuation.
+
+ - Function: call-with-values THUNK PROC
+ THUNK must be a procedure of no arguments, and PROC must be a
+ procedure. `call-with-values' calls THUNK with a continuation
+ that, when passed some values, calls PROC with those values as
+ arguments.
+
+ Except for continuations created by the `call-with-values'
+ procedure, all continuations take exactly one value, as now; the
+ effect of passing no value or more than one value to continuations
+ that were not created by the `call-with-values' procedure is
+ unspecified.
+
+
+File: slib.info, Node: Session Support, Next: Extra-SLIB Packages, Prev: Standards Support, Up: Other Packages
+
+Session Support
+===============
+
+* Menu:
+
+* Repl:: Macros at top-level
+* Quick Print:: Loop-safe Output
+* Debug:: To err is human ...
+* Breakpoints:: Pause execution
+* Trace:: 'trace
+* System Interface:: 'system, 'getenv, and 'net-clients
+
+
+File: slib.info, Node: Repl, Next: Quick Print, Prev: Session Support, Up: Session Support
+
+Repl
+----
+
+ `(require 'repl)'
+
+ Here is a read-eval-print-loop which, given an eval, evaluates forms.
+
+ - Procedure: repl:top-level REPL:EVAL
+ `read's, `repl:eval's and `write's expressions from
+ `(current-input-port)' to `(current-output-port)' until an
+ end-of-file is encountered. `load', `slib:eval', `slib:error',
+ and `repl:quit' dynamically bound during `repl:top-level'.
+
+ - Procedure: repl:quit
+ Exits from the invocation of `repl:top-level'.
+
+ The `repl:' procedures establish, as much as is possible to do
+portably, a top level environment supporting macros. `repl:top-level'
+uses `dynamic-wind' to catch error conditions and interrupts. If your
+implementation supports this you are all set.
+
+ Otherwise, if there is some way your implementation can catch error
+conditions and interrupts, then have them call `slib:error'. It will
+display its arguments and reenter `repl:top-level'. `slib:error'
+dynamically bound by `repl:top-level'.
+
+ To have your top level loop always use macros, add any interrupt
+catching lines and the following lines to your Scheme init file:
+ (require 'macro)
+ (require 'repl)
+ (repl:top-level macro:eval)
+
+
+File: slib.info, Node: Quick Print, Next: Debug, Prev: Repl, Up: Session Support
+
+Quick Print
+-----------
+
+ `(require 'qp)'
+
+When displaying error messages and warnings, it is paramount that the
+output generated for circular lists and large data structures be
+limited. This section supplies a procedure to do this. It could be
+much improved.
+
+ Notice that the neccessity for truncating output eliminates
+ Common-Lisp's *Note Format:: from consideration; even when
+ variables `*print-level*' and `*print-level*' are set, huge
+ strings and bit-vectors are *not* limited.
+
+ - Procedure: qp ARG1 ...
+ - Procedure: qpn ARG1 ...
+ - Procedure: qpr ARG1 ...
+ `qp' writes its arguments, separated by spaces, to
+ `(current-output-port)'. `qp' compresses printing by substituting
+ `...' for substructure it does not have sufficient room to print.
+ `qpn' is like `qp' but outputs a newline before returning. `qpr'
+ is like `qpn' except that it returns its last argument.
+
+ - Variable: *qp-width*
+ `*qp-width*' is the largest number of characters that `qp' should
+ use.
+
+
+File: slib.info, Node: Debug, Next: Breakpoints, Prev: Quick Print, Up: Session Support
+
+Debug
+-----
+
+ `(require 'debug)'
+
+Requiring `debug' automatically requires `trace' and `break'.
+
+An application with its own datatypes may want to substitute its own
+printer for `qp'. This example shows how to do this:
+
+ (define qpn (lambda args) ...)
+ (provide 'qp)
+ (require 'debug)
+
+ - Procedure: trace-all FILE
+ Traces (*note Trace::.) all procedures `define'd at top-level in
+ file `file'.
+
+ - Procedure: break-all FILE
+ Breakpoints (*note Breakpoints::.) all procedures `define'd at
+ top-level in file `file'.
+
+
+File: slib.info, Node: Breakpoints, Next: Trace, Prev: Debug, Up: Session Support
+
+Breakpoints
+-----------
+
+ `(require 'break)'
+
+ - Function: init-debug
+ If your Scheme implementation does not support `break' or `abort',
+ a message will appear when you `(require 'break)' or `(require
+ 'debug)' telling you to type `(init-debug)'. This is in order to
+ establish a top-level continuation. Typing `(init-debug)' at top
+ level sets up a continuation for `break'.
+
+ - Function: breakpoint ARG1 ...
+ Returns from the top level continuation and pushes the
+ continuation from which it was called on a continuation stack.
+
+ - Function: continue
+ Pops the topmost continuation off of the continuation stack and
+ returns an unspecified value to it.
+
+ - Function: continue ARG1 ...
+ Pops the topmost continuation off of the continuation stack and
+ returns ARG1 ... to it.
+
+ - Macro: break PROC1 ...
+ Redefines the top-level named procedures given as arguments so that
+ `breakpoint' is called before calling PROC1 ....
+
+ - Macro: break
+ With no arguments, makes sure that all the currently broken
+ identifiers are broken (even if those identifiers have been
+ redefined) and returns a list of the broken identifiers.
+
+ - Macro: unbreak PROC1 ...
+ Turns breakpoints off for its arguments.
+
+ - Macro: unbreak
+ With no arguments, unbreaks all currently broken identifiers and
+ returns a list of these formerly broken identifiers.
+
+ The following routines are the procedures which actually do the
+tracing when this module is supplied by SLIB, rather than natively. If
+defmacros are not natively supported by your implementation, these might
+be more convenient to use.
+
+ - Function: breakf PROC
+ - Function: breakf PROC NAME
+ - Function: debug:breakf PROC
+ - Function: debug:breakf PROC NAME
+ To break, type
+ (set! SYMBOL (breakf SYMBOL))
+
+ or
+ (set! SYMBOL (breakf SYMBOL 'SYMBOL))
+
+ or
+ (define SYMBOL (breakf FUNCTION))
+
+ or
+ (define SYMBOL (breakf FUNCTION 'SYMBOL))
+
+ - Function: unbreakf PROC
+ - Function: debug:unbreakf PROC
+ To unbreak, type
+ (set! SYMBOL (unbreakf SYMBOL))
+
+
+File: slib.info, Node: Trace, Next: System Interface, Prev: Breakpoints, Up: Session Support
+
+Tracing
+-------
+
+ `(require 'trace)'
+
+ - Macro: trace PROC1 ...
+ Traces the top-level named procedures given as arguments.
+
+ - Macro: trace
+ With no arguments, makes sure that all the currently traced
+ identifiers are traced (even if those identifiers have been
+ redefined) and returns a list of the traced identifiers.
+
+ - Macro: untrace PROC1 ...
+ Turns tracing off for its arguments.
+
+ - Macro: untrace
+ With no arguments, untraces all currently traced identifiers and
+ returns a list of these formerly traced identifiers.
+
+ The following routines are the procedures which actually do the
+tracing when this module is supplied by SLIB, rather than natively. If
+defmacros are not natively supported by your implementation, these might
+be more convenient to use.
+
+ - Function: tracef PROC
+ - Function: tracef PROC NAME
+ - Function: debug:tracef PROC
+ - Function: debug:tracef PROC NAME
+ To trace, type
+ (set! SYMBOL (tracef SYMBOL))
+
+ or
+ (set! SYMBOL (tracef SYMBOL 'SYMBOL))
+
+ or
+ (define SYMBOL (tracef FUNCTION))
+
+ or
+ (define SYMBOL (tracef FUNCTION 'SYMBOL))
+
+ - Function: untracef PROC
+ - Function: debug:untracef PROC
+ To untrace, type
+ (set! SYMBOL (untracef SYMBOL))
+
+
+File: slib.info, Node: System Interface, Prev: Trace, Up: Session Support
+
+System Interface
+----------------
+
+If `(provided? 'getenv)':
+
+ - Function: getenv NAME
+ Looks up NAME, a string, in the program environment. If NAME is
+ found a string of its value is returned. Otherwise, `#f' is
+ returned.
+
+If `(provided? 'system)':
+
+ - Function: system COMMAND-STRING
+ Executes the COMMAND-STRING on the computer and returns the
+ integer status code.
+
+If `system' is provided by the Scheme implementation, the "net-clients"
+package provides interfaces to common network client programs like FTP,
+mail, and Netscape.
+
+ `(require 'net-clients)'
+
+ - Function: call-with-tmpnam PROC
+ - Function: call-with-tmpnam PROC K
+ Calls PROC with K arguments, strings returned by successive calls
+ to `tmpnam'. If PROC returns, then any files named by the
+ arguments to PROC are deleted automatically and the value(s)
+ yielded by the PROC is(are) returned. K may be ommited, in which
+ case it defaults to `1'.
+
+ - Function: user-email-address
+ `user-email-address' returns a string of the form
+ `username@hostname'. If this e-mail address cannot be obtained,
+ #f is returned.
+
+ - Function: current-directory
+ `current-directory' returns a string containing the absolute file
+ name representing the current working directory. If this string
+ cannot be obtained, #f is returned.
+
+ If `current-directory' cannot be supported by the platform, the
+ value of `current-directory' is #f.
+
+ - Function: make-directory NAME
+ Creates a sub-directory NAME of the current-directory. If
+ successful, `make-directory' returns #t; otherwise #f.
+
+ - Function: null-directory? FILE-NAME
+ Returns #t if changing directory to FILE-NAME makes the current
+ working directory the same as it is before changing directory;
+ otherwise returns #f.
+
+ - Function: absolute-path? FILE-NAME
+ Returns #t if FILE-NAME is a fully specified pathname (does not
+ depend on the current working directory); otherwise returns #f.
+
+ - Function: glob-pattern? STR
+ Returns #t if the string STR contains characters used for
+ specifying glob patterns, namely `*', `?', or `['.
+
+ - Function: parse-ftp-address URL
+ Returns a list of the decoded FTP URL; or #f if indecipherable.
+ FTP "Uniform Resource Locator", "ange-ftp", and "getit" formats
+ are handled. The returned list has four elements which are
+ strings or #f:
+
+ 0. username
+
+ 1. password
+
+ 2. remote-site
+
+ 3. remote-directory
+
+ - Function: ftp-upload PATHS USER PASSWORD REMOTE-SITE REMOTE-DIR
+ PASSWORD must be a non-empty string or #f. PATHS must be a
+ non-empty list of pathnames or Glob patterns (*note Filenames::.)
+ matching files to transfer.
+
+ `ftp-upload' puts the files specified by PATHS into the REMOTE-DIR
+ directory of FTP REMOTE-SITE using name USER with (optional)
+ PASSWORD.
+
+ If PASSWORD is #f and USER is not `ftp' or `anonymous', then USER
+ is ignored; FTP takes the username and password from the `.netrc'
+ or equivalent file.
+
+ - Function: path->url PATH
+ Returns a URL-string for PATH on the local host.
+
+ - Function: browse-url-netscape URL
+ If a `netscape' browser is running, `browse-url-netscape' causes
+ the browser to display the page specified by string URL and
+ returns #t.
+
+ If the browser is not running, `browse-url-netscape' runs
+ `netscape' with the argument URL. If the browser starts as a |
+ background job, `browse-url-netscape' returns #t immediately; if |
+ the browser starts as a foreground job, then `browse-url-netscape' |
+ returns #t when the browser exits; otherwise it returns #f. |
+
+
+File: slib.info, Node: Extra-SLIB Packages, Prev: Session Support, Up: Other Packages
+
+Extra-SLIB Packages
+===================
+
+ Several Scheme packages have been written using SLIB. There are
+several reasons why a package might not be included in the SLIB
+distribution:
+ * Because it requires special hardware or software which is not
+ universal.
+
+ * Because it is large and of limited interest to most Scheme users.
+
+ * Because it has copying terms different enough from the other SLIB
+ packages that its inclusion would cause confusion.
+
+ * Because it is an application program, rather than a library module.
+
+ * Because I have been too busy to integrate it.
+
+ Once an optional package is installed (and an entry added to
+`*catalog*', the `require' mechanism allows it to be called up and used
+as easily as any other SLIB package. Some optional packages (for which
+`*catalog*' already has entries) available from SLIB sites are:
+
+SLIB-PSD is a portable debugger for Scheme (requires emacs editor).
+ http://swissnet.ai.mit.edu/ftpdir/scm/slib-psd1-3.tar.gz |
+ ftp.gnu.org:pub/gnu/jacal/slib-psd1-3.tar.gz
+ ftp.maths.tcd.ie:pub/bosullvn/jacal/slib-psd1-3.tar.gz
+ ftp.cs.indiana.edu:/pub/scheme-repository/utl/slib-psd1-3.tar.gz
+
+ With PSD, you can run a Scheme program in an Emacs buffer, set
+ breakpoints, single step evaluation and access and modify the
+ program's variables. It works by instrumenting the original source
+ code, so it should run with any R4RS compliant Scheme. It has been
+ tested with SCM, Elk 1.5, and the sci interpreter in the Scheme->C
+ system, but should work with other Schemes with a minimal amount
+ of porting, if at all. Includes documentation and user's manual.
+ Written by Pertti Kellom\"aki, pk@cs.tut.fi. The Lisp Pointers
+ article describing PSD (Lisp Pointers VI(1):15-23, January-March
+ 1993) is available as
+ `http://www.cs.tut.fi/staff/pk/scheme/psd/article/article.html'
+
+SCHELOG is an embedding of Prolog in Scheme.
+ `http://www.cs.rice.edu/CS/PLT/packages/schelog/'
+
+
+File: slib.info, Node: About SLIB, Next: Index, Prev: Other Packages, Up: Top
+
+About SLIB
+**********
+
+More people than I can name have contributed to SLIB. Thanks to all of |
+you! |
+ |
+ SLIB 2c7, released December 1999. |
+ Aubrey Jaffer <jaffer @ ai.mit.edu> |
+ Hyperactive Software - The Maniac Inside! |
+ `http://swissnet.ai.mit.edu/~jaffer/SLIB.html' |
+ |
+* Menu:
+
+* Installation:: How to install SLIB on your system.
+* Porting:: SLIB to new platforms.
+* Coding Standards:: How to write modules for SLIB.
+* Copyrights:: Intellectual propery issues.
+ |
+
+File: slib.info, Node: Installation, Next: Porting, Prev: About SLIB, Up: About SLIB
+
+Installation
+============
+
+ Check the manifest in `README' to find a configuration file for your
+Scheme implementation. Initialization files for most IEEE P1178
+compliant Scheme Implementations are included with this distribution.
+
+ If the Scheme implementation supports `getenv', then the value of the
+shell environment variable SCHEME_LIBRARY_PATH will be used for
+`(library-vicinity)' if it is defined. Currently, Chez, Elk,
+MITScheme, scheme->c, VSCM, and SCM support `getenv'. Scheme48
+supports `getenv' but does not use it for determining
+`library-vicinity'. (That is done from the Makefile.)
+
+ You should check the definitions of `software-type',
+`scheme-implementation-version', `implementation-vicinity', and
+`library-vicinity' in the initialization file. There are comments in
+the file for how to configure it.
+
+ Once this is done you can modify the startup file for your Scheme
+implementation to `load' this initialization file. SLIB is then
+installed.
+
+ Multiple implementations of Scheme can all use the same SLIB
+directory. Simply configure each implementation's initialization file
+as outlined above.
+
+ The SCM implementation does not require any initialization file as
+SLIB support is already built in to SCM. See the documentation with
+SCM for installation instructions.
+
+ SLIB includes methods to create heap images for the VSCM and Scheme48
+implementations. The instructions for creating a VSCM image are in
+comments in `vscm.init'. To make a Scheme48 image for an installation
+under `<prefix>', `cd' to the SLIB directory and type `make
+prefix=<prefix> slib48'. To install the image, type `make
+prefix=<prefix> install48'. This will also create a shell script with
+the name `slib48' which will invoke the saved image.
+
+
+File: slib.info, Node: Porting, Next: Coding Standards, Prev: Installation, Up: About SLIB
+
+Porting
+=======
+
+ If there is no initialization file for your Scheme implementation, you
+will have to create one. Your Scheme implementation must be largely
+compliant with `IEEE Std 1178-1990', `Revised^4 Report on the
+Algorithmic Language Scheme', or `Revised^5 Report on the Algorithmic
+Language Scheme' in order to support SLIB. (1)
+
+ `Template.scm' is an example configuration file. The comments inside
+will direct you on how to customize it to reflect your system. Give
+your new initialization file the implementation's name with `.init'
+appended. For instance, if you were porting `foo-scheme' then the
+initialization file might be called `foo.init'.
+
+ Your customized version should then be loaded as part of your scheme
+implementation's initialization. It will load `require.scm' from the
+library; this will allow the use of `provide', `provided?', and
+`require' along with the "vicinity" functions (these functions are
+documented in the section *Note Require::). The rest of the library
+will then be accessible in a system independent fashion.
+
+ Please mail new working configuration files to `jaffer @ ai.mit.edu'
+so that they can be included in the SLIB distribution.
+
+ ---------- Footnotes ----------
+
+ (1) If you are porting a `Revised^3 Report on the Algorithmic
+Language Scheme' implementation, then you will need to finish writing
+`sc4sc3.scm' and `load' it from your initialization file.
+
+
+File: slib.info, Node: Coding Standards, Next: Copyrights, Prev: Porting, Up: About SLIB
+
+Coding Standards
+================
+
+ All library packages are written in IEEE P1178 Scheme and assume that
+a configuration file and `require.scm' package have already been
+loaded. Other versions of Scheme can be supported in library packages
+as well by using, for example, `(provided? 'rev3-report)' or `(require
+'rev3-report)' (*note Require::.).
+
+ The module name and `:' should prefix each symbol defined in the
+package. Definitions for external use should then be exported by having
+`(define foo module-name:foo)'.
+
+ Code submitted for inclusion in SLIB should not duplicate routines
+already in SLIB files. Use `require' to force those library routines
+to be used by your package. Care should be taken that there are no
+circularities in the `require's and `load's between the library
+packages.
+
+ Documentation should be provided in Emacs Texinfo format if possible,
+But documentation must be provided.
+
+ Your package will be released sooner with SLIB if you send me a file
+which tests your code. Please run this test *before* you send me the
+code!
+
+Modifications
+-------------
+
+ Please document your changes. A line or two for `ChangeLog' is
+sufficient for simple fixes or extensions. Look at the format of
+`ChangeLog' to see what information is desired. Please send me `diff'
+files from the latest SLIB distribution (remember to send `diff's of
+`slib.texi' and `ChangeLog'). This makes for less email traffic and
+makes it easier for me to integrate when more than one person is
+changing a file (this happens a lot with `slib.texi' and `*.init'
+files).
+
+ If someone else wrote a package you want to significantly modify,
+please try to contact the author, who may be working on a new version.
+This will insure against wasting effort on obsolete versions.
+
+ Please *do not* reformat the source code with your favorite
+beautifier, make 10 fixes, and send me the resulting source code. I do
+not have the time to fish through 10000 diffs to find your 10 real
+fixes.
+
+
+File: slib.info, Node: Copyrights, Prev: Coding Standards, Up: About SLIB
+
+Copyrights
+==========
+
+ This section has instructions for SLIB authors regarding copyrights.
+
+ Each package in SLIB must either be in the public domain, or come
+with a statement of terms permitting users to copy, redistribute and
+modify it. The comments at the beginning of `require.scm' and
+`macwork.scm' illustrate copyright and appropriate terms.
+
+ If your code or changes amount to less than about 10 lines, you do not
+need to add your copyright or send a disclaimer.
+
+Putting code into the Public Domain
+-----------------------------------
+
+ In order to put code in the public domain you should sign a copyright
+disclaimer and send it to the SLIB maintainer. Contact jaffer @
+ai.mit.edu for the address to mail the disclaimer to.
+
+ I, NAME, hereby affirm that I have placed the software package
+ NAME in the public domain.
+
+ I affirm that I am the sole author and sole copyright holder for
+ the software package, that I have the right to place this software
+ package in the public domain, and that I will do nothing to
+ undermine this status in the future.
+
+ SIGNATURE AND DATE
+
+ This wording assumes that you are the sole author. If you are not the
+sole author, the wording needs to be different. If you don't want to be
+bothered with sending a letter every time you release or modify a
+module, make your letter say that it also applies to your future
+revisions of that module.
+
+ Make sure no employer has any claim to the copyright on the work you
+are submitting. If there is any doubt, create a copyright disclaimer
+and have your employer sign it. Mail the signed disclaimer to the SLIB
+maintainer. Contact jaffer @ ai.mit.edu for the address to mail the
+disclaimer to. An example disclaimer follows.
+
+Explicit copying terms
+----------------------
+
+If you submit more than about 10 lines of code which you are not placing
+into the Public Domain (by sending me a disclaimer) you need to:
+
+ * Arrange that your name appears in a copyright line for the
+ appropriate year. Multiple copyright lines are acceptable.
+
+ * With your copyright line, specify any terms you require to be
+ different from those already in the file.
+
+ * Make sure no employer has any claim to the copyright on the work
+ you are submitting. If there is any doubt, create a copyright
+ disclaimer and have your employer sign it. Mail the signed
+ disclaim to the SLIB maintainer. Contact jaffer @ ai.mit.edu for
+ the address to mail the disclaimer to.
+
+Example: Company Copyright Disclaimer
+-------------------------------------
+
+ This disclaimer should be signed by a vice president or general
+manager of the company. If you can't get at them, anyone else
+authorized to license out software produced there will do. Here is a
+sample wording:
+
+ EMPLOYER Corporation hereby disclaims all copyright interest in
+ the program PROGRAM written by NAME.
+
+ EMPLOYER Corporation affirms that it has no other intellectual
+ property interest that would undermine this release, and will do
+ nothing to undermine it in the future.
+
+ SIGNATURE AND DATE,
+ NAME, TITLE, EMPLOYER Corporation
+
+
+File: slib.info, Node: Index, Prev: About SLIB, Up: Top
+
+Procedure and Macro Index
+*************************
+
+ This is an alphabetical list of all the procedures and macros in SLIB.
+
+* Menu:
+
+* -: Multi-argument / and -.
+* -1+: Rev2 Procedures.
+* /: Multi-argument / and -.
+* 1+: Rev2 Procedures.
+* <=?: Rev2 Procedures.
+* <?: Rev2 Procedures.
+* =?: Rev2 Procedures.
+* >=?: Rev2 Procedures.
+* >?: Rev2 Procedures.
+* absolute-path?: System Interface.
+* add-domain: Database Utilities.
+* add-process!: Multi-Processing.
+* add-setter: Setters.
+* adjoin: Lists as sets.
+* adjoin-parameters!: Parameter lists.
+* alarm: Multi-Processing.
+* alarm-interrupt: Multi-Processing.
+* alist->wt-tree: Construction of Weight-Balanced Trees.
+* alist-associator: Association Lists.
+* alist-for-each: Association Lists.
+* alist-inquirer: Association Lists.
+* alist-map: Association Lists.
+* alist-remover: Association Lists.
+* and?: Non-List functions.
+* any?: Collections.
+* append!: Rev2 Procedures.
+* apply: Multi-argument Apply.
+* array-1d-ref: Arrays.
+* array-1d-set!: Arrays.
+* array-2d-ref: Arrays.
+* array-2d-set!: Arrays.
+* array-3d-ref: Arrays.
+* array-3d-set!: Arrays.
+* array-copy!: Array Mapping.
+* array-dimensions: Arrays.
+* array-for-each: Array Mapping.
+* array-in-bounds?: Arrays.
+* array-index-map!: Array Mapping.
+* array-indexes: Array Mapping.
+* array-map!: Array Mapping.
+* array-rank: Arrays.
+* array-ref: Arrays.
+* array-set!: Arrays.
+* array-shape: Arrays.
+* array?: Arrays.
+* asctime: Posix Time.
+* ash: Bit-Twiddling.
+* atom?: Non-List functions. |
+* batch:call-with-output-script: Batch.
+* batch:command: Batch. |
+* batch:comment: Batch.
+* batch:delete-file: Batch.
+* batch:initialize!: Batch.
+* batch:lines->file: Batch.
+* batch:rename-file: Batch.
+* batch:run-script: Batch.
+* batch:try-chopped-command: Batch. |
+* batch:try-command: Batch. |
+* bit-extract: Bit-Twiddling.
+* bit-field: Bit-Twiddling.
+* bitwise-if: Bit-Twiddling.
+* break: Breakpoints.
+* break-all: Debug.
+* breakf: Breakpoints.
+* breakpoint: Breakpoints.
+* browse: Database Browser.
+* browse-url-netscape: System Interface.
+* butlast: Lists as sequences.
+* butnthcdr: Lists as sequences.
+* byte-ref: Byte.
+* byte-set!: Byte.
+* bytes: Byte.
+* bytes->list: Byte.
+* bytes-length: Byte.
+* call-with-dynamic-binding: Dynamic Data Type.
+* call-with-input-string: String Ports.
+* call-with-output-string: String Ports.
+* call-with-tmpnam: System Interface.
+* call-with-values: Values.
+* capture-syntactic-environment: Syntactic Closures.
+* cart-prod-tables: Relational Database Operations.
+* catalog->html: HTML HTTP and CGI.
+* catalog->page: HTML HTTP and CGI.
+* cgi:read-query-string: HTML HTTP and CGI.
+* cgi:serve-command: HTML HTTP and CGI.
+* chap:next-string: Chapter Ordering.
+* chap:string<=?: Chapter Ordering.
+* chap:string<?: Chapter Ordering.
+* chap:string>=?: Chapter Ordering.
+* chap:string>?: Chapter Ordering.
+* check-parameters: Parameter lists.
+* close-base: Base Table.
+* close-database: Relational Database Operations.
+* close-table: Table Operations.
+* coerce: Non-List functions.
+* collection?: Collections.
+* combined-rulesets: Commutative Rings.
+* command->html: HTML HTTP and CGI.
+* continue: Breakpoints.
+* copy-bit: Bit-Twiddling.
+* copy-bit-field: Bit-Twiddling.
+* copy-list: List construction.
+* copy-random-state: Random Numbers.
+* copy-tree: Tree Operations.
+* create-database <1>: Database Utilities.
+* create-database: Creating and Opening Relational Databases.
+* create-report: Database Reports.
+* create-table: Relational Database Operations.
+* create-view: Relational Database Operations.
+* cring:define-rule: Commutative Rings.
+* ctime: Posix Time.
+* current-directory: System Interface.
+* current-error-port: Input/Output.
+* current-input-port <1>: Byte.
+* current-input-port: Ruleset Definition and Use.
+* current-output-port: Byte.
+* current-time: Time and Date.
+* debug:breakf: Breakpoints.
+* debug:tracef: Trace.
+* debug:unbreakf: Breakpoints.
+* debug:untracef: Trace.
+* decode-universal-time: Common-Lisp Time.
+* define-access-operation: Setters.
+* define-operation: Yasos interface.
+* define-predicate: Yasos interface.
+* define-record: Structures.
+* define-syntax: Macro by Example.
+* define-tables: Database Utilities.
+* defmacro: Defmacro.
+* defmacro:eval: Defmacro.
+* defmacro:expand*: Defmacro.
+* defmacro:load: Defmacro.
+* defmacro?: Defmacro.
+* delete <1>: Destructive list operations.
+* delete: Base Table.
+* delete*: Base Table.
+* delete-domain: Database Utilities.
+* delete-file: Input/Output.
+* delete-if: Destructive list operations.
+* delete-if-not: Destructive list operations.
+* delete-table: Relational Database Operations.
+* dequeue!: Queues.
+* difftime: Time and Date.
+* display-file: Line I/O.
+* do-elts: Collections.
+* do-keys: Collections.
+* domain-checker: Database Utilities.
+* dynamic-ref: Dynamic Data Type.
+* dynamic-set!: Dynamic Data Type.
+* dynamic-wind: Dynamic-Wind.
+* dynamic?: Dynamic Data Type.
+* empty?: Collections.
+* encode-universal-time: Common-Lisp Time.
+* enquque!: Queues.
+* equal?: Byte.
+* eval: Eval.
+* every: Lists as sets.
+* every?: Collections.
+* extended-euclid: Modular Arithmetic.
+* factor: Prime Numbers.
+* fft: Fast Fourier Transform.
+* fft-1: Fast Fourier Transform.
+* file-exists?: Input/Output.
+* filename:match-ci??: Filenames.
+* filename:match??: Filenames.
+* filename:substitute-ci??: Filenames.
+* filename:substitute??: Filenames.
+* fill-empty-parameters: Parameter lists.
+* find-if: Lists as sets.
+* find-string-from-port?: String Search.
+* fluid-let: Fluid-Let.
+* for-each-elt: Collections.
+* for-each-key <1>: Collections.
+* for-each-key: Base Table.
+* for-each-row: Table Operations.
+* force-output: Input/Output.
+* format: Format Interface.
+* fprintf: Standard Formatted Output.
+* fscanf: Standard Formatted Input.
+* ftp-upload: System Interface.
+* generic-write: Generic-Write.
+* gentemp: Defmacro.
+* get: Table Operations.
+* get*: Table Operations.
+* get-decoded-time: Common-Lisp Time.
+* get-method: Object.
+* get-universal-time: Common-Lisp Time.
+* getenv: System Interface.
+* getopt: Getopt.
+* getopt--: Getopt.
+* getopt->arglist: Getopt Parameter lists.
+* getopt->parameter-list: Getopt Parameter lists.
+* glob-pattern?: System Interface.
+* gmktime: Posix Time.
+* gmtime: Posix Time.
+* gtime: Posix Time.
+* has-duplicates?: Lists as sets.
+* hash: Hashing.
+* hash-associator: Hash Tables.
+* hash-for-each: Hash Tables.
+* hash-inquirer: Hash Tables.
+* hash-map: Hash Tables.
+* hash-remover: Hash Tables.
+* hashq: Hashing.
+* hashv: Hashing.
+* heap-extract-max!: Priority Queues.
+* heap-insert!: Priority Queues.
+* heap-length: Priority Queues.
+* home-vicinity: Vicinity.
+* html:comment: HTML HTTP and CGI.
+* html:end-form: HTML HTTP and CGI.
+* html:end-page: HTML HTTP and CGI.
+* html:end-table: HTML HTTP and CGI.
+* html:heading: HTML HTTP and CGI.
+* html:href-heading: HTML HTTP and CGI.
+* html:pre: HTML HTTP and CGI.
+* html:start-form: HTML HTTP and CGI.
+* html:start-page: HTML HTTP and CGI.
+* html:start-table: HTML HTTP and CGI.
+* http:read-request-line: HTML HTTP and CGI.
+* http:serve-query: HTML HTTP and CGI.
+* identifier=?: Syntactic Closures.
+* identifier?: Syntactic Closures.
+* identity: Legacy.
+* implementation-vicinity: Vicinity.
+* in-vicinity: Vicinity.
+* init-debug: Breakpoints.
+* integer-expt: Bit-Twiddling.
+* integer-length: Bit-Twiddling.
+* integer-sqrt: Root Finding.
+* interaction-environment: Eval.
+* intersection: Lists as sets.
+* jacobi-symbol: Prime Numbers.
+* kill-process!: Multi-Processing.
+* kill-table: Base Table.
+* laguerre:find-polynomial-root: Root Finding.
+* laguerre:find-root: Root Finding.
+* last: Lists as sequences.
+* last-pair: Legacy.
+* library-vicinity: Vicinity.
+* list*: List construction.
+* list->bytes: Byte.
+* list->string: Rev4 Optional Procedures.
+* list->vector: Rev4 Optional Procedures.
+* list-tail: Rev4 Optional Procedures.
+* load-option: Weight-Balanced Trees.
+* localtime: Posix Time.
+* logand: Bit-Twiddling.
+* logbit?: Bit-Twiddling.
+* logcount: Bit-Twiddling.
+* logior: Bit-Twiddling.
+* lognot: Bit-Twiddling.
+* logtest: Bit-Twiddling.
+* logxor: Bit-Twiddling.
+* macro:eval <1>: Syntax-Case Macros.
+* macro:eval <2>: Syntactic Closures.
+* macro:eval <3>: Macros That Work.
+* macro:eval: R4RS Macros.
+* macro:expand <1>: Syntax-Case Macros.
+* macro:expand <2>: Syntactic Closures.
+* macro:expand <3>: Macros That Work.
+* macro:expand: R4RS Macros.
+* macro:load <1>: Syntax-Case Macros.
+* macro:load <2>: Syntactic Closures.
+* macro:load <3>: Macros That Work.
+* macro:load: R4RS Macros.
+* macroexpand: Defmacro.
+* macroexpand-1: Defmacro.
+* macwork:eval: Macros That Work.
+* macwork:expand: Macros That Work.
+* macwork:load: Macros That Work.
+* make-: Structures.
+* make-array: Arrays.
+* make-atval: HTML HTTP and CGI.
+* make-base: Base Table.
+* make-bytes: Byte.
+* make-command-server: Database Utilities.
+* make-directory: System Interface.
+* make-dynamic: Dynamic Data Type.
+* make-generic-method: Object.
+* make-generic-predicate: Object.
+* make-getter: Base Table.
+* make-hash-table: Hash Tables.
+* make-heap: Priority Queues.
+* make-key->list: Base Table.
+* make-key-extractor: Base Table.
+* make-keyifier-1: Base Table.
+* make-list: List construction.
+* make-list-keyifier: Base Table.
+* make-method!: Object.
+* make-object: Object.
+* make-parameter-list: Parameter lists.
+* make-plain: HTML HTTP and CGI.
+* make-port-crc: Cyclic Checksum.
+* make-predicate!: Object.
+* make-promise: Promises.
+* make-putter: Base Table.
+* make-queue: Queues.
+* make-random-state: Random Numbers.
+* make-record-type: Records.
+* make-relational-system: Creating and Opening Relational Databases.
+* make-row-converter: HTML HTTP and CGI.
+* make-ruleset: Commutative Rings.
+* make-shared-array: Arrays.
+* make-sierpinski-indexer: Hashing.
+* make-syntactic-closure: Syntactic Closures.
+* make-table: Base Table.
+* make-vicinity: Vicinity.
+* make-wt-tree: Construction of Weight-Balanced Trees.
+* make-wt-tree-type: Construction of Weight-Balanced Trees.
+* map-elts: Collections.
+* map-key: Base Table.
+* map-keys: Collections.
+* member-if: Lists as sets.
+* merge: Sorting.
+* merge!: Sorting.
+* mktime: Posix Time.
+* modular:: Modular Arithmetic.
+* modular:*: Modular Arithmetic.
+* modular:+: Modular Arithmetic.
+* modular:expt: Modular Arithmetic.
+* modular:invert: Modular Arithmetic.
+* modular:invertable?: Modular Arithmetic.
+* modular:negate: Modular Arithmetic.
+* modular:normalize: Modular Arithmetic.
+* modulus->integer: Modular Arithmetic.
+* must-be-first: Batch.
+* must-be-last: Batch.
+* nconc: Destructive list operations.
+* newton:find-root: Root Finding.
+* newtown:find-integer-root: Root Finding.
+* notany: Lists as sets.
+* notevery: Lists as sets.
+* nreverse: Destructive list operations.
+* nthcdr: Lists as sequences.
+* null-directory?: System Interface.
+* null-environment: Eval.
+* object: Yasos interface.
+* object->limited-string: Object-To-String.
+* object->string: Object-To-String.
+* object-with-ancestors: Yasos interface.
+* object?: Object.
+* offset-time: Time and Date.
+* open-base: Base Table.
+* open-database <1>: Database Utilities.
+* open-database: Creating and Opening Relational Databases.
+* open-database!: Database Utilities.
+* open-table <1>: Relational Database Operations.
+* open-table: Base Table.
+* operate-as: Yasos interface.
+* or?: Non-List functions.
+* ordered-for-each-key: Base Table.
+* os->batch-dialect: Batch.
+* output-port-height: Input/Output.
+* output-port-width: Input/Output.
+* parameter-list->arglist: Parameter lists.
+* parameter-list-expand: Parameter lists.
+* parameter-list-ref: Parameter lists.
+* parse-ftp-address: System Interface.
+* path->url: System Interface.
+* plot!: Plotting.
+* position: Lists as sequences.
+* pprint-file: Pretty-Print.
+* pprint-filter-file: Pretty-Print.
+* prec:commentfix: Grammar Rule Definition.
+* prec:define-grammar: Ruleset Definition and Use.
+* prec:delim: Grammar Rule Definition.
+* prec:infix: Grammar Rule Definition.
+* prec:inmatchfix: Grammar Rule Definition.
+* prec:make-led: Nud and Led Definition.
+* prec:make-nud: Nud and Led Definition.
+* prec:matchfix: Grammar Rule Definition.
+* prec:nary: Grammar Rule Definition.
+* prec:nofix: Grammar Rule Definition.
+* prec:parse: Ruleset Definition and Use.
+* prec:postfix: Grammar Rule Definition.
+* prec:prefix: Grammar Rule Definition.
+* prec:prestfix: Grammar Rule Definition.
+* predicate->asso: Association Lists.
+* predicate->hash: Hash Tables.
+* predicate->hash-asso: Hash Tables.
+* present?: Base Table.
+* pretty-print: Pretty-Print.
+* prime?: Prime Numbers.
+* primes<: Prime Numbers.
+* primes>: Prime Numbers.
+* print: Yasos interface.
+* printf: Standard Formatted Output.
+* process:schedule!: Multi-Processing.
+* program-vicinity: Vicinity.
+* project-table: Relational Database Operations.
+* provide <1>: Require.
+* provide: Feature.
+* provided? <1>: Require.
+* provided?: Feature.
+* qp: Quick Print.
+* qpn: Quick Print.
+* qpr: Quick Print.
+* queue-empty?: Queues.
+* queue-front: Queues.
+* queue-pop!: Queues.
+* queue-push!: Queues.
+* queue-rear: Queues.
+* queue?: Queues.
+* random: Random Numbers.
+* random:exp: Random Numbers.
+* random:hollow-sphere!: Random Numbers.
+* random:normal: Random Numbers.
+* random:normal-vector!: Random Numbers.
+* random:solid-sphere!: Random Numbers.
+* random:uniform: Random Numbers.
+* rationalize: Rationalize.
+* read-byte: Byte.
+* read-command: Command Line.
+* read-line: Line I/O.
+* read-line!: Line I/O.
+* read-options-file: Command Line.
+* record-accessor: Records.
+* record-constructor: Records.
+* record-modifier: Records.
+* record-predicate: Records.
+* reduce <1>: Lists as sequences.
+* reduce: Collections.
+* reduce-init: Lists as sequences.
+* remove: Lists as sets.
+* remove-duplicates: Lists as sets.
+* remove-if: Lists as sets.
+* remove-if-not: Lists as sets.
+* remove-setter-for: Setters.
+* repl:quit: Repl.
+* repl:top-level: Repl.
+* replace-suffix: Filenames.
+* require <1>: Require.
+* require <2>: Catalog Compilation.
+* require: Requesting Features.
+* require:feature->path <1>: Require.
+* require:feature->path: Requesting Features.
+* restrict-table: Relational Database Operations.
+* row:delete: Table Operations.
+* row:delete*: Table Operations.
+* row:insert: Table Operations.
+* row:insert*: Table Operations.
+* row:remove: Table Operations.
+* row:remove*: Table Operations.
+* row:retrieve: Table Operations.
+* row:retrieve*: Table Operations.
+* row:update: Table Operations.
+* row:update*: Table Operations.
+* scanf: Standard Formatted Input.
+* scanf-read-list: Standard Formatted Input.
+* scheme-report-environment: Eval.
+* schmooz: Schmooz.
+* secant:find-bracketed-root: Root Finding.
+* secant:find-root: Root Finding.
+* seed->random-state: Random Numbers.
+* serve-urlencoded-command: HTML HTTP and CGI.
+* set: Setters.
+* set-: Structures.
+* set-difference: Lists as sets.
+* Setter: Collections.
+* setter: Setters.
+* singleton-wt-tree: Construction of Weight-Balanced Trees.
+* size <1>: Collections.
+* size: Yasos interface.
+* slib:error: System.
+* slib:eval: System.
+* slib:eval-load: System.
+* slib:exit: System.
+* slib:load: System.
+* slib:load-compiled: System.
+* slib:load-source: System.
+* slib:report: Configuration.
+* slib:report-version: Configuration.
+* slib:warn: System.
+* software-type: Configuration.
+* some: Lists as sets.
+* sort: Sorting.
+* sort!: Sorting.
+* sorted?: Sorting.
+* soundex: Hashing.
+* sprintf: Standard Formatted Output.
+* sscanf: Standard Formatted Input.
+* string->list: Rev4 Optional Procedures.
+* string-capitalize: String-Case.
+* string-captialize!: String-Case.
+* string-ci->symbol: String-Case.
+* string-copy: Rev4 Optional Procedures.
+* string-downcase: String-Case.
+* string-downcase!: String-Case.
+* string-fill!: Rev4 Optional Procedures.
+* string-index: String Search.
+* string-index-ci: String Search.
+* string-join: Batch.
+* string-null?: Rev2 Procedures.
+* string-reverse-index: String Search.
+* string-reverse-index-ci: String Search.
+* string-subst: String Search.
+* string-upcase: String-Case.
+* string-upcase!: String-Case.
+* sub-vicinity: Vicinity.
+* subst: Tree Operations.
+* substq: Tree Operations.
+* substring-ci?: String Search.
+* substring-fill!: Rev2 Procedures.
+* substring-move-left!: Rev2 Procedures.
+* substring-move-right!: Rev2 Procedures.
+* substring?: String Search.
+* substv: Tree Operations.
+* supported-key-type?: Base Table.
+* supported-type?: Base Table.
+* symmetric:modulus: Modular Arithmetic.
+* sync-base: Base Table.
+* syncase:eval: Syntax-Case Macros.
+* syncase:expand: Syntax-Case Macros.
+* syncase:load: Syntax-Case Macros.
+* synclo:eval: Syntactic Closures.
+* synclo:expand: Syntactic Closures.
+* synclo:load: Syntactic Closures.
+* syntax-rules: Macro by Example.
+* system: System Interface.
+* table->html: HTML HTTP and CGI.
+* table->page: HTML HTTP and CGI.
+* table-exists?: Relational Database Operations.
+* table-name->filename: HTML HTTP and CGI.
+* TAG: Structures.
+* tek40:draw: Tektronix Graphics Support.
+* tek40:graphics: Tektronix Graphics Support.
+* tek40:init: Tektronix Graphics Support.
+* tek40:linetype: Tektronix Graphics Support.
+* tek40:move: Tektronix Graphics Support.
+* tek40:put-text: Tektronix Graphics Support.
+* tek40:reset: Tektronix Graphics Support.
+* tek40:text: Tektronix Graphics Support.
+* tek41:draw: Tektronix Graphics Support.
+* tek41:encode-int: Tektronix Graphics Support.
+* tek41:encode-x-y: Tektronix Graphics Support.
+* tek41:graphics: Tektronix Graphics Support.
+* tek41:init: Tektronix Graphics Support.
+* tek41:move: Tektronix Graphics Support.
+* tek41:point: Tektronix Graphics Support.
+* tek41:reset: Tektronix Graphics Support.
+* time-zone: Time Zone.
+* tmpnam: Input/Output.
+* tok:char-group: Token definition.
+* topological-sort: Topological Sort.
+* trace: Trace.
+* trace-all: Debug.
+* tracef: Trace.
+* transcript-off: Transcripts.
+* transcript-on: Transcripts.
+* transformer: Syntactic Closures.
+* truncate-up-to: Batch.
+* tsort: Topological Sort.
+* two-arg:-: Multi-argument / and -.
+* two-arg:/: Multi-argument / and -.
+* two-arg:apply: Multi-argument Apply.
+* type-of: Non-List functions.
+* tz:params: Time Zone.
+* tzset: Time Zone.
+* unbreak: Breakpoints.
+* unbreakf: Breakpoints.
+* union: Lists as sets.
+* unmake-method!: Object.
+* untrace: Trace.
+* untracef: Trace.
+* user-email-address: System Interface.
+* user-vicinity: Vicinity.
+* values: Values.
+* variant-case: Structures.
+* vector->list: Rev4 Optional Procedures.
+* vector-fill!: Rev4 Optional Procedures.
+* with-input-from-file: With-File.
+* with-output-to-file: With-File.
+* write-base: Base Table.
+* write-byte: Byte.
+* write-database: Relational Database Operations.
+* write-line: Line I/O.
+* wt-tree/add: Basic Operations on Weight-Balanced Trees.
+* wt-tree/add!: Basic Operations on Weight-Balanced Trees.
+* wt-tree/delete: Basic Operations on Weight-Balanced Trees.
+* wt-tree/delete!: Basic Operations on Weight-Balanced Trees.
+* wt-tree/delete-min: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/delete-min!: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/difference: Advanced Operations on Weight-Balanced Trees.
+* wt-tree/empty?: Basic Operations on Weight-Balanced Trees.
+* wt-tree/fold: Advanced Operations on Weight-Balanced Trees.
+* wt-tree/for-each: Advanced Operations on Weight-Balanced Trees.
+* wt-tree/index: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/index-datum: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/index-pair: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/intersection: Advanced Operations on Weight-Balanced Trees.
+* wt-tree/lookup: Basic Operations on Weight-Balanced Trees.
+* wt-tree/member?: Basic Operations on Weight-Balanced Trees.
+* wt-tree/min: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/min-datum: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/min-pair: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/rank: Indexing Operations on Weight-Balanced Trees.
+* wt-tree/set-equal?: Advanced Operations on Weight-Balanced Trees.
+* wt-tree/size: Basic Operations on Weight-Balanced Trees.
+* wt-tree/split<: Advanced Operations on Weight-Balanced Trees.
+* wt-tree/split>: Advanced Operations on Weight-Balanced Trees.
+* wt-tree/subset?: Advanced Operations on Weight-Balanced Trees.
+* wt-tree/union: Advanced Operations on Weight-Balanced Trees.
+* wt-tree?: Basic Operations on Weight-Balanced Trees.
+
+Variable Index
+**************
+
+ This is an alphabetical list of all the global variables in SLIB.
+
+* Menu:
+
+* *catalog*: Require.
+* *features*: Require.
+* *html:output-port*: HTML HTTP and CGI.
+* *modules*: Require.
+* *optarg*: Getopt.
+* *optind*: Getopt.
+* *qp-width*: Quick Print.
+* *random-state*: Random Numbers.
+* *ruleset*: Commutative Rings.
+* *syn-defs*: Ruleset Definition and Use.
+* *syn-ignore-whitespace*: Ruleset Definition and Use.
+* *timezone*: Time Zone.
+* batch:platform: Batch.
+* catalog-id: Base Table.
+* char-code-limit: Configuration.
+* charplot:height: Plotting.
+* charplot:width: Plotting.
+* column-domains: Table Operations.
+* column-foreigns: Table Operations.
+* column-names: Table Operations.
+* column-types: Table Operations.
+* daylight?: Time Zone.
+* distribute*: Commutative Rings.
+* distribute/: Commutative Rings.
+* most-positive-fixnum: Configuration.
+* nil: Legacy.
+* number-wt-type: Construction of Weight-Balanced Trees.
+* primary-limit: Table Operations.
+* prime:prngs: Prime Numbers.
+* prime:trials: Prime Numbers.
+* slib:form-feed: Configuration.
+* slib:tab: Configuration.
+* stderr: Standard Formatted I/O.
+* stdin: Standard Formatted I/O.
+* stdout: Standard Formatted I/O.
+* string-wt-type: Construction of Weight-Balanced Trees.
+* t: Legacy.
+* tok:decimal-digits: Token definition.
+* tok:lower-case: Token definition.
+* tok:upper-case: Token definition.
+* tok:whitespaces: Token definition.
+* tzname: Time Zone.
+
+Concept and Feature Index
+*************************
+
+* Menu:
+
+* alist: Association Lists.
+* alist-table <1>: Creating and Opening Relational Databases.
+* alist-table: Base Table.
+* ange-ftp: System Interface.
+* array: Arrays.
+* array-for-each: Array Mapping.
+* attribute-value: HTML HTTP and CGI.
+* balanced binary trees: Weight-Balanced Trees.
+* batch: Batch.
+* binary trees: Weight-Balanced Trees.
+* binary trees, as discrete maps: Weight-Balanced Trees.
+* binary trees, as sets: Weight-Balanced Trees.
+* break: Breakpoints.
+* byte: Byte.
+* calendar time <1>: Posix Time.
+* calendar time: Time and Date.
+* Calendar-Time: Posix Time.
+* caltime: Posix Time.
+* careful: Commutative Rings.
+* catalog: Requesting Features.
+* Catalog File: Library Catalogs.
+* chapter-order: Chapter Ordering.
+* charplot: Plotting.
+* collect: Collections.
+* command line: Command Line.
+* commentfix: Precedence Parsing Overview.
+* common-list-functions <1>: Common List Functions.
+* common-list-functions: Collections.
+* commutative-ring: Commutative Rings.
+* Coordinated Universal Time: Posix Time.
+* database-utilities <1>: Database Utilities.
+* database-utilities: Batch.
+* debug <1>: Breakpoints.
+* debug: Debug.
+* defmacroexpand <1>: Pretty-Print.
+* defmacroexpand: Defmacro.
+* delim: Precedence Parsing Overview.
+* discrete maps, using binary trees: Weight-Balanced Trees.
+* dynamic: Dynamic Data Type.
+* dynamic-wind: Dynamic-Wind.
+* Euclidean Domain: Commutative Rings.
+* factor: Prime Numbers.
+* feature <1>: About this manual.
+* feature <2>: Requesting Features.
+* feature: Feature.
+* fft: Fast Fourier Transform.
+* fluid-let <1>: Database Utilities.
+* fluid-let: Fluid-Let.
+* form: HTML HTTP and CGI.
+* format: Format.
+* generic-write: Generic-Write.
+* getit: System Interface.
+* getopt <1>: Database Utilities.
+* getopt: Getopt.
+* glob <1>: Batch.
+* glob: Filenames.
+* hash: Hashing.
+* hash-table: Hash Tables.
+* HOME <1>: Vicinity.
+* HOME: Library Catalogs.
+* homecat: Catalog Compilation.
+* implcat: Catalog Compilation.
+* infix: Precedence Parsing Overview.
+* inmatchfix: Precedence Parsing Overview.
+* Left Denotation, led: Nud and Led Definition.
+* line-i: Line I/O.
+* logical: Bit-Twiddling.
+* macro <1>: Repl.
+* macro: R4RS Macros.
+* macro-by-example: Macro by Example.
+* macros-that-work: Macros That Work.
+* make-crc: Cyclic Checksum.
+* match: Base Table.
+* match-key: Base Table.
+* match-keys: Table Operations.
+* matchfix: Precedence Parsing Overview.
+* minimum field width (printf): Standard Formatted Output.
+* mkimpcat.scm: Catalog Compilation.
+* mklibcat.scm: Catalog Compilation.
+* modular: Modular Arithmetic.
+* multiarg-apply: Multi-argument Apply.
+* mutliarg: Multi-argument / and -.
+* nary: Precedence Parsing Overview.
+* net-clients: System Interface.
+* nofix: Precedence Parsing Overview.
+* Null Denotation, nud: Nud and Led Definition.
+* object: Object.
+* object->string: Object-To-String.
+* oop: Yasos.
+* option, run-time-loadable: Weight-Balanced Trees.
+* options file: Command Line. |
+* parameters <1>: Database Utilities.
+* parameters <2>: Batch.
+* parameters: Parameter lists.
+* parse: Precedence Parsing.
+* plain-text: HTML HTTP and CGI.
+* posix-time: Posix Time.
+* postfix: Precedence Parsing Overview.
+* pprint-file: Pretty-Print.
+* PRE: HTML HTTP and CGI.
+* precedence: Precedence Parsing.
+* precision (printf): Standard Formatted Output.
+* prefix: Precedence Parsing Overview.
+* prestfix: Precedence Parsing Overview.
+* pretty-print: Pretty-Print.
+* primes: Prime Numbers.
+* printf: Standard Formatted Output.
+* priority-queue: Priority Queues.
+* PRNG: Random Numbers.
+* process: Multi-Processing.
+* promise: Promises.
+* qp <1>: Quick Print.
+* qp: Getopt.
+* query-string: HTML HTTP and CGI.
+* queue: Queues.
+* random: Random Numbers.
+* rationalize: Rationalize.
+* read-command: Command Line.
+* record: Records.
+* relational-database: Relational Database.
+* repl <1>: Repl.
+* repl: Syntax-Case Macros.
+* rev2-procedures: Rev2 Procedures.
+* rev3-report: Coding Standards.
+* rev4-optional-procedures: Rev4 Optional Procedures.
+* ring, commutative: Commutative Rings.
+* RNG: Random Numbers.
+* root: Root Finding.
+* run-time-loadable option: Weight-Balanced Trees.
+* scanf: Standard Formatted Input. |
+* schmooz: Schmooz.
+* session: Feature.
+* sets, using binary trees: Weight-Balanced Trees.
+* sierpinski: Hashing.
+* sitecat: Catalog Compilation. |
+* slibcat: Catalog Compilation.
+* sort: Sorting.
+* soundex: Hashing.
+* stdio: Standard Formatted I/O.
+* string-case: String-Case.
+* string-port: String Ports.
+* string-search: String Search.
+* struct: Structures.
+* syntactic-closures: Syntactic Closures.
+* syntax-case: Syntax-Case Macros.
+* time: Time and Date.
+* time-zone: Time Zone.
+* topological-sort: Topological Sort.
+* trace: Trace.
+* transcript: Transcripts.
+* tree: Tree Operations.
+* trees, balanced binary: Weight-Balanced Trees.
+* tsort: Topological Sort.
+* TZ-string: Time Zone.
+* Uniform Resource Locator: System Interface.
+* Unique Factorization: Commutative Rings.
+* usercat: Catalog Compilation.
+* UTC: Posix Time.
+* values: Values.
+* weight-balanced binary trees: Weight-Balanced Trees.
+* wild-card: Base Table.
+* with-file: With-File.
+* wt-tree: Weight-Balanced Trees.
+* yasos: Yasos.
+
+
+
+Tag Table:
+Node: Top1057
+Node: The Library System1870
+Node: Feature2184
+Node: Requesting Features3134
+Node: Library Catalogs4493
+Node: Catalog Compilation6945
+Node: Built-in Support9755
+Node: Require10386
+Node: Vicinity12879
+Node: Configuration15846
+Node: Input/Output18787
+Node: Legacy20386
+Node: System21228
+Node: About this manual23720
+Node: Scheme Syntax Extension Packages24277
+Node: Defmacro24962
+Node: R4RS Macros26912
+Node: Macro by Example28167
+Node: Macros That Work31043
+Node: Syntactic Closures37101
+Node: Syntax-Case Macros54534
+Node: Fluid-Let58661
+Node: Yasos59602
+Node: Yasos terms60395
+Node: Yasos interface61419
+Node: Setters63496
+Node: Yasos examples66138
+Node: Textual Conversion Packages69132
+Node: Precedence Parsing69708
+Node: Precedence Parsing Overview70371
+Node: Ruleset Definition and Use72572
+Node: Token definition74953
+Node: Nud and Led Definition77222
+Node: Grammar Rule Definition79671
+Node: Format87245
+Node: Format Interface87493
+Node: Format Specification89230
+Node: Standard Formatted I/O99287
+Node: Standard Formatted Output99853
+Node: Standard Formatted Input108913
+Node: Programs and Arguments115572
+Node: Getopt116085
+Node: Command Line121927
+Node: Parameter lists125116
+Node: Getopt Parameter lists128753
+Node: Filenames130948
+Node: Batch134178
+Node: HTML HTTP and CGI142791
+Node: Printing Scheme149960
+Node: Generic-Write150283
+Node: Object-To-String151686
+Node: Pretty-Print152090
+Node: Time and Date154036
+Node: Time Zone155063
+Node: Posix Time159625
+Node: Common-Lisp Time161761
+Node: Vector Graphics163340
+Node: Tektronix Graphics Support163529
+Node: Schmooz164903
+Node: Mathematical Packages169129
+Node: Bit-Twiddling169721
+Node: Modular Arithmetic174312
+Node: Prime Numbers176446
+Node: Random Numbers178453
+Node: Fast Fourier Transform183166
+Node: Cyclic Checksum184084
+Node: Plotting185802
+Node: Root Finding188377
+Node: Commutative Rings192371
+Node: Determinant203757
+Node: Database Packages204055
+Node: Base Table204319
+Node: Relational Database214477
+Node: Motivations215261
+Node: Creating and Opening Relational Databases220308
+Node: Relational Database Operations222740
+Node: Table Operations225537
+Node: Catalog Representation233415
+Node: Unresolved Issues236313
+Node: Database Utilities239264
+Node: Database Reports254919
+Node: Database Browser257674
+Node: Weight-Balanced Trees258735
+Node: Construction of Weight-Balanced Trees262605
+Node: Basic Operations on Weight-Balanced Trees266055
+Node: Advanced Operations on Weight-Balanced Trees269020
+Node: Indexing Operations on Weight-Balanced Trees275042
+Node: Other Packages278956
+Node: Data Structures279355
+Node: Arrays280074
+Node: Array Mapping283028
+Node: Association Lists284945
+Node: Byte287196
+Node: Collections289427
+Node: Dynamic Data Type295534
+Node: Hash Tables296795
+Node: Hashing298912
+Node: Object303687
+Node: Priority Queues311924
+Node: Queues312767
+Node: Records313893
+Node: Structures317404
+Node: Procedures318704
+Node: Common List Functions319391
+Node: List construction319815
+Node: Lists as sets321478
+Node: Lists as sequences326850
+Node: Destructive list operations332096
+Node: Non-List functions334760
+Node: Tree Operations336108
+Node: Chapter Ordering337654
+Node: Sorting339274
+Node: Topological Sort345051
+Node: String-Case346738
+Node: String Ports347359
+Node: String Search348123
+Node: Line I/O350490
+Node: Multi-Processing352139
+Node: Standards Support353223
+Node: With-File353878
+Node: Transcripts354154
+Node: Rev2 Procedures354475
+Node: Rev4 Optional Procedures356182
+Node: Multi-argument / and -356752
+Node: Multi-argument Apply357403
+Node: Rationalize357889
+Node: Promises358552
+Node: Dynamic-Wind358969
+Node: Eval360223
+Node: Values363560
+Node: Session Support364347
+Node: Repl364815
+Node: Quick Print366098
+Node: Debug367211
+Node: Breakpoints367853
+Node: Trace370071
+Node: System Interface371445
+Node: Extra-SLIB Packages375246
+Node: About SLIB377378
+Node: Installation378462
+Node: Porting380312
+Node: Coding Standards381829
+Node: Copyrights383908
+Node: Index387192
+
+End Tag Table