diff options
Diffstat (limited to 'slib.info')
-rw-r--r-- | slib.info | 11240 |
1 files changed, 11240 insertions, 0 deletions
diff --git a/slib.info b/slib.info new file mode 100644 index 0000000..8e62273 --- /dev/null +++ b/slib.info @@ -0,0 +1,11240 @@ +This is Info file slib.info, produced by Makeinfo version 1.68 from the +input file slib.texi. + +INFO-DIR-SECTION The Algorithmic Language Scheme +START-INFO-DIR-ENTRY +* SLIB: (slib). Scheme Library +END-INFO-DIR-ENTRY + + This file documents SLIB, the portable Scheme library. + + Copyright (C) 1993 Todd R. Eigenschink +Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Aubrey Jaffer | + + Permission is granted to make and distribute verbatim copies of this +manual provided the copyright notice and this permission notice are +preserved on all copies. + + Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + + Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be stated in a +translation approved by the author. + + +File: slib.info, Node: Top, Next: The Library System, Prev: (dir), Up: (dir) + +"SLIB" is a portable library for the programming language "Scheme". It | +provides a platform independent framework for using "packages" of | +Scheme procedures and syntax. As distributed, SLIB contains useful +packages for all Scheme implementations. Its catalog can be | +transparently extended to accomodate packages specific to a site, | +implementation, user, or directory. | + +* Menu: + +* The Library System:: How to use and customize. +* Scheme Syntax Extension Packages:: +* Textual Conversion Packages:: +* Mathematical Packages:: +* Database Packages:: +* Other Packages:: +* About SLIB:: Install, etc. +* Index:: + + +File: slib.info, Node: The Library System, Next: Scheme Syntax Extension Packages, Prev: Top, Up: Top + +The Library System +****************** + +* Menu: + +* Feature:: SLIB names. +* Requesting Features:: +* Library Catalogs:: +* Catalog Compilation:: +* Built-in Support:: +* About this manual:: + + +File: slib.info, Node: Feature, Next: Requesting Features, Prev: The Library System, Up: The Library System + +Feature +======= + +SLIB denotes "features" by symbols. SLIB maintains a list of features +supported by the Scheme "session". The set of features provided by a +session may change over time. Some features are properties of the +Scheme implementation being used. The following features detail what +sort of numbers are available from an implementation. + + * 'inexact + + * 'rational + + * 'real + + * 'complex + + * 'bignum + +Other features correspond to the presence of sets of Scheme procedures +or syntax (macros). + + - Function: provided? FEATURE + Returns `#t' if FEATURE is supported by the current Scheme session. + + - Procedure: provide FEATURE + Informs SLIB that FEATURE is supported. Henceforth `(provided? + FEATURE)' will return `#t'. + + (provided? 'foo) => #f + (provide 'foo) + (provided? 'foo) => #t + + +File: slib.info, Node: Requesting Features, Next: Library Catalogs, Prev: Feature, Up: The Library System + +Requesting Features +=================== + +SLIB creates and maintains a "catalog" mapping features to locations of +files introducing procedures and syntax denoted by those features. + +At the beginning of each section of this manual, there is a line like +`(require 'FEATURE)'. The Scheme files comprising SLIB are cataloged +so that these feature names map to the corresponding files. + +SLIB provides a form, `require', which loads the files providing the +requested feature. + + - Procedure: require FEATURE + * If `(provided? FEATURE)' is true, then `require' just returns + an unspecified value. + + * Otherwise, if FEATURE is found in the catalog, then the + corresponding files will be loaded and an unspecified value + returned. + + Subsequently `(provided? FEATURE)' will return `#t'. + + * Otherwise (FEATURE not found in the catalog), an error is + signaled. + +The catalog can also be queried using `require:feature->path'. + + - Function: require:feature->path FEATURE + * If FEATURE is already provided, then returns `#t'. + + * Otherwise, if FEATURE is in the catalog, the path or list of + paths associated with FEATURE is returned. + + * Otherwise, returns `#f'. + + +File: slib.info, Node: Library Catalogs, Next: Catalog Compilation, Prev: Requesting Features, Up: The Library System + +Library Catalogs +================ + +At the start of a session no catalog is present, but is created with the +first catalog inquiry (such as `(require 'random)'). Several sources +of catalog information are combined to produce the catalog: + + * standard SLIB packages. + + * additional packages of interest to this site. + + * packages specifically for the variety of Scheme which this session + is running. + + * packages this user wants to always have available. This catalog + is the file `homecat' in the user's "HOME" directory. + + * packages germane to working in this (current working) directory. + This catalog is the file `usercat' in the directory to which it + applies. One would typically `cd' to this directory before + starting the Scheme session. + +Catalog files consist of one or more "association list"s. In the +circumstance where a feature symbol appears in more than one list, the +latter list's association is retrieved. Here are the supported formats +for elements of catalog lists: + +`(FEATURE . <symbol>)' + Redirects to the feature named <symbol>. + +`(FEATURE . "<path>")' + Loads file <path>. + +`(FEATURE source "<path>")' + `slib:load's the Scheme source file <path>. + +`(FEATURE compiled "<path>" ...)' + `slib:load-compiled's the files <path> .... + +The various macro styles first `require' the named macro package, then +just load <path> or load-and-macro-expand <path> as appropriate for the +implementation. + +`(FEATURE defmacro "<path>")' + `defmacro:load's the Scheme source file <path>. + +`(FEATURE macro-by-example "<path>")' + `defmacro:load's the Scheme source file <path>. + +`(FEATURE macro "<path>")' + `macro:load's the Scheme source file <path>. + +`(FEATURE macros-that-work "<path>")' + `macro:load's the Scheme source file <path>. + +`(FEATURE syntax-case "<path>")' + `macro:load's the Scheme source file <path>. + +`(FEATURE syntactic-closures "<path>")' + `macro:load's the Scheme source file <path>. + +Here is an example of a `usercat' catalog. A Program in this directory +can invoke the `run' feature with `(require 'run)'. + + ;;; "usercat": SLIB catalog additions for SIMSYNCH. -*-scheme-*- + + ( + (simsynch . "../synch/simsynch.scm") + (run . "../synch/run.scm") + (schlep . "schlep.scm") + ) + + +File: slib.info, Node: Catalog Compilation, Next: Built-in Support, Prev: Library Catalogs, Up: The Library System + +Catalog Compilation +=================== + +SLIB combines the catalog information which doesn't vary per user into +the file `slibcat' in the implementation-vicinity. Therefore `slibcat' +needs change only when new software is installed or compiled. Because +the actual pathnames of files can differ from installation to +installation, SLIB builds a separate catalog for each implementation it +is used with. + +The definition of `*SLIB-VERSION*' in SLIB file `require.scm' is +checked against the catalog association of `*SLIB-VERSION*' to +ascertain when versions have changed. I recommend that the definition +of `*SLIB-VERSION*' be changed whenever the library is changed. If +multiple implementations of Scheme use SLIB, remember that recompiling +one `slibcat' will fix only that implementation's catalog. + +The compilation scripts of Scheme implementations which work with SLIB +can automatically trigger catalog compilation by deleting `slibcat' or +by invoking a special form of `require': + + - Procedure: require 'new-catalog + This will load `mklibcat', which compiles and writes a new + `slibcat'. + +Another special form of `require' erases SLIB's catalog, forcing it to +be reloaded the next time the catalog is queried. + + - Procedure: require #f + Removes SLIB's catalog information. This should be done before + saving an executable image so that, when restored, its catalog + will be loaded afresh. + +Each file in the table below is descibed in terms of its file-system +independent "vicinity" (*note Vicinity::.). The entries of a catalog +in the table override those of catalogs above it in the table. + +`implementation-vicinity' `slibcat' + This file contains the associations for the packages comprising + SLIB, the `implcat' and the `sitecat's. The associations in the + other catalogs override those of the standard catalog. + +`library-vicinity' `mklibcat.scm' + creates `slibcat'. + +`library-vicinity' `sitecat' + This file contains the associations specific to an SLIB + installation. + +`implementation-vicinity' `implcat' + This file contains the associations specific to an implementation + of Scheme. Different implementations of Scheme should have + different `implementation-vicinity'. + +`implementation-vicinity' `mkimpcat.scm' + if present, creates `implcat'. + +`implementation-vicinity' `sitecat' + This file contains the associations specific to a Scheme + implementation installation. + +`home-vicinity' `homecat' + This file contains the associations specific to an SLIB user. + +`user-vicinity' `usercat' + This file contains associations effecting only those sessions whose + "working directory" is `user-vicinity'. + + +File: slib.info, Node: Built-in Support, Next: About this manual, Prev: Catalog Compilation, Up: The Library System + +Built-in Support +================ + +The procedures described in these sections are supported by all +implementations as part of the `*.init' files or by `require.scm'. + +* Menu: + +* Require:: Module Management +* Vicinity:: Pathname Management +* Configuration:: Characteristics of Scheme Implementation +* Input/Output:: Things not provided by the Scheme specs. +* Legacy:: +* System:: LOADing, EVALing, ERRORing, and EXITing + + +File: slib.info, Node: Require, Next: Vicinity, Prev: Built-in Support, Up: Built-in Support + +Require +------- + + - Variable: *features* + Is a list of symbols denoting features supported in this + implementation. *FEATURES* can grow as modules are `require'd. + *FEATURES* must be defined by all implementations (*note + Porting::.). + + Here are features which SLIB (`require.scm') adds to *FEATURES* + when appropriate. + + * 'inexact + + * 'rational + + * 'real + + * 'complex + + * 'bignum + + For each item, `(provided? 'FEATURE)' will return `#t' if that + feature is available, and `#f' if not. + + - Variable: *modules* + Is a list of pathnames denoting files which have been loaded. + + - Variable: *catalog* + Is an association list of features (symbols) and pathnames which + will supply those features. The pathname can be either a string + or a pair. If pathname is a pair then the first element should be + a macro feature symbol, `source', or `compiled'. The cdr of the + pathname should be either a string or a list. + +In the following functions if the argument FEATURE is not a symbol it +is assumed to be a pathname. + + - Function: provided? FEATURE + Returns `#t' if FEATURE is a member of `*features*' or `*modules*' + or if FEATURE is supported by a file already loaded and `#f' + otherwise. + + - Procedure: require FEATURE + FEATURE is a symbol. If `(provided? FEATURE)' is true `require' + returns. Otherwise, if `(assq FEATURE *catalog*)' is not `#f', + the associated files will be loaded and `(provided? FEATURE)' will + henceforth return `#t'. An unspecified value is returned. If + FEATURE is not found in `*catalog*', then an error is signaled. + + - Procedure: require PATHNAME + PATHNAME is a string. If PATHNAME has not already been given as + an argument to `require', PATHNAME is loaded. An unspecified + value is returned. + + - Procedure: provide FEATURE + Assures that FEATURE is contained in `*features*' if FEATURE is a + symbol and `*modules*' otherwise. + + - Function: require:feature->path FEATURE + Returns `#t' if FEATURE is a member of `*features*' or `*modules*' + or if FEATURE is supported by a file already loaded. Returns a + path if one was found in `*catalog*' under the feature name, and + `#f' otherwise. The path can either be a string suitable as an + argument to load or a pair as described above for *catalog*. + + +File: slib.info, Node: Vicinity, Next: Configuration, Prev: Require, Up: Built-in Support + +Vicinity +-------- + +A vicinity is a descriptor for a place in the file system. Vicinities +hide from the programmer the concepts of host, volume, directory, and +version. Vicinities express only the concept of a file environment +where a file name can be resolved to a file in a system independent +manner. Vicinities can even be used on "flat" file systems (which have +no directory structure) by having the vicinity express constraints on +the file name. On most systems a vicinity would be a string. All of +these procedures are file system dependent. + +These procedures are provided by all implementations. + + - Function: make-vicinity PATH + Returns the vicinity of PATH for use by `in-vicinity'. + + - Function: program-vicinity + Returns the vicinity of the currently loading Scheme code. For an + interpreter this would be the directory containing source code. + For a compiled system (with multiple files) this would be the + directory where the object or executable files are. If no file is + currently loading it the result is undefined. *Warning:* + `program-vicinity' can return incorrect values if your program + escapes back into a `load'. + + - Function: library-vicinity + Returns the vicinity of the shared Scheme library. + + - Function: implementation-vicinity + Returns the vicinity of the underlying Scheme implementation. This + vicinity will likely contain startup code and messages and a + compiler. + + - Function: user-vicinity + Returns the vicinity of the current directory of the user. On most + systems this is `""' (the empty string). + + - Function: home-vicinity + Returns the vicinity of the user's "HOME" directory, the directory + which typically contains files which customize a computer + environment for a user. If scheme is running without a user (eg. + a daemon) or if this concept is meaningless for the platform, then + `home-vicinity' returns `#f'. + + - Function: in-vicinity VICINITY FILENAME + Returns a filename suitable for use by `slib:load', + `slib:load-source', `slib:load-compiled', `open-input-file', + `open-output-file', etc. The returned filename is FILENAME in + VICINITY. `in-vicinity' should allow FILENAME to override + VICINITY when FILENAME is an absolute pathname and VICINITY is + equal to the value of `(user-vicinity)'. The behavior of + `in-vicinity' when FILENAME is absolute and VICINITY is not equal + to the value of `(user-vicinity)' is unspecified. For most systems + `in-vicinity' can be `string-append'. + + - Function: sub-vicinity VICINITY NAME + Returns the vicinity of VICINITY restricted to NAME. This is used + for large systems where names of files in subsystems could + conflict. On systems with directory structure `sub-vicinity' will + return a pathname of the subdirectory NAME of VICINITY. + + +File: slib.info, Node: Configuration, Next: Input/Output, Prev: Vicinity, Up: Built-in Support + +Configuration +------------- + +These constants and procedures describe characteristics of the Scheme +and underlying operating system. They are provided by all +implementations. + + - Constant: char-code-limit + An integer 1 larger that the largest value which can be returned by + `char->integer'. + + - Constant: most-positive-fixnum + In implementations which support integers of practically unlimited + size, MOST-POSITIVE-FIXNUM is a large exact integer within the + range of exact integers that may result from computing the length + of a list, vector, or string. + + In implementations which do not support integers of practically + unlimited size, MOST-POSITIVE-FIXNUM is the largest exact integer + that may result from computing the length of a list, vector, or + string. + + - Constant: slib:tab + The tab character. + + - Constant: slib:form-feed + The form-feed character. + + - Function: software-type + Returns a symbol denoting the generic operating system type. For + instance, `unix', `vms', `macos', `amiga', or `ms-dos'. + + - Function: slib:report-version + Displays the versions of SLIB and the underlying Scheme + implementation and the name of the operating system. An + unspecified value is returned. + + (slib:report-version) => slib "2c7" on scm "5b1" on unix | + + - Function: slib:report + Displays the information of `(slib:report-version)' followed by + almost all the information neccessary for submitting a problem + report. An unspecified value is returned. + + - Function: slib:report #T + provides a more verbose listing. + + - Function: slib:report FILENAME + Writes the report to file `filename'. + + (slib:report) + => + slib "2c7" on scm "5b1" on unix | + (implementation-vicinity) is "/home/jaffer/scm/" + (library-vicinity) is "/home/jaffer/slib/" + (scheme-file-suffix) is ".scm" + loaded *features* : + trace alist qp sort + common-list-functions macro values getopt + compiled + implementation *features* : + bignum complex real rational + inexact vicinity ed getenv + tmpnam abort transcript with-file + ieee-p1178 rev4-report rev4-optional-procedures hash + object-hash delay eval dynamic-wind + multiarg-apply multiarg/and- logical defmacro + string-port source current-time record + rev3-procedures rev2-procedures sun-dl string-case + array dump char-ready? full-continuation + system + implementation *catalog* : + (i/o-extensions compiled "/home/jaffer/scm/ioext.so") + ... + + +File: slib.info, Node: Input/Output, Next: Legacy, Prev: Configuration, Up: Built-in Support + +Input/Output +------------ + +These procedures are provided by all implementations. + + - Procedure: file-exists? FILENAME + Returns `#t' if the specified file exists. Otherwise, returns + `#f'. If the underlying implementation does not support this + feature then `#f' is always returned. + + - Procedure: delete-file FILENAME + Deletes the file specified by FILENAME. If FILENAME can not be + deleted, `#f' is returned. Otherwise, `#t' is returned. + + - Procedure: tmpnam + Returns a pathname for a file which will likely not be used by any + other process. Successive calls to `(tmpnam)' will return + different pathnames. + + - Procedure: current-error-port + Returns the current port to which diagnostic and error output is + directed. + + - Procedure: force-output + - Procedure: force-output PORT + Forces any pending output on PORT to be delivered to the output + device and returns an unspecified value. The PORT argument may be + omitted, in which case it defaults to the value returned by + `(current-output-port)'. + + - Procedure: output-port-width + - Procedure: output-port-width PORT + Returns the width of PORT, which defaults to + `(current-output-port)' if absent. If the width cannot be + determined 79 is returned. + + - Procedure: output-port-height + - Procedure: output-port-height PORT + Returns the height of PORT, which defaults to + `(current-output-port)' if absent. If the height cannot be + determined 24 is returned. + + +File: slib.info, Node: Legacy, Next: System, Prev: Input/Output, Up: Built-in Support + +Legacy +------ + + These procedures are provided by all implementations. + + - Function: identity X + IDENTITY returns its argument. + + Example: + (identity 3) + => 3 + (identity '(foo bar)) + => (foo bar) + (map identity LST) + == (copy-list LST) + +The following procedures were present in Scheme until R4RS (*note +Language changes: (r4rs)Notes.). They are provided by all SLIB +implementations. + + - Constant: t + Derfined as `#t'. + + - Constant: nil + Defined as `#f'. + + - Function: last-pair L + Returns the last pair in the list L. Example: + (last-pair (cons 1 2)) + => (1 . 2) + (last-pair '(1 2)) + => (2) + == (cons 2 '()) + + +File: slib.info, Node: System, Prev: Legacy, Up: Built-in Support + +System +------ + +These procedures are provided by all implementations. + + - Procedure: slib:load-source NAME + Loads a file of Scheme source code from NAME with the default + filename extension used in SLIB. For instance if the filename + extension used in SLIB is `.scm' then `(slib:load-source "foo")' + will load from file `foo.scm'. + + - Procedure: slib:load-compiled NAME + On implementations which support separtely loadable compiled + modules, loads a file of compiled code from NAME with the + implementation's filename extension for compiled code appended. + + - Procedure: slib:load NAME + Loads a file of Scheme source or compiled code from NAME with the + appropriate suffixes appended. If both source and compiled code + are present with the appropriate names then the implementation + will load just one. It is up to the implementation to choose + which one will be loaded. + + If an implementation does not support compiled code then + `slib:load' will be identical to `slib:load-source'. + + - Procedure: slib:eval OBJ + `eval' returns the value of OBJ evaluated in the current top level + environment. *Note Eval:: provides a more general evaluation + facility. + + - Procedure: slib:eval-load FILENAME EVAL + FILENAME should be a string. If filename names an existing file, + the Scheme source code expressions and definitions are read from + the file and EVAL called with them sequentially. The + `slib:eval-load' procedure does not affect the values returned by + `current-input-port' and `current-output-port'. + + - Procedure: slib:warn ARG1 ARG2 ... + Outputs a warning message containing the arguments. + + - Procedure: slib:error ARG1 ARG2 ... + Outputs an error message containing the arguments, aborts + evaluation of the current form and responds in a system dependent + way to the error. Typical responses are to abort the program or + to enter a read-eval-print loop. + + - Procedure: slib:exit N + - Procedure: slib:exit + Exits from the Scheme session returning status N to the system. + If N is omitted or `#t', a success status is returned to the + system (if possible). If N is `#f' a failure is returned to the + system (if possible). If N is an integer, then N is returned to + the system (if possible). If the Scheme session cannot exit an + unspecified value is returned from `slib:exit'. + + +File: slib.info, Node: About this manual, Prev: Built-in Support, Up: The Library System + +About this manual +================= + + * Entries that are labeled as Functions are called for their return + values. Entries that are labeled as Procedures are called + primarily for their side effects. + + * Examples in this text were produced using the `scm' Scheme + implementation. + + * At the beginning of each section, there is a line that looks like + `(require 'feature)'. Include this line in your code prior to + using the package. + + +File: slib.info, Node: Scheme Syntax Extension Packages, Next: Textual Conversion Packages, Prev: The Library System, Up: Top + +Scheme Syntax Extension Packages +******************************** + +* Menu: + +* Defmacro:: Supported by all implementations + +* R4RS Macros:: 'macro +* Macro by Example:: 'macro-by-example +* Macros That Work:: 'macros-that-work +* Syntactic Closures:: 'syntactic-closures +* Syntax-Case Macros:: 'syntax-case + +Syntax extensions (macros) included with SLIB. Also *Note Structures::. + +* Fluid-Let:: 'fluid-let +* Yasos:: 'yasos, 'oop, 'collect + + +File: slib.info, Node: Defmacro, Next: R4RS Macros, Prev: Scheme Syntax Extension Packages, Up: Scheme Syntax Extension Packages + +Defmacro +======== + + Defmacros are supported by all implementations. + + - Function: gentemp + Returns a new (interned) symbol each time it is called. The symbol + names are implementation-dependent + (gentemp) => scm:G0 + (gentemp) => scm:G1 + + - Function: defmacro:eval E + Returns the `slib:eval' of expanding all defmacros in scheme + expression E. + + - Function: defmacro:load FILENAME + FILENAME should be a string. If filename names an existing file, + the `defmacro:load' procedure reads Scheme source code expressions + and definitions from the file and evaluates them sequentially. + These source code expressions and definitions may contain defmacro + definitions. The `macro:load' procedure does not affect the values + returned by `current-input-port' and `current-output-port'. + + - Function: defmacro? SYM + Returns `#t' if SYM has been defined by `defmacro', `#f' otherwise. + + - Function: macroexpand-1 FORM + - Function: macroexpand FORM + If FORM is a macro call, `macroexpand-1' will expand the macro + call once and return it. A FORM is considered to be a macro call + only if it is a cons whose `car' is a symbol for which a `defmacr' + has been defined. + + `macroexpand' is similar to `macroexpand-1', but repeatedly + expands FORM until it is no longer a macro call. + + - Macro: defmacro NAME LAMBDA-LIST FORM ... + When encountered by `defmacro:eval', `defmacro:macroexpand*', or + `defmacro:load' defines a new macro which will henceforth be + expanded when encountered by `defmacro:eval', + `defmacro:macroexpand*', or `defmacro:load'. + +Defmacroexpand +-------------- + + `(require 'defmacroexpand)' + + - Function: defmacro:expand* E + Returns the result of expanding all defmacros in scheme expression + E. + + +File: slib.info, Node: R4RS Macros, Next: Macro by Example, Prev: Defmacro, Up: Scheme Syntax Extension Packages + +R4RS Macros +=========== + + `(require 'macro)' is the appropriate call if you want R4RS +high-level macros but don't care about the low level implementation. If +an SLIB R4RS macro implementation is already loaded it will be used. +Otherwise, one of the R4RS macros implemetations is loaded. + + The SLIB R4RS macro implementations support the following uniform +interface: + + - Function: macro:expand SEXPRESSION + Takes an R4RS expression, macro-expands it, and returns the result + of the macro expansion. + + - Function: macro:eval SEXPRESSION + Takes an R4RS expression, macro-expands it, evals the result of the + macro expansion, and returns the result of the evaluation. + + - Procedure: macro:load FILENAME + FILENAME should be a string. If filename names an existing file, + the `macro:load' procedure reads Scheme source code expressions and + definitions from the file and evaluates them sequentially. These + source code expressions and definitions may contain macro + definitions. The `macro:load' procedure does not affect the + values returned by `current-input-port' and `current-output-port'. + + +File: slib.info, Node: Macro by Example, Next: Macros That Work, Prev: R4RS Macros, Up: Scheme Syntax Extension Packages + +Macro by Example +================ + + `(require 'macro-by-example)' + + A vanilla implementation of `Macro by Example' (Eugene Kohlbecker, +R4RS) by Dorai Sitaram, (dorai@cs.rice.edu) using `defmacro'. + + * generating hygienic global `define-syntax' Macro-by-Example macros + *cheaply*. + + * can define macros which use `...'. + + * needn't worry about a lexical variable in a macro definition + clashing with a variable from the macro use context + + * don't suffer the overhead of redefining the repl if `defmacro' + natively supported (most implementations) + +Caveat +------ + + These macros are not referentially transparent (*note Macros: +(r4rs)Macros.). Lexically scoped macros (i.e., `let-syntax' and +`letrec-syntax') are not supported. In any case, the problem of +referential transparency gains poignancy only when `let-syntax' and +`letrec-syntax' are used. So you will not be courting large-scale +disaster unless you're using system-function names as local variables +with unintuitive bindings that the macro can't use. However, if you +must have the full `r4rs' macro functionality, look to the more +featureful (but also more expensive) versions of syntax-rules available +in slib *Note Macros That Work::, *Note Syntactic Closures::, and *Note +Syntax-Case Macros::. + + - Macro: define-syntax KEYWORD TRANSFORMER-SPEC + The KEYWORD is an identifier, and the TRANSFORMER-SPEC should be + an instance of `syntax-rules'. + + The top-level syntactic environment is extended by binding the + KEYWORD to the specified transformer. + + (define-syntax let* + (syntax-rules () + ((let* () body1 body2 ...) + (let () body1 body2 ...)) + ((let* ((name1 val1) (name2 val2) ...) + body1 body2 ...) + (let ((name1 val1)) + (let* (( name2 val2) ...) + body1 body2 ...))))) + + - Macro: syntax-rules LITERALS SYNTAX-RULE ... + LITERALS is a list of identifiers, and each SYNTAX-RULE should be + of the form + + `(PATTERN TEMPLATE)' + + where the PATTERN and TEMPLATE are as in the grammar above. + + An instance of `syntax-rules' produces a new macro transformer by + specifying a sequence of hygienic rewrite rules. A use of a macro + whose keyword is associated with a transformer specified by + `syntax-rules' is matched against the patterns contained in the + SYNTAX-RULEs, beginning with the leftmost SYNTAX-RULE. When a + match is found, the macro use is trancribed hygienically according + to the template. + + Each pattern begins with the keyword for the macro. This keyword + is not involved in the matching and is not considered a pattern + variable or literal identifier. + + +File: slib.info, Node: Macros That Work, Next: Syntactic Closures, Prev: Macro by Example, Up: Scheme Syntax Extension Packages + +Macros That Work +================ + + `(require 'macros-that-work)' + + `Macros That Work' differs from the other R4RS macro implementations +in that it does not expand derived expression types to primitive +expression types. + + - Function: macro:expand EXPRESSION + - Function: macwork:expand EXPRESSION + Takes an R4RS expression, macro-expands it, and returns the result + of the macro expansion. + + - Function: macro:eval EXPRESSION + - Function: macwork:eval EXPRESSION + `macro:eval' returns the value of EXPRESSION in the current top + level environment. EXPRESSION can contain macro definitions. + Side effects of EXPRESSION will affect the top level environment. + + - Procedure: macro:load FILENAME + - Procedure: macwork:load FILENAME + FILENAME should be a string. If filename names an existing file, + the `macro:load' procedure reads Scheme source code expressions and + definitions from the file and evaluates them sequentially. These + source code expressions and definitions may contain macro + definitions. The `macro:load' procedure does not affect the + values returned by `current-input-port' and `current-output-port'. + + References: + + The `Revised^4 Report on the Algorithmic Language Scheme' Clinger and +Rees [editors]. To appear in LISP Pointers. Also available as a +technical report from the University of Oregon, MIT AI Lab, and Cornell. + + Macros That Work. Clinger and Rees. POPL '91. + + The supported syntax differs from the R4RS in that vectors are allowed +as patterns and as templates and are not allowed as pattern or template +data. + + transformer spec ==> (syntax-rules literals rules) + + rules ==> () + | (rule . rules) + + rule ==> (pattern template) + + pattern ==> pattern_var ; a symbol not in literals + | symbol ; a symbol in literals + | () + | (pattern . pattern) + | (ellipsis_pattern) + | #(pattern*) ; extends R4RS + | #(pattern* ellipsis_pattern) ; extends R4RS + | pattern_datum + + template ==> pattern_var + | symbol + | () + | (template2 . template2) + | #(template*) ; extends R4RS + | pattern_datum + + template2 ==> template + | ellipsis_template + + pattern_datum ==> string ; no vector + | character + | boolean + | number + + ellipsis_pattern ==> pattern ... + + ellipsis_template ==> template ... + + pattern_var ==> symbol ; not in literals + + literals ==> () + | (symbol . literals) + +Definitions +----------- + +Scope of an ellipsis + Within a pattern or template, the scope of an ellipsis (`...') is + the pattern or template that appears to its left. + +Rank of a pattern variable + The rank of a pattern variable is the number of ellipses within + whose scope it appears in the pattern. + +Rank of a subtemplate + The rank of a subtemplate is the number of ellipses within whose + scope it appears in the template. + +Template rank of an occurrence of a pattern variable + The template rank of an occurrence of a pattern variable within a + template is the rank of that occurrence, viewed as a subtemplate. + +Variables bound by a pattern + The variables bound by a pattern are the pattern variables that + appear within it. + +Referenced variables of a subtemplate + The referenced variables of a subtemplate are the pattern + variables that appear within it. + +Variables opened by an ellipsis template + The variables opened by an ellipsis template are the referenced + pattern variables whose rank is greater than the rank of the + ellipsis template. + +Restrictions +------------ + + No pattern variable appears more than once within a pattern. + + For every occurrence of a pattern variable within a template, the +template rank of the occurrence must be greater than or equal to the +pattern variable's rank. + + Every ellipsis template must open at least one variable. + + For every ellipsis template, the variables opened by an ellipsis +template must all be bound to sequences of the same length. + + The compiled form of a RULE is + + rule ==> (pattern template inserted) + + pattern ==> pattern_var + | symbol + | () + | (pattern . pattern) + | ellipsis_pattern + | #(pattern) + | pattern_datum + + template ==> pattern_var + | symbol + | () + | (template2 . template2) + | #(pattern) + | pattern_datum + + template2 ==> template + | ellipsis_template + + pattern_datum ==> string + | character + | boolean + | number + + pattern_var ==> #(V symbol rank) + + ellipsis_pattern ==> #(E pattern pattern_vars) + + ellipsis_template ==> #(E template pattern_vars) + + inserted ==> () + | (symbol . inserted) + + pattern_vars ==> () + | (pattern_var . pattern_vars) + + rank ==> exact non-negative integer + + where V and E are unforgeable values. + + The pattern variables associated with an ellipsis pattern are the +variables bound by the pattern, and the pattern variables associated +with an ellipsis template are the variables opened by the ellipsis +template. + + If the template contains a big chunk that contains no pattern +variables or inserted identifiers, then the big chunk will be copied +unnecessarily. That shouldn't matter very often. + + +File: slib.info, Node: Syntactic Closures, Next: Syntax-Case Macros, Prev: Macros That Work, Up: Scheme Syntax Extension Packages + +Syntactic Closures +================== + + `(require 'syntactic-closures)' + + - Function: macro:expand EXPRESSION + - Function: synclo:expand EXPRESSION + Returns scheme code with the macros and derived expression types of + EXPRESSION expanded to primitive expression types. + + - Function: macro:eval EXPRESSION + - Function: synclo:eval EXPRESSION + `macro:eval' returns the value of EXPRESSION in the current top + level environment. EXPRESSION can contain macro definitions. + Side effects of EXPRESSION will affect the top level environment. + + - Procedure: macro:load FILENAME + - Procedure: synclo:load FILENAME + FILENAME should be a string. If filename names an existing file, + the `macro:load' procedure reads Scheme source code expressions and + definitions from the file and evaluates them sequentially. These + source code expressions and definitions may contain macro + definitions. The `macro:load' procedure does not affect the + values returned by `current-input-port' and `current-output-port'. + +Syntactic Closure Macro Facility +-------------------------------- + + A Syntactic Closures Macro Facility + + by Chris Hanson + + 9 November 1991 + + This document describes "syntactic closures", a low-level macro +facility for the Scheme programming language. The facility is an +alternative to the low-level macro facility described in the `Revised^4 +Report on Scheme.' This document is an addendum to that report. + + The syntactic closures facility extends the BNF rule for TRANSFORMER +SPEC to allow a new keyword that introduces a low-level macro +transformer: + TRANSFORMER SPEC := (transformer EXPRESSION) + + Additionally, the following procedures are added: + make-syntactic-closure + capture-syntactic-environment + identifier? + identifier=? + + The description of the facility is divided into three parts. The +first part defines basic terminology. The second part describes how +macro transformers are defined. The third part describes the use of +"identifiers", which extend the syntactic closure mechanism to be +compatible with `syntax-rules'. + +Terminology +........... + + This section defines the concepts and data types used by the syntactic +closures facility. + + * "Forms" are the syntactic entities out of which programs are + recursively constructed. A form is any expression, any + definition, any syntactic keyword, or any syntactic closure. The + variable name that appears in a `set!' special form is also a + form. Examples of forms: + 17 + #t + car + (+ x 4) + (lambda (x) x) + (define pi 3.14159) + if + define + + * An "alias" is an alternate name for a given symbol. It can appear + anywhere in a form that the symbol could be used, and when quoted + it is replaced by the symbol; however, it does not satisfy the + predicate `symbol?'. Macro transformers rarely distinguish + symbols from aliases, referring to both as identifiers. + + * A "syntactic" environment maps identifiers to their meanings. + More precisely, it determines whether an identifier is a syntactic + keyword or a variable. If it is a keyword, the meaning is an + interpretation for the form in which that keyword appears. If it + is a variable, the meaning identifies which binding of that + variable is referenced. In short, syntactic environments contain + all of the contextual information necessary for interpreting the + meaning of a particular form. + + * A "syntactic closure" consists of a form, a syntactic environment, + and a list of identifiers. All identifiers in the form take their + meaning from the syntactic environment, except those in the given + list. The identifiers in the list are to have their meanings + determined later. A syntactic closure may be used in any context + in which its form could have been used. Since a syntactic closure + is also a form, it may not be used in contexts where a form would + be illegal. For example, a form may not appear as a clause in the + cond special form. A syntactic closure appearing in a quoted + structure is replaced by its form. + +Transformer Definition +...................... + + This section describes the `transformer' special form and the +procedures `make-syntactic-closure' and `capture-syntactic-environment'. + + - Syntax: transformer EXPRESSION + Syntax: It is an error if this syntax occurs except as a + TRANSFORMER SPEC. + + Semantics: The EXPRESSION is evaluated in the standard transformer + environment to yield a macro transformer as described below. This + macro transformer is bound to a macro keyword by the special form + in which the `transformer' expression appears (for example, + `let-syntax'). + + A "macro transformer" is a procedure that takes two arguments, a + form and a syntactic environment, and returns a new form. The + first argument, the "input form", is the form in which the macro + keyword occurred. The second argument, the "usage environment", + is the syntactic environment in which the input form occurred. + The result of the transformer, the "output form", is automatically + closed in the "transformer environment", which is the syntactic + environment in which the `transformer' expression occurred. + + For example, here is a definition of a push macro using + `syntax-rules': + (define-syntax push + (syntax-rules () + ((push item list) + (set! list (cons item list))))) + + Here is an equivalent definition using `transformer': + (define-syntax push + (transformer + (lambda (exp env) + (let ((item + (make-syntactic-closure env '() (cadr exp))) + (list + (make-syntactic-closure env '() (caddr exp)))) + `(set! ,list (cons ,item ,list)))))) + + In this example, the identifiers `set!' and `cons' are closed in + the transformer environment, and thus will not be affected by the + meanings of those identifiers in the usage environment `env'. + + Some macros may be non-hygienic by design. For example, the + following defines a loop macro that implicitly binds `exit' to an + escape procedure. The binding of `exit' is intended to capture + free references to `exit' in the body of the loop, so `exit' must + be left free when the body is closed: + (define-syntax loop + (transformer + (lambda (exp env) + (let ((body (cdr exp))) + `(call-with-current-continuation + (lambda (exit) + (let f () + ,@(map (lambda (exp) + (make-syntactic-closure env '(exit) + exp)) + body) + (f)))))))) + + To assign meanings to the identifiers in a form, use + `make-syntactic-closure' to close the form in a syntactic + environment. + + - Function: make-syntactic-closure ENVIRONMENT FREE-NAMES FORM + ENVIRONMENT must be a syntactic environment, FREE-NAMES must be a + list of identifiers, and FORM must be a form. + `make-syntactic-closure' constructs and returns a syntactic closure + of FORM in ENVIRONMENT, which can be used anywhere that FORM could + have been used. All the identifiers used in FORM, except those + explicitly excepted by FREE-NAMES, obtain their meanings from + ENVIRONMENT. + + Here is an example where FREE-NAMES is something other than the + empty list. It is instructive to compare the use of FREE-NAMES in + this example with its use in the `loop' example above: the examples + are similar except for the source of the identifier being left + free. + (define-syntax let1 + (transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (exp (cadddr exp))) + `((lambda (,id) + ,(make-syntactic-closure env (list id) exp)) + ,(make-syntactic-closure env '() init)))))) + + `let1' is a simplified version of `let' that only binds a single + identifier, and whose body consists of a single expression. When + the body expression is syntactically closed in its original + syntactic environment, the identifier that is to be bound by + `let1' must be left free, so that it can be properly captured by + the `lambda' in the output form. + + To obtain a syntactic environment other than the usage + environment, use `capture-syntactic-environment'. + + - Function: capture-syntactic-environment PROCEDURE + `capture-syntactic-environment' returns a form that will, when + transformed, call PROCEDURE on the current syntactic environment. + PROCEDURE should compute and return a new form to be transformed, + in that same syntactic environment, in place of the form. + + An example will make this clear. Suppose we wanted to define a + simple `loop-until' keyword equivalent to + (define-syntax loop-until + (syntax-rules () + ((loop-until id init test return step) + (letrec ((loop + (lambda (id) + (if test return (loop step))))) + (loop init))))) + + The following attempt at defining `loop-until' has a subtle bug: + (define-syntax loop-until + (transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (test (cadddr exp)) + (return (cadddr (cdr exp))) + (step (cadddr (cddr exp))) + (close + (lambda (exp free) + (make-syntactic-closure env free exp)))) + `(letrec ((loop + (lambda (,id) + (if ,(close test (list id)) + ,(close return (list id)) + (loop ,(close step (list id))))))) + (loop ,(close init '()))))))) + + This definition appears to take all of the proper precautions to + prevent unintended captures. It carefully closes the + subexpressions in their original syntactic environment and it + leaves the `id' identifier free in the `test', `return', and + `step' expressions, so that it will be captured by the binding + introduced by the `lambda' expression. Unfortunately it uses the + identifiers `if' and `loop' within that `lambda' expression, so if + the user of `loop-until' just happens to use, say, `if' for the + identifier, it will be inadvertently captured. + + The syntactic environment that `if' and `loop' want to be exposed + to is the one just outside the `lambda' expression: before the + user's identifier is added to the syntactic environment, but after + the identifier loop has been added. + `capture-syntactic-environment' captures exactly that environment + as follows: + (define-syntax loop-until + (transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (test (cadddr exp)) + (return (cadddr (cdr exp))) + (step (cadddr (cddr exp))) + (close + (lambda (exp free) + (make-syntactic-closure env free exp)))) + `(letrec ((loop + ,(capture-syntactic-environment + (lambda (env) + `(lambda (,id) + (,(make-syntactic-closure env '() `if) + ,(close test (list id)) + ,(close return (list id)) + (,(make-syntactic-closure env '() + `loop) + ,(close step (list id))))))))) + (loop ,(close init '()))))))) + + In this case, having captured the desired syntactic environment, + it is convenient to construct syntactic closures of the + identifiers `if' and the `loop' and use them in the body of the + `lambda'. + + A common use of `capture-syntactic-environment' is to get the + transformer environment of a macro transformer: + (transformer + (lambda (exp env) + (capture-syntactic-environment + (lambda (transformer-env) + ...)))) + +Identifiers +........... + + This section describes the procedures that create and manipulate +identifiers. Previous syntactic closure proposals did not have an +identifier data type - they just used symbols. The identifier data +type extends the syntactic closures facility to be compatible with the +high-level `syntax-rules' facility. + + As discussed earlier, an identifier is either a symbol or an "alias". +An alias is implemented as a syntactic closure whose "form" is an +identifier: + (make-syntactic-closure env '() 'a) + => an "alias" + + Aliases are implemented as syntactic closures because they behave just +like syntactic closures most of the time. The difference is that an +alias may be bound to a new value (for example by `lambda' or +`let-syntax'); other syntactic closures may not be used this way. If +an alias is bound, then within the scope of that binding it is looked +up in the syntactic environment just like any other identifier. + + Aliases are used in the implementation of the high-level facility +`syntax-rules'. A macro transformer created by `syntax-rules' uses a +template to generate its output form, substituting subforms of the +input form into the template. In a syntactic closures implementation, +all of the symbols in the template are replaced by aliases closed in +the transformer environment, while the output form itself is closed in +the usage environment. This guarantees that the macro transformation +is hygienic, without requiring the transformer to know the syntactic +roles of the substituted input subforms. + + - Function: identifier? OBJECT + Returns `#t' if OBJECT is an identifier, otherwise returns `#f'. + Examples: + (identifier? 'a) + => #t + (identifier? (make-syntactic-closure env '() 'a)) + => #t + (identifier? "a") + => #f + (identifier? #\a) + => #f + (identifier? 97) + => #f + (identifier? #f) + => #f + (identifier? '(a)) + => #f + (identifier? '#(a)) + => #f + + The predicate `eq?' is used to determine if two identifers are + "the same". Thus `eq?' can be used to compare identifiers exactly + as it would be used to compare symbols. Often, though, it is + useful to know whether two identifiers "mean the same thing". For + example, the `cond' macro uses the symbol `else' to identify the + final clause in the conditional. A macro transformer for `cond' + cannot just look for the symbol `else', because the `cond' form + might be the output of another macro transformer that replaced the + symbol `else' with an alias. Instead the transformer must look + for an identifier that "means the same thing" in the usage + environment as the symbol `else' means in the transformer + environment. + + - Function: identifier=? ENVIRONMENT1 IDENTIFIER1 ENVIRONMENT2 + IDENTIFIER2 + ENVIRONMENT1 and ENVIRONMENT2 must be syntactic environments, and + IDENTIFIER1 and IDENTIFIER2 must be identifiers. `identifier=?' + returns `#t' if the meaning of IDENTIFIER1 in ENVIRONMENT1 is the + same as that of IDENTIFIER2 in ENVIRONMENT2, otherwise it returns + `#f'. Examples: + + (let-syntax + ((foo + (transformer + (lambda (form env) + (capture-syntactic-environment + (lambda (transformer-env) + (identifier=? transformer-env 'x env 'x))))))) + (list (foo) + (let ((x 3)) + (foo)))) + => (#t #f) + + (let-syntax ((bar foo)) + (let-syntax + ((foo + (transformer + (lambda (form env) + (capture-syntactic-environment + (lambda (transformer-env) + (identifier=? transformer-env 'foo + env (cadr form)))))))) + (list (foo foo) + (foobar)))) + => (#f #t) + +Acknowledgements +................ + + The syntactic closures facility was invented by Alan Bawden and +Jonathan Rees. The use of aliases to implement `syntax-rules' was +invented by Alan Bawden (who prefers to call them "synthetic names"). +Much of this proposal is derived from an earlier proposal by Alan +Bawden. + + +File: slib.info, Node: Syntax-Case Macros, Next: Fluid-Let, Prev: Syntactic Closures, Up: Scheme Syntax Extension Packages + +Syntax-Case Macros +================== + + `(require 'syntax-case)' + + - Function: macro:expand EXPRESSION + - Function: syncase:expand EXPRESSION + Returns scheme code with the macros and derived expression types of + EXPRESSION expanded to primitive expression types. + + - Function: macro:eval EXPRESSION + - Function: syncase:eval EXPRESSION + `macro:eval' returns the value of EXPRESSION in the current top + level environment. EXPRESSION can contain macro definitions. + Side effects of EXPRESSION will affect the top level environment. + + - Procedure: macro:load FILENAME + - Procedure: syncase:load FILENAME + FILENAME should be a string. If filename names an existing file, + the `macro:load' procedure reads Scheme source code expressions and + definitions from the file and evaluates them sequentially. These + source code expressions and definitions may contain macro + definitions. The `macro:load' procedure does not affect the + values returned by `current-input-port' and `current-output-port'. + + This is version 2.1 of `syntax-case', the low-level macro facility +proposed and implemented by Robert Hieb and R. Kent Dybvig. + + This version is further adapted by Harald Hanche-Olsen +<hanche@imf.unit.no> to make it compatible with, and easily usable +with, SLIB. Mainly, these adaptations consisted of: + + * Removing white space from `expand.pp' to save space in the + distribution. This file is not meant for human readers anyway... + + * Removed a couple of Chez scheme dependencies. + + * Renamed global variables used to minimize the possibility of name + conflicts. + + * Adding an SLIB-specific initialization file. + + * Removing a couple extra files, most notably the documentation (but + see below). + + If you wish, you can see exactly what changes were done by reading the +shell script in the file `syncase.sh'. + + The two PostScript files were omitted in order to not burden the SLIB +distribution with them. If you do intend to use `syntax-case', +however, you should get these files and print them out on a PostScript +printer. They are available with the original `syntax-case' +distribution by anonymous FTP in +`cs.indiana.edu:/pub/scheme/syntax-case'. + + In order to use syntax-case from an interactive top level, execute: + (require 'syntax-case) + (require 'repl) + (repl:top-level macro:eval) + See the section Repl (*note Repl::.) for more information. + + To check operation of syntax-case get +`cs.indiana.edu:/pub/scheme/syntax-case', and type + (require 'syntax-case) + (syncase:sanity-check) + + Beware that `syntax-case' takes a long time to load - about 20s on a +SPARCstation SLC (with SCM) and about 90s on a Macintosh SE/30 (with +Gambit). + +Notes +----- + + All R4RS syntactic forms are defined, including `delay'. Along with +`delay' are simple definitions for `make-promise' (into which `delay' +expressions expand) and `force'. + + `syntax-rules' and `with-syntax' (described in `TR356') are defined. + + `syntax-case' is actually defined as a macro that expands into calls +to the procedure `syntax-dispatch' and the core form `syntax-lambda'; +do not redefine these names. + + Several other top-level bindings not documented in TR356 are created: + * the "hooks" in `hooks.ss' + + * the `build-' procedures in `output.ss' + + * `expand-syntax' (the expander) + + The syntax of define has been extended to allow `(define ID)', which +assigns ID to some unspecified value. + + We have attempted to maintain R4RS compatibility where possible. The +incompatibilities should be confined to `hooks.ss'. Please let us know +if there is some incompatibility that is not flagged as such. + + Send bug reports, comments, suggestions, and questions to Kent Dybvig +(dyb@iuvax.cs.indiana.edu). + +Note from maintainer +-------------------- + + Included with the `syntax-case' files was `structure.scm' which +defines a macro `define-structure'. There is no documentation for this +macro and it is not used by any code in SLIB. + + +File: slib.info, Node: Fluid-Let, Next: Yasos, Prev: Syntax-Case Macros, Up: Scheme Syntax Extension Packages + +Fluid-Let +========= + + `(require 'fluid-let)' + + - Syntax: fluid-let `(BINDINGS ...)' FORMS... + + (fluid-let ((VARIABLE INIT) ...) + EXPRESSION EXPRESSION ...) + + The INITs are evaluated in the current environment (in some +unspecified order), the current values of the VARIABLEs are saved, the +results are assigned to the VARIABLEs, the EXPRESSIONs are evaluated +sequentially in the current environment, the VARIABLEs are restored to +their original values, and the value of the last EXPRESSION is returned. + + The syntax of this special form is similar to that of `let', but +`fluid-let' temporarily rebinds existing VARIABLEs. Unlike `let', +`fluid-let' creates no new bindings; instead it *assigns* the values of +each INIT to the binding (determined by the rules of lexical scoping) +of its corresponding VARIABLE. + + +File: slib.info, Node: Yasos, Prev: Fluid-Let, Up: Scheme Syntax Extension Packages + +Yasos +===== + + `(require 'oop)' or `(require 'yasos)' + + `Yet Another Scheme Object System' is a simple object system for +Scheme based on the paper by Norman Adams and Jonathan Rees: `Object +Oriented Programming in Scheme', Proceedings of the 1988 ACM Conference +on LISP and Functional Programming, July 1988 [ACM #552880]. + + Another reference is: + + Ken Dickey. Scheming with Objects `AI Expert' Volume 7, Number 10 +(October 1992), pp. 24-33. + +* Menu: + +* Yasos terms:: Definitions and disclaimer. +* Yasos interface:: The Yasos macros and procedures. +* Setters:: Dylan-like setters in Yasos. +* Yasos examples:: Usage of Yasos and setters. + + +File: slib.info, Node: Yasos terms, Next: Yasos interface, Prev: Yasos, Up: Yasos + +Terms +----- + +"Object" + Any Scheme data object. + +"Instance" + An instance of the OO system; an "object". + +"Operation" + A METHOD. + +*Notes:* + The object system supports multiple inheritance. An instance can + inherit from 0 or more ancestors. In the case of multiple + inherited operations with the same identity, the operation used is + that from the first ancestor which contains it (in the ancestor + `let'). An operation may be applied to any Scheme data + object--not just instances. As code which creates instances is + just code, there are no "classes" and no meta-ANYTHING. Method + dispatch is by a procedure call a la CLOS rather than by `send' + syntax a la Smalltalk. + +*Disclaimer:* + There are a number of optimizations which can be made. This + implementation is expository (although performance should be quite + reasonable). See the L&FP paper for some suggestions. + + +File: slib.info, Node: Yasos interface, Next: Setters, Prev: Yasos terms, Up: Yasos + +Interface +--------- + + - Syntax: define-operation `('OPNAME SELF ARG ...`)' DEFAULT-BODY + Defines a default behavior for data objects which don't handle the + operation OPNAME. The default behavior (for an empty + DEFAULT-BODY) is to generate an error. + + - Syntax: define-predicate OPNAME? + Defines a predicate OPNAME?, usually used for determining the + "type" of an object, such that `(OPNAME? OBJECT)' returns `#t' if + OBJECT has an operation OPNAME? and `#f' otherwise. + + - Syntax: object `((NAME SELF ARG ...) BODY)' ... + Returns an object (an instance of the object system) with + operations. Invoking `(NAME OBJECT ARG ...' executes the BODY of + the OBJECT with SELF bound to OBJECT and with argument(s) ARG.... + + - Syntax: object-with-ancestors `(('ANCESTOR1 INIT1`)' ...`)' + OPERATION ... + A `let'-like form of `object' for multiple inheritance. It + returns an object inheriting the behaviour of ANCESTOR1 etc. An + operation will be invoked in an ancestor if the object itself does + not provide such a method. In the case of multiple inherited + operations with the same identity, the operation used is the one + found in the first ancestor in the ancestor list. + + - Syntax: operate-as COMPONENT OPERATION SELF ARG ... + Used in an operation definition (of SELF) to invoke the OPERATION + in an ancestor COMPONENT but maintain the object's identity. Also + known as "send-to-super". + + - Procedure: print OBJ PORT + A default `print' operation is provided which is just `(format + PORT OBJ)' (*note Format::.) for non-instances and prints OBJ + preceded by `#<INSTANCE>' for instances. + + - Function: size OBJ + The default method returns the number of elements in OBJ if it is + a vector, string or list, `2' for a pair, `1' for a character and + by default id an error otherwise. Objects such as collections + (*note Collections::.) may override the default in an obvious way. + + +File: slib.info, Node: Setters, Next: Yasos examples, Prev: Yasos interface, Up: Yasos + +Setters +------- + + "Setters" implement "generalized locations" for objects associated +with some sort of mutable state. A "getter" operation retrieves a +value from a generalized location and the corresponding setter +operation stores a value into the location. Only the getter is named - +the setter is specified by a procedure call as below. (Dylan uses +special syntax.) Typically, but not necessarily, getters are access +operations to extract values from Yasos objects (*note Yasos::.). +Several setters are predefined, corresponding to getters `car', `cdr', +`string-ref' and `vector-ref' e.g., `(setter car)' is equivalent to +`set-car!'. + + This implementation of setters is similar to that in Dylan(TM) +(`Dylan: An object-oriented dynamic language', Apple Computer Eastern +Research and Technology). Common LISP provides similar facilities +through `setf'. + + - Function: setter GETTER + Returns the setter for the procedure GETTER. E.g., since + `string-ref' is the getter corresponding to a setter which is + actually `string-set!': + (define foo "foo") + ((setter string-ref) foo 0 #\F) ; set element 0 of foo + foo => "Foo" + + - Syntax: set PLACE NEW-VALUE + If PLACE is a variable name, `set' is equivalent to `set!'. + Otherwise, PLACE must have the form of a procedure call, where the + procedure name refers to a getter and the call indicates an + accessible generalized location, i.e., the call would return a + value. The return value of `set' is usually unspecified unless + used with a setter whose definition guarantees to return a useful + value. + (set (string-ref foo 2) #\O) ; generalized location with getter + foo => "FoO" + (set foo "foo") ; like set! + foo => "foo" + + - Procedure: add-setter GETTER SETTER + Add procedures GETTER and SETTER to the (inaccessible) list of + valid setter/getter pairs. SETTER implements the store operation + corresponding to the GETTER access operation for the relevant + state. The return value is unspecified. + + - Procedure: remove-setter-for GETTER + Removes the setter corresponding to the specified GETTER from the + list of valid setters. The return value is unspecified. + + - Syntax: define-access-operation GETTER-NAME + Shorthand for a Yasos `define-operation' defining an operation + GETTER-NAME that objects may support to return the value of some + mutable state. The default operation is to signal an error. The + return value is unspecified. + + +File: slib.info, Node: Yasos examples, Prev: Setters, Up: Yasos + +Examples +-------- + + ;;; These definitions for PRINT and SIZE are + ;;; already supplied by + (require 'yasos) + + (define-operation (print obj port) + (format port + (if (instance? obj) "#<instance>" "~s") + obj)) + + (define-operation (size obj) + (cond + ((vector? obj) (vector-length obj)) + ((list? obj) (length obj)) + ((pair? obj) 2) + ((string? obj) (string-length obj)) + ((char? obj) 1) + (else + (error "Operation not supported: size" obj)))) + + (define-predicate cell?) + (define-operation (fetch obj)) + (define-operation (store! obj newValue)) + + (define (make-cell value) + (object + ((cell? self) #t) + ((fetch self) value) + ((store! self newValue) + (set! value newValue) + newValue) + ((size self) 1) + ((print self port) + (format port "#<Cell: ~s>" (fetch self))))) + + (define-operation (discard obj value) + (format #t "Discarding ~s~%" value)) + + (define (make-filtered-cell value filter) + (object-with-ancestors + ((cell (make-cell value))) + ((store! self newValue) + (if (filter newValue) + (store! cell newValue) + (discard self newValue))))) + + (define-predicate array?) + (define-operation (array-ref array index)) + (define-operation (array-set! array index value)) + + (define (make-array num-slots) + (let ((anArray (make-vector num-slots))) + (object + ((array? self) #t) + ((size self) num-slots) + ((array-ref self index) + (vector-ref anArray index)) + ((array-set! self index newValue) + (vector-set! anArray index newValue)) + ((print self port) + (format port "#<Array ~s>" (size self)))))) + + (define-operation (position obj)) + (define-operation (discarded-value obj)) + + (define (make-cell-with-history value filter size) + (let ((pos 0) (most-recent-discard #f)) + (object-with-ancestors + ((cell (make-filtered-call value filter)) + (sequence (make-array size))) + ((array? self) #f) + ((position self) pos) + ((store! self newValue) + (operate-as cell store! self newValue) + (array-set! self pos newValue) + (set! pos (+ pos 1))) + ((discard self value) + (set! most-recent-discard value)) + ((discarded-value self) most-recent-discard) + ((print self port) + (format port "#<Cell-with-history ~s>" + (fetch self)))))) + + (define-access-operation fetch) + (add-setter fetch store!) + (define foo (make-cell 1)) + (print foo #f) + => "#<Cell: 1>" + (set (fetch foo) 2) + => + (print foo #f) + => "#<Cell: 2>" + (fetch foo) + => 2 + + +File: slib.info, Node: Textual Conversion Packages, Next: Mathematical Packages, Prev: Scheme Syntax Extension Packages, Up: Top + +Textual Conversion Packages +*************************** + +* Menu: + +* Precedence Parsing:: +* Format:: Common-Lisp Format +* Standard Formatted I/O:: Posix printf and scanf +* Programs and Arguments:: +* HTML HTTP and CGI:: Generate pages and serve WWW sites +* Printing Scheme:: Nicely +* Time and Date:: +* Vector Graphics:: +* Schmooz:: Documentation markup for Scheme programs + + +File: slib.info, Node: Precedence Parsing, Next: Format, Prev: Textual Conversion Packages, Up: Textual Conversion Packages + +Precedence Parsing +================== + + `(require 'precedence-parse)' or `(require 'parse)' + +This package implements: + + * a Pratt style precedence parser; + + * a "tokenizer" which congeals tokens according to assigned classes + of constituent characters; + + * procedures giving direct control of parser rulesets; + + * procedures for higher level specification of rulesets. + +* Menu: + +* Precedence Parsing Overview:: +* Ruleset Definition and Use:: +* Token definition:: +* Nud and Led Definition:: +* Grammar Rule Definition:: + + +File: slib.info, Node: Precedence Parsing Overview, Next: Ruleset Definition and Use, Prev: Precedence Parsing, Up: Precedence Parsing + +Precedence Parsing Overview +--------------------------- + +This package offers improvements over previous parsers. + + * Common computer language constructs are concisely specified. + + * Grammars can be changed dynamically. Operators can be assigned + different meanings within a lexical context. + + * Rulesets don't need compilation. Grammars can be changed + incrementally. + + * Operator precedence is specified by integers. + + * All possibilities of bad input are handled (1) and return as much + structure as was parsed when the error occured; The symbol `?' is + substituted for missing input. + +Here are the higher-level syntax types and an example of each. +Precedence considerations are omitted for clarity. See *Note Grammar +Rule Definition:: for full details. + + - Grammar: nofix bye exit + bye + calls the function `exit' with no arguments. + + - Grammar: prefix - negate + - 42 + Calls the function `negate' with the argument `42'. + + - Grammar: infix - difference + x - y + Calls the function `difference' with arguments `x' and `y'. + + - Grammar: nary + sum + x + y + z + Calls the function `sum' with arguments `x', `y', and `y'. + + - Grammar: postfix ! factorial + 5 ! + Calls the function `factorial' with the argument `5'. + + - Grammar: prestfix set set! + set foo bar + Calls the function `set!' with the arguments `foo' and `bar'. + + - Grammar: commentfix /* */ + /* almost any text here */ + Ignores the comment delimited by `/*' and `*/'. + + - Grammar: matchfix { list } + {0, 1, 2} + Calls the function `list' with the arguments `0', `1', and `2'. + + - Grammar: inmatchfix ( funcall ) + f(x, y) + Calls the function `funcall' with the arguments `f', `x', and `y'. + + - Grammar: delim ; + set foo bar; + delimits the extent of the restfix operator `set'. + + ---------- Footnotes ---------- + + (1) How do I know this? I parsed 250kbyte of random input (an e-mail +file) with a non-trivial grammar utilizing all constructs. + + +File: slib.info, Node: Ruleset Definition and Use, Next: Token definition, Prev: Precedence Parsing Overview, Up: Precedence Parsing + +Ruleset Definition and Use +-------------------------- + + - Variable: *syn-defs* + A grammar is built by one or more calls to `prec:define-grammar'. + The rules are appended to *SYN-DEFS*. The value of *SYN-DEFS* is + the grammar suitable for passing as an argument to `prec:parse'. + + - Constant: *syn-ignore-whitespace* + Is a nearly empty grammar with whitespace characters set to group + 0, which means they will not be made into tokens. Most rulesets + will want to start with `*syn-ignore-whitespace*' + +In order to start defining a grammar, either + + (set! *syn-defs* '()) + +or + + (set! *syn-defs* *syn-ignore-whitespace*) + + - Function: prec:define-grammar RULE1 ... + Appends RULE1 ... to *SYN-DEFS*. `prec:define-grammar' is used to + define both the character classes and rules for tokens. + +Once your grammar is defined, save the value of `*syn-defs*' in a +variable (for use when calling `prec:parse'). + + (define my-ruleset *syn-defs*) + + - Function: prec:parse RULESET DELIM + - Function: prec:parse RULESET DELIM PORT + The RULESET argument must be a list of rules as constructed by + `prec:define-grammar' and extracted from *SYN-DEFS*. + + The token DELIM may be a character, symbol, or string. A + character DELIM argument will match only a character token; i.e. a + character for which no token-group is assigned. A symbols or + string will match only a token string; i.e. a token resulting from + a token group. + + `prec:parse' reads a RULESET grammar expression delimited by DELIM + from the given input PORT. `prec:parse' returns the next object + parsable from the given input PORT, updating PORT to point to the + first character past the end of the external representation of the + object. + + If an end of file is encountered in the input before any + characters are found that can begin an object, then an end of file + object is returned. If a delimiter (such as DELIM) is found + before any characters are found that can begin an object, then + `#f' is returned. + + The PORT argument may be omitted, in which case it defaults to the + value returned by `current-input-port'. It is an error to parse + from a closed port. + + +File: slib.info, Node: Token definition, Next: Nud and Led Definition, Prev: Ruleset Definition and Use, Up: Precedence Parsing + +Token definition +---------------- + + - Function: tok:char-group GROUP CHARS CHARS-PROC + The argument CHARS may be a single character, a list of + characters, or a string. Each character in CHARS is treated as + though `tok:char-group' was called with that character alone. + + The argument CHARS-PROC must be a procedure of one argument, a + list of characters. After `tokenize' has finished accumulating + the characters for a token, it calls CHARS-PROC with the list of + characters. The value returned is the token which `tokenize' + returns. + + The argument GROUP may be an exact integer or a procedure of one + character argument. The following discussion concerns the + treatment which the tokenizing routine, `tokenize', will accord to + characters on the basis of their groups. + + When GROUP is a non-zero integer, characters whose group number is + equal to or exactly one less than GROUP will continue to + accumulate. Any other character causes the accumulation to stop + (until a new token is to be read). + + The GROUP of zero is special. These characters are ignored when + parsed pending a token, and stop the accumulation of token + characters when the accumulation has already begun. Whitespace + characters are usually put in group 0. + + If GROUP is a procedure, then, when triggerd by the occurence of + an initial (no accumulation) CHARS character, this procedure will + be repeatedly called with each successive character from the input + stream until the GROUP procedure returns a non-false value. + +The following convenient constants are provided for use with +`tok:char-group'. + + - Constant: tok:decimal-digits + Is the string `"0123456789"'. + + - Constant: tok:upper-case + Is the string consisting of all upper-case letters + ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"). + + - Constant: tok:lower-case + Is the string consisting of all lower-case letters + ("abcdefghijklmnopqrstuvwxyz"). + + - Constant: tok:whitespaces + Is the string consisting of all characters between 0 and 255 for + which `char-whitespace?' returns true. + + +File: slib.info, Node: Nud and Led Definition, Next: Grammar Rule Definition, Prev: Token definition, Up: Precedence Parsing + +Nud and Led Definition +---------------------- + + This section describes advanced features. You can skip this section +on first reading. + +The "Null Denotation" (or "nud") of a token is the procedure and +arguments applying for that token when "Left", an unclaimed parsed +expression is not extant. + +The "Left Denotation" (or "led") of a token is the procedure, +arguments, and lbp applying for that token when there is a "Left", an +unclaimed parsed expression. + +In his paper, + + Pratt, V. R. Top Down Operator Precendence. `SIGACT/SIGPLAN + Symposium on Principles of Programming Languages', Boston, 1973, + pages 41-51 + + the "left binding power" (or "lbp") was an independent property of +tokens. I think this was done in order to allow tokens with NUDs but +not LEDs to also be used as delimiters, which was a problem for +statically defined syntaxes. It turns out that *dynamically binding* +NUDs and LEDs allows them independence. + +For the rule-defining procedures that follow, the variable TK may be a +character, string, or symbol, or a list composed of characters, +strings, and symbols. Each element of TK is treated as though the +procedure were called for each element. + +Character TK arguments will match only character tokens; i.e. +characters for which no token-group is assigned. Symbols and strings +will both match token strings; i.e. tokens resulting from token groups. + + - Function: prec:make-nud TK SOP ARG1 ... + Returns a rule specifying that SOP be called when TK is parsed. + If SOP is a procedure, it is called with TK and ARG1 ... as its + arguments; the resulting value is incorporated into the expression + being built. Otherwise, `(list SOP ARG1 ...)' is incorporated. + +If no NUD has been defined for a token; then if that token is a string, +it is converted to a symbol and returned; if not a string, the token is +returned. + + - Function: prec:make-led TK SOP ARG1 ... + Returns a rule specifying that SOP be called when TK is parsed and + LEFT has an unclaimed parsed expression. If SOP is a procedure, + it is called with LEFT, TK, and ARG1 ... as its arguments; the + resulting value is incorporated into the expression being built. + Otherwise, LEFT is incorporated. + +If no LED has been defined for a token, and LEFT is set, the parser +issues a warning. + + +File: slib.info, Node: Grammar Rule Definition, Prev: Nud and Led Definition, Up: Precedence Parsing + +Grammar Rule Definition +----------------------- + +Here are procedures for defining rules for the syntax types introduced +in *Note Precedence Parsing Overview::. + +For the rule-defining procedures that follow, the variable TK may be a +character, string, or symbol, or a list composed of characters, +strings, and symbols. Each element of TK is treated as though the +procedure were called for each element. + +For procedures prec:delim, ..., prec:prestfix, if the SOP argument is +`#f', then the token which triggered this rule is converted to a symbol +and returned. A false SOP argument to the procedures prec:commentfix, +prec:matchfix, or prec:inmatchfix has a different meaning. + +Character TK arguments will match only character tokens; i.e. +characters for which no token-group is assigned. Symbols and strings +will both match token strings; i.e. tokens resulting from token groups. + + - Function: prec:delim TK + Returns a rule specifying that TK should not be returned from + parsing; i.e. TK's function is purely syntactic. The end-of-file + is always treated as a delimiter. + + - Function: prec:nofix TK SOP + Returns a rule specifying the following actions take place when TK + is parsed: + * If SOP is a procedure, it is called with no arguments; the + resulting value is incorporated into the expression being + built. Otherwise, the list of SOP is incorporated. + + - Function: prec:prefix TK SOP BP RULE1 ... + Returns a rule specifying the following actions take place when TK + is parsed: + * The rules RULE1 ... augment and, in case of conflict, override + rules currently in effect. + + * `prec:parse1' is called with binding-power BP. + + * If SOP is a procedure, it is called with the expression + returned from `prec:parse1'; the resulting value is + incorporated into the expression being built. Otherwise, the + list of SOP and the expression returned from `prec:parse1' is + incorporated. + + * The ruleset in effect before TK was parsed is restored; RULE1 + ... are forgotten. + + - Function: prec:infix TK SOP LBP BP RULE1 ... + Returns a rule declaring the left-binding-precedence of the token + TK is LBP and specifying the following actions take place when TK + is parsed: + * The rules RULE1 ... augment and, in case of conflict, override + rules currently in effect. + + * One expression is parsed with binding-power LBP. If instead a + delimiter is encountered, a warning is issued. + + * If SOP is a procedure, it is applied to the list of LEFT and + the parsed expression; the resulting value is incorporated + into the expression being built. Otherwise, the list of SOP, + the LEFT expression, and the parsed expression is + incorporated. + + * The ruleset in effect before TK was parsed is restored; RULE1 + ... are forgotten. + + - Function: prec:nary TK SOP BP + Returns a rule declaring the left-binding-precedence of the token + TK is BP and specifying the following actions take place when TK + is parsed: + * Expressions are parsed with binding-power BP as far as they + are interleaved with the token TK. + + * If SOP is a procedure, it is applied to the list of LEFT and + the parsed expressions; the resulting value is incorporated + into the expression being built. Otherwise, the list of SOP, + the LEFT expression, and the parsed expressions is + incorporated. + + - Function: prec:postfix TK SOP LBP + Returns a rule declaring the left-binding-precedence of the token + TK is LBP and specifying the following actions take place when TK + is parsed: + * If SOP is a procedure, it is called with the LEFT expression; + the resulting value is incorporated into the expression being + built. Otherwise, the list of SOP and the LEFT expression is + incorporated. + + - Function: prec:prestfix TK SOP BP RULE1 ... + Returns a rule specifying the following actions take place when TK + is parsed: + * The rules RULE1 ... augment and, in case of conflict, override + rules currently in effect. + + * Expressions are parsed with binding-power BP until a + delimiter is reached. + + * If SOP is a procedure, it is applied to the list of parsed + expressions; the resulting value is incorporated into the + expression being built. Otherwise, the list of SOP and the + parsed expressions is incorporated. + + * The ruleset in effect before TK was parsed is restored; RULE1 + ... are forgotten. + + - Function: prec:commentfix TK STP MATCH RULE1 ... + Returns rules specifying the following actions take place when TK + is parsed: + * The rules RULE1 ... augment and, in case of conflict, override + rules currently in effect. + + * Characters are read until and end-of-file or a sequence of + characters is read which matches the *string* MATCH. + + * If STP is a procedure, it is called with the string of all + that was read between the TK and MATCH (exclusive). + + * The ruleset in effect before TK was parsed is restored; RULE1 + ... are forgotten. + + Parsing of commentfix syntax differs from the others in several + ways. It reads directly from input without tokenizing; It calls + STP but does not return its value; nay any value. I added the STP + argument so that comment text could be echoed. + + - Function: prec:matchfix TK SOP SEP MATCH RULE1 ... + Returns a rule specifying the following actions take place when TK + is parsed: + * The rules RULE1 ... augment and, in case of conflict, override + rules currently in effect. + + * A rule declaring the token MATCH a delimiter takes effect. + + * Expressions are parsed with binding-power `0' until the token + MATCH is reached. If the token SEP does not appear between + each pair of expressions parsed, a warning is issued. + + * If SOP is a procedure, it is applied to the list of parsed + expressions; the resulting value is incorporated into the + expression being built. Otherwise, the list of SOP and the + parsed expressions is incorporated. + + * The ruleset in effect before TK was parsed is restored; RULE1 + ... are forgotten. + + - Function: prec:inmatchfix TK SOP SEP MATCH LBP RULE1 ... + Returns a rule declaring the left-binding-precedence of the token + TK is LBP and specifying the following actions take place when TK + is parsed: + * The rules RULE1 ... augment and, in case of conflict, override + rules currently in effect. + + * A rule declaring the token MATCH a delimiter takes effect. + + * Expressions are parsed with binding-power `0' until the token + MATCH is reached. If the token SEP does not appear between + each pair of expressions parsed, a warning is issued. + + * If SOP is a procedure, it is applied to the list of LEFT and + the parsed expressions; the resulting value is incorporated + into the expression being built. Otherwise, the list of SOP, + the LEFT expression, and the parsed expressions is + incorporated. + + * The ruleset in effect before TK was parsed is restored; RULE1 + ... are forgotten. + + +File: slib.info, Node: Format, Next: Standard Formatted I/O, Prev: Precedence Parsing, Up: Textual Conversion Packages + +Format (version 3.0) +==================== + + `(require 'format)' + +* Menu: + +* Format Interface:: +* Format Specification:: + + +File: slib.info, Node: Format Interface, Next: Format Specification, Prev: Format, Up: Format + +Format Interface +---------------- + + - Function: format DESTINATION FORMAT-STRING . ARGUMENTS + An almost complete implementation of Common LISP format description + according to the CL reference book `Common LISP' from Guy L. + Steele, Digital Press. Backward compatible to most of the + available Scheme format implementations. + + Returns `#t', `#f' or a string; has side effect of printing + according to FORMAT-STRING. If DESTINATION is `#t', the output is + to the current output port and `#t' is returned. If DESTINATION + is `#f', a formatted string is returned as the result of the call. + NEW: If DESTINATION is a string, DESTINATION is regarded as the + format string; FORMAT-STRING is then the first argument and the + output is returned as a string. If DESTINATION is a number, the + output is to the current error port if available by the + implementation. Otherwise DESTINATION must be an output port and + `#t' is returned. + + FORMAT-STRING must be a string. In case of a formatting error + format returns `#f' and prints a message on the current output or + error port. Characters are output as if the string were output by + the `display' function with the exception of those prefixed by a + tilde (~). For a detailed description of the FORMAT-STRING syntax + please consult a Common LISP format reference manual. For a test + suite to verify this format implementation load `formatst.scm'. + Please send bug reports to `lutzeb@cs.tu-berlin.de'. + + Note: `format' is not reentrant, i.e. only one `format'-call may + be executed at a time. + + + +File: slib.info, Node: Format Specification, Prev: Format Interface, Up: Format + +Format Specification (Format version 3.0) +----------------------------------------- + + Please consult a Common LISP format reference manual for a detailed +description of the format string syntax. For a demonstration of the +implemented directives see `formatst.scm'. + + This implementation supports directive parameters and modifiers (`:' +and `@' characters). Multiple parameters must be separated by a comma +(`,'). Parameters can be numerical parameters (positive or negative), +character parameters (prefixed by a quote character (`''), variable +parameters (`v'), number of rest arguments parameter (`#'), empty and +default parameters. Directive characters are case independent. The +general form of a directive is: + +DIRECTIVE ::= ~{DIRECTIVE-PARAMETER,}[:][@]DIRECTIVE-CHARACTER + +DIRECTIVE-PARAMETER ::= [ [-|+]{0-9}+ | 'CHARACTER | v | # ] + +Implemented CL Format Control Directives +........................................ + + Documentation syntax: Uppercase characters represent the corresponding +control directive characters. Lowercase characters represent control +directive parameter descriptions. + +`~A' + Any (print as `display' does). + `~@A' + left pad. + + `~MINCOL,COLINC,MINPAD,PADCHARA' + full padding. + +`~S' + S-expression (print as `write' does). + `~@S' + left pad. + + `~MINCOL,COLINC,MINPAD,PADCHARS' + full padding. + +`~D' + Decimal. + `~@D' + print number sign always. + + `~:D' + print comma separated. + + `~MINCOL,PADCHAR,COMMACHARD' + padding. + +`~X' + Hexadecimal. + `~@X' + print number sign always. + + `~:X' + print comma separated. + + `~MINCOL,PADCHAR,COMMACHARX' + padding. + +`~O' + Octal. + `~@O' + print number sign always. + + `~:O' + print comma separated. + + `~MINCOL,PADCHAR,COMMACHARO' + padding. + +`~B' + Binary. + `~@B' + print number sign always. + + `~:B' + print comma separated. + + `~MINCOL,PADCHAR,COMMACHARB' + padding. + +`~NR' + Radix N. + `~N,MINCOL,PADCHAR,COMMACHARR' + padding. + +`~@R' + print a number as a Roman numeral. + +`~:@R' + print a number as an "old fashioned" Roman numeral. + +`~:R' + print a number as an ordinal English number. + +`~:@R' + print a number as a cardinal English number. + +`~P' + Plural. + `~@P' + prints `y' and `ies'. + + `~:P' + as `~P but jumps 1 argument backward.' + + `~:@P' + as `~@P but jumps 1 argument backward.' + +`~C' + Character. + `~@C' + prints a character as the reader can understand it (i.e. `#\' + prefixing). + + `~:C' + prints a character as emacs does (eg. `^C' for ASCII 03). + +`~F' + Fixed-format floating-point (prints a flonum like MMM.NNN). + `~WIDTH,DIGITS,SCALE,OVERFLOWCHAR,PADCHARF' + + `~@F' + If the number is positive a plus sign is printed. + +`~E' + Exponential floating-point (prints a flonum like MMM.NNN`E'EE). + `~WIDTH,DIGITS,EXPONENTDIGITS,SCALE,OVERFLOWCHAR,PADCHAR,EXPONENTCHARE' + + `~@E' + If the number is positive a plus sign is printed. + +`~G' + General floating-point (prints a flonum either fixed or + exponential). + `~WIDTH,DIGITS,EXPONENTDIGITS,SCALE,OVERFLOWCHAR,PADCHAR,EXPONENTCHARG' + + `~@G' + If the number is positive a plus sign is printed. + +`~$' + Dollars floating-point (prints a flonum in fixed with signs + separated). + `~DIGITS,SCALE,WIDTH,PADCHAR$' + + `~@$' + If the number is positive a plus sign is printed. + + `~:@$' + A sign is always printed and appears before the padding. + + `~:$' + The sign appears before the padding. + +`~%' + Newline. + `~N%' + print N newlines. + +`~&' + print newline if not at the beginning of the output line. + `~N&' + prints `~&' and then N-1 newlines. + +`~|' + Page Separator. + `~N|' + print N page separators. + +`~~' + Tilde. + `~N~' + print N tildes. + +`~'<newline> + Continuation Line. + `~:'<newline> + newline is ignored, white space left. + + `~@'<newline> + newline is left, white space ignored. + +`~T' + Tabulation. + `~@T' + relative tabulation. + + `~COLNUM,COLINCT' + full tabulation. + +`~?' + Indirection (expects indirect arguments as a list). + `~@?' + extracts indirect arguments from format arguments. + +`~(STR~)' + Case conversion (converts by `string-downcase'). + `~:(STR~)' + converts by `string-capitalize'. + + `~@(STR~)' + converts by `string-capitalize-first'. + + `~:@(STR~)' + converts by `string-upcase'. + +`~*' + Argument Jumping (jumps 1 argument forward). + `~N*' + jumps N arguments forward. + + `~:*' + jumps 1 argument backward. + + `~N:*' + jumps N arguments backward. + + `~@*' + jumps to the 0th argument. + + `~N@*' + jumps to the Nth argument (beginning from 0) + +`~[STR0~;STR1~;...~;STRN~]' + Conditional Expression (numerical clause conditional). + `~N[' + take argument from N. + + `~@[' + true test conditional. + + `~:[' + if-else-then conditional. + + `~;' + clause separator. + + `~:;' + default clause follows. + +`~{STR~}' + Iteration (args come from the next argument (a list)). + `~N{' + at most N iterations. + + `~:{' + args from next arg (a list of lists). + + `~@{' + args from the rest of arguments. + + `~:@{' + args from the rest args (lists). + +`~^' + Up and out. + `~N^' + aborts if N = 0 + + `~N,M^' + aborts if N = M + + `~N,M,K^' + aborts if N <= M <= K + +Not Implemented CL Format Control Directives +............................................ + +`~:A' + print `#f' as an empty list (see below). + +`~:S' + print `#f' as an empty list (see below). + +`~<~>' + Justification. + +`~:^' + (sorry I don't understand its semantics completely) + +Extended, Replaced and Additional Control Directives +.................................................... + +`~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHD' + +`~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHX' + +`~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHO' + +`~MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHB' + +`~N,MINCOL,PADCHAR,COMMACHAR,COMMAWIDTHR' + COMMAWIDTH is the number of characters between two comma + characters. + +`~I' + print a R4RS complex number as `~F~@Fi' with passed parameters for + `~F'. + +`~Y' + Pretty print formatting of an argument for scheme code lists. + +`~K' + Same as `~?.' + +`~!' + Flushes the output if format DESTINATION is a port. + +`~_' + Print a `#\space' character + `~N_' + print N `#\space' characters. + +`~/' + Print a `#\tab' character + `~N/' + print N `#\tab' characters. + +`~NC' + Takes N as an integer representation for a character. No arguments + are consumed. N is converted to a character by `integer->char'. N + must be a positive decimal number. + +`~:S' + Print out readproof. Prints out internal objects represented as + `#<...>' as strings `"#<...>"' so that the format output can always + be processed by `read'. + +`~:A' + Print out readproof. Prints out internal objects represented as + `#<...>' as strings `"#<...>"' so that the format output can always + be processed by `read'. + +`~Q' + Prints information and a copyright notice on the format + implementation. + `~:Q' + prints format version. + +`~F, ~E, ~G, ~$' + may also print number strings, i.e. passing a number as a string + and format it accordingly. + +Configuration Variables +....................... + + Format has some configuration variables at the beginning of +`format.scm' to suit the systems and users needs. There should be no +modification necessary for the configuration that comes with SLIB. If +modification is desired the variable should be set after the format +code is loaded. Format detects automatically if the running scheme +system implements floating point numbers and complex numbers. + +FORMAT:SYMBOL-CASE-CONV + Symbols are converted by `symbol->string' so the case type of the + printed symbols is implementation dependent. + `format:symbol-case-conv' is a one arg closure which is either + `#f' (no conversion), `string-upcase', `string-downcase' or + `string-capitalize'. (default `#f') + +FORMAT:IOBJ-CASE-CONV + As FORMAT:SYMBOL-CASE-CONV but applies for the representation of + implementation internal objects. (default `#f') + +FORMAT:EXPCH + The character prefixing the exponent value in `~E' printing. + (default `#\E') + +Compatibility With Other Format Implementations +............................................... + +SLIB format 2.x: + See `format.doc'. + +SLIB format 1.4: + Downward compatible except for padding support and `~A', `~S', + `~P', `~X' uppercase printing. SLIB format 1.4 uses C-style + `printf' padding support which is completely replaced by the CL + `format' padding style. + +MIT C-Scheme 7.1: + Downward compatible except for `~', which is not documented + (ignores all characters inside the format string up to a newline + character). (7.1 implements `~a', `~s', ~NEWLINE, `~~', `~%', + numerical and variable parameters and `:/@' modifiers in the CL + sense). + +Elk 1.5/2.0: + Downward compatible except for `~A' and `~S' which print in + uppercase. (Elk implements `~a', `~s', `~~', and `~%' (no + directive parameters or modifiers)). + +Scheme->C 01nov91: + Downward compatible except for an optional destination parameter: + S2C accepts a format call without a destination which returns a + formatted string. This is equivalent to a #f destination in S2C. + (S2C implements `~a', `~s', `~c', `~%', and `~~' (no directive + parameters or modifiers)). + + This implementation of format is solely useful in the SLIB context +because it requires other components provided by SLIB. + + +File: slib.info, Node: Standard Formatted I/O, Next: Programs and Arguments, Prev: Format, Up: Textual Conversion Packages + +Standard Formatted I/O +====================== + +* Menu: + +* Standard Formatted Output:: 'printf +* Standard Formatted Input:: 'scanf + +stdio +----- + + `(require 'stdio)' + + `require's `printf' and `scanf' and additionally defines the symbols: + + - Variable: stdin + Defined to be `(current-input-port)'. + + - Variable: stdout + Defined to be `(current-output-port)'. + + - Variable: stderr + Defined to be `(current-error-port)'. + + +File: slib.info, Node: Standard Formatted Output, Next: Standard Formatted Input, Prev: Standard Formatted I/O, Up: Standard Formatted I/O + +Standard Formatted Output +------------------------- + + `(require 'printf)' + + - Procedure: printf FORMAT ARG1 ... + - Procedure: fprintf PORT FORMAT ARG1 ... + - Procedure: sprintf STR FORMAT ARG1 ... + - Procedure: sprintf #F FORMAT ARG1 ... + - Procedure: sprintf K FORMAT ARG1 ... + Each function converts, formats, and outputs its ARG1 ... + arguments according to the control string FORMAT argument and + returns the number of characters output. + + `printf' sends its output to the port `(current-output-port)'. + `fprintf' sends its output to the port PORT. `sprintf' + `string-set!'s locations of the non-constant string argument STR + to the output characters. + + Two extensions of `sprintf' return new strings. If the first + argument is `#f', then the returned string's length is as many + characters as specified by the FORMAT and data; if the first + argument is a non-negative integer K, then the length of the + returned string is also bounded by K. + + The string FORMAT contains plain characters which are copied to + the output stream, and conversion specifications, each of which + results in fetching zero or more of the arguments ARG1 .... The + results are undefined if there are an insufficient number of + arguments for the format. If FORMAT is exhausted while some of the + ARG1 ... arguments remain unused, the excess ARG1 ... arguments + are ignored. + + The conversion specifications in a format string have the form: + + % [ FLAGS ] [ WIDTH ] [ . PRECISION ] [ TYPE ] CONVERSION + + An output conversion specifications consist of an initial `%' + character followed in sequence by: + + * Zero or more "flag characters" that modify the normal + behavior of the conversion specification. + + `-' + Left-justify the result in the field. Normally the + result is right-justified. + + `+' + For the signed `%d' and `%i' conversions and all inexact + conversions, prefix a plus sign if the value is positive. + + ` ' + For the signed `%d' and `%i' conversions, if the result + doesn't start with a plus or minus sign, prefix it with + a space character instead. Since the `+' flag ensures + that the result includes a sign, this flag is ignored if + both are specified. + + `#' + For inexact conversions, `#' specifies that the result + should always include a decimal point, even if no digits + follow it. For the `%g' and `%G' conversions, this also + forces trailing zeros after the decimal point to be + printed where they would otherwise be elided. + + For the `%o' conversion, force the leading digit to be + `0', as if by increasing the precision. For `%x' or + `%X', prefix a leading `0x' or `0X' (respectively) to + the result. This doesn't do anything useful for the + `%d', `%i', or `%u' conversions. Using this flag + produces output which can be parsed by the `scanf' + functions with the `%i' conversion (*note Standard + Formatted Input::.). + + `0' + Pad the field with zeros instead of spaces. The zeros + are placed after any indication of sign or base. This + flag is ignored if the `-' flag is also specified, or if + a precision is specified for an exact converson. + + * An optional decimal integer specifying the "minimum field + width". If the normal conversion produces fewer characters + than this, the field is padded (with spaces or zeros per the + `0' flag) to the specified width. This is a *minimum* width; + if the normal conversion produces more characters than this, + the field is *not* truncated. + + Alternatively, if the field width is `*', the next argument + in the argument list (before the actual value to be printed) + is used as the field width. The width value must be an + integer. If the value is negative it is as though the `-' + flag is set (see above) and the absolute value is used as the + field width. + + * An optional "precision" to specify the number of digits to be + written for numeric conversions and the maximum field width + for string conversions. The precision is specified by a + period (`.') followed optionally by a decimal integer (which + defaults to zero if omitted). + + Alternatively, if the precision is `.*', the next argument in + the argument list (before the actual value to be printed) is + used as the precision. The value must be an integer, and is + ignored if negative. If you specify `*' for both the field + width and precision, the field width argument precedes the + precision argument. The `.*' precision is an enhancement. C + library versions may not accept this syntax. + + For the `%f', `%e', and `%E' conversions, the precision + specifies how many digits follow the decimal-point character. + The default precision is `6'. If the precision is + explicitly `0', the decimal point character is suppressed. + + For the `%g' and `%G' conversions, the precision specifies how + many significant digits to print. Significant digits are the + first digit before the decimal point, and all the digits + after it. If the precision is `0' or not specified for `%g' + or `%G', it is treated like a value of `1'. If the value + being printed cannot be expressed accurately in the specified + number of digits, the value is rounded to the nearest number + that fits. + + For exact conversions, if a precision is supplied it + specifies the minimum number of digits to appear; leading + zeros are produced if necessary. If a precision is not + supplied, the number is printed with as many digits as + necessary. Converting an exact `0' with an explicit + precision of zero produces no characters. + + * An optional one of `l', `h' or `L', which is ignored for + numeric conversions. It is an error to specify these + modifiers for non-numeric conversions. + + * A character that specifies the conversion to be applied. + +Exact Conversions +................. + + `d', `i' + Print an integer as a signed decimal number. `%d' and `%i' + are synonymous for output, but are different when used with + `scanf' for input (*note Standard Formatted Input::.). + + `o' + Print an integer as an unsigned octal number. + + `u' + Print an integer as an unsigned decimal number. + + `x', `X' + Print an integer as an unsigned hexadecimal number. `%x' + prints using the digits `0123456789abcdef'. `%X' prints + using the digits `0123456789ABCDEF'. + +Inexact Conversions +................... + + `f' + Print a floating-point number in fixed-point notation. + + `e', `E' + Print a floating-point number in exponential notation. `%e' + prints `e' between mantissa and exponont. `%E' prints `E' + between mantissa and exponont. + + `g', `G' + Print a floating-point number in either fixed or exponential | + notation, whichever is more appropriate for its magnitude. + Unless an `#' flag has been supplied trailing zeros after a + decimal point will be stripped off. `%g' prints `e' between + mantissa and exponont. `%G' prints `E' between mantissa and + exponent. + +Other Conversions +................. + + `c' + Print a single character. The `-' flag is the only one which + can be specified. It is an error to specify a precision. + + `s' + Print a string. The `-' flag is the only one which can be + specified. A precision specifies the maximum number of + characters to output; otherwise all characters in the string + are output. + + `a', `A' + Print a scheme expression. The `-' flag left-justifies the + output. The `#' flag specifies that strings and characters + should be quoted as by `write' (which can be read using + `read'); otherwise, output is as `display' prints. A + precision specifies the maximum number of characters to + output; otherwise as many characters as needed are output. + + *Note:* `%a' and `%A' are SLIB extensions. + + `%' + Print a literal `%' character. No argument is consumed. It + is an error to specifiy flags, field width, precision, or + type modifiers with `%%'. + + +File: slib.info, Node: Standard Formatted Input, Prev: Standard Formatted Output, Up: Standard Formatted I/O + +Standard Formatted Input +------------------------ + + `(require 'scanf)' + + - Function: scanf-read-list FORMAT + - Function: scanf-read-list FORMAT PORT + - Function: scanf-read-list FORMAT STRING + + - Macro: scanf FORMAT ARG1 ... + - Macro: fscanf PORT FORMAT ARG1 ... + - Macro: sscanf STR FORMAT ARG1 ... + Each function reads characters, interpreting them according to the + control string FORMAT argument. + + `scanf-read-list' returns a list of the items specified as far as + the input matches FORMAT. `scanf', `fscanf', and `sscanf' return + the number of items successfully matched and stored. `scanf', + `fscanf', and `sscanf' also set the location corresponding to ARG1 + ... using the methods: + + symbol + `set!' + + car expression + `set-car!' + + cdr expression + `set-cdr!' + + vector-ref expression + `vector-set!' + + substring expression + `substring-move-left!' + + The argument to a `substring' expression in ARG1 ... must be a + non-constant string. Characters will be stored starting at the + position specified by the second argument to `substring'. The + number of characters stored will be limited by either the position + specified by the third argument to `substring' or the length of the + matched string, whichever is less. + + The control string, FORMAT, contains conversion specifications and + other characters used to direct interpretation of input sequences. + The control string contains: + + * White-space characters (blanks, tabs, newlines, or formfeeds) + that cause input to be read (and discarded) up to the next + non-white-space character. + + * An ordinary character (not `%') that must match the next + character of the input stream. + + * Conversion specifications, consisting of the character `%', an + optional assignment suppressing character `*', an optional + numerical maximum-field width, an optional `l', `h' or `L' + which is ignored, and a conversion code. + + Unless the specification contains the `n' conversion character + (described below), a conversion specification directs the + conversion of the next input field. The result of a conversion + specification is returned in the position of the corresponding + argument points, unless `*' indicates assignment suppression. + Assignment suppression provides a way to describe an input field + to be skipped. An input field is defined as a string of + characters; it extends to the next inappropriate character or + until the field width, if specified, is exhausted. + + *Note:* This specification of format strings differs from the + `ANSI C' and `POSIX' specifications. In SLIB, white space + before an input field is not skipped unless white space + appears before the conversion specification in the format + string. In order to write format strings which work + identically with `ANSI C' and SLIB, prepend whitespace to all + conversion specifications except `[' and `c'. + + The conversion code indicates the interpretation of the input + field; For a suppressed field, no value is returned. The + following conversion codes are legal: + + `%' + A single % is expected in the input at this point; no value + is returned. + + `d', `D' + A decimal integer is expected. + + `u', `U' + An unsigned decimal integer is expected. + + `o', `O' + An octal integer is expected. + + `x', `X' + A hexadecimal integer is expected. + + `i' + An integer is expected. Returns the value of the next input + item, interpreted according to C conventions; a leading `0' + implies octal, a leading `0x' implies hexadecimal; otherwise, + decimal is assumed. + + `n' + Returns the total number of bytes (including white space) + read by `scanf'. No input is consumed by `%n'. + + `f', `F', `e', `E', `g', `G' + A floating-point number is expected. The input format for + floating-point numbers is an optionally signed string of + digits, possibly containing a radix character `.', followed + by an optional exponent field consisting of an `E' or an `e', + followed by an optional `+', `-', or space, followed by an + integer. + + `c', `C' + WIDTH characters are expected. The normal + skip-over-white-space is suppressed in this case; to read the + next non-space character, use `%1s'. If a field width is + given, a string is returned; up to the indicated number of + characters is read. + + `s', `S' + A character string is expected The input field is terminated + by a white-space character. `scanf' cannot read a null + string. + + `[' + Indicates string data and the normal + skip-over-leading-white-space is suppressed. The left + bracket is followed by a set of characters, called the + scanset, and a right bracket; the input field is the maximal + sequence of input characters consisting entirely of + characters in the scanset. `^', when it appears as the first + character in the scanset, serves as a complement operator and + redefines the scanset as the set of all characters not + contained in the remainder of the scanset string. + Construction of the scanset follows certain conventions. A + range of characters may be represented by the construct + first-last, enabling `[0123456789]' to be expressed `[0-9]'. + Using this convention, first must be lexically less than or + equal to last; otherwise, the dash stands for itself. The + dash also stands for itself when it is the first or the last + character in the scanset. To include the right square + bracket as an element of the scanset, it must appear as the + first character (possibly preceded by a `^') of the scanset, + in which case it will not be interpreted syntactically as the + closing bracket. At least one character must match for this + conversion to succeed. + + The `scanf' functions terminate their conversions at end-of-file, + at the end of the control string, or when an input character + conflicts with the control string. In the latter case, the + offending character is left unread in the input stream. + + +File: slib.info, Node: Programs and Arguments, Next: HTML HTTP and CGI, Prev: Standard Formatted I/O, Up: Textual Conversion Packages + +Program and Arguments +===================== + +* Menu: + +* Getopt:: Command Line option parsing +* Command Line:: A command line reader for Scheme shells +* Parameter lists:: 'parameters +* Getopt Parameter lists:: 'getopt-parameters +* Filenames:: 'glob or 'filename +* Batch:: 'batch + + +File: slib.info, Node: Getopt, Next: Command Line, Prev: Programs and Arguments, Up: Programs and Arguments + +Getopt +------ + + `(require 'getopt)' + + This routine implements Posix command line argument parsing. Notice +that returning values through global variables means that `getopt' is +*not* reentrant. + + - Variable: *optind* + Is the index of the current element of the command line. It is + initially one. In order to parse a new command line or reparse an + old one, *OPTING* must be reset. + + - Variable: *optarg* + Is set by getopt to the (string) option-argument of the current + option. + + - Procedure: getopt ARGC ARGV OPTSTRING + Returns the next option letter in ARGV (starting from `(vector-ref + argv *optind*)') that matches a letter in OPTSTRING. ARGV is a + vector or list of strings, the 0th of which getopt usually + ignores. ARGC is the argument count, usually the length of ARGV. + OPTSTRING is a string of recognized option characters; if a + character is followed by a colon, the option takes an argument + which may be immediately following it in the string or in the next + element of ARGV. + + *OPTIND* is the index of the next element of the ARGV vector to be + processed. It is initialized to 1 by `getopt.scm', and `getopt' + updates it when it finishes with each element of ARGV. + + `getopt' returns the next option character from ARGV that matches + a character in OPTSTRING, if there is one that matches. If the + option takes an argument, `getopt' sets the variable *OPTARG* to + the option-argument as follows: + + * If the option was the last character in the string pointed to + by an element of ARGV, then *OPTARG* contains the next + element of ARGV, and *OPTIND* is incremented by 2. If the + resulting value of *OPTIND* is greater than or equal to ARGC, + this indicates a missing option argument, and `getopt' + returns an error indication. + + * Otherwise, *OPTARG* is set to the string following the option + character in that element of ARGV, and *OPTIND* is + incremented by 1. + + If, when `getopt' is called, the string `(vector-ref argv + *optind*)' either does not begin with the character `#\-' or is + just `"-"', `getopt' returns `#f' without changing *OPTIND*. If + `(vector-ref argv *optind*)' is the string `"--"', `getopt' + returns `#f' after incrementing *OPTIND*. + + If `getopt' encounters an option character that is not contained in + OPTSTRING, it returns the question-mark `#\?' character. If it + detects a missing option argument, it returns the colon character + `#\:' if the first character of OPTSTRING was a colon, or a + question-mark character otherwise. In either case, `getopt' sets + the variable GETOPT:OPT to the option character that caused the + error. + + The special option `"--"' can be used to delimit the end of the + options; `#f' is returned, and `"--"' is skipped. + + RETURN VALUE + + `getopt' returns the next option character specified on the command + line. A colon `#\:' is returned if `getopt' detects a missing + argument and the first character of OPTSTRING was a colon `#\:'. + + A question-mark `#\?' is returned if `getopt' encounters an option + character not in OPTSTRING or detects a missing argument and the + first character of OPTSTRING was not a colon `#\:'. + + Otherwise, `getopt' returns `#f' when all command line options + have been parsed. + + Example: + #! /usr/local/bin/scm + ;;;This code is SCM specific. + (define argv (program-arguments)) + (require 'getopt) + + (define opts ":a:b:cd") + (let loop ((opt (getopt (length argv) argv opts))) + (case opt + ((#\a) (print "option a: " *optarg*)) + ((#\b) (print "option b: " *optarg*)) + ((#\c) (print "option c")) + ((#\d) (print "option d")) + ((#\?) (print "error" getopt:opt)) + ((#\:) (print "missing arg" getopt:opt)) + ((#f) (if (< *optind* (length argv)) + (print "argv[" *optind* "]=" + (list-ref argv *optind*))) + (set! *optind* (+ *optind* 1)))) + (if (< *optind* (length argv)) + (loop (getopt (length argv) argv opts)))) + + (slib:exit) + +Getopt- +------- + + - Function: getopt- ARGC ARGV OPTSTRING + The procedure `getopt--' is an extended version of `getopt' which + parses "long option names" of the form `--hold-the-onions' and + `--verbosity-level=extreme'. `Getopt--' behaves as `getopt' + except for non-empty options beginning with `--'. + + Options beginning with `--' are returned as strings rather than + characters. If a value is assigned (using `=') to a long option, + `*optarg*' is set to the value. The `=' and value are not + returned as part of the option string. + + No information is passed to `getopt--' concerning which long + options should be accepted or whether such options can take + arguments. If a long option did not have an argument, `*optarg' + will be set to `#f'. The caller is responsible for detecting and + reporting errors. + + (define opts ":-:b:") + (define argc 5) + (define argv '("foo" "-b9" "--f1" "--2=" "--g3=35234.342" "--")) + (define *optind* 1) + (define *optarg* #f) + (require 'qp) + (do ((i 5 (+ -1 i))) + ((zero? i)) + (define opt (getopt-- argc argv opts)) + (print *optind* opt *optarg*))) + -| + 2 #\b "9" + 3 "f1" #f + 4 "2" "" + 5 "g3" "35234.342" + 5 #f "35234.342" + + +File: slib.info, Node: Command Line, Next: Parameter lists, Prev: Getopt, Up: Programs and Arguments + +Command Line +------------ + + `(require 'read-command)' + + - Function: read-command PORT + - Function: read-command + `read-command' converts a "command line" into a list of strings + suitable for parsing by `getopt'. The syntax of command lines + supported resembles that of popular "shell"s. `read-command' + updates PORT to point to the first character past the command + delimiter. + + If an end of file is encountered in the input before any + characters are found that can begin an object or comment, then an + end of file object is returned. + + The PORT argument may be omitted, in which case it defaults to the + value returned by `current-input-port'. + + The fields into which the command line is split are delimited by + whitespace as defined by `char-whitespace?'. The end of a command + is delimited by end-of-file or unescaped semicolon (<;>) or + <newline>. Any character can be literally included in a field by + escaping it with a backslach (<\>). + + The initial character and types of fields recognized are: + `\' + The next character has is taken literally and not interpreted + as a field delimiter. If <\> is the last character before a + <newline>, that <newline> is just ignored. Processing + continues from the characters after the <newline> as though + the backslash and <newline> were not there. + + `"' + The characters up to the next unescaped <"> are taken + literally, according to [R4RS] rules for literal strings + (*note Strings: (r4rs)Strings.). + + `(', `%'' + One scheme expression is `read' starting with this character. + The `read' expression is evaluated, converted to a string + (using `display'), and replaces the expression in the returned + field. + + `;' + Semicolon delimits a command. Using semicolons more than one + command can appear on a line. Escaped semicolons and + semicolons inside strings do not delimit commands. + + The comment field differs from the previous fields in that it must + be the first character of a command or appear after whitespace in + order to be recognized. <#> can be part of fields if these + conditions are not met. For instance, `ab#c' is just the field + ab#c. + + `#' + Introduces a comment. The comment continues to the end of + the line on which the semicolon appears. Comments are + treated as whitespace by `read-dommand-line' and backslashes + before <newline>s in comments are also ignored. + + - Function: read-options-file FILENAME + `read-options-file' converts an "options file" into a list of + strings suitable for parsing by `getopt'. The syntax of options + files is the same as the syntax for command lines, except that + <newline>s do not terminate reading (only <;> or end of file). + + If an end of file is encountered before any characters are found + that can begin an object or comment, then an end of file object is + returned. + + +File: slib.info, Node: Parameter lists, Next: Getopt Parameter lists, Prev: Command Line, Up: Programs and Arguments + +Parameter lists +--------------- + + `(require 'parameters)' + +Arguments to procedures in scheme are distinguished from each other by +their position in the procedure call. This can be confusing when a +procedure takes many arguments, many of which are not often used. + +A "parameter-list" is a way of passing named information to a +procedure. Procedures are also defined to set unused parameters to +default values, check parameters, and combine parameter lists. + +A PARAMETER has the form `(parameter-name value1 ...)'. This format +allows for more than one value per parameter-name. + +A PARAMETER-LIST is a list of PARAMETERs, each with a different +PARAMETER-NAME. + + - Function: make-parameter-list PARAMETER-NAMES + Returns an empty parameter-list with slots for PARAMETER-NAMES. + + - Function: parameter-list-ref PARAMETER-LIST PARAMETER-NAME + PARAMETER-NAME must name a valid slot of PARAMETER-LIST. + `parameter-list-ref' returns the value of parameter PARAMETER-NAME + of PARAMETER-LIST. + + - Procedure: adjoin-parameters! PARAMETER-LIST PARAMETER1 ... + Returns PARAMETER-LIST with PARAMETER1 ... merged in. + + - Procedure: parameter-list-expand EXPANDERS PARAMETER-LIST + EXPANDERS is a list of procedures whose order matches the order of + the PARAMETER-NAMEs in the call to `make-parameter-list' which + created PARAMETER-LIST. For each non-false element of EXPANDERS + that procedure is mapped over the corresponding parameter value + and the returned parameter lists are merged into PARAMETER-LIST. + + This process is repeated until PARAMETER-LIST stops growing. The + value returned from `parameter-list-expand' is unspecified. + + - Function: fill-empty-parameters DEFAULTERS PARAMETER-LIST + DEFAULTERS is a list of procedures whose order matches the order + of the PARAMETER-NAMEs in the call to `make-parameter-list' which + created PARAMETER-LIST. `fill-empty-parameters' returns a new + parameter-list with each empty parameter replaced with the list + returned by calling the corresponding DEFAULTER with + PARAMETER-LIST as its argument. + + - Function: check-parameters CHECKS PARAMETER-LIST + CHECKS is a list of procedures whose order matches the order of + the PARAMETER-NAMEs in the call to `make-parameter-list' which + created PARAMETER-LIST. + + `check-parameters' returns PARAMETER-LIST if each CHECK of the + corresponding PARAMETER-LIST returns non-false. If some CHECK + returns `#f' an error is signaled. + +In the following procedures ARITIES is a list of symbols. The elements +of `arities' can be: + +`single' + Requires a single parameter. + +`optional' + A single parameter or no parameter is acceptable. + +`boolean' + A single boolean parameter or zero parameters is acceptable. + +`nary' + Any number of parameters are acceptable. + +`nary1' + One or more of parameters are acceptable. + + - Function: parameter-list->arglist POSITIONS ARITIES TYPES + PARAMETER-LIST + Returns PARAMETER-LIST converted to an argument list. Parameters + of ARITY type `single' and `boolean' are converted to the single + value associated with them. The other ARITY types are converted + to lists of the value(s) of type TYPES. + + POSITIONS is a list of positive integers whose order matches the + order of the PARAMETER-NAMEs in the call to `make-parameter-list' + which created PARAMETER-LIST. The integers specify in which + argument position the corresponding parameter should appear. + + +File: slib.info, Node: Getopt Parameter lists, Next: Filenames, Prev: Parameter lists, Up: Programs and Arguments + +Getopt Parameter lists +---------------------- + + `(require 'getopt-parameters)' + + - Function: getopt->parameter-list ARGC ARGV OPTNAMES ARITIES TYPES + ALIASES + Returns ARGV converted to a parameter-list. OPTNAMES are the + parameter-names. ALIASES is a list of lists of strings and + elements of OPTNAMES. Each of these strings which have length of + 1 will be treated as a single <-> option by `getopt'. Longer + strings will be treated as long-named options (*note getopt-: + Getopt.). + + - Function: getopt->arglist ARGC ARGV OPTNAMES POSITIONS ARITIES TYPES + DEFAULTERS CHECKS ALIASES + Like `getopt->parameter-list', but converts ARGV to an + argument-list as specified by OPTNAMES, POSITIONS, ARITIES, TYPES, + DEFAULTERS, CHECKS, and ALIASES. + +These `getopt' functions can be used with SLIB relational databases. +For an example, *Note make-command-server: Database Utilities. + +If errors are encountered while processing options, directions for using +the options are printed to `current-error-port'. + + (begin + (set! *optind* 1) + (getopt->parameter-list + 2 + '("cmd" "-?") + '(flag number symbols symbols string flag2 flag3 num2 num3) + '(boolean optional nary1 nary single boolean boolean nary nary) + '(boolean integer symbol symbol string boolean boolean integer integer) + '(("flag" flag) + ("f" flag) + ("Flag" flag2) + ("B" flag3) + ("optional" number) + ("o" number) + ("nary1" symbols) + ("N" symbols) + ("nary" symbols) + ("n" symbols) + ("single" string) + ("s" string) + ("a" num2) + ("Abs" num3)))) + -| + Usage: cmd [OPTION ARGUMENT ...] ... + + -f, --flag + -o, --optional=<number> + -n, --nary=<symbols> ... + -N, --nary1=<symbols> ... + -s, --single=<string> + --Flag + -B + -a <num2> ... + --Abs=<num3> ... + + ERROR: getopt->parameter-list "unrecognized option" "-?" + + +File: slib.info, Node: Filenames, Next: Batch, Prev: Getopt Parameter lists, Up: Programs and Arguments + +Filenames +--------- + + `(require 'filename)' or `(require 'glob)' + + - Function: filename:match?? PATTERN + - Function: filename:match-ci?? PATTERN + Returns a predicate which returns a non-false value if its string + argument matches (the string) PATTERN, false otherwise. Filename + matching is like "glob" expansion described the bash manpage, + except that names beginning with `.' are matched and `/' + characters are not treated specially. + + These functions interpret the following characters specially in + PATTERN strings: + `*' + Matches any string, including the null string. + + `?' + Matches any single character. + + `[...]' + Matches any one of the enclosed characters. A pair of + characters separated by a minus sign (-) denotes a range; any + character lexically between those two characters, inclusive, + is matched. If the first character following the `[' is a + `!' or a `^' then any character not enclosed is matched. A + `-' or `]' may be matched by including it as the first or + last character in the set. + + + - Function: filename:substitute?? PATTERN TEMPLATE + - Function: filename:substitute-ci?? PATTERN TEMPLATE + Returns a function transforming a single string argument according + to glob patterns PATTERN and TEMPLATE. PATTERN and TEMPLATE must + have the same number of wildcard specifications, which need not be + identical. PATTERN and TEMPLATE may have a different number of + literal sections. If an argument to the function matches PATTERN + in the sense of `filename:match??' then it returns a copy of + TEMPLATE in which each wildcard specification is replaced by the + part of the argument matched by the corresponding wildcard + specification in PATTERN. A `*' wildcard matches the longest + leftmost string possible. If the argument does not match PATTERN + then false is returned. + + TEMPLATE may be a function accepting the same number of string + arguments as there are wildcard specifications in PATTERN. In the + case of a match the result of applying TEMPLATE to a list of the + substrings matched by wildcard specifications will be returned, + otherwise TEMPLATE will not be called and `#f' will be returned. + + ((filename:substitute?? "scm_[0-9]*.html" "scm5c4_??.htm") + "scm_10.html") + => "scm5c4_10.htm" + ((filename:substitute?? "??" "beg?mid?end") "AZ") + => "begAmidZend" + ((filename:substitute?? "*na*" "?NA?") "banana") + => "banaNA" + ((filename:substitute?? "?*?" (lambda (s1 s2 s3) (string-append s3 s1))) "ABZ") + => "ZA" + + - Function: replace-suffix STR OLD NEW + STR can be a string or a list of strings. Returns a new string + (or strings) similar to `str' but with the suffix string OLD + removed and the suffix string NEW appended. If the end of STR + does not match OLD, an error is signaled. + + (replace-suffix "/usr/local/lib/slib/batch.scm" ".scm" ".c") + => "/usr/local/lib/slib/batch.c" + + +File: slib.info, Node: Batch, Prev: Filenames, Up: Programs and Arguments + +Batch +----- + + `(require 'batch)' + +The batch procedures provide a way to write and execute portable scripts +for a variety of operating systems. Each `batch:' procedure takes as +its first argument a parameter-list (*note Parameter lists::.). This +parameter-list argument PARMS contains named associations. Batch +currently uses 2 of these: + +`batch-port' + The port on which to write lines of the batch file. + +`batch-dialect' + The syntax of batch file to generate. Currently supported are: + * unix + + * dos + + * vms + + * amigados + + * system + + * *unknown* + +`batch.scm' uses 2 enhanced relational tables (*note Database +Utilities::.) to store information linking the names of +`operating-system's to `batch-dialect'es. + + - Function: batch:initialize! DATABASE + Defines `operating-system' and `batch-dialect' tables and adds the + domain `operating-system' to the enhanced relational database + DATABASE. + + - Variable: batch:platform + Is batch's best guess as to which operating-system it is running + under. `batch:platform' is set to `(software-type)' (*note + Configuration::.) unless `(software-type)' is `unix', in which + case finer distinctions are made. + + - Function: batch:call-with-output-script PARMS FILE PROC + PROC should be a procedure of one argument. If FILE is an + output-port, `batch:call-with-output-script' writes an appropriate + header to FILE and then calls PROC with FILE as the only argument. + If FILE is a string, `batch:call-with-output-script' opens a + output-file of name FILE, writes an appropriate header to FILE, + and then calls PROC with the newly opened port as the only + argument. Otherwise, `batch:call-with-output-script' acts as if + it was called with the result of `(current-output-port)' as its + third argument. + | +The rest of the `batch:' procedures write (or execute if +`batch-dialect' is `system') commands to the batch port which has been +added to PARMS or `(copy-tree PARMS)' by the code: + + (adjoin-parameters! PARMS (list 'batch-port PORT)) + + - Function: batch:command PARMS STRING1 STRING2 ... | + Calls `batch:try-command' (below) with arguments, but signals an | + error if `batch:try-command' returns `#f'. | + +These functions return a non-false value if the command was successfully +translated into the batch dialect and `#f' if not. In the case of the +`system' dialect, the value is non-false if the operation suceeded. + + - Function: batch:try-command PARMS STRING1 STRING2 ... | + Writes a command to the `batch-port' in PARMS which executes the + program named STRING1 with arguments STRING2 .... + + - Function: batch:try-chopped-command PARMS ARG1 ARG2 ... LIST | + breaks the last argument LIST into chunks small enough so that the | + command: | + | + ARG1 ARG2 ... CHUNK | + | + fits withing the platform's maximum command-line length. | + | + `batch:try-chopped-command' calls `batch:try-command' with the | + command and returns non-false only if the commands all fit and | + `batch:try-command' of each command line returned non-false. | + | + - Function: batch:run-script PARMS STRING1 STRING2 ... + Writes a command to the `batch-port' in PARMS which executes the + batch script named STRING1 with arguments STRING2 .... + + *Note:* `batch:run-script' and `batch:try-command' are not the | + same for some operating systems (VMS). | + + - Function: batch:comment PARMS LINE1 ... + Writes comment lines LINE1 ... to the `batch-port' in PARMS. + + - Function: batch:lines->file PARMS FILE LINE1 ... + Writes commands to the `batch-port' in PARMS which create a file + named FILE with contents LINE1 .... + + - Function: batch:delete-file PARMS FILE + Writes a command to the `batch-port' in PARMS which deletes the + file named FILE. + + - Function: batch:rename-file PARMS OLD-NAME NEW-NAME + Writes a command to the `batch-port' in PARMS which renames the + file OLD-NAME to NEW-NAME. + +In addition, batch provides some small utilities very useful for writing +scripts: + + - Function: truncate-up-to PATH CHAR + - Function: truncate-up-to PATH STRING + - Function: truncate-up-to PATH CHARLIST + PATH can be a string or a list of strings. Returns PATH sans any + prefixes ending with a character of the second argument. This can + be used to derive a filename moved locally from elsewhere. + + (truncate-up-to "/usr/local/lib/slib/batch.scm" "/") + => "batch.scm" + + - Function: string-join JOINER STRING1 ... + Returns a new string consisting of all the strings STRING1 ... in + order appended together with the string JOINER between each + adjacent pair. + + - Function: must-be-first LIST1 LIST2 + Returns a new list consisting of the elements of LIST2 ordered so + that if some elements of LIST1 are `equal?' to elements of LIST2, + then those elements will appear first and in the order of LIST1. + + - Function: must-be-last LIST1 LIST2 + Returns a new list consisting of the elements of LIST1 ordered so + that if some elements of LIST2 are `equal?' to elements of LIST1, + then those elements will appear last and in the order of LIST2. + + - Function: os->batch-dialect OSNAME + Returns its best guess for the `batch-dialect' to be used for the + operating-system named OSNAME. `os->batch-dialect' uses the + tables added to DATABASE by `batch:initialize!'. + +Here is an example of the use of most of batch's procedures: + + (require 'database-utilities) + (require 'parameters) + (require 'batch) + (require 'glob) + + (define batch (create-database #f 'alist-table)) + (batch:initialize! batch) + + (define my-parameters + (list (list 'batch-dialect (os->batch-dialect batch:platform)) + (list 'platform batch:platform) + (list 'batch-port (current-output-port)))) ;gets filled in later + + (batch:call-with-output-script + my-parameters + "my-batch" + (lambda (batch-port) + (adjoin-parameters! my-parameters (list 'batch-port batch-port)) + (and + (batch:comment my-parameters + "================ Write file with C program.") + (batch:rename-file my-parameters "hello.c" "hello.c~") + (batch:lines->file my-parameters "hello.c" + "#include <stdio.h>" + "int main(int argc, char **argv)" + "{" + " printf(\"hello world\\n\");" + " return 0;" + "}" ) + (batch:command my-parameters "cc" "-c" "hello.c") | + (batch:command my-parameters "cc" "-o" "hello" | + (replace-suffix "hello.c" ".c" ".o")) + (batch:command my-parameters "hello") | + (batch:delete-file my-parameters "hello") + (batch:delete-file my-parameters "hello.c") + (batch:delete-file my-parameters "hello.o") + (batch:delete-file my-parameters "my-batch") + ))) + +Produces the file `my-batch': + + #!/bin/sh + # "my-batch" script created by SLIB/batch Sun Oct 31 18:24:10 1999 | + # ================ Write file with C program. + mv -f hello.c hello.c~ + rm -f hello.c + echo '#include <stdio.h>'>>hello.c + echo 'int main(int argc, char **argv)'>>hello.c + echo '{'>>hello.c + echo ' printf("hello world\n");'>>hello.c + echo ' return 0;'>>hello.c + echo '}'>>hello.c + cc -c hello.c + cc -o hello hello.o + hello + rm -f hello + rm -f hello.c + rm -f hello.o + rm -f my-batch + +When run, `my-batch' prints: + + bash$ my-batch + mv: hello.c: No such file or directory + hello world + + +File: slib.info, Node: HTML HTTP and CGI, Next: Printing Scheme, Prev: Programs and Arguments, Up: Textual Conversion Packages + +HTML Forms +========== + + `(require 'html-form)' + + - Variable: *html:output-port* + Procedure names starting with `html:' send their output to the + port *HTML:OUTPUT-PORT*. *HTML:OUTPUT-PORT* is initially the + current output port. + + - Function: make-atval TXT + Returns a string with character substitutions appropriate to send + TXT as an "attribute-value". + + - Function: make-plain TXT + Returns a string with character substitutions appropriate to send + TXT as an "plain-text". + + - Function: html:start-page TITLE BACKLINK TAGS ... + - Function: html:start-page TITLE BACKLINK + - Function: html:start-page TITLE + Outputs headers for an HTML page named TITLE. If string arguments + BACKLINK ... are supplied they are printed verbatim within the + <HEAD> section. + + - Function: html:end-page + Outputs HTML codes to end a page. + + - Function: html:pre LINE1 LINE ... + Writes (using `html:printf') the strings LINE1, LINES as + "PRE"formmated plain text (rendered in fixed-width font). + Newlines are inserted between LINE1, LINES. HTML tags (`<tag>') + within LINES will be visible verbatim. + + - Function: html:comment LINE1 LINE ... + Writes (using `html:printf') the strings LINE1 as HTML comments. + +HTML Tables +=========== + + - Function: html:start-table CAPTION + + - Function: html:end-table + + - Function: html:heading COLUMNS + Outputs a heading row for the currently-started table. + + - Function: html:href-heading COLUMNS URLS + Outputs a heading row with column-names COLUMNS linked to URLs + URLS. + + - Function: make-row-converter K FOREIGNS + The positive integer K is the primary-key-limit (number of + primary-keys) of the table. FOREIGNS is a list of the filenames of + foreign-key field pages and #f for non foreign-key fields. + + `make-row-converter' returns a procedure taking a row for its + single argument. This returned procedure prints the table row to + *HTML:OUTPUT-PORT*. + + - Function: table-name->filename TABLE-NAME + Returns the symbol TABLE-NAME converted to a filename. + + - Function: table->html CAPTION DB TABLE-NAME MATCH-KEY1 ... + Writes HTML for DB table TABLE-NAME to *HTML:OUTPUT-PORT*. + + The optional MATCH-KEY1 ... arguments restrict actions to a subset + of the table. *Note match-key: Table Operations. + + - Function: table->page DB TABLE-NAME INDEX-FILENAME + Writes a complete HTML page to *HTML:OUTPUT-PORT*. The string + INDEX-FILENAME names the page which refers to this one. + + - Function: catalog->html DB CAPTION + Writes HTML for the catalog table of DB to *HTML:OUTPUT-PORT*. + + - Function: catalog->page DB CAPTION + Writes a complete HTML page for the catalog of DB to + *HTML:OUTPUT-PORT*. + +HTML Forms +========== + + - Function: html:start-form METHOD ACTION + The symbol METHOD is either `get', `head', `post', `put', or + `delete'. `html:start-form' prints the header for an HTML "form". + + - Function: html:end-form PNAME SUBMIT-LABEL + `html:end-form' prints the footer for an HTML "form". The string + SUBMIT-LABEL appears on the button which submits the form. + + - Function: command->html RDB COMMAND-TABLE COMMAND METHOD ACTION + The symbol COMMAND-TABLE names a command table in the RDB + relational database. + + `command->html' writes an HTML-2.0 "form" for command COMMAND to + the current-output-port. The `SUBMIT' button, which is labeled + COMMAND, invokes the URI ACTION with method METHOD with a hidden + attribute `*command*' bound to the command symbol submitted. + + An action may invoke a CGI script + (`http://www.my-site.edu/cgi-bin/search.cgi') or HTTP daemon + (`http://www.my-site.edu:8001'). + + This example demonstrates how to create a HTML-form for the `build' + command. + + (require (in-vicinity (implementation-vicinity) "build.scm")) + (call-with-output-file "buildscm.html" + (lambda (port) + (fluid-let ((*html:output-port* port)) + (html:start-page 'commands) + (command->html + build '*commands* 'build 'post + (or "/cgi-bin/build.cgi" + "http://localhost:8081/buildscm")) + html:end-page))) + +HTTP and CGI service +==================== + + `(require 'html-form)' + + - Function: cgi:serve-command RDB COMMAND-TABLE + Reads a `"POST"' or `"GET"' query from `(current-input-port)' and + executes the encoded command from COMMAND-TABLE in + relational-database RDB. + + This example puts up a plain-text page in response to a CGI query. + + (display "Content-Type: text/plain") (newline) (newline) + (require 'html-form) + (load (in-vicinity (implementation-vicinity) "build.scm")) + (cgi:serve-command build '*commands*) + + - Function: serve-urlencoded-command RDB COMMAND-TABLE URLENCODED + Reads attribute-value pairs from URLENCODED, converts them to + parameters and invokes the RDB command named by the parameter + `*command*'. + + - Function: http:serve-query INPUT-PORT OUTPUT-PORT SERVE-PROC + reads the "query-string" from INPUT-PORT. If this is a valid + `"POST"' or `"GET"' query, then `http:serve-query' calls + SERVE-PROC with two arguments, the query-string and the + header-alist. + + Otherwise, `http:serve-query' replies (to OUTPUT-PORT) with + appropriate HTML describing the problem. + + This example services HTTP queries from port 8081: + + (define socket (make-stream-socket AF_INET 0)) + (socket:bind socket 8081) + (socket:listen socket 10) + (dynamic-wind + (lambda () #f) + (lambda () + (do ((port (socket:accept socket) + (socket:accept socket))) + (#f) + (dynamic-wind + (lambda () #f) + (lambda () + (fluid-let ((*html:output-port* port)) + (http:serve-query + port port + (lambda (query-string header) + (http:send-header + '(("Content-Type" . "text/plain"))) + (with-output-to-port port + (lambda () + (serve-urlencoded-command + build '*commands* query-string))))))) + (lambda () (close-port port))))) + (lambda () (close-port socket))) + + - Function: http:read-request-line PORT + Reads the first non-blank line from PORT and, if successful, + returns a list of three itmes from the request-line: + + 0. Method + + Either one of the symbols `options', `get', `head', `post', + `put', `delete', or `trace'; Or a string. + + 1. Request-URI + + A string. At the minimum, it will be the string `"/"'. + + 2. HTTP-Version + + A string. For example, `HTTP/1.0'. + + - Function: cgi:read-query-string + Reads the "query-string" from `(current-input-port)'. + `cgi:read-query-string' reads a `"POST"' or `"GET"' queries, + depending on the value of `(getenv "REQUEST_METHOD")'. + + +File: slib.info, Node: Printing Scheme, Next: Time and Date, Prev: HTML HTTP and CGI, Up: Textual Conversion Packages + +Printing Scheme +=============== + +* Menu: + +* Generic-Write:: 'generic-write +* Object-To-String:: 'object->string +* Pretty-Print:: 'pretty-print, 'pprint-file + + +File: slib.info, Node: Generic-Write, Next: Object-To-String, Prev: Printing Scheme, Up: Printing Scheme + +Generic-Write +------------- + + `(require 'generic-write)' + + `generic-write' is a procedure that transforms a Scheme data value +(or Scheme program expression) into its textual representation and +prints it. The interface to the procedure is sufficiently general to +easily implement other useful formatting procedures such as pretty +printing, output to a string and truncated output. + + - Procedure: generic-write OBJ DISPLAY? WIDTH OUTPUT + OBJ + Scheme data value to transform. + + DISPLAY? + Boolean, controls whether characters and strings are quoted. + + WIDTH + Extended boolean, selects format: + #f + single line format + + integer > 0 + pretty-print (value = max nb of chars per line) + + OUTPUT + Procedure of 1 argument of string type, called repeatedly with + successive substrings of the textual representation. This + procedure can return `#f' to stop the transformation. + + The value returned by `generic-write' is undefined. + + Examples: + (write obj) == (generic-write obj #f #f DISPLAY-STRING) + (display obj) == (generic-write obj #t #f DISPLAY-STRING) + + where + DISPLAY-STRING == + (lambda (s) (for-each write-char (string->list s)) #t) + + +File: slib.info, Node: Object-To-String, Next: Pretty-Print, Prev: Generic-Write, Up: Printing Scheme + +Object-To-String +---------------- + + `(require 'object->string)' + + - Function: object->string OBJ + Returns the textual representation of OBJ as a string. + + - Function: object->limited-string OBJ LIMIT + Returns the textual representation of OBJ as a string of length at + most LIMIT. + + +File: slib.info, Node: Pretty-Print, Prev: Object-To-String, Up: Printing Scheme + +Pretty-Print +------------ + + `(require 'pretty-print)' + + - Procedure: pretty-print OBJ + - Procedure: pretty-print OBJ PORT + `pretty-print's OBJ on PORT. If PORT is not specified, + `current-output-port' is used. + + Example: + (pretty-print '((1 2 3 4 5) (6 7 8 9 10) (11 12 13 14 15) + (16 17 18 19 20) (21 22 23 24 25))) + -| ((1 2 3 4 5) + -| (6 7 8 9 10) + -| (11 12 13 14 15) + -| (16 17 18 19 20) + -| (21 22 23 24 25)) + + `(require 'pprint-file)' + + - Procedure: pprint-file INFILE + - Procedure: pprint-file INFILE OUTFILE + Pretty-prints all the code in INFILE. If OUTFILE is specified, + the output goes to OUTFILE, otherwise it goes to + `(current-output-port)'. + + - Function: pprint-filter-file INFILE PROC OUTFILE + - Function: pprint-filter-file INFILE PROC + INFILE is a port or a string naming an existing file. Scheme + source code expressions and definitions are read from the port (or + file) and PROC is applied to them sequentially. + + OUTFILE is a port or a string. If no OUTFILE is specified then + `current-output-port' is assumed. These expanded expressions are + then `pretty-print'ed to this port. + + Whitepsace and comments (introduced by `;') which are not part of + scheme expressions are reproduced in the output. This procedure + does not affect the values returned by `current-input-port' and + `current-output-port'. + + `pprint-filter-file' can be used to pre-compile macro-expansion and +thus can reduce loading time. The following will write into +`exp-code.scm' the result of expanding all defmacros in `code.scm'. + (require 'pprint-file) + (require 'defmacroexpand) + (defmacro:load "my-macros.scm") + (pprint-filter-file "code.scm" defmacro:expand* "exp-code.scm") + + +File: slib.info, Node: Time and Date, Next: Vector Graphics, Prev: Printing Scheme, Up: Textual Conversion Packages + +Time and Date +============= + +* Menu: + +* Time Zone:: +* Posix Time:: 'posix-time +* Common-Lisp Time:: 'common-lisp-time + +If `(provided? 'current-time)': + +The procedures `current-time', `difftime', and `offset-time' deal with +a "calendar time" datatype which may or may not be disjoint from other +Scheme datatypes. + + - Function: current-time + Returns the time since 00:00:00 GMT, January 1, 1970, measured in + seconds. Note that the reference time is different from the + reference time for `get-universal-time' in *Note Common-Lisp + Time::. + + - Function: difftime CALTIME1 CALTIME0 + Returns the difference (number of seconds) between twe calendar + times: CALTIME1 - CALTIME0. CALTIME0 may also be a number. + + - Function: offset-time CALTIME OFFSET + Returns the calendar time of CALTIME offset by OFFSET number of + seconds `(+ caltime offset)'. + + +File: slib.info, Node: Time Zone, Next: Posix Time, Prev: Time and Date, Up: Time and Date + +Time Zone +--------- + + (require 'time-zone) + + - Data Format: TZ-string + POSIX standards specify several formats for encoding time-zone + rules. + + :<pathname> + If the first character of <pathname> is `/', then <pathname> + specifies the absolute pathname of a tzfile(5) format + time-zone file. Otherwise, <pathname> is interpreted as a + pathname within TZFILE:VICINITY (/usr/lib/zoneinfo/) naming a + tzfile(5) format time-zone file. + + <std><offset> + The string <std> consists of 3 or more alphabetic characters. + <offset> specifies the time difference from GMT. The <offset> + is positive if the local time zone is west of the Prime + Meridian and negative if it is east. <offset> can be the + number of hours or hours and minutes (and optionally seconds) + separated by `:'. For example, `-4:30'. + + <std><offset><dst> + <dst> is the at least 3 alphabetic characters naming the local + daylight-savings-time. + + <std><offset><dst><doffset> + <doffset> specifies the offset from the Prime Meridian when + daylight-savings-time is in effect. + + The non-tzfile formats can optionally be followed by transition + times specifying the day and time when a zone changes from + standard to daylight-savings and back again. + + ,<date>/<time>,<date>/<time> + The <time>s are specified like the <offset>s above, except + that leading `+' and `-' are not allowed. + + Each <date> has one of the formats: + + J<day> + specifies the Julian day with <day> between 1 and 365. + February 29 is never counted and cannot be referenced. + + <day> + This specifies the Julian day with n between 0 and 365. + February 29 is counted in leap years and can be + specified. + + M<month>.<week>.<day> + This specifies day <day> (0 <= <day> <= 6) of week + <week> (1 <= <week> <= 5) of month <month> (1 <= <month> + <= 12). Week 1 is the first week in which day d occurs + and week 5 is the last week in which day <day> occurs. + Day 0 is a Sunday. + + + - Data Type: time-zone + is a datatype encoding how many hours from Greenwich Mean Time the + local time is, and the "Daylight Savings Time" rules for changing + it. + + - Function: time-zone TZ-STRING + Creates and returns a time-zone object specified by the string + TZ-STRING. If `time-zone' cannot interpret TZ-STRING, `#f' is + returned. + + - Function: tz:params CALTIME TZ + TZ is a time-zone object. `tz:params' returns a list of three + items: + 0. An integer. 0 if standard time is in effect for timezone TZ + at CALTIME; 1 if daylight savings time is in effect for + timezone TZ at CALTIME. + + 1. The number of seconds west of the Prime Meridian timezone TZ + is at CALTIME. + + 2. The name for timezone TZ at CALTIME. + + `tz:params' is unaffected by the default timezone; inquiries can be + made of any timezone at any calendar time. + + +The rest of these procedures and variables are provided for POSIX +compatability. Because of shared state they are not thread-safe. + + - Function: tzset + Returns the default time-zone. + + - Function: tzset TZ + Sets (and returns) the default time-zone to TZ. + + - Function: tzset TZ-STRING + Sets (and returns) the default time-zone to that specified by + TZ-STRING. + + `tzset' also sets the variables *TIMEZONE*, DAYLIGHT?, and TZNAME. + This function is automatically called by the time conversion + procedures which depend on the time zone (*note Time and Date::.). + + - Variable: *timezone* + Contains the difference, in seconds, between Greenwich Mean Time + and local standard time (for example, in the U.S. Eastern time + zone (EST), timezone is 5*60*60). `*timezone*' is initialized by + `tzset'. + + - Variable: daylight? + is `#t' if the default timezone has rules for "Daylight Savings + Time". *Note:* DAYLIGHT? does not tell you when Daylight Savings + Time is in effect, just that the default zone sometimes has + Daylight Savings Time. + + - Variable: tzname + is a vector of strings. Index 0 has the abbreviation for the + standard timezone; If DAYLIGHT?, then index 1 has the abbreviation + for the Daylight Savings timezone. + + +File: slib.info, Node: Posix Time, Next: Common-Lisp Time, Prev: Time Zone, Up: Time and Date + +Posix Time +---------- + + (require 'posix-time) + + - Data Type: Calendar-Time + is a datatype encapsulating time. + + - Data Type: Coordinated Universal Time + (abbreviated "UTC") is a vector of integers representing time: + + 0. seconds (0 - 61) + + 1. minutes (0 - 59) + + 2. hours since midnight (0 - 23) + + 3. day of month (1 - 31) + + 4. month (0 - 11). Note difference from + `decode-universal-time'. + + 5. the number of years since 1900. Note difference from + `decode-universal-time'. + + 6. day of week (0 - 6) + + 7. day of year (0 - 365) + + 8. 1 for daylight savings, 0 for regular time + + - Function: gmtime CALTIME + Converts the calendar time CALTIME to UTC and returns it. + + - Function: localtime CALTIME TZ + Returns CALTIME converted to UTC relative to timezone TZ. + + - Function: localtime CALTIME + converts the calendar time CALTIME to a vector of integers + expressed relative to the user's time zone. `localtime' sets the + variable *TIMEZONE* with the difference between Coordinated + Universal Time (UTC) and local standard time in seconds (*note + tzset: Time Zone.). + + + - Function: gmktime UNIVTIME + Converts a vector of integers in GMT Coordinated Universal Time + (UTC) format to a calendar time. + + - Function: mktime UNIVTIME + Converts a vector of integers in local Coordinated Universal Time + (UTC) format to a calendar time. + + - Function: mktime UNIVTIME TZ + Converts a vector of integers in Coordinated Universal Time (UTC) + format (relative to time-zone TZ) to calendar time. + + - Function: asctime UNIVTIME + Converts the vector of integers CALTIME in Coordinated Universal + Time (UTC) format into a string of the form `"Wed Jun 30 21:49:08 + 1993"'. + + - Function: gtime CALTIME + - Function: ctime CALTIME + - Function: ctime CALTIME TZ + Equivalent to `(asctime (gmtime CALTIME))', `(asctime (localtime + CALTIME))', and `(asctime (localtime CALTIME TZ))', respectively. + + +File: slib.info, Node: Common-Lisp Time, Prev: Posix Time, Up: Time and Date + +Common-Lisp Time +---------------- + + - Function: get-decoded-time + Equivalent to `(decode-universal-time (get-universal-time))'. + + - Function: get-universal-time + Returns the current time as "Universal Time", number of seconds + since 00:00:00 Jan 1, 1900 GMT. Note that the reference time is + different from `current-time'. + + - Function: decode-universal-time UNIVTIME + Converts UNIVTIME to "Decoded Time" format. Nine values are + returned: + 0. seconds (0 - 61) + + 1. minutes (0 - 59) + + 2. hours since midnight + + 3. day of month + + 4. month (1 - 12). Note difference from `gmtime' and + `localtime'. + + 5. year (A.D.). Note difference from `gmtime' and `localtime'. + + 6. day of week (0 - 6) + + 7. #t for daylight savings, #f otherwise + + 8. hours west of GMT (-24 - +24) + + Notice that the values returned by `decode-universal-time' do not + match the arguments to `encode-universal-time'. + + - Function: encode-universal-time SECOND MINUTE HOUR DATE MONTH YEAR + - Function: encode-universal-time SECOND MINUTE HOUR DATE MONTH YEAR + TIME-ZONE + Converts the arguments in Decoded Time format to Universal Time + format. If TIME-ZONE is not specified, the returned time is + adjusted for daylight saving time. Otherwise, no adjustment is + performed. + + Notice that the values returned by `decode-universal-time' do not + match the arguments to `encode-universal-time'. + + +File: slib.info, Node: Vector Graphics, Next: Schmooz, Prev: Time and Date, Up: Textual Conversion Packages + +Vector Graphics +=============== + +* Menu: + +* Tektronix Graphics Support:: + + +File: slib.info, Node: Tektronix Graphics Support, Prev: Vector Graphics, Up: Vector Graphics + +Tektronix Graphics Support +-------------------------- + + *Note:* The Tektronix graphics support files need more work, and are +not complete. + +Tektronix 4000 Series Graphics +.............................. + + The Tektronix 4000 series graphics protocol gives the user a 1024 by +1024 square drawing area. The origin is in the lower left corner of the +screen. Increasing y is up and increasing x is to the right. + + The graphics control codes are sent over the current-output-port and +can be mixed with regular text and ANSI or other terminal control +sequences. + + - Procedure: tek40:init + + - Procedure: tek40:graphics + + - Procedure: tek40:text + + - Procedure: tek40:linetype LINETYPE + + - Procedure: tek40:move X Y + + - Procedure: tek40:draw X Y + + - Procedure: tek40:put-text X Y STR + + - Procedure: tek40:reset + +Tektronix 4100 Series Graphics +.............................. + + The graphics control codes are sent over the current-output-port and +can be mixed with regular text and ANSI or other terminal control +sequences. + + - Procedure: tek41:init + + - Procedure: tek41:reset + + - Procedure: tek41:graphics + + - Procedure: tek41:move X Y + + - Procedure: tek41:draw X Y + + - Procedure: tek41:point X Y NUMBER + + - Procedure: tek41:encode-x-y X Y + + - Procedure: tek41:encode-int NUMBER + + +File: slib.info, Node: Schmooz, Prev: Vector Graphics, Up: Textual Conversion Packages + +Schmooz +======= + + "Schmooz" is a simple, lightweight markup language for interspersing +Texinfo documentation with Scheme source code. Schmooz does not create +the top level Texinfo file; it creates `txi' files which can be +imported into the documentation using the Texinfo command `@include'. + + `(require 'schmooz)' defines the function `schmooz', which is used to +process files. Files containing schmooz documentation should not +contain `(require 'schmooz)'. + + - Procedure: schmooz FILENAMEscm ... + FILENAMEscm should be a string ending with `scm' naming an + existing file containing Scheme source code. `schmooz' extracts + top-level comments containing schmooz commands from FILENAMEscm + and writes the converted Texinfo source to a file named + FILENAMEtxi. + + - Procedure: schmooz FILENAMEtexi ... + - Procedure: schmooz FILENAMEtex ... + - Procedure: schmooz FILENAMEtxi ... + FILENAME should be a string naming an existing file containing + Texinfo source code. For every occurrence of the string `@include + FILENAMEtxi' within that file, `schmooz' calls itself with the + argument `FILENAMEscm'. + + Schmooz comments are distinguished (from non-schmooz comments) by +their first line, which must start with an at-sign (@) preceded by one +or more semicolons (;). A schmooz comment ends at the first subsequent +line which does *not* start with a semicolon. Currently schmooz +comments are recognized only at top level. + + Schmooz comments are copied to the Texinfo output file with the +leading contiguous semicolons removed. Certain character sequences +starting with at-sign are treated specially. Others are copied +unchanged. + + A schmooz comment starting with `@body' must be followed by a Scheme +definition. All comments between the `@body' line and the definition +will be included in a Texinfo definition, either a `@defun' or a +`@defvar', depending on whether a procedure or a variable is being +defined. + + Within the text of that schmooz comment, at-sign followed by `0' will +be replaced by `@code{procedure-name}' if the following definition is +of a procedure; or `@var{variable}' if defining a variable. + + An at-sign followed by a non-zero digit will expand to the variable +citation of that numbered argument: `@var{argument-name}'. + + If more than one definition follows a `@body' comment line without an +intervening blank or comment line, then those definitions will be +included in the same Texinfo definition using `@defvarx' or `@defunx', +depending on whether the first definition is of a variable or of a +procedure. + + Schmooz can figure out whether a definition is of a procedure if it +is of the form: + + `(define (<identifier> <arg> ...) <expression>)' + +or if the left hand side of the definition is some form ending in a +lambda expression. Obviously, it can be fooled. In order to force +recognition of a procedure definition, start the documentation with +`@args' instead of `@body'. `@args' should be followed by the argument +list of the function being defined, which may be enclosed in +parentheses and delimited by whitespace, (as in Scheme), enclosed in +braces and separated by commas, (as in Texinfo), or consist of the +remainder of the line, separated by whitespace. + + For example: + + ;;@args arg1 args ... + ;;@0 takes argument @1 and any number of @2 + (define myfun (some-function-returning-magic)) + + Will result in: + + @defun myfun arg1 args @dots{} + + @code{myfun} takes argument @var{arg1} and any number of @var{args} + @end defun + + `@args' may also be useful for indicating optional arguments by name. +If `@args' occurs inside a schmooz comment section, rather than at the +beginning, then it will generate a `@defunx' line with the arguments +supplied. + + If the first at-sign in a schmooz comment is immediately followed by +whitespace, then the comment will be expanded to whatever follows that +whitespace. If the at-sign is followed by a non-whitespace character +then the at-sign will be included as the first character of the +expansion. This feature is intended to make it easy to include Texinfo +directives in schmooz comments. + + +File: slib.info, Node: Mathematical Packages, Next: Database Packages, Prev: Textual Conversion Packages, Up: Top + +Mathematical Packages +********************* + +* Menu: + +* Bit-Twiddling:: 'logical +* Modular Arithmetic:: 'modular +* Prime Numbers:: 'factor +* Random Numbers:: 'random +* Fast Fourier Transform:: 'fft +* Cyclic Checksum:: 'make-crc +* Plotting:: 'charplot +* Root Finding:: 'root +* Commutative Rings:: 'commutative-ring +* Determinant:: 'determinant + + +File: slib.info, Node: Bit-Twiddling, Next: Modular Arithmetic, Prev: Mathematical Packages, Up: Mathematical Packages + +Bit-Twiddling +============= + + `(require 'logical)' + + The bit-twiddling functions are made available through the use of the +`logical' package. `logical' is loaded by inserting `(require +'logical)' before the code that uses these functions. These functions +behave as though operating on integers in two's-complement +representation. + +Bitwise Operations +------------------ + + - Function: logand N1 N1 + Returns the integer which is the bit-wise AND of the two integer + arguments. + + Example: + (number->string (logand #b1100 #b1010) 2) + => "1000" + + - Function: logior N1 N2 + Returns the integer which is the bit-wise OR of the two integer + arguments. + + Example: + (number->string (logior #b1100 #b1010) 2) + => "1110" + + - Function: logxor N1 N2 + Returns the integer which is the bit-wise XOR of the two integer + arguments. + + Example: + (number->string (logxor #b1100 #b1010) 2) + => "110" + + - Function: lognot N + Returns the integer which is the 2s-complement of the integer + argument. + + Example: + (number->string (lognot #b10000000) 2) + => "-10000001" + (number->string (lognot #b0) 2) + => "-1" + + - Function: bitwise-if MASK N0 N1 + Returns an integer composed of some bits from integer N0 and some + from integer N1. A bit of the result is taken from N0 if the + corresponding bit of integer MASK is 1 and from N1 if that bit of + MASK is 0. + + - Function: logtest J K + (logtest j k) == (not (zero? (logand j k))) + + (logtest #b0100 #b1011) => #f + (logtest #b0100 #b0111) => #t + + - Function: logcount N + Returns the number of bits in integer N. If integer is positive, + the 1-bits in its binary representation are counted. If negative, + the 0-bits in its two's-complement binary representation are + counted. If 0, 0 is returned. + + Example: + (logcount #b10101010) + => 4 + (logcount 0) + => 0 + (logcount -2) + => 1 + +Bit Within Word +--------------- + + - Function: logbit? INDEX J + (logbit? index j) == (logtest (integer-expt 2 index) j) + + (logbit? 0 #b1101) => #t + (logbit? 1 #b1101) => #f + (logbit? 2 #b1101) => #t + (logbit? 3 #b1101) => #t + (logbit? 4 #b1101) => #f + + - Function: copy-bit INDEX FROM BIT + Returns an integer the same as FROM except in the INDEXth bit, + which is 1 if BIT is `#t' and 0 if BIT is `#f'. + + Example: + (number->string (copy-bit 0 0 #t) 2) => "1" + (number->string (copy-bit 2 0 #t) 2) => "100" + (number->string (copy-bit 2 #b1111 #f) 2) => "1011" + +Fields of Bits +-------------- + + - Function: bit-field N START END + Returns the integer composed of the START (inclusive) through END + (exclusive) bits of N. The STARTth bit becomes the 0-th bit in + the result. + + This function was called `bit-extract' in previous versions of + SLIB. + + Example: + (number->string (bit-field #b1101101010 0 4) 2) + => "1010" + (number->string (bit-field #b1101101010 4 9) 2) + => "10110" + + - Function: copy-bit-field TO START END FROM + Returns an integer the same as TO except possibly in the START + (inclusive) through END (exclusive) bits, which are the same as + those of FROM. The 0-th bit of FROM becomes the STARTth bit of + the result. + + Example: + (number->string (copy-bit-field #b1101101010 0 4 0) 2) + => "1101100000" + (number->string (copy-bit-field #b1101101010 0 4 -1) 2) + => "1101101111" + + - Function: ash INT COUNT + Returns an integer equivalent to `(inexact->exact (floor (* INT + (expt 2 COUNT))))'. + + Example: + (number->string (ash #b1 3) 2) + => "1000" + (number->string (ash #b1010 -1) 2) + => "101" + + - Function: integer-length N + Returns the number of bits neccessary to represent N. + + Example: + (integer-length #b10101010) + => 8 + (integer-length 0) + => 0 + (integer-length #b1111) + => 4 + + - Function: integer-expt N K + Returns N raised to the non-negative integer exponent K. + + Example: + (integer-expt 2 5) + => 32 + (integer-expt -3 3) + => -27 + + +File: slib.info, Node: Modular Arithmetic, Next: Prime Numbers, Prev: Bit-Twiddling, Up: Mathematical Packages + +Modular Arithmetic +================== + + `(require 'modular)' + + - Function: extended-euclid N1 N2 + Returns a list of 3 integers `(d x y)' such that d = gcd(N1, N2) = + N1 * x + N2 * y. + + - Function: symmetric:modulus N + Returns `(quotient (+ -1 n) -2)' for positive odd integer N. + + - Function: modulus->integer MODULUS + Returns the non-negative integer characteristic of the ring formed + when MODULUS is used with `modular:' procedures. + + - Function: modular:normalize MODULUS N + Returns the integer `(modulo N (modulus->integer MODULUS))' in the + representation specified by MODULUS. + +The rest of these functions assume normalized arguments; That is, the +arguments are constrained by the following table: + +For all of these functions, if the first argument (MODULUS) is: +`positive?' + Work as before. The result is between 0 and MODULUS. + +`zero?' + The arguments are treated as integers. An integer is returned. + +`negative?' + The arguments and result are treated as members of the integers + modulo `(+ 1 (* -2 MODULUS))', but with "symmetric" + representation; i.e. `(<= (- MODULUS) N MODULUS)'. + +If all the arguments are fixnums the computation will use only fixnums. + + - Function: modular:invertable? MODULUS K + Returns `#t' if there exists an integer n such that K * n == 1 mod + MODULUS, and `#f' otherwise. + + - Function: modular:invert MODULUS K2 + Returns an integer n such that 1 = (n * K2) mod MODULUS. If K2 + has no inverse mod MODULUS an error is signaled. + + - Function: modular:negate MODULUS K2 + Returns (-K2) mod MODULUS. + + - Function: modular:+ MODULUS K2 K3 + Returns (K2 + K3) mod MODULUS. + + - Function: modular:- MODULUS K2 K3 + Returns (K2 - K3) mod MODULUS. + + - Function: modular:* MODULUS K2 K3 + Returns (K2 * K3) mod MODULUS. + + The Scheme code for `modular:*' with negative MODULUS is not + completed for fixnum-only implementations. + + - Function: modular:expt MODULUS K2 K3 + Returns (K2 ^ K3) mod MODULUS. + + +File: slib.info, Node: Prime Numbers, Next: Random Numbers, Prev: Modular Arithmetic, Up: Mathematical Packages + +Prime Numbers +============= + + `(require 'factor)' + + - Variable: prime:prngs + PRIME:PRNGS is the random-state (*note Random Numbers::.) used by + these procedures. If you call these procedures from more than one | + thread (or from interrupt), `random' may complain about reentrant | + calls. | + | + *Note:* The prime test and generation procedures implement (or use) | +the Solovay-Strassen primality test. See | + | + * Robert Solovay and Volker Strassen, `A Fast Monte-Carlo Test for | + Primality', SIAM Journal on Computing, 1977, pp 84-85. | + + - Function: jacobi-symbol P Q + Returns the value (+1, -1, or 0) of the Jacobi-Symbol of exact + non-negative integer P and exact positive odd integer Q. + + - Variable: prime:trials + PRIME:TRIALS the maxinum number of iterations of Solovay-Strassen + that will be done to test a number for primality. + + - Function: prime? N + Returns `#f' if N is composite; `#t' if N is prime. There is a + slight chance `(expt 2 (- prime:trials))' that a composite will + return `#t'. + + - Function: primes< START COUNT + Returns a list of the first COUNT prime numbers less than START. + If there are fewer than COUNT prime numbers less than START, then + the returned list will have fewer than START elements. + + - Function: primes> START COUNT + Returns a list of the first COUNT prime numbers greater than START. + + - Function: factor K + Returns a list of the prime factors of K. The order of the + factors is unspecified. In order to obtain a sorted list do + `(sort! (factor K) <)'. + + +File: slib.info, Node: Random Numbers, Next: Fast Fourier Transform, Prev: Prime Numbers, Up: Mathematical Packages + +Random Numbers +============== + + `(require 'random)' + + A pseudo-random number generator is only as good as the tests it +passes. George Marsaglia of Florida State University developed a +battery of tests named "DIEHARD" +(`http://stat.fsu.edu/~geo/diehard.html'). `diehard.c' has a bug which +the patch | +`http://swissnet.ai.mit.edu/ftpdir/users/jaffer/diehard.c.pat' corrects. | + + SLIB's new PRNG generates 8 bits at a time. With the degenerate seed +`0', the numbers generated pass DIEHARD; but when bits are combined +from sequential bytes, tests fail. With the seed +`http://swissnet.ai.mit.edu/~jaffer/SLIB.html', all of those tests pass. + + - Function: random N + - Function: random N STATE + Accepts a positive integer or real N and returns a number of the + same type between zero (inclusive) and N (exclusive). The values + returned by `random' are uniformly distributed from 0 to N. + + The optional argument STATE must be of the type returned by + `(seed->random-state)' or `(make-random-state)'. It defaults to + the value of the variable `*random-state*'. This object is used + to maintain the state of the pseudo-random-number generator and is + altered as a side effect of calls to `random'. + + - Variable: *random-state* + Holds a data structure that encodes the internal state of the + random-number generator that `random' uses by default. The nature + of this data structure is implementation-dependent. It may be + printed out and successfully read back in, but may or may not + function correctly as a random-number state object in another + implementation. + + - Function: copy-random-state STATE + Returns a new copy of argument STATE. + + - Function: copy-random-state + Returns a new copy of `*random-state*'. + + - Function: seed->random-state SEED + Returns a new object of type suitable for use as the value of the + variable `*random-state*' or as a second argument to `random'. + The number or string SEED is used to initialize the state. If + `seed->random-state' is called twice with arguments which are + `equal?', then the returned data structures will be `equal?'. + Calling `seed->random-state' with unequal arguments will nearly + always return unequal states. + + - Function: make-random-state + - Function: make-random-state OBJ + Returns a new object of type suitable for use as the value of the + variable `*random-state*' or as a second argument to `random'. If + the optional argument OBJ is given, it should be a printable + Scheme object; the first 50 characters of its printed + representation will be used as the seed. Otherwise the value of + `*random-state*' is used as the seed. + + If inexact numbers are supported by the Scheme implementation, +`randinex.scm' will be loaded as well. `randinex.scm' contains +procedures for generating inexact distributions. + + - Function: random:uniform + - Function: random:uniform STATE + Returns an uniformly distributed inexact real random number in the + range between 0 and 1. + + - Function: random:exp + - Function: random:exp STATE + Returns an inexact real in an exponential distribution with mean + 1. For an exponential distribution with mean U use + `(* U (random:exp))'. + + - Function: random:normal + - Function: random:normal STATE + Returns an inexact real in a normal distribution with mean 0 and + standard deviation 1. For a normal distribution with mean M and + standard deviation D use `(+ M (* D (random:normal)))'. + + - Function: random:normal-vector! VECT + - Function: random:normal-vector! VECT STATE + Fills VECT with inexact real random numbers which are independent + and standard normally distributed (i.e., with mean 0 and variance + 1). + + - Function: random:hollow-sphere! VECT + - Function: random:hollow-sphere! VECT STATE + Fills VECT with inexact real random numbers the sum of whose + squares is less than 1.0. Thinking of VECT as coordinates in + space of dimension N = `(vector-length VECT)', the coordinates are + uniformly distributed within the unit N-shere. The sum of the + squares of the numbers is returned. + + - Function: random:solid-sphere! VECT + - Function: random:solid-sphere! VECT STATE + Fills VECT with inexact real random numbers the sum of whose + squares is equal to 1.0. Thinking of VECT as coordinates in space + of dimension n = `(vector-length VECT)', the coordinates are + uniformly distributed over the surface of the unit n-shere. + + +File: slib.info, Node: Fast Fourier Transform, Next: Cyclic Checksum, Prev: Random Numbers, Up: Mathematical Packages + +Fast Fourier Transform +====================== + + `(require 'fft)' + + - Function: fft ARRAY + ARRAY is an array of `(expt 2 n)' numbers. `fft' returns an array + of complex numbers comprising the "Discrete Fourier Transform" of + ARRAY. + + - Function: fft-1 ARRAY + `fft-1' returns an array of complex numbers comprising the inverse + Discrete Fourier Transform of ARRAY. + + `(fft-1 (fft ARRAY))' will return an array of values close to ARRAY. + + (fft '#(1 0+i -1 0-i 1 0+i -1 0-i)) => + + #(0.0 0.0 0.0+628.0783185208527e-18i 0.0 + 0.0 0.0 8.0-628.0783185208527e-18i 0.0) + + (fft-1 '#(0 0 0 0 0 0 8 0)) => + + #(1.0 -61.23031769111886e-18+1.0i -1.0 61.23031769111886e-18-1.0i + 1.0 -61.23031769111886e-18+1.0i -1.0 61.23031769111886e-18-1.0i) + + +File: slib.info, Node: Cyclic Checksum, Next: Plotting, Prev: Fast Fourier Transform, Up: Mathematical Packages + +Cyclic Checksum +=============== + + `(require 'make-crc)' + + - Function: make-port-crc + - Function: make-port-crc DEGREE + - Function: make-port-crc DEGREE GENERATOR + Returns an expression for a procedure of one argument, a port. + This procedure reads characters from the port until the end of + file and returns the integer checksum of the bytes read. + + The integer DEGREE, if given, specifies the degree of the + polynomial being computed - which is also the number of bits + computed in the checksums. The default value is 32. + + The integer GENERATOR specifies the polynomial being computed. + The power of 2 generating each 1 bit is the exponent of a term of + the polynomial. The bit at position DEGREE is implicit and should + not be part of GENERATOR. This allows systems with numbers + limited to 32 bits to calculate 32 bit checksums. The default + value of GENERATOR when DEGREE is 32 (its default) is: + + (make-port-crc 32 #b00000100110000010001110110110111) + + Creates a procedure to calculate the P1003.2/D11.2 (POSIX.2) 32-bit + checksum from the polynomial: + + 32 26 23 22 16 12 11 + ( x + x + x + x + x + x + x + + + 10 8 7 5 4 2 1 + x + x + x + x + x + x + x + 1 ) mod 2 + + (require 'make-crc) + (define crc32 (slib:eval (make-port-crc))) + (define (file-check-sum file) (call-with-input-file file crc32)) + (file-check-sum (in-vicinity (library-vicinity) "ratize.scm")) + + => 3553047446 + + +File: slib.info, Node: Plotting, Next: Root Finding, Prev: Cyclic Checksum, Up: Mathematical Packages + +Plotting on Character Devices +============================= + + `(require 'charplot)' + + The plotting procedure is made available through the use of the +`charplot' package. `charplot' is loaded by inserting `(require +'charplot)' before the code that uses this procedure. + + - Variable: charplot:height + The number of rows to make the plot vertically. + + - Variable: charplot:width + The number of columns to make the plot horizontally. + + - Procedure: plot! COORDS X-LABEL Y-LABEL + COORDS is a list of pairs of x and y coordinates. X-LABEL and + Y-LABEL are strings with which to label the x and y axes. + + Example: + (require 'charplot) + (set! charplot:height 19) + (set! charplot:width 45) + + (define (make-points n) + (if (zero? n) + '() + (cons (cons (/ n 6) (sin (/ n 6))) (make-points (1- n))))) + + (plot! (make-points 37) "x" "Sin(x)") + -| + Sin(x) ______________________________________________ + 1.25|- | + | | + 1|- **** | + | ** ** | + 750.0e-3|- * * | + | * * | + 500.0e-3|- * * | + | * | + 250.0e-3|- * | + | * * | + 0|-------------------*--------------------------| + | * | + -250.0e-3|- * * | + | * * | + -500.0e-3|- * | + | * * | + -750.0e-3|- * * | + | ** ** | + -1|- **** | + |____________:_____._____:_____._____:_________| + x 2 4 + + +File: slib.info, Node: Root Finding, Next: Commutative Rings, Prev: Plotting, Up: Mathematical Packages + +Root Finding +============ + + `(require 'root)' + + - Function: newtown:find-integer-root F DF/DX X0 + Given integer valued procedure F, its derivative (with respect to + its argument) DF/DX, and initial integer value X0 for which + DF/DX(X0) is non-zero, returns an integer X for which F(X) is + closer to zero than either of the integers adjacent to X; or + returns `#f' if such an integer can't be found. + + To find the closest integer to a given integers square root: + + (define (integer-sqrt y) + (newton:find-integer-root + (lambda (x) (- (* x x) y)) + (lambda (x) (* 2 x)) + (ash 1 (quotient (integer-length y) 2)))) + + (integer-sqrt 15) => 4 + + - Function: integer-sqrt Y + Given a non-negative integer Y, returns the rounded square-root of + Y. + + - Function: newton:find-root F DF/DX X0 PREC + Given real valued procedures F, DF/DX of one (real) argument, + initial real value X0 for which DF/DX(X0) is non-zero, and + positive real number PREC, returns a real X for which `abs'(F(X)) + is less than PREC; or returns `#f' if such a real can't be found. + + If PREC is instead a negative integer, `newton:find-root' returns + the result of -PREC iterations. + +H. J. Orchard, `The Laguerre Method for Finding the Zeros of +Polynomials', IEEE Transactions on Circuits and Systems, Vol. 36, No. +11, November 1989, pp 1377-1381. + + There are 2 errors in Orchard's Table II. Line k=2 for starting + value of 1000+j0 should have Z_k of 1.0475 + j4.1036 and line k=2 + for starting value of 0+j1000 should have Z_k of 1.0988 + j4.0833. + + - Function: laguerre:find-root F DF/DZ DDF/DZ^2 Z0 PREC + Given complex valued procedure F of one (complex) argument, its + derivative (with respect to its argument) DF/DX, its second + derivative DDF/DZ^2, initial complex value Z0, and positive real + number PREC, returns a complex number Z for which + `magnitude'(F(Z)) is less than PREC; or returns `#f' if such a + number can't be found. + + If PREC is instead a negative integer, `laguerre:find-root' + returns the result of -PREC iterations. + + - Function: laguerre:find-polynomial-root DEG F DF/DZ DDF/DZ^2 Z0 PREC + Given polynomial procedure F of integer degree DEG of one + argument, its derivative (with respect to its argument) DF/DX, its + second derivative DDF/DZ^2, initial complex value Z0, and positive + real number PREC, returns a complex number Z for which + `magnitude'(F(Z)) is less than PREC; or returns `#f' if such a + number can't be found. + + If PREC is instead a negative integer, + `laguerre:find-polynomial-root' returns the result of -PREC + iterations. + + - Function: secant:find-root F X0 X1 PREC + - Function: secant:find-bracketed-root F X0 X1 PREC + Given a real valued procedure F and two real valued starting + points X0 and X1, returns a real X for which `(abs (f x))' is less + than PREC; or returns `#f' if such a real can't be found. + + If X0 and X1 are chosen such that they bracket a root, that is + (or (< (f x0) 0 (f x1)) + (< (f x1) 0 (f x0))) + then the root returned will be between X0 and X1, and F will not + be passed an argument outside of that interval. + + `secant:find-bracketed-root' will return `#f' unless X0 and X1 + bracket a root. + + The secant method is used until a bracketing interval is found, at + which point a modified regula falsi method is used. + + If PREC is instead a negative integer, `secant:find-root' returns + the result of -PREC iterations. + + If PREC is a procedure it should accept 5 arguments: X0 F0 X1 F1 + and COUNT, where F0 will be `(f x0)', F1 `(f x1)', and COUNT the + number of iterations performed so far. PREC should return + non-false if the iteration should be stopped. + + +File: slib.info, Node: Commutative Rings, Next: Determinant, Prev: Root Finding, Up: Mathematical Packages + +Commutative Rings +================= + + Scheme provides a consistent and capable set of numeric functions. +Inexacts implement a field; integers a commutative ring (and Euclidean +domain). This package allows one to use basic Scheme numeric functions +with symbols and non-numeric elements of commutative rings. + + `(require 'commutative-ring)' + + The "commutative-ring" package makes the procedures `+', `-', `*', +`/', and `^' "careful" in the sense that any non-numeric arguments they +do not reduce appear in the expression output. In order to see what +working with this package is like, self-set all the single letter +identifiers (to their corresponding symbols). + + (define a 'a) + ... + (define z 'z) + + Or just `(require 'self-set)'. Now try some sample expressions: + + (+ (+ a b) (- a b)) => (* a 2) + (* (+ a b) (+ a b)) => (^ (+ a b) 2) + (* (+ a b) (- a b)) => (* (+ a b) (- a b)) + (* (- a b) (- a b)) => (^ (- a b) 2) + (* (- a b) (+ a b)) => (* (+ a b) (- a b)) + (/ (+ a b) (+ c d)) => (/ (+ a b) (+ c d)) + (^ (+ a b) 3) => (^ (+ a b) 3) + (^ (+ a 2) 3) => (^ (+ 2 a) 3) + + Associative rules have been applied and repeated addition and +multiplication converted to multiplication and exponentiation. + + We can enable distributive rules, thus expanding to sum of products +form: + (set! *ruleset* (combined-rulesets distribute* distribute/)) + + (* (+ a b) (+ a b)) => (+ (* 2 a b) (^ a 2) (^ b 2)) + (* (+ a b) (- a b)) => (- (^ a 2) (^ b 2)) + (* (- a b) (- a b)) => (- (+ (^ a 2) (^ b 2)) (* 2 a b)) + (* (- a b) (+ a b)) => (- (^ a 2) (^ b 2)) + (/ (+ a b) (+ c d)) => (+ (/ a (+ c d)) (/ b (+ c d))) + (/ (+ a b) (- c d)) => (+ (/ a (- c d)) (/ b (- c d))) + (/ (- a b) (- c d)) => (- (/ a (- c d)) (/ b (- c d))) + (/ (- a b) (+ c d)) => (- (/ a (+ c d)) (/ b (+ c d))) + (^ (+ a b) 3) => (+ (* 3 a (^ b 2)) (* 3 b (^ a 2)) (^ a 3) (^ b 3)) + (^ (+ a 2) 3) => (+ 8 (* a 12) (* (^ a 2) 6) (^ a 3)) + + Use of this package is not restricted to simple arithmetic +expressions: + + (require 'determinant) + + (determinant '((a b c) (d e f) (g h i))) => + (- (+ (* a e i) (* b f g) (* c d h)) (* a f h) (* b d i) (* c e g)) + + Currently, only `+', `-', `*', `/', and `^' support non-numeric +elements. Expressions with `-' are converted to equivalent expressions +without `-', so behavior for `-' is not defined separately. `/' +expressions are handled similarly. + + This list might be extended to include `quotient', `modulo', +`remainder', `lcm', and `gcd'; but these work only for the more +restrictive Euclidean (Unique Factorization) Domain. + +Rules and Rulesets +================== + + The "commutative-ring" package allows control of ring properties +through the use of "rulesets". + + - Variable: *ruleset* + Contains the set of rules currently in effect. Rules defined by + `cring:define-rule' are stored within the value of *ruleset* at the + time `cring:define-rule' is called. If *RULESET* is `#f', then no + rules apply. + + - Function: make-ruleset RULE1 ... + - Function: make-ruleset NAME RULE1 ... + Returns a new ruleset containing the rules formed by applying + `cring:define-rule' to each 4-element list argument RULE. If the + first argument to `make-ruleset' is a symbol, then the database + table created for the new ruleset will be named NAME. Calling + `make-ruleset' with no rule arguments creates an empty ruleset. + + - Function: combined-rulesets RULESET1 ... + - Function: combined-rulesets NAME RULESET1 ... + Returns a new ruleset containing the rules contained in each + ruleset argument RULESET. If the first argument to + `combined-ruleset' is a symbol, then the database table created for + the new ruleset will be named NAME. Calling `combined-ruleset' + with no ruleset arguments creates an empty ruleset. + + Two rulesets are defined by this package. + + - Constant: distribute* + Contain the ruleset to distribute multiplication over addition and + subtraction. + + - Constant: distribute/ + Contain the ruleset to distribute division over addition and + subtraction. + + Take care when using both DISTRIBUTE* and DISTRIBUTE/ + simultaneously. It is possible to put `/' into an infinite loop. + + You can specify how sum and product expressions containing non-numeric +elements simplify by specifying the rules for `+' or `*' for cases +where expressions involving objects reduce to numbers or to expressions +involving different non-numeric elements. + + - Function: cring:define-rule OP SUB-OP1 SUB-OP2 REDUCTION + Defines a rule for the case when the operation represented by + symbol OP is applied to lists whose `car's are SUB-OP1 and + SUB-OP2, respectively. The argument REDUCTION is a procedure + accepting 2 arguments which will be lists whose `car's are SUB-OP1 + and SUB-OP2. + + - Function: cring:define-rule OP SUB-OP1 'IDENTITY REDUCTION + Defines a rule for the case when the operation represented by + symbol OP is applied to a list whose `car' is SUB-OP1, and some + other argument. REDUCTION will be called with the list whose + `car' is SUB-OP1 and some other argument. + + If REDUCTION returns `#f', the reduction has failed and other + reductions will be tried. If REDUCTION returns a non-false value, + that value will replace the two arguments in arithmetic (`+', `-', + and `*') calculations involving non-numeric elements. + + The operations `+' and `*' are assumed commutative; hence both + orders of arguments to REDUCTION will be tried if necessary. + + The following rule is the definition for distributing `*' over `+'. + + (cring:define-rule + '* '+ 'identity + (lambda (exp1 exp2) + (apply + (map (lambda (trm) (* trm exp2)) (cdr exp1)))))) + +How to Create a Commutative Ring +================================ + + The first step in creating your commutative ring is to write +procedures to create elements of the ring. A non-numeric element of +the ring must be represented as a list whose first element is a symbol +or string. This first element identifies the type of the object. A +convenient and clear convention is to make the type-identifying element +be the same symbol whose top-level value is the procedure to create it. + + (define (n . list1) + (cond ((and (= 2 (length list1)) + (eq? (car list1) (cadr list1))) + 0) + ((not (term< (first list1) (last1 list1))) + (apply n (reverse list1))) + (else (cons 'n list1)))) + + (define (s x y) (n x y)) + + (define (m . list1) + (cond ((neq? (first list1) (term_min list1)) + (apply m (cyclicrotate list1))) + ((term< (last1 list1) (cadr list1)) + (apply m (reverse (cyclicrotate list1)))) + (else (cons 'm list1)))) + + Define a procedure to multiply 2 non-numeric elements of the ring. +Other multiplicatons are handled automatically. Objects for which rules +have *not* been defined are not changed. + + (define (n*n ni nj) + (let ((list1 (cdr ni)) (list2 (cdr nj))) + (cond ((null? (intersection list1 list2)) #f) + ((and (eq? (last1 list1) (first list2)) + (neq? (first list1) (last1 list2))) + (apply n (splice list1 list2))) + ((and (eq? (first list1) (first list2)) + (neq? (last1 list1) (last1 list2))) + (apply n (splice (reverse list1) list2))) + ((and (eq? (last1 list1) (last1 list2)) + (neq? (first list1) (first list2))) + (apply n (splice list1 (reverse list2)))) + ((and (eq? (last1 list1) (first list2)) + (eq? (first list1) (last1 list2))) + (apply m (cyclicsplice list1 list2))) + ((and (eq? (first list1) (first list2)) + (eq? (last1 list1) (last1 list2))) + (apply m (cyclicsplice (reverse list1) list2))) + (else #f)))) + + Test the procedures to see if they work. + + ;;; where cyclicrotate(list) is cyclic rotation of the list one step + ;;; by putting the first element at the end + (define (cyclicrotate list1) + (append (rest list1) (list (first list1)))) + ;;; and where term_min(list) is the element of the list which is + ;;; first in the term ordering. + (define (term_min list1) + (car (sort list1 term<))) + (define (term< sym1 sym2) + (string<? (symbol->string sym1) (symbol->string sym2))) + (define first car) + (define rest cdr) + (define (last1 list1) (car (last-pair list1))) + (define (neq? obj1 obj2) (not (eq? obj1 obj2))) + ;;; where splice is the concatenation of list1 and list2 except that their + ;;; common element is not repeated. + (define (splice list1 list2) + (cond ((eq? (last1 list1) (first list2)) + (append list1 (cdr list2))) + (else (error 'splice list1 list2)))) + ;;; where cyclicsplice is the result of leaving off the last element of + ;;; splice(list1,list2). + (define (cyclicsplice list1 list2) + (cond ((and (eq? (last1 list1) (first list2)) + (eq? (first list1) (last1 list2))) + (butlast (splice list1 list2) 1)) + (else (error 'cyclicsplice list1 list2)))) + + (N*N (S a b) (S a b)) => (m a b) + + Then register the rule for multiplying type N objects by type N +objects. + + (cring:define-rule '* 'N 'N N*N)) + + Now we are ready to compute! + + (define (t) + (define detM + (+ (* (S g b) + (+ (* (S f d) + (- (* (S a f) (S d g)) (* (S a g) (S d f)))) + (* (S f f) + (- (* (S a g) (S d d)) (* (S a d) (S d g)))) + (* (S f g) + (- (* (S a d) (S d f)) (* (S a f) (S d d)))))) + (* (S g d) + (+ (* (S f b) + (- (* (S a g) (S d f)) (* (S a f) (S d g)))) + (* (S f f) + (- (* (S a b) (S d g)) (* (S a g) (S d b)))) + (* (S f g) + (- (* (S a f) (S d b)) (* (S a b) (S d f)))))) + (* (S g f) + (+ (* (S f b) + (- (* (S a d) (S d g)) (* (S a g) (S d d)))) + (* (S f d) + (- (* (S a g) (S d b)) (* (S a b) (S d g)))) + (* (S f g) + (- (* (S a b) (S d d)) (* (S a d) (S d b)))))) + (* (S g g) + (+ (* (S f b) + (- (* (S a f) (S d d)) (* (S a d) (S d f)))) + (* (S f d) + (- (* (S a b) (S d f)) (* (S a f) (S d b)))) + (* (S f f) + (- (* (S a d) (S d b)) (* (S a b) (S d d)))))))) + (* (S b e) (S c a) (S e c) + detM + )) + (pretty-print (t)) + -| + (- (+ (m a c e b d f g) + (m a c e b d g f) + (m a c e b f d g) + (m a c e b f g d) + (m a c e b g d f) + (m a c e b g f d)) + (* 2 (m a b e c) (m d f g)) + (* (m a c e b d) (m f g)) + (* (m a c e b f) (m d g)) + (* (m a c e b g) (m d f))) + + +File: slib.info, Node: Determinant, Prev: Commutative Rings, Up: Mathematical Packages + +Determinant +=========== + + (require 'determinant) + (determinant '((1 2) (3 4))) => -2 + (determinant '((1 2 3) (4 5 6) (7 8 9))) => 0 + (determinant '((1 2 3 4) (5 6 7 8) (9 10 11 12))) => 0 + + +File: slib.info, Node: Database Packages, Next: Other Packages, Prev: Mathematical Packages, Up: Top + +Database Packages +***************** + +* Menu: + +* Base Table:: +* Relational Database:: 'relational-database +* Weight-Balanced Trees:: 'wt-tree + + +File: slib.info, Node: Base Table, Next: Relational Database, Prev: Database Packages, Up: Database Packages + +Base Table +========== + + A base table implementation using Scheme association lists is +available as the value of the identifier `alist-table' after doing: + + `(require 'alist-table)' + + Association list base tables are suitable for small databases and +support all Scheme types when temporary and readable/writeable Scheme +types when saved. I hope support for other base table implementations +will be added in the future. + + This rest of this section documents the interface for a base table +implementation from which the *Note Relational Database:: package +constructs a Relational system. It will be of interest primarily to +those wishing to port or write new base-table implementations. + + All of these functions are accessed through a single procedure by +calling that procedure with the symbol name of the operation. A +procedure will be returned if that operation is supported and `#f' +otherwise. For example: + + (require 'alist-table) + (define open-base (alist-table 'make-base)) + make-base => *a procedure* + (define foo (alist-table 'foo)) + foo => #f + + - Function: make-base FILENAME KEY-DIMENSION COLUMN-TYPES + Returns a new, open, low-level database (collection of tables) + associated with FILENAME. This returned database has an empty + table associated with CATALOG-ID. The positive integer + KEY-DIMENSION is the number of keys composed to make a PRIMARY-KEY + for the catalog table. The list of symbols COLUMN-TYPES describes + the types of each column for that table. If the database cannot + be created as specified, `#f' is returned. + + Calling the `close-base' method on this database and possibly other + operations will cause FILENAME to be written to. If FILENAME is + `#f' a temporary, non-disk based database will be created if such + can be supported by the base table implelentation. + + - Function: open-base FILENAME MUTABLE + Returns an open low-level database associated with FILENAME. If + MUTABLE? is `#t', this database will have methods capable of + effecting change to the database. If MUTABLE? is `#f', only + methods for inquiring the database will be available. If the + database cannot be opened as specified `#f' is returned. + + Calling the `close-base' (and possibly other) method on a MUTABLE? + database will cause FILENAME to be written to. + + - Function: write-base LLDB FILENAME + Causes the low-level database LLDB to be written to FILENAME. If + the write is successful, also causes LLDB to henceforth be + associated with FILENAME. Calling the `close-database' (and + possibly other) method on LLDB may cause FILENAME to be written + to. If FILENAME is `#f' this database will be changed to a + temporary, non-disk based database if such can be supported by the + underlying base table implelentation. If the operations completed + successfully, `#t' is returned. Otherwise, `#f' is returned. + + - Function: sync-base LLDB + Causes the file associated with the low-level database LLDB to be + updated to reflect its current state. If the associated filename + is `#f', no action is taken and `#f' is returned. If this + operation completes successfully, `#t' is returned. Otherwise, + `#f' is returned. + + - Function: close-base LLDB + Causes the low-level database LLDB to be written to its associated + file (if any). If the write is successful, subsequent operations + to LLDB will signal an error. If the operations complete + successfully, `#t' is returned. Otherwise, `#f' is returned. + + - Function: make-table LLDB KEY-DIMENSION COLUMN-TYPES + Returns the BASE-ID for a new base table, otherwise returns `#f'. + The base table can then be opened using `(open-table LLDB + BASE-ID)'. The positive integer KEY-DIMENSION is the number of + keys composed to make a PRIMARY-KEY for this table. The list of + symbols COLUMN-TYPES describes the types of each column. + + - Constant: catalog-id + A constant BASE-ID suitable for passing as a parameter to + `open-table'. CATALOG-ID will be used as the base table for the + system catalog. + + - Function: open-table LLDB BASE-ID KEY-DIMENSION COLUMN-TYPES + Returns a HANDLE for an existing base table in the low-level + database LLDB if that table exists and can be opened in the mode + indicated by MUTABLE?, otherwise returns `#f'. + + As with `make-table', the positive integer KEY-DIMENSION is the + number of keys composed to make a PRIMARY-KEY for this table. The + list of symbols COLUMN-TYPES describes the types of each column. + + - Function: kill-table LLDB BASE-ID KEY-DIMENSION COLUMN-TYPES + Returns `#t' if the base table associated with BASE-ID was removed + from the low level database LLDB, and `#f' otherwise. + + - Function: make-keyifier-1 TYPE + Returns a procedure which accepts a single argument which must be + of type TYPE. This returned procedure returns an object suitable + for being a KEY argument in the functions whose descriptions + follow. + + Any 2 arguments of the supported type passed to the returned + function which are not `equal?' must result in returned values + which are not `equal?'. + + - Function: make-list-keyifier KEY-DIMENSION TYPES + The list of symbols TYPES must have at least KEY-DIMENSION + elements. Returns a procedure which accepts a list of length + KEY-DIMENSION and whose types must corresopond to the types named + by TYPES. This returned procedure combines the elements of its + list argument into an object suitable for being a KEY argument in + the functions whose descriptions follow. + + Any 2 lists of supported types (which must at least include + symbols and non-negative integers) passed to the returned function + which are not `equal?' must result in returned values which are not + `equal?'. + + - Function: make-key-extractor KEY-DIMENSION TYPES COLUMN-NUMBER + Returns a procedure which accepts objects produced by application + of the result of `(make-list-keyifier KEY-DIMENSION TYPES)'. This + procedure returns a KEY which is `equal?' to the COLUMN-NUMBERth + element of the list which was passed to create COMBINED-KEY. The + list TYPES must have at least KEY-DIMENSION elements. + + - Function: make-key->list KEY-DIMENSION TYPES + Returns a procedure which accepts objects produced by application + of the result of `(make-list-keyifier KEY-DIMENSION TYPES)'. This + procedure returns a list of KEYs which are elementwise `equal?' to + the list which was passed to create COMBINED-KEY. + +In the following functions, the KEY argument can always be assumed to +be the value returned by a call to a *keyify* routine. + +In contrast, a MATCH-KEY argument is a list of length equal to the +number of primary keys. The MATCH-KEY restricts the actions of the +table command to those records whose primary keys all satisfy the +corresponding element of the MATCH-KEY list. The elements and their +actions are: + + `#f' + The false value matches any key in the corresponding position. + + an object of type procedure + This procedure must take a single argument, the key in the + corresponding position. Any key for which the procedure + returns a non-false value is a match; Any key for which the + procedure returns a `#f' is not. + + other values + Any other value matches only those keys `equal?' to it. + + - Function: for-each-key HANDLE PROCEDURE MATCH-KEY + Calls PROCEDURE once with each KEY in the table opened in HANDLE + which satisfies MATCH-KEY in an unspecified order. An unspecified + value is returned. + + - Function: map-key HANDLE PROCEDURE MATCH-KEY + Returns a list of the values returned by calling PROCEDURE once + with each KEY in the table opened in HANDLE which satisfies + MATCH-KEY in an unspecified order. + + - Function: ordered-for-each-key HANDLE PROCEDURE MATCH-KEY + Calls PROCEDURE once with each KEY in the table opened in HANDLE + which satisfies MATCH-KEY in the natural order for the types of + the primary key fields of that table. An unspecified value is + returned. + + - Function: delete* HANDLE MATCH-KEY + Removes all rows which satisfy MATCH-KEY from the table opened in + HANDLE. An unspecified value is returned. + + - Function: present? HANDLE KEY + Returns a non-`#f' value if there is a row associated with KEY in + the table opened in HANDLE and `#f' otherwise. + + - Function: delete HANDLE KEY + Removes the row associated with KEY from the table opened in + HANDLE. An unspecified value is returned. + + - Function: make-getter KEY-DIMENSION TYPES + Returns a procedure which takes arguments HANDLE and KEY. This + procedure returns a list of the non-primary values of the relation + (in the base table opened in HANDLE) whose primary key is KEY if + it exists, and `#f' otherwise. + + - Function: make-putter KEY-DIMENSION TYPES + Returns a procedure which takes arguments HANDLE and KEY and + VALUE-LIST. This procedure associates the primary key KEY with + the values in VALUE-LIST (in the base table opened in HANDLE) and + returns an unspecified value. + + - Function: supported-type? SYMBOL + Returns `#t' if SYMBOL names a type allowed as a column value by + the implementation, and `#f' otherwise. At a minimum, an + implementation must support the types `integer', `symbol', + `string', `boolean', and `base-id'. + + - Function: supported-key-type? SYMBOL + Returns `#t' if SYMBOL names a type allowed as a key value by the + implementation, and `#f' otherwise. At a minimum, an + implementation must support the types `integer', and `symbol'. + +`integer' + Scheme exact integer. + +`symbol' + Scheme symbol. + +`boolean' + `#t' or `#f'. + +`base-id' + Objects suitable for passing as the BASE-ID parameter to + `open-table'. The value of CATALOG-ID must be an acceptable + `base-id'. + + +File: slib.info, Node: Relational Database, Next: Weight-Balanced Trees, Prev: Base Table, Up: Database Packages + +Relational Database +=================== + + `(require 'relational-database)' + + This package implements a database system inspired by the Relational +Model (`E. F. Codd, A Relational Model of Data for Large Shared Data +Banks'). An SLIB relational database implementation can be created +from any *Note Base Table:: implementation. + +* Menu: + +* Motivations:: Database Manifesto +* Creating and Opening Relational Databases:: +* Relational Database Operations:: +* Table Operations:: +* Catalog Representation:: +* Unresolved Issues:: +* Database Utilities:: 'database-utilities +* Database Reports:: +* Database Browser:: 'database-browse + + +File: slib.info, Node: Motivations, Next: Creating and Opening Relational Databases, Prev: Relational Database, Up: Relational Database + +Motivations +----------- + + Most nontrivial programs contain databases: Makefiles, configure +scripts, file backup, calendars, editors, source revision control, CAD +systems, display managers, menu GUIs, games, parsers, debuggers, +profilers, and even error reporting are all rife with databases. Coding +databases is such a common activity in programming that many may not be +aware of how often they do it. + + A database often starts as a dispatch in a program. The author, +perhaps because of the need to make the dispatch configurable, the need +for correlating dispatch in other routines, or because of changes or +growth, devises a data structure to contain the information, a routine +for interpreting that data structure, and perhaps routines for +augmenting and modifying the stored data. The dispatch must be +converted into this form and tested. + + The programmer may need to devise an interactive program for enabling +easy examination and modification of the information contained in this +database. Often, in an attempt to foster modularity and avoid delays in +release, intermediate file formats for the database information are +devised. It often turns out that users prefer modifying these +intermediate files with a text editor to using the interactive program +in order to do operations (such as global changes) not forseen by the +program's author. + + In order to address this need, the conscientious software engineer may +even provide a scripting language to allow users to make repetitive +database changes. Users will grumble that they need to read a large +manual and learn yet another programming language (even if it *almost* +has language "xyz" syntax) in order to do simple configuration. + + All of these facilities need to be designed, coded, debugged, +documented, and supported; often causing what was very simple in concept +to become a major developement project. + + This view of databases just outlined is somewhat the reverse of the +view of the originators of the "Relational Model" of database +abstraction. The relational model was devised to unify and allow +interoperation of large multi-user databases running on diverse +platforms. A fairly general purpose "Comprehensive Language" for +database manipulations is mandated (but not specified) as part of the +relational model for databases. + + One aspect of the Relational Model of some importance is that the +"Comprehensive Language" must be expressible in some form which can be +stored in the database. This frees the programmer from having to make +programs data-driven in order to use a database. + + This package includes as one of its basic supported types Scheme +"expression"s. This type allows expressions as defined by the Scheme +standards to be stored in the database. Using `slib:eval' retrieved +expressions can be evaluated (in the top-level environment). Scheme's +`lambda' facilitates closure of environments, modularity, etc. so that +procedures (which could not be stored directly most databases) can +still be effectively retrieved. Since `slib:eval' evaluates +expressions in the top-level environment, built-in and user defined +procedures can be easily accessed by name. + + This package's purpose is to standardize (through a common interface) +database creation and usage in Scheme programs. The relational model's +provision for inclusion of language expressions as data as well as the +description (in tables, of course) of all of its tables assures that +relational databases are powerful enough to assume the roles currently +played by thousands of ad-hoc routines and data formats. + +Such standardization to a relational-like model brings many benefits: + + * Tables, fields, domains, and types can be dealt with by name in + programs. + + * The underlying database implementation can be changed (for + performance or other reasons) by changing a single line of code. + + * The formats of tables can be easily extended or changed without + altering code. + + * Consistency checks are specified as part of the table descriptions. + Changes in checks need only occur in one place. + + * All the configuration information which the developer wishes to + group together is easily grouped, without needing to change + programs aware of only some of these tables. + + * Generalized report generators, interactive entry programs, and + other database utilities can be part of a shared library. The + burden of adding configurability to a program is greatly reduced. + + * Scheme is the "comprehensive language" for these databases. + Scripting for configuration no longer needs to be in a separate + language with additional documentation. + + * Scheme's latent types mesh well with the strict typing and logical + requirements of the relational model. + + * Portable formats allow easy interchange of data. The included + table descriptions help prevent misinterpretation of format. + + +File: slib.info, Node: Creating and Opening Relational Databases, Next: Relational Database Operations, Prev: Motivations, Up: Relational Database + +Creating and Opening Relational Databases +----------------------------------------- + + - Function: make-relational-system BASE-TABLE-IMPLEMENTATION + Returns a procedure implementing a relational database using the + BASE-TABLE-IMPLEMENTATION. + + All of the operations of a base table implementation are accessed + through a procedure defined by `require'ing that implementation. + Similarly, all of the operations of the relational database + implementation are accessed through the procedure returned by + `make-relational-system'. For instance, a new relational database + could be created from the procedure returned by + `make-relational-system' by: + + (require 'alist-table) + (define relational-alist-system + (make-relational-system alist-table)) + (define create-alist-database + (relational-alist-system 'create-database)) + (define my-database + (create-alist-database "mydata.db")) + +What follows are the descriptions of the methods available from +relational system returned by a call to `make-relational-system'. + + - Function: create-database FILENAME + Returns an open, nearly empty relational database associated with + FILENAME. The only tables defined are the system catalog and + domain table. Calling the `close-database' method on this database + and possibly other operations will cause FILENAME to be written + to. If FILENAME is `#f' a temporary, non-disk based database will + be created if such can be supported by the underlying base table + implelentation. If the database cannot be created as specified + `#f' is returned. For the fields and layout of descriptor tables, + *Note Catalog Representation:: + + - Function: open-database FILENAME MUTABLE? + Returns an open relational database associated with FILENAME. If + MUTABLE? is `#t', this database will have methods capable of + effecting change to the database. If MUTABLE? is `#f', only + methods for inquiring the database will be available. Calling the + `close-database' (and possibly other) method on a MUTABLE? + database will cause FILENAME to be written to. If the database + cannot be opened as specified `#f' is returned. + + +File: slib.info, Node: Relational Database Operations, Next: Table Operations, Prev: Creating and Opening Relational Databases, Up: Relational Database + +Relational Database Operations +------------------------------ + +These are the descriptions of the methods available from an open +relational database. A method is retrieved from a database by calling +the database with the symbol name of the operation. For example: + + (define my-database + (create-alist-database "mydata.db")) + (define telephone-table-desc + ((my-database 'create-table) 'telephone-table-desc)) + + - Function: close-database + Causes the relational database to be written to its associated + file (if any). If the write is successful, subsequent operations + to this database will signal an error. If the operations completed + successfully, `#t' is returned. Otherwise, `#f' is returned. + + - Function: write-database FILENAME + Causes the relational database to be written to FILENAME. If the + write is successful, also causes the database to henceforth be + associated with FILENAME. Calling the `close-database' (and + possibly other) method on this database will cause FILENAME to be + written to. If FILENAME is `#f' this database will be changed to + a temporary, non-disk based database if such can be supported by + the underlying base table implelentation. If the operations + completed successfully, `#t' is returned. Otherwise, `#f' is + returned. + + - Function: table-exists? TABLE-NAME + Returns `#t' if TABLE-NAME exists in the system catalog, otherwise + returns `#f'. + + - Function: open-table TABLE-NAME MUTABLE? + Returns a "methods" procedure for an existing relational table in + this database if it exists and can be opened in the mode indicated + by MUTABLE?, otherwise returns `#f'. + +These methods will be present only in databases which are MUTABLE?. + + - Function: delete-table TABLE-NAME + Removes and returns the TABLE-NAME row from the system catalog if + the table or view associated with TABLE-NAME gets removed from the + database, and `#f' otherwise. + + - Function: create-table TABLE-DESC-NAME + Returns a methods procedure for a new (open) relational table for + describing the columns of a new base table in this database, + otherwise returns `#f'. For the fields and layout of descriptor + tables, *Note Catalog Representation::. + + - Function: create-table TABLE-NAME TABLE-DESC-NAME + Returns a methods procedure for a new (open) relational table with + columns as described by TABLE-DESC-NAME, otherwise returns `#f'. + + - Function: create-view ?? + - Function: project-table ?? + - Function: restrict-table ?? + - Function: cart-prod-tables ?? + Not yet implemented. + + +File: slib.info, Node: Table Operations, Next: Catalog Representation, Prev: Relational Database Operations, Up: Relational Database + +Table Operations +---------------- + +These are the descriptions of the methods available from an open +relational table. A method is retrieved from a table by calling the +table with the symbol name of the operation. For example: + + (define telephone-table-desc + ((my-database 'create-table) 'telephone-table-desc)) + (require 'common-list-functions) + (define ndrp (telephone-table-desc 'row:insert)) + (ndrp '(1 #t name #f string)) + (ndrp '(2 #f telephone + (lambda (d) + (and (string? d) (> (string-length d) 2) + (every + (lambda (c) + (memv c '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 + #\+ #\( #\ #\) #\-))) + (string->list d)))) + string)) + +Some operations described below require primary key arguments. Primary +keys arguments are denoted KEY1 KEY2 .... It is an error to call an +operation for a table which takes primary key arguments with the wrong +number of primary keys for that table. + +The term "row" used below refers to a Scheme list of values (one for +each column) in the order specified in the descriptor (table) for this +table. Missing values appear as `#f'. Primary keys must not be +missing. + + - Function: get COLUMN-NAME + Returns a procedure of arguments KEY1 KEY2 ... which returns the + value for the COLUMN-NAME column of the row associated with + primary keys KEY1, KEY2 ... if that row exists in the table, or + `#f' otherwise. + + ((plat 'get 'processor) 'djgpp) => i386 + ((plat 'get 'processor) 'be-os) => #f + + - Function: get* COLUMN-NAME + Returns a procedure of optional arguments MATCH-KEY1 ... which + returns a list of the values for the specified column for all rows + in this table. The optional MATCH-KEY1 ... arguments restrict + actions to a subset of the table. See the match-key description + below for details. + + ((plat 'get* 'processor)) => + (i386 8086 i386 8086 i386 i386 8086 m68000 + m68000 m68000 m68000 m68000 powerpc) + + ((plat 'get* 'processor) #f) => + (i386 8086 i386 8086 i386 i386 8086 m68000 + m68000 m68000 m68000 m68000 powerpc) + + (define (a-key? key) + (char=? #\a (string-ref (symbol->string key) 0))) + + ((plat 'get* 'processor) a-key?) => + (m68000 m68000 m68000 m68000 m68000 powerpc) + + ((plat 'get* 'name) a-key?) => + (atari-st-turbo-c atari-st-gcc amiga-sas/c-5.10 + amiga-aztec amiga-dice-c aix) + + - Function: row:retrieve + Returns a procedure of arguments KEY1 KEY2 ... which returns the + row associated with primary keys KEY1, KEY2 ... if it exists, or + `#f' otherwise. + + ((plat 'row:retrieve) 'linux) => (linux i386 linux gcc) + ((plat 'row:retrieve) 'multics) => #f + + - Function: row:retrieve* + Returns a procedure of optional arguments MATCH-KEY1 ... which + returns a list of all rows in this table. The optional MATCH-KEY1 + ... arguments restrict actions to a subset of the table. See the + match-key description below for details. + + ((plat 'row:retrieve*) a-key?) => + ((atari-st-turbo-c m68000 atari turbo-c) + (atari-st-gcc m68000 atari gcc) + (amiga-sas/c-5.10 m68000 amiga sas/c) + (amiga-aztec m68000 amiga aztec) + (amiga-dice-c m68000 amiga dice-c) + (aix powerpc aix -)) + + - Function: row:remove + Returns a procedure of arguments KEY1 KEY2 ... which removes and + returns the row associated with primary keys KEY1, KEY2 ... if it + exists, or `#f' otherwise. + + - Function: row:remove* + Returns a procedure of optional arguments MATCH-KEY1 ... which + removes and returns a list of all rows in this table. The optional + MATCH-KEY1 ... arguments restrict actions to a subset of the + table. See the match-key description below for details. + + - Function: row:delete + Returns a procedure of arguments KEY1 KEY2 ... which deletes the + row associated with primary keys KEY1, KEY2 ... if it exists. The + value returned is unspecified. + + - Function: row:delete* + Returns a procedure of optional arguments MATCH-KEY1 ... which + Deletes all rows from this table. The optional MATCH-KEY1 ... + arguments restrict deletions to a subset of the table. See the + match-key description below for details. The value returned is + unspecified. The descriptor table and catalog entry for this + table are not affected. + + - Function: row:update + Returns a procedure of one argument, ROW, which adds the row, ROW, + to this table. If a row for the primary key(s) specified by ROW + already exists in this table, it will be overwritten. The value + returned is unspecified. + + - Function: row:update* + Returns a procedure of one argument, ROWS, which adds each row in + the list of rows, ROWS, to this table. If a row for the primary + key specified by an element of ROWS already exists in this table, + it will be overwritten. The value returned is unspecified. + + - Function: row:insert + Adds the row ROW to this table. If a row for the primary key(s) + specified by ROW already exists in this table an error is + signaled. The value returned is unspecified. + + - Function: row:insert* + Returns a procedure of one argument, ROWS, which adds each row in + the list of rows, ROWS, to this table. If a row for the primary + key specified by an element of ROWS already exists in this table, + an error is signaled. The value returned is unspecified. + + - Function: for-each-row + Returns a procedure of arguments PROC MATCH-KEY1 ... which calls + PROC with each ROW in this table in the (implementation-dependent) + natural ordering for rows. The optional MATCH-KEY1 ... arguments + restrict actions to a subset of the table. See the match-key + description below for details. + + *Real* relational programmers would use some least-upper-bound join + for every row to get them in order; But we don't have joins yet. + +The (optional) MATCH-KEY1 ... arguments are used to restrict actions of +a whole-table operation to a subset of that table. Those procedures +(returned by methods) which accept match-key arguments will accept any +number of match-key arguments between zero and the number of primary +keys in the table. Any unspecified MATCH-KEY arguments default to `#f'. + +The MATCH-KEY1 ... restrict the actions of the table command to those +records whose primary keys each satisfy the corresponding MATCH-KEY +argument. The arguments and their actions are: + + `#f' + The false value matches any key in the corresponding position. + + an object of type procedure + This procedure must take a single argument, the key in the + corresponding position. Any key for which the procedure + returns a non-false value is a match; Any key for which the + procedure returns a `#f' is not. + + other values + Any other value matches only those keys `equal?' to it. + + - Function: close-table + Subsequent operations to this table will signal an error. + + - Constant: column-names + - Constant: column-foreigns + - Constant: column-domains + - Constant: column-types + Return a list of the column names, foreign-key table names, domain + names, or type names respectively for this table. These 4 methods + are different from the others in that the list is returned, rather + than a procedure to obtain the list. + + - Constant: primary-limit + Returns the number of primary keys fields in the relations in this + table. + + +File: slib.info, Node: Catalog Representation, Next: Unresolved Issues, Prev: Table Operations, Up: Relational Database + +Catalog Representation +---------------------- + +Each database (in an implementation) has a "system catalog" which +describes all the user accessible tables in that database (including +itself). + +The system catalog base table has the following fields. `PRI' +indicates a primary key for that table. + + PRI table-name + column-limit the highest column number + coltab-name descriptor table name + bastab-id data base table identifier + user-integrity-rule + view-procedure A scheme thunk which, when called, + produces a handle for the view. coltab + and bastab are specified if and only if + view-procedure is not. + +Descriptors for base tables (not views) are tables (pointed to by +system catalog). Descriptor (base) tables have the fields: + + PRI column-number sequential integers from 1 + primary-key? boolean TRUE for primary key components + column-name + column-integrity-rule + domain-name + +A "primary key" is any column marked as `primary-key?' in the +corresponding descriptor table. All the `primary-key?' columns must +have lower column numbers than any non-`primary-key?' columns. Every +table must have at least one primary key. Primary keys must be +sufficient to distinguish all rows from each other in the table. All of +the system defined tables have a single primary key. + +This package currently supports tables having from 1 to 4 primary keys +if there are non-primary columns, and any (natural) number if *all* +columns are primary keys. If you need more than 4 primary keys, I would +like to hear what you are doing! + +A "domain" is a category describing the allowable values to occur in a +column. It is described by a (base) table with the fields: + + PRI domain-name + foreign-table + domain-integrity-rule + type-id + type-param + +The "type-id" field value is a symbol. This symbol may be used by the +underlying base table implementation in storing that field. + +If the `foreign-table' field is non-`#f' then that field names a table +from the catalog. The values for that domain must match a primary key +of the table referenced by the TYPE-PARAM (or `#f', if allowed). This +package currently does not support composite foreign-keys. + +The types for which support is planned are: + atom + symbol + string [<length>] + number [<base>] + money <currency> + date-time + boolean + + foreign-key <table-name> + expression + virtual <expression> + + +File: slib.info, Node: Unresolved Issues, Next: Database Utilities, Prev: Catalog Representation, Up: Relational Database + +Unresolved Issues +----------------- + + Although `rdms.scm' is not large, I found it very difficult to write +(six rewrites). I am not aware of any other examples of a generalized +relational system (although there is little new in CS). I left out +several aspects of the Relational model in order to simplify the job. +The major features lacking (which might be addressed portably) are +views, transaction boundaries, and protection. + + Protection needs a model for specifying priveledges. Given how +operations are accessed from handles it should not be difficult to +restrict table accesses to those allowed for that user. + + The system catalog has a field called `view-procedure'. This should +allow a purely functional implementation of views. This will work but +is unsatisfying for views resulting from a "select"ion (subset of +rows); for whole table operations it will not be possible to reduce the +number of keys scanned over when the selection is specified only by an +opaque procedure. + + Transaction boundaries present the most intriguing area. Transaction +boundaries are actually a feature of the "Comprehensive Language" of the +Relational database and not of the database. Scheme would seem to +provide the opportunity for an extremely clean semantics for transaction +boundaries since the builtin procedures with side effects are small in +number and easily identified. + + These side-effect builtin procedures might all be portably redefined +to versions which properly handled transactions. Compiled library +routines would need to be recompiled as well. Many system extensions +(delete-file, system, etc.) would also need to be redefined. + +There are 2 scope issues that must be resolved for multiprocess +transaction boundaries: + +Process scope + The actions captured by a transaction should be only for the + process which invoked the start of transaction. Although standard + Scheme does not provide process primitives as such, `dynamic-wind' + would provide a workable hook into process switching for many + implementations. + +Shared utilities with state + Some shared utilities have state which should *not* be part of a + transaction. An example would be calling a pseudo-random number + generator. If the success of a transaction depended on the + pseudo-random number and failed, the state of the generator would + be set back. Subsequent calls would keep returning the same + number and keep failing. + + Pseudo-random number generators are not reentrant; thus they would + require locks in order to operate properly in a multiprocess + environment. Are all examples of utilities whose state should not + be part of transactions also non-reentrant? If so, perhaps + suspending transaction capture for the duration of locks would + solve this problem. + + +File: slib.info, Node: Database Utilities, Next: Database Reports, Prev: Unresolved Issues, Up: Relational Database + +Database Utilities +------------------ + + `(require 'database-utilities)' + +This enhancement wraps a utility layer on `relational-database' which +provides: + * Automatic loading of the appropriate base-table package when + opening a database. + + * Automatic execution of initialization commands stored in database. + + * Transparent execution of database commands stored in `*commands*' + table in database. + +Also included are utilities which provide: + * Data definition from Scheme lists and + + * Report generation + +for any SLIB relational database. + + - Function: create-database FILENAME BASE-TABLE-TYPE + Returns an open, nearly empty enhanced (with `*commands*' table) + relational database (with base-table type BASE-TABLE-TYPE) + associated with FILENAME. + + - Function: open-database FILENAME + - Function: open-database FILENAME BASE-TABLE-TYPE + Returns an open enchanced relational database associated with + FILENAME. The database will be opened with base-table type + BASE-TABLE-TYPE) if supplied. If BASE-TABLE-TYPE is not supplied, + `open-database' will attempt to deduce the correct + base-table-type. If the database can not be opened or if it lacks + the `*commands*' table, `#f' is returned. + + - Function: open-database! FILENAME + - Function: open-database! FILENAME BASE-TABLE-TYPE + Returns *mutable* open enchanced relational database ... + +The table `*commands*' in an "enhanced" relational-database has the +fields (with domains): + PRI name symbol + parameters parameter-list + procedure expression + documentation string + + The `parameters' field is a foreign key (domain `parameter-list') of +the `*catalog-data*' table and should have the value of a table +described by `*parameter-columns*'. This `parameter-list' table +describes the arguments suitable for passing to the associated command. +The intent of this table is to be of a form such that different +user-interfaces (for instance, pull-down menus or plain-text queries) +can operate from the same table. A `parameter-list' table has the +following fields: + PRI index uint + name symbol + arity parameter-arity + domain domain + defaulter expression + expander expression + documentation string + + The `arity' field can take the values: + +`single' + Requires a single parameter of the specified domain. + +`optional' + A single parameter of the specified domain or zero parameters is + acceptable. + +`boolean' + A single boolean parameter or zero parameters (in which case `#f' + is substituted) is acceptable. + +`nary' + Any number of parameters of the specified domain are acceptable. + The argument passed to the command function is always a list of the + parameters. + +`nary1' + One or more of parameters of the specified domain are acceptable. + The argument passed to the command function is always a list of the + parameters. + + The `domain' field specifies the domain which a parameter or +parameters in the `index'th field must satisfy. + + The `defaulter' field is an expression whose value is either `#f' or +a procedure of one argument (the parameter-list) which returns a *list* +of the default value or values as appropriate. Note that since the +`defaulter' procedure is called every time a default parameter is +needed for this column, "sticky" defaults can be implemented using +shared state with the domain-integrity-rule. + +Invoking Commands +................. + + When an enhanced relational-database is called with a symbol which +matches a NAME in the `*commands*' table, the associated procedure +expression is evaluated and applied to the enhanced +relational-database. A procedure should then be returned which the user +can invoke on (optional) arguments. + + The command `*initialize*' is special. If present in the +`*commands*' table, `open-database' or `open-database!' will return +the value of the `*initialize*' command. Notice that arbitrary code +can be run when the `*initialize*' procedure is automatically applied +to the enhanced relational-database. + + Note also that if you wish to shadow or hide from the user +relational-database methods described in *Note Relational Database +Operations::, this can be done by a dispatch in the closure returned by +the `*initialize*' expression rather than by entries in the +`*commands*' table if it is desired that the underlying methods remain +accessible to code in the `*commands*' table. + + - Function: make-command-server RDB TABLE-NAME + Returns a procedure of 2 arguments, a (symbol) command and a + call-back procedure. When this returned procedure is called, it + looks up COMMAND in table TABLE-NAME and calls the call-back + procedure with arguments: + COMMAND + The COMMAND + + COMMAND-VALUE + The result of evaluating the expression in the PROCEDURE + field of TABLE-NAME and calling it with RDB. + + PARAMETER-NAME + A list of the "official" name of each parameter. Corresponds + to the `name' field of the COMMAND's parameter-table. + + POSITIONS + A list of the positive integer index of each parameter. + Corresponds to the `index' field of the COMMAND's + parameter-table. + + ARITIES + A list of the arities of each parameter. Corresponds to the + `arity' field of the COMMAND's parameter-table. For a + description of `arity' see table above. + + TYPES + A list of the type name of each parameter. Correspnds to the + `type-id' field of the contents of the `domain' of the + COMMAND's parameter-table. + + DEFAULTERS + A list of the defaulters for each parameter. Corresponds to + the `defaulters' field of the COMMAND's parameter-table. + + DOMAIN-INTEGRITY-RULES + A list of procedures (one for each parameter) which tests + whether a value for a parameter is acceptable for that + parameter. The procedure should be called with each datum in + the list for `nary' arity parameters. + + ALIASES + A list of lists of `(alias parameter-name)'. There can be + more than one alias per PARAMETER-NAME. + + For information about parameters, *Note Parameter lists::. Here is an +example of setting up a command with arguments and parsing those +arguments from a `getopt' style argument list (*note Getopt::.). + + (require 'database-utilities) + (require 'fluid-let) + (require 'parameters) + (require 'getopt) + + (define my-rdb (create-database #f 'alist-table)) + + (define-tables my-rdb + '(foo-params + *parameter-columns* + *parameter-columns* + ((1 single-string single string + (lambda (pl) '("str")) #f "single string") + (2 nary-symbols nary symbol + (lambda (pl) '()) #f "zero or more symbols") + (3 nary1-symbols nary1 symbol + (lambda (pl) '(symb)) #f "one or more symbols") + (4 optional-number optional uint + (lambda (pl) '()) #f "zero or one number") + (5 flag boolean boolean + (lambda (pl) '(#f)) #f "a boolean flag"))) + '(foo-pnames + ((name string)) + ((parameter-index uint)) + (("s" 1) + ("single-string" 1) + ("n" 2) + ("nary-symbols" 2) + ("N" 3) + ("nary1-symbols" 3) + ("o" 4) + ("optional-number" 4) + ("f" 5) + ("flag" 5))) + '(my-commands + ((name symbol)) + ((parameters parameter-list) + (parameter-names parameter-name-translation) + (procedure expression) + (documentation string)) + ((foo + foo-params + foo-pnames + (lambda (rdb) (lambda args (print args))) + "test command arguments")))) + + (define (dbutil:serve-command-line rdb command-table + command argc argv) + (set! argv (if (vector? argv) (vector->list argv) argv)) + ((make-command-server rdb command-table) + command + (lambda (comname comval options positions + arities types defaulters dirs aliases) + (apply comval (getopt->arglist + argc argv options positions + arities types defaulters dirs aliases))))) + + (define (cmd . opts) + (fluid-let ((*optind* 1)) + (printf "%-34s => " + (call-with-output-string + (lambda (pt) (write (cons 'cmd opts) pt)))) + (set! opts (cons "cmd" opts)) + (force-output) + (dbutil:serve-command-line + my-rdb 'my-commands 'foo (length opts) opts))) + + (cmd) => ("str" () (symb) () #f) + (cmd "-f") => ("str" () (symb) () #t) + (cmd "--flag") => ("str" () (symb) () #t) + (cmd "-o177") => ("str" () (symb) (177) #f) + (cmd "-o" "177") => ("str" () (symb) (177) #f) + (cmd "--optional" "621") => ("str" () (symb) (621) #f) + (cmd "--optional=621") => ("str" () (symb) (621) #f) + (cmd "-s" "speciality") => ("speciality" () (symb) () #f) + (cmd "-sspeciality") => ("speciality" () (symb) () #f) + (cmd "--single" "serendipity") => ("serendipity" () (symb) () #f) + (cmd "--single=serendipity") => ("serendipity" () (symb) () #f) + (cmd "-n" "gravity" "piety") => ("str" () (piety gravity) () #f) + (cmd "-ngravity" "piety") => ("str" () (piety gravity) () #f) + (cmd "--nary" "chastity") => ("str" () (chastity) () #f) + (cmd "--nary=chastity" "") => ("str" () ( chastity) () #f) + (cmd "-N" "calamity") => ("str" () (calamity) () #f) + (cmd "-Ncalamity") => ("str" () (calamity) () #f) + (cmd "--nary1" "surety") => ("str" () (surety) () #f) + (cmd "--nary1=surety") => ("str" () (surety) () #f) + (cmd "-N" "levity" "fealty") => ("str" () (fealty levity) () #f) + (cmd "-Nlevity" "fealty") => ("str" () (fealty levity) () #f) + (cmd "--nary1" "surety" "brevity") => ("str" () (brevity surety) () #f) + (cmd "--nary1=surety" "brevity") => ("str" () (brevity surety) () #f) + (cmd "-?") + -| + Usage: cmd [OPTION ARGUMENT ...] ... + + -f, --flag + -o, --optional[=]<number> + -n, --nary[=]<symbols> ... + -N, --nary1[=]<symbols> ... + -s, --single[=]<string> + + ERROR: getopt->parameter-list "unrecognized option" "-?" + + Some commands are defined in all extended relational-databases. The +are called just like *Note Relational Database Operations::. + + - Function: add-domain DOMAIN-ROW + Adds DOMAIN-ROW to the "domains" table if there is no row in the + domains table associated with key `(car DOMAIN-ROW)' and returns + `#t'. Otherwise returns `#f'. + + For the fields and layout of the domain table, *Note Catalog + Representation::. Currently, these fields are + * domain-name + + * foreign-table + + * domain-integrity-rule + + * type-id + + * type-param + + The following example adds 3 domains to the `build' database. + `Optstring' is either a string or `#f'. `filename' is a string + and `build-whats' is a symbol. + + (for-each (build 'add-domain) + '((optstring #f + (lambda (x) (or (not x) (string? x))) + string + #f) + (filename #f #f string #f) + (build-whats #f #f symbol #f))) + + - Function: delete-domain DOMAIN-NAME + Removes and returns the DOMAIN-NAME row from the "domains" table. + + - Function: domain-checker DOMAIN + Returns a procedure to check an argument for conformance to domain + DOMAIN. + +Defining Tables +............... + + - Procedure: define-tables RDB SPEC-0 ... + Adds tables as specified in SPEC-0 ... to the open + relational-database RDB. Each SPEC has the form: + + (<name> <descriptor-name> <descriptor-name> <rows>) + or + (<name> <primary-key-fields> <other-fields> <rows>) + + where <name> is the table name, <descriptor-name> is the symbol + name of a descriptor table, <primary-key-fields> and + <other-fields> describe the primary keys and other fields + respectively, and <rows> is a list of data rows to be added to the + table. + + <primary-key-fields> and <other-fields> are lists of field + descriptors of the form: + + (<column-name> <domain>) + or + (<column-name> <domain> <column-integrity-rule>) + + where <column-name> is the column name, <domain> is the domain of + the column, and <column-integrity-rule> is an expression whose + value is a procedure of one argument (which returns `#f' to signal + an error). + + If <domain> is not a defined domain name and it matches the name of + this table or an already defined (in one of SPEC-0 ...) single key + field table, a foriegn-key domain will be created for it. + +The following example shows a new database with the name of `foo.db' +being created with tables describing processor families and +processor/os/compiler combinations. + +The database command `define-tables' is defined to call `define-tables' +with its arguments. The database is also configured to print `Welcome' +when the database is opened. The database is then closed and reopened. + + (require 'database-utilities) + (define my-rdb (create-database "foo.db" 'alist-table)) + + (define-tables my-rdb + '(*commands* + ((name symbol)) + ((parameters parameter-list) + (procedure expression) + (documentation string)) + ((define-tables + no-parameters + no-parameter-names + (lambda (rdb) (lambda specs (apply define-tables rdb specs))) + "Create or Augment tables from list of specs") + (*initialize* + no-parameters + no-parameter-names + (lambda (rdb) (display "Welcome") (newline) rdb) + "Print Welcome")))) + + ((my-rdb 'define-tables) + '(processor-family + ((family atom)) + ((also-ran processor-family)) + ((m68000 #f) + (m68030 m68000) + (i386 8086) + (8086 #f) + (powerpc #f))) + + '(platform + ((name symbol)) + ((processor processor-family) + (os symbol) + (compiler symbol)) + ((aix powerpc aix -) + (amiga-dice-c m68000 amiga dice-c) + (amiga-aztec m68000 amiga aztec) + (amiga-sas/c-5.10 m68000 amiga sas/c) + (atari-st-gcc m68000 atari gcc) + (atari-st-turbo-c m68000 atari turbo-c) + (borland-c-3.1 8086 ms-dos borland-c) + (djgpp i386 ms-dos gcc) + (linux i386 linux gcc) + (microsoft-c 8086 ms-dos microsoft-c) + (os/2-emx i386 os/2 gcc) + (turbo-c-2 8086 ms-dos turbo-c) + (watcom-9.0 i386 ms-dos watcom)))) + + ((my-rdb 'close-database)) + + (set! my-rdb (open-database "foo.db" 'alist-table)) + -| + Welcome + + +File: slib.info, Node: Database Reports, Next: Database Browser, Prev: Database Utilities, Up: Relational Database + +Database Reports +---------------- + +Code for generating database reports is in `report.scm'. After writing +it using `format', I discovered that Common-Lisp `format' is not +useable for this application because there is no mechanismm for +truncating fields. `report.scm' needs to be rewritten using `printf'. + + - Procedure: create-report RDB DESTINATION REPORT-NAME TABLE + - Procedure: create-report RDB DESTINATION REPORT-NAME + The symbol REPORT-NAME must be primary key in the table named + `*reports*' in the relational database RDB. DESTINATION is a + port, string, or symbol. If DESTINATION is a: + + port + The table is created as ascii text and written to that port. + + string + The table is created as ascii text and written to the file + named by DESTINATION. + + symbol + DESTINATION is the primary key for a row in the table named + *printers*. + + The report is prepared as follows: + + * `Format' (*note Format::.) is called with the `header' field + and the (list of) `column-names' of the table. + + * `Format' is called with the `reporter' field and (on + successive calls) each record in the natural order for the + table. A count is kept of the number of newlines output by + format. When the number of newlines to be output exceeds the + number of lines per page, the set of lines will be broken if + there are more than `minimum-break' left on this page and the + number of lines for this row is larger or equal to twice + `minimum-break'. + + * `Format' is called with the `footer' field and the (list of) + `column-names' of the table. The footer field should not + output a newline. + + * A new page is output. + + * This entire process repeats until all the rows are output. + + Each row in the table *reports* has the fields: + +name + The report name. + +default-table + The table to report on if none is specified. + +header, footer + A `format' string. At the beginning and end of each page + respectively, `format' is called with this string and the (list of) + column-names of this table. + +reporter + A `format' string. For each row in the table, `format' is called + with this string and the row. + +minimum-break + The minimum number of lines into which the report lines for a row + can be broken. Use `0' if a row's lines should not be broken over + page boundaries. + + Each row in the table *printers* has the fields: + +name + The printer name. + +print-procedure + The procedure to call to actually print. + + +File: slib.info, Node: Database Browser, Prev: Database Reports, Up: Relational Database + +Database Browser +---------------- + + (require 'database-browse) + + - Procedure: browse DATABASE + Prints the names of all the tables in DATABASE and sets browse's + default to DATABASE. + + - Procedure: browse + Prints the names of all the tables in the default database. + + - Procedure: browse TABLE-NAME + For each record of the table named by the symbol TABLE-NAME, + prints a line composed of all the field values. + + - Procedure: browse PATHNAME + Opens the database named by the string PATHNAME, prints the names + of all its tables, and sets browse's default to the database. + + - Procedure: browse DATABASE TABLE-NAME + Sets browse's default to DATABASE and prints the records of the + table named by the symbol TABLE-NAME. + + - Procedure: browse PATHNAME TABLE-NAME + Opens the database named by the string PATHNAME and sets browse's + default to it; `browse' prints the records of the table named by + the symbol TABLE-NAME. + + + +File: slib.info, Node: Weight-Balanced Trees, Prev: Relational Database, Up: Database Packages + +Weight-Balanced Trees +===================== + + `(require 'wt-tree)' + + Balanced binary trees are a useful data structure for maintaining +large sets of ordered objects or sets of associations whose keys are +ordered. MIT Scheme has an comprehensive implementation of +weight-balanced binary trees which has several advantages over the +other data structures for large aggregates: + + * In addition to the usual element-level operations like insertion, + deletion and lookup, there is a full complement of collection-level + operations, like set intersection, set union and subset test, all + of which are implemented with good orders of growth in time and + space. This makes weight balanced trees ideal for rapid + prototyping of functionally derived specifications. + + * An element in a tree may be indexed by its position under the + ordering of the keys, and the ordinal position of an element may + be determined, both with reasonable efficiency. + + * Operations to find and remove minimum element make weight balanced + trees simple to use for priority queues. + + * The implementation is *functional* rather than *imperative*. This + means that operations like `inserting' an association in a tree do + not destroy the old tree, in much the same way that `(+ 1 x)' + modifies neither the constant 1 nor the value bound to `x'. The + trees are referentially transparent thus the programmer need not + worry about copying the trees. Referential transparency allows + space efficiency to be achieved by sharing subtrees. + + These features make weight-balanced trees suitable for a wide range of +applications, especially those that require large numbers of sets or +discrete maps. Applications that have a few global databases and/or +concentrate on element-level operations like insertion and lookup are +probably better off using hash-tables or red-black trees. + + The *size* of a tree is the number of associations that it contains. +Weight balanced binary trees are balanced to keep the sizes of the +subtrees of each node within a constant factor of each other. This +ensures logarithmic times for single-path operations (like lookup and +insertion). A weight balanced tree takes space that is proportional to +the number of associations in the tree. For the current +implementation, the constant of proportionality is six words per +association. + + Weight balanced trees can be used as an implementation for either +discrete sets or discrete maps (associations). Sets are implemented by +ignoring the datum that is associated with the key. Under this scheme +if an associations exists in the tree this indicates that the key of the +association is a member of the set. Typically a value such as `()', +`#t' or `#f' is associated with the key. + + Many operations can be viewed as computing a result that, depending on +whether the tree arguments are thought of as sets or maps, is known by +two different names. An example is `wt-tree/member?', which, when +regarding the tree argument as a set, computes the set membership +operation, but, when regarding the tree as a discrete map, +`wt-tree/member?' is the predicate testing if the map is defined at an +element in its domain. Most names in this package have been chosen +based on interpreting the trees as sets, hence the name +`wt-tree/member?' rather than `wt-tree/defined-at?'. + + The weight balanced tree implementation is a run-time-loadable option. +To use weight balanced trees, execute + + (load-option 'wt-tree) + +once before calling any of the procedures defined here. + +* Menu: + +* Construction of Weight-Balanced Trees:: +* Basic Operations on Weight-Balanced Trees:: +* Advanced Operations on Weight-Balanced Trees:: +* Indexing Operations on Weight-Balanced Trees:: + + +File: slib.info, Node: Construction of Weight-Balanced Trees, Next: Basic Operations on Weight-Balanced Trees, Prev: Weight-Balanced Trees, Up: Weight-Balanced Trees + +Construction of Weight-Balanced Trees +------------------------------------- + + Binary trees require there to be a total order on the keys used to +arrange the elements in the tree. Weight balanced trees are organized +by *types*, where the type is an object encapsulating the ordering +relation. Creating a tree is a two-stage process. First a tree type +must be created from the predicate which gives the ordering. The tree +type is then used for making trees, either empty or singleton trees or +trees from other aggregate structures like association lists. Once +created, a tree `knows' its type and the type is used to test +compatibility between trees in operations taking two trees. Usually a +small number of tree types are created at the beginning of a program and +used many times throughout the program's execution. + + - procedure+: make-wt-tree-type KEY<? + This procedure creates and returns a new tree type based on the + ordering predicate KEY<?. KEY<? must be a total ordering, having + the property that for all key values `a', `b' and `c': + + (key<? a a) => #f + (and (key<? a b) (key<? b a)) => #f + (if (and (key<? a b) (key<? b c)) + (key<? a c) + #t) => #t + + Two key values are assumed to be equal if neither is less than the + other by KEY<?. + + Each call to `make-wt-tree-type' returns a distinct value, and + trees are only compatible if their tree types are `eq?'. A + consequence is that trees that are intended to be used in binary + tree operations must all be created with a tree type originating + from the same call to `make-wt-tree-type'. + + - variable+: number-wt-type + A standard tree type for trees with numeric keys. `Number-wt-type' + could have been defined by + + (define number-wt-type (make-wt-tree-type <)) + + - variable+: string-wt-type + A standard tree type for trees with string keys. `String-wt-type' + could have been defined by + + (define string-wt-type (make-wt-tree-type string<?)) + + - procedure+: make-wt-tree WT-TREE-TYPE + This procedure creates and returns a newly allocated weight + balanced tree. The tree is empty, i.e. it contains no + associations. WT-TREE-TYPE is a weight balanced tree type + obtained by calling `make-wt-tree-type'; the returned tree has + this type. + + - procedure+: singleton-wt-tree WT-TREE-TYPE KEY DATUM + This procedure creates and returns a newly allocated weight + balanced tree. The tree contains a single association, that of + DATUM with KEY. WT-TREE-TYPE is a weight balanced tree type + obtained by calling `make-wt-tree-type'; the returned tree has + this type. + + - procedure+: alist->wt-tree TREE-TYPE ALIST + Returns a newly allocated weight-balanced tree that contains the + same associations as ALIST. This procedure is equivalent to: + + (lambda (type alist) + (let ((tree (make-wt-tree type))) + (for-each (lambda (association) + (wt-tree/add! tree + (car association) + (cdr association))) + alist) + tree)) + + +File: slib.info, Node: Basic Operations on Weight-Balanced Trees, Next: Advanced Operations on Weight-Balanced Trees, Prev: Construction of Weight-Balanced Trees, Up: Weight-Balanced Trees + +Basic Operations on Weight-Balanced Trees +----------------------------------------- + + This section describes the basic tree operations on weight balanced +trees. These operations are the usual tree operations for insertion, +deletion and lookup, some predicates and a procedure for determining the +number of associations in a tree. + + - procedure+: wt-tree? OBJECT + Returns `#t' if OBJECT is a weight-balanced tree, otherwise + returns `#f'. + + - procedure+: wt-tree/empty? WT-TREE + Returns `#t' if WT-TREE contains no associations, otherwise + returns `#f'. + + - procedure+: wt-tree/size WT-TREE + Returns the number of associations in WT-TREE, an exact + non-negative integer. This operation takes constant time. + + - procedure+: wt-tree/add WT-TREE KEY DATUM + Returns a new tree containing all the associations in WT-TREE and + the association of DATUM with KEY. If WT-TREE already had an + association for KEY, the new association overrides the old. The + average and worst-case times required by this operation are + proportional to the logarithm of the number of associations in + WT-TREE. + + - procedure+: wt-tree/add! WT-TREE KEY DATUM + Associates DATUM with KEY in WT-TREE and returns an unspecified + value. If WT-TREE already has an association for KEY, that + association is replaced. The average and worst-case times + required by this operation are proportional to the logarithm of + the number of associations in WT-TREE. + + - procedure+: wt-tree/member? KEY WT-TREE + Returns `#t' if WT-TREE contains an association for KEY, otherwise + returns `#f'. The average and worst-case times required by this + operation are proportional to the logarithm of the number of + associations in WT-TREE. + + - procedure+: wt-tree/lookup WT-TREE KEY DEFAULT + Returns the datum associated with KEY in WT-TREE. If WT-TREE + doesn't contain an association for KEY, DEFAULT is returned. The + average and worst-case times required by this operation are + proportional to the logarithm of the number of associations in + WT-TREE. + + - procedure+: wt-tree/delete WT-TREE KEY + Returns a new tree containing all the associations in WT-TREE, + except that if WT-TREE contains an association for KEY, it is + removed from the result. The average and worst-case times required + by this operation are proportional to the logarithm of the number + of associations in WT-TREE. + + - procedure+: wt-tree/delete! WT-TREE KEY + If WT-TREE contains an association for KEY the association is + removed. Returns an unspecified value. The average and worst-case + times required by this operation are proportional to the logarithm + of the number of associations in WT-TREE. + + +File: slib.info, Node: Advanced Operations on Weight-Balanced Trees, Next: Indexing Operations on Weight-Balanced Trees, Prev: Basic Operations on Weight-Balanced Trees, Up: Weight-Balanced Trees + +Advanced Operations on Weight-Balanced Trees +-------------------------------------------- + + In the following the *size* of a tree is the number of associations +that the tree contains, and a *smaller* tree contains fewer +associations. + + - procedure+: wt-tree/split< WT-TREE BOUND + Returns a new tree containing all and only the associations in + WT-TREE which have a key that is less than BOUND in the ordering + relation of the tree type of WT-TREE. The average and worst-case + times required by this operation are proportional to the logarithm + of the size of WT-TREE. + + - procedure+: wt-tree/split> WT-TREE BOUND + Returns a new tree containing all and only the associations in + WT-TREE which have a key that is greater than BOUND in the + ordering relation of the tree type of WT-TREE. The average and + worst-case times required by this operation are proportional to the + logarithm of size of WT-TREE. + + - procedure+: wt-tree/union WT-TREE-1 WT-TREE-2 + Returns a new tree containing all the associations from both trees. + This operation is asymmetric: when both trees have an association + for the same key, the returned tree associates the datum from + WT-TREE-2 with the key. Thus if the trees are viewed as discrete + maps then `wt-tree/union' computes the map override of WT-TREE-1 by + WT-TREE-2. If the trees are viewed as sets the result is the set + union of the arguments. The worst-case time required by this + operation is proportional to the sum of the sizes of both trees. + If the minimum key of one tree is greater than the maximum key of + the other tree then the time required is at worst proportional to + the logarithm of the size of the larger tree. + + - procedure+: wt-tree/intersection WT-TREE-1 WT-TREE-2 + Returns a new tree containing all and only those associations from + WT-TREE-1 which have keys appearing as the key of an association + in WT-TREE-2. Thus the associated data in the result are those + from WT-TREE-1. If the trees are being used as sets the result is + the set intersection of the arguments. As a discrete map + operation, `wt-tree/intersection' computes the domain restriction + of WT-TREE-1 to (the domain of) WT-TREE-2. The time required by + this operation is never worse that proportional to the sum of the + sizes of the trees. + + - procedure+: wt-tree/difference WT-TREE-1 WT-TREE-2 + Returns a new tree containing all and only those associations from + WT-TREE-1 which have keys that *do not* appear as the key of an + association in WT-TREE-2. If the trees are viewed as sets the + result is the asymmetric set difference of the arguments. As a + discrete map operation, it computes the domain restriction of + WT-TREE-1 to the complement of (the domain of) WT-TREE-2. The + time required by this operation is never worse that proportional to + the sum of the sizes of the trees. + + - procedure+: wt-tree/subset? WT-TREE-1 WT-TREE-2 + Returns `#t' iff the key of each association in WT-TREE-1 is the + key of some association in WT-TREE-2, otherwise returns `#f'. + Viewed as a set operation, `wt-tree/subset?' is the improper subset + predicate. A proper subset predicate can be constructed: + + (define (proper-subset? s1 s2) + (and (wt-tree/subset? s1 s2) + (< (wt-tree/size s1) (wt-tree/size s2)))) + + As a discrete map operation, `wt-tree/subset?' is the subset test + on the domain(s) of the map(s). In the worst-case the time + required by this operation is proportional to the size of + WT-TREE-1. + + - procedure+: wt-tree/set-equal? WT-TREE-1 WT-TREE-2 + Returns `#t' iff for every association in WT-TREE-1 there is an + association in WT-TREE-2 that has the same key, and *vice versa*. + + Viewing the arguments as sets `wt-tree/set-equal?' is the set + equality predicate. As a map operation it determines if two maps + are defined on the same domain. + + This procedure is equivalent to + + (lambda (wt-tree-1 wt-tree-2) + (and (wt-tree/subset? wt-tree-1 wt-tree-2 + (wt-tree/subset? wt-tree-2 wt-tree-1))) + + In the worst-case the time required by this operation is + proportional to the size of the smaller tree. + + - procedure+: wt-tree/fold COMBINER INITIAL WT-TREE + This procedure reduces WT-TREE by combining all the associations, + using an reverse in-order traversal, so the associations are + visited in reverse order. COMBINER is a procedure of three + arguments: a key, a datum and the accumulated result so far. + Provided COMBINER takes time bounded by a constant, `wt-tree/fold' + takes time proportional to the size of WT-TREE. + + A sorted association list can be derived simply: + + (wt-tree/fold (lambda (key datum list) + (cons (cons key datum) list)) + '() + WT-TREE)) + + The data in the associations can be summed like this: + + (wt-tree/fold (lambda (key datum sum) (+ sum datum)) + 0 + WT-TREE) + + - procedure+: wt-tree/for-each ACTION WT-TREE + This procedure traverses the tree in-order, applying ACTION to + each association. The associations are processed in increasing + order of their keys. ACTION is a procedure of two arguments which + take the key and datum respectively of the association. Provided + ACTION takes time bounded by a constant, `wt-tree/for-each' takes + time proportional to in the size of WT-TREE. The example prints + the tree: + + (wt-tree/for-each (lambda (key value) + (display (list key value))) + WT-TREE)) + + +File: slib.info, Node: Indexing Operations on Weight-Balanced Trees, Prev: Advanced Operations on Weight-Balanced Trees, Up: Weight-Balanced Trees + +Indexing Operations on Weight-Balanced Trees +-------------------------------------------- + + Weight balanced trees support operations that view the tree as sorted +sequence of associations. Elements of the sequence can be accessed by +position, and the position of an element in the sequence can be +determined, both in logarthmic time. + + - procedure+: wt-tree/index WT-TREE INDEX + - procedure+: wt-tree/index-datum WT-TREE INDEX + - procedure+: wt-tree/index-pair WT-TREE INDEX + Returns the 0-based INDEXth association of WT-TREE in the sorted + sequence under the tree's ordering relation on the keys. + `wt-tree/index' returns the INDEXth key, `wt-tree/index-datum' + returns the datum associated with the INDEXth key and + `wt-tree/index-pair' returns a new pair `(KEY . DATUM)' which is + the `cons' of the INDEXth key and its datum. The average and + worst-case times required by this operation are proportional to + the logarithm of the number of associations in the tree. + + These operations signal an error if the tree is empty, if + INDEX`<0', or if INDEX is greater than or equal to the number of + associations in the tree. + + Indexing can be used to find the median and maximum keys in the + tree as follows: + + median: (wt-tree/index WT-TREE + (quotient (wt-tree/size WT-TREE) 2)) + + maximum: (wt-tree/index WT-TREE + (-1+ (wt-tree/size WT-TREE))) + + - procedure+: wt-tree/rank WT-TREE KEY + Determines the 0-based position of KEY in the sorted sequence of + the keys under the tree's ordering relation, or `#f' if the tree + has no association with for KEY. This procedure returns either an + exact non-negative integer or `#f'. The average and worst-case + times required by this operation are proportional to the logarithm + of the number of associations in the tree. + + - procedure+: wt-tree/min WT-TREE + - procedure+: wt-tree/min-datum WT-TREE + - procedure+: wt-tree/min-pair WT-TREE + Returns the association of WT-TREE that has the least key under + the tree's ordering relation. `wt-tree/min' returns the least key, + `wt-tree/min-datum' returns the datum associated with the least key + and `wt-tree/min-pair' returns a new pair `(key . datum)' which is + the `cons' of the minimum key and its datum. The average and + worst-case times required by this operation are proportional to the + logarithm of the number of associations in the tree. + + These operations signal an error if the tree is empty. They could + be written + (define (wt-tree/min tree) (wt-tree/index tree 0)) + (define (wt-tree/min-datum tree) (wt-tree/index-datum tree 0)) + (define (wt-tree/min-pair tree) (wt-tree/index-pair tree 0)) + + - procedure+: wt-tree/delete-min WT-TREE + Returns a new tree containing all of the associations in WT-TREE + except the association with the least key under the WT-TREE's + ordering relation. An error is signalled if the tree is empty. + The average and worst-case times required by this operation are + proportional to the logarithm of the number of associations in the + tree. This operation is equivalent to + + (wt-tree/delete WT-TREE (wt-tree/min WT-TREE)) + + - procedure+: wt-tree/delete-min! WT-TREE + Removes the association with the least key under the WT-TREE's + ordering relation. An error is signalled if the tree is empty. + The average and worst-case times required by this operation are + proportional to the logarithm of the number of associations in the + tree. This operation is equivalent to + + (wt-tree/delete! WT-TREE (wt-tree/min WT-TREE)) + + +File: slib.info, Node: Other Packages, Next: About SLIB, Prev: Database Packages, Up: Top + +Other Packages +************** + +* Menu: + +* Data Structures:: Various data structures. +* Procedures:: Miscellaneous utility procedures. +* Standards Support:: Support for Scheme Standards. +* Session Support:: REPL and Debugging. +* Extra-SLIB Packages:: + + +File: slib.info, Node: Data Structures, Next: Procedures, Prev: Other Packages, Up: Other Packages + +Data Structures +=============== + +* Menu: + +* Arrays:: 'array +* Array Mapping:: 'array-for-each +* Association Lists:: 'alist +* Byte:: 'byte +* Collections:: 'collect +* Dynamic Data Type:: 'dynamic +* Hash Tables:: 'hash-table +* Hashing:: 'hash, 'sierpinski, 'soundex +* Object:: 'object +* Priority Queues:: 'priority-queue +* Queues:: 'queue +* Records:: 'record +* Structures:: 'struct, 'structure + + +File: slib.info, Node: Arrays, Next: Array Mapping, Prev: Data Structures, Up: Data Structures + +Arrays +------ + + `(require 'array)' + + - Function: array? OBJ + Returns `#t' if the OBJ is an array, and `#f' if not. + + - Function: make-array INITIAL-VALUE BOUND1 BOUND2 ... + Creates and returns an array that has as many dimensins as there + are BOUNDs and fills it with INITIAL-VALUE. + + When constructing an array, BOUND is either an inclusive range of +indices expressed as a two element list, or an upper bound expressed as +a single integer. So + (make-array 'foo 3 3) == (make-array 'foo '(0 2) '(0 2)) + + - Function: make-shared-array ARRAY MAPPER BOUND1 BOUND2 ... + `make-shared-array' can be used to create shared subarrays of other + arrays. The MAPPER is a function that translates coordinates in + the new array into coordinates in the old array. A MAPPER must be + linear, and its range must stay within the bounds of the old + array, but it can be otherwise arbitrary. A simple example: + (define fred (make-array #f 8 8)) + (define freds-diagonal + (make-shared-array fred (lambda (i) (list i i)) 8)) + (array-set! freds-diagonal 'foo 3) + (array-ref fred 3 3) + => FOO + (define freds-center + (make-shared-array fred (lambda (i j) (list (+ 3 i) (+ 3 j))) + 2 2)) + (array-ref freds-center 0 0) + => FOO + + - Function: array-rank OBJ + Returns the number of dimensions of OBJ. If OBJ is not an array, + 0 is returned. + + - Function: array-shape ARRAY + `array-shape' returns a list of inclusive bounds. So: + (array-shape (make-array 'foo 3 5)) + => ((0 2) (0 4)) + + - Function: array-dimensions ARRAY + `array-dimensions' is similar to `array-shape' but replaces + elements with a 0 minimum with one greater than the maximum. So: + (array-dimensions (make-array 'foo 3 5)) + => (3 5) + + - Procedure: array-in-bounds? ARRAY INDEX1 INDEX2 ... + Returns `#t' if its arguments would be acceptable to `array-ref'. + + - Function: array-ref ARRAY INDEX1 INDEX2 ... + Returns the element at the `(INDEX1, INDEX2)' element in ARRAY. + + - Procedure: array-set! ARRAY NEW-VALUE INDEX1 INDEX2 ... + + - Function: array-1d-ref ARRAY INDEX + - Function: array-2d-ref ARRAY INDEX1 INDEX2 + - Function: array-3d-ref ARRAY INDEX1 INDEX2 INDEX3 + + - Procedure: array-1d-set! ARRAY NEW-VALUE INDEX + - Procedure: array-2d-set! ARRAY NEW-VALUE INDEX1 INDEX2 + - Procedure: array-3d-set! ARRAY NEW-VALUE INDEX1 INDEX2 INDEX3 + + The functions are just fast versions of `array-ref' and `array-set!' +that take a fixed number of arguments, and perform no bounds checking. + + If you comment out the bounds checking code, this is about as +efficient as you could ask for without help from the compiler. + + An exercise left to the reader: implement the rest of APL. + + +File: slib.info, Node: Array Mapping, Next: Association Lists, Prev: Arrays, Up: Data Structures + +Array Mapping +------------- + + `(require 'array-for-each)' + + - Function: array-map! ARRAY0 PROC ARRAY1 ... + ARRAY1, ... must have the same number of dimensions as ARRAY0 and + have a range for each index which includes the range for the + corresponding index in ARRAY0. PROC is applied to each tuple of + elements of ARRAY1 ... and the result is stored as the + corresponding element in ARRAY0. The value returned is + unspecified. The order of application is unspecified. + + - Function: array-for-each PROC ARRAY0 ... + PROC is applied to each tuple of elements of ARRAY0 ... in + row-major order. The value returned is unspecified. + + - Function: array-indexes ARRAY + Returns an array of lists of indexes for ARRAY such that, if LI is + a list of indexes for which ARRAY is defined, (equal? LI (apply + array-ref (array-indexes ARRAY) LI)). + + - Function: array-index-map! ARRAY PROC + applies PROC to the indices of each element of ARRAY in turn, + storing the result in the corresponding element. The value + returned and the order of application are unspecified. + + One can implement ARRAY-INDEXES as + (define (array-indexes array) + (let ((ra (apply make-array #f (array-shape array)))) + (array-index-map! ra (lambda x x)) + ra)) + Another example: + (define (apl:index-generator n) + (let ((v (make-uniform-vector n 1))) + (array-index-map! v (lambda (i) i)) + v)) + + - Function: array-copy! SOURCE DESTINATION + Copies every element from vector or array SOURCE to the + corresponding element of DESTINATION. DESTINATION must have the + same rank as SOURCE, and be at least as large in each dimension. + The order of copying is unspecified. + + +File: slib.info, Node: Association Lists, Next: Byte, Prev: Array Mapping, Up: Data Structures + +Association Lists +----------------- + + `(require 'alist)' + + Alist functions provide utilities for treating a list of key-value +pairs as an associative database. These functions take an equality +predicate, PRED, as an argument. This predicate should be repeatable, +symmetric, and transitive. + + Alist functions can be used with a secondary index method such as hash +tables for improved performance. + + - Function: predicate->asso PRED + Returns an "association function" (like `assq', `assv', or + `assoc') corresponding to PRED. The returned function returns a + key-value pair whose key is `pred'-equal to its first argument or + `#f' if no key in the alist is PRED-equal to the first argument. + + - Function: alist-inquirer PRED + Returns a procedure of 2 arguments, ALIST and KEY, which returns + the value associated with KEY in ALIST or `#f' if KEY does not + appear in ALIST. + + - Function: alist-associator PRED + Returns a procedure of 3 arguments, ALIST, KEY, and VALUE, which + returns an alist with KEY and VALUE associated. Any previous + value associated with KEY will be lost. This returned procedure + may or may not have side effects on its ALIST argument. An + example of correct usage is: + (define put (alist-associator string-ci=?)) + (define alist '()) + (set! alist (put alist "Foo" 9)) + + - Function: alist-remover PRED + Returns a procedure of 2 arguments, ALIST and KEY, which returns + an alist with an association whose KEY is key removed. This + returned procedure may or may not have side effects on its ALIST + argument. An example of correct usage is: + (define rem (alist-remover string-ci=?)) + (set! alist (rem alist "foo")) + + - Function: alist-map PROC ALIST + Returns a new association list formed by mapping PROC over the + keys and values of ALIST. PROC must be a function of 2 arguments + which returns the new value part. + + - Function: alist-for-each PROC ALIST + Applies PROC to each pair of keys and values of ALIST. PROC must + be a function of 2 arguments. The returned value is unspecified. + + +File: slib.info, Node: Byte, Next: Collections, Prev: Association Lists, Up: Data Structures + +Byte +---- + + `(require 'byte)' + + Some algorithms are expressed in terms of arrays of small integers. +Using Scheme strings to implement these arrays is not portable vis-a-vis +the correspondence between integers and characters and non-ascii +character sets. These functions abstract the notion of a "byte". + + - Function: byte-ref BYTES K + K must be a valid index of BYTES. `byte-ref' returns byte K of + BYTES using zero-origin indexing. + + - Procedure: byte-set! BYTES K BYTE + K must be a valid index of BYTES%, and BYTE must be a small + integer. `Byte-set!' stores BYTE in element K of BYTES and + returns an unspecified value. + + - Function: make-bytes K + - Function: make-bytes K BYTE + `Make-bytes' returns a newly allocated byte-array of length K. If + BYTE is given, then all elements of the byte-array are initialized + to BYTE, otherwise the contents of the byte-array are unspecified. + + + - Function: bytes-length BYTES + `bytes-length' returns length of byte-array BYTES. + + + - Function: write-byte BYTE + - Function: write-byte BYTE PORT + Writes the byte BYTE (not an external representation of the byte) + to the given PORT and returns an unspecified value. The PORT + argument may be omitted, in which case it defaults to the value + returned by `current-output-port'. + + + - Function: read-byte + - Function: read-byte PORT + Returns the next byte available from the input PORT, updating the + PORT to point to the following byte. If no more bytes are + available, an end of file object is returned. PORT may be + omitted, in which case it defaults to the value returned by + `current-input-port'. + + + - Function: bytes BYTE ... + Returns a newly allocated byte-array composed of the arguments. + + + - Function: bytes->list BYTES + - Function: list->bytes BYTES + `Bytes->list' returns a newly allocated list of the bytes that + make up the given byte-array. `List->bytes' returns a newly + allocated byte-array formed from the small integers in the list + BYTES. `Bytes->list' and `list->bytes' are inverses so far as + `equal?' is concerned. + + + +File: slib.info, Node: Collections, Next: Dynamic Data Type, Prev: Byte, Up: Data Structures + +Collections +----------- + + `(require 'collect)' + + Routines for managing collections. Collections are aggregate data +structures supporting iteration over their elements, similar to the +Dylan(TM) language, but with a different interface. They have +"elements" indexed by corresponding "keys", although the keys may be +implicit (as with lists). + + New types of collections may be defined as YASOS objects (*note +Yasos::.). They must support the following operations: + * `(collection? SELF)' (always returns `#t'); + + * `(size SELF)' returns the number of elements in the collection; + + * `(print SELF PORT)' is a specialized print operation for the + collection which prints a suitable representation on the given + PORT or returns it as a string if PORT is `#t'; + + * `(gen-elts SELF)' returns a thunk which on successive invocations + yields elements of SELF in order or gives an error if it is + invoked more than `(size SELF)' times; + + * `(gen-keys SELF)' is like `gen-elts', but yields the collection's + keys in order. + + They might support specialized `for-each-key' and `for-each-elt' +operations. + + - Function: collection? OBJ + A predicate, true initially of lists, vectors and strings. New + sorts of collections must answer `#t' to `collection?'. + + - Procedure: map-elts PROC . COLLECTIONS + - Procedure: do-elts PROC . COLLECTIONS + PROC is a procedure taking as many arguments as there are + COLLECTIONS (at least one). The COLLECTIONS are iterated over in + their natural order and PROC is applied to the elements yielded by + each iteration in turn. The order in which the arguments are + supplied corresponds to te order in which the COLLECTIONS appear. + `do-elts' is used when only side-effects of PROC are of interest + and its return value is unspecified. `map-elts' returns a + collection (actually a vector) of the results of the applications + of PROC. + + Example: + (map-elts + (list 1 2 3) (vector 1 2 3)) + => #(2 4 6) + + - Procedure: map-keys PROC . COLLECTIONS + - Procedure: do-keys PROC . COLLECTIONS + These are analogous to `map-elts' and `do-elts', but each + iteration is over the COLLECTIONS' *keys* rather than their + elements. + + Example: + (map-keys + (list 1 2 3) (vector 1 2 3)) + => #(0 2 4) + + - Procedure: for-each-key COLLECTION PROC + - Procedure: for-each-elt COLLECTION PROC + These are like `do-keys' and `do-elts' but only for a single + collection; they are potentially more efficient. + + - Function: reduce PROC SEED . COLLECTIONS + A generalization of the list-based `comlist:reduce-init' (*note + Lists as sequences::.) to collections which will shadow the + list-based version if `(require 'collect)' follows `(require + 'common-list-functions)' (*note Common List Functions::.). + + Examples: + (reduce + 0 (vector 1 2 3)) + => 6 + (reduce union '() '((a b c) (b c d) (d a))) + => (c b d a). + + - Function: any? PRED . COLLECTIONS + A generalization of the list-based `some' (*note Lists as + sequences::.) to collections. + + Example: + (any? odd? (list 2 3 4 5)) + => #t + + - Function: every? PRED . COLLECTIONS + A generalization of the list-based `every' (*note Lists as + sequences::.) to collections. + + Example: + (every? collection? '((1 2) #(1 2))) + => #t + + - Function: empty? COLLECTION + Returns `#t' iff there are no elements in COLLECTION. + + `(empty? COLLECTION) == (zero? (size COLLECTION))' + + - Function: size COLLECTION + Returns the number of elements in COLLECTION. + + - Function: Setter LIST-REF + See *Note Setters:: for a definition of "setter". N.B. `(setter + list-ref)' doesn't work properly for element 0 of a list. + + Here is a sample collection: `simple-table' which is also a `table'. + (define-predicate TABLE?) + (define-operation (LOOKUP table key failure-object)) + (define-operation (ASSOCIATE! table key value)) ;; returns key + (define-operation (REMOVE! table key)) ;; returns value + + (define (MAKE-SIMPLE-TABLE) + (let ( (table (list)) ) + (object + ;; table behaviors + ((TABLE? self) #t) + ((SIZE self) (size table)) + ((PRINT self port) (format port "#<SIMPLE-TABLE>")) + ((LOOKUP self key failure-object) + (cond + ((assq key table) => cdr) + (else failure-object) + )) + ((ASSOCIATE! self key value) + (cond + ((assq key table) + => (lambda (bucket) (set-cdr! bucket value) key)) + (else + (set! table (cons (cons key value) table)) + key) + )) + ((REMOVE! self key);; returns old value + (cond + ((null? table) (slib:error "TABLE:REMOVE! Key not found: " key)) + ((eq? key (caar table)) + (let ( (value (cdar table)) ) + (set! table (cdr table)) + value) + ) + (else + (let loop ( (last table) (this (cdr table)) ) + (cond + ((null? this) + (slib:error "TABLE:REMOVE! Key not found: " key)) + ((eq? key (caar this)) + (let ( (value (cdar this)) ) + (set-cdr! last (cdr this)) + value) + ) + (else + (loop (cdr last) (cdr this))) + ) ) ) + )) + ;; collection behaviors + ((COLLECTION? self) #t) + ((GEN-KEYS self) (collect:list-gen-elts (map car table))) + ((GEN-ELTS self) (collect:list-gen-elts (map cdr table))) + ((FOR-EACH-KEY self proc) + (for-each (lambda (bucket) (proc (car bucket))) table) + ) + ((FOR-EACH-ELT self proc) + (for-each (lambda (bucket) (proc (cdr bucket))) table) + ) + ) ) ) + + +File: slib.info, Node: Dynamic Data Type, Next: Hash Tables, Prev: Collections, Up: Data Structures + +Dynamic Data Type +----------------- + + `(require 'dynamic)' + + - Function: make-dynamic OBJ + Create and returns a new "dynamic" whose global value is OBJ. + + - Function: dynamic? OBJ + Returns true if and only if OBJ is a dynamic. No object + satisfying `dynamic?' satisfies any of the other standard type + predicates. + + - Function: dynamic-ref DYN + Return the value of the given dynamic in the current dynamic + environment. + + - Procedure: dynamic-set! DYN OBJ + Change the value of the given dynamic to OBJ in the current + dynamic environment. The returned value is unspecified. + + - Function: call-with-dynamic-binding DYN OBJ THUNK + Invoke and return the value of the given thunk in a new, nested + dynamic environment in which the given dynamic has been bound to a + new location whose initial contents are the value OBJ. This + dynamic environment has precisely the same extent as the + invocation of the thunk and is thus captured by continuations + created within that invocation and re-established by those + continuations when they are invoked. + + The `dynamic-bind' macro is not implemented. + + +File: slib.info, Node: Hash Tables, Next: Hashing, Prev: Dynamic Data Type, Up: Data Structures + +Hash Tables +----------- + + `(require 'hash-table)' + + - Function: predicate->hash PRED + Returns a hash function (like `hashq', `hashv', or `hash') + corresponding to the equality predicate PRED. PRED should be + `eq?', `eqv?', `equal?', `=', `char=?', `char-ci=?', `string=?', or + `string-ci=?'. + + A hash table is a vector of association lists. + + - Function: make-hash-table K + Returns a vector of K empty (association) lists. + + Hash table functions provide utilities for an associative database. +These functions take an equality predicate, PRED, as an argument. PRED +should be `eq?', `eqv?', `equal?', `=', `char=?', `char-ci=?', +`string=?', or `string-ci=?'. + + - Function: predicate->hash-asso PRED + Returns a hash association function of 2 arguments, KEY and + HASHTAB, corresponding to PRED. The returned function returns a + key-value pair whose key is PRED-equal to its first argument or + `#f' if no key in HASHTAB is PRED-equal to the first argument. + + - Function: hash-inquirer PRED + Returns a procedure of 3 arguments, `hashtab' and `key', which + returns the value associated with `key' in `hashtab' or `#f' if + key does not appear in `hashtab'. + + - Function: hash-associator PRED + Returns a procedure of 3 arguments, HASHTAB, KEY, and VALUE, which + modifies HASHTAB so that KEY and VALUE associated. Any previous + value associated with KEY will be lost. + + - Function: hash-remover PRED + Returns a procedure of 2 arguments, HASHTAB and KEY, which + modifies HASHTAB so that the association whose key is KEY is + removed. + + - Function: hash-map PROC HASH-TABLE + Returns a new hash table formed by mapping PROC over the keys and + values of HASH-TABLE. PROC must be a function of 2 arguments + which returns the new value part. + + - Function: hash-for-each PROC HASH-TABLE + Applies PROC to each pair of keys and values of HASH-TABLE. PROC + must be a function of 2 arguments. The returned value is + unspecified. + + +File: slib.info, Node: Hashing, Next: Object, Prev: Hash Tables, Up: Data Structures + +Hashing +------- + + `(require 'hash)' + + These hashing functions are for use in quickly classifying objects. +Hash tables use these functions. + + - Function: hashq OBJ K + - Function: hashv OBJ K + - Function: hash OBJ K + Returns an exact non-negative integer less than K. For each + non-negative integer less than K there are arguments OBJ for which + the hashing functions applied to OBJ and K returns that integer. + + For `hashq', `(eq? obj1 obj2)' implies `(= (hashq obj1 k) (hashq + obj2))'. + + For `hashv', `(eqv? obj1 obj2)' implies `(= (hashv obj1 k) (hashv + obj2))'. + + For `hash', `(equal? obj1 obj2)' implies `(= (hash obj1 k) (hash + obj2))'. + + `hash', `hashv', and `hashq' return in time bounded by a constant. + Notice that items having the same `hash' implies the items have + the same `hashv' implies the items have the same `hashq'. + + `(require 'sierpinski)' + + - Function: make-sierpinski-indexer MAX-COORDINATE + Returns a procedure (eg hash-function) of 2 numeric arguments which + preserves *nearness* in its mapping from NxN to N. + + MAX-COORDINATE is the maximum coordinate (a positive integer) of a + population of points. The returned procedures is a function that + takes the x and y coordinates of a point, (non-negative integers) + and returns an integer corresponding to the relative position of + that point along a Sierpinski curve. (You can think of this as + computing a (pseudo-) inverse of the Sierpinski spacefilling + curve.) + + Example use: Make an indexer (hash-function) for integer points + lying in square of integer grid points [0,99]x[0,99]: + (define space-key (make-sierpinski-indexer 100)) + Now let's compute the index of some points: + (space-key 24 78) => 9206 + (space-key 23 80) => 9172 + + Note that locations (24, 78) and (23, 80) are near in index and + therefore, because the Sierpinski spacefilling curve is + continuous, we know they must also be near in the plane. Nearness + in the plane does not, however, necessarily correspond to nearness + in index, although it *tends* to be so. + + Example applications: + * Sort points by Sierpinski index to get heuristic solution to + *travelling salesman problem*. For details of performance, + see L. Platzman and J. Bartholdi, "Spacefilling curves and the + Euclidean travelling salesman problem", JACM 36(4):719-737 + (October 1989) and references therein. + + * Use Sierpinski index as key by which to store 2-dimensional + data in a 1-dimensional data structure (such as a table). + Then locations that are near each other in 2-d space will + tend to be near each other in 1-d data structure; and + locations that are near in 1-d data structure will be near in + 2-d space. This can significantly speed retrieval from + secondary storage because contiguous regions in the plane + will tend to correspond to contiguous regions in secondary + storage. (This is a standard technique for managing CAD/CAM + or geographic data.) + + + `(require 'soundex)' + + - Function: soundex NAME + Computes the *soundex* hash of NAME. Returns a string of an + initial letter and up to three digits between 0 and 6. Soundex + supposedly has the property that names that sound similar in normal + English pronunciation tend to map to the same key. + + Soundex was a classic algorithm used for manual filing of personal + records before the advent of computers. It performs adequately for + English names but has trouble with other nationalities. + + See Knuth, Vol. 3 `Sorting and searching', pp 391-2 + + To manage unusual inputs, `soundex' omits all non-alphabetic + characters. Consequently, in this implementation: + + (soundex <string of blanks>) => "" + (soundex "") => "" + + Examples from Knuth: + + (map soundex '("Euler" "Gauss" "Hilbert" "Knuth" + "Lloyd" "Lukasiewicz")) + => ("E460" "G200" "H416" "K530" "L300" "L222") + + (map soundex '("Ellery" "Ghosh" "Heilbronn" "Kant" + "Ladd" "Lissajous")) + => ("E460" "G200" "H416" "K530" "L300" "L222") + + Some cases in which the algorithm fails (Knuth): + + (map soundex '("Rogers" "Rodgers")) => ("R262" "R326") + + (map soundex '("Sinclair" "St. Clair")) => ("S524" "S324") + + (map soundex '("Tchebysheff" "Chebyshev")) => ("T212" "C121") + + +File: slib.info, Node: Object, Next: Priority Queues, Prev: Hashing, Up: Data Structures + +Macroless Object System +----------------------- + + `(require 'object)' + + This is the Macroless Object System written by Wade Humeniuk +(whumeniu@datap.ca). Conceptual Tributes: *Note Yasos::, MacScheme's +%object, CLOS, Lack of R4RS macros. + +Concepts +-------- + +OBJECT + An object is an ordered association-list (by `eq?') of methods + (procedures). Methods can be added (`make-method!'), deleted + (`unmake-method!') and retrieved (`get-method'). Objects may + inherit methods from other objects. The object binds to the + environment it was created in, allowing closures to be used to + hide private procedures and data. + +GENERIC-METHOD + A generic-method associates (in terms of `eq?') object's method. + This allows scheme function style to be used for objects. The + calling scheme for using a generic method is `(generic-method + object param1 param2 ...)'. + +METHOD + A method is a procedure that exists in the object. To use a method + get-method must be called to look-up the method. Generic methods + implement the get-method functionality. Methods may be added to an + object associated with any scheme obj in terms of eq? + +GENERIC-PREDICATE + A generic method that returns a boolean value for any scheme obj. + +PREDICATE + A object's method asscociated with a generic-predicate. Returns + `#t'. + +Procedures +---------- + + - Function: make-object ANCESTOR ... + Returns an object. Current object implementation is a tagged + vector. ANCESTORs are optional and must be objects in terms of + object?. ANCESTORs methods are included in the object. Multiple + ANCESTORs might associate the same generic-method with a method. + In this case the method of the ANCESTOR first appearing in the + list is the one returned by `get-method'. + + - Function: object? OBJ + Returns boolean value whether OBJ was created by make-object. + + - Function: make-generic-method EXCEPTION-PROCEDURE + Returns a procedure which be associated with an object's methods. + If EXCEPTION-PROCEDURE is specified then it is used to process + non-objects. + + - Function: make-generic-predicate + Returns a boolean procedure for any scheme object. + + - Function: make-method! OBJECT GENERIC-METHOD METHOD + Associates METHOD to the GENERIC-METHOD in the object. The METHOD + overrides any previous association with the GENERIC-METHOD within + the object. Using `unmake-method!' will restore the object's + previous association with the GENERIC-METHOD. METHOD must be a + procedure. + + - Function: make-predicate! OBJECT GENERIC-PRECIATE + Makes a predicate method associated with the GENERIC-PREDICATE. + + - Function: unmake-method! OBJECT GENERIC-METHOD + Removes an object's association with a GENERIC-METHOD . + + - Function: get-method OBJECT GENERIC-METHOD + Returns the object's method associated (if any) with the + GENERIC-METHOD. If no associated method exists an error is + flagged. + +Examples +-------- + + (require 'object) + + (define instantiate (make-generic-method)) + + (define (make-instance-object . ancestors) + (define self (apply make-object + (map (lambda (obj) (instantiate obj)) ancestors))) + (make-method! self instantiate (lambda (self) self)) + self) + + (define who (make-generic-method)) + (define imigrate! (make-generic-method)) + (define emigrate! (make-generic-method)) + (define describe (make-generic-method)) + (define name (make-generic-method)) + (define address (make-generic-method)) + (define members (make-generic-method)) + + (define society + (let () + (define self (make-instance-object)) + (define population '()) + (make-method! self imigrate! + (lambda (new-person) + (if (not (eq? new-person self)) + (set! population (cons new-person population))))) + (make-method! self emigrate! + (lambda (person) + (if (not (eq? person self)) + (set! population + (comlist:remove-if (lambda (member) + (eq? member person)) + population))))) + (make-method! self describe + (lambda (self) + (map (lambda (person) (describe person)) population))) + (make-method! self who + (lambda (self) (map (lambda (person) (name person)) + population))) + (make-method! self members (lambda (self) population)) + self)) + + (define (make-person %name %address) + (define self (make-instance-object society)) + (make-method! self name (lambda (self) %name)) + (make-method! self address (lambda (self) %address)) + (make-method! self who (lambda (self) (name self))) + (make-method! self instantiate + (lambda (self) + (make-person (string-append (name self) "-son-of") + %address))) + (make-method! self describe + (lambda (self) (list (name self) (address self)))) + (imigrate! self) + self) + +Inverter Documentation +...................... + + Inheritance: + <inverter>::(<number> <description>) + Generic-methods + <inverter>::value => <number>::value + <inverter>::set-value! => <number>::set-value! + <inverter>::describe => <description>::describe + <inverter>::help + <inverter>::invert + <inverter>::inverter? + +Number Documention +.................. + + Inheritance + <number>::() + Slots + <number>::<x> + Generic Methods + <number>::value + <number>::set-value! + +Inverter code +............. + + (require 'object) + + (define value (make-generic-method (lambda (val) val))) + (define set-value! (make-generic-method)) + (define invert (make-generic-method + (lambda (val) + (if (number? val) + (/ 1 val) + (error "Method not supported:" val))))) + (define noop (make-generic-method)) + (define inverter? (make-generic-predicate)) + (define describe (make-generic-method)) + (define help (make-generic-method)) + + (define (make-number x) + (define self (make-object)) + (make-method! self value (lambda (this) x)) + (make-method! self set-value! + (lambda (this new-value) (set! x new-value))) + self) + + (define (make-description str) + (define self (make-object)) + (make-method! self describe (lambda (this) str)) + (make-method! self help (lambda (this) "Help not available")) + self) + + (define (make-inverter) + (let* ((self (make-object + (make-number 1) + (make-description "A number which can be inverted"))) + (<value> (get-method self value))) + (make-method! self invert (lambda (self) (/ 1 (<value> self)))) + (make-predicate! self inverter?) + (unmake-method! self help) + (make-method! self help + (lambda (self) + (display "Inverter Methods:") (newline) + (display " (value inverter) ==> n") (newline))) + self)) + + ;;;; Try it out + + (define invert! (make-generic-method)) + + (define x (make-inverter)) + + (make-method! x invert! (lambda (x) (set-value! x (/ 1 (value x))))) + + (value x) => 1 + (set-value! x 33) => undefined + (invert! x) => undefined + (value x) => 1/33 + + (unmake-method! x invert!) => undefined + + (invert! x) error--> ERROR: Method not supported: x + + +File: slib.info, Node: Priority Queues, Next: Queues, Prev: Object, Up: Data Structures + +Priority Queues +--------------- + + `(require 'priority-queue)' + + - Function: make-heap PRED<? + Returns a binary heap suitable which can be used for priority queue + operations. + + - Function: heap-length HEAP + Returns the number of elements in HEAP. + + - Procedure: heap-insert! HEAP ITEM + Inserts ITEM into HEAP. ITEM can be inserted multiple times. The + value returned is unspecified. + + - Function: heap-extract-max! HEAP + Returns the item which is larger than all others according to the + PRED<? argument to `make-heap'. If there are no items in HEAP, an + error is signaled. + + The algorithm for priority queues was taken from `Introduction to +Algorithms' by T. Cormen, C. Leiserson, R. Rivest. 1989 MIT Press. + + +File: slib.info, Node: Queues, Next: Records, Prev: Priority Queues, Up: Data Structures + +Queues +------ + + `(require 'queue)' + + A "queue" is a list where elements can be added to both the front and +rear, and removed from the front (i.e., they are what are often called +"dequeues"). A queue may also be used like a stack. + + - Function: make-queue + Returns a new, empty queue. + + - Function: queue? OBJ + Returns `#t' if OBJ is a queue. + + - Function: queue-empty? Q + Returns `#t' if the queue Q is empty. + + - Procedure: queue-push! Q DATUM + Adds DATUM to the front of queue Q. + + - Procedure: enquque! Q DATUM + Adds DATUM to the rear of queue Q. + + All of the following functions raise an error if the queue Q is empty. + + - Function: queue-front Q + Returns the datum at the front of the queue Q. + + - Function: queue-rear Q + Returns the datum at the rear of the queue Q. + + - Prcoedure: queue-pop! Q + - Procedure: dequeue! Q + Both of these procedures remove and return the datum at the front + of the queue. `queue-pop!' is used to suggest that the queue is + being used like a stack. + + +File: slib.info, Node: Records, Next: Structures, Prev: Queues, Up: Data Structures + +Records +------- + + `(require 'record)' + + The Record package provides a facility for user to define their own +record data types. + + - Function: make-record-type TYPE-NAME FIELD-NAMES + Returns a "record-type descriptor", a value representing a new data + type disjoint from all others. The TYPE-NAME argument must be a + string, but is only used for debugging purposes (such as the + printed representation of a record of the new type). The + FIELD-NAMES argument is a list of symbols naming the "fields" of a + record of the new type. It is an error if the list contains any + duplicates. It is unspecified how record-type descriptors are + represented. + + - Function: record-constructor RTD [FIELD-NAMES] + Returns a procedure for constructing new members of the type + represented by RTD. The returned procedure accepts exactly as + many arguments as there are symbols in the given list, + FIELD-NAMES; these are used, in order, as the initial values of + those fields in a new record, which is returned by the constructor + procedure. The values of any fields not named in that list are + unspecified. The FIELD-NAMES argument defaults to the list of + field names in the call to `make-record-type' that created the + type represented by RTD; if the FIELD-NAMES argument is provided, + it is an error if it contains any duplicates or any symbols not in + the default list. + + - Function: record-predicate RTD + Returns a procedure for testing membership in the type represented + by RTD. The returned procedure accepts exactly one argument and + returns a true value if the argument is a member of the indicated + record type; it returns a false value otherwise. + + - Function: record-accessor RTD FIELD-NAME + Returns a procedure for reading the value of a particular field of + a member of the type represented by RTD. The returned procedure + accepts exactly one argument which must be a record of the + appropriate type; it returns the current value of the field named + by the symbol FIELD-NAME in that record. The symbol FIELD-NAME + must be a member of the list of field-names in the call to + `make-record-type' that created the type represented by RTD. + + - Function: record-modifier RTD FIELD-NAME + Returns a procedure for writing the value of a particular field of + a member of the type represented by RTD. The returned procedure + accepts exactly two arguments: first, a record of the appropriate + type, and second, an arbitrary Scheme value; it modifies the field + named by the symbol FIELD-NAME in that record to contain the given + value. The returned value of the modifier procedure is + unspecified. The symbol FIELD-NAME must be a member of the list + of field-names in the call to `make-record-type' that created the + type represented by RTD. + + In May of 1996, as a product of discussion on the `rrrs-authors' +mailing list, I rewrote `record.scm' to portably implement type +disjointness for record data types. + + As long as an implementation's procedures are opaque and the `record' +code is loaded before other programs, this will give disjoint record +types which are unforgeable and incorruptible by R4RS procedures. + + As a consequence, the procedures `record?', `record-type-descriptor', +`record-type-name'.and `record-type-field-names' are no longer +supported. + + +File: slib.info, Node: Structures, Prev: Records, Up: Data Structures + +Structures +---------- + + `(require 'struct)' (uses defmacros) + + `defmacro's which implement "records" from the book `Essentials of +Programming Languages' by Daniel P. Friedman, M. Wand and C.T. Haynes. +Copyright 1992 Jeff Alexander, Shinnder Lee, and Lewis Patterson + + Matthew McDonald <mafm@cs.uwa.edu.au> added field setters. + + - Macro: define-record TAG (VAR1 VAR2 ...) + Defines several functions pertaining to record-name TAG: + + - Function: make-TAG VAR1 VAR2 ... + + - Function: TAG? OBJ + + - Function: TAG->VAR1 OBJ + + - Function: TAG->VAR2 OBJ + ... + + - Function: set-TAG-VAR1! OBJ VAL + + - Function: set-TAG-VAR2! OBJ VAL + ... + + Here is an example of its use. + + (define-record term (operator left right)) + => #<unspecified> + (define foo (make-term 'plus 1 2)) + => foo + (term->left foo) + => 1 + (set-term-left! foo 2345) + => #<unspecified> + (term->left foo) + => 2345 + + - Macro: variant-case EXP (TAG (VAR1 VAR2 ...) BODY) ... + executes the following for the matching clause: + + ((lambda (VAR1 VAR ...) BODY) + (TAG->VAR1 EXP) + (TAG->VAR2 EXP) ...) + + +File: slib.info, Node: Procedures, Next: Standards Support, Prev: Data Structures, Up: Other Packages + +Procedures +========== + + Anything that doesn't fall neatly into any of the other categories +winds up here. + +* Menu: + +* Common List Functions:: 'common-list-functions +* Tree Operations:: 'tree +* Chapter Ordering:: 'chapter-order +* Sorting:: 'sort +* Topological Sort:: Keep your socks on. +* String-Case:: 'string-case +* String Ports:: 'string-port +* String Search:: Also Search from a Port. +* Line I/O:: 'line-i/o +* Multi-Processing:: 'process + + +File: slib.info, Node: Common List Functions, Next: Tree Operations, Prev: Procedures, Up: Procedures + +Common List Functions +--------------------- + + `(require 'common-list-functions)' + + The procedures below follow the Common LISP equivalents apart from +optional arguments in some cases. + +* Menu: + +* List construction:: +* Lists as sets:: +* Lists as sequences:: +* Destructive list operations:: +* Non-List functions:: + + +File: slib.info, Node: List construction, Next: Lists as sets, Prev: Common List Functions, Up: Common List Functions + +List construction +................. + + - Function: make-list K . INIT + `make-list' creates and returns a list of K elements. If INIT is + included, all elements in the list are initialized to INIT. + + Example: + (make-list 3) + => (#<unspecified> #<unspecified> #<unspecified>) + (make-list 5 'foo) + => (foo foo foo foo foo) + + - Function: list* X . Y + Works like `list' except that the cdr of the last pair is the last + argument unless there is only one argument, when the result is + just that argument. Sometimes called `cons*'. E.g.: + (list* 1) + => 1 + (list* 1 2 3) + => (1 2 . 3) + (list* 1 2 '(3 4)) + => (1 2 3 4) + (list* ARGS '()) + == (list ARGS) + + - Function: copy-list LST + `copy-list' makes a copy of LST using new pairs and returns it. + Only the top level of the list is copied, i.e., pairs forming + elements of the copied list remain `eq?' to the corresponding + elements of the original; the copy is, however, not `eq?' to the + original, but is `equal?' to it. + + Example: + (copy-list '(foo foo foo)) + => (foo foo foo) + (define q '(foo bar baz bang)) + (define p q) + (eq? p q) + => #t + (define r (copy-list q)) + (eq? q r) + => #f + (equal? q r) + => #t + (define bar '(bar)) + (eq? bar (car (copy-list (list bar 'foo)))) + => #t + + +File: slib.info, Node: Lists as sets, Next: Lists as sequences, Prev: List construction, Up: Common List Functions + +Lists as sets +............. + + `eqv?' is used to test for membership by procedures which treat lists +as sets. + + - Function: adjoin E L + `adjoin' returns the adjoint of the element E and the list L. + That is, if E is in L, `adjoin' returns L, otherwise, it returns + `(cons E L)'. + + Example: + (adjoin 'baz '(bar baz bang)) + => (bar baz bang) + (adjoin 'foo '(bar baz bang)) + => (foo bar baz bang) + + - Function: union L1 L2 + `union' returns the combination of L1 and L2. Duplicates between + L1 and L2 are culled. Duplicates within L1 or within L2 may or + may not be removed. + + Example: + (union '(1 2 3 4) '(5 6 7 8)) + => (4 3 2 1 5 6 7 8) + (union '(1 2 3 4) '(3 4 5 6)) + => (2 1 3 4 5 6) + + - Function: intersection L1 L2 + `intersection' returns all elements that are in both L1 and L2. + + Example: + (intersection '(1 2 3 4) '(3 4 5 6)) + => (3 4) + (intersection '(1 2 3 4) '(5 6 7 8)) + => () + + - Function: set-difference L1 L2 + `set-difference' returns the union of all elements that are in L1 + but not in L2. + + Example: + (set-difference '(1 2 3 4) '(3 4 5 6)) + => (1 2) + (set-difference '(1 2 3 4) '(1 2 3 4 5 6)) + => () + + - Function: member-if PRED LST + `member-if' returns LST if `(PRED ELEMENT)' is `#t' for any + ELEMENT in LST. Returns `#f' if PRED does not apply to any + ELEMENT in LST. + + Example: + (member-if vector? '(1 2 3 4)) + => #f + (member-if number? '(1 2 3 4)) + => (1 2 3 4) + + - Function: some PRED LST . MORE-LSTS + PRED is a boolean function of as many arguments as there are list + arguments to `some' i.e., LST plus any optional arguments. PRED + is applied to successive elements of the list arguments in order. + `some' returns `#t' as soon as one of these applications returns + `#t', and is `#f' if none returns `#t'. All the lists should have + the same length. + + Example: + (some odd? '(1 2 3 4)) + => #t + + (some odd? '(2 4 6 8)) + => #f + + (some > '(2 3) '(1 4)) + => #f + + - Function: every PRED LST . MORE-LSTS + `every' is analogous to `some' except it returns `#t' if every + application of PRED is `#t' and `#f' otherwise. + + Example: + (every even? '(1 2 3 4)) + => #f + + (every even? '(2 4 6 8)) + => #t + + (every > '(2 3) '(1 4)) + => #f + + - Function: notany PRED . LST + `notany' is analogous to `some' but returns `#t' if no application + of PRED returns `#t' or `#f' as soon as any one does. + + - Function: notevery PRED . LST + `notevery' is analogous to `some' but returns `#t' as soon as an + application of PRED returns `#f', and `#f' otherwise. + + Example: + (notevery even? '(1 2 3 4)) + => #t + + (notevery even? '(2 4 6 8)) + => #f + + - Function: find-if PRED LST + `find-if' searches for the first ELEMENT in LST such that `(PRED + ELEMENT)' returns `#t'. If it finds any such ELEMENT in LST, + ELEMENT is returned. Otherwise, `#f' is returned. + + Example: + (find-if number? '(foo 1 bar 2)) + => 1 + + (find-if number? '(foo bar baz bang)) + => #f + + (find-if symbol? '(1 2 foo bar)) + => foo + + - Function: remove ELT LST + `remove' removes all occurrences of ELT from LST using `eqv?' to + test for equality and returns everything that's left. N.B.: other + implementations (Chez, Scheme->C and T, at least) use `equal?' as + the equality test. + + Example: + (remove 1 '(1 2 1 3 1 4 1 5)) + => (2 3 4 5) + + (remove 'foo '(bar baz bang)) + => (bar baz bang) + + - Function: remove-if PRED LST + `remove-if' removes all ELEMENTs from LST where `(PRED ELEMENT)' + is `#t' and returns everything that's left. + + Example: + (remove-if number? '(1 2 3 4)) + => () + + (remove-if even? '(1 2 3 4 5 6 7 8)) + => (1 3 5 7) + + - Function: remove-if-not PRED LST + `remove-if-not' removes all ELEMENTs from LST for which `(PRED + ELEMENT)' is `#f' and returns everything that's left. + + Example: + (remove-if-not number? '(foo bar baz)) + => () + (remove-if-not odd? '(1 2 3 4 5 6 7 8)) + => (1 3 5 7) + + - Function: has-duplicates? LST + returns `#t' if 2 members of LST are `equal?', `#f' otherwise. + + Example: + (has-duplicates? '(1 2 3 4)) + => #f + + (has-duplicates? '(2 4 3 4)) + => #t + + The procedure `remove-duplicates' uses `member' (rather than `memv'). + + - Function: remove-duplicates LST + returns a copy of LST with its duplicate members removed. + Elements are considered duplicate if they are `equal?'. + + Example: + (remove-duplicates '(1 2 3 4)) + => (4 3 2 1) + + (remove-duplicates '(2 4 3 4)) + => (3 4 2) + + +File: slib.info, Node: Lists as sequences, Next: Destructive list operations, Prev: Lists as sets, Up: Common List Functions + +Lists as sequences +.................. + + - Function: position OBJ LST + `position' returns the 0-based position of OBJ in LST, or `#f' if + OBJ does not occur in LST. + + Example: + (position 'foo '(foo bar baz bang)) + => 0 + (position 'baz '(foo bar baz bang)) + => 2 + (position 'oops '(foo bar baz bang)) + => #f + + - Function: reduce P LST + `reduce' combines all the elements of a sequence using a binary + operation (the combination is left-associative). For example, + using `+', one can add up all the elements. `reduce' allows you to + apply a function which accepts only two arguments to more than 2 + objects. Functional programmers usually refer to this as "foldl". + `collect:reduce' (*note Collections::.) provides a version of + `collect' generalized to collections. + + Example: + (reduce + '(1 2 3 4)) + => 10 + (define (bad-sum . l) (reduce + l)) + (bad-sum 1 2 3 4) + == (reduce + (1 2 3 4)) + == (+ (+ (+ 1 2) 3) 4) + => 10 + (bad-sum) + == (reduce + ()) + => () + (reduce string-append '("hello" "cruel" "world")) + == (string-append (string-append "hello" "cruel") "world") + => "hellocruelworld" + (reduce anything '()) + => () + (reduce anything '(x)) + => x + + What follows is a rather non-standard implementation of `reverse' + in terms of `reduce' and a combinator elsewhere called "C". + + ;;; Contributed by Jussi Piitulainen (jpiitula@ling.helsinki.fi) + + (define commute + (lambda (f) + (lambda (x y) + (f y x)))) + + (define reverse + (lambda (args) + (reduce-init (commute cons) '() args))) + + - Function: reduce-init P INIT LST + `reduce-init' is the same as reduce, except that it implicitly + inserts INIT at the start of the list. `reduce-init' is preferred + if you want to handle the null list, the one-element, and lists + with two or more elements consistently. It is common to use the + operator's idempotent as the initializer. Functional programmers + usually call this "foldl". + + Example: + (define (sum . l) (reduce-init + 0 l)) + (sum 1 2 3 4) + == (reduce-init + 0 (1 2 3 4)) + == (+ (+ (+ (+ 0 1) 2) 3) 4) + => 10 + (sum) + == (reduce-init + 0 '()) + => 0 + + (reduce-init string-append "@" '("hello" "cruel" "world")) + == + (string-append (string-append (string-append "@" "hello") + "cruel") + "world") + => "@hellocruelworld" + + Given a differentiation of 2 arguments, `diff', the following will + differentiate by any number of variables. + (define (diff* exp . vars) + (reduce-init diff exp vars)) + + Example: + ;;; Real-world example: Insertion sort using reduce-init. + + (define (insert l item) + (if (null? l) + (list item) + (if (< (car l) item) + (cons (car l) (insert (cdr l) item)) + (cons item l)))) + (define (insertion-sort l) (reduce-init insert '() l)) + + (insertion-sort '(3 1 4 1 5) + == (reduce-init insert () (3 1 4 1 5)) + == (insert (insert (insert (insert (insert () 3) 1) 4) 1) 5) + == (insert (insert (insert (insert (3)) 1) 4) 1) 5) + == (insert (insert (insert (1 3) 4) 1) 5) + == (insert (insert (1 3 4) 1) 5) + == (insert (1 1 3 4) 5) + => (1 1 3 4 5) + + - Function: last LST N + `last' returns the last N elements of LST. N must be a + non-negative integer. + + Example: + (last '(foo bar baz bang) 2) + => (baz bang) + (last '(1 2 3) 0) + => 0 + + - Function: butlast LST N + `butlast' returns all but the last N elements of LST. + + Example: + (butlast '(a b c d) 3) + => (a) + (butlast '(a b c d) 4) + => () + +`last' and `butlast' split a list into two parts when given identical +arugments. + (last '(a b c d e) 2) + => (d e) + (butlast '(a b c d e) 2) + => (a b c) + + - Function: nthcdr N LST + `nthcdr' takes N `cdr's of LST and returns the result. Thus + `(nthcdr 3 LST)' == `(cdddr LST)' + + Example: + (nthcdr 2 '(a b c d)) + => (c d) + (nthcdr 0 '(a b c d)) + => (a b c d) + + - Function: butnthcdr N LST + `butnthcdr' returns all but the nthcdr N elements of LST. + + Example: + (butnthcdr 3 '(a b c d)) + => (a b c) + (butnthcdr 4 '(a b c d)) + => () + +`nthcdr' and `butnthcdr' split a list into two parts when given +identical arugments. + (nthcdr 2 '(a b c d e)) + => (c d e) + (butnthcdr 2 '(a b c d e)) + => (a b) + + +File: slib.info, Node: Destructive list operations, Next: Non-List functions, Prev: Lists as sequences, Up: Common List Functions + +Destructive list operations +........................... + + These procedures may mutate the list they operate on, but any such +mutation is undefined. + + - Procedure: nconc ARGS + `nconc' destructively concatenates its arguments. (Compare this + with `append', which copies arguments rather than destroying them.) + Sometimes called `append!' (*note Rev2 Procedures::.). + + Example: You want to find the subsets of a set. Here's the + obvious way: + + (define (subsets set) + (if (null? set) + '(()) + (append (mapcar (lambda (sub) (cons (car set) sub)) + (subsets (cdr set))) + (subsets (cdr set))))) + But that does way more consing than you need. Instead, you could + replace the `append' with `nconc', since you don't have any need + for all the intermediate results. + + Example: + (define x '(a b c)) + (define y '(d e f)) + (nconc x y) + => (a b c d e f) + x + => (a b c d e f) + + `nconc' is the same as `append!' in `sc2.scm'. + + - Procedure: nreverse LST + `nreverse' reverses the order of elements in LST by mutating + `cdr's of the list. Sometimes called `reverse!'. + + Example: + (define foo '(a b c)) + (nreverse foo) + => (c b a) + foo + => (a) + + Some people have been confused about how to use `nreverse', + thinking that it doesn't return a value. It needs to be pointed + out that + (set! lst (nreverse lst)) + + is the proper usage, not + (nreverse lst) + The example should suffice to show why this is the case. + + - Procedure: delete ELT LST + - Procedure: delete-if PRED LST + - Procedure: delete-if-not PRED LST + Destructive versions of `remove' `remove-if', and `remove-if-not'. + + Example: + (define lst '(foo bar baz bang)) + (delete 'foo lst) + => (bar baz bang) + lst + => (foo bar baz bang) + + (define lst '(1 2 3 4 5 6 7 8 9)) + (delete-if odd? lst) + => (2 4 6 8) + lst + => (1 2 4 6 8) + + Some people have been confused about how to use `delete', + `delete-if', and `delete-if', thinking that they dont' return a + value. It needs to be pointed out that + (set! lst (delete el lst)) + + is the proper usage, not + (delete el lst) + The examples should suffice to show why this is the case. + + +File: slib.info, Node: Non-List functions, Prev: Destructive list operations, Up: Common List Functions + +Non-List functions +.................. + + - Function: and? . ARGS + `and?' checks to see if all its arguments are true. If they are, + `and?' returns `#t', otherwise, `#f'. (In contrast to `and', this + is a function, so all arguments are always evaluated and in an + unspecified order.) + + Example: + (and? 1 2 3) + => #t + (and #f 1 2) + => #f + + - Function: or? . ARGS + `or?' checks to see if any of its arguments are true. If any is + true, `or?' returns `#t', and `#f' otherwise. (To `or' as `and?' + is to `and'.) + + Example: + (or? 1 2 #f) + => #t + (or? #f #f #f) + => #f + + - Function: atom? OBJECT + Returns `#t' if OBJECT is not a pair and `#f' if it is pair. + (Called `atom' in Common LISP.) + (atom? 1) + => #t + (atom? '(1 2)) + => #f + (atom? #(1 2)) ; dubious! + => #t + + - Function: type-of OBJECT + Returns a symbol name for the type of OBJECT. + + - Function: coerce OBJECT RESULT-TYPE + Converts and returns OBJECT of type `char', `number', `string', + `symbol', `list', or `vector' to RESULT-TYPE (which must be one of + these symbols). + + +File: slib.info, Node: Tree Operations, Next: Chapter Ordering, Prev: Common List Functions, Up: Procedures + +Tree operations +--------------- + + `(require 'tree)' + + These are operations that treat lists a representations of trees. + + - Function: subst NEW OLD TREE + - Function: substq NEW OLD TREE + - Function: substv NEW OLD TREE + `subst' makes a copy of TREE, substituting NEW for every subtree + or leaf of TREE which is `equal?' to OLD and returns a modified + tree. The original TREE is unchanged, but may share parts with + the result. + + `substq' and `substv' are similar, but test against OLD using + `eq?' and `eqv?' respectively. + + Examples: + (substq 'tempest 'hurricane '(shakespeare wrote (the hurricane))) + => (shakespeare wrote (the tempest)) + (substq 'foo '() '(shakespeare wrote (twelfth night))) + => (shakespeare wrote (twelfth night . foo) . foo) + (subst '(a . cons) '(old . pair) + '((old . spice) ((old . shoes) old . pair) (old . pair))) + => ((old . spice) ((old . shoes) a . cons) (a . cons)) + + - Function: copy-tree TREE + Makes a copy of the nested list structure TREE using new pairs and + returns it. All levels are copied, so that none of the pairs in + the tree are `eq?' to the original ones - only the leaves are. + + Example: + (define bar '(bar)) + (copy-tree (list bar 'foo)) + => ((bar) foo) + (eq? bar (car (copy-tree (list bar 'foo)))) + => #f + + +File: slib.info, Node: Chapter Ordering, Next: Sorting, Prev: Tree Operations, Up: Procedures + +Chapter Ordering +---------------- + + `(require 'chapter-order)' + + The `chap:' functions deal with strings which are ordered like +chapter numbers (or letters) in a book. Each section of the string +consists of consecutive numeric or consecutive aphabetic characters of +like case. + + - Function: chap:string<? STRING1 STRING2 + Returns #t if the first non-matching run of alphabetic upper-case + or the first non-matching run of alphabetic lower-case or the first + non-matching run of numeric characters of STRING1 is `string<?' + than the corresponding non-matching run of characters of STRING2. + + (chap:string<? "a.9" "a.10") => #t + (chap:string<? "4c" "4aa") => #t + (chap:string<? "Revised^{3.99}" "Revised^{4}") => #t + + - Function: chap:string>? STRING1 STRING2 + - Function: chap:string<=? STRING1 STRING2 + - Function: chap:string>=? STRING1 STRING2 + Implement the corresponding chapter-order predicates. + + - Function: chap:next-string STRING + Returns the next string in the *chapter order*. If STRING has no + alphabetic or numeric characters, `(string-append STRING "0")' is + returnd. The argument to chap:next-string will always be + `chap:string<?' than the result. + + (chap:next-string "a.9") => "a.10" + (chap:next-string "4c") => "4d" + (chap:next-string "4z") => "4aa" + (chap:next-string "Revised^{4}") => "Revised^{5}" + + +File: slib.info, Node: Sorting, Next: Topological Sort, Prev: Chapter Ordering, Up: Procedures + +Sorting +------- + + `(require 'sort)' + + Many Scheme systems provide some kind of sorting functions. They do +not, however, always provide the *same* sorting functions, and those +that I have had the opportunity to test provided inefficient ones (a +common blunder is to use quicksort which does not perform well). + + Because `sort' and `sort!' are not in the standard, there is very +little agreement about what these functions look like. For example, +Dybvig says that Chez Scheme provides + (merge predicate list1 list2) + (merge! predicate list1 list2) + (sort predicate list) + (sort! predicate list) + +while MIT Scheme 7.1, following Common LISP, offers unstable + (sort list predicate) + +TI PC Scheme offers + (sort! list/vector predicate?) + +and Elk offers + (sort list/vector predicate?) + (sort! list/vector predicate?) + + Here is a comprehensive catalogue of the variations I have found. + + 1. Both `sort' and `sort!' may be provided. + + 2. `sort' may be provided without `sort!'. + + 3. `sort!' may be provided without `sort'. + + 4. Neither may be provided. + + 5. The sequence argument may be either a list or a vector. + + 6. The sequence argument may only be a list. + + 7. The sequence argument may only be a vector. + + 8. The comparison function may be expected to behave like `<'. + + 9. The comparison function may be expected to behave like `<='. + + 10. The interface may be `(sort predicate? sequence)'. + + 11. The interface may be `(sort sequence predicate?)'. + + 12. The interface may be `(sort sequence &optional (predicate? <))'. + + 13. The sort may be stable. + + 14. The sort may be unstable. + + All of this variation really does not help anybody. A nice simple +merge sort is both stable and fast (quite a lot faster than *quick* +sort). + + I am providing this source code with no restrictions at all on its use +(but please retain D.H.D.Warren's credit for the original idea). You +may have to rename some of these functions in order to use them in a +system which already provides incompatible or inferior sorts. For each +of the functions, only the top-level define needs to be edited to do +that. + + I could have given these functions names which would not clash with +any Scheme that I know of, but I would like to encourage implementors to +converge on a single interface, and this may serve as a hint. The +argument order for all functions has been chosen to be as close to +Common LISP as made sense, in order to avoid NIH-itis. + + Each of the five functions has a required *last* parameter which is a +comparison function. A comparison function `f' is a function of 2 +arguments which acts like `<'. For example, + + (not (f x x)) + (and (f x y) (f y z)) == (f x z) + + The standard functions `<', `>', `char<?', `char>?', `char-ci<?', +`char-ci>?', `string<?', `string>?', `string-ci<?', and `string-ci>?' +are suitable for use as comparison functions. Think of `(less? x y)' +as saying when `x' must *not* precede `y'. + + - Function: sorted? SEQUENCE LESS? + Returns `#t' when the sequence argument is in non-decreasing order + according to LESS? (that is, there is no adjacent pair `... x y + ...' for which `(less? y x)'). + + Returns `#f' when the sequence contains at least one out-of-order + pair. It is an error if the sequence is neither a list nor a + vector. + + - Function: merge LIST1 LIST2 LESS? + This merges two lists, producing a completely new list as result. + I gave serious consideration to producing a Common-LISP-compatible + version. However, Common LISP's `sort' is our `sort!' (well, in + fact Common LISP's `stable-sort' is our `sort!', merge sort is + *fast* as well as stable!) so adapting CL code to Scheme takes a + bit of work anyway. I did, however, appeal to CL to determine the + *order* of the arguments. + + - Procedure: merge! LIST1 LIST2 LESS? + Merges two lists, re-using the pairs of LIST1 and LIST2 to build + the result. If the code is compiled, and LESS? constructs no new + pairs, no pairs at all will be allocated. The first pair of the + result will be either the first pair of LIST1 or the first pair of + LIST2, but you can't predict which. + + The code of `merge' and `merge!' could have been quite a bit + simpler, but they have been coded to reduce the amount of work + done per iteration. (For example, we only have one `null?' test + per iteration.) + + - Function: sort SEQUENCE LESS? + Accepts either a list or a vector, and returns a new sequence + which is sorted. The new sequence is the same type as the input. + Always `(sorted? (sort sequence less?) less?)'. The original + sequence is not altered in any way. The new sequence shares its + *elements* with the old one; no elements are copied. + + - Procedure: sort! SEQUENCE LESS? + Returns its sorted result in the original boxes. If the original + sequence is a list, no new storage is allocated at all. If the + original sequence is a vector, the sorted elements are put back in + the same vector. + + Some people have been confused about how to use `sort!', thinking + that it doesn't return a value. It needs to be pointed out that + (set! slist (sort! slist <)) + + is the proper usage, not + (sort! slist <) + + Note that these functions do *not* accept a CL-style `:key' argument. +A simple device for obtaining the same expressiveness is to define + (define (keyed less? key) + (lambda (x y) (less? (key x) (key y)))) + +and then, when you would have written + (sort a-sequence #'my-less :key #'my-key) + +in Common LISP, just write + (sort! a-sequence (keyed my-less? my-key)) + +in Scheme. + + +File: slib.info, Node: Topological Sort, Next: String-Case, Prev: Sorting, Up: Procedures + +Topological Sort +---------------- + + `(require 'topological-sort)' or `(require 'tsort)' + +The algorithm is inspired by Cormen, Leiserson and Rivest (1990) +`Introduction to Algorithms', chapter 23. + + - Function: tsort DAG PRED + - Function: topological-sort DAG PRED + where + DAG + is a list of sublists. The car of each sublist is a vertex. + The cdr is the adjacency list of that vertex, i.e. a list of + all vertices to which there exists an edge from the car + vertex. + + PRED + is one of `eq?', `eqv?', `equal?', `=', `char=?', + `char-ci=?', `string=?', or `string-ci=?'. + + Sort the directed acyclic graph DAG so that for every edge from + vertex U to V, U will come before V in the resulting list of + vertices. + + Time complexity: O (|V| + |E|) + + Example (from Cormen): + Prof. Bumstead topologically sorts his clothing when getting + dressed. The first argument to `tsort' describes which + garments he needs to put on before others. (For example, + Prof Bumstead needs to put on his shirt before he puts on his + tie or his belt.) `tsort' gives the correct order of + dressing: + + (require 'tsort) + (tsort '((shirt tie belt) + (tie jacket) + (belt jacket) + (watch) + (pants shoes belt) + (undershorts pants shoes) + (socks shoes)) + eq?) + => + (socks undershorts pants shoes watch shirt belt tie jacket) + + +File: slib.info, Node: String-Case, Next: String Ports, Prev: Topological Sort, Up: Procedures + +String-Case +----------- + + `(require 'string-case)' + + - Procedure: string-upcase STR + - Procedure: string-downcase STR + - Procedure: string-capitalize STR + The obvious string conversion routines. These are non-destructive. + + - Function: string-upcase! STR + - Function: string-downcase! STR + - Function: string-captialize! STR + The destructive versions of the functions above. + + - Function: string-ci->symbol STR + Converts string STR to a symbol having the same case as if the + symbol had been `read'. + + +File: slib.info, Node: String Ports, Next: String Search, Prev: String-Case, Up: Procedures + +String Ports +------------ + + `(require 'string-port)' + + - Procedure: call-with-output-string PROC + PROC must be a procedure of one argument. This procedure calls + PROC with one argument: a (newly created) output port. When the + function returns, the string composed of the characters written + into the port is returned. + + - Procedure: call-with-input-string STRING PROC + PROC must be a procedure of one argument. This procedure calls + PROC with one argument: an (newly created) input port from which + STRING's contents may be read. When PROC returns, the port is + closed and the value yielded by the procedure PROC is returned. + + +File: slib.info, Node: String Search, Next: Line I/O, Prev: String Ports, Up: Procedures + +String Search +------------- + + `(require 'string-search)' + + - Procedure: string-index STRING CHAR + - Procedure: string-index-ci STRING CHAR + Returns the index of the first occurence of CHAR within STRING, or + `#f' if the STRING does not contain a character CHAR. + + - Procedure: string-reverse-index STRING CHAR + - Procedure: string-reverse-index-ci STRING CHAR + Returns the index of the last occurence of CHAR within STRING, or + `#f' if the STRING does not contain a character CHAR. + + - procedure: substring? PATTERN STRING + - procedure: substring-ci? PATTERN STRING + Searches STRING to see if some substring of STRING is equal to + PATTERN. `substring?' returns the index of the first character of + the first substring of STRING that is equal to PATTERN; or `#f' if + STRING does not contain PATTERN. + + (substring? "rat" "pirate") => 2 + (substring? "rat" "outrage") => #f + (substring? "" any-string) => 0 + + - Procedure: find-string-from-port? STR IN-PORT MAX-NO-CHARS + Looks for a string STR within the first MAX-NO-CHARS chars of the + input port IN-PORT. + + - Procedure: find-string-from-port? STR IN-PORT + When called with two arguments, the search span is limited by the + end of the input stream. + + - Procedure: find-string-from-port? STR IN-PORT CHAR + Searches up to the first occurrence of character CHAR in STR. + + - Procedure: find-string-from-port? STR IN-PORT PROC + Searches up to the first occurrence of the procedure PROC + returning non-false when called with a character (from IN-PORT) + argument. + + When the STR is found, `find-string-from-port?' returns the number + of characters it has read from the port, and the port is set to + read the first char after that (that is, after the STR) The + function returns `#f' when the STR isn't found. + + `find-string-from-port?' reads the port *strictly* sequentially, + and does not perform any buffering. So `find-string-from-port?' + can be used even if the IN-PORT is open to a pipe or other + communication channel. + + - Function: string-subst TXT OLD1 NEW1 ... + Returns a copy of string TXT with all occurrences of string OLD1 + in TXT replaced with NEW1, OLD2 replaced with NEW2 .... + + +File: slib.info, Node: Line I/O, Next: Multi-Processing, Prev: String Search, Up: Procedures + +Line I/O +-------- + + `(require 'line-i/o)' + + - Function: read-line + - Function: read-line PORT + Returns a string of the characters up to, but not including a + newline or end of file, updating PORT to point to the character + following the newline. If no characters are available, an end of + file object is returned. The PORT argument may be omitted, in + which case it defaults to the value returned by + `current-input-port'. + + - Function: read-line! STRING + - Function: read-line! STRING PORT + Fills STRING with characters up to, but not including a newline or + end of file, updating the PORT to point to the last character read + or following the newline if it was read. If no characters are + available, an end of file object is returned. If a newline or end + of file was found, the number of characters read is returned. + Otherwise, `#f' is returned. The PORT argument may be omitted, in + which case it defaults to the value returned by + `current-input-port'. + + - Function: write-line STRING + - Function: write-line STRING PORT + Writes STRING followed by a newline to the given PORT and returns + an unspecified value. The PORT argument may be omited, in which + case it defaults to the value returned by `current-input-port'. + + - Function: display-file PATH + - Function: display-file PATH PORT + Displays the contents of the file named by PATH to PORT. The PORT + argument may be ommited, in which case it defaults to the value + returned by `current-output-port'. + + +File: slib.info, Node: Multi-Processing, Prev: Line I/O, Up: Procedures + +Multi-Processing +---------------- + + `(require 'process)' + + This module implements asynchronous (non-polled) time-sliced +multi-processing in the SCM Scheme implementation using procedures +`alarm' and `alarm-interrupt'. Until this is ported to another +implementation, consider it an example of writing schedulers in Scheme. + + - Procedure: add-process! PROC + Adds proc, which must be a procedure (or continuation) capable of + accepting accepting one argument, to the `process:queue'. The + value returned is unspecified. The argument to PROC should be + ignored. If PROC returns, the process is killed. + + - Procedure: process:schedule! + Saves the current process on `process:queue' and runs the next + process from `process:queue'. The value returned is unspecified. + + - Procedure: kill-process! + Kills the current process and runs the next process from + `process:queue'. If there are no more processes on + `process:queue', `(slib:exit)' is called (*note System::.). + + +File: slib.info, Node: Standards Support, Next: Session Support, Prev: Procedures, Up: Other Packages + +Standards Support +================= + +* Menu: + +* With-File:: 'with-file +* Transcripts:: 'transcript +* Rev2 Procedures:: 'rev2-procedures +* Rev4 Optional Procedures:: 'rev4-optional-procedures +* Multi-argument / and -:: 'multiarg/and- +* Multi-argument Apply:: 'multiarg-apply +* Rationalize:: 'rationalize +* Promises:: 'promise +* Dynamic-Wind:: 'dynamic-wind +* Eval:: 'eval +* Values:: 'values + + +File: slib.info, Node: With-File, Next: Transcripts, Prev: Standards Support, Up: Standards Support + +With-File +--------- + + `(require 'with-file)' + + - Function: with-input-from-file FILE THUNK + - Function: with-output-to-file FILE THUNK + Description found in R4RS. + + +File: slib.info, Node: Transcripts, Next: Rev2 Procedures, Prev: With-File, Up: Standards Support + +Transcripts +----------- + + `(require 'transcript)' + + - Function: transcript-on FILENAME + - Function: transcript-off FILENAME + Redefines `read-char', `read', `write-char', `write', `display', + and `newline'. + + +File: slib.info, Node: Rev2 Procedures, Next: Rev4 Optional Procedures, Prev: Transcripts, Up: Standards Support + +Rev2 Procedures +--------------- + + `(require 'rev2-procedures)' + + The procedures below were specified in the `Revised^2 Report on +Scheme'. *N.B.*: The symbols `1+' and `-1+' are not `R4RS' syntax. +Scheme->C, for instance, barfs on this module. + + - Procedure: substring-move-left! STRING1 START1 END1 STRING2 START2 + - Procedure: substring-move-right! STRING1 START1 END1 STRING2 START2 + STRING1 and STRING2 must be a strings, and START1, START2 and END1 + must be exact integers satisfying + + 0 <= START1 <= END1 <= (string-length STRING1) + 0 <= START2 <= END1 - START1 + START2 <= (string-length STRING2) + + `substring-move-left!' and `substring-move-right!' store + characters of STRING1 beginning with index START1 (inclusive) and + ending with index END1 (exclusive) into STRING2 beginning with + index START2 (inclusive). + + `substring-move-left!' stores characters in time order of + increasing indices. `substring-move-right!' stores characters in + time order of increasing indeces. + + - Procedure: substring-fill! STRING START END CHAR + Fills the elements START-END of STRING with the character CHAR. + + - Function: string-null? STR + == `(= 0 (string-length STR))' + + - Procedure: append! . PAIRS + Destructively appends its arguments. Equivalent to `nconc'. + + - Function: 1+ N + Adds 1 to N. + + - Function: -1+ N + Subtracts 1 from N. + + - Function: <? + - Function: <=? + - Function: =? + - Function: >? + - Function: >=? + These are equivalent to the procedures of the same name but + without the trailing `?'. + + +File: slib.info, Node: Rev4 Optional Procedures, Next: Multi-argument / and -, Prev: Rev2 Procedures, Up: Standards Support + +Rev4 Optional Procedures +------------------------ + + `(require 'rev4-optional-procedures)' + + For the specification of these optional procedures, *Note Standard +procedures: (r4rs)Standard procedures. + + - Function: list-tail L P + + - Function: string->list S + + - Function: list->string L + + - Function: string-copy + + - Procedure: string-fill! S OBJ + + - Function: list->vector L + + - Function: vector->list S + + - Procedure: vector-fill! S OBJ + + +File: slib.info, Node: Multi-argument / and -, Next: Multi-argument Apply, Prev: Rev4 Optional Procedures, Up: Standards Support + +Multi-argument / and - +---------------------- + + `(require 'mutliarg/and-)' + + For the specification of these optional forms, *Note Numerical +operations: (r4rs)Numerical operations. The `two-arg:'* forms are only +defined if the implementation does not support the many-argument forms. + + - Function: two-arg:/ N1 N2 + The original two-argument version of `/'. + + - Function: / DIVIDENT . DIVISORS + + - Function: two-arg:- N1 N2 + The original two-argument version of `-'. + + - Function: - MINUEND . SUBTRAHENDS + + +File: slib.info, Node: Multi-argument Apply, Next: Rationalize, Prev: Multi-argument / and -, Up: Standards Support + +Multi-argument Apply +-------------------- + + `(require 'multiarg-apply)' + +For the specification of this optional form, *Note Control features: +(r4rs)Control features. + + - Function: two-arg:apply PROC L + The implementation's native `apply'. Only defined for + implementations which don't support the many-argument version. + + - Function: apply PROC . ARGS + + +File: slib.info, Node: Rationalize, Next: Promises, Prev: Multi-argument Apply, Up: Standards Support + +Rationalize +----------- + + `(require 'rationalize)' + + The procedure rationalize is interesting because most programming +languages do not provide anything analogous to it. For simplicity, we +present an algorithm which computes the correct result for exact +arguments (provided the implementation supports exact rational numbers +of unlimited precision), and produces a reasonable answer for inexact +arguments when inexact arithmetic is implemented using floating-point. +We thank Alan Bawden for contributing this algorithm. + + - Function: rationalize X E + + +File: slib.info, Node: Promises, Next: Dynamic-Wind, Prev: Rationalize, Up: Standards Support + +Promises +-------- + + `(require 'promise)' + + - Function: make-promise PROC + + Change occurrences of `(delay EXPRESSION)' to `(make-promise (lambda +() EXPRESSION))' and `(define force promise:force)' to implement +promises if your implementation doesn't support them (*note Control +features: (r4rs)Control features.). + + +File: slib.info, Node: Dynamic-Wind, Next: Eval, Prev: Promises, Up: Standards Support + +Dynamic-Wind +------------ + + `(require 'dynamic-wind)' + + This facility is a generalization of Common LISP `unwind-protect', +designed to take into account the fact that continuations produced by +`call-with-current-continuation' may be reentered. + + - Procedure: dynamic-wind THUNK1 THUNK2 THUNK3 + The arguments THUNK1, THUNK2, and THUNK3 must all be procedures of + no arguments (thunks). + + `dynamic-wind' calls THUNK1, THUNK2, and then THUNK3. The value + returned by THUNK2 is returned as the result of `dynamic-wind'. + THUNK3 is also called just before control leaves the dynamic + context of THUNK2 by calling a continuation created outside that + context. Furthermore, THUNK1 is called before reentering the + dynamic context of THUNK2 by calling a continuation created inside + that context. (Control is inside the context of THUNK2 if THUNK2 + is on the current return stack). + + *Warning:* There is no provision for dealing with errors or + interrupts. If an error or interrupt occurs while using + `dynamic-wind', the dynamic environment will be that in effect at + the time of the error or interrupt. + + +File: slib.info, Node: Eval, Next: Values, Prev: Dynamic-Wind, Up: Standards Support + +Eval +---- + + `(require 'eval)' + + - Function: eval EXPRESSION ENVIRONMENT-SPECIFIER + Evaluates EXPRESSION in the specified environment and returns its + value. EXPRESSION must be a valid Scheme expression represented + as data, and ENVIRONMENT-SPECIFIER must be a value returned by one + of the three procedures described below. Implementations may + extend `eval' to allow non-expression programs (definitions) as + the first argument and to allow other values as environments, with + the restriction that `eval' is not allowed to create new bindings + in the environments associated with `null-environment' or + `scheme-report-environment'. + + (eval '(* 7 3) (scheme-report-environment 5)) + => 21 + + (let ((f (eval '(lambda (f x) (f x x)) + (null-environment)))) + (f + 10)) + => 20 + + - Function: scheme-report-environment VERSION + - Function: null-environment VERSION + - Function: null-environment + VERSION must be an exact non-negative integer N corresponding to a + version of one of the Revised^N Reports on Scheme. + `Scheme-report-environment' returns a specifier for an environment + that contains the set of bindings specified in the corresponding + report that the implementation supports. `Null-environment' + returns a specifier for an environment that contains only the + (syntactic) bindings for all the syntactic keywords defined in the + given version of the report. + + Not all versions may be available in all implementations at all + times. However, an implementation that conforms to version N of + the Revised^N Reports on Scheme must accept version N. An error + is signalled if the specified version is not available. + + The effect of assigning (through the use of `eval') a variable + bound in a `scheme-report-environment' (for example `car') is + unspecified. Thus the environments specified by + `scheme-report-environment' may be immutable. + + + - Function: interaction-environment + This optional procedure returns a specifier for the environment + that contains implementation-defined bindings, typically a + superset of those listed in the report. The intent is that this + procedure will return the environment in which the implementation + would evaluate expressions dynamically typed by the user. + +Here are some more `eval' examples: + + (require 'eval) + => #<unspecified> + (define car 'volvo) + => #<unspecified> + car + => volvo + (eval 'car (interaction-environment)) + => volvo + (eval 'car (scheme-report-environment 5)) + => #<primitive-procedure car> + (eval '(eval 'car (interaction-environment)) + (scheme-report-environment 5)) + => volvo + (eval '(eval '(set! car 'buick) (interaction-environment)) + (scheme-report-environment 5)) + => #<unspecified> + car + => buick + (eval 'car (scheme-report-environment 5)) + => #<primitive-procedure car> + (eval '(eval 'car (interaction-environment)) + (scheme-report-environment 5)) + => buick + + +File: slib.info, Node: Values, Prev: Eval, Up: Standards Support + +Values +------ + + `(require 'values)' + + - Function: values OBJ ... + `values' takes any number of arguments, and passes (returns) them + to its continuation. + + - Function: call-with-values THUNK PROC + THUNK must be a procedure of no arguments, and PROC must be a + procedure. `call-with-values' calls THUNK with a continuation + that, when passed some values, calls PROC with those values as + arguments. + + Except for continuations created by the `call-with-values' + procedure, all continuations take exactly one value, as now; the + effect of passing no value or more than one value to continuations + that were not created by the `call-with-values' procedure is + unspecified. + + +File: slib.info, Node: Session Support, Next: Extra-SLIB Packages, Prev: Standards Support, Up: Other Packages + +Session Support +=============== + +* Menu: + +* Repl:: Macros at top-level +* Quick Print:: Loop-safe Output +* Debug:: To err is human ... +* Breakpoints:: Pause execution +* Trace:: 'trace +* System Interface:: 'system, 'getenv, and 'net-clients + + +File: slib.info, Node: Repl, Next: Quick Print, Prev: Session Support, Up: Session Support + +Repl +---- + + `(require 'repl)' + + Here is a read-eval-print-loop which, given an eval, evaluates forms. + + - Procedure: repl:top-level REPL:EVAL + `read's, `repl:eval's and `write's expressions from + `(current-input-port)' to `(current-output-port)' until an + end-of-file is encountered. `load', `slib:eval', `slib:error', + and `repl:quit' dynamically bound during `repl:top-level'. + + - Procedure: repl:quit + Exits from the invocation of `repl:top-level'. + + The `repl:' procedures establish, as much as is possible to do +portably, a top level environment supporting macros. `repl:top-level' +uses `dynamic-wind' to catch error conditions and interrupts. If your +implementation supports this you are all set. + + Otherwise, if there is some way your implementation can catch error +conditions and interrupts, then have them call `slib:error'. It will +display its arguments and reenter `repl:top-level'. `slib:error' +dynamically bound by `repl:top-level'. + + To have your top level loop always use macros, add any interrupt +catching lines and the following lines to your Scheme init file: + (require 'macro) + (require 'repl) + (repl:top-level macro:eval) + + +File: slib.info, Node: Quick Print, Next: Debug, Prev: Repl, Up: Session Support + +Quick Print +----------- + + `(require 'qp)' + +When displaying error messages and warnings, it is paramount that the +output generated for circular lists and large data structures be +limited. This section supplies a procedure to do this. It could be +much improved. + + Notice that the neccessity for truncating output eliminates + Common-Lisp's *Note Format:: from consideration; even when + variables `*print-level*' and `*print-level*' are set, huge + strings and bit-vectors are *not* limited. + + - Procedure: qp ARG1 ... + - Procedure: qpn ARG1 ... + - Procedure: qpr ARG1 ... + `qp' writes its arguments, separated by spaces, to + `(current-output-port)'. `qp' compresses printing by substituting + `...' for substructure it does not have sufficient room to print. + `qpn' is like `qp' but outputs a newline before returning. `qpr' + is like `qpn' except that it returns its last argument. + + - Variable: *qp-width* + `*qp-width*' is the largest number of characters that `qp' should + use. + + +File: slib.info, Node: Debug, Next: Breakpoints, Prev: Quick Print, Up: Session Support + +Debug +----- + + `(require 'debug)' + +Requiring `debug' automatically requires `trace' and `break'. + +An application with its own datatypes may want to substitute its own +printer for `qp'. This example shows how to do this: + + (define qpn (lambda args) ...) + (provide 'qp) + (require 'debug) + + - Procedure: trace-all FILE + Traces (*note Trace::.) all procedures `define'd at top-level in + file `file'. + + - Procedure: break-all FILE + Breakpoints (*note Breakpoints::.) all procedures `define'd at + top-level in file `file'. + + +File: slib.info, Node: Breakpoints, Next: Trace, Prev: Debug, Up: Session Support + +Breakpoints +----------- + + `(require 'break)' + + - Function: init-debug + If your Scheme implementation does not support `break' or `abort', + a message will appear when you `(require 'break)' or `(require + 'debug)' telling you to type `(init-debug)'. This is in order to + establish a top-level continuation. Typing `(init-debug)' at top + level sets up a continuation for `break'. + + - Function: breakpoint ARG1 ... + Returns from the top level continuation and pushes the + continuation from which it was called on a continuation stack. + + - Function: continue + Pops the topmost continuation off of the continuation stack and + returns an unspecified value to it. + + - Function: continue ARG1 ... + Pops the topmost continuation off of the continuation stack and + returns ARG1 ... to it. + + - Macro: break PROC1 ... + Redefines the top-level named procedures given as arguments so that + `breakpoint' is called before calling PROC1 .... + + - Macro: break + With no arguments, makes sure that all the currently broken + identifiers are broken (even if those identifiers have been + redefined) and returns a list of the broken identifiers. + + - Macro: unbreak PROC1 ... + Turns breakpoints off for its arguments. + + - Macro: unbreak + With no arguments, unbreaks all currently broken identifiers and + returns a list of these formerly broken identifiers. + + The following routines are the procedures which actually do the +tracing when this module is supplied by SLIB, rather than natively. If +defmacros are not natively supported by your implementation, these might +be more convenient to use. + + - Function: breakf PROC + - Function: breakf PROC NAME + - Function: debug:breakf PROC + - Function: debug:breakf PROC NAME + To break, type + (set! SYMBOL (breakf SYMBOL)) + + or + (set! SYMBOL (breakf SYMBOL 'SYMBOL)) + + or + (define SYMBOL (breakf FUNCTION)) + + or + (define SYMBOL (breakf FUNCTION 'SYMBOL)) + + - Function: unbreakf PROC + - Function: debug:unbreakf PROC + To unbreak, type + (set! SYMBOL (unbreakf SYMBOL)) + + +File: slib.info, Node: Trace, Next: System Interface, Prev: Breakpoints, Up: Session Support + +Tracing +------- + + `(require 'trace)' + + - Macro: trace PROC1 ... + Traces the top-level named procedures given as arguments. + + - Macro: trace + With no arguments, makes sure that all the currently traced + identifiers are traced (even if those identifiers have been + redefined) and returns a list of the traced identifiers. + + - Macro: untrace PROC1 ... + Turns tracing off for its arguments. + + - Macro: untrace + With no arguments, untraces all currently traced identifiers and + returns a list of these formerly traced identifiers. + + The following routines are the procedures which actually do the +tracing when this module is supplied by SLIB, rather than natively. If +defmacros are not natively supported by your implementation, these might +be more convenient to use. + + - Function: tracef PROC + - Function: tracef PROC NAME + - Function: debug:tracef PROC + - Function: debug:tracef PROC NAME + To trace, type + (set! SYMBOL (tracef SYMBOL)) + + or + (set! SYMBOL (tracef SYMBOL 'SYMBOL)) + + or + (define SYMBOL (tracef FUNCTION)) + + or + (define SYMBOL (tracef FUNCTION 'SYMBOL)) + + - Function: untracef PROC + - Function: debug:untracef PROC + To untrace, type + (set! SYMBOL (untracef SYMBOL)) + + +File: slib.info, Node: System Interface, Prev: Trace, Up: Session Support + +System Interface +---------------- + +If `(provided? 'getenv)': + + - Function: getenv NAME + Looks up NAME, a string, in the program environment. If NAME is + found a string of its value is returned. Otherwise, `#f' is + returned. + +If `(provided? 'system)': + + - Function: system COMMAND-STRING + Executes the COMMAND-STRING on the computer and returns the + integer status code. + +If `system' is provided by the Scheme implementation, the "net-clients" +package provides interfaces to common network client programs like FTP, +mail, and Netscape. + + `(require 'net-clients)' + + - Function: call-with-tmpnam PROC + - Function: call-with-tmpnam PROC K + Calls PROC with K arguments, strings returned by successive calls + to `tmpnam'. If PROC returns, then any files named by the + arguments to PROC are deleted automatically and the value(s) + yielded by the PROC is(are) returned. K may be ommited, in which + case it defaults to `1'. + + - Function: user-email-address + `user-email-address' returns a string of the form + `username@hostname'. If this e-mail address cannot be obtained, + #f is returned. + + - Function: current-directory + `current-directory' returns a string containing the absolute file + name representing the current working directory. If this string + cannot be obtained, #f is returned. + + If `current-directory' cannot be supported by the platform, the + value of `current-directory' is #f. + + - Function: make-directory NAME + Creates a sub-directory NAME of the current-directory. If + successful, `make-directory' returns #t; otherwise #f. + + - Function: null-directory? FILE-NAME + Returns #t if changing directory to FILE-NAME makes the current + working directory the same as it is before changing directory; + otherwise returns #f. + + - Function: absolute-path? FILE-NAME + Returns #t if FILE-NAME is a fully specified pathname (does not + depend on the current working directory); otherwise returns #f. + + - Function: glob-pattern? STR + Returns #t if the string STR contains characters used for + specifying glob patterns, namely `*', `?', or `['. + + - Function: parse-ftp-address URL + Returns a list of the decoded FTP URL; or #f if indecipherable. + FTP "Uniform Resource Locator", "ange-ftp", and "getit" formats + are handled. The returned list has four elements which are + strings or #f: + + 0. username + + 1. password + + 2. remote-site + + 3. remote-directory + + - Function: ftp-upload PATHS USER PASSWORD REMOTE-SITE REMOTE-DIR + PASSWORD must be a non-empty string or #f. PATHS must be a + non-empty list of pathnames or Glob patterns (*note Filenames::.) + matching files to transfer. + + `ftp-upload' puts the files specified by PATHS into the REMOTE-DIR + directory of FTP REMOTE-SITE using name USER with (optional) + PASSWORD. + + If PASSWORD is #f and USER is not `ftp' or `anonymous', then USER + is ignored; FTP takes the username and password from the `.netrc' + or equivalent file. + + - Function: path->url PATH + Returns a URL-string for PATH on the local host. + + - Function: browse-url-netscape URL + If a `netscape' browser is running, `browse-url-netscape' causes + the browser to display the page specified by string URL and + returns #t. + + If the browser is not running, `browse-url-netscape' runs + `netscape' with the argument URL. If the browser starts as a | + background job, `browse-url-netscape' returns #t immediately; if | + the browser starts as a foreground job, then `browse-url-netscape' | + returns #t when the browser exits; otherwise it returns #f. | + + +File: slib.info, Node: Extra-SLIB Packages, Prev: Session Support, Up: Other Packages + +Extra-SLIB Packages +=================== + + Several Scheme packages have been written using SLIB. There are +several reasons why a package might not be included in the SLIB +distribution: + * Because it requires special hardware or software which is not + universal. + + * Because it is large and of limited interest to most Scheme users. + + * Because it has copying terms different enough from the other SLIB + packages that its inclusion would cause confusion. + + * Because it is an application program, rather than a library module. + + * Because I have been too busy to integrate it. + + Once an optional package is installed (and an entry added to +`*catalog*', the `require' mechanism allows it to be called up and used +as easily as any other SLIB package. Some optional packages (for which +`*catalog*' already has entries) available from SLIB sites are: + +SLIB-PSD is a portable debugger for Scheme (requires emacs editor). + http://swissnet.ai.mit.edu/ftpdir/scm/slib-psd1-3.tar.gz | + ftp.gnu.org:pub/gnu/jacal/slib-psd1-3.tar.gz + ftp.maths.tcd.ie:pub/bosullvn/jacal/slib-psd1-3.tar.gz + ftp.cs.indiana.edu:/pub/scheme-repository/utl/slib-psd1-3.tar.gz + + With PSD, you can run a Scheme program in an Emacs buffer, set + breakpoints, single step evaluation and access and modify the + program's variables. It works by instrumenting the original source + code, so it should run with any R4RS compliant Scheme. It has been + tested with SCM, Elk 1.5, and the sci interpreter in the Scheme->C + system, but should work with other Schemes with a minimal amount + of porting, if at all. Includes documentation and user's manual. + Written by Pertti Kellom\"aki, pk@cs.tut.fi. The Lisp Pointers + article describing PSD (Lisp Pointers VI(1):15-23, January-March + 1993) is available as + `http://www.cs.tut.fi/staff/pk/scheme/psd/article/article.html' + +SCHELOG is an embedding of Prolog in Scheme. + `http://www.cs.rice.edu/CS/PLT/packages/schelog/' + + +File: slib.info, Node: About SLIB, Next: Index, Prev: Other Packages, Up: Top + +About SLIB +********** + +More people than I can name have contributed to SLIB. Thanks to all of | +you! | + | + SLIB 2c7, released December 1999. | + Aubrey Jaffer <jaffer @ ai.mit.edu> | + Hyperactive Software - The Maniac Inside! | + `http://swissnet.ai.mit.edu/~jaffer/SLIB.html' | + | +* Menu: + +* Installation:: How to install SLIB on your system. +* Porting:: SLIB to new platforms. +* Coding Standards:: How to write modules for SLIB. +* Copyrights:: Intellectual propery issues. + | + +File: slib.info, Node: Installation, Next: Porting, Prev: About SLIB, Up: About SLIB + +Installation +============ + + Check the manifest in `README' to find a configuration file for your +Scheme implementation. Initialization files for most IEEE P1178 +compliant Scheme Implementations are included with this distribution. + + If the Scheme implementation supports `getenv', then the value of the +shell environment variable SCHEME_LIBRARY_PATH will be used for +`(library-vicinity)' if it is defined. Currently, Chez, Elk, +MITScheme, scheme->c, VSCM, and SCM support `getenv'. Scheme48 +supports `getenv' but does not use it for determining +`library-vicinity'. (That is done from the Makefile.) + + You should check the definitions of `software-type', +`scheme-implementation-version', `implementation-vicinity', and +`library-vicinity' in the initialization file. There are comments in +the file for how to configure it. + + Once this is done you can modify the startup file for your Scheme +implementation to `load' this initialization file. SLIB is then +installed. + + Multiple implementations of Scheme can all use the same SLIB +directory. Simply configure each implementation's initialization file +as outlined above. + + The SCM implementation does not require any initialization file as +SLIB support is already built in to SCM. See the documentation with +SCM for installation instructions. + + SLIB includes methods to create heap images for the VSCM and Scheme48 +implementations. The instructions for creating a VSCM image are in +comments in `vscm.init'. To make a Scheme48 image for an installation +under `<prefix>', `cd' to the SLIB directory and type `make +prefix=<prefix> slib48'. To install the image, type `make +prefix=<prefix> install48'. This will also create a shell script with +the name `slib48' which will invoke the saved image. + + +File: slib.info, Node: Porting, Next: Coding Standards, Prev: Installation, Up: About SLIB + +Porting +======= + + If there is no initialization file for your Scheme implementation, you +will have to create one. Your Scheme implementation must be largely +compliant with `IEEE Std 1178-1990', `Revised^4 Report on the +Algorithmic Language Scheme', or `Revised^5 Report on the Algorithmic +Language Scheme' in order to support SLIB. (1) + + `Template.scm' is an example configuration file. The comments inside +will direct you on how to customize it to reflect your system. Give +your new initialization file the implementation's name with `.init' +appended. For instance, if you were porting `foo-scheme' then the +initialization file might be called `foo.init'. + + Your customized version should then be loaded as part of your scheme +implementation's initialization. It will load `require.scm' from the +library; this will allow the use of `provide', `provided?', and +`require' along with the "vicinity" functions (these functions are +documented in the section *Note Require::). The rest of the library +will then be accessible in a system independent fashion. + + Please mail new working configuration files to `jaffer @ ai.mit.edu' +so that they can be included in the SLIB distribution. + + ---------- Footnotes ---------- + + (1) If you are porting a `Revised^3 Report on the Algorithmic +Language Scheme' implementation, then you will need to finish writing +`sc4sc3.scm' and `load' it from your initialization file. + + +File: slib.info, Node: Coding Standards, Next: Copyrights, Prev: Porting, Up: About SLIB + +Coding Standards +================ + + All library packages are written in IEEE P1178 Scheme and assume that +a configuration file and `require.scm' package have already been +loaded. Other versions of Scheme can be supported in library packages +as well by using, for example, `(provided? 'rev3-report)' or `(require +'rev3-report)' (*note Require::.). + + The module name and `:' should prefix each symbol defined in the +package. Definitions for external use should then be exported by having +`(define foo module-name:foo)'. + + Code submitted for inclusion in SLIB should not duplicate routines +already in SLIB files. Use `require' to force those library routines +to be used by your package. Care should be taken that there are no +circularities in the `require's and `load's between the library +packages. + + Documentation should be provided in Emacs Texinfo format if possible, +But documentation must be provided. + + Your package will be released sooner with SLIB if you send me a file +which tests your code. Please run this test *before* you send me the +code! + +Modifications +------------- + + Please document your changes. A line or two for `ChangeLog' is +sufficient for simple fixes or extensions. Look at the format of +`ChangeLog' to see what information is desired. Please send me `diff' +files from the latest SLIB distribution (remember to send `diff's of +`slib.texi' and `ChangeLog'). This makes for less email traffic and +makes it easier for me to integrate when more than one person is +changing a file (this happens a lot with `slib.texi' and `*.init' +files). + + If someone else wrote a package you want to significantly modify, +please try to contact the author, who may be working on a new version. +This will insure against wasting effort on obsolete versions. + + Please *do not* reformat the source code with your favorite +beautifier, make 10 fixes, and send me the resulting source code. I do +not have the time to fish through 10000 diffs to find your 10 real +fixes. + + +File: slib.info, Node: Copyrights, Prev: Coding Standards, Up: About SLIB + +Copyrights +========== + + This section has instructions for SLIB authors regarding copyrights. + + Each package in SLIB must either be in the public domain, or come +with a statement of terms permitting users to copy, redistribute and +modify it. The comments at the beginning of `require.scm' and +`macwork.scm' illustrate copyright and appropriate terms. + + If your code or changes amount to less than about 10 lines, you do not +need to add your copyright or send a disclaimer. + +Putting code into the Public Domain +----------------------------------- + + In order to put code in the public domain you should sign a copyright +disclaimer and send it to the SLIB maintainer. Contact jaffer @ +ai.mit.edu for the address to mail the disclaimer to. + + I, NAME, hereby affirm that I have placed the software package + NAME in the public domain. + + I affirm that I am the sole author and sole copyright holder for + the software package, that I have the right to place this software + package in the public domain, and that I will do nothing to + undermine this status in the future. + + SIGNATURE AND DATE + + This wording assumes that you are the sole author. If you are not the +sole author, the wording needs to be different. If you don't want to be +bothered with sending a letter every time you release or modify a +module, make your letter say that it also applies to your future +revisions of that module. + + Make sure no employer has any claim to the copyright on the work you +are submitting. If there is any doubt, create a copyright disclaimer +and have your employer sign it. Mail the signed disclaimer to the SLIB +maintainer. Contact jaffer @ ai.mit.edu for the address to mail the +disclaimer to. An example disclaimer follows. + +Explicit copying terms +---------------------- + +If you submit more than about 10 lines of code which you are not placing +into the Public Domain (by sending me a disclaimer) you need to: + + * Arrange that your name appears in a copyright line for the + appropriate year. Multiple copyright lines are acceptable. + + * With your copyright line, specify any terms you require to be + different from those already in the file. + + * Make sure no employer has any claim to the copyright on the work + you are submitting. If there is any doubt, create a copyright + disclaimer and have your employer sign it. Mail the signed + disclaim to the SLIB maintainer. Contact jaffer @ ai.mit.edu for + the address to mail the disclaimer to. + +Example: Company Copyright Disclaimer +------------------------------------- + + This disclaimer should be signed by a vice president or general +manager of the company. If you can't get at them, anyone else +authorized to license out software produced there will do. Here is a +sample wording: + + EMPLOYER Corporation hereby disclaims all copyright interest in + the program PROGRAM written by NAME. + + EMPLOYER Corporation affirms that it has no other intellectual + property interest that would undermine this release, and will do + nothing to undermine it in the future. + + SIGNATURE AND DATE, + NAME, TITLE, EMPLOYER Corporation + + +File: slib.info, Node: Index, Prev: About SLIB, Up: Top + +Procedure and Macro Index +************************* + + This is an alphabetical list of all the procedures and macros in SLIB. + +* Menu: + +* -: Multi-argument / and -. +* -1+: Rev2 Procedures. +* /: Multi-argument / and -. +* 1+: Rev2 Procedures. +* <=?: Rev2 Procedures. +* <?: Rev2 Procedures. +* =?: Rev2 Procedures. +* >=?: Rev2 Procedures. +* >?: Rev2 Procedures. +* absolute-path?: System Interface. +* add-domain: Database Utilities. +* add-process!: Multi-Processing. +* add-setter: Setters. +* adjoin: Lists as sets. +* adjoin-parameters!: Parameter lists. +* alarm: Multi-Processing. +* alarm-interrupt: Multi-Processing. +* alist->wt-tree: Construction of Weight-Balanced Trees. +* alist-associator: Association Lists. +* alist-for-each: Association Lists. +* alist-inquirer: Association Lists. +* alist-map: Association Lists. +* alist-remover: Association Lists. +* and?: Non-List functions. +* any?: Collections. +* append!: Rev2 Procedures. +* apply: Multi-argument Apply. +* array-1d-ref: Arrays. +* array-1d-set!: Arrays. +* array-2d-ref: Arrays. +* array-2d-set!: Arrays. +* array-3d-ref: Arrays. +* array-3d-set!: Arrays. +* array-copy!: Array Mapping. +* array-dimensions: Arrays. +* array-for-each: Array Mapping. +* array-in-bounds?: Arrays. +* array-index-map!: Array Mapping. +* array-indexes: Array Mapping. +* array-map!: Array Mapping. +* array-rank: Arrays. +* array-ref: Arrays. +* array-set!: Arrays. +* array-shape: Arrays. +* array?: Arrays. +* asctime: Posix Time. +* ash: Bit-Twiddling. +* atom?: Non-List functions. | +* batch:call-with-output-script: Batch. +* batch:command: Batch. | +* batch:comment: Batch. +* batch:delete-file: Batch. +* batch:initialize!: Batch. +* batch:lines->file: Batch. +* batch:rename-file: Batch. +* batch:run-script: Batch. +* batch:try-chopped-command: Batch. | +* batch:try-command: Batch. | +* bit-extract: Bit-Twiddling. +* bit-field: Bit-Twiddling. +* bitwise-if: Bit-Twiddling. +* break: Breakpoints. +* break-all: Debug. +* breakf: Breakpoints. +* breakpoint: Breakpoints. +* browse: Database Browser. +* browse-url-netscape: System Interface. +* butlast: Lists as sequences. +* butnthcdr: Lists as sequences. +* byte-ref: Byte. +* byte-set!: Byte. +* bytes: Byte. +* bytes->list: Byte. +* bytes-length: Byte. +* call-with-dynamic-binding: Dynamic Data Type. +* call-with-input-string: String Ports. +* call-with-output-string: String Ports. +* call-with-tmpnam: System Interface. +* call-with-values: Values. +* capture-syntactic-environment: Syntactic Closures. +* cart-prod-tables: Relational Database Operations. +* catalog->html: HTML HTTP and CGI. +* catalog->page: HTML HTTP and CGI. +* cgi:read-query-string: HTML HTTP and CGI. +* cgi:serve-command: HTML HTTP and CGI. +* chap:next-string: Chapter Ordering. +* chap:string<=?: Chapter Ordering. +* chap:string<?: Chapter Ordering. +* chap:string>=?: Chapter Ordering. +* chap:string>?: Chapter Ordering. +* check-parameters: Parameter lists. +* close-base: Base Table. +* close-database: Relational Database Operations. +* close-table: Table Operations. +* coerce: Non-List functions. +* collection?: Collections. +* combined-rulesets: Commutative Rings. +* command->html: HTML HTTP and CGI. +* continue: Breakpoints. +* copy-bit: Bit-Twiddling. +* copy-bit-field: Bit-Twiddling. +* copy-list: List construction. +* copy-random-state: Random Numbers. +* copy-tree: Tree Operations. +* create-database <1>: Database Utilities. +* create-database: Creating and Opening Relational Databases. +* create-report: Database Reports. +* create-table: Relational Database Operations. +* create-view: Relational Database Operations. +* cring:define-rule: Commutative Rings. +* ctime: Posix Time. +* current-directory: System Interface. +* current-error-port: Input/Output. +* current-input-port <1>: Byte. +* current-input-port: Ruleset Definition and Use. +* current-output-port: Byte. +* current-time: Time and Date. +* debug:breakf: Breakpoints. +* debug:tracef: Trace. +* debug:unbreakf: Breakpoints. +* debug:untracef: Trace. +* decode-universal-time: Common-Lisp Time. +* define-access-operation: Setters. +* define-operation: Yasos interface. +* define-predicate: Yasos interface. +* define-record: Structures. +* define-syntax: Macro by Example. +* define-tables: Database Utilities. +* defmacro: Defmacro. +* defmacro:eval: Defmacro. +* defmacro:expand*: Defmacro. +* defmacro:load: Defmacro. +* defmacro?: Defmacro. +* delete <1>: Destructive list operations. +* delete: Base Table. +* delete*: Base Table. +* delete-domain: Database Utilities. +* delete-file: Input/Output. +* delete-if: Destructive list operations. +* delete-if-not: Destructive list operations. +* delete-table: Relational Database Operations. +* dequeue!: Queues. +* difftime: Time and Date. +* display-file: Line I/O. +* do-elts: Collections. +* do-keys: Collections. +* domain-checker: Database Utilities. +* dynamic-ref: Dynamic Data Type. +* dynamic-set!: Dynamic Data Type. +* dynamic-wind: Dynamic-Wind. +* dynamic?: Dynamic Data Type. +* empty?: Collections. +* encode-universal-time: Common-Lisp Time. +* enquque!: Queues. +* equal?: Byte. +* eval: Eval. +* every: Lists as sets. +* every?: Collections. +* extended-euclid: Modular Arithmetic. +* factor: Prime Numbers. +* fft: Fast Fourier Transform. +* fft-1: Fast Fourier Transform. +* file-exists?: Input/Output. +* filename:match-ci??: Filenames. +* filename:match??: Filenames. +* filename:substitute-ci??: Filenames. +* filename:substitute??: Filenames. +* fill-empty-parameters: Parameter lists. +* find-if: Lists as sets. +* find-string-from-port?: String Search. +* fluid-let: Fluid-Let. +* for-each-elt: Collections. +* for-each-key <1>: Collections. +* for-each-key: Base Table. +* for-each-row: Table Operations. +* force-output: Input/Output. +* format: Format Interface. +* fprintf: Standard Formatted Output. +* fscanf: Standard Formatted Input. +* ftp-upload: System Interface. +* generic-write: Generic-Write. +* gentemp: Defmacro. +* get: Table Operations. +* get*: Table Operations. +* get-decoded-time: Common-Lisp Time. +* get-method: Object. +* get-universal-time: Common-Lisp Time. +* getenv: System Interface. +* getopt: Getopt. +* getopt--: Getopt. +* getopt->arglist: Getopt Parameter lists. +* getopt->parameter-list: Getopt Parameter lists. +* glob-pattern?: System Interface. +* gmktime: Posix Time. +* gmtime: Posix Time. +* gtime: Posix Time. +* has-duplicates?: Lists as sets. +* hash: Hashing. +* hash-associator: Hash Tables. +* hash-for-each: Hash Tables. +* hash-inquirer: Hash Tables. +* hash-map: Hash Tables. +* hash-remover: Hash Tables. +* hashq: Hashing. +* hashv: Hashing. +* heap-extract-max!: Priority Queues. +* heap-insert!: Priority Queues. +* heap-length: Priority Queues. +* home-vicinity: Vicinity. +* html:comment: HTML HTTP and CGI. +* html:end-form: HTML HTTP and CGI. +* html:end-page: HTML HTTP and CGI. +* html:end-table: HTML HTTP and CGI. +* html:heading: HTML HTTP and CGI. +* html:href-heading: HTML HTTP and CGI. +* html:pre: HTML HTTP and CGI. +* html:start-form: HTML HTTP and CGI. +* html:start-page: HTML HTTP and CGI. +* html:start-table: HTML HTTP and CGI. +* http:read-request-line: HTML HTTP and CGI. +* http:serve-query: HTML HTTP and CGI. +* identifier=?: Syntactic Closures. +* identifier?: Syntactic Closures. +* identity: Legacy. +* implementation-vicinity: Vicinity. +* in-vicinity: Vicinity. +* init-debug: Breakpoints. +* integer-expt: Bit-Twiddling. +* integer-length: Bit-Twiddling. +* integer-sqrt: Root Finding. +* interaction-environment: Eval. +* intersection: Lists as sets. +* jacobi-symbol: Prime Numbers. +* kill-process!: Multi-Processing. +* kill-table: Base Table. +* laguerre:find-polynomial-root: Root Finding. +* laguerre:find-root: Root Finding. +* last: Lists as sequences. +* last-pair: Legacy. +* library-vicinity: Vicinity. +* list*: List construction. +* list->bytes: Byte. +* list->string: Rev4 Optional Procedures. +* list->vector: Rev4 Optional Procedures. +* list-tail: Rev4 Optional Procedures. +* load-option: Weight-Balanced Trees. +* localtime: Posix Time. +* logand: Bit-Twiddling. +* logbit?: Bit-Twiddling. +* logcount: Bit-Twiddling. +* logior: Bit-Twiddling. +* lognot: Bit-Twiddling. +* logtest: Bit-Twiddling. +* logxor: Bit-Twiddling. +* macro:eval <1>: Syntax-Case Macros. +* macro:eval <2>: Syntactic Closures. +* macro:eval <3>: Macros That Work. +* macro:eval: R4RS Macros. +* macro:expand <1>: Syntax-Case Macros. +* macro:expand <2>: Syntactic Closures. +* macro:expand <3>: Macros That Work. +* macro:expand: R4RS Macros. +* macro:load <1>: Syntax-Case Macros. +* macro:load <2>: Syntactic Closures. +* macro:load <3>: Macros That Work. +* macro:load: R4RS Macros. +* macroexpand: Defmacro. +* macroexpand-1: Defmacro. +* macwork:eval: Macros That Work. +* macwork:expand: Macros That Work. +* macwork:load: Macros That Work. +* make-: Structures. +* make-array: Arrays. +* make-atval: HTML HTTP and CGI. +* make-base: Base Table. +* make-bytes: Byte. +* make-command-server: Database Utilities. +* make-directory: System Interface. +* make-dynamic: Dynamic Data Type. +* make-generic-method: Object. +* make-generic-predicate: Object. +* make-getter: Base Table. +* make-hash-table: Hash Tables. +* make-heap: Priority Queues. +* make-key->list: Base Table. +* make-key-extractor: Base Table. +* make-keyifier-1: Base Table. +* make-list: List construction. +* make-list-keyifier: Base Table. +* make-method!: Object. +* make-object: Object. +* make-parameter-list: Parameter lists. +* make-plain: HTML HTTP and CGI. +* make-port-crc: Cyclic Checksum. +* make-predicate!: Object. +* make-promise: Promises. +* make-putter: Base Table. +* make-queue: Queues. +* make-random-state: Random Numbers. +* make-record-type: Records. +* make-relational-system: Creating and Opening Relational Databases. +* make-row-converter: HTML HTTP and CGI. +* make-ruleset: Commutative Rings. +* make-shared-array: Arrays. +* make-sierpinski-indexer: Hashing. +* make-syntactic-closure: Syntactic Closures. +* make-table: Base Table. +* make-vicinity: Vicinity. +* make-wt-tree: Construction of Weight-Balanced Trees. +* make-wt-tree-type: Construction of Weight-Balanced Trees. +* map-elts: Collections. +* map-key: Base Table. +* map-keys: Collections. +* member-if: Lists as sets. +* merge: Sorting. +* merge!: Sorting. +* mktime: Posix Time. +* modular:: Modular Arithmetic. +* modular:*: Modular Arithmetic. +* modular:+: Modular Arithmetic. +* modular:expt: Modular Arithmetic. +* modular:invert: Modular Arithmetic. +* modular:invertable?: Modular Arithmetic. +* modular:negate: Modular Arithmetic. +* modular:normalize: Modular Arithmetic. +* modulus->integer: Modular Arithmetic. +* must-be-first: Batch. +* must-be-last: Batch. +* nconc: Destructive list operations. +* newton:find-root: Root Finding. +* newtown:find-integer-root: Root Finding. +* notany: Lists as sets. +* notevery: Lists as sets. +* nreverse: Destructive list operations. +* nthcdr: Lists as sequences. +* null-directory?: System Interface. +* null-environment: Eval. +* object: Yasos interface. +* object->limited-string: Object-To-String. +* object->string: Object-To-String. +* object-with-ancestors: Yasos interface. +* object?: Object. +* offset-time: Time and Date. +* open-base: Base Table. +* open-database <1>: Database Utilities. +* open-database: Creating and Opening Relational Databases. +* open-database!: Database Utilities. +* open-table <1>: Relational Database Operations. +* open-table: Base Table. +* operate-as: Yasos interface. +* or?: Non-List functions. +* ordered-for-each-key: Base Table. +* os->batch-dialect: Batch. +* output-port-height: Input/Output. +* output-port-width: Input/Output. +* parameter-list->arglist: Parameter lists. +* parameter-list-expand: Parameter lists. +* parameter-list-ref: Parameter lists. +* parse-ftp-address: System Interface. +* path->url: System Interface. +* plot!: Plotting. +* position: Lists as sequences. +* pprint-file: Pretty-Print. +* pprint-filter-file: Pretty-Print. +* prec:commentfix: Grammar Rule Definition. +* prec:define-grammar: Ruleset Definition and Use. +* prec:delim: Grammar Rule Definition. +* prec:infix: Grammar Rule Definition. +* prec:inmatchfix: Grammar Rule Definition. +* prec:make-led: Nud and Led Definition. +* prec:make-nud: Nud and Led Definition. +* prec:matchfix: Grammar Rule Definition. +* prec:nary: Grammar Rule Definition. +* prec:nofix: Grammar Rule Definition. +* prec:parse: Ruleset Definition and Use. +* prec:postfix: Grammar Rule Definition. +* prec:prefix: Grammar Rule Definition. +* prec:prestfix: Grammar Rule Definition. +* predicate->asso: Association Lists. +* predicate->hash: Hash Tables. +* predicate->hash-asso: Hash Tables. +* present?: Base Table. +* pretty-print: Pretty-Print. +* prime?: Prime Numbers. +* primes<: Prime Numbers. +* primes>: Prime Numbers. +* print: Yasos interface. +* printf: Standard Formatted Output. +* process:schedule!: Multi-Processing. +* program-vicinity: Vicinity. +* project-table: Relational Database Operations. +* provide <1>: Require. +* provide: Feature. +* provided? <1>: Require. +* provided?: Feature. +* qp: Quick Print. +* qpn: Quick Print. +* qpr: Quick Print. +* queue-empty?: Queues. +* queue-front: Queues. +* queue-pop!: Queues. +* queue-push!: Queues. +* queue-rear: Queues. +* queue?: Queues. +* random: Random Numbers. +* random:exp: Random Numbers. +* random:hollow-sphere!: Random Numbers. +* random:normal: Random Numbers. +* random:normal-vector!: Random Numbers. +* random:solid-sphere!: Random Numbers. +* random:uniform: Random Numbers. +* rationalize: Rationalize. +* read-byte: Byte. +* read-command: Command Line. +* read-line: Line I/O. +* read-line!: Line I/O. +* read-options-file: Command Line. +* record-accessor: Records. +* record-constructor: Records. +* record-modifier: Records. +* record-predicate: Records. +* reduce <1>: Lists as sequences. +* reduce: Collections. +* reduce-init: Lists as sequences. +* remove: Lists as sets. +* remove-duplicates: Lists as sets. +* remove-if: Lists as sets. +* remove-if-not: Lists as sets. +* remove-setter-for: Setters. +* repl:quit: Repl. +* repl:top-level: Repl. +* replace-suffix: Filenames. +* require <1>: Require. +* require <2>: Catalog Compilation. +* require: Requesting Features. +* require:feature->path <1>: Require. +* require:feature->path: Requesting Features. +* restrict-table: Relational Database Operations. +* row:delete: Table Operations. +* row:delete*: Table Operations. +* row:insert: Table Operations. +* row:insert*: Table Operations. +* row:remove: Table Operations. +* row:remove*: Table Operations. +* row:retrieve: Table Operations. +* row:retrieve*: Table Operations. +* row:update: Table Operations. +* row:update*: Table Operations. +* scanf: Standard Formatted Input. +* scanf-read-list: Standard Formatted Input. +* scheme-report-environment: Eval. +* schmooz: Schmooz. +* secant:find-bracketed-root: Root Finding. +* secant:find-root: Root Finding. +* seed->random-state: Random Numbers. +* serve-urlencoded-command: HTML HTTP and CGI. +* set: Setters. +* set-: Structures. +* set-difference: Lists as sets. +* Setter: Collections. +* setter: Setters. +* singleton-wt-tree: Construction of Weight-Balanced Trees. +* size <1>: Collections. +* size: Yasos interface. +* slib:error: System. +* slib:eval: System. +* slib:eval-load: System. +* slib:exit: System. +* slib:load: System. +* slib:load-compiled: System. +* slib:load-source: System. +* slib:report: Configuration. +* slib:report-version: Configuration. +* slib:warn: System. +* software-type: Configuration. +* some: Lists as sets. +* sort: Sorting. +* sort!: Sorting. +* sorted?: Sorting. +* soundex: Hashing. +* sprintf: Standard Formatted Output. +* sscanf: Standard Formatted Input. +* string->list: Rev4 Optional Procedures. +* string-capitalize: String-Case. +* string-captialize!: String-Case. +* string-ci->symbol: String-Case. +* string-copy: Rev4 Optional Procedures. +* string-downcase: String-Case. +* string-downcase!: String-Case. +* string-fill!: Rev4 Optional Procedures. +* string-index: String Search. +* string-index-ci: String Search. +* string-join: Batch. +* string-null?: Rev2 Procedures. +* string-reverse-index: String Search. +* string-reverse-index-ci: String Search. +* string-subst: String Search. +* string-upcase: String-Case. +* string-upcase!: String-Case. +* sub-vicinity: Vicinity. +* subst: Tree Operations. +* substq: Tree Operations. +* substring-ci?: String Search. +* substring-fill!: Rev2 Procedures. +* substring-move-left!: Rev2 Procedures. +* substring-move-right!: Rev2 Procedures. +* substring?: String Search. +* substv: Tree Operations. +* supported-key-type?: Base Table. +* supported-type?: Base Table. +* symmetric:modulus: Modular Arithmetic. +* sync-base: Base Table. +* syncase:eval: Syntax-Case Macros. +* syncase:expand: Syntax-Case Macros. +* syncase:load: Syntax-Case Macros. +* synclo:eval: Syntactic Closures. +* synclo:expand: Syntactic Closures. +* synclo:load: Syntactic Closures. +* syntax-rules: Macro by Example. +* system: System Interface. +* table->html: HTML HTTP and CGI. +* table->page: HTML HTTP and CGI. +* table-exists?: Relational Database Operations. +* table-name->filename: HTML HTTP and CGI. +* TAG: Structures. +* tek40:draw: Tektronix Graphics Support. +* tek40:graphics: Tektronix Graphics Support. +* tek40:init: Tektronix Graphics Support. +* tek40:linetype: Tektronix Graphics Support. +* tek40:move: Tektronix Graphics Support. +* tek40:put-text: Tektronix Graphics Support. +* tek40:reset: Tektronix Graphics Support. +* tek40:text: Tektronix Graphics Support. +* tek41:draw: Tektronix Graphics Support. +* tek41:encode-int: Tektronix Graphics Support. +* tek41:encode-x-y: Tektronix Graphics Support. +* tek41:graphics: Tektronix Graphics Support. +* tek41:init: Tektronix Graphics Support. +* tek41:move: Tektronix Graphics Support. +* tek41:point: Tektronix Graphics Support. +* tek41:reset: Tektronix Graphics Support. +* time-zone: Time Zone. +* tmpnam: Input/Output. +* tok:char-group: Token definition. +* topological-sort: Topological Sort. +* trace: Trace. +* trace-all: Debug. +* tracef: Trace. +* transcript-off: Transcripts. +* transcript-on: Transcripts. +* transformer: Syntactic Closures. +* truncate-up-to: Batch. +* tsort: Topological Sort. +* two-arg:-: Multi-argument / and -. +* two-arg:/: Multi-argument / and -. +* two-arg:apply: Multi-argument Apply. +* type-of: Non-List functions. +* tz:params: Time Zone. +* tzset: Time Zone. +* unbreak: Breakpoints. +* unbreakf: Breakpoints. +* union: Lists as sets. +* unmake-method!: Object. +* untrace: Trace. +* untracef: Trace. +* user-email-address: System Interface. +* user-vicinity: Vicinity. +* values: Values. +* variant-case: Structures. +* vector->list: Rev4 Optional Procedures. +* vector-fill!: Rev4 Optional Procedures. +* with-input-from-file: With-File. +* with-output-to-file: With-File. +* write-base: Base Table. +* write-byte: Byte. +* write-database: Relational Database Operations. +* write-line: Line I/O. +* wt-tree/add: Basic Operations on Weight-Balanced Trees. +* wt-tree/add!: Basic Operations on Weight-Balanced Trees. +* wt-tree/delete: Basic Operations on Weight-Balanced Trees. +* wt-tree/delete!: Basic Operations on Weight-Balanced Trees. +* wt-tree/delete-min: Indexing Operations on Weight-Balanced Trees. +* wt-tree/delete-min!: Indexing Operations on Weight-Balanced Trees. +* wt-tree/difference: Advanced Operations on Weight-Balanced Trees. +* wt-tree/empty?: Basic Operations on Weight-Balanced Trees. +* wt-tree/fold: Advanced Operations on Weight-Balanced Trees. +* wt-tree/for-each: Advanced Operations on Weight-Balanced Trees. +* wt-tree/index: Indexing Operations on Weight-Balanced Trees. +* wt-tree/index-datum: Indexing Operations on Weight-Balanced Trees. +* wt-tree/index-pair: Indexing Operations on Weight-Balanced Trees. +* wt-tree/intersection: Advanced Operations on Weight-Balanced Trees. +* wt-tree/lookup: Basic Operations on Weight-Balanced Trees. +* wt-tree/member?: Basic Operations on Weight-Balanced Trees. +* wt-tree/min: Indexing Operations on Weight-Balanced Trees. +* wt-tree/min-datum: Indexing Operations on Weight-Balanced Trees. +* wt-tree/min-pair: Indexing Operations on Weight-Balanced Trees. +* wt-tree/rank: Indexing Operations on Weight-Balanced Trees. +* wt-tree/set-equal?: Advanced Operations on Weight-Balanced Trees. +* wt-tree/size: Basic Operations on Weight-Balanced Trees. +* wt-tree/split<: Advanced Operations on Weight-Balanced Trees. +* wt-tree/split>: Advanced Operations on Weight-Balanced Trees. +* wt-tree/subset?: Advanced Operations on Weight-Balanced Trees. +* wt-tree/union: Advanced Operations on Weight-Balanced Trees. +* wt-tree?: Basic Operations on Weight-Balanced Trees. + +Variable Index +************** + + This is an alphabetical list of all the global variables in SLIB. + +* Menu: + +* *catalog*: Require. +* *features*: Require. +* *html:output-port*: HTML HTTP and CGI. +* *modules*: Require. +* *optarg*: Getopt. +* *optind*: Getopt. +* *qp-width*: Quick Print. +* *random-state*: Random Numbers. +* *ruleset*: Commutative Rings. +* *syn-defs*: Ruleset Definition and Use. +* *syn-ignore-whitespace*: Ruleset Definition and Use. +* *timezone*: Time Zone. +* batch:platform: Batch. +* catalog-id: Base Table. +* char-code-limit: Configuration. +* charplot:height: Plotting. +* charplot:width: Plotting. +* column-domains: Table Operations. +* column-foreigns: Table Operations. +* column-names: Table Operations. +* column-types: Table Operations. +* daylight?: Time Zone. +* distribute*: Commutative Rings. +* distribute/: Commutative Rings. +* most-positive-fixnum: Configuration. +* nil: Legacy. +* number-wt-type: Construction of Weight-Balanced Trees. +* primary-limit: Table Operations. +* prime:prngs: Prime Numbers. +* prime:trials: Prime Numbers. +* slib:form-feed: Configuration. +* slib:tab: Configuration. +* stderr: Standard Formatted I/O. +* stdin: Standard Formatted I/O. +* stdout: Standard Formatted I/O. +* string-wt-type: Construction of Weight-Balanced Trees. +* t: Legacy. +* tok:decimal-digits: Token definition. +* tok:lower-case: Token definition. +* tok:upper-case: Token definition. +* tok:whitespaces: Token definition. +* tzname: Time Zone. + +Concept and Feature Index +************************* + +* Menu: + +* alist: Association Lists. +* alist-table <1>: Creating and Opening Relational Databases. +* alist-table: Base Table. +* ange-ftp: System Interface. +* array: Arrays. +* array-for-each: Array Mapping. +* attribute-value: HTML HTTP and CGI. +* balanced binary trees: Weight-Balanced Trees. +* batch: Batch. +* binary trees: Weight-Balanced Trees. +* binary trees, as discrete maps: Weight-Balanced Trees. +* binary trees, as sets: Weight-Balanced Trees. +* break: Breakpoints. +* byte: Byte. +* calendar time <1>: Posix Time. +* calendar time: Time and Date. +* Calendar-Time: Posix Time. +* caltime: Posix Time. +* careful: Commutative Rings. +* catalog: Requesting Features. +* Catalog File: Library Catalogs. +* chapter-order: Chapter Ordering. +* charplot: Plotting. +* collect: Collections. +* command line: Command Line. +* commentfix: Precedence Parsing Overview. +* common-list-functions <1>: Common List Functions. +* common-list-functions: Collections. +* commutative-ring: Commutative Rings. +* Coordinated Universal Time: Posix Time. +* database-utilities <1>: Database Utilities. +* database-utilities: Batch. +* debug <1>: Breakpoints. +* debug: Debug. +* defmacroexpand <1>: Pretty-Print. +* defmacroexpand: Defmacro. +* delim: Precedence Parsing Overview. +* discrete maps, using binary trees: Weight-Balanced Trees. +* dynamic: Dynamic Data Type. +* dynamic-wind: Dynamic-Wind. +* Euclidean Domain: Commutative Rings. +* factor: Prime Numbers. +* feature <1>: About this manual. +* feature <2>: Requesting Features. +* feature: Feature. +* fft: Fast Fourier Transform. +* fluid-let <1>: Database Utilities. +* fluid-let: Fluid-Let. +* form: HTML HTTP and CGI. +* format: Format. +* generic-write: Generic-Write. +* getit: System Interface. +* getopt <1>: Database Utilities. +* getopt: Getopt. +* glob <1>: Batch. +* glob: Filenames. +* hash: Hashing. +* hash-table: Hash Tables. +* HOME <1>: Vicinity. +* HOME: Library Catalogs. +* homecat: Catalog Compilation. +* implcat: Catalog Compilation. +* infix: Precedence Parsing Overview. +* inmatchfix: Precedence Parsing Overview. +* Left Denotation, led: Nud and Led Definition. +* line-i: Line I/O. +* logical: Bit-Twiddling. +* macro <1>: Repl. +* macro: R4RS Macros. +* macro-by-example: Macro by Example. +* macros-that-work: Macros That Work. +* make-crc: Cyclic Checksum. +* match: Base Table. +* match-key: Base Table. +* match-keys: Table Operations. +* matchfix: Precedence Parsing Overview. +* minimum field width (printf): Standard Formatted Output. +* mkimpcat.scm: Catalog Compilation. +* mklibcat.scm: Catalog Compilation. +* modular: Modular Arithmetic. +* multiarg-apply: Multi-argument Apply. +* mutliarg: Multi-argument / and -. +* nary: Precedence Parsing Overview. +* net-clients: System Interface. +* nofix: Precedence Parsing Overview. +* Null Denotation, nud: Nud and Led Definition. +* object: Object. +* object->string: Object-To-String. +* oop: Yasos. +* option, run-time-loadable: Weight-Balanced Trees. +* options file: Command Line. | +* parameters <1>: Database Utilities. +* parameters <2>: Batch. +* parameters: Parameter lists. +* parse: Precedence Parsing. +* plain-text: HTML HTTP and CGI. +* posix-time: Posix Time. +* postfix: Precedence Parsing Overview. +* pprint-file: Pretty-Print. +* PRE: HTML HTTP and CGI. +* precedence: Precedence Parsing. +* precision (printf): Standard Formatted Output. +* prefix: Precedence Parsing Overview. +* prestfix: Precedence Parsing Overview. +* pretty-print: Pretty-Print. +* primes: Prime Numbers. +* printf: Standard Formatted Output. +* priority-queue: Priority Queues. +* PRNG: Random Numbers. +* process: Multi-Processing. +* promise: Promises. +* qp <1>: Quick Print. +* qp: Getopt. +* query-string: HTML HTTP and CGI. +* queue: Queues. +* random: Random Numbers. +* rationalize: Rationalize. +* read-command: Command Line. +* record: Records. +* relational-database: Relational Database. +* repl <1>: Repl. +* repl: Syntax-Case Macros. +* rev2-procedures: Rev2 Procedures. +* rev3-report: Coding Standards. +* rev4-optional-procedures: Rev4 Optional Procedures. +* ring, commutative: Commutative Rings. +* RNG: Random Numbers. +* root: Root Finding. +* run-time-loadable option: Weight-Balanced Trees. +* scanf: Standard Formatted Input. | +* schmooz: Schmooz. +* session: Feature. +* sets, using binary trees: Weight-Balanced Trees. +* sierpinski: Hashing. +* sitecat: Catalog Compilation. | +* slibcat: Catalog Compilation. +* sort: Sorting. +* soundex: Hashing. +* stdio: Standard Formatted I/O. +* string-case: String-Case. +* string-port: String Ports. +* string-search: String Search. +* struct: Structures. +* syntactic-closures: Syntactic Closures. +* syntax-case: Syntax-Case Macros. +* time: Time and Date. +* time-zone: Time Zone. +* topological-sort: Topological Sort. +* trace: Trace. +* transcript: Transcripts. +* tree: Tree Operations. +* trees, balanced binary: Weight-Balanced Trees. +* tsort: Topological Sort. +* TZ-string: Time Zone. +* Uniform Resource Locator: System Interface. +* Unique Factorization: Commutative Rings. +* usercat: Catalog Compilation. +* UTC: Posix Time. +* values: Values. +* weight-balanced binary trees: Weight-Balanced Trees. +* wild-card: Base Table. +* with-file: With-File. +* wt-tree: Weight-Balanced Trees. +* yasos: Yasos. + + + +Tag Table: +Node: Top1057 +Node: The Library System1870 +Node: Feature2184 +Node: Requesting Features3134 +Node: Library Catalogs4493 +Node: Catalog Compilation6945 +Node: Built-in Support9755 +Node: Require10386 +Node: Vicinity12879 +Node: Configuration15846 +Node: Input/Output18787 +Node: Legacy20386 +Node: System21228 +Node: About this manual23720 +Node: Scheme Syntax Extension Packages24277 +Node: Defmacro24962 +Node: R4RS Macros26912 +Node: Macro by Example28167 +Node: Macros That Work31043 +Node: Syntactic Closures37101 +Node: Syntax-Case Macros54534 +Node: Fluid-Let58661 +Node: Yasos59602 +Node: Yasos terms60395 +Node: Yasos interface61419 +Node: Setters63496 +Node: Yasos examples66138 +Node: Textual Conversion Packages69132 +Node: Precedence Parsing69708 +Node: Precedence Parsing Overview70371 +Node: Ruleset Definition and Use72572 +Node: Token definition74953 +Node: Nud and Led Definition77222 +Node: Grammar Rule Definition79671 +Node: Format87245 +Node: Format Interface87493 +Node: Format Specification89230 +Node: Standard Formatted I/O99287 +Node: Standard Formatted Output99853 +Node: Standard Formatted Input108913 +Node: Programs and Arguments115572 +Node: Getopt116085 +Node: Command Line121927 +Node: Parameter lists125116 +Node: Getopt Parameter lists128753 +Node: Filenames130948 +Node: Batch134178 +Node: HTML HTTP and CGI142791 +Node: Printing Scheme149960 +Node: Generic-Write150283 +Node: Object-To-String151686 +Node: Pretty-Print152090 +Node: Time and Date154036 +Node: Time Zone155063 +Node: Posix Time159625 +Node: Common-Lisp Time161761 +Node: Vector Graphics163340 +Node: Tektronix Graphics Support163529 +Node: Schmooz164903 +Node: Mathematical Packages169129 +Node: Bit-Twiddling169721 +Node: Modular Arithmetic174312 +Node: Prime Numbers176446 +Node: Random Numbers178453 +Node: Fast Fourier Transform183166 +Node: Cyclic Checksum184084 +Node: Plotting185802 +Node: Root Finding188377 +Node: Commutative Rings192371 +Node: Determinant203757 +Node: Database Packages204055 +Node: Base Table204319 +Node: Relational Database214477 +Node: Motivations215261 +Node: Creating and Opening Relational Databases220308 +Node: Relational Database Operations222740 +Node: Table Operations225537 +Node: Catalog Representation233415 +Node: Unresolved Issues236313 +Node: Database Utilities239264 +Node: Database Reports254919 +Node: Database Browser257674 +Node: Weight-Balanced Trees258735 +Node: Construction of Weight-Balanced Trees262605 +Node: Basic Operations on Weight-Balanced Trees266055 +Node: Advanced Operations on Weight-Balanced Trees269020 +Node: Indexing Operations on Weight-Balanced Trees275042 +Node: Other Packages278956 +Node: Data Structures279355 +Node: Arrays280074 +Node: Array Mapping283028 +Node: Association Lists284945 +Node: Byte287196 +Node: Collections289427 +Node: Dynamic Data Type295534 +Node: Hash Tables296795 +Node: Hashing298912 +Node: Object303687 +Node: Priority Queues311924 +Node: Queues312767 +Node: Records313893 +Node: Structures317404 +Node: Procedures318704 +Node: Common List Functions319391 +Node: List construction319815 +Node: Lists as sets321478 +Node: Lists as sequences326850 +Node: Destructive list operations332096 +Node: Non-List functions334760 +Node: Tree Operations336108 +Node: Chapter Ordering337654 +Node: Sorting339274 +Node: Topological Sort345051 +Node: String-Case346738 +Node: String Ports347359 +Node: String Search348123 +Node: Line I/O350490 +Node: Multi-Processing352139 +Node: Standards Support353223 +Node: With-File353878 +Node: Transcripts354154 +Node: Rev2 Procedures354475 +Node: Rev4 Optional Procedures356182 +Node: Multi-argument / and -356752 +Node: Multi-argument Apply357403 +Node: Rationalize357889 +Node: Promises358552 +Node: Dynamic-Wind358969 +Node: Eval360223 +Node: Values363560 +Node: Session Support364347 +Node: Repl364815 +Node: Quick Print366098 +Node: Debug367211 +Node: Breakpoints367853 +Node: Trace370071 +Node: System Interface371445 +Node: Extra-SLIB Packages375246 +Node: About SLIB377378 +Node: Installation378462 +Node: Porting380312 +Node: Coding Standards381829 +Node: Copyrights383908 +Node: Index387192 + +End Tag Table |