aboutsummaryrefslogtreecommitdiffstats
path: root/slib.texi
diff options
context:
space:
mode:
Diffstat (limited to 'slib.texi')
-rw-r--r--slib.texi11739
1 files changed, 6700 insertions, 5039 deletions
diff --git a/slib.texi b/slib.texi
index 1d41fdc..e9b1c10 100644
--- a/slib.texi
+++ b/slib.texi
@@ -5,6 +5,9 @@
@setchapternewpage on
@c Choices for setchapternewpage are {on,off,odd}.
@paragraphindent 2
+@defcodeindex ft
+@syncodeindex ft cp
+@syncodeindex tp cp
@c %**end of header
@iftex
@@ -17,8 +20,8 @@
@ifinfo
This file documents SLIB, the portable Scheme library.
-Copyright (C) 1993 Todd R. Eigenschink
-Copyright (C) 1993, 1994, 1995 Aubrey Jaffer
+Copyright (C) 1993 Todd R. Eigenschink@*
+Copyright (C) 1993, 1994, 1995, 1996, 1997 Aubrey Jaffer
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -45,13 +48,13 @@ by the author.
@titlepage
@title SLIB
@subtitle The Portable Scheme Library
-@subtitle Version 2a3
-@subtitle June 1995
-@author by Todd R. Eigenschink, Dave Love, and Aubrey Jaffer
+@subtitle Version 2c0
+@author by Aubrey Jaffer
@page
@vskip 0pt plus 1filll
-Copyright @copyright{} 1993, 1994, 1995 Todd R. Eigenschink and Aubrey Jaffer
+Copyright @copyright{} 1993 Todd R. Eigenschink@*
+Copyright @copyright{} 1993, 1994, 1995, 1996, 1997 Aubrey Jaffer
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -69,1248 +72,3712 @@ by the author.
@end titlepage
+@node Top, The Library System, (dir), (dir)
+@ifinfo
+@cindex SLIB
+@dfn{SLIB} is a portable library for the programming language
+@cindex Scheme
+@dfn{Scheme}. It provides a platform independent framework for using
+@dfn{packages} of Scheme procedures and syntax.
+@cindex packages
+@cindex package
+As distributed, SLIB contains useful packages for all implementations.
+Its catalog can be transparently extended to accomodate packages
+specific to a site, implementation, user, or directory.
+@quotation
+Aubrey Jaffer <jaffer@@ai.mit.edu>@*
+@i{Hyperactive Software} -- The Maniac Inside!@*
+http://www-swiss.ai.mit.edu/~jaffer/SLIB.html
+@end quotation
+@end ifinfo
-@node Top, Overview, (dir), (dir)
-
-@ifinfo
-This file documents SLIB, the portable Scheme library.
+@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::
+@end menu
-@heading Good Engineering is 1% inspiration and 99% documentation.
+@node The Library System, Scheme Syntax Extension Packages, Top, Top
+@chapter The Library System
-Herein lies the good part. Many thanks to Todd Eigenschink
-<eigenstr@@CS.Rose-Hulman.Edu> (who thanks Dave Love <D.Love@@dl.ac.uk>)
-for creating @file{slib.texi}. I have learned much from their example.
+@iftex
+@section Introduction
-Aubrey Jaffer
-jaffer@@ai.mit.edu
-@end ifinfo
+@noindent
+@cindex SLIB
+@dfn{SLIB} is a portable library for the programming language
+@cindex Scheme
+@dfn{Scheme}. It provides a platform independent framework for using
+@dfn{packages} of Scheme procedures and syntax.
+@cindex packages
+@cindex package
+As distributed, SLIB contains useful packages for all implementations.
+Its catalog can be transparently extended to accomodate packages
+specific to a site, implementation, user, or directory.
+@quotation
+Aubrey Jaffer <jaffer@@ai.mit.edu>@*
+@i{Hyperactive Software} -- The Maniac Inside!@*
+@ifset html
+<A HREF="http://www-swiss.ai.mit.edu/~jaffer/SLIB.html">
+@end ifset
+http://www-swiss.ai.mit.edu/~jaffer/SLIB.html
+@ifset html
+</A>
+@end ifset
+@end quotation
+@end iftex
@menu
-* Overview:: What is SLIB?
+* Feature:: SLIB names.
+* Requesting Features::
+* Library Catalogs::
+* Catalog Compilation::
+* Built-in Support::
+* About this manual::
+@end menu
-* Data Structures:: Various data structures.
-* Macros:: Extensions to Scheme syntax.
-* Numerics::
-* Procedures:: Miscellaneous utility procedures.
-* Standards Support:: Support for Scheme Standards.
-* Session Support:: Debugging, Pathnames, Require, etc.
-* Optional SLIB Packages::
-* Procedure and Macro Index::
-* Variable Index::
-@end menu
+@node Feature, Requesting Features, The Library System, The Library System
+@section Feature
+@noindent
+@cindex feature
+SLIB denotes @dfn{features} by symbols. SLIB maintains a list of
+features supported by the Scheme @dfn{session}. The set of features
+@cindex session
+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.
-@node Overview, Data Structures, Top, Top
-@chapter Overview
+@itemize @bullet
+@item
+'inexact
+@item
+'rational
+@item
+'real
+@item
+'complex
+@item
+'bignum
+@end itemize
-SLIB is a portable Scheme library meant to provide compatibility and
-utility functions for all standard Scheme implementations, and fixes
-several implementations which are non-conforming. SLIB conforms to
-@cite{Revised^4 Report on the Algorithmic Language Scheme} and the IEEE
-P1178 specification. SLIB supports Unix and similar systems, VMS, and
-MS-DOS.@refill
+@noindent
+Other features correspond to the presence of sets of Scheme procedures
+or syntax (macros).
-For a summary of what each file contains, see the file @file{README}.
-For a list of the features that have changed since the last SLIB
-release, see the file @file{ANNOUNCE}. For a list of the features that
-have changed over time, see the file @file{ChangeLog}.
+@defun provided? feature
+Returns @code{#t} if @var{feature} is supported by the current Scheme
+session.
+@end defun
-The maintainer can be reached as @samp{jaffer@@ai.mit.edu}.
+@deffn Procedure provide feature
+Informs SLIB that @var{feature} is supported. Henceforth
+@code{(provided? @var{feature})} will return @code{#t}.
+@end deffn
-@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.
-* Manual Conventions:: Conventions used in this manual.
-@end menu
+@example
+(provided? 'foo) @result{} #f
+(provide 'foo)
+(provided? 'foo) @result{} #t
+@end example
-@node Installation, Porting, Overview, Overview
-@section Installation
-Check the manifest in @file{README} to find a configuration file for
-your Scheme implementation. Initialization files for most IEEE P1178
-compliant Scheme Implementations are included with this distribution.
+@node Requesting Features, Library Catalogs, Feature, The Library System
+@section Requesting Features
-If the Scheme implementation supports @code{getenv}, then the value of
-the shell environment variable @var{SCHEME_LIBRARY_PATH} will be used
-for @code{(library-vicinity)} if it is defined. Currently, Chez, Elk,
-MITScheme, scheme->c, VSCM, and SCM support @code{getenv}.
+@noindent
+@cindex catalog
+SLIB creates and maintains a @dfn{catalog} mapping features to locations
+of files introducing procedures and syntax denoted by those features.
-You should check the definitions of @code{software-type},
-@code{scheme-implementation-version},
-@iftex
-@*
-@end iftex
-@code{implementation-vicinity},
-and @code{library-vicinity} in the initialization file. There are
-comments in the file for how to configure it.
+@noindent
+At the beginning of each section of this manual, there is a line like
+@code{(require '@var{feature})}.
+@ftindex feature
+The Scheme files comprising SLIB are cataloged so that these feature
+names map to the corresponding files.
-Once this is done you can modify the startup file for your Scheme
-implementation to @code{load} this initialization file. SLIB is then
-installed.
+@noindent
+SLIB provides a form, @code{require}, which loads the files providing
+the requested feature.
-Multiple implementations of Scheme can all use the same SLIB directory.
-Simply configure each implementation's initialization file as outlined
-above.
+@deffn Procedure require feature
+@itemize @bullet
+@item
+If @code{(provided? @var{feature})} is true,
+then @code{require} just returns an unspecified value.
+@item
+Otherwise, if @var{feature} is found in the catalog, then the
+corresponding files will be loaded and an unspecified value returned.
-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.
+Subsequently @code{(provided? @var{feature})} will return @code{#t}.
+@item
+Otherwise (@var{feature} not found in the catalog), an error is
+signaled.
+@end itemize
+@end deffn
-SLIB includes methods to create heap images for the VSCM and Scheme48
-implementations. The instructions for creating a VSCM image are in
-comments in @file{vscm.init}. To make a Scheme48 image, @code{cd} to
-the SLIB directory and type @code{make slib48}. This will also create a
-shell script with the name @code{slib48} which will invoke the saved
-image.
+@noindent
+The catalog can also be queried using @code{require:feature->path}.
-@node Porting, Coding Standards, Installation, Overview
-@section Porting
+@defun require:feature->path feature
+@itemize @bullet
+@item
+If @var{feature} is already provided, then returns @code{#t}.
+@item
+Otherwise, if @var{feature} is in the catalog, the path or list of paths
+associated with @var{feature} is returned.
+@item
+Otherwise, returns @code{#f}.
+@end itemize
+@end defun
-If there is no initialization file for your Scheme implementation, you
-will have to create one. Your Scheme implementation must be largely
-compliant with @cite{IEEE Std 1178-1990} or @cite{Revised^4 Report on
-the Algorithmic Language Scheme} to support SLIB.
-@file{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
-@file{.init} appended. For instance, if you were porting
-@code{foo-scheme} then the initialization file might be called
-@file{foo.init}.
+@node Library Catalogs, Catalog Compilation, Requesting Features, The Library System
+@section Library Catalogs
-Your customized version should then be loaded as part of your scheme
-implementation's initialization. It will load @file{require.scm}
-(@xref{Require}) from the library; this will allow the use of
-@code{provide}, @code{provided?}, and @code{require} along with the
-@dfn{vicinity} functions (@code{vicinity} functions are documented in
-the section on Require. @xref{Require}). The rest of the library will
-then be accessible in a system independent fashion.@refill
+@noindent
+At the start of a session no catalog is present, but is created with the
+first catalog inquiry (such as @code{(require 'random)}). Several
+sources of catalog information are combined to produce the catalog:
-Please mail new working configuration files to @code{jaffer@@ai.mit.edu}
-so that they can be included in the SLIB distribution.@refill
+@itemize @bullet
+@item
+standard SLIB packages.
+@item
+additional packages of interest to this site.
+@item
+packages specifically for the variety of Scheme which this
+session is running.
+@item
+packages this user wants to always have available. This catalog is the
+file @file{homecat} in the user's @dfn{HOME} directory.
+@cindex HOME
+@item
+packages germane to working in this (current working) directory. This
+catalog is the file @file{usercat} in the directory to which it applies.
+One would typically @code{cd} to this directory before starting the
+Scheme session.
+@end itemize
-@node Coding Standards, Copyrights, Porting, Overview
-@section Coding Standards
+@noindent
+Catalog files consist of one or more @dfn{association list}s.
+@cindex Catalog File
+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:
-All library packages are written in IEEE P1178 Scheme and assume that a
-configuration file and @file{require.scm} package have already been
-loaded. Other versions of Scheme can be supported in library packages
-as well by using, for example, @code{(provided? 'rev3-report)} or
-@code{(require 'rev3-report)} (@xref{Require}).@refill
+@table @code
+@item (@var{feature} . @i{<symbol>})
+Redirects to the feature named @i{<symbol>}.
+@item (@var{feature} . "@i{<path>}")
+Loads file @i{<path>}.
+@item (@var{feature} source "@i{<path>"})
+@code{slib:load}s the Scheme source file @i{<path>}.
+@item (@var{feature} compiled "@i{<path>"} @dots{})
+@code{slib:load-compiled}s the files @i{<path>} @dots{}.
+@end table
-@file{require.scm} defines @code{*catalog*}, an association list of
-module names and filenames. When a new package is added to the library,
-an entry should be added to @file{require.scm}. Local packages can also
-be added to @code{*catalog*} and even shadow entries already in the
-table.@refill
+@noindent
+The various macro styles first @code{require} the named macro package,
+then just load @i{<path>} or load-and-macro-expand @i{<path>} as
+appropriate for the implementation.
-The module name and @samp{:} should prefix each symbol defined in the
-package. Definitions for external use should then be exported by having
-@code{(define foo module-name:foo)}.@refill
+@table @code
+@item (@var{feature} defmacro "@i{<path>"})
+@code{defmacro:load}s the Scheme source file @i{<path>}.
+@item (@var{feature} macro-by-example "@i{<path>"})
+@code{defmacro:load}s the Scheme source file @i{<path>}.
+@end table
-Submitted code should not duplicate routines which are already in SLIB
-files. Use @code{require} to force those features to be supported in
-your package. Care should be taken that there are no circularities in
-the @code{require}s and @code{load}s between the library
-packages.@refill
+@table @code
+@item (@var{feature} macro "@i{<path>"})
+@code{macro:load}s the Scheme source file @i{<path>}.
+@item (@var{feature} macros-that-work "@i{<path>"})
+@code{macro:load}s the Scheme source file @i{<path>}.
+@item (@var{feature} syntax-case "@i{<path>"})
+@code{macro:load}s the Scheme source file @i{<path>}.
+@item (@var{feature} syntactic-closures "@i{<path>"})
+@code{macro:load}s the Scheme source file @i{<path>}.
+@end table
-Documentation should be provided in Emacs Texinfo format if possible,
-But documentation must be provided.
+@noindent
+Here is an example of a @file{usercat} catalog. A Program in this
+directory can invoke the @samp{run} feature with @code{(require 'run)}.
-Your package will be released sooner with SLIB if you send me a file
-which tests your code. Please run this test @emph{before} you send me
-the code!
+@example
+;;; "usercat": SLIB catalog additions for SIMSYNCH. -*-scheme-*-
-@subheading Modifications
+(
+ (simsynch . "../synch/simsynch.scm")
+ (run . "../synch/run.scm")
+ (schlep . "schlep.scm")
+)
+@end example
-Please document your changes. A line or two for @file{ChangeLog} is
-sufficient for simple fixes or extensions. Look at the format of
-@file{ChangeLog} to see what information is desired. Please send me
-@code{diff} files from the latest SLIB distribution (remember to send
-@code{diff}s of @file{slib.texi} and @file{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
-@file{slib.texi} and @samp{*.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.
+@node Catalog Compilation, Built-in Support, Library Catalogs, The Library System
+@section Catalog Compilation
-Please @emph{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.
-@node Copyrights, Manual Conventions, Coding Standards, Overview
-@section Copyrights
+@noindent
+SLIB combines the catalog information which doesn't vary per user into
+the file @file{slibcat} in the implementation-vicinity. Therefore
+@file{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.
-This section has instructions for SLIB authors regarding copyrights.
+@noindent
+The definition of @code{*SLIB-VERSION*} in SLIB file @file{require.scm}
+is checked against the catalog association of @code{*SLIB-VERSION*} to
+ascertain when versions have changed. I recommend that the definition
+of @code{*SLIB-VERSION*} be changed whenever the library is changed. If
+multiple implementations of Scheme use SLIB, remember that recompiling
+one @file{slibcat} will fix only that implementation's catalog.
-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 @file{require.scm} and
-@file{macwork.scm} illustrate copyright and appropriate terms.
+@noindent
+The compilation scripts of Scheme implementations which work with SLIB
+can automatically trigger catalog compilation by deleting
+@file{slibcat} or by invoking a special form of @code{require}:
-If your code or changes amount to less than about 10 lines, you do not
-need to add your copyright or send a disclaimer.
+@deffn Procedure require @r{'new-catalog}
+This will load @file{mklibcat}, which compiles and writes a new
+@file{slibcat}.
+@end deffn
-@subheading Putting code into the Public Domain
+@noindent
+Another special form of @code{require} erases SLIB's catalog, forcing it
+to be reloaded the next time the catalog is queried.
-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.
+@deffn Procedure require @r{#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.
+@end deffn
-@quotation
-I, @var{name}, hereby affirm that I have placed the software package
-@var{name} in the public domain.
+@noindent
+Each file in the table below is descibed in terms of its
+file-system independent @dfn{vicinity} (@pxref{Vicinity}). The entries
+of a catalog in the table override those of catalogs above it in the
+table.
-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.
+@table @asis
-@flushright
- @var{signature and date}
-@end flushright
-@end quotation
+@item @code{implementation-vicinity} @file{slibcat}
+@cindex slibcat
+This file contains the associations for the packages comprising SLIB,
+the @file{implcat} and the @file{sitecat}s. The associations in the
+other catalogs override those of the standard catalog.
-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.
+@item @code{library-vicinity} @file{mklibcat.scm}
+@cindex mklibcat.scm
+creates @file{slibcat}.
-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.
+@item @code{library-vicinity} @file{sitecat}
+@cindex sitecat
+This file contains the associations specific to an SLIB installation.
-@subheading Explicit copying terms
+@item @code{implementation-vicinity} @file{implcat}
+@cindex implcat
+This file contains the associations specific to an implementation of
+Scheme. Different implementations of Scheme should have different
+@code{implementation-vicinity}.
+
+@item @code{implementation-vicinity} @file{mkimpcat.scm}
+@cindex mkimpcat.scm
+if present, creates @file{implcat}.
+
+@item @code{implementation-vicinity} @file{sitecat}
+@cindex sitecat
+This file contains the associations specific to a Scheme implementation
+installation.
+
+@item @code{home-vicinity} @file{homecat}
+@cindex homecat
+This file contains the associations specific to an SLIB user.
+
+@item @code{user-vicinity} @file{usercat}
+@cindex usercat
+This file contains associations effecting only those sessions whose
+@dfn{working directory} is @code{user-vicinity}.
+
+@end table
+
+@node Built-in Support, About this manual, Catalog Compilation, The Library System
+@section Built-in Support
@noindent
-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:
+The procedures described in these sections are supported by all
+implementations as part of the @samp{*.init} files or by
+@file{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
+@end menu
+
+
+@node Require, Vicinity, Built-in Support, Built-in Support
+@subsection Require
+
+@defvar *features*
+Is a list of symbols denoting features supported in this implementation.
+@var{*features*} can grow as modules are @code{require}d.
+@var{*features*} must be defined by all implementations
+(@pxref{Porting}).
+
+Here are features which SLIB (@file{require.scm}) adds to
+@var{*features*} when appropriate.
@itemize @bullet
@item
-Arrange that your name appears in a copyright line for the appropriate
-year. Multiple copyright lines are acceptable.
+'inexact
@item
-With your copyright line, specify any terms you require to be different
-from those already in the file.
+'rational
@item
-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.
+'real
+@item
+'complex
+@item
+'bignum
@end itemize
-@subheading Example: Company Copyright Disclaimer
+For each item, @code{(provided? '@var{feature})} will return @code{#t}
+if that feature is available, and @code{#f} if not.
+@end defvar
-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:
+@defvar *modules*
+Is a list of pathnames denoting files which have been loaded.
+@end defvar
-@quotation
-@var{employer} Corporation hereby disclaims all copyright
-interest in the program @var{program} written by @var{name}.
+@defvar *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, @code{source}, or @code{compiled}. The cdr of the pathname
+should be either a string or a list.
+@end defvar
-@var{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.
+@noindent
+In the following functions if the argument @var{feature} is not a symbol
+it is assumed to be a pathname.@refill
-@flushleft
-@var{signature and date},
-@var{name}, @var{title}, @var{employer} Corporation
-@end flushleft
-@end quotation
+@defun provided? feature
+Returns @code{#t} if @var{feature} is a member of @code{*features*} or
+@code{*modules*} or if @var{feature} is supported by a file already
+loaded and @code{#f} otherwise.@refill
+@end defun
+
+@deffn Procedure require feature
+@var{feature} is a symbol. If @code{(provided? @var{feature})} is true
+@code{require} returns. Otherwise, if @code{(assq @var{feature}
+*catalog*)} is not @code{#f}, the associated files will be loaded and
+@code{(provided? @var{feature})} will henceforth return @code{#t}. An
+unspecified value is returned. If @var{feature} is not found in
+@code{*catalog*}, then an error is signaled.
+
+@deffnx Procedure require pathname
+@var{pathname} is a string. If @var{pathname} has not already been given as
+an argument to @code{require}, @var{pathname} is loaded.
+An unspecified value is returned.
+@end deffn
-@node Manual Conventions, , Copyrights, Overview
-@section Manual Conventions
+@deffn Procedure provide feature
+Assures that @var{feature} is contained in @code{*features*} if
+@var{feature} is a symbol and @code{*modules*} otherwise.@refill
+@end deffn
+
+@defun require:feature->path feature
+Returns @code{#t} if @var{feature} is a member of @code{*features*} or
+@code{*modules*} or if @var{feature} is supported by a file already
+loaded. Returns a path if one was found in @code{*catalog*} under the
+feature name, and @code{#f} otherwise. The path can either be a string
+suitable as an argument to load or a pair as described above for
+*catalog*.
+@end defun
-Things that are labeled as Functions are called for their return values.
-Things that are labeled as Procedures are called primarily for their
-side effects.
-All examples throughout this text were produced using the @code{scm}
-Scheme implementation.
-At the beginning of each section, there is a line that looks something
-like
-@code{(require 'feature)}.
+@node Vicinity, Configuration, Require, Built-in Support
+@subsection Vicinity
@noindent
-This means that, in order to use @code{feature}, you must include the
-line @code{(require 'feature)} somewhere in your code prior to the use
-of that feature. @code{require} will make sure that the feature is
-loaded.@refill
+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 @dfn{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.
+@noindent
+These procedures are provided by all implementations.
+@defun make-vicinity filename
+Returns the vicinity of @var{filename} for use by @code{in-vicinity}.
+@end defun
+@defun 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. @strong{Warning:} @code{program-vicinity} can
+return incorrect values if your program escapes back into a
+@code{load}.@refill
+@end defun
+@defun library-vicinity
+Returns the vicinity of the shared Scheme library.
+@end defun
-@node Data Structures, Macros, Overview, Top
-@chapter Data Structures
+@defun implementation-vicinity
+Returns the vicinity of the underlying Scheme implementation. This
+vicinity will likely contain startup code and messages and a compiler.
+@end defun
+@defun user-vicinity
+Returns the vicinity of the current directory of the user. On most
+systems this is @file{""} (the empty string).
+@end defun
+@defun home-vicinity
+Returns the vicinity of the user's @dfn{HOME} directory, the directory
+@cindex HOME
+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 @code{home-vicinity}
+returns @code{#f}.
+@end defun
-@menu
-* Arrays:: 'array
-* Array Mapping:: 'array-for-each
-* Association Lists:: 'alist
-* Collections:: 'collect
-* Dynamic Data Type:: 'dynamic
-* Hash Tables:: 'hash-table
-* Hashing:: 'hash, 'sierpinski, 'soundex
-* Chapter Ordering:: 'chapter-order
-* Object:: 'object
-* Parameter lists:: 'parameters
-* Priority Queues:: 'priority-queue
-* Queues:: 'queue
-* Records:: 'record
-* Base Table::
-* Relational Database:: 'relational-database
-* Weight-Balanced Trees:: 'wt-tree
-* Structures:: 'struct, 'structure
-@end menu
+@c @defun scheme-file-suffix
+@c Returns the default filename suffix for scheme source files. On most
+@c systems this is @samp{.scm}.@refill
+@c @end defun
+@defun in-vicinity vicinity filename
+Returns a filename suitable for use by @code{slib:load},
+@code{slib:load-source}, @code{slib:load-compiled},
+@code{open-input-file}, @code{open-output-file}, etc. The returned
+filename is @var{filename} in @var{vicinity}. @code{in-vicinity} should
+allow @var{filename} to override @var{vicinity} when @var{filename} is
+an absolute pathname and @var{vicinity} is equal to the value of
+@code{(user-vicinity)}. The behavior of @code{in-vicinity} when
+@var{filename} is absolute and @var{vicinity} is not equal to the value
+of @code{(user-vicinity)} is unspecified. For most systems
+@code{in-vicinity} can be @code{string-append}.@refill
+@end defun
+@defun sub-vicinity vicinity name
+Returns the vicinity of @var{vicinity} restricted to @var{name}. This
+is used for large systems where names of files in subsystems could
+conflict. On systems with directory structure @code{sub-vicinity} will
+return a pathname of the subdirectory @var{name} of
+@var{vicinity}.@refill
+@end defun
-@node Arrays, Array Mapping, Data Structures, Data Structures
-@section Arrays
-@code{(require 'array)}
+@node Configuration, Input/Output, Vicinity, Built-in Support
+@subsection Configuration
-@defun array? obj
-Returns @code{#t} if the @var{obj} is an array, and @code{#f} if not.
-@end defun
+@noindent
+These constants and procedures describe characteristics of the Scheme
+and underlying operating system. They are provided by all
+implementations.
-@defun make-array initial-value bound1 bound2 @dots{}
-Creates and returns an array that has as many dimensins as there are
-@var{bound}s and fills it with @var{initial-value}.@refill
+@defvr Constant char-code-limit
+An integer 1 larger that the largest value which can be returned by
+@code{char->integer}.@refill
+@end defvr
+
+@defvr Constant most-positive-fixnum
+The immediate integer closest to positive infinity.
+@end defvr
+
+@defvr Constant slib:tab
+The tab character.
+@end defvr
+
+@defvr Constant slib:form-feed
+The form-feed character.
+@end defvr
+
+@defun software-type
+Returns a symbol denoting the generic operating system type. For
+instance, @code{unix}, @code{vms}, @code{macos}, @code{amiga}, or
+@code{ms-dos}.
@end defun
-When constructing an array, @var{bound} is either an inclusive range of
-indices expressed as a two element list, or an upper bound expressed as
-a single integer. So@refill
-@lisp
-(make-array 'foo 3 3) @equiv{} (make-array 'foo '(0 2) '(0 2))
-@end lisp
+@defun 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.
-@defun make-shared-array array mapper bound1 bound2 @dots{}
-@code{make-shared-array} can be used to create shared subarrays of other
-arrays. The @var{mapper} is a function that translates coordinates in
-the new array into coordinates in the old array. A @var{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:@refill
-@lisp
-(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)
- @result{} FOO
-(define freds-center
- (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j)))
- 2 2))
-(array-ref freds-center 0 0)
- @result{} FOO
-@end lisp
+@example
+(slib:report-version) @result{} slib "2c0" on scm "5b1" on unix
+@end example
@end defun
-@defun array-rank obj
-Returns the number of dimensions of @var{obj}. If @var{obj} is not an
-array, 0 is returned.
+@defun slib:report
+Displays the information of @code{(slib:report-version)} followed by
+almost all the information neccessary for submitting a problem report.
+An unspecified value is returned.
+
+@defunx slib:report #t
+provides a more verbose listing.
+
+@defunx slib:report filename
+Writes the report to file @file{filename}.
+
+@example
+(slib:report)
+@result{}
+slib "2c0" 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")
+ ...
+@end example
@end defun
-@defun array-shape array
-@code{array-shape} returns a list of inclusive bounds. So:
+@node Input/Output, Legacy, Configuration, Built-in Support
+@subsection Input/Output
+
+@noindent
+These procedures are provided by all implementations.
+
+@deffn Procedure file-exists? filename
+Returns @code{#t} if the specified file exists. Otherwise, returns
+@code{#f}. If the underlying implementation does not support this
+feature then @code{#f} is always returned.
+@end deffn
+
+@deffn Procedure delete-file filename
+Deletes the file specified by @var{filename}. If @var{filename} can not
+be deleted, @code{#f} is returned. Otherwise, @code{#t} is
+returned.@refill
+@end deffn
+
+@deffn Procedure tmpnam
+Returns a pathname for a file which will likely not be used by any other
+process. Successive calls to @code{(tmpnam)} will return different
+pathnames.@refill
+@end deffn
+
+@deffn Procedure current-error-port
+Returns the current port to which diagnostic and error output is
+directed.
+@end deffn
+
+@deffn Procedure force-output
+@deffnx Procedure force-output port
+Forces any pending output on @var{port} to be delivered to the output
+device and returns an unspecified value. The @var{port} argument may be
+omitted, in which case it defaults to the value returned by
+@code{(current-output-port)}.@refill
+@end deffn
+
+@deffn Procedure output-port-width
+@deffnx Procedure output-port-width port
+
+Returns the width of @var{port}, which defaults to
+@code{(current-output-port)} if absent. If the width cannot be
+determined 79 is returned.@refill
+@end deffn
+
+@deffn Procedure output-port-height
+@deffnx Procedure output-port-height port
+
+Returns the height of @var{port}, which defaults to
+@code{(current-output-port)} if absent. If the height cannot be
+determined 24 is returned.@refill
+@end deffn
+
+@node Legacy, System, Input/Output, Built-in Support
+@subsection Legacy
+
+These procedures are provided by all implementations.
+
+@defun identity x
+@var{identity} returns its argument.
+
+Example:
@lisp
-(array-shape (make-array 'foo 3 5))
- @result{} ((0 2) (0 4))
+(identity 3)
+ @result{} 3
+(identity '(foo bar))
+ @result{} (foo bar)
+(map identity @var{lst})
+ @equiv{} (copy-list @var{lst})
@end lisp
@end defun
-@defun array-dimensions array
-@code{array-dimensions} is similar to @code{array-shape} but replaces
-elements with a 0 minimum with one greater than the maximum. So:
+@noindent
+The following procedures were present in Scheme until R4RS
+(@pxref{Notes, , Language changes ,r4rs, Revised(4) Scheme}).
+They are provided by all SLIB implementations.
+
+@defvr Constant t
+Derfined as @code{#t}.
+@end defvr
+
+@defvr Constant nil
+Defined as @code{#f}.
+@end defvr
+
+@defun last-pair l
+Returns the last pair in the list @var{l}. Example:
@lisp
-(array-dimensions (make-array 'foo 3 5))
- @result{} (3 5)
+(last-pair (cons 1 2))
+ @result{} (1 . 2)
+(last-pair '(1 2))
+ @result{} (2)
+ @equiv{} (cons 2 '())
@end lisp
@end defun
-@deffn Procedure array-in-bounds? array index1 index2 @dots{}
-Returns @code{#t} if its arguments would be acceptable to
-@code{array-ref}.
+@node System, , Legacy, Built-in Support
+@subsection System
+
+@noindent
+These procedures are provided by all implementations.
+
+@deffn Procedure slib:load-source name
+Loads a file of Scheme source code from @var{name} with the default
+filename extension used in SLIB. For instance if the filename extension
+used in SLIB is @file{.scm} then @code{(slib:load-source "foo")} will
+load from file @file{foo.scm}.
@end deffn
-@defun array-ref array index1 index2 @dots{}
-Returns the element at the @code{(@var{index1}, @var{index2})} element
-in @var{array}.@refill
-@end defun
+@deffn Procedure slib:load-compiled name
+On implementations which support separtely loadable compiled modules,
+loads a file of compiled code from @var{name} with the implementation's
+filename extension for compiled code appended.
+@end deffn
-@deffn Procedure array-set! array new-value index1 index2 @dots{}
+@deffn Procedure slib:load name
+Loads a file of Scheme source or compiled code from @var{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
+@code{slib:load} will be identical to @code{slib:load-source}.
@end deffn
-@defun array-1d-ref array index
-@defunx array-2d-ref array index index
-@defunx array-3d-ref array index index index
-@end defun
+@deffn Procedure slib:eval obj
+@code{eval} returns the value of @var{obj} evaluated in the current top
+level environment.@refill
+@end deffn
-@deffn Procedure array-1d-set! array new-value index
-@deffnx Procedure array-2d-set! array new-value index index
-@deffnx Procedure array-3d-set! array new-value index index index
+@deffn Procedure slib:eval-load filename eval
+@var{filename} should be a string. If filename names an existing file,
+the Scheme source code expressions and definitions are read from the
+file and @var{eval} called with them sequentially. The
+@code{slib:eval-load} procedure does not affect the values returned by
+@code{current-input-port} and @code{current-output-port}.@refill
@end deffn
-The functions are just fast versions of @code{array-ref} and
-@code{array-set!} that take a fixed number of arguments, and perform no
-bounds checking.@refill
+@deffn Procedure slib:warn arg1 arg2 @dots{}
+Outputs a warning message containing the arguments.
+@end deffn
-If you comment out the bounds checking code, this is about as efficient
-as you could ask for without help from the compiler.
+@deffn Procedure slib:error arg1 arg2 @dots{}
+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.@refill
+@end deffn
-An exercise left to the reader: implement the rest of APL.
+@deffn Procedure slib:exit n
+@deffnx Procedure slib:exit
+Exits from the Scheme session returning status @var{n} to the system.
+If @var{n} is omitted or @code{#t}, a success status is returned to the
+system (if possible). If @var{n} is @code{#f} a failure is returned to
+the system (if possible). If @var{n} is an integer, then @var{n} is
+returned to the system (if possible). If the Scheme session cannot exit
+an unspecified value is returned from @code{slib:exit}.
+@end deffn
+@node About this manual, , Built-in Support, The Library System
+@section About this manual
-@node Array Mapping, Association Lists, Arrays, Data Structures
-@section Array Mapping
+@itemize @bullet
+@item
+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.
-@code{(require 'array-for-each)}
+@item
+Examples in this text were produced using the @code{scm} Scheme
+implementation.
-@defun array-map! array0 proc array1 @dots{}
-@var{array1}, @dots{} must have the same number of dimensions as
-@var{array0} and have a range for each index which includes the range
-for the corresponding index in @var{array0}. @var{proc} is applied to
-each tuple of elements of @var{array1} @dots{} and the result is stored
-as the corresponding element in @var{array0}. The value returned is
-unspecified. The order of application is unspecified.
-@end defun
+@item
+At the beginning of each section, there is a line that looks like
+@ftindex feature
+@code{(require 'feature)}. Include this line in your code prior to
+using the package.
+@end itemize
-@defun array-for-each @var{proc} @var{array0} @dots{}
-@var{proc} is applied to each tuple of elements of @var{array0} @dots{}
-in row-major order. The value returned is unspecified.
-@end defun
-@defun array-indexes @var{array}
-Returns an array of lists of indexes for @var{array} such that, if
-@var{li} is a list of indexes for which @var{array} is defined, (equal?
-@var{li} (apply array-ref (array-indexes @var{array}) @var{li})).
-@end defun
+@node Scheme Syntax Extension Packages, Textual Conversion Packages, The Library System, Top
+@chapter Scheme Syntax Extension Packages
-@defun array-copy! source destination
-Copies every element from vector or array @var{source} to the
-corresponding element of @var{destination}. @var{destination} must have
-the same rank as @var{source}, and be at least as large in each
-dimension. The order of copying is unspecified.
-@end defun
+@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
-@node Association Lists, Collections, Array Mapping, Data Structures
-@section Association Lists
+Syntax extensions (macros) included with SLIB. Also @xref{Structures}.
-@code{(require 'alist)}
+* Fluid-Let:: 'fluid-let
+* Yasos:: 'yasos, 'oop, 'collect
+@end menu
-Alist functions provide utilities for treating a list of key-value pairs
-as an associative database. These functions take an equality predicate,
-@var{pred}, as an argument. This predicate should be repeatable,
-symmetric, and transitive.@refill
-Alist functions can be used with a secondary index method such as hash
-tables for improved performance.
+@node Defmacro, R4RS Macros, Scheme Syntax Extension Packages, Scheme Syntax Extension Packages
+@section Defmacro
-@defun predicate->asso pred
-Returns an @dfn{association function} (like @code{assq}, @code{assv}, or
-@code{assoc}) corresponding to @var{pred}. The returned function
-returns a key-value pair whose key is @code{pred}-equal to its first
-argument or @code{#f} if no key in the alist is @var{pred}-equal to the
-first argument.@refill
+Defmacros are supported by all implementations.
+@c See also @code{gentemp}, in @ref{Macros}.
+
+@defun gentemp
+Returns a new (interned) symbol each time it is called. The symbol
+names are implementation-dependent
+@lisp
+(gentemp) @result{} scm:G0
+(gentemp) @result{} scm:G1
+@end lisp
@end defun
-@defun alist-inquirer pred
-Returns a procedure of 2 arguments, @var{alist} and @var{key}, which
-returns the value associated with @var{key} in @var{alist} or @code{#f} if
-@var{key} does not appear in @var{alist}.@refill
+@defun defmacro:eval e
+Returns the @code{slib:eval} of expanding all defmacros in scheme
+expression @var{e}.
@end defun
-@defun alist-associator pred
-Returns a procedure of 3 arguments, @var{alist}, @var{key}, and
-@var{value}, which returns an alist with @var{key} and @var{value}
-associated. Any previous value associated with @var{key} will be
-lost. This returned procedure may or may not have side effects on its
-@var{alist} argument. An example of correct usage is:@refill
-@lisp
-(define put (alist-associator string-ci=?))
-(define alist '())
-(set! alist (put alist "Foo" 9))
-@end lisp
+@defun defmacro:load filename
+@var{filename} should be a string. If filename names an existing file,
+the @code{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 @code{macro:load} procedure does not affect the values
+returned by @code{current-input-port} and
+@code{current-output-port}.@refill
@end defun
-@defun alist-remover pred
-Returns a procedure of 2 arguments, @var{alist} and @var{key}, which
-returns an alist with an association whose @var{key} is key removed.
-This returned procedure may or may not have side effects on its
-@var{alist} argument. An example of correct usage is:@refill
-@lisp
-(define rem (alist-remover string-ci=?))
-(set! alist (rem alist "foo"))
-@end lisp
+@defun defmacro? sym
+Returns @code{#t} if @var{sym} has been defined by @code{defmacro},
+@code{#f} otherwise.
@end defun
-@defun alist-map proc alist
-Returns a new association list formed by mapping @var{proc} over the
-keys and values of @var{alist}. @var{proc} must be a function of 2
-arguments which returns the new value part.
+@defun macroexpand-1 form
+@defunx macroexpand form
+If @var{form} is a macro call, @code{macroexpand-1} will expand the
+macro call once and return it. A @var{form} is considered to be a macro
+call only if it is a cons whose @code{car} is a symbol for which a
+@code{defmacr} has been defined.
+
+@code{macroexpand} is similar to @code{macroexpand-1}, but repeatedly
+expands @var{form} until it is no longer a macro call.
@end defun
-@defun alist-for-each proc alist
-Applies @var{proc} to each pair of keys and values of @var{alist}.
-@var{proc} must be a function of 2 arguments. The returned value is
-unspecified.
+@defmac defmacro name lambda-list form @dots{}
+When encountered by @code{defmacro:eval}, @code{defmacro:macroexpand*},
+or @code{defmacro:load} defines a new macro which will henceforth be
+expanded when encountered by @code{defmacro:eval},
+@code{defmacro:macroexpand*}, or @code{defmacro:load}.
+@end defmac
+
+@subsection Defmacroexpand
+@code{(require 'defmacroexpand)}
+@ftindex defmacroexpand
+
+@defun defmacro:expand* e
+Returns the result of expanding all defmacros in scheme expression
+@var{e}.
@end defun
+@node R4RS Macros, Macro by Example, Defmacro, Scheme Syntax Extension Packages
+@section R4RS Macros
-@node Collections, Dynamic Data Type, Association Lists, Data Structures
-@section Collections
+@code{(require 'macro)} is the appropriate call if you want R4RS
+@ftindex macro
+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.
-@c Much of the documentation in this section was written by Dave Love
-@c (d.love@dl.ac.uk) -- don't blame Ken Dickey for its faults.
-@c but we can blame him for not writing it!
+The SLIB R4RS macro implementations support the following uniform
+interface:
-@code{(require 'collect)}
+@defun macro:expand sexpression
+Takes an R4RS expression, macro-expands it, and returns the result of
+the macro expansion.
+@end defun
-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
-@dfn{elements} indexed by corresponding @dfn{keys}, although the keys
-may be implicit (as with lists).@refill
+@defun macro:eval sexpression
+Takes an R4RS expression, macro-expands it, evals the result of the
+macro expansion, and returns the result of the evaluation.
+@end defun
+
+@deffn Procedure macro:load filename
+@var{filename} should be a string. If filename names an existing file,
+the @code{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
+@code{macro:load} procedure does not affect the values returned by
+@code{current-input-port} and @code{current-output-port}.@refill
+@end deffn
+
+@node Macro by Example, Macros That Work, R4RS Macros, Scheme Syntax Extension Packages
+@section Macro by Example
+
+@code{(require 'macro-by-example)}
+@ftindex macro-by-example
+
+A vanilla implementation of @cite{Macro by Example} (Eugene Kohlbecker,
+R4RS) by Dorai Sitaram, (dorai@@cs.rice.edu) using @code{defmacro}.
-New types of collections may be defined as YASOS objects (@xref{Yasos}).
-They must support the following operations:
@itemize @bullet
-@item
-@code{(collection? @var{self})} (always returns @code{#t});
@item
-@code{(size @var{self})} returns the number of elements in the collection;
+generating hygienic global @code{define-syntax} Macro-by-Example macros
+@strong{cheaply}.
@item
-@code{(print @var{self} @var{port})} is a specialized print operation
-for the collection which prints a suitable representation on the given
-@var{port} or returns it as a string if @var{port} is @code{#t};@refill
+can define macros which use @code{...}.
@item
-@code{(gen-elts @var{self})} returns a thunk which on successive
-invocations yields elements of @var{self} in order or gives an error if
-it is invoked more than @code{(size @var{self})} times;@refill
+needn't worry about a lexical variable in a macro definition
+clashing with a variable from the macro use context
@item
-@code{(gen-keys @var{self})} is like @code{gen-elts}, but yields the
-collection's keys in order.
+don't suffer the overhead of redefining the repl if @code{defmacro}
+natively supported (most implementations)
@end itemize
-They might support specialized @code{for-each-key} and
-@code{for-each-elt} operations.@refill
+@subsection Caveat
+These macros are not referentially transparent (@pxref{Macros, , ,r4rs,
+Revised(4) Scheme}). Lexically scoped macros (i.e., @code{let-syntax}
+and @code{letrec-syntax}) are not supported. In any case, the problem
+of referential transparency gains poignancy only when @code{let-syntax}
+and @code{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 @cite{r4rs} macro functionality, look to the
+more featureful (but also more expensive) versions of syntax-rules
+available in slib @ref{Macros That Work}, @ref{Syntactic Closures}, and
+@ref{Syntax-Case Macros}.
-@defun collection? obj
-A predicate, true initially of lists, vectors and strings. New sorts of
-collections must answer @code{#t} to @code{collection?}.@refill
+@defmac define-syntax keyword transformer-spec
+The @var{keyword} is an identifier, and the @var{transformer-spec}
+should be an instance of @code{syntax-rules}.
+
+The top-level syntactic environment is extended by binding the
+@var{keyword} to the specified transformer.
+
+@example
+(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 ...)))))
+@end example
+@end defmac
+
+@defmac syntax-rules literals syntax-rule @dots{}
+@var{literals} is a list of identifiers, and each @var{syntax-rule}
+should be of the form
+
+@code{(@var{pattern} @var{template})}
+
+where the @var{pattern} and @var{template} are as in the grammar above.
+
+An instance of @code{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
+@code{syntax-rules} is matched against the patterns contained in the
+@var{syntax-rule}s, beginning with the leftmost @var{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.
+@end defmac
+
+@node Macros That Work, Syntactic Closures, Macro by Example, Scheme Syntax Extension Packages
+@section Macros That Work
+
+@code{(require 'macros-that-work)}
+@ftindex macros-that-work
+
+@cite{Macros That Work} differs from the other R4RS macro
+implementations in that it does not expand derived expression types to
+primitive expression types.
+
+@defun macro:expand expression
+@defunx macwork:expand expression
+Takes an R4RS expression, macro-expands it, and returns the result of
+the macro expansion.
@end defun
-@deffn Procedure map-elts proc . collections
-@deffnx Procedure do-elts proc . collections
-@var{proc} is a procedure taking as many arguments as there are
-@var{collections} (at least one). The @var{collections} are iterated
-over in their natural order and @var{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 @var{collections} appear.
-@code{do-elts} is used when only side-effects of @var{proc} are of
-interest and its return value is unspecified. @code{map-elts} returns a
-collection (actually a vector) of the results of the applications of
-@var{proc}.@refill
+@defun macro:eval expression
+@defunx macwork:eval expression
+@code{macro:eval} returns the value of @var{expression} in the current
+top level environment. @var{expression} can contain macro definitions.
+Side effects of @var{expression} will affect the top level
+environment.@refill
+@end defun
-Example:
+@deffn Procedure macro:load filename
+@deffnx Procedure macwork:load filename
+@var{filename} should be a string. If filename names an existing file,
+the @code{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
+@code{macro:load} procedure does not affect the values returned by
+@code{current-input-port} and @code{current-output-port}.@refill
+@end deffn
+
+References:
+
+The @cite{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.@refill
+
+@center 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.
+
+@example
+transformer spec @expansion{} (syntax-rules literals rules)
+
+rules @expansion{} ()
+ | (rule . rules)
+
+rule @expansion{} (pattern template)
+
+pattern @expansion{} 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 @expansion{} pattern_var
+ | symbol
+ | ()
+ | (template2 . template2)
+ | #(template*) ; extends R4RS
+ | pattern_datum
+
+template2 @expansion{} template
+ | ellipsis_template
+
+pattern_datum @expansion{} string ; no vector
+ | character
+ | boolean
+ | number
+
+ellipsis_pattern @expansion{} pattern ...
+
+ellipsis_template @expansion{} template ...
+
+pattern_var @expansion{} symbol ; not in literals
+
+literals @expansion{} ()
+ | (symbol . literals)
+@end example
+
+@subsection Definitions
+
+@table @asis
+
+@item Scope of an ellipsis
+Within a pattern or template, the scope of an ellipsis (@code{...}) is
+the pattern or template that appears to its left.
+
+@item Rank of a pattern variable
+The rank of a pattern variable is the number of ellipses within whose
+scope it appears in the pattern.
+
+@item Rank of a subtemplate
+The rank of a subtemplate is the number of ellipses within whose scope
+it appears in the template.
+
+@item 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.
+
+@item Variables bound by a pattern
+The variables bound by a pattern are the pattern variables that appear
+within it.
+
+@item Referenced variables of a subtemplate
+The referenced variables of a subtemplate are the pattern variables that
+appear within it.
+
+@item 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.
+
+@end table
+
+@subsection 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 @var{rule} is
+
+@example
+rule @expansion{} (pattern template inserted)
+
+pattern @expansion{} pattern_var
+ | symbol
+ | ()
+ | (pattern . pattern)
+ | ellipsis_pattern
+ | #(pattern)
+ | pattern_datum
+
+template @expansion{} pattern_var
+ | symbol
+ | ()
+ | (template2 . template2)
+ | #(pattern)
+ | pattern_datum
+
+template2 @expansion{} template
+ | ellipsis_template
+
+pattern_datum @expansion{} string
+ | character
+ | boolean
+ | number
+
+pattern_var @expansion{} #(V symbol rank)
+
+ellipsis_pattern @expansion{} #(E pattern pattern_vars)
+
+ellipsis_template @expansion{} #(E template pattern_vars)
+
+inserted @expansion{} ()
+ | (symbol . inserted)
+
+pattern_vars @expansion{} ()
+ | (pattern_var . pattern_vars)
+
+rank @expansion{} exact non-negative integer
+@end example
+
+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.
+
+
+
+
+
+@node Syntactic Closures, Syntax-Case Macros, Macros That Work, Scheme Syntax Extension Packages
+@section Syntactic Closures
+
+@code{(require 'syntactic-closures)}
+@ftindex syntactic-closures
+
+@defun macro:expand expression
+@defunx synclo:expand expression
+Returns scheme code with the macros and derived expression types of
+@var{expression} expanded to primitive expression types.@refill
+@end defun
+
+@defun macro:eval expression
+@defunx synclo:eval expression
+@code{macro:eval} returns the value of @var{expression} in the current
+top level environment. @var{expression} can contain macro definitions.
+Side effects of @var{expression} will affect the top level
+environment.@refill
+@end defun
+
+@deffn Procedure macro:load filename
+@deffnx Procedure synclo:load filename
+@var{filename} should be a string. If filename names an existing file,
+the @code{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 @code{macro:load} procedure does not affect the values returned by
+@code{current-input-port} and @code{current-output-port}.@refill
+@end deffn
+
+@subsection Syntactic Closure Macro Facility
+
+@center A Syntactic Closures Macro Facility
+@center by Chris Hanson
+@center 9 November 1991
+
+This document describes @dfn{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
+@cite{Revised^4 Report on Scheme.} This document is an addendum to that
+report.
+
+The syntactic closures facility extends the BNF rule for
+@var{transformer spec} to allow a new keyword that introduces a
+low-level macro transformer:@refill
+@example
+@var{transformer spec} := (transformer @var{expression})
+@end example
+
+Additionally, the following procedures are added:
@lisp
-(map-elts + (list 1 2 3) (vector 1 2 3))
- @result{} #(2 4 6)
+make-syntactic-closure
+capture-syntactic-environment
+identifier?
+identifier=?
@end lisp
-@end deffn
-@deffn Procedure map-keys proc . collections
-@deffnx Procedure do-keys proc . collections
-These are analogous to @code{map-elts} and @code{do-elts}, but each
-iteration is over the @var{collections}' @emph{keys} rather than their
-elements.@refill
+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
+@dfn{identifiers}, which extend the syntactic closure mechanism to be
+compatible with @code{syntax-rules}.@refill
-Example:
+@subsubsection Terminology
+
+This section defines the concepts and data types used by the syntactic
+closures facility.
+
+@itemize @bullet
+
+@item @dfn{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 @code{set!} special form is also a form. Examples of
+forms:@refill
@lisp
-(map-keys + (list 1 2 3) (vector 1 2 3))
- @result{} #(0 2 4)
+17
+#t
+car
+(+ x 4)
+(lambda (x) x)
+(define pi 3.14159)
+if
+define
@end lisp
-@end deffn
-@deffn Procedure for-each-key collection proc
-@deffnx Procedure for-each-elt collection proc
-These are like @code{do-keys} and @code{do-elts} but only for a single
-collection; they are potentially more efficient.
+@item An @dfn{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
+@code{symbol?}. Macro transformers rarely distinguish symbols from
+aliases, referring to both as identifiers.@refill
+
+@item A @dfn{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.@refill
+
+@item A @dfn{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.@refill
+
+@end itemize
+
+@subsubsection Transformer Definition
+
+This section describes the @code{transformer} special form and the
+procedures @code{make-syntactic-closure} and
+@code{capture-syntactic-environment}.@refill
+
+@deffn Syntax transformer expression
+
+Syntax: It is an error if this syntax occurs except as a
+@var{transformer spec}.@refill
+
+Semantics: The @var{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
+@code{transformer} expression appears (for example,
+@code{let-syntax}).@refill
+
+A @dfn{macro transformer} is a procedure that takes two arguments, a
+form and a syntactic environment, and returns a new form. The first
+argument, the @dfn{input form}, is the form in which the macro keyword
+occurred. The second argument, the @dfn{usage environment}, is the
+syntactic environment in which the input form occurred. The result of
+the transformer, the @dfn{output form}, is automatically closed in the
+@dfn{transformer environment}, which is the syntactic environment in
+which the @code{transformer} expression occurred.@refill
+
+For example, here is a definition of a push macro using
+@code{syntax-rules}:@refill
+@lisp
+(define-syntax push
+ (syntax-rules ()
+ ((push item list)
+ (set! list (cons item list)))))
+@end lisp
+
+Here is an equivalent definition using @code{transformer}:
+@lisp
+(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))))))
+@end lisp
+
+In this example, the identifiers @code{set!} and @code{cons} are closed
+in the transformer environment, and thus will not be affected by the
+meanings of those identifiers in the usage environment
+@code{env}.@refill
+
+Some macros may be non-hygienic by design. For example, the following
+defines a loop macro that implicitly binds @code{exit} to an escape
+procedure. The binding of @code{exit} is intended to capture free
+references to @code{exit} in the body of the loop, so @code{exit} must
+be left free when the body is closed:@refill
+@lisp
+(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))))))))
+@end lisp
+
+To assign meanings to the identifiers in a form, use
+@code{make-syntactic-closure} to close the form in a syntactic
+environment.@refill
@end deffn
-@defun reduce proc seed . collections
-A generalization of the list-based @code{comlist:reduce-init}
-(@xref{Lists as sequences}) to collections which will shadow the
-list-based version if @code{(require 'collect)} follows @code{(require
-'common-list-functions)} (@xref{Common List Functions}).@refill
+@defun make-syntactic-closure environment free-names form
-Examples:
+@var{environment} must be a syntactic environment, @var{free-names} must
+be a list of identifiers, and @var{form} must be a form.
+@code{make-syntactic-closure} constructs and returns a syntactic closure
+of @var{form} in @var{environment}, which can be used anywhere that
+@var{form} could have been used. All the identifiers used in
+@var{form}, except those explicitly excepted by @var{free-names}, obtain
+their meanings from @var{environment}.@refill
+
+Here is an example where @var{free-names} is something other than the
+empty list. It is instructive to compare the use of @var{free-names} in
+this example with its use in the @code{loop} example above: the examples
+are similar except for the source of the identifier being left
+free.@refill
@lisp
-(reduce + 0 (vector 1 2 3))
- @result{} 6
-(reduce union '() '((a b c) (b c d) (d a)))
- @result{} (c b d a).
+(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))))))
@end lisp
+
+@code{let1} is a simplified version of @code{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 @code{let1} must be
+left free, so that it can be properly captured by the @code{lambda} in
+the output form.@refill
+
+To obtain a syntactic environment other than the usage environment, use
+@code{capture-syntactic-environment}.@refill
@end defun
-@defun any? pred . collections
-A generalization of the list-based @code{some} (@xref{Lists as
-sequences}) to collections.@refill
+@defun capture-syntactic-environment procedure
-Example:
+@code{capture-syntactic-environment} returns a form that will, when
+transformed, call @var{procedure} on the current syntactic environment.
+@var{procedure} should compute and return a new form to be transformed,
+in that same syntactic environment, in place of the form.@refill
+
+An example will make this clear. Suppose we wanted to define a simple
+@code{loop-until} keyword equivalent to@refill
@lisp
-(any? odd? (list 2 3 4 5))
- @result{} #t
+(define-syntax loop-until
+ (syntax-rules ()
+ ((loop-until id init test return step)
+ (letrec ((loop
+ (lambda (id)
+ (if test return (loop step)))))
+ (loop init)))))
+@end lisp
+
+The following attempt at defining @code{loop-until} has a subtle bug:
+@lisp
+(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 '())))))))
+@end lisp
+
+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 @code{id} identifier
+free in the @code{test}, @code{return}, and @code{step} expressions, so
+that it will be captured by the binding introduced by the @code{lambda}
+expression. Unfortunately it uses the identifiers @code{if} and
+@code{loop} within that @code{lambda} expression, so if the user of
+@code{loop-until} just happens to use, say, @code{if} for the
+identifier, it will be inadvertently captured.@refill
+
+The syntactic environment that @code{if} and @code{loop} want to be
+exposed to is the one just outside the @code{lambda} expression: before
+the user's identifier is added to the syntactic environment, but after
+the identifier loop has been added.
+@code{capture-syntactic-environment} captures exactly that environment
+as follows:@refill
+@lisp
+(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 '())))))))
+@end lisp
+
+In this case, having captured the desired syntactic environment, it is
+convenient to construct syntactic closures of the identifiers @code{if}
+and the @code{loop} and use them in the body of the
+@code{lambda}.@refill
+
+A common use of @code{capture-syntactic-environment} is to get the
+transformer environment of a macro transformer:@refill
+@lisp
+(transformer
+ (lambda (exp env)
+ (capture-syntactic-environment
+ (lambda (transformer-env)
+ ...))))
@end lisp
@end defun
-@defun every? pred . collections
-A generalization of the list-based @code{every} (@xref{Lists as
-sequences}) to collections.@refill
+@subsubsection Identifiers
-Example:
+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 @code{syntax-rules} facility.@refill
+
+As discussed earlier, an identifier is either a symbol or an
+@dfn{alias}. An alias is implemented as a syntactic closure whose
+@dfn{form} is an identifier:@refill
@lisp
-(every? collection? '((1 2) #(1 2)))
+(make-syntactic-closure env '() 'a)
+ @result{} an @dfn{alias}
+@end lisp
+
+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 @code{lambda} or
+@code{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.@refill
+
+Aliases are used in the implementation of the high-level facility
+@code{syntax-rules}. A macro transformer created by @code{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.
+
+@defun identifier? object
+Returns @code{#t} if @var{object} is an identifier, otherwise returns
+@code{#f}. Examples:@refill
+@lisp
+(identifier? 'a)
@result{} #t
+(identifier? (make-syntactic-closure env '() 'a))
+ @result{} #t
+(identifier? "a")
+ @result{} #f
+(identifier? #\a)
+ @result{} #f
+(identifier? 97)
+ @result{} #f
+(identifier? #f)
+ @result{} #f
+(identifier? '(a))
+ @result{} #f
+(identifier? '#(a))
+ @result{} #f
@end lisp
+
+The predicate @code{eq?} is used to determine if two identifers are
+``the same''. Thus @code{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 @code{cond} macro uses the symbol @code{else} to identify
+the final clause in the conditional. A macro transformer for
+@code{cond} cannot just look for the symbol @code{else}, because the
+@code{cond} form might be the output of another macro transformer that
+replaced the symbol @code{else} with an alias. Instead the transformer
+must look for an identifier that ``means the same thing'' in the usage
+environment as the symbol @code{else} means in the transformer
+environment.@refill
@end defun
-@defun empty? collection
-Returns @code{#t} iff there are no elements in @var{collection}.
+@defun identifier=? environment1 identifier1 environment2 identifier2
+@var{environment1} and @var{environment2} must be syntactic
+environments, and @var{identifier1} and @var{identifier2} must be
+identifiers. @code{identifier=?} returns @code{#t} if the meaning of
+@var{identifier1} in @var{environment1} is the same as that of
+@var{identifier2} in @var{environment2}, otherwise it returns @code{#f}.
+Examples:@refill
-@code{(empty? @var{collection}) @equiv{} (zero? (size @var{collection}))}
+@lisp
+(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))))
+ @result{} (#t #f)
+@end lisp
+
+@lisp
+(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))))
+ @result{} (#f #t)
+@end lisp
@end defun
-@defun size collection
-Returns the number of elements in @var{collection}.
+@subsubsection Acknowledgements
+
+The syntactic closures facility was invented by Alan Bawden and Jonathan
+Rees. The use of aliases to implement @code{syntax-rules} was invented
+by Alan Bawden (who prefers to call them @dfn{synthetic names}). Much
+of this proposal is derived from an earlier proposal by Alan
+Bawden.@refill
+
+
+
+
+
+@node Syntax-Case Macros, Fluid-Let, Syntactic Closures, Scheme Syntax Extension Packages
+@section Syntax-Case Macros
+
+@code{(require 'syntax-case)}
+@ftindex syntax-case
+
+@defun macro:expand expression
+@defunx syncase:expand expression
+Returns scheme code with the macros and derived expression types of
+@var{expression} expanded to primitive expression types.@refill
@end defun
-@defun Setter list-ref
-See @xref{Setters} for a definition of @dfn{setter}. N.B.
-@code{(setter list-ref)} doesn't work properly for element 0 of a
-list.@refill
+@defun macro:eval expression
+@defunx syncase:eval expression
+@code{macro:eval} returns the value of @var{expression} in the current
+top level environment. @var{expression} can contain macro definitions.
+Side effects of @var{expression} will affect the top level
+environment.@refill
@end defun
-Here is a sample collection: @code{simple-table} which is also a
-@code{table}.@refill
+@deffn Procedure macro:load filename
+@deffnx Procedure syncase:load filename
+@var{filename} should be a string. If filename names an existing file,
+the @code{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 @code{macro:load} procedure does not affect the values returned by
+@code{current-input-port} and @code{current-output-port}.@refill
+@end deffn
+
+This is version 2.1 of @code{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:
+
+@itemize @bullet
+@item
+Removing white space from @file{expand.pp} to save space in the
+distribution. This file is not meant for human readers anyway@dots{}
+
+@item
+Removed a couple of Chez scheme dependencies.
+
+@item
+Renamed global variables used to minimize the possibility of name
+conflicts.
+
+@item
+Adding an SLIB-specific initialization file.
+
+@item
+Removing a couple extra files, most notably the documentation (but see
+below).
+@end itemize
+
+If you wish, you can see exactly what changes were done by reading the
+shell script in the file @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 @code{syntax-case},
+however, you should get these files and print them out on a PostScript
+printer. They are available with the original @code{syntax-case}
+distribution by anonymous FTP in
+@file{cs.indiana.edu:/pub/scheme/syntax-case}.@refill
+
+In order to use syntax-case from an interactive top level, execute:
@lisp
-(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
+(require 'syntax-case)
+@ftindex syntax-case
+(require 'repl)
+@ftindex repl
+(repl:top-level macro:eval)
+@end lisp
+See the section Repl (@xref{Repl}) for more information.
-(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)
- )
- ) ) )
+To check operation of syntax-case get
+@file{cs.indiana.edu:/pub/scheme/syntax-case}, and type
+@lisp
+(require 'syntax-case)
+@ftindex syntax-case
+(syncase:sanity-check)
@end lisp
+Beware that @code{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).
+@subsection Notes
+All R4RS syntactic forms are defined, including @code{delay}. Along
+with @code{delay} are simple definitions for @code{make-promise} (into
+which @code{delay} expressions expand) and @code{force}.@refill
+@code{syntax-rules} and @code{with-syntax} (described in @cite{TR356})
+are defined.@refill
-@node Dynamic Data Type, Hash Tables, Collections, Data Structures
-@section Dynamic Data Type
+@code{syntax-case} is actually defined as a macro that expands into
+calls to the procedure @code{syntax-dispatch} and the core form
+@code{syntax-lambda}; do not redefine these names.@refill
-@code{(require 'dynamic)}
+Several other top-level bindings not documented in TR356 are created:
+@itemize @bullet
+@item the ``hooks'' in @file{hooks.ss}
+@item the @code{build-} procedures in @file{output.ss}
+@item @code{expand-syntax} (the expander)
+@end itemize
-@defun make-dynamic obj
-Create and returns a new @dfn{dynamic} whose global value is @var{obj}.
-@end defun
+The syntax of define has been extended to allow @code{(define @var{id})},
+which assigns @var{id} to some unspecified value.@refill
-@defun dynamic? obj
-Returns true if and only if @var{obj} is a dynamic. No object
-satisfying @code{dynamic?} satisfies any of the other standard type
-predicates.@refill
-@end defun
+We have attempted to maintain R4RS compatibility where possible. The
+incompatibilities should be confined to @file{hooks.ss}. Please let us
+know if there is some incompatibility that is not flagged as such.@refill
-@defun dynamic-ref dyn
-Return the value of the given dynamic in the current dynamic
-environment.
-@end defun
+Send bug reports, comments, suggestions, and questions to Kent Dybvig
+(dyb@@iuvax.cs.indiana.edu).
-@deffn Procedure dynamic-set! dyn obj
-Change the value of the given dynamic to @var{obj} in the current
-dynamic environment. The returned value is unspecified.@refill
-@end deffn
+@subsection Note from maintainer
-@defun 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 @var{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.@refill
-@end defun
+Included with the @code{syntax-case} files was @file{structure.scm}
+which defines a macro @code{define-structure}. There is no
+documentation for this macro and it is not used by any code in SLIB.
-The @code{dynamic-bind} macro is not implemented.
+@node Fluid-Let, Yasos, Syntax-Case Macros, Scheme Syntax Extension Packages
+@section Fluid-Let
+@code{(require 'fluid-let)}
+@ftindex fluid-let
+@deffn Syntax fluid-let @code{(@var{bindings} @dots{})} @var{forms}@dots{}
+@end deffn
+@lisp
+(fluid-let ((@var{variable} @var{init}) @dots{})
+ @var{expression} @var{expression} @dots{})
+@end lisp
+The @var{init}s are evaluated in the current environment (in some
+unspecified order), the current values of the @var{variable}s are saved,
+the results are assigned to the @var{variable}s, the @var{expression}s
+are evaluated sequentially in the current environment, the
+@var{variable}s are restored to their original values, and the value of
+the last @var{expression} is returned.@refill
-@node Hash Tables, Hashing, Dynamic Data Type, Data Structures
-@section Hash Tables
+The syntax of this special form is similar to that of @code{let}, but
+@code{fluid-let} temporarily rebinds existing @var{variable}s. Unlike
+@code{let}, @code{fluid-let} creates no new bindings; instead it
+@emph{assigns} the values of each @var{init} to the binding (determined
+by the rules of lexical scoping) of its corresponding
+@var{variable}.@refill
-@code{(require 'hash-table)}
-@defun predicate->hash pred
-Returns a hash function (like @code{hashq}, @code{hashv}, or
-@code{hash}) corresponding to the equality predicate @var{pred}.
-@var{pred} should be @code{eq?}, @code{eqv?}, @code{equal?}, @code{=},
-@code{char=?}, @code{char-ci=?}, @code{string=?}, or
-@code{string-ci=?}.@refill
-@end defun
+@node Yasos, , Fluid-Let, Scheme Syntax Extension Packages
+@section Yasos
-A hash table is a vector of association lists.
+@c Much of the documentation in this section was written by Dave Love
+@c (d.love@dl.ac.uk) -- don't blame Ken Dickey for its faults.
+@c but we can blame him for not writing it!
-@defun make-hash-table k
-Returns a vector of @var{k} empty (association) lists.
-@end defun
+@code{(require 'oop)} or @code{(require 'yasos)}
+@ftindex oop
+@ftindex yasos
-Hash table functions provide utilities for an associative database.
-These functions take an equality predicate, @var{pred}, as an argument.
-@var{pred} should be @code{eq?}, @code{eqv?}, @code{equal?}, @code{=},
-@code{char=?}, @code{char-ci=?}, @code{string=?}, or
-@code{string-ci=?}.@refill
+`Yet Another Scheme Object System' is a simple object system for Scheme
+based on the paper by Norman Adams and Jonathan Rees: @cite{Object
+Oriented Programming in Scheme}, Proceedings of the 1988 ACM Conference
+on LISP and Functional Programming, July 1988 [ACM #552880].@refill
-@defun predicate->hash-asso pred
-Returns a hash association function of 2 arguments, @var{key} and
-@var{hashtab}, corresponding to @var{pred}. The returned function
-returns a key-value pair whose key is @var{pred}-equal to its first
-argument or @code{#f} if no key in @var{hashtab} is @var{pred}-equal to
-the first argument.@refill
-@end defun
+Another reference is:
-@defun hash-inquirer pred
-Returns a procedure of 3 arguments, @code{hashtab} and @code{key}, which
-returns the value associated with @code{key} in @code{hashtab} or
-@code{#f} if key does not appear in @code{hashtab}.@refill
-@end defun
+Ken Dickey.
+@ifset html
+<A HREF="ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/pubs/swob.txt">
+@end ifset
+Scheming with Objects
+@ifset html
+</A>
+@end ifset
+@cite{AI Expert} Volume 7, Number 10 (October 1992), pp. 24-33.
-@defun hash-associator pred
-Returns a procedure of 3 arguments, @var{hashtab}, @var{key}, and
-@var{value}, which modifies @var{hashtab} so that @var{key} and
-@var{value} associated. Any previous value associated with @var{key}
-will be lost.@refill
-@end defun
+@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.
+@end menu
-@defun hash-remover pred
-Returns a procedure of 2 arguments, @var{hashtab} and @var{key}, which
-modifies @var{hashtab} so that the association whose key is @var{key} is
-removed.@refill
-@end defun
+@node Yasos terms, Yasos interface, Yasos, Yasos
+@subsection Terms
-@defun hash-map proc hash-table
-Returns a new hash table formed by mapping @var{proc} over the
-keys and values of @var{hash-table}. @var{proc} must be a function of 2
-arguments which returns the new value part.
-@end defun
+@table @asis
+@item @dfn{Object}
+Any Scheme data object.
-@defun hash-for-each proc hash-table
-Applies @var{proc} to each pair of keys and values of @var{hash-table}.
-@var{proc} must be a function of 2 arguments. The returned value is
-unspecified.
-@end defun
+@item @dfn{Instance}
+An instance of the OO system; an @dfn{object}.
+@item @dfn{Operation}
+A @var{method}.
+@end table
+@table @emph
+@item 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 @code{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 @dfn{classes}
+and no meta-@var{anything}. Method dispatch is by a procedure call a la
+CLOS rather than by @code{send} syntax a la Smalltalk.@refill
+@item 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.@refill
+@end table
-@node Hashing, Chapter Ordering, Hash Tables, Data Structures
-@section Hashing
-@code{(require 'hash)}
-These hashing functions are for use in quickly classifying objects.
-Hash tables use these functions.
-@defun hashq obj k
-@defunx hashv obj k
-@defunx hash obj k
-Returns an exact non-negative integer less than @var{k}. For each
-non-negative integer less than @var{k} there are arguments @var{obj} for
-which the hashing functions applied to @var{obj} and @var{k} returns
-that integer.@refill
+@node Yasos interface, Setters, Yasos terms, Yasos
+@subsection Interface
-For @code{hashq}, @code{(eq? obj1 obj2)} implies @code{(= (hashq obj1 k)
-(hashq obj2))}.@refill
+@deffn Syntax define-operation @code{(}opname self arg @dots{}@code{)} @var{default-body}
+Defines a default behavior for data objects which don't handle the
+operation @var{opname}. The default default behavior (for an empty
+@var{default-body}) is to generate an error.@refill
+@end deffn
-For @code{hashv}, @code{(eqv? obj1 obj2)} implies @code{(= (hashv obj1 k)
-(hashv obj2))}.@refill
+@deffn Syntax define-predicate opname?
+Defines a predicate @var{opname?}, usually used for determining the
+@dfn{type} of an object, such that @code{(@var{opname?} @var{object})}
+returns @code{#t} if @var{object} has an operation @var{opname?} and
+@code{#f} otherwise.@refill
+@end deffn
-For @code{hash}, @code{(equal? obj1 obj2)} implies @code{(= (hash obj1 k)
-(hash obj2))}.@refill
+@deffn Syntax object @code{((@var{name} @var{self} @var{arg} @dots{}) @var{body})} @dots{}
+Returns an object (an instance of the object system) with operations.
+Invoking @code{(@var{name} @var{object} @var{arg} @dots{}} executes the
+@var{body} of the @var{object} with @var{self} bound to @var{object} and
+with argument(s) @var{arg}@dots{}.@refill
+@end deffn
-@code{hash}, @code{hashv}, and @code{hashq} return in time bounded by a
-constant. Notice that items having the same @code{hash} implies the
-items have the same @code{hashv} implies the items have the same
-@code{hashq}.@refill
+@deffn Syntax object-with-ancestors @code{((}ancestor1 init1@code{)} @dots{}@code{)} operation @dots{}
+A @code{let}-like form of @code{object} for multiple inheritance. It
+returns an object inheriting the behaviour of @var{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.
+@end deffn
+
+@deffn Syntax operate-as component operation self arg @dots{}
+Used in an operation definition (of @var{self}) to invoke the
+@var{operation} in an ancestor @var{component} but maintain the object's
+identity. Also known as ``send-to-super''.@refill
+@end deffn
+
+@deffn Procedure print obj port
+A default @code{print} operation is provided which is just @code{(format
+@var{port} @var{obj})} (@xref{Format}) for non-instances and prints
+@var{obj} preceded by @samp{#<INSTANCE>} for instances.
+@end deffn
+
+@defun size obj
+The default method returns the number of elements in @var{obj} if it is
+a vector, string or list, @code{2} for a pair, @code{1} for a character
+and by default id an error otherwise. Objects such as collections
+(@xref{Collections}) may override the default in an obvious way.@refill
@end defun
-@code{(require 'sierpinski)}
-@defun make-sierpinski-indexer max-coordinate
-Returns a procedure (eg hash-function) of 2 numeric arguments which
-preserves @emph{nearness} in its mapping from NxN to N.
-@var{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]:
+@node Setters, Yasos examples, Yasos interface, Yasos
+@subsection Setters
+
+@dfn{Setters} implement @dfn{generalized locations} for objects
+associated with some sort of mutable state. A @dfn{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 (@xref{Yasos}).
+Several setters are predefined, corresponding to getters @code{car},
+@code{cdr}, @code{string-ref} and @code{vector-ref} e.g., @code{(setter
+car)} is equivalent to @code{set-car!}.
+
+This implementation of setters is similar to that in Dylan(TM)
+(@cite{Dylan: An object-oriented dynamic language}, Apple Computer
+Eastern Research and Technology). Common LISP provides similar
+facilities through @code{setf}.
+
+@defun setter getter
+Returns the setter for the procedure @var{getter}. E.g., since
+@code{string-ref} is the getter corresponding to a setter which is
+actually @code{string-set!}:
@example
-(define space-key (make-sierpinski-indexer 100))
+(define foo "foo")
+((setter string-ref) foo 0 #\F) ; set element 0 of foo
+foo @result{} "Foo"
@end example
-Now let's compute the index of some points:
+@end defun
+
+@deffn Syntax set place new-value
+If @var{place} is a variable name, @code{set} is equivalent to
+@code{set!}. Otherwise, @var{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 @code{set} is usually unspecified unless used with a
+setter whose definition guarantees to return a useful value.
@example
-(space-key 24 78) @result{} 9206
-(space-key 23 80) @result{} 9172
+(set (string-ref foo 2) #\O) ; generalized location with getter
+foo @result{} "FoO"
+(set foo "foo") ; like set!
+foo @result{} "foo"
@end example
+@end deffn
-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
-@emph{tends} to be so.
+@deffn Procedure add-setter getter setter
+Add procedures @var{getter} and @var{setter} to the (inaccessible) list
+of valid setter/getter pairs. @var{setter} implements the store
+operation corresponding to the @var{getter} access operation for the
+relevant state. The return value is unspecified.
+@end deffn
-Example applications:
-@table @asis
+@deffn Procedure remove-setter-for getter
+Removes the setter corresponding to the specified @var{getter} from the
+list of valid setters. The return value is unspecified.
+@end deffn
-@item
-Sort points by Sierpinski index to get heuristic solution to
-@emph{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.
+@deffn Syntax define-access-operation getter-name
+Shorthand for a Yasos @code{define-operation} defining an operation
+@var{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.
+@end deffn
-@item
-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.)
-@end table
-@end defun
-@code{(require 'soundex)}
+@node Yasos examples, , Setters, Yasos
+@subsection Examples
-@defun soundex name
-Computes the @emph{soundex} hash of @var{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.
+@lisp
+;;; These definitions for PRINT and SIZE are already supplied by
+(require 'yasos)
-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.
+(define-operation (print obj port)
+ (format port
+ (if (instance? obj) "#<instance>" "~s")
+ obj))
-See Knuth, Vol. 3 @cite{Sorting and searching}, pp 391--2
+(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))))
-To manage unusual inputs, @code{soundex} omits all non-alphabetic
-characters. Consequently, in this implementation:
+(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)
+@result{} "#<Cell: 1>"
+(set (fetch foo) 2)
+@result{}
+(print foo #f)
+@result{} "#<Cell: 2>"
+(fetch foo)
+@result{} 2
+@end lisp
+
+@node Textual Conversion Packages, Mathematical Packages, Scheme Syntax Extension Packages, Top
+@chapter Textual Conversion Packages
+
+@menu
+* Precedence Parsing::
+* Format:: Common-Lisp Format
+* Standard Formatted I/O:: Posix printf and scanf
+* Program Arguments:: Commands and Options.
+* Printing Scheme:: Nicely
+* Time and Date::
+* Vector Graphics::
+@end menu
+
+
+@node Precedence Parsing, Format, Textual Conversion Packages, Textual Conversion Packages
+@section Precedence Parsing
+
+@code{(require 'precedence-parse)} or @code{(require 'parse)}
+@ftindex parse
+@ftindex precedence
+
+@noindent
+This package implements:
+
+@itemize @bullet
+@item
+a Pratt style precedence parser;
+@item
+a @dfn{tokenizer} which congeals tokens according to assigned classes of
+constituent characters;
+@item
+procedures giving direct control of parser rulesets;
+@item
+procedures for higher level specification of rulesets.
+@end itemize
+
+@menu
+* Precedence Parsing Overview::
+* Ruleset Definition and Use::
+* Token definition::
+* Nud and Led Definition::
+* Grammar Rule Definition::
+@end menu
+
+@node Precedence Parsing Overview, Ruleset Definition and Use, Precedence Parsing, Precedence Parsing
+@subsection Precedence Parsing Overview
+
+@noindent
+This package offers improvements over previous parsers.
+
+@itemize @bullet
+@item
+Common computer language constructs are concisely specified.
+@item
+Grammars can be changed dynamically. Operators can be assigned
+different meanings within a lexical context.
+@item
+Rulesets don't need compilation. Grammars can be changed incrementally.
+@item
+Operator precedence is specified by integers.
+@item
+All possibilities of bad input are handled @footnote{How do I know this?
+I parsed 250kbyte of random input (an e-mail file) with a non-trivial
+grammar utilizing all constructs.} and return as much structure as was
+parsed when the error occured; The symbol @code{?} is substituted for
+missing input.
+@end itemize
+
+@noindent
+Here are the higher-level syntax types and an example of each.
+Precedence considerations are omitted for clarity. @xref{Grammar
+Rule Definition} for full details.
+@deftp Grammar nofix bye exit
@example
-(soundex <string of blanks>) @result{} ""
-(soundex "") @result{} ""
+bye
+@end example
+calls the function @code{exit} with no arguments.
+@end deftp
+@deftp Grammar prefix - negate
+@example
+- 42
@end example
+Calls the function @code{negate} with the argument @code{42}.
+@end deftp
+@deftp Grammar infix - difference
+@example
+x - y
+@end example
+Calls the function @code{difference} with arguments @code{x} and @code{y}.
+@end deftp
+@deftp Grammar nary + sum
+@example
+x + y + z
+@end example
+Calls the function @code{sum} with arguments @code{x}, @code{y}, and
+@code{y}.
+@end deftp
+@deftp Grammar postfix ! factorial
+@example
+5 !
+@end example
+Calls the function @code{factorial} with the argument @code{5}.
+@end deftp
+@deftp Grammar prestfix set set!
+@example
+set foo bar
+@end example
+Calls the function @code{set!} with the arguments @code{foo} and
+@code{bar}.
+@end deftp
+@deftp Grammar commentfix /* */
+@example
+/* almost any text here */
+@end example
+Ignores the comment delimited by @code{/*} and @code{*/}.
+@end deftp
+@deftp Grammar matchfix @{ list @}
+@example
+@{0, 1, 2@}
+@end example
+Calls the function @code{list} with the arguments @code{0}, @code{1},
+and @code{2}.
+@end deftp
+@deftp Grammar inmatchfix ( funcall )
+@example
+f(x, y)
+@end example
+Calls the function @code{funcall} with the arguments @code{f}, @code{x},
+and @code{y}.
+@end deftp
+@deftp Grammar delim ;
+@example
+set foo bar;
+@end example
+delimits the extent of the restfix operator @code{set}.
+@end deftp
-Examples from Knuth:
+
+@node Ruleset Definition and Use, Token definition, Precedence Parsing Overview, Precedence Parsing
+@subsection Ruleset Definition and Use
+
+@defvar *syn-defs*
+A grammar is built by one or more calls to @code{prec:define-grammar}.
+The rules are appended to @var{*syn-defs*}. The value of
+@var{*syn-defs*} is the grammar suitable for passing as an argument to
+@code{prec:parse}.
+@end defvar
+
+@defvr 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 @code{*syn-ignore-whitespace*}
+@end defvr
+
+@noindent
+In order to start defining a grammar, either
@example
-(map soundex '("Euler" "Gauss" "Hilbert" "Knuth"
- "Lloyd" "Lukasiewicz"))
- @result{} ("E460" "G200" "H416" "K530" "L300" "L222")
+(set! *syn-defs* '())
+@end example
+@noindent
+or
-(map soundex '("Ellery" "Ghosh" "Heilbronn" "Kant"
- "Ladd" "Lissajous"))
- @result{} ("E460" "G200" "H416" "K530" "L300" "L222")
+@example
+(set! *syn-defs* *syn-ignore-whitespace*)
@end example
-Some cases in which the algorithm fails (Knuth):
+@defun prec:define-grammar rule1 @dots{}
+Appends @var{rule1} @dots{} to @var{*syn-defs*}.
+@code{prec:define-grammar} is used to define both the character classes
+and rules for tokens.
+@end defun
+
+@noindent
+Once your grammar is defined, save the value of @code{*syn-defs*} in a
+variable (for use when calling @code{prec:parse}).
@example
-(map soundex '("Rogers" "Rodgers")) @result{} ("R262" "R326")
+(define my-ruleset *syn-defs*)
+@end example
-(map soundex '("Sinclair" "St. Clair")) @result{} ("S524" "S324")
+@defun prec:parse ruleset delim
+@defunx prec:parse ruleset delim port
+The @var{ruleset} argument must be a list of rules as constructed by
+@code{prec:define-grammar} and extracted from @var{*syn-defs*}.
-(map soundex '("Tchebysheff" "Chebyshev")) @result{} ("T212" "C121")
-@end example
+The token @var{delim} may be a character, symbol, or string. A
+character @var{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.
+
+@code{prec:parse} reads a @var{ruleset} grammar expression delimited
+by @var{delim} from the given input @var{port}. @code{prec:parse}
+returns the next object parsable from the given input @var{port},
+updating @var{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 @var{delim}) is found before any characters are
+found that can begin an object, then @code{#f} is returned.
+
+The @var{port} argument may be omitted, in which case it defaults to the
+value returned by @code{current-input-port}. It is an error to parse
+from a closed port.
+@findex current-input-port
@end defun
-@node Chapter Ordering, Object, Hashing, Data Structures
-@section Chapter Ordering
+@node Token definition, Nud and Led Definition, Ruleset Definition and Use, Precedence Parsing
+@subsection Token definition
-@code{(require 'chapter-order)}
+@defun tok:char-group group chars chars-proc
+The argument @var{chars} may be a single character, a list of
+characters, or a string. Each character in @var{chars} is treated as
+though @code{tok:char-group} was called with that character alone.
-The @samp{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.
+The argument @var{chars-proc} must be a procedure of one argument, a
+list of characters. After @code{tokenize} has finished
+accumulating the characters for a token, it calls @var{chars-proc} with
+the list of characters. The value returned is the token which
+@code{tokenize} returns.
-@defun 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 @var{string1} is
-@code{string<?} than the corresponding non-matching run of characters of
-@var{string2}.
+The argument @var{group} may be an exact integer or a procedure of one
+character argument. The following discussion concerns the treatment
+which the tokenizing routine, @code{tokenize}, will accord to characters
+on the basis of their groups.
-@example
-(chap:string<? "a.9" "a.10") @result{} #t
-(chap:string<? "4c" "4aa") @result{} #t
-(chap:string<? "Revised^@{3.99@}" "Revised^@{4@}") @result{} #t
-@end example
+When @var{group} is a non-zero integer, characters whose group number is
+equal to or exactly one less than @var{group} will continue to
+accumulate. Any other character causes the accumulation to stop (until
+a new token is to be read).
-@defunx chap:string>? string1 string2
-@defunx chap:string<=? string1 string2
-@defunx chap:string>=? string1 string2
-Implement the corresponding chapter-order predicates.
+The @var{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 @var{group} is a procedure, then, when triggerd by the occurence of
+an initial (no accumulation) @var{chars} character, this procedure will
+be repeatedly called with each successive character from the input
+stream until the @var{group} procedure returns a non-false value.
@end defun
-@defun chap:next-string string
-Returns the next string in the @emph{chapter order}. If @var{string}
-has no alphabetic or numeric characters,
-@code{(string-append @var{string} "0")} is returnd. The argument to
-chap:next-string will always be @code{chap:string<?} than the result.
+@noindent
+The following convenient constants are provided for use with
+@code{tok:char-group}.
-@example
-(chap:next-string "a.9") @result{} "a.10"
-(chap:next-string "4c") @result{} "4d"
-(chap:next-string "4z") @result{} "4aa"
-(chap:next-string "Revised^@{4@}") @result{} "Revised^@{5@}"
+@defvr Constant tok:decimal-digits
+Is the string @code{"0123456789"}.
+@end defvr
+@defvr Constant tok:upper-case
+Is the string consisting of all upper-case letters
+("ABCDEFGHIJKLMNOPQRSTUVWXYZ").
+@end defvr
+@defvr Constant tok:lower-case
+Is the string consisting of all lower-case letters
+("abcdefghijklmnopqrstuvwxyz").
+@end defvr
+@defvr Constant tok:whitespaces
+Is the string consisting of all characters between 0 and 255 for which
+@code{char-whitespace?} returns true.
+@end defvr
-@end example
+
+@node Nud and Led Definition, Grammar Rule Definition, Token definition, Precedence Parsing
+@subsection Nud and Led Definition
+
+This section describes advanced features. You can skip this section on
+first reading.
+
+@noindent
+The @dfn{Null Denotation} (or @dfn{nud})
+@cindex Null Denotation, nud
+of a token is the procedure and arguments applying for that token when
+@dfn{Left}, an unclaimed parsed expression is not extant.
+
+@noindent
+The @dfn{Left Denotation} (or @dfn{led})
+@cindex Left Denotation, led
+of a token is the procedure, arguments, and lbp applying for that token
+when there is a @dfn{Left}, an unclaimed parsed expression.
+
+@noindent
+In his paper,
+
+@quotation
+Pratt, V. R.
+Top Down Operator Precendence.
+@cite{SIGACT/SIGPLAN Symposium on Principles of Programming Languages},
+Boston, 1973, pages 41-51
+@end quotation
+
+the @dfn{left binding power} (or @dfn{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 @emph{dynamically
+binding} NUDs and LEDs allows them independence.
+
+@noindent
+For the rule-defining procedures that follow, the variable @var{tk} may
+be a character, string, or symbol, or a list composed of characters,
+strings, and symbols. Each element of @var{tk} is treated as though the
+procedure were called for each element.
+
+@noindent
+Character @var{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.
+
+@defun prec:make-nud tk sop arg1 @dots{}
+Returns a rule specifying that @var{sop} be called when @var{tk} is
+parsed. If @var{sop} is a procedure, it is called with @var{tk} and
+@var{arg1} @dots{} as its arguments; the resulting value is incorporated
+into the expression being built. Otherwise, @code{(list @var{sop}
+@var{arg1} @dots{})} is incorporated.
@end defun
-@node Object, Parameter lists, Chapter Ordering, Data Structures
-@section Macroless Object System
+@noindent
+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.
-@code{(require 'object)}
+@defun prec:make-led tk sop arg1 @dots{}
+Returns a rule specifying that @var{sop} be called when @var{tk} is
+parsed and @var{left} has an unclaimed parsed expression. If @var{sop}
+is a procedure, it is called with @var{left}, @var{tk}, and @var{arg1}
+@dots{} as its arguments; the resulting value is incorporated into the
+expression being built. Otherwise, @var{left} is incorporated.
+@end defun
-This is the Macroless Object System written by Wade Humeniuk
-(whumeniu@@datap.ca). Conceptual Tributes: @ref{Yasos}, MacScheme's
-%object, CLOS, Lack of R4RS macros.
+@noindent
+If no LED has been defined for a token, and @var{left} is set, the
+parser issues a warning.
-@subsection Concepts
-@table @asis
+@node Grammar Rule Definition, , Nud and Led Definition, Precedence Parsing
+@subsection Grammar Rule Definition
-@item OBJECT
-An object is an ordered association-list (by @code{eq?}) of methods
-(procedures). Methods can be added (@code{make-method!}), deleted
-(@code{unmake-method!}) and retrieved (@code{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.
-
-@item GENERIC-METHOD
-A generic-method associates (in terms of @code{eq?}) object's method.
-This allows scheme function style to be used for objects. The calling
-scheme for using a generic method is @code{(generic-method object param1
-param2 ...)}.
-
-@item 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?
-
-@item GENERIC-PREDICATE
-A generic method that returns a boolean value for any scheme obj.
-
-@item PREDICATE
-A object's method asscociated with a generic-predicate. Returns
-@code{#t}.
-@end table
+@noindent
+Here are procedures for defining rules for the syntax types introduced
+in @ref{Precedence Parsing Overview}.
-@subsection Procedures
+@noindent
+For the rule-defining procedures that follow, the variable @var{tk} may
+be a character, string, or symbol, or a list composed of characters,
+strings, and symbols. Each element of @var{tk} is treated as though the
+procedure were called for each element.
-@defun make-object ancestor @dots{}
-Returns an object. Current object implementation is a tagged vector.
-@var{ancestor}s are optional and must be objects in terms of object?.
-@var{ancestor}s methods are included in the object. Multiple
-@var{ancestor}s might associate the same generic-method with a method.
-In this case the method of the @var{ancestor} first appearing in the
-list is the one returned by @code{get-method}.
+@noindent
+For procedures prec:delim, @dots{}, prec:prestfix, if the @var{sop}
+argument is @code{#f}, then the token which triggered this rule is
+converted to a symbol and returned. A false @var{sop} argument to the
+procedures prec:commentfix, prec:matchfix, or prec:inmatchfix has a
+different meaning.
+
+@noindent
+Character @var{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.
+
+@defun prec:delim tk
+Returns a rule specifying that @var{tk} should not be returned from
+parsing; i.e. @var{tk}'s function is purely syntactic. The end-of-file
+is always treated as a delimiter.
@end defun
-@defun object? obj
-Returns boolean value whether @var{obj} was created by make-object.
+@defun prec:nofix tk sop
+Returns a rule specifying the following actions take place when @var{tk}
+is parsed:
+@itemize @bullet
+@item
+If @var{sop} is a procedure, it is called with no arguments; the
+resulting value is incorporated into the expression being built.
+Otherwise, the list of @var{sop} is incorporated.
+@end itemize
@end defun
-@defun make-generic-method exception-procedure
-Returns a procedure which be associated with an object's methods. If
-@var{exception-procedure} is specified then it is used to process
-non-objects.
+@defun prec:prefix tk sop bp rule1 @dots{}
+Returns a rule specifying the following actions take place when @var{tk}
+is parsed:
+@itemize @bullet
+@item
+The rules @var{rule1} @dots{} augment and, in case of conflict, override
+rules currently in effect.
+@item
+@code{prec:parse1} is called with binding-power @var{bp}.
+@item
+If @var{sop} is a procedure, it is called with the expression returned
+from @code{prec:parse1}; the resulting value is incorporated into the
+expression being built. Otherwise, the list of @var{sop} and the
+expression returned from @code{prec:parse1} is incorporated.
+@item
+The ruleset in effect before @var{tk} was parsed is restored;
+@var{rule1} @dots{} are forgotten.
+@end itemize
@end defun
-@defun make-generic-predicate
-Returns a boolean procedure for any scheme object.
+@defun prec:infix tk sop lbp bp rule1 @dots{}
+Returns a rule declaring the left-binding-precedence of the token
+@var{tk} is @var{lbp} and specifying the following actions take place
+when @var{tk} is parsed:
+@itemize @bullet
+@item
+The rules @var{rule1} @dots{} augment and, in case of conflict, override
+rules currently in effect.
+@item
+One expression is parsed with binding-power @var{lbp}. If instead a delimiter
+is encountered, a warning is issued.
+@item
+If @var{sop} is a procedure, it is applied to the list of @var{left} and
+the parsed expression; the resulting value is incorporated into the
+expression being built. Otherwise, the list of @var{sop}, the
+@var{left} expression, and the parsed expression is incorporated.
+@item
+The ruleset in effect before @var{tk} was parsed is restored;
+@var{rule1} @dots{} are forgotten.
+@end itemize
@end defun
-@defun make-method! object generic-method method
-Associates @var{method} to the @var{generic-method} in the object. The
-@var{method} overrides any previous association with the
-@var{generic-method} within the object. Using @code{unmake-method!}
-will restore the object's previous association with the
-@var{generic-method}. @var{method} must be a procedure.
+@defun prec:nary tk sop bp
+Returns a rule declaring the left-binding-precedence of the token
+@var{tk} is @var{bp} and specifying the following actions take place
+when @var{tk} is parsed:
+@itemize @bullet
+@item
+Expressions are parsed with binding-power @var{bp} as far as they are
+interleaved with the token @var{tk}.
+@item
+If @var{sop} is a procedure, it is applied to the list of @var{left} and
+the parsed expressions; the resulting value is incorporated into the
+expression being built. Otherwise, the list of @var{sop}, the
+@var{left} expression, and the parsed expressions is incorporated.
+@end itemize
@end defun
-@defun make-predicate! object generic-preciate
-Makes a predicate method associated with the @var{generic-predicate}.
+@defun prec:postfix tk sop lbp
+Returns a rule declaring the left-binding-precedence of the token
+@var{tk} is @var{lbp} and specifying the following actions take place
+when @var{tk} is parsed:
+@itemize @bullet
+@item
+If @var{sop} is a procedure, it is called with the @var{left} expression;
+the resulting value is incorporated into the expression being built.
+Otherwise, the list of @var{sop} and the @var{left} expression is
+incorporated.
+@end itemize
@end defun
-@defun unmake-method! object generic-method
-Removes an object's association with a @var{generic-method} .
+@defun prec:prestfix tk sop bp rule1 @dots{}
+Returns a rule specifying the following actions take place when @var{tk}
+is parsed:
+@itemize @bullet
+@item
+The rules @var{rule1} @dots{} augment and, in case of conflict, override
+rules currently in effect.
+@item
+Expressions are parsed with binding-power @var{bp} until a delimiter is
+reached.
+@item
+If @var{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 @var{sop} and the parsed
+expressions is incorporated.
+@item
+The ruleset in effect before @var{tk} was parsed is restored;
+@var{rule1} @dots{} are forgotten.
+@end itemize
@end defun
-@defun get-method object generic-method
-Returns the object's method associated (if any) with the
-@var{generic-method}. If no associated method exists an error is
-flagged.
+@defun prec:commentfix tk stp match rule1 @dots{}
+Returns rules specifying the following actions take place when @var{tk}
+is parsed:
+@itemize @bullet
+@item
+The rules @var{rule1} @dots{} augment and, in case of conflict, override
+rules currently in effect.
+@item
+Characters are read untile and end-of-file or a sequence of characters
+is read which matches the @emph{string} @var{match}.
+@item
+If @var{stp} is a procedure, it is called with the string of all that
+was read between the @var{tk} and @var{match} (exclusive).
+@item
+The ruleset in effect before @var{tk} was parsed is restored;
+@var{rule1} @dots{} are forgotten.
+@end itemize
+
+Parsing of commentfix syntax differs from the others in several ways.
+It reads directly from input without tokenizing; It calls @var{stp} but
+does not return its value; nay any value. I added the @var{stp}
+argument so that comment text could be echoed.
@end defun
-@subsection Examples
+@defun prec:matchfix tk sop sep match rule1 @dots{}
+Returns a rule specifying the following actions take place when @var{tk}
+is parsed:
+@itemize @bullet
+@item
+The rules @var{rule1} @dots{} augment and, in case of conflict, override
+rules currently in effect.
+@item
+A rule declaring the token @var{match} a delimiter takes effect.
+@item
+Expressions are parsed with binding-power @code{0} until the token
+@var{match} is reached. If the token @var{sep} does not appear between
+each pair of expressions parsed, a warning is issued.
+@item
+If @var{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 @var{sop} and the parsed
+expressions is incorporated.
+@item
+The ruleset in effect before @var{tk} was parsed is restored;
+@var{rule1} @dots{} are forgotten.
+@end itemize
+@end defun
+
+@defun prec:inmatchfix tk sop sep match lbp rule1 @dots{}
+Returns a rule declaring the left-binding-precedence of the token
+@var{tk} is @var{lbp} and specifying the following actions take place
+when @var{tk} is parsed:
+@itemize @bullet
+@item
+The rules @var{rule1} @dots{} augment and, in case of conflict, override
+rules currently in effect.
+@item
+A rule declaring the token @var{match} a delimiter takes effect.
+@item
+Expressions are parsed with binding-power @code{0} until the token
+@var{match} is reached. If the token @var{sep} does not appear between
+each pair of expressions parsed, a warning is issued.
+@item
+If @var{sop} is a procedure, it is applied to the list of @var{left} and
+the parsed expressions; the resulting value is incorporated into the
+expression being built. Otherwise, the list of @var{sop}, the
+@var{left} expression, and the parsed expressions is incorporated.
+@item
+The ruleset in effect before @var{tk} was parsed is restored;
+@var{rule1} @dots{} are forgotten.
+@end itemize
+@end defun
+
+
+@node Format, Standard Formatted I/O, Precedence Parsing, Textual Conversion Packages
+@section Format (version 3.0)
+
+@code{(require 'format)}
+@ftindex format
+
+@menu
+* Format Interface::
+* Format Specification::
+@end menu
+
+@node Format Interface, Format Specification, Format, Format
+@subsection Format Interface
+
+@defun format destination format-string . arguments
+An almost complete implementation of Common LISP format description
+according to the CL reference book @cite{Common LISP} from Guy L.
+Steele, Digital Press. Backward compatible to most of the available
+Scheme format implementations.
+
+Returns @code{#t}, @code{#f} or a string; has side effect of printing
+according to @var{format-string}. If @var{destination} is @code{#t},
+the output is to the current output port and @code{#t} is returned. If
+@var{destination} is @code{#f}, a formatted string is returned as the
+result of the call. NEW: If @var{destination} is a string,
+@var{destination} is regarded as the format string; @var{format-string} is
+then the first argument and the output is returned as a string. If
+@var{destination} is a number, the output is to the current error port
+if available by the implementation. Otherwise @var{destination} must be
+an output port and @code{#t} is returned.@refill
+
+@var{format-string} must be a string. In case of a formatting error
+format returns @code{#f} and prints a message on the current output or
+error port. Characters are output as if the string were output by the
+@code{display} function with the exception of those prefixed by a tilde
+(~). For a detailed description of the @var{format-string} syntax
+please consult a Common LISP format reference manual. For a test suite
+to verify this format implementation load @file{formatst.scm}. Please
+send bug reports to @code{lutzeb@@cs.tu-berlin.de}.
+
+Note: @code{format} is not reentrant, i.e. only one @code{format}-call
+may be executed at a time.
+
+@end defun
+
+@node Format Specification, , Format Interface, Format
+@subsection 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 @file{formatst.scm}.@refill
+
+This implementation supports directive parameters and modifiers
+(@code{:} and @code{@@} characters). Multiple parameters must be
+separated by a comma (@code{,}). Parameters can be numerical parameters
+(positive or negative), character parameters (prefixed by a quote
+character (@code{'}), variable parameters (@code{v}), number of rest
+arguments parameter (@code{#}), empty and default parameters. Directive
+characters are case independent. The general form of a directive
+is:@refill
+
+@noindent
+@var{directive} ::= ~@{@var{directive-parameter},@}[:][@@]@var{directive-character}
+
+@noindent
+@var{directive-parameter} ::= [ [-|+]@{0-9@}+ | '@var{character} | v | # ]
+
+
+@subsubsection Implemented CL Format Control Directives
+
+Documentation syntax: Uppercase characters represent the corresponding
+control directive characters. Lowercase characters represent control
+directive parameter descriptions.
+
+@table @asis
+@item @code{~A}
+Any (print as @code{display} does).
+@table @asis
+@item @code{~@@A}
+left pad.
+@item @code{~@var{mincol},@var{colinc},@var{minpad},@var{padchar}A}
+full padding.
+@end table
+@item @code{~S}
+S-expression (print as @code{write} does).
+@table @asis
+@item @code{~@@S}
+left pad.
+@item @code{~@var{mincol},@var{colinc},@var{minpad},@var{padchar}S}
+full padding.
+@end table
+@item @code{~D}
+Decimal.
+@table @asis
+@item @code{~@@D}
+print number sign always.
+@item @code{~:D}
+print comma separated.
+@item @code{~@var{mincol},@var{padchar},@var{commachar}D}
+padding.
+@end table
+@item @code{~X}
+Hexadecimal.
+@table @asis
+@item @code{~@@X}
+print number sign always.
+@item @code{~:X}
+print comma separated.
+@item @code{~@var{mincol},@var{padchar},@var{commachar}X}
+padding.
+@end table
+@item @code{~O}
+Octal.
+@table @asis
+@item @code{~@@O}
+print number sign always.
+@item @code{~:O}
+print comma separated.
+@item @code{~@var{mincol},@var{padchar},@var{commachar}O}
+padding.
+@end table
+@item @code{~B}
+Binary.
+@table @asis
+@item @code{~@@B}
+print number sign always.
+@item @code{~:B}
+print comma separated.
+@item @code{~@var{mincol},@var{padchar},@var{commachar}B}
+padding.
+@end table
+@item @code{~@var{n}R}
+Radix @var{n}.
+@table @asis
+@item @code{~@var{n},@var{mincol},@var{padchar},@var{commachar}R}
+padding.
+@end table
+@item @code{~@@R}
+print a number as a Roman numeral.
+@item @code{~:R}
+print a number as an ordinal English number.
+@item @code{~:@@R}
+print a number as a cardinal English number.
+@item @code{~P}
+Plural.
+@table @asis
+@item @code{~@@P}
+prints @code{y} and @code{ies}.
+@item @code{~:P}
+as @code{~P but jumps 1 argument backward.}
+@item @code{~:@@P}
+as @code{~@@P but jumps 1 argument backward.}
+@end table
+@item @code{~C}
+Character.
+@table @asis
+@item @code{~@@C}
+prints a character as the reader can understand it (i.e. @code{#\} prefixing).
+@item @code{~:C}
+prints a character as emacs does (eg. @code{^C} for ASCII 03).
+@end table
+@item @code{~F}
+Fixed-format floating-point (prints a flonum like @var{mmm.nnn}).
+@table @asis
+@item @code{~@var{width},@var{digits},@var{scale},@var{overflowchar},@var{padchar}F}
+@item @code{~@@F}
+If the number is positive a plus sign is printed.
+@end table
+@item @code{~E}
+Exponential floating-point (prints a flonum like @var{mmm.nnn}@code{E}@var{ee}).
+@table @asis
+@item @code{~@var{width},@var{digits},@var{exponentdigits},@var{scale},@var{overflowchar},@var{padchar},@var{exponentchar}E}
+@item @code{~@@E}
+If the number is positive a plus sign is printed.
+@end table
+@item @code{~G}
+General floating-point (prints a flonum either fixed or exponential).
+@table @asis
+@item @code{~@var{width},@var{digits},@var{exponentdigits},@var{scale},@var{overflowchar},@var{padchar},@var{exponentchar}G}
+@item @code{~@@G}
+If the number is positive a plus sign is printed.
+@end table
+@item @code{~$}
+Dollars floating-point (prints a flonum in fixed with signs separated).
+@table @asis
+@item @code{~@var{digits},@var{scale},@var{width},@var{padchar}$}
+@item @code{~@@$}
+If the number is positive a plus sign is printed.
+@item @code{~:@@$}
+A sign is always printed and appears before the padding.
+@item @code{~:$}
+The sign appears before the padding.
+@end table
+@item @code{~%}
+Newline.
+@table @asis
+@item @code{~@var{n}%}
+print @var{n} newlines.
+@end table
+@item @code{~&}
+print newline if not at the beginning of the output line.
+@table @asis
+@item @code{~@var{n}&}
+prints @code{~&} and then @var{n-1} newlines.
+@end table
+@item @code{~|}
+Page Separator.
+@table @asis
+@item @code{~@var{n}|}
+print @var{n} page separators.
+@end table
+@item @code{~~}
+Tilde.
+@table @asis
+@item @code{~@var{n}~}
+print @var{n} tildes.
+@end table
+@item @code{~}<newline>
+Continuation Line.
+@table @asis
+@item @code{~:}<newline>
+newline is ignored, white space left.
+@item @code{~@@}<newline>
+newline is left, white space ignored.
+@end table
+@item @code{~T}
+Tabulation.
+@table @asis
+@item @code{~@@T}
+relative tabulation.
+@item @code{~@var{colnum,colinc}T}
+full tabulation.
+@end table
+@item @code{~?}
+Indirection (expects indirect arguments as a list).
+@table @asis
+@item @code{~@@?}
+extracts indirect arguments from format arguments.
+@end table
+@item @code{~(@var{str}~)}
+Case conversion (converts by @code{string-downcase}).
+@table @asis
+@item @code{~:(@var{str}~)}
+converts by @code{string-capitalize}.
+@item @code{~@@(@var{str}~)}
+converts by @code{string-capitalize-first}.
+@item @code{~:@@(@var{str}~)}
+converts by @code{string-upcase}.
+@end table
+@item @code{~*}
+Argument Jumping (jumps 1 argument forward).
+@table @asis
+@item @code{~@var{n}*}
+jumps @var{n} arguments forward.
+@item @code{~:*}
+jumps 1 argument backward.
+@item @code{~@var{n}:*}
+jumps @var{n} arguments backward.
+@item @code{~@@*}
+jumps to the 0th argument.
+@item @code{~@var{n}@@*}
+jumps to the @var{n}th argument (beginning from 0)
+@end table
+@item @code{~[@var{str0}~;@var{str1}~;...~;@var{strn}~]}
+Conditional Expression (numerical clause conditional).
+@table @asis
+@item @code{~@var{n}[}
+take argument from @var{n}.
+@item @code{~@@[}
+true test conditional.
+@item @code{~:[}
+if-else-then conditional.
+@item @code{~;}
+clause separator.
+@item @code{~:;}
+default clause follows.
+@end table
+@item @code{~@{@var{str}~@}}
+Iteration (args come from the next argument (a list)).
+@table @asis
+@item @code{~@var{n}@{}
+at most @var{n} iterations.
+@item @code{~:@{}
+args from next arg (a list of lists).
+@item @code{~@@@{}
+args from the rest of arguments.
+@item @code{~:@@@{}
+args from the rest args (lists).
+@end table
+@item @code{~^}
+Up and out.
+@table @asis
+@item @code{~@var{n}^}
+aborts if @var{n} = 0
+@item @code{~@var{n},@var{m}^}
+aborts if @var{n} = @var{m}
+@item @code{~@var{n},@var{m},@var{k}^}
+aborts if @var{n} <= @var{m} <= @var{k}
+@end table
+@end table
+
+
+@subsubsection Not Implemented CL Format Control Directives
+
+@table @asis
+@item @code{~:A}
+print @code{#f} as an empty list (see below).
+@item @code{~:S}
+print @code{#f} as an empty list (see below).
+@item @code{~<~>}
+Justification.
+@item @code{~:^}
+(sorry I don't understand its semantics completely)
+@end table
+
+
+@subsubsection Extended, Replaced and Additional Control Directives
+
+@table @asis
+@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}D}
+@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}X}
+@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}O}
+@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}B}
+@item @code{~@var{n},@var{mincol},@var{padchar},@var{commachar},@var{commawidth}R}
+@var{commawidth} is the number of characters between two comma characters.
+@end table
+
+@table @asis
+@item @code{~I}
+print a R4RS complex number as @code{~F~@@Fi} with passed parameters for
+@code{~F}.
+@item @code{~Y}
+Pretty print formatting of an argument for scheme code lists.
+@item @code{~K}
+Same as @code{~?.}
+@item @code{~!}
+Flushes the output if format @var{destination} is a port.
+@item @code{~_}
+Print a @code{#\space} character
+@table @asis
+@item @code{~@var{n}_}
+print @var{n} @code{#\space} characters.
+@end table
+@item @code{~/}
+Print a @code{#\tab} character
+@table @asis
+@item @code{~@var{n}/}
+print @var{n} @code{#\tab} characters.
+@end table
+@item @code{~@var{n}C}
+Takes @var{n} as an integer representation for a character. No arguments
+are consumed. @var{n} is converted to a character by
+@code{integer->char}. @var{n} must be a positive decimal number.@refill
+@item @code{~:S}
+Print out readproof. Prints out internal objects represented as
+@code{#<...>} as strings @code{"#<...>"} so that the format output can always
+be processed by @code{read}.
+@refill
+@item @code{~:A}
+Print out readproof. Prints out internal objects represented as
+@code{#<...>} as strings @code{"#<...>"} so that the format output can always
+be processed by @code{read}.
+@item @code{~Q}
+Prints information and a copyright notice on the format implementation.
+@table @asis
+@item @code{~:Q}
+prints format version.
+@end table
+@refill
+@item @code{~F, ~E, ~G, ~$}
+may also print number strings, i.e. passing a number as a string and
+format it accordingly.
+@end table
+
+@subsubsection Configuration Variables
+
+Format has some configuration variables at the beginning of
+@file{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.
+
+@table @asis
+
+@item @var{format:symbol-case-conv}
+Symbols are converted by @code{symbol->string} so the case type of the
+printed symbols is implementation dependent.
+@code{format:symbol-case-conv} is a one arg closure which is either
+@code{#f} (no conversion), @code{string-upcase}, @code{string-downcase}
+or @code{string-capitalize}. (default @code{#f})
+
+@item @var{format:iobj-case-conv}
+As @var{format:symbol-case-conv} but applies for the representation of
+implementation internal objects. (default @code{#f})
+
+@item @var{format:expch}
+The character prefixing the exponent value in @code{~E} printing. (default
+@code{#\E})
+
+@end table
+
+@subsubsection Compatibility With Other Format Implementations
+
+@table @asis
+@item SLIB format 2.x:
+See @file{format.doc}.
+
+@item SLIB format 1.4:
+Downward compatible except for padding support and @code{~A}, @code{~S},
+@code{~P}, @code{~X} uppercase printing. SLIB format 1.4 uses C-style
+@code{printf} padding support which is completely replaced by the CL
+@code{format} padding style.
+
+@item MIT C-Scheme 7.1:
+Downward compatible except for @code{~}, which is not documented
+(ignores all characters inside the format string up to a newline
+character). (7.1 implements @code{~a}, @code{~s},
+~@var{newline}, @code{~~}, @code{~%}, numerical and variable
+parameters and @code{:/@@} modifiers in the CL sense).@refill
+
+@item Elk 1.5/2.0:
+Downward compatible except for @code{~A} and @code{~S} which print in
+uppercase. (Elk implements @code{~a}, @code{~s}, @code{~~}, and
+@code{~%} (no directive parameters or modifiers)).@refill
+
+@item 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
+@code{~a}, @code{~s}, @code{~c}, @code{~%}, and @code{~~} (no directive
+parameters or modifiers)).@refill
+
+@end table
+
+This implementation of format is solely useful in the SLIB context
+because it requires other components provided by SLIB.@refill
+
+
+@node Standard Formatted I/O, Program Arguments, Format, Textual Conversion Packages
+@section Standard Formatted I/O
+
+@menu
+* Standard Formatted Output:: 'printf
+* Standard Formatted Input:: 'scanf
+@end menu
+
+@subsection stdio
+
+@code{(require 'stdio)}
+@ftindex stdio
+
+@code{require}s @code{printf} and @code{scanf} and additionally defines
+the symbols:
+
+@defvar stdin
+Defined to be @code{(current-input-port)}.
+@end defvar
+@defvar stdout
+Defined to be @code{(current-output-port)}.
+@end defvar
+@defvar stderr
+Defined to be @code{(current-error-port)}.
+@end defvar
+
+
+@node Standard Formatted Output, Standard Formatted Input, Standard Formatted I/O, Standard Formatted I/O
+@subsection Standard Formatted Output
+
+@code{(require 'printf)}
+@ftindex printf
+
+@deffn Procedure printf format arg1 @dots{}
+@deffnx Procedure fprintf port format arg1 @dots{}
+@deffnx Procedure sprintf str format arg1 @dots{}
+
+Each function converts, formats, and outputs its @var{arg1} @dots{}
+arguments according to the control string @var{format} argument and
+returns the number of characters output.
+
+@code{printf} sends its output to the port @code{(current-output-port)}.
+@code{fprintf} sends its output to the port @var{port}. @code{sprintf}
+@code{string-set!}s locations of the non-constant string argument
+@var{str} to the output characters.
+
+@quotation
+@emph{Note:} sprintf should be changed to a macro so a @code{substring}
+expression could be used for the @var{str} argument.
+@end quotation
+
+The string @var{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 @var{arg1} @dots{}. The
+results are undefined if there are an insufficient number of arguments
+for the format. If @var{format} is exhausted while some of the
+@var{arg1} @dots{} arguments remain unused, the excess @var{arg1}
+@dots{} arguments are ignored.
+
+The conversion specifications in a format string have the form:
@example
-(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)
+% @r{[} @var{flags} @r{]} @r{[} @var{width} @r{]} @r{[} . @var{precision} @r{]} @r{[} @var{type} @r{]} @var{conversion}
@end example
-@subsubsection Inverter Documentation
-Inheritance:
-@lisp
- <inverter>::(<number> <description>)
-@end lisp
-Generic-methods
-@lisp
- <inverter>::value @result{} <number>::value
- <inverter>::set-value! @result{} <number>::set-value!
- <inverter>::describe @result{} <description>::describe
- <inverter>::help
- <inverter>::invert
- <inverter>::inverter?
-@end lisp
+An output conversion specifications consist of an initial @samp{%}
+character followed in sequence by:
-@subsubsection Number Documention
-Inheritance
-@lisp
- <number>::()
-@end lisp
-Slots
-@lisp
- <number>::<x>
-@end lisp
-Generic Methods
+@itemize @bullet
+@item
+Zero or more @dfn{flag characters} that modify the normal behavior of
+the conversion specification.
+
+@table @asis
+@item @samp{-}
+Left-justify the result in the field. Normally the result is
+right-justified.
+
+@item @samp{+}
+For the signed @samp{%d} and @samp{%i} conversions and all inexact
+conversions, prefix a plus sign if the value is positive.
+
+@item @samp{ }
+For the signed @samp{%d} and @samp{%i} conversions, if the result
+doesn't start with a plus or minus sign, prefix it with a space
+character instead. Since the @samp{+} flag ensures that the result
+includes a sign, this flag is ignored if both are specified.
+
+@item @samp{#}
+For inexact conversions, @samp{#} specifies that the result should
+always include a decimal point, even if no digits follow it. For the
+@samp{%g} and @samp{%G} conversions, this also forces trailing zeros
+after the decimal point to be printed where they would otherwise be
+elided.
+
+For the @samp{%o} conversion, force the leading digit to be @samp{0}, as
+if by increasing the precision. For @samp{%x} or @samp{%X}, prefix a
+leading @samp{0x} or @samp{0X} (respectively) to the result. This
+doesn't do anything useful for the @samp{%d}, @samp{%i}, or @samp{%u}
+conversions. Using this flag produces output which can be parsed by the
+@code{scanf} functions with the @samp{%i} conversion (@pxref{Standard
+Formatted Input}).
+
+
+@item @samp{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 @samp{-}
+flag is also specified, or if a precision is specified for an exact
+converson.
+@end table
+
+@item
+An optional decimal integer specifying the @dfn{minimum field width}.
+If the normal conversion produces fewer characters than this, the field
+is padded (with spaces or zeros per the @samp{0} flag) to the specified
+width. This is a @emph{minimum} width; if the normal conversion
+produces more characters than this, the field is @emph{not} truncated.
+@cindex minimum field width (@code{printf})
+
+Alternatively, if the field width is @samp{*}, 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 @samp{-} flag is set (see above) and the
+absolute value is used as the field width.
+
+@item
+An optional @dfn{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 (@samp{.}) followed
+optionally by a decimal integer (which defaults to zero if omitted).
+@cindex precision (@code{printf})
+
+Alternatively, if the precision is @samp{.*}, 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 @samp{*} for both the field width and precision, the
+field width argument precedes the precision argument. The @samp{.*}
+precision is an enhancement. C library versions may not accept this
+syntax.
+
+For the @samp{%f}, @samp{%e}, and @samp{%E} conversions, the precision
+specifies how many digits follow the decimal-point character. The
+default precision is @code{6}. If the precision is explicitly @code{0},
+the decimal point character is suppressed.
+
+For the @samp{%g} and @samp{%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 @code{0} or not specified for @samp{%g} or @samp{%G}, it is
+treated like a value of @code{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 @samp{0} with an
+explicit precision of zero produces no characters.
+
+@item
+An optional one of @samp{l}, @samp{h} or @samp{L}, which is ignored for
+numeric conversions. It is an error to specify these modifiers for
+non-numeric conversions.
+
+@item
+A character that specifies the conversion to be applied.
+@end itemize
+
+@subsubsection Exact Conversions
+
+@table @asis
+@item @samp{d}, @samp{i}
+Print an integer as a signed decimal number. @samp{%d} and @samp{%i}
+are synonymous for output, but are different when used with @code{scanf}
+for input (@pxref{Standard Formatted Input}).
+
+@item @samp{o}
+Print an integer as an unsigned octal number.
+
+@item @samp{u}
+Print an integer as an unsigned decimal number.
+
+@item @samp{x}, @samp{X}
+Print an integer as an unsigned hexadecimal number. @samp{%x} prints
+using the digits @samp{0123456789abcdef}. @samp{%X} prints using the
+digits @samp{0123456789ABCDEF}.
+@end table
+
+@subsubsection Inexact Conversions
+@emph{Note:} Inexact conversions are not supported yet.
+
+@table @asis
+@item @samp{f}
+Print a floating-point number in fixed-point notation.
+
+@item @samp{e}, @samp{E}
+Print a floating-point number in exponential notation. @samp{%e} prints
+@samp{e} between mantissa and exponont. @samp{%E} prints @samp{E}
+between mantissa and exponont.
+
+@item @samp{g}, @samp{G}
+Print a floating-point number in either normal or exponential notation,
+whichever is more appropriate for its magnitude. @samp{%g} prints
+@samp{e} between mantissa and exponont. @samp{%G} prints @samp{E}
+between mantissa and exponont.
+@end table
+
+@subsubsection Other Conversions
+@table @asis
+@item @samp{c}
+Print a single character. The @samp{-} flag is the only one which can
+be specified. It is an error to specify a precision.
+
+@item @samp{s}
+Print a string. The @samp{-} 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.
+
+@item @samp{a}, @samp{A}
+Print a scheme expression. The @samp{-} flag left-justifies the output.
+The @samp{#} flag specifies that strings and characters should be quoted
+as by @code{write} (which can be read using @code{read}); otherwise,
+output is as @code{display} prints. A precision specifies the maximum
+number of characters to output; otherwise as many characters as needed
+are output.
+
+@emph{Note:} @samp{%a} and @samp{%A} are SLIB extensions.
+
+@c @item @samp{p}
+@c Print the value of a pointer.
+
+@c @item @samp{n}
+@c Get the number of characters printed so far. @xref{Other Output Conversions}.
+@c Note that this conversion specification never produces any output.
+
+@c @item @samp{m}
+@c Print the string corresponding to the value of @code{errno}.
+@c (This is a GNU extension.)
+@c @xref{Other Output Conversions}.
+
+@item @samp{%}
+Print a literal @samp{%} character. No argument is consumed. It is an
+error to specifiy flags, field width, precision, or type modifiers with
+@samp{%%}.
+@end table
+@end deffn
+
+
+@node Standard Formatted Input, , Standard Formatted Output, Standard Formatted I/O
+@subsection Standard Formatted Input
+
+@code{(require 'scanf)}
+@ftindex scanf
+
+@deffn Function scanf-read-list format
+@deffnx Function scanf-read-list format port
+@deffnx Function scanf-read-list format string
+@end deffn
+
+@defmac scanf format arg1 @dots{}
+@defmacx fscanf port format arg1 @dots{}
+@defmacx sscanf str format arg1 @dots{}
+
+Each function reads characters, interpreting them according to the
+control string @var{format} argument.
+
+@code{scanf-read-list} returns a list of the items specified as far as
+the input matches @var{format}. @code{scanf}, @code{fscanf}, and
+@code{sscanf} return the number of items successfully matched and
+stored. @code{scanf}, @code{fscanf}, and @code{sscanf} also set the
+location corresponding to @var{arg1} @dots{} using the methods:
+
+@table @asis
+@item symbol
+@code{set!}
+@item car expression
+@code{set-car!}
+@item cdr expression
+@code{set-cdr!}
+@item vector-ref expression
+@code{vector-set!}
+@item substring expression
+@code{substring-move-left!}
+@end table
+
+The argument to a @code{substring} expression in @var{arg1} @dots{} must
+be a non-constant string. Characters will be stored starting at the
+position specified by the second argument to @code{substring}. The
+number of characters stored will be limited by either the position
+specified by the third argument to @code{substring} or the length of the
+matched string, whichever is less.
+
+The control string, @var{format}, contains conversion specifications and
+other characters used to direct interpretation of input sequences. The
+control string contains:
+
+@itemize @bullet
+@item White-space characters (blanks, tabs, newlines, or formfeeds)
+that cause input to be read (and discarded) up to the next
+non-white-space character.
+
+@item An ordinary character (not @samp{%}) that must match the next
+character of the input stream.
+
+@item Conversion specifications, consisting of the character @samp{%}, an
+optional assignment suppressing character @samp{*}, an optional
+numerical maximum-field width, an optional @samp{l}, @samp{h} or
+@samp{L} which is ignored, and a conversion code.
+
+@c @item The conversion specification can alternatively be prefixed by
+@c the character sequence @samp{%n$} instead of the character @samp{%},
+@c where @var{n} is a decimal integer in the range. The @samp{%n$}
+@c construction indicates that the value of the next input field should be
+@c placed in the @var{n}th place in the return list, rather than to the next
+@c unused one. The two forms of introducing a conversion specification,
+@c @samp{%} and @samp{%n$}, must not be mixed within a single format string
+@c with the following exception: Skip fields (see below) can be designated
+@c as @samp{%*} or @samp{%n$*}. In the latter case, @var{n} is ignored.
+
+@end itemize
+
+Unless the specification contains the @samp{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
+@samp{*} 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.
+
+@quotation
+@emph{Note:} This specification of format strings differs from the
+@cite{ANSI C} and @cite{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 @cite{ANSI C} and SLIB,
+prepend whitespace to all conversion specifications except @samp{[} and
+@samp{c}.
+@end quotation
+
+The conversion code indicates the interpretation of the input field; For
+a suppressed field, no value is returned. The following conversion
+codes are legal:
+
+@table @asis
+
+@item @samp{%}
+A single % is expected in the input at this point; no value is returned.
+
+@item @samp{d}, @samp{D}
+A decimal integer is expected.
+
+@item @samp{u}, @samp{U}
+An unsigned decimal integer is expected.
+
+@item @samp{o}, @samp{O}
+An octal integer is expected.
+
+@item @samp{x}, @samp{X}
+A hexadecimal integer is expected.
+
+@item @samp{i}
+An integer is expected. Returns the value of the next input item,
+interpreted according to C conventions; a leading @samp{0} implies
+octal, a leading @samp{0x} implies hexadecimal; otherwise, decimal is
+assumed.
+
+@item @samp{n}
+Returns the total number of bytes (including white space) read by
+@code{scanf}. No input is consumed by @code{%n}.
+
+@item @samp{f}, @samp{F}, @samp{e}, @samp{E}, @samp{g}, @samp{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 @samp{.}, followed by an optional
+exponent field consisting of an @samp{E} or an @samp{e}, followed by an
+optional @samp{+}, @samp{-}, or space, followed by an integer.
+
+@item @samp{c}, @samp{C}
+@var{Width} characters are expected. The normal skip-over-white-space
+is suppressed in this case; to read the next non-space character, use
+@samp{%1s}. If a field width is given, a string is returned; up to the
+indicated number of characters is read.
+
+@item @samp{s}, @samp{S}
+A character string is expected The input field is terminated by a
+white-space character. @code{scanf} cannot read a null string.
+
+@item @samp{[}
+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. @samp{^}, 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 @samp{[0123456789]} to be expressed @samp{[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 @samp{^}) 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.
+@end table
+
+The @code{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.
+@end defmac
+
+
+@node Program Arguments, Printing Scheme, Standard Formatted I/O, Textual Conversion Packages
+@section Program Arguments
+
+@menu
+* Getopt:: Command Line option parsing
+* Command Line:: A command line reader for Scheme shells
+* Parameter lists:: 'parameters
+* Batch:: 'batch
+@end menu
+
+@node Getopt, Command Line, Program Arguments, Program Arguments
+@subsection Getopt
+
+@code{(require 'getopt)}
+@ftindex getopt
+
+This routine implements Posix command line argument parsing. Notice
+that returning values through global variables means that @code{getopt}
+is @emph{not} reentrant.
+
+@defvar *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, @var{*opting*} must be reset.
+@end defvar
+
+@defvar *optarg*
+Is set by getopt to the (string) option-argument of the current option.
+@end defvar
+
+@deffn Procedure getopt argc argv optstring
+Returns the next option letter in @var{argv} (starting from
+@code{(vector-ref argv *optind*)}) that matches a letter in
+@var{optstring}. @var{argv} is a vector or list of strings, the 0th of
+which getopt usually ignores. @var{argc} is the argument count, usually
+the length of @var{argv}. @var{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 @var{argv}.
+
+@var{*optind*} is the index of the next element of the @var{argv} vector
+to be processed. It is initialized to 1 by @file{getopt.scm}, and
+@code{getopt} updates it when it finishes with each element of
+@var{argv}.
+
+@code{getopt} returns the next option character from @var{argv} that
+matches a character in @var{optstring}, if there is one that matches.
+If the option takes an argument, @code{getopt} sets the variable
+@var{*optarg*} to the option-argument as follows:
+
+@itemize @bullet
+@item
+If the option was the last character in the string pointed to by an
+element of @var{argv}, then @var{*optarg*} contains the next element of
+@var{argv}, and @var{*optind*} is incremented by 2. If the resulting
+value of @var{*optind*} is greater than or equal to @var{argc}, this
+indicates a missing option argument, and @code{getopt} returns an error
+indication.
+
+@item
+Otherwise, @var{*optarg*} is set to the string following the option
+character in that element of @var{argv}, and @var{*optind*} is
+incremented by 1.
+@end itemize
+
+If, when @code{getopt} is called, the string @code{(vector-ref argv
+*optind*)} either does not begin with the character @code{#\-} or is
+just @code{"-"}, @code{getopt} returns @code{#f} without changing
+@var{*optind*}. If @code{(vector-ref argv *optind*)} is the string
+@code{"--"}, @code{getopt} returns @code{#f} after incrementing
+@var{*optind*}.
+
+If @code{getopt} encounters an option character that is not contained in
+@var{optstring}, it returns the question-mark @code{#\?} character. If
+it detects a missing option argument, it returns the colon character
+@code{#\:} if the first character of @var{optstring} was a colon, or a
+question-mark character otherwise. In either case, @code{getopt} sets
+the variable @var{getopt:opt} to the option character that caused the
+error.
+
+The special option @code{"--"} can be used to delimit the end of the
+options; @code{#f} is returned, and @code{"--"} is skipped.
+
+RETURN VALUE
+
+@code{getopt} returns the next option character specified on the command
+line. A colon @code{#\:} is returned if @code{getopt} detects a missing argument
+and the first character of @var{optstring} was a colon @code{#\:}.
+
+A question-mark @code{#\?} is returned if @code{getopt} encounters an option
+character not in @var{optstring} or detects a missing argument and the first
+character of @var{optstring} was not a colon @code{#\:}.
+
+Otherwise, @code{getopt} returns @code{#f} when all command line options have been
+parsed.
+
+Example:
@lisp
- <number>::value
- <number>::set-value!
+#! /usr/local/bin/scm
+;;;This code is SCM specific.
+(define argv (program-arguments))
+(require 'getopt)
+@ftindex 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)
@end lisp
+@end deffn
+
+@subsection Getopt--
+
+@defun getopt-- argc argv optstring
+The procedure @code{getopt--} is an extended version of @code{getopt}
+which parses @dfn{long option names} of the form
+@samp{--hold-the-onions} and @samp{--verbosity-level=extreme}.
+@w{@code{Getopt--}} behaves as @code{getopt} except for non-empty
+options beginning with @samp{--}.
+
+Options beginning with @samp{--} are returned as strings rather than
+characters. If a value is assigned (using @samp{=}) to a long option,
+@code{*optarg*} is set to the value. The @samp{=} and value are
+not returned as part of the option string.
+
+No information is passed to @code{getopt--} concerning which long
+options should be accepted or whether such options can take arguments.
+If a long option did not have an argument, @code{*optarg} will be set to
+@code{#f}. The caller is responsible for detecting and reporting
+errors.
-@subsubsection Inverter code
@example
-(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)
- (define self (make-object
- (make-number 1)
- (make-description "A number which can be inverted")))
- (define <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 () (set-value! x (/ 1 (value x)))))
-
-(value x) @result{} 1
-(set-value! x 33) @result{} undefined
-(invert! x) @result{} undefined
-(value x) @result{} 1/33
-
-(unmake-method! x invert!) @result{} undefined
-
-(invert! x) @error{} ERROR: Method not supported: x
+(define opts ":-:b:")
+(define argc 5)
+(define argv '("foo" "-b9" "--f1" "--2=" "--g3=35234.342" "--"))
+(define *optind* 1)
+(define *optarg* #f)
+(require 'qp)
+@ftindex qp
+(do ((i 5 (+ -1 i)))
+ ((zero? i))
+ (define opt (getopt-- argc argv opts))
+ (print *optind* opt *optarg*)))
+@print{}
+2 #\b "9"
+3 "f1" #f
+4 "2" ""
+5 "g3" "35234.342"
+5 #f "35234.342"
@end example
+@end defun
-@node Parameter lists, Priority Queues, Object, Data Structures
-@section Parameter lists
+@node Command Line, Parameter lists, Getopt, Program Arguments
+@subsection Command Line
+
+@code{(require 'read-command)}
+@ftindex read-command
+
+@defun read-command port
+@defunx read-command
+@code{read-command} converts a @dfn{command line} into a list of strings
+@cindex command line
+suitable for parsing by @code{getopt}. The syntax of command lines
+supported resembles that of popular @dfn{shell}s. @code{read-command}
+updates @var{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 @var{port} argument may be omitted, in which case it defaults to the
+value returned by @code{current-input-port}.
+
+The fields into which the command line is split are delimited by
+whitespace as defined by @code{char-whitespace?}. The end of a command
+is delimited by end-of-file or unescaped semicolon (@key{;}) or
+@key{newline}. Any character can be literally included in a field by
+escaping it with a backslach (@key{\}).
+
+The initial character and types of fields recognized are:
+@table @asis
+@item @samp{\}
+The next character has is taken literally and not interpreted as a field
+delimiter. If @key{\} is the last character before a @key{newline},
+that @key{newline} is just ignored. Processing continues from the
+characters after the @key{newline} as though the backslash and
+@key{newline} were not there.
+@item @samp{"}
+The characters up to the next unescaped @key{"} are taken literally,
+according to [R4RS] rules for literal strings (@pxref{Strings, , ,r4rs,
+Revised(4) Scheme}).
+@item @samp{(}, @samp{%'}
+One scheme expression is @code{read} starting with this character. The
+@code{read} expression is evaluated, converted to a string
+(using @code{display}), and replaces the expression in the returned
+field.
+@item @samp{;}
+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.
+@end table
+
+@noindent
+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. @key{#} can be part of fields if these conditions are
+not met. For instance, @code{ab#c} is just the field ab#c.
+
+@table @samp
+@item #
+Introduces a comment. The comment continues to the end of the line on
+which the semicolon appears. Comments are treated as whitespace by
+@code{read-dommand-line} and backslashes before @key{newline}s in
+comments are also ignored.
+@end table
+@end defun
+
+@defun read-options-file filename
+@code{read-options-file} converts an @dfn{options file} into a list of
+@cindex options file
+strings suitable for parsing by @code{getopt}. The syntax of options
+files is the same as the syntax for command
+lines, except that @key{newline}s do not terminate reading (only @key{;}
+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.
+@end defun
+
+
+
+@node Parameter lists, Batch, Command Line, Program Arguments
+@subsection Parameter lists
@code{(require 'parameters)}
+@ftindex parameters
@noindent
Arguments to procedures in scheme are distinguished from each other by
@@ -1357,12 +3824,13 @@ This process is repeated until @var{parameter-list} stops growing. The
value returned from @code{parameter-list-expand} is unspecified.
@end deffn
-@deffn Function fill-empty-parameters defaults parameter-list
-@var{defaults} is a list of lists whose order matches the order of the
-@var{parameter-name}s in the call to @code{make-parameter-list} which
-created @var{parameter-list}. @code{fill-empty-parameters} returns a
-new parameter-list with each empty parameter filled with the
-corresponding @var{default}.
+@deffn Function fill-empty-parameters defaulters parameter-list
+@var{defaulters} is a list of procedures whose order matches the order
+of the @var{parameter-name}s in the call to @code{make-parameter-list}
+which created @var{parameter-list}. @code{fill-empty-parameters}
+returns a new parameter-list with each empty parameter replaced with the
+list returned by calling the corresponding @var{defaulter} with
+@var{parameter-list} as its argument.
@end deffn
@deffn Function check-parameters checks parameter-list
@@ -1413,223 +3881,1661 @@ elements of @var{optnames}. Each of these strings which have length of
strings will be treated as long-named options (@pxref{Getopt, getopt--}).
@end deffn
-@deffn Function getopt->arglist argc argv optnames positions arities types defaults checks aliases
+@deffn Function getopt->arglist argc argv optnames positions arities types defaulters checks aliases
Like @code{getopt->parameter-list}, but converts @var{argv} to an
argument-list as specified by @var{optnames}, @var{positions},
-@var{arities}, @var{types}, @var{defaults}, @var{checks}, and
+@var{arities}, @var{types}, @var{defaulters}, @var{checks}, and
@var{aliases}.
@end deffn
+@noindent
These @code{getopt} functions can be used with SLIB relational
databases. For an example, @xref{Database Utilities,
make-command-server}.
-@node Priority Queues, Queues, Parameter lists, Data Structures
-@section Priority Queues
+@noindent
+If errors are encountered while processing options, directions for using
+the options are printed to @code{current-error-port}.
-@code{(require 'priority-queue)}
+@example
+(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))))
+@print{}
+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" "-?"
+@end example
-@defun make-heap pred<?
-Returns a binary heap suitable which can be used for priority queue
-operations.
+
+@node Batch, , Parameter lists, Program Arguments
+@subsection Batch
+
+@code{(require 'batch)}
+@ftindex batch
+
+@noindent
+The batch procedures provide a way to write and execute portable scripts
+for a variety of operating systems. Each @code{batch:} procedure takes
+as its first argument a parameter-list (@pxref{Parameter lists}). This
+parameter-list argument @var{parms} contains named associations. Batch
+currently uses 2 of these:
+
+@table @code
+@item batch-port
+The port on which to write lines of the batch file.
+@item batch-dialect
+The syntax of batch file to generate. Currently supported are:
+@itemize @bullet
+@item
+unix
+@item
+dos
+@item
+vms
+@item
+system
+@item
+*unknown*
+@end itemize
+@end table
+
+@noindent
+@file{batch.scm} uses 2 enhanced relational tables (@pxref{Database
+Utilities}) to store information linking the names of
+@code{operating-system}s to @code{batch-dialect}es.
+
+@defun batch:initialize! database
+Defines @code{operating-system} and @code{batch-dialect} tables and adds
+the domain @code{operating-system} to the enhanced relational database
+@var{database}.
@end defun
-@defun heap-length heap
-Returns the number of elements in @var{heap}.@refill
+@defvar batch:platform
+Is batch's best guess as to which operating-system it is running under.
+@code{batch:platform} is set to @code{(software-type)}
+(@pxref{Configuration}) unless @code{(software-type)} is @code{unix},
+in which case finer distinctions are made.
+@end defvar
+
+@defun batch:call-with-output-script parms file proc
+@var{proc} should be a procedure of one argument. If @var{file} is an
+output-port, @code{batch:call-with-output-script} writes an appropriate
+header to @var{file} and then calls @var{proc} with @var{file} as the
+only argument. If @var{file} is a string,
+@code{batch:call-with-output-script} opens a output-file of name
+@var{file}, writes an appropriate header to @var{file}, and then calls
+@var{proc} with the newly opened port as the only argument. Otherwise,
+@code{batch:call-with-output-script} acts as if it was called with the
+result of @code{(current-output-port)} as its third argument.
@end defun
-@deffn Procedure heap-insert! heap item
-Inserts @var{item} into @var{heap}. @var{item} can be inserted multiple
-times. The value returned is unspecified.@refill
-@end deffn
+@defun batch:apply-chop-to-fit proc arg1 arg2 @dots{} list
+The procedure @var{proc} must accept at least one argument and return
+@code{#t} if successful, @code{#f} if not.
+@code{batch:apply-chop-to-fit} calls @var{proc} with @var{arg1},
+@var{arg2}, @dots{}, and @var{chunk}, where @var{chunk} is a subset of
+@var{list}. @code{batch:apply-chop-to-fit} tries @var{proc} with
+successively smaller subsets of @var{list} until either @var{proc}
+returns non-false, or the @var{chunk}s become empty.
+@end defun
-@defun heap-extract-max! heap
-Returns the item which is larger than all others according to the
-@var{pred<?} argument to @code{make-heap}. If there are no items in
-@var{heap}, an error is signaled.@refill
+@noindent
+The rest of the @code{batch:} procedures write (or execute if
+@code{batch-dialect} is @code{system}) commands to the batch port which
+has been added to @var{parms} or @code{(copy-tree @var{parms})} by the
+code:
+
+@example
+(adjoin-parameters! @var{parms} (list 'batch-port @var{port}))
+@end example
+
+@defun batch:system parms string1 string2 @dots{}
+Calls @code{batch:try-system} (below) with arguments, but signals an
+error if @code{batch:try-system} returns @code{#f}.
@end defun
-The algorithm for priority queues was taken from @cite{Introduction to
-Algorithms} by T. Cormen, C. Leiserson, R. Rivest. 1989 MIT Press.
+@noindent
+These functions return a non-false value if the command was successfully
+translated into the batch dialect and @code{#f} if not. In the case of
+the @code{system} dialect, the value is non-false if the operation
+suceeded.
+@defun batch:try-system parms string1 string2 @dots{}
+Writes a command to the @code{batch-port} in @var{parms} which executes
+the program named @var{string1} with arguments @var{string2} @dots{}.
+@end defun
+@defun batch:run-script parms string1 string2 @dots{}
+Writes a command to the @code{batch-port} in @var{parms} which executes
+the batch script named @var{string1} with arguments @var{string2}
+@dots{}.
-@node Queues, Records, Priority Queues, Data Structures
-@section Queues
+@emph{Note:} @code{batch:run-script} and @code{batch:try-system} are not the
+same for some operating systems (VMS).
+@end defun
-@code{(require 'queue)}
+@defun batch:comment parms line1 @dots{}
+Writes comment lines @var{line1} @dots{} to the @code{batch-port} in
+@var{parms}.
+@end defun
-A @dfn{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 @dfn{dequeues}). A queue may also be used like a stack.@refill
+@defun batch:lines->file parms file line1 @dots{}
+Writes commands to the @code{batch-port} in @var{parms} which create a
+file named @var{file} with contents @var{line1} @dots{}.
+@end defun
-@defun make-queue
-Returns a new, empty queue.
+@defun batch:delete-file parms file
+Writes a command to the @code{batch-port} in @var{parms} which deletes
+the file named @var{file}.
@end defun
-@defun queue? obj
-Returns @code{#t} if @var{obj} is a queue.
+@defun batch:rename-file parms old-name new-name
+Writes a command to the @code{batch-port} in @var{parms} which renames
+the file @var{old-name} to @var{new-name}.
@end defun
-@defun queue-empty? q
-Returns @code{#t} if the queue @var{q} is empty.
+@noindent
+In addition, batch provides some small utilities very useful for writing
+scripts:
+
+@defun truncate-up-to path char
+@defunx truncate-up-to path string
+@defunx truncate-up-to path charlist
+@var{path} can be a string or a list of strings. Returns @var{path}
+sans any prefixes ending with a character of the second argument. This
+can be used to derive a filename moved locally from elsewhere.
+
+@example
+(truncate-up-to "/usr/local/lib/slib/batch.scm" "/")
+@result{} "batch.scm"
+@end example
@end defun
-@deffn Procedure queue-push! q datum
-Adds @var{datum} to the front of queue @var{q}.
+@defun replace-suffix str old new
+@var{str} can be a string or a list of strings. Returns a new string
+(or strings) similar to @code{str} but with the suffix string @var{old}
+removed and the suffix string @var{new} appended. If the end of
+@var{str} does not match @var{old}, an error is signaled.
+
+@example
+(replace-suffix "/usr/local/lib/slib/batch.scm" ".scm" ".c")
+@result{} "/usr/local/lib/slib/batch.c"
+@end example
+@end defun
+
+@defun string-join joiner string1 @dots{}
+Returns a new string consisting of all the strings @var{string1} @dots{}
+in order appended together with the string @var{joiner} between each
+adjacent pair.
+@end defun
+
+@defun must-be-first list1 list2
+Returns a new list consisting of the elements of @var{list2} ordered so
+that if some elements of @var{list1} are @code{equal?} to elements of
+@var{list2}, then those elements will appear first and in the order of
+@var{list1}.
+@end defun
+
+@defun must-be-last list1 list2
+Returns a new list consisting of the elements of @var{list1} ordered so
+that if some elements of @var{list2} are @code{equal?} to elements of
+@var{list1}, then those elements will appear last and in the order of
+@var{list2}.
+@end defun
+
+@defun os->batch-dialect osname
+Returns its best guess for the @code{batch-dialect} to be used for the
+operating-system named @var{osname}. @code{os->batch-dialect} uses the
+tables added to @var{database} by @code{batch:initialize!}.
+@end defun
+
+@noindent
+Here is an example of the use of most of batch's procedures:
+
+@example
+(require 'database-utilities)
+@ftindex database-utilities
+(require 'parameters)
+@ftindex parameters
+(require 'batch)
+@ftindex batch
+
+(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:system my-parameters "cc" "-c" "hello.c")
+ (batch:system my-parameters "cc" "-o" "hello"
+ (replace-suffix "hello.c" ".c" ".o"))
+ (batch:system 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")
+ )))
+@end example
+
+@noindent
+Produces the file @file{my-batch}:
+
+@example
+#!/bin/sh
+# "my-batch" build script created Sat Jun 10 21:20:37 1995
+# ================ 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
+@end example
+
+@noindent
+When run, @file{my-batch} prints:
+
+@example
+bash$ my-batch
+mv: hello.c: No such file or directory
+hello world
+@end example
+
+
+@node Printing Scheme, Time and Date, Program Arguments, Textual Conversion Packages
+@section Printing Scheme
+
+@menu
+* Generic-Write:: 'generic-write
+* Object-To-String:: 'object->string
+* Pretty-Print:: 'pretty-print, 'pprint-file
+@end menu
+
+
+@node Generic-Write, Object-To-String, Printing Scheme, Printing Scheme
+@subsection Generic-Write
+
+@code{(require 'generic-write)}
+@ftindex generic-write
+
+@code{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.@refill
+
+@deffn Procedure generic-write obj display? width output
+@table @var
+@item obj
+Scheme data value to transform.
+@item display?
+Boolean, controls whether characters and strings are quoted.
+@item width
+Extended boolean, selects format:
+@table @asis
+@item #f
+single line format
+@item integer > 0
+pretty-print (value = max nb of chars per line)
+@end table
+@item output
+Procedure of 1 argument of string type, called repeatedly with
+successive substrings of the textual representation. This procedure can
+return @code{#f} to stop the transformation.
+@end table
+
+The value returned by @code{generic-write} is undefined.
+
+Examples:
+@lisp
+(write obj) @equiv{} (generic-write obj #f #f @var{display-string})
+(display obj) @equiv{} (generic-write obj #t #f @var{display-string})
+@end lisp
+@noindent
+where
+@lisp
+@var{display-string} @equiv{}
+(lambda (s) (for-each write-char (string->list s)) #t)
+@end lisp
@end deffn
-@deffn Procedure enquque! q datum
-Adds @var{datum} to the rear of queue @var{q}.
+
+
+@node Object-To-String, Pretty-Print, Generic-Write, Printing Scheme
+@subsection Object-To-String
+
+@code{(require 'object->string)}
+@ftindex object->string
+
+@defun object->string obj
+Returns the textual representation of @var{obj} as a string.
+@end defun
+
+
+
+
+@node Pretty-Print, , Object-To-String, Printing Scheme
+@subsection Pretty-Print
+
+@code{(require 'pretty-print)}
+@ftindex pretty-print
+
+@deffn Procedure pretty-print obj
+@deffnx Procedure pretty-print obj port
+
+@code{pretty-print}s @var{obj} on @var{port}. If @var{port} is not
+specified, @code{current-output-port} is used.
+
+Example:
+@example
+@group
+(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)))
+ @print{} ((1 2 3 4 5)
+ @print{} (6 7 8 9 10)
+ @print{} (11 12 13 14 15)
+ @print{} (16 17 18 19 20)
+ @print{} (21 22 23 24 25))
+@end group
+@end example
@end deffn
-All of the following functions raise an error if the queue @var{q} is
-empty.@refill
-@defun queue-front q
-Returns the datum at the front of the queue @var{q}.
+@code{(require 'pprint-file)}
+@ftindex pprint-file
+
+@deffn Procedure pprint-file infile
+@deffnx Procedure pprint-file infile outfile
+Pretty-prints all the code in @var{infile}. If @var{outfile} is
+specified, the output goes to @var{outfile}, otherwise it goes to
+@code{(current-output-port)}.@refill
+@end deffn
+
+@defun pprint-filter-file infile proc outfile
+@defunx pprint-filter-file infile proc
+@var{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 @var{proc} is applied to them sequentially.
+
+@var{outfile} is a port or a string. If no @var{outfile} is specified
+then @code{current-output-port} is assumed. These expanded expressions
+are then @code{pretty-print}ed to this port.
+
+Whitepsace and comments (introduced by @code{;}) which are not part of
+scheme expressions are reproduced in the output. This procedure does
+not affect the values returned by @code{current-input-port} and
+@code{current-output-port}.@refill
@end defun
-@defun queue-rear q
-Returns the datum at the rear of the queue @var{q}.
+@code{pprint-filter-file} can be used to pre-compile macro-expansion and
+thus can reduce loading time. The following will write into
+@file{exp-code.scm} the result of expanding all defmacros in
+@file{code.scm}.
+@lisp
+(require 'pprint-file)
+@ftindex pprint-file
+(require 'defmacroexpand)
+@ftindex defmacroexpand
+(defmacro:load "my-macros.scm")
+(pprint-filter-file "code.scm" defmacro:expand* "exp-code.scm")
+@end lisp
+
+@node Time and Date, Vector Graphics, Printing Scheme, Textual Conversion Packages
+@section Time and Date
+
+@menu
+* Posix Time:: 'posix-time
+* Common-Lisp Time:: 'common-lisp-time
+@end menu
+
+
+@node Posix Time, Common-Lisp Time, Time and Date, Time and Date
+@subsection Posix Time
+
+@example
+(require 'posix-time)
+@ftindex posix-time
+@end example
+
+@deftp {Data Type} {Calendar-Time}
+@cindex calendar time
+@cindex caltime
+is a datatype encapsulating time.
+@end deftp
+
+@deftp {Data Type} {Coordinated Universal Time}
+@cindex Coordinated Universal Time
+@cindex UTC
+(abbreviated @dfn{UTC}) is a vector of integers representing time:
+
+@enumerate 0
+@item
+ seconds (0 - 61)
+@item
+ minutes (0 - 59)
+@item
+ hours since midnight (0 - 23)
+@item
+ day of month (1 - 31)
+@item
+ month (0 - 11). Note difference from @code{decode-universal-time}.
+@item
+ the number of years since 1900. Note difference from
+@code{decode-universal-time}.
+@item
+ day of week (0 - 6)
+@item
+ day of year (0 - 365)
+@item
+ 1 for daylight savings, 0 for regular time
+@end enumerate
+@end deftp
+
+@defun gmtime caltime
+Converts the calendar time @var{caltime} to UTC and returns it.
+
+@defunx localtime caltime tz
+Returns @var{caltime} converted to UTC relative to timezone @var{tz}.
+
+@defunx localtime caltime
+converts the calendar time @var{caltime} to a vector of integers
+expressed relative to the user's time zone. @code{localtime} sets the
+variable @var{*timezone*} with the difference between Coordinated
+Universal Time (UTC) and local standard time in seconds
+(@pxref{Time Zone,tzset}).
+
@end defun
-@deffn Prcoedure queue-pop! q
-@deffnx Procedure dequeue! q
-Both of these procedures remove and return the datum at the front of the
-queue. @code{queue-pop!} is used to suggest that the queue is being
-used like a stack.@refill
+@defun gmktime univtime
+Converts a vector of integers in GMT Coordinated Universal Time (UTC)
+format to a calendar time.
+
+@defunx mktime univtime
+Converts a vector of integers in local Coordinated Universal Time (UTC)
+format to a calendar time.
+
+@defunx mktime univtime tz
+Converts a vector of integers in Coordinated Universal Time (UTC) format
+(relative to time-zone @var{tz})
+to calendar time.
+@end defun
+
+@defun asctime univtime
+Converts the vector of integers @var{caltime} in Coordinated
+Universal Time (UTC) format into a string of the form
+@code{"Wed Jun 30 21:49:08 1993"}.
+@end defun
+
+@defun gtime caltime
+@defunx ctime caltime
+@defunx ctime caltime tz
+Equivalent to @code{(asctime (gmtime @var{caltime}))},
+@code{(asctime (localtime @var{caltime}))}, and
+@code{(asctime (localtime @var{caltime} @var{tz}))}, respectively.
+@end defun
+
+
+@node Common-Lisp Time, , Posix Time, Time and Date
+@subsection Common-Lisp Time
+
+@defun get-decoded-time
+Equivalent to @code{(decode-universal-time (get-universal-time))}.
+@end defun
+
+@defun get-universal-time
+Returns the current time as @dfn{Universal Time}, number of seconds
+since 00:00:00 Jan 1, 1900 GMT. Note that the reference time is
+different from @code{current-time}.
+@end defun
+
+@defun decode-universal-time univtime
+Converts @var{univtime} to @dfn{Decoded Time} format.
+Nine values are returned:
+@enumerate 0
+@item
+ seconds (0 - 61)
+@item
+ minutes (0 - 59)
+@item
+ hours since midnight
+@item
+ day of month
+@item
+ month (1 - 12). Note difference from @code{gmtime} and @code{localtime}.
+@item
+ year (A.D.). Note difference from @code{gmtime} and @code{localtime}.
+@item
+ day of week (0 - 6)
+@item
+ #t for daylight savings, #f otherwise
+@item
+ hours west of GMT (-24 - +24)
+@end enumerate
+
+Notice that the values returned by @code{decode-universal-time} do not
+match the arguments to @code{encode-universal-time}.
+@end defun
+
+@defun encode-universal-time second minute hour date month year
+@defunx encode-universal-time second minute hour date month year time-zone
+Converts the arguments in Decoded Time format to Universal Time format.
+If @var{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 @code{decode-universal-time} do not
+match the arguments to @code{encode-universal-time}.
+@end defun
+
+
+@node Vector Graphics, , Time and Date, Textual Conversion Packages
+@section Vector Graphics
+
+@menu
+* Tektronix Graphics Support::
+@end menu
+
+@node Tektronix Graphics Support, , Vector Graphics, Vector Graphics
+@subsection Tektronix Graphics Support
+
+@emph{Note:} The Tektronix graphics support files need more work, and
+are not complete.
+
+@subsubsection 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.
+
+@deffn Procedure tek40:init
+@end deffn
+
+@deffn Procedure tek40:graphics
+@end deffn
+
+@deffn Procedure tek40:text
@end deffn
+@deffn Procedure tek40:linetype linetype
+@end deffn
+@deffn Procedure tek40:move x y
+@end deffn
+@deffn Procedure tek40:draw x y
+@end deffn
+@deffn Procedure tek40:put-text x y str
+@end deffn
-@node Records, Base Table, Queues, Data Structures
-@section Records
+@deffn Procedure tek40:reset
+@end deffn
-@code{(require 'record)}
-The Record package provides a facility for user to define their own
-record data types.
+@subsubsection Tektronix 4100 Series Graphics
-@defun make-record-type type-name field-names
-Returns a @dfn{record-type descriptor}, a value representing a new data
-type disjoint from all others. The @var{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 @var{field-names}
-argument is a list of symbols naming the @dfn{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.@refill
+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.
+
+@deffn Procedure tek41:init
+@end deffn
+
+@deffn Procedure tek41:reset
+@end deffn
+
+@deffn Procedure tek41:graphics
+@end deffn
+
+@deffn Procedure tek41:move x y
+@end deffn
+
+@deffn Procedure tek41:draw x y
+@end deffn
+
+@deffn Procedure tek41:point x y number
+@end deffn
+
+@deffn Procedure tek41:encode-x-y x y
+@end deffn
+
+@deffn Procedure tek41:encode-int number
+@end deffn
+
+
+@node Mathematical Packages, Database Packages, Textual Conversion Packages, Top
+@chapter Mathematical Packages
+
+@menu
+* Bit-Twiddling:: 'logical
+* Modular Arithmetic:: 'modular
+* Prime Testing and Generation:: 'primes
+* Prime Factorization:: 'factor
+* Random Numbers:: 'random
+* Cyclic Checksum:: 'make-crc
+* Plotting:: 'charplot
+* Root Finding:: 'root
+* Commutative Rings:: 'commutative-ring
+* Determinant::
+@end menu
+
+
+@node Bit-Twiddling, Modular Arithmetic, Mathematical Packages, Mathematical Packages
+@section Bit-Twiddling
+
+@code{(require 'logical)}
+@ftindex logical
+
+The bit-twiddling functions are made available through the use of the
+@code{logical} package. @code{logical} is loaded by inserting
+@code{(require 'logical)} before the code that uses these
+@ftindex logical
+functions.@refill
+
+@defun logand n1 n1
+Returns the integer which is the bit-wise AND of the two integer
+arguments.
+
+Example:
+@lisp
+(number->string (logand #b1100 #b1010) 2)
+ @result{} "1000"
+@end lisp
@end defun
-@c @defun make-record-sub-type type-name field-names rtd
-@c Returns a @dfn{record-type descriptor}, a value representing a new data
-@c type, disjoint from all others. The @var{type-name} argument must be a
-@c string. The @var{field-names} argument is a list of symbols naming the
-@c additional @dfn{fields} to be appended to @var{field-names} of
-@c @var{rtd}. It is an error if the combinded list contains any
-@c duplicates.@refill
-@c
-@c Record-modifiers and record-accessors for @var{rtd} work for the new
-@c record-sub-type as well. But record-modifiers and record-accessors for
-@c the new record-sub-type will not neccessarily work for @var{rtd}.@refill
-@c @end defun
+@defun logior n1 n2
+Returns the integer which is the bit-wise OR of the two integer
+arguments.
-@defun record-constructor rtd [field-names]
-Returns a procedure for constructing new members of the type represented
-by @var{rtd}. The returned procedure accepts exactly as many arguments
-as there are symbols in the given list, @var{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 @var{field-names}
-argument defaults to the list of field names in the call to
-@code{make-record-type} that created the type represented by @var{rtd};
-if the @var{field-names} argument is provided, it is an error if it
-contains any duplicates or any symbols not in the default list.@refill
+Example:
+@lisp
+(number->string (logior #b1100 #b1010) 2)
+ @result{} "1110"
+@end lisp
@end defun
-@defun record-predicate rtd
-Returns a procedure for testing membership in the type represented by
-@var{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.@refill
+@defun logxor n1 n2
+Returns the integer which is the bit-wise XOR of the two integer
+arguments.
+
+Example:
+@lisp
+(number->string (logxor #b1100 #b1010) 2)
+ @result{} "110"
+@end lisp
@end defun
-@c @defun record-sub-predicate rtd
-@c Returns a procedure for testing membership in the type represented by
-@c @var{rtd} or its parents. The returned procedure accepts exactly one
-@c argument and returns a true value if the argument is a member of the
-@c indicated record type or its parents; it returns a false value
-@c otherwise.@refill
-@c @end defun
+@defun lognot n
+Returns the integer which is the 2s-complement of the integer argument.
-@defun record-accessor rtd field-name
-Returns a procedure for reading the value of a particular field of a
-member of the type represented by @var{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
-@var{field-name} in that record. The symbol @var{field-name} must be a
-member of the list of field-names in the call to @code{make-record-type}
-that created the type represented by @var{rtd}.@refill
+Example:
+@lisp
+(number->string (lognot #b10000000) 2)
+ @result{} "-10000001"
+(number->string (lognot #b0) 2)
+ @result{} "-1"
+@end lisp
@end defun
+@defun logtest j k
+@example
+(logtest j k) @equiv{} (not (zero? (logand j k)))
-@defun record-modifier rtd field-name
-Returns a procedure for writing the value of a particular field of a
-member of the type represented by @var{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 @var{field-name} in that record to contain the given value.
-The returned value of the modifier procedure is unspecified. The symbol
-@var{field-name} must be a member of the list of field-names in the call
-to @code{make-record-type} that created the type represented by
-@var{rtd}.@refill
+(logtest #b0100 #b1011) @result{} #f
+(logtest #b0100 #b0111) @result{} #t
+@end example
@end defun
-@defun record? obj
-Returns a true value if @var{obj} is a record of any type and a false
-value otherwise. Note that @code{record?} may be true of any Scheme
-value; of course, if it returns true for some particular value, then
-@code{record-type-descriptor} is applicable to that value and returns an
-appropriate descriptor.@refill
+@defun logbit? index j
+@example
+(logbit? index j) @equiv{} (logtest (integer-expt 2 index) j)
+
+(logbit? 0 #b1101) @result{} #t
+(logbit? 1 #b1101) @result{} #f
+(logbit? 2 #b1101) @result{} #t
+(logbit? 3 #b1101) @result{} #t
+(logbit? 4 #b1101) @result{} #f
+@end example
@end defun
-@defun record-type-descriptor record
-Returns a record-type descriptor representing the type of the given
-record. That is, for example, if the returned descriptor were passed to
-@code{record-predicate}, the resulting predicate would return a true
-value when passed the given record. Note that it is not necessarily the
-case that the returned descriptor is the one that was passed to
-@code{record-constructor} in the call that created the constructor
-procedure that created the given record.@refill
+@defun ash int count
+Returns an integer equivalent to
+@code{(inexact->exact (floor (* @var{int} (expt 2 @var{count}))))}.@refill
+
+Example:
+@lisp
+(number->string (ash #b1 3) 2)
+ @result{} "1000"
+(number->string (ash #b1010 -1) 2)
+ @result{} "101"
+@end lisp
@end defun
-@defun record-type-name rtd
-Returns the type-name associated with the type represented by rtd. The
-returned value is @code{eqv?} to the @var{type-name} argument given in
-the call to @code{make-record-type} that created the type represented by
-@var{rtd}.@refill
+@defun logcount n
+Returns the number of bits in integer @var{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:
+@lisp
+(logcount #b10101010)
+ @result{} 4
+(logcount 0)
+ @result{} 0
+(logcount -2)
+ @result{} 1
+@end lisp
@end defun
-@defun record-type-field-names rtd
-Returns a list of the symbols naming the fields in members of the type
-represented by @var{rtd}. The returned value is @code{equal?} to the
-field-names argument given in the call to @code{make-record-type} that
-created the type represented by @var{rtd}.@refill
+@defun integer-length n
+Returns the number of bits neccessary to represent @var{n}.
+
+Example:
+@lisp
+(integer-length #b10101010)
+ @result{} 8
+(integer-length 0)
+ @result{} 0
+(integer-length #b1111)
+ @result{} 4
+@end lisp
@end defun
+@defun integer-expt n k
+Returns @var{n} raised to the non-negative integer exponent @var{k}.
+
+Example:
+@lisp
+(integer-expt 2 5)
+ @result{} 32
+(integer-expt -3 3)
+ @result{} -27
+@end lisp
+@end defun
+@defun bit-extract n start end
+Returns the integer composed of the @var{start} (inclusive) through
+@var{end} (exclusive) bits of @var{n}. The @var{start}th bit becomes
+the 0-th bit in the result.@refill
-@node Base Table, Relational Database, Records, Data Structures
+Example:
+@lisp
+(number->string (bit-extract #b1101101010 0 4) 2)
+ @result{} "1010"
+(number->string (bit-extract #b1101101010 4 9) 2)
+ @result{} "10110"
+@end lisp
+@end defun
+
+
+@node Modular Arithmetic, Prime Testing and Generation, Bit-Twiddling, Mathematical Packages
+@section Modular Arithmetic
+
+@code{(require 'modular)}
+@ftindex modular
+
+@defun extended-euclid n1 n2
+Returns a list of 3 integers @code{(d x y)} such that d = gcd(@var{n1},
+@var{n2}) = @var{n1} * x + @var{n2} * y.@refill
+@end defun
+
+@defun symmetric:modulus n
+Returns @code{(quotient (+ -1 n) -2)} for positive odd integer @var{n}.
+@end defun
+
+@defun modulus->integer modulus
+Returns the non-negative integer characteristic of the ring formed when
+@var{modulus} is used with @code{modular:} procedures.
+@end defun
+
+@defun modular:normalize modulus n
+Returns the integer @code{(modulo @var{n} (modulus->integer
+@var{modulus}))} in the representation specified by @var{modulus}.
+@end defun
+
+@noindent
+The rest of these functions assume normalized arguments; That is, the
+arguments are constrained by the following table:
+
+@noindent
+For all of these functions, if the first argument (@var{modulus}) is:
+@table @code
+@item positive?
+Work as before. The result is between 0 and @var{modulus}.
+
+@item zero?
+The arguments are treated as integers. An integer is returned.
+
+@item negative?
+The arguments and result are treated as members of the integers modulo
+@code{(+ 1 (* -2 @var{modulus}))}, but with @dfn{symmetric}
+representation; i.e. @code{(<= (- @var{modulus}) @var{n}
+@var{modulus})}.
+@end table
+
+@noindent
+If all the arguments are fixnums the computation will use only fixnums.
+
+@defun modular:invertable? modulus k
+Returns @code{#t} if there exists an integer n such that @var{k} * n
+@equiv{} 1 mod @var{modulus}, and @code{#f} otherwise.
+@end defun
+
+@defun modular:invert modulus k2
+Returns an integer n such that 1 = (n * @var{k2}) mod @var{modulus}. If
+@var{k2} has no inverse mod @var{modulus} an error is signaled.
+@end defun
+
+@defun modular:negate modulus k2
+Returns (@minus{}@var{k2}) mod @var{modulus}.
+@end defun
+
+@defun modular:+ modulus k2 k3
+Returns (@var{k2} + @var{k3}) mod @var{modulus}.
+@end defun
+
+@defun modular:@minus{} modulus k2 k3
+Returns (@var{k2} @minus{} @var{k3}) mod @var{modulus}.
+@end defun
+
+@defun modular:* modulus k2 k3
+Returns (@var{k2} * @var{k3}) mod @var{modulus}.
+
+The Scheme code for @code{modular:*} with negative @var{modulus} is not
+completed for fixnum-only implementations.
+@end defun
+
+@defun modular:expt modulus k2 k3
+Returns (@var{k2} ^ @var{k3}) mod @var{modulus}.
+@end defun
+
+
+@node Prime Testing and Generation, Prime Factorization, Modular Arithmetic, Mathematical Packages
+@section Prime Testing and Generation
+
+@code{(require 'primes)}
+@ftindex primes
+
+This package tests and generates prime numbers. The strategy used is
+as follows:
+
+@itemize @bullet
+@item
+First, use trial division by small primes (primes less than 1000) to
+quickly weed out composites with small factors. As a side benefit, this
+makes the test precise for numbers up to one million.
+@item
+Second, apply the Miller-Rabin primality test to detect (with high
+probability) any remaining composites.
+@end itemize
+
+The Miller-Rabin test is a Monte-Carlo test---in other words, it's fast
+and it gets the right answer with high probability. For a candidate
+that @emph{is} prime, the Miller-Rabin test is certain to report
+"prime"; it will never report "composite". However, for a candidate
+that is composite, there is a (small) probability that the Miller-Rabin
+test will erroneously report "prime". This probability can be made
+arbitarily small by adjusting the number of iterations of the
+Miller-Rabin test.
+
+@defun probably-prime? candidate
+@defunx probably-prime? candidate iter
+Returns @code{#t} if @code{candidate} is probably prime. The optional
+parameter @code{iter} controls the number of iterations of the
+Miller-Rabin test. The probability of a composite candidate being
+mistaken for a prime is at most @code{(1/4)^iter}. The default value of
+@code{iter} is 15, which makes the probability less than 1 in 10^9.
+
+@end defun
+
+@defun primes< start count
+@defunx primes< start count iter
+@defunx primes> start count
+@defunx primes> start count iter
+Returns a list of the first @code{count} odd probable primes less (more)
+than or equal to @code{start}. The optional parameter @code{iter}
+controls the number of iterations of the Miller-Rabin test for each
+candidate. The probability of a composite candidate being mistaken for
+a prime is at most @code{(1/4)^iter}. The default value of @code{iter}
+is 15, which makes the probability less than 1 in 10^9.
+
+@end defun
+
+@menu
+* The Miller-Rabin Test:: How the Miller-Rabin test works
+@end menu
+
+@node The Miller-Rabin Test, , Prime Testing and Generation, Prime Testing and Generation
+@subsection Theory
+
+Rabin and Miller's result can be summarized as follows. Let @code{p}
+(the candidate prime) be any odd integer greater than 2. Let @code{b}
+(the "base") be an integer in the range @code{2 ... p-1}. There is a
+fairly simple Boolean function---call it @code{C}, for
+"Composite"---with the following properties:
+@itemize @bullet
+
+@item
+If @code{p} is prime, @code{C(p, b)} is false for all @code{b} in the range
+@code{2 ... p-1}.
+
+@item
+If @code{p} is composite, @code{C(p, b)} is false for at most 1/4 of all
+@code{b} in the range @code{ 2 ... p-1}. (If the test fails for base
+@code{b}, @code{p} is called a @emph{strong pseudo-prime to base
+@code{b}}.)
+
+@end itemize
+For details of @code{C}, and why it fails for at most 1/4 of the
+potential bases, please consult a book on number theory or cryptography
+such as "A Course in Number Theory and Cryptography" by Neal Koblitz,
+published by Springer-Verlag 1994.
+
+There is nothing probablistic about this result. It's true for all
+@code{p}. If we had time to test @code{(1/4)p + 1} different bases, we
+could definitively determine the primality of @code{p}. For large
+candidates, that would take much too long---much longer than the simple
+approach of dividing by all numbers up to @code{sqrt(p)}. This is
+where probability enters the picture.
+
+Suppose we have some candidate prime @code{p}. Pick a random integer
+@code{b} in the range @code{2 ... p-1}. Compute @code{C(p,b)}. If
+@code{p} is prime, the result will certainly be false. If @code{p} is
+composite, the probability is at most 1/4 that the result will be false
+(demonstrating that @code{p} is a strong pseudoprime to base @code{b}).
+The test can be repeated with other random bases. If @code{p} is prime,
+each test is certain to return false. If @code{p} is composite, the
+probability of @code{C(p,b)} returning false is at most 1/4 for each
+test. Since the @code{b} are chosen at random, the tests outcomes are
+independent. So if @code{p} is composite and the test is repeated, say,
+15 times, the probability of it returning false all fifteen times is at
+most (1/4)^15, or about 10^-9. If the test is repeated 30 times, the
+probability of failure drops to at most 8.3e-25.
+
+Rabin and Miller's result holds for @emph{all} candidates @code{p}.
+However, if the candidate @code{p} is picked at random, the probability
+of the Miller-Rabin test failing is much less than the computed bound.
+This is because, for @emph{most} composite numbers, the fraction of
+bases that cause the test to fail is much less than 1/4. For example,
+if you pick a random odd number less than 1000 and apply the
+Miller-Rabin test with only 3 random bases, the computed failure bound
+is (1/4)^3, or about 1.6e-2. However, the actual probability of failure
+is much less---about 7.2e-5. If you accidentally pick 703 to test for
+primality, the probability of failure is (161/703)^3, or about 1.2e-2,
+which is almost as high as the computed bound. This is because 703 is a
+strong pseudoprime to 161 bases. But if you pick at random there is
+only a small chance of picking 703, and no other number less than 1000
+has that high a percentage of pseudoprime bases.
+
+The Miller-Rabin test is sometimes used in a slightly different fashion,
+where it can, at least in principle, cause problems. The weaker version
+uses small prime bases instead of random bases. If you are picking
+candidates at random and testing for primality, this works well since
+very few composites are strong pseudo-primes to small prime bases. (For
+example, there is only one composite less than 2.5e10 that is a strong
+pseudo-prime to the bases 2, 3, 5, and 7.) The problem with this
+approach is that once a candidate has been picked, the test is
+deterministic. This distinction is subtle, but real. With the
+randomized test, for @emph{any} candidate you pick---even if your
+candidate-picking procedure is strongly biased towards troublesome
+numbers, the test will work with high probability. With the
+deterministic version, for any particular candidate, the test will
+either work (with probability 1), or fail (with probability 1). It
+won't fail for very many candidates, but that won't be much consolation
+if your candidate-picking procedure is somehow biased toward troublesome
+numbers.
+
+
+@node Prime Factorization, Random Numbers, Prime Testing and Generation, Mathematical Packages
+@section Prime Factorization
+
+@code{(require 'factor)}
+@ftindex factor
+
+
+@defun factor k
+Returns a list of the prime factors of @var{k}. The order of the
+factors is unspecified. In order to obtain a sorted list do
+@code{(sort! (factor k) <)}.@refill
+@end defun
+
+@emph{Note:} The rest of these procedures implement the Solovay-Strassen
+primality test. This test has been superseeded by the faster
+@xref{Prime Testing and Generation, probably-prime?}. However these are
+left here as they take up little space and may be of use to an
+implementation without bignums.
+
+See Robert Solovay and Volker Strassen, @cite{A Fast Monte-Carlo Test
+for Primality}, SIAM Journal on Computing, 1977, pp 84-85.
+
+@defun jacobi-symbol p q
+Returns the value (+1, @minus{}1, or 0) of the Jacobi-Symbol of exact
+non-negative integer @var{p} and exact positive odd integer
+@var{q}.@refill
+@end defun
+
+@defun prime? p
+Returns @code{#f} if @var{p} is composite; @code{#t} if @var{p} is
+prime. There is a slight chance @code{(expt 2 (- prime:trials))} that a
+composite will return @code{#t}.@refill
+@end defun
+
+@defun prime:trials
+Is the maxinum number of iterations of Solovay-Strassen that will be
+done to test a number for primality.
+@end defun
+
+
+
+@node Random Numbers, Cyclic Checksum, Prime Factorization, Mathematical Packages
+@section Random Numbers
+
+@code{(require 'random)}
+@ftindex random
+
+
+@deffn Procedure random n
+@deffnx Procedure random n state
+Accepts a positive integer or real @var{n} and returns a number of the
+same type between zero (inclusive) and @var{n} (exclusive). The values
+returned have a uniform distribution.@refill
+
+The optional argument @var{state} must be of the type produced by
+@code{(make-random-state)}. It defaults to the value of the variable
+@code{*random-state*}. This object is used to maintain the state of the
+pseudo-random-number generator and is altered as a side effect of the
+@code{random} operation.@refill
+@end deffn
+
+@defvar *random-state*
+Holds a data structure that encodes the internal state of the
+random-number generator that @code{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.@refill
+@end defvar
+
+@deffn Procedure make-random-state
+@deffnx Procedure make-random-state state
+Returns a new object of type suitable for use as the value of the
+variable @code{*random-state*} and as a second argument to
+@code{random}. If argument @var{state} is given, a copy of it is
+returned. Otherwise a copy of @code{*random-state*} is returned.@refill
+@end deffn
+
+If inexact numbers are support by the Scheme implementation,
+@file{randinex.scm} will be loaded as well. @file{randinex.scm}
+contains procedures for generating inexact distributions.@refill
+
+@deffn Procedure random:uniform state
+Returns an uniformly distributed inexact real random number in the
+range between 0 and 1.
+@end deffn
+
+@deffn Procedure random:solid-sphere! vect
+@deffnx Procedure random:solid-sphere! vect state
+Fills @var{vect} with inexact real random numbers the sum of whose
+squares is less than 1.0. Thinking of @var{vect} as coordinates in
+space of dimension @var{n} = @code{(vector-length @var{vect})}, the
+coordinates are uniformly distributed within the unit @var{n}-shere.
+The sum of the squares of the numbers is returned.@refill
+@end deffn
+
+@deffn Procedure random:hollow-sphere! vect
+@deffnx Procedure random:hollow-sphere! vect state
+Fills @var{vect} with inexact real random numbers the sum of whose
+squares is equal to 1.0. Thinking of @var{vect} as coordinates in space
+of dimension n = @code{(vector-length @var{vect})}, the coordinates are
+uniformly distributed over the surface of the unit n-shere.@refill
+@end deffn
+
+@deffn Procedure random:normal
+@deffnx Procedure random:normal state
+Returns an inexact real in a normal distribution with mean 0 and
+standard deviation 1. For a normal distribution with mean @var{m} and
+standard deviation @var{d} use @code{(+ @var{m} (* @var{d}
+(random:normal)))}.@refill
+@end deffn
+
+@deffn Procedure random:normal-vector! vect
+@deffnx Procedure random:normal-vector! vect state
+Fills @var{vect} with inexact real random numbers which are independent
+and standard normally distributed (i.e., with mean 0 and variance 1).
+@end deffn
+
+@deffn Procedure random:exp
+@deffnx Procedure random:exp state
+Returns an inexact real in an exponential distribution with mean 1. For
+an exponential distribution with mean @var{u} use (* @var{u}
+(random:exp)).@refill
+@end deffn
+
+
+@node Cyclic Checksum, Plotting, Random Numbers, Mathematical Packages
+@section Cyclic Checksum
+
+@code{(require 'make-crc)}
+@ftindex make-crc
+
+@defun make-port-crc
+@defunx make-port-crc degree
+@defunx 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 @var{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 @var{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 @var{degree} is implicit and should not
+be part of @var{generator}. This allows systems with numbers limited to
+32 bits to calculate 32 bit checksums. The default value of
+@var{generator} when @var{degree} is 32 (its default) is:
+
+@example
+(make-port-crc 32 #b00000100110000010001110110110111)
+@end example
+
+Creates a procedure to calculate the P1003.2/D11.2 (POSIX.2) 32-bit
+checksum from the polynomial:
+
+@example
+ 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
+@end example
+@end defun
+
+@example
+(require 'make-crc)
+@ftindex 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"))
+
+@result{} 3553047446
+@end example
+
+@node Plotting, Root Finding, Cyclic Checksum, Mathematical Packages
+@section Plotting on Character Devices
+
+@code{(require 'charplot)}
+@ftindex charplot
+
+The plotting procedure is made available through the use of the
+@code{charplot} package. @code{charplot} is loaded by inserting
+@code{(require 'charplot)} before the code that uses this
+@ftindex charplot
+procedure.@refill
+
+@defvar charplot:height
+The number of rows to make the plot vertically.
+@end defvar
+
+@defvar charplot:width
+The number of columns to make the plot horizontally.
+@end defvar
+
+@deffn Procedure plot! coords x-label y-label
+@var{coords} is a list of pairs of x and y coordinates. @var{x-label}
+and @var{y-label} are strings with which to label the x and y
+axes.@refill
+
+Example:
+@example
+(require 'charplot)
+@ftindex 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)")
+@print{}
+@group
+ 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
+@end group
+@end example
+@end deffn
+
+
+@node Root Finding, Commutative Rings, Plotting, Mathematical Packages
+@section Root Finding
+
+@code{(require 'root)}
+@ftindex root
+
+@defun newtown:find-integer-root f df/dx x0
+Given integer valued procedure @var{f}, its derivative (with respect to
+its argument) @var{df/dx}, and initial integer value @var{x0} for which
+@var{df/dx}(@var{x0}) is non-zero, returns an integer @var{x} for which
+@var{f}(@var{x}) is closer to zero than either of the integers adjacent
+to @var{x}; or returns @code{#f} if such an integer can't be found.
+
+To find the closest integer to a given integers square root:
+
+@example
+(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) @result{} 4
+@end example
+@end defun
+
+@defun integer-sqrt y
+Given a non-negative integer @var{y}, returns the rounded square-root of
+@var{y}.
+@end defun
+
+@defun newton:find-root f df/dx x0 prec
+Given real valued procedures @var{f}, @var{df/dx} of one (real)
+argument, initial real value @var{x0} for which @var{df/dx}(@var{x0}) is
+non-zero, and positive real number @var{prec}, returns a real @var{x}
+for which @code{abs}(@var{f}(@var{x})) is less than @var{prec}; or
+returns @code{#f} if such a real can't be found.
+
+If @code{prec} is instead a negative integer, @code{newton:find-root}
+returns the result of -@var{prec} iterations.
+@end defun
+
+@noindent
+H. J. Orchard, @cite{The Laguerre Method for Finding the Zeros of
+Polynomials}, IEEE Transactions on Circuits and Systems, Vol. 36,
+No. 11, November 1989, pp 1377-1381.
+
+@quotation
+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.
+@end quotation
+
+
+@defun laguerre:find-root f df/dz ddf/dz^2 z0 prec
+Given complex valued procedure @var{f} of one (complex) argument, its
+derivative (with respect to its argument) @var{df/dx}, its second
+derivative @var{ddf/dz^2}, initial complex value @var{z0}, and positive
+real number @var{prec}, returns a complex number @var{z} for which
+@code{magnitude}(@var{f}(@var{z})) is less than @var{prec}; or returns
+@code{#f} if such a number can't be found.
+
+If @code{prec} is instead a negative integer, @code{laguerre:find-root}
+returns the result of -@var{prec} iterations.
+@end defun
+
+@defun laguerre:find-polynomial-root deg f df/dz ddf/dz^2 z0 prec
+Given polynomial procedure @var{f} of integer degree @var{deg} of one
+argument, its derivative (with respect to its argument) @var{df/dx}, its
+second derivative @var{ddf/dz^2}, initial complex value @var{z0}, and
+positive real number @var{prec}, returns a complex number @var{z} for
+which @code{magnitude}(@var{f}(@var{z})) is less than @var{prec}; or
+returns @code{#f} if such a number can't be found.
+
+If @code{prec} is instead a negative integer,
+@code{laguerre:find-polynomial-root} returns the result of -@var{prec}
+iterations.
+@end defun
+
+@node Commutative Rings, Determinant, Root Finding, Mathematical Packages
+@section 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 the user to use basic Scheme numeric
+functions with symbols and non-numeric elements of commutative rings.
+
+@code{(require 'commutative-ring)}
+@ftindex commutative-ring
+@cindex ring, commutative
+
+The @dfn{commutative-ring} package makes @code{+}, @code{-}, @code{*},
+@code{/}, and @code{^} @dfn{careful} in the sense that any non-numeric
+@cindex careful
+arguments which it cannot 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).
+
+@example
+(define a 'a)
+@dots{}
+(define z 'z)
+@end example
+Or just @code{(require 'self-set)}. Now for some sample expressions:
+
+@example
+(* (+ a b) (+ a b)) @result{} (+ (* 2 a b) (^ a 2) (^ b 2))
+(* (+ a b) (- a b)) @result{} (- (^ a 2) (^ b 2))
+(* (- a b) (- a b)) @result{} (- (+ (^ a 2) (^ b 2)) (* 2 a b))
+(* (- a b) (+ a b)) @result{} (- (^ a 2) (^ b 2))
+(/ (+ a b) (+ c d)) @result{} (+ (/ a (+ c d)) (/ b (+ c d)))
+(/ (+ a b) (- c d)) @result{} (+ (/ a (- c d)) (/ b (- c d)))
+(/ (- a b) (- c d)) @result{} (- (/ a (- c d)) (/ b (- c d)))
+(/ (- a b) (+ c d)) @result{} (- (/ a (+ c d)) (/ b (+ c d)))
+(^ (+ a b) 3) @result{} (+ (* 3 a (^ b 2)) (* 3 b (^ a 2)) (^ a 3) (^ b 3))
+(^ (+ a 2) 3) @result{} (+ 8 (* a 12) (* (^ a 2) 6) (^ a 3))
+@end example
+
+Use of this package is not restricted to simple arithmetic expressions:
+
+@example
+(require 'determinant)
+
+(determinant '((a b c) (d e f) (g h i))) @result{}
+(- (+ (* a e i) (* b f g) (* c d h)) (* a f h) (* b d i) (* c e g))
+@end example
+
+The @dfn{commutative-ring} package differs from other extension
+mechanisms in that it automatically, using properties true of all
+commutative rings, simplifies sum and product expressions containing
+non-numeric elements. One need only specify behavior for @code{+} or
+@code{*} for cases where expressions involving objects reduce to numbers
+or to expressions involving different non-numeric elements.
+
+Currently, only @code{+}, @code{-}, @code{*}, @code{/}, and @code{^}
+support non-numeric elements. Expressions with @code{-} are converted
+to equivalent expressions without @code{-}, so behavior for @code{-} is
+not defined separately. @code{/} expressions are handled similarly.
+
+This list might be extended to include @code{quotient}, @code{modulo},
+@code{remainder}, @code{lcm}, and @code{gcd}; but these work only for
+the more restrictive Euclidean (Unique Factorization) Domain.
+@cindex Unique Factorization
+@cindex Euclidean Domain
+
+@defun cring:define-rule op sub-op1 sub-op2 reduction
+Defines a rule for the case when the operation represented by symbol
+@var{op} is applied to lists whose @code{car}s are @var{sub-op1} and
+@var{sub-op2}, respectively. The argument @var{reduction} is a
+procedure accepting 2 arguments which will be lists whose @code{car}s
+are @var{sub-op1} and @var{sub-op2}.
+
+@defunx cring:define-rule op sub-op1 'identity reduction
+Defines a rule for the case when the operation represented by symbol
+@var{op} is applied to a list whose @code{car} is @var{sub-op1}, and
+some other argument. @var{Reduction} will be called with the list whose
+@code{car} is @var{sub-op1} and some other argument.
+
+If @var{reduction} returns @code{#f}, the reduction has failed and other
+reductions will be tried. If @var{reduction} returns a non-false value,
+that value will replace the two arguments in arithmetic (@code{+},
+@code{-}, and @code{*}) calculations involving non-numeric elements.
+
+The operations @code{+} and @code{*} are assumed commutative; hence both
+orders of arguments to @var{reduction} will be tried if necessary.
+
+The following rule is the built-in definition for distributing @code{*}
+over @code{+}.
+
+@example
+(cring:define-rule
+ '* '+ 'identity
+ (lambda (exp1 exp2)
+ (apply + (map (lambda (trm) (* trm exp2)) (cdr exp1))))))
+@end example
+@end defun
+
+@heading 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.
+
+@example
+(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))))
+@end example
+
+Define a procedure to multiply 2 non-numeric elements of the ring.
+Other multiplicatons are handled automatically. Objects for which rules
+have @emph{not} been defined are not changed.
+
+@example
+(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))))
+@end example
+
+Test the procedures to see if they work.
+
+@example
+;;; 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)) @result{} (m a b)
+@end example
+
+Then register the rule for multiplying type N objects by type N objects.
+
+@example
+(cring:define-rule '* 'N 'N N*N))
+@end example
+
+Now we are ready to compute!
+
+@example
+(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))
+@print{}
+(- (+ (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)))
+@end example
+
+@node Determinant, , Commutative Rings, Mathematical Packages
+@section Determinant
+
+@example
+(require 'determinant)
+(determinant '((1 2) (3 4))) @result{} -2
+(determinant '((1 2 3) (4 5 6) (7 8 9))) @result{} 0
+(determinant '((1 2 3 4) (5 6 7 8) (9 10 11 12))) @result{} 0
+@end example
+
+
+@node Database Packages, Other Packages, Mathematical Packages, Top
+@chapter Database Packages
+
+@menu
+* Base Table::
+* Relational Database:: 'relational-database
+* Weight-Balanced Trees:: 'wt-tree
+@end menu
+
+@node Base Table, Relational Database, Database Packages, Database Packages
@section Base Table
A base table implementation using Scheme association lists is available
as the value of the identifier @code{alist-table} after doing:
-@example
-(require 'alist-table)
-@end example
+@code{(require 'alist-table)}
+@ftindex alist-table
Association list base tables are suitable for small databases and
@@ -1650,6 +5556,7 @@ otherwise. For example:
@example
@group
(require 'alist-table)
+@ftindex alist-table
(define open-base (alist-table 'make-base))
make-base @result{} *a procedure*
(define foo (alist-table 'foo))
@@ -1785,21 +5692,51 @@ This procedure returns a list of @var{key}s which are elementwise
In the following functions, the @var{key} argument can always be assumed
to be the value returned by a call to a @emph{keyify} routine.
-@defun for-each-key handle procedure
+@noindent
+@cindex match-key
+@cindex match
+@cindex wild-card
+In contrast, a @var{match-key} argument is a list of length equal to the
+number of primary keys. The @var{match-key} restricts the actions of
+the table command to those records whose primary keys all satisfy the
+corresponding element of the @var{match-key} list.
+The elements and their actions are:
+
+@quotation
+@table @asis
+@item @code{#f}
+The false value matches any key in the corresponding position.
+@item 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 @code{#f} is not.
+@item other values
+Any other value matches only those keys @code{equal?} to it.
+@end table
+@end quotation
+
+@defun for-each-key handle procedure match-key
Calls @var{procedure} once with each @var{key} in the table opened in
-@var{handle} in an unspecified order. An unspecified value is returned.
+@var{handle} which satisfies @var{match-key} in an unspecified order.
+An unspecified value is returned.
@end defun
-@defun map-key handle procedure
+@defun map-key handle procedure match-key
Returns a list of the values returned by calling @var{procedure} once
-with each @var{key} in the table opened in @var{handle} in an
-unspecified order.
+with each @var{key} in the table opened in @var{handle} which satisfies
+@var{match-key} in an unspecified order.
@end defun
-@defun ordered-for-each-key handle procedure
+@defun ordered-for-each-key handle procedure match-key
Calls @var{procedure} once with each @var{key} in the table opened in
-@var{handle} in the natural order for the types of the primary key
-fields of that table. An unspecified value is returned.
+@var{handle} which satisfies @var{match-key} in the natural order for
+the types of the primary key fields of that table. An unspecified value
+is returned.
+@end defun
+
+@defun delete* handle match-key
+Removes all rows which satisfy @var{match-key} from the table opened in
+@var{handle}. An unspecified value is returned.
@end defun
@defun present? handle key
@@ -1852,10 +5789,11 @@ Objects suitable for passing as the @var{base-id} parameter to
@code{base-id}.
@end table
-@node Relational Database, Weight-Balanced Trees, Base Table, Data Structures
+@node Relational Database, Weight-Balanced Trees, Base Table, Database Packages
@section Relational Database
@code{(require 'relational-database)}
+@ftindex relational-database
This package implements a database system inspired by the Relational
Model (@cite{E. F. Codd, A Relational Model of Data for Large Shared
@@ -1994,6 +5932,7 @@ could be created from the procedure returned by
@example
(require 'alist-table)
+@ftindex alist-table
(define relational-alist-system
(make-relational-system alist-table))
(define create-alist-database
@@ -2133,15 +6072,6 @@ the table with the symbol name of the operation. For example:
@end example
@noindent
-Operations on a single column of a table are retrieved by giving the
-column name as the second argument to the methods procedure. For
-example:
-
-@example
-(define column-ids ((telephone-table-desc 'get* 'column-number)))
-@end example
-
-@noindent
Some operations described below require primary key arguments. Primary
keys arguments are denoted @var{key1} @var{key2} @dots{}. It is an
error to call an operation for a table which takes primary key arguments
@@ -2150,72 +6080,164 @@ with the wrong number of primary keys for that table.
@noindent
The term @dfn{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 @code{#f}. Primary keys may not
+table. Missing values appear as @code{#f}. Primary keys must not
be missing.
-@defun get key1 key2 @dots{}
-Returns the value for the specified column of the row associated with
-primary keys @var{key1}, @var{key2} @dots{} if it exists, or @code{#f}
-otherwise.
+@defun get column-name
+Returns a procedure of arguments @var{key1} @var{key2} @dots{} which
+returns the value for the @var{column-name} column of the row associated
+with primary keys @var{key1}, @var{key2} @dots{} if that row exists in
+the table, or @code{#f} otherwise.
+
+@example
+((plat 'get 'processor) 'djgpp) @result{} i386
+((plat 'get 'processor) 'be-os) @result{} #f
+@end example
+
+@defunx get* column-name
+Returns a procedure of optional arguments @var{match-key1} @dots{} which
+returns a list of the values for the specified column for all rows in
+this table. The optional @var{match-key1} @dots{} arguments restrict
+actions to a subset of the table. See the match-key description below
+for details.
+
+@example
+((plat 'get* 'processor)) @result{}
+(i386 8086 i386 8086 i386 i386 8086 m68000
+ m68000 m68000 m68000 m68000 powerpc)
-@defunx get*
-Returns a list of the values for the specified column for all rows in
-this table.
+((plat 'get* 'processor) #f) @result{}
+(i386 8086 i386 8086 i386 i386 8086 m68000
+ m68000 m68000 m68000 m68000 powerpc)
-@defunx row:retrieve key1 key2 @dots{}
-Returns the row associated with primary keys @var{key1}, @var{key2}
+(define (a-key? key)
+ (char=? #\a (string-ref (symbol->string key) 0)))
+
+((plat 'get* 'processor) a-key?) @result{}
+(m68000 m68000 m68000 m68000 m68000 powerpc)
+
+((plat 'get* 'name) a-key?) @result{}
+(atari-st-turbo-c atari-st-gcc amiga-sas/c-5.10
+ amiga-aztec amiga-dice-c aix)
+@end example
+@end defun
+
+@defun row:retrieve
+Returns a procedure of arguments @var{key1} @var{key2} @dots{} which
+returns the row associated with primary keys @var{key1}, @var{key2}
@dots{} if it exists, or @code{#f} otherwise.
+@example
+((plat 'row:retrieve) 'linux) @result{} (linux i386 linux gcc)
+((plat 'row:retrieve) 'multics) @result{} #f
+@end example
+
@defunx row:retrieve*
-Returns a list of all rows in this table.
+Returns a procedure of optional arguments @var{match-key1} @dots{} which
+returns a list of all rows in this table. The optional @var{match-key1}
+@dots{} arguments restrict actions to a subset of the table. See the
+match-key description below for details.
@end defun
-@defun row:remove key1 key2 @dots{}
-Removes and returns the row associated with primary keys @var{key1},
+@example
+((plat 'row:retrieve*) a-key?) @result{}
+((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 -))
+@end example
+
+@defun row:remove
+Returns a procedure of arguments @var{key1} @var{key2} @dots{} which
+removes and returns the row associated with primary keys @var{key1},
@var{key2} @dots{} if it exists, or @code{#f} otherwise.
@defunx row:remove*
-Removes and returns a list of all rows in this table.
+Returns a procedure of optional arguments @var{match-key1} @dots{} which
+removes and returns a list of all rows in this table. The optional
+@var{match-key1} @dots{} arguments restrict actions to a subset of the
+table. See the match-key description below for details.
@end defun
-@defun row:delete key1 key2 @dots{}
-Deletes the row associated with primary keys @var{key1}, @var{key2}
+@defun row:delete
+Returns a procedure of arguments @var{key1} @var{key2} @dots{} which
+deletes the row associated with primary keys @var{key1}, @var{key2}
@dots{} if it exists. The value returned is unspecified.
@defunx row:delete*
-Deletes all rows in this table. The value returned is unspecified. The
-descriptor table and catalog entry for this table are not affected.
+Returns a procedure of optional arguments @var{match-key1} @dots{} which
+Deletes all rows from this table. The optional @var{match-key1} @dots{}
+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.
@end defun
-@defun row:update row
-Adds the row, @var{row}, to this table. If a row for the primary key(s)
-specified by @var{row} already exists in this table, it will be
-overwritten. The value returned is unspecified.
+@defun row:update
+Returns a procedure of one argument, @var{row}, which adds the row,
+@var{row}, to this table. If a row for the primary key(s) specified by
+@var{row} already exists in this table, it will be overwritten. The
+value returned is unspecified.
-@defunx row:update* rows
-Adds each row in the list @var{rows}, to this table. If a row for the
-primary key specified by an element of @var{rows} already exists in this
-table, it will be overwritten. The value returned is unspecified.
+@defunx row:update*
+Returns a procedure of one argument, @var{rows}, which adds each row in
+the list of rows, @var{rows}, to this table. If a row for the primary
+key specified by an element of @var{rows} already exists in this table,
+it will be overwritten. The value returned is unspecified.
@end defun
-@defun row:insert row
+@defun row:insert
Adds the row @var{row} to this table. If a row for the primary key(s)
specified by @var{row} already exists in this table an error is
signaled. The value returned is unspecified.
-@defunx row:insert* rows
-Adds each row in the list @var{rows}, to this table. If a row for the
-primary key specified by an element of @var{rows} already exists in this
-table, an error is signaled. The value returned is unspecified.
+@defunx row:insert*
+Returns a procedure of one argument, @var{rows}, which adds each row in
+the list of rows, @var{rows}, to this table. If a row for the primary
+key specified by an element of @var{rows} already exists in this table,
+an error is signaled. The value returned is unspecified.
@end defun
-@defun for-each-row proc
-Calls @var{proc} with each @var{row} in this table in the natural
-ordering for the primary key types. @emph{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.
+@defun for-each-row
+Returns a procedure of arguments @var{proc} @var{match-key1} @dots{}
+which calls @var{proc} with each @var{row} in this table in the
+(implementation-dependent) natural ordering for rows. The optional
+@var{match-key1} @dots{} arguments restrict actions to a subset of the
+table. See the match-key description below for details.
+
+@emph{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.
@end defun
+@noindent
+@cindex match-keys
+The (optional) @var{match-key1} @dots{} 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 @var{match-key} arguments
+default to @code{#f}.
+
+@noindent
+The @var{match-key1} @dots{} restrict the actions of the table command
+to those records whose primary keys each satisfy the corresponding
+@var{match-key} argument. The arguments and their actions are:
+
+@quotation
+@table @asis
+@item @code{#f}
+The false value matches any key in the corresponding position.
+@item 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 @code{#f} is not.
+@item other values
+Any other value matches only those keys @code{equal?} to it.
+@end table
+@end quotation
+
@defun close-table
Subsequent operations to this table will signal an error.
@end defun
@@ -2334,12 +6356,12 @@ The types for which support is planned are:
@node Unresolved Issues, Database Utilities, Catalog Representation, Relational Database
@subsection Unresolved Issues
-Although @file{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.
+Although @file{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
@@ -2382,17 +6404,18 @@ 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 and so would require
-locks in order to operate properly in a multiprocess environment. Are
-all examples of utilities whose state should not part of transactions
-also non-reentrant? If so, perhaps suspending transaction capture for
-the duration of locks would fix it.
+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.
@end table
@node Database Utilities, , Unresolved Issues, Relational Database
@subsection Database Utilities
@code{(require 'database-utilities)}
+@ftindex database-utilities
@noindent
This enhancement wraps a utility layer on @code{relational-database}
@@ -2465,7 +6488,8 @@ PRI index uint
name symbol
arity parameter-arity
domain domain
- default expression
+ defaulter expression
+ expander expression
documentation string
@end group
@end example
@@ -2494,13 +6518,12 @@ parameters.
The @code{domain} field specifies the domain which a parameter or
parameters in the @code{index}th field must satisfy.
-The @code{default} field is an expression whose value is either
-@code{#f} or a procedure of no arguments which returns a parameter or
-parameter list as appropriate. If the expression's value is @code{#f}
-then no default is appropriate for this parameter. Note that since the
-@code{default} procedure is called every time a default parameter is
-needed for this column, @dfn{sticky} defaults can be implemented using
-shared state with the domain-integrity-rule.
+The @code{defaulter} field is an expression whose value is either
+@code{#f} or a procedure of one argument (the parameter-list) which
+returns a @emph{list} of the default value or values as appropriate.
+Note that since the @code{defaulter} procedure is called every time a
+default parameter is needed for this column, @dfn{sticky} defaults can
+be implemented using shared state with the domain-integrity-rule.
@subsubheading Invoking Commands
@@ -2544,9 +6567,13 @@ the @code{index} field of the @var{command}'s parameter-table.
A list of the arities of each parameter. Corresponds to the
@code{arity} field of the @var{command}'s parameter-table. For a
description of @code{arity} see table above.
-@item defaults
-A list of the defaults for each parameter. Corresponds to
-the @code{defaults} field of the @var{command}'s parameter-table.
+@item types
+A list of the type name of each parameter. Correspnds to the
+@code{type-id} field of the contents of the @code{domain} of the
+@var{command}'s parameter-table.
+@item defaulters
+A list of the defaulters for each parameter. Corresponds to
+the @code{defaulters} field of the @var{command}'s parameter-table.
@item 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
@@ -2564,8 +6591,13 @@ arguments from a @code{getopt} style argument list (@pxref{Getopt}).
@example
(require 'database-utilities)
+@ftindex database-utilities
+(require 'fluid-let)
+@ftindex fluid-let
(require 'parameters)
+@ftindex parameters
(require 'getopt)
+@ftindex getopt
(define my-rdb (create-database #f 'alist-table))
@@ -2573,13 +6605,29 @@ arguments from a @code{getopt} style argument list (@pxref{Getopt}).
'(foo-params
*parameter-columns*
*parameter-columns*
- ((1 first-argument single string "hithere" "first argument")
- (2 flag boolean boolean #f "a flag")))
+ ((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))
- (("l" 1)
- ("a" 2)))
+ (("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)
@@ -2589,7 +6637,7 @@ arguments from a @code{getopt} style argument list (@pxref{Getopt}).
((foo
foo-params
foo-pnames
- (lambda (rdb) (lambda (foo aflag) (print foo aflag)))
+ (lambda (rdb) (lambda args (print args)))
"test command arguments"))))
(define (dbutil:serve-command-line rdb command-table
@@ -2598,17 +6646,56 @@ arguments from a @code{getopt} style argument list (@pxref{Getopt}).
((make-command-server rdb command-table)
command
(lambda (comname comval options positions
- arities types defaults dirs aliases)
- (apply comval (getopt->arglist argc argv options positions
- arities types defaults dirs aliases)))))
-
-(define (test)
- (set! *optind* 1)
- (dbutil:serve-command-line
- my-rdb 'my-commands 'foo 4 '("dummy" "-l" "foo" "-a")))
-(test)
-@print{}
-"foo" #t
+ 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 @result{} "
+ (call-with-output-string (lambda (pt) (write (cons 'cmd opts) pt)))
+ ;;(apply string-append (map (lambda (x) (string-append x " ")) opts))
+ )
+ (set! opts (cons "cmd" opts))
+ (force-output)
+ (dbutil:serve-command-line
+ my-rdb 'my-commands 'foo (length opts) opts)))
+
+(cmd) @result{} ("str" () (symb) () #f)
+(cmd "-f") @result{} ("str" () (symb) () #t)
+(cmd "--flag") @result{} ("str" () (symb) () #t)
+(cmd "-o177") @result{} ("str" () (symb) (177) #f)
+(cmd "-o" "177") @result{} ("str" () (symb) (177) #f)
+(cmd "--optional" "621") @result{} ("str" () (symb) (621) #f)
+(cmd "--optional=621") @result{} ("str" () (symb) (621) #f)
+(cmd "-s" "speciality") @result{} ("speciality" () (symb) () #f)
+(cmd "-sspeciality") @result{} ("speciality" () (symb) () #f)
+(cmd "--single" "serendipity") @result{} ("serendipity" () (symb) () #f)
+(cmd "--single=serendipity") @result{} ("serendipity" () (symb) () #f)
+(cmd "-n" "gravity" "piety") @result{} ("str" () (piety gravity) () #f)
+(cmd "-ngravity" "piety") @result{} ("str" () (piety gravity) () #f)
+(cmd "--nary" "chastity") @result{} ("str" () (chastity) () #f)
+(cmd "--nary=chastity" "") @result{} ("str" () ( chastity) () #f)
+(cmd "-N" "calamity") @result{} ("str" () (calamity) () #f)
+(cmd "-Ncalamity") @result{} ("str" () (calamity) () #f)
+(cmd "--nary1" "surety") @result{} ("str" () (surety) () #f)
+(cmd "--nary1=surety") @result{} ("str" () (surety) () #f)
+(cmd "-N" "levity" "fealty") @result{} ("str" () (fealty levity) () #f)
+(cmd "-Nlevity" "fealty") @result{} ("str" () (fealty levity) () #f)
+(cmd "--nary1" "surety" "brevity") @result{} ("str" () (brevity surety) () #f)
+(cmd "--nary1=surety" "brevity") @result{} ("str" () (brevity surety) () #f)
+(cmd "-?")
+@print{}
+Usage: cmd [OPTION ARGUMENT ...] ...
+
+ -f, --flag
+ -o, --optional[=]<number>
+ -n, --nary[=]<symbols> ...
+ -N, --nary1[=]<symbols> ...
+ -s, --single[=]<string>
+
+ERROR: getopt->parameter-list "unrecognized option" "-?"
@end example
Some commands are defined in all extended relational-databases. The are
@@ -2620,7 +6707,33 @@ the domains table associated with key @code{(car @var{domain-row})} and
returns @code{#t}. Otherwise returns @code{#f}.
For the fields and layout of the domain table, @xref{Catalog
-Representation}
+Representation}. Currently, these fields are
+@itemize @bullet
+@item
+domain-name
+@item
+foreign-table
+@item
+domain-integrity-rule
+@item
+type-id
+@item
+type-param
+@end itemize
+
+The following example adds 3 domains to the @samp{build} database.
+@samp{Optstring} is either a string or @code{#f}. @code{filename} is a
+string and @code{build-whats} is a symbol.
+
+@example
+(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)))
+@end example
@end defun
@defun delete-domain domain-name
@@ -2633,7 +6746,7 @@ Returns a procedure to check an argument for conformance to domain
@var{domain}.
@end defun
-@subheading Defining Tables
+@subsubheading Defining Tables
@deffn Procedure define-tables rdb spec-0 @dots{}
Adds tables as specified in @var{spec-0} @dots{} to the open
@@ -2666,8 +6779,8 @@ or
where @r{<column-name>} is the column name, @r{<domain>} is the domain
of the column, and @r{<column-integrity-rule>} is an expression whose
-value is a procedure of one argument (and returns non-@code{#f} to
-signal an error).
+value is a procedure of one argument (which returns @code{#f} to signal
+an error).
If @r{<domain>} is not a defined domain name and it matches the name of
this table or an already defined (in one of @var{spec-0} @dots{}) single
@@ -2723,7 +6836,7 @@ The procedure to call to actually print.
The report is prepared as follows:
-@itemize
+@itemize @bullet
@item
@code{Format} (@pxref{Format}) is called with the @code{header} field
and the (list of) @code{column-names} of the table.
@@ -2759,6 +6872,7 @@ database is then closed and reopened.
@example
(require 'database-utilities)
+@ftindex database-utilities
(define my-rdb (create-database "foo.db" 'alist-table))
(define-tables my-rdb
@@ -2814,10 +6928,12 @@ database is then closed and reopened.
Welcome
@end example
-@node Weight-Balanced Trees, Structures, Relational Database, Data Structures
+
+@node Weight-Balanced Trees, , Relational Database, Database Packages
@section Weight-Balanced Trees
@code{(require 'wt-tree)}
+@ftindex wt-tree
@cindex trees, balanced binary
@cindex balanced binary trees
@@ -3323,2278 +7439,1093 @@ operation is equivalent to
@end deffn
+@node Other Packages, About SLIB, Database Packages, Top
+@chapter Other Packages
-@node Structures, , Weight-Balanced Trees, Data Structures
-@section Structures
-
-@code{(require 'struct)} (uses defmacros)
-
-@code{defmacro}s which implement @dfn{records} from the book
-@cite{Essentials of Programming Languages} by Daniel P. Friedman, M.
-Wand and C.T. Haynes. Copyright 1992 Jeff Alexander, Shinnder Lee, and
-Lewis Patterson@refill
-
-Matthew McDonald <mafm@@cs.uwa.edu.au> added field setters.
-
-@defmac define-record tag (var1 var2 @dots{})
-Defines several functions pertaining to record-name @var{tag}:
-
-@defun make-@var{tag} var1 var2 @dots{}
-@end defun
-@defun @var{tag}? obj
-@end defun
-@defun @var{tag}->var1 obj
-@end defun
-@defun @var{tag}->var2 obj
-@end defun
-@dots{}
-@defun set-@var{@var{tag}}-var1! obj val
-@end defun
-@defun set-@var{@var{tag}}-var2! obj val
-@end defun
-@dots{}
+@menu
+* Data Structures:: Various data structures.
+* Procedures:: Miscellaneous utility procedures.
+* Standards Support:: Support for Scheme Standards.
+* Session Support:: REPL and Debugging.
+* Extra-SLIB Packages::
+@end menu
-Here is an example of its use.
-@example
-(define-record term (operator left right))
-@result{} #<unspecified>
-(define foo (make-term 'plus 1 2))
-@result{} foo
-(term-left foo)
-@result{} 1
-(set-term-left! foo 2345)
-@result{} #<unspecified>
-(term-left foo)
-@result{} 2345
-@end example
-@end defmac
+@node Data Structures, Procedures, Other Packages, Other Packages
+@section Data Structures
-@defmac variant-case exp (tag (var1 var2 @dots{}) body) @dots{}
-executes the following for the matching clause:
-@example
-((lambda (@var{var1} @var{var} @dots{}) @var{body})
- (@var{tag->var1} @var{exp})
- (@var{tag->var2} @var{exp}) @dots{})
-@end example
-@end defmac
-@node Macros, Numerics, Data Structures, Top
-@chapter Macros
@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 @xref{Structures}.
-
-* Fluid-Let:: 'fluid-let
-* Yasos:: 'yasos, 'oop, 'collect
+* 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
+* Priority Queues:: 'priority-queue
+* Queues:: 'queue
+* Records:: 'record
+* Structures:: 'struct, 'structure
@end menu
-@node Defmacro, R4RS Macros, Macros, Macros
-@section Defmacro
-Defmacros are supported by all implementations.
-@c See also @code{gentemp}, in @ref{Macros}.
-@defun gentemp
-Returns a new (interned) symbol each time it is called. The symbol
-names are implementation-dependent
-@lisp
-(gentemp) @result{} scm:G0
-(gentemp) @result{} scm:G1
-@end lisp
-@end defun
+@node Arrays, Array Mapping, Data Structures, Data Structures
+@subsection Arrays
-@defun defmacro:eval e
-Returns the @code{slib:eval} of expanding all defmacros in scheme
-expression @var{e}.
-@end defun
+@code{(require 'array)}
+@ftindex array
-@defun defmacro:load filename
-@var{filename} should be a string. If filename names an existing file,
-the @code{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 @code{macro:load} procedure does not affect the values
-returned by @code{current-input-port} and
-@code{current-output-port}.@refill
+@defun array? obj
+Returns @code{#t} if the @var{obj} is an array, and @code{#f} if not.
@end defun
-@defun defmacro? sym
-Returns @code{#t} if @var{sym} has been defined by @code{defmacro},
-@code{#f} otherwise.
+@defun make-array initial-value bound1 bound2 @dots{}
+Creates and returns an array that has as many dimensins as there are
+@var{bound}s and fills it with @var{initial-value}.@refill
@end defun
-@defun macroexpand-1 form
-@defunx macroexpand form
-If @var{form} is a macro call, @code{macroexpand-1} will expand the
-macro call once and return it. A @var{form} is considered to be a macro
-call only if it is a cons whose @code{car} is a symbol for which a
-@code{defmacr} has been defined.
+When constructing an array, @var{bound} is either an inclusive range of
+indices expressed as a two element list, or an upper bound expressed as
+a single integer. So@refill
+@lisp
+(make-array 'foo 3 3) @equiv{} (make-array 'foo '(0 2) '(0 2))
+@end lisp
-@code{macroexpand} is similar to @code{macroexpand-1}, but repeatedly
-expands @var{form} until it is no longer a macro call.
+@defun make-shared-array array mapper bound1 bound2 @dots{}
+@code{make-shared-array} can be used to create shared subarrays of other
+arrays. The @var{mapper} is a function that translates coordinates in
+the new array into coordinates in the old array. A @var{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:@refill
+@lisp
+(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)
+ @result{} FOO
+(define freds-center
+ (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j)))
+ 2 2))
+(array-ref freds-center 0 0)
+ @result{} FOO
+@end lisp
@end defun
-@defmac defmacro name lambda-list form @dots{}
-When encountered by @code{defmacro:eval}, @code{defmacro:macroexpand*},
-or @code{defmacro:load} defines a new macro which will henceforth be
-expanded when encountered by @code{defmacro:eval},
-@code{defmacro:macroexpand*}, or @code{defmacro:load}.
-@end defmac
-
-@subsection Defmacroexpand
-@code{(require 'defmacroexpand)}
-
-@defun defmacro:expand* e
-Returns the result of expanding all defmacros in scheme expression
-@var{e}.
+@defun array-rank obj
+Returns the number of dimensions of @var{obj}. If @var{obj} is not an
+array, 0 is returned.
@end defun
-@node R4RS Macros, Macro by Example, Defmacro, Macros
-@section R4RS Macros
-
-@code{(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:
-
-@defun macro:expand sexpression
-Takes an R4RS expression, macro-expands it, and returns the result of
-the macro expansion.
+@defun array-shape array
+@code{array-shape} returns a list of inclusive bounds. So:
+@lisp
+(array-shape (make-array 'foo 3 5))
+ @result{} ((0 2) (0 4))
+@end lisp
@end defun
-@defun macro:eval sexpression
-Takes an R4RS expression, macro-expands it, evals the result of the
-macro expansion, and returns the result of the evaluation.
+@defun array-dimensions array
+@code{array-dimensions} is similar to @code{array-shape} but replaces
+elements with a 0 minimum with one greater than the maximum. So:
+@lisp
+(array-dimensions (make-array 'foo 3 5))
+ @result{} (3 5)
+@end lisp
@end defun
-@deffn Procedure macro:load filename
-@var{filename} should be a string. If filename names an existing file,
-the @code{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
-@code{macro:load} procedure does not affect the values returned by
-@code{current-input-port} and @code{current-output-port}.@refill
+@deffn Procedure array-in-bounds? array index1 index2 @dots{}
+Returns @code{#t} if its arguments would be acceptable to
+@code{array-ref}.
@end deffn
-@node Macro by Example, Macros That Work, R4RS Macros, Macros
-@section Macro by Example
-
-@code{(require 'macro-by-example)}
-
-A vanilla implementation of @cite{Macro by Example} (Eugene Kohlbecker,
-R4RS) by Dorai Sitaram, (dorai@@cs.rice.edu) using @code{defmacro}.
-
-@itemize @bullet
-
-@item
-generating hygienic global @code{define-syntax} Macro-by-Example macros
-@strong{cheaply}.
-
-@item
-can define macros which use @code{...}.
-
-@item
-needn't worry about a lexical variable in a macro definition
-clashing with a variable from the macro use context
-
-@item
-don't suffer the overhead of redefining the repl if @code{defmacro}
-natively supported (most implementations)
-
-@end itemize
-@subsection Caveat
-These macros are not referentially transparent (@pxref{Macros, , ,r4rs,
-Revised(4) Scheme}). Lexically scoped macros (i.e., @code{let-syntax}
-and @code{letrec-syntax}) are not supported. In any case, the problem
-of referential transparency gains poignancy only when @code{let-syntax}
-and @code{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 @cite{r4rs} macro functionality, look to the
-more featureful (but also more expensive) versions of syntax-rules
-available in slib @ref{Macros That Work}, @ref{Syntactic Closures}, and
-@ref{Syntax-Case Macros}.
-
-@defmac define-syntax keyword transformer-spec
-The @var{keyword} is an identifier, and the @var{transformer-spec}
-should be an instance of @code{syntax-rules}.
+@defun array-ref array index1 index2 @dots{}
+Returns the element at the @code{(@var{index1}, @var{index2})} element
+in @var{array}.@refill
+@end defun
-The top-level syntactic environment is extended by binding the
-@var{keyword} to the specified transformer.
+@deffn Procedure array-set! array new-value index1 index2 @dots{}
+@end deffn
-@example
-(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 ...)))))
-@end example
-@end defmac
+@defun array-1d-ref array index
+@defunx array-2d-ref array index index
+@defunx array-3d-ref array index index index
+@end defun
-@defmac syntax-rules literals syntax-rule @dots{}
-@var{literals} is a list of identifiers, and each @var{syntax-rule}
-should be of the form
+@deffn Procedure array-1d-set! array new-value index
+@deffnx Procedure array-2d-set! array new-value index index
+@deffnx Procedure array-3d-set! array new-value index index index
+@end deffn
-@code{(@var{pattern} @var{template})}
+The functions are just fast versions of @code{array-ref} and
+@code{array-set!} that take a fixed number of arguments, and perform no
+bounds checking.@refill
-where the @var{pattern} and @var{template} are as in the grammar above.
+If you comment out the bounds checking code, this is about as efficient
+as you could ask for without help from the compiler.
-An instance of @code{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
-@code{syntax-rules} is matched against the patterns contained in the
-@var{syntax-rule}s, beginning with the leftmost @var{syntax-rule}.
-When a match is found, the macro use is trancribed hygienically
-according to the template.
+An exercise left to the reader: implement the rest of APL.
-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.
-@end defmac
-@node Macros That Work, Syntactic Closures, Macro by Example, Macros
-@section Macros That Work
-@code{(require 'macros-that-work)}
+@node Array Mapping, Association Lists, Arrays, Data Structures
+@subsection Array Mapping
-@cite{Macros That Work} differs from the other R4RS macro
-implementations in that it does not expand derived expression types to
-primitive expression types.
+@code{(require 'array-for-each)}
+@ftindex array-for-each
-@defun macro:expand expression
-@defunx macwork:expand expression
-Takes an R4RS expression, macro-expands it, and returns the result of
-the macro expansion.
+@defun array-map! array0 proc array1 @dots{}
+@var{array1}, @dots{} must have the same number of dimensions as
+@var{array0} and have a range for each index which includes the range
+for the corresponding index in @var{array0}. @var{proc} is applied to
+each tuple of elements of @var{array1} @dots{} and the result is stored
+as the corresponding element in @var{array0}. The value returned is
+unspecified. The order of application is unspecified.
@end defun
-@defun macro:eval expression
-@defunx macwork:eval expression
-@code{macro:eval} returns the value of @var{expression} in the current
-top level environment. @var{expression} can contain macro definitions.
-Side effects of @var{expression} will affect the top level
-environment.@refill
+@defun array-for-each @var{proc} @var{array0} @dots{}
+@var{proc} is applied to each tuple of elements of @var{array0} @dots{}
+in row-major order. The value returned is unspecified.
@end defun
-@deffn Procedure macro:load filename
-@deffnx Procedure macwork:load filename
-@var{filename} should be a string. If filename names an existing file,
-the @code{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
-@code{macro:load} procedure does not affect the values returned by
-@code{current-input-port} and @code{current-output-port}.@refill
-@end deffn
-
-References:
-
-The @cite{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.@refill
-
-@center Macros That Work. Clinger and Rees. POPL '91.
+@defun array-indexes @var{array}
+Returns an array of lists of indexes for @var{array} such that, if
+@var{li} is a list of indexes for which @var{array} is defined, (equal?
+@var{li} (apply array-ref (array-indexes @var{array}) @var{li})).
+@end defun
-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.
+@defun array-index-map! array proc
+applies @var{proc} to the indices of each element of @var{array} in
+turn, storing the result in the corresponding element. The value
+returned and the order of application are unspecified.
+One can implement @var{array-indexes} as
@example
-transformer spec @expansion{} (syntax-rules literals rules)
-
-rules @expansion{} ()
- | (rule . rules)
-
-rule @expansion{} (pattern template)
-
-pattern @expansion{} 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 @expansion{} pattern_var
- | symbol
- | ()
- | (template2 . template2)
- | #(template*) ; extends R4RS
- | pattern_datum
-
-template2 @expansion{} template
- | ellipsis_template
-
-pattern_datum @expansion{} string ; no vector
- | character
- | boolean
- | number
-
-ellipsis_pattern @expansion{} pattern ...
-
-ellipsis_template @expansion{} template ...
-
-pattern_var @expansion{} symbol ; not in literals
-
-literals @expansion{} ()
- | (symbol . literals)
+(define (array-indexes array)
+ (let ((ra (apply make-array #f (array-shape array))))
+ (array-index-map! ra (lambda x x))
+ ra))
@end example
-
-@subsection Definitions
-
-@table @asis
-
-@item Scope of an ellipsis
-Within a pattern or template, the scope of an ellipsis (@code{...}) is
-the pattern or template that appears to its left.
-
-@item Rank of a pattern variable
-The rank of a pattern variable is the number of ellipses within whose
-scope it appears in the pattern.
-
-@item Rank of a subtemplate
-The rank of a subtemplate is the number of ellipses within whose scope
-it appears in the template.
-
-@item 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.
-
-@item Variables bound by a pattern
-The variables bound by a pattern are the pattern variables that appear
-within it.
-
-@item Referenced variables of a subtemplate
-The referenced variables of a subtemplate are the pattern variables that
-appear within it.
-
-@item 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.
-
-@end table
-
-@subsection 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 @var{rule} is
-
+Another example:
@example
-rule @expansion{} (pattern template inserted)
-
-pattern @expansion{} pattern_var
- | symbol
- | ()
- | (pattern . pattern)
- | ellipsis_pattern
- | #(pattern)
- | pattern_datum
-
-template @expansion{} pattern_var
- | symbol
- | ()
- | (template2 . template2)
- | #(pattern)
- | pattern_datum
-
-template2 @expansion{} template
- | ellipsis_template
-
-pattern_datum @expansion{} string
- | character
- | boolean
- | number
-
-pattern_var @expansion{} #(V symbol rank)
-
-ellipsis_pattern @expansion{} #(E pattern pattern_vars)
-
-ellipsis_template @expansion{} #(E template pattern_vars)
-
-inserted @expansion{} ()
- | (symbol . inserted)
-
-pattern_vars @expansion{} ()
- | (pattern_var . pattern_vars)
-
-rank @expansion{} exact non-negative integer
+(define (apl:index-generator n)
+ (let ((v (make-uniform-vector n 1)))
+ (array-index-map! v (lambda (i) i))
+ v))
@end example
-
-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.
-
-
-
-
-
-@node Syntactic Closures, Syntax-Case Macros, Macros That Work, Macros
-@section Syntactic Closures
-
-@code{(require 'syntactic-closures)}
-
-@defun macro:expand expression
-@defunx synclo:expand expression
-Returns scheme code with the macros and derived expression types of
-@var{expression} expanded to primitive expression types.@refill
@end defun
-@defun macro:eval expression
-@defunx synclo:eval expression
-@code{macro:eval} returns the value of @var{expression} in the current
-top level environment. @var{expression} can contain macro definitions.
-Side effects of @var{expression} will affect the top level
-environment.@refill
+@defun array-copy! source destination
+Copies every element from vector or array @var{source} to the
+corresponding element of @var{destination}. @var{destination} must have
+the same rank as @var{source}, and be at least as large in each
+dimension. The order of copying is unspecified.
@end defun
-@deffn Procedure macro:load filename
-@deffnx Procedure synclo:load filename
-@var{filename} should be a string. If filename names an existing file,
-the @code{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 @code{macro:load} procedure does not affect the values returned by
-@code{current-input-port} and @code{current-output-port}.@refill
-@end deffn
-
-@subsection Syntactic Closure Macro Facility
-
-@center A Syntactic Closures Macro Facility
-@center by Chris Hanson
-@center 9 November 1991
-
-This document describes @dfn{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
-@cite{Revised^4 Report on Scheme.} This document is an addendum to that
-report.
-
-The syntactic closures facility extends the BNF rule for
-@var{transformer spec} to allow a new keyword that introduces a
-low-level macro transformer:@refill
-@example
-@var{transformer spec} := (transformer @var{expression})
-@end example
-
-Additionally, the following procedures are added:
-@lisp
-make-syntactic-closure
-capture-syntactic-environment
-identifier?
-identifier=?
-@end lisp
-
-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
-@dfn{identifiers}, which extend the syntactic closure mechanism to be
-compatible with @code{syntax-rules}.@refill
-
-@subsubsection Terminology
-
-This section defines the concepts and data types used by the syntactic
-closures facility.
-
-@itemize
-
-@item @dfn{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 @code{set!} special form is also a form. Examples of
-forms:@refill
-@lisp
-17
-#t
-car
-(+ x 4)
-(lambda (x) x)
-(define pi 3.14159)
-if
-define
-@end lisp
-
-@item An @dfn{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
-@code{symbol?}. Macro transformers rarely distinguish symbols from
-aliases, referring to both as identifiers.@refill
-
-@item A @dfn{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.@refill
-
-@item A @dfn{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.@refill
-
-@end itemize
-
-@subsubsection Transformer Definition
-
-This section describes the @code{transformer} special form and the
-procedures @code{make-syntactic-closure} and
-@code{capture-syntactic-environment}.@refill
-
-@deffn Syntax transformer expression
-
-Syntax: It is an error if this syntax occurs except as a
-@var{transformer spec}.@refill
-
-Semantics: The @var{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
-@code{transformer} expression appears (for example,
-@code{let-syntax}).@refill
-
-A @dfn{macro transformer} is a procedure that takes two arguments, a
-form and a syntactic environment, and returns a new form. The first
-argument, the @dfn{input form}, is the form in which the macro keyword
-occurred. The second argument, the @dfn{usage environment}, is the
-syntactic environment in which the input form occurred. The result of
-the transformer, the @dfn{output form}, is automatically closed in the
-@dfn{transformer environment}, which is the syntactic environment in
-which the @code{transformer} expression occurred.@refill
-
-For example, here is a definition of a push macro using
-@code{syntax-rules}:@refill
-@lisp
-(define-syntax push
- (syntax-rules ()
- ((push item list)
- (set! list (cons item list)))))
-@end lisp
-
-Here is an equivalent definition using @code{transformer}:
-@lisp
-(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))))))
-@end lisp
-
-In this example, the identifiers @code{set!} and @code{cons} are closed
-in the transformer environment, and thus will not be affected by the
-meanings of those identifiers in the usage environment
-@code{env}.@refill
-
-Some macros may be non-hygienic by design. For example, the following
-defines a loop macro that implicitly binds @code{exit} to an escape
-procedure. The binding of @code{exit} is intended to capture free
-references to @code{exit} in the body of the loop, so @code{exit} must
-be left free when the body is closed:@refill
-@lisp
-(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))))))))
-@end lisp
-To assign meanings to the identifiers in a form, use
-@code{make-syntactic-closure} to close the form in a syntactic
-environment.@refill
-@end deffn
-
-@defun make-syntactic-closure environment free-names form
+@node Association Lists, Byte, Array Mapping, Data Structures
+@subsection Association Lists
-@var{environment} must be a syntactic environment, @var{free-names} must
-be a list of identifiers, and @var{form} must be a form.
-@code{make-syntactic-closure} constructs and returns a syntactic closure
-of @var{form} in @var{environment}, which can be used anywhere that
-@var{form} could have been used. All the identifiers used in
-@var{form}, except those explicitly excepted by @var{free-names}, obtain
-their meanings from @var{environment}.@refill
+@code{(require 'alist)}
+@ftindex alist
-Here is an example where @var{free-names} is something other than the
-empty list. It is instructive to compare the use of @var{free-names} in
-this example with its use in the @code{loop} example above: the examples
-are similar except for the source of the identifier being left
-free.@refill
-@lisp
-(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))))))
-@end lisp
+Alist functions provide utilities for treating a list of key-value pairs
+as an associative database. These functions take an equality predicate,
+@var{pred}, as an argument. This predicate should be repeatable,
+symmetric, and transitive.@refill
-@code{let1} is a simplified version of @code{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 @code{let1} must be
-left free, so that it can be properly captured by the @code{lambda} in
-the output form.@refill
+Alist functions can be used with a secondary index method such as hash
+tables for improved performance.
-To obtain a syntactic environment other than the usage environment, use
-@code{capture-syntactic-environment}.@refill
+@defun predicate->asso pred
+Returns an @dfn{association function} (like @code{assq}, @code{assv}, or
+@code{assoc}) corresponding to @var{pred}. The returned function
+returns a key-value pair whose key is @code{pred}-equal to its first
+argument or @code{#f} if no key in the alist is @var{pred}-equal to the
+first argument.@refill
@end defun
-@defun capture-syntactic-environment procedure
-
-@code{capture-syntactic-environment} returns a form that will, when
-transformed, call @var{procedure} on the current syntactic environment.
-@var{procedure} should compute and return a new form to be transformed,
-in that same syntactic environment, in place of the form.@refill
-
-An example will make this clear. Suppose we wanted to define a simple
-@code{loop-until} keyword equivalent to@refill
-@lisp
-(define-syntax loop-until
- (syntax-rules ()
- ((loop-until id init test return step)
- (letrec ((loop
- (lambda (id)
- (if test return (loop step)))))
- (loop init)))))
-@end lisp
-
-The following attempt at defining @code{loop-until} has a subtle bug:
-@lisp
-(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 '())))))))
-@end lisp
-
-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 @code{id} identifier
-free in the @code{test}, @code{return}, and @code{step} expressions, so
-that it will be captured by the binding introduced by the @code{lambda}
-expression. Unfortunately it uses the identifiers @code{if} and
-@code{loop} within that @code{lambda} expression, so if the user of
-@code{loop-until} just happens to use, say, @code{if} for the
-identifier, it will be inadvertently captured.@refill
-
-The syntactic environment that @code{if} and @code{loop} want to be
-exposed to is the one just outside the @code{lambda} expression: before
-the user's identifier is added to the syntactic environment, but after
-the identifier loop has been added.
-@code{capture-syntactic-environment} captures exactly that environment
-as follows:@refill
-@lisp
-(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 '())))))))
-@end lisp
-
-In this case, having captured the desired syntactic environment, it is
-convenient to construct syntactic closures of the identifiers @code{if}
-and the @code{loop} and use them in the body of the
-@code{lambda}.@refill
-
-A common use of @code{capture-syntactic-environment} is to get the
-transformer environment of a macro transformer:@refill
-@lisp
-(transformer
- (lambda (exp env)
- (capture-syntactic-environment
- (lambda (transformer-env)
- ...))))
-@end lisp
+@defun alist-inquirer pred
+Returns a procedure of 2 arguments, @var{alist} and @var{key}, which
+returns the value associated with @var{key} in @var{alist} or @code{#f} if
+@var{key} does not appear in @var{alist}.@refill
@end defun
-@subsubsection 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 @code{syntax-rules} facility.@refill
-
-As discussed earlier, an identifier is either a symbol or an
-@dfn{alias}. An alias is implemented as a syntactic closure whose
-@dfn{form} is an identifier:@refill
-@lisp
-(make-syntactic-closure env '() 'a)
- @result{} an @dfn{alias}
-@end lisp
-
-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 @code{lambda} or
-@code{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.@refill
-
-Aliases are used in the implementation of the high-level facility
-@code{syntax-rules}. A macro transformer created by @code{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.
-
-@defun identifier? object
-Returns @code{#t} if @var{object} is an identifier, otherwise returns
-@code{#f}. Examples:@refill
+@defun alist-associator pred
+Returns a procedure of 3 arguments, @var{alist}, @var{key}, and
+@var{value}, which returns an alist with @var{key} and @var{value}
+associated. Any previous value associated with @var{key} will be
+lost. This returned procedure may or may not have side effects on its
+@var{alist} argument. An example of correct usage is:@refill
@lisp
-(identifier? 'a)
- @result{} #t
-(identifier? (make-syntactic-closure env '() 'a))
- @result{} #t
-(identifier? "a")
- @result{} #f
-(identifier? #\a)
- @result{} #f
-(identifier? 97)
- @result{} #f
-(identifier? #f)
- @result{} #f
-(identifier? '(a))
- @result{} #f
-(identifier? '#(a))
- @result{} #f
+(define put (alist-associator string-ci=?))
+(define alist '())
+(set! alist (put alist "Foo" 9))
@end lisp
-
-The predicate @code{eq?} is used to determine if two identifers are
-``the same''. Thus @code{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 @code{cond} macro uses the symbol @code{else} to identify
-the final clause in the conditional. A macro transformer for
-@code{cond} cannot just look for the symbol @code{else}, because the
-@code{cond} form might be the output of another macro transformer that
-replaced the symbol @code{else} with an alias. Instead the transformer
-must look for an identifier that ``means the same thing'' in the usage
-environment as the symbol @code{else} means in the transformer
-environment.@refill
@end defun
-@defun identifier=? environment1 identifier1 environment2 identifier2
-@var{environment1} and @var{environment2} must be syntactic
-environments, and @var{identifier1} and @var{identifier2} must be
-identifiers. @code{identifier=?} returns @code{#t} if the meaning of
-@var{identifier1} in @var{environment1} is the same as that of
-@var{identifier2} in @var{environment2}, otherwise it returns @code{#f}.
-Examples:@refill
-
-@lisp
-(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))))
- @result{} (#t #f)
-@end lisp
-
+@defun alist-remover pred
+Returns a procedure of 2 arguments, @var{alist} and @var{key}, which
+returns an alist with an association whose @var{key} is key removed.
+This returned procedure may or may not have side effects on its
+@var{alist} argument. An example of correct usage is:@refill
@lisp
-(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))))
- @result{} (#f #t)
+(define rem (alist-remover string-ci=?))
+(set! alist (rem alist "foo"))
@end lisp
@end defun
-@subsubsection Acknowledgements
-
-The syntactic closures facility was invented by Alan Bawden and Jonathan
-Rees. The use of aliases to implement @code{syntax-rules} was invented
-by Alan Bawden (who prefers to call them @dfn{synthetic names}). Much
-of this proposal is derived from an earlier proposal by Alan
-Bawden.@refill
-
-
-
-
-
-@node Syntax-Case Macros, Fluid-Let, Syntactic Closures, Macros
-@section Syntax-Case Macros
-
-@code{(require 'syntax-case)}
-
-@defun macro:expand expression
-@defunx syncase:expand expression
-Returns scheme code with the macros and derived expression types of
-@var{expression} expanded to primitive expression types.@refill
+@defun alist-map proc alist
+Returns a new association list formed by mapping @var{proc} over the
+keys and values of @var{alist}. @var{proc} must be a function of 2
+arguments which returns the new value part.
@end defun
-@defun macro:eval expression
-@defunx syncase:eval expression
-@code{macro:eval} returns the value of @var{expression} in the current
-top level environment. @var{expression} can contain macro definitions.
-Side effects of @var{expression} will affect the top level
-environment.@refill
+@defun alist-for-each proc alist
+Applies @var{proc} to each pair of keys and values of @var{alist}.
+@var{proc} must be a function of 2 arguments. The returned value is
+unspecified.
@end defun
-@deffn Procedure macro:load filename
-@deffnx Procedure syncase:load filename
-@var{filename} should be a string. If filename names an existing file,
-the @code{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 @code{macro:load} procedure does not affect the values returned by
-@code{current-input-port} and @code{current-output-port}.@refill
-@end deffn
-
-This is version 2.1 of @code{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:
+@node Byte, Collections, Association Lists, Data Structures
+@subsection Byte
-@itemize @bullet
-@item
-Removing white space from @file{expand.pp} to save space in the
-distribution. This file is not meant for human readers anyway@dots{}
+@code{(require 'byte)}
-@item
-Removed a couple of Chez scheme dependencies.
+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 @dfn{byte}.
+@cindex byte
-@item
-Renamed global variables used to minimize the possibility of name
-conflicts.
-
-@item
-Adding an SLIB-specific initialization file.
-
-@item
-Removing a couple extra files, most notably the documentation (but see
-below).
-@end itemize
-
-If you wish, you can see exactly what changes were done by reading the
-shell script in the file @file{syncase.sh}.
+@deffn Function byte-ref bytes k
+@var{k} must be a valid index of @var{bytes}. @code{byte-ref} returns
+byte @var{k} of @var{bytes} using zero-origin indexing.
+@findex byte-ref
+@end deffn
-The two PostScript files were omitted in order to not burden the SLIB
-distribution with them. If you do intend to use @code{syntax-case},
-however, you should get these files and print them out on a PostScript
-printer. They are available with the original @code{syntax-case}
-distribution by anonymous FTP in
-@file{cs.indiana.edu:/pub/scheme/syntax-case}.@refill
+@deffn Procedure byte-set! bytes k byte
+@var{k} must be a valid index of @var{bytes}%, and @var{byte} must be a
+small integer. @code{Byte-set!} stores @var{byte} in element @var{k}
+of @var{bytes}
+@findex byte-set!
+and returns an unspecified value. @c <!>
-In order to use syntax-case from an interactive top level, execute:
-@lisp
-(require 'syntax-case)
-(require 'repl)
-(repl:top-level macro:eval)
-@end lisp
-See the section Repl (@xref{Repl}) for more information.
+@end deffn
-To check operation of syntax-case get
-@file{cs.indiana.edu:/pub/scheme/syntax-case}, and type
-@lisp
-(require 'syntax-case)
-(syncase:sanity-check)
-@end lisp
+@deffn Function make-bytes k
+@deffnx Function make-bytes k byte
-Beware that @code{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).
+@code{Make-bytes} returns a newly allocated byte-array of
+@findex make-bytes
+length @var{k}. If @var{byte} is given, then all elements of the
+byte-array are initialized to @var{byte}, otherwise the contents of the
+byte-array are unspecified.
-@subsection Notes
+@end deffn
-All R4RS syntactic forms are defined, including @code{delay}. Along
-with @code{delay} are simple definitions for @code{make-promise} (into
-which @code{delay} expressions expand) and @code{force}.@refill
+@deffn Function write-byte byte
+@deffnx Function write-byte byte port
-@code{syntax-rules} and @code{with-syntax} (described in @cite{TR356})
-are defined.@refill
+Writes the byte @var{byte} (not an external representation of the
+byte) to the given @var{port} and returns an unspecified value. The
+@var{port} argument may be omitted, in which case it defaults to the value
+returned by @code{current-output-port}.
+@findex current-output-port
-@code{syntax-case} is actually defined as a macro that expands into
-calls to the procedure @code{syntax-dispatch} and the core form
-@code{syntax-lambda}; do not redefine these names.@refill
+@end deffn
-Several other top-level bindings not documented in TR356 are created:
-@itemize
-@item the ``hooks'' in @file{hooks.ss}
-@item the @code{build-} procedures in @file{output.ss}
-@item @code{expand-syntax} (the expander)
-@end itemize
+@deffn Function read-byte
+@deffnx Function read-byte port
-The syntax of define has been extended to allow @code{(define @var{id})},
-which assigns @var{id} to some unspecified value.@refill
+Returns the next byte available from the input @var{port}, updating
+the @var{port} to point to the following byte. If no more bytes
+are available, an end of file object is returned. @var{Port} may be
+omitted, in which case it defaults to the value returned by
+@code{current-input-port}.
+@findex current-input-port
-We have attempted to maintain R4RS compatibility where possible. The
-incompatibilities should be confined to @file{hooks.ss}. Please let us
-know if there is some incompatibility that is not flagged as such.@refill
+@end deffn
-Send bug reports, comments, suggestions, and questions to Kent Dybvig
-(dyb@@iuvax.cs.indiana.edu).
+@deffn Function bytes byte @dots{}
-@subsection Note from maintainer
+Returns a newly allocated byte-array composed of the arguments.
-Included with the @code{syntax-case} files was @file{structure.scm}
-which defines a macro @code{define-structure}. There is no
-documentation for this macro and it is not used by any code in SLIB.
+@end deffn
-@node Fluid-Let, Yasos, Syntax-Case Macros, Macros
-@section Fluid-Let
+@deffn Function bytes->list bytes
+@deffnx Function list->bytes bytes
-@code{(require 'fluid-let)}
+@code{Bytes->list} returns a newly allocated list of the
+@findex bytes->list
+bytes that make up the given byte-array. @code{List->bytes}
+@findex list->bytes
+returns a newly allocated byte-array formed from the small integers in
+the list @var{bytes}. @code{Bytes->list} and @code{list->bytes} are
+@findex list->bytes
+@findex bytes->list
+inverses so far as @code{equal?} is concerned.
+@findex equal?
-@deffn Syntax fluid-let @code{(@var{bindings} @dots{})} @var{forms}@dots{}
@end deffn
-@lisp
-(fluid-let ((@var{variable} @var{init}) @dots{})
- @var{expression} @var{expression} @dots{})
-@end lisp
-The @var{init}s are evaluated in the current environment (in some
-unspecified order), the current values of the @var{variable}s are saved,
-the results are assigned to the @var{variable}s, the @var{expression}s
-are evaluated sequentially in the current environment, the
-@var{variable}s are restored to their original values, and the value of
-the last @var{expression} is returned.@refill
-
-The syntax of this special form is similar to that of @code{let}, but
-@code{fluid-let} temporarily rebinds existing @var{variable}s. Unlike
-@code{let}, @code{fluid-let} creates no new bindings; instead it
-@emph{assigns} the values of each @var{init} to the binding (determined
-by the rules of lexical scoping) of its corresponding
-@var{variable}.@refill
-
-@node Yasos, , Fluid-Let, Macros
-@section Yasos
+@node Collections, Dynamic Data Type, Byte, Data Structures
+@subsection Collections
@c Much of the documentation in this section was written by Dave Love
@c (d.love@dl.ac.uk) -- don't blame Ken Dickey for its faults.
@c but we can blame him for not writing it!
-@code{(require 'oop)} or @code{(require 'yasos)}
-
-`Yet Another Scheme Object System' is a simple object system for Scheme
-based on the paper by Norman Adams and Jonathan Rees: @cite{Object
-Oriented Programming in Scheme}, Proceedings of the 1988 ACM Conference
-on LISP and Functional Programming, July 1988 [ACM #552880].@refill
-
-Another reference is:
-
-Ken Dickey.
-@ifset html
-<A HREF="ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/pubs/swob.txt">
-@end ifset
-Scheming with Objects
-@ifset html
-</A>
-@end ifset
-@cite{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.
-@end menu
-
-@node Yasos terms, Yasos interface, Yasos, Yasos
-@subsection Terms
-
-@table @asis
-@item @dfn{Object}
-Any Scheme data object.
-
-@item @dfn{Instance}
-An instance of the OO system; an @dfn{object}.
-
-@item @dfn{Operation}
-A @var{method}.
-@end table
-
-@table @emph
-@item 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 @code{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 @dfn{classes}
-and no meta-@var{anything}. Method dispatch is by a procedure call a la
-CLOS rather than by @code{send} syntax a la Smalltalk.@refill
-
-@item 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.@refill
-@end table
-
-
-
-
-
-@node Yasos interface, Setters, Yasos terms, Yasos
-@subsection Interface
-
-@deffn Syntax define-operation @code{(}opname self arg @dots{}@code{)} @var{default-body}
-Defines a default behavior for data objects which don't handle the
-operation @var{opname}. The default default behavior (for an empty
-@var{default-body}) is to generate an error.@refill
-@end deffn
-
-@deffn Syntax define-predicate opname?
-Defines a predicate @var{opname?}, usually used for determining the
-@dfn{type} of an object, such that @code{(@var{opname?} @var{object})}
-returns @code{#t} if @var{object} has an operation @var{opname?} and
-@code{#f} otherwise.@refill
-@end deffn
-
-@deffn Syntax object @code{((@var{name} @var{self} @var{arg} @dots{}) @var{body})} @dots{}
-Returns an object (an instance of the object system) with operations.
-Invoking @code{(@var{name} @var{object} @var{arg} @dots{}} executes the
-@var{body} of the @var{object} with @var{self} bound to @var{object} and
-with argument(s) @var{arg}@dots{}.@refill
-@end deffn
-
-@deffn Syntax object-with-ancestors @code{((}ancestor1 init1@code{)} @dots{}@code{)} operation @dots{}
-A @code{let}-like form of @code{object} for multiple inheritance. It
-returns an object inheriting the behaviour of @var{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.
-@end deffn
-
-@deffn Syntax operate-as component operation self arg @dots{}
-Used in an operation definition (of @var{self}) to invoke the
-@var{operation} in an ancestor @var{component} but maintain the object's
-identity. Also known as ``send-to-super''.@refill
-@end deffn
-
-@deffn Procedure print obj port
-A default @code{print} operation is provided which is just @code{(format
-@var{port} @var{obj})} (@xref{Format}) for non-instances and prints
-@var{obj} preceded by @samp{#<INSTANCE>} for instances.
-@end deffn
-
-@defun size obj
-The default method returns the number of elements in @var{obj} if it is
-a vector, string or list, @code{2} for a pair, @code{1} for a character
-and by default id an error otherwise. Objects such as collections
-(@xref{Collections}) may override the default in an obvious way.@refill
-@end defun
+@code{(require 'collect)}
+@ftindex 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
+@dfn{elements} indexed by corresponding @dfn{keys}, although the keys
+may be implicit (as with lists).@refill
+New types of collections may be defined as YASOS objects (@xref{Yasos}).
+They must support the following operations:
+@itemize @bullet
+@item
+@code{(collection? @var{self})} (always returns @code{#t});
+@item
+@code{(size @var{self})} returns the number of elements in the collection;
+@item
+@code{(print @var{self} @var{port})} is a specialized print operation
+for the collection which prints a suitable representation on the given
+@var{port} or returns it as a string if @var{port} is @code{#t};@refill
-@node Setters, Yasos examples, Yasos interface, Yasos
-@subsection Setters
+@item
+@code{(gen-elts @var{self})} returns a thunk which on successive
+invocations yields elements of @var{self} in order or gives an error if
+it is invoked more than @code{(size @var{self})} times;@refill
-@dfn{Setters} implement @dfn{generalized locations} for objects
-associated with some sort of mutable state. A @dfn{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 (@xref{Yasos}).
-Several setters are predefined, corresponding to getters @code{car},
-@code{cdr}, @code{string-ref} and @code{vector-ref} e.g., @code{(setter
-car)} is equivalent to @code{set-car!}.
+@item
+@code{(gen-keys @var{self})} is like @code{gen-elts}, but yields the
+collection's keys in order.
-This implementation of setters is similar to that in Dylan(TM)
-(@cite{Dylan: An object-oriented dynamic language}, Apple Computer
-Eastern Research and Technology). Common LISP provides similar
-facilities through @code{setf}.
+@end itemize
+They might support specialized @code{for-each-key} and
+@code{for-each-elt} operations.@refill
-@defun setter getter
-Returns the setter for the procedure @var{getter}. E.g., since
-@code{string-ref} is the getter corresponding to a setter which is
-actually @code{string-set!}:
-@example
-(define foo "foo")
-((setter string-ref) foo 0 #\F) ; set element 0 of foo
-foo @result{} "Foo"
-@end example
+@defun collection? obj
+A predicate, true initially of lists, vectors and strings. New sorts of
+collections must answer @code{#t} to @code{collection?}.@refill
@end defun
-@deffn Syntax set place new-value
-If @var{place} is a variable name, @code{set} is equivalent to
-@code{set!}. Otherwise, @var{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 @code{set} is usually unspecified unless used with a
-setter whose definition guarantees to return a useful value.
-@example
-(set (string-ref foo 2) #\O) ; generalized location with getter
-foo @result{} "FoO"
-(set foo "foo") ; like set!
-foo @result{} "foo"
-@end example
-@end deffn
-
-@deffn Procedure add-setter getter setter
-Add procedures @var{getter} and @var{setter} to the (inaccessible) list
-of valid setter/getter pairs. @var{setter} implements the store
-operation corresponding to the @var{getter} access operation for the
-relevant state. The return value is unspecified.
-@end deffn
-
-@deffn Procedure remove-setter-for getter
-Removes the setter corresponding to the specified @var{getter} from the
-list of valid setters. The return value is unspecified.
-@end deffn
-
-@deffn Syntax define-access-operation getter-name
-Shorthand for a Yasos @code{define-operation} defining an operation
-@var{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.
-@end deffn
-
-
-
-
-
-@node Yasos examples, , Setters, Yasos
-@subsection Examples
+@deffn Procedure map-elts proc . collections
+@deffnx Procedure do-elts proc . collections
+@var{proc} is a procedure taking as many arguments as there are
+@var{collections} (at least one). The @var{collections} are iterated
+over in their natural order and @var{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 @var{collections} appear.
+@code{do-elts} is used when only side-effects of @var{proc} are of
+interest and its return value is unspecified. @code{map-elts} returns a
+collection (actually a vector) of the results of the applications of
+@var{proc}.@refill
+Example:
@lisp
-(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)
-@result{} "#<Cell: 1>"
-(set (fetch foo) 2)
-@result{}
-(print foo #f)
-@result{} "#<Cell: 2>"
-(fetch foo)
-@result{} 2
+(map-elts + (list 1 2 3) (vector 1 2 3))
+ @result{} #(2 4 6)
@end lisp
+@end deffn
-@node Numerics, Procedures, Macros, Top
-@chapter Numerics
-
-@menu
-* Bit-Twiddling:: 'logical
-* Modular Arithmetic:: 'modular
-* Prime Testing and Generation:: 'primes
-* Prime Factorization:: 'factor
-* Random Numbers:: 'random
-* Cyclic Checksum:: 'make-crc
-* Plotting:: 'charplot
-* Root Finding::
-@end menu
-
-
-@node Bit-Twiddling, Modular Arithmetic, Numerics, Numerics
-@section Bit-Twiddling
-
-@code{(require 'logical)}
-
-The bit-twiddling functions are made available through the use of the
-@code{logical} package. @code{logical} is loaded by inserting
-@code{(require 'logical)} before the code that uses these
-functions.@refill
-
-@defun logand n1 n1
-Returns the integer which is the bit-wise AND of the two integer
-arguments.
+@deffn Procedure map-keys proc . collections
+@deffnx Procedure do-keys proc . collections
+These are analogous to @code{map-elts} and @code{do-elts}, but each
+iteration is over the @var{collections}' @emph{keys} rather than their
+elements.@refill
Example:
@lisp
-(number->string (logand #b1100 #b1010) 2)
- @result{} "1000"
+(map-keys + (list 1 2 3) (vector 1 2 3))
+ @result{} #(0 2 4)
@end lisp
-@end defun
+@end deffn
-@defun logior n1 n2
-Returns the integer which is the bit-wise OR of the two integer
-arguments.
+@deffn Procedure for-each-key collection proc
+@deffnx Procedure for-each-elt collection proc
+These are like @code{do-keys} and @code{do-elts} but only for a single
+collection; they are potentially more efficient.
+@end deffn
-Example:
+@defun reduce proc seed . collections
+A generalization of the list-based @code{comlist:reduce-init}
+(@xref{Lists as sequences}) to collections which will shadow the
+list-based version if @code{(require 'collect)} follows
+@ftindex collect
+@code{(require 'common-list-functions)} (@xref{Common List Functions}).@refill
+@ftindex common-list-functions
+
+Examples:
@lisp
-(number->string (logior #b1100 #b1010) 2)
- @result{} "1110"
+(reduce + 0 (vector 1 2 3))
+ @result{} 6
+(reduce union '() '((a b c) (b c d) (d a)))
+ @result{} (c b d a).
@end lisp
@end defun
-@defun logxor n1 n2
-Returns the integer which is the bit-wise XOR of the two integer
-arguments.
+@defun any? pred . collections
+A generalization of the list-based @code{some} (@xref{Lists as
+sequences}) to collections.@refill
Example:
@lisp
-(number->string (logxor #b1100 #b1010) 2)
- @result{} "110"
+(any? odd? (list 2 3 4 5))
+ @result{} #t
@end lisp
@end defun
-@defun lognot n
-Returns the integer which is the 2s-complement of the integer argument.
+@defun every? pred . collections
+A generalization of the list-based @code{every} (@xref{Lists as
+sequences}) to collections.@refill
Example:
@lisp
-(number->string (lognot #b10000000) 2)
- @result{} "-10000001"
-(number->string (lognot #b0) 2)
- @result{} "-1"
+(every? collection? '((1 2) #(1 2)))
+ @result{} #t
@end lisp
@end defun
-@defun logtest j k
-@example
-(logtest j k) @equiv{} (not (zero? (logand j k)))
+@defun empty? collection
+Returns @code{#t} iff there are no elements in @var{collection}.
-(logtest #b0100 #b1011) @result{} #f
-(logtest #b0100 #b0111) @result{} #t
-@end example
+@code{(empty? @var{collection}) @equiv{} (zero? (size @var{collection}))}
@end defun
-@defun logbit? index j
-@example
-(logbit? index j) @equiv{} (logtest (integer-expt 2 index) j)
-
-(logbit? 0 #b1101) @result{} #t
-(logbit? 1 #b1101) @result{} #f
-(logbit? 2 #b1101) @result{} #t
-(logbit? 3 #b1101) @result{} #t
-(logbit? 4 #b1101) @result{} #f
-@end example
+@defun size collection
+Returns the number of elements in @var{collection}.
@end defun
-@defun ash int count
-Returns an integer equivalent to
-@code{(inexact->exact (floor (* @var{int} (expt 2 @var{count}))))}.@refill
-
-Example:
-@lisp
-(number->string (ash #b1 3) 2)
- @result{} "1000"
-(number->string (ash #b1010 -1) 2)
- @result{} "101"
-@end lisp
+@defun Setter list-ref
+See @xref{Setters} for a definition of @dfn{setter}. N.B.
+@code{(setter list-ref)} doesn't work properly for element 0 of a
+list.@refill
@end defun
-@defun logcount n
-Returns the number of bits in integer @var{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:
+Here is a sample collection: @code{simple-table} which is also a
+@code{table}.@refill
@lisp
-(logcount #b10101010)
- @result{} 4
-(logcount 0)
- @result{} 0
-(logcount -2)
- @result{} 1
-@end lisp
-@end defun
-
-@defun integer-length n
-Returns the number of bits neccessary to represent @var{n}.
+(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
-Example:
-@lisp
-(integer-length #b10101010)
- @result{} 8
-(integer-length 0)
- @result{} 0
-(integer-length #b1111)
- @result{} 4
+(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)
+ )
+ ) ) )
@end lisp
-@end defun
-@defun integer-expt n k
-Returns @var{n} raised to the non-negative integer exponent @var{k}.
-Example:
-@lisp
-(integer-expt 2 5)
- @result{} 32
-(integer-expt -3 3)
- @result{} -27
-@end lisp
-@end defun
-
-@defun bit-extract n start end
-Returns the integer composed of the @var{start} (inclusive) through
-@var{end} (exclusive) bits of @var{n}. The @var{start}th bit becomes
-the 0-th bit in the result.@refill
-Example:
-@lisp
-(number->string (bit-extract #b1101101010 0 4) 2)
- @result{} "1010"
-(number->string (bit-extract #b1101101010 4 9) 2)
- @result{} "10110"
-@end lisp
-@end defun
-@node Modular Arithmetic, Prime Testing and Generation, Bit-Twiddling, Numerics
-@section Modular Arithmetic
+@node Dynamic Data Type, Hash Tables, Collections, Data Structures
+@subsection Dynamic Data Type
-@code{(require 'modular)}
+@code{(require 'dynamic)}
+@ftindex dynamic
-@defun extended-euclid n1 n2
-Returns a list of 3 integers @code{(d x y)} such that d = gcd(@var{n1},
-@var{n2}) = @var{n1} * x + @var{n2} * y.@refill
+@defun make-dynamic obj
+Create and returns a new @dfn{dynamic} whose global value is @var{obj}.
@end defun
-@defun symmetric:modulus n
-Returns @code{(quotient (+ -1 n) -2)} for positive odd integer @var{n}.
+@defun dynamic? obj
+Returns true if and only if @var{obj} is a dynamic. No object
+satisfying @code{dynamic?} satisfies any of the other standard type
+predicates.@refill
@end defun
-@defun modulus->integer modulus
-Returns the non-negative integer characteristic of the ring formed when
-@var{modulus} is used with @code{modular:} procedures.
+@defun dynamic-ref dyn
+Return the value of the given dynamic in the current dynamic
+environment.
@end defun
-@defun modular:normalize modulus n
-Returns the integer @code{(modulo @var{n} (modulus->integer
-@var{modulus}))} in the representation specified by @var{modulus}.
-@end defun
+@deffn Procedure dynamic-set! dyn obj
+Change the value of the given dynamic to @var{obj} in the current
+dynamic environment. The returned value is unspecified.@refill
+@end deffn
-@noindent
-The rest of these functions assume normalized arguments; That is, the
-arguments are constrained by the following table:
+@defun 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 @var{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.@refill
+@end defun
-@noindent
-For all of these functions, if the first argument (@var{modulus}) is:
-@table @code
-@item positive?
-Work as before. The result is between 0 and @var{modulus}.
+The @code{dynamic-bind} macro is not implemented.
-@item zero?
-The arguments are treated as integers. An integer is returned.
-@item negative?
-The arguments and result are treated as members of the integers modulo
-@code{(+ 1 (* -2 @var{modulus}))}, but with @dfn{symmetric}
-representation; i.e. @code{(<= (- @var{modulus}) @var{n}
-@var{modulus})}.
-@end table
-@noindent
-If all the arguments are fixnums the computation will use only fixnums.
-@defun modular:invertable? modulus k
-Returns @code{#t} if there exists an integer n such that @var{k} * n
-@equiv{} 1 mod @var{modulus}, and @code{#f} otherwise.
-@end defun
+@node Hash Tables, Hashing, Dynamic Data Type, Data Structures
+@subsection Hash Tables
-@defun modular:invert modulus k2
-Returns an integer n such that 1 = (n * @var{k2}) mod @var{modulus}. If
-@var{k2} has no inverse mod @var{modulus} an error is signaled.
-@end defun
+@code{(require 'hash-table)}
+@ftindex hash-table
-@defun modular:negate modulus k2
-Returns (@minus{}@var{k2}) mod @var{modulus}.
+@defun predicate->hash pred
+Returns a hash function (like @code{hashq}, @code{hashv}, or
+@code{hash}) corresponding to the equality predicate @var{pred}.
+@var{pred} should be @code{eq?}, @code{eqv?}, @code{equal?}, @code{=},
+@code{char=?}, @code{char-ci=?}, @code{string=?}, or
+@code{string-ci=?}.@refill
@end defun
-@defun modular:+ modulus k2 k3
-Returns (@var{k2} + @var{k3}) mod @var{modulus}.
-@end defun
+A hash table is a vector of association lists.
-@defun modular:@minus{} modulus k2 k3
-Returns (@var{k2} @minus{} @var{k3}) mod @var{modulus}.
+@defun make-hash-table k
+Returns a vector of @var{k} empty (association) lists.
@end defun
-@defun modular:* modulus k2 k3
-Returns (@var{k2} * @var{k3}) mod @var{modulus}.
+Hash table functions provide utilities for an associative database.
+These functions take an equality predicate, @var{pred}, as an argument.
+@var{pred} should be @code{eq?}, @code{eqv?}, @code{equal?}, @code{=},
+@code{char=?}, @code{char-ci=?}, @code{string=?}, or
+@code{string-ci=?}.@refill
-The Scheme code for @code{modular:*} with negative @var{modulus} is not
-completed for fixnum-only implementations.
+@defun predicate->hash-asso pred
+Returns a hash association function of 2 arguments, @var{key} and
+@var{hashtab}, corresponding to @var{pred}. The returned function
+returns a key-value pair whose key is @var{pred}-equal to its first
+argument or @code{#f} if no key in @var{hashtab} is @var{pred}-equal to
+the first argument.@refill
@end defun
-@defun modular:expt modulus k2 k3
-Returns (@var{k2} ^ @var{k3}) mod @var{modulus}.
+@defun hash-inquirer pred
+Returns a procedure of 3 arguments, @code{hashtab} and @code{key}, which
+returns the value associated with @code{key} in @code{hashtab} or
+@code{#f} if key does not appear in @code{hashtab}.@refill
@end defun
-
-@node Prime Testing and Generation, Prime Factorization, Modular Arithmetic, Numerics
-@section Prime Testing and Generation
-
-@code{(require 'primes)}
-
-This package tests and generates prime numbers. The strategy used is
-as follows:
-
-@itemize
-@item
-First, use trial division by small primes (primes less than 1000) to
-quickly weed out composites with small factors. As a side benefit, this
-makes the test precise for numbers up to one million.
-@item
-Second, apply the Miller-Rabin primality test to detect (with high
-probability) any remaining composites.
-@end itemize
-
-The Miller-Rabin test is a Monte-Carlo test---in other words, it's fast
-and it gets the right answer with high probability. For a candidate
-that @emph{is} prime, the Miller-Rabin test is certain to report
-"prime"; it will never report "composite". However, for a candidate
-that is composite, there is a (small) probability that the Miller-Rabin
-test will erroneously report "prime". This probability can be made
-arbitarily small by adjusting the number of iterations of the
-Miller-Rabin test.
-
-@defun probably-prime? candidate
-@defunx probably-prime? candidate iter
-Returns @code{#t} if @code{candidate} is probably prime. The optional
-parameter @code{iter} controls the number of iterations of the
-Miller-Rabin test. The probability of a composite candidate being
-mistaken for a prime is at most @code{(1/4)^iter}. The default value of
-@code{iter} is 15, which makes the probability less than 1 in 10^9.
-
+@defun hash-associator pred
+Returns a procedure of 3 arguments, @var{hashtab}, @var{key}, and
+@var{value}, which modifies @var{hashtab} so that @var{key} and
+@var{value} associated. Any previous value associated with @var{key}
+will be lost.@refill
@end defun
-@defun primes< start count
-@defunx primes< start count iter
-@defunx primes> start count
-@defunx primes> start count iter
-Returns a list of the first @code{count} odd probable primes less (more)
-than or equal to @code{start}. The optional parameter @code{iter}
-controls the number of iterations of the Miller-Rabin test for each
-candidate. The probability of a composite candidate being mistaken for
-a prime is at most @code{(1/4)^iter}. The default value of @code{iter}
-is 15, which makes the probability less than 1 in 10^9.
-
+@defun hash-remover pred
+Returns a procedure of 2 arguments, @var{hashtab} and @var{key}, which
+modifies @var{hashtab} so that the association whose key is @var{key} is
+removed.@refill
@end defun
-@menu
-* The Miller-Rabin Test:: How the Miller-Rabin test works
-@end menu
-
-@node The Miller-Rabin Test, , Prime Testing and Generation, Prime Testing and Generation
-@subsection Theory
-
-Rabin and Miller's result can be summarized as follows. Let @code{p}
-(the candidate prime) be any odd integer greater than 2. Let @code{b}
-(the "base") be an integer in the range @code{2 ... p-1}. There is a
-fairly simple Boolean function---call it @code{C}, for
-"Composite"---with the following properties:
-@itemize
-
-@item
-If @code{p} is prime, @code{C(p, b)} is false for all @code{b} in the range
-@code{2 ... p-1}.
-
-@item
-If @code{p} is composite, @code{C(p, b)} is false for at most 1/4 of all
-@code{b} in the range @code{ 2 ... p-1}. (If the test fails for base
-@code{b}, @code{p} is called a @emph{strong pseudo-prime to base
-@code{b}}.)
-
-@end itemize
-For details of @code{C}, and why it fails for at most 1/4 of the
-potential bases, please consult a book on number theory or cryptography
-such as "A Course in Number Theory and Cryptography" by Neal Koblitz,
-published by Springer-Verlag 1994.
-
-There is nothing probablistic about this result. It's true for all
-@code{p}. If we had time to test @code{(1/4)p + 1} different bases, we
-could definitively determine the primality of @code{p}. For large
-candidates, that would take much too long---much longer than the simple
-approach of dividing by all numbers up to @code{sqrt(p)}. This is
-where probability enters the picture.
+@defun hash-map proc hash-table
+Returns a new hash table formed by mapping @var{proc} over the
+keys and values of @var{hash-table}. @var{proc} must be a function of 2
+arguments which returns the new value part.
+@end defun
-Suppose we have some candidate prime @code{p}. Pick a random integer
-@code{b} in the range @code{2 ... p-1}. Compute @code{C(p,b)}. If
-@code{p} is prime, the result will certainly be false. If @code{p} is
-composite, the probability is at most 1/4 that the result will be false
-(demonstrating that @code{p} is a strong pseudoprime to base @code{b}).
-The test can be repeated with other random bases. If @code{p} is prime,
-each test is certain to return false. If @code{p} is composite, the
-probability of @code{C(p,b)} returning false is at most 1/4 for each
-test. Since the @code{b} are chosen at random, the tests outcomes are
-independent. So if @code{p} is composite and the test is repeated, say,
-15 times, the probability of it returning false all fifteen times is at
-most (1/4)^15, or about 10^-9. If the test is repeated 30 times, the
-probability of failure drops to at most 8.3e-25.
+@defun hash-for-each proc hash-table
+Applies @var{proc} to each pair of keys and values of @var{hash-table}.
+@var{proc} must be a function of 2 arguments. The returned value is
+unspecified.
+@end defun
-Rabin and Miller's result holds for @emph{all} candidates @code{p}.
-However, if the candidate @code{p} is picked at random, the probability
-of the Miller-Rabin test failing is much less than the computed bound.
-This is because, for @emph{most} composite numbers, the fraction of
-bases that cause the test to fail is much less than 1/4. For example,
-if you pick a random odd number less than 1000 and apply the
-Miller-Rabin test with only 3 random bases, the computed failure bound
-is (1/4)^3, or about 1.6e-2. However, the actual probability of failure
-is much less---about 7.2e-5. If you accidentally pick 703 to test for
-primality, the probability of failure is (161/703)^3, or about 1.2e-2,
-which is almost as high as the computed bound. This is because 703 is a
-strong pseudoprime to 161 bases. But if you pick at random there is
-only a small chance of picking 703, and no other number less than 1000
-has that high a percentage of pseudoprime bases.
-The Miller-Rabin test is sometimes used in a slightly different fashion,
-where it can, at least in principle, cause problems. The weaker version
-uses small prime bases instead of random bases. If you are picking
-candidates at random and testing for primality, this works well since
-very few composites are strong pseudo-primes to small prime bases. (For
-example, there is only one composite less than 2.5e10 that is a strong
-pseudo-prime to the bases 2, 3, 5, and 7.) The problem with this
-approach is that once a candidate has been picked, the test is
-deterministic. This distinction is subtle, but real. With the
-randomized test, for @emph{any} candidate you pick---even if your
-candidate-picking procedure is strongly biased towards troublesome
-numbers, the test will work with high probability. With the
-deterministic version, for any particular candidate, the test will
-either work (with probability 1), or fail (with probability 1). It
-won't fail for very many candidates, but that won't be much consolation
-if your candidate-picking procedure is somehow biased toward troublesome
-numbers.
-@node Prime Factorization, Random Numbers, Prime Testing and Generation, Numerics
-@section Prime Factorization
-@code{(require 'factor)}
+@node Hashing, Priority Queues, Hash Tables, Data Structures
+@subsection Hashing
+@code{(require 'hash)}
+@ftindex hash
-@defun factor k
-Returns a list of the prime factors of @var{k}. The order of the
-factors is unspecified. In order to obtain a sorted list do
-@code{(sort! (factor k) <)}.@refill
-@end defun
+These hashing functions are for use in quickly classifying objects.
+Hash tables use these functions.
-@emph{Note:} The rest of these procedures implement the Solovay-Strassen
-primality test. This test has been superseeded by the faster
-@xref{Prime Testing and Generation, probably-prime?}. However these are
-left here as they take up little space and may be of use to an
-implementation without bignums.
+@defun hashq obj k
+@defunx hashv obj k
+@defunx hash obj k
+Returns an exact non-negative integer less than @var{k}. For each
+non-negative integer less than @var{k} there are arguments @var{obj} for
+which the hashing functions applied to @var{obj} and @var{k} returns
+that integer.@refill
-See Robert Solovay and Volker Strassen, @cite{A Fast Monte-Carlo Test
-for Primality}, SIAM Journal on Computing, 1977, pp 84-85.
+For @code{hashq}, @code{(eq? obj1 obj2)} implies @code{(= (hashq obj1 k)
+(hashq obj2))}.@refill
-@defun jacobi-symbol p q
-Returns the value (+1, @minus{}1, or 0) of the Jacobi-Symbol of exact
-non-negative integer @var{p} and exact positive odd integer
-@var{q}.@refill
-@end defun
+For @code{hashv}, @code{(eqv? obj1 obj2)} implies @code{(= (hashv obj1 k)
+(hashv obj2))}.@refill
-@defun prime? p
-Returns @code{#f} if @var{p} is composite; @code{#t} if @var{p} is
-prime. There is a slight chance @code{(expt 2 (- prime:trials))} that a
-composite will return @code{#t}.@refill
-@end defun
+For @code{hash}, @code{(equal? obj1 obj2)} implies @code{(= (hash obj1 k)
+(hash obj2))}.@refill
-@defun prime:trials
-Is the maxinum number of iterations of Solovay-Strassen that will be
-done to test a number for primality.
+@code{hash}, @code{hashv}, and @code{hashq} return in time bounded by a
+constant. Notice that items having the same @code{hash} implies the
+items have the same @code{hashv} implies the items have the same
+@code{hashq}.@refill
@end defun
+@code{(require 'sierpinski)}
+@ftindex sierpinski
-@node Random Numbers, Cyclic Checksum, Prime Factorization, Numerics
-@section Random Numbers
-
-@code{(require 'random)}
-
-
-@deffn Procedure random n
-@deffnx Procedure random n state
-Accepts a positive integer or real @var{n} and returns a number of the
-same type between zero (inclusive) and @var{n} (exclusive). The values
-returned have a uniform distribution.@refill
+@defun make-sierpinski-indexer max-coordinate
+Returns a procedure (eg hash-function) of 2 numeric arguments which
+preserves @emph{nearness} in its mapping from NxN to N.
-The optional argument @var{state} must be of the type produced by
-@code{(make-random-state)}. It defaults to the value of the variable
-@code{*random-state*}. This object is used to maintain the state of the
-pseudo-random-number generator and is altered as a side effect of the
-@code{random} operation.@refill
-@end deffn
+@var{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.)
-@defvar *random-state*
-Holds a data structure that encodes the internal state of the
-random-number generator that @code{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.@refill
-@end defvar
+Example use: Make an indexer (hash-function) for integer points lying in
+square of integer grid points [0,99]x[0,99]:
+@example
+(define space-key (make-sierpinski-indexer 100))
+@end example
+Now let's compute the index of some points:
+@example
+(space-key 24 78) @result{} 9206
+(space-key 23 80) @result{} 9172
+@end example
-@deffn Procedure make-random-state
-@deffnx Procedure make-random-state state
-Returns a new object of type suitable for use as the value of the
-variable @code{*random-state*} and as a second argument to
-@code{random}. If argument @var{state} is given, a copy of it is
-returned. Otherwise a copy of @code{*random-state*} is returned.@refill
-@end deffn
+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
+@emph{tends} to be so.
-If inexact numbers are support by the Scheme implementation,
-@file{randinex.scm} will be loaded as well. @file{randinex.scm}
-contains procedures for generating inexact distributions.@refill
+Example applications:
+@itemize @bullet
-@deffn Procedure random:uniform state
-Returns an uniformly distributed inexact real random number in the
-range between 0 and 1.
-@end deffn
+@item
+Sort points by Sierpinski index to get heuristic solution to
+@emph{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.
-@deffn Procedure random:solid-sphere! vect
-@deffnx Procedure random:solid-sphere! vect state
-Fills @var{vect} with inexact real random numbers the sum of whose
-squares is less than 1.0. Thinking of @var{vect} as coordinates in
-space of dimension @var{n} = @code{(vector-length @var{vect})}, the
-coordinates are uniformly distributed within the unit @var{n}-shere.
-The sum of the squares of the numbers is returned.@refill
-@end deffn
+@item
+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.)
-@deffn Procedure random:hollow-sphere! vect
-@deffnx Procedure random:hollow-sphere! vect state
-Fills @var{vect} with inexact real random numbers the sum of whose
-squares is equal to 1.0. Thinking of @var{vect} as coordinates in space
-of dimension n = @code{(vector-length @var{vect})}, the coordinates are
-uniformly distributed over the surface of the unit n-shere.@refill
-@end deffn
+@end itemize
+@end defun
-@deffn Procedure random:normal
-@deffnx Procedure random:normal state
-Returns an inexact real in a normal distribution with mean 0 and
-standard deviation 1. For a normal distribution with mean @var{m} and
-standard deviation @var{d} use @code{(+ @var{m} (* @var{d}
-(random:normal)))}.@refill
-@end deffn
-@deffn Procedure random:normal-vector! vect
-@deffnx Procedure random:normal-vector! vect state
-Fills @var{vect} with inexact real random numbers which are independent
-and standard normally distributed (i.e., with mean 0 and variance 1).
-@end deffn
-@deffn Procedure random:exp
-@deffnx Procedure random:exp state
-Returns an inexact real in an exponential distribution with mean 1. For
-an exponential distribution with mean @var{u} use (* @var{u}
-(random:exp)).@refill
-@end deffn
-
-
-@node Cyclic Checksum, Plotting, Random Numbers, Numerics
-@section Cyclic Checksum
+@code{(require 'soundex)}
+@ftindex soundex
-@code{(require 'make-crc)}
+@defun soundex name
+Computes the @emph{soundex} hash of @var{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.
-@defun make-port-crc
-@defunx make-port-crc degree
-@defunx 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.
+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.
-The integer @var{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.
+See Knuth, Vol. 3 @cite{Sorting and searching}, pp 391--2
-The integer @var{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 @var{degree} is implicit and should not
-be part of @var{generator}. This allows systems with numbers limited to
-32 bits to calculate 32 bit checksums. The default value of
-@var{generator} when @var{degree} is 32 (its default) is:
+To manage unusual inputs, @code{soundex} omits all non-alphabetic
+characters. Consequently, in this implementation:
@example
-(make-port-crc 32 #b00000100110000010001110110110111)
+(soundex <string of blanks>) @result{} ""
+(soundex "") @result{} ""
@end example
-Creates a procedure to calculate the P1003.2/D11.2 (POSIX.2) 32-bit
-checksum from the polynomial:
+Examples from Knuth:
@example
- 32 26 23 22 16 12 11
- ( x + x + x + x + x + x + x +
+(map soundex '("Euler" "Gauss" "Hilbert" "Knuth"
+ "Lloyd" "Lukasiewicz"))
+ @result{} ("E460" "G200" "H416" "K530" "L300" "L222")
- 10 8 7 5 4 2 1
- x + x + x + x + x + x + x + 1 ) mod 2
+(map soundex '("Ellery" "Ghosh" "Heilbronn" "Kant"
+ "Ladd" "Lissajous"))
+ @result{} ("E460" "G200" "H416" "K530" "L300" "L222")
@end example
-@end defun
-@example
-(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"))
+Some cases in which the algorithm fails (Knuth):
-@result{} 3553047446
-@end example
+@example
+(map soundex '("Rogers" "Rodgers")) @result{} ("R262" "R326")
-@node Plotting, Root Finding, Cyclic Checksum, Numerics
-@section Plotting on Character Devices
+(map soundex '("Sinclair" "St. Clair")) @result{} ("S524" "S324")
-@code{(require 'charplot)}
+(map soundex '("Tchebysheff" "Chebyshev")) @result{} ("T212" "C121")
+@end example
+@end defun
-The plotting procedure is made available through the use of the
-@code{charplot} package. @code{charplot} is loaded by inserting
-@code{(require 'charplot)} before the code that uses this
-procedure.@refill
-@defvar charplot:height
-The number of rows to make the plot vertically.
-@end defvar
+@node Priority Queues, Queues, Hashing, Data Structures
+@subsection Priority Queues
-@defvar charplot:width
-The number of columns to make the plot horizontally.
-@end defvar
-
-@deffn Procedure plot! coords x-label y-label
-@var{coords} is a list of pairs of x and y coordinates. @var{x-label}
-and @var{y-label} are strings with which to label the x and y
-axes.@refill
+@code{(require 'priority-queue)}
+@ftindex priority-queue
-Example:
-@example
-(require 'charplot)
-(set! charplot:height 19)
-(set! charplot:width 45)
+@defun make-heap pred<?
+Returns a binary heap suitable which can be used for priority queue
+operations.
+@end defun
-(define (make-points n)
- (if (zero? n)
- '()
- (cons (cons (/ n 6) (sin (/ n 6))) (make-points (1- n)))))
+@defun heap-length heap
+Returns the number of elements in @var{heap}.@refill
+@end defun
-(plot! (make-points 37) "x" "Sin(x)")
-@print{}
-@group
- 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
-@end group
-@end example
+@deffn Procedure heap-insert! heap item
+Inserts @var{item} into @var{heap}. @var{item} can be inserted multiple
+times. The value returned is unspecified.@refill
@end deffn
+@defun heap-extract-max! heap
+Returns the item which is larger than all others according to the
+@var{pred<?} argument to @code{make-heap}. If there are no items in
+@var{heap}, an error is signaled.@refill
+@end defun
-@node Root Finding, , Plotting, Numerics
-@section Root Finding
+The algorithm for priority queues was taken from @cite{Introduction to
+Algorithms} by T. Cormen, C. Leiserson, R. Rivest. 1989 MIT Press.
-@code{(require 'root)}
-@defun newtown:find-integer-root f df/dx x0
-Given integer valued procedure @var{f}, its derivative (with respect to
-its argument) @var{df/dx}, and initial integer value @var{x0} for which
-@var{df/dx}(@var{x0}) is non-zero, returns an integer @var{x} for which
-@var{f}(@var{x}) is closer to zero than either of the integers adjacent
-to @var{x}; or returns @code{#f} if such an integer can't be found.
-To find the closest integer to a given integers square root:
+@node Queues, Records, Priority Queues, Data Structures
+@subsection Queues
-@example
-(define (integer-sqrt y)
- (newton:find-integer-root
- (lambda (x) (- (* x x) y))
- (lambda (x) (* 2 x))
- (ash 1 (quotient (integer-length y) 2))))
+@code{(require 'queue)}
+@ftindex queue
-(integer-sqrt 15) @result{} 4
-@end example
-@end defun
+A @dfn{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 @dfn{dequeues}). A queue may also be used like a stack.@refill
-@defun integer-sqrt y
-Given a non-negative integer @var{y}, returns the rounded square-root of
-@var{y}.
+@defun make-queue
+Returns a new, empty queue.
@end defun
-@defun newton:find-root f df/dx x0 prec
-Given real valued procedures @var{f}, @var{df/dx} of one (real)
-argument, initial real value @var{x0} for which @var{df/dx}(@var{x0}) is
-non-zero, and positive real number @var{prec}, returns a real @var{x}
-for which @code{abs}(@var{f}(@var{x})) is less than @var{prec}; or
-returns @code{#f} if such a real can't be found.
-
-If @code{prec} is instead a negative integer, @code{newton:find-root}
-returns the result of -@var{prec} iterations.
+@defun queue? obj
+Returns @code{#t} if @var{obj} is a queue.
@end defun
-@noindent
-H. J. Orchard, @cite{The Laguerre Method for Finding the Zeros of
-Polynomials}, IEEE Transactions on Circuits and Systems, Vol. 36,
-No. 11, November 1989, pp 1377-1381.
+@defun queue-empty? q
+Returns @code{#t} if the queue @var{q} is empty.
+@end defun
-@quotation
-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.
-@end quotation
+@deffn Procedure queue-push! q datum
+Adds @var{datum} to the front of queue @var{q}.
+@end deffn
+@deffn Procedure enquque! q datum
+Adds @var{datum} to the rear of queue @var{q}.
+@end deffn
-@defun laguerre:find-root f df/dz ddf/dz^2 z0 prec
-Given complex valued procedure @var{f} of one (complex) argument, its
-derivative (with respect to its argument) @var{df/dx}, its second
-derivative @var{ddf/dz^2}, initial complex value @var{z0}, and positive
-real number @var{prec}, returns a complex number @var{z} for which
-@code{magnitude}(@var{f}(@var{z})) is less than @var{prec}; or returns
-@code{#f} if such a number can't be found.
+All of the following functions raise an error if the queue @var{q} is
+empty.@refill
-If @code{prec} is instead a negative integer, @code{laguerre:find-root}
-returns the result of -@var{prec} iterations.
+@defun queue-front q
+Returns the datum at the front of the queue @var{q}.
@end defun
-@defun laguerre:find-polynomial-root deg f df/dz ddf/dz^2 z0 prec
-Given polynomial procedure @var{f} of integer degree @var{deg} of one
-argument, its derivative (with respect to its argument) @var{df/dx}, its
-second derivative @var{ddf/dz^2}, initial complex value @var{z0}, and
-positive real number @var{prec}, returns a complex number @var{z} for
-which @code{magnitude}(@var{f}(@var{z})) is less than @var{prec}; or
-returns @code{#f} if such a number can't be found.
-
-If @code{prec} is instead a negative integer,
-@code{laguerre:find-polynomial-root} returns the result of -@var{prec}
-iterations.
+@defun queue-rear q
+Returns the datum at the rear of the queue @var{q}.
@end defun
+@deffn Prcoedure queue-pop! q
+@deffnx Procedure dequeue! q
+Both of these procedures remove and return the datum at the front of the
+queue. @code{queue-pop!} is used to suggest that the queue is being
+used like a stack.@refill
+@end deffn
-@node Procedures, Standards Support, Numerics, Top
-@chapter Procedures
-
-Anything that doesn't fall neatly into any of the other categories winds
-up here.
-@menu
-* Batch:: 'batch
-* Common List Functions:: 'common-list-functions
-* Format:: 'format
-* Generic-Write:: 'generic-write
-* Line I/O:: 'line-i/o
-* Multi-Processing:: 'process
-* Object-To-String:: 'object->string
-* Pretty-Print:: 'pretty-print, 'pprint-file
-* Sorting:: 'sort
-* Topological Sort::
-* Standard Formatted I/O:: 'printf, 'scanf
-* String-Case:: 'string-case
-* String Ports:: 'string-port
-* String Search::
-* Tektronix Graphics Support::
-* Tree Operations:: 'tree
-@end menu
-@node Batch, Common List Functions, Procedures, Procedures
-@section Batch
-@code{(require 'batch)}
-@noindent
-The batch procedures provide a way to write and execute portable scripts
-for a variety of operating systems. Each @code{batch:} procedure takes
-as its first argument a parameter-list (@pxref{Parameter lists}). This
-parameter-list argument @var{parms} contains named associations. Batch
-currently uses 2 of these:
+@node Records, Structures, Queues, Data Structures
+@subsection Records
-@table @code
-@item batch-port
-The port on which to write lines of the batch file.
-@item batch-dialect
-The syntax of batch file to generate. Currently supported are:
-@itemize @bullet
-@item
-unix
-@item
-dos
-@item
-vms
-@item
-system
-@item
-*unknown*
-@end itemize
-@end table
+@code{(require 'record)}
+@ftindex record
-@noindent
-@file{batch.scm} uses 2 enhanced relational tables (@pxref{Database
-Utilities}) to store information linking the names of
-@code{operating-system}s to @code{batch-dialect}es.
+The Record package provides a facility for user to define their own
+record data types.
-@defun batch:initialize! database
-Defines @code{operating-system} and @code{batch-dialect} tables and adds
-the domain @code{operating-system} to the enhanced relational database
-@var{database}.
+@defun make-record-type type-name field-names
+Returns a @dfn{record-type descriptor}, a value representing a new data
+type disjoint from all others. The @var{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 @var{field-names}
+argument is a list of symbols naming the @dfn{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.@refill
@end defun
-@defvar batch:platform
-Is batch's best guess as to which operating-system it is running under.
-@code{batch:platform} is set to @code{(software-type)}
-(@pxref{Configuration}) unless @code{(software-type)} is @code{unix},
-in which case finer distinctions are made.
-@end defvar
+@c @defun make-record-sub-type type-name field-names rtd
+@c Returns a @dfn{record-type descriptor}, a value representing a new data
+@c type, disjoint from all others. The @var{type-name} argument must be a
+@c string. The @var{field-names} argument is a list of symbols naming the
+@c additional @dfn{fields} to be appended to @var{field-names} of
+@c @var{rtd}. It is an error if the combinded list contains any
+@c duplicates.@refill
+@c
+@c Record-modifiers and record-accessors for @var{rtd} work for the new
+@c record-sub-type as well. But record-modifiers and record-accessors for
+@c the new record-sub-type will not neccessarily work for @var{rtd}.@refill
+@c @end defun
-@defun batch:call-with-output-script parms file proc
-@var{proc} should be a procedure of one argument. If @var{file} is an
-output-port, @code{batch:call-with-output-script} writes an appropriate
-header to @var{file} and then calls @var{proc} with @var{file} as the
-only argument. If @var{file} is a string,
-@code{batch:call-with-output-script} opens a output-file of name
-@var{file}, writes an appropriate header to @var{file}, and then calls
-@var{proc} with the newly opened port as the only argument. Otherwise,
-@code{batch:call-with-output-script} acts as if it was called with the
-result of @code{(current-output-port)} as its third argument.
+@defun record-constructor rtd [field-names]
+Returns a procedure for constructing new members of the type represented
+by @var{rtd}. The returned procedure accepts exactly as many arguments
+as there are symbols in the given list, @var{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 @var{field-names}
+argument defaults to the list of field names in the call to
+@code{make-record-type} that created the type represented by @var{rtd};
+if the @var{field-names} argument is provided, it is an error if it
+contains any duplicates or any symbols not in the default list.@refill
@end defun
-@defun batch:apply-chop-to-fit proc arg1 arg2 @dots{} list
-The procedure @var{proc} must accept at least one argument and return
-@code{#t} if successful, @code{#f} if not.
-@code{batch:apply-chop-to-fit} calls @var{proc} with @var{arg1},
-@var{arg2}, @dots{}, and @var{chunk}, where @var{chunk} is a subset of
-@var{list}. @code{batch:apply-chop-to-fit} tries @var{proc} with
-successively smaller subsets of @var{list} until either @var{proc}
-returns non-false, or the @var{chunk}s become empty.
+@defun record-predicate rtd
+Returns a procedure for testing membership in the type represented by
+@var{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.@refill
@end defun
-@noindent
-The rest of the @code{batch:} procedures write (or execute if
-@code{batch-dialect} is @code{system}) commands to the batch port which
-has been added to @var{parms} or @code{(copy-tree @var{parms})} by the
-code:
-
-@example
-(adjoin-parameters! @var{parms} (list 'batch-port @var{port}))
-@end example
+@c @defun record-sub-predicate rtd
+@c Returns a procedure for testing membership in the type represented by
+@c @var{rtd} or its parents. The returned procedure accepts exactly one
+@c argument and returns a true value if the argument is a member of the
+@c indicated record type or its parents; it returns a false value
+@c otherwise.@refill
+@c @end defun
-@defun batch:system parms string1 string2 @dots{}
-Calls @code{batch:try-system} (below) with arguments, but signals an
-error if @code{batch:try-system} returns @code{#f}.
+@defun record-accessor rtd field-name
+Returns a procedure for reading the value of a particular field of a
+member of the type represented by @var{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
+@var{field-name} in that record. The symbol @var{field-name} must be a
+member of the list of field-names in the call to @code{make-record-type}
+that created the type represented by @var{rtd}.@refill
@end defun
-@noindent
-These functions return a non-false value if the command was successfully
-translated into the batch dialect and @code{#f} if not. In the case of
-the @code{system} dialect, the value is non-false if the operation
-suceeded.
-@defun batch:try-system parms string1 string2 @dots{}
-Writes a command to the @code{batch-port} in @var{parms} which executes
-the program named @var{string1} with arguments @var{string2} @dots{}.
+@defun record-modifier rtd field-name
+Returns a procedure for writing the value of a particular field of a
+member of the type represented by @var{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 @var{field-name} in that record to contain the given value.
+The returned value of the modifier procedure is unspecified. The symbol
+@var{field-name} must be a member of the list of field-names in the call
+to @code{make-record-type} that created the type represented by
+@var{rtd}.@refill
@end defun
-@defun batch:run-script parms string1 string2 @dots{}
-Writes a command to the @code{batch-port} in @var{parms} which executes
-the batch script named @var{string1} with arguments @var{string2}
-@dots{}.
+In May of 1996, as a product of discussion on the @code{rrrs-authors}
+mailing list, I rewrote @file{record.scm} to portably implement type
+disjointness for record data types.
-@emph{Note:} @code{batch:run-script} and @code{batch:try-system} are not the
-same for some operating systems (VMS).
-@end defun
+As long as an implementation's procedures are opaque and the
+@code{record} code is loaded before other programs, this will give
+disjoint record types which are unforgeable and incorruptible by R4RS
+procedures.
-@defun batch:comment parms line1 @dots{}
-Writes comment lines @var{line1} @dots{} to the @code{batch-port} in
-@var{parms}.
-@end defun
+As a consequence, the procedures @code{record?},
+@code{record-type-descriptor}, @code{record-type-name}.and
+@code{record-type-field-names} are no longer supported.
-@defun batch:lines->file parms file line1 @dots{}
-Writes commands to the @code{batch-port} in @var{parms} which create a
-file named @var{file} with contents @var{line1} @dots{}.
+@ignore
+@defun record? obj
+Returns a true value if @var{obj} is a record of any type and a false
+value otherwise. Note that @code{record?} may be true of any Scheme
+value; of course, if it returns true for some particular value, then
+@code{record-type-descriptor} is applicable to that value and returns an
+appropriate descriptor.@refill
@end defun
-@defun batch:delete-file parms file
-Writes a command to the @code{batch-port} in @var{parms} which deletes
-the file named @var{file}.
+@defun record-type-descriptor record
+Returns a record-type descriptor representing the type of the given
+record. That is, for example, if the returned descriptor were passed to
+@code{record-predicate}, the resulting predicate would return a true
+value when passed the given record. Note that it is not necessarily the
+case that the returned descriptor is the one that was passed to
+@code{record-constructor} in the call that created the constructor
+procedure that created the given record.@refill
@end defun
-@defun batch:rename-file parms old-name new-name
-Writes a command to the @code{batch-port} in @var{parms} which renames
-the file @var{old-name} to @var{new-name}.
+@defun record-type-name rtd
+Returns the type-name associated with the type represented by rtd. The
+returned value is @code{eqv?} to the @var{type-name} argument given in
+the call to @code{make-record-type} that created the type represented by
+@var{rtd}.@refill
@end defun
-@noindent
-In addition, batch provides some small utilities very useful for writing
-scripts:
-
-@defun replace-suffix str old new
-Returns a new string similar to @code{str} but with the suffix string
-@var{old} removed and the suffix string @var{new} appended. If the end
-of @var{str} does not match @var{old}, an error is signaled.
+@defun record-type-field-names rtd
+Returns a list of the symbols naming the fields in members of the type
+represented by @var{rtd}. The returned value is @code{equal?} to the
+field-names argument given in the call to @code{make-record-type} that
+created the type represented by @var{rtd}.@refill
@end defun
+@end ignore
-@defun string-join joiner string1 @dots{}
-Returns a new string consisting of all the strings @var{string1} @dots{}
-in order appended together with the string @var{joiner} between each
-adjacent pair.
-@end defun
-@defun must-be-first list1 list2
-Returns a new list consisting of the elements of @var{list2} ordered so
-that if some elements of @var{list1} are @code{equal?} to elements of
-@var{list2}, then those elements will appear first and in the order of
-@var{list1}.
-@end defun
+@node Structures, , Records, Data Structures
+@subsection Structures
-@defun must-be-last list1 list2
-Returns a new list consisting of the elements of @var{list1} ordered so
-that if some elements of @var{list2} are @code{equal?} to elements of
-@var{list1}, then those elements will appear last and in the order of
-@var{list2}.
-@end defun
+@code{(require 'struct)} (uses defmacros)
+@ftindex struct
-@defun os->batch-dialect osname
-Returns its best guess for the @code{batch-dialect} to be used for the
-operating-system named @var{osname}. @code{os->batch-dialect} uses the
-tables added to @var{database} by @code{batch:initialize!}.
-@end defun
+@code{defmacro}s which implement @dfn{records} from the book
+@cite{Essentials of Programming Languages} by Daniel P. Friedman, M.
+Wand and C.T. Haynes. Copyright 1992 Jeff Alexander, Shinnder Lee, and
+Lewis Patterson@refill
-@noindent
-Here is an example of the use of most of batch's procedures:
+Matthew McDonald <mafm@@cs.uwa.edu.au> added field setters.
-@example
-(require 'database-utilities)
-(require 'parameters)
-(require 'batch)
+@defmac define-record tag (var1 var2 @dots{})
+Defines several functions pertaining to record-name @var{tag}:
-(define batch (create-database #f 'alist-table))
-(batch:initialize! batch)
+@defun make-@var{tag} var1 var2 @dots{}
+@end defun
+@defun @var{tag}? obj
+@end defun
+@defun @var{tag}->var1 obj
+@end defun
+@defun @var{tag}->var2 obj
+@end defun
+@dots{}
+@defun set-@var{tag}-var1! obj val
+@end defun
+@defun set-@var{tag}-var2! obj val
+@end defun
+@dots{}
-(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
+Here is an example of its use.
-(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:system my-parameters "cc" "-c" "hello.c")
- (batch:system my-parameters "cc" "-o" "hello"
- (replace-suffix "hello.c" ".c" ".o"))
- (batch:system 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")
- )))
+@example
+(define-record term (operator left right))
+@result{} #<unspecified>
+(define foo (make-term 'plus 1 2))
+@result{} foo
+(term->left foo)
+@result{} 1
+(set-term-left! foo 2345)
+@result{} #<unspecified>
+(term->left foo)
+@result{} 2345
@end example
+@end defmac
-@noindent
-Produces the file @file{my-batch}:
+@defmac variant-case exp (tag (var1 var2 @dots{}) body) @dots{}
+executes the following for the matching clause:
@example
-#!/bin/sh
-# "my-batch" build script created Sat Jun 10 21:20:37 1995
-# ================ 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
+((lambda (@var{var1} @var{var} @dots{}) @var{body})
+ (@var{tag->var1} @var{exp})
+ (@var{tag->var2} @var{exp}) @dots{})
@end example
+@end defmac
-@noindent
-When run, @file{my-batch} prints:
-@example
-bash$ my-batch
-mv: hello.c: No such file or directory
-hello world
-@end example
+@node Procedures, Standards Support, Data Structures, Other Packages
+@section 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
+@end menu
-@node Common List Functions, Format, Batch, Procedures
-@section Common List Functions
+@node Common List Functions, Tree Operations, Procedures, Procedures
+@subsection Common List Functions
@code{(require 'common-list-functions)}
+@ftindex common-list-functions
The procedures below follow the Common LISP equivalents apart from
optional arguments in some cases.
@@ -5609,7 +8540,7 @@ optional arguments in some cases.
@node List construction, Lists as sets, Common List Functions, Common List Functions
-@subsection List construction
+@subsubsection List construction
@defun make-list k . init
@code{make-list} creates and returns a list of @var{k} elements. If
@@ -5674,7 +8605,7 @@ Example:
@node Lists as sets, Lists as sequences, List construction, Common List Functions
-@subsection Lists as sets
+@subsubsection Lists as sets
@code{eq?} is used to test for membership by all the procedures below
which treat lists as sets.@refill
@@ -5887,7 +8818,7 @@ Example:
@node Lists as sequences, Destructive list operations, Lists as sets, Common List Functions
-@subsection Lists as sequences
+@subsubsection Lists as sequences
@defun position obj lst
@code{position} returns the 0-based position of @var{obj} in @var{lst},
@@ -5948,7 +8879,7 @@ in terms of @code{reduce} and a combinator elsewhere called
(define reverse
(lambda (args)
- (reduce-init (commute cons) args)))
+ (reduce-init (commute cons) '() args)))
@end lisp
@end defun
@@ -6009,19 +8940,42 @@ Example:
@end lisp
@end defun
+@defun last lst n
+@code{last} returns the last @var{n} elements of @var{lst}. @var{n}
+must be a non-negative integer.
+
+Example:
+@lisp
+(last '(foo bar baz bang) 2)
+ @result{} (baz bang)
+(last '(1 2 3) 0)
+ @result{} 0
+@end lisp
+@end defun
+
@defun butlast lst n
@code{butlast} returns all but the last @var{n} elements of
@var{lst}.@refill
Example:
@lisp
-(butlast '(1 2 3 4) 3)
- @result{} (1)
-(butlast '(1 2 3 4) 4)
+(butlast '(a b c d) 3)
+ @result{} (a)
+(butlast '(a b c d) 4)
@result{} ()
@end lisp
@end defun
+@noindent
+@code{last} and @code{butlast} split a list into two parts when given
+identical arugments.
+@example
+(last '(a b c d e) 2)
+ @result{} (d e)
+(butlast '(a b c d e) 2)
+ @result{} (a b c)
+@end example
+
@defun nthcdr n lst
@code{nthcdr} takes @var{n} @code{cdr}s of @var{lst} and returns the
result. Thus @code{(nthcdr 3 @var{lst})} @equiv{} @code{(cdddr
@@ -6029,33 +8983,40 @@ result. Thus @code{(nthcdr 3 @var{lst})} @equiv{} @code{(cdddr
Example:
@lisp
-(nthcdr 2 '(1 2 3 4))
- @result{} (3 4)
-(nthcdr 0 '(1 2 3 4))
- @result{} (1 2 3 4)
+(nthcdr 2 '(a b c d))
+ @result{} (c d)
+(nthcdr 0 '(a b c d))
+ @result{} (a b c d)
@end lisp
@end defun
-@defun last lst n
-@code{last} returns the last @var{n} elements of @var{lst}. @var{n}
-must be a non-negative integer.
+@defun butnthcdr n lst
+@code{butnthcdr} returns all but the nthcdr @var{n} elements of
+@var{lst}.@refill
Example:
@lisp
-(last '(foo bar baz bang) 2)
- @result{} (baz bang)
-(last '(1 2 3) 0)
- @result{} 0
+(butnthcdr 3 '(a b c d))
+ @result{} (a b c)
+(butnthcdr 4 '(a b c d))
+ @result{} ()
@end lisp
@end defun
-
-
+@noindent
+@code{nthcdr} and @code{butnthcdr} split a list into two parts when
+given identical arugments.
+@example
+(nthcdr 2 '(a b c d e))
+ @result{} (c d e)
+(butnthcdr 2 '(a b c d e))
+ @result{} (a b)
+@end example
@node Destructive list operations, Non-List functions, Lists as sequences, Common List Functions
-@subsection Destructive list operations
+@subsubsection Destructive list operations
These procedures may mutate the list they operate on, but any such
mutation is undefined.
@@ -6157,7 +9118,7 @@ The examples should suffice to show why this is the case.
@node Non-List functions, , Destructive list operations, Common List Functions
-@subsection Non-List functions
+@subsubsection Non-List functions
@defun and? . args
@code{and?} checks to see if all its arguments are true. If they are,
@@ -6211,637 +9172,105 @@ Converts and returns @var{object} of type @code{char}, @code{number},
@var{result-type} (which must be one of these symbols).
@end defun
-@node Format, Generic-Write, Common List Functions, Procedures
-@section Format
-
-@code{(require 'format)}
-
-@menu
-* Format Interface::
-* Format Specification::
-@end menu
-
-@node Format Interface, Format Specification, Format, Format
-@subsection Format Interface
-
-@defun format destination format-string . arguments
-An almost complete implementation of Common LISP format description
-according to the CL reference book @cite{Common LISP} from Guy L.
-Steele, Digital Press. Backward compatible to most of the available
-Scheme format implementations.
-
-Returns @code{#t}, @code{#f} or a string; has side effect of printing
-according to @var{format-string}. If @var{destination} is @code{#t},
-the output is to the current output port and @code{#t} is returned. If
-@var{destination} is @code{#f}, a formatted string is returned as the
-result of the call. NEW: If @var{destination} is a string,
-@var{destination} is regarded as the format string; @var{format-string} is
-then the first argument and the output is returned as a string. If
-@var{destination} is a number, the output is to the current error port
-if available by the implementation. Otherwise @var{destination} must be
-an output port and @code{#t} is returned.@refill
-
-@var{format-string} must be a string. In case of a formatting error
-format returns @code{#f} and prints a message on the current output or
-error port. Characters are output as if the string were output by the
-@code{display} function with the exception of those prefixed by a tilde
-(~). For a detailed description of the @var{format-string} syntax
-please consult a Common LISP format reference manual. For a test suite
-to verify this format implementation load @file{formatst.scm}. Please
-send bug reports to @code{lutzeb@@cs.tu-berlin.de}.
-
-Note: @code{format} is not reentrant, i.e. only one @code{format}-call
-may be executed at a time.
-
-@end defun
-
-@node Format Specification, , Format Interface, Format
-@subsection 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 @file{formatst.scm}.@refill
-
-This implementation supports directive parameters and modifiers
-(@code{:} and @code{@@} characters). Multiple parameters must be
-separated by a comma (@code{,}). Parameters can be numerical parameters
-(positive or negative), character parameters (prefixed by a quote
-character (@code{'}), variable parameters (@code{v}), number of rest
-arguments parameter (@code{#}), empty and default parameters. Directive
-characters are case independent. The general form of a directive
-is:@refill
-
-@noindent
-@var{directive} ::= ~@{@var{directive-parameter},@}[:][@@]@var{directive-character}
-
-@noindent
-@var{directive-parameter} ::= [ [-|+]@{0-9@}+ | '@var{character} | v | # ]
-
-
-@subsubsection Implemented CL Format Control Directives
-
-Documentation syntax: Uppercase characters represent the corresponding
-control directive characters. Lowercase characters represent control
-directive parameter descriptions.
-
-@table @asis
-@item @code{~A}
-Any (print as @code{display} does).
-@table @asis
-@item @code{~@@A}
-left pad.
-@item @code{~@var{mincol},@var{colinc},@var{minpad},@var{padchar}A}
-full padding.
-@end table
-@item @code{~S}
-S-expression (print as @code{write} does).
-@table @asis
-@item @code{~@@S}
-left pad.
-@item @code{~@var{mincol},@var{colinc},@var{minpad},@var{padchar}S}
-full padding.
-@end table
-@item @code{~D}
-Decimal.
-@table @asis
-@item @code{~@@D}
-print number sign always.
-@item @code{~:D}
-print comma separated.
-@item @code{~@var{mincol},@var{padchar},@var{commachar}D}
-padding.
-@end table
-@item @code{~X}
-Hexadecimal.
-@table @asis
-@item @code{~@@X}
-print number sign always.
-@item @code{~:X}
-print comma separated.
-@item @code{~@var{mincol},@var{padchar},@var{commachar}X}
-padding.
-@end table
-@item @code{~O}
-Octal.
-@table @asis
-@item @code{~@@O}
-print number sign always.
-@item @code{~:O}
-print comma separated.
-@item @code{~@var{mincol},@var{padchar},@var{commachar}O}
-padding.
-@end table
-@item @code{~B}
-Binary.
-@table @asis
-@item @code{~@@B}
-print number sign always.
-@item @code{~:B}
-print comma separated.
-@item @code{~@var{mincol},@var{padchar},@var{commachar}B}
-padding.
-@end table
-@item @code{~@var{n}R}
-Radix @var{n}.
-@table @asis
-@item @code{~@var{n},@var{mincol},@var{padchar},@var{commachar}R}
-padding.
-@end table
-@item @code{~@@R}
-print a number as a Roman numeral.
-@item @code{~:R}
-print a number as an ordinal English number.
-@item @code{~:@@R}
-print a number as a cardinal English number.
-@item @code{~P}
-Plural.
-@table @asis
-@item @code{~@@P}
-prints @code{y} and @code{ies}.
-@item @code{~:P}
-as @code{~P but jumps 1 argument backward.}
-@item @code{~:@@P}
-as @code{~@@P but jumps 1 argument backward.}
-@end table
-@item @code{~C}
-Character.
-@table @asis
-@item @code{~@@C}
-prints a character as the reader can understand it (i.e. @code{#\} prefixing).
-@item @code{~:C}
-prints a character as emacs does (eg. @code{^C} for ASCII 03).
-@end table
-@item @code{~F}
-Fixed-format floating-point (prints a flonum like @var{mmm.nnn}).
-@table @asis
-@item @code{~@var{width},@var{digits},@var{scale},@var{overflowchar},@var{padchar}F}
-@item @code{~@@F}
-If the number is positive a plus sign is printed.
-@end table
-@item @code{~E}
-Exponential floating-point (prints a flonum like @var{mmm.nnn@code{E}ee}).
-@table @asis
-@item @code{~@var{width},@var{digits},@var{exponentdigits},@var{scale},@var{overflowchar},@var{padchar},@var{exponentchar}E}
-@item @code{~@@E}
-If the number is positive a plus sign is printed.
-@end table
-@item @code{~G}
-General floating-point (prints a flonum either fixed or exponential).
-@table @asis
-@item @code{~@var{width},@var{digits},@var{exponentdigits},@var{scale},@var{overflowchar},@var{padchar},@var{exponentchar}G}
-@item @code{~@@G}
-If the number is positive a plus sign is printed.
-@end table
-@item @code{~$}
-Dollars floating-point (prints a flonum in fixed with signs separated).
-@table @asis
-@item @code{~@var{digits},@var{scale},@var{width},@var{padchar}$}
-@item @code{~@@$}
-If the number is positive a plus sign is printed.
-@item @code{~:@@$}
-A sign is always printed and appears before the padding.
-@item @code{~:$}
-The sign appears before the padding.
-@end table
-@item @code{~%}
-Newline.
-@table @asis
-@item @code{~@var{n}%}
-print @var{n} newlines.
-@end table
-@item @code{~&}
-print newline if not at the beginning of the output line.
-@table @asis
-@item @code{~@var{n}&}
-prints @code{~&} and then @var{n-1} newlines.
-@end table
-@item @code{~|}
-Page Separator.
-@table @asis
-@item @code{~@var{n}|}
-print @var{n} page separators.
-@end table
-@item @code{~~}
-Tilde.
-@table @asis
-@item @code{~@var{n}~}
-print @var{n} tildes.
-@end table
-@item @code{~}<newline>
-Continuation Line.
-@table @asis
-@item @code{~:}<newline>
-newline is ignored, white space left.
-@item @code{~@@}<newline>
-newline is left, white space ignored.
-@end table
-@item @code{~T}
-Tabulation.
-@table @asis
-@item @code{~@@T}
-relative tabulation.
-@item @code{~@var{colnum,colinc}T}
-full tabulation.
-@end table
-@item @code{~?}
-Indirection (expects indirect arguments as a list).
-@table @asis
-@item @code{~@@?}
-extracts indirect arguments from format arguments.
-@end table
-@item @code{~(@var{str}~)}
-Case conversion (converts by @code{string-downcase}).
-@table @asis
-@item @code{~:(@var{str}~)}
-converts by @code{string-capitalize}.
-@item @code{~@@(@var{str}~)}
-converts by @code{string-capitalize-first}.
-@item @code{~:@@(@var{str}~)}
-converts by @code{string-upcase}.
-@end table
-@item @code{~*}
-Argument Jumping (jumps 1 argument forward).
-@table @asis
-@item @code{~@var{n}*}
-jumps @var{n} arguments forward.
-@item @code{~:*}
-jumps 1 argument backward.
-@item @code{~@var{n}:*}
-jumps @var{n} arguments backward.
-@item @code{~@@*}
-jumps to the 0th argument.
-@item @code{~@var{n}@@*}
-jumps to the @var{n}th argument (beginning from 0)
-@end table
-@item @code{~[@var{str0}~;@var{str1}~;...~;@var{strn}~]}
-Conditional Expression (numerical clause conditional).
-@table @asis
-@item @code{~@var{n}[}
-take argument from @var{n}.
-@item @code{~@@[}
-true test conditional.
-@item @code{~:[}
-if-else-then conditional.
-@item @code{~;}
-clause separator.
-@item @code{~:;}
-default clause follows.
-@end table
-@item @code{~@{@var{str}~@}}
-Iteration (args come from the next argument (a list)).
-@table @asis
-@item @code{~@var{n}@{}
-at most @var{n} iterations.
-@item @code{~:@{}
-args from next arg (a list of lists).
-@item @code{~@@@{}
-args from the rest of arguments.
-@item @code{~:@@@{}
-args from the rest args (lists).
-@end table
-@item @code{~^}
-Up and out.
-@table @asis
-@item @code{~@var{n}^}
-aborts if @var{n} = 0
-@item @code{~@var{n},@var{m}^}
-aborts if @var{n} = @var{m}
-@item @code{~@var{n},@var{m},@var{k}^}
-aborts if @var{n} <= @var{m} <= @var{k}
-@end table
-@end table
-
-
-@subsubsection Not Implemented CL Format Control Directives
-
-@table @asis
-@item @code{~:A}
-print @code{#f} as an empty list (see below).
-@item @code{~:S}
-print @code{#f} as an empty list (see below).
-@item @code{~<~>}
-Justification.
-@item @code{~:^}
-(sorry I don't understand its semantics completely)
-@end table
-
-
-@subsubsection Extended, Replaced and Additional Control Directives
-
-@table @asis
-@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}D}
-@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}X}
-@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}O}
-@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}B}
-@item @code{~@var{n},@var{mincol},@var{padchar},@var{commachar},@var{commawidth}R}
-@var{commawidth} is the number of characters between two comma characters.
-@end table
-
-@table @asis
-@item @code{~I}
-print a R4RS complex number as @code{~F~@@Fi} with passed parameters for
-@code{~F}.
-@item @code{~Y}
-Pretty print formatting of an argument for scheme code lists.
-@item @code{~K}
-Same as @code{~?.}
-@item @code{~!}
-Flushes the output if format @var{destination} is a port.
-@item @code{~_}
-Print a @code{#\space} character
-@table @asis
-@item @code{~@var{n}_}
-print @var{n} @code{#\space} characters.
-@end table
-@item @code{~/}
-Print a @code{#\tab} character
-@table @asis
-@item @code{~@var{n}/}
-print @var{n} @code{#\tab} characters.
-@end table
-@item @code{~@var{n}C}
-Takes @var{n} as an integer representation for a character. No arguments
-are consumed. @var{n} is converted to a character by
-@code{integer->char}. @var{n} must be a positive decimal number.@refill
-@item @code{~:S}
-Print out readproof. Prints out internal objects represented as
-@code{#<...>} as strings @code{"#<...>"} so that the format output can always
-be processed by @code{read}.
-@refill
-@item @code{~:A}
-Print out readproof. Prints out internal objects represented as
-@code{#<...>} as strings @code{"#<...>"} so that the format output can always
-be processed by @code{read}.
-@item @code{~Q}
-Prints information and a copyright notice on the format implementation.
-@table @asis
-@item @code{~:Q}
-prints format version.
-@end table
-@refill
-@item @code{~F, ~E, ~G, ~$}
-may also print number strings, i.e. passing a number as a string and
-format it accordingly.
-@end table
-
-@subsubsection Configuration Variables
-
-Format has some configuration variables at the beginning of
-@file{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.
-
-@table @asis
-
-@item @var{format:symbol-case-conv}
-Symbols are converted by @code{symbol->string} so the case type of the
-printed symbols is implementation dependent.
-@code{format:symbol-case-conv} is a one arg closure which is either
-@code{#f} (no conversion), @code{string-upcase}, @code{string-downcase}
-or @code{string-capitalize}. (default @code{#f})
-
-@item @var{format:iobj-case-conv}
-As @var{format:symbol-case-conv} but applies for the representation of
-implementation internal objects. (default @code{#f})
-
-@item @var{format:expch}
-The character prefixing the exponent value in @code{~E} printing. (default
-@code{#\E})
-
-@end table
-
-@subsubsection Compatibility With Other Format Implementations
-
-@table @asis
-@item SLIB format 2.x:
-See @file{format.doc}.
-
-@item SLIB format 1.4:
-Downward compatible except for padding support and @code{~A}, @code{~S},
-@code{~P}, @code{~X} uppercase printing. SLIB format 1.4 uses C-style
-@code{printf} padding support which is completely replaced by the CL
-@code{format} padding style.
-@item MIT C-Scheme 7.1:
-Downward compatible except for @code{~}, which is not documented
-(ignores all characters inside the format string up to a newline
-character). (7.1 implements @code{~a}, @code{~s},
-~@var{newline}, @code{~~}, @code{~%}, numerical and variable
-parameters and @code{:/@@} modifiers in the CL sense).@refill
-
-@item Elk 1.5/2.0:
-Downward compatible except for @code{~A} and @code{~S} which print in
-uppercase. (Elk implements @code{~a}, @code{~s}, @code{~~}, and
-@code{~%} (no directive parameters or modifiers)).@refill
-
-@item 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
-@code{~a}, @code{~s}, @code{~c}, @code{~%}, and @code{~~} (no directive
-parameters or modifiers)).@refill
+@node Tree Operations, Chapter Ordering, Common List Functions, Procedures
+@subsection Tree operations
-@end table
-
-This implementation of format is solely useful in the SLIB context
-because it requires other components provided by SLIB.@refill
-
-
-@node Generic-Write, Line I/O, Format, Procedures
-@section Generic-Write
-
-@code{(require 'generic-write)}
+@code{(require 'tree)}
+@ftindex tree
-@code{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.@refill
+These are operations that treat lists a representations of trees.
-@deffn Procedure generic-write obj display? width output
-@table @var
-@item obj
-Scheme data value to transform.
-@item display?
-Boolean, controls whether characters and strings are quoted.
-@item width
-Extended boolean, selects format:
-@table @asis
-@item #f
-single line format
-@item integer > 0
-pretty-print (value = max nb of chars per line)
-@end table
-@item output
-Procedure of 1 argument of string type, called repeatedly with
-successive substrings of the textual representation. This procedure can
-return @code{#f} to stop the transformation.
-@end table
+@defun subst new old tree
+@defunx substq new old tree
+@defunx substv new old tree
+@code{subst} makes a copy of @var{tree}, substituting @var{new} for
+every subtree or leaf of @var{tree} which is @code{equal?} to @var{old}
+and returns a modified tree. The original @var{tree} is unchanged, but
+may share parts with the result.@refill
-The value returned by @code{generic-write} is undefined.
+@code{substq} and @code{substv} are similar, but test against @var{old}
+using @code{eq?} and @code{eqv?} respectively.@refill
Examples:
@lisp
-(write obj) @equiv{} (generic-write obj #f #f @var{display-string})
-(display obj) @equiv{} (generic-write obj #t #f @var{display-string})
-@end lisp
-@noindent
-where
-@lisp
-@var{display-string} @equiv{}
-(lambda (s) (for-each write-char (string->list s)) #t)
+(substq 'tempest 'hurricane '(shakespeare wrote (the hurricane)))
+ @result{} (shakespeare wrote (the tempest))
+(substq 'foo '() '(shakespeare wrote (twelfth night)))
+ @result{} (shakespeare wrote (twelfth night . foo) . foo)
+(subst '(a . cons) '(old . pair)
+ '((old . spice) ((old . shoes) old . pair) (old . pair)))
+ @result{} ((old . spice) ((old . shoes) a . cons) (a . cons))
@end lisp
-@end deffn
-
-
-
-
-
-@node Line I/O, Multi-Processing, Generic-Write, Procedures
-@section Line I/O
-
-@code{(require 'line-i/o)}
-
-@defun read-line
-@defunx read-line port
-Returns a string of the characters up to, but not including a newline or
-end of file, updating @var{port} to point to the character following the
-newline. If no characters are available, an end of file object is
-returned. @var{port} may be omitted, in which case it defaults to the
-value returned by @code{current-input-port}.@refill
-@end defun
-
-@defun read-line! string
-@defunx read-line! string port
-Fills @var{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, @code{#f}
-is returned. @var{port} may be omitted, in which case it defaults to
-the value returned by @code{current-input-port}.@refill
-@end defun
-
-@defun write-line string
-@defunx write-line string port
-Writes @var{string} followed by a newline to the given port and returns
-an unspecified value. Port may be omited, in which case it defaults to
-the value returned by @code{current-input-port}.@refill
@end defun
+@defun copy-tree tree
+Makes a copy of the nested list structure @var{tree} using new pairs and
+returns it. All levels are copied, so that none of the pairs in the
+tree are @code{eq?} to the original ones -- only the leaves are.@refill
-
-
-@node Multi-Processing, Object-To-String, Line I/O, Procedures
-@section Multi-Processing
-
-@code{(require 'process)}
-
-@deffn Procedure add-process! proc
-Adds proc, which must be a procedure (or continuation) capable of
-accepting accepting one argument, to the @code{process:queue}. The
-value returned is unspecified. The argument to @var{proc} should be
-ignored. If @var{proc} returns, the process is killed.@refill
-@end deffn
-
-@deffn Procedure process:schedule!
-Saves the current process on @code{process:queue} and runs the next
-process from @code{process:queue}. The value returned is
-unspecified.@refill
-@end deffn
-
-
-@deffn Procedure kill-process!
-Kills the current process and runs the next process from
-@code{process:queue}. If there are no more processes on
-@code{process:queue}, @code{(slib:exit)} is called (@xref{System}).
-@end deffn
-
-
-
-
-
-@node Object-To-String, Pretty-Print, Multi-Processing, Procedures
-@section Object-To-String
-
-@code{(require 'object->string)}
-
-@defun object->string obj
-Returns the textual representation of @var{obj} as a string.
+Example:
+@lisp
+(define bar '(bar))
+(copy-tree (list bar 'foo))
+ @result{} ((bar) foo)
+(eq? bar (car (copy-tree (list bar 'foo))))
+ @result{} #f
+@end lisp
@end defun
+@node Chapter Ordering, Sorting, Tree Operations, Procedures
+@subsection Chapter Ordering
+@code{(require 'chapter-order)}
+@ftindex chapter-order
-@node Pretty-Print, Sorting, Object-To-String, Procedures
-@section Pretty-Print
-
-@code{(require 'pretty-print)}
-
-@deffn Procedure pretty-print obj
-@deffnx Procedure pretty-print obj port
+The @samp{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.
-@code{pretty-print}s @var{obj} on @var{port}. If @var{port} is not
-specified, @code{current-output-port} is used.
+@defun 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 @var{string1} is
+@code{string<?} than the corresponding non-matching run of characters of
+@var{string2}.
-Example:
@example
-@group
-(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)))
- @print{} ((1 2 3 4 5)
- @print{} (6 7 8 9 10)
- @print{} (11 12 13 14 15)
- @print{} (16 17 18 19 20)
- @print{} (21 22 23 24 25))
-@end group
+(chap:string<? "a.9" "a.10") @result{} #t
+(chap:string<? "4c" "4aa") @result{} #t
+(chap:string<? "Revised^@{3.99@}" "Revised^@{4@}") @result{} #t
@end example
-@end deffn
+@defunx chap:string>? string1 string2
+@defunx chap:string<=? string1 string2
+@defunx chap:string>=? string1 string2
+Implement the corresponding chapter-order predicates.
+@end defun
-@code{(require 'pprint-file)}
-
-@deffn Procedure pprint-file infile
-@deffnx Procedure pprint-file infile outfile
-Pretty-prints all the code in @var{infile}. If @var{outfile} is
-specified, the output goes to @var{outfile}, otherwise it goes to
-@code{(current-output-port)}.@refill
-@end deffn
-
-@defun pprint-filter-file infile proc outfile
-@defunx pprint-filter-file infile proc
-@var{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 @var{proc} is applied to them sequentially.
+@defun chap:next-string string
+Returns the next string in the @emph{chapter order}. If @var{string}
+has no alphabetic or numeric characters,
+@code{(string-append @var{string} "0")} is returnd. The argument to
+chap:next-string will always be @code{chap:string<?} than the result.
-@var{outfile} is a port or a string. If no @var{outfile} is specified
-then @code{current-output-port} is assumed. These expanded expressions
-are then @code{pretty-print}ed to this port.
+@example
+(chap:next-string "a.9") @result{} "a.10"
+(chap:next-string "4c") @result{} "4d"
+(chap:next-string "4z") @result{} "4aa"
+(chap:next-string "Revised^@{4@}") @result{} "Revised^@{5@}"
-Whitepsace and comments (introduced by @code{;}) which are not part of
-scheme expressions are reproduced in the output. This procedure does
-not affect the values returned by @code{current-input-port} and
-@code{current-output-port}.@refill
+@end example
@end defun
-@code{pprint-filter-file} can be used to pre-compile macro-expansion and
-thus can reduce loading time. The following will write into
-@file{exp-code.scm} the result of expanding all defmacros in
-@file{code.scm}.
-@lisp
-(require 'pprint-file)
-(require 'defmacroexpand)
-(defmacro:load "my-macros.scm")
-(pprint-filter-file "code.scm" defmacro:expand* "exp-code.scm")
-@end lisp
-
-@node Sorting, Topological Sort, Pretty-Print, Procedures
-@section Sorting
+@node Sorting, Topological Sort, Chapter Ordering, Procedures
+@subsection Sorting
@code{(require 'sort)}
+@ftindex sort
Many Scheme systems provide some kind of sorting functions. They do
not, however, always provide the @emph{same} sorting functions, and
@@ -7016,10 +9445,12 @@ in Common LISP, just write
@noindent
in Scheme.
-@node Topological Sort, Standard Formatted I/O, Sorting, Procedures
-@section Topological Sort
+@node Topological Sort, String-Case, Sorting, Procedures
+@subsection Topological Sort
@code{(require 'topological-sort)} or @code{(require 'tsort)}
+@ftindex topological-sort
+@ftindex tsort
@noindent
The algorithm is inspired by Cormen, Leiserson and Rivest (1990)
@@ -7055,6 +9486,7 @@ tie or his belt.) `tsort' gives the correct order of dressing:
@example
(require 'tsort)
+@ftindex tsort
(tsort '((shirt tie belt)
(tie jacket)
(belt jacket)
@@ -7068,423 +9500,13 @@ tie or his belt.) `tsort' gives the correct order of dressing:
@end example
@end defun
-@node Standard Formatted I/O, String-Case, Topological Sort, Procedures
-@section Standard Formatted I/O
-
-@menu
-* Standard Formatted Output::
-* Standard Formatted Input::
-@end menu
-
-@subsection stdio
-
-@code{(require 'stdio)}
-
-@code{require}s @code{printf} and @code{scanf} and additionally defines
-the symbols:
-
-@defvar stdin
-Defined to be @code{(current-input-port)}.
-@end defvar
-@defvar stdout
-Defined to be @code{(current-output-port)}.
-@end defvar
-@defvar stderr
-Defined to be @code{(current-error-port)}.
-@end defvar
-
-
-@node Standard Formatted Output, Standard Formatted Input, Standard Formatted I/O, Standard Formatted I/O
-@subsection Standard Formatted Output
-
-@code{(require 'printf)}
-
-@deffn Procedure printf format arg1 @dots{}
-@deffnx Procedure fprintf port format arg1 @dots{}
-@deffnx Procedure sprintf str format arg1 @dots{}
-
-Each function converts, formats, and outputs its @var{arg1} @dots{}
-arguments according to the control string @var{format} argument and
-returns the number of characters output.
-
-@code{printf} sends its output to the port @code{(current-output-port)}.
-@code{fprintf} sends its output to the port @var{port}. @code{sprintf}
-@code{string-set!}s locations of the non-constant string argument
-@var{str} to the output characters.
-
-@quotation
-@emph{Note:} sprintf should be changed to a macro so a @code{substring}
-expression could be used for the @var{str} argument.
-@end quotation
-
-The string @var{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 @var{arg1} @dots{}. The
-results are undefined if there are an insufficient number of arguments
-for the format. If @var{format} is exhausted while some of the
-@var{arg1} @dots{} arguments remain unused, the excess @var{arg1}
-@dots{} arguments are ignored.
-
-The conversion specifications in a format string have the form:
-
-@example
-% @r{[} @var{flags} @r{]} @r{[} @var{width} @r{]} @r{[} . @var{precision} @r{]} @r{[} @var{type} @r{]} @var{conversion}
-@end example
-
-An output conversion specifications consist of an initial @samp{%}
-character followed in sequence by:
-
-@itemize @bullet
-@item
-Zero or more @dfn{flag characters} that modify the normal behavior of
-the conversion specification.
-
-@table @asis
-@item @samp{-}
-Left-justify the result in the field. Normally the result is
-right-justified.
-
-@item @samp{+}
-For the signed @samp{%d} and @samp{%i} conversions and all inexact
-conversions, prefix a plus sign if the value is positive.
-
-@item @samp{ }
-For the signed @samp{%d} and @samp{%i} conversions, if the result
-doesn't start with a plus or minus sign, prefix it with a space
-character instead. Since the @samp{+} flag ensures that the result
-includes a sign, this flag is ignored if both are specified.
-
-@item @samp{#}
-For inexact conversions, @samp{#} specifies that the result should
-always include a decimal point, even if no digits follow it. For the
-@samp{%g} and @samp{%G} conversions, this also forces trailing zeros
-after the decimal point to be printed where they would otherwise be
-elided.
-
-For the @samp{%o} conversion, force the leading digit to be @samp{0}, as
-if by increasing the precision. For @samp{%x} or @samp{%X}, prefix a
-leading @samp{0x} or @samp{0X} (respectively) to the result. This
-doesn't do anything useful for the @samp{%d}, @samp{%i}, or @samp{%u}
-conversions. Using this flag produces output which can be parsed by the
-@code{scanf} functions with the @samp{%i} conversion (@pxref{Standard
-Formatted Input}).
-
-
-@item @samp{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 @samp{-}
-flag is also specified, or if a precision is specified for an exact
-converson.
-@end table
-
-@item
-An optional decimal integer specifying the @dfn{minimum field width}.
-If the normal conversion produces fewer characters than this, the field
-is padded (with spaces or zeros per the @samp{0} flag) to the specified
-width. This is a @emph{minimum} width; if the normal conversion
-produces more characters than this, the field is @emph{not} truncated.
-@cindex minimum field width (@code{printf})
-
-Alternatively, if the field width is @samp{*}, 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 @samp{-} flag is set (see above) and the
-absolute value is used as the field width.
-@item
-An optional @dfn{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 (@samp{.}) followed
-optionally by a decimal integer (which defaults to zero if omitted).
-@cindex precision (@code{printf})
-Alternatively, if the precision is @samp{.*}, 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 @samp{*} for both the field width and precision, the
-field width argument precedes the precision argument. The @samp{.*}
-precision is an enhancement. C library versions may not accept this
-syntax.
-
-For the @samp{%f}, @samp{%e}, and @samp{%E} conversions, the precision
-specifies how many digits follow the decimal-point character. The
-default precision is @code{6}. If the precision is explicitly @code{0},
-the decimal point character is suppressed.
-
-For the @samp{%g} and @samp{%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 @code{0} or not specified for @samp{%g} or @samp{%G}, it is
-treated like a value of @code{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 @samp{0} with an
-explicit precision of zero produces no characters.
-
-@item
-An optional one of @samp{l}, @samp{h} or @samp{L}, which is ignored for
-numeric conversions. It is an error to specify these modifiers for
-non-numeric conversions.
-
-@item
-A character that specifies the conversion to be applied.
-@end itemize
-
-@subsubsection Exact Conversions
-
-@table @asis
-@item @samp{d}, @samp{i}
-Print an integer as a signed decimal number. @samp{%d} and @samp{%i}
-are synonymous for output, but are different when used with @code{scanf}
-for input (@pxref{Standard Formatted Input}).
-
-@item @samp{o}
-Print an integer as an unsigned octal number.
-
-@item @samp{u}
-Print an integer as an unsigned decimal number.
-
-@item @samp{x}, @samp{X}
-Print an integer as an unsigned hexadecimal number. @samp{%x} prints
-using the digits @samp{0123456789abcdef}. @samp{%X} prints using the
-digits @samp{0123456789ABCDEF}.
-@end table
-
-@subsubsection Inexact Conversions
-@emph{Note:} Inexact conversions are not supported yet.
-
-@table @asis
-@item @samp{f}
-Print a floating-point number in fixed-point notation.
-
-@item @samp{e}, @samp{E}
-Print a floating-point number in exponential notation. @samp{%e} prints
-@samp{e} between mantissa and exponont. @samp{%E} prints @samp{E}
-between mantissa and exponont.
-
-@item @samp{g}, @samp{G}
-Print a floating-point number in either normal or exponential notation,
-whichever is more appropriate for its magnitude. @samp{%g} prints
-@samp{e} between mantissa and exponont. @samp{%G} prints @samp{E}
-between mantissa and exponont.
-@end table
-
-@subsubsection Other Conversions
-@table @asis
-@item @samp{c}
-Print a single character. The @samp{-} flag is the only one which can
-be specified. It is an error to specify a precision.
-
-@item @samp{s}
-Print a string. The @samp{-} 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.
-
-@item @samp{a}, @samp{A}
-Print a scheme expression. The @samp{-} flag left-justifies the output.
-The @samp{#} flag specifies that strings and characters should be quoted
-as by @code{write} (which can be read using @code{read}); otherwise,
-output is as @code{display} prints. A precision specifies the maximum
-number of characters to output; otherwise as many characters as needed
-are output.
-
-@emph{Note:} @samp{%a} and @samp{%A} are SLIB extensions.
-
-@c @item @samp{p}
-@c Print the value of a pointer.
-
-@c @item @samp{n}
-@c Get the number of characters printed so far. @xref{Other Output Conversions}.
-@c Note that this conversion specification never produces any output.
-
-@c @item @samp{m}
-@c Print the string corresponding to the value of @code{errno}.
-@c (This is a GNU extension.)
-@c @xref{Other Output Conversions}.
-
-@item @samp{%}
-Print a literal @samp{%} character. No argument is consumed. It is an
-error to specifiy flags, field width, precision, or type modifiers with
-@samp{%%}.
-@end table
-@end deffn
-
-
-@node Standard Formatted Input, , Standard Formatted Output, Standard Formatted I/O
-@subsection Standard Formatted Input
-
-@code{(require 'scanf)}
-
-@deffn Function scanf-read-list format
-@deffnx Function scanf-read-list format port
-@deffnx Function scanf-read-list format string
-@end deffn
-
-@defmac scanf format arg1 @dots{}
-@defmacx fscanf port format arg1 @dots{}
-@defmacx sscanf str format arg1 @dots{}
-
-Each function reads characters, interpreting them according to the
-control string @var{format} argument.
-
-@code{scanf-read-list} returns a list of the items specified as far as
-the input matches @var{format}. @code{scanf}, @code{fscanf}, and
-@code{sscanf} return the number of items successfully matched and
-stored. @code{scanf}, @code{fscanf}, and @code{sscanf} also set the
-location corresponding to @var{arg1} @dots{} using the methods:
-
-@table @asis
-@item symbol
-@code{set!}
-@item car expression
-@code{set-car!}
-@item cdr expression
-@code{set-cdr!}
-@item vector-ref expression
-@code{vector-set!}
-@item substring expression
-@code{substring-move-left!}
-@end table
-
-The argument to a @code{substring} expression in @var{arg1} @dots{} must
-be a non-constant string. Characters will be stored starting at the
-position specified by the second argument to @code{substring}. The
-number of characters stored will be limited by either the position
-specified by the third argument to @code{substring} or the length of the
-matched string, whichever is less.
-
-The control string, @var{format}, contains conversion specifications and
-other characters used to direct interpretation of input sequences. The
-control string contains:
-
-@itemize @bullet
-@item White-space characters (blanks, tabs, newlines, or formfeeds)
-that cause input to be read (and discarded) up to the next
-non-white-space character.
-
-@item An ordinary character (not @samp{%}) that must match the next
-character of the input stream.
-
-@item Conversion specifications, consisting of the character @samp{%}, an
-optional assignment suppressing character @samp{*}, an optional
-numerical maximum-field width, an optional @samp{l}, @samp{h} or
-@samp{L} which is ignored, and a conversion code.
-
-@c @item The conversion specification can alternatively be prefixed by
-@c the character sequence @samp{%n$} instead of the character @samp{%},
-@c where @var{n} is a decimal integer in the range. The @samp{%n$}
-@c construction indicates that the value of the next input field should be
-@c placed in the @var{n}th place in the return list, rather than to the next
-@c unused one. The two forms of introducing a conversion specification,
-@c @samp{%} and @samp{%n$}, must not be mixed within a single format string
-@c with the following exception: Skip fields (see below) can be designated
-@c as @samp{%*} or @samp{%n$*}. In the latter case, @var{n} is ignored.
-
-@end itemize
-
-Unless the specification contains the @samp{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
-@samp{*} 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.
-
-@quotation
-@emph{Note:} This specification of format strings differs from the
-@cite{ANSI C} and @cite{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 @cite{ANSI C} and SLIB,
-prepend whitespace to all conversion specifications except @samp{[} and
-@samp{c}.
-@end quotation
-
-The conversion code indicates the interpretation of the input field; For
-a suppressed field, no value is returned. The following conversion
-codes are legal:
-
-@table @asis
-
-@item @samp{%}
-A single % is expected in the input at this point; no value is returned.
-
-@item @samp{d}, @samp{D}
-A decimal integer is expected.
-
-@item @samp{u}, @samp{U}
-An unsigned decimal integer is expected.
-
-@item @samp{o}, @samp{O}
-An octal integer is expected.
-
-@item @samp{x}, @samp{X}
-A hexadecimal integer is expected.
-
-@item @samp{i}
-An integer is expected. Returns the value of the next input item,
-interpreted according to C conventions; a leading @samp{0} implies
-octal, a leading @samp{0x} implies hexadecimal; otherwise, decimal is
-assumed.
-
-@item @samp{n}
-Returns the total number of bytes (including white space) read by
-@code{scanf}. No input is consumed by @code{%n}.
-
-@item @samp{f}, @samp{F}, @samp{e}, @samp{E}, @samp{g}, @samp{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 @samp{.}, followed by an optional
-exponent field consisting of an @samp{E} or an @samp{e}, followed by an
-optional @samp{+}, @samp{-}, or space, followed by an integer.
-
-@item @samp{c}, @samp{C}
-@var{Width} characters are expected. The normal skip-over-white-space
-is suppressed in this case; to read the next non-space character, use
-@samp{%1s}. If a field width is given, a string is returned; up to the
-indicated number of characters is read.
-
-@item @samp{s}, @samp{S}
-A character string is expected The input field is terminated by a
-white-space character. @code{scanf} cannot read a null string.
-
-@item @samp{[}
-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. @samp{^}, 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 @samp{[0123456789]} to be expressed @samp{[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 @samp{^}) 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.
-@end table
-
-The @code{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.
-@end defmac
-
-@node String-Case, String Ports, Standard Formatted I/O, Procedures
-@section String-Case
+@node String-Case, String Ports, Topological Sort, Procedures
+@subsection String-Case
@code{(require 'string-case)}
+@ftindex string-case
@deffn Procedure string-upcase str
@deffnx Procedure string-downcase str
@@ -7503,9 +9525,10 @@ The destructive versions of the functions above.
@node String Ports, String Search, String-Case, Procedures
-@section String Ports
+@subsection String Ports
@code{(require 'string-port)}
+@ftindex string-port
@deffn Procedure call-with-output-string proc
@var{proc} must be a procedure of one argument. This procedure calls
@@ -7523,18 +9546,28 @@ returned.@refill
@end deffn
-@node String Search, Tektronix Graphics Support, String Ports, Procedures
-@section String Search
+@node String Search, Line I/O, String Ports, Procedures
+@subsection String Search
@code{(require 'string-search)}
+@ftindex string-search
@deffn Procedure string-index string char
+@deffnx Procedure string-index-ci string char
Returns the index of the first occurence of @var{char} within
@var{string}, or @code{#f} if the @var{string} does not contain a
character @var{char}.
@end deffn
+@deffn Procedure string-reverse-index string char
+@deffnx Procedure string-reverse-index-ci string char
+Returns the index of the last occurence of @var{char} within
+@var{string}, or @code{#f} if the @var{string} does not contain a
+character @var{char}.
+@end deffn
+
@deffn procedure substring? pattern string
+@deffnx procedure substring-ci? pattern string
Searches @var{string} to see if some substring of @var{string} is equal
to @var{pattern}. @code{substring?} returns the index of the first
character of the first substring of @var{string} that is equal to
@@ -7549,14 +9582,23 @@ character of the first substring of @var{string} that is equal to
@end deffn
@deffn Procedure find-string-from-port? str in-port max-no-chars
-@deffnx Procedure find-string-from-port? str in-port
Looks for a string @var{str} within the first @var{max-no-chars} chars
-of the input port @var{in-port}. @var{max-no-chars} may be omitted: in
-that case, the search span is limited by the end of the input stream.
-When the @var{str} is found, the function 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 @var{str}) The function
-returns @code{#f} when the @var{str} isn't found.
+of the input port @var{in-port}.
+@deffnx 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.
+@deffnx Procedure find-string-from-port? str in-port char
+Searches up to the first occurrence of character @var{char} in
+@var{str}.
+@deffnx Procedure find-string-from-port? str in-port proc
+Searches up to the first occurrence of the procedure @var{proc}
+returning non-false when called with a character (from @var{in-port})
+argument.
+
+When the @var{str} is found, @code{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 @var{str}) The
+function returns @code{#f} when the @var{str} isn't found.
@code{find-string-from-port?} reads the port @emph{strictly}
sequentially, and does not perform any buffering. So
@@ -7565,128 +9607,79 @@ open to a pipe or other communication channel.
@end deffn
-@node Tektronix Graphics Support, Tree Operations, String Search, Procedures
-@section Tektronix Graphics Support
-
-@emph{Note:} The Tektronix graphics support files need more work, and
-are not complete.
+@node Line I/O, Multi-Processing, String Search, Procedures
+@subsection Line I/O
-@subsection 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.
-
-@deffn Procedure tek40:init
-@end deffn
-
-@deffn Procedure tek40:graphics
-@end deffn
-
-@deffn Procedure tek40:text
-@end deffn
-
-@deffn Procedure tek40:linetype linetype
-@end deffn
-
-@deffn Procedure tek40:move x y
-@end deffn
-
-@deffn Procedure tek40:draw x y
-@end deffn
-
-@deffn Procedure tek40:put-text x y str
-@end deffn
+@code{(require 'line-i/o)}
+@ftindex line-i
-@deffn Procedure tek40:reset
-@end deffn
+@defun read-line
+@defunx read-line port
+Returns a string of the characters up to, but not including a newline or
+end of file, updating @var{port} to point to the character following the
+newline. If no characters are available, an end of file object is
+returned. @var{port} may be omitted, in which case it defaults to the
+value returned by @code{current-input-port}.@refill
+@end defun
+@defun read-line! string
+@defunx read-line! string port
+Fills @var{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, @code{#f}
+is returned. @var{port} may be omitted, in which case it defaults to
+the value returned by @code{current-input-port}.@refill
+@end defun
-@subsection Tektronix 4100 Series Graphics
+@defun write-line string
+@defunx write-line string port
+Writes @var{string} followed by a newline to the given port and returns
+an unspecified value. Port may be omited, in which case it defaults to
+the value returned by @code{current-input-port}.@refill
+@end defun
-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.
-@deffn Procedure tek41:init
-@end deffn
-@deffn Procedure tek41:reset
-@end deffn
-@deffn Procedure tek41:graphics
-@end deffn
+@node Multi-Processing, , Line I/O, Procedures
+@subsection Multi-Processing
-@deffn Procedure tek41:move x y
-@end deffn
+@code{(require 'process)}
+@ftindex process
-@deffn Procedure tek41:draw x y
-@end deffn
+This module implements asynchronous (non-polled) time-sliced
+multi-processing in the SCM Scheme implementation using procedures
+@code{alarm} and @code{alarm-interrupt}.
+@findex alarm
+@findex alarm-interrupt
+Until this is ported to another implementation, consider it an example
+of writing schedulers in Scheme.
-@deffn Procedure tek41:point x y number
+@deffn Procedure add-process! proc
+Adds proc, which must be a procedure (or continuation) capable of
+accepting accepting one argument, to the @code{process:queue}. The
+value returned is unspecified. The argument to @var{proc} should be
+ignored. If @var{proc} returns, the process is killed.@refill
@end deffn
-@deffn Procedure tek41:encode-x-y x y
+@deffn Procedure process:schedule!
+Saves the current process on @code{process:queue} and runs the next
+process from @code{process:queue}. The value returned is
+unspecified.@refill
@end deffn
-@deffn Procedure tek41:encode-int number
+@deffn Procedure kill-process!
+Kills the current process and runs the next process from
+@code{process:queue}. If there are no more processes on
+@code{process:queue}, @code{(slib:exit)} is called (@xref{System}).
@end deffn
-@node Tree Operations, , Tektronix Graphics Support, Procedures
-@section Tree operations
-
-@code{(require 'tree)}
-
-These are operations that treat lists a representations of trees.
-
-@defun subst new old tree
-@defunx substq new old tree
-@defunx substv new old tree
-@code{subst} makes a copy of @var{tree}, substituting @var{new} for
-every subtree or leaf of @var{tree} which is @code{equal?} to @var{old}
-and returns a modified tree. The original @var{tree} is unchanged, but
-may share parts with the result.@refill
-
-@code{substq} and @code{substv} are similar, but test against @var{old}
-using @code{eq?} and @code{eqv?} respectively.@refill
-
-Examples:
-@lisp
-(substq 'tempest 'hurricane '(shakespeare wrote (the hurricane)))
- @result{} (shakespeare wrote (the tempest))
-(substq 'foo '() '(shakespeare wrote (twelfth night)))
- @result{} (shakespeare wrote (twelfth night . foo) . foo)
-(subst '(a . cons) '(old . pair)
- '((old . spice) ((old . shoes) old . pair) (old . pair)))
- @result{} ((old . spice) ((old . shoes) a . cons) (a . cons))
-@end lisp
-@end defun
-
-@defun copy-tree tree
-Makes a copy of the nested list structure @var{tree} using new pairs and
-returns it. All levels are copied, so that none of the pairs in the
-tree are @code{eq?} to the original ones -- only the leaves are.@refill
-
-Example:
-@lisp
-(define bar '(bar))
-(copy-tree (list bar 'foo))
- @result{} ((bar) foo)
-(eq? bar (car (copy-tree (list bar 'foo))))
- @result{} #f
-@end lisp
-@end defun
-
-
-
-
-
-@node Standards Support, Session Support, Procedures, Top
-@chapter Standards Support
+@node Standards Support, Session Support, Procedures, Other Packages
+@section Standards Support
@@ -7701,14 +9694,13 @@ Example:
* Promises:: 'promise
* Dynamic-Wind:: 'dynamic-wind
* Values:: 'values
-* Time:: 'time
-* CLTime:: 'common-lisp-time
@end menu
@node With-File, Transcripts, Standards Support, Standards Support
-@section With-File
+@subsection With-File
@code{(require 'with-file)}
+@ftindex with-file
@defun with-input-from-file file thunk
@defunx with-output-to-file file thunk
@@ -7716,9 +9708,10 @@ Description found in R4RS.
@end defun
@node Transcripts, Rev2 Procedures, With-File, Standards Support
-@section Transcripts
+@subsection Transcripts
@code{(require 'transcript)}
+@ftindex transcript
@defun transcript-on filename
@defunx transcript-off filename
@@ -7731,9 +9724,10 @@ Redefines @code{read-char}, @code{read}, @code{write-char},
@node Rev2 Procedures, Rev4 Optional Procedures, Transcripts, Standards Support
-@section Rev2 Procedures
+@subsection Rev2 Procedures
@code{(require 'rev2-procedures)}
+@ftindex rev2-procedures
The procedures below were specified in the @cite{Revised^2 Report on
Scheme}. @strong{N.B.}: The symbols @code{1+} and @code{-1+} are not
@@ -7793,9 +9787,10 @@ trailing @samp{?}.
@node Rev4 Optional Procedures, Multi-argument / and -, Rev2 Procedures, Standards Support
-@section Rev4 Optional Procedures
+@subsection Rev4 Optional Procedures
@code{(require 'rev4-optional-procedures)}
+@ftindex rev4-optional-procedures
For the specification of these optional procedures,
@xref{Standard procedures, , ,r4rs, Revised(4) Scheme}.
@@ -7829,9 +9824,10 @@ For the specification of these optional procedures,
@node Multi-argument / and -, Multi-argument Apply, Rev4 Optional Procedures, Standards Support
-@section Multi-argument / and -
+@subsection Multi-argument / and -
@code{(require 'mutliarg/and-)}
+@ftindex mutliarg
For the specification of these optional forms, @xref{Numerical
operations, , ,r4rs, Revised(4) Scheme}. The @code{two-arg:}* forms are
@@ -7857,9 +9853,10 @@ The original two-argument version of @code{-}.
@node Multi-argument Apply, Rationalize, Multi-argument / and -, Standards Support
-@section Multi-argument Apply
+@subsection Multi-argument Apply
@code{(require 'multiarg-apply)}
+@ftindex multiarg-apply
@noindent
For the specification of this optional form,
@@ -7878,9 +9875,10 @@ implementations which don't support the many-argument version.
@node Rationalize, Promises, Multi-argument Apply, Standards Support
-@section Rationalize
+@subsection Rationalize
@code{(require 'rationalize)}
+@ftindex rationalize
The procedure rationalize is interesting because most programming
languages do not provide anything analogous to it. For simplicity, we
@@ -7898,9 +9896,10 @@ We thank Alan Bawden for contributing this algorithm.
@node Promises, Dynamic-Wind, Rationalize, Standards Support
-@section Promises
+@subsection Promises
@code{(require 'promise)}
+@ftindex promise
@defun make-promise proc
@end defun
@@ -7915,9 +9914,10 @@ doesn't support them
@node Dynamic-Wind, Values, Promises, Standards Support
-@section Dynamic-Wind
+@subsection Dynamic-Wind
@code{(require 'dynamic-wind)}
+@ftindex dynamic-wind
This facility is a generalization of Common LISP @code{unwind-protect},
designed to take into account the fact that continuations produced by
@@ -7945,10 +9945,11 @@ the time of the error or interrupt.@refill
-@node Values, Time, Dynamic-Wind, Standards Support
-@section Values
+@node Values, , Dynamic-Wind, Standards Support
+@subsection Values
@code{(require 'values)}
+@ftindex values
@defun values obj @dots{}
@code{values} takes any number of arguments, and passes (returns) them
@@ -7969,154 +9970,9 @@ not created by the @code{call-with-values} procedure is
unspecified.@refill
@end defun
-@node Time, CLTime, Values, Standards Support
-@section Time
-
-The procedures @code{current-time}, @code{difftime}, and
-@code{offset-time} are supported by all implementations (SLIB provides
-them if feature @code{('current-time)} is missing. @code{current-time}
-returns a @dfn{calendar time} (caltime) which can be a number or other
-type.
-
-@defun 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 @code{get-universal-time} in @ref{CLTime}. On implementations
-which cannot support actual times, @code{current-time} will increment a
-counter and return its value when called.
-@end defun
-
-@defun difftime caltime1 caltime0
-Returns the difference (number of seconds) between twe calendar times:
-@var{caltime1} - @var{caltime0}. @var{caltime0} can also be a number.
-@end defun
-@defun offset-time caltime offset
-Returns the calendar time of @var{caltime} offset by @var{offset} number
-of seconds @code{(+ caltime offset)}.
-@end defun
-
-@example
-(require 'posix-time)
-@end example
-
-These procedures are intended to be compatible with Posix time
-conversion functions.
-
-@defvar *timezone*
-contains the difference, in seconds, between UTC and local standard time
-(for example, in the U.S. Eastern time zone (EST), timezone is
-5*60*60). @code{*timezone*} is initialized by @code{tzset}.
-@end defvar
-
-@defun tzset
-initializes the @var{*timezone*} variable from the TZ environment
-variable. This function is automatically called by the other time
-conversion functions that depend on the time zone.
-@end defun
-
-@defun gmtime caltime
-converts the calendar time @var{caltime} to a vector of integers
-representing the time expressed as Coordinated Universal Time (UTC).
-
-@defunx localtime caltime
-converts the calendar time @var{caltime} to a vector of integers expressed
-relative to the user's time zone. @code{localtime} sets the variable
-@var{*timezone*} with the difference between Coordinated Universal Time
-(UTC) and local standard time in seconds by calling @code{tzset}.
-The elements of the returned vector are as follows:
-
-@enumerate 0
-@item
- seconds (0 - 61)
-@item
- minutes (0 - 59)
-@item
- hours since midnight
-@item
- day of month
-@item
- month (0 - 11). Note difference from @code{decode-universal-time}.
-@item
- year (A.D.)
-@item
- day of week (0 - 6)
-@item
- day of year (0 - 365)
-@item
- 1 for daylight savings, 0 for regular time
-@end enumerate
-@end defun
-
-@defun mktime univtime
-Converts a vector of integers in Coordinated Universal Time (UTC) format
-to calendar time (caltime) format.
-@end defun
-
-@defun asctime univtime
-Converts the vector of integers @var{caltime} in Coordinated
-Universal Time (UTC) format into a string of the form
-@code{"Wed Jun 30 21:49:08 1993"}.
-@end defun
-
-@defun ctime caltime
-Equivalent to @code{(time:asctime (time:localtime @var{caltime}))}.
-@end defun
-
-@node CLTime, , Time, Standards Support
-@section CLTime
-
-@defun get-decoded-time
-Equivalent to @code{(decode-universal-time (get-universal-time))}.
-@end defun
-
-@defun get-universal-time
-Returns the current time as @dfn{Universal Time}, number of seconds
-since 00:00:00 Jan 1, 1900 GMT. Note that the reference time is
-different from @code{current-time}.
-@end defun
-
-@defun decode-universal-time univtime
-Converts @var{univtime} to @dfn{Decoded Time} format.
-Nine values are returned:
-@enumerate 0
-@item
- seconds (0 - 61)
-@item
- minutes (0 - 59)
-@item
- hours since midnight
-@item
- day of month
-@item
- month (1 - 12). Note difference from @code{gmtime} and @code{localtime}.
-@item
- year (A.D.)
-@item
- day of week (0 - 6)
-@item
- #t for daylight savings, #f otherwise
-@item
- hours west of GMT (-24 - +24)
-@end enumerate
-
-Notice that the values returned by @code{decode-universal-time} do not
-match the arguments to @code{encode-universal-time}.
-@end defun
-
-@defun encode-universal-time second minute hour date month year
-@defunx encode-universal-time second minute hour date month year time-zone
-Converts the arguments in Decoded Time format to Universal Time format.
-If @var{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 @code{decode-universal-time} do not
-match the arguments to @code{encode-universal-time}.
-@end defun
-
-
-@node Session Support, Optional SLIB Packages, Standards Support, Top
-@chapter Session Support
+@node Session Support, Extra-SLIB Packages, Standards Support, Other Packages
+@section Session Support
@menu
* Repl:: Macros at top-level
@@ -8124,31 +9980,16 @@ match the arguments to @code{encode-universal-time}.
* Debug:: To err is human ...
* Breakpoints:: Pause execution
* Trace:: 'trace
-* Getopt:: Command Line option parsing
-* Command Line:: A command line reader for Scheme shells
* System Interface:: 'system and 'getenv
-
-Certain features are so simple, system-dependent, or widely subcribed
-that they are supported by all implementations as part of the
-@samp{*.init} files.
-
-The features described in the following sections are provided by all
-implementations.
-
-* 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
+* Time Zone::
@end menu
-
@node Repl, Quick Print, Session Support, Session Support
-@section Repl
+@subsection Repl
@code{(require 'repl)}
+@ftindex repl
Here is a read-eval-print-loop which, given an eval, evaluates forms.
@@ -8178,14 +10019,17 @@ To have your top level loop always use macros, add any interrupt
catching lines and the following lines to your Scheme init file:
@lisp
(require 'macro)
+@ftindex macro
(require 'repl)
+@ftindex repl
(repl:top-level macro:eval)
@end lisp
@node Quick Print, Debug, Repl, Session Support
-@section Quick Print
+@subsection Quick Print
@code{(require 'qp)}
+@ftindex qp
@noindent
When displaying error messages and warnings, it is paramount that the
@@ -8217,9 +10061,10 @@ should use.@refill
@end defvar
@node Debug, Breakpoints, Quick Print, Session Support
-@section Debug
+@subsection Debug
@code{(require 'debug)}
+@ftindex debug
@noindent
Requiring @code{debug} automatically requires @code{trace} and
@@ -8233,6 +10078,7 @@ printer for @code{qp}. This example shows how to do this:
(define qpn (lambda args) @dots{})
(provide 'qp)
(require 'debug)
+@ftindex debug
@end example
@deffn Procedure trace-all file
@@ -8246,14 +10092,17 @@ top-level in file @file{file}.
@end deffn
@node Breakpoints, Trace, Debug, Session Support
-@section Breakpoints
+@subsection Breakpoints
@code{(require 'break)}
+@ftindex break
@defun init-debug
If your Scheme implementation does not support @code{break} or
@code{abort}, a message will appear when you @code{(require 'break)} or
+@ftindex break
@code{(require 'debug)} telling you to type @code{(init-debug)}. This
+@ftindex debug
is in order to establish a top-level continuation. Typing
@code{(init-debug)} at top level sets up a continuation for
@code{break}.
@@ -8326,10 +10175,11 @@ To unbreak, type
@end lisp
@end defun
-@node Trace, Getopt, Breakpoints, Session Support
-@section Tracing
+@node Trace, System Interface, Breakpoints, Session Support
+@subsection Tracing
@code{(require 'trace)}
+@ftindex trace
@defmac trace proc1 @dots{}
Traces the top-level named procedures given as arguments.
@@ -8385,225 +10235,10 @@ To untrace, type
@end defun
-@node Getopt, Command Line, Trace, Session Support
-@section Getopt
-
-@code{(require 'getopt)}
-
-This routine implements Posix command line argument parsing. Notice
-that returning values through global variables means that @code{getopt}
-is @emph{not} reentrant.
-
-@defvar *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, @var{*opting*} must be reset.
-@end defvar
-
-@defvar *optarg*
-Is set by getopt to the (string) option-argument of the current option.
-@end defvar
-
-@deffn Procedure getopt argc argv optstring
-Returns the next option letter in @var{argv} (starting from
-@code{(vector-ref argv *optind*)}) that matches a letter in
-@var{optstring}. @var{argv} is a vector or list of strings, the 0th of
-which getopt usually ignores. @var{argc} is the argument count, usually
-the length of @var{argv}. @var{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 @var{argv}.
-
-@var{*optind*} is the index of the next element of the @var{argv} vector
-to be processed. It is initialized to 1 by @file{getopt.scm}, and
-@code{getopt} updates it when it finishes with each element of
-@var{argv}.
-
-@code{getopt} returns the next option character from @var{argv} that
-matches a character in @var{optstring}, if there is one that matches.
-If the option takes an argument, @code{getopt} sets the variable
-@var{*optarg*} to the option-argument as follows:
-
-@itemize @bullet
-@item
-If the option was the last character in the string pointed to by an
-element of @var{argv}, then @var{*optarg*} contains the next element of
-@var{argv}, and @var{*optind*} is incremented by 2. If the resulting
-value of @var{*optind*} is greater than or equal to @var{argc}, this
-indicates a missing option argument, and @code{getopt} returns an error
-indication.
-
-@item
-Otherwise, @var{*optarg*} is set to the string following the option
-character in that element of @var{argv}, and @var{*optind*} is
-incremented by 1.
-@end itemize
-
-If, when @code{getopt} is called, the string @code{(vector-ref argv
-*optind*)} either does not begin with the character @code{#\-} or is
-just @code{"-"}, @code{getopt} returns @code{#f} without changing
-@var{*optind*}. If @code{(vector-ref argv *optind*)} is the string
-@code{"--"}, @code{getopt} returns @code{#f} after incrementing
-@var{*optind*}.
-
-If @code{getopt} encounters an option character that is not contained in
-@var{optstring}, it returns the question-mark @code{#\?} character. If
-it detects a missing option argument, it returns the colon character
-@code{#\:} if the first character of @var{optstring} was a colon, or a
-question-mark character otherwise. In either case, @code{getopt} sets
-the variable @var{getopt:opt} to the option character that caused the
-error.
-
-The special option @code{"--"} can be used to delimit the end of the
-options; @code{#f} is returned, and @code{"--"} is skipped.
-
-RETURN VALUE
-
-@code{getopt} returns the next option character specified on the command
-line. A colon @code{#\:} is returned if @code{getopt} detects a missing argument
-and the first character of @var{optstring} was a colon @code{#\:}.
-
-A question-mark @code{#\?} is returned if @code{getopt} encounters an option
-character not in @var{optstring} or detects a missing argument and the first
-character of @var{optstring} was not a colon @code{#\:}.
-
-Otherwise, @code{getopt} returns @code{#f} when all command line options have been
-parsed.
-
-Example:
-@lisp
-#! /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)
-@end lisp
-@end deffn
-
-@section Getopt--
-
-@defun getopt-- argc argv optstring
-The procedure @code{getopt--} is an extended version of @code{getopt}
-which parses @dfn{long option names} of the form
-@samp{--hold-the-onions} and @samp{--verbosity-level=extreme}.
-@w{@code{Getopt--}} behaves as @code{getopt} except for non-empty
-options beginning with @samp{--}.
-
-Options beginning with @samp{--} are returned as strings rather than
-characters. If a value is assigned (using @samp{=}) to a long option,
-@code{*optarg*} is set to the value. The @samp{=} and value are
-not returned as part of the option string.
-
-No information is passed to @code{getopt--} concerning which long
-options should be accepted or whether such options can take arguments.
-If a long option did not have an argument, @code{*optarg} will be set to
-@code{#f}. The caller is responsible for detecting and reporting
-errors.
-
-@example
-(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*)))
-@print{}
-2 #\b "9"
-3 "f1" #f
-4 "2" ""
-5 "g3" "35234.342"
-5 #f "35234.342"
-@end example
-@end defun
-
-@node Command Line, System Interface, Getopt, Session Support
-@section Command Line
-
-@code{(require 'read-command)}
-
-@defun read-command port
-@defunx read-command
-@code{read-command} converts a @dfn{command line} into a list of strings
-suitable for parsing by @code{getopt}. The syntax of command lines
-supported resembles that of popular @dfn{shell}s. @code{read-command}
-updates @var{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 @var{port} argument may be omitted, in which case it defaults to the
-value returned by @code{current-input-port}.
-
-The fields into which the command line is split are delimited by
-whitespace as defined by @code{char-whitespace?}. The end of a command
-is delimited by end-of-file or unescaped semicolon (@key{;}) or
-@key{newline}. Any character can be literally included in a field by
-escaping it with a backslach (@key{\}).
-
-The initial character and types of fields recognized are:
-@table @asis
-@item @samp{\}
-The next character has is taken literally and not interpreted as a field
-delimiter. If @key{\} is the last character before a @key{newline},
-that @key{newline} is just ignored. Processing continues from the
-characters after the @key{newline} as though the backslash and
-@key{newline} were not there.
-@item @samp{"}
-The characters up to the next unescaped @key{"} are taken literally,
-according to [R4RS] rules for literal strings (@pxref{Strings, , ,r4rs,
-Revised(4) Scheme}).
-@item @samp{(}, @samp{%'}
-One scheme expression is @code{read} starting with this character. The
-@code{read} expression is evaluated, converted to a string
-(using @code{display}), and replaces the expression in the returned
-field.
-@item @samp{;}
-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.
-@end table
+@node System Interface, Time Zone, Trace, Session Support
+@subsection System Interface
@noindent
-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. @key{#} can be part of fields if these conditions are
-not met. For instance, @code{ab#c} is just the field ab#c.
-
-@table @samp
-@item #
-Introduces a comment. The comment continues to the end of the line on
-which the semicolon appears. Comments are treated as whitespace by
-@code{read-dommand-line} and backslashes before @key{newline}s in
-comments are also ignored.
-@end table
-@end defun
-
-@node System Interface, Require, Command Line, Session Support
-@section System Interface
-
If @code{(provided? 'getenv)}:
@defun getenv name
@@ -8611,6 +10246,7 @@ Looks up @var{name}, a string, in the program environment. If @var{name} is
found a string of its value is returned. Otherwise, @code{#f} is returned.
@end defun
+@noindent
If @code{(provided? 'system)}:
@defun system command-string
@@ -8618,441 +10254,466 @@ Executes the @var{command-string} on the computer and returns the
integer status code.
@end defun
+@noindent
+If @code{(provided? 'current-time)}:
-@node Require, Vicinity, System Interface, Session Support
-@section Require
+@noindent
+The procedures @code{current-time}, @code{difftime}, and
+@code{offset-time} deal with a @dfn{calendar time} datatype
+@cindex time
+@cindex calendar time
+which may or may not be disjoint from other Scheme datatypes.
-These variables and procedures are provided by all implementations.
+@defun 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 @code{get-universal-time} in @ref{Common-Lisp Time}.
+@end defun
-@defvar *features*
-Is a list of symbols denoting features supported in this implementation.
-@end defvar
+@defun difftime caltime1 caltime0
+Returns the difference (number of seconds) between twe calendar times:
+@var{caltime1} - @var{caltime0}. @var{caltime0} may also be a number.
+@end defun
-@defvar *modules*
-Is a list of pathnames denoting files which have been loaded.
-@end defvar
+@defun offset-time caltime offset
+Returns the calendar time of @var{caltime} offset by @var{offset} number
+of seconds @code{(+ caltime offset)}.
+@end defun
-@defvar *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, @code{source}, or @code{compiled}. The cdr of the pathname
-should be either a string or a list.
-@end defvar
+@node Time Zone, , System Interface, Session Support
+@subsection Time Zone
+
+(require 'time-zone)
+
+@deftp {Data Format} TZ-string
+
+POSIX standards specify several formats for encoding time-zone rules.
+
+@table @t
+@item :@i{<pathname>}
+If the first character of @i{<pathname>} is @samp{/}, then
+@i{<pathname>} specifies the absolute pathname of a tzfile(5) format
+time-zone file. Otherwise, @i{<pathname>} is interpreted as a pathname
+within @var{tzfile:vicinity} (/usr/lib/zoneinfo/) naming a tzfile(5)
+format time-zone file.
+@item @i{<std>}@i{<offset>}
+The string @i{<std>} consists of 3 or more alphabetic characters.
+@i{<offset>} specifies the time difference from GMT. The @i{<offset>}
+is positive if the local time zone is west of the Prime Meridian and
+negative if it is east. @i{<offset>} can be the number of hours or
+hours and minutes (and optionally seconds) separated by @samp{:}. For
+example, @code{-4:30}.
+@item @i{<std>}@i{<offset>}@i{<dst>}
+@i{<dst>} is the at least 3 alphabetic characters naming the local
+daylight-savings-time.
+@item @i{<std>}@i{<offset>}@i{<dst>}@i{<doffset>}
+@i{<doffset>} specifies the offset from the Prime Meridian when
+daylight-savings-time is in effect.
+@end table
-In the following three functions if @var{feature} is not a symbol it is
-assumed to be a pathname.@refill
+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.
+
+@table @t
+@item ,@i{<date>}/@i{<time>},@i{<date>}/@i{<time>}
+The @i{<time>}s are specified like the @i{<offset>}s above, except that
+leading @samp{+} and @samp{-} are not allowed.
+
+Each @i{<date>} has one of the formats:
+
+@table @t
+@item J@i{<day>}
+specifies the Julian day with @i{<day>} between 1 and 365. February 29
+is never counted and cannot be referenced.
+@item @i{<day>}
+This specifies the Julian day with n between 0 and 365. February 29 is
+counted in leap years and can be specified.
+@item M@i{<month>}.@i{<week>}.@i{<day>}
+This specifies day @i{<day>} (0 <= @i{<day>} <= 6) of week @i{<week>} (1
+<= @i{<week>} <= 5) of month @i{<month>} (1 <= @i{<month>} <= 12). Week
+1 is the first week in which day d occurs and week 5 is the last week in
+which day @i{<day>} occurs. Day 0 is a Sunday.
+@end table
+@end table
-@defun provided? feature
-Returns @code{#t} if @var{feature} is a member of @code{*features*} or
-@code{*modules*} or if @var{feature} is supported by a file already
-loaded and @code{#f} otherwise.@refill
-@end defun
+@end deftp
-@deffn Procedure require feature
-If @code{(not (provided? @var{feature}))} it is loaded if @var{feature}
-is a pathname or if @code{(assq @var{feature} *catalog*)}. Otherwise an
-error is signaled.@refill
-@end deffn
+@deftp {Data Type} time-zone
+is a datatype encoding how many hours from Greenwich Mean Time the local
+time is, and the @dfn{Daylight Savings Time} rules for changing it.
+@end deftp
-@deffn Procedure provide feature
-Assures that @var{feature} is contained in @code{*features*} if
-@var{feature} is a symbol and @code{*modules*} otherwise.@refill
-@end deffn
-
-@defun require:feature->path feature
-Returns @code{#t} if @var{feature} is a member of @code{*features*} or
-@code{*modules*} or if @var{feature} is supported by a file already
-loaded. Returns a path if one was found in @code{*catalog*} under the
-feature name, and @code{#f} otherwise. The path can either be a string
-suitable as an argument to load or a pair as described above for
-*catalog*.
+@defun time-zone TZ-string
+Creates and returns a time-zone object specified by the string
+@var{TZ-string}. If @code{time-zone} cannot interpret @var{TZ-string},
+@code{#f} is returned.
@end defun
-Below is a list of features that are automatically determined by
-@code{require}. For each item, @code{(provided? '@var{feature})} will
-return @code{#t} if that feature is available, and @code{#f} if
-not.@refill
-
-@itemize @bullet
-@item
-'inexact
-@item
-'rational
+@defun tz:params caltime tz
+@var{tz} is a time-zone object. @code{tz:params} returns a list of
+three items:
+@enumerate 0
+@item
+An integer. 0 if standard time is in effect for timezone @var{tz} at
+@var{caltime}; 1 if daylight savings time is in effect for timezone
+@var{tz} at @var{caltime}.
@item
-'real
+The number of seconds west of the Prime Meridian timezone @var{tz} is at
+@var{caltime}.
@item
-'complex
-@item
-'bignum
-@end itemize
-
-
-
-
+The name for timezone @var{tz} at @var{caltime}.
+@end enumerate
-@node Vicinity, Configuration, Require, Session Support
-@section Vicinity
+@code{tz:params} is unaffected by the default timezone; inquiries can be
+made of any timezone at any calendar time.
-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 @dfn{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.
+@end defun
-These procedures are provided by all implementations.
+@noindent
+The rest of these procedures and variables are provided for POSIX
+compatability. Because of shared state they are not thread-safe.
-@defun make-vicinity filename
-Returns the vicinity of @var{filename} for use by @code{in-vicinity}.
-@end defun
+@defun tzset
+Returns the default time-zone.
+@defunx tzset tz
+Sets (and returns) the default time-zone to @var{tz}.
+@defunx tzset TZ-string
+Sets (and returns) the default time-zone to that specified by
+@var{TZ-string}.
-@defun 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. @strong{Warning:} @code{program-vicinity} can
-return incorrectl values if your program escapes back into a
-@code{load}.@refill
+@code{tzset} also sets the variables @var{*timezone*}, @var{daylight?},
+and @var{tzname}. This function is automatically called by the time
+conversion procedures which depend on the time zone (@pxref{Time and
+Date}).
@end defun
-@defun library-vicinity
-Returns the vicinity of the shared Scheme library.
-@end defun
+@defvar *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). @code{*timezone*} is initialized by @code{tzset}.
+@end defvar
-@defun implementation-vicinity
-Returns the vicinity of the underlying Scheme implementation. This
-vicinity will likely contain startup code and messages and a compiler.
-@end defun
+@defvar daylight?
+is @code{#t} if the default timezone has rules for @dfn{Daylight Savings
+Time}. @emph{Note:} @var{daylight?} does not tell you when Daylight
+Savings Time is in effect, just that the default zone sometimes has
+Daylight Savings Time.
+@end defvar
-@defun user-vicinity
-Returns the vicinity of the current directory of the user. On most
-systems this is @file{""} (the empty string).
-@end defun
+@defvar tzname
+is a vector of strings. Index 0 has the abbreviation for the standard
+timezone; If @var{daylight?}, then index 1 has the abbreviation for the
+Daylight Savings timezone.
+@end defvar
-@c @defun scheme-file-suffix
-@c Returns the default filename suffix for scheme source files. On most
-@c systems this is @samp{.scm}.@refill
-@c @end defun
-@defun in-vicinity vicinity filename
-Returns a filename suitable for use by @code{slib:load},
-@code{slib:load-source}, @code{slib:load-compiled},
-@code{open-input-file}, @code{open-output-file}, etc. The returned
-filename is @var{filename} in @var{vicinity}. @code{in-vicinity} should
-allow @var{filename} to override @var{vicinity} when @var{filename} is
-an absolute pathname and @var{vicinity} is equal to the value of
-@code{(user-vicinity)}. The behavior of @code{in-vicinity} when
-@var{filename} is absolute and @var{vicinity} is not equal to the value
-of @code{(user-vicinity)} is unspecified. For most systems
-@code{in-vicinity} can be @code{string-append}.@refill
-@end defun
+@node Extra-SLIB Packages, , Session Support, Other Packages
+@section Extra-SLIB Packages
-@defun sub-vicinity vicinity name
-Returns the vicinity of @var{vicinity} restricted to @var{name}. This
-is used for large systems where names of files in subsystems could
-conflict. On systems with directory structure @code{sub-vicinity} will
-return a pathname of the subdirectory @var{name} of
-@var{vicinity}.@refill
-@end defun
+Several Scheme packages have been written using SLIB. There are several
+reasons why a package might not be included in the SLIB distribution:
+@itemize @bullet
+@item
+Because it requires special hardware or software which is not universal.
+@item
+Because it is large and of limited interest to most Scheme users.
+@item
+Because it has copying terms different enough from the other SLIB
+packages that its inclusion would cause confusion.
+@item
+Because it is an application program, rather than a library module.
+@item
+Because I have been too busy to integrate it.
+@end itemize
+Once an optional package is installed (and an entry added to
+@code{*catalog*}, the @code{require} mechanism allows it to be called up
+and used as easily as any other SLIB package. Some optional packages
+(for which @code{*catalog*} already has entries) available from SLIB
+sites are:
+@table @asis
+@item SLIB-PSD is a portable debugger for Scheme (requires emacs editor).
+@lisp
+ftp-swiss.ai.mit.edu:pub/scm/slib-psd1-3.tar.gz
+prep.ai.mit.edu: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
+@end lisp
-@node Configuration, Input/Output, Vicinity, Session Support
-@section Configuration
+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
+@ifset html
+<A HREF="http://www.cs.tut.fi/staff/pk/scheme/psd/article/article.html">
+@end ifset
+@lisp
+http://www.cs.tut.fi/staff/pk/scheme/psd/article/article.html
+@end lisp
+@ifset html
+</A>
+@end ifset
+@item SCHELOG is an embedding of Prolog in Scheme.
+@ifset html
+<A HREF="http://www.cs.rice.edu/CS/PLT/packages/schelog/">
+@end ifset
+@lisp
+http://www.cs.rice.edu/CS/PLT/packages/schelog/
+@end lisp
+@ifset html
+</A>
+@end ifset
+@end table
-These constants and procedures describe characteristics of the Scheme
-and underlying operating system. They are provided by all
-implementations.
-@defvr Constant char-code-limit
-An integer 1 larger that the largest value which can be returned by
-@code{char->integer}.@refill
-@end defvr
+@node About SLIB, Index, Other Packages, Top
+@chapter About SLIB
-@defvr Constant most-positive-fixnum
-The immediate integer closest to positive infinity.
-@end defvr
+@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.
+@end menu
-@defvr Constant slib:tab
-The tab character.
-@end defvr
+@noindent
+More people than I can name have contributed to SLIB. Thanks to all of
+you.
-@defvr Constant slib:form-feed
-The form-feed character.
-@end defvr
-@defun software-type
-Returns a symbol denoting the generic operating system type. For
-instance, @code{unix}, @code{vms}, @code{macos}, @code{amiga}, or
-@code{ms-dos}.
-@end defun
+@node Installation, Porting, About SLIB, About SLIB
+@section Installation
-@defun 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.
+Check the manifest in @file{/usr/doc/slib/README.gz} to find a
+configuration file for your Scheme implementation. Initialization files
+for most IEEE P1178 compliant Scheme Implementations are included with
+this distribution.
-@example
-(slib:report-version) @result{} slib "2a3" on scm "4e1" on unix
-@end example
-@end defun
+If the Scheme implementation supports @code{getenv}, then the value of
+the shell environment variable @var{SCHEME_LIBRARY_PATH} will be used
+for @code{(library-vicinity)} if it is defined. Currently, Chez, Elk,
+MITScheme, scheme->c, VSCM, and SCM support @code{getenv}. Scheme48
+supports @code{getenv} but does not use it for determining
+@code{library-vicinity}. (That is done from the Makefile.)
-@defun slib:report
-Displays the information of @code{(slib:report-version)} followed by
-almost all the information neccessary for submitting a problem report.
-An unspecified value is returned.
+You should check the definitions of @code{software-type},
+@code{scheme-implementation-version},
+@iftex
+@*
+@end iftex
+@code{implementation-vicinity},
+and @code{library-vicinity} in the initialization file. There are
+comments in the file for how to configure it.
-@defunx slib:report #t
-provides a more verbose listing.
+Once this is done you can modify the startup file for your Scheme
+implementation to @code{load} this initialization file. SLIB is then
+installed. The startup files are located in
+@file{/usr/lib/slib/init/}.
-@defunx slib:report filename
-Writes the report to file @file{filename}.
+Multiple implementations of Scheme can all use the same SLIB directory.
+Simply configure each implementation's initialization file as outlined
+above.
-@example
-(slib:report)
-@result{}
-slib "2a3" on scm "4e1" on unix
-(implementation-vicinity) is "/usr/local/src/scm/"
-(library-vicinity) is "/usr/local/lib/slib/"
-(scheme-file-suffix) is ".scm"
-implementation *features* :
- bignum complex real rational
- inexact vicinity ed getenv
- tmpnam system 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 array-for-each
- array full-continuation char-ready? line-i/o
- i/o-extensions pipe
-implementation *catalog* :
- (rev4-optional-procedures . "/usr/local/lib/slib/sc4opt")
- ...
-@end example
-@end defun
+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.
-@node Input/Output, Legacy, Configuration, Session Support
-@section Input/Output
+SLIB includes methods to create heap images for the VSCM and Scheme48
+implementations. The instructions for creating a VSCM image are in
+comments in @file{vscm.init}. To make a Scheme48 image for an
+installation under @code{<prefix>}, @code{cd} to the SLIB directory and
+type @code{make prefix=<prefix> slib48}. To install the image, type
+@code{make prefix=<prefix> install48}. This will also create a shell
+script with the name @code{slib48} which will invoke the saved image.
-These procedures are provided by all implementations.
+@node Porting, Coding Standards, Installation, About SLIB
+@section Porting
-@deffn Procedure file-exists? filename
-Returns @code{#t} if the specified file exists. Otherwise, returns
-@code{#f}. If the underlying implementation does not support this
-feature then @code{#f} is always returned.
-@end deffn
+If there is no initialization file for your Scheme implementation, you
+will have to create one. Your Scheme implementation must be largely
+compliant with @cite{IEEE Std 1178-1990} or @cite{Revised^4 Report on
+the Algorithmic Language Scheme} to support SLIB. @footnote{If you are
+porting a @cite{Revised^3 Report on the Algorithmic Language Scheme}
+implementation, then you will need to finish writing @file{sc4sc3.scm}
+and @code{load} it from your initialization file.}
-@deffn Procedure delete-file filename
-Deletes the file specified by @var{filename}. If @var{filename} can not
-be deleted, @code{#f} is returned. Otherwise, @code{#t} is
-returned.@refill
-@end deffn
+@file{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
+@file{.init} appended. For instance, if you were porting
+@code{foo-scheme} then the initialization file might be called
+@file{foo.init}.
-@deffn Procedure tmpnam
-Returns a pathname for a file which will likely not be used by any other
-process. Successive calls to @code{(tmpnam)} will return different
-pathnames.@refill
-@end deffn
+Your customized version should then be loaded as part of your scheme
+implementation's initialization. It will load @file{require.scm} from
+the library; this will allow the use of @code{provide},
+@code{provided?}, and @code{require} along with the @dfn{vicinity}
+functions (these functions are documented in the section
+@xref{Require}). The rest of the library will then be accessible in a
+system independent fashion.@refill
-@deffn Procedure current-error-port
-Returns the current port to which diagnostic and error output is
-directed.
-@end deffn
+Please mail new working configuration files to @code{jaffer@@ai.mit.edu}
+so that they can be included in the SLIB distribution.@refill
-@deffn Procedure force-output
-@deffnx Procedure force-output port
-Forces any pending output on @var{port} to be delivered to the output
-device and returns an unspecified value. The @var{port} argument may be
-omitted, in which case it defaults to the value returned by
-@code{(current-output-port)}.@refill
-@end deffn
-@deffn Procedure output-port-width
-@deffnx Procedure output-port-width port
+@node Coding Standards, Copyrights, Porting, About SLIB
+@section Coding Standards
-Returns the width of @var{port}, which defaults to
-@code{(current-output-port)} if absent. If the width cannot be
-determined 79 is returned.@refill
-@end deffn
+All library packages are written in IEEE P1178 Scheme and assume that a
+configuration file and @file{require.scm} package have already been
+loaded. Other versions of Scheme can be supported in library packages
+as well by using, for example, @code{(provided? 'rev3-report)} or
+@code{(require 'rev3-report)} (@xref{Require}).@refill
+@ftindex rev3-report
-@deffn Procedure output-port-height
-@deffnx Procedure output-port-height port
+The module name and @samp{:} should prefix each symbol defined in the
+package. Definitions for external use should then be exported by having
+@code{(define foo module-name:foo)}.@refill
-Returns the height of @var{port}, which defaults to
-@code{(current-output-port)} if absent. If the height cannot be
-determined 24 is returned.@refill
-@end deffn
+Code submitted for inclusion in SLIB should not duplicate routines
+already in SLIB files. Use @code{require} to force those library
+routines to be used by your package. Care should be taken that there
+are no circularities in the @code{require}s and @code{load}s between the
+library packages.@refill
-@node Legacy, System, Input/Output, Session Support
-@section Legacy
+Documentation should be provided in Emacs Texinfo format if possible,
+But documentation must be provided.
-@defun identity x
-@var{identity} returns its argument.
+Your package will be released sooner with SLIB if you send me a file
+which tests your code. Please run this test @emph{before} you send me
+the code!
-Example:
-@lisp
-(identity 3)
- @result{} 3
-(identity '(foo bar))
- @result{} (foo bar)
-(map identity @var{lst})
- @equiv{} (copy-list @var{lst})
-@end lisp
-@end defun
+@subheading Modifications
-These were present in Scheme until R4RS (@pxref{Notes, , Language
-changes ,r4rs, Revised(4) Scheme}).
+Please document your changes. A line or two for @file{ChangeLog} is
+sufficient for simple fixes or extensions. Look at the format of
+@file{ChangeLog} to see what information is desired. Please send me
+@code{diff} files from the latest SLIB distribution (remember to send
+@code{diff}s of @file{slib.texi} and @file{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
+@file{slib.texi} and @samp{*.init} files).
-@defvr Constant t
-Derfined as @code{#t}.
-@end defvr
+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.
-@defvr Constant nil
-Defined as @code{#f}.
-@end defvr
+Please @emph{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.
-@defun last-pair l
-Returns the last pair in the list @var{l}. Example:
-@lisp
-(last-pair (cons 1 2))
- @result{} (1 . 2)
-(last-pair '(1 2))
- @result{} (2)
- @equiv{} (cons 2 '())
-@end lisp
-@end defun
+@node Copyrights, , Coding Standards, About SLIB
+@section Copyrights
-@node System, , Legacy, Session Support
-@section System
+This section has instructions for SLIB authors regarding copyrights.
-These procedures are provided by all implementations.
+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 @file{require.scm} and
+@file{macwork.scm} illustrate copyright and appropriate terms.
-@deffn Procedure slib:load-source name
-Loads a file of Scheme source code from @var{name} with the default
-filename extension used in SLIB. For instance if the filename extension
-used in SLIB is @file{.scm} then @code{(slib:load-source "foo")} will
-load from file @file{foo.scm}.
-@end deffn
+If your code or changes amount to less than about 10 lines, you do not
+need to add your copyright or send a disclaimer.
-@deffn Procedure slib:load-compiled name
-On implementations which support separtely loadable compiled modules,
-loads a file of compiled code from @var{name} with the implementation's
-filename extension for compiled code appended.
-@end deffn
+@subheading Putting code into the Public Domain
-@deffn Procedure slib:load name
-Loads a file of Scheme source or compiled code from @var{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.
+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.
-If an implementation does not support compiled code then
-@code{slib:load} will be identical to @code{slib:load-source}.
-@end deffn
+@quotation
+I, @var{name}, hereby affirm that I have placed the software package
+@var{name} in the public domain.
-@deffn Procedure slib:eval obj
-@code{eval} returns the value of @var{obj} evaluated in the current top
-level environment.@refill
-@end deffn
+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.
-@deffn Procedure slib:eval-load filename eval
-@var{filename} should be a string. If filename names an existing file,
-the Scheme source code expressions and definitions are read from the
-file and @var{eval} called with them sequentially. The
-@code{slib:eval-load} procedure does not affect the values returned by
-@code{current-input-port} and @code{current-output-port}.@refill
-@end deffn
+@flushright
+ @var{signature and date}
+@end flushright
+@end quotation
-@deffn Procedure slib:error arg1 arg2 @dots{}
-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.@refill
-@end deffn
+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.
-@deffn Procedure slib:exit n
-@deffnx Procedure slib:exit
-Exits from the Scheme session returning status @var{n} to the system.
-If @var{n} is omitted or @code{#t}, a success status is returned to the
-system (if possible). If @var{n} is @code{#f} a failure is returned to
-the system (if possible). If @var{n} is an integer, then @var{n} is
-returned to the system (if possible). If the Scheme session cannot exit
-an unspecified value is returned from @code{slib:exit}.
-@end deffn
+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.
+@subheading Explicit copying terms
-@node Optional SLIB Packages, Procedure and Macro Index, Session Support, Top
-@chapter Optional SLIB Packages
+@noindent
+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:
-Several Scheme packages have been written using SLIB. There are several
-reasons why a package might not be included in the SLIB distribution:
@itemize @bullet
@item
-Because it requires special hardware or software which is not universal.
-@item
-Because it is large and of limited interest to most Scheme users.
-@item
-Because it has copying terms different enough from the other SLIB
-packages that its inclusion would cause confusion.
+Arrange that your name appears in a copyright line for the appropriate
+year. Multiple copyright lines are acceptable.
@item
-Because it is an application program, rather than a library module.
+With your copyright line, specify any terms you require to be different
+from those already in the file.
@item
-Because I have been too busy to integrate it.
+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.
@end itemize
-Once an optional package is installed (and an entry added to
-@code{*catalog*}, the @code{require} mechanism allows it to be called up
-and used as easily as any other SLIB package. Some optional packages
-(for which @code{*catalog*} already has entries) available from SLIB
-sites are:
+@subheading Example: Company Copyright Disclaimer
-@table @asis
-@item SLIB-PSD is a portable debugger for Scheme (requires emacs editor).
-@lisp
-ftp-swiss.ai.mit.edu:pub/scm/slib-psd1-3.tar.gz
-prep.ai.mit.edu: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
-@end lisp
+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:
-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
-@lisp
-http://www.cs.tut.fi/staff/pk/scheme/psd/article/article.html
-@end lisp
-@item SLIB-SCHELOG is an embedding of Prolog in Scheme.
-@lisp
-ftp-swiss.ai.mit.edu:pub/scm/slib-schelog.tar.gz
-prep.ai.mit.edu:pub/gnu/jacal/slib-schelog.tar.gz
-ftp.maths.tcd.ie:pub/bosullvn/jacal/slib-schelog.tar.gz
-ftp.cs.indiana.edu:/pub/scheme-repository/utl/slib-schelog.tar.gz
-@end lisp
-@end table
+@quotation
+@var{employer} Corporation hereby disclaims all copyright
+interest in the program @var{program} written by @var{name}.
+
+@var{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.
-@node Procedure and Macro Index, Variable Index, Optional SLIB Packages, Top
+@flushleft
+@var{signature and date},
+@var{name}, @var{title}, @var{employer} Corporation
+@end flushleft
+@end quotation
+
+@node Index, , About SLIB, Top
+@c @node Procedure and Macro Index, Variable Index, About SLIB, Top
@unnumbered Procedure and Macro Index
This is an alphabetical list of all the procedures and macros in SLIB.
@printindex fn
-@node Variable Index, , Procedure and Macro Index, Top
+@c @node Variable Index, Concept Index, Procedure and Macro Index, Top
@unnumbered Variable Index
This is an alphabetical list of all the global variables in SLIB.
@printindex vr
+@c @node Concept Index, , Variable Index, Top
+@unnumbered Concept and Feature Index
+
+@printindex cp
+
@contents
@bye