From: Chris Hanson Date: Tue, 15 Apr 2003 03:30:25 +0000 (+0000) Subject: Break up document into chapters. The 900kB single file was getting X-Git-Tag: 20090517-FFI~1926 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=39adb8cd46330403489c2ba52b654ce217214e2f;p=mit-scheme.git Break up document into chapters. The 900kB single file was getting too big to edit comfortably. --- diff --git a/v7/doc/ref-manual/Makefile.in b/v7/doc/ref-manual/Makefile.in index b6c92ebdb..8f5f10bfe 100644 --- a/v7/doc/ref-manual/Makefile.in +++ b/v7/doc/ref-manual/Makefile.in @@ -1,5 +1,5 @@ -# $Id: Makefile.in,v 1.6 2003/02/14 19:22:43 cph Exp $ +# $Id: Makefile.in,v 1.7 2003/04/15 03:29:18 cph Exp $ # # Copyright 2000,2001,2002,2003 Massachusetts Institute of Technology # @@ -63,25 +63,47 @@ htmldir = @htmldir@ pdfdir = @pdfdir@ psdir = @psdir@ +SOURCES = \ + scheme.texinfo \ + associations.texi \ + bit-strings.texi \ + characters.texi \ + environments.texi \ + equivalence.texi \ + error.texi \ + gfdl.texinfo \ + graphics.texi \ + io.texi \ + lists.texi \ + misc-datatypes.texi \ + numbers.texi \ + os-interface.texi \ + overview.texi \ + procedures.texi \ + special-forms.texi \ + strings.texi \ + vectors.texi \ + win32-packaging.texi + INFO_TARGET = mit-scheme-ref.info all: $(INFO_TARGET) scheme.html scheme.pdf scheme.ps -$(INFO_TARGET): scheme.texinfo gfdl.texinfo +$(INFO_TARGET): $(SOURCES) rm -f $(INFO_TARGET)* makeinfo --output=$(INFO_TARGET) scheme.texinfo -scheme.html: scheme.texinfo gfdl.texinfo +scheme.html: $(SOURCES) rm -f scheme*.html texi2html -split_chapter scheme.texinfo -scheme.pdf: scheme.texinfo gfdl.texinfo +scheme.pdf: $(SOURCES) texi2pdf scheme.texinfo scheme.ps: scheme.dvi dvips -o $@ $^ -scheme.dvi: scheme.texinfo gfdl.texinfo +scheme.dvi: $(SOURCES) texi2dvi scheme.texinfo AUX_SUFFIXES = aux log toc diff --git a/v7/doc/ref-manual/associations.texi b/v7/doc/ref-manual/associations.texi new file mode 100644 index 000000000..b6cc797bf --- /dev/null +++ b/v7/doc/ref-manual/associations.texi @@ -0,0 +1,1867 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: associations.texi,v 1.1 2003/04/15 03:29:22 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Associations, Procedures, Miscellaneous Datatypes, Top +@chapter Associations + +MIT/GNU Scheme provides several mechanisms for associating objects with +one another. Each of these mechanisms creates a link between one or +more objects, called @dfn{keys}, and some other object, called a +@dfn{datum}. Beyond this common idea, however, each of the mechanisms +has various different properties that make it appropriate in different +situations: + +@itemize @bullet +@item +@dfn{Association lists} are one of Lisp's oldest association mechanisms. +Because they are made from ordinary pairs, they are easy to build and +manipulate, and very flexible in use. However, the average lookup time +for an association list is linear in the number of associations. + +@item +@dfn{1D tables} have a very simple interface, making them easy to use, +and offer the feature that they do not prevent their keys from being +reclaimed by the garbage collector. Like association lists, their +average lookup time is linear in the number of associations; but 1D +tables aren't as flexible. + +@item +@cindex property list +@dfn{The association table} is MIT/GNU Scheme's equivalent to the +@dfn{property lists} of Lisp. It has the advantages that the keys may +be any type of object and that it does not prevent the keys from being +reclaimed by the garbage collector. However, two linear-time lookups +must be performed, one for each key, whereas for traditional property +lists only one lookup is required for both keys. + +@item +@dfn{Hash tables} are a powerful mechanism with constant-time access to +large amounts of data. Hash tables are not as flexible as association +lists, but because their access times are independent of the number of +associations in the table, for most applications they are the mechanism +of choice. + +@item +@dfn{Balanced binary trees} are another association mechanism that is +useful for applications in which the keys are ordered. Binary trees +have access times that are proportional to the logarithm of the number +of associations in the tree. While they aren't as fast as hash tables, +they offer the advantage that the contents of the tree can be converted +to a sorted alist in linear time. Additionally, two trees can be +compared for equality in worst-case linear time. + +@item +@dfn{Red-Black trees} are a kind of balanced binary tree. The +implementation supports destructive insertion and deletion operations +with a good constant factor. + +@item +@dfn{Weight-Balanced trees} are a kind of balanced binary tree. The +implementation provides non-destructive operations. There is a +comprehensive set of operations, including: a constant-time size +operation; many high-level operations such as the set operations union, +intersection and difference; and indexing of elements by position. + +@end itemize + +@menu +* Association Lists:: +* 1D Tables:: +* The Association Table:: +* Hash Tables:: +* Object Hashing:: +* Red-Black Trees:: +* Weight-Balanced Trees:: +@end menu + +@node Association Lists, 1D Tables, Associations, Associations +@section Association Lists + +@comment **** begin CLTL **** +@cindex association list (defn) +@cindex list, association (defn) +@cindex alist (defn) +@cindex key, of association list element (defn) +An @dfn{association list}, or @dfn{alist}, is a data structure used very +frequently in Scheme. An alist is a list of pairs, each of which is +called an @dfn{association}. The car of an association is called the +@dfn{key}. + +An advantage of the alist representation is that an alist can be +incrementally augmented simply by adding new entries to the front. +Moreover, because the searching procedures @code{assv} et al.@: search the +alist in order, new entries can ``shadow'' old entries. If an alist is +viewed as a mapping from keys to data, then the mapping can be not only +augmented but also altered in a non-destructive manner by adding new +entries to the front of the alist.@footnote{This introduction is taken +from @cite{Common Lisp, The Language}, second edition, p.@: 431.} +@comment **** end CLTL **** + +@deffn procedure alist? object +@cindex type predicate, for alist +@findex list? +Returns @code{#t} if @var{object} is an association list (including the +empty list); otherwise returns @code{#f}. Any @var{object} satisfying this +predicate also satisfies @code{list?}. +@end deffn + +@deffn procedure assq object alist +@deffnx procedure assv object alist +@deffnx procedure assoc object alist +@cindex searching, of alist +@findex eq? +@findex eqv? +@findex equal? +These procedures find the first pair in @var{alist} whose car field is +@var{object}, and return that pair; the returned pair is always an +@emph{element} of @var{alist}, @emph{not} one of the pairs from which +@var{alist} is composed. If no pair in @var{alist} has @var{object} as +its car, @code{#f} (n.b.: not the empty list) is returned. @code{assq} +uses @code{eq?} to compare @var{object} with the car fields of the pairs +in @var{alist}, while @code{assv} uses @code{eqv?} and @code{assoc} uses +@code{equal?}.@footnote{Although they are often used as predicates, +@code{assq}, @code{assv}, and @code{assoc} do not have question marks in +their names because they return useful values rather than just @code{#t} +or @code{#f}.} + +@example +@group +(define e '((a 1) (b 2) (c 3))) +(assq 'a e) @result{} (a 1) +(assq 'b e) @result{} (b 2) +(assq 'd e) @result{} #f +(assq (list 'a) '(((a)) ((b)) ((c)))) @result{} #f +(assoc (list 'a) '(((a)) ((b)) ((c)))) @result{} ((a)) +(assq 5 '((2 3) (5 7) (11 13))) @result{} @r{unspecified} +(assv 5 '((2 3) (5 7) (11 13))) @result{} (5 7) +@end group +@end example +@end deffn + +@deffn procedure association-procedure predicate selector +Returns an association procedure that is similar to @code{assv}, except +that @var{selector} (a procedure of one argument) is used to select the +key from the association, and @var{predicate} (an equivalence predicate) +is used to compare the key to the given item. This can be used to make +association lists whose elements are, say, vectors instead of pairs +(also @pxref{Searching Lists}). + +For example, here is how @code{assv} could be implemented: + +@example +(define assv (association-procedure eqv? car)) +@end example + +Another example is a ``reverse association'' procedure: + +@example +(define rassv (association-procedure eqv? cdr)) +@end example +@end deffn + +@deffn procedure del-assq object alist +@deffnx procedure del-assv object alist +@deffnx procedure del-assoc object alist +@cindex deletion, of alist element +@findex eq? +@findex eqv? +@findex equal? +These procedures return a newly allocated copy of @var{alist} in which +all associations with keys equal to @var{object} have been removed. +Note that while the returned copy is a newly allocated list, the +association pairs that are the elements of the list are shared with +@var{alist}, not copied. @code{del-assq} uses @code{eq?} to compare +@var{object} with the keys, while @code{del-assv} uses @code{eqv?} and +@code{del-assoc} uses @code{equal?}. + +@example +@group +(define a + '((butcher . "231 e22nd St.") + (baker . "515 w23rd St.") + (hardware . "988 Lexington Ave."))) + +(del-assq 'baker a) + @result{} + ((butcher . "231 e22nd St.") + (hardware . "988 Lexington Ave.")) +@end group +@end example +@end deffn + +@deffn procedure del-assq! object alist +@deffnx procedure del-assv! object alist +@deffnx procedure del-assoc! object alist +@findex eq? +@findex eqv? +@findex equal? +These procedures remove from @var{alist} all associations with keys +equal to @var{object}. They return the resulting list. +@code{del-assq!} uses @code{eq?} to compare @var{object} with the keys, +while @code{del-assv!} uses @code{eqv?} and @code{del-assoc!} uses +@code{equal?}. These procedures are like @code{del-assq}, +@code{del-assv}, and @code{del-assoc}, respectively, except that they +destructively modify @var{alist}. +@end deffn + +@deffn procedure delete-association-procedure deletor predicate selector +@findex list-deletor +@findex list-deletor! +This returns a deletion procedure similar to @code{del-assv} or +@code{del-assq!}. The @var{predicate} and @var{selector} arguments are +the same as those for @code{association-procedure}, while the +@var{deletor} argument should be either the procedure +@code{list-deletor} (for non-destructive deletions), or the procedure +@code{list-deletor!} (for destructive deletions). + +For example, here is a possible implementation of @code{del-assv}: + +@example +@group +(define del-assv + (delete-association-procedure list-deletor eqv? car)) +@end group +@end example +@end deffn + +@deffn procedure alist-copy alist +@cindex copying, of alist +@findex list-copy +Returns a newly allocated copy of @var{alist}. This is similar to +@code{list-copy} except that the ``association'' pairs, i.e.@: the +elements of the list @var{alist}, are also copied. @code{alist-copy} +could have been implemented like this: + +@example +@group +(define (alist-copy alist) + (if (null? alist) + '() + (cons (cons (car (car alist)) (cdr (car alist))) + (alist-copy (cdr alist))))) +@end group +@end example +@end deffn + +@node 1D Tables, The Association Table, Association Lists, Associations +@section 1D Tables + +@cindex 1D table (defn) +@cindex one-dimensional table (defn) +@cindex table, one-dimensional (defn) +@cindex weak pair, and 1D table +@dfn{1D tables} (``one-dimensional'' tables) are similar to association +lists. In a 1D table, unlike an association list, the keys of the table +are held @dfn{weakly}: if a key is garbage-collected, its associated +value in the table is removed. 1D tables compare their keys for +equality using @code{eq?}. + +@cindex property list +1D tables can often be used as a higher-performance alternative to the +two-dimensional association table (@pxref{The Association Table}). If +one of the keys being associated is a compound object such as a vector, +a 1D table can be stored in one of the vector's slots. Under these +circumstances, accessing items in a 1D table will be comparable in +performance to using a property list in a conventional Lisp. + +@deffn procedure make-1d-table +Returns a newly allocated empty 1D table. +@end deffn + +@deffn procedure 1d-table? object +@cindex type predicate, for 1D table +@findex list? +Returns @code{#t} if @var{object} is a 1D table, otherwise returns +@code{#f}. Any object that satisfies this predicate also satisfies +@code{list?}. +@end deffn + +@deffn procedure 1d-table/put! 1d-table key datum +Creates an association between @var{key} and @var{datum} in +@var{1d-table}. Returns an unspecified value. +@end deffn + +@deffn procedure 1d-table/remove! 1d-table key +Removes any association for @var{key} in @var{1d-table} and returns an +unspecified value. +@end deffn + +@deffn procedure 1d-table/get 1d-table key default +Returns the @var{datum} associated with @var{key} in @var{1d-table}. If +there is no association for @var{key}, @var{default} is returned. +@end deffn + +@deffn procedure 1d-table/lookup 1d-table key if-found if-not-found +@var{If-found} must be a procedure of one argument, and +@var{if-not-found} must be a procedure of no arguments. If +@var{1d-table} contains an association for @var{key}, @var{if-found} is +invoked on the @var{datum} of the association. Otherwise, +@var{if-not-found} is invoked with no arguments. In either case, the +result of the invoked procedure is returned as the result of +@code{1d-table/lookup}. +@end deffn + +@deffn procedure 1d-table/alist 1d-table +Returns a newly allocated association list that contains the same +information as @var{1d-table}. +@end deffn + +@node The Association Table, Hash Tables, 1D Tables, Associations +@section The Association Table + +@cindex association table (defn) +@cindex table, association (defn) +@cindex property list +@findex eq? +MIT/GNU Scheme provides a generalization of the property-list mechanism +found in most other implementations of Lisp: a global two-dimensional +@dfn{association table}. This table is indexed by two keys, called +@var{x-key} and @var{y-key} in the following procedure descriptions. +These keys and the datum associated with them can be arbitrary objects. +@code{eq?} is used to discriminate keys. + +Think of the association table as a matrix: a single datum can be +accessed using both keys, a column using @var{x-key} only, and a row +using @var{y-key} only. + +@deffn procedure 2d-put! x-key y-key datum +Makes an entry in the association table that associates @var{datum} with +@var{x-key} and @var{y-key}. Returns an unspecified result. +@end deffn + +@deffn procedure 2d-remove! x-key y-key +If the association table has an entry for @var{x-key} and @var{y-key}, +it is removed. Returns an unspecified result. +@end deffn + +@deffn procedure 2d-get x-key y-key +Returns the @var{datum} associated with @var{x-key} and @var{y-key}. +Returns @code{#f} if no such association exists. +@end deffn + +@deffn procedure 2d-get-alist-x x-key +Returns an association list of all entries in the association table that +are associated with @var{x-key}. The result is a list of +@code{(@var{y-key} . @var{datum})} pairs. Returns the empty list if no +entries for @var{x-key} exist. + +@example +@group +(2d-put! 'foo 'bar 5) +(2d-put! 'foo 'baz 6) +(2d-get-alist-x 'foo) @result{} ((baz . 6) (bar . 5)) +@end group +@end example +@end deffn + +@deffn procedure 2d-get-alist-y y-key +Returns an association list of all entries in the association table that +are associated with @var{y-key}. The result is a list of +@code{(@var{x-key} . @var{datum})} pairs. Returns the empty list if no +entries for @var{y-key} exist. + +@example +@group +(2d-put! 'bar 'foo 5) +(2d-put! 'baz 'foo 6) +(2d-get-alist-y 'foo) @result{} ((baz . 6) (bar . 5)) +@end group +@end example +@end deffn + +@node Hash Tables, Object Hashing, The Association Table, Associations +@section Hash Tables + +@cindex hash table +Hash tables are a fast, powerful mechanism for storing large numbers of +associations. MIT/GNU Scheme's hash tables feature automatic resizing, +customizable growth parameters, and customizable hash procedures. + +The average times for the insertion, deletion, and lookup operations on +a hash table are bounded by a constant. The space required by the table +is proportional to the number of associations in the table; the +constant of proportionality is described below (@pxref{Resizing of Hash +Tables}). + +(Previously, the hash-table implementation was a run-time-loadable +option, but as of release 7.7.0 it is loaded by default. It's no longer +necessary to call @code{load-option} prior to using hash tables.) + +@menu +* Construction of Hash Tables:: +* Basic Hash Table Operations:: +* Resizing of Hash Tables:: +* Address Hashing:: +* Low-Level Hash Table Operations:: +@end menu + +@node Construction of Hash Tables, Basic Hash Table Operations, Hash Tables, Hash Tables +@subsection Construction of Hash Tables + +@cindex construction, of hash table +The next few procedures are hash-table constructors. All hash table +constructors are procedures that accept one optional argument, +@var{initial-size}, and return a newly allocated hash table. If +@var{initial-size} is given, it must be an exact non-negative integer or +@code{#f}. The meaning of @var{initial-size} is discussed below +(@pxref{Resizing of Hash Tables}). + +@cindex equivalence predicate, of hash table +@cindex strongly held keys, of hash table +@cindex weakly held keys, of hash table +Hash tables are normally characterized by two things: the equivalence +predicate that is used to compare keys, and whether or not the table +allows its keys to be reclaimed by the garbage collector. If a table +prevents its keys from being reclaimed by the garbage collector, it is +said to hold its keys @dfn{strongly}; otherwise it holds its keys +@dfn{weakly} (@pxref{Weak Pairs}). + +@deffn procedure make-eq-hash-table [initial-size] +@findex eq? +Returns a newly allocated hash table that accepts arbitrary objects as +keys, and compares those keys with @code{eq?}. The keys are held +weakly. These are the fastest of the standard hash tables. +@end deffn + +@deffn procedure make-eqv-hash-table [initial-size] +@findex eqv? +Returns a newly allocated hash table that accepts arbitrary objects as +keys, and compares those keys with @code{eqv?}. The keys are held +weakly, except that booleans, characters, and numbers are held strongly. +These hash tables are a little slower than those made by +@code{make-eq-hash-table}. +@end deffn + +@deffn procedure make-equal-hash-table [initial-size] +@findex equal? +Returns a newly allocated hash table that accepts arbitrary objects as +keys, and compares those keys with @code{equal?}. The keys are held +strongly. These hash tables are quite a bit slower than those made by +@code{make-eq-hash-table}. +@end deffn + +@deffn procedure make-string-hash-table [initial-size] +@findex string=? +Returns a newly allocated hash table that accepts character strings as +keys, and compares them with @code{string=?}. The keys are held +strongly. +@end deffn + +The next two procedures are used to create new hash-table constructors. +All of the above hash table constructors, with the exception of +@code{make-eqv-hash-table}, could have been created by calls to these +``constructor-constructors''; see the examples below. + +@deffn procedure strong-hash-table/constructor key-hash key=? [rehash-after-gc?] +@deffnx procedure weak-hash-table/constructor key-hash key=? [rehash-after-gc?] +@cindex hashing, of key in hash table +@cindex modulus, of hashing procedure +Each of these procedures accepts two arguments and returns a hash-table +constructor. The @var{key=?} argument is an equivalence predicate for +the keys of the hash table. The @var{key-hash} argument is a procedure +that computes a hash number. Specifically, @var{key-hash} accepts two +arguments, a key and an exact positive integer (the @dfn{modulus}), and +returns an exact non-negative integer that is less than the modulus. + +The optional argument @var{rehash-after-gc?}, if true, says that the +values returned by @var{key-hash} might change after a garbage +collection. If so, the hash-table implementation arranges for the table +to be rehashed when necessary. (@xref{Address Hashing}, for +information about hash procedures that have this property.) Otherwise, +it is assumed that @var{key-hash} always returns the same value for the +same arguments. The default value of this argument is @code{#f}. + +The constructors returned by @code{strong-hash-table/constructor} make +hash tables that hold their keys strongly. The constructors returned by +@code{weak-hash-table/constructor} make hash tables that hold their keys +weakly. +@end deffn + +Some examples showing how some standard hash-table constructors could have +been defined: + +@findex eq-hash-mod +@findex eq? +@findex equal-hash-mod +@findex equal? +@findex string-hash-mod +@findex string=? +@example +@group +(define make-eq-hash-table + (weak-hash-table/constructor eq-hash-mod eq? #t)) + +(define make-equal-hash-table + (strong-hash-table/constructor equal-hash-mod equal? #t)) + +(define make-string-hash-table + (strong-hash-table/constructor string-hash-mod string=? #f)) +@end group +@end example + +The following procedure is sometimes useful in conjunction with weak +hash tables. Normally it is not needed, because such hash tables clean +themselves automatically as they are used. + +@deffn procedure hash-table/clean! hash-table +If @var{hash-table} is a type of hash table that holds its @var{key}s +weakly, this procedure recovers any space that was being used to record +associations for objects that have been reclaimed by the garbage +collector. Otherwise, this procedure does nothing. In either case, it +returns an unspecified result. +@end deffn + +@node Basic Hash Table Operations, Resizing of Hash Tables, Construction of Hash Tables, Hash Tables +@subsection Basic Hash Table Operations + +The procedures described in this section are the basic operations on +hash tables. They provide the functionality most often needed by +programmers. Subsequent sections describe other operations that provide +additional functionality needed by some applications. + +@deffn procedure hash-table? object +@cindex type predicate, for hash table +Returns @code{#t} if @var{object} is a hash table, otherwise returns +@code{#f}. +@end deffn + +@deffn procedure hash-table/put! hash-table key datum +Associates @var{datum} with @var{key} in @var{hash-table} and returns an +unspecified result. The average time required by this operation is +bounded by a constant. +@end deffn + +@deffn procedure hash-table/get hash-table key default +Returns the datum associated with @var{key} in @var{hash-table}. If +there is no association for @var{key}, @var{default} is returned. The +average time required by this operation is bounded by a constant. +@end deffn + +@deffn procedure hash-table/remove! hash-table key +If @var{hash-table} has an association for @var{key}, removes it. +Returns an unspecified result. The average time required by this +operation is bounded by a constant. +@end deffn + +@deffn procedure hash-table/clear! hash-table +Removes all associations in @var{hash-table} and returns an unspecified +result. The average and worst-case times required by this operation are +bounded by a constant. +@end deffn + +@deffn procedure hash-table/count hash-table +Returns the number of associations in @var{hash-table} as an exact +non-negative integer. If @var{hash-table} holds its keys weakly, this +is a conservative upper bound that may count some associations whose +keys have recently been reclaimed by the garbage collector. The average +and worst-case times required by this operation are bounded by a +constant. +@end deffn + +@deffn procedure hash-table->alist hash-table +Returns the contents of @var{hash-table} as a newly allocated alist. +Each element of the alist is a pair @code{(@var{key} . @var{datum})} +where @var{key} is one of the keys of @var{hash-table}, and @var{datum} +is its associated datum. The average and worst-case times required by +this operation are linear in the number of associations +in the table. +@end deffn + +@deffn procedure hash-table/key-list hash-table +Returns a newly allocated list of the keys in @var{hash-table}. The +average and worst-case times required by this operation are linear in +the number of associations in the table. +@end deffn + +@deffn procedure hash-table/datum-list hash-table +Returns a newly allocated list of the datums in @var{hash-table}. Each +element of the list corresponds to one of the associations in +@var{hash-table}; if the table contains multiple associations with the +same datum, so will this list. The average and worst-case times +required by this operation are linear in the number of associations in +the table. +@end deffn + +@deffn procedure hash-table/for-each hash-table procedure +@var{Procedure} must be a procedure of two arguments. Invokes +@var{procedure} once for each association in @var{hash-table}, passing +the association's @var{key} and @var{datum} as arguments, in that order. +Returns an unspecified result. @var{Procedure} must not modify +@var{hash-table}, with one exception: it is permitted to call +@code{hash-table/remove!} to remove the association being processed. +@end deffn + +The following procedure is an alternate form of @code{hash-table/get} +that is useful in some situations. Usually, @code{hash-table/get} is +preferable because it is faster. + +@deffn procedure hash-table/lookup hash-table key if-found if-not-found +@var{If-found} must be a procedure of one argument, and +@var{if-not-found} must be a procedure of no arguments. If +@var{hash-table} contains an association for @var{key}, @var{if-found} +is invoked on the datum of the association. Otherwise, +@var{if-not-found} is invoked with no arguments. In either case, the +result yielded by the invoked procedure is returned as the result of +@code{hash-table/lookup} (@code{hash-table/lookup} @emph{reduces} into +the invoked procedure, i.e.@: calls it tail-recursively). The average +time required by this operation is bounded by a constant. +@end deffn + +@node Resizing of Hash Tables, Address Hashing, Basic Hash Table Operations, Hash Tables +@subsection Resizing of Hash Tables + +@cindex resizing, of hash table +@cindex size, of hash table (defn) +Normally, hash tables automatically resize themselves according to need. +Because of this, the programmer need not be concerned with management of +the table's size. However, some limited control over the table's size +is provided, which will be discussed below. This discussion involves +two concepts, @dfn{usable size} and @dfn{physical size}, which we will +now define. + +@cindex usable size, of hash table (defn) +The @dfn{usable size} of a hash table is the number of associations that +the table can hold at a given time. If the number of associations in +the table exceeds the usable size, the table will automatically grow, +increasing the usable size to a new value that is sufficient to hold the +associations. + +@cindex physical size, of hash table (defn) +The @dfn{physical size} is an abstract measure of a hash table that +specifies how much space is allocated to hold the associations of the +table. The physical size is always greater than or equal to the usable +size. The physical size is not interesting in itself; it is interesting +only for its effect on the performance of the hash table. While the +average performance of a hash-table lookup is bounded by a constant, the +worst-case performance is not. For a table containing a given number of +associations, increasing the physical size of the table decreases the +probability that worse-than-average performance will occur. + +The physical size of a hash table is statistically related to the number +of associations. However, it is possible to place bounds on the +physical size, and from this to estimate the amount of space used by the +table: + +@example +@group +(define (hash-table-space-bounds count rehash-size rehash-threshold) + (let ((tf (/ 1 rehash-threshold))) + (values (if (exact-integer? rehash-size) + (- (* count (+ 4 tf)) + (* tf (+ rehash-size rehash-size))) + (* count (+ 4 (/ tf (* rehash-size rehash-size))))) + (* count (+ 4 tf))))) +@end group +@end example + +@noindent +What this formula shows is that, for a ``normal'' rehash size (that is, +not an exact integer), the amount of space used by the hash table is +proportional to the number of associations in the table. The constant +of proportionality varies statistically, with the low bound being + +@example +(+ 4 (/ (/ 1 rehash-threshold) (* rehash-size rehash-size))) +@end example + +@noindent +and the high bound being + +@example +(+ 4 (/ 1 rehash-threshold)) +@end example + +@noindent +which, for the default values of these parameters, are @code{4.25} and +@code{5}, respectively. Reducing the rehash size will tighten these +bounds, but increases the amount of time spent resizing, so you can see +that the rehash size gives some control over the time-space tradeoff of +the table. + +The programmer can control the size of a hash table by means of three +parameters: + +@itemize @bullet +@item +Each table's @var{initial-size} may be specified when the table is +created. + +@item +Each table has a @dfn{rehash size} that specifies how the size of the +table is changed when it is necessary to grow or shrink the table. + +@item +Each table has a @dfn{rehash threshold} that specifies the relationship +of the table's physical size to its usable size. +@end itemize + +@cindex initial size, of hash table +If the programmer knows that the table will initially contain a specific +number of items, @var{initial-size} can be given when the table is +created. If @var{initial-size} is an exact non-negative integer, it +specifies the initial usable size of the hash table; the table will not +change size until the number of items in the table exceeds +@var{initial-size}, after which automatic resizing is enabled and +@var{initial-size} no longer has any effect. Otherwise, if +@var{initial-size} is not given or is @code{#f}, the table is +initialized to an unspecified size and automatic resizing is immediately +enabled. + +@cindex rehash size, of hash table (defn) +The @dfn{rehash size} specifies how much to increase the usable size of +the hash table when it becomes full. It is either an exact positive +integer, or a real number greater than one. If it is an integer, the +new size is the sum of the old size and the rehash size. Otherwise, it +is a real number, and the new size is the product of the old size and +the rehash size. Increasing the rehash size decreases the average cost +of an insertion, but increases the average amount of space used by the +table. The rehash size of a table may be altered dynamically by the +application in order to optimize the resizing of the table; for example, +if the table will grow quickly for a known period and afterwards will +not change size, performance might be improved by using a large rehash +size during the growth phase and a small one during the static phase. +The default rehash size of a newly constructed hash table is @code{2.0}. + +@strong{Warning}: The use of an exact positive integer for a rehash +size is almost always undesirable; this option is provided solely for +compatibility with the Common Lisp hash-table mechanism. The reason for +this has to do with the time penalty for resizing the hash table. The +time needed to resize a hash table is proportional to the +number of associations in the table. This resizing cost is +@dfn{amortized} across the insertions required to fill the table to the +point where it needs to grow again. If the table grows by an amount +proportional to the number of associations, then the cost of +resizing and the increase in size are both proportional to the +number of associations, so the @dfn{amortized cost} of an insertion +operation is still bounded by a constant. However, if the table grows +by a constant amount, this is not true: the amortized cost of an +insertion is not bounded by a constant. Thus, using a constant rehash +size means that the average cost of an insertion increases +proportionally to the number of associations in the hash table. + +@cindex rehash threshold, of hash table (defn) +The @dfn{rehash threshold} is a real number, between zero exclusive and +one inclusive, that specifies the ratio between a hash table's usable +size and its physical size. Decreasing the rehash threshold decreases +the probability of worse-than-average insertion, deletion, and lookup +times, but increases the physical size of the table for a given usable +size. The default rehash threshold of a newly constructed hash table is +@code{1}. + +@deffn procedure hash-table/size hash-table +Returns the usable size of @var{hash-table} as an exact positive +integer. This is the number of associations that @var{hash-table} can +hold before it will grow. +@end deffn + +@deffn procedure hash-table/rehash-size hash-table +Returns the rehash size of @var{hash-table}. +@end deffn + +@deffn procedure set-hash-table/rehash-size! hash-table x +@var{X} must be either an exact positive integer, or a real number that +is greater than one. Sets the rehash size of @var{hash-table} to +@var{x} and returns an unspecified result. This operation adjusts the +``shrink threshold'' of the table; the table might shrink if the number +of associations is less than the new threshold. +@end deffn + +@deffn procedure hash-table/rehash-threshold hash-table +Returns the rehash threshold of @var{hash-table}. +@end deffn + +@deffn procedure set-hash-table/rehash-threshold! hash-table x +@var{X} must be a real number between zero exclusive and one inclusive. +Sets the rehash threshold of @var{hash-table} to @var{x} and returns an +unspecified result. This operation does not change the usable size of +the table, but it usually changes the physical size of the table, which +causes the table to be rehashed. +@end deffn + +@node Address Hashing, Low-Level Hash Table Operations, Resizing of Hash Tables, Hash Tables +@subsection Address Hashing +@cindex address hashing + +The procedures described in this section may be used to make very +efficient key-hashing procedures for arbitrary objects. All of these +procedures are based on @dfn{address hashing}, which uses the address of +an object as its hash number. The great advantage of address hashing is +that converting an arbitrary object to a hash number is extremely fast +and takes the same amount of time for any object. + +The disadvantage of address hashing is that the garbage collector +changes the addresses of most objects. The hash-table implementation +compensates for this disadvantage by automatically rehashing tables that +use address hashing when garbage collections occur. Thus, in order to +use these procedures for key hashing, it is necessary to tell the +hash-table implementation (by means of the @var{rehash-after-gc?} +argument to the ``constructor-constructor'' procedure) that the hash +numbers computed by your key-hashing procedure must be recomputed after +a garbage collection. + +@deffn procedure eq-hash object +@deffnx procedure eqv-hash object +@deffnx procedure equal-hash object +These procedures return a hash number for @var{object}. The result is +always a non-negative integer, and in the case of @code{eq-hash}, a +non-negative fixnum. Two objects that are equivalent according to +@code{eq?}, @code{eqv?}, or @code{equal?}, respectively, will produce the +same hash number when passed as arguments to these procedures, provided +that the garbage collector does not run during or between the two calls. +@end deffn + +The following procedures are the key-hashing procedures used by the +standard address-hash-based hash tables. + +@deffn procedure eq-hash-mod object modulus +This procedure is the key-hashing procedure used by +@code{make-eq-hash-table}. +@end deffn + +@deffn procedure eqv-hash-mod object modulus +This procedure is the key-hashing procedure used by +@code{make-eqv-hash-table}. +@end deffn + +@deffn procedure equal-hash-mod object modulus +This procedure is the key-hashing procedure used by +@code{make-equal-hash-table}. +@end deffn + +@node Low-Level Hash Table Operations, , Address Hashing, Hash Tables +@subsection Low-Level Hash Table Operations + +The procedures in this section allow the programmer to control some of +the internal structure of a hash table. Normally, hash tables maintain +associations between keys and datums using pairs or weak pairs. These +procedures allow the programmer to specify the use of some other data +structure to maintain the association. In this section, the data +structure that represents an association in a hash table is called an +@dfn{entry}. + +@deffn procedure hash-table/constructor key-hash key=? make-entry entry-valid? entry-key entry-datum set-entry-datum! [rehash-after-gc?] +Creates and returns a hash-table constructor procedure +(@pxref{Construction of Hash Tables}). The arguments define the +characteristics of the hash table as follows: + +@table @var +@item key-hash +The hashing procedure. A procedure that accepts two arguments, a key and +an exact positive integer (the @dfn{modulus}), and returns an exact +non-negative integer that is less than the modulus. + +@item key=? +A equivalence predicate that accepts two keys and is true iff they are +the same key. If this predicate is true of two keys, then +@var{key-hash} must return the same value for each of these keys (given +the same modulus in both cases). + +@item make-entry +A procedure that accepts a key and a datum as arguments and returns a +newly allocated entry. + +@item entry-valid? +A procedure that accepts an entry and returns @code{#f} iff the entry's +key has been reclaimed by the garbage collector. Instead of a +procedure, this may be @code{#t}, which is equivalent to @code{(lambda +(entry) #t)}. +@findex weak-pair/car? + +@item entry-key +A procedure that accepts an entry as an argument and returns the entry's +key. + +@item entry-datum +A procedure that accepts an entry as an argument and returns the entry's +datum. + +@item set-entry-datum! +A procedure that accepts an entry and an object as arguments, modifies +the entry's datum to be the object, and returns an unspecified +result. + +@item rehash-after-gc? +An optional argument that, if true, says the values returned by +@var{key-hash} might change after a garbage collection. If so, the +hash-table implementation arranges for the table to be rehashed when +necessary. (@xref{Address Hashing}, for information about hash +procedures that have this property.) Otherwise, it is assumed that +@var{key-hash} always returns the same value for the same arguments. +The default value of this argument is @code{#f}. +@end table +@end deffn + +@noindent +For example, here is how the constructors for ordinary hash tables could +be defined: + +@example +@group +(define (strong-hash-table/constructor key-hash key=? + #!optional rehash-after-gc?) + (hash-table/constructor key-hash key=? + cons #t car cdr set-cdr! + (if (default-object? rehash-after-gc?) + #f + rehash-after-gc?))) +@end group + +@group +(define (weak-hash-table/constructor key-hash key=? + #!optional rehash-after-gc?) + (hash-table/constructor key-hash key=? weak-cons weak-pair/car? + weak-car weak-cdr weak-set-cdr! + (if (default-object? rehash-after-gc?) + #f + rehash-after-gc?))) +@end group +@end example + +@deffn procedure hash-table/key-hash hash-table +@deffnx procedure hash-table/key=? hash-table +@deffnx procedure hash-table/make-entry hash-table +@deffnx procedure hash-table/entry-valid? hash-table +@deffnx procedure hash-table/entry-key hash-table +@deffnx procedure hash-table/entry-datum hash-table +@deffnx procedure hash-table/set-entry-datum! hash-table +Each procedure returns the value of the corresponding argument that was +used to construct @var{hash-table}. +@end deffn + +The following procedures return the contents of a hash table as a +collection of entries. While the data structure holding the entries is +newly allocated, the entries themselves are not copied. Since hash +table operations can modify these entries, the entries should be copied +if it is desired to keep them while continuing to modify the table. + +@deffn procedure hash-table/entries-list hash-table +Returns a newly allocated list of the entries in @var{hash-table}. +@end deffn + +@deffn procedure hash-table/entries-vector hash-table +Returns a newly allocated vector of the entries in @var{hash-table}. +Equivalent to + +@example +(list->vector (hash-table/entries-list @var{hash-table})) +@end example +@end deffn + +@node Object Hashing, Red-Black Trees, Hash Tables, Associations +@section Object Hashing + +@cindex object hashing +@cindex hashing, of object +The MIT/GNU Scheme object-hashing facility provides a mechanism for +generating a unique hash number for an arbitrary object. This hash +number, unlike an object's address, is unchanged by garbage collection. +The object-hashing facility is useful in conjunction with hash tables, +but it may be used for other things as well. In particular, it is used +in the generation of the written representation for many objects +(@pxref{Custom Output}). + +All of these procedures accept an optional argument called @var{table}; +this table contains the object-integer associations. If given, this +argument must be an object-hash table as constructed by +@code{hash-table/make} (see below). If not given, a default table is +used. + +@deffn procedure hash object [table] +@findex eq? +@code{hash} associates an exact non-negative integer with @var{object} +and returns that integer. If @code{hash} was previously called with +@var{object} as its argument, the integer returned is the same as was +returned by the previous call. @code{hash} guarantees that distinct +objects (in the sense of @code{eq?}) are associated with distinct +integers. +@end deffn + +@deffn procedure unhash k [table] +@code{unhash} takes an exact non-negative integer @var{k} and returns +the object associated with that integer. If there is no object +associated with @var{k}, or if the object previously associated with +@var{k} has been reclaimed by the garbage collector, an error of type +@code{condition-type:bad-range-argument} is signalled. In other words, +if @code{hash} previously returned @var{k} for some object, and that +object has not been reclaimed, it is the value of the call to +@code{unhash}. +@findex condition-type:bad-range-argument +@end deffn + +An object that is passed to @code{hash} as an argument is not protected +from being reclaimed by the garbage collector. If all other references +to that object are eliminated, the object will be reclaimed. +Subsequently calling @code{unhash} with the hash number of the (now +reclaimed) object will signal an error. + +@example +@group +(define x (cons 0 0)) @result{} @r{unspecified} +(hash x) @result{} 77 +(eqv? (hash x) (hash x)) @result{} #t +(define x 0) @result{} @r{unspecified} +(gc-flip) @r{;force a garbage collection} +(unhash 77) @error{} +@end group +@end example + +@deffn procedure object-hashed? object [table] +This predicate is true if @var{object} has an associated hash number. +Otherwise it is false. +@end deffn + +@deffn procedure valid-hash-number? k [table] +This predicate is true if @var{k} is the hash number associated with +some object. Otherwise it is false. +@end deffn + +The following two procedures provide a lower-level interface to the +object-hashing mechanism. + +@deffn procedure object-hash object [table [insert?]] +@findex eq? +@code{object-hash} is like @code{hash}, except that it accepts an +additional optional argument, @var{insert?}. If @var{insert?}@: is +supplied and is @code{#f}, @code{object-hash} will return an integer for +@var{object} only if there is already an association in the table; +otherwise, it will return @code{#f}. If @var{insert?} is not supplied, +or is not @code{#f}, @code{object-hash} always returns an integer, +creating an association in the table if necessary. + +@code{object-hash} additionally treats @code{#f} differently than does +@code{hash}. Calling @code{object-hash} with @code{#f} as its argument +will return an integer that, when passed to @code{unhash}, will signal +an error rather than returning @code{#f}. Likewise, +@code{valid-hash-number?} will return @code{#f} for this integer. +@end deffn + +@deffn procedure object-unhash k [table] +@code{object-unhash} is like @code{unhash}, except that when @var{k} is +not associated with any object or was previously associated with an +object that has been reclaimed, @code{object-unhash} returns @code{#f}. +This means that there is an ambiguity in the value returned by +@code{object-unhash}: if @code{#f} is returned, there is no way to +tell if @var{k} is associated with @code{#f} or is not associated with +any object at all. +@end deffn + +Finally, this procedure makes new object-hash tables: + +@deffn procedure hash-table/make +This procedure creates and returns a new, empty object-hash table that +is suitable for use as the optional @var{table} argument to the above +procedures. The returned table contains no associations. +@end deffn + +@node Red-Black Trees, Weight-Balanced Trees, Object Hashing, Associations +@section Red-Black Trees + +@cindex trees, balanced binary +@cindex balanced binary trees +@cindex binary trees +@cindex red-black binary trees +Balanced binary trees are a useful data structure for maintaining large +sets of associations whose keys are ordered. While most applications +involving large association sets should use hash tables, some +applications can benefit from the use of binary trees. Binary trees +have two advantages over hash tables: + +@itemize @bullet +@item +The contents of a binary tree can be converted to an alist, sorted by +key, in time proportional to the number of associations in the +tree. A hash table can be converted into an unsorted alist in linear +time; sorting it requires additional time. + +@item +Two binary trees can be compared for equality in linear time. Hash +tables, on the other hand, cannot be compared at all; they must be +converted to alists before comparison can be done, and alist comparison +is quadratic unless the alists are sorted. +@end itemize + +MIT/GNU Scheme provides an implementation of @dfn{red-black} trees. The +red-black tree-balancing algorithm provides generally good performance +because it doesn't try to keep the tree very closely balanced. At any +given node in the tree, one side of the node can be twice as high as the +other in the worst case. With typical data the tree will remain fairly +well balanced anyway. + +A red-black tree takes space that is proportional to the number of +associations in the tree. For the current implementation, the constant +of proportionality is eight words per association. + +Red-black trees hold their keys @dfn{strongly}. In other words, if a +red-black tree contains an association for a given key, that key cannot +be reclaimed by the garbage collector. + +@cindex run-time-loadable option +@cindex option, run-time-loadable +The red-black tree implementation is a run-time-loadable option. To use +red-black trees, execute + +@example +(load-option 'rb-tree) +@end example +@findex load-option + +@noindent +once before calling any of the procedures defined here. + +@deffn procedure make-rb-tree key=? keyalist rb-tree +Returns the contents of @var{rb-tree} as a newly allocated alist. Each +element of the alist is a pair @code{(@var{key} . @var{datum})} where +@var{key} is one of the keys of @var{rb-tree}, and @var{datum} is its +associated datum. The alist is sorted by key according to the +@var{keyalist rb-tree))) +@end example +@end deffn + +@deffn procedure rb-tree/equal? rb-tree-1 rb-tree-2 datum=? +Compares @var{rb-tree-1} and @var{rb-tree-2} for equality, returning +@code{#t} iff they are equal and @code{#f} otherwise. The trees must +have been constructed with the same equality and order predicates (same +in the sense of @code{eq?}). The keys of the trees are compared using +the @var{key=?} predicate used to build the trees, while the datums of +the trees are compared using the equivalence predicate @var{datum=?}. +The worst-case time required by this operation is proportional to the +number of associations in the tree. +@end deffn + +@deffn procedure rb-tree/empty? rb-tree +Returns @code{#t} iff @var{rb-tree} contains no associations. Otherwise +returns @code{#f}. +@end deffn + +@deffn procedure rb-tree/size rb-tree +Returns the number of associations in @var{rb-tree}, an exact +non-negative integer. The average and worst-case times required by this +operation are proportional to the number of associations in the tree. +@end deffn + +@deffn procedure rb-tree/height rb-tree +Returns the height of @var{rb-tree}, an exact non-negative integer. +This is the length of the longest path from a leaf of the tree to the +root. The average and worst-case times required by this operation are +proportional to the number of associations in the tree. + +The returned value satisfies the following: + +@example +@group +(lambda (rb-tree) + (let ((size (rb-tree/size rb-tree)) + (lg (lambda (x) (/ (log x) (log 2))))) + (<= (lg size) + (rb-tree/height rb-tree) + (* 2 (lg (+ size 1)))))) +@end group +@end example +@end deffn + +@deffn procedure rb-tree/copy rb-tree +Returns a newly allocated copy of @var{rb-tree}. The copy is identical +to @var{rb-tree} in all respects, except that changes to @var{rb-tree} +do not affect the copy, and vice versa. The time required by this +operation is proportional to the number of associations in the tree. +@end deffn + +@deffn procedure alist->rb-tree alist key=? keywt-tree tree-type alist +Returns a newly allocated weight-balanced tree that contains the same +associations as @var{alist}. This procedure is equivalent to: + +@example +@group +(lambda (type alist) + (let ((tree (make-wt-tree type))) + (for-each (lambda (association) + (wt-tree/add! tree + (car association) + (cdr association))) + alist) + tree)) +@end group +@end example +@end deffn + +@node Basic Operations on Weight-Balanced Trees, Advanced Operations on Weight-Balanced Trees, Construction of Weight-Balanced Trees, Weight-Balanced Trees +@subsection 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. + +@deffn procedure wt-tree? object +Returns @code{#t} if @var{object} is a weight-balanced tree, otherwise +returns @code{#f}. +@end deffn + +@deffn procedure wt-tree/empty? wt-tree +Returns @code{#t} if @var{wt-tree} contains no associations, otherwise +returns @code{#f}. +@end deffn + +@deffn procedure wt-tree/size wt-tree +Returns the number of associations in @var{wt-tree}, an exact +non-negative integer. This operation takes constant time. +@end deffn + +@deffn procedure wt-tree/add wt-tree key datum +Returns a new tree containing all the associations in @var{wt-tree} and +the association of @var{datum} with @var{key}. If @var{wt-tree} already +had an association for @var{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 +@var{wt-tree}. +@end deffn + +@deffn procedure wt-tree/add! wt-tree key datum +Associates @var{datum} with @var{key} in @var{wt-tree} and returns an +unspecified value. If @var{wt-tree} already has an association for +@var{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 @var{wt-tree}. +@end deffn + +@deffn procedure wt-tree/member? key wt-tree +Returns @code{#t} if @var{wt-tree} contains an association for +@var{key}, otherwise returns @code{#f}. The average and worst-case +times required by this operation are proportional to the logarithm of +the number of associations in @var{wt-tree}. +@end deffn + +@deffn procedure wt-tree/lookup wt-tree key default +Returns the datum associated with @var{key} in @var{wt-tree}. If +@var{wt-tree} doesn't contain an association for @var{key}, +@var{default} is returned. The average and worst-case times required by +this operation are proportional to the logarithm of the number of +associations in @var{wt-tree}. +@end deffn + +@deffn procedure wt-tree/delete wt-tree key +Returns a new tree containing all the associations in @var{wt-tree}, +except that if @var{wt-tree} contains an association for @var{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 @var{wt-tree}. +@end deffn + +@deffn procedure wt-tree/delete! wt-tree key +If @var{wt-tree} contains an association for @var{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 @var{wt-tree}. +@end deffn + +@node Advanced Operations on Weight-Balanced Trees, Indexing Operations on Weight-Balanced Trees, Basic Operations on Weight-Balanced Trees, Weight-Balanced Trees +@subsection Advanced Operations on Weight-Balanced Trees + +In the following the @emph{size} of a tree is the number of associations +that the tree contains, and a @emph{smaller} tree contains fewer +associations. + +@deffn procedure wt-tree/split< wt-tree bound +Returns a new tree containing all and only the associations in +@var{wt-tree} that have a key that is less than @var{bound} in the +ordering relation of the tree type of @var{wt-tree}. The average and +worst-case times required by this operation are proportional to the +logarithm of the size of @var{wt-tree}. +@end deffn + +@deffn procedure wt-tree/split> wt-tree bound +Returns a new tree containing all and only the associations in +@var{wt-tree} that have a key that is greater than @var{bound} in the +ordering relation of the tree type of @var{wt-tree}. The average and +worst-case times required by this operation are proportional to the +logarithm of the size of @var{wt-tree}. +@end deffn + +@deffn 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 @var{wt-tree-2} +with the key. Thus if the trees are viewed as discrete maps then +@code{wt-tree/union} computes the map override of @var{wt-tree-1} by +@var{wt-tree-2}. If the trees are viewed as sets the result is the set +union of the arguments. +The worst-case time required by this operation +is proportional to the sum of the sizes of both trees. +If the minimum key of one tree is greater than the maximum key of +the other tree then the worst-case time required is proportional to +the logarithm of the size of the larger tree. +@end deffn + +@deffn procedure wt-tree/intersection wt-tree-1 wt-tree-2 +Returns a new tree containing all and only those associations from +@var{wt-tree-1} that have keys appearing as the key of an association +in @var{wt-tree-2}. Thus the associated data in the result are those +from @var{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, +@code{wt-tree/intersection} computes the domain restriction of +@var{wt-tree-1} to (the domain of) @var{wt-tree-2}. +The worst-case time required by this operation is proportional to +the sum of the sizes of the trees. +@end deffn + +@deffn procedure wt-tree/difference wt-tree-1 wt-tree-2 +Returns a new tree containing all and only those associations from +@var{wt-tree-1} that have keys that @emph{do not} appear as the key of +an association in @var{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 @var{wt-tree-1} to +the complement of (the domain of) @var{wt-tree-2}. +The worst-case time required by this operation is proportional to +the sum of the sizes of the trees. +@end deffn + +@deffn procedure wt-tree/subset? wt-tree-1 wt-tree-2 +Returns @code{#t} iff the key of each association in @var{wt-tree-1} is +the key of some association in @var{wt-tree-2}, otherwise returns @code{#f}. +Viewed as a set operation, @code{wt-tree/subset?} is the improper subset +predicate. +A proper subset predicate can be constructed: + +@example +@group +(define (proper-subset? s1 s2) + (and (wt-tree/subset? s1 s2) + (< (wt-tree/size s1) (wt-tree/size s2)))) +@end group +@end example + +As a discrete map operation, @code{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 +@var{wt-tree-1}. +@end deffn + +@deffn procedure wt-tree/set-equal? wt-tree-1 wt-tree-2 +Returns @code{#t} iff for every association in @var{wt-tree-1} there is +an association in @var{wt-tree-2} that has the same key, and @emph{vice +versa}. + +Viewing the arguments as sets, @code{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 + +@example +@group +(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))) +@end group +@end example + +In the worst case the time required by this operation is proportional to +the size of the smaller tree. +@end deffn + +@deffn procedure wt-tree/fold combiner initial wt-tree +This procedure reduces @var{wt-tree} by combining all the associations, +using an reverse in-order traversal, so the associations are visited in +reverse order. @var{Combiner} is a procedure of three arguments: a key, +a datum and the accumulated result so far. Provided @var{combiner} +takes time bounded by a constant, @code{wt-tree/fold} takes time +proportional to the size of @var{wt-tree}. + +A sorted association list can be derived simply: + +@example +@group +(wt-tree/fold (lambda (key datum list) + (cons (cons key datum) list)) + '() + @var{wt-tree})) +@end group +@end example + +The data in the associations can be summed like this: + +@example +@group +(wt-tree/fold (lambda (key datum sum) (+ sum datum)) + 0 + @var{wt-tree}) +@end group +@end example +@end deffn + +@deffn procedure wt-tree/for-each action wt-tree +This procedure traverses @var{wt-tree} in order, applying @var{action} to +each association. +The associations are processed in increasing order of their keys. +@var{Action} is a procedure of two arguments that takes the key and +datum respectively of the association. +Provided @var{action} takes time bounded by a constant, +@code{wt-tree/for-each} takes time proportional to the size of +@var{wt-tree}. +The example prints the tree: + +@example +@group +(wt-tree/for-each (lambda (key value) + (display (list key value))) + @var{wt-tree})) +@end group +@end example +@end deffn + +@deffn procedure wt-tree/union-merge wt-tree-1 wt-tree-2 merge +Returns a new tree containing all the associations from both trees. If +both trees have an association for the same key, the datum associated +with that key in the result tree is computed by applying the procedure +@var{merge} to the key, the value from @var{wt-tree-1} and the value +from @var{wt-tree-2}. @var{Merge} is of the form + +@example +(lambda (@var{key} @var{datum-1} @var{datum-2}) @dots{}) +@end example + +If some key occurs only in one tree, that association will appear in the +result tree without being processed by @var{merge}, so for this +operation to make sense, either @var{merge} must have both a right and +left identity that correspond to the association being absent in one of +the trees, or some guarantee must be made, for example, all the keys in +one tree are known to occur in the other. + +These are all reasonable procedures for @var{merge} + +@example +@group +(lambda (key val1 val2) (+ val1 val2)) +(lambda (key val1 val2) (append val1 val2)) +(lambda (key val1 val2) (wt-tree/union val1 val2)) +@end group +@end example + +However, a procedure like + +@example +(lambda (key val1 val2) (- val1 val2)) +@end example + +would result in a subtraction of the data for all associations with keys +occuring in both trees but associations with keys occuring in only the +second tree would be copied, not negated, as is presumably be intent. +The programmer might ensure that this never happens. + +This procedure has the same time behavior as @code{wt-tree/union} but +with a slightly worse constant factor. Indeed, @code{wt-tree/union} +might have been defined like this: + +@example +@group +(define (wt-tree/union tree1 tree2) + (wt-tree/union-merge tree1 tree2 + (lambda (key val1 val2) val2))) +@end group +@end example +@end deffn + +The @var{merge} procedure takes the @var{key} as a parameter in case the +data are not independent of the key. + + +@node Indexing Operations on Weight-Balanced Trees, , Advanced Operations on Weight-Balanced Trees, Weight-Balanced Trees +@subsection 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. + +@deffn procedure wt-tree/index wt-tree index +@deffnx procedure wt-tree/index-datum wt-tree index +@deffnx procedure wt-tree/index-pair wt-tree index +Returns the 0-based @var{index}th association of @var{wt-tree} in the +sorted sequence under the tree's ordering relation on the keys. +@code{wt-tree/index} returns the @var{index}th key, +@code{wt-tree/index-datum} returns the datum associated with the +@var{index}th key and @code{wt-tree/index-pair} returns a new pair +@code{(@var{key} . @var{datum})} which is the @code{cons} of the +@var{index}th key and its datum. The average and worst-case times +required by this operation are proportional to the logarithm of the +number of associations in the tree. + +These operations signal a condition of type +@code{condition-type:bad-range-argument} if @var{index}@code{<0} or if +@var{index} is greater than or equal to the number of associations in +the tree. If the tree is empty, they signal an anonymous error. + +Indexing can be used to find the median and maximum keys in the tree as +follows: + +@example +@group +median: (wt-tree/index @var{wt-tree} + (quotient (wt-tree/size @var{wt-tree}) + 2)) +maximum: (wt-tree/index @var{wt-tree} + (- (wt-tree/size @var{wt-tree}) + 1)) +@end group +@end example +@end deffn + +@deffn procedure wt-tree/rank wt-tree key +Determines the 0-based position of @var{key} in the sorted sequence of +the keys under the tree's ordering relation, or @code{#f} if the tree +has no association with for @var{key}. This procedure returns either an +exact non-negative integer or @code{#f}. The average and worst-case +times required by this operation are proportional to the logarithm of +the number of associations in the tree. +@end deffn + +@deffn procedure wt-tree/min wt-tree +@deffnx procedure wt-tree/min-datum wt-tree +@deffnx procedure wt-tree/min-pair wt-tree +Returns the association of @var{wt-tree} that has the least key under the tree's ordering relation. +@code{wt-tree/min} returns the least key, +@code{wt-tree/min-datum} returns the datum associated with the +least key and @code{wt-tree/min-pair} returns a new pair +@code{(key . datum)} which is the @code{cons} of the minimum key and its datum. +The average and worst-case times required by this operation are +proportional to the logarithm of the number of associations in the tree. + +These operations signal an error if the tree is empty. +They could have been written + +@example +@group +(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)) +@end group +@end example +@end deffn + +@deffn procedure wt-tree/delete-min wt-tree +Returns a new tree containing all of the associations in @var{wt-tree} +except the association with the least key under the @var{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 + +@example +(wt-tree/delete @var{wt-tree} (wt-tree/min @var{wt-tree})) +@end example +@end deffn + +@deffn procedure wt-tree/delete-min! wt-tree +Removes the association with the least key under the @var{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 + +@example +(wt-tree/delete! @var{wt-tree} (wt-tree/min @var{wt-tree})) +@end example +@end deffn diff --git a/v7/doc/ref-manual/bit-strings.texi b/v7/doc/ref-manual/bit-strings.texi new file mode 100644 index 000000000..12904fc18 --- /dev/null +++ b/v7/doc/ref-manual/bit-strings.texi @@ -0,0 +1,306 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: bit-strings.texi,v 1.1 2003/04/15 03:29:26 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Bit Strings, Miscellaneous Datatypes, Vectors, Top +@chapter Bit Strings + +@cindex bit string (defn) +@cindex string, of bits (defn) +A @dfn{bit string} is a sequence of bits. Bit strings can be used to +represent sets or to manipulate binary data. The elements of a bit +string are numbered from zero up to the number of bits in the string +less one, in @emph{right to left order}, (the rightmost bit is numbered +zero). When you convert from a bit string to an integer, the zero-th +bit is associated with the zero-th power of two, the first bit is +associated with the first power, and so on. + +Bit strings are encoded very densely in memory. Each bit occupies +exactly one bit of storage, and the overhead for the entire bit string +is bounded by a small constant. However, accessing a bit in a bit +string is slow compared to accessing an element of a vector or character +string. If performance is of overriding concern, it is better to use +character strings to store sets of boolean values even though they +occupy more space. + +@cindex length, of bit string (defn) +@cindex index, of bit string (defn) +@cindex valid index, of bit string (defn) +@cindex bit string length (defn) +@cindex bit string index (defn) +The @dfn{length} of a bit string is the number of bits that it contains. +This number is an exact non-negative integer that is fixed when the bit +string is created. The @dfn{valid indexes} of a bit string are the +exact non-negative integers less than the length of the bit string. + +@cindex external representation, for bit string +@cindex #* as external representation +@cindex asterisk, as external representation +Bit strings may contain zero or more bits. They are not limited by the +length of a machine word. In the printed representation of a bit +string, the contents of the bit string are preceded by @samp{#*}. The +contents are printed starting with the most significant bit (highest +index). + +Note that the external representation of bit strings uses a bit ordering +that is the reverse of the representation for bit strings in Common +Lisp. It is likely that MIT/GNU Scheme's representation will be +changed in the future, to be compatible with Common Lisp. For the time +being this representation should be considered a convenience for viewing +bit strings rather than a means of entering them as data. + +@example +@group +#*11111 +#*1010 +#*00000000 +#* +@end group +@end example + +All of the bit-string procedures are MIT/GNU Scheme extensions. + +@menu +* Construction of Bit Strings:: +* Selecting Bit String Components:: +* Cutting and Pasting Bit Strings:: +* Bitwise Operations on Bit Strings:: +* Modification of Bit Strings:: +* Integer Conversions of Bit Strings:: +@end menu + +@node Construction of Bit Strings, Selecting Bit String Components, Bit Strings, Bit Strings +@section Construction of Bit Strings +@cindex construction, of bit string + +@deffn procedure make-bit-string k initialization +Returns a newly allocated bit string of length @var{k}. If +@var{initialization} is @code{#f}, the bit string is filled with 0 bits; +otherwise, the bit string is filled with 1 bits. + +@example +(make-bit-string 7 #f) @result{} #*0000000 +@end example +@end deffn + +@deffn procedure bit-string-allocate k +Returns a newly allocated bit string of length @var{k}, but does not +initialize it. +@end deffn + +@deffn procedure bit-string-copy bit-string +@cindex copying, of bit string +Returns a newly allocated copy of @var{bit-string}. +@end deffn + +@node Selecting Bit String Components, Cutting and Pasting Bit Strings, Construction of Bit Strings, Bit Strings +@section Selecting Bit String Components + +@deffn procedure bit-string? object +@cindex type predicate, for bit string +Returns @code{#t} if @var{object} is a bit string; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure bit-string-length bit-string +@cindex length, of bit string +Returns the length of @var{bit-string}. +@end deffn + +@deffn procedure bit-string-ref bit-string k +@cindex selection, of bit string component +@cindex component selection, of bit string +Returns @code{#t} if the @var{k}th bit is 1; otherwise returns +@code{#f}. @var{K} must be a valid index of @var{bit-string}. +@end deffn + +@deffn procedure bit-string-set! bit-string k +Sets the @var{k}th bit in @var{bit-string} to 1 and returns an +unspecified value. @var{K} must be a valid index of @var{bit-string}. +@end deffn + +@deffn procedure bit-string-clear! bit-string k +Sets the @var{k}th bit in @var{bit-string} to 0 and returns an +unspecified value. @var{K} must be a valid index of @var{bit-string}. +@end deffn + +@deffn procedure bit-substring-find-next-set-bit bit-string start end +@cindex searching, of bit string +Returns the index of the first occurrence of a set bit in the substring +of @var{bit-string} from @var{start} (inclusive) to @var{end} +(exclusive). If none of the bits in the substring are set @code{#f} is +returned. The index returned is relative to the whole bit string, not +substring. + +The following procedure uses @code{bit-substring-find-next-set-bit} to +find all the set bits and display their indexes: + +@example +@group +(define (scan-bitstring bs) + (let ((end (bit-string-length bs))) + (let loop ((start 0)) + (let ((next + (bit-substring-find-next-set-bit bs start end))) + (if next + (begin + (write-line next) + (if (< next end) + (loop (+ next 1))))))))) +@end group +@end example +@end deffn + +@node Cutting and Pasting Bit Strings, Bitwise Operations on Bit Strings, Selecting Bit String Components, Bit Strings +@section Cutting and Pasting Bit Strings +@cindex cutting, of bit string +@cindex pasting, of bit strings + +@deffn procedure bit-string-append bit-string-1 bit-string-2 +@cindex appending, of bit strings +Appends the two bit string arguments, returning a newly allocated bit +string as its result. In the result, the bits copied from +@var{bit-string-1} are less significant (smaller indices) than those +copied from @var{bit-string-2}. +@end deffn + +@deffn procedure bit-substring bit-string start end +@cindex substring, of bit string +Returns a newly allocated bit string whose bits are copied from +@var{bit-string}, starting at index @var{start} (inclusive) and ending +at @var{end} (exclusive). +@end deffn + +@node Bitwise Operations on Bit Strings, Modification of Bit Strings, Cutting and Pasting Bit Strings, Bit Strings +@section Bitwise Operations on Bit Strings + +@deffn procedure bit-string-zero? bit-string +Returns @code{#t} if @var{bit-string} contains only 0 bits; otherwise +returns @code{#f}. +@end deffn + +@deffn procedure bit-string=? bit-string-1 bit-string-2 +@cindex equivalence predicate, for bit strings +@cindex comparison, of bit strings +Compares the two bit string arguments and returns @code{#t} if they are the +same length and contain the same bits; otherwise returns @code{#f}. +@end deffn + +@deffn procedure bit-string-not bit-string +@cindex inverse, of bit string +Returns a newly allocated bit string that is the bitwise-logical +negation of @var{bit-string}. +@end deffn + +@deffn procedure bit-string-movec! target-bit-string bit-string +The destructive version of @code{bit-string-not}. The arguments +@var{target-bit-string} and @var{bit-string} must be bit strings of the +same length. The bitwise-logical negation of @var{bit-string} is +computed and the result placed in @var{target-bit-string}. The value of +this procedure is unspecified. +@end deffn + +@deffn procedure bit-string-and bit-string-1 bit-string-2 +Returns a newly allocated bit string that is the bitwise-logical ``and'' +of the arguments. The arguments must be bit strings of identical +length. +@end deffn + +@deffn procedure bit-string-andc bit-string-1 bit-string-2 +Returns a newly allocated bit string that is the bitwise-logical ``and'' +of @var{bit-string-1} with the bitwise-logical negation of +@var{bit-string-2}. The arguments must be bit strings of identical +length. +@end deffn + +@deffn procedure bit-string-or bit-string-1 bit-string-2 +Returns a newly allocated bit string that is the bitwise-logical +``inclusive or'' of the arguments. The arguments must be bit strings of +identical length. +@end deffn + +@deffn procedure bit-string-xor bit-string-1 bit-string-2 +Returns a newly allocated bit string that is the bitwise-logical +``exclusive or'' of the arguments. The arguments must be bit strings of +identical length. +@end deffn + +@deffn procedure bit-string-and! target-bit-string bit-string +@deffnx procedure bit-string-or! target-bit-string bit-string +@deffnx procedure bit-string-xor! target-bit-string bit-string +@deffnx procedure bit-string-andc! target-bit-string bit-string +These are destructive versions of the above operations. The arguments +@var{target-bit-string} and @var{bit-string} must be bit strings of the +same length. Each of these procedures performs the corresponding +bitwise-logical operation on its arguments, places the result into +@var{target-bit-string}, and returns an unspecified result. +@end deffn + +@node Modification of Bit Strings, Integer Conversions of Bit Strings, Bitwise Operations on Bit Strings, Bit Strings +@section Modification of Bit Strings +@cindex modification, of bit string +@cindex filling, of bit string +@cindex moving, of bit string elements + +@deffn procedure bit-string-fill! bit-string initialization +Fills @var{bit-string} with zeroes if @var{initialization} is @code{#f}; +otherwise fills @var{bit-string} with ones. Returns an unspecified +value. +@end deffn + +@deffn procedure bit-string-move! target-bit-string bit-string +Moves the contents of @var{bit-string} into @var{target-bit-string}. Both +arguments must be bit strings of the same length. The results of the +operation are undefined if the arguments are the same bit string. +@end deffn + +@deffn procedure bit-substring-move-right! bit-string-1 start1 end1 bit-string-2 start2 +Destructively copies the bits of @var{bit-string-1}, starting at index +@var{start1} (inclusive) and ending at @var{end1} (exclusive), into +@var{bit-string-2} starting at index @var{start2} (inclusive). +@var{Start1} and @var{end1} must be valid substring indices for +@var{bit-string-1}, and @var{start2} must be a valid index for +@var{bit-string-2}. The length of the source substring must not exceed +the length of @var{bit-string-2} minus the index @var{start2}. + +The bits are copied starting from the MSB and working towards the LSB; the +direction of copying only matters when @var{bit-string-1} and +@var{bit-string-2} are @code{eqv?}. +@end deffn + +@need 1000 +@node Integer Conversions of Bit Strings, , Modification of Bit Strings, Bit Strings +@section Integer Conversions of Bit Strings +@cindex integer, converting to bit string + +@deffn procedure unsigned-integer->bit-string length integer +Both @var{length} and @var{integer} must be exact non-negative integers. +Converts @var{integer} into a newly allocated bit string of @var{length} +bits. Signals an error of type @code{condition-type:bad-range-argument} +if @var{integer} is too large to be represented in @var{length} bits. +@findex condition-type:bad-range-argument +@end deffn + +@deffn procedure signed-integer->bit-string length integer +@var{Length} must be an exact non-negative integer, and @var{integer} +may be any exact integer. Converts @var{integer} into a newly allocated +bit string of @var{length} bits, using two's complement encoding for +negative numbers. Signals an error of type +@code{condition-type:bad-range-argument} if @var{integer} is too large +to be represented in @var{length} bits. +@findex condition-type:bad-range-argument +@end deffn + +@deffn procedure bit-string->unsigned-integer bit-string +@deffnx procedure bit-string->signed-integer bit-string +Converts @var{bit-string} into an exact integer. +@code{bit-string->signed-integer} regards @var{bit-string} as a two's +complement representation of a signed integer, and produces an integer +of like sign and absolute value. @code{bit-string->unsigned-integer} +regards @var{bit-string} as an unsigned quantity and converts to an +integer accordingly. +@end deffn diff --git a/v7/doc/ref-manual/characters.texi b/v7/doc/ref-manual/characters.texi new file mode 100644 index 000000000..26932c423 --- /dev/null +++ b/v7/doc/ref-manual/characters.texi @@ -0,0 +1,792 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: characters.texi,v 1.1 2003/04/15 03:29:29 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Characters, Strings, Numbers, Top +@chapter Characters + +@cindex character (defn) +Characters are objects that represent printed characters, such as +letters and digits.@footnote{Some of the details in this section depend +on the fact that the underlying operating system uses the +@acronym{ASCII} character set. This may change when someone ports MIT/GNU +Scheme to a non-@acronym{ASCII} operating system.} + +@menu +* External Representation of Characters:: +* Comparison of Characters:: +* Miscellaneous Character Operations:: +* Internal Representation of Characters:: +* ISO-8859-1 Characters:: +* Character Sets:: +* Unicode:: +@end menu + +@node External Representation of Characters, Comparison of Characters, Characters, Characters +@section External Representation of Characters +@cindex external representation, for character + +@cindex #\ as external representation +@findex #\ +Characters are written using the notation @code{#\@var{character}} or +@code{#\@var{character-name}}. For example: + +@example +@group +#\a @r{; lowercase letter} +#\A @r{; uppercase letter} +#\( @r{; left parenthesis} +#\space @r{; the space character} +#\newline @r{; the newline character} +@end group +@end example +@findex #\space +@findex #\newline + +@noindent +Case is significant in @code{#\@var{character}}, but not in +@code{#\@var{character-name}}. If @var{character} in +@code{#\@var{character}} is a letter, @var{character} must be followed +by a delimiter character such as a space or parenthesis. Characters +written in the @code{#\} notation are self-evaluating; you don't need to +quote them. + +@cindex bucky bit, prefix (defn) +@cindex control, bucky bit prefix (defn) +@cindex meta, bucky bit prefix (defn) +@cindex super, bucky bit prefix (defn) +@cindex hyper, bucky bit prefix (defn) +@cindex top, bucky bit prefix (defn) +A character name may include one or more @dfn{bucky bit} prefixes to +indicate that the character includes one or more of the keyboard shift +keys Control, Meta, Super, Hyper, or Top (note that the Control bucky +bit prefix is not the same as the @acronym{ASCII} control key). The +bucky bit prefixes and their meanings are as follows (case is not +significant): + +@example +@group +Key Bucky bit prefix Bucky bit +--- ---------------- --------- + +Meta M- or Meta- 1 +Control C- or Control- 2 +Super S- or Super- 4 +Hyper H- or Hyper- 8 +Top T- or Top- 16 +@end group +@end example + +@noindent +For example, + +@example +@group +#\c-a @r{; Control-a} +#\meta-b @r{; Meta-b} +#\c-s-m-h-a @r{; Control-Meta-Super-Hyper-A} +@end group +@end example + +@cindex character, named (defn) +@cindex name, of character +The following @var{character-name}s are supported, shown here with their +@acronym{ASCII} equivalents: + +@example +@group +Character Name ASCII Name +-------------- ---------- + +altmode ESC +backnext US +backspace BS +call SUB +linefeed LF +page FF +return CR +rubout DEL +space +tab HT +@end group +@end example +@findex #\altmode +@findex #\backnext +@findex #\backspace +@findex #\call +@findex #\linefeed +@findex #\page +@findex #\return +@findex #\rubout +@findex #\space +@findex #\tab + +@noindent +@cindex newline character (defn) +@findex #\newline +In addition, @code{#\newline} is the same as @code{#\linefeed} (but this +may change in the future, so you should not depend on it). All of the +standard @acronym{ASCII} names for non-printing characters are supported: + +@example +@group +NUL SOH STX ETX EOT ENQ ACK BEL +BS HT LF VT FF CR SO SI +DLE DC1 DC2 DC3 DC4 NAK SYN ETB +CAN EM SUB ESC FS GS RS US +DEL +@end group +@end example + +@deffn procedure char->name char [slashify?] +Returns a string corresponding to the printed representation of +@var{char}. This is the @var{character} or @var{character-name} +component of the external representation, combined with the appropriate +bucky bit prefixes. + +@example +@group +(char->name #\a) @result{} "a" +(char->name #\space) @result{} "Space" +(char->name #\c-a) @result{} "C-a" +(char->name #\control-a) @result{} "C-a" +@end group +@end example + +@findex read +@var{Slashify?}, if specified and true, says to insert the necessary +backslash characters in the result so that @code{read} will parse it +correctly. In other words, the following generates the external +representation of @var{char}: + +@example +(string-append "#\\" (char->name @var{char} #t)) +@end example + +@noindent +If @var{slashify?} is not specified, it defaults to @code{#f}. +@end deffn + +@deffn procedure name->char string +Converts a string that names a character into the character specified. +If @var{string} does not name any character, @code{name->char} signals +an error. + +@example +@group +(name->char "a") @result{} #\a +(name->char "space") @result{} #\Space +(name->char "c-a") @result{} #\C-a +(name->char "control-a") @result{} #\C-a +@end group +@end example +@end deffn + +@node Comparison of Characters, Miscellaneous Character Operations, External Representation of Characters, Characters +@section Comparison of Characters +@cindex ordering, of characters +@cindex comparison, of characters +@cindex equivalence predicates, for characters + +@deffn procedure char=? char1 char2 +@deffnx procedure char? char1 char2 +@deffnx procedure char<=? char1 char2 +@deffnx procedure char>=? char1 char2 +@deffnx {procedure} char-ci=? char1 char2 +@deffnx {procedure} char-ci? char1 char2 +@deffnx {procedure} char-ci<=? char1 char2 +@deffnx {procedure} char-ci>=? char1 char2 +@cindex equivalence predicate, for characters +Returns @code{#t} if the specified characters are have the appropriate +order relationship to one another; otherwise returns @code{#f}. The +@code{-ci} procedures don't distinguish uppercase and lowercase letters. + +Character ordering follows these rules: + +@itemize @bullet +@item +The digits are in order; for example, @code{(chardigit char [radix] +If @var{char} is a character representing a digit in the given +@var{radix}, returns the corresponding integer value. If you specify +@var{radix} (which must be an exact integer between 2 and 36 inclusive), +the conversion is done in that base, otherwise it is done in base 10. +If @var{char} doesn't represent a digit in base @var{radix}, +@code{char->digit} returns @code{#f}. + +Note that this procedure is insensitive to the alphabetic case of +@var{char}. + +@example +@group +(char->digit #\8) @result{} 8 +(char->digit #\e 16) @result{} 14 +(char->digit #\e) @result{} #f +@end group +@end example +@end deffn + +@deffn procedure digit->char digit [radix] +Returns a character that represents @var{digit} in the radix given by +@var{radix}. @var{Radix} must be an exact integer between 2 and 36 +(inclusive), and defaults to 10. @var{Digit}, which must be an +exact non-negative integer, should be less than @var{radix}; if +@var{digit} is greater than or equal to @var{radix}, @code{digit->char} +returns @code{#f}. + +@example +@group +(digit->char 8) @result{} #\8 +(digit->char 14 16) @result{} #\E +@end group +@end example +@end deffn + +@node Internal Representation of Characters, ISO-8859-1 Characters, Miscellaneous Character Operations, Characters +@section Internal Representation of Characters +@cindex internal representation, for character + +@cindex character code (defn) +@cindex character bits (defn) +@cindex code, of character (defn) +@cindex bucky bit, of character (defn) +@cindex ASCII character +An MIT/GNU Scheme character consists of a @dfn{code} part and a @dfn{bucky +bits} part. The MIT/GNU Scheme set of characters can represent more +characters than @acronym{ASCII} can; it includes characters with Super, +Hyper, and Top bucky bits, as well as Control and Meta. Every +@acronym{ASCII} character corresponds to some MIT/GNU Scheme character, but not +vice versa.@footnote{Note that the Control bucky bit is different from +the @acronym{ASCII} control key. This means that @code{#\SOH} (@acronym{ASCII} +ctrl-A) is different from @code{#\C-A}. In fact, the Control bucky bit +is completely orthogonal to the @acronym{ASCII} control key, making possible +such characters as @code{#\C-SOH}.} + +MIT/GNU Scheme uses a 16-bit character code with 5 bucky bits. Normally, +Scheme uses the least significant 8 bits of the character code to +contain the @acronym{ISO-8859-1} representation for the character. The +representation is expanded in order to allow for the use of +@acronym{UTF-16} in the future. + +@deffn procedure make-char code bucky-bits +@cindex construction, of character +Builds a character from @var{code} and @var{bucky-bits}. Both +@var{code} and @var{bucky-bits} must be exact non-negative integers in +the appropriate range. Use @code{char-code} and @code{char-bits} to +extract the code and bucky bits from the character. If @code{0} is +specified for @var{bucky-bits}, @code{make-char} produces an ordinary +character; otherwise, the appropriate bits are turned on as follows: + +@example +@group +1 Meta +2 Control +4 Super +8 Hyper +16 Top +@end group +@end example + +For example, + +@example +@group +(make-char 97 0) @result{} #\a +(make-char 97 1) @result{} #\M-a +(make-char 97 2) @result{} #\C-a +(make-char 97 3) @result{} #\C-M-a +@end group +@end example +@end deffn + +@deffn procedure char-bits char +@cindex selection, of character component +@cindex component selection, of character +Returns the exact integer representation of @var{char}'s bucky bits. +For example, + +@example +@group +(char-bits #\a) @result{} 0 +(char-bits #\m-a) @result{} 1 +(char-bits #\c-a) @result{} 2 +(char-bits #\c-m-a) @result{} 3 +@end group +@end example +@end deffn + +@deffn procedure char-code char +Returns the character code of @var{char}, an exact integer. For +example, + +@example +@group +(char-code #\a) @result{} 97 +(char-code #\c-a) @result{} 97 +@end group +@end example +@end deffn + +@defvr variable char-code-limit +@defvrx variable char-bits-limit +These variables define the (exclusive) upper limits for the character +code and bucky bits (respectively). The character code and bucky bits +are always exact non-negative integers, and are strictly less than the +value of their respective limit variable. +@end defvr + +@deffn procedure char->integer char +@deffnx procedure integer->char k +@code{char->integer} returns the character code representation for +@var{char}. @code{integer->char} returns the character whose character +code representation is @var{k}. + +@findex char-ascii? +@findex char->ascii +In MIT/GNU Scheme, if @code{(char-ascii? @var{char})} is true, then + +@example +(eqv? (char->ascii @var{char}) (char->integer @var{char})) +@end example + +@noindent +However, this behavior is not required by the Scheme standard, and +code that depends on it is not portable to other implementations. + +@findex char<=? +@findex <= +These procedures implement order isomorphisms between the set of +characters under the @code{char<=?} ordering and some subset of the +integers under the @code{<=} ordering. That is, if + +@example +(char<=? a b) @result{} #t @r{and} (<= x y) @result{} #t +@end example + +and @code{x} and @code{y} are in the range of @code{char->integer}, +then + +@example +@group +(<= (char->integer a) + (char->integer b)) @result{} #t +(char<=? (integer->char x) + (integer->char y)) @result{} #t +@end group +@end example + +Note: If the argument to @code{char->integer} or @code{integer->char} is +a constant, the compiler will constant-fold the call, replacing it with +the corresponding result. This is a very useful way to denote unusual +character constants or @acronym{ASCII} codes. +@end deffn + +@defvr variable char-integer-limit +The range of @code{char->integer} is defined to be the exact +non-negative integers that are less than the value of this variable +(exclusive). +@end defvr + +@node ISO-8859-1 Characters, Character Sets, Internal Representation of Characters, Characters +@section ISO-8859-1 Characters + +MIT/GNU Scheme internally uses @acronym{ISO-8859-1} codes for +@acronym{I/O}, and stores character objects in a fashion that makes it +convenient to convert between @acronym{ISO-8859-1} codes and +characters. Also, character strings are implemented as byte vectors +whose elements are @acronym{ISO-8859-1} codes; these codes are +converted to character objects when accessed. For these reasons it is +sometimes desirable to be able to convert between @acronym{ISO-8859-1} +codes and characters. + +@cindex ISO-8859-1 character (defn) +@cindex character, ISO-8859-1 (defn) +Not all characters can be represented as @acronym{ISO-8859-1} codes. A +character that has an equivalent @acronym{ISO-8859-1} representation is +called an @dfn{ISO-8859-1 character}. + +For historical reasons, the procedures that manipulate +@acronym{ISO-8859-1} characters use the word ``@acronym{ASCII}'' rather +than ``@acronym{ISO-8859-1}''. + +@deffn procedure char-ascii? char +Returns the @acronym{ISO-8859-1} code for @var{char} if @var{char} has an +@acronym{ISO-8859-1} representation; otherwise returns @code{#f}. + +In the current implementation, the characters that satisfy this +predicate are those in which the bucky bits are turned off, and for +which the character code is less than 256. +@end deffn + +@deffn procedure char->ascii char +Returns the @acronym{ISO-8859-1} code for @var{char}. An error +@code{condition-type:bad-range-argument} is signalled if @var{char} +doesn't have an @acronym{ISO-8859-1} representation. +@findex condition-type:bad-range-argument +@end deffn + +@deffn procedure ascii->char code +@var{Code} must be the exact integer representation of an +@acronym{ISO-8859-1} code. This procedure returns the character +corresponding to @var{code}. +@end deffn + +@node Character Sets, Unicode, ISO-8859-1 Characters, Characters +@section Character Sets +@cindex character set +@cindex set, of characters + +MIT/GNU Scheme's character-set abstraction is used to represent groups of +characters, such as the letters or digits. Character sets may contain +only @acronym{ISO-8859-1} characters; in the future this may be changed +to allow the full range of characters. + +There is no meaningful external representation for character sets; use +@code{char-set-members} to examine their contents. There is (at +present) no specific equivalence predicate for character sets; use +@code{equal?} for this purpose. + +@deffn procedure char-set? object +@cindex type predicate, for character set +Returns @code{#t} if @var{object} is a character set; otherwise returns +@code{#f}. +@end deffn + +@defvr variable char-set:upper-case +@defvrx variable char-set:lower-case +@defvrx variable char-set:alphabetic +@defvrx variable char-set:numeric +@defvrx variable char-set:alphanumeric +@defvrx variable char-set:whitespace +@defvrx variable char-set:not-whitespace +@defvrx variable char-set:graphic +@defvrx variable char-set:not-graphic +@defvrx variable char-set:standard +These variables contain predefined character sets. +To see the contents of one of these sets, use @code{char-set-members}. + +@cindex alphabetic character (defn) +@cindex character, alphabetic (defn) +@cindex numeric character (defn) +@cindex character, numeric (defn) +@cindex alphanumeric character (defn) +@cindex character, alphanumeric (defn) +@cindex whitespace character (defn) +@cindex character, whitespace (defn) +@cindex graphic character (defn) +@cindex character, graphic (defn) +@cindex standard character (defn) +@cindex character, standard (defn) +@findex #\space +@findex #\tab +@findex #\page +@findex #\linefeed +@findex #\return +@findex #\newline +@dfn{Alphabetic} characters are the 52 upper and lower case letters. +@dfn{Numeric} characters are the 10 decimal digits. @dfn{Alphanumeric} +characters are those in the union of these two sets. @dfn{Whitespace} +characters are @code{#\space}, @code{#\tab}, @code{#\page}, +@code{#\linefeed}, and @code{#\return}. @var{Graphic} characters are +the printing characters and @code{#\space}. @var{Standard} characters +are the printing characters, @code{#\space}, and @code{#\newline}. +These are the printing characters: + +@example +@group +! " # $ % & ' ( ) * + , - . / +0 1 2 3 4 5 6 7 8 9 +: ; < = > ? @@ +A B C D E F G H I J K L M N O P Q R S T U V W X Y Z +[ \ ] ^ _ ` +a b c d e f g h i j k l m n o p q r s t u v w x y z +@{ | @} ~ +@end group +@end example +@end defvr + +@deffn {procedure} char-upper-case? char +@deffnx {procedure} char-lower-case? char +@deffnx {procedure} char-alphabetic? char +@deffnx {procedure} char-numeric? char +@deffnx procedure char-alphanumeric? char +@deffnx {procedure} char-whitespace? char +@deffnx procedure char-graphic? char +@deffnx procedure char-standard? object +These predicates are defined in terms of the respective character sets +defined above. +@end deffn + +@deffn procedure char-set-members char-set +Returns a newly allocated list of the characters in @var{char-set}. +@end deffn + +@deffn procedure char-set-member? char-set char +Returns @code{#t} if @var{char} is in @var{char-set}; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure char-set char @dots{} +@cindex construction, of character set +Returns a character set consisting of the specified @acronym{ISO-8859-1} +characters. With no arguments, @code{char-set} returns an empty +character set. +@end deffn + +@deffn procedure chars->char-set chars +Returns a character set consisting of @var{chars}, which must be a list +of @acronym{ISO-8859-1} characters. This is equivalent to @code{(apply +char-set @var{chars})}. +@end deffn + +@deffn procedure string->char-set string +Returns a character set consisting of all the characters that occur in +@var{string}. +@end deffn + +@deffn procedure ascii-range->char-set lower upper +@var{Lower} and @var{upper} must be exact non-negative integers +representing @acronym{ISO-8859-1} character codes, and @var{lower} must +be less than or equal to @var{upper}. This procedure creates and +returns a new character set consisting of the characters whose +@acronym{ISO-8859-1} codes are between @var{lower} (inclusive) and +@var{upper} (exclusive). + +For historical reasons, the name of this procedure refers to +``@acronym{ASCII}'' rather than ``@acronym{ISO-8859-1}''. +@end deffn + +@deffn procedure predicate->char-set predicate +@var{Predicate} must be a procedure of one argument. +@code{predicate->char-set} creates and returns a character set +consisting of the @acronym{ISO-8859-1} characters for which +@var{predicate} is true. +@end deffn + +@deffn procedure char-set-difference char-set1 char-set2 +Returns a character set consisting of the characters that are in +@var{char-set1} but aren't in @var{char-set2}. +@end deffn + +@deffn procedure char-set-intersection char-set @dots{} +Returns a character set consisting of the characters that are in all of +the @var{char-set}s. +@end deffn + +@deffn procedure char-set-union char-set @dots{} +Returns a character set consisting of the characters that are in at +least one o the @var{char-set}s. +@end deffn + +@deffn procedure char-set-invert char-set +Returns a character set consisting of the @acronym{ISO-8859-1} +characters that are not in @var{char-set}. +@end deffn + +@node Unicode, , Character Sets, Characters +@section Unicode + +@cindex Unicode +MIT/GNU Scheme provides rudimentary support for Unicode characters. In an +ideal world, Unicode would be the base character set for MIT/GNU Scheme, +but this implementation predates the invention of Unicode. And +converting an application of this size is a considerable undertaking. +So for the time being, the base character set is @acronym{ISO-8859-1} +and Unicode support is grafted on. + +This Unicode support was implemented as a part of the @acronym{XML} +parser (@pxref{XML Parser}) implementation. @acronym{XML} uses +Unicode as its base character set, and any @acronym{XML} +implementation @emph{must} support Unicode. + +The Unicode implementation consists of two parts: @acronym{I/O} +procedures that read and write @acronym{UTF-8} characters, and an +@dfn{alphabet} abstraction, which is an efficient implementation of +sets of Unicode code points (similar to the @code{char-set} +abstraction). + +@cindex Code point, Unicode +The basic unit in a Unicode implementation is the @dfn{code point}. + +@deffn procedure unicode-code-point? object +Returns @code{#t} if @var{object} is a Unicode code point. Code +points are implemented as exact non-negative integers. Code points +are further limited, by the Unicode standard, to be strictly less than +@code{#x80000000}. +@end deffn + +The next few procedures do @acronym{I/O} on code points. + +@deffn procedure read-utf8-code-point port +Reads and returns a @acronym{UTF-8}-encoded code point from +@var{port}. Returns an end-of-file object if there are no more +characters available from @var{port}. Signals an error if the input +stream isn't a valid @acronym{UTF-8} encoding. +@end deffn + +@deffn procedure write-utf8-code-point code-point port +Writes @var{code-point} to @var{port} in the @acronym{UTF-8} encoding. +@end deffn + +@deffn procedure utf8-string->code-point string +Reads and returns a @acronym{UTF-8}-encoded code point from +@var{string}. Equivalent to + +@example +(read-utf8-code-point (string->input-port @var{string})) +@end example +@end deffn + +@deffn procedure code-point->utf8-string code-point +Returns a newly-allocated string containing the @acronym{UTF-8} +encoding of @var{code-point}. Equivalent to + +@example +@group +(with-string-output-port + (lambda (port) + (write-utf8-code-point @var{code-point} port))) +@end group +@end example +@end deffn + +@cindex Alphabet, Unicode +Applications often need to manipulate sets of characters, such as the +set of alphabetic characters or the set of whitespace characters. The +@dfn{alphabet} abstraction provides an efficient implementation of +sets of Unicode code points. + +@deffn procedure alphabet? object +Returns @code{#t} if @var{object} is a Unicode alphabet, otherwise +returns @code{#f}. +@end deffn + +@deffn procedure code-points->alphabet items +Returns a Unicode alphabet containing the code points described by +@var{items}. @var{Items} must satisfy +@code{well-formed-code-points-list?}. +@end deffn + +@deffn procedure alphabet->code-points alphabet +Returns a well-formed code-points list that describes the code points +represented by @var{alphabet}. +@end deffn + +@deffn procedure well-formed-code-points-list? object +Returns @code{#t} if @var{object} is a well-formed code-points list, +otherwise returns @code{#f}. A well-formed code-points list is a +proper list, each element of which is either a code point or a pair of +code points. A pair of code points represents a contiguous range of +code points. The @sc{car} of the pair is the lower limit, and the +@sc{cdr} is the upper limit. Both limits are inclusive, and the lower +limit must be strictly less than the upper limit. +@end deffn + +@deffn procedure code-point-in-alphabet? code-point alphabet +Returns @code{#t} if @var{code-point} is a member of @var{alphabet}, +otherwise returns @code{#f}. +@end deffn + +@deffn procedure char-in-alphabet? char alphabet +Returns @code{#t} if @var{char} is a member of @var{alphabet}, +otherwise returns @code{#f}. Equivalent to + +@example +(code-point-in-alphabet? (char-code @var{char}) @var{alphabet}) +@end example +@end deffn + +Character sets and alphabets can be converted to one another, provided +that the alphabet contains only 8-bit code points. This is true +because 8-bit code points in Unicode map directly to +@acronym{ISO-8859-1} characters, which is what character sets contain. + +@deffn procedure char-set->alphabet char-set +Returns a Unicode alphabet containing the code points that correspond +to characters that are members of @var{char-set}. +@end deffn + +@deffn procedure alphabet->char-set alphabet +Returns a character set containing the characters that correspond to +8-bit code points that are members of @var{alphabet}. (Code points +outside the 8-bit range are ignored.) +@end deffn + +@deffn procedure string->alphabet string +Returns a Unicode alphabet containing the code points corresponding to +the characters in @var{string}. Equivalent to + +@example +(char-set->alphabet (string->char-set @var{string})) +@end example +@end deffn + +@deffn procedure alphabet->string alphabet +Returns a newly-allocated string containing the characters +corresponding to the 8-bit code points in @var{alphabet}. (Code +points outside the 8-bit range are ignored.) +@end deffn + +@deffn procedure 8-bit-alphabet? alphabet +Returns @code{#t} if @var{alphabet} contains only 8-bit code points, +otherwise returns @code{#f}. +@end deffn + +@deffn procedure alphabet+ alphabet @dots{} +Returns a Unicode alphabet that contains each code point that is a +member of any of the @var{alphabet} arguments. +@end deffn + +@deffn procedure alphabet- alphabet1 alphabet2 +Returns a Unicode alphabet that contains each code point that is a +member of @var{alphabet1} and is not a member of @var{alphabet2}. +@end deffn diff --git a/v7/doc/ref-manual/environments.texi b/v7/doc/ref-manual/environments.texi new file mode 100644 index 000000000..5068d482e --- /dev/null +++ b/v7/doc/ref-manual/environments.texi @@ -0,0 +1,320 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: environments.texi,v 1.1 2003/04/15 03:29:32 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Environments, Input/Output, Procedures, Top +@chapter Environments + +@menu +* Environment Operations:: +* Environment Variables:: +* REPL Environment:: +* Top-level Environments:: +@end menu + +@node Environment Operations, Environment Variables, Environments, Environments +@section Environment Operations + +Environments are first-class objects in MIT/GNU Scheme. An environment +consists of some bindings and possibly a parent environment, from which +other bindings are inherited. The operations in this section reveal the +frame-like structure of environments by permitting you to examine the +bindings of a particular environment separately from those of its +parent. + +@cindex variable binding +@cindex binding, variable +@cindex unassigned binding +@cindex binding, unassigned +@findex condition-type:unassigned-variable +There are several types of bindings that can occur in an environment. +The most common is the simple variable binding, which associates a value +(any Scheme object) with an identifier (a symbol). A variable binding +can also be @dfn{unassigned}, which means that it has no value. An +unassigned variable is bound, in that is will shadow other bindings of +the same name in ancestor environments, but a reference to that variable +will signal an error of type @code{condition-type:unassigned-variable}. +An unassigned variable can be @dfn{assigned} (using @code{set!} or +@code{environment-assign!}) to give it a value. + +@cindex keyword binding +@cindex syntactic keyword binding +@cindex binding, syntactic keyword +@findex condition-type:macro-binding +In addition to variable bindings, an environment can also have +@dfn{keyword bindings}. A keyword binding associates a syntactic +keyword (usually a macro transformer) with an identifier. Keyword +bindings are special in that they are considered ``bound'', but ordinary +variable references don't work on them. So an attempt to reference or +assign a keyword binding results in an error of type +@code{condition-type:macro-binding}. However, keyword bindings can be +redefined using @code{define} or @code{environment-define}. + +@deffn procedure environment? object +@cindex type predicate, for environment +Returns @code{#t} if @var{object} is an environment; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure environment-has-parent? environment +Returns @code{#t} if @var{environment} has a parent environment; +otherwise returns @code{#f}. +@end deffn + +@deffn procedure environment-parent environment +Returns the parent environment of @var{environment}. It is an error if +@var{environment} has no parent. +@end deffn + +@deffn procedure environment-bound-names environment +Returns a newly allocated list of the names (symbols) that are bound by +@var{environment}. This does not include the names that are bound by +the parent environment of @var{environment}. It does include names that +are unassigned or keywords in @var{environment}. +@end deffn + +@deffn procedure environment-macro-names environment +Returns a newly allocated list of the names (symbols) that are bound to +syntactic keywords in @var{environment}. +@end deffn + +@deffn procedure environment-bindings environment +Returns a newly allocated list of the bindings of @var{environment}; +does not include the bindings of the parent environment. Each element +of this list takes one of two forms: @code{(@var{symbol})} indicates +that @var{symbol} is bound but unassigned, while @code{(@var{symbol} +@var{object})} indicates that @var{symbol} is bound, and its value is +@var{object}. +@end deffn + +@deffn procedure environment-reference-type environment symbol +Returns a symbol describing the @dfn{reference type} of @var{symbol} in +@var{environment} or one of its ancestor environments. The result is +one of the following: + +@table @code +@item normal +means @var{symbol} is a variable binding with a normal value. + +@item unassigned +means @var{symbol} is a variable binding with no value. + +@item macro +means @var{symbol} is a keyword binding. + +@item unbound +means @var{symbol} has no associated binding. +@end table +@end deffn + +@deffn procedure environment-bound? environment symbol +Returns @code{#t} if @var{symbol} is bound in @var{environment} or one +of its ancestor environments; otherwise returns @code{#f}. This is +equivalent to + +@example +(not (eq? 'unbound + (environment-reference-type @var{environment} @var{symbol}))) +@end example +@end deffn + +@deffn procedure environment-assigned? environment symbol +Returns @code{#t} if @var{symbol} is bound in @var{environment} or one +of its ancestor environments, and has a normal value. Returns @code{#f} +if it is bound but unassigned. Signals an error if it is unbound or is +bound to a keyword. +@end deffn + +@deffn procedure environment-lookup environment symbol +@var{Symbol} must be bound to a normal value in @var{environment} or one +of its ancestor environments. Returns the value to which it is bound. +Signals an error if unbound, unassigned, or a keyword. +@end deffn + +@deffn procedure environment-lookup-macro environment symbol +If @var{symbol} is a keyword binding in @var{environment} or one of its +ancestor environments, returns the value of the binding. Otherwise, +returns @code{#f}. Does not signal any errors other than argument-type +errors. +@end deffn + +@deffn procedure environment-assignable? environment symbol +@var{Symbol} must be bound in @var{environment} or one of its ancestor +environments. Returns @code{#t} if the binding may be modified by side +effect. +@end deffn + +@deffn procedure environment-assign! environment symbol object +@var{Symbol} must be bound in @var{environment} or one of its ancestor +environments, and must be assignable. Modifies the binding to have +@var{object} as its value, and returns an unspecified result. +@end deffn + +@deffn procedure environment-definable? environment symbol +Returns @code{#t} if @var{symbol} is definable in @var{environment}, and +@code{#f} otherwise. At present, this is false for environments +generated by application of compiled procedures, and true for all other +environments. +@end deffn + +@deffn procedure environment-define environment symbol object +Defines @var{symbol} to be bound to @var{object} in @var{environment}, +and returns an unspecified value. Signals an error if @var{symbol} +isn't definable in @var{environment}. +@end deffn + +@deffn procedure environment-define-macro environment symbol transformer +Defines @var{symbol} to be a keyword bound to @var{transformer} in +@var{environment}, and returns an unspecified value. Signals an error +if @var{symbol} isn't definable in @var{environment}. The type of +@var{transformer} is defined by the syntax engine and is not checked by +this procedure. If the type is incorrect this will subsequently signal +an error during syntax expansion. +@end deffn + +@deffn procedure eval expression environment +@cindex s-expression +@cindex evaluation, of s-expression +Evaluates @var{expression}, a list-structure representation (sometimes +called s-expression representation) of a Scheme expression, in +@var{environment}. You rarely need @code{eval} in ordinary programs; it +is useful mostly for evaluating expressions that have been created ``on +the fly'' by a program. @code{eval} is relatively expensive because it +must convert @var{expression} to an internal form before it is executed. + +@example +@group +(define foo (list '+ 1 2)) +(eval foo (the-environment)) @result{} 3 +@end group +@end example +@end deffn + +@node Environment Variables, REPL Environment, Environment Operations, Environments +@section Environment Variables + +@findex define +The @code{user-initial-environment} is where the top-level +read-eval-print (@acronym{REP}) loop evaluates expressions and binds +definitions. It is a child of @code{system-global-environment}, which +is where all of the Scheme system definitions are bound. All of the +bindings in @code{system-global-environment} are available when the +current environment is @code{user-initial-environment}. However, any +new bindings that you create in the @acronym{REP} loop (with +@code{define} forms or by loading files containing @code{define} forms) +occur in @code{user-initial-environment}. + +@defvr variable system-global-environment +The variable @code{system-global-environment} is bound to the +distinguished environment that's the ancestor of most other environments +(except for those created by @code{make-root-top-level-environment}). +It is the parent environment of @code{user-initial-environment}. +Primitives, system procedures, and most syntactic keywords are bound +(and sometimes closed) in this environment. +@end defvr + +@defvr variable user-initial-environment +The variable @code{user-initial-environment} is bound to the default +environment in which typed expressions are evaluated by the top-level +@acronym{REP} loop. + +Although all bindings in @code{system-global-environment} are visible to +the @acronym{REP} loop, definitions that are typed at, or loaded by, the +@acronym{REP} loop occur in the @code{user-initial-environment}. This +is partly a safety measure: if you enter a definition that happens to +have the same name as a critical system procedure, your definition will +be visible only to the procedures you define in the +@code{user-initial-environment}; the MIT/GNU Scheme system procedures, which +are defined in @code{system-global-environment}, will continue to see +the original definition. +@end defvr + +@node REPL Environment, Top-level Environments, Environment Variables, Environments +@section REPL Environment + +@deffn procedure nearest-repl/environment +@findex user-initial-environment +Returns the current @acronym{REP} loop environment (i.e.@: the current +environment of the closest enclosing @acronym{REP} loop). When Scheme +first starts up, this is the same as @code{user-initial-environment}. +@end deffn + +@deffn procedure ge environment +Changes the current @acronym{REP} loop environment to @var{environment}. +@var{Environment} can be either an environment or a procedure object. +If it's a procedure, the environment in which that procedure was closed +is the new environment. +@end deffn + +@node Top-level Environments, , REPL Environment, Environments +@section Top-level Environments + +@cindex top-level environment +@cindex interpreter environment +@cindex environment, top-level +@cindex environment, interpreter +The operations in this section manipulate @dfn{top-level environments}, +as opposed to environments created by the application of procedures. +For historical reasons, top-level environments are referred to as +@dfn{interpreter environments}. + +@deffn {special form} the-environment +@cindex current environment +@cindex environment, current +Returns the current environment. This form may only be evaluated in a +top-level environment. An error is signalled if it appears elsewhere. +@end deffn + +@deffn procedure top-level-environment? object +@deffnx procedure interpreter-environment? object +@cindex type predicate, for top-level environment +Returns @code{#t} if @var{object} is an top-level environment; otherwise +returns @code{#f}. + +@code{interpreter-environment?} is an alias for +@code{top-level-environment?}. +@end deffn + +@deffn procedure extend-top-level-environment environment [names [values]] +@deffnx procedure make-root-top-level-environment [names [values]] +Returns a newly allocated top-level environment. +@code{extend-top-level-environment} creates an environment that has +parent @var{environment}, while @code{make-root-top-level-environment} +creates an environment that has no parent. + +The optional arguments @var{names} and @var{values} are used to specify +initial bindings in the new environment. If specified, @var{names} must +be a list of symbols, and @var{values} must be a list of objects. If +only @var{names} is specified, each name in @var{names} will be bound in +the environment, but unassigned. If @var{names} and @var{values} are +both specified, they must be the same length, and each name in +@var{names} will be bound to the corresponding value in @var{values}. +If neither @var{names} nor @var{values} is specified, the environment +will have no initial bindings. +@end deffn + +@deffn procedure link-variables environment1 symbol1 environment2 symbol2 +Defines @var{symbol1} in @var{environment1} to have the same binding as +@var{symbol2} in @var{environment2}, and returns an unspecified value. +Prior to the call, @var{symbol2} must be bound in @var{environment2}, +but the type of binding is irrelevant; it may be a normal binding, an +unassigned binding, or a keyword binding. Signals an error if +@var{symbol1} isn't definable in @var{environment1}, or if @var{symbol2} +is unbound in @var{environment2}. + +By ``the same binding'', we mean that the value cell is shared between +the two environments. If a value is assigned to @var{symbol1} in +@var{environment1}, a subsequent reference to @var{symbol2} in +@var{environment2} will see that value, and vice versa. +@end deffn + +@deffn procedure unbind-variable environment symbol +If @var{symbol} is bound in @var{environment} or one of its ancestor +environments, removes the binding, so that subsequent accesses to that +symbol behave as if the binding never existed. Returns @code{#t} if there +was a binding prior to the call, and @code{#f} if there wasn't. +@end deffn diff --git a/v7/doc/ref-manual/equivalence.texi b/v7/doc/ref-manual/equivalence.texi new file mode 100644 index 000000000..e61a71e7f --- /dev/null +++ b/v7/doc/ref-manual/equivalence.texi @@ -0,0 +1,295 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: equivalence.texi,v 1.1 2003/04/15 03:29:35 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Equivalence Predicates, Numbers, Special Forms, Top +@chapter Equivalence Predicates + +@cindex predicate (defn) +@cindex predicate, equivalence (defn) +@cindex equivalence predicate (defn) +@cindex comparison, for equivalence +@findex eq? +@findex eqv? +@findex equal? +A @dfn{predicate} is a procedure that always returns a boolean value +(@code{#t} or @code{#f}). An @dfn{equivalence predicate} is the +computational analogue of a mathematical equivalence relation (it is +symmetric, reflexive, and transitive). Of the equivalence predicates +described in this section, @code{eq?} is the finest or most +discriminating, and @code{equal?} is the coarsest. @code{eqv?} is +slightly less discriminating than @code{eq?}. + +@deffn procedure eqv? obj1 obj2 +The @code{eqv?} procedure defines a useful equivalence relation on +objects. Briefly, it returns @code{#t} if @var{obj1} and @var{obj2} +should normally be regarded as the same object. + +The @code{eqv?} procedure returns @code{#t} if: + +@itemize @bullet +@item +@var{obj1} and @var{obj2} are both @code{#t} or both @code{#f}. + +@item +@var{obj1} and @var{obj2} are both interned symbols and + +@example +@group +(string=? (symbol->string @var{obj1}) + (symbol->string @var{obj2})) + @result{} #t +@end group +@end example +@findex string=? +@findex symbol->string + +@item +@var{obj1} and @var{obj2} are both numbers, are numerically equal +according to the @code{=} procedure, and are either both exact or both +inexact (@pxref{Numbers}). +@findex = + +@item +@var{obj1} and @var{obj2} are both characters and are the same character +according to the @code{char=?} procedure (@pxref{Characters}). +@findex char=? + +@item +both @var{obj1} and @var{obj2} are the empty list. + +@item +@var{obj1} and @var{obj2} are procedures whose location tags are equal. + +@item +@var{obj1} and @var{obj2} are pairs, vectors, strings, bit strings, +records, cells, or weak pairs that denote the same locations in the +store. +@end itemize + +@noindent +The @code{eqv?} procedure returns @code{#f} if: + +@itemize @bullet +@item +@var{obj1} and @var{obj2} are of different types. + +@item +one of @var{obj1} and @var{obj2} is @code{#t} but the other is +@code{#f}. + +@item +@var{obj1} and @var{obj2} are symbols but + +@example +@group +(string=? (symbol->string @var{obj1}) + (symbol->string @var{obj2})) + @result{} #f +@end group +@end example +@findex string=? +@findex symbol->string + +@item +one of @var{obj1} and @var{obj2} is an exact number but the other is an +inexact number. + +@item +@var{obj1} and @var{obj2} are numbers for which the @code{=} procedure +returns @code{#f}. +@findex = + +@item +@var{obj1} and @var{obj2} are characters for which the @code{char=?} +procedure returns @code{#f}. +@findex char=? + +@item +one of @var{obj1} and @var{obj2} is the empty list but the other is not. + +@item +@var{obj1} and @var{obj2} are procedures that would behave differently +(return a different value or have different side effects) for some +arguments. + +@item +@var{obj1} and @var{obj2} are pairs, vectors, strings, bit strings, +records, cells, or weak pairs that denote distinct locations. +@end itemize + +Some examples: + +@example +@group +(eqv? 'a 'a) @result{} #t +(eqv? 'a 'b) @result{} #f +(eqv? 2 2) @result{} #t +(eqv? '() '()) @result{} #t +(eqv? 100000000 100000000) @result{} #t +(eqv? (cons 1 2) (cons 1 2)) @result{} #f +(eqv? (lambda () 1) + (lambda () 2)) @result{} #f +(eqv? #f 'nil) @result{} #f +(let ((p (lambda (x) x))) + (eqv? p p)) @result{} #t +@end group +@end example + +The following examples illustrate cases in which the above rules do not +fully specify the behavior of @code{eqv?}. All that can be said about +such cases is that the value returned by @code{eqv?} must be a boolean. + +@example +@group +(eqv? "" "") @result{} @r{unspecified} +(eqv? '#() '#()) @result{} @r{unspecified} +(eqv? (lambda (x) x) + (lambda (x) x)) @result{} @r{unspecified} +(eqv? (lambda (x) x) + (lambda (y) y)) @result{} @r{unspecified} +@end group +@end example + +The next set of examples shows the use of @code{eqv?} with procedures +that have local state. @code{gen-counter} must return a distinct +procedure every time, since each procedure has its own internal counter. +@code{gen-loser}, however, returns equivalent procedures each time, +since the local state does not affect the value or side effects of the +procedures. + +@example +@group +(define gen-counter + (lambda () + (let ((n 0)) + (lambda () (set! n (+ n 1)) n)))) +(let ((g (gen-counter))) + (eqv? g g)) @result{} #t +(eqv? (gen-counter) (gen-counter)) + @result{} #f +@end group + +@group +(define gen-loser + (lambda () + (let ((n 0)) + (lambda () (set! n (+ n 1)) 27)))) +(let ((g (gen-loser))) + (eqv? g g)) @result{} #t +(eqv? (gen-loser) (gen-loser)) + @result{} @r{unspecified} +@end group + +@group +(letrec ((f (lambda () (if (eqv? f g) 'both 'f))) + (g (lambda () (if (eqv? f g) 'both 'g))) + (eqv? f g)) + @result{} @r{unspecified} + +(letrec ((f (lambda () (if (eqv? f g) 'f 'both))) + (g (lambda () (if (eqv? f g) 'g 'both))) + (eqv? f g)) + @result{} #f +@end group +@end example + +Objects of distinct types must never be regarded as the same object. + +Since it is an error to modify constant objects (those returned by +literal expressions), the implementation may share structure between +constants where appropriate. Thus the value of @code{eqv?} on constants +is sometimes unspecified. + +@example +@group +(let ((x '(a))) + (eqv? x x)) @result{} #t +(eqv? '(a) '(a)) @result{} @r{unspecified} +(eqv? "a" "a") @result{} @r{unspecified} +(eqv? '(b) (cdr '(a b))) @result{} @r{unspecified} +@end group +@end example + +Rationale: The above definition of @code{eqv?} allows implementations +latitude in their treatment of procedures and literals: implementations +are free either to detect or to fail to detect that two procedures or +two literals are equivalent to each other, and can decide whether or not +to merge representations of equivalent objects by using the same pointer +or bit pattern to represent both. +@end deffn + +@page +@deffn procedure eq? obj1 obj2 +@code{eq?} is similar to @code{eqv?} except that in some cases it is +capable of discerning distinctions finer than those detectable by +@code{eqv?}. + +@code{eq?} and @code{eqv?} are guaranteed to have the same behavior on +symbols, booleans, the empty list, pairs, records, and non-empty strings +and vectors. @code{eq?}'s behavior on numbers and characters is +implementation-dependent, but it will always return either true or +false, and will return true only when @code{eqv?} would also return +true. @code{eq?} may also behave differently from @code{eqv?} on empty +vectors and empty strings. + +@example +@group +(eq? 'a 'a) @result{} #t +(eq? '(a) '(a)) @result{} @r{unspecified} +(eq? (list 'a) (list 'a)) @result{} #f +(eq? "a" "a") @result{} @r{unspecified} +(eq? "" "") @result{} @r{unspecified} +(eq? '() '()) @result{} #t +(eq? 2 2) @result{} @r{unspecified} +(eq? #\A #\A) @result{} @r{unspecified} +(eq? car car) @result{} #t +(let ((n (+ 2 3))) + (eq? n n)) @result{} @r{unspecified} +(let ((x '(a))) + (eq? x x)) @result{} #t +(let ((x '#())) + (eq? x x)) @result{} #t +(let ((p (lambda (x) x))) + (eq? p p)) @result{} #t +@end group +@end example + +Rationale: It will usually be possible to implement @code{eq?} much more +efficiently than @code{eqv?}, for example, as a simple pointer +comparison instead of as some more complicated operation. One reason is +that it may not be possible to compute @code{eqv?} of two numbers in +constant time, whereas @code{eq?} implemented as pointer comparison will +always finish in constant time. @code{eq?} may be used like @code{eqv?} +in applications using procedures to implement objects with state since +it obeys the same constraints as @code{eqv?}. +@end deffn + +@page +@deffn procedure equal? obj1 obj2 +@cindex circular structure +@code{equal?} recursively compares the contents of pairs, vectors, and +strings, applying @code{eqv?} on other objects such as numbers, symbols, +and records. A rule of thumb is that objects are generally +@code{equal?} if they print the same. @code{equal?} may fail to +terminate if its arguments are circular data structures. + +@example +@group +(equal? 'a 'a) @result{} #t +(equal? '(a) '(a)) @result{} #t +(equal? '(a (b) c) + '(a (b) c)) @result{} #t +(equal? "abc" "abc") @result{} #t +(equal? 2 2) @result{} #t +(equal? (make-vector 5 'a) + (make-vector 5 'a)) @result{} #t +(equal? (lambda (x) x) + (lambda (y) y)) @result{} @r{unspecified} +@end group +@end example +@end deffn diff --git a/v7/doc/ref-manual/error.texi b/v7/doc/ref-manual/error.texi new file mode 100644 index 000000000..da90c61b4 --- /dev/null +++ b/v7/doc/ref-manual/error.texi @@ -0,0 +1,1712 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: error.texi,v 1.1 2003/04/15 03:29:39 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Error System, Graphics, Operating-System Interface, Top +@chapter Error System + +@findex error +The MIT/GNU Scheme error system provides a uniform mechanism for the +signalling of errors and other exceptional conditions. The simplest and +most generally useful procedures in the error system are: + +@table @code +@item error +is used to signal simple errors, specifying a message and some irritant +objects (@pxref{Condition Signalling}). Errors are usually handled by +stopping the computation and putting the user in an error @sc{repl}. + +@item warn +is used to signal warnings (@pxref{Condition Signalling}). Warnings are +usually handled by printing a message on the console and continuing the +computation normally. + +@item ignore-errors +is used to suppress the normal handling of errors within a given dynamic +extent (@pxref{Condition Handling}). Any error that occurs within the +extent is trapped, returning immediately to the caller of +@code{ignore-errors}. +@end table + +More demanding applications require more powerful facilities. To give a +concrete example, suppose you want floating-point division to return a very +large number whenever the denominator is zero. This behavior can be +implemented using the error system. + +The Scheme arithmetic system can signal many different kinds of errors, +including floating-point divide by zero. In our example, we would like to +handle this particular condition specially, allowing the system to handle +other arithmetic errors in its usual way. + +The error system supports this kind of application by providing +mechanisms for distinguishing different types of error conditions and +for specifying where control should be transferred should a given +condition arise. In this example, there is a specific object that +represents the ``floating-point divide by zero'' condition type, and it +is possible to dynamically specify an arbitrary Scheme procedure to be +executed when a condition of that type is signalled. This procedure +then finds the stack frame containing the call to the division operator, +and returns the appropriate value from that frame. + +Another useful kind of behavior is the ability to specify uniform +handling for related classes of conditions. For example, it might be +desirable, when opening a file for input, to gracefully handle a variety of +different conditions associated with the file system. One such condition +might be that the file does not exist, in which case the program will try +some other action, perhaps opening a different file instead. Another +related condition is that the file exists, but is read protected, so it +cannot be opened for input. If these or any other related conditions +occur, the program would like to skip this operation and move on to +something else. + +At the same time, errors unrelated to the file system should be treated in +their usual way. For example, calling @code{car} on the argument @code{3} +should signal an error. Or perhaps the name given for the file is +syntactically incorrect, a condition that probably wants to be handled +differently from the case of the file not existing. + +@cindex taxonomical link, of condition type (defn) +@cindex specialization, of condition types (defn) +@cindex generalization, of condition types (defn) +To facilitate the handling of classes of conditions, the error system +taxonomically organizes all condition types. The types are related to one +another by @dfn{taxonomical links}, which specify that one type is a ``kind +of'' another type. If two types are linked this way, one is considered to +be a @dfn{specialization} of the other; or vice-versa, the second is a +@dfn{generalization} of the first. In our example, all of the errors +associated with opening an input file would be specializations of the +condition type ``cannot open input file''. + +@vindex condition-type:simple-condition +@vindex condition-type:warning +@vindex condition-type:breakpoint +@vindex condition-type:serious-condition +The taxonomy of condition types permits any condition type to have no +more than one immediate generalization. Thus, the condition types form +a forest (set of trees). While users can create new trees, the standard +taxonomy (@pxref{Taxonomy}) is rooted at +@code{condition-type:serious-condition}, @code{condition-type:warning}, +@code{condition-type:simple-condition}, and +@code{condition-type:breakpoint}; users are encouraged to add new +subtypes to these condition types rather than create new trees in the +forest. + +To summarize, the error system provides facilities for the following tasks. +The sections that follow will describe these facilities in more +detail. + +@table @asis +@item Signalling a condition +@findex signal-condition +A condition may be signalled in a number of different ways. Simple +errors may be signalled, without explicitly defining a condition type, +using @code{error}. The @code{signal-condition} procedure provides the +most general signalling mechanism. + +@item Handling a condition +@findex bind-condition-handler +The programmer can dynamically specify handlers for particular condition +types or for classes of condition types, by means of the +@code{bind-condition-handler} procedure. Individual handlers have +complete control over the handling of a condition, and additionally may +decide not to handle a particular condition, passing it on to previously +bound handlers. + +@item Restarting from a handler +@findex with-restart +The @code{with-restart} procedure provides a means for +condition-signalling code to communicate to condition-handling code what +must be done to proceed past the condition. Handlers can examine the +restarts in effect when a condition was signalled, allowing a structured +way to continue an interrupted computation. + +@item Packaging condition state +Each condition is represented by an explicit object. Condition objects +contain information about the nature of the condition, information that +describes the state of the computation from which the condition arose, +and information about the ways the computation can be restarted. + +@item Classification of conditions +@cindex condition type +@cindex type, condition +@cindex specialization, of condition types +@cindex generalization, of condition types +Each condition has a type, represented by a condition type object. Each +condition type may be a specialization of some other condition types. A +group of types that share a common generalization can be handled +uniformly by specifying a handler for the generalization. +@end table + +@menu +* Condition Signalling:: +* Error Messages:: +* Condition Handling:: +* Restarts:: +* Condition Instances:: +* Condition Types:: +* Taxonomy:: +@end menu + +@node Condition Signalling, Error Messages, Error System, Error System +@section Condition Signalling + +@cindex condition signalling (defn) +@cindex signalling, of condition (defn) +@findex make-condition +Once a condition instance has been created using @code{make-condition} +(or any condition constructor), it can be @dfn{signalled}. The act of +signalling a condition is separated from the act of creating the +condition to allow more flexibility in how conditions are handled. For +example, a condition instance could be returned as the value of a +procedure, indicating that something unusual has happened, to allow the +caller to clean up some state. The caller could then signal the +condition once it is ready. + +A more important reason for having a separate condition-signalling +mechanism is that it allows @emph{resignalling}. When a signalled +condition has been caught by a particular handler, and the handler decides +that it doesn't want to process that particular condition, it can signal +the condition again. This is one way to allow other handlers to get a +chance to see the condition. + +@deffn procedure error reason argument @dots{} +@cindex REP loop +@findex signal-condition +@findex warn +This is the simplest and most common way to signal a condition that +requires intervention before a computation can proceed (when +intervention is not required, @code{warn} is more appropriate). +@code{error} signals a condition (using @code{signal-condition}), and if +no handler for that condition alters the flow of control (by invoking a +restart, for example) it calls the procedure +@code{standard-error-handler}, which normally prints an error message +and stops the computation, entering an error @sc{repl}. Under normal +circumstances @code{error} will not return a value (although an +interactive debugger can be used to force this to occur). + +@findex make-condition +@vindex condition-type:simple-error +Precisely what condition is signalled depends on the first argument to +@code{error}. If @var{reason} is a condition, then that condition is +signalled and the @var{argument}s are ignored. If @var{reason} is a +condition type, then a new instance of this type is generated and +signalled; the @var{argument}s are used to generate the values of the +fields for this condition type (they are passed as the @var{field-plist} +argument to @code{make-condition}). In the most common case, however, +@var{reason} is neither a condition nor a condition type, but rather a +string or symbol. In this case a condition of type +@code{condition-type:simple-error} is created with the @var{message} +field containing the @var{reason} and the @var{irritants} field +containing the @var{argument}s. +@end deffn + +@deffn procedure warn reason argument @dots{} +@findex error +@findex signal-condition +@vindex condition-type:simple-warning +When a condition is not severe enough to warrant intervention, it is +appropriate to signal the condition with @code{warn} rather than +@code{error}. As with @code{error}, @code{warn} first calls +@code{signal-condition}; the condition that is signalled is chosen +exactly as in @code{error} except that a condition of type +@code{condition-type:simple-warning} is signalled if @var{reason} is +neither a condition nor a condition type. If the condition is not +handled, @code{warn} calls the procedure +@code{standard-warning-handler}, which normally prints a warning message +and continues the computation by returning from @code{warn}. + +@findex muffle-warning +@code{warn} establishes a restart named @code{muffle-warning} before +calling @code{signal-condition}. This allows a signal handler to +prevent the generation of the warning message by calling +@code{muffle-warning}. The value of a call to @code{warn} is +unspecified. +@end deffn + +@deffn procedure signal-condition condition +@cindex generalization, of condition types +@cindex specialization, of condition types +@findex break-on-signals +@findex bind-default-condition-handler +@findex bind-condition-handler +This is the fundamental operation for signalling a condition. The +precise operation of @code{signal-condition} depends on the condition +type of which @var{condition} is an instance, the condition types set by +@code{break-on-signals}, and the handlers established by +@code{bind-condition-handler} and @code{bind-default-condition-handler}. + +@cindex REP loop +If the @var{condition} is an instance of a type that is a specialization +of any of the types specified by @code{break-on-signals}, then a +breakpoint @sc{repl} is initiated. Otherwise (or when that @sc{repl} +returns), the handlers established by @code{bind-condition-handler} are +checked, most recent first. Each applicable handler is invoked, and the +search for a handler continues if the handler returns normally. If all +applicable handlers return, then the applicable handlers established by +@code{bind-default-condition-handler} are checked, again most recent +first. Finally, if no handlers apply (or all return in a normal +manner), @code{signal-condition} returns an unspecified value. + +@emph{Note:} unlike many other systems, the MIT/GNU Scheme runtime library +does @emph{not} establish handlers of any kind. (However, the Edwin +text editor uses condition handlers extensively.) Thus, calls to +@code{signal-condition} will return to the caller unless there are user +supplied condition handlers, as the following example shows: + +@example +@group +(signal-condition + (make-condition + condition-type:error + (call-with-current-continuation (lambda (x) x)) + '() @r{; no restarts} + '())) @r{; no fields} +@result{} @r{unspecified} +@end group +@end example +@end deffn + +@node Error Messages, Condition Handling, Condition Signalling, Error System +@section Error Messages + +@cindex error messages, conventions +@cindex conventions for error messages +By convention, error messages (and in general, the reports generated by +@code{write-condition-report}) should consist of one or more complete +sentences. The usual rules for sentences should be followed: the first +word of the sentence should be capitalized, and the sentence should be +terminated by a period. The message should not contain extraneous +whitespace such as line breaks or indentation. + + +The error system provides a simple formatting language that allows the +programmer to have some control over the printing of error messages. +This formatting language will probably be redesigned in a future +release. + +@findex display +@findex write +Error messages typically consist of a string describing the error, +followed by some irritant objects. The string is printed using +@code{display}, and the irritants are printed using @code{write}, +typically with a space between each irritant. To allow simple +formatting, we introduce a @dfn{noise} object, printed using +@code{display}. The irritant list may contain ordinary objects +interspersed with noise objects. Each noise object is printed using +@code{display}, with no extra whitespace, while each normal object is +printed using @code{write}, prefixed by a single space character. + +Here is an example: + +@example +@group +(define (error-within-procedure message irritant procedure) + (error message + irritant + (error-irritant/noise "within procedure") + procedure + (error-irritant/noise "."))) +@end group +@end example + +@noindent +This would format as follows: + +@example +@group +(error-within-procedure "Bad widget" 'widget-32 'invert-widget) @error{} + +Bad widget widget-32 within procedure invert-widget. +@end group +@end example + +Here are the operations supporting error messages: + +@deffn procedure format-error-message message irritants port +@var{Message} is typically a string (although this is not required), +@var{irritants} a list of irritant objects, and @var{port} an output +port. Formats @var{message} and @var{irritants} to @var{port} in the +standard way. Note that, during the formatting process, the depth and +breadth to which lists are printed are each limited to small numbers, to +guarantee that the output from each irritant is not arbitrarily large. +@end deffn + +@deffn procedure error-irritant/noise value +Creates and returns a noise object whose value is @var{value}. +@end deffn + +@node Condition Handling, Restarts, Error Messages, Error System +@section Condition Handling + +@cindex handler, condition (defn) +@cindex condition handler (defn) +@findex bind-condition-handler +@findex bind-default-condition-handler +The occurrence of a condition is signalled using +@code{signal-condition}. @code{signal-condition} attempts to locate and +invoke a @dfn{condition handler} that is prepared to deal with the type +of condition that has occurred. A condition handler is a procedure of +one parameter, the condition that is being signalled. A procedure is +installed as a condition handler by calling +@code{bind-condition-handler} (to establish a handler that is in effect +only while a particular thunk is executing) or +@code{bind-default-condition-handler} (to establish a handler that is in +effect permanently). As implied by the name, handlers created by +@code{bind-default-condition-handler} are invoked only after all other +applicable handlers have been invoked. + +A @var{handler} may process a signal in any way it deems appropriate, +but the common patterns are: + +@table @asis +@item Ignore the condition. +By returning from the handler in the usual manner. + +@item Handle the condition. +By doing some processing and then invoking a restart (or, less +preferably, a continuation) that was established at some point prior to +the call to @code{signal-condition}. + +@item Resignal a condition. +By doing some processing and calling @code{signal-condition} with either +the same condition or a newly created one. In order to support this, +@code{signal-condition} runs @var{handler} in such a way that a +subsequent call to @code{signal-condition} sees only the handlers that +were established prior to this one. +@end table + +@cindex REP loop +@findex break-on-signals +As an aid to debugging condition handlers, Scheme maintains a set of +condition types that will cause an interactive breakpoint to occur prior +to normal condition signalling. That is, @code{signal-condition} +creates a new @sc{repl} prior to its normal operation when its argument +is a condition that is a specialization of any of these types. The +procedure @code{break-on-signals} establishes this set of condition +types. + +@deffn procedure ignore-errors thunk +@findex error +@vindex condition-type:error +Executes @var{thunk} with a condition handler that intercepts the +signalling of any specialization of @code{condition-type:error} +(including those produced by calls to @code{error}) and immediately +terminates the execution of @var{thunk} and returns from the call to +@code{ignore-errors} with the signalled condition as its value. If +@var{thunk} returns normally, its value is returned from +@code{ignore-errors}. + +Notice that @code{ignore-errors} does not ``turn off signalling'' or +condition handling. Condition handling takes place in the normal manner +but conditions specialized from @code{condition-type:error} are trapped +rather than propogated as they would be by default. +@end deffn + +@deffn procedure bind-condition-handler condition-types handler thunk +@findex signal-condition +Invokes @var{thunk} after adding @var{handler} as a condition handler +for the conditions specified by @var{condition-types}. +@var{Condition-types} must be a list of condition types; signalling a +condition whose type is a specialization of any of these types will +cause the @var{handler} to be invoked. See @code{signal-condition} for +a description of the mechanism used to invoke handlers. + +By special extension, if @var{condition-types} is the empty list then +the @var{handler} is called for all conditions. +@end deffn + +@deffn procedure bind-default-condition-handler condition-types handler +@findex signal-condition +Installs @var{handler} as a (permanent) condition handler for the +conditions specified by @var{condition-types}. @var{Condition-types} +must be a list of condition types; signalling a condition whose type is +a specialization of any of these types will cause the @var{handler} to +be invoked. See @code{signal-condition} for a description of the +mechanism used to invoke handlers. + +By special extension, if @var{condition-types} is the empty list then +the @var{handler} is called for all conditions. +@end deffn + +@deffn procedure break-on-signals condition-types +@findex signal-condition +@cindex REP loop +Arranges for @code{signal-condition} to create an interactive @sc{repl} +before it signals a condition that is a specialization of any of the +types in the list of @var{condition-types}. This can be extremely +helpful when trying to debug code that uses custom condition handlers. +In order to create a @sc{repl} when @emph{any} condition type is +signalled it is best to actually put a breakpoint on entry to +@code{signal-condition}. +@end deffn + +@deffn procedure standard-error-handler condition +@findex error +@findex ignore-error +@vindex standard-error-hook +@cindex REP loop +Called internally by @code{error} after it calls +@code{signal-condition}. Normally creates creates a new @sc{repl} with +the prompt @code{"error>"} (but see @code{standard-error-hook}). In +order to simulate the effect of calling @code{error}, code may call +@code{signal-condition} directly and then call +@code{standard-error-handler} if @code{signal-condition} returns. +@end deffn + +@defvr variable standard-error-hook +@findex standard-error-handler +@cindex fluid binding +@cindex dynamic binding +@cindex REP loop +This variable controls the behavior of the procedure +@code{standard-error-handler}, and hence @code{error}. It is intended +to be bound with @code{fluid-let} and is normally @code{#f}. It may be +changed to a procedure of one argument and will then be invoked (with +@code{standard-error-hook} rebound to @code{#f}) by +@code{standard-error-handler} just prior to starting the error +@sc{repl}. It is passed one argument, the condition being signalled. +@end defvr + +@deffn procedure standard-warning-handler condition +@vindex standard-warning-hook +@findex signal-condition +@findex notification-output-port +@findex write-condition-report +This is the procedure called internally by @code{warn} after it calls +@code{signal-condition}. The normal behavior of +@code{standard-warning-handler} is to print a message (but see +@code{standard-warning-hook}). More precisely, the message is printed +to the port returned by @code{notification-output-port}. The message is +formed by first printing the string @code{"Warning: "} to this port, and +then calling @code{write-condition-report} on @var{condition} and the port. + +@findex muffle-warning +In order to simulate the effect of calling @code{warn}, code may call +@code{signal-condition} directly and then call +@code{standard-warning-handler} if @code{signal-condition} returns. +(This is not sufficient to implement the @code{muffle-warning} protocol, +however. For that purpose an explicit restart must be provided.) +@end deffn + +@defvr variable standard-warning-hook +@findex standard-warning-handler +@cindex fluid binding +@cindex dynamic binding +This variable controls the behavior of the procedure +@code{standard-warning-handler}, and hence @code{warn}. It is intended +to be bound with @code{fluid-let} and is normally @code{#f}. It may be +changed to a procedure of one argument and will then be invoked (with +@code{standard-warning-hook} rebound to @code{#f}) by +@code{standard-warning-handler} in lieu of writing the warning message. +It is passed one argument, the condition being signalled. +@end defvr + +@node Restarts, Condition Instances, Condition Handling, Error System +@section Restarts + +@cindex restart effector (defn) +@cindex effector, restart (defn) +@cindex restart (defn) +@findex with-restart +@findex with-simple-restart +The Scheme error system provides a mechanism, known as @dfn{restarts}, +that helps coordinate condition-signalling code with condition-handling +code. A module of code that detects and signals conditions can provide +procedures (using @code{with-simple-restart} or @code{with-restart}) to +be invoked by handlers that wish to continue, abort, or restart the +computation. These procedures, called @dfn{restart effectors}, are +encapsulated in restart objects. + +@findex find-restart +@findex invoke-restart +@findex invoke-restart-interactively +When a condition object is created, it contains a set of restart +objects, each of which contains a restart effector. Condition handlers +can inspect the condition they are handling (using @code{find-restart} +to find restarts by name, or @code{condition/restarts} to see the entire +set), and they can invoke the associated effectors (using +@code{invoke-restart} or @code{invoke-restart-interactively}). +Effectors can take arguments, and these may be computed directly by the +condition-handling code or by gathering them interactively from the +user. + +@findex abort +@findex continue +@findex muffle-warning +@findex retry +@findex store-value +@findex use-value +@cindex protocol, restart (defn) +@cindex restart protocol +The names of restarts can be chosen arbitrarily, but the choice of name +is significant. These names are used to coordinate between the +signalling code (which supplies names for restarts) and the handling +code (which typically chooses a restart effector by the name of its +restart). Thus, the names specify the @dfn{restart protocol} +implemented by the signalling code and invoked by the handling code. +The protocol indicates the number of arguments required by the effector +code as well as the semantics of the arguments. + +Scheme provides a conventional set of names (hence, protocols) for +common use. By choosing the names of restarts from this set, signalling +code can indicate that it is able to perform a small set of fairly +common actions (@code{abort}, @code{continue}, @code{muffle-warning}, +@code{retry}, @code{store-value}, @code{use-value}). In turn, simple +condition-handling code can look for the kind of action it wishes to +perform and simply invoke it by name. All of Scheme's conventional +names are symbols, although in general restart names are not restricted +to any particular data type. In addition, the object @code{#f} is +reserved to indicate the ``not for automated use'' protocol: these +restarts should be activated only under human control. + +@findex with-simple-restart +Restarts themselves are first-class objects. They encapsulate their +name, a procedure (known as the @var{effector}) to be executed if they +are invoked, and a thunk (known as the @var{reporter}) that can be +invoked to display a description of the restart (used, for example, by +the interactive debugger). Invoking a restart is an indication that a +handler has chosen to accept control for a condition; as a consequence, +the @var{effector} of the restart should not return, since this would +indicate that the handler declined to handle the condition. Thus, the +@var{effector} should call a continuation captured before the +condition-signalling process began. The most common pattern of usage by +signalling code is encapsulated in @code{with-simple-restart}. + +Within this chapter, a parameter named @var{restarts} will accept any of +the following values: + +@itemize @bullet +@item +A list of restart objects. + +@item +A condition. The procedure @code{condition/restarts} is called on the +condition, and the resulting list of restarts is used in place of the +condition. + +@item +The symbol @code{bound-restarts}. The procedure @code{bound-restarts} +is called (with no arguments), and the resulting list of restarts is +used in place of the symbol. + +@item +If the @var{restarts} parameter is optional and is not supplied, it is +equivalent to having specified the symbol @code{bound-restarts}. +@end itemize + +@menu +* Establishing Restart Code:: +* Invoking Standard Restart Code:: +* Finding and Invoking General Restart Code:: +* The Named Restart Abstraction:: +@end menu + +@node Establishing Restart Code, Invoking Standard Restart Code, Restarts, Restarts +@subsection Establishing Restart Code + +@deffn procedure with-simple-restart name reporter thunk +Invokes @var{thunk} in a dynamic environment created by adding a restart +named @var{name} to the existing named restarts. @var{Reporter} may be +used during the execution of @var{thunk} to produce a description of the +newly created restart; it must either be a procedure of one argument (a +port) or a string. By convention, the description generated by +@var{reporter} should be a short complete sentence, with first word +capitalized and terminated by a period. The sentence should fit on one +line with a little room to spare (see the examples below); usually this +means that the sentence should be 70 characters or less in length. + +If the restart created by @code{with-simple-restart} is invoked it +simply aborts the computation in progress by returning an unspecified +value from the call to @code{with-simple-restart}. Otherwise +@code{with-simple-restart} returns the value computed by @var{thunk}. +@end deffn + +@example +@group +(with-simple-restart 'george "This restart is named george." + (lambda () 3)) @result{} 3 + +(with-simple-restart 'george "This restart is named george." + (lambda () + (invoke-restart (find-restart 'george)))) @result{} @code{unspecific} + +(with-simple-restart 'george "This restart is named george." + (lambda () (car 3))) +;The object 3, passed as the first argument to car, +; is not the correct type. +;To continue, call RESTART with an option number: +; (RESTART 3) => Specify an argument to use in its place. +; (RESTART 2) => This restart is named george. +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn procedure with-restart name reporter effector interactor thunk +@findex invoke-restart +Invokes @var{thunk} in a dynamic environment created by adding a restart +named @var{name} to the existing named restarts. @var{Reporter} may be +used during the execution of @var{thunk} to produce a description of the +newly created restart; it must either be a procedure of one argument (a +port) or a string. @var{Effector} is a procedure which will be called +when the restart is invoked by @code{invoke-restart}. @var{Interactor} +specifies the arguments that are to be passed to @var{effector} when it +is invoked interactively; it may be either a procedure of no arguments, +or @code{#f}. If @var{interactor} is @code{#f}, this restart is not +meant to be invoked interactively. + +The value returned by @code{with-restart} is the value returned by +@var{thunk}. Should the restart be invoked by a condition handler, +however, the @var{effector} will not return back to the handler that +invoked it. Instead, the @var{effector} should call a continuation +created before the condition-signalling process began, and +@code{with-restart} will therefore not return in the normal manner. +@end deffn + +@example +@group +(define (by-george! thunk) + @r{; This code handles conditions that arise while executing @var{thunk}} + @r{; by invoking the GEORGE restart, passing 1 and 2 to the restart's} + @r{; @var{effector} code.} + (bind-condition-handler '() ; All conditions + (lambda (condition) + (invoke-restart (find-restart 'george) 1 2)) + thunk)) +@end group + +@group +(define (can-george! thunk) + @r{; This code provides a way of handling errors: the GEORGE restart.} + @r{; In order to GEORGE you must supply two values.} + (lambda () + (call-with-current-continuation + (lambda (kappa) + (with-restart + 'george @r{; Name} + "This restart is named george." @r{; Reporter} + (lambda (a b) @r{; Effector} + (kappa (list 'george a b))) + values @r{; Interactor} + thunk))))) @r{; Thunk} +@end group + +@group +(by-george! (can-george! (lambda () -3)) @result{} -3 +(by-george! (can-george! (lambda () (car 'x)))) @result{} (george 1 2) +@end group +@end example + +@node Invoking Standard Restart Code, Finding and Invoking General Restart Code, Establishing Restart Code, Restarts +@subsection Invoking Standard Restart Code + +Scheme supports six standard protocols for restarting from a condition, +each encapsulated using a named restart (for use by condition-signalling +code) and a simple procedure (for use by condition-handling code). +Unless otherwise specified, if one of these procedures is unable to find +its corresponding restart, it returns immediately with an unspecified +value. + +Each of these procedures accepts an optional argument @var{restarts}, +which is described above in @ref{Restarts}. + +@deffn procedure abort [restarts] +@cindex REP loop +Abort the computation, using the restart named @code{abort}. The +corresponding effector takes no arguments and abandons the current line +of computation. This is the restart provided by Scheme's @sc{repl}. + +@vindex condition-type:no-such-restart +If there is no restart named @code{abort}, this procedure signals an +error of type @code{condition-type:no-such-restart}. +@end deffn + +@deffn procedure continue [restarts] +Continue the current computation, using the restart named +@code{continue}. The corresponding effector takes no arguments and +continues the computation beyond the point at which the condition was +signalled. +@end deffn + +@deffn procedure muffle-warning [restarts] +@findex warn +Continue the current computation, using the restart named +@code{muffle-warning}. The corresponding effector takes no arguments +and continues the computation beyond the point at which any warning +message resulting from the condition would be presented to the user. +The procedure @code{warn} establishes a @code{muffle-warning} restart +for this purpose. + +@vindex condition-type:no-such-restart +If there is no restart named @code{muffle-warning}, this procedure +signals an error of type @code{condition-type:no-such-restart}. +@end deffn + +@deffn procedure retry [restarts] +Retry the current computation, using the restart named @code{retry}. +The corresponding effector takes no arguments and simply retries the +same computation that triggered the condition. The condition may +reoccur, of course, if the root cause has not been eliminated. The code +that signals a ``file does not exist'' error can be expected to supply a +@code{retry} restart. The restart would be invoked after first creating +the missing file, since the computation is then likely to succeed if it +is simply retried. +@end deffn + +@deffn procedure store-value new-value [restarts] +Retry the current computation, using the restart named +@code{store-value}, after first storing @var{new-value}. The +corresponding effector takes one argument, @var{new-value}, and stores +it away in a restart-dependent location, then retries the same +computation that triggered the condition. The condition may reoccur, of +course, if the root cause has not been eliminated. The code that +signals an ``unassigned variable'' error can be expected to supply a +@code{store-value} restart; this would store the value in the variable +and continue the computation. +@end deffn + +@deffn procedure use-value new-value [restarts] +@findex retry +@findex store-value +Retry the current computation, using the restart named @code{use-value}, +but substituting @var{new-value} for a value that previously caused a +failure. The corresponding effector takes one argument, +@var{new-value}, and retries the same computation that triggered the +condition with the new value substituted for the failing value. The +condition may reoccur, of course, if the new value also induces the +condition. + +The code that signals an ``unassigned variable'' error can be expected +to supply a @code{use-value} restart; this would simply continue the +computation with @var{new-value} instead of the value of the variable. +Contrast this with the @code{retry} and @code{store-value} restarts. If +the @code{retry} restart is used it will fail because the variable still +has no value. The @code{store-value} restart could be used, but it +would alter the value of the variable, so that future references to the +variable would not be detected. +@end deffn + +@node Finding and Invoking General Restart Code, The Named Restart Abstraction, Invoking Standard Restart Code, Restarts +@subsection Finding and Invoking General Restart Code + +@findex with-restart +@findex with-simple-restart +@findex bound-restart +@findex find-restart +@findex invoke-restart +@findex invoke-restart-interactively +Restarts are a general mechanism for establishing a protocol between +condition-signalling and condition-handling code. The Scheme error +system provides ``packaging'' for a number of common protocols. It also +provides lower-level hooks that are intended for implementing customized +protocols. The mechanism used by signalling code (@code{with-restart} +and @code{with-simple-restart}) is used for both purposes. + +Four additional operations are provided for the use of +condition-handling code. Two operations (@code{bound-restarts} and +@code{find-restart}) allow condition-handling code to locate active +restarts. The other two operations (@code{invoke-restart} and +@code{invoke-restart-interactively}) allow restart effectors to be +invoked once the restart object has been located. + +In addition, there is a data abstraction that provides access to the +information encapsulated in restart objects. + +@deffn procedure bound-restarts +Returns a list of all currently active restart objects, most recently +installed first. @code{bound-restarts} should be used with caution by +condition-handling code, since it reveals all restarts that are active +at the time it is called, rather than at the time the condition was +signalled. It is useful, however, for collecting the list of restarts +for inclusion in newly generated condition objects or for inspecting the +current state of the system. +@end deffn + +@deffn procedure find-restart name [restarts] +Returns the first restart object named @var{name} in the list of +@var{restarts} (permissible values for @var{restarts} are described +above in @ref{Restarts}). When used in a condition handler, +@code{find-restart} is usually passed the name of a particular restart +@emph{and} the condition object that has been signalled. In this way +the handler finds only restarts that were available when the condition +was created (usually the same as when it was signalled). If +@var{restarts} is omitted, the currently active restarts would be used, +and these often include restarts added after the condition ocurred. +@end deffn + +@deffn procedure invoke-restart restart argument @dots{} +@findex invoke-restart-interactively +Calls the restart effector encapsulated in @var{restart}, passing the +specified @var{argument}s to it. @code{invoke-restart} is intended for +use by condition-handling code that understands the protocol implemented +by @var{restart}, and can therefore calculate and pass an appropriate +set of arguments. + +If a condition handler needs to interact with a user to gather the +arguments for an effector (e.g.@: if it does not understand the protocol +implemented by @var{restart}) @code{invoke-restart-interactively} should +be used instead of @code{invoke-restart}. +@end deffn + +@deffn procedure invoke-restart-interactively restart +First calls the interactor encapsulated in @var{restart} to +interactively gather the arguments needed for @var{restart}'s effector. +It then calls the effector, passing these arguments to it. + +@findex restart/interactor +@code{invoke-restart-interactively} is intended for calling interactive +restarts (those for which @code{restart/interactor} is not @code{#f}). +For convenience, @code{invoke-restart-interactively} will call the +restart's effector with no arguments if the restart has no interactor; +this behavior may change in the future. +@end deffn + +@node The Named Restart Abstraction, , Finding and Invoking General Restart Code, Restarts +@subsection The Named Restart Abstraction + +A restart object is very simple, since it encapsulates only a name, +effector, interactor, and description. + +@deffn procedure restart? object +Returns @code{#f} if and only if @var{object} is not a restart. +@end deffn + +@deffn procedure restart/name restart +@findex eq? +Returns the name of @var{restart}. While the Scheme error system uses +only symbols and the object @code{#f} for its predefined names, programs +may use arbitrary objects (name equivalence is tested using @code{eq?}). +@end deffn + +@deffn procedure restart/effector restart +@findex invoke-restart +@findex invoke-restart-interactively +Returns the effector encapsulated in @var{restart}. Normally this +procedure is not used since @code{invoke-restart} and +@code{invoke-restart-interactively} capture the most common invocation +patterns. +@end deffn + +@deffn procedure restart/interactor restart +@findex invoke-restart-interactively +Returns the interactor encapsulated in @var{restart}. This is either a +procedure of no arguments or the object @code{#f}. Normally this +procedure is not used since @code{invoke-restart-interactively} captures +the most common usage. Thus @code{restart/interactor} is most useful as +a predicate to determine if @var{restart} is intended to be invoked +interactively. +@end deffn + +@deffn procedure write-restart-report restart port +Writes a description of @var{restart} to @var{port}. This works by +either displaying (if it is a string) or calling (if it is a procedure) +the @var{reporter} that was supplied when the restart was created. +@end deffn + +@node Condition Instances, Condition Types, Restarts, Error System +@section Condition Instances + +@cindex condition (defn) +@cindex condition instance (defn) +@cindex instance, of condition (defn) +A @dfn{condition}, in addition to the information associated with its +type, usually contains other information that is not shared with other +conditions of the same type. For example, the condition type associated +with ``unbound variable'' errors does not specify the name of the +variable that was unbound. The additional information is captured in a +@dfn{condition} object, also called a @dfn{condition instance}. + +In addition to information that is specific to a given type of condition +(such as the variable name for ``unbound variable'' conditions), every +condition instance also contains a continuation that encapsulates the +state of the computation in which the condition occurred. This +continuation is used for analyzing the computation to learn more about +the context in which the condition occurred. It is @emph{not} intended +to provide a mechanism for continuing the computation; that mechanism is +provided by restarts. + +@menu +* Generating Operations on Conditions:: +* Condition State:: +* Simple Condition Instance Operations:: +@end menu + +@node Generating Operations on Conditions, Condition State, Condition Instances, Condition Instances +@subsection Generating Operations on Conditions + +@findex condition-constructor +@findex condition-accessor +@findex condition-signaller +@findex condition-predicate +Scheme provides four procedures that take a condition type as input and +produce operations on the corresponding condition object. These are +reminiscent of the operations on record types that produce record +operators (@pxref{Records}). Given a condition type it is possible to +generate: a constructor for instances of the type (using +@code{condition-constructor}); an accessor to extract the contents of a +field in instances of the type (using @code{condition-accessor}); a +predicate to test for instances of the type (using +@code{condition-predicate}); and a procedure to create and signal an +instance of the type (using @code{condition-signaller}). + +Notice that the creation of a condition object is distinct from +signalling an occurrence of the condition. Condition objects are +first-class; they may be created and never signalled, or they may be +signalled more than once. Further notice that there are no procedures +for modifying conditions; once created, a condition cannot be altered. + +@deffn procedure condition-constructor condition-type field-names +@findex condition/restarts +@cindex bound-restarts +@cindex restarts, bound +Returns a constructor procedure that takes as arguments values for the +fields specified in @var{field-names} and creates a condition of type +@var{condition-type}. @var{Field-names} must be a list of symbols that +is a subset of the @var{field-names} in @var{condition-type}. The +constructor procedure returned by @code{condition-constructor} has +signature + +@example +(lambda (@var{continuation} @var{restarts} . @var{field-values}) @dots{}) +@end example + +@noindent +where the @var{field-names} correspond to the @var{field-values}. The +constructor argument @var{restarts} is described in @ref{Restarts}. +Conditions created by the constructor procedure have @code{#f} for the +values of all fields other than those specified by @var{field-names}. + +For example, the following procedure @code{make-simple-warning} +constructs a condition of type @code{condition-type:simple-warning} +given a continuation (where the condition occurred), a description of +the restarts to be made available, a warning message, and a list of +irritants that caused the warning: + +@example +@group +(define make-simple-warning + (condition-constructor condition-type:simple-warning + '(message irritants))) +@end group +@end example +@end deffn + +@deffn procedure condition-accessor condition-type field-name +@cindex specialization, of condition types +Returns a procedure that takes as input a condition object of type +@var{condition-type} and extracts the contents of the specified +@var{field-name}. @code{condition-accessor} signals +@code{error:bad-range-argument} if the @var{field-name} isn't one of the +named fields of @var{condition-type}; the returned procedure will signal +@code{error:wrong-type-argument} if passed an object other than a +condition of type @var{condition-type} or one of its specializations. + +@findex access-condition +If it is known in advance that a particular field of a condition will be +accessed repeatedly it is worth constructing an accessor for the field +using @code{condition-accessor} rather than using the (possibly more +convenient, but slower) @code{access-condition} procedure. +@end deffn + +@deffn procedure condition-predicate condition-type +@cindex specialization, of condition types +Returns a predicate procedure for testing whether an object is a +condition of type @var{condition-type} or one of its specializations +(there is no predefined way to test for a condition of a given type but +@emph{not} a specialization of that type). +@end deffn + +@deffn procedure condition-signaller condition-type field-names default-handler +Returns a signalling procedure with parameters @var{field-names}. When +the signalling procedure is called it creates and signals a condition of +type @var{condition-type}. If the condition isn't handled (i.e.@: if no +handler is invoked that causes an escape from the current continuation) +the signalling procedure reduces to a call to @var{default-handler} with +the condition as its argument. + +There are several standard procedures that are conventionally used for +@var{default-handler}. If @var{condition-type} is a specialization of +@code{condition-type:error}, @var{default-handler} should be the +procedure@* @code{standard-error-handler}. If @var{condition-type} is a +specialization of @code{condition-type:warning}, @var{default-handler} +should be the procedure @code{standard-warning-handler}. If +@var{condition-type} is a specialization of +@code{condition-type:breakpoint}, @var{default-handler} should be the +procedure @code{standard-breakpoint-handler}. +@end deffn + +@node Condition State, Simple Condition Instance Operations, Generating Operations on Conditions, Condition Instances +@subsection Condition Abstraction + +The condition data type is abstracted through a predicate +@code{condition?} and a set of accessor procedures. + +@deffn procedure condition? object +Returns @code{#f} if and only if @var{object} is not a condition. +@end deffn + +@deffn procedure condition/type condition +Returns the condition type of which @var{condition} is an instance. +@end deffn + +@deffn procedure condition/error? condition +@vindex condition-type:error +@cindex specialization, of condition types +Returns @code{#t} if the @var{condition} is an instance of condition +type @code{condition-type:error} or a specialization of it, @code{#f} +otherwise. +@end deffn + +@deffn procedure condition/restarts condition +Returns the list of restarts specified when @var{condition} was created. +@end deffn + +@deffn procedure condition/continuation condition +Returns the continuation specified when @var{condition} was created. +This is provided for inspecting the state of the system when the +condition occurred, @emph{not} for continuing or restarting the +computation. +@end deffn + +@deffn procedure write-condition-report condition port +Writes a description of @var{condition} to @var{port}, using the +reporter function from the condition type associated with +@var{condition}. See also @code{condition/report-string}. +@end deffn + +@node Simple Condition Instance Operations, , Condition State, Condition Instances +@subsection Simple Operations on Condition Instances + +The simple procedures described in this section are built on top of the +more detailed abstraction of condition objects described above. While +these procedures are sometimes easier to use, they are often less +efficient. + +@deffn procedure make-condition condition-type continuation restarts field-plist +@findex condition/restarts +@cindex bound-restarts +@cindex restarts, bound +Create a new condition object as an instance of @var{condition-type}, +associated with @var{continuation}. The @var{continuation} is provided +for inspection purposes only, @emph{not} for restarting the computation. +The @var{restarts} argument is described in @ref{Restarts}. The +@var{field-plist} is an alternating list of field names and values for +those fields, where the field names are those that would be returned by +@code{(condition-type/field-names @var{condition-type})}. It is used to +provide values for fields in the condition object; fields with no value +specified are set to @code{#f}. Once a condition object has been +created there is no way to alter the values of these fields. +@end deffn + +@deffn procedure access-condition condition field-name +@findex condition-accessor +Returns the value stored in the field @var{field-name} within +@var{condition}. @var{Field-name} must be one of the names returned by +@code{(condition-type/field-names (condition/type @var{condition}))}. +@code{access-condition} looks up the @var{field-name} at runtime, so it +is more efficient to use @code{condition-accessor} to create an access +function if the same field is to be extracted from several instances of +the same condition type. +@end deffn + +@deffn procedure condition/report-string condition +@findex write-condition-report +Returns a string containing a report of the @var{condition}. This is +generated by calling @code{write-condition-report} on @var{condition} +and a string output port, and returning the output collected by the port +as a string. +@end deffn + +@node Condition Types, Taxonomy, Condition Instances, Error System +@section Condition Types + +@cindex condition type +@cindex type, of condition +Each condition has a @dfn{condition type} object associated with it. +These objects are used as a means of focusing on related classes of +conditions, first by concentrating all of the information about a +specific class of condition in a single place, and second by specifying +an inheritance relationship between types. This inheritance +relationship forms the taxonomic structure of the condition hierarchy +(@pxref{Taxonomy}). + +The following procedures consititute the abstraction for condition +types. + +@deffn procedure make-condition-type name generalization field-names reporter +@cindex generalization, of condition types +Creates and returns a (new) condition type that is a specialization of +@var{generalization} (if it is a condition type) or is the root of a new +tree of condition types (if @var{generalization} is @code{#f}). For +debugging purposes, the condition type has a @var{name}, and instances +of this type contain storage for the fields specified by +@var{field-names} (a list of symbols) in addition to the fields common +to all conditions (@var{type}, @var{continuation} and @var{restarts}). + +@var{Reporter} is used to produce a description of a particular +condition of this type. It may be a string describing the condition, a +procedure of arity two (the first argument will be a condition of this +type and the second a port) that will @code{write} the message to the +given port, or @code{#f} to specify that the reporter should be taken +from the condition type @var{generalization} (or produce an +``undocumented condition of type @dots{}'' message if @var{generalization} +is @code{#f}). The conventions used to form descriptions are spelled +out in @ref{Error Messages}. +@end deffn + +@deffn procedure condition-type/error? condition-type +@vindex condition-type:error +@cindex specialization, of condition types +Returns @code{#t} if the @var{condition-type} is +@code{condition-type:error} or a specialization of it, @code{#f} +otherwise. +@end deffn + +@deffn procedure condition-type/field-names condition-type +@cindex generalization, of condition types +Returns a list of all of the field names for a condition of type +@var{condition-type}. This is the set union of the fields specified +when this @var{condition-type} was created with the +@code{condition-type/field-names} of the generalization of this +@var{condition-type}. +@end deffn + +@deffn procedure condition-type/generalizations condition-type +@cindex generalization, of condition types +Returns a list of all of the generalizations of @var{condition-type}. +Notice that every condition type is considered a generalization of +itself. +@end deffn + +@deffn procedure condition-type? object +Returns @code{#f} if and only if @var{object} is not a condition type. +@end deffn + +@node Taxonomy, , Condition Types, Error System +@section Condition-Type Taxonomy + +The MIT/GNU Scheme error system provides a rich set of predefined condition +types. These are organized into a forest through taxonomic links +providing the relationships for ``specializes'' and ``generalizes''. +The chart appearing below shows these relationships by indenting all the +specializations of a given type relative to the type. Note that the +variables that are bound to these condition types are prefixed by +@samp{condition-type:}; for example, the type appearing in the following +table as @samp{simple-error} is stored in the variable +@code{condition-type:simple-error}. Users are encouraged to add new +condition types by creating specializations of existing ones. + +Following the chart are detailed descriptions of the predefined +condition types. Some of these types are marked as @dfn{abstract} +types. Abstract types are not intended to be used directly as the type +of a condition; they are to be used as generalizations of other types, +and for binding condition handlers. Types that are not marked as +abstract are @dfn{concrete}; they are intended to be explicitly used as +a condition's type. + +@page +@example +@group +serious-condition + error + simple-error + illegal-datum + wrong-type-datum + wrong-type-argument + wrong-number-of-arguments + datum-out-of-range + bad-range-argument + inapplicable-object + file-error + file-operation-error + derived-file-error + port-error + derived-port-error + variable-error + unbound-variable + unassigned-variable + arithmetic-error + divide-by-zero + floating-point-overflow + floating-point-underflow + control-error + no-such-restart + not-loading + primitive-procedure-error + system-call-error +warning + simple-warning +simple-condition +breakpoint +@end group +@end example + +@deffn {condition type} condition-type:serious-condition +This is an abstract type. All serious conditions that require some form +of intervention should inherit from this type. In particular, all +errors inherit from this type. +@end deffn + +@deffn {condition type} condition-type:error +This is an abstract type. All errors should inherit from this type. +@end deffn + +@deffn {condition type} condition-type:simple-error message irritants +This is the condition generated by the @code{error} procedure when its +first argument is not a condition or condition type. The fields +@var{message} and @var{irritants} are taken directly from the arguments +to @code{error}; @var{message} contains an object (usually a string) and +@var{irritants} contains a list of objects. The reporter for this type +uses @code{format-error-message} to generate its output from +@var{message} and @var{irritants}. +@end deffn + +@deffn {condition type} condition-type:illegal-datum datum +This is an abstract type. This type indicates the class of errors in +which a program discovers an object that lacks specific required +properties. Most commonly, the object is of the wrong type or is +outside a specific range. The @var{datum} field contains the offending +object. +@end deffn + +@deffn {condition type} condition-type:wrong-type-datum datum type +This type indicates the class of errors in which a program discovers an +object that is of the wrong type. The @var{type} field contains a +string describing the type that was expected, and the @var{datum} field +contains the object that is of the wrong type. +@end deffn + +@example +@group +(error:wrong-type-datum 3.4 "integer") @error{} +;The object 3.4 is not an integer. +;To continue, call RESTART with an option number: +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn procedure error:wrong-type-datum datum type +This procedure signals a condition of type +@code{condition-type:wrong-type-datum}. The @var{datum} and @var{type} +fields of the condition are filled in from the corresponding arguments +to the procedure. +@end deffn + +@deffn {condition type} condition-type:wrong-type-argument datum type operator operand +This type indicates that a procedure was passed an argument of the wrong +type. The @var{operator} field contains the procedure (or a symbol +naming the procedure), the @var{operand} field indicates the argument +position that was involved (this field contains either a symbol, a +non-negative integer, or @code{#f}), the @var{type} field contains a +string describing the type that was expected, and the @var{datum} field +contains the offending argument. +@end deffn + +@example +@group +(+ 'a 3) @error{} +;The object a, passed as the first argument to integer-add, +; is not the correct type. +;To continue, call RESTART with an option number: +; (RESTART 2) => Specify an argument to use in its place. +; (RESTART 1) => Return to read-eval-print level 1. +@end group + +@group +(list-copy 3) +;The object 3, passed as an argument to list-copy, is not a list. +;To continue, call RESTART with an option number: +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn procedure error:wrong-type-argument datum type operator +This procedure signals a condition of type +@code{condition-type:wrong-type-argument}. The @var{datum}, @var{type} +and @var{operator} fields of the condition are filled in from the +corresponding arguments to the procedure; the @var{operand} field of the +condition is set to @code{#f}. +@end deffn + +@deffn {condition type} condition-type:wrong-number-of-arguments datum type operands +This type indicates that a procedure was called with the wrong number of +arguments. The @var{datum} field contains the procedure being called, +the @var{type} field contains the number of arguments that the procedure +accepts, and the @var{operands} field contains a list of the arguments +that were passed to the procedure. +@end deffn + +@example +@group +(car 3 4) @error{} +;The procedure car has been called with 2 arguments; +; it requires exactly 1 argument. +;To continue, call RESTART with an option number: +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn procedure error:wrong-number-of-arguments datum type operands +This procedure signals a condition of type +@code{condition-type:wrong-number-of-arguments}. The @var{datum}, +@var{type} and @var{operands} fields of the condition are filled in from +the corresponding arguments to the procedure. +@end deffn + +@deffn {condition type} condition-type:datum-out-of-range datum +This type indicates the class of errors in which a program discovers an +object that is of the correct type but is otherwise out of range. Most +often, this type indicates that an index to some data structure is +outside of the range of indices for that structure. The @var{datum} +field contains the offending object. +@end deffn + +@example +@group +(error:datum-out-of-range 3) @error{} +;The object 3 is not in the correct range. +;To continue, call RESTART with an option number: +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn procedure error:datum-out-of-range datum +This procedure signals a condition of type +@code{condition-type:datum-out-of-range}. The @var{datum} field of the +condition is filled in from the corresponding argument to the procedure. +@end deffn + +@deffn {condition type} condition-type:bad-range-argument datum operator operand +This type indicates that a procedure was passed an argument that is of +the correct type but is otherwise out of range. Most often, this type +indicates that an index to some data structure is outside of the range +of indices for that structure. The @var{operator} field contains the +procedure (or a symbol naming the procedure), the @var{operand} field +indicates the argument position that was involved (this field contains +either a symbol, a non-negative integer, or @code{#f}), and the +@var{datum} field is the offending argument. +@end deffn + +@example +@group +(string-ref "abc" 3) @error{} +;The object 3, passed as the second argument to string-ref, +; is not in the correct range. +;To continue, call RESTART with an option number: +; (RESTART 2) => Specify an argument to use in its place. +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn procedure error:bad-range-argument datum operator +This procedure signals a condition of type +@code{condition-type:bad-range-argument}. The @var{datum} and +@var{operator} fields of the condition are filled in from the +corresponding arguments to the procedure; the @var{operand} field of the +condition is set to @code{#f}. +@end deffn + +@deffn {condition type} condition-type:inapplicable-object datum operands +This type indicates an error in which a program attempted to apply an +object that is not a procedure. The object being applied is saved in +the @var{datum} field, and the arguments being passed to the object are +saved as a list in the @var{operands} field. +@end deffn + +@example +@group +(3 4) @error{} +;The object 3 is not applicable. +;To continue, call RESTART with an option number: +; (RESTART 2) => Specify a procedure to use in its place. +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn {condition type} condition-type:file-error filename +This is an abstract type. It indicates that an error associated with a +file has occurred. For example, attempting to delete a nonexistent file +will signal an error. The @var{filename} field contains a filename or +pathname associated with the operation that failed. +@end deffn + +@deffn {condition type} condition-type:file-operation-error filename verb noun reason operator operands +This is the most common condition type for file system errors. The +@var{filename} field contains the filename or pathname that was being +operated on. The @var{verb} field contains a string which is the verb +or verb phrase describing the operation being performed, and the +@var{noun} field contains a string which is a noun or noun phrase +describing the object being operated on. The @var{reason} field +contains a string describing the error that occurred. The +@var{operator} field contains the procedure performing the operation (or +a symbol naming that procedure), and the @var{operands} field contains a +list of the arguments that were passed to that procedure. For example, +an attempt to delete a nonexistent file would have the following field +values: + +@example +@group +filename "/zu/cph/tmp/no-such-file" +verb "delete" +noun "file" +reason "no such file or directory" +operator file-remove +operands ("/zu/cph/tmp/no-such-file") +@end group +@end example + +@noindent +and would generate a message like this: + +@example +@group +(delete-file "/zu/cph/tmp/no-such-file") @error{} +;Unable to delete file "/zu/cph/tmp/no-such-file" because: +; No such file or directory. +;To continue, call RESTART with an option number: +; (RESTART 3) => Try to delete the same file again. +; (RESTART 2) => Try to delete a different file. +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example +@end deffn + +@deffn procedure error:file-operation-error filename verb noun reason operator operands +This procedure signals a condition of type +@code{condition-type:file-operation-error}. The fields of the condition +are filled in from the corresponding arguments to the procedure. +@end deffn + +@deffn {condition type} condition-type:derived-file-error filename condition +This is another kind of file error, which is generated by obscure +file-system errors that do not fit into the standard categories. The +@var{filename} field contains the filename or pathname that was being +operated on, and the @var{condition} field contains a condition +describing the error in more detail. Usually the @var{condition} field +contains a condition of type @code{condition-type:system-call-error}. +@end deffn + +@deffn procedure error:derived-file filename condition +This procedure signals a condition of type +@code{condition-type:derived-file-error}. The @var{filename} and +@var{condition} fields of the condition are filled in from the +corresponding arguments to the procedure. +@end deffn + +@deffn {condition type} condition-type:port-error port +This is an abstract type. It indicates that an error associated with a +I/O port has occurred. For example, writing output to a file port can +signal an error if the disk containing the file is full; that error +would be signalled as a port error. The @var{port} field contains the +associated port. +@end deffn + +@deffn {condition type} condition-type:derived-port-error port condition +This is a concrete type that is signalled when port errors occur. The +@var{port} field contains the port associated with the error, and the +@var{condition} field contains a condition object that describes the +error in more detail. Usually the @var{condition} field contains a +condition of type @code{condition-type:system-call-error}. +@end deffn + +@deffn procedure error:derived-port port condition +This procedure signals a condition of type +@code{condition-type:derived-port-error}. The @var{port} and +@var{condition} fields of the condition are filled in from the +corresponding arguments to the procedure. +@end deffn + +@deffn {condition type} condition-type:variable-error location environment +This is an abstract type. It indicates that an error associated with a +variable has occurred. The @var{location} field contains the name of +the variable, and the @var{environment} field contains the environment +in which the variable was referenced. +@end deffn + +@deffn {condition type} condition-type:unbound-variable location environment +This type is generated when a program attempts to access or modify a +variable that is not bound. The @var{location} field contains the name +of the variable, and the @var{environment} field contains the +environment in which the reference occurred. +@end deffn + +@example +@group +foo @error{} +;Unbound variable: foo +;To continue, call RESTART with an option number: +; (RESTART 3) => Specify a value to use instead of foo. +; (RESTART 2) => Define foo to a given value. +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn {condition type} condition-type:unassigned-variable location environment +This type is generated when a program attempts to access a variable that +is not assigned. The @var{location} field contains the name of the +variable, and the @var{environment} field contains the environment in +which the reference occurred. +@end deffn + +@example +@group +foo @error{} +;Unassigned variable: foo +;To continue, call RESTART with an option number: +; (RESTART 3) => Specify a value to use instead of foo. +; (RESTART 2) => Set foo to a given value. +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn {condition type} condition-type:arithmetic-error operator operands +This is an abstract type. It indicates that a numerical operation was +unable to complete because of an arithmetic error. (For example, +division by zero.) The @var{operator} field contains the procedure that +implements the operation (or a symbol naming the procedure), and the +@var{operands} field contains a list of the arguments that were passed +to the procedure. +@end deffn + +@deffn {condition type} condition-type:divide-by-zero operator operands +This type is generated when a program attempts to divide by zero. The +@var{operator} field contains the procedure that implements the failing +operation (or a symbol naming the procedure), and the @var{operands} +field contains a list of the arguments that were passed to the +procedure. +@end deffn + +@example +@group +(/ 1 0) +;Division by zero signalled by /. +;To continue, call RESTART with an option number: +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn procedure error:divide-by-zero operator operands +This procedure signals a condition of type +@code{condition-type:divide-by-zero}. The @var{operator} and +@var{operands} fields of the condition are filled in from the +corresponding arguments to the procedure. +@end deffn + +@deffn {condition type} condition-type:floating-point-overflow operator operands +This type is generated when a program performs an arithmetic operation +that results in a floating-point overflow. The @var{operator} field +contains the procedure that implements the operation (or a symbol naming +the procedure), and the @var{operands} field contains a list of the +arguments that were passed to the procedure. +@end deffn + +@deffn {condition type} condition-type:floating-point-underflow operator operands +This type is generated when a program performs an arithmetic operation +that results in a floating-point underflow. The @var{operator} field +contains the procedure that implements the operation (or a symbol naming +the procedure), and the @var{operands} field contains a list of the +arguments that were passed to the procedure. +@end deffn + +@deffn {condition type} condition-type:primitive-procedure-error operator operands +This is an abstract type. It indicates that an error was generated by a +primitive procedure call. Primitive procedures are distinguished from +ordinary procedures in that they are not written in Scheme but instead +in the underlying language of the Scheme implementation. The +@var{operator} field contains the procedure that implements the +operation (or a symbol naming the procedure), and the @var{operands} +field contains a list of the arguments that were passed to the +procedure. +@end deffn + +@deffn {condition type} condition-type:system-call-error operator operands system-call error-type +This is the most common condition type generated by primitive +procedures. A condition of this type indicates that the primitive made +a system call to the operating system, and that the system call +signalled an error. The system-call error is reflected back to Scheme +as a condition of this type, except that many common system-call errors +are automatically translated by the Scheme implementation into more +useful forms; for example, a system-call error that occurs while trying +to delete a file will be translated into a condition of type +@code{condition-type:file-operation-error}. The @var{operator} field +contains the procedure that implements the operation (or a symbol naming +the procedure), and the @var{operands} field contains a list of the +arguments that were passed to the procedure. The @var{system-call} and +@var{error-type} fields contain symbols that describe the specific +system call that was being made and the error that occurred, +respectively; these symbols are completely operating-system dependent. +@end deffn + +@deffn {condition type} condition-type:control-error +This is an abstract type. It describes a class of errors relating to +program control flow. +@end deffn + +@deffn {condition type} condition-type:no-such-restart name +This type indicates that a named restart was not active when it was +expected to be. Conditions of this type are signalled by several +procedures that look for particular named restarts, for example +@code{muffle-warning}. The @var{name} field contains the name that was +being searched for. +@end deffn + +@example +@group +(muffle-warning) @error{} +;The restart named muffle-warning is not bound. +;To continue, call RESTART with an option number: +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn procedure error:no-such-restart name +This procedure signals a condition of type +@code{condition-type:no-such-restart}. The @var{name} field of the +condition is filled in from the corresponding argument to the procedure. +@end deffn + +@deffn {condition type} condition-type:not-loading +A condition of this type is generated when the procedure +@code{current-load-pathname} is called from somewhere other than inside +a file being loaded. +@end deffn + +@example +@group +(current-load-pathname) @error{} +;No file being loaded. +;To continue, call RESTART with an option number: +; (RESTART 1) => Return to read-eval-print level 1. +@end group +@end example + +@deffn {condition type} condition-type:warning +This is an abstract type. All warnings should inherit from this type. +Warnings are a class of conditions that are usually handled by informing +the user of the condition and proceeding the computation normally. +@end deffn + +@deffn {condition type} condition-type:simple-warning message irritants +This is the condition generated by the @code{warn} procedure. The +fields @var{message} and @var{irritants} are taken directly from the +arguments to @code{warn}; @var{message} contains an object (usually a +string) and @var{irritants} contains a list of objects. The reporter +for this type uses @code{format-error-message} to generate its output +from @var{message} and @var{irritants}. +@end deffn + +@deffn {condition type} condition-type:simple-condition message irritants +This is an unspecialized condition that does not fall into any of the +standard condition classes. The @var{message} field contains an object +(usually a string) and @var{irritants} contains a list of objects. The +reporter for this type uses @code{format-error-message} to generate its +output from @var{message} and @var{irritants}. +@end deffn + +@deffn {condition type} condition-type:breakpoint environment message prompt +A condition of this type is generated by the breakpoint mechanism. The +contents of its fields are beyond the scope of this document. +@end deffn diff --git a/v7/doc/ref-manual/graphics.texi b/v7/doc/ref-manual/graphics.texi new file mode 100644 index 000000000..b648406ab --- /dev/null +++ b/v7/doc/ref-manual/graphics.texi @@ -0,0 +1,1456 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: graphics.texi,v 1.1 2003/04/15 03:29:42 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Graphics, Win32 Package Reference, Error System, Top +@chapter Graphics +@cindex graphics + +MIT/GNU Scheme has a simple two-dimensional line-graphics interface +that is suitable for many graphics applications. In particular it is +often used for plotting data points from experiments. The interface is +generic in that it can support different types of graphics devices in a +uniform manner. At the present time only one type of graphics device +is implemented on each operating system. + +Procedures are available for drawing points, lines, and text; defining +the coordinate system; clipping graphics output; controlling some of the +drawing characteristics; and controlling the output buffer (for devices +that perform buffering). Additionally, devices may support custom +operations, such as control of colors. + +There are some constraints on the arguments to the procedures described +in this chapter. Any argument named @var{graphics-device} must be a +graphics device object that was returned from a call to +@code{make-graphics-device}. Any argument that is a coordinate must be +either an exact integer or an inexact real. + +@menu +* Opening and Closing of Graphics Devices:: +* Coordinates for Graphics:: +* Drawing Graphics:: +* Characteristics of Graphics Output:: +* Buffering of Graphics Output:: +* Clipping of Graphics Output:: +* Custom Graphics Operations:: +* Images:: +* X Graphics:: Graphics on the X Window System +* Win32 Graphics:: Graphics on Microsoft Windows and Windows NT +* OS/2 Graphics:: Graphics on IBM OS/2 +@end menu + +@node Opening and Closing of Graphics Devices, Coordinates for Graphics, Graphics, Graphics +@section Opening and Closing of Graphics Devices +@cindex graphics, opening and closing devices + +@deffn procedure graphics-type-available? graphics-device-type +This predicate returns @code{#t} if the graphics system named by the +symbol @var{graphics-device-type} is implemented by the Scheme system. +Otherwise it returns @code{#f}, in which case it is an error to attempt +to make a graphics device using @var{graphics-device-type}. +@end deffn + +@deffn procedure enumerate-graphics-types +This procedure returns a list of symbols which are the names of all the +graphics device types that are supported by the Scheme system. The +result is useful in deciding what additional arguments to supply to +@code{make-graphics-device}, as each device type typically has a unique +way of specifying the initial size, shape and other attributes. +@end deffn + +@deffn procedure make-graphics-device graphics-device-type object @dots{} +This operation creates and returns a graphics device object. +@var{Graphics-device-type} is a symbol naming a graphics device type, +and both the number and the meaning of the remaining arguments is +determined by that type (see the description of each device type for +details); @var{graphics-device-type} must satisfy +@code{graphics-type-available?}. @var{Graphics-device-type} may also be +@code{#f}, in which case the graphics device type is chosen by the +system from what is available. This allows completely portable graphics +programs to be written provided no custom graphics operations are used. +When @var{graphics-device-type} is @code{#f} no further arguments may be +given; each graphics device type will use some ``sensible'' defaults. +If more control is required then the program should use one of the two +procedures above to dispatch on the available types. + +This procedure opens and initializes the device, which remains valid +until explicitly closed by the procedure @code{graphics-close}. +Depending on the implementation of the graphics device, if this object +is reclaimed by the garbage collector, the graphics device may remain +open or it may be automatically closed. While a graphics device remains +open the resources associated with it are not released. +@end deffn + +@deffn procedure graphics-close graphics-device +Closes @var{graphics-device}, releasing its resources. Subsequently it +is an error to use @var{graphics-device}. +@end deffn + +@node Coordinates for Graphics, Drawing Graphics, Opening and Closing of Graphics Devices, Graphics +@section Coordinates for Graphics +@cindex graphics, coordinate systems + +@cindex coordinates, graphics +@cindex device coordinates, graphics (defn) +@cindex graphics, device coordinates (defn) +@cindex virtual coordinates, graphics (defn) +@cindex graphics, virtual coordinates (defn) +Each graphics device has two different coordinate systems associated +with it: @dfn{device coordinates} and @dfn{virtual coordinates}. Device +coordinates are generally defined by low-level characteristics of the +device itself, and often cannot be changed. Most device coordinate +systems are defined in terms of pixels, and usually the upper-left-hand +corner is the origin of the coordinate system, with @var{x} coordinates +increasing to the right and @var{y} coordinates increasing downwards. + +In contrast, virtual coordinates are more flexible in the units +employed, the position of the origin, and even the direction in which +the coordinates increase. A virtual coordinate system is defined by +assigning coordinates to the edges of a device. Because these edge +coordinates are arbitrary real numbers, any Cartesian coordinate system +can be defined. + +All graphics procedures that use coordinates are defined on virtual +coordinates. For example, to draw a line at a particular place on a +device, the virtual coordinates for the endpoints of that line are +given. + +When a graphics device is initialized, its virtual coordinate system is +reset so that the left edge corresponds to an x-coordinate of @code{-1}, +the right edge to x-coordinate @code{1}, the bottom edge to y-coordinate +@code{-1}, and the top edge to y-coordinate @code{1}. + +@deffn procedure graphics-device-coordinate-limits graphics-device +Returns (as multiple values) the device coordinate limits for +@var{graphics-device}. The values, which are exact non-negative +integers, are: @var{x-left}, @var{y-bottom}, @var{x-right}, and +@var{y-top}. +@end deffn + +@deffn procedure graphics-coordinate-limits graphics-device +Returns (as multiple values) the virtual coordinate limits for +@var{graphics-device}. The values, which are real numbers, are: +@var{x-left}, @var{y-bottom}, @var{x-right}, and @var{y-top}. +@end deffn + +@deffn procedure graphics-set-coordinate-limits graphics-device x-left y-bottom x-right y-top +Changes the virtual coordinate limits of @var{graphics-device} to the +given arguments. @var{X-left}, @var{y-bottom}, @var{x-right}, and +@var{y-top} must be real numbers. Subsequent calls to +@code{graphics-coordinate-limits} will return the new limits. This +operation has no effect on the device's displayed contents. + +Note: This operation usually resets the clip rectangle, although it is +not guaranteed to do so. If a clip rectangle is in effect when this +procedure is called, it is necessary to redefine the clip rectangle +afterwards. +@end deffn + +@node Drawing Graphics, Characteristics of Graphics Output, Coordinates for Graphics, Graphics +@section Drawing Graphics +@cindex graphics, drawing + +The procedures in this section provide the basic drawing capabilities of +Scheme's graphics system. + +@deffn procedure graphics-clear graphics-device +Clears the display of @var{graphics-device}. Unaffected by the current +drawing mode. +@end deffn + +@deffn procedure graphics-draw-point graphics-device x y +Draws a single point on @var{graphics-device} at the virtual coordinates +given by @var{x} and @var{y}, using the current drawing mode. +@end deffn + +@deffn procedure graphics-erase-point graphics-device x y +Erases a single point on @var{graphics-device} at the virtual +coordinates given by @var{x} and @var{y}. This procedure is unaffected +by the current drawing mode. +@end deffn + +@noindent +This is equivalent to + +@example +@group +(lambda (device x y) + (graphics-bind-drawing-mode device 0 + (lambda () + (graphics-draw-point device x y)))) +@end group +@end example + +@deffn procedure graphics-draw-line graphics-device x-start y-start x-end y-end +@var{X-start}, @var{y-start}, @var{x-end}, and @var{y-end} must be real +numbers. Draws a line on @var{graphics-device} that connects the points +(@var{x-start}, @var{y-start}) and (@var{x-end}, @var{y-end}). The line +is drawn using the current drawing mode and line style. +@end deffn + +@deffn procedure graphics-draw-text graphics-device x y string +Draws the characters of @var{string} at the point (@var{x}, @var{y}) on +@var{graphics-device}, using the current drawing mode. The +characteristics of the characters drawn are device-dependent, but all +devices are initialized so that the characters are drawn upright, from +left to right, with the leftmost edge of the leftmost character at +@var{x}, and the baseline of the characters at @var{y}. +@end deffn + +@cindex graphics, cursor (defn) +@cindex cursor, graphics (defn) +The following two procedures provide an alternate mechanism for drawing +lines, which is more akin to using a plotter. They maintain a +@dfn{cursor}, which can be positioned to a particular point and then +dragged to another point, producing a line. Sequences of connected line +segments can be drawn by dragging the cursor from point to point. + +Many graphics operations have an unspecified effect on the cursor. The +following exceptions are guaranteed to leave the cursor unaffected: + +@example +@group +graphics-device-coordinate-limits +graphics-coordinate-limits +graphics-enable-buffering +graphics-disable-buffering +graphics-flush +graphics-bind-drawing-mode +graphics-set-drawing-mode +graphics-bind-line-style +graphics-set-line-style +@end group +@end example + +The initial state of the cursor is unspecified. + +@deffn procedure graphics-move-cursor graphics-device x y +Moves the cursor for @var{graphics-device} to the point (@var{x}, +@var{y}). The contents of the device's display are unchanged. +@end deffn + +@deffn procedure graphics-drag-cursor graphics-device x y +Draws a line from @var{graphics-device}'s cursor to the point (@var{x}, +@var{y}), simultaneously moving the cursor to that point. The line is +drawn using the current drawing mode and line style. +@end deffn + +@node Characteristics of Graphics Output, Buffering of Graphics Output, Drawing Graphics, Graphics +@section Characteristics of Graphics Output + +@cindex graphics, output characteristics +Two characteristics of graphics output are so useful that they are +supported uniformly by all graphics devices: @dfn{drawing mode} and +@dfn{line style}. A third characteristic, @dfn{color}, is equally +useful (if not more so), but implementation restrictions prohibit a +uniform interface. + +@cindex drawing mode, graphics (defn) +@cindex graphics, drawing mode (defn) +The @dfn{drawing mode}, an exact integer in the range @code{0} to +@code{15} inclusive, determines how the figure being drawn is combined +with the background over which it is drawn to generate the final result. +Initially the drawing mode is set to ``source'', so that the new output +overwrites whatever appears in that place. Useful alternative drawing +modes can, for example, erase what was already there, or invert it. + +Altogether 16 boolean operations are available for combining the source +(what is being drawn) and the destination (what is being drawn over). +The source and destination are combined by the device on a +pixel-by-pixel basis as follows: + +@example +@group +Mode Meaning +---- ------- +0 ZERO @r{[erase; use background color]} +1 source AND destination +2 source AND (NOT destination) +3 source +4 (NOT source) AND destination +5 destination +6 source XOR destination +7 source OR destination +8 NOT (source OR destination) +9 NOT (source XOR destination) +10 NOT destination +11 source OR (NOT destination) +12 NOT source +13 (NOT source) OR destination +14 (NOT source) OR (NOT destination) +15 ONE @r{[use foreground color]} +@end group +@end example + +@cindex line style, graphics (defn) +@cindex graphics, line style (defn) +The @dfn{line style}, an exact integer in the range @code{0} to @code{7} +inclusive, determines which parts of a line are drawn in the foreground +color, and which in the background color. The default line style, +``solid'', draws the entire line in the foreground color. +Alternatively, the ``dash'' style alternates between foreground and +background colors to generate a dashed line. This capability is useful +for plotting several things on the same graph. + +Here is a table showing the name and approximate pattern of the +different styles. A @samp{1} in the pattern represents a foreground +pixel, while a @samp{-} represents a background pixel. Note that the +precise output for each style will vary from device to device. The only +style that is guaranteed to be the same for every device is ``solid''. + +@example +@group +Style Name Pattern +----- ------- ------- +0 solid 1111111111111111 +1 dash 11111111-------- +2 dot 1-1-1-1-1-1-1-1- +3 dash dot 1111111111111-1- +4 dash dot dot 11111111111-1-1- +5 long dash 11111111111----- +6 center dash 111111111111-11- +7 center dash dash 111111111-11-11- +@end group +@end example + +@deffn procedure graphics-bind-drawing-mode graphics-device drawing-mode thunk +@deffnx procedure graphics-bind-line-style graphics-device line-style thunk +These procedures bind the drawing mode or line style, respectively, of +@var{graphics-device}, invoke the procedure @var{thunk} with no +arguments, then undo the binding when @var{thunk} returns. The value of +each procedure is the value returned by @var{thunk}. Graphics +operations performed during @var{thunk}'s dynamic extent will see the +newly bound mode or style as current. +@end deffn + +@deffn procedure graphics-set-drawing-mode graphics-device drawing-mode +@deffnx procedure graphics-set-line-style graphics-device line-style +These procedures change the drawing mode or line style, respectively, of +@var{graphics-device}. The mode or style will remain in effect until +subsequent changes or bindings. +@end deffn + +@node Buffering of Graphics Output, Clipping of Graphics Output, Characteristics of Graphics Output, Graphics +@section Buffering of Graphics Output +@cindex buffering, of graphics output +@cindex graphics, buffering of output + +To improve performance of graphics output, most graphics devices provide +some form of buffering. By default, Scheme's graphics procedures flush +this buffer after every drawing operation. The procedures in this +section allow the user to control the flushing of the output +buffer. + +@deffn procedure graphics-enable-buffering graphics-device +Enables buffering for @var{graphics-device}. In other words, after this +procedure is called, graphics operations are permitted to buffer their +drawing requests. This usually means that the drawing is delayed until +the buffer is flushed explicitly by the user, or until it fills up and +is flushed by the system. +@end deffn + +@deffn procedure graphics-disable-buffering graphics-device +Disables buffering for @var{graphics-device}. By default, all graphics +devices are initialized with buffering disabled. After this procedure +is called, all drawing operations perform their output immediately, +before returning. + +Note: @code{graphics-disable-buffering} flushes the output buffer if +necessary. +@end deffn + +@deffn procedure graphics-flush graphics-device +Flushes the graphics output buffer for @var{graphics-device}. This +operation has no effect for devices that do not support buffering, or if +buffering is disabled for the device. +@end deffn + +@node Clipping of Graphics Output, Custom Graphics Operations, Buffering of Graphics Output, Graphics +@section Clipping of Graphics Output +@cindex graphics, clipping +@cindex clipping, of graphics + +@cindex clip rectangle, graphics (defn) +Scheme provides a rudimentary mechanism for restricting graphics output +to a given rectangular subsection of a graphics device. By default, +graphics output that is drawn anywhere within the device's virtual +coordinate limits will appear on the device. When a @dfn{clip +rectangle} is specified, however, output that would have appeared +outside the clip rectangle is not drawn. + +Note that changing the virtual coordinate limits for a device will +usually reset the clip rectangle for that device, as will any operation +that affects the size of the device (such as a window resizing +operation). However, programs should not depend on this. + +@deffn procedure graphics-set-clip-rectangle graphics-device x-left y-bottom x-right y-top +Specifies the clip rectangle for @var{graphics-device} in virtual +coordinates. @var{X-left}, @var{y-bottom}, @var{x-right}, and +@var{y-top} must be real numbers. Subsequent graphics output is clipped +to the intersection of this rectangle and the device's virtual +coordinate limits. +@end deffn + +@deffn procedure graphics-reset-clip-rectangle graphics-device +Eliminates the clip rectangle for @var{graphics-device}. Subsequent +graphics output is clipped to the virtual coordinate limits of the +device. +@end deffn + +@node Custom Graphics Operations, Images, Clipping of Graphics Output, Graphics +@section Custom Graphics Operations +@cindex custom operations, on graphics device +@cindex graphics, custom operations + +In addition to the standard operations, a graphics device may support +@dfn{custom operations}. For example, most devices have custom +operations to control color. @code{graphics-operation} is used to +invoke custom operations. + +@deffn procedure graphics-operation graphics-device name object @dots{} +Invokes the graphics operation on @var{graphics-device} whose name is +the symbol @var{name}, passing it the remaining arguments. This +procedure can be used to invoke the standard operations, as well as +custom operations that are specific to a particular graphics device +type. The names of the standard graphics operations are formed by +removing the @code{graphics-} prefix from the corresponding procedure. +For example, the following are equivalent: + +@example +@group +(graphics-draw-point device x y) +(graphics-operation device 'draw-point x y) +@end group +@end example + +For information on the custom operations for a particular device, see +the documentation for its type. +@end deffn + +@node Images, X Graphics, Custom Graphics Operations, Graphics +@section Images +@cindex graphics, images +@cindex images, graphics +@cindex graphics, bitmaps +@cindex bitmaps, graphics + +Some graphics device types support images, which are rectangular pieces +of picture that may be drawn into a graphics device. Images are often +called something else in the host graphics system, such as bitmaps or +pixmaps. The operations supported vary between devices, so look under +the different device types to see what operations are available. All +devices that support images support the following operations. + +@defop operation graphics-device create-image width height +Images are created using the @code{create-image} graphics operation, +specifying the @var{width} and @var{height} of the image in device +coordinates (pixels). + +@example +(graphics-operation device 'create-image 200 100) +@end example + +@noindent +The initial contents of an image are unspecified. + +@code{create-image} is a graphics operation rather than a procedure +because the kind of image returned depends on the kind of graphics +device used and the options specified in its creation. The image may be +used freely with other graphics devices created with the same +attributes, but the effects of using an image with a graphics device +with different attributes (for example, different colors) is undefined. +Under X, the image is display dependent. +@end defop + +@defop operation graphics-device draw-image x y image +The image is copied into the graphics device at the specified position. +@end defop + +@defop operation graphics-device draw-subimage x y image im-x im-y w h +Part of the image is copied into the graphics device at the specified +(@var{x}, @var{y}) position. The part of the image that is copied is the +rectangular region at @var{im-x} and @var{im-y} and of width @var{w} and +height @var{h}. These four numbers are given in device coordinates +(pixels). +@end defop + +@deffn procedure image? object +Returns @code{#t} if @var{object} is an image, otherwise returns +@code{#f}. +@end deffn + +@deffn procedure image/destroy image +This procedure destroys @var{image}, returning storage to the system. +Programs should destroy images after they have been used because even +modest images may use large amounts of memory. Images are reclaimed by +the garbage collector, but they may be implemented using memory outside +of Scheme's heap. If an image is reclaimed before being destroyed, the +implementation might not deallocate that non-heap memory, which can +cause a subsequent call to @code{create-image} to fail because it is +unable to allocate enough memory. +@end deffn + +@c @deffn procedure image/descriptor image +@c The procedure returns the implementation dependent image. Its use is +@c discouraged as it is non-portable. +@c @end deffn + +@deffn procedure image/height image +Returns the height of the image in device coordinates. +@end deffn + +@deffn procedure image/width image +Returns the width of the image in device coordinates. +@end deffn + +@deffn procedure image/fill-from-byte-vector image bytes +The contents of @var{image} are set in a device-dependent way, using one +byte per pixel from @var{bytes} (a string). Pixels are filled row by +row from the top of the image to the bottom, with each row being filled +from left to right. There must be at least @code{(* (image/height +@var{image}) (image/width @var{image}))} bytes in @var{bytes}. +@end deffn + +@node X Graphics, Win32 Graphics, Images, Graphics +@section X Graphics +@cindex X graphics + +@cindex X window system +MIT/GNU Scheme supports graphics in the X window system (version 11). +Arbitrary numbers of displays may be opened, and arbitrary numbers of +graphics windows may be created for each display. A variety of +operations is available to manipulate various aspects of the windows, to +control their size, position, colors, and mapping. The X graphics +device type supports images, which are implemented as Xlib @code{XImage} +objects. X display, window, and image objects are automatically closed +if they are reclaimed by the garbage collector. + +@menu +* X Graphics Type:: +* Utilities for X Graphics:: +* Custom Operations on X Graphics Devices:: +@end menu + +@node X Graphics Type, Utilities for X Graphics, X Graphics, X Graphics +@subsection X Graphics Type + + +A graphics device for X windows is created by passing the symbol +@code{x} as the graphics device type name to +@code{make-graphics-device}: + +@example +(make-graphics-device 'x #!optional @var{display} @var{geometry} @var{suppress-map?}) +@end example + +@noindent +where @var{display} is either a display object, @code{#f}, or a string; +@var{geometry} is either @code{#f} or a string; and @var{suppress-map?} +is a boolean or a vector (see below). A new window is created on the +appropriate display, and a graphics device representing that window is +returned. + +@findex x-open-display +@var{Display} specifies which X display the window is to be opened on; +if it is @code{#f} or a string, it is passed as an argument to +@code{x-open-display}, and the value returned by that procedure is used +in place of the original argument. @var{Geometry} is an X geometry +string, or @code{#f} which means to use the default geometry (which is +specified as a resource). + +@var{Suppress-map?}, if given, may take two forms. First, it may be a +boolean: if @code{#f} (the default), the window is automatically mapped +after it is created; otherwise, @code{#t} means to suppress this +automatic mapping. The second form is a vector of three elements. The +first element is a boolean with the same meaning as the boolean form of +@var{suppress-map?}. The second element is a string, which specifies an +alternative resource name to be used for looking up the window's +resources. The third element is also a string, which specifies a class +name for looking up the window's resources. The default value for +@var{suppress-map?} is @code{#f}. + +The default resource and class names are @code{"schemeGraphics"} and +@code{"SchemeGraphics"} respectively. + +@cindex resources, X graphics +@cindex X resources, graphics +The window is initialized using the resource and class names specified +by @var{suppress-map?}, and is sensitive to the following resource +properties: + +@example +@group +Property Class Default +-------- ----- ------- +geometry Geometry 512x384+0+0 +font Font fixed +borderWidth BorderWidth 2 +internalBorder BorderWidth @r{[border width]} +background Background white +foreground Foreground black +borderColor BorderColor @r{[foreground color]} +cursorColor Foreground @r{[foreground color]} +pointerColor Foreground @r{[foreground color]} +@end group +@end example + +The window is created with a @code{backing_store} attribute of +@code{Always}. The window's name and icon name are initialized to +@code{"scheme-graphics"}. + + +@node Utilities for X Graphics, Custom Operations on X Graphics Devices, X Graphics Type, X Graphics +@subsection Utilities for X Graphics + +@deffn procedure x-graphics/open-display display-name +@cindex display, X graphics +@cindex X display, graphics +Opens a connection to the display whose name is @var{display-name}, +returning a display object. If unable to open a connection, @code{#f} +is returned. @var{Display-name} is normally a string, which is an X +display name in the usual form; however, @code{#f} is also allowed, +meaning to use the value of the unix environment variable +@code{DISPLAY}. +@end deffn + +@deffn procedure x-graphics/close-display display +Closes @var{display}; after calling this procedure, it is an error to +use @var{display} for any purpose. Any windows that were previously +opened on @var{display} are destroyed and their resources returned to +the operating system. +@end deffn + +@deffn procedure x-close-all-displays +Closes all open connections to X displays. Equivalent to calling +@code{x-close-display} on all open displays. +@end deffn + +@deffn procedure x-geometry-string x y width height +@cindex geometry string, X graphics +@cindex X geometry string, graphics +This procedure creates and returns a standard X geometry string from the +given arguments. @var{X} and @var{y} must be either exact integers or +@code{#f}, while @var{width} and @var{height} must be either exact +non-negative integers or @code{#f}. Usually either @var{x} and @var{y} +are both specified or both @code{#f}; similarly for @var{width} and +@var{height}. If only one of the elements of such a pair is specified, +it is ignored. + +Examples: + +@example +@group +(x-geometry-string #f #f 100 200) @result{} "100x200" +(x-geometry-string 2 -3 100 200) @result{} "100x200+2-3" +(x-geometry-string 2 -3 #f #f) @result{} "+2-3" +@end group +@end example + +Note that the @var{x} and @var{y} arguments cannot distinguish between +@code{+0} and @code{-0}, even though these have different meanings in X. +If either of those arguments is @code{0}, it means @code{+0} in X +terminology. If you need to distinguish these two cases you must create +your own geometry string using Scheme's string and number primitives. +@end deffn + +@node Custom Operations on X Graphics Devices, , Utilities for X Graphics, X Graphics +@subsection Custom Operations on X Graphics Devices + +Custom operations are invoked using the procedure +@code{graphics-operation}. For example, + +@example +(graphics-operation device 'set-foreground-color "blue") +@end example + +@defop operation x-graphics-device set-background-color color-name +@defopx operation x-graphics-device set-foreground-color color-name +@defopx operation x-graphics-device set-border-color color-name +@defopx operation x-graphics-device set-mouse-color color-name +@findex graphics-clear +These operations change the colors associated with a window. +@var{Color-name} must be a string, which is the X server's name for the +desired color. @code{set-border-color} and @code{set-mouse-color} +immediately change the border and mouse-cursor colors. +@code{set-background-color} and @code{set-foreground-color} change the +colors to be used when drawing, but have no effect on anything drawn +prior to their invocation. Because changing the background color +affects the entire window, we recommend calling @code{graphics-clear} on +the window's device afterwards. Color names include both mnemonic +names, like @code{"red"}, and intensity names specified in the +@code{"#@var{rrggbb}"} notation. +@end defop + +@defop operation x-graphics-device draw-arc x y radius-x radius-y angle-start angle-sweep fill? +@cindex drawing arcs and circles, graphics +@cindex graphics, drawing arcs and circles +@cindex circles, drawing +@findex draw-arc + +Operation @code{draw-arc} draws or fills an arc. An arc is a segment of +a circle, which may have been stretched along the x- or y- axis to form +an ellipse. + +The parameters @var{x}, @var{y}, @var{radius-x} and @var{radius-y} +describe the circle and @var{angle-start} and @var{angle-sweep} choose +which part of the circle is drawn. The arc is drawn on the graphics +device with the center of the circle at the virtual coordinates given by +@var{x} and @var{y}. @var{radius-x} and @var{radius-y} determine the +size of the circle in virtual coordinate units. + +The parameter @var{angle-start} determines where the arc starts. It is +measured in degrees in an anti-clockwise direction, starting at 3 +o'clock. @var{angle-sweep} determines how much of the circle is drawn. +It too is measured anti-clockwise in degrees. A negative value means +the measurement is in a clockwise direction. + +Note that the angles are determined on a unit circle before it is +stretched into an ellipse, so the actual angles that you will see on the +computer screen depends on all of: @var{radius-x} and @var{radius-y}, +the window size, and the virtual coordinates. + +If @var{fill?} is @code{#f} then just the segment of the circle is +drawn, otherwise the arc is filled in a pie-slice fashion. + +This draws a quarter circle pie slice, standing on its point, with point +at virtual coordinates (3,5): + +@example +(graphics-opereration g 'draw-arc 3 5 .5 .5 45 90 #t) +@end example + +@end defop + +@defop operation x-graphics-device draw-circle x y radius +@defopx operation x-graphics-device fill-circle x y radius +@cindex drawing arcs and circles, graphics +@cindex graphics, drawing arcs and circles +@cindex circles, drawing +@findex draw-circle +@findex fill-circle +These operations draw a circle (outline) or a filled circle (solid) at +on the graphics device at the virtual coordinates given by @var{x} and +@var{y}. These operations could be implemented trivially interms of the +@code{draw-arc} operation. +@end defop + +@defop operation x-graphics-device set-border-width width +@defopx operation x-graphics-device set-internal-border-width width +@findex graphics-clear +These operations change the external and internal border widths of a +window. @var{Width} must be an exact non-negative integer, specified in +pixels. The change takes place immediately. Note that changing the +internal border width can cause displayed graphics to be garbled; we +recommend calling @code{graphics-clear} on the window's device after +doing so. +@end defop + +@defop operation x-graphics-device set-font font-name +Changes the font used when drawing text in a window. @var{Font-name} +must be a string that is a font name known to the X server. This +operation does not affect text drawn prior to its invocation. +@end defop + +@defop operation x-graphics-device set-mouse-shape shape-number +Changes the shape of the mouse cursor. @var{Shape-number} is an exact +non-negative integer that is used as an index into the mouse-shape font; +when multiplied by 2 this number corresponds to an index in the file@* +@file{/usr/include/X11/cursorfont.h}. +@end defop + +@defop operation x-graphics-device map-window +@defopx operation x-graphics-device withdraw-window +These operations control the mapping of windows. They correspond +directly to Xlib's @code{XMapWindow} and @code{XWithdrawWindow}. +@end defop + +@defop operation x-graphics-device resize-window width height +Changes the size of a window. @var{Width} and @var{height} must be +exact non-negative integers. The operation corresponds directly to +Xlib's @code{XResizeWindow}. + +This operation resets the virtual coordinate system and the clip +rectangle. +@end defop + +@defop operation x-graphics-device move-window x y +Changes the position of a window on the display. @var{X} and @var{y} +must be exact integers. The operation corresponds directly to Xlib's +@code{XMoveWindow}. Note that the coordinates @var{x} and @var{y} do +not take the external border into account, and therefore will not +position the window as you might like. The only reliable way to +position a window is to ask a window manager to do it for you. +@end defop + +@defop operation x-graphics-device get-default resource property +This operation corresponds directly to Xlib's @code{XGetDefault}. +@var{Resource} and @var{property} must be strings. The operation +returns the character string corresponding to the association of +@var{resource} and @var{property}; if no such association exists, +@code{#f} is returned. +@end defop + +@defop operation x-graphics-device copy-area source-x-left source-y-top width height destination-x-left destination-y-top +This operation copies the contents of the rectangle specified by +@var{source-x-left}, @var{source-y-top}, @var{width}, and @var{height} to +the rectangle of the same dimensions at @var{destination-x-left} and +@var{destination-y-top}. +@end defop + +@defop operation x-graphics-device font-structure font-name +Returns a Scheme equivalent of the X font structure for the font named +@var{font-name}. If the string @var{font-name} does not name a font +known to the X server, or names a 16-bit font, @code{#f} is returned. +@end defop + +@deffn procedure x-font-structure/name font-structure +@deffnx procedure x-font-structure/direction font-structure +@deffnx procedure x-font-structure/all-chars-exist font-structure +@deffnx procedure x-font-structure/default-char font-structure +@deffnx procedure x-font-structure/min-bounds font-structure +@deffnx procedure x-font-structure/max-bounds font-structure +@deffnx procedure x-font-structure/start-index font-structure +@deffnx procedure x-font-structure/character-bounds font-structure +@deffnx procedure x-font-structure/max-ascent font-structure +@deffnx procedure x-font-structure/max-descent font-structure +These procedures extract the components of the font description +structure returned by the X graphics operation @code{font-structure}. A +more complete description of these components appears in documentation +of the @code{XLoadQueryFont} Xlib call. @code{start-index} is the index +of the first character available in the font. The @code{min-bounds} and +@code{max-bounds} components are structures of type +@code{x-character-bounds}, and the @code{character-bounds} component is +a vector of the same type. +@end deffn + +@deffn procedure x-character-bounds/lbearing character-bounds +@deffnx procedure x-character-bounds/rbearing character-bounds +@deffnx procedure x-character-bounds/width character-bounds +@deffnx procedure x-character-bounds/ascent character-bounds +@deffnx procedure x-character-bounds/descent character-bounds +These procedures extract components of objects of type +@code{x-character-bounds}. A more complete description of them appears +in documentation of the@* @code{XLoadQueryFont} Xlib call. +@end deffn + +@node Win32 Graphics, OS/2 Graphics, X Graphics, Graphics +@section Win32 Graphics +@cindex Win32 graphics + +MIT/GNU Scheme supports graphics on Microsoft Windows 95, Windows 98, and +Windows NT. In addition to the usual operations, there are operations +to control the size, position and colors of a graphics window. Win32 +devices support images, which are implemented as device independent +bitmaps (@sc{dib}s). + +The Win32 graphics device type is implemented as a top level window. +@code{graphics-enable-buffering} is implemented and gives a 2x to 4x +speedup on many graphics operations. As a convenience, when buffering +is enabled clicking on the graphics window's title bar effects a +@code{graphics-flush} operation. The user has the benefit of the +increased performance and the ability to view the progress in drawing at +the click of a mouse button. + + +@menu +* Win32 Graphics Type:: +* Custom Operations for Win32 Graphics:: Custom Operations for Win32 Graphics Devices +@end menu + +@node Win32 Graphics Type, Custom Operations for Win32 Graphics, Win32 Graphics, Win32 Graphics +@subsection Win32 Graphics Type + +Win32 graphics devices are created by specifying the symbol @code{win32} +as the @var{graphics-device-type} argument to +@code{make-graphics-device}. The Win32 graphics device type is +implemented as a top-level window and supports color drawing in addition +to the standard Scheme graphics operations. + +Graphics devices are opened as follows: + +@example +(make-graphics-device 'win32 #!optional @var{width} @var{height} @var{palette}) +@end example + +@noindent +where @var{width} and @var{height} specify the size, in pixels, of the +drawing area in the graphics window (i.e.@: excluding the frame). +@var{Palette} determines the colors available for drawing in the window. + +When a color is specified for drawing, the nearest color available in +the palette is used. Permitted values for @var{palette} are + +@table @asis +@item @code{'grayscale} +The window allocates colors from a grayscale palette +of approximately 236 shades of gray. + +@item @code{'grayscale-128} +The window allocates colors from a grayscale palette of 128 shades of +gray. + +@item @code{'standard} +The standard palette has good selection of colors and grays. + +@item @code{#f} or @code{'system} +The colors available are those in the system palette. There are usually +16 to 20 colors in the system palette and these are usually sufficent +for simple applications like line drawings and x-vs-y graphs of +mathematical functions. Drawing with the system palette can be more +efficient. + +@end table +@noindent +If @var{palette} is not specified then the @code{standard} palette is +used. + + + +@node Custom Operations for Win32 Graphics, , Win32 Graphics Type, Win32 Graphics +@subsection Custom Operations for Win32 Graphics + +Custom operations are invoked using the procedure +@code{graphics-operation}. For example, + +@example +(graphics-operation device 'set-foreground-color "blue") +@end example + +@defop operation win32-graphics-device set-background-color color-name +@defopx operation win32-graphics-device set-foreground-color color-name +@findex set-background-color +@findex set-foreground-color +@cindex color +These operations change the colors associated with a window. +@var{Color-name} must be of one of the valid color specification forms +listed below. @code{set-background-color} and +@code{set-foreground-color} change the colors to be used when drawing, +but have no effect on anything drawn prior to their invocation. Because +changing the background color affects the entire window, we recommend +calling @code{graphics-clear} on the window's device afterwards. + +The foreground color affects the drawing of text, points, lines, +ellipses and filled polygons. + +Colors are specified in one of three ways: + +@table @asis +@item An integer +This is the Win32 internal RGB value. + +@item By name +A limited number of names are understood by the system. +Names are strings, e.g.@: @code{"red"}, @code{"blue"}, @code{"black"}. +More names can be registered with the @code{define-color} operation. + +@item RGB (Red-Green-Blue) triples +A triple is either a vector or list of three integers in the range +0--255 inclusive which specify the intensity of the red, green and blue +components of the color. Thus @code{#(0 0 0)} is black, @code{(0 0 +128)} is dark blue and @code{#(255 255 255)} is white. +@end table + +@noindent +If the color is not available in the graphics device then the nearest +available color is used instead. +@end defop + + +@defop operation win32-graphics-device define-color name spec +Define the string @var{name} to be the color specified by @var{spec}. +@var{Spec} may be any acceptable color specification. Note that the +color names defined this way are available to any Win32 graphics device, +and the names do @emph{not} have to be defined for each device. + + +Color names defined by this interface may also be used when setting the +colors of the Scheme console window, or the colors of Edwin editor +windows. +@end defop + +@defop operation win32-graphics-device find-color name +Looks up a color previously defined by @code{define-color}. This returns +the color in its most efficient form for operations +@code{set-foreground-color} or @code{set-background-color}. +@end defop + + +@defop operation win32-graphics-device draw-ellipse left top right bottom +@cindex ellipse, graphics +@cindex circle, graphics +@cindex graphics, ellipse +@cindex graphics, circle +Draw an ellipse. @var{Left}, @var{top}, @var{right} and @var{bottom} +indicate the coordinates of the bounding rectangle of the ellipse. +Circles are merely ellipses with equal width and height. Note that the +bounding rectangle has horizontal and vertical sides. Ellipses with +rotated axes cannot be drawn. The rectangle applies to the center of the +line used to draw the ellipse; if the line width has been set to greater +than 1 then the ellipse will spill outside the bounding rectange by half +of the line width. +@end defop + + +@defop operation win32-graphics-device fill-polygon points +@findex fill-polygon +Draws a filled polygon using the current foreground color. +@var{Points} is a vector of real numbers. +The numbers are in the order x1 y1 x2 y2 @dots{} xn yn. +For example, + +@example +(graphics-operation device 'fill-polygon #(0 0 0 1 1 0)) +@end example + +@noindent +draws a solid triangular region between the points (0, 0), (0, 1) and +(1, 0). +@end defop + + +@defop operation win32-graphics-device load-bitmap pathname +@cindex bitmaps +The graphics device contents and size are initialized from the windows +bitmap file specified by @var{pathname}. If no file type is supplied +then a @code{".BMP"} extension is added. If a clip rectangle is in +effect when this procedure is called, it is necessary to redefine the +clip rectangle afterwards. +@end defop + +@defop operation win32-graphics-device save-bitmap pathname +@cindex printing graphics output +The graphics device contents are saved as a bitmap to the file specified +by @var{pathname}. If no file type is supplied then a @code{".BMP"} +extension is added. The saved bitmap may be incorporated into documents +or printed. +@end defop + +@defop operation win32-graphics-device move-window x y +The graphics device window is moved to the screen position specified by +@var{x} and @var{y}. +@end defop + +@defop operation win32-graphics-device resize-window width height +The graphics device window is resized to the specified @var{width} and +@var{height} in device coordinates (pixels). If a clip rectangle is in effect +when this procedure is called, it is necessary to redefine the clip +rectangle afterwards. +@end defop + +@defop operation win32-graphics-device set-line-width width +This operation sets the line width for future drawing of lines, points +and ellipses. It does not affect existing lines and has no effect on +filled polygons. The line width is specified in device units. The +default and initial value of this parameter is 1 pixel. +@end defop + +@defop operation win32-graphics-device set-window-name name +This sets the window title to the string @var{name}. The window is +given the name @code{"Scheme Graphics"} at creation. +@end defop + +@defop operation win32-graphics-device set-font handle +Sets the font for drawing text. Currently not well supported. If you +can get a Win32 font handle it can be used here. +@end defop + +@defop operation win32-graphics-device copy-area source-x-left source-y-top width height destination-x-left destination-y-top +This operation copies the contents of the rectangle specified by +@var{source-x-left}, @var{source-y-top}, @var{width}, and @var{height} +to the rectangle of the same dimensions at @var{destination-x-left} and +@var{destination-y-top}. +@end defop + +@node OS/2 Graphics, , Win32 Graphics, Graphics +@section OS/2 Graphics +@cindex OS/2 graphics + +MIT/GNU Scheme supports graphics under the OS/2 Presentation Manager in +OS/2 version 2.1 and later. The OS/2 graphics device type is +implemented as a top level window. In addition to the usual operations, +there are operations to control the size, position, and colors of a +graphics window. OS/2 graphics devices support images, which are +implemented as memory presentation spaces. + +The custom graphics operations defined in this section are invoked using +the procedure @code{graphics-operation}. For example, + +@example +(graphics-operation device 'set-foreground-color "blue") +@end example + +@menu +* OS/2 Graphics Type:: +* Color Operations for OS/2 Graphics:: +* Window Operations for OS/2 Graphics:: +* Event Operations for OS/2 Graphics:: +* Miscellaneous Operations for OS/2 Graphics:: +@end menu + +@node OS/2 Graphics Type, Color Operations for OS/2 Graphics, OS/2 Graphics, OS/2 Graphics +@subsection OS/2 Graphics Type + +OS/2 graphics devices are created by specifying the symbol +@code{os/2} as the @var{graphics-device-type} argument to +@code{make-graphics-device}. The OS/2 graphics device type is +implemented as a top-level window and supports color drawing in addition +to the standard Scheme graphics operations. + +Graphics devices are opened as follows: + +@example +(make-graphics-device 'os/2 #!optional @var{width} @var{height}) +@end example + +@noindent +where @var{width} and @var{height} specify the size, in pixels, of the +drawing area in the graphics window (i.e.@: excluding the frame). + +@node Color Operations for OS/2 Graphics, Window Operations for OS/2 Graphics, OS/2 Graphics Type, OS/2 Graphics +@subsection Color Operations for OS/2 Graphics + +These operations control the colors used when drawing on an OS/2 +graphics device. + +@defop operation os2-graphics-device color? +@findex color? +This operation returns @code{#t} if the display supports color. +@end defop + +@defop operation os2-graphics-device set-background-color color-name +@defopx operation os2-graphics-device set-foreground-color color-name +@findex set-background-color +@findex set-foreground-color +@cindex color +These operations change the colors associated with a window. +@var{Color-name} must be one of the valid color specification forms +listed below. @code{set-background-color} and +@code{set-foreground-color} change the colors to be used when drawing, +but have no effect on anything drawn prior to their invocation. Because +changing the background color affects the entire window, we recommend +calling @code{graphics-clear} on the window's device afterwards. + +The foreground color affects the drawing of text, points, and lines. +Colors are specified in one of these ways: + +@table @asis +@item An integer between @code{0} and @code{#xffffff} inclusive +This is the OS/2 internal RGB value. + +@item By name +A limited number of names are understood by the system. Names are +strings, e.g.@: @code{"red"}, @code{"blue"}, @code{"black"}. More names +can be registered with the @code{define-color} operation. + +@item RGB (Red-Green-Blue) triples +A triple is a list of three integers between @code{0} and @code{#xff} +inclusive which specify the intensity of the red, green and blue +components of the color. Thus @code{(0 0 0)} is black, @code{(0 0 128)} +is dark blue and @code{(255 255 255)} is white. +@end table + +@noindent +If the color is not available in the graphics device then the nearest +available color is used instead. +@end defop + +@defop operation os2-graphics-device define-color name spec +Define the string @var{name} to be the color specified by @var{spec}. +@var{Spec} may be any acceptable color specification. Note that the +color names defined this way are available to any OS/2 graphics +device, and the names do @emph{not} have to be defined for each device. + +Color names defined by this interface may also be used when setting the +colors of the Scheme console window, or the colors of Edwin editor +windows. +@end defop + +@defop operation os2-graphics-device find-color name +Looks up a color previously defined by @code{define-color}. This +returns the color in its most efficient form for operations +@code{set-foreground-color} or @code{set-background-color}. +@end defop + +@node Window Operations for OS/2 Graphics, Event Operations for OS/2 Graphics, Color Operations for OS/2 Graphics, OS/2 Graphics +@subsection Window Operations for OS/2 Graphics + +These operations control the window that contains the OS/2 graphics +device. They provide facilities to change the window's size and +position; to raise and lower the window relative to other windows on the +desktop; to hide or minimize the window, and to restore it from the +hidden or minimized state; to activate or deactivate the window (that +is, control the keyboard focus); and to control the text that appears in +the window's title bar. + +@defop operation os2-graphics-device window-position +This operation returns the position of the graphics-device window on the +desktop. The position is returned as two values +(@pxref{Continuations}), which are the x and y coordinates of the +position. These coordinates are in units of pels (pixels), and measure +the distance between the lower left hand corner of the desktop and the +lower left hand corner of the graphics device window's frame. +@end defop + +@defop operation os2-graphics-device set-window-position x y +The graphics-device window is moved to the screen position specified by +@var{x} and @var{y}. The coordinates @var{x} and @var{y} are in units +of pels (pixels), and measure the distance between the lower left hand +corner of the desktop and the lower left hand corner of the graphics +device window's frame. +@end defop + +@defop operation os2-graphics-device window-size +This operation returns the size of the client area of the +graphics-device window. The client area is the part of the window that +you draw on; it does not include the window frame, title bar, etc. The +size is returned as two values (@pxref{Continuations}), which are the +width and height of the client area in units of pels (pixels). +@end defop + +@defop operation os2-graphics-device set-window-size width height +This operation sets the size of the client area of the graphics-device +window to the specified @var{width} and @var{height}, which are in units +of pels (pixels). The client area is the part of the window that you +draw on; it does not include the window frame, title bar, etc. +@end defop + +@defop operation os2-graphics-device window-frame-size +This operation returns the size of the graphics-device window's frame. +This includes the client area, as well as the border, title bar, etc. +The size is returned as two values (@pxref{Continuations}), which are +the width and height of the frame in units of pels (pixels). + +The frame size is useful in conjunction with the window position and the +desktop size to determine relative placement of the window or to +guarantee that the entire window is visible on the desktop. +@end defop + +@defop operation os2-graphics-device desktop-size +This operation returns the size of the OS/2 desktop. The size is +returned as two values (@pxref{Continuations}), which are the width and +height of the frame in units of pels (pixels). +@end defop + +@defop operation os2-graphics-device raise-window +This operation raises the graphics-device window so that it is on top of +any other windows on the desktop. +@end defop + +@defop operation os2-graphics-device lower-window +This operation lowers the graphics-device window so that it is below all +other windows on the desktop. +@end defop + +@defop operation os2-graphics-device hide-window +This operation hides the graphics-device window. The window disappears +from the desktop, but still appears in the window list. +@end defop + +@defop operation os2-graphics-device minimize-window +This operation minimizes the graphics-device window. The window +disappears from the desktop, but still appears in the window list. +Depending on how you have configured your desktop, the window may appear +as an icon, either on the desktop or in the minimized window viewer. +@end defop + +@defop operation os2-graphics-device maximize-window +This operation maximizes the graphics-device window. This causes the +window to fill the entire desktop. +@end defop + +@defop operation os2-graphics-device restore-window +This operation restores the graphics-device window to its normal state. +If the window is hidden or minimized, it is shown again, at its former +position on the desktop. If the window is maximized, it is returned to +its normal size. +@end defop + +@defop operation os2-graphics-device activate-window +This operation makes the graphics-device window be the active window. +This causes the window to be put in front of all other windows on the +desktop, highlights its frame, and gives it the keyboard focus. +@end defop + +@defop operation os2-graphics-device deactivate-window +This operation deactivates the graphics-device window if it was active +(otherwise it has no effect). This causes some other window to be +chosen to be active in its place. +@end defop + +@defop operation os2-graphics-device set-window-title title +This operation changes the text that appears in the graphics device +window's title bar. The new text is given by @var{title}, which must be +a string. +@end defop + +@node Event Operations for OS/2 Graphics, Miscellaneous Operations for OS/2 Graphics, Window Operations for OS/2 Graphics, OS/2 Graphics +@subsection Event Operations for OS/2 Graphics + +These operations allow you to read some of the events that are generated +by the Presentation Manager and put in the message queue of a +graphics-device window. + +@defop operation os2-graphics-device read-button +This operation waits for the user to push a mouse button inside the +client area of the graphics-device window. It then returns four values +(@pxref{Continuations}) which are: the button number; the x and y +coordinates of the mouse pointer at the time the button was pressed, in +pels (pixels) relative to the lower left hand corner of the client area; +and the graphics device that the mouse pointer was over at the time the +button was pressed. + +Note that this operation only works when button events are selected +(which is the default). +@end defop + +@defop operation os2-graphics-device select-user-events mask +This operation sets the event-selection mask for the graphics device to +@var{mask}. The event-selection mask is an exact non-negative integer +that specifies which types of incoming events are to be saved in the +user-event queue for later retrieval by the @code{read-user-event} +operation. The mask is specified by setting the bits corresponding to +the event types that you are interested in, as follows: + +@example +@group +Number Mask Description +------ ----- ----------- +0 #x001 Button press/release +1 #x002 Close (close the window) [WM_CLOSE] +2 #x004 Focus change [WM_SETFOCUS] +3 #x008 Key press/release [WM_CHAR] +4 #x010 Paint [WM_PAINT] +5 #x020 Size change [WM_SIZE] +6 #x040 Visibility change [WM_SHOW] +7 #x080 Command [WM_COMMAND] +8 #x100 Help [WM_HELP] +9 #x200 Mouse-move [WM_MOUSEMOVE] +@end group +@end example + +@noindent +Note that this operation does not affect any events that are already in +the user-event queue. Changing the mask only affects what events will +be added to the queue in the future. +@end defop + +@defop operation os2-graphics-device read-user-event +This operation returns the next user event available from the user-event +queue. If there are no events in the queue, the operation waits for an +event to arrive before returning. +@end defop + +An event is a vector whose first element is the event-type number, whose +second element is the graphics device that the event refers to, and +whose remaining elements provide information about the event. Here is a +table of the possible event types and their vector layout: + +@table @code +@item #(0 @var{device} @var{number} @var{type} @var{x} @var{y} @var{flags}) +A button event. @var{Number} is the button number, for example button +number @code{0} is usually the left mouse button, @code{1} is usually +the right button, etc. @var{Type} specifies what occurred: @code{0} +means the button was pressed, @code{1} means the button was released, +@code{2} means the button was clicked, and @code{3} means the button was +double clicked. @var{X} and @var{y} are the position of the mouse +pointer at the time of the event, in units of pels (pixels) measured +from the lower left corner of the client area of the associated window. +Finally, @var{flags} specifies what shift keys were pressed at the time +of the button event; it is a mask word created by combining zero or more +of the following flags: @code{#x08} means the shift key was pressed, +@code{#x10} means the control key was pressed, and @code{#x20} means the +alt key was pressed. + +@item #(1 @var{device}) +A close event. The user has selected the close button from the system +menu, or typed @key{Alt-f4}. + +@item #(2 @var{device} @var{gained?}) +A focus event. If @var{gained?} is @code{#t}, the keyboard focus is +being gained, and if @var{gained?} is @code{#f}, it is being lost. + +@item #(3 @var{device} @var{code} @var{flags} @var{repeat}) +A keyboard event. This is much too complicated to describe here. See +the OS/2 toolkit documentation for details. + +@item #(4 @var{device} @var{xl} @var{xh} @var{yl} @var{yh}) +A paint event. Part of the graphics-device window that was obscured has +been revealed and the Presentation Manager is informing the window that +it must repaint that area. Scheme will take care of the painting for +you, so this event isn't very useful. + +@item #(5 @var{device} @var{width} @var{height}) +A size-change event. The size of the graphics-device window has +changed, and @var{width} and @var{height} specify the new size in pels +(pixels). + +@item #(6 @var{device} @var{shown?}) +A visibility event. Indicates that the graphics-device window has been +hidden or revealed. If @var{shown?} is @code{#f}, the window is hidden, +and if it is @code{#t}, the window is shown. + +@item #(7 @var{device} @var{source} @var{mouse?}) +@itemx #(8 @var{device} @var{source} @var{mouse?}) +A menu command. @var{Source} specifies which menu item was selected to +cause this event, and @var{mouse?} is a boolean indicating whether the +item was selected with the mouse or the keyboard. The event-type number +@code{7} indicates a command from a @samp{WM_COMMAND} message, while +@code{8} is a command from a @samp{WM_HELP} message. + +@item #(9 @var{device} @var{x} @var{y} @var{hit-test} @var{flags}) +The mouse was moved. @var{X} and @var{y} specify the position of the +mouse, @var{hit-test} contains the hit-test information, and @var{flags} +specifies the modifier keys that were pressed at the time. +@end table + +@defop operation os2-graphics-device discard-events +This operation discards any events that are in the user-event queue. +This is sometimes useful when you want to prompt the user for some input +and don't want to consider any previous input. +@end defop + +@node Miscellaneous Operations for OS/2 Graphics, , Event Operations for OS/2 Graphics, OS/2 Graphics +@subsection Miscellaneous Operations for OS/2 Graphics + +These operations allow you to: change the font used for drawing text in +a graphics-device window; take a snapshot of a graphics-device window +and return it as an image object; and draw multiple lines efficiently. + +@defop operation os2-graphics-device set-font font-name +This operation sets the font used for drawing text in the +graphics-device window. @var{Font-name} is a string describing the +font; this string is in the form ".", for +example, @code{"10.Courier"}. You may specify any fixed-pitch font +family, in any point size that is supported for that font family. This +includes both image fonts and outline fonts. +@end defop + +@defop operation os2-graphics-device capture-image x-left y-bottom x-right y-top +This operation creates and returns an image that contains part of the +client area of the graphics-device window. The portion of the client +area that is selected is specified by the four coordinate arguments, +which are given in the current virtual coordinates for the device. +@xref{Images}, for more information about manipulating images. +@end defop + +@defop operation os2-graphics-device draw-lines xv yv +This operation draws multiple disjoint lines; it is like multiple calls +to @code{graphics-draw-line} but much faster. The arguments @var{xv} +and @var{yv} are vectors of coordinates; these vectors must be the same +length, and the length must be a multiple of two. The contents of the +vectors are alternating start/end pairs. For example, the following are +equivalent: + +@example +@group +(graphics-draw-line device xs ys xe ye) +(graphics-operation device 'draw-lines + (vector xs xe) + (vector ys ye)) +@end group +@end example +@end defop diff --git a/v7/doc/ref-manual/io.texi b/v7/doc/ref-manual/io.texi new file mode 100644 index 000000000..45f6e8d27 --- /dev/null +++ b/v7/doc/ref-manual/io.texi @@ -0,0 +1,3179 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: io.texi,v 1.1 2003/04/15 03:29:46 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Input/Output, Operating-System Interface, Environments, Top +@chapter Input/Output + +@cindex input +@cindex output +@cindex port +This chapter describes the procedures that are used for input and +output (@acronym{I/O}). The chapter first describes @dfn{ports} and +how they are manipulated, then describes the @acronym{I/O} operations. +Finally, some low-level procedures are described that permit the +implementation of custom ports and high-performance @acronym{I/O}. + +@menu +* Ports:: +* File Ports:: +* String Ports:: +* Input Procedures:: +* Output Procedures:: +* Format:: +* Custom Output:: +* Prompting:: +* Port Primitives:: +* Parser Buffers:: +* Parser Language:: +* XML Parser:: +@end menu + +@node Ports, File Ports, Input/Output, Input/Output +@section Ports + +@cindex port (defn) +@findex console-i/o-port +Scheme uses ports for @acronym{I/O}. A @dfn{port}, which can be +treated like any other Scheme object, serves as a source or sink for +data. A port must be open before it can be read from or written to. +The standard @acronym{I/O} port, @code{console-i/o-port}, is opened +automatically when you start Scheme. When you use a file for input or +output, you need to explicitly open and close a port to the file (with +procedures described in this chapter). Additional procedures let you +open ports to strings. + +@cindex current input port (defn) +@cindex input port, current (defn) +@cindex port, current +@findex read-char +@findex read +Many input procedures, such as @code{read-char} and @code{read}, read +data from the current input port by default, or from a port that you +specify. The current input port is initially @code{console-i/o-port}, +but Scheme provides procedures that let you change the current input +port to be a file or string. + +@cindex current output port (defn) +@cindex output port, current (defn) +@findex write-char +@findex display +Similarly, many output procedures, such as @code{write-char} and +@code{display}, write data to the current output port by default, or to +a port that you specify. The current output port is initially +@code{console-i/o-port}, but Scheme provides procedures that let you +change the current output port to be a file or string. + +All ports read or write only @acronym{ISO-8859-1} characters. + +Every port is either an input port, an output port, or both. The +following predicates distinguish all of the possible cases. + +@deffn procedure port? object +@cindex type predicate, for port +Returns @code{#t} if @var{object} is a port, otherwise returns +@code{#f}. +@end deffn + +@deffn procedure input-port? object +Returns @code{#t} if @var{object} is an input port, otherwise returns +@code{#f}. Any object satisfying this predicate also satisfies +@code{port?}. +@end deffn + +@deffn procedure output-port? object +Returns @code{#t} if @var{object} is an output port, otherwise returns +@code{#f}. Any object satisfying this predicate also satisfies +@code{port?}. +@end deffn + +@deffn procedure i/o-port? object +Returns @code{#t} if @var{object} is both an input port and an output +port, otherwise returns @code{#f}. Any object satisfying this predicate +also satisfies @code{port?}, @code{input-port?}, and +@code{output-port?}. +@end deffn + +@deffn procedure guarantee-port object +@deffnx procedure guarantee-input-port object +@deffnx procedure guarantee-output-port object +@deffnx procedure guarantee-i/o-port object +These procedures check the type of @var{object}, signalling an error +of type@* @code{condition-type:wrong-type-argument} if it is not a +port, input port, output port, or @acronym{I/O} port, respectively. +Otherwise they return @var{object}. +@findex condition-type:wrong-type-argument +@end deffn + +@cindex standard ports +The next five procedures return the runtime system's @dfn{standard +ports}. All of the standard ports are dynamically bound by the +@acronym{REP} loop; this means that when a new @acronym{REP} loop is +started, for example by an error, each of these ports is dynamically +bound to the @acronym{I/O} port of the @acronym{REP} loop. When the +@acronym{REP} loop exits, the ports revert to their original values. + +@deffn procedure current-input-port +@findex console-input-port +Returns the current input port. This is the default port used by many +input procedures. Initially, @code{current-input-port} returns the +value of @code{console-i/o-port}. +@end deffn + +@deffn procedure current-output-port +@findex console-output-port +Returns the current output port. This is the default port used by many +output procedures. Initially, @code{current-output-port} returns the +value of @code{console-i/o-port}. +@end deffn + +@deffn procedure notification-output-port +Returns an output port suitable for generating ``notifications'', that +is, messages to the user that supply interesting information about the +execution of a program. For example, the @code{load} procedure writes +messages to this port informing the user that a file is being loaded. +Initially, @code{notification-output-port} returns the value of +@code{console-i/o-port}. +@end deffn + +@deffn procedure trace-output-port +Returns an output port suitable for generating ``tracing'' information +about a program's execution. The output generated by the @code{trace} +procedure is sent to this port. Initially, @code{trace-output-port} +returns the value of @code{console-i/o-port}. +@end deffn + +@deffn procedure interaction-i/o-port +Returns an @acronym{I/O} port suitable for querying or prompting the +user. The standard prompting procedures use this port by default +(@pxref{Prompting}). Initially, @code{interaction-i/o-port} returns +the value of @code{console-i/o-port}. +@end deffn + +@deffn procedure with-input-from-port input-port thunk +@deffnx procedure with-output-to-port output-port thunk +@deffnx procedure with-notification-output-port output-port thunk +@deffnx procedure with-trace-output-port output-port thunk +@deffnx procedure with-interaction-i/o-port i/o-port thunk +@var{Thunk} must be a procedure of no arguments. Each of these +procedures binds one of the standard ports to its first argument, calls +@var{thunk} with no arguments, restores the port to its original value, +and returns the result that was yielded by @var{thunk}. This temporary +binding is performed the same way as dynamic binding of a variable, +including the behavior in the presence of continuations (@pxref{Dynamic +Binding}). + +@code{with-input-from-port} binds the current input port, +@code{with-output-to-port} binds the current output port, +@code{with-notification-output-port} binds the ``notification'' output +port, @code{with-trace-output-port} binds the ``trace'' output port, +and @code{with-interaction-i/o-port} binds the ``interaction'' +@acronym{I/O} port. +@end deffn + +@deffn procedure set-current-input-port! input-port +@deffnx procedure set-current-output-port! output-port +@deffnx procedure set-notification-output-port! output-port +@deffnx procedure set-trace-output-port! output-port +@deffnx procedure set-interaction-i/o-port! i/o-port +Each of these procedures alters the binding of one of the standard ports +and returns an unspecified value. The binding that is modified +corresponds to the name of the procedure. +@end deffn + +@defvr variable console-i/o-port +@cindex port, console +@cindex console, port +@cindex input port, console +@cindex output port, console +@code{console-i/o-port} is an @acronym{I/O} port that communicates +with the ``console''. Under unix, the console is the controlling +terminal of the Scheme process. Under Windows and OS/2, the console +is the window that is created when Scheme starts up. + +This variable is rarely used; instead programs should use one of the +standard ports defined above. This variable should not be modified. +@end defvr + +@deffn procedure close-port port +@cindex closing, of port +Closes @var{port} and returns an unspecified value. If @var{port} is a +file port, the file is closed. +@end deffn + +@deffn procedure close-input-port port +Closes @var{port} and returns an unspecified value. @var{Port} must +be an input port or an @acronym{I/O} port; if it is an @acronym{I/O} +port, then only the input side of the port is closed. +@end deffn + +@deffn procedure close-output-port port +Closes @var{port} and returns an unspecified value. @var{Port} must +be an output port or an @acronym{I/O} port; if it is an @acronym{I/O} +port, then only the output side of the port is closed. +@end deffn + +@node File Ports, String Ports, Ports, Input/Output +@section File Ports + +@cindex file, input and output ports +@cindex port, file +@cindex input port, file +@cindex output port, file +@cindex I/O, to files +Before Scheme can access a file for reading or writing, it is necessary +to open a port to the file. This section describes procedures used to +open ports to files. Such ports are closed (like any other port) by +@code{close-port}. File ports are automatically closed if and when they +are reclaimed by the garbage collector. + +@findex merge-pathnames +Before opening a file for input or output, by whatever method, the +@var{filename} argument is converted to canonical form by calling the +procedure @code{merge-pathnames} with @var{filename} as its sole +argument. Thus, @var{filename} can be either a string or a pathname, +and it is merged with the current pathname defaults to produce the +pathname that is then opened. + +@cindex binary file ports +@cindex newline translation +Any file can be opened in one of two modes, @dfn{normal} or +@dfn{binary}. Normal mode is for accessing text files, and binary mode +is for accessing other files. Unix does not distinguish these modes, +but Windows and OS/2 do: in normal mode, their file ports perform +@dfn{newline translation}, mapping between the carriage-return/linefeed +sequence that terminates text lines in files, and the @code{#\newline} +that terminates lines in Scheme. In binary mode, such ports do not +perform newline translation. Unless otherwise mentioned, the procedures +in this section open files in normal mode. + +@deffn procedure open-input-file filename +@cindex construction, of file input port +Takes a filename referring to an existing file and returns an input port +capable of delivering characters from the file. If the file cannot be +opened, an error of type @code{condition-type:file-operation-error} is +signalled. +@findex condition-type:file-operation-error +@end deffn + +@deffn procedure open-output-file filename [append?] +@cindex construction, of file output port +Takes a filename referring to an output file to be created and returns +an output port capable of writing characters to a new file by that name. +If the file cannot be opened, an error of type +@code{condition-type:file-operation-error} is signalled. +@findex condition-type:file-operation-error + +@cindex appending, to output file +The optional argument @var{append?} is an MIT/GNU Scheme extension. If +@var{append?} is given and not @code{#f}, the file is opened in +@dfn{append} mode. In this mode, the contents of the file are not +overwritten; instead any characters written to the file are appended to +the end of the existing contents. If the file does not exist, append +mode creates the file and writes to it in the normal way. +@end deffn + +@deffn procedure open-i/o-file filename +@cindex construction, of file input port +Takes a filename referring to an existing file and returns an +@acronym{I/O} port capable of both reading and writing the file. If +the file cannot be opened, an error of type +@code{condition-type:file-operation-error} is signalled. +@findex condition-type:file-operation-error + +This procedure is often used to open special files. For example, under +unix this procedure can be used to open terminal device files, @sc{pty} +device files, and named pipes. +@end deffn + +@deffn procedure open-binary-input-file filename +@deffnx procedure open-binary-output-file filename [append?] +@deffnx procedure open-binary-i/o-file filename +These procedures open files in binary mode. In all other respects they +are identical to @code{open-input-file}, @code{open-output-file}, and +@code{open-i/o-file}, respectively. +@end deffn + +@deffn procedure close-all-open-files +@cindex closing, of file port +This procedure closes all file ports that are open at the time that it +is called, and returns an unspecified value. +@end deffn + +@deffn procedure call-with-input-file filename procedure +@deffnx procedure call-with-output-file filename procedure +These procedures call @var{procedure} with one argument: the port +obtained by opening the named file for input or output, respectively. +If the file cannot be opened, an error of type +@code{condition-type:file-operation-error} is signalled. If +@var{procedure} returns, then the port is closed automatically and the +value yielded by @var{procedure} is returned. If @var{procedure} does +not return, then the port will not be closed automatically unless it is +reclaimed by the garbage collector.@footnote{Because Scheme's escape +procedures have unlimited extent, it is possible to escape from the +current continuation but later to escape back in. If implementations +were permitted to close the port on any escape from the current +continuation, then it would be impossible to write portable code using +both @code{call-with-current-continuation} and +@code{call-with-input-file} or @code{call-with-output-file}.} +@end deffn + +@deffn procedure call-with-binary-input-file filename procedure +@deffnx procedure call-with-binary-output-file filename procedure +These procedures open files in binary mode. In all other respects they +are identical to @code{call-with-input-file} and +@code{call-with-output-file}, respectively. +@end deffn + +@deffn procedure with-input-from-file filename thunk +@deffnx procedure with-output-to-file filename thunk +@cindex current input port, rebinding +@cindex current output port, rebinding +@findex current-input-port +@findex current-output-port +@var{Thunk} must be a procedure of no arguments. +The file is opened for input or output, an input or output port +connected to it is made the default value returned by +@code{current-input-port} or @code{current-output-port}, and the +@var{thunk} is called with no arguments. When the @var{thunk} returns, +the port is closed and the previous default is restored. +@code{with-input-from-file} and @code{with-output-to-file} return the +value yielded by @var{thunk}. If an escape procedure is used to escape +from the continuation of these procedures, their behavior is +implementation-dependent; in that situation MIT/GNU Scheme leaves the files +open. +@end deffn + +@deffn procedure with-input-from-binary-file filename thunk +@deffnx procedure with-output-to-binary-file filename thunk +These procedures open files in binary mode. In all other respects they +are identical to @code{with-input-from-file} and +@code{with-output-to-file}, respectively. +@end deffn + +@node String Ports, Input Procedures, File Ports, Input/Output +@section String Ports + +@cindex string, input and output ports +@cindex port, string +@cindex input port, string +@cindex output port, string +@cindex I/O, to strings +This section describes the simplest kinds of ports: input ports that +read their input from given strings, and output ports that accumulate +their output and return it as a string. It also describes +``truncating'' output ports, which can limit the length of the resulting +string to a given value. + +@deffn procedure string->input-port string [start [end]] +@cindex string, converting to input port +@cindex construction, of string input port +Returns a new string port that delivers characters from @var{string}. +The optional arguments @var{start} and @var{end} may be used to specify +that the string port delivers characters from a substring of +@var{string}; if not given, @var{start} defaults to @code{0} and +@var{end} defaults to @code{(string-length @var{string})}. +@end deffn + +@deffn procedure with-input-from-string string thunk +@cindex current input port, rebinding +@var{Thunk} must be a procedure of no arguments. +@code{with-input-from-string} creates a new input port that reads from +@var{string}, makes that port the current input port, and calls +@var{thunk}. When @var{thunk} returns, @code{with-input-from-string} +restores the previous current input port and returns the result yielded +by @var{thunk}. + +@example +(with-input-from-string "(a b c) (d e f)" read) @result{} (a b c) +@end example + +Note: this procedure is equivalent to: + +@example +(with-input-from-port (string->input-port @var{string}) @var{thunk}) +@end example +@end deffn + +@deffn procedure with-string-output-port procedure +@var{Procedure} is called with one argument, an output port. The value +yielded by @var{procedure} is ignored. When @var{procedure} returns, +@code{with-string-output-port} returns the port's accumulated output as +a newly allocated string. +@end deffn + +@deffn procedure with-output-to-string thunk +@cindex current output port, rebinding +@cindex construction, of string output port +@findex current-output-port +@var{Thunk} must be a procedure of no arguments. +@code{with-output-to-string} creates a new output port that accumulates +output, makes that port the default value returned by +@code{current-output-port}, and calls @var{thunk} with no arguments. +When @var{thunk} returns, @code{with-output-to-string} restores the +previous default and returns the accumulated output as a newly allocated +string. + +@example +@group +(with-output-to-string + (lambda () + (write 'abc))) @result{} "abc" +@end group +@end example + +Note: this procedure is equivalent to: + +@example +@group +(with-string-output-port + (lambda (port) + (with-output-to-port port @var{thunk}))) +@end group +@end example +@end deffn + +@deffn procedure with-output-to-truncated-string k thunk +Similar to @code{with-output-to-string}, except that the output is +limited to @var{k} characters. If @var{thunk} attempts to write more +than @var{k} characters, it will be aborted by invoking an escape +procedure that returns from @code{with-output-to-truncated-string}. + +The value of this procedure is a pair; the car of the pair is @code{#t} +if @var{thunk} attempted to write more than @var{k} characters, and +@code{#f} otherwise. The cdr of the pair is a newly allocated string +containing the accumulated output. + +This procedure is helpful for displaying circular lists, as shown in this +example: + +@example +@group +(define inf (list 'inf)) +(with-output-to-truncated-string 40 + (lambda () + (write inf))) @result{} (#f . "(inf)") +(set-cdr! inf inf) +(with-output-to-truncated-string 40 + (lambda () + (write inf))) + @result{} (#t . "(inf inf inf inf inf inf inf inf inf inf") +@end group +@end example +@end deffn + +@deffn procedure write-to-string object [k] +Writes @var{object} to a string output port, and returns the resulting +newly allocated string. If @var{k} is supplied and not @code{#f}, this +procedure is equivalent to + +@example +@group +(with-output-to-truncated-string @var{k} + (lambda () + (write @var{object}))) +@end group +@end example + +otherwise it is equivalent to + +@example +@group +(with-output-to-string + (lambda () + (write @var{object}))) +@end group +@end example +@end deffn + +@node Input Procedures, Output Procedures, String Ports, Input/Output +@section Input Procedures +@cindex input operations + +This section describes the procedures that read input. Input procedures +can read either from the current input port or from a given port. +Remember that to read from a file, you must first open a port to the +file. + +@cindex interactive input ports (defn) +Input ports can be divided into two types, called @dfn{interactive} and +@dfn{non-interactive}. Interactive input ports are ports that read +input from a source that is time-dependent; for example, a port that +reads input from a terminal or from another program. Non-interactive +input ports read input from a time-independent source, such as an +ordinary file or a character string. + +All optional arguments called @var{input-port}, if not supplied, default +to the current input port. + +@deffn procedure read-char [input-port] +@cindex character, input from port +Returns the next character available from @var{input-port}, updating +@var{input-port} to point to the following character. If no more +characters are available, an end-of-file object is returned. + +In MIT/GNU Scheme, if @var{input-port} is an interactive input port and no +characters are immediately available, @code{read-char} will hang waiting +for input, even if the port is in non-blocking mode. +@end deffn + +@deffn procedure peek-char [input-port] +Returns the next character available from @var{input-port}, +@emph{without} updating @var{input-port} to point to the following +character. If no more characters are available, an end-of-file object +is returned.@footnote{The value returned by a call to @code{peek-char} +is the same as the value that would have been returned by a call to +@code{read-char} on the same port. The only difference is that the very +next call to @code{read-char} or @code{peek-char} on that +@var{input-port} will return the value returned by the preceding call to +@code{peek-char}. In particular, a call to @code{peek-char} on an +interactive port will hang waiting for input whenever a call to +@code{read-char} would have hung.} + +In MIT/GNU Scheme, if @var{input-port} is an interactive input port and no +characters are immediately available, @code{peek-char} will hang waiting +for input, even if the port is in non-blocking mode. +@end deffn + +@deffn procedure char-ready? [input-port] +@findex read-char +Returns @code{#t} if a character is ready on @var{input-port} and +returns @code{#f} otherwise. If @code{char-ready?} returns @code{#t} +then the next @code{read-char} operation on @var{input-port} is +guaranteed not to hang. If @var{input-port} is a file port at end of +file then @code{char-ready?} returns +@code{#t}.@footnote{@code{char-ready?} exists to make it possible for a +program to accept characters from interactive ports without getting +stuck waiting for input. Any input editors associated with such ports +must make sure that characters whose existence has been asserted by +@code{char-ready?} cannot be rubbed out. If @code{char-ready?} were to +return @code{#f} at end of file, a port at end of file would be +indistinguishable from an interactive port that has no ready +characters.} +@end deffn + +@deffn procedure read [input-port] +@cindex expression, input from port +@cindex external representation, parsing +@cindex parsing, of external representation +Converts external representations of Scheme objects into the objects +themselves. @code{read} returns the next object parsable from +@var{input-port}, updating @var{input-port} to point to the first +character past the end of the written representation of the object. If +an end of file is encountered in the input before any characters are +found that can begin an object, @code{read} returns an end-of-file +object. The @var{input-port} remains open, and further attempts to read +will also return an end-of-file object. If an end of file is +encountered after the beginning of an object's written representation, +but the written representation is incomplete and therefore not parsable, +an error is signalled. +@end deffn + +@deffn procedure eof-object? object +@cindex type predicate, for EOF object +@cindex EOF object, predicate for +@cindex end of file object (see EOF object) +@cindex file, end-of-file marker (see EOF object) +Returns @code{#t} if @var{object} is an end-of-file object; otherwise +returns @code{#f}. +@end deffn + +@deffn procedure read-char-no-hang [input-port] +If @var{input-port} can deliver a character without blocking, this +procedure acts exactly like @code{read-char}, immediately returning that +character. Otherwise, @code{#f} is returned, unless @var{input-port} is +a file port at end of file, in which case an end-of-file object is +returned. In no case will this procedure block waiting for input. +@end deffn + +@deffn procedure read-string char-set [input-port] +@cindex string, input from port +Reads characters from @var{input-port} until it finds a terminating +character that is a member of @var{char-set} (@pxref{Character Sets}) or +encounters end of file. The port is updated to point to the terminating +character, or to end of file if no terminating character was found. +@code{read-string} returns the characters, up to but excluding the +terminating character, as a newly allocated string. + +This procedure ignores the blocking mode of the port, blocking +unconditionally until it sees either a delimiter or eof of file. If end +of file is encountered before any characters are read, an end-of-file +object is returned. + +@findex read-char +On many input ports, this operation is significantly faster than the +following equivalent code using @code{peek-char} and @code{read-char}: + +@example +@group +(define (read-string char-set input-port) + (let ((char (peek-char input-port))) + (if (eof-object? char) + char + (list->string + (let loop ((char char)) + (if (or (eof-object? char) + (char-set-member? char-set char)) + '() + (begin + (read-char input-port) + (cons char + (loop (peek-char input-port)))))))))) +@end group +@end example +@end deffn + +@deffn procedure read-line [input-port] +@code{read-line} reads a single line of text from @var{input-port}, and +returns that line as a newly allocated string. The @code{#\newline} +terminating the line, if any, is discarded and does not appear in the +returned string. + +This procedure ignores the blocking mode of the port, blocking +unconditionally until it has read an entire line. If end of file is +encountered before any characters are read, an end-of-file object is +returned. +@end deffn + +@deffn procedure read-string! string [input-port] +@deffnx procedure read-substring! string start end [input-port] +@code{read-string!} and @code{read-substring!} fill the specified region +of @var{string} with characters read from @var{input-port} until the +region is full or else there are no more characters available from the +port. For @code{read-string!}, the region is all of @var{string}, and +for @code{read-substring!}, the region is that part of @var{string} +specified by @var{start} and @var{end}. + +The returned value is the number of characters filled into the region. +However, there are several interesting cases to consider: + +@itemize @bullet +@item +If @code{read-string!} (@code{read-substring!}) is called when +@var{input-port} is at ``end-of-file'', then the returned value is +@code{0}. Note that ``end-of-file'' can mean a file port that is at the +file's end, a string port that is at the string's end, or any other port +that will never produce more characters. + +@item +If @var{input-port} is an interactive port (e.g.@: a terminal), and one +or more characters are immediately available, the region is filled using +the available characters. The procedure then returns immediately, +without waiting for further characters, even if the number of available +characters is less than the size of the region. The returned value is +the number of characters actually filled in. + +@item +If @var{input-port} is an interactive port and no characters are +immediately available, the result of the operation depends on the +blocking mode of the port. If the port is in non-blocking mode, +@code{read-string!} (@code{read-substring!}) immediately returns the +value @code{#f}. Otherwise, the operation blocks until a character is +available. As soon as at least one character is available, the region +is filled using the available characters. The procedure then returns +immediately, without waiting for further characters, even if the number +of available characters is less than the size of the region. The +returned value is the number of characters actually filled in. +@end itemize + +The importance of @code{read-string!} and @code{read-substring!} are +that they are both flexible and extremely fast, especially for large +amounts of data. +@end deffn + +The following variables may be dynamically bound to change the behavior +of the @code{read} procedure. + +@defvr variable *parser-radix* +This variable defines the radix used by the reader when it parses +numbers. This is similar to passing a radix argument to +@code{string->number}. The value of this variable must be one of +@code{2}, @code{8}, @code{10}, or @code{16}; any other value is ignored, +and the reader uses radix @code{10}. + +Note that much of the number syntax is invalid for radixes other than +@code{10}. The reader detects cases where such invalid syntax is used +and signals an error. However, problems can still occur when +@code{*parser-radix*} is set to @code{16}, because syntax that normally +denotes symbols can now denote numbers (e.g.@: @code{abc}). Because of +this, it is usually undesirable to set this variable to anything other +than the default. + +The default value of this variable is @code{10}. +@end defvr + +@defvr variable *parser-canonicalize-symbols?* +This variable controls how the parser handles case-sensitivity of +symbols. If it is bound to its default value of @code{#t}, symbols read +by the parser are converted to lower case before being interned. +Otherwise, symbols are interned without case conversion. + +In general, it is a bad idea to use this feature, as it doesn't really +make Scheme case-sensitive, and therefore can break features of the +Scheme runtime that depend on case-insensitive symbols. +@end defvr + +@node Output Procedures, Format, Input Procedures, Input/Output +@section Output Procedures +@cindex output procedures + +@cindex buffering, of output +@cindex flushing, of buffered output +Output ports may or may not support @dfn{buffering} of output, in which +output characters are collected together in a buffer and then sent to +the output device all at once. (Most of the output ports implemented by +the runtime system support buffering.) Sending all of the characters in +the buffer to the output device is called @dfn{flushing} the buffer. In +general, output procedures do not flush the buffer of an output port +unless the buffer is full. + +@cindex discretionary flushing, of buffered output +@findex discretionary-flush-output +However, the standard output procedures described in this section +perform what is called @dfn{discretionary} flushing of the buffer. +Discretionary output flushing works as follows. After a procedure +performs its output (writing characters to the output buffer), it checks +to see if the port implements an operation called +@code{discretionary-flush-output}. If so, then that operation is +invoked to flush the buffer. At present, only the console port defines +@code{discretionary-flush-output}; this is used to guarantee that output +to the console appears immediately after it is written, without +requiring calls to @code{flush-output}. + +All optional arguments called @var{output-port}, if not supplied, +default to the current output port. + +@deffn procedure write-char char [output-port] +@cindex character, output to port +Writes @var{char} (the character itself, not a written representation of +the character) to @var{output-port}, performs discretionary output +flushing, and returns an unspecified value. +@end deffn + +@deffn procedure write-string string [output-port] +@cindex string, output to port +Writes @var{string} to @var{output-port}, performs discretionary output +flushing, and returns an unspecified value. This is equivalent to +writing the contents of @var{string}, one character at a time using +@code{write-char}, except that it is usually much faster. +@end deffn + +@deffn procedure write-substring string start end [output-port] +@cindex string, output to port +Writes the substring defined by @var{string}, @var{start}, and @var{end} +to @var{output-port}, performs discretionary output flushing, and +returns an unspecified value. This is equivalent to writing the +contents of the substring, one character at a time using +@code{write-char}, except that it is usually much faster. +@end deffn + +@deffn procedure write object [output-port] +@cindex expression, output to port +Writes a written representation of @var{object} to @var{output-port}, +and returns an unspecified value. If @var{object} has a standard +external representation, then the written representation generated by +@code{write} shall be parsable by @code{read} into an equivalent object. +Thus strings that appear in the written representation are enclosed in +doublequotes, and within those strings backslash and doublequote are +escaped by backslashes. @code{write} performs discretionary output +flushing and returns an unspecified value. +@end deffn + +@deffn procedure display object [output-port] +@cindex external representation, generating +@cindex generating, external representation +Writes a representation of @var{object} to @var{output-port}. Strings +appear in the written representation as if written by +@code{write-string} instead of by @code{write}. Character objects +appear in the representation as if written by @code{write-char} instead +of by @code{write}. @code{display} performs discretionary output +flushing and returns an unspecified value.@footnote{@code{write} is +intended for producing machine-readable output and @code{display} is for +producing human-readable output.} +@end deffn + +@deffn procedure newline [output-port] +@cindex newline character, output to port +Writes an end-of-line to @var{output-port}, performs discretionary +output flushing, and returns an unspecified value. Equivalent to +@code{(write-char #\newline @var{output-port})}. +@end deffn + +@deffn procedure fresh-line [output-port] +Most output ports are able to tell whether or not they are at the +beginning of a line of output. If @var{output-port} is such a port, +this procedure writes an end-of-line to the port only if the port is not +already at the beginning of a line. If @var{output-port} is not such a +port, this procedure is identical to @code{newline}. In either case, +@code{fresh-line} performs discretionary output flushing and returns an +unspecified value. +@end deffn + +@deffn procedure write-line object [output-port] +Like @code{write}, except that it writes an end-of-line to +@var{output-port} after writing @var{object}'s representation. This +procedure performs discretionary output flushing and returns an +unspecified value. +@end deffn + +@deffn procedure flush-output [output-port] +If @var{output-port} is buffered, this causes the contents of its buffer +to be written to the output device. Otherwise it has no effect. +Returns an unspecified value. +@end deffn + +@deffn procedure beep [output-port] +@cindex console, ringing the bell +@cindex ringing the console bell +@cindex bell, ringing on console +Performs a ``beep'' operation on @var{output-port}, performs +discretionary output flushing, and returns an unspecified value. On the +console port, this usually causes the console bell to beep, but more +sophisticated interactive ports may take other actions, such as flashing +the screen. On most output ports, e.g.@: file and string output ports, +this does nothing. +@end deffn + +@deffn procedure clear [output-port] +@cindex console, clearing +@cindex display, clearing +@cindex screen, clearing +@cindex terminal screen, clearing +@cindex clearing the console screen +``Clears the screen'' of @var{output-port}, performs discretionary +output flushing, and returns an unspecified value. On a terminal or +window, this has a well-defined effect. On other output ports, e.g.@: +file and string output ports, this does nothing. +@end deffn + +@deffn procedure pp object [output-port [as-code?]] +@cindex pretty printer +@code{pp} prints @var{object} in a visually appealing and structurally +revealing manner on @var{output-port}. If object is a procedure, +@code{pp} attempts to print the source text. If the optional argument +@var{as-code?} is true, @code{pp} prints lists as Scheme code, providing +appropriate indentation; by default this argument is false. @code{pp} +performs discretionary output flushing and returns an unspecified value. +@end deffn + +The following variables may be dynamically bound to change the behavior +of the @code{write} and @code{display} procedures. + +@defvr variable *unparser-radix* +This variable specifies the default radix used to print numbers. Its +value must be one of the exact integers @code{2}, @code{8}, @code{10}, +or @code{16}; the default is @code{10}. If @code{*unparser-radix*} is +not @code{10}, numbers are prefixed to indicate their radix. +@end defvr + +@defvr variable *unparser-list-breadth-limit* +This variable specifies a limit on the length of the printed +representation of a list or vector; for example, if the limit is +@code{4}, only the first four elements of any list are printed, followed +by ellipses to indicate any additional elements. The value of this +variable must be an exact non-negative integer, or @code{#f} meaning no +limit; the default is @code{#f}. + +@example +@group +(fluid-let ((*unparser-list-breadth-limit* 4)) + (write-to-string '(a b c d))) + @result{} "(a b c d)" +(fluid-let ((*unparser-list-breadth-limit* 4)) + (write-to-string '(a b c d e))) + @result{} "(a b c d ...)" +@end group +@end example +@end defvr + +@defvr variable *unparser-list-depth-limit* +This variable specifies a limit on the nesting of lists and vectors in +the printed representation. If lists (or vectors) are more deeply +nested than the limit, the part of the representation that exceeds the +limit is replaced by ellipses. The value of this variable must be an +exact non-negative integer, or @code{#f} meaning no limit; the default +is @code{#f}. + +@example +@group +(fluid-let ((*unparser-list-depth-limit* 4)) + (write-to-string '((((a))) b c d))) + @result{} "((((a))) b c d)" +(fluid-let ((*unparser-list-depth-limit* 4)) + (write-to-string '(((((a)))) b c d))) + @result{} "((((...))) b c d)" +@end group +@end example +@end defvr + +@defvr variable *unparser-string-length-limit* +This variable specifies a limit on the length of the printed +representation of strings. If a string's length exceeds this limit, the +part of the printed representation for the characters exceeding the +limit is replaced by ellipses. The value of this variable must be an +exact non-negative integer, or @code{#f} meaning no limit; the default +is @code{#f}. + +@example +@group +(fluid-let ((*unparser-string-length-limit* 4)) + (write-to-string "abcd")) + @result{} "\"abcd\"" +(fluid-let ((*unparser-string-length-limit* 4)) + (write-to-string "abcde")) + @result{} "\"abcd...\"" +@end group +@end example +@end defvr + +@defvr variable *unparse-with-maximum-readability?* +This variable, which takes a boolean value, tells the printer to use a +special printed representation for objects that normally print in a form +that cannot be recognized by @code{read}. These objects are printed +using the representation @code{#@@@var{n}}, where @var{n} is the result +of calling @code{hash} on the object to be printed. The reader +recognizes this syntax, calling @code{unhash} on @var{n} to get back the +original object. Note that this printed representation can only be +recognized by the Scheme program in which it was generated, because +these hash numbers are different for each invocation of Scheme. +@end defvr + +@node Format, Custom Output, Output Procedures, Input/Output +@section Format + +@comment **** begin CLTL **** + +The procedure @code{format} is very useful for producing nicely +formatted text, producing good-looking messages, and so on. MIT/GNU +Scheme's implementation of @code{format} is similar to that of Common +Lisp, except that Common Lisp defines many more +directives.@footnote{This description of @code{format} is adapted from +@cite{Common Lisp, The Language}, second edition, section 22.3.3.} + +@cindex run-time-loadable option +@cindex option, run-time-loadable +@code{format} is a run-time-loadable option. To use it, execute + +@example +(load-option 'format) +@end example +@findex load-option + +@noindent +once before calling it. + +@deffn procedure format destination control-string argument @dots{} +@findex write-string +@cindex format directive (defn) +@cindex directive, format (defn) +Writes the characters of @var{control-string} to @var{destination}, +except that a tilde (@code{~}) introduces a @dfn{format directive}. The +character after the tilde, possibly preceded by prefix parameters and +modifiers, specifies what kind of formatting is desired. Most +directives use one or more @var{argument}s to create their output; the +typical directive puts the next @var{argument} into the output, +formatted in some special way. It is an error if no argument remains +for a directive requiring an argument, but it is not an error if one or +more arguments remain unprocessed by a directive. + +The output is sent to @var{destination}. If @var{destination} is +@code{#f}, a string is created that contains the output; this string is +returned as the value of the call to @code{format}. In all other cases +@code{format} returns an unspecified value. If @var{destination} is +@code{#t}, the output is sent to the current output port. Otherwise, +@var{destination} must be an output port, and the output is sent there. + +This procedure performs discretionary output flushing (@pxref{Output +Procedures}). + +A @code{format} directive consists of a tilde (@code{~}), optional +prefix parameters separated by commas, optional colon (@code{:}) and +at-sign (@code{@@}) modifiers, and a single character indicating what +kind of directive this is. The alphabetic case of the directive +character is ignored. The prefix parameters are generally integers, +notated as optionally signed decimal numbers. If both the colon and +at-sign modifiers are given, they may appear in either order. + +@cindex V as format parameter +@cindex # as format parameter +In place of a prefix parameter to a directive, you can put the letter +@samp{V} (or @samp{v}), which takes an @var{argument} for use as a +parameter to the directive. Normally this should be an exact integer. +This feature allows variable-width fields and the like. You can also +use the character @samp{#} in place of a parameter; it represents the +number of arguments remaining to be processed. + +It is an error to give a format directive more parameters than it is +described here as accepting. It is also an error to give colon or +at-sign modifiers to a directive in a combination not specifically +described here as being meaningful. + +@table @code +@item ~A +The next @var{argument}, which may be any object, is printed as if by +@code{display}. @code{~@var{mincol}A} inserts spaces on the right, if +necessary, to make the width at least @var{mincol} columns. The +@code{@@} modifier causes the spaces to be inserted on the left rather +than the right. + +@item ~S +The next @var{argument}, which may be any object, is printed as if by +@code{write}. @code{~@var{mincol}S} inserts spaces on the right, if +necessary, to make the width at least @var{mincol} columns. The +@code{@@} modifier causes the spaces to be inserted on the left rather +than the right. + +@item ~% +This outputs a @code{#\newline} character. @code{~@var{n}%} outputs +@var{n} newlines. No @var{argument} is used. Simply putting a newline +in @var{control-string} would work, but @code{~%} is often used because +it makes the control string look nicer in the middle of a program. + +@item ~~ +This outputs a tilde. @code{~@var{n}~} outputs @var{n} tildes. + +@item ~@var{newline} +Tilde immediately followed by a newline ignores the newline and any +following non-newline whitespace characters. With an @code{@@}, the +newline is left in place, but any following whitespace is ignored. This +directive is typically used when @var{control-string} is too long to fit +nicely into one line of the program: + +@example +@group +(define (type-clash-error procedure arg spec actual) + (format + #t + "~%Procedure ~S~%requires its %A argument ~ + to be of type ~S,~%but it was called with ~ + an argument of type ~S.~%" + procedure arg spec actual)) +@end group +@end example + +@example +@group +(type-clash-error 'vector-ref + "first" + 'integer + 'vector) + +@r{prints} + +Procedure vector-ref +requires its first argument to be of type integer, +but it was called with an argument of type vector. +@end group +@end example + +@noindent +Note that in this example newlines appear in the output only as +specified by the @code{~%} directives; the actual newline characters in +the control string are suppressed because each is preceded by a tilde. +@end table +@end deffn + +@comment **** end CLTL **** + +@node Custom Output, Prompting, Format, Input/Output +@section Custom Output + +MIT/GNU Scheme provides hooks for specifying that certain kinds of objects +have special written representations. There are no restrictions on the +written representations, but only a few kinds of objects may have custom +representation specified for them, specifically: records +(@pxref{Records}), vectors that have special tags in their zero-th +elements (@pxref{Vectors}), and pairs that have special tags in their +car fields (@pxref{Lists}). There is a different procedure for +specifying the written representation of each of these types. + +@deffn procedure set-record-type-unparser-method! record-type unparser-method +Changes the unparser method of the type represented by @var{record-type} +to be @var{unparser-method}, and returns an unspecified value. +Subsequently, when the unparser encounters a record of this type, it +will invoke @var{unparser-method} to generate the written +representation. +@end deffn + +@deffn procedure unparser/set-tagged-vector-method! tag unparser-method +Changes the unparser method of the vector type represented by @var{tag} +to be @var{unparser-method}, and returns an unspecified value. +Subsequently, when the unparser encounters a vector with @var{tag} as +its zero-th element, it will invoke @var{unparser-method} to generate +the written representation. +@end deffn + +@deffn procedure unparser/set-tagged-pair-method! tag unparser-method +Changes the unparser method of the pair type represented by @var{tag} to +be @var{unparser-method}, and returns an unspecified value. +Subsequently, when the unparser encounters a pair with @var{tag} in its +car field, it will invoke @var{unparser-method} to generate the written +representation. +@end deffn + +@cindex unparser method (defn) +@cindex method, unparser (defn) +An @dfn{unparser method} is a procedure that is invoked with two +arguments: an unparser state and an object. An unparser method +generates a written representation for the object, writing it to the +output port specified by the unparser state. The value yielded by an +unparser method is ignored. Note that an unparser state is not an +output port, rather it is an object that contains an output port as one +of its components. Application programs generally do not construct or +examine unparser state objects, but just pass them along. + +There are two ways to create an unparser method (which is then +registered by one of the above procedures). The first, and easiest, is +to use @code{standard-unparser-method}. The second is to define your +own method using the procedure @code{with-current-unparser-state}. We +encourage the use of the first method, as it results in a more uniform +appearance for objects. Many predefined datatypes, for example +procedures and environments, already have this appearance. + +@deffn procedure standard-unparser-method name procedure +Returns a standard unparser method. @var{Name} may be any object, and +is used as the name of the type with which the unparser method is +associated; @var{name} is usually a symbol. @var{Procedure} must be +@code{#f} or a procedure of two arguments. + +@cindex #[ as external representation +If @var{procedure} is @code{#f}, the returned method generates an +external representation of this form: + +@example +#[@var{name} @var{hash}] +@end example + +@noindent +@findex write +@findex write-string +@findex hash +Here @var{name} is the external representation of the argument +@var{name}, as generated by @code{write},@footnote{Except that if the +argument @var{name} is a string, its external representation is +generated by @code{write-string}.} and @var{hash} is the external +representation of an exact non-negative integer unique to the object +being printed (specifically, it is the result of calling @code{hash} on +the object). Subsequently, the expression + +@example +#@@@var{hash} +@end example + +@noindent +is notation for the object. + +If @var{procedure} is supplied, the returned method generates a slightly +different external representation: + +@example +#[@var{name} @var{hash} @var{output}] +@end example + +@noindent +Here @var{name} and @var{hash} are as above, and @var{output} is the +output generated by @var{procedure}. The representation is constructed +in three stages: + +@enumerate +@item +The first part of the format (up to @var{output}) is written to the +output port specified by the unparser state. This is @code{"#["}, +@var{name}, @code{" "}, and @var{hash}. + +@item +@var{Procedure} is invoked on two arguments: the object and an output +port. + +@item +The closing bracket is written to the output port. +@end enumerate +@end deffn + +The following procedure is useful for writing more general kinds of +unparser methods. + +@deffn procedure with-current-unparser-state unparser-state procedure +This procedure calls @var{procedure} with one argument, the output port +from @var{unparser-state}. Additionally, it arranges for the remaining +components of @var{unparser-state} to be given to the printer when they +are needed. The @var{procedure} generates some output by writing to the +output port using the usual output operations, and the value yielded by +@var{procedure} is returned from @code{with-current-unparser-state}. + +The port passed to @var{procedure} should only be used within the +dynamic extent of @var{procedure}. +@end deffn + +@node Prompting, Port Primitives, Custom Output, Input/Output +@section Prompting +@cindex prompting + +This section describes procedures that prompt the user for input. Why +should the programmer use these procedures when it is possible to do +prompting using ordinary input and output procedures? One reason is +that the prompting procedures are more succinct. However, a second and +better reason is that the prompting procedures can be separately +customized for each user interface, providing more natural interaction. +The interfaces for Edwin and for GNU Emacs have already been customized +in this fashion; because Edwin and Emacs are very similar editors, their +customizations provide very similar behavior. + +@findex interaction-i/o-port +Each of these procedure accepts an optional argument called +@var{port}, which if given must be an @acronym{I/O} port. If not +given, this port defaults to the value of +@code{(interaction-i/o-port)}; this is initially the console +@acronym{I/O} port. + +@deffn procedure prompt-for-command-expression prompt [port] +Prompts the user for an expression that is to be executed as a command. +This is the procedure called by the @acronym{REP} loop to read the +user's expressions. + +If @var{prompt} is a string, it is used verbatim as the prompt string. +Otherwise, it must be a pair whose car is @code{standard} and whose cdr +is a string; in this case the prompt string is formed by prepending to +the string the current @acronym{REP} loop ``level number'' and a space. +Also, a space is appended to the string, unless it already ends in a +space or is an empty string. + +The default behavior of this procedure is to print a fresh line, a +newline, and the prompt string; flush the output buffer; then read an +object and return it. + +Under Edwin and Emacs, before the object is read, the interaction buffer +is put into a mode that allows expressions to be edited and submitted +for input using specific editor commands. The first expression that is +submitted is returned as the value of this procedure. +@end deffn + +@deffn procedure prompt-for-command-char prompt [port] +@findex char-graphic? +Prompts the user for a single character that is to be executed as a +command; the returned character is guaranteed to satisfy +@code{char-graphic?}. If at all possible, the character is read from +the user interface using a mode that reads the character as a single +keystroke; in other words, it should not be necessary for the user to +follow the character with a carriage return or something similar. + +@findex debug +@findex where +This is the procedure called by @code{debug} and @code{where} to read +the user's commands. + +If @var{prompt} is a string, it is used verbatim as the prompt string. +Otherwise, it must be a pair whose car is @code{standard} and whose cdr +is a string; in this case the prompt string is formed by prepending to +the string the current @acronym{REP} loop ``level number'' and a space. +Also, a space is appended to the string, unless it already ends in a +space or is an empty string. + +The default behavior of this procedure is to print a fresh line, a +newline, and the prompt string; flush the output buffer; read a +character in raw mode, echo that character, and return it. + +Under Edwin and Emacs, instead of reading a character, the interaction +buffer is put into a mode in which graphic characters submit themselves +as input. After this mode change, the first such character submitted is +returned as the value of this procedure. +@end deffn + +@deffn procedure prompt-for-expression prompt [port] +Prompts the user for an expression. + +The prompt string is formed by appending a colon and a space to +@var{prompt}, unless @var{prompt} already ends in a space or is the null +string. + +The default behavior of this procedure is to print a fresh line, a +newline, and the prompt string; flush the output buffer; then read an +object and return it. + +Under Edwin and Emacs, the expression is read in the minibuffer. +@end deffn + +@deffn procedure prompt-for-evaluated-expression prompt [environment [port]] +Prompts the user for an evaluated expression. Calls +@code{prompt-for-expression} to read an expression, then evaluates the +expression using @var{environment}; if @var{environment} is not given, +the @acronym{REP} loop environment is used. +@end deffn + +@deffn procedure prompt-for-confirmation prompt [port] +Prompts the user for confirmation. The result yielded by this procedure +is a boolean. + +The prompt string is formed by appending the string @code{" (y or n)? "} +to @var{prompt}, unless @var{prompt} already ends in a space or is the +null string. + +The default behavior of this procedure is to print a fresh line, a +newline, and the prompt string; flush the output buffer; then read a +character in raw mode. If the character is @code{#\y}, @code{#\Y}, or +@code{#\space}, the procedure returns @code{#t}; If the character is +@code{#\n}, @code{#\N}, or @code{#\rubout}, the procedure returns +@code{#f}. Otherwise the prompt is repeated. + +Under Edwin or Emacs, the confirmation is read in the minibuffer. +@end deffn + +@node Port Primitives, Parser Buffers, Prompting, Input/Output +@section Port Primitives +@cindex port primitives + +This section describes the low-level operations that can be used to +build and manipulate @acronym{I/O} ports. + +The purpose of these operations is twofold: to allow programmers to +construct new kinds of @acronym{I/O} ports, and to provide faster +@acronym{I/O} operations than those supplied by the standard high +level procedures. The latter is useful because the standard +@acronym{I/O} operations provide defaulting and error checking, and +sometimes other features, which are often unnecessary. This interface +provides the means to bypass such features, thus improving +performance. + +The abstract model of an @acronym{I/O} port, as implemented here, is a +combination of a set of named operations and a state. The state is an +arbitrary object, the meaning of which is determined by the +operations. The operations are defined by a mapping from names to +procedures. + +@cindex port type +The set of named operations is represented by an object called a +@dfn{port type}. A port type is constructed from a set of named +operations, and is subsequently used to construct a port. The port type +completely specifies the behavior of the port. Port types also support +a simple form of inheritance, allowing you to create new ports that are +similar to existing ports. + +The port operations are divided into two classes: + +@table @asis +@item Standard operations +There is a specific set of standard operations for input ports, and a +different set for output ports. Applications can assume that the +standard input operations are implemented for all input ports, and +likewise the standard output operations are implemented for all output +ports. +@cindex standard operations, on port + +@item Custom operations +Some ports support additional operations. For example, ports that +implement output to terminals (or windows) may define an operation named +@code{y-size} that returns the height of the terminal in characters. +Because only some ports will implement these operations, programs that +use custom operations must test each port for their existence, and be +prepared to deal with ports that do not implement them. +@cindex custom operations, on port +@findex y-size +@end table + +@menu +* Port Types:: +* Constructors and Accessors for Ports:: +* Input Port Operations:: +* Output Port Operations:: +* Blocking Mode:: +* Terminal Mode:: +@end menu + +@node Port Types, Constructors and Accessors for Ports, Port Primitives, Port Primitives +@subsection Port Types + +The procedures in this section provide means for constructing port types +with standard and custom operations, and accessing their operations. + +@deffn procedure make-port-type operations port-type +@cindex construction, of port type +Creates and returns a new port type. +@var{Operations} must be a list; each element is a list of two elements, +the name of the operation (a symbol) and the procedure that implements +it. @var{Port-type} is either @code{#f} or a port type; if it is a port +type, any operations implemented by @var{port-type} but not specified in +@var{operations} will be implemented by the resulting port type. + +@var{Operations} need not contain definitions for all of the standard +operations; the procedure will provide defaults for any standard +operations that are not defined. At a minimum, the following operations +must be defined: for input ports, @code{read-char} and @code{peek-char}; +for output ports, either @code{write-char} or @code{write-substring}. +@acronym{I/O} ports must supply the minimum operations for both input and +output. + +If an operation in @var{operations} is defined to be @code{#f}, then the +corresponding operation in @var{port-type} is @emph{not} inherited. + +If @code{read-char} is defined in @var{operations}, then any standard +input operations defined in @var{port-type} are ignored. Likewise, if +@code{write-char} or @code{write-substring} is defined in +@var{operations}, then any standard output operations defined in +@var{port-type} are ignored. This feature allows overriding the +standard operations without having to enumerate them. +@end deffn + +@deffn procedure port-type? object +@deffnx procedure input-port-type? object +@deffnx procedure output-port-type? object +@deffnx procedure i/o-port-type? object +These predicates return @code{#t} if @var{object} is a port type, +input-port type, output-port type, or @acronym{I/O}-port type, +respectively. Otherwise, they return @code{#f}. +@end deffn + +@deffn procedure port-type/operations port-type +Returns a newly allocated list containing all of the operations +implemented by @var{port-type}. Each element of the list is a list of +two elements --- the name and its associated operation. +@end deffn + +@deffn procedure port-type/operation-names port-type +Returns a newly allocated list whose elements are the names of the +operations implemented by @var{port-type}. +@end deffn + +@deffn procedure port-type/operation port-type symbol +Returns the operation named @var{symbol} in @var{port-type}. If +@var{port-type} has no such operation, returns @code{#f}. +@end deffn + +@node Constructors and Accessors for Ports, Input Port Operations, Port Types, Port Primitives +@subsection Constructors and Accessors for Ports + +The procedures in this section provide means for constructing ports, +accessing the type of a port, and manipulating the state of a port. + +@deffn procedure make-port port-type state +Returns a new port with type @var{port-type} and the given +@var{state}. The port will be an input, output, or @acronym{I/O} port +according to @var{port-type}. +@end deffn + +@deffn procedure port/type port +Returns the port type of @var{port}. +@end deffn + +@deffn procedure port/state port +Returns the state component of @var{port}. +@end deffn + +@deffn procedure set-port/state! port object +Changes the state component of @var{port} to be @var{object}. +Returns an unspecified value. +@end deffn + +@deffn procedure port/operation port symbol +Equivalent to + +@example +(port-type/operation (port/type @var{port}) @var{symbol}) +@end example +@end deffn + +@deffn procedure port/operation-names port +Equivalent to + +@example +(port-type/operation-names (port/type @var{port})) +@end example +@end deffn + +@deffn procedure make-eof-object input-port +@cindex EOF object, construction +@cindex construction, of EOF object +@findex eof-object? +Returns an object that satisfies the predicate @code{eof-object?}. This +is sometimes useful when building input ports. +@end deffn + +@node Input Port Operations, Output Port Operations, Constructors and Accessors for Ports, Port Primitives +@subsection Input Port Operations +@cindex input port operations + +This section describes the standard operations on input ports. +Following that, some useful custom operations are described. + +@defop operation {input port} read-char input-port +@cindex character, input from port +Removes the next character available from @var{input-port} and returns +it. If @var{input-port} has no more characters and will never have any +(e.g.@: at the end of an input file), this operation returns an +end-of-file object. If @var{input-port} has no more characters but will +eventually have some more (e.g.@: a terminal where nothing has been +typed recently), and it is in non-blocking mode, @code{#f} is returned; +otherwise the operation hangs until input is available. +@end defop + +@defop operation {input port} peek-char input-port +Reads the next character available from @var{input-port} and returns it. +The character is @emph{not} removed from @var{input-port}, and a +subsequent attempt to read from the port will get that character again. +In other respects this operation behaves like @code{read-char}. +@end defop + +@defop operation {input port} discard-char input-port +Discards the next character available from @var{input-port} and returns +an unspecified value. In other respects this operation behaves like +@code{read-char}. +@end defop + +@defop operation {input port} char-ready? input-port k +@code{char-ready?} returns @code{#t} if at least one character is +available to be read from @var{input-port}. If no characters are +available, the operation waits up to @var{k} milliseconds before +returning @code{#f}, returning immediately if any characters become +available while it is waiting. +@end defop + +@defop operation {input port} read-string input-port char-set +@defopx operation {input port} discard-chars input-port char-set +@cindex string, input from port +These operations are like @code{read-char} and @code{discard-char}, +except that they read or discard multiple characters at once. This can +have a marked performance improvement on buffered input ports. All +characters up to, but excluding, the first character in @var{char-set} +(or end of file) are read from @var{input-port}. @code{read-string} +returns these characters as a newly allocated string, while +@code{discard-chars} discards them and returns an unspecified value. +These operations hang until sufficient input is available, even if +@var{input-port} is in non-blocking mode. If end of file is encountered +before any input characters, @code{read-string} returns an end-of-file +object. +@end defop + +@defop operation {input port} read-substring input-port string start end +Reads characters from @var{input-port} into the substring defined by +@var{string}, @var{start}, and @var{end} until either the substring has +been filled or there are no more characters available. Returns the +number of characters written to the substring. + +If @var{input-port} is an interactive port, and at least one character +is immediately available, the available characters are written to the +substring and this operation returns immediately. If no characters are +available, and @var{input-port} is in blocking mode, the operation +blocks until at least one character is available. Otherwise, the +operation returns @code{#f} immediately. + +This is an extremely fast way to read characters from a port. +@end defop + +@deffn procedure input-port/read-char input-port +@deffnx procedure input-port/peek-char input-port +@deffnx procedure input-port/discard-char input-port +@deffnx procedure input-port/char-ready? input-port k +@deffnx procedure input-port/read-string input-port char-set +@deffnx procedure input-port/discard-chars input-port char-set +@deffnx procedure input-port/read-substring input-port string start end +Each of these procedures invokes the respective operation on +@var{input-port}. For example, the following are equivalent: + +@example +@group +(input-port/read-char @var{input-port}) +((input-port/operation @var{input-port} 'read-char) @var{input-port}) +@end group +@end example +@end deffn + +The following custom operations are implemented for input ports to +files, and will also work with some other kinds of input ports: + +@defop operation {input port} eof? input-port +Returns @code{#t} if @var{input-port} is known to be at end of file, +otherwise it returns @code{#f}. +@end defop + +@defop operation {input port} chars-remaining input-port +Returns an estimate of the number of characters remaining to be read +from @var{input-port}. This is useful only when @var{input-port} is a +file port in binary mode; in other cases, it returns @code{#f}. +@end defop + +@defop operation {input port} buffered-input-chars input-port +Returns the number of unread characters that are stored in +@var{input-port}'s buffer. This will always be less than or equal to +the buffer's size. +@end defop + +@defop operation {input port} input-buffer-size input-port +Returns the maximum number of characters that @var{input-port}'s buffer +can hold. +@end defop + +@defop operation {input port} set-input-buffer-size input-port size +Resizes @var{input-port}'s buffer so that it can hold at most @var{size} +characters. Characters in the buffer are discarded. @var{Size} must be +an exact non-negative integer. +@end defop + +@node Output Port Operations, Blocking Mode, Input Port Operations, Port Primitives +@subsection Output Port Operations +@cindex output port operations + +This section describes the standard operations on output ports. +Following that, some useful custom operations are described. + +@defop operation {output port} write-char output-port char +@cindex character, output to port +Writes @var{char} to @var{output-port} and returns an unspecified value. +@end defop + +@defop operation {output port} write-substring output-port string start end +@cindex substring, output to port +Writes the substring specified by @var{string}, @var{start}, and +@var{end} to @var{output-port} and returns an unspecified value. +Equivalent to writing the characters of the substring, one by one, to +@var{output-port}, but is implemented very efficiently. +@end defop + +@defop operation {output port} fresh-line output-port +Most output ports are able to tell whether or not they are at the +beginning of a line of output. If @var{output-port} is such a port, +end-of-line is written to the port only if the port is not already at +the beginning of a line. If @var{output-port} is not such a port, an +end-of-line is unconditionally written to the port. Returns an +unspecified value. +@end defop + +@defop operation {output port} flush-output output-port +If @var{output-port} is buffered, this causes its buffer to be written +out. Otherwise it has no effect. Returns an unspecified value. +@end defop + +@defop operation {output port} discretionary-flush-output output-port +Normally, this operation does nothing. However, ports that support +discretionary output flushing implement this operation identically to @code{flush-output}. +@end defop + +@deffn procedure output-port/write-char output-port char +@deffnx procedure output-port/write-substring output-port string start end +@deffnx procedure output-port/fresh-line output-port +@deffnx procedure output-port/flush-output output-port +@deffnx procedure output-port/discretionary-flush-output output-port +Each of these procedures invokes the respective operation on +@var{output-port}. For example, the following are equivalent: + +@example +@group +(output-port/write-char @var{output-port} @var{char}) +((output-port/operation @var{output-port} 'write-char) + @var{output-port} @var{char}) +@end group +@end example +@end deffn + +@deffn procedure output-port/write-string output-port string +Writes @var{string} to @var{output-port}. Equivalent to + +@example +@group +(output-port/write-substring @var{output-port} + @var{string} + 0 + (string-length @var{string})) +@end group +@end example +@end deffn + +The following custom operations are generally useful. + +@defop operation {output port} buffered-output-chars output-port +Returns the number of unwritten characters that are stored in +@var{output-port}'s buffer. This will always be less than or equal to +the buffer's size. +@end defop + +@defop operation {output port} output-buffer-size output-port +Returns the maximum number of characters that @var{output-port}'s buffer +can hold. +@end defop + +@defop operation {output port} set-output-buffer-size output-port size +Resizes @var{output-port}'s buffer so that it can hold at most @var{size} +characters. Characters in the buffer are discarded. @var{Size} must be +an exact non-negative integer. +@end defop + +@defop operation {output port} x-size output-port +Returns an exact positive integer that is the width of @var{output-port} +in characters. If @var{output-port} has no natural width, e.g.@: if it is +a file port, @code{#f} is returned. +@end defop + +@defop operation {output port} y-size output-port +Returns an exact positive integer that is the height of +@var{output-port} in characters. If @var{output-port} has no natural +height, e.g.@: if it is a file port, @code{#f} is returned. +@end defop + +@deffn procedure output-port/x-size output-port +This procedure invokes the custom operation whose name is the symbol +@code{x-size}, if it exists. If the @code{x-size} operation is both +defined and returns a value other than @code{#f}, that value is returned +as the result of this procedure. Otherwise, @code{output-port/x-size} +returns a default value (currently @code{80}). + +@code{output-port/x-size} is useful for programs that tailor their +output to the width of the display (a fairly common practice). If the +output device is not a display, such programs normally want some +reasonable default width to work with, and this procedure provides +exactly that. +@end deffn + +@deffn procedure output-port/y-size output-port +This procedure invokes the custom operation whose name is the symbol +@code{y-size}, if it exists. If the @code{y-size} operation is defined, +the value it returns is returned as the result of this procedure; +otherwise, @code{#f} is returned. +@end deffn + +@node Blocking Mode, Terminal Mode, Output Port Operations, Port Primitives +@subsection Blocking Mode + +@cindex blocking mode, of port +An interactive port is always in one of two modes: @dfn{blocking} or +@dfn{non-blocking}. This mode is independent of the terminal mode: +each can be changed independent of the other. Furthermore, if it is +an interactive @acronym{I/O} port, there are separate blocking modes +for input and for output. + +If an input port is in blocking mode, attempting to read from it when no +input is available will cause Scheme to ``block'', i.e.@: suspend +itself, until input is available. If an input port is in non-blocking +mode, attempting to read from it when no input is available will cause +the reading procedure to return immediately, indicating the lack of +input in some way (exactly how this situation is indicated is separately +specified for each procedure or operation). + +An output port in blocking mode will block if the output device is not +ready to accept output. In non-blocking mode it will return immediately +after performing as much output as the device will allow (again, each +procedure or operation reports this situation in its own way). + +Interactive ports are initially in blocking mode; this can be changed at +any time with the procedures defined in this section. + +These procedures represent blocking mode by the symbol @code{blocking}, +and non-blocking mode by the symbol @code{nonblocking}. An argument +called @var{mode} must be one of these symbols. A @var{port} argument +to any of these procedures may be any port, even if that port does not +support blocking mode; in that case, the port is not modified in any +way. + +@deffn procedure port/input-blocking-mode port +Returns the input blocking mode of @var{port}. +@end deffn + +@deffn procedure port/set-input-blocking-mode port mode +Changes the input blocking mode of @var{port} to be @var{mode}. Returns +an unspecified value. +@end deffn + +@deffn procedure port/with-input-blocking-mode port mode thunk +@var{Thunk} must be a procedure of no arguments. +@code{port/with-input-blocking-mode} +binds the input blocking mode of @var{port} to be @var{mode}, executes +@var{thunk}, restores the input blocking mode of @var{port} to what it +was when @code{port/with-input-blocking-mode} was called, and returns +the value that was yielded by @var{thunk}. This binding is performed +by @code{dynamic-wind}, which guarantees that the input blocking mode is +restored if @var{thunk} escapes from its continuation. +@end deffn + +@deffn procedure port/output-blocking-mode port +Returns the output blocking mode of @var{port}. +@end deffn + +@deffn procedure port/set-output-blocking-mode port mode +Changes the output blocking mode of @var{port} to be @var{mode}. +Returns an unspecified value. +@end deffn + +@deffn procedure port/with-output-blocking-mode port mode thunk +@var{Thunk} must be a procedure of no arguments. +@code{port/with-output-blocking-mode} +binds the output blocking mode of @var{port} to be @var{mode}, executes +@var{thunk}, restores the output blocking mode of @var{port} to what it +was when @code{port/with-output-blocking-mode} was called, and returns +the value that was yielded by @var{thunk}. This binding is performed +by @code{dynamic-wind}, which guarantees that the output blocking mode +is restored if @var{thunk} escapes from its continuation. +@end deffn + +@node Terminal Mode, , Blocking Mode, Port Primitives +@subsection Terminal Mode + +@cindex terminal mode, of port +A port that reads from or writes to a terminal has a @dfn{terminal +mode}; this is either @dfn{cooked} or @dfn{raw}. This mode is +independent of the blocking mode: each can be changed independent of +the other. Furthermore, a terminal @acronym{I/O} port has independent +terminal modes both for input and for output. + +@cindex cooked mode, of terminal port +A terminal port in cooked mode provides some standard processing to make +the terminal easy to communicate with. For example, under unix, cooked +mode on input reads from the terminal a line at a time and provides +rubout processing within the line, while cooked mode on output might +translate linefeeds to carriage-return/linefeed pairs. In general, the +precise meaning of cooked mode is operating-system dependent, and +furthermore might be customizable by means of operating system +utilities. The basic idea is that cooked mode does whatever is +necessary to make the terminal handle all of the usual user-interface +conventions for the operating system, while keeping the program's +interaction with the port as normal as possible. + +@cindex raw mode, of terminal port +A terminal port in raw mode disables all of that processing. In raw +mode, characters are directly read from and written to the device +without any translation or interpretation by the operating system. On +input, characters are available as soon as they are typed, and are not +echoed on the terminal by the operating system. In general, programs +that put ports in raw mode have to know the details of interacting with +the terminal. In particular, raw mode is used for writing programs such +as text editors. + +Terminal ports are initially in cooked mode; this can be changed at any +time with the procedures defined in this section. + +These procedures represent cooked mode by the symbol @code{cooked}, and +raw mode by the symbol @code{raw}. Additionally, the value @code{#f} +represents ``no mode''; it is the terminal mode of a port that is not a +terminal. An argument called @var{mode} must be one of these three +values. A @var{port} argument to any of these procedures may be any +port, even if that port does not support terminal mode; in that case, +the port is not modified in any way. + +@deffn procedure port/input-terminal-mode port +Returns the input terminal mode of @var{port}. +@end deffn + +@deffn procedure port/set-input-terminal-mode port mode +Changes the input terminal mode of @var{port} to be @var{mode}. +Returns an unspecified value. +@end deffn + +@deffn procedure port/with-input-terminal-mode port mode thunk +@var{Thunk} must be a procedure of no arguments. +@code{port/with-input-terminal-mode} +binds the input terminal mode of @var{port} to be @var{mode}, executes +@var{thunk}, restores the input terminal mode of @var{port} to what it +was when @code{port/with-input-terminal-mode} was called, and returns +the value that was yielded by @var{thunk}. This binding is performed +by @code{dynamic-wind}, which guarantees that the input terminal mode is +restored if @var{thunk} escapes from its continuation. +@end deffn + +@deffn procedure port/output-terminal-mode port +Returns the output terminal mode of @var{port}. +@end deffn + +@deffn procedure port/set-output-terminal-mode port mode +Changes the output terminal mode of @var{port} to be @var{mode}. +Returns an unspecified value. +@end deffn + +@deffn procedure port/with-output-terminal-mode port mode thunk +@var{Thunk} must be a procedure of no arguments. +@code{port/with-output-terminal-mode} +binds the output terminal mode of @var{port} to be @var{mode}, executes +@var{thunk}, restores the output terminal mode of @var{port} to what it +was when @code{port/with-output-terminal-mode} was called, and returns +the value that was yielded by @var{thunk}. This binding is performed +by @code{dynamic-wind}, which guarantees that the output terminal mode is +restored if @var{thunk} escapes from its continuation. +@end deffn + +@node Parser Buffers, Parser Language, Port Primitives, Input/Output +@section Parser Buffers + +@cindex Parser buffer +The @dfn{parser buffer} mechanism facilitates construction of parsers +for complex grammars. It does this by providing an input stream with +unbounded buffering and backtracking. The amount of buffering is +under program control. The stream can backtrack to any position in +the buffer. + +@cindex Parser-buffer pointer +The mechanism defines two data types: the @dfn{parser buffer} and the +@dfn{parser-buffer pointer}. A parser buffer is like an input port +with buffering and backtracking. A parser-buffer pointer is a pointer +into the stream of characters provided by a parser buffer. + +Note that all of the procedures defined here consider a parser buffer +to contain a stream of 8-bit characters in the @acronym{ISO-8859-1} +character set, except for @code{match-utf8-char-in-alphabet} which +treats it as a stream of Unicode characters encoded as 8-bit bytes in +the @acronym{UTF-8} encoding. + +There are several constructors for parser buffers: + +@deffn procedure input-port->parser-buffer port +Returns a parser buffer that buffers characters read from @var{port}. +@end deffn + +@deffn procedure substring->parser-buffer string start end +Returns a parser buffer that buffers the characters in the argument +substring. This is equivalent to creating a string input port and +calling @code{input-port->parser-buffer}, but it runs faster and uses +less memory. +@end deffn + +@deffn procedure string->parser-buffer string +Like @code{substring->parser-buffer} but buffers the entire string. +@end deffn + +@deffn procedure source->parser-buffer source +Returns a parser buffer that buffers the characters returned by +calling @var{source}. @var{Source} is a procedure of three arguments: +a string, a start index, and an end index (in other words, a substring +specifier). Each time @var{source} is called, it writes some +characters in the substring, and returns the number of characters +written. When there are no more characters available, it returns +zero. It must not return zero in any other circumstance. +@end deffn + +Parser buffers and parser-buffer pointers may be distinguished from +other objects: + +@deffn procedure parser-buffer? object +Returns @code{#t} if @var{object} is a parser buffer, otherwise +returns @code{#f}. +@end deffn + +@deffn procedure parser-buffer-pointer? object +Returns @code{#t} if @var{object} is a parser-buffer pointer, +otherwise returns @code{#f}. +@end deffn + +Characters can be read from a parser buffer much as they can be read +from an input port. The parser buffer maintains an internal pointer +indicating its current position in the input stream. Additionally, +the buffer remembers all characters that were previously read, and can +look at characters arbitrarily far ahead in the stream. It is this +buffering capability that facilitates complex matching and +backtracking. + +@deffn procedure read-parser-buffer-char buffer +Returns the next character in @var{buffer}, advancing the internal +pointer past that character. If there are no more characters +available, returns @code{#f} and leaves the internal pointer +unchanged. +@end deffn + +@deffn procedure peek-parser-buffer-char buffer +Returns the next character in @var{buffer}, or @code{#f} if no +characters are available. Leaves the internal pointer unchanged. +@end deffn + +@deffn procedure parser-buffer-ref buffer index +Returns a character in @var{buffer}. @var{Index} is a non-negative +integer specifying the character to be returned. If @var{index} is +zero, returns the next available character; if it is one, returns the +character after that, and so on. If @var{index} specifies a position +after the last character in @var{buffer}, returns @code{#f}. Leaves +the internal pointer unchanged. +@end deffn + +The internal pointer of a parser buffer can be read or written: + +@deffn procedure get-parser-buffer-pointer buffer +Returns a parser-buffer pointer object corresponding to the internal +pointer of @var{buffer}. +@end deffn + +@deffn procedure set-parser-buffer-pointer! buffer pointer +Sets the internal pointer of @var{buffer} to the position specified by +@var{pointer}. @var{Pointer} must have been returned from a previous +call of @code{get-parser-buffer-pointer} on @var{buffer}. +Additionally, if some of @var{buffer}'s characters have been discarded +by @code{discard-parser-buffer-head!}, @var{pointer} must be outside +the range that was discarded. +@end deffn + +@deffn procedure get-parser-buffer-tail buffer pointer +Returns a newly-allocated string consisting of all of the characters +in @var{buffer} that fall between @var{pointer} and @var{buffer}'s +internal pointer. @var{Pointer} must have been returned from a +previous call of @code{get-parser-buffer-pointer} on @var{buffer}. +Additionally, if some of @var{buffer}'s characters have been discarded +by @code{discard-parser-buffer-head!}, @var{pointer} must be outside +the range that was discarded. +@end deffn + +@deffn procedure discard-parser-buffer-head! buffer +Discards all characters in @var{buffer} that have already been read; +in other words, all characters prior to the internal pointer. After +this operation has completed, it is no longer possible to move the +internal pointer backwards past the current position by calling +@code{set-parser-buffer-pointer!}. +@end deffn + +The next rather large set of procedures does conditional matching +against the contents of a parser buffer. All matching is performed +relative to the buffer's internal pointer, so the first character to +be matched against is the next character that would be returned by +@code{peek-parser-buffer-char}. The returned value is always +@code{#t} for a successful match, and @code{#f} otherwise. For +procedures whose names do not end in @samp{-no-advance}, a successful +match also moves the internal pointer of the buffer forward to the end +of the matched text; otherwise the internal pointer is unchanged. + +@deffn procedure match-parser-buffer-char buffer char +@deffnx procedure match-parser-buffer-char-ci buffer char +@deffnx procedure match-parser-buffer-not-char buffer char +@deffnx procedure match-parser-buffer-not-char-ci buffer char +@deffnx procedure match-parser-buffer-char-no-advance buffer char +@deffnx procedure match-parser-buffer-char-ci-no-advance buffer char +@deffnx procedure match-parser-buffer-not-char-no-advance buffer char +@deffnx procedure match-parser-buffer-not-char-ci-no-advance buffer char +Each of these procedures compares a single character in @var{buffer} +to @var{char}. The basic comparison @code{match-parser-buffer-char} +compares the character to @var{char} using @code{char=?}. The +procedures whose names contain the @samp{-ci} modifier do +case-insensitive comparison (i.e.@: they use @code{char-ci=?}). The +procedures whose names contain the @samp{not-} modifier are successful +if the character @emph{doesn't} match @var{char}. +@end deffn + +@deffn procedure match-parser-buffer-char-in-set buffer char-set +@deffnx procedure match-parser-buffer-char-in-set-no-advance buffer char-set +These procedures compare the next character in @var{buffer} against +@var{char-set} using @code{char-set-member?}. +@end deffn + +@deffn procedure match-parser-buffer-string buffer string +@deffnx procedure match-parser-buffer-string-ci buffer string +@deffnx procedure match-parser-buffer-string-no-advance buffer string +@deffnx procedure match-parser-buffer-string-ci-no-advance buffer string +These procedures match @var{string} against @var{buffer}'s contents. +The @samp{-ci} procedures do case-insensitive matching. +@end deffn + +@deffn procedure match-parser-buffer-substring buffer string start end +@deffnx procedure match-parser-buffer-substring-ci buffer string start end +@deffnx procedure match-parser-buffer-substring-no-advance buffer string start end +@deffnx procedure match-parser-buffer-substring-ci-no-advance buffer string start end +These procedures match the specified substring against @var{buffer}'s +contents. The @samp{-ci} procedures do case-insensitive matching. +@end deffn + +@deffn procedure match-utf8-char-in-alphabet buffer alphabet +This procedure treats @var{buffer}'s contents as @acronym{UTF-8} +encoded Unicode characters and matches the next such character against +@var{alphabet}, which must be a Unicode alphabet (@pxref{Unicode}). +@acronym{UTF-8} represents characters with 1 to 6 bytes, so a +successful match can move the internal pointer forward by as many as 6 +bytes. +@end deffn + +The remaining procedures provide information that can be used to +identify locations in a parser buffer's stream. + +@deffn procedure parser-buffer-position-string pointer +Returns a string describing the location of @var{pointer} in terms of +its character and line indexes. This resulting string is meant to be +presented to an end user in order to direct their attention to a +feature in the input stream. In this string, the indexes are +presented as one-based numbers. + +@var{Pointer} may alternatively be a parser buffer, in which case it +is equivalent to having specified the buffer's internal pointer. +@end deffn + +@deffn procedure parser-buffer-pointer-index pointer +@deffnx procedure parser-buffer-pointer-line pointer +Returns the character or line index, respectively, of @var{pointer}. +Both indexes are zero-based. +@end deffn + +@node Parser Language, XML Parser, Parser Buffers, Input/Output +@section Parser Language + +@cindex Parser language +Although it is possible to write parsers using the parser-buffer +abstraction (@pxref{Parser Buffers}), it is tedious. The problem is +that the abstraction isn't closely matched to the way that people +think about syntactic structures. In this section, we introduce a +higher-level mechanism that greatly simplifies the implementation of a +parser. + +The @dfn{parser language} described here allows the programmer to +write @acronym{BNF}-like specifications that are translated into +efficient Scheme code at compile time. The language is declarative, +but it can be freely mixed with Scheme code; this allows the parsing +of grammars that aren't conveniently described in the language. + +@cindex Backtracking, in parser language +The language also provides backtracking. For example, this expression +matches any sequence of alphanumeric characters followed by a single +alphabetic character: + +@example +@group +(*matcher + (seq (* (char-set char-set:alphanumeric)) + (char-set char-set:alphabetic))) +@end group +@end example + +@noindent +The way that this works is that the matcher matches alphanumeric +characters in the input stream until it finds a non-alphanumeric +character. It then tries to match an alphabetic character, which of +course fails. At this point, if it matched at least one alphanumeric +character, it @emph{backtracks}: the last matched alphanumeric is +``unmatched'', and it again attempts to match an alphabetic +character. The backtracking can be arbitrarily deep; the matcher will +continue to back up until it finds a way to match the remainder of the +expression. + +So far, this sounds a lot like regular-expression matching +(@pxref{Regular Expressions}). However, there are some important +differences. + +@itemize @bullet +@item +The parser language uses a Scheme-like syntax that is easier to read +and write than regular-expression notation. + +@item +The language provides macros so that common syntactic constructs can +be abstracted. + +@item +The language mixes easily with Scheme code, allowing the full power of +Scheme to be applied to program around limitations in the parser +language. + +@item +The language provides expressive facilities for converting syntax into +parsed structure. It also makes it easy to convert parsed strings +into meaningful objects (e.g.@: numbers). + +@item +The language is compiled into machine language; regular expressions +are usually interpreted. +@end itemize + +Here is an example that shows off several of the features of the +parser language. The example is a parser for @acronym{XML} start +tags: + +@anchor{with-pointer example} +@example +@group +(*parser + (with-pointer p + (seq "<" + parse-name + parse-attribute-list + (alt (match ">") + (match "/>") + (sexp + (lambda (b) + (error + (string-append + "Unterminated start tag at " + (parser-buffer-position-string p))))))))) +@end group +@end example + +@noindent +This shows that the basic description of a start tag is very similar +to its @acronym{BNF}. Non-terminal symbols @code{parse-name} and +@code{parse-attribute-list} do most of the work, and the noise strings +@code{"<"} and @code{">"} are the syntactic markers delimiting the +form. There are two alternate endings for start tags, and if the +parser doesn't find either of the endings, the Scheme code (wrapped in +@code{sexp}) is run to signal an error. The error procedure +@code{perror} takes a pointer @code{p}, which it uses to indicate the +position in the input stream at which the error occurred. In this +case, that is the beginning of the start tag, i.e.@: the position of +the leading @code{"<"} marker. + +This example still looks pretty complicated, mostly due to the +error-signalling code. In practice, this is abstracted into a macro, +after which the expression is quite succinct: + +@example +@group +(*parser + (bracket "start tag" + (seq (noise (string "<")) parse-name) + (match (alt (string ">") (string "/>"))) + parse-attribute-list)) +@end group +@end example + +@noindent +The @code{bracket} macro captures the pattern of a bracketed item, and +hides much of the detail. + +The parser language actually consists of two languages: one for +defining matchers, and one for defining parsers. The languages are +intentionally very similar, and are meant to be used together. Each +sub-language is described below in its own section. + +@cindex run-time-loadable option +@cindex option, run-time-loadable +The parser language is a run-time-loadable option; to use it, execute + +@example +(load-option '*parser) +@end example +@findex load-option + +@noindent +once before compiling any code that uses the language. + +@menu +* *Matcher:: +* *Parser:: +* Parser-language Macros:: +@end menu + +@node *Matcher, *Parser, Parser Language, Parser Language +@subsection *Matcher + +@cindex Matcher language +@cindex Matcher procedure +The @dfn{matcher language} is a declarative language for specifying a +@dfn{matcher procedure}. A matcher procedure is a procedure that +accepts a single parser-buffer argument and returns a boolean value +indicating whether the match it performs was successful. If the match +succeeds, the internal pointer of the parser buffer is moved forward +over the matched text. If the match fails, the internal pointer is +unchanged. + +For example, here is a matcher procedure that matches the character +@samp{a}: + +@example +(lambda (b) (match-parser-buffer-char b #\a)) +@end example + +@noindent +Here is another example that matches two given characters, @var{c1} +and @var{c2}, in sequence: + +@example +@group +(lambda (b) + (let ((p (get-parser-buffer-pointer b))) + (if (match-parser-buffer-char b @var{c1}) + (if (match-parser-buffer-char b @var{c2}) + #t + (begin + (set-parser-buffer-pointer! b p) + #f)) + #f))) +@end group +@end example + +@noindent +This is code is clear, but has lots of details that get in the way of +understanding what it is doing. Here is the same example in the +matcher language: + +@example +(*matcher (seq (char @var{c1}) (char @var{c2}))) +@end example + +@noindent +This is much simpler and more intuitive. And it generates virtually +the same code: + +@example +@group +(pp (*matcher (seq (char c1) (char c2)))) +@print{} (lambda (#[b1]) +@print{} (let ((#[p1] (get-parser-buffer-pointer #[b1]))) +@print{} (and (match-parser-buffer-char #[b1] c1) +@print{} (if (match-parser-buffer-char #[b1] c2) +@print{} #t +@print{} (begin +@print{} (set-parser-buffer-pointer! #[b1] #[p1]) +@print{} #f))))) +@end group +@end example + +Now that we have seen an example of the language, it's time to look at +the detail. The @code{*matcher} special form is the interface between +the matcher language and Scheme. + +@deffn {special form} *matcher mexp +The operand @var{mexp} is an expression in the matcher language. The +@code{*matcher} expression expands into Scheme code that implements a +matcher procedure. +@end deffn + +Here are the predefined matcher expressions. New matcher expressions +can be defined using the macro facility (@pxref{Parser-language +Macros}). We will start with the primitive expressions. + +@deffn {matcher expression} char expression +@deffnx {matcher expression} char-ci expression +@deffnx {matcher expression} not-char expression +@deffnx {matcher expression} not-char-ci expression +These expressions match a given character. In each case, the +@var{expression} operand is a Scheme expression that must evaluate to +a character at run time. The @samp{-ci} expressions do +case-insensitive matching. The @samp{not-} expressions match any +character other than the given one. +@end deffn + +@deffn {matcher expression} string expression +@deffnx {matcher expression} string-ci expression +These expressions match a given string. The @var{expression} operand +is a Scheme expression that must evaluate to a string at run time. +The @code{string-ci} expression does case-insensitive matching. +@end deffn + +@deffn {matcher expression} char-set expression +These expressions match a single character that is a member of a given +character set. The @var{expression} operand is a Scheme expression +that must evaluate to a character set at run time. +@end deffn + +@deffn {matcher expression} alphabet expression +These expressions match a single character that is a member of a given +Unicode alphabet (@pxref{Unicode}). The @var{expression} operand is a +Scheme expression that must evaluate to an alphabet at run time. +@end deffn + +@deffn {matcher expression} end-of-input +The @code{end-of-input} expression is successful only when there are +no more characters available to be matched. +@end deffn + +@deffn {matcher expression} discard-matched +The @code{discard-matched} expression always successfully matches the +null string. However, it isn't meant to be used as a matching +expression; it is used for its effect. @code{discard-matched} causes +all of the buffered text prior to this point to be discarded (i.e.@: +it calls @code{discard-parser-buffer-head!} on the parser buffer). + +Note that @code{discard-matched} may not be used in certain places in +a matcher expression. The reason for this is that it deliberately +discards information needed for backtracking, so it may not be used in +a place where subsequent backtracking will need to back over it. As a +rule of thumb, use @code{discard-matched} only in the last operand of +a @code{seq} or @code{alt} expression (including any @code{seq} or +@code{alt} expressions in which it is indirectly contained). +@end deffn + +In addition to the above primitive expressions, there are two +convenient abbreviations. A character literal (e.g.@: @samp{#\A}) is +a legal primitive expression, and is equivalent to a @code{char} +expression with that literal as its operand (e.g.@: @samp{(char +#\A)}). Likewise, a string literal is equivalent to a @code{string} +expression (e.g.@: @samp{(string "abc")}). + +Next there are several combinator expressions. These closely +correspond to similar combinators in regular expressions. Parameters +named @var{mexp} are arbitrary expressions in the matcher language. + +@deffn {matcher expression} seq mexp @dots{} +This matches each @var{mexp} operand in sequence. For example, + +@example +@group +(seq (char-set char-set:alphabetic) + (char-set char-set:numeric)) +@end group +@end example + +@noindent +matches an alphabetic character followed by a numeric character, such +as @samp{H4}. + +Note that if there are no @var{mexp} operands, the @code{seq} +expression successfully matches the null string. +@end deffn + +@deffn {matcher expression} alt mexp @dots{} +This attempts to match each @var{mexp} operand in order from left to +right. The first one that successfully matches becomes the match for +the entire @code{alt} expression. + +The @code{alt} expression participates in backtracking. If one of the +@var{mexp} operands matches, but the overall match in which this +expression is embedded fails, the backtracking mechanism will cause +the @code{alt} expression to try the remaining @var{mexp} operands. +For example, if the expression + +@example +(seq (alt "ab" "a") "b") +@end example + +@noindent +is matched against the text @samp{abc}, the @code{alt} expression will +initially match its first operand. But it will then fail to match the +second operand of the @code{seq} expression. This will cause the +@code{alt} to be restarted, at which time it will match @samp{a}, and +the overall match will succeed. + +Note that if there are no @var{mexp} operands, the @code{alt} match +will always fail. +@end deffn + +@deffn {matcher expression} * mexp +This matches zero or more occurrences of the @var{mexp} operand. +(Consequently this match always succeeds.) + +The @code{*} expression participates in backtracking; if it matches +@var{N} occurrences of @var{mexp}, but the overall match fails, it +will backtrack to @var{N-1} occurrences and continue. If the overall +match continues to fail, the @code{*} expression will continue to +backtrack until there are no occurrences left. +@end deffn + +@deffn {matcher expression} + mexp +This matches one or more occurrences of the @var{mexp} operand. It is +equivalent to + +@example +(seq @var{mexp} (* @var{mexp})) +@end example +@end deffn + +@deffn {matcher expression} ? mexp +This matches zero or one occurrences of the @var{mexp} operand. It is +equivalent to + +@example +(alt @var{mexp} (seq)) +@end example +@end deffn + +@deffn {matcher expression} sexp expression +The @code{sexp} expression allows arbitrary Scheme code to be embedded +inside a matcher. The @var{expression} operand must evaluate to a +matcher procedure at run time; the procedure is called to match the +parser buffer. For example, + +@example +@group +(*matcher + (seq "a" + (sexp parse-foo) + "b")) +@end group +@end example + +@noindent +expands to + +@example +@group +(lambda (#[b1]) + (let ((#[p1] (get-parser-buffer-pointer #[b1]))) + (and (match-parser-buffer-char #[b1] #\a) + (if (parse-foo #[b1]) + (if (match-parser-buffer-char #[b1] #\b) + #t + (begin + (set-parser-buffer-pointer! #[b1] #[p1]) + #f)) + (begin + (set-parser-buffer-pointer! #[b1] #[p1]) + #f))))) +@end group +@end example + +The case in which @var{expression} is a symbol is so common that it +has an abbreviation: @samp{(sexp @var{symbol})} may be abbreviated as +just @var{symbol}. +@end deffn + +@deffn {matcher expression} with-pointer identifier mexp +The @code{with-pointer} expression fetches the parser buffer's +internal pointer (using @code{get-parser-buffer-pointer}), binds it to +@var{identifier}, and then matches the pattern specified by +@var{mexp}. @var{Identifier} must be a symbol. + +This is meant to be used on conjunction with @code{sexp}, as a way to +capture a pointer to a part of the input stream that is outside the +@code{sexp} expression. An example of the use of @code{with-pointer} +appears above (@pxref{with-pointer example}). +@end deffn + +@node *Parser, Parser-language Macros, *Matcher, Parser Language +@subsection *Parser + +@cindex Parser language +@cindex Parser procedure +The @dfn{parser language} is a declarative language for specifying a +@dfn{parser procedure}. A parser procedure is a procedure that +accepts a single parser-buffer argument and parses some of the input +from the buffer. If the parse is successful, the procedure returns a +vector of objects that are the result of the parse, and the internal +pointer of the parser buffer is advanced past the input that was +parsed. If the parse fails, the procedure returns @code{#f} and the +internal pointer is unchanged. This interface is much like that of a +matcher procedure, except that on success the parser procedure returns +a vector of values rather than @code{#t}. + +The @code{*parser} special form is the interface between the parser +language and Scheme. + +@deffn {special form} *parser pexp +The operand @var{pexp} is an expression in the parser language. The +@code{*parser} expression expands into Scheme code that implements a +parser procedure. +@end deffn + +There are several primitive expressions in the parser language. The +first two provide a bridge to the matcher language (@pxref{*Matcher}): + +@deffn {parser expression} match mexp +The @code{match} expression performs a match on the parser buffer. +The match to be performed is specified by @var{mexp}, which is an +expression in the matcher language. If the match is successful, the +result of the @code{match} expression is a vector of one element: a +string containing that text. +@end deffn + +@deffn {parser expression} noise mexp +The @code{noise} expression performs a match on the parser buffer. +The match to be performed is specified by @var{mexp}, which is an +expression in the matcher language. If the match is successful, the +result of the @code{noise} expression is a vector of zero elements. +(In other words, the text is matched and then thrown away.) + +The @var{mexp} operand is often a known character or string, so in the +case that @var{mexp} is a character or string literal, the +@code{noise} expression can be abbreviated as the literal. In other +words, @samp{(noise "foo")} can be abbreviated just @samp{"foo"}. +@end deffn + +@deffn {parser expression} values expression @dots{} +Sometimes it is useful to be able to insert arbitrary values into the +parser result. The @code{values} expression supports this. The +@var{expression} arguments are arbitrary Scheme expressions that are +evaluated at run time and returned in a vector. The @code{values} +expression always succeeds and never modifies the internal pointer of +the parser buffer. +@end deffn + +@deffn {parser expression} discard-matched +The @code{discard-matched} expression always succeeds, returning a +vector of zero elements. In all other respects it is identical to the +@code{discard-matched} expression in the matcher language. +@end deffn + +Next there are several combinator expressions. Parameters named +@var{pexp} are arbitrary expressions in the parser language. The +first few combinators are direct equivalents of those in the matcher +language. + +@deffn {parser expression} seq pexp @dots{} +The @code{seq} expression parses each of the @var{pexp} operands in +order. If all of the @var{pexp} operands successfully match, the +result is the concatenation of their values (by @code{vector-append}). +@end deffn + +@deffn {parser expression} alt pexp @dots{} +The @code{alt} expression attempts to parse each @var{pexp} operand in +order from left to right. The first one that successfully parses +produces the result for the entire @code{alt} expression. + +Like the @code{alt} expression in the matcher language, this +expression participates in backtracking. +@end deffn + +@deffn {parser expression} * pexp +The @code{*} expression parses zero or more occurrences of @var{pexp}. +The results of the parsed occurrences are concatenated together (by +@code{vector-append}) to produce the expression's result. + +Like the @code{*} expression in the matcher language, this expression +participates in backtracking. +@end deffn + +@deffn {parser expression} + pexp +The @code{*} expression parses one or more occurrences of @var{pexp}. +It is equivalent to + +@example +(seq @var{pexp} (* @var{pexp})) +@end example +@end deffn + +@deffn {parser expression} ? pexp +The @code{*} expression parses zero or one occurrences of @var{pexp}. +It is equivalent to + +@example +(alt @var{pexp} (seq)) +@end example +@end deffn + +The next three expressions do not have equivalents in the matcher +language. Each accepts a single @var{pexp} argument, which is parsed +in the usual way. These expressions perform transformations on the +returned values of a successful match. + +@deffn {parser expression} transform expression pexp +The @code{transform} expression performs an arbitrary transformation +of the values returned by parsing @var{pexp}. @var{Expression} is a +Scheme expression that must evaluate to a procedure at run time. If +@var{pexp} is successfully parsed, the procedure is called with the +vector of values as its argument, and must return a vector or +@code{#f}. If it returns a vector, the parse is successful, and those +are the resulting values. If it returns @code{#f}, the parse fails +and the internal pointer of the parser buffer is returned to what it +was before @var{pexp} was parsed. + +For example: + +@example +(transform (lambda (v) (if (= 0 (vector-length v)) #f v)) @dots{}) +@end example +@end deffn + +@deffn {parser expression} encapsulate expression pexp +The @code{encapsulate} expression transforms the values returned by +parsing @var{pexp} into a single value. @var{Expression} is a Scheme +expression that must evaluate to a procedure at run time. If +@var{pexp} is successfully parsed, the procedure is called with the +vector of values as its argument, and may return any Scheme object. +The result of the @code{encapsulate} expression is a vector of length +one containing that object. (And consequently @code{encapsulate} +doesn't change the success or failure of @var{pexp}, only its value.) + +For example: + +@example +(encapsulate vector->list @dots{}) +@end example +@end deffn + +@deffn {parser expression} map expression pexp +The @code{map} expression performs a per-element transform on the +values returned by parsing @var{pexp}. @var{Expression} is a Scheme +expression that must evaluate to a procedure at run time. If +@var{pexp} is successfully parsed, the procedure is mapped (by +@code{vector-map}) over the values returned from the parse. The +mapped values are returned as the result of the @code{map} expression. +(And consequently @code{map} doesn't change the success or failure of +@var{pexp}, nor the number of values returned.) + +For example: + +@example +(map string->symbol @dots{}) +@end example +@end deffn + +Finally, as in the matcher language, we have @code{sexp} and +@code{with-pointer} to support embedding Scheme code in the parser. + +@deffn {parser expression} sexp expression +The @code{sexp} expression allows arbitrary Scheme code to be embedded +inside a parser. The @var{expression} operand must evaluate to a +parser procedure at run time; the procedure is called to parse the +parser buffer. This is the parser-language equivalent of the +@code{sexp} expression in the matcher language. + +The case in which @var{expression} is a symbol is so common that it +has an abbreviation: @samp{(sexp @var{symbol})} may be abbreviated as +just @var{symbol}. +@end deffn + +@deffn {parser expression} with-pointer identifier pexp +The @code{with-pointer} expression fetches the parser buffer's +internal pointer (using @code{get-parser-buffer-pointer}), binds it to +@var{identifier}, and then parses the pattern specified by @var{pexp}. +@var{Identifier} must be a symbol. This is the parser-language +equivalent of the @code{with-pointer} expression in the matcher +language. +@end deffn + +@node Parser-language Macros, , *Parser, Parser Language +@subsection Parser-language Macros + +The parser and matcher languages provide a macro facility so that +common patterns can be abstracted. The macro facility allows new +expression types to be independently defined in the two languages. +The macros are defined in heirarchically organized tables, so that +different applications can have private macro bindings. + +@deffn {special form} define-*matcher-macro formals expression +@deffnx {special form} define-*parser-macro formals expression +These special forms are used to define macros in the matcher and +parser language, respectively. @var{Formals} is like the +@var{formals} list of a @code{define} special form, and +@var{expression} is a Scheme expression. + +If @var{formals} is a list (or improper list) of symbols, the first +symbol in the list is the name of the macro, and the remaining symbols +are interpreted as the @var{formals} of a lambda expression. A lambda +expression is formed by combining the latter @var{formals} with the +@var{expression}, and this lambda expression, when evaluated, becomes +the @dfn{expander}. The defined macro accepts the same number of +operands as the expander. A macro instance is expanded by applying +the expander to the list of operands; the result of the application is +interpreted as a replacement expression for the macro instance. + +If @var{formals} is a symbol, it is the name of the macro. In this +case, the expander is a procedure of no arguments whose body is +@var{expression}. When the @var{formals} symbol appears by itself as +an expression in the language, the expander is called with no +arguments, and the result is interpreted as a replacement expression +for the symbol. +@end deffn + +@deffn procedure define-*matcher-expander identifier expander +@deffnx procedure define-*parser-expander identifier expander +These procedures provide a procedural interface to the +macro-definition mechanism. @var{Identifier} must be a symbol, and +@var{expander} must be an expander procedure, as defined above. +Instances of the @code{define-*matcher-macro} and +@code{define-*parser-macro} special forms expand into calls to these +procedures. +@end deffn + +The remaining procedures define the interface to the parser-macros +table abstraction. Each parser-macro table has a separate binding +space for macros in the matcher and parser languages. However, the +table inherits bindings from one specified table; it's not possible to +inherit matcher-language bindings from one table and parser-language +bindings from another. + +@deffn procedure make-parser-macros parent-table +Create and return a new parser-macro table that inherits from +@var{parent-table}. @var{Parent-table} must be either a parser-macro +table, or @code{#f}; usually it is specified as the value of +@code{global-parser-macros}. +@end deffn + +@deffn procedure parser-macros? object +This is a predicate for parser-macro tables. +@end deffn + +@deffn procedure global-parser-macros +Return the global parser-macro table. This table is predefined and +contains all of the bindings documented here. +@end deffn + +There is a ``current'' table at all times, and macro definitions are +always placed in this table. By default, the current table is the +global macro table, but the following procedures allow this to be +changed. + +@deffn procedure current-parser-macros +Return the current parser-macro table. +@end deffn + +@deffn procedure set-current-parser-macros! table +Change the current parser-macro table to @var{table}, which must +satisfy @code{parser-macros?}. +@end deffn + +@deffn procedure with-current-parser-macros table thunk +Bind the current parser-macro table to @var{table}, call @var{thunk} +with no arguments, then restore the original table binding. The value +returned by @var{thunk} is the returned as the value of this +procedure. @var{Table} must satisfy @code{parser-macros?}, and +@var{thunk} must be a procedure of no arguments. +@end deffn + +@node XML Parser, , Parser Language, Input/Output +@section XML Parser + +@cindex XML parser +@cindex parser, XML +MIT/GNU Scheme provides a simple non-validating @acronym{XML} parser. +This parser is mostly conformant, with the exception that it doesn't +support @acronym{UTF-16}. The parser also does not support external +document type declarations (@acronym{DTD}s). The output of the parser +is a record tree that closely reflects the structure of the +@acronym{XML} document. + +@cindex XML output +@cindex output, XML +There is also an output mechanism that writes an @acronym{XML} record +tree to a port. There is no guarantee that parsing an @acronym{XML} +document and writing it back out will make a verbatim copy of the +document. The output will be semantically identical but may have +small syntactic differences. For example, comments are discarded by +the parser, and entities are substituted during the parsing process. + +The purpose of the @acronym{XML} support is to provide a mechanism for +reading and writing simple @acronym{XML} documents. In the future +this support may be further developed to support a standard interface +such as @acronym{DOM} or @acronym{SAX}. + +@cindex run-time-loadable option +@cindex option, run-time-loadable +The @acronym{XML} support is a run-time-loadable option; to use it, +execute + +@example +(load-option 'xml) +@end example +@findex load-option + +@noindent +once before compiling any code that uses it. + +The @acronym{XML} interface consists of an input procedure, an output +procedure, and a set of record types. + +@deffn procedure parse-xml-document buffer +This procedure parses an @acronym{XML} input stream and returns a +newly-allocated @acronym{XML} record tree. The @var{buffer} argument +must be a parser buffer (@pxref{Parser Buffers}). Most errors in the +input stream are detected and signalled, with information identifying +the location of the error where possible. Note that the input stream +is assumed to be @acronym{UTF-8}. +@end deffn + +@deffn procedure write-xml xml-document port +This procedure writes an @acronym{XML} record tree to @var{port}. The +@var{xml-document} argument must be a record of type +@code{xml-document}, which is the root record of an @acronym{XML} +record tree. The output is encoded in @acronym{UTF-8}. +@end deffn + +@cindex XML names +@cindex names, XML +@acronym{XML} names are represented in memory as symbols. All symbols +appearing within @acronym{XML} records are @acronym{XML} names. +Because @acronym{XML} names are case sensitive, there is a procedure +to intern these symbols: + +@deffn procedure xml-intern string +@cindex XML name +Returns the @acronym{XML} name called @var{string}. @acronym{XML} +names are represented as symbols, but unlike ordinary Scheme symbols, +they are case sensitive. The following is true for any two strings +@var{string1} and @var{string2}: + +@example +@group +(let ((name1 (xml-intern @var{string1})) + (name2 (xml-intern @var{string2}))) + (if (string=? @var{string1} @var{string2}) + (eq? name1 name2) + (not (eq? name1 name2)))) +@end group +@end example +@end deffn + +The output from the @acronym{XML} parser and the input to the +@acronym{XML} output procedure is a complex data structure composed of +a heirarchy of typed components. Each component is a record whose +fields correspond to parts of the @acronym{XML} structure that the +record represents. There are no special operations on these records; +each is a tuple with named subparts. The root record type is +@code{xml-document}, which represents a complete @acronym{XML} +document. + +Each record type @var{type} has the following associated bindings: + +@table @code +@item <@var{type}> +is a variable bound to the record-type descriptor for @var{type}. The +record-type descriptor may be used as a specializer in @acronym{SOS} +method definitions, which greatly simplifies code to dispatch on these +types. + +@item @var{type}? +is a predicate for records of type @var{type}. It accepts one +argument, which can be any object, and returns @code{#t} if the object +is a record of this type, or @code{#f} otherwise. + +@item make-@var{type} +is a constructor for records of type @var{type}. It accepts one +argument for each field of @var{type}, in the same order that they are +written in the type description, and returns a newly-allocated record +of that type. + +@item @var{type}-@var{field} +is an accessor procedure for the field @var{field} in records of type +@var{type}. It accepts one argument, which must be a record of that +type, and returns the contents of the corresponding field in the +record. + +@item set-@var{type}-@var{field}! +is a modifier procedure for the field @var{field} in records of type +@var{type}. It accepts two arguments: the first must be a record of +that type, and the second is a new value for the corresponding field. +The record's field is modified to have the new value. +@end table + +@deftp {record type} xml-document declaration misc-1 dtd misc-2 root misc-3 +@vindex +@findex xml-document? +@findex make-xml-document +@findex xml-document-declaration +@findex xml-document-misc-1 +@findex xml-document-dtd +@findex xml-document-misc-2 +@findex xml-document-root +@findex xml-document-misc-3 +@findex set-xml-document-declaration! +@findex set-xml-document-misc-1! +@findex set-xml-document-dtd! +@findex set-xml-document-misc-2! +@findex set-xml-document-root! +@findex set-xml-document-misc-3! +The @code{xml-document} record is the top-level record representing a +complete @acronym{XML} document. @var{Declaration} is either an +@code{xml-declaration} object or @code{#f}. @var{Dtd} is either an +@code{xml-dtd} object or @code{#f}. @var{Root} is an @code{xml-element} +object. @var{Misc-1}, @var{misc-2}, and @var{misc-3} are lists of +miscellaneous items; a miscellaneous item is either an +@code{xml-comment} object, an @code{xml-processing-instructions} object, +or a string of whitespace. +@end deftp + +@deftp {record type} xml-declaration version encoding standalone +@vindex +@findex xml-declaration? +@findex make-xml-declaration +@findex xml-declaration-version +@findex xml-declaration-encoding +@findex xml-declaration-standalone +@findex set-xml-declaration-version! +@findex set-xml-declaration-encoding! +@findex set-xml-declaration-standalone! +The @code{xml-declaration} record represents the @samp{} declaration that optionally appears at the beginning of an +@acronym{XML} document. @var{Version} is a version string, typically +@code{"1.0"}. @var{Encoding} is either an encoding string or +@code{#f}. @var{Standalone} is either @code{"yes"}, @code{"no"}, or +@code{#f}. +@end deftp + +@deftp {record type} xml-element name attributes contents +@vindex +@findex xml-element? +@findex make-xml-element +@findex xml-element-name +@findex xml-element-attributes +@findex xml-element-contents +@findex set-xml-element-name! +@findex set-xml-element-attributes! +@findex set-xml-element-contents! +The @code{xml-element} record represents general @acronym{XML} +elements; the bulk of a typical @acronym{XML} document consists of +these elements. @var{Name} is the element name (a symbol). +@var{Attributes} is a list of attributes; each attribute is a pair +whose @sc{car} is the attribute name (a symbol), and whose @sc{cdr} is +the attribute value (a string). @var{Contents} is a list of the +contents of the element. Each element of this list is either a +string, an @code{xml-element} record, an +@code{xml-processing-instructions} record, or an +@code{xml-uninterpreted} record. +@end deftp + +@deftp {record type} xml-processing-instructions name text +@vindex +@findex xml-processing-instructions? +@findex make-xml-processing-instructions +@findex xml-processing-instructions-name +@findex xml-processing-instructions-text +@findex set-xml-processing-instructions-name! +@findex set-xml-processing-instructions-text! +The @code{xml-processing-instructions} record represents processing +instructions, which have the form @samp{}. +These instructions are intended to contain non-@acronym{XML} data that +will be processed by another interpreter; for example they might +contain @acronym{PHP} programs. The @var{name} field is the processor +name (a symbol), and the @var{text} field is the body of the +instructions (a string). +@end deftp + +@deftp {record type} xml-uninterpreted text +@vindex +@findex xml-uninterpreted? +@findex make-xml-uninterpreted +@findex xml-uninterpreted-text +@findex set-xml-uninterpreted-text! +Some documents contain entity references that can't be expanded by the +parser, perhaps because the document requires an external +@acronym{DTD}. Such references are left uninterpreted in the output +by wrapping them in @code{xml-uninterpreted} records. In some +situations, for example when they are embedded in attribute values, +the surrounding text is also included in the @code{xml-uninterpreted} +record. The @var{text} field contains the uninterpreted @acronym{XML} +text (a string). +@end deftp + +@deftp {record type} xml-dtd root external internal +@vindex +@findex xml-dtd? +@findex make-xml-dtd +@findex xml-dtd-root +@findex xml-dtd-external +@findex xml-dtd-internal +@findex set-xml-dtd-root! +@findex set-xml-dtd-external! +@findex set-xml-dtd-internal! +The @code{xml-dtd} record represents a document type declaration. The +@var{root} field is an @acronym{XML} name for the root element of the +document. @var{External} is either an @code{xml-external-id} record +or @code{#f}. @var{Internal} is a list of @acronym{DTD} element +records (e.g.@: @code{xml-!element}, @code{xml-!attlist}, etc.). +@end deftp + +The remaining record types are valid only within a @acronym{DTD}. + +@deftp {record type} xml-!element name content-type +@vindex +@findex xml-!element? +@findex make-xml-!element +@findex xml-!element-name +@findex xml-!element-content-type +@findex set-xml-!element-name! +@findex set-xml-!element-content-type! +The @code{xml-!element} record represents an element-type +declaration. @var{Name} is the @acronym{XML} name of the type being +declared (a symbol). @var{Content-type} describes the type and can +have several different values, as follows: + +@itemize @bullet +@item +The @acronym{XML} names @samp{EMPTY} and @samp{ANY} correspond to the +@acronym{XML} keywords of the same name. + +@item +A list @samp{(MIX @var{type} @dots{})} corresponds to the +@samp{(#PCDATA | @var{type} | @dots{})} syntax. +@end itemize +@end deftp + +@deftp {record type} xml-!attlist name definitions +@vindex +@findex xml-!attlist? +@findex make-xml-!attlist +@findex xml-!attlist-name +@findex xml-!attlist-definitions +@findex set-xml-!attlist-name! +@findex set-xml-!attlist-definitions! +The @code{xml-!attlist} record represents an attribute-list +declaration. @var{Name} is the @acronym{XML} name of the type for +which attributes are being declared (a symbol). @var{Definitions} is +a list of attribute definitions, each of which is a list of three +elements @code{(@var{name} @var{type} @var{default})}. @var{Name} is +an @acronym{XML} name for the name of the attribute (a symbol). +@var{Type} describes the attribute type, and can have one of the +following values: + +@itemize @bullet +@item +The @acronym{XML} names @samp{CDATA}, @samp{IDREFS}, @samp{IDREF}, +@samp{ID}, @samp{ENTITY}, @samp{ENTITIES}, @samp{NMTOKENS}, and +@samp{NMTOKEN} correspond to the @acronym{XML} keywords of the same +names. + +@item +A list @samp{(NOTATION @var{name1} @var{name2} @dots{})} corresponds +to the @samp{NOTATION (@var{name1} | @var{name2} @dots{})} syntax. + +@item +A list @samp{(ENUMERATED @var{name1} @var{name2} @dots{})} corresponds +to the @samp{(@var{name1} | @var{name2} @dots{})} syntax. +@end itemize + +@var{Default} describes the default value for the attribute, and can +have one of the following values: + +@itemize @bullet +@item +The @acronym{XML} names @samp{#REQUIRED} and @samp{#IMPLIED} +correspond to the @acronym{XML} keywords of the same names. + +@item +A list @samp{(#FIXED @var{value})} corresponds to the @samp{#FIXED +"@var{value}"} syntax. @var{Value} is represented as a string, but +might also be an @code{xml-uninterpreted} record. + +@item +A list @samp{(DEFAULT @var{value})} corresponds to the +@samp{"@var{value}"} syntax. @var{Value} is represented as a string, +but might also be an @code{xml-uninterpreted} record. +@end itemize +@end deftp + +@deftp {record type} xml-!entity name value +@vindex +@findex xml-!entity? +@findex make-xml-!entity +@findex xml-!entity-name +@findex xml-!entity-value +@findex set-xml-!entity-name! +@findex set-xml-!entity-value! +The @code{xml-!entity} record represents a general entity +declaration. @var{Name} is an @acronym{XML} name for the entity. +@var{Value} is the entity's value, either a string, an +@code{xml-uninterpreted} record, or an @code{xml-external-id} record. +@end deftp + +@deftp {record type} xml-parameter-!entity name value +@vindex +@findex xml-parameter-!entity? +@findex make-xml-parameter-!entity +@findex xml-parameter-!entity-name +@findex xml-parameter-!entity-value +@findex set-xml-parameter-!entity-name! +@findex set-xml-parameter-!entity-value! +The @code{xml-parameter-!entity} record represents a parameter entity +declaration. @var{Name} is an @acronym{XML} name for the entity. +@var{Value} is the entity's value, either a string, an +@code{xml-uninterpreted} record, or an @code{xml-external-id} record. +@end deftp + +@deftp {record type} xml-unparsed-!entity name id notation +@vindex +@findex xml-unparsed-!entity? +@findex make-xml-unparsed-!entity +@findex xml-unparsed-!entity-name +@findex xml-unparsed-!entity-id +@findex xml-unparsed-!entity-notation +@findex set-xml-unparsed-!entity-name! +@findex set-xml-unparsed-!entity-id! +@findex set-xml-unparsed-!entity-notation! +The @code{xml-unparsed-!entity} record represents an unparsed entity +declaration. @code{Name} is an @acronym{XML} name for the entity. +@var{Id} is an @code{xml-external-id} record. @var{Notation} is an +@acronym{XML} name for the notation. +@end deftp + +@deftp {record type} xml-!notation name id +@vindex +@findex xml-!notation? +@findex make-xml-!notation +@findex xml-!notation-name +@findex xml-!notation-id +@findex set-xml-!notation-name! +@findex set-xml-!notation-id! +The @code{xml-!notation} record represents a notation declaration. +@code{Name} is an @acronym{XML} name for the notation. @var{Id} is an +@code{xml-external-id} record. +@end deftp + +@deftp {record type} xml-external-id id uri +@vindex +@findex xml-external-id? +@findex make-xml-external-id +@findex xml-external-id-id +@findex xml-external-id-uri +@findex set-xml-external-id-id! +@findex set-xml-external-id-uri! +The @code{xml-external-id} record is a reference to an external +@acronym{DTD}. This reference consists of two parts: @var{id} is a +public @acronym{ID} literal, corresponding to the @samp{PUBLIC} +keyword, while @var{uri} is a system literal, corresponding to the +@samp{SYSTEM} keyword. Either or both may be present, depending on +the context. Each is represented as a string. +@end deftp diff --git a/v7/doc/ref-manual/lists.texi b/v7/doc/ref-manual/lists.texi new file mode 100644 index 000000000..653cd25ed --- /dev/null +++ b/v7/doc/ref-manual/lists.texi @@ -0,0 +1,1116 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: lists.texi,v 1.1 2003/04/15 03:29:50 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Lists, Vectors, Strings, Top +@chapter Lists + +@cindex pair (defn) +@cindex dotted pair (see pair) +@cindex car field, of pair (defn) +@cindex cdr field, of pair (defn) +A @dfn{pair} (sometimes called a @dfn{dotted pair}) is a data structure +with two fields called the @dfn{car} and @dfn{cdr} fields (for +historical reasons). Pairs are created by the procedure @code{cons}. +The car and cdr fields are accessed by the procedures @code{car} and +@code{cdr}. The car and cdr fields are assigned by the procedures +@code{set-car!} and @code{set-cdr!}. + +@cindex list (defn) +Pairs are used primarily to represent @dfn{lists}. A list can be +defined recursively as either the empty list or a pair whose cdr is +a list. More precisely, the set of lists is defined as the smallest set +@var{X} such that + +@itemize @bullet +@item +The empty list is in @var{X}. + +@item +If @var{list} is in @var{X}, then any pair whose cdr field contains +@var{list} is also in @var{X}. +@end itemize + +@cindex element, of list (defn) +@cindex length, of list (defn) +@cindex empty list (defn) +The objects in the car fields of successive pairs of a list are the +@dfn{elements} of the list. For example, a two-element list is a pair +whose car is the first element and whose cdr is a pair whose car is the +second element and whose cdr is the empty list. The @dfn{length} of a +list is the number of elements, which is the same as the number of +pairs. The @dfn{empty list} is a special object of its own type (it is +not a pair); it has no elements and its length is zero.@footnote{The +above definitions imply that all lists have finite length and are +terminated by the empty list.} + +@cindex dotted notation, for pair (defn) +@cindex notation, dotted (defn) +@cindex external representation, for pair +@cindex pair, external representation +@cindex ( as external representation +@cindex ) as external representation +@cindex . as external representation +@cindex parenthesis, as external representation +@cindex dot, as external representation +@cindex period, as external representation +@findex ( +@findex ) +@findex . +The most general notation (external representation) for Scheme pairs is +the ``dotted'' notation @code{(@var{c1} . @var{c2})} where @var{c1} is +the value of the car field and @var{c2} is the value of the cdr field. +For example, @code{(4 . 5)} is a pair whose car is @code{4} and whose +cdr is @code{5}. Note that @code{(4 . 5)} is the external +representation of a pair, not an expression that evaluates to a pair. + +@cindex external representation, for list +@cindex list, external representation +@cindex external representation, for empty list +@cindex empty list, external representation +@findex () +A more streamlined notation can be used for lists: the elements of the +list are simply enclosed in parentheses and separated by spaces. The +empty list is written @code{()}. For example, the following are +equivalent notations for a list of symbols: + +@example +@group +(a b c d e) +(a . (b . (c . (d . (e . ()))))) +@end group +@end example + +@findex set-cdr! +Whether a given pair is a list depends upon what is stored in the cdr +field. When the @code{set-cdr!} procedure is used, an object can be a +list one moment and not the next: + +@example +@group +(define x (list 'a 'b 'c)) +(define y x) +y @result{} (a b c) +(list? y) @result{} #t +(set-cdr! x 4) @result{} @r{unspecified} +x @result{} (a . 4) +(eqv? x y) @result{} #t +y @result{} (a . 4) +(list? y) @result{} #f +(set-cdr! x x) @result{} @r{unspecified} +(list? y) @result{} #f +@end group +@end example + +@cindex improper list (defn) +@cindex list, improper (defn) +A chain of pairs that doesn't end in the empty list is called an +@dfn{improper list}. Note that an improper list is not a list. The +list and dotted notations can be combined to represent improper lists, +as the following equivalent notations show: + +@example +@group +(a b c . d) +(a . (b . (c . d))) +@end group +@end example + +@findex quote +@findex quasiquote +@findex unquote +@findex unquote-splicing +@findex ' +@findex ` +@findex , +@findex ,@@ +@findex read +Within literal expressions and representations of objects read by the +@code{read} procedure, the forms @code{'@var{datum}}, +@code{`@var{datum}}, @code{,@var{datum}}, and @code{,@@@var{datum}} +denote two-element lists whose first elements are the symbols +@code{quote}, @code{quasiquote}, @code{unquote}, and +@code{unquote-splicing}, respectively. The second element in each case +is @var{datum}. This convention is supported so that arbitrary Scheme +programs may be represented as lists. Among other things, this permits +the use of the @code{read} procedure to parse Scheme programs. + +@menu +* Pairs:: +* Construction of Lists:: +* Selecting List Components:: +* Cutting and Pasting Lists:: +* Filtering Lists:: +* Searching Lists:: +* Mapping of Lists:: +* Reduction of Lists:: +* Miscellaneous List Operations:: +@end menu + +@node Pairs, Construction of Lists, Lists, Lists +@section Pairs + +This section describes the simple operations that are available for +constructing and manipulating arbitrary graphs constructed from pairs. + +@deffn procedure pair? object +@cindex type predicate, for pair +Returns @code{#t} if @var{object} is a pair; otherwise returns +@code{#f}. + +@example +@group +(pair? '(a . b)) @result{} #t +(pair? '(a b c)) @result{} #t +(pair? '()) @result{} #f +(pair? '#(a b)) @result{} #f +@end group +@end example +@end deffn + +@deffn procedure cons obj1 obj2 +@cindex construction, of pair +@findex eqv? +Returns a newly allocated pair whose car is @var{obj1} and whose cdr is +@var{obj2}. The pair is guaranteed to be different (in the sense of +@code{eqv?}) from every previously existing object. + +@example +@group +(cons 'a '()) @result{} (a) +(cons '(a) '(b c d)) @result{} ((a) b c d) +(cons "a" '(b c)) @result{} ("a" b c) +(cons 'a 3) @result{} (a . 3) +(cons '(a b) 'c) @result{} ((a b) . c) +@end group +@end example +@end deffn + +@deffn procedure car pair +@cindex selection, of pair component +@cindex component selection, of pair +Returns the contents of the car field of @var{pair}. Note that it is an +error to take the @code{car} of the empty list. + +@example +@group +(car '(a b c)) @result{} a +(car '((a) b c d)) @result{} (a) +(car '(1 . 2)) @result{} 1 +(car '()) @error{} Illegal datum +@end group +@end example +@end deffn + +@deffn procedure cdr pair +Returns the contents of the cdr field of @var{pair}. Note that it is an +error to take the @code{cdr} of the empty list. + +@example +@group +(cdr '((a) b c d)) @result{} (b c d) +(cdr '(1 . 2)) @result{} 2 +(cdr '()) @error{} Illegal datum +@end group +@end example +@end deffn + +@deffn procedure set-car! pair object +Stores @var{object} in the car field of @var{pair}. The value returned +by @code{set-car!} is unspecified. + +@example +@group +(define (f) (list 'not-a-constant-list)) +(define (g) '(constant-list)) +(set-car! (f) 3) @result{} @r{unspecified} +(set-car! (g) 3) @error{} Illegal datum +@end group +@end example +@end deffn + +@deffn procedure set-cdr! pair object +Stores @var{object} in the cdr field of @var{pair}. The value returned +by @code{set-cdr!} is unspecified. +@end deffn + +@deffn procedure caar pair +@deffnx procedure cadr pair +@deffnx procedure cdar pair +@deffnx procedure cddr pair +@deffnx procedure caaar pair +@deffnx procedure caadr pair +@deffnx procedure cadar pair +@deffnx procedure caddr pair +@deffnx procedure cdaar pair +@deffnx procedure cdadr pair +@deffnx procedure cddar pair +@deffnx procedure cdddr pair +@deffnx procedure caaaar pair +@deffnx procedure caaadr pair +@deffnx procedure caadar pair +@deffnx procedure caaddr pair +@deffnx procedure cadaar pair +@deffnx procedure cadadr pair +@deffnx procedure caddar pair +@deffnx procedure cadddr pair +@deffnx procedure cdaaar pair +@deffnx procedure cdaadr pair +@deffnx procedure cdadar pair +@deffnx procedure cdaddr pair +@deffnx procedure cddaar pair +@deffnx procedure cddadr pair +@deffnx procedure cdddar pair +@deffnx procedure cddddr pair +These procedures are compositions of @code{car} and @code{cdr}; for +example, @code{caddr} could be defined by + +@example +(define caddr (lambda (x) (car (cdr (cdr x))))) +@end example +@end deffn + +@deffn procedure general-car-cdr object path +This procedure is a generalization of @code{car} and @code{cdr}. +@var{Path} encodes a particular sequence of @code{car} and @code{cdr} +operations, which @code{general-car-cdr} executes on @var{object}. +@var{Path} is an exact non-negative integer that encodes the operations +in a bitwise fashion: a zero bit represents a @code{cdr} operation, and +a one bit represents a @code{car}. The bits are executed LSB to MSB, +and the most significant one bit, rather than being interpreted as an +operation, signals the end of the sequence.@footnote{Note that +@var{path} is restricted to a machine-dependent range, usually the size +of a machine word. On many machines, this means that the maximum length +of @var{path} will be 30 operations (32 bits, less the sign bit and the +``end-of-sequence'' bit).} + +For example, the following are equivalent: +@example +@group +(general-car-cdr @var{object} #b1011) +(cdr (car (car @var{object}))) +@end group +@end example + +Here is a partial table of path/operation equivalents: + +@example +@group +#b10 cdr +#b11 car +#b100 cddr +#b101 cdar +#b110 cadr +#b111 caar +#b1000 cdddr +@end group +@end example +@end deffn + +@deffn procedure tree-copy tree +@cindex copying, of tree +@cindex tree, copying +This copies an arbitrary @var{tree} constructed from pairs, copying both +the car and cdr elements of every pair. This could have been defined by + +@example +@group +(define (tree-copy tree) + (let loop ((tree tree)) + (if (pair? tree) + (cons (loop (car tree)) (loop (cdr tree))) + tree))) +@end group +@end example +@end deffn + +@node Construction of Lists, Selecting List Components, Pairs, Lists +@section Construction of Lists +@cindex construction, of list + +@deffn procedure list object @dots{} +Returns a list of its arguments. + +@example +@group +(list 'a (+ 3 4) 'c) @result{} (a 7 c) +(list) @result{} () +@end group +@end example + +These expressions are equivalent: + +@example +@group +(list @var{obj1} @var{obj2} @dots{} @var{objN}) +(cons @var{obj1} (cons @var{obj2} @dots{} (cons @var{objN} '()) @dots{})) +@end group +@end example +@end deffn + +@deffn procedure make-list k [element] +This procedure returns a newly allocated list of length @var{k}, +whose elements are all @var{element}. If @var{element} is not supplied, +it defaults to the empty list. +@end deffn + +@deffn procedure cons* object object @dots{} +@findex list +@code{cons*} is similar to @code{list}, except that @code{cons*} conses +together the last two arguments rather than consing the last argument +with the empty list. If the last argument is not a list the result is +an improper list. If the last argument is a list, the result is a list +consisting of the initial arguments and all of the items in the final +argument. If there is only one argument, the result is the argument. + +@example +@group +(cons* 'a 'b 'c) @result{} (a b . c) +(cons* 'a 'b '(c d)) @result{} (a b c d) +(cons* 'a) @result{} a +@end group +@end example + +These expressions are equivalent: + +@example +@group +(cons* @var{obj1} @var{obj2} @dots{} @var{objN-1} @var{objN}) +(cons @var{obj1} (cons @var{obj2} @dots{} (cons @var{objN-1} @var{objN}) @dots{})) +@end group +@end example +@end deffn + +@deffn procedure list-copy list +Returns a newly allocated copy of @var{list}. This copies each of the +pairs comprising @var{list}. This could have been defined by + +@example +@group +(define (list-copy list) + (if (null? list) + '() + (cons (car list) + (list-copy (cdr list))))) +@end group +@end example +@end deffn + +@deffn procedure vector->list vector +@deffnx procedure subvector->list vector start end +@cindex vector, converting to list +@findex list->vector +@code{vector->list} returns a newly allocated list of the elements of +@var{vector}.@* @code{subvector->list} returns a newly allocated list of +the elements of the given subvector. The inverse of @code{vector->list} +is @code{list->vector}. + +@example +(vector->list '#(dah dah didah)) @result{} (dah dah didah) +@end example +@end deffn + +@deffn {procedure} string->list string +@deffnx {procedure} substring->list string start end +@cindex string, converting to list +@findex list->string +@code{string->list} returns a newly allocated list of the character +elements of @var{string}.@* +@code{substring->list} returns a newly allocated list of the character +elements of the given substring. The inverse of @code{string->list} is +@code{list->string}. + +@example +@group +(string->list "abcd") @result{} (#\a #\b #\c #\d) +(substring->list "abcdef" 1 3) @result{} (#\b #\c) +@end group +@end example +@end deffn + +@node Selecting List Components, Cutting and Pasting Lists, Construction of Lists, Lists +@section Selecting List Components +@cindex selection, of list component +@cindex component selection, of list + +@deffn procedure list? object +@cindex type predicate, for list +@cindex circular list +Returns @code{#t} if @var{object} is a list, otherwise returns +@code{#f}. By definition, all lists have finite length and are +terminated by the empty list. This procedure returns an answer even for +circular structures. + +@findex pair? +@findex null? +Any @var{object} satisfying this predicate will also satisfy exactly one +of @code{pair?} or @code{null?}. + +@example +@group +(list? '(a b c)) @result{} #t +(list? '()) @result{} #t +(list? '(a . b)) @result{} #f +(let ((x (list 'a))) + (set-cdr! x x) + (list? x)) @result{} #f +@end group +@end example +@end deffn + +@deffn procedure length list +Returns the length of @var{list}. Signals an error if @var{list} isn't +a proper list. + +@example +@group +(length '(a b c)) @result{} 3 +(length '(a (b) (c d e))) @result{} 3 +(length '()) @result{} 0 +@end group +@end example +@end deffn + +@deffn procedure null? object +@cindex type predicate, for empty list +@cindex empty list, predicate for +Returns @code{#t} if @var{object} is the empty list; otherwise returns +@code{#f} (but @pxref{True and False}). + +@example +@group +(null? '(a . b)) @result{} #f +(null? '(a b c)) @result{} #f +(null? '()) @result{} #t +@end group +@end example +@end deffn + +@deffn procedure list-ref list k +@cindex index, of list (defn) +@cindex valid index, of list (defn) +@cindex list index (defn) +Returns the @var{k}th element of @var{list}, using zero-origin indexing. +The @dfn{valid indexes} of a list are the exact non-negative integers +less than the length of the list. The first element of a list has index +@code{0}, the second has index @code{1}, and so on. + +@example +@group +(list-ref '(a b c d) 2) @result{} c +(list-ref '(a b c d) + (inexact->exact (round 1.8))) + @result{} c +@end group +@end example + +@findex list-tail +@code{(list-ref @var{list} @var{k})} is equivalent to @code{(car +(list-tail @var{list} @var{k}))}. +@end deffn + +@deffn procedure first list +@deffnx procedure second list +@deffnx procedure third list +@deffnx procedure fourth list +@deffnx procedure fifth list +@deffnx procedure sixth list +@deffnx procedure seventh list +@deffnx procedure eighth list +@deffnx procedure ninth list +@deffnx procedure tenth list +Returns the specified element of @var{list}. It is an error if +@var{list} is not long enough to contain the specified element (for +example, if the argument to @code{seventh} is a list that contains only +six elements). +@end deffn + +@node Cutting and Pasting Lists, Filtering Lists, Selecting List Components, Lists +@section Cutting and Pasting Lists +@cindex cutting, of list +@cindex pasting, of lists + +@deffn procedure sublist list start end +@var{Start} and @var{end} must be exact integers satisfying + +@example +0 <= @var{start} <= @var{end} <= (length @var{list}) +@end example + +@code{sublist} returns a newly allocated list formed from the elements +of @var{list} beginning at index @var{start} (inclusive) and ending at +@var{end} (exclusive). +@end deffn + +@deffn procedure list-head list k +Returns a newly allocated list consisting of the first @var{k} elements of +@var{list}. @var{K} must not be greater than the length of +@var{list}. + +We could have defined @code{list-head} this way: + +@example +@group +(define (list-head list k) + (sublist list 0 k)) +@end group +@end example +@end deffn + +@deffn procedure list-tail list k +Returns the sublist of @var{list} obtained by omitting the first @var{k} +elements. The result, if it is not the empty list, shares structure +with @var{list}. @var{K} must not be greater than the length of +@var{list}. +@end deffn + +@deffn {procedure} append list @dots{} +@cindex appending, of lists +Returns a list consisting of the elements of the first @var{list} +followed by the elements of the other @var{list}s. + +@example +@group +(append '(x) '(y)) @result{} (x y) +(append '(a) '(b c d)) @result{} (a b c d) +(append '(a (b)) '((c))) @result{} (a (b) (c)) +(append) @result{} () +@end group +@end example + +The resulting list is always newly allocated, except that it shares +structure with the last @var{list} argument. The last argument may +actually be any object; an improper list results if the last argument is +not a proper list. + +@example +@group +(append '(a b) '(c . d)) @result{} (a b c . d) +(append '() 'a) @result{} a +@end group +@end example +@end deffn + +@deffn procedure append! list @dots{} +Returns a list that is the argument @var{list}s concatenated together. +The arguments are changed rather than copied. (Compare this with +@code{append}, which copies arguments rather than destroying them.) For +example: + +@example +@group +(define x '(a b c)) +(define y '(d e f)) +(define z '(g h)) +(append! x y z) @result{} (a b c d e f g h) +x @result{} (a b c d e f g h) +y @result{} (d e f g h) +z @result{} (g h) +@end group +@end example +@end deffn + +@deffn procedure last-pair list +Returns the last pair in @var{list}, which may be an improper list. +@code{last-pair} could have been defined this way: + +@example +@group +(define last-pair + (lambda (x) + (if (pair? (cdr x)) + (last-pair (cdr x)) + x))) +@end group +@end example +@end deffn + +@deffn procedure except-last-pair list +@deffnx procedure except-last-pair! list +These procedures remove the last pair from @var{list}. @var{List} may +be an improper list, except that it must consist of at least one pair. +@code{except-last-pair} returns a newly allocated copy of @var{list} +that omits the last pair. @code{except-last-pair!} destructively +removes the last pair from @var{list} and returns @var{list}. If the +cdr of @var{list} is not a pair, the empty list is returned by either +procedure. +@end deffn + +@node Filtering Lists, Searching Lists, Cutting and Pasting Lists, Lists +@section Filtering Lists +@cindex filtering, of list +@cindex deletion, of list element + +@deffn procedure keep-matching-items list predicate +@deffnx procedure delete-matching-items list predicate +These procedures return a newly allocated copy of @var{list} containing +only the elements for which @var{predicate} is (respectively) true or +false. @var{Predicate} must be a procedure of one argument. + +@example +@group +(keep-matching-items '(1 2 3 4 5) odd?) @result{} (1 3 5) +(delete-matching-items '(1 2 3 4 5) odd?) @result{} (2 4) +@end group +@end example + +@findex list-transform-positive +@findex list-transform-negative +For compatibility, the procedure @code{list-transform-positive} is an +alias for @code{keep-matching-items}, and @code{list-transform-negative} +is an alias for @code{delete-matching-items}. +@end deffn + +@deffn procedure keep-matching-items! list predicate +@deffnx procedure delete-matching-items! list predicate +These procedures are exactly like @code{keep-matching-items} and +@code{delete-matching-items}, respectively, except that they +destructively modify the @var{list} argument rather than allocating a +new result. +@end deffn + +@deffn procedure delq element list +@deffnx procedure delv element list +@deffnx procedure delete element list +@findex eq? +@findex eqv? +@findex equal? +Returns a newly allocated copy of @var{list} with all entries equal to +@var{element} removed. @code{delq} uses @code{eq?} to compare +@var{element} with the entries in @var{list}, @code{delv} uses +@code{eqv?}, and @code{delete} uses @code{equal?}. +@end deffn + +@deffn procedure delq! element list +@deffnx procedure delv! element list +@deffnx procedure delete! element list +@findex eq? +@findex eqv? +@findex equal? +Returns a list consisting of the top-level elements of @var{list} with +all entries equal to @var{element} removed. These procedures are like +@code{delq}, @code{delv}, and @code{delete} except that they +destructively modify @var{list}. @code{delq!} uses @code{eq?} to +compare element with the entries in @var{list}, @code{delv!} uses +@code{eqv?}, and @code{delete!} uses @code{equal?}. Because the result +may not be @code{eq?} to @var{list}, it is desirable to do something +like @code{(set! x (delete! x))}. + +@example +@group +(define x '(a b c b)) +(delete 'b x) @result{} (a c) +x @result{} (a b c b) + +(define x '(a b c b)) +(delete! 'b x) @result{} (a c) +x @result{} (a c) +@r{;; Returns correct result:} +(delete! 'a x) @result{} (c) + +@r{;; Didn't modify what x points to:} +x @result{} (a c) +@end group +@end example +@end deffn + +@deffn procedure delete-member-procedure deletor predicate +@findex list-deletor +@findex list-deletor! +@findex delv +@findex delete! +Returns a deletion procedure similar to @code{delv} or @code{delete!}. +@var{Deletor} should be one of the procedures @code{list-deletor} or +@code{list-deletor!}. @var{Predicate} must be an equivalence predicate. +The returned procedure accepts exactly two arguments: first, an object +to be deleted, and second, a list of objects from which it is to be +deleted. If @var{deletor} is @code{list-deletor}, the procedure +returns a newly allocated copy of the given list in which all entries +equal to the given object have been removed. If @var{deletor} is +@code{list-deletor!}, the procedure returns a list consisting of the +top-level elements of the given list with all entries equal to the given +object removed; the given list is destructively modified to produce the +result. In either case @var{predicate} is used to compare the given +object to the elements of the given list. + +Here are some examples that demonstrate how +@code{delete-member-procedure} could have been used to implement +@code{delv} and @code{delete!}: + +@example +@group +(define delv + (delete-member-procedure list-deletor eqv?)) +(define delete! + (delete-member-procedure list-deletor! equal?)) +@end group +@end example +@end deffn + +@deffn procedure list-deletor predicate +@deffnx procedure list-deletor! predicate +These procedures each return a procedure that deletes elements from +lists. @var{Predicate} must be a procedure of one argument. The +returned procedure accepts exactly one argument, which must be a proper +list, and applies @var{predicate} to each of the elements of the +argument, deleting those for which it is true. + +The procedure returned by @code{list-deletor} deletes elements +non-destructively, by returning a newly allocated copy of the argument +with the appropriate elements removed. The procedure returned by +@code{list-deletor!} performs a destructive deletion. +@end deffn + +@node Searching Lists, Mapping of Lists, Filtering Lists, Lists +@section Searching Lists +@cindex searching, of list + +@deffn procedure find-matching-item list predicate +Returns the first element in @var{list} for which @var{predicate} is +true; returns @code{#f} if it doesn't find such an element. (This means +that if @var{predicate} is true for @code{#f}, it may be impossible to +distinguish a successful result from an unsuccessful one.) +@var{Predicate} must be a procedure of one argument. + +@findex list-search-positive +@findex list-search-negative +For compatibility, @code{list-search-positive} is an alias for +@code{find-matching-item}. @code{list-search-negative} is similar but +the sense of the predicate is reversed. +@end deffn + +@deffn procedure memq object list +@deffnx procedure memv object list +@deffnx procedure member object list +@findex eq? +@findex eqv? +@findex equal? +These procedures return the first pair of @var{list} whose car is +@var{object}; the returned pair is always one from which @var{list} is +composed. If @var{object} does not occur in @var{list}, @code{#f} +(n.b.: not the empty list) is returned. @code{memq} uses @code{eq?} to +compare @var{object} with the elements of @var{list}, while @code{memv} +uses @code{eqv?} and @code{member} uses @code{equal?}.@footnote{Although +they are often used as predicates, @code{memq}, @code{memv}, and +@code{member} do not have question marks in their names because they +return useful values rather than just @code{#t} or @code{#f}.} + +@example +@group +(memq 'a '(a b c)) @result{} (a b c) +(memq 'b '(a b c)) @result{} (b c) +(memq 'a '(b c d)) @result{} #f +(memq (list 'a) '(b (a) c)) @result{} #f +(member (list 'a) '(b (a) c)) @result{} ((a) c) +(memq 101 '(100 101 102)) @result{} @r{unspecified} +(memv 101 '(100 101 102)) @result{} (101 102) +@end group +@end example +@end deffn + +@deffn procedure member-procedure predicate +Returns a procedure similar to @code{memq}, except that @var{predicate}, +which must be an equivalence predicate, is used instead of @code{eq?}. +This could be used to define @code{memv} as follows: + +@example +(define memv (member-procedure eqv?)) +@end example +@end deffn + +@need 1000 +@node Mapping of Lists, Reduction of Lists, Searching Lists, Lists +@section Mapping of Lists +@cindex mapping, of list + +@deffn {procedure} map procedure list list @dots{} +@var{Procedure} must be a procedure taking as many arguments as there +are @var{list}s. If more than one @var{list} is given, then they must +all be the same length. @code{map} applies @var{procedure} element-wise +to the elements of the @var{list}s and returns a list of the results, in +order from left to right. The dynamic order in which @var{procedure} is +applied to the elements of the @var{list}s is unspecified; use +@code{for-each} to sequence side effects. + +@example +@group +(map cadr '((a b) (d e) (g h))) @result{} (b e h) +(map (lambda (n) (expt n n)) '(1 2 3 4)) @result{} (1 4 27 256) +(map + '(1 2 3) '(4 5 6)) @result{} (5 7 9) +(let ((count 0)) + (map (lambda (ignored) + (set! count (+ count 1)) + count) + '(a b c))) @result{} @r{unspecified} +@end group +@end example +@end deffn + +@deffn procedure map* initial-value procedure list1 list2 @dots{} +Similar to @code{map}, except that the resulting list is terminated by +@var{initial-value} rather than the empty list. The following are +equivalent: + +@example +@group +(map @var{procedure} @var{list} @var{list} @dots{}) +(map* '() @var{procedure} @var{list} @var{list} @dots{}) +@end group +@end example +@end deffn + +@deffn procedure append-map procedure list list @dots{} +@deffnx procedure append-map* initial-value procedure list list @dots{} +@findex append +Similar to @code{map} and @code{map*}, respectively, except that the +results of applying @var{procedure} to the elements of @var{list}s are +concatenated together by @code{append} rather than by @code{cons}. The +following are equivalent, except that the former is more efficient: + +@example +@group +(append-map @var{procedure} @var{list} @var{list} @dots{}) +(apply append (map @var{procedure} @var{list} @var{list} @dots{})) +@end group +@end example +@end deffn + +@deffn procedure append-map! procedure list list @dots{} +@deffnx procedure append-map*! initial-value procedure list list @dots{} +@findex append! +Similar to @code{map} and @code{map*}, respectively, except that the +results of applying @var{procedure} to the elements of @var{list}s are +concatenated together by @code{append!} rather than by @code{cons}. The +following are equivalent, except that the former is more efficient: + +@example +@group +(append-map! @var{procedure} @var{list} @var{list} @dots{}) +(apply append! (map @var{procedure} @var{list} @var{list} @dots{})) +@end group +@end example +@end deffn + +@deffn {procedure} for-each procedure list list @dots{} +The arguments to @code{for-each} are like the arguments to @code{map}, +but @code{for-each} calls @var{procedure} for its side effects rather +than for its values. Unlike @code{map}, @code{for-each} is guaranteed +to call @var{procedure} on the elements of the @var{list}s in order from +the first element to the last, and the value returned by @code{for-each} +is unspecified. + +@example +@group +(let ((v (make-vector 5))) + (for-each (lambda (i) + (vector-set! v i (* i i))) + '(0 1 2 3 4)) + v) @result{} #(0 1 4 9 16) +@end group +@end example +@end deffn + +@node Reduction of Lists, Miscellaneous List Operations, Mapping of Lists, Lists +@section Reduction of Lists +@cindex reduction, of list + +@deffn procedure reduce procedure initial list +Combines all the elements of @var{list} using the binary operation +@var{procedure}. For example, using @code{+} one can add up all the +elements: + +@example +(reduce + 0 list-of-numbers) +@end example + +The argument @var{initial} is used only if @var{list} is empty; in this +case @var{initial} is the result of the call to @code{reduce}. If +@var{list} has a single argument, it is returned. Otherwise, the arguments +are reduced in a left-associative fashion. For example: + +@example +@group +(reduce + 0 '(1 2 3 4)) @result{} 10 +(reduce + 0 '(1 2)) @result{} 3 +(reduce + 0 '(1)) @result{} 1 +(reduce + 0 '()) @result{} 0 +(reduce + 0 '(foo)) @result{} foo +(reduce list '() '(1 2 3 4)) @result{} (((1 2) 3) 4) +@end group +@end example +@end deffn + +@deffn procedure reduce-right procedure initial list +Like @code{reduce} except that it is right-associative. + +@example +(reduce-right list '() '(1 2 3 4)) @result{} (1 (2 (3 4))) +@end example +@end deffn + +@deffn procedure fold-right procedure initial list +Combines all of the elements of @var{list} using the binary operation +@var{procedure}. Unlike @code{reduce} and @code{reduce-right}, +@var{initial} is always used: + +@example +@group +(fold-right + 0 '(1 2 3 4)) @result{} 10 +(fold-right + 0 '(foo)) @error{} Illegal datum +(fold-right list '() '(1 2 3 4)) @result{} (1 (2 (3 (4 ())))) +@end group +@end example + +@code{Fold-right} has interesting properties because it establishes a +homomorphism between (@code{cons}, @code{()}) and (@var{procedure}, +@var{initial}). It can be thought of as replacing the pairs in the +spine of the list with @var{procedure} and replacing the @code{()} at +the end with @var{initial}. Many of the classical list-processing +procedures can be expressed in terms of @code{fold-right}, at least for +the simple versions that take a fixed number of arguments: + +@example +@group +(define (copy-list list) + (fold-right cons '() list)) + +(define (append list1 list2) + (fold-right cons list2 list1)) + +(define (map p list) + (fold-right (lambda (x r) (cons (p x) r)) '() list)) + +(define (reverse items) + (fold-right (lambda (x r) (append r (list x))) '() items)) +@end group +@end example +@end deffn + +@deffn procedure fold-left procedure initial list +Combines all the elements of @var{list} using the binary operation +@var{procedure}. Elements are combined starting with @var{initial} and +then the elements of @var{list} from left to right. Whereas +@code{fold-right} is recursive in nature, capturing the essence of +@code{cdr}-ing down a list and then computing a result, @var{fold-left} +is iterative in nature, combining the elements as the list is traversed. + +@example +@group +(fold-left list '() '(1 2 3 4)) @result{} ((((() 1) 2) 3) 4) + +(define (length list) + (fold-left (lambda (sum element) (+ sum 1)) 0 list)) + +(define (reverse items) + (fold-left (lambda (x y) (cons y x)) () items)) +@end group +@end example +@end deffn + +@deffn procedure there-exists? list predicate +@var{Predicate} must be a procedure of one argument. Applies +@var{predicate} to each element of @var{list}, in order from left to +right. If @var{predicate} is true for any element of @var{list}, the +value yielded by @var{predicate} is immediately returned as the value of +@code{there-exists?}; @var{predicate} will not be applied to the +remaining elements of @var{list}. If @var{predicate} returns @code{#f} +for all of the elements of @var{list}, then @code{#f} is returned. +@end deffn + +@deffn procedure for-all? list predicate +@var{Predicate} must be a procedure of one argument. Applies +@var{predicate} to each element of @var{list}, in order from left to +right. If @var{predicate} returns @code{#f} for any element of +@var{list}, @code{#f} is immediately returned as the value of +@code{for-all?}; @var{predicate} will not be applied to the remaining +elements of @var{list}. If @var{predicate} is true for all of the +elements of @var{list}, then @code{#t} is returned. +@end deffn + +@node Miscellaneous List Operations, , Reduction of Lists, Lists +@section Miscellaneous List Operations + +@deffn procedure circular-list object @dots{} +@deffnx procedure make-circular-list k [element] +@cindex circular list +@cindex construction, of circular list +@findex list +@findex make-list +These procedures are like @code{list} and @code{make-list}, +respectively, except that the returned lists are circular. +@code{circular-list} could have been defined like this: + +@example +@group +(define (circular-list . objects) + (append! objects objects)) +@end group +@end example +@end deffn + +@deffn procedure reverse list +@cindex reversal, of list +Returns a newly allocated list consisting of the top-level elements of +@var{list} in reverse order. + +@example +@group +(reverse '(a b c)) @result{} (c b a) +(reverse '(a (b c) d (e (f)))) @result{} ((e (f)) d (b c) a) +@end group +@end example +@end deffn + +@deffn procedure reverse! list +Returns a list consisting of the top-level elements of @var{list} in +reverse order. @code{reverse!} is like @code{reverse}, except that it +destructively modifies @var{list}. Because the result may not be +@code{eqv?} to @var{list}, it is desirable to do something like +@code{(set! x (reverse! x))}. +@end deffn + +@deffn procedure sort sequence procedure +@deffnx procedure merge-sort sequence procedure +@deffnx procedure quick-sort sequence procedure +@cindex total ordering (defn) +@var{Sequence} must be either a list or a vector. @var{Procedure} must be a +procedure of two arguments that defines a @dfn{total ordering} on the +elements of @var{sequence}. In other words, if @var{x} and @var{y} are two +distinct elements of @var{sequence}, then it must be the case that + +@example +@group +(and (@var{procedure} @var{x} @var{y}) + (@var{procedure} @var{y} @var{x})) + @result{} #f +@end group +@end example + +If @var{sequence} is a list (vector), @code{sort} returns a newly +allocated list (vector) whose elements are those of @var{sequence}, +except that they are rearranged to be sorted in the order defined by +@var{procedure}. So, for example, if the elements of @var{sequence} are +numbers, and @var{procedure} is @code{<}, then the resulting elements +are sorted in monotonically nondecreasing order. Likewise, if +@var{procedure} is @code{>}, the resulting elements are sorted in +monotonically nonincreasing order. To be precise, if @var{x} and +@var{y} are any two adjacent elements in the result, where @var{x} +precedes @var{y}, it is the case that + +@example +@group +(@var{procedure} @var{y} @var{x}) + @result{} #f +@end group +@end example + +Two sorting algorithms are implemented: @code{merge-sort} and +@code{quick-sort}. The procedure @code{sort} is an alias for +@code{merge-sort}. + +See also the definition of @code{sort!}. +@end deffn diff --git a/v7/doc/ref-manual/misc-datatypes.texi b/v7/doc/ref-manual/misc-datatypes.texi new file mode 100644 index 000000000..90645c085 --- /dev/null +++ b/v7/doc/ref-manual/misc-datatypes.texi @@ -0,0 +1,937 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: misc-datatypes.texi,v 1.1 2003/04/15 03:29:53 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Miscellaneous Datatypes, Associations, Bit Strings, Top +@chapter Miscellaneous Datatypes + +@menu +* Booleans:: +* Symbols:: +* Cells:: +* Records:: +* Promises:: +* Streams:: +* Weak Pairs:: +@end menu + +@node Booleans, Symbols, Miscellaneous Datatypes, Miscellaneous Datatypes +@section Booleans + +@findex #t +@findex #f +@cindex #t as external representation +@cindex #f as external representation +@cindex boolean object (defn) +@cindex true, boolean object (defn) +@cindex false, boolean object (defn) +The @dfn{boolean objects} are @dfn{true} and @dfn{false}. The boolean +constant true is written as @samp{#t}, and the boolean constant false is +written as @samp{#f}. + +@findex if +@findex cond +@findex and +@findex or +The primary use for boolean objects is in the conditional expressions +@code{if}, @code{cond}, @code{and}, and @code{or}; the behavior of these +expressions is determined by whether objects are true or false. These +expressions count only @code{#f} as false. They count everything else, +including @code{#t}, pairs, symbols, numbers, strings, vectors, and +procedures as true (but @pxref{True and False}). + +@findex t +@findex nil +Programmers accustomed to other dialects of Lisp should note that Scheme +distinguishes @code{#f} and the empty list from the symbol @code{nil}. +Similarly, @code{#t} is distinguished from the symbol @code{t}. In +fact, the boolean objects (and the empty list) are not symbols at all. + +Boolean constants evaluate to themselves, so you don't need to quote +them. + +@example +@group +#t @result{} #t +#f @result{} #f +'#f @result{} #f +t @error{} Unbound variable +@end group +@end example + +@defvr variable false +@defvrx variable true +These variables are bound to the objects @code{#f} and @code{#t} +respectively. The compiler, given the @code{usual-integrations} +declaration, replaces references to these variables with their +respective values. + +Note that the symbol @code{true} is not equivalent to @code{#t}, and the +symbol @code{false} is not equivalent to @code{#f}. +@end defvr + +@deffn procedure boolean? object +@cindex type predicate, for boolean +Returns @code{#t} if @var{object} is either @code{#t} or @code{#f}; +otherwise returns @code{#f}. + +@example +@group +(boolean? #f) @result{} #t +(boolean? 0) @result{} #f +@end group +@end example +@end deffn + +@deffn procedure not object +@deffnx procedure false? object +@cindex false, predicate for +@cindex inverse, of boolean object +These procedures return @code{#t} if @var{object} is false; otherwise +they return @code{#f}. In other words they @emph{invert} boolean +values. These two procedures have identical semantics; their names are +different to give different connotations to the test. + +@example +@group +(not #t) @result{} #f +(not 3) @result{} #f +(not (list 3)) @result{} #f +(not #f) @result{} #t +@end group +@end example +@end deffn + +@deffn procedure boolean=? obj1 obj2 +@cindex boolean object, equivalence predicate +@cindex equivalence predicate, for boolean objects +@cindex comparison, of boolean objects +This predicate is true iff @var{obj1} and @var{obj2} are either both true +or both false. +@end deffn + +@deffn procedure boolean/and object @dots{} +This procedure returns @code{#t} if none of its arguments are @code{#f}. +Otherwise it returns @code{#f}. +@end deffn + +@deffn procedure boolean/or object @dots{} +This procedure returns @code{#f} if all of its arguments are @code{#f}. +Otherwise it returns @code{#t}. +@end deffn + +@node Symbols, Cells, Booleans, Miscellaneous Datatypes +@section Symbols + +@cindex symbol (defn) +@cindex interned symbol (defn) +@cindex uninterned symbol (defn) +@cindex property list, of symbol +@cindex disembodied property list +@findex read +MIT/GNU Scheme provides two types of symbols: @dfn{interned} and +@dfn{uninterned}. Interned symbols are far more common than uninterned +symbols, and there are more ways to create them. Interned symbols have +an external representation that is recognized by the procedure +@code{read}; uninterned symbols do not.@footnote{In older dialects of +Lisp, uninterned symbols were fairly important. This was true because +symbols were complicated data structures: in addition to having value +cells (and sometimes, function cells), these structures contained +@dfn{property lists}. Because of this, uninterned symbols were often +used merely for their property lists --- sometimes an uninterned symbol +used this way was referred to as a @dfn{disembodied property list}. In +MIT/GNU Scheme, symbols do not have property lists, or any other components +besides their names. There is a different data structure similar to +disembodied property lists: one-dimensional tables (@pxref{1D Tables}). +For these reasons, uninterned symbols are not very useful in MIT/GNU Scheme. +In fact, their primary purpose is to simplify the generation of unique +variable names in programs that generate Scheme code.} + +@findex string=? +@findex eq? +Interned symbols have an extremely useful property: any two interned +symbols whose names are the same, in the sense of @code{string=?}, are +the same object (i.e.@: they are @code{eq?} to one another). The term +@dfn{interned} refers to the process of @dfn{interning} by which this is +accomplished. Uninterned symbols do not share this property. + +@cindex case, of interned symbol +@cindex alphabetic case, of interned symbol +@findex write +The names of interned symbols are not distinguished by their alphabetic +case. Because of this, MIT/GNU Scheme converts all alphabetic +characters in the name of an interned symbol to a specific case (lower +case) when the symbol is created. When the name of an interned symbol +is referenced (using @code{symbol->string}) or written (using +@code{write}) it appears in this case. It is a bad idea to depend on +the name being lower case. In fact, it is preferable to take this one +step further: don't depend on the name of a symbol being in a uniform +case. + +@cindex external representation, for symbol +@findex read +@findex write +The rules for writing an interned symbol are the same as the rules for +writing an identifier (@pxref{Identifiers}). Any interned symbol that +has been returned as part of a literal expression, or read using the +@code{read} procedure and subsequently written out using the +@code{write} procedure, will read back in as the identical symbol (in +the sense of @code{eq?}). + +Usually it is also true that reading in an interned symbol that was +previously written out produces the same symbol. An exception are +symbols created by the procedures @code{string->symbol} and +@code{intern}; they can create symbols for which this write/read +invariance may not hold because the symbols' names contain special +characters or letters in the non-standard case.@footnote{MIT/GNU Scheme +reserves a specific set of interned symbols for its own use. If you use +these reserved symbols it is possible that you could break specific +pieces of software that depend on them. The reserved symbols all have +names beginning with the characters @samp{#[} and ending with the +character @samp{]}; thus none of these symbols can be read by the +procedure @code{read} and hence are not likely to be used by accident. +For example, @code{(intern "#[unnamed-procedure]")} produces a reserved +symbol.} + +@findex read +The external representation for uninterned symbols is special, to +distinguish them from interned symbols and prevent them from being +recognized by the @code{read} procedure: + +@example +@group +(string->uninterned-symbol "foo") + @result{} #[uninterned-symbol 30 foo] +@end group +@end example + +In this section, the procedures that return symbols as values will +either always return interned symbols, or always return uninterned +symbols. The procedures that accept symbols as arguments will always +accept either interned or uninterned symbols, and do not distinguish the +two. + +@deffn procedure symbol? object +@cindex type predicate, for symbol +Returns @code{#t} if @var{object} is a symbol, otherwise returns +@code{#f}. + +@example +@group +(symbol? 'foo) @result{} #t +(symbol? (car '(a b))) @result{} #t +(symbol? "bar") @result{} #f +@end group +@end example +@end deffn + +@deffn procedure symbol->string symbol +@cindex name, of symbol +@cindex print name, of symbol +@findex string=? +@findex string-set! +Returns the name of @var{symbol} as a string. If @var{symbol} was +returned by @code{string->symbol}, the value of this procedure will be +identical (in the sense of @code{string=?}) to the string that was +passed to @code{string->symbol}. It is an error to apply mutation +procedures such as @code{string-set!} to strings returned by this +procedure. + +@example +@group +(symbol->string 'flying-fish) @result{} "flying-fish" +(symbol->string 'Martin) @result{} "martin" +(symbol->string (string->symbol "Malvina")) + @result{} "Malvina" +@end group +@end example + +Note that two distinct uninterned symbols can have the same name. +@end deffn + +@deffn procedure intern string +@cindex interning, of symbols +@cindex construction, of symbols +Returns the interned symbol whose name is @var{string}. Converts +@var{string} to the standard alphabetic case before generating the +symbol. This is the preferred way to create interned symbols, as it +guarantees the following independent of which case the implementation +uses for symbols' names: + +@example +(eq? 'bitBlt (intern "bitBlt")) @result{} #t +@end example + +The user should take care that @var{string} obeys the rules for +identifiers (@pxref{Identifiers}), otherwise the resulting symbol cannot +be read as itself. +@end deffn + +@deffn procedure intern-soft string +Returns the interned symbol whose name is @var{string}. Converts +@var{string} to the standard alphabetic case before generating the +symbol. If no such interned symbol exists, returns @code{#f}. + +This is exactly like @code{intern}, except that it will not create an +interned symbol, but only returns symbols that already exist. +@end deffn + +@deffn procedure string->symbol string +@cindex string, interning as symbol +Returns the interned symbol whose name is @var{string}. Although you +can use this procedure to create symbols with names containing special +characters or lowercase letters, it's usually a bad idea to create such +symbols because they cannot be read as themselves. See +@code{symbol->string}. + +@example +@group +(eq? 'mISSISSIppi 'mississippi) @result{} #t +(string->symbol "mISSISSIppi") + @result{} @r{the symbol with the name} "mISSISSIppi" +(eq? 'bitBlt (string->symbol "bitBlt")) @result{} #f +(eq? 'JollyWog + (string->symbol + (symbol->string 'JollyWog))) @result{} #t +(string=? "K. Harper, M.D." + (symbol->string + (string->symbol + "K. Harper, M.D."))) @result{} #t +@end group +@end example +@end deffn + +@deffn procedure string->uninterned-symbol string +Returns a newly allocated uninterned symbol whose name is @var{string}. +It is unimportant what case or characters are used in +@var{string}. + +Note: this is the fastest way to make a symbol. +@end deffn + +@deffn procedure generate-uninterned-symbol [object] +@cindex gensym (see uninterned symbol) +@findex eq? +Returns a newly allocated uninterned symbol that is guaranteed to be +different from any other object. The symbol's name consists of a prefix +string followed by the (exact non-negative integer) value of an internal +counter. The counter is initially zero, and is incremented after each +call to this procedure. + +The optional argument @var{object} is used to control how the symbol is +generated. It may take one of the following values: + +@itemize @bullet +@item +If @var{object} is omitted or @code{#f}, the prefix is @code{"G"}. + +@item +If @var{object} is an exact non-negative integer, the internal counter +is set to that integer prior to generating the result. + +@item +If @var{object} is a string, it is used as the prefix. + +@item +If @var{object} is a symbol, its name is used as the prefix. +@end itemize + +@example +@group +(generate-uninterned-symbol) + @result{} #[uninterned-symbol 31 G0] +(generate-uninterned-symbol) + @result{} #[uninterned-symbol 32 G1] +(generate-uninterned-symbol 'this) + @result{} #[uninterned-symbol 33 this2] +(generate-uninterned-symbol) + @result{} #[uninterned-symbol 34 G3] +(generate-uninterned-symbol 100) + @result{} #[uninterned-symbol 35 G100] +(generate-uninterned-symbol) + @result{} #[uninterned-symbol 36 G101] +@end group +@end example +@end deffn + +@deffn procedure symbol-append symbol @dots{} +@cindex appending, of symbols +@cindex pasting, of symbols +Returns the interned symbol whose name is formed by concatenating the +names of the given symbols. This procedure preserves the case of the +names of its arguments, so if one or more of the arguments' names has +non-standard case, the result will also have non-standard case. + +@example +@group +(symbol-append 'foo- 'bar) @result{} foo-bar +@r{;; the arguments may be uninterned:} +(symbol-append 'foo- (string->uninterned-symbol "baz")) + @result{} foo-baz +@r{;; the result has the same case as the arguments:} +(symbol-append 'foo- (string->symbol "BAZ")) @result{} foo-BAZ +@end group +@end example +@end deffn + +@deffn procedure symbol-hash symbol +@cindex hashing, of symbol +@findex string-hash +Returns a hash number for @var{symbol}, which is computed by calling +@code{string-hash} on @var{symbol}'s name. The hash number is an exact +non-negative integer. +@end deffn + +@deffn procedure symbol-hash-mod symbol modulus +@var{Modulus} must be an exact positive integer. Equivalent to + +@example +@group +(modulo (symbol-hash @var{symbol}) @var{modulus}) +@end group +@end example + +This procedure is provided for convenience in constructing hash tables. +However, it is normally preferable to use @code{make-eq-hash-table} to +build hash tables keyed by symbols, because @code{eq?} hash tables are +much faster. +@end deffn + +@deffn procedure symbolstring @var{symbol1}) + (symbol->string @var{symbol2})) +@end group +@end example +@end deffn + +@node Cells, Records, Symbols, Miscellaneous Datatypes +@section Cells + +@cindex cell (defn) +@dfn{Cells} are data structures similar to pairs except that they have +only one element. They are useful for managing state. + +@deffn procedure cell? object +@cindex type predicate, for cell +Returns @code{#t} if @var{object} is a cell; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure make-cell object +@cindex construction, of cell +Returns a newly allocated cell whose contents is @var{object}. +@end deffn + +@deffn procedure cell-contents cell +@cindex selection, of cell component +@cindex component selection, of cell +Returns the current contents of @var{cell}. +@end deffn + +@deffn procedure set-cell-contents! cell object +Alters the contents of @var{cell} to be @var{object}. Returns an +unspecified value. +@end deffn + +@deffn procedure bind-cell-contents! cell object thunk +Alters the contents of @var{cell} to be @var{object}, calls @var{thunk} +with no arguments, then restores the original contents of @var{cell} and +returns the value returned by @var{thunk}. This is completely +equivalent to dynamic binding of a variable, including the behavior when +continuations are used (@pxref{Dynamic Binding}). +@end deffn + +@node Records, Promises, Cells, Miscellaneous Datatypes +@section Records + +MIT/GNU Scheme provides a @dfn{record} abstraction, which is a simple and +flexible mechanism for building structures with named components. +Records can be defined and accessed using the procedures defined in this +section. A less flexible but more concise way to manipulate records is +to use the @code{define-structure} special form (@pxref{Structure +Definitions}). +@findex define-structure + +@deffn procedure make-record-type type-name field-names +@cindex record-type descriptor (defn) +Returns a @dfn{record-type descriptor}, a value representing a new data +type, disjoint from all others. The @var{type-name} argument must be a +string, but is only used for debugging purposes (such as the printed +representation of a record of the new type). The @var{field-names} +argument is a list of symbols naming the @dfn{fields} of a record of the +new type. It is an error if the list contains any duplicates. It is +unspecified how record-type descriptors are represented. +@end deffn + +@deffn procedure record-constructor record-type [field-names] +Returns a procedure for constructing new members of the type represented +by @var{record-type}. The returned procedure accepts exactly as many +arguments as there are symbols in the given list, @var{field-names}; +these are used, in order, as the initial values of those fields in a new +record, which is returned by the constructor procedure. The values of +any fields not named in the list of @var{field-names} are unspecified. +The @var{field-names} argument defaults to the list of field-names in +the call to @code{make-record-type} that created the type represented by +@var{record-type}; if the @var{field-names} argument is provided, it is +an error if it contains any duplicates or any symbols not in the default +list. +@end deffn + +@deffn procedure record-predicate record-type +Returns a procedure for testing membership in the type represented by +@var{record-type}. The returned procedure accepts exactly one argument +and returns @code{#t} if the argument is a member of the indicated +record type; it returns @code{#f} otherwise. +@end deffn + +@deffn procedure record-accessor record-type field-name +Returns a procedure for reading the value of a particular field of a +member of the type represented by @var{record-type}. The returned +procedure accepts exactly one argument which must be a record of the +appropriate type; it returns the current value of the field named by the +symbol @var{field-name} in that record. The symbol @var{field-name} +must be a member of the list of field names in the call to +@code{make-record-type} that created the type represented by +@var{record-type}. +@end deffn + +@deffn procedure record-modifier record-type field-name +Returns a procedure for writing the value of a particular field of a +member of the type represented by @var{record-type}. The returned +procedure accepts exactly two arguments: first, a record of the +appropriate type, and second, an arbitrary Scheme value; it modifies the +field named by the symbol @var{field-name} in that record to contain the +given value. The returned value of the modifier procedure is +unspecified. The symbol @var{field-name} must be a member of the list +of field names in the call to @code{make-record-type} that created the +type represented by @var{record-type}. +@end deffn + +@deffn procedure record? object +@cindex type predicate, for record +Returns @code{#t} if @var{object} is a record of any type and @code{#f} +otherwise. Note that @code{record?} may be true of any Scheme value; of +course, if it returns @code{#t} for some particular value, then +@code{record-type-descriptor} is applicable to that value and returns an +appropriate descriptor. +@end deffn + +@deffn procedure record-type-descriptor record +Returns the record-type descriptor representing the type of +@var{record}. That is, for example, if the returned descriptor were +passed to @code{record-predicate}, the resulting predicate would return +@code{#t} when passed @var{record}. Note that it is not necessarily the +case that the returned descriptor is the one that was passed to +@code{record-constructor} in the call that created the constructor +procedure that created @var{record}. +@end deffn + +@deffn procedure record-type? object +@cindex type predicate, for record type +Returns @code{#t} if @var{object} is a record-type descriptor; otherwise +returns @code{#f}. +@end deffn + +@deffn procedure record-type-name record-type +Returns the type name associated with the type represented by +@var{record-type}. The returned value is @code{eqv?} to the +@var{type-name} argument given in the call to @code{make-record-type} +that created the type represented by @var{record-type}. +@end deffn + +@deffn procedure record-type-field-names record-type +Returns a list of the symbols naming the fields in members of the type +represented by @var{record-type}. The returned value is @code{equal?} +to the @var{field-names} argument given in the call to +@code{make-record-type} that created the type represented by +@var{record-type}.@footnote{In MIT/GNU Scheme, the returned list is always +newly allocated.} +@end deffn + +@node Promises, Streams, Records, Miscellaneous Datatypes +@section Promises + +@deffn {special form} delay expression +@cindex promise (defn) +@cindex promise, construction +@cindex construction, of promise +@cindex lazy evaluation (defn) +@cindex call by need evaluation (defn) +@cindex evaluation, lazy (defn) +@cindex evaluation, call by need (defn) +The @code{delay} construct is used together with the procedure +@code{force} to implement @dfn{lazy evaluation} or @dfn{call by need}. +@code{(delay @var{expression})} returns an object called a @dfn{promise} +which at some point in the future may be asked (by the @code{force} +procedure) to evaluate @var{expression} and deliver the resulting value. +@end deffn + +@deffn procedure force promise +@cindex promise, forcing +@cindex forcing, of promise +@cindex memoization, of promise +Forces the value of @emph{promise}. If no value has been computed for +the promise, then a value is computed and returned. The value of the +promise is cached (or ``memoized'') so that if it is forced a second +time, the previously computed value is returned without any +recomputation. + +@example +@group +(force (delay (+ 1 2))) @result{} 3 + +(let ((p (delay (+ 1 2)))) + (list (force p) (force p))) @result{} (3 3) +@end group + +@group +(define head car) + +(define tail + (lambda (stream) + (force (cdr stream)))) +@end group + +@group +(define a-stream + (letrec ((next + (lambda (n) + (cons n (delay (next (+ n 1))))))) + (next 0))) + +(head (tail (tail a-stream))) @result{} 2 +@end group +@end example +@end deffn + +@deffn procedure promise? object +@cindex type predicate, for promise +Returns @code{#t} if @var{object} is a promise; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure promise-forced? promise +Returns @code{#t} if @var{promise} has been forced and its value cached; +otherwise returns @code{#f}. +@end deffn + +@deffn procedure promise-value promise +If @var{promise} has been forced and its value cached, this procedure +returns the cached value. Otherwise, an error is signalled. +@end deffn + +@code{force} and @code{delay} are mainly intended for programs written +in functional style. The following examples should not be considered to +illustrate good programming style, but they illustrate the property that +the value of a promise is computed at most once. + +@example +@group +(define count 0) + +(define p + (delay + (begin + (set! count (+ count 1)) + (* x 3)))) + +(define x 5) +@end group + +@group +count @result{} 0 +p @result{} #[promise 54] +(force p) @result{} 15 +p @result{} #[promise 54] +count @result{} 1 +(force p) @result{} 15 +count @result{} 1 +@end group +@end example + +Here is a possible implementation of @code{delay} and @code{force}. We +define the expression + +@example +(delay @var{expression}) +@end example + +@noindent +to have the same meaning as the procedure call + +@example +(make-promise (lambda () @var{expression})) +@end example + +@noindent +where @code{make-promise} is defined as follows: + +@example +@group +(define make-promise + (lambda (proc) + (let ((already-run? #f) + (result #f)) + (lambda () + (cond ((not already-run?) + (set! result (proc)) + (set! already-run? #t))) + result)))) +@end group +@end example + +Promises are implemented here as procedures of no arguments, and +@code{force} simply calls its argument. + +@example +@group +(define force + (lambda (promise) + (promise))) +@end group +@end example + +Various extensions to this semantics of @code{delay} and @code{force} +are supported in some implementations (none of these are currently +supported in MIT/GNU Scheme): + +@itemize @bullet +@item +Calling @code{force} on an object that is not a promise may simply +return the object. + +@item +It may be the case that there is no means by which a promise can be +operationally distinguished from its forced value. That is, expressions +like the following may evaluate to either @code{#t} or @code{#f}, +depending on the implementation: + +@example +@group +(eqv? (delay 1) 1) @result{} @r{unspecified} +(pair? (delay (cons 1 2))) @result{} @r{unspecified} +@end group +@end example + +@item +Some implementations will implement ``implicit forcing'', where the +value of a promise is forced by primitive procedures like @code{car} and +@code{+}: + +@example +(+ (delay (* 3 7)) 13) @result{} 34 +@end example +@end itemize + +@node Streams, Weak Pairs, Promises, Miscellaneous Datatypes +@section Streams + +@cindex stream (defn) +In addition to promises, MIT/GNU Scheme supports a higher-level abstraction +called @dfn{streams}. Streams are similar to lists, except that the +tail of a stream is not computed until it is referred to. +This allows streams to be used to represent infinitely long lists. + +@deffn procedure stream object @dots{} +@cindex construction, of stream +Returns a newly allocated stream whose elements are the arguments. Note +that the expression @code{(stream)} returns the empty stream, or +end-of-stream marker. +@end deffn + +@deffn procedure list->stream list +@cindex list, converting to stream +Returns a newly allocated stream whose elements are the elements of +@var{list}. Equivalent to @code{(apply stream @var{list})}. +@end deffn + +@deffn procedure stream->list stream +@cindex stream, converting to list +Returns a newly allocated list whose elements are the elements of +@var{stream}. If @var{stream} has infinite length this procedure will +not terminate. This could have been defined by + +@example +@group +(define (stream->list stream) + (if (stream-null? stream) + '() + (cons (stream-car stream) + (stream->list (stream-cdr stream))))) +@end group +@end example +@end deffn + +@deffn {special form} cons-stream object expression +Returns a newly allocated stream pair. Equivalent to @code{(cons +@var{object} (delay @var{expression}))}. +@end deffn + +@deffn procedure stream-pair? object +@cindex type predicate, for stream pair +Returns @code{#t} if @var{object} is a pair whose cdr contains a +promise. Otherwise returns @code{#f}. This could have been defined by + +@example +@group +(define (stream-pair? object) + (and (pair? object) + (promise? (cdr object)))) +@end group +@end example +@end deffn + +@deffn procedure stream-car stream +@deffnx procedure stream-first stream +@findex car +Returns the first element in @var{stream}. @code{stream-car} is +equivalent to @code{car}. @code{stream-first} is a synonym for +@code{stream-car}. +@end deffn + +@deffn procedure stream-cdr stream +@deffnx procedure stream-rest stream +@findex force +@findex cdr +Returns the first tail of @var{stream}. Equivalent to @code{(force (cdr +@var{stream}))}. @code{stream-rest} is a synonym for @code{stream-cdr}. +@end deffn + +@deffn procedure stream-null? stream +@cindex empty stream, predicate for +@findex null? +Returns @code{#t} if @var{stream} is the end-of-stream marker; otherwise +returns @code{#f}. This is equivalent to @code{null?}, but should be +used whenever testing for the end of a stream. +@end deffn + +@deffn procedure stream-length stream +@cindex length, of stream +Returns the number of elements in @var{stream}. If @var{stream} has an +infinite number of elements this procedure will not terminate. Note +that this procedure forces all of the promises that comprise +@var{stream}. +@end deffn + +@deffn procedure stream-ref stream k +@cindex selecting, of stream component +@cindex component selection, of stream +Returns the element of @var{stream} that is indexed by @var{k}; that is, +the @var{k}th element. @var{K} must be an exact non-negative integer +strictly less than the length of @var{stream}. +@end deffn + +@deffn procedure stream-head stream k +Returns the first @var{k} elements of @var{stream} as a list. @var{K} +must be an exact non-negative integer strictly less than the length of +@var{stream}. +@end deffn + +@deffn procedure stream-tail stream k +Returns the tail of @var{stream} that is indexed by @var{k}; that is, +the @var{k}th tail. This is equivalent to performing @code{stream-cdr} +@var{k} times. @var{K} must be an exact non-negative integer strictly +less than the length of @var{stream}. +@end deffn + +@deffn procedure stream-map procedure stream stream @dots{} +@cindex mapping, of stream +Returns a newly allocated stream, each element being the result of +invoking @var{procedure} with the corresponding elements of the +@var{stream}s as its arguments. +@end deffn + +@node Weak Pairs, , Streams, Miscellaneous Datatypes +@section Weak Pairs + +@cindex weak pair (defn) +@cindex pair, weak (defn) +@dfn{Weak pairs} are a mechanism for building data structures that point +at objects without protecting them from garbage collection. The car of +a weak pair holds its pointer weakly, while the cdr holds its pointer in +the normal way. If the object in the car of a weak pair is not held +normally by any other data structure, it will be garbage-collected. + +@findex pair? +Note: weak pairs are @emph{not} pairs; that is, they do not satisfy the +predicate @code{pair?}. + +@deffn procedure weak-pair? object +@cindex type predicate, for weak pair +Returns @code{#t} if @var{object} is a weak pair; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure weak-cons car cdr +@cindex construction, of weak pair +Allocates and returns a new weak pair, with components @var{car} and +@var{cdr}. The @var{car} component is held weakly. +@end deffn + +@deffn procedure weak-pair/car? weak-pair +This predicate returns @code{#f} if the car of @var{weak-pair} has been +garbage-collected; otherwise returns @code{#t}. In other words, it is +true if @var{weak-pair} has a valid car component. +@end deffn + +@deffn procedure weak-car weak-pair +@cindex selection, of weak pair component +@cindex component selection, of weak pair +Returns the car component of @var{weak-pair}. If the car component has +been garbage-collected, this operation returns @code{#f}, but it can +also return @code{#f} if that is the value that was stored in the car. +@end deffn + +Normally, @code{weak-pair/car?} is used to determine if @code{weak-car} +would return a valid value. An obvious way of doing this would be: + +@example +@group +(if (weak-pair/car? x) + (weak-car x) + @dots{}) +@end group +@end example + +@noindent +However, since a garbage collection could occur between the call to +@code{weak-pair/car?} and @code{weak-car}, this would not always work +correctly. Instead, the following should be used, which always works: + +@example +@group +(or (weak-car x) + (and (not (weak-pair/car? x)) + @dots{})) +@end group +@end example + +The reason that the latter expression works is that @code{weak-car} +returns @code{#f} in just two instances: when the car component is +@code{#f}, and when the car component has been garbage-collected. In +the former case, if a garbage collection happens between the two calls, +it won't matter, because @code{#f} will never be garbage-collected. And +in the latter case, it also won't matter, because the car component no +longer exists and cannot be affected by the garbage collector. + +@deffn procedure weak-set-car! weak-pair object +Sets the car component of @var{weak-pair} to @var{object} and returns an +unspecified result. +@end deffn + +@deffn procedure weak-cdr weak-pair +Returns the cdr component of @var{weak-cdr}. +@end deffn + +@deffn procedure weak-set-cdr! weak-pair object +Sets the cdr component of @var{weak-pair} to @var{object} and returns an +unspecified result. +@end deffn diff --git a/v7/doc/ref-manual/numbers.texi b/v7/doc/ref-manual/numbers.texi new file mode 100644 index 000000000..d33cc12d5 --- /dev/null +++ b/v7/doc/ref-manual/numbers.texi @@ -0,0 +1,1421 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: numbers.texi,v 1.1 2003/04/15 03:29:56 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Numbers, Characters, Equivalence Predicates, Top +@chapter Numbers +@cindex number + +(This section is largely taken from the @cite{Revised^4 Report on the +Algorithmic Language Scheme}.) + +Numerical computation has traditionally been neglected by the Lisp +community. Until Common Lisp there was no carefully thought out +strategy for organizing numerical computation, and with the exception of +the MacLisp system little effort was made to execute numerical code +efficiently. This report recognizes the excellent work of the Common +Lisp committee and accepts many of their recommendations. In some ways +this report simplifies and generalizes their proposals in a manner +consistent with the purposes of Scheme. + +It is important to distinguish between the mathematical numbers, the +Scheme numbers that attempt to model them, the machine representations +used to implement the Scheme numbers, and notations used to write +numbers. This report uses the types @emph{number}, @emph{complex}, +@emph{real}, @emph{rational}, and @emph{integer} to refer to both +mathematical numbers and Scheme numbers. Machine representations such +as fixed point and floating point are referred to by names such as +@emph{fixnum} and @emph{flonum}. + +@menu +* Numerical types:: +* Exactness:: +* Implementation restrictions:: +* Syntax of numerical constants:: +* Numerical operations:: +* Numerical input and output:: +* Fixnum and Flonum Operations:: +* Random Numbers:: +@end menu + +@node Numerical types, Exactness, Numbers, Numbers +@section Numerical types +@cindex numerical types + +Mathematically, numbers may be arranged into a tower of subtypes in +which each level is a subset of the level above it: + +@display +@group +number +complex +real +rational +integer +@end group +@end display + +For example, 3 is an integer. Therefore 3 is also a rational, a real, +and a complex. The same is true of the Scheme numbers that model 3. +For Scheme numbers, these types are defined by the predicates +@code{number?}, @code{complex?}, @code{real?}, @code{rational?}, and +@code{integer?}. + +There is no simple relationship between a number's type and its +representation inside a computer. Although most implementations of +Scheme will offer at least two different representations of 3, these +different representations denote the same integer. + +Scheme's numerical operations treat numbers as abstract data, as +independent of their representation as possible. Although an +implementation of Scheme may use fixnum, flonum, and perhaps other +representations for numbers, this should not be apparent to a casual +programmer writing simple programs. + +It is necessary, however, to distinguish between numbers that are +represented exactly and those that may not be. For example, indexes +into data structures must be known exactly, as must some polynomial +coefficients in a symbolic algebra system. On the other hand, the +results of measurements are inherently inexact, and irrational numbers +may be approximated by rational and therefore inexact approximations. +In order to catch uses of inexact numbers where exact numbers are +required, Scheme explicitly distinguishes exact from inexact numbers. +This distinction is orthogonal to the dimension of type. + +@node Exactness, Implementation restrictions, Numerical types, Numbers +@section Exactness +@cindex exactness + +Scheme numbers are either @emph{exact} or @emph{inexact}. A number is +exact if it was written as an exact constant or was derived from exact +numbers using only exact operations. A number is inexact if it was +written as an inexact constant, if it was derived using inexact +ingredients, or if it was derived using inexact operations. Thus +inexactness is a contagious property of a number. + +If two implementations produce exact results for a computation that did +not involve inexact intermediate results, the two ultimate results will +be mathematically equivalent. This is generally not true of +computations involving inexact numbers since approximate methods such as +floating point arithmetic may be used, but it is the duty of each +implementation to make the result as close as practical to the +mathematically ideal result. + +@findex + +Rational operations such as @code{+} should always produce exact results +when given exact arguments. If the operation is unable to produce an +exact result, then it may either report the violation of an +implementation restriction or it may silently coerce its result to an +inexact value. @xref{Implementation restrictions}. + +@findex inexact->exact +With the exception of @code{inexact->exact}, the operations described in +this section must generally return inexact results when given any +inexact arguments. An operation may, however, return an exact result if +it can prove that the value of the result is unaffected by the +inexactness of its arguments. For example, multiplication of any number +by an exact zero may produce an exact zero result, even if the other +argument is inexact. + +@node Implementation restrictions, Syntax of numerical constants, Exactness, Numbers +@section Implementation restrictions +@cindex implementation restriction + +Implementations of Scheme are not required to implement the whole tower +of subtypes (@pxref{Numerical types}), but they must implement a +coherent subset consistent with both the purposes of the implementation +and the spirit of the Scheme language. For example, an implementation +in which all numbers are real may still be quite useful.@footnote{MIT/GNU +Scheme implements the whole tower of numerical types. It has +unlimited-precision exact integers and exact rationals. Flonums are +used to implement all inexact reals; on machines that support @sc{ieee} +floating-point arithmetic these are double-precision floating-point +numbers.} + +Implementations may also support only a limited range of numbers of any +type, subject to the requirements of this section. The supported range +for exact numbers of any type may be different from the supported range +for inexact numbers of that type. For example, an implementation that +uses flonums to represent all its inexact real numbers may support a +practically unbounded range of exact integers and rationals while +limiting the range of inexact reals (and therefore the range of inexact +integers and rationals) to the dynamic range of the flonum format. +Furthermore the gaps between the representable inexact integers and +rationals are likely to be very large in such an implementation as the +limits of this range are approached. + +@findex length +@findex vector-length +@findex string-length +An implementation of Scheme must support exact integers throughout the +range of numbers that may be used for indexes of lists, vectors, and +strings or that may result from computing the length of a list, vector, +or string. The @code{length}, @code{vector-length}, and +@code{string-length} procedures must return an exact integer, and it is +an error to use anything but an exact integer as an index. Furthermore +any integer constant within the index range, if expressed by an exact +integer syntax, will indeed be read as an exact integer, regardless of +any implementation restrictions that may apply outside this range. +Finally, the procedures listed below will always return an exact integer +result provided all their arguments are exact integers and the +mathematically expected result is representable as an exact integer +within the implementation: + +@example +@group +* gcd modulo ++ imag-part numerator +- inexact->exact quotient +abs lcm rationalize +angle magnitude real-part +ceiling make-polar remainder +denominator make-rectangular round +expt max truncate +floor min +@end group +@end example + +@findex / +Implementations are encouraged, but not required, to support exact +integers and exact rationals of practically unlimited size and +precision, and to implement the above procedures and the @code{/} +procedure in such a way that they always return exact results when given +exact arguments. If one of these procedures is unable to deliver an +exact result when given exact arguments, then it may either report a +violation of an implementation restriction or it may silently coerce its +result to an inexact number. Such a coercion may cause an error +later. + +An implementation may use floating point and other approximate +representation strategies for inexact numbers. This report recommends, +but does not require, that the @sc{ieee} 32-bit and 64-bit floating +point standards be followed by implementations that use flonum +representations, and that implementations using other representations +should match or exceed the precision achievable using these floating +point standards. + +@findex sqrt +In particular, implementations that use flonum representations must +follow these rules: A flonum result must be represented with at least as +much precision as is used to express any of the inexact arguments to +that operation. It is desirable (but not required) for potentially +inexact operations such as @code{sqrt}, when applied to exact arguments, +to produce exact answers whenever possible (for example the square root +of an exact 4 ought to be an exact 2). If, however, an exact number is +operated upon so as to produce an inexact result (as by @code{sqrt}), +and if the result is represented as a flonum, then the most precise +flonum format available must be used; but if the result is represented +in some other way then the representation must have at least as much +precision as the most precise flonum format available. + +Although Scheme allows a variety of written notations for numbers, any +particular implementation may support only some of them.@footnote{MIT/GNU +Scheme implements all of the written notations for numbers.} For +example, an implementation in which all numbers are real need not +support the rectangular and polar notations for complex numbers. If an +implementation encounters an exact numerical constant that it cannot +represent as an exact number, then it may either report a violation of +an implementation restriction or it may silently represent the constant +by an inexact number. + +@node Syntax of numerical constants, Numerical operations, Implementation restrictions, Numbers +@section Syntax of numerical constants +@cindex number, external representation +@cindex external representation, for number + +@findex #b +@findex #o +@findex #d +@findex #x +@cindex #b as external representation +@cindex #o as external representation +@cindex #d as external representation +@cindex #x as external representation +A number may be written in binary, octal, decimal, or hexadecimal by the +use of a radix prefix. The radix prefixes are @code{#b} (binary), +@code{#o} (octal), @code{#d} (decimal), and @code{#x} (hexadecimal). +With no radix prefix, a number is assumed to be expressed in +decimal. + +@findex #e +@findex #i +@findex # +@cindex #e as external representation +@cindex #i as external representation +@cindex # in external representation of number +A numerical constant may be specified to be either exact or inexact by a +prefix. The prefixes are @code{#e} for exact, and @code{#i} for +inexact. An exactness prefix may appear before or after any radix +prefix that is used. If the written representation of a number has no +exactness prefix, the constant may be either inexact or exact. It is +inexact if it contains a decimal point, an exponent, or a @code{#} +character in the place of a digit, otherwise it is exact. + +@cindex s, as exponent marker in number +@cindex f, as exponent marker in number +@cindex d, as exponent marker in number +@cindex l, as exponent marker in number +@cindex e, as exponent marker in number +@cindex exponent marker (defn) +@cindex precision, of inexact number +@cindex numeric precision, inexact +@cindex internal representation, for inexact number +@cindex short precision, of inexact number +@cindex single precision, of inexact number +@cindex double precision, of inexact number +@cindex long precision, of inexact number +In systems with inexact numbers of varying precisions it may be useful +to specify the precision of a constant. For this purpose, numerical +constants may be written with an @dfn{exponent marker} that indicates +the desired precision of the inexact representation. The letters +@code{s}, @code{f}, @code{d}, and @code{l} specify the use of +@emph{short}, @emph{single}, @emph{double}, and @emph{long} precision, +respectively. (When fewer than four internal inexact representations +exist, the four size specifications are mapped onto those available. +For example, an implementation with two internal representations may map +short and single together and long and double together.) In addition, +the exponent marker @code{e} specifies the default precision for the +implementation. The default precision has at least as much precision as +@emph{double}, but implementations may wish to allow this default to be +set by the user. + +@example +@group +3.14159265358979F0 + @r{Round to single ---} 3.141593 +0.6L0 + @r{Extend to long ---} .600000000000000 +@end group +@end example + +@node Numerical operations, Numerical input and output, Syntax of numerical constants, Numbers +@section Numerical operations +@cindex numerical operations + +@xref{Entry Format}, for a summary of the naming conventions used to +specify restrictions on the types of arguments to numerical routines. +The examples used in this section assume that any numerical constant +written using an exact notation is indeed represented as an exact +number. Some examples also assume that certain numerical constants +written using an inexact notation can be represented without loss of +accuracy; the inexact constants were chosen so that this is likely to be +true in implementations that use flonums to represent inexact +numbers. + +@deffn procedure number? object +@deffnx procedure complex? object +@deffnx procedure real? object +@deffnx procedure rational? object +@deffnx procedure integer? object +@cindex type predicate, for number +These numerical type predicates can be applied to any kind of argument, +including non-numbers. They return @code{#t} if the object is of the +named type, and otherwise they return @code{#f}. In general, if a type +predicate is true of a number then all higher type predicates are also +true of that number. Consequently, if a type predicate is false of a +number, then all lower type predicates are also false of that +number.@footnote{In MIT/GNU Scheme the @code{rational?} procedure is the +same as @code{real?}, and the @code{complex?} procedure is the same as +@code{number?}.} + +@findex zero? +@findex = +If @var{z} is an inexact complex number, then @code{(real? @var{z})} is +true if and only if @code{(zero? (imag-part @var{z}))} is true. If +@var{x} is an inexact real number, then @code{(integer? @var{x})} is +true if and only if @code{(= @var{x} (round @var{x}))}. + +@example +@group +(complex? 3+4i) @result{} #t +(complex? 3) @result{} #t +(real? 3) @result{} #t +(real? -2.5+0.0i) @result{} #t +(real? #e1e10) @result{} #t +(rational? 6/10) @result{} #t +(rational? 6/3) @result{} #t +(integer? 3+0i) @result{} #t +(integer? 3.0) @result{} #t +(integer? 8/4) @result{} #t +@end group +@end example + +Note: The behavior of these type predicates on inexact numbers is +unreliable, since any inaccuracy may affect the result. + +@end deffn + +@deffn procedure exact? z +@deffnx procedure inexact? z +These numerical predicates provide tests for the exactness of a +quantity. For any Scheme number, precisely one of these predicates is +true. +@end deffn + +@deffn procedure exact-integer? object +@deffnx procedure exact-nonnegative-integer? object +@deffnx procedure exact-rational? object +These procedures test for some very common types of numbers. These +tests could be written in terms of simpler predicates, but are more +efficient. +@end deffn + +@deffn procedure = z1 z2 z3 @dots{} +@deffnx procedure < x1 x2 x3 @dots{} +@deffnx procedure > x1 x2 x3 @dots{} +@deffnx procedure <= x1 x2 x3 @dots{} +@deffnx procedure >= x1 x2 x3 @dots{} +@cindex ordering, of numbers +@cindex comparison, of numbers +@cindex equivalence predicate, for numbers +These procedures return @code{#t} if their arguments are (respectively): +equal, monotonically increasing, monotonically decreasing, monotonically +nondecreasing, or monotonically nonincreasing. + +These predicates are transitive. Note that the traditional +implementations of these predicates in Lisp-like languages are not +transitive. + +Note: While it is not an error to compare inexact numbers using these +predicates, the results may be unreliable because a small inaccuracy may +affect the result; this is especially true of @code{=} and @code{zero?}. +When in doubt, consult a numerical analyst. +@end deffn + +@deffn procedure zero? z +@deffnx procedure positive? x +@deffnx procedure negative? x +@deffnx procedure odd? x +@deffnx procedure even? x +@cindex zero +@cindex positive number +@cindex negative number +@cindex odd number +@cindex even number +These numerical predicates test a number for a particular property, +returning @code{#t} or @code{#f}. See note above regarding inexact +numbers. +@end deffn + +@deffn procedure max x1 x2 @dots{} +@deffnx procedure min x1 x2 @dots{} +@cindex minimum, of numbers +@cindex maximum, of numbers +These procedures return the maximum or minimum of their +arguments. + +@example +@group +(max 3 4) @result{} 4 @r{; exact} +(max 3.9 4) @result{} 4.0 @r{; inexact} +@end group +@end example + +Note: If any argument is inexact, then the result will also be inexact +(unless the procedure can prove that the inaccuracy is not large enough +to affect the result, which is possible only in unusual +implementations). If @code{min} or @code{max} is used to compare +numbers of mixed exactness, and the numerical value of the result cannot +be represented as an inexact number without loss of accuracy, then the +procedure may report a violation of an implementation +restriction.@footnote{MIT/GNU Scheme signals an error of type +@code{condition-type:bad-range-argument} in this case.} +@findex condition-type:bad-range-argument +@end deffn + +@deffn procedure + z1 @dots{} +@deffnx procedure * z1 @dots{} +@cindex addition, of numbers +@cindex sum, of numbers +@cindex identity, additive +@cindex multiplication, of numbers +@cindex product, of numbers +@cindex identity, multiplicative +These procedures return the sum or product of their arguments. + +@example +@group +(+ 3 4) @result{} 7 +(+ 3) @result{} 3 +(+) @result{} 0 +(* 4) @result{} 4 +(*) @result{} 1 +@end group +@end example +@end deffn + +@deffn procedure - z1 z2 @dots{} +@deffnx procedure / z1 z2 @dots{} +@cindex subtraction, of numbers +@cindex difference, of numbers +@cindex inverse, additive, of number +@cindex division, of numbers +@cindex quotient, of numbers +@cindex inverse, multiplicative, of number +With two or more arguments, these procedures return the difference or +quotient of their arguments, associating to the left. With one +argument, however, they return the additive or multiplicative inverse of +their argument. + +@example +@group +(- 3 4) @result{} -1 +(- 3 4 5) @result{} -6 +(- 3) @result{} -3 +(/ 3 4 5) @result{} 3/20 +(/ 3) @result{} 1/3 +@end group +@end example +@end deffn + +@deffn procedure 1+ z +@deffnx procedure -1+ z +@code{(1+ z)} is equivalent to @code{(+ z 1)}; @code{(-1+ z)} is +equivalent to @code{(- z 1)}. +@end deffn + +@deffn procedure abs x +@cindex absolute value, of number +@cindex magnitude, of real number +@code{abs} returns the magnitude of its argument. + +@example +(abs -7) @result{} 7 +@end example +@end deffn + +@deffn procedure quotient n1 n2 +@deffnx procedure remainder n1 n2 +@deffnx procedure modulo n1 n2 +@cindex division, of integers +@cindex quotient, of integers +@cindex remainder, of integers +@cindex modulus, of integers +@cindex integer division +These procedures implement number-theoretic (integer) division: for +positive integers @var{n1} and @var{n2}, if @var{n3} and @var{n4} are +integers such that +@tex +$$n_1=n_2n_3+n_4$$ +$$0\leq n_4inexact (/ 6 4))) @result{} 2.0 +@end group +@end example +@end deffn + +@deffn procedure floor x +@deffnx procedure ceiling x +@deffnx procedure truncate x +@deffnx procedure round x +These procedures return integers. @code{floor} returns the largest +integer not larger than @var{x}. @code{ceiling} returns the smallest +integer not smaller than @var{x}. @code{truncate} returns the integer +closest to @var{x} whose absolute value is not larger than the absolute +value of @var{x}. @code{round} returns the closest integer to @var{x}, +rounding to even when @var{x} is halfway between two integers. + +Rationale: @code{round} rounds to even for consistency with the rounding +modes required by the @sc{ieee} floating point standard. + +Note: If the argument to one of these procedures is inexact, then the +result will also be inexact. If an exact value is needed, the result +should be passed to the @code{inexact->exact} procedure (or use one of +the procedures below). + +@example +@group +(floor -4.3) @result{} -5.0 +(ceiling -4.3) @result{} -4.0 +(truncate -4.3) @result{} -4.0 +(round -4.3) @result{} -4.0 + +(floor 3.5) @result{} 3.0 +(ceiling 3.5) @result{} 4.0 +(truncate 3.5) @result{} 3.0 +(round 3.5) @result{} 4.0 @r{; inexact} + +(round 7/2) @result{} 4 @r{; exact} +(round 7) @result{} 7 +@end group +@end example +@end deffn + +@deffn procedure floor->exact x +@deffnx procedure ceiling->exact x +@deffnx procedure truncate->exact x +@deffnx procedure round->exact x +These procedures are similar to the preceding procedures except that +they always return an exact result. For example, the following are +equivalent + +@example +@group +(floor->exact x) +(inexact->exact (floor x)) +@end group +@end example + +@noindent +except that the former is faster and has fewer range restrictions. +@end deffn + +@deffn procedure rationalize x y +@deffnx procedure rationalize->exact x y +@cindex simplest rational (defn) +@cindex rational, simplest (defn) +@code{rationalize} returns the @emph{simplest} rational number differing +from @var{x} by no more than @var{y}. A rational number @var{r1} is +@emph{simpler} than another rational number @var{r2} if +@t{@var{r1}=@var{p1}/@var{q1}} and @t{@var{r2}=@var{p2}/@var{q2}} (both +in lowest terms) and @t{|@var{p1}|<=|@var{p2}|} and +@t{|@var{q1}|<=|@var{q2}|}. Thus @t{3/5} is simpler than @t{4/7}. +Although not all rationals are comparable in this ordering (consider +@t{2/7} and @t{3/5}) any interval contains a rational number that is +simpler than every other rational number in that interval (the simpler +@t{2/5} lies between @t{2/7} and @t{3/5}). Note that @t{0=0/1} is the +simplest rational of all. + +@example +@group +(rationalize (inexact->exact .3) 1/10) @result{} 1/3 @r{; exact} +(rationalize .3 1/10) @result{} #i1/3 @r{; inexact} +@end group +@end example + +@code{rationalize->exact} is similar to @code{rationalize} except that +it always returns an exact result. +@end deffn + +@deffn procedure simplest-rational x y +@deffnx procedure simplest-exact-rational x y +@code{simplest-rational} returns the simplest rational number between +@var{x} and @var{y} inclusive; @code{simplest-exact-rational} is similar +except that it always returns an exact result. + +These procedures implement the same functionality as @code{rationalize} +and @code{rationalize->exact}, except that they specify the input range +by its endpoints; @code{rationalize} specifies the range by its center +point and its (half-) width. +@end deffn + +@deffn procedure exp z +@deffnx procedure log z +@deffnx procedure sin z +@deffnx procedure cos z +@deffnx procedure tan z +@deffnx procedure asin z +@deffnx procedure acos z +@deffnx procedure atan z +@deffnx procedure atan y x +@findex angle +@findex make-rectangular +These procedures compute the usual transcendental functions. @code{log} +computes the natural logarithm of @var{z} (not the base ten logarithm). +@code{asin}, @code{acos}, and @code{atan} compute arcsine, arccosine, +and arctangent, respectively. The two-argument variant of @code{atan} +computes @code{(angle (make-rectangular @var{x} @var{y}))} (see +below). + +In general, the mathematical functions log, arcsine, arccosine, and +arctangent are multiply defined. For nonzero real @var{x}, the value of +log @var{x} is defined to be the one whose imaginary part lies in the +range minus @var{pi} (exclusive) to @var{pi} (inclusive). log 0 is +undefined. The value of log @var{z} when @var{z} is complex is defined +according to the formula +@tex +$$\log z = \log {\rm magnitude}(z) + i {\rm angle} (z)$$ +@end tex +@ifinfo + +@example +log @var{z} = log magnitude(@var{z}) + i angle(@var{z}) +@end example + +@end ifinfo +With log defined this way, the values of arcsine, arccosine, and +arctangent are according to the following formulae: +@tex +$$\sin^{-1} z = -i \log (i z + \sqrt{1 - z^2})$$ +$$\cos^{-1} z = \pi / 2 - \sin^{-1} z$$ +$$\tan^{-1} z = (\log (1 + i z) - \log (1 - i z)) / (2 i)$$ +@end tex +@ifinfo + +@example +@group +arcsin(@var{z}) = -i log(i @var{z} + sqrt(1 - @var{z}^2)) +arccos(@var{z}) = pi/2 - arcsin(@var{z}) +arctan(@var{z}) = (log(1 + i @var{z}) + log(1 - i @var{z})) / (2 i) +@end group +@end example + +@end ifinfo +The above specification follows @cite{Common Lisp: the Language}, which +in turn cites @cite{Principal Values and Branch Cuts in Complex APL}; +refer to these sources for more detailed discussion of branch cuts, +boundary conditions, and implementation of these functions. When it is +possible these procedures produce a real result from a real +argument. +@end deffn + +@deffn procedure sqrt z +Returns the principal square root of @var{z}. The result will have +either positive real part, or zero real part and non-negative imaginary +part. +@end deffn + +@deffn procedure expt z1 z2 +Returns @var{z1} raised to the power @var{z2}: +@tex +$${z_1}^{z_2} = e^{z_2 \log {z_1}}$$ +$0^0$ is defined to be equal to 1. +@end tex +@ifinfo + +@example +@var{z1}^@var{z2} = e^(@var{z2} log @var{z1}) +@end example + +@noindent +0^0 is defined to be equal to 1. +@end ifinfo +@end deffn + +@deffn procedure make-rectangular x1 x2 +@deffnx procedure make-polar x3 x4 +@deffnx procedure real-part z +@deffnx procedure imag-part z +@deffnx procedure magnitude z +@deffnx procedure angle z +@deffnx procedure conjugate z +Suppose @var{x1}, @var{x2}, @var{x3}, and @var{x4} are real numbers and +@var{z} is a complex number such that +@tex + $$ z = x_1 + x_2\hbox{$i$} + = x_3 \cdot e^{{\displaystyle{\hbox{$i$}} x_4}}$$ +@end tex +@ifinfo + +@example +@var{z} = @var{x1} + @var{x2} i = @var{x3} e^(i @var{x4}) +@end example + +@end ifinfo +@noindent +Then @code{make-rectangular} and @code{make-polar} return @var{z}, +@code{real-part} returns @var{x1}, @code{imag-part} returns @var{x2}, +@code{magnitude} returns @var{x3}, and @code{angle} returns @var{x4}. +In the case of @code{angle}, whose value is not uniquely determined by +the preceding rule, the value returned will be the one in the range +minus @var{pi} (exclusive) to @var{pi} (inclusive). + +@code{conjugate} returns the complex conjugate of @var{z}. +@end deffn + +@deffn procedure exact->inexact z +@deffnx procedure inexact->exact z +@code{exact->inexact} returns an inexact representation of @var{z}. The +value returned is the inexact number that is numerically closest to the +argument. If an exact argument has no reasonably close inexact +equivalent, then a violation of an implementation restriction may be +reported; MIT/GNU Scheme signals an error of type +@code{condition-type:bad-range-argument} in this case. +@findex condition-type:bad-range-argument + +@code{inexact->exact} returns an exact representation of @var{z}. The +value returned is the exact number that is numerically closest to the +argument. If an inexact argument has no reasonably close exact +equivalent, then a violation of an implementation restriction may be +reported; in MIT/GNU Scheme this case does not occur because all inexact +numbers are representable as exact numbers. + +These procedures implement the natural one-to-one correspondence between +exact and inexact integers throughout an implementation-dependent range. +@xref{Implementation restrictions}. +@end deffn + +@node Numerical input and output, Fixnum and Flonum Operations, Numerical operations, Numbers +@section Numerical input and output +@cindex numerical input and output + +@deffn procedure number->string number [radix] +@var{Radix} must be an exact integer, either 2, 8, 10, or 16. If +omitted, @var{radix} defaults to 10. The procedure +@code{number->string} takes a number and a radix and returns as a string +an external representation of the given number in the given radix such +that + +@example +@group +(let ((number @var{number}) + (radix @var{radix})) + (eqv? number + (string->number (number->string number radix) + radix))) +@end group +@end example + +@noindent +is true. It is an error if no possible result makes this expression +true. + +If @var{number} is inexact, the radix is 10, and the above expression +can be satisfied by a result that contains a decimal point, then the +result contains a decimal point and is expressed using the minimum +number of digits (exclusive of exponent and trailing zeroes) needed to +make the above expression true; otherwise the format of the result is +unspecified. + +The result returned by @code{number->string} never contains an explicit +radix prefix. + +Note: The error case can occur only when @var{number} is not a complex +number or is a complex number with an non-rational real or imaginary +part. + +Rationale: If @var{number} is an inexact number represented using +flonums, and the radix is 10, then the above expression is normally +satisfied by a result containing a decimal point. The unspecified case +allows for infinities, NaNs, and non-flonum representations. +@end deffn + +@defvr variable flonum-parser-fast? +This variable controls the behavior of @code{string->number} when +parsing inexact numbers. Specifically, it allows the user to trade off +accuracy against speed. + +When set to its default value, @code{#f}, the parser provides maximal +accuracy, as required by the Scheme standard. If set to @code{#t}, the +parser uses faster algorithms that will sometimes introduce small errors +in the result. The errors affect a few of the least-significant bits of +the result, and consequently can be tolerated by many applications. +@end defvr + +@defvr variable flonum-unparser-cutoff +This variable controls the action of @code{number->string} when +@var{number} is a flonum (and consequently controls all printing of +flonums). The value of this variable is normally a list of three items: + +@table @var +@item rounding-type +One of the following symbols: @code{normal}, @code{relative}, or +@code{absolute}. The symbol @code{normal} means that the number should +be printed with full precision. The symbol @code{relative} means that +the number should be rounded to a specific number of digits. The symbol +@code{absolute} means that the number should be rounded so that there +are a specific number of digits to the right of the decimal point. + +@item precision +An exact integer. If @var{rounding-type} is @code{normal}, +@var{precision} is ignored. If @var{rounding-type} is @code{relative}, +@var{precision} must be positive, and it specifies the number of digits +to which the printed representation will be rounded. If +@var{rounding-type} is @code{absolute}, the printed representation will +be rounded @var{precision} digits to the right of the decimal point; if +@var{precision} is negative, the representation is rounded @code{(- +@var{precision})} digits to the left of the decimal point. + +@item format-type +One of the symbols: @code{normal}, @code{scientific}, or +@code{engineering}. This specifies the format in which the number will +be printed.@* @code{scientific} specifies that the number will be printed +using scientific notation: @code{@var{x}.@var{xxx}e@var{yyy}}. In other +words, the number is printed as a mantissa between zero inclusive and +ten exclusive, and an exponent. @code{engineering} is like +@code{scientific}, except that the exponent is always a power of three, +and the mantissa is constrained to be between zero inclusive and 1000 +exclusive. If @code{normal} is specified, the number will be printed in +positional notation if it is ``small enough'', otherwise it is printed +in scientific notation. A number is ``small enough'' when the number of +digits that would be printed using positional notation does not exceed +the number of digits of precision in the underlying floating-point +number representation; @sc{ieee} double-precision floating-point numbers +have 17 digits of precision. +@end table + +@noindent +This three-element list may be abbreviated in two ways. First, the +symbol @code{normal} may be used, which is equivalent to the list +@code{(normal 0 normal)}. Second, the third element of the list, +@var{format-type}, may be omitted, in which case it defaults to +@code{normal}. + +@noindent +The default value for @code{flonum-unparser-cutoff} is @code{normal}. +If it is bound to a value different from those described here, +@code{number->string} issues a warning and acts as though the value had +been @code{normal}. +@end defvr + +@noindent +Some examples of @code{flonum-unparser-cutoff}: + +@example +(number->string (* 4 (atan 1 1))) + @result{} "3.141592653589793" +(fluid-let ((flonum-unparser-cutoff '(relative 5))) + (number->string (* 4 (atan 1 1)))) + @result{} "3.1416" +(fluid-let ((flonum-unparser-cutoff '(relative 5))) + (number->string (* 4000 (atan 1 1)))) + @result{} "3141.6" +(fluid-let ((flonum-unparser-cutoff '(relative 5 scientific))) + (number->string (* 4000 (atan 1 1)))) + @result{} "3.1416e3" +(fluid-let ((flonum-unparser-cutoff '(relative 5 scientific))) + (number->string (* 40000 (atan 1 1)))) + @result{} "3.1416e4" +(fluid-let ((flonum-unparser-cutoff '(relative 5 engineering))) + (number->string (* 40000 (atan 1 1)))) + @result{} "31.416e3" +(fluid-let ((flonum-unparser-cutoff '(absolute 5))) + (number->string (* 4 (atan 1 1)))) + @result{} "3.14159" +(fluid-let ((flonum-unparser-cutoff '(absolute 5))) + (number->string (* 4000 (atan 1 1)))) + @result{} "3141.59265" +(fluid-let ((flonum-unparser-cutoff '(absolute -4))) + (number->string (* 4e10 (atan 1 1)))) + @result{} "31415930000." +(fluid-let ((flonum-unparser-cutoff '(absolute -4 scientific))) + (number->string (* 4e10 (atan 1 1)))) + @result{} "3.141593e10" +(fluid-let ((flonum-unparser-cutoff '(absolute -4 engineering))) + (number->string (* 4e10 (atan 1 1)))) + @result{} "31.41593e9" +(fluid-let ((flonum-unparser-cutoff '(absolute -5))) + (number->string (* 4e10 (atan 1 1)))) + @result{} "31415900000." +@end example + +@deffn procedure string->number string [radix] +Returns a number of the maximally precise representation expressed by +the given @var{string}. @var{Radix} must be an exact integer, either 2, +8, 10, or 16. If supplied, @var{radix} is a default radix that may be +overridden by an explicit radix prefix in @var{string} (e.g.@: +@code{"#o177"}). If @var{radix} is not supplied, then the default radix +is 10. If @var{string} is not a syntactically valid notation for a +number, then @code{string->number} returns @code{#f}. + +@example +@group +(string->number "100") @result{} 100 +(string->number "100" 16) @result{} 256 +(string->number "1e2") @result{} 100.0 +(string->number "15##") @result{} 1500.0 +@end group +@end example + +@noindent +Note that a numeric representation using a decimal point or an exponent +marker is not recognized unless @var{radix} is @code{10}. +@end deffn + +@node Fixnum and Flonum Operations, Random Numbers, Numerical input and output, Numbers +@section Fixnum and Flonum Operations + +This section describes numerical operations that are restricted forms of +the operations described above. These operations are useful because +they compile very efficiently. However, care should be exercised: if +used improperly, these operations can return incorrect answers, or even +malformed objects that confuse the garbage collector. + +@menu +* Fixnum Operations:: +* Flonum Operations:: +@end menu + +@node Fixnum Operations, Flonum Operations, Fixnum and Flonum Operations, Fixnum and Flonum Operations +@subsection Fixnum Operations + +@cindex fixnum (defn) +A @dfn{fixnum} is an exact integer that is small enough to fit in a +machine word. In MIT/GNU Scheme, fixnums are typically 24 or 26 bits, +depending on the machine; it is reasonable to assume that fixnums are at +least 24 bits. Fixnums are signed; they are encoded using 2's +complement. + +All exact integers that are small enough to be encoded as fixnums are +always encoded as fixnums --- in other words, any exact integer that is +not a fixnum is too big to be encoded as such. For this reason, small +constants such as @code{0} or @code{1} are guaranteed to be fixnums. + +@deffn procedure fix:fixnum? object +@cindex type predicate, for fixnum +Returns @code{#t} if @var{object} is a fixnum; otherwise returns +@code{#f}. +@end deffn + +Here is an expression that determines the largest fixnum: + +@example +@group +(let loop ((n 1)) + (if (fix:fixnum? n) + (loop (* n 2)) + (- n 1))) +@end group +@end example + +@noindent +A similar expression determines the smallest fixnum. + +@deffn procedure fix:= fixnum fixnum +@deffnx procedure fix:< fixnum fixnum +@deffnx procedure fix:> fixnum fixnum +@deffnx procedure fix:<= fixnum fixnum +@deffnx procedure fix:>= fixnum fixnum +@cindex equivalence predicate, for fixnums +These are the standard order and equality predicates on fixnums. When +compiled, they do not check the types of their arguments. +@end deffn + +@deffn procedure fix:zero? fixnum +@deffnx procedure fix:positive? fixnum +@deffnx procedure fix:negative? fixnum +These procedures compare their argument to zero. When compiled, they do +not check the type of their argument. The code produced by the +following expressions is identical: + +@example +@group +(fix:zero? @var{fixnum}) +(fix:= @var{fixnum} 0) +@end group +@end example + +@noindent +Similarly, @code{fix:positive?} and @code{fix:negative?} produce code +identical to equivalent expressions using @code{fix:>} and @code{fix:<}. +@end deffn + +@deffn procedure fix:+ fixnum fixnum +@deffnx procedure fix:- fixnum fixnum +@deffnx procedure fix:* fixnum fixnum +@deffnx procedure fix:quotient fixnum fixnum +@deffnx procedure fix:remainder fixnum fixnum +@deffnx procedure fix:gcd fixnum fixnum +@deffnx procedure fix:1+ fixnum +@deffnx procedure fix:-1+ fixnum +These procedures are the standard arithmetic operations on fixnums. +When compiled, they do not check the types of their arguments. +Furthermore, they do not check to see if the result can be encoded as a +fixnum. If the result is too large to be encoded as a fixnum, a +malformed object is returned, with potentially disastrous effect on the +garbage collector. +@end deffn + +@deffn procedure fix:divide fixnum fixnum +@findex integer-divide +@findex integer-divide-quotient +@findex integer-divide-remainder +This procedure is like @code{integer-divide}, except that its arguments +and its results must be fixnums. It should be used in conjunction with +@code{integer-divide-quotient} and @code{integer-divide-remainder}. +@end deffn + +@cindex logical operations, on fixnums +@cindex bitwise-logical operations, on fixnums +The following are @dfn{bitwise-logical} operations on fixnums. + +@deffn procedure fix:not fixnum +This returns the bitwise-logical inverse of its argument. When +compiled, it does not check the type of its argument. + +@example +@group +(fix:not 0) @result{} -1 +(fix:not -1) @result{} 0 +(fix:not 1) @result{} -2 +(fix:not -34) @result{} 33 +@end group +@end example +@end deffn + +@deffn procedure fix:and fixnum fixnum +This returns the bitwise-logical ``and'' of its arguments. When +compiled, it does not check the types of its arguments. + +@example +@group +(fix:and #x43 #x0f) @result{} 3 +(fix:and #x43 #xf0) @result{} #x40 +@end group +@end example +@end deffn + +@deffn procedure fix:andc fixnum fixnum +Returns the bitwise-logical ``and'' of the first argument with the +bitwise-logical inverse of the second argument. When compiled, it does +not check the types of its arguments. + +@example +@group +(fix:andc #x43 #x0f) @result{} #x40 +(fix:andc #x43 #xf0) @result{} 3 +@end group +@end example +@end deffn + +@deffn procedure fix:or fixnum fixnum +This returns the bitwise-logical ``inclusive or'' of its arguments. +When compiled, it does not check the types of its arguments. + +@example +@group +(fix:or #x40 3) @result{} #x43 +(fix:or #x41 3) @result{} #x43 +@end group +@end example +@end deffn + +@deffn procedure fix:xor fixnum fixnum +This returns the bitwise-logical ``exclusive or'' of its arguments. +When compiled, it does not check the types of its arguments. + +@example +@group +(fix:xor #x40 3) @result{} #x43 +(fix:xor #x41 3) @result{} #x42 +@end group +@end example +@end deffn + +@deffn procedure fix:lsh fixnum1 fixnum2 +This procedure returns the result of logically shifting @var{fixnum1} by +@var{fixnum2} bits. If @var{fixnum2} is positive, @var{fixnum1} is +shifted left; if negative, it is shifted right. When compiled, it does +not check the types of its arguments, nor the validity of its result. + +@example +@group +(fix:lsh 1 10) @result{} #x400 +(fix:lsh #x432 -10) @result{} 1 +(fix:lsh -1 3) @result{} -8 +(fix:lsh -128 -4) @result{} #x3FFFF8 +@end group +@end example +@end deffn + +@node Flonum Operations, , Fixnum Operations, Fixnum and Flonum Operations +@subsection Flonum Operations + +@cindex flonum (defn) +A @dfn{flonum} is an inexact real number that is implemented as a +floating-point number. In MIT/GNU Scheme, all inexact real numbers are +flonums. For this reason, constants such as @code{0.} and @code{2.3} +are guaranteed to be flonums. + +@deffn procedure flo:flonum? object +@cindex type predicate, for flonum +Returns @code{#t} if @var{object} is a flonum; otherwise returns @code{#f}. +@end deffn + +@deffn procedure flo:= flonum1 flonum2 +@deffnx procedure flo:< flonum1 flonum2 +@deffnx procedure flo:> flonum1 flonum2 +@cindex equivalence predicate, for flonums +These procedures are the standard order and equality predicates on +flonums. When compiled, they do not check the types of their arguments. +@end deffn + +@deffn procedure flo:zero? flonum +@deffnx procedure flo:positive? flonum +@deffnx procedure flo:negative? flonum +Each of these procedures compares its argument to zero. When compiled, +they do not check the type of their argument. +@end deffn + +@deffn procedure flo:+ flonum1 flonum2 +@deffnx procedure flo:- flonum1 flonum2 +@deffnx procedure flo:* flonum1 flonum2 +@deffnx procedure flo:/ flonum1 flonum2 +These procedures are the standard arithmetic operations on flonums. +When compiled, they do not check the types of their arguments. +@end deffn + +@deffn procedure flo:finite? flonum +@vindex +inf +@vindex -inf +@vindex NaN +@cindex positive infinity (@code{+inf}) +@cindex negative infinity (@code{-inf}) +@cindex not a number (@code{NaN}) +The @acronym{IEEE} floating-point number specification supports three +special ``numbers'': positive infinity (@code{+inf}), negative infinity +(@code{-inf}), and not-a-number (@code{NaN}). This predicate returns +@code{#f} if @var{flonum} is one of these objects, and @code{#t} if it +is any other floating-point number. +@end deffn + +@deffn procedure flo:negate flonum +This procedure returns the negation of its argument. When compiled, it +does not check the type of its argument. Equivalent to @code{(flo:- 0. +@var{flonum})}. +@end deffn + +@deffn procedure flo:abs flonum +@deffnx procedure flo:exp flonum +@deffnx procedure flo:log flonum +@deffnx procedure flo:sin flonum +@deffnx procedure flo:cos flonum +@deffnx procedure flo:tan flonum +@deffnx procedure flo:asin flonum +@deffnx procedure flo:acos flonum +@deffnx procedure flo:atan flonum +@deffnx procedure flo:sqrt flonum +@deffnx procedure flo:expt flonum1 flonum2 +@deffnx procedure flo:floor flonum +@deffnx procedure flo:ceiling flonum +@deffnx procedure flo:truncate flonum +@deffnx procedure flo:round flonum +@deffnx procedure flo:floor->exact flonum +@deffnx procedure flo:ceiling->exact flonum +@deffnx procedure flo:truncate->exact flonum +@deffnx procedure flo:round->exact flonum +These procedures are flonum versions of the corresponding procedures. +When compiled, they do not check the types of their arguments. +@end deffn + +@deffn procedure flo:atan2 flonum1 flonum2 +@findex atan +This is the flonum version of @code{atan} with two arguments. When +compiled, it does not check the types of its arguments. +@end deffn + +@node Random Numbers, , Fixnum and Flonum Operations, Numbers +@section Random Numbers +@cindex random number +@cindex pseudo-random number +@cindex number, pseudo-random + +MIT/GNU Scheme provides a facility for generating pseudo-random numbers. +The current implementation is a ``subtract-with-carry'' random-number +generator, based on the algorithm from @cite{A New Class of Random +Number Generators}, George Marsaglia and Arif Zaman, @cite{The Annals of +Applied Probability}, Vol.@: 1, No.@: 3, 1991. At the time it was +implemented, this was a good algorithm for general purposes, but the +state of the art in random-number generation is constantly changing. If +necessary, the implementation will be updated to use a new algorithm +while retaining the same interface. + +The interface described here is very similar to that of Common Lisp. + +@deffn procedure random modulus [state] +@var{Modulus} must be a positive real number. @code{random} returns a +pseudo-random number between zero (inclusive) and @var{modulus} +(exclusive). The exactness of the returned number is the same as the +exactness of @var{modulus}. Additionally, if @var{modulus} is an exact +integer, the returned number will be also. Usually, @var{modulus} is +either an exact integer or an inexact real; the current implementation +has been tuned to make these two cases fast. + +If @var{state} is given and not @code{#f}, it must be a random-state +object; otherwise, it defaults to the value of the variable +@code{*random-state*}. This object is used to maintain the state of the +pseudo-random-number generator and is altered as a side effect of the +@code{random} procedure. + +@example +@group +(random 1.0) @result{} .32744744667719056 +(random 1.0) @result{} .01668326768172354 +(random 10) @result{} 3 +(random 10) @result{} 8 +(random 100) @result{} 38 +(random 100) @result{} 63 +(random 100/3) @result{} 130501475769920525/6755399441055744 +(random 100/3) @result{} 170571694016427575/13510798882111488 +@end group +@end example +@end deffn + +@deffn procedure flo:random-unit state +@var{State} must be a random-state object. @code{flo:random-unit} +returns a pseudo-random number between zero inclusive and one exclusive; +the returned number is always a flonum and therefore an inexact real +number. @code{flo:random-unit} is equivalent to @code{random} with a +@var{modulus} of @code{1.0}, except that it is faster. +@end deffn + +The next three definitions concern random-state objects. In addition to +these definitions, it is important to know that random-state objects are +specifically designed so that they can be saved to disk using the +@code{fasdump} procedure, and later restored using the @code{fasload} +procedure. This allows a particular random-state object to be saved in +order to replay a particular pseudo-random sequence. + +@defvr variable *random-state* +This variable holds a data structure, a random-state object, that +encodes the internal state of the random-number generator that +@code{random} uses by default. A call to @code{random} will perform a +side effect on this data structure. This variable may be changed, using +@code{set!} or @code{fluid-let}, to hold a new random-state object. +@end defvr + +@deffn procedure make-random-state [state] +This procedure returns a new random-state object, suitable for use as +the value of the variable @code{*random-state*}, or as the @var{state} +argument to @code{random}. If @var{state} is not given or @code{#f}, +@code{make-random-state} returns a @emph{copy} of the current +random-number state object (the value of the variable +@code{*random-state*}). If @var{state} is a random-state object, a copy +of that object is returned. If @var{state} is @code{#t}, then a new +random-state object is returned that has been ``randomly'' initialized +by some means (such as by a time-of-day clock). +@end deffn + +@deffn procedure random-state? object +Returns @code{#t} if @var{object} is a random-state object, otherwise +returns @code{#f}. +@end deffn diff --git a/v7/doc/ref-manual/os-interface.texi b/v7/doc/ref-manual/os-interface.texi new file mode 100644 index 000000000..2cbe59ea2 --- /dev/null +++ b/v7/doc/ref-manual/os-interface.texi @@ -0,0 +1,2711 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: os-interface.texi,v 1.1 2003/04/15 03:30:00 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Operating-System Interface, Error System, Input/Output, Top +@chapter Operating-System Interface +@cindex Operating-System Interface + +The Scheme standard provides a simple mechanism for reading and writing +files: file ports. MIT/GNU Scheme provides additional tools for +dealing with other aspects of the operating system: + +@itemize @bullet +@item +@dfn{Pathnames} are a reasonably operating-system independent tool for +manipulating the component parts of file names. This can be useful for +implementing defaulting of file name components. +@cindex pathname + +@item +Control over the @dfn{current working directory}: the place in the file +system from which relative file names are interpreted. +@cindex current working directory + +@item +Procedures that rename, copy, delete, and test for the existence of +files. Also, procedures that return detailed information about a +particular file, such as its type (directory, link, etc.) or length. + +@item +Procedures for reading the contents of a directory. + +@item +Procedures for obtaining times in various formats, converting between +the formats, and generating human-readable time strings. + +@item +Procedures to run other programs as subprocesses of Scheme, to read +their output, and write input to them. + +@item +A means to determine the operating system Scheme is running under. +@end itemize + +@menu +* Pathnames:: +* Working Directory:: +* File Manipulation:: +* Directory Reader:: +* Date and Time:: +* Machine Time:: +* Subprocesses:: +* TCP Sockets:: +* Miscellaneous OS Facilities:: +@end menu + +@node Pathnames, Working Directory, Operating-System Interface, Operating-System Interface +@section Pathnames + +@comment **** begin CLTL **** +@cindex file name +MIT/GNU Scheme programs need to use names to designate files. The main +difficulty in dealing with names of files is that different file systems +have different naming formats for files. For example, here is a table +of several file systems (actually, operating systems that provide file +systems) and what equivalent file names might look like for each one: + +@example +@group +System File Name +------ --------- +TOPS-20 FORMAT.FASL.13 +TOPS-10 FORMAT.FAS[1,4] +ITS LISPIO;FORMAT FASL +MULTICS >udd>LispIO>format.fasl +TENEX FORMAT.FASL;13 +VAX/VMS [LISPIO]FORMAT.FAS;13 +UNIX /usr/lispio/format.fasl +DOS C:\USR\LISPIO\FORMAT.FAS +@end group +@end example + +@cindex filename (defn) +@cindex pathname (defn) +It would be impossible for each program that deals with file names to +know about each different file name format that exists; a new operating +system to which Scheme was ported might use a format different from any +of its predecessors. Therefore, MIT/GNU Scheme provides @emph{two} ways to +represent file names: @dfn{filenames} (also called @dfn{namestrings}), +which are strings in the implementation-dependent form customary for the +file system, and @dfn{pathnames}, which are special abstract data +objects that represent file names in an implementation-independent way. +Procedures are provided to convert between these two representations, +and all manipulations of files can be expressed in machine-independent +terms by using pathnames. + +@cindex host, in filename +In order to allow MIT/GNU Scheme programs to operate in a network +environment that may have more than one kind of file system, the +pathname facility allows a file name to specify which file system is to +be used. In this context, each file system is called a @dfn{host}, in +keeping with the usual networking terminology.@footnote{This +introduction is adapted from @cite{Common Lisp, The Language}, second +edition, section 23.1.} +@comment **** end CLTL **** + +Note that the examples given in this section are specific to unix +pathnames. Pathnames for other operating systems have different +external representations. + +@menu +* Filenames and Pathnames:: +* Components of Pathnames:: +* Operations on Pathnames:: +* Miscellaneous Pathnames:: +@end menu + +@node Filenames and Pathnames, Components of Pathnames, Pathnames, Pathnames +@subsection Filenames and Pathnames + +Pathname objects are usually created by parsing filenames (character +strings) into component parts. MIT/GNU Scheme provides operations that +convert filenames into pathnames and vice versa. + +@deffn procedure ->pathname object +@cindex construction, of pathname +Returns a pathname that is the equivalent of @var{object}. @var{Object} +must be a pathname or a string. If @var{object} is a pathname, it is +returned. If @var{object} is a string, this procedure returns the +pathname that corresponds to the string; in this case it is equivalent +to @code{(parse-namestring @var{object} #f #f)}. + +@example +@group +(->pathname "foo") @result{} #[pathname 65 "foo"] +(->pathname "/usr/morris") @result{} #[pathname 66 "/usr/morris"] +@end group +@end example +@end deffn + + +@deffn procedure parse-namestring thing [host [defaults]] +@cindex construction, of pathname +This turns @var{thing} into a pathname. +@var{Thing} must be a pathname or a string. +If @var{thing} is a pathname, it is returned. If @var{thing} is a +string, this procedure returns the pathname that corresponds to the +string, parsed according to the syntax of the file system specified by +@var{host}. + +This procedure @emph{does not} do defaulting of pathname components. + +The optional arguments are used to determine what syntax should be used +for parsing the string. In general this is only really useful if your +implementation of MIT/GNU Scheme supports more than one file system, +otherwise you would use @code{->pathname}. If given, @var{host} must be +a host object or @code{#f}, and @var{defaults} must be a pathname. +@var{Host} specifies the syntax used to parse the string. If @var{host} +is not given or @code{#f}, the host component from @var{defaults} is +used instead; if @var{defaults} is not given, the host component from +@code{*default-pathname-defaults*} is used. +@end deffn + +@deffn procedure ->namestring pathname +@cindex conversion, pathname to string +@code{->namestring} returns a newly allocated string that is the +filename corresponding to @var{pathname}. +@example +@group +(->namestring (->pathname "/usr/morris/minor.van")) + @result{} "/usr/morris/minor.van" +@end group +@end example +@end deffn + + +@deffn procedure pathname-simplify pathname +@cindex simplification, of pathname +Returns a pathname that locates the same file or directory as +@var{pathname}, but is in some sense simpler. Note that +@code{pathname-simplify} might not always be able to simplify the +pathname, e.g.@: on unix with symbolic links the directory +@file{/usr/morris/../} need not be the same as @file{/usr/}. In cases +of uncertainty the behavior is conservative, returning the original or a +partly simplified pathname. + +@example +@group +(pathname-simplify "/usr/morris/../morris/dance") + @result{} #[pathname "/usr/morris/dance"] +@end group +@end example +@end deffn + +@node Components of Pathnames, Operations on Pathnames, Filenames and Pathnames, Pathnames +@subsection Components of Pathnames +@cindex components, of pathname +@cindex pathname components + +@comment **** begin CLTL **** +A pathname object always has six components, described below. These +components are the common interface that allows programs to work the +same way with different file systems; the mapping of the pathname +components into the concepts peculiar to each file system is taken care +of by the Scheme implementation. + +@table @var +@item host +The name of the file system on which the file resides. In the current +implementation, this component is always a host object that is filled in +automatically by the runtime system. When specifying the host +component, use either @code{#f} or the value of the variable +@code{local-host}. +@cindex host, pathname component + +@item device +Corresponds to the ``device'' or ``file structure'' concept in many host +file systems: the name of a (logical or physical) device containing +files. This component is the drive letter for PC file systems, and is +unused for unix file systems. +@cindex device, pathname component + +@item directory +Corresponds to the ``directory'' concept in many host file systems: the +name of a group of related files (typically those belonging to a single +user or project). This component is always used for all file systems. +@cindex directory, pathname component + +@item name +The name of a group of files that can be thought of as conceptually the +``same'' file. This component is always used for all file systems. +@cindex name, pathname component + +@item type +Corresponds to the ``filetype'' or ``extension'' concept in many host +file systems. This says what kind of file this is. Files with the same +name but different type are usually related in some specific way, such +as one being a source file, another the compiled form of that source, +and a third the listing of error messages from the compiler. This +component is currently used for all file systems, and is formed by +taking the characters that follow the last dot in the namestring. +@cindex type, pathname component + +@item version +Corresponds to the ``version number'' concept in many host file systems. +Typically this is a number that is incremented every time the file is +modified. This component is currently unused for all file systems. +@cindex version, pathname component +@end table + +Note that a pathname is not necessarily the name of a specific file. +Rather, it is a specification (possibly only a partial specification) of +how to access a file. A pathname need not correspond to any file that +actually exists, and more than one pathname can refer to the same file. +For example, the pathname with a version of @code{newest} may refer to +the same file as a pathname with the same components except a certain +number as the version. Indeed, a pathname with version @code{newest} +may refer to different files as time passes, because the meaning of such +a pathname depends on the state of the file system. In file systems +with such facilities as ``links'', multiple file names, logical devices, +and so on, two pathnames that look quite different may turn out to +address the same file. To access a file given a pathname, one must do a +file-system operation such as @code{open-input-file}. + +Two important operations involving pathnames are @dfn{parsing} and +@dfn{merging}. Parsing is the conversion of a filename (which might be +something supplied interactively by the users when asked to supply the +name of a file) into a pathname object. This operation is +implementation-dependent, because the format of filenames is +implementation-dependent. Merging takes a pathname with missing +components and supplies values for those components from a source of +default values. + +Not all of the components of a pathname need to be specified. If a +component of a pathname is missing, its value is @code{#f}. +Before the file system interface can do anything interesting with a +file, such as opening the file, all the missing components of a pathname +must be filled in. Pathnames with missing components are used +internally for various purposes; in particular, parsing a namestring +that does not specify certain components will result in a pathname with +missing components. + +Any component of a pathname may be the symbol @code{unspecific}, meaning +that the component simply does not exist, for file systems in which such +a value makes no sense. For example, unix, Windows, and OS/2 file +systems usually do not support version numbers, so the version component +for such a host might be @code{unspecific}.@footnote{This description is +adapted from @cite{Common Lisp, The Language}, second edition, section +23.1.1.} +@comment **** end CLTL **** + +In addition to @code{#f} and @code{unspecific}, the components of a +pathname may take on the following meaningful values: + +@table @var +@item host +An implementation-defined type which may be tested for using the +@code{host?} predicate. + +@item device +On systems that support this component (Windows and OS/2), it may be +specified as a string containing a single alphabetic character, for +which the alphabetic case is ignored. + +@item directory +A non-empty list, which represents a @dfn{directory path}: a sequence of +directories, each of which has a name in the previous directory, the +last of which is the directory specified by the entire path. Each +element in such a path specifies the name of the directory relative to +the directory specified by the elements to its left. The first element +of the list is either the symbol @code{absolute} or the symbol +@code{relative}. If the first element in the list is the symbol +@code{absolute}, then the directory component (and subsequently the +pathname) is @dfn{absolute}; the first component in the sequence is to +be found at the ``root'' of the file system. If the directory is +@dfn{relative} then the first component is to be found in some as yet +unspecified directory; typically this is later specified to be the +@dfn{current working directory}. +@cindex root, as pathname component +@cindex directory path (defn) +@cindex path, directory (defn) + +@cindex up, as pathname component +@cindex parent, of directory +Aside from @code{absolute} and @code{relative}, which may only appear as +the first element of the list, each subsequent element in the list is +either: a string, which is a literal component; the symbol @code{wild}, +meaningful only when used in conjunction with the directory reader; or +the symbol @code{up}, meaning the next directory is the ``parent'' of +the previous one. @code{up} corresponds to the file @file{..} in unix +and PC file systems. + +(The following note does not refer to any file system currently +supported by MIT/GNU Scheme, but is included for completeness.) In file +systems that do not have ``hierarchical'' structure, a specified +directory component will always be a list whose first element is +@code{absolute}. If the system does not support directories other than +a single global directory, the list will have no other elements. If the +system supports ``flat'' directories, i.e.@: a global set of directories +with no subdirectories, then the list will contain a second element, +which is either a string or @code{wild}. In other words, a +non-hierarchical file system is treated as if it were hierarchical, but +the hierarchical features are unused. This representation is somewhat +inconvenient for such file systems, but it discourages programmers from +making code depend on the lack of a file hierarchy. + +@item name +A string, which is a literal component; or the symbol @code{wild}, +meaningful only when used in conjunction with the directory reader. + +@item type +A string, which is a literal component; or the symbol @code{wild}, +meaningful only when used in conjunction with the directory reader. + +@item version +An exact positive integer, which is a literal component; the symbol +@code{newest}, which means to choose the largest available version +number for that file; the symbol @code{oldest}, which means to choose +the smallest version number; or the symbol @code{wild}, meaningful only +when used in conjunction with the directory reader. In the future some +other possible values may be added, e.g.@: @code{installed}. Note that +currently no file systems support version numbers; thus this component +is not used and should be specified as @code{#f}. +@cindex newest, as pathname component +@cindex oldest, as pathname component +@cindex installed, as pathname component +@end table + +@deffn procedure make-pathname host device directory name type version +@cindex construction, of pathname +Returns a pathname object whose components are the respective arguments. +Each argument must satisfy the restrictions for the corresponding +component, which were outlined above. + +@example +@group +(make-pathname #f + #f + '(absolute "usr" "morris") + "foo" + "scm" + #f) + @result{} #[pathname 67 "/usr/morris/foo.scm"] +@end group +@end example +@end deffn + +@deffn procedure pathname-host pathname +@deffnx procedure pathname-device pathname +@deffnx procedure pathname-directory pathname +@deffnx procedure pathname-name pathname +@deffnx procedure pathname-type pathname +@deffnx procedure pathname-version pathname +Returns a particular component of @var{pathname}. + +@example +@group +(define x (->pathname "/usr/morris/foo.scm")) +(pathname-host x) @result{} #[host 1] +(pathname-device x) @result{} unspecific +(pathname-directory x) @result{} (absolute "usr" "morris") +(pathname-name x) @result{} "foo" +(pathname-type x) @result{} "scm" +(pathname-version x) @result{} unspecific +@end group +@end example +@end deffn + +@deffn procedure pathname-new-device pathname device +@deffnx procedure pathname-new-directory pathname directory +@deffnx procedure pathname-new-name pathname name +@deffnx procedure pathname-new-type pathname type +@deffnx procedure pathname-new-version pathname version +Returns a new copy of @var{pathname} with the respective component +replaced by the second argument. @var{Pathname} is unchanged. +Portable programs should not explicitly replace a component with +@code{unspecific} because this might not be permitted in some +situations. + +@example +@group +(define p (->pathname "/usr/blisp/rel15")) +p + @result{} #[pathname 71 "/usr/blisp/rel15"] +(pathname-new-name p "rel100") + @result{} #[pathname 72 "/usr/blisp/rel100"] +(pathname-new-directory p '(relative "test" "morris")) + @result{} #[pathname 73 "test/morris/rel15"] +p + @result{} #[pathname 71 "/usr/blisp/rel15"] +@end group +@end example +@end deffn + +@deffn procedure pathname-default-device pathname device +@deffnx procedure pathname-default-directory pathname directory +@deffnx procedure pathname-default-name pathname name +@deffnx procedure pathname-default-type pathname type +@deffnx procedure pathname-default-version pathname version +These operations are similar to the @code{pathname-new-@var{component}} +operations, except that they only change the specified @var{component} +if it has the value @code{#f} in @var{pathname}. +@end deffn + +@node Operations on Pathnames, Miscellaneous Pathnames, Components of Pathnames, Pathnames +@subsection Operations on Pathnames + +@deffn procedure pathname? object +@cindex type predicate, for pathname +Returns @code{#t} if @var{object} is a pathname; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure pathname=? pathname1 pathname2 +@cindex equivalence predicate, for pathnames +Returns @code{#t} if @var{pathname1} is equivalent to @var{pathname2}; +otherwise returns @code{#f}. +Pathnames are equivalent if all of their components are equivalent, +hence two pathnames that are equivalent must identify the same file or +equivalent partial pathnames. +However, the converse is not true: non-equivalent pathnames may specify +the same file (e.g.@: via absolute and relative directory components), +and pathnames that specify no file at all (e.g.@: name and directory +components unspecified) may be equivalent. +@end deffn + +@deffn procedure pathname-absolute? pathname +Returns @code{#t} if @var{pathname} is an absolute rather than relative +pathname object; otherwise returns @code{#f}. Specifically, this +procedure returns @code{#t} when the directory component of +@var{pathname} is a list starting with the symbol @code{absolute}, and +returns @code{#f} in all other cases. All pathnames are either absolute +or relative, so if this procedure returns @code{#f}, the argument is a +relative pathname. +@end deffn + +@deffn procedure directory-pathname? pathname +Returns @code{#t} if @var{pathname} has only directory components and no +file components. This is roughly equivalent to + +@example +@group +(define (directory-pathname? pathname) + (string-null? (file-namestring pathname))) +@end group +@end example + +@noindent +except that it is faster. +@end deffn + +@deffn procedure pathname-wild? pathname +Returns @code{#t} if @var{pathname} contains any wildcard components; +otherwise returns @code{#f}. +@end deffn + +@deffn procedure merge-pathnames pathname [defaults [default-version]] +@cindex merging, of pathnames +@cindex defaulting, of pathname +Returns a pathname whose components are obtained by combining those of +@var{pathname} and @var{defaults}. @var{Defaults} defaults to the value +of @code{*default-pathname-defaults*} and @var{default-version} defaults +to @code{newest}. + +The pathnames are combined by components: if @var{pathname} has a +non-missing component, that is the resulting component, otherwise the +component from @var{defaults} is used. +The default version can be @code{#f} to preserve the information that +the component was missing from @var{pathname}. +The directory component is handled specially: if both pathnames have +directory components that are lists, and the directory component from +@var{pathname} is relative (i.e.@: starts with @code{relative}), then the +resulting directory component is formed by appending @var{pathname}'s +component to @var{defaults}'s component. +For example: + +@example +@group +(define path1 (->pathname "scheme/foo.scm")) +(define path2 (->pathname "/usr/morris")) +path1 + @result{} #[pathname 74 "scheme/foo.scm"] +path2 + @result{} #[pathname 75 "/usr/morris"] +(merge-pathnames path1 path2) + @result{} #[pathname 76 "/usr/scheme/foo.scm"] +(merge-pathnames path2 path1) + @result{} #[pathname 77 "/usr/morris.scm"] +@end group +@end example + +The merging rules for the version are more complex and depend on whether +@var{pathname} specifies a name. If @var{pathname} does not specify a +name, then the version, if not provided, will come from @var{defaults}. +However, if @var{pathname} does specify a name then the version is not +affected by @var{defaults}. The reason is that the version ``belongs +to'' some other file name and is unlikely to have anything to do with +the new one. Finally, if this process leaves the version missing, then +@var{default-version} is used. + +The net effect is that if the user supplies just a name, then the host, +device, directory and type will come from @var{defaults}, but the +version will come from @var{default-version}. If the user supplies +nothing, or just a directory, the name, type and version will come over +from @var{defaults} together. +@end deffn + +@defvr variable *default-pathname-defaults* +@cindex defaulting, of pathname +This is the default pathname-defaults pathname; if any pathname +primitive that needs a set of defaults is not given one, it uses this +one. @code{set-working-directory-pathname!} sets this variable to a new +value, computed by merging the new working directory with the variable's +old value. +@end defvr + +@deffn procedure pathname-default pathname device directory name type version +This procedure defaults all of the components of @var{pathname} +simultaneously. It could have been defined by: + +@example +@group +(define (pathname-default pathname + device directory name type version) + (make-pathname (pathname-host pathname) + (or (pathname-device pathname) device) + (or (pathname-directory pathname) directory) + (or (pathname-name pathname) name) + (or (pathname-type pathname) type) + (or (pathname-version pathname) version))) +@end group +@end example +@end deffn + +@deffn procedure file-namestring pathname +@deffnx procedure directory-namestring pathname +@deffnx procedure host-namestring pathname +@deffnx procedure enough-namestring pathname [defaults] +@cindex conversion, pathname to string +These procedures return a string corresponding to a subset of the +@var{pathname} information. @code{file-namestring} returns a string +representing just the @var{name}, @var{type} and @var{version} +components of @var{pathname}; the result of @code{directory-namestring} +represents just the @var{host}, @var{device}, and @var{directory} +components; and @code{host-namestring} returns a string for just the +@var{host} portion. + +@code{enough-namestring} takes another argument, @var{defaults}. +It returns an abbreviated namestring that is just sufficient to identify +the file named by @var{pathname} when considered relative to the +@var{defaults} (which defaults to @code{*default-pathname-defaults*}). + +@example +@group +(file-namestring "/usr/morris/minor.van") + @result{} "minor.van" +(directory-namestring "/usr/morris/minor.van") + @result{} "/usr/morris/" +(enough-namestring "/usr/morris/men") + @result{} "men" @r{;perhaps} +@end group +@end example +@end deffn + +@deffn procedure file-pathname pathname +@deffnx procedure directory-pathname pathname +@deffnx procedure enough-pathname pathname [defaults] +@cindex selection, components of pathname +These procedures return a pathname corresponding to a subset of the +@var{pathname} information. +@code{file-pathname} returns a pathname with just the +@var{name}, @var{type} and @var{version} components of @var{pathname}. +The result of @code{directory-pathname} is a pathname containing the +@var{host}, @var{device} and @var{directory} components of @var{pathname}. + +@code{enough-pathname} takes another argument, @var{defaults}. +It returns an abbreviated pathname that is just sufficient to identify +the file named by @var{pathname} when considered relative to the +@var{defaults} (which defaults to @code{*default-pathname-defaults*}). + +These procedures are similar to @code{file-namestring}, +@code{directory-namestring} and @code{enough-namestring}, but they +return pathnames instead of strings. +@end deffn + +@deffn procedure directory-pathname-as-file pathname +@cindex file, converting pathname directory to +Returns a pathname that is equivalent to @var{pathname}, but in which +the directory component is represented as a file. +The last directory is removed from the directory component and converted +into name and type components. +This is the inverse operation to @code{pathname-as-directory}. + +@example +@group +(directory-pathname-as-file (->pathname "/usr/blisp/")) + @result{} #[pathname "/usr/blisp"] +@end group +@end example +@end deffn + +@deffn procedure pathname-as-directory pathname +@cindex directory, converting pathname to +Returns a pathname that is equivalent to @var{pathname}, but in which +any file components have been converted to a directory component. If +@var{pathname} does not have name, type, or version components, it is +returned without modification. Otherwise, these file components are +converted into a string, and the string is added to the end of the list +of directory components. This is the inverse operation to +@code{directory-pathname-as-file}. + +@example +@group +(pathname-as-directory (->pathname "/usr/blisp/rel5")) + @result{} #[pathname "/usr/blisp/rel5/"] +@end group +@end example +@end deffn + + +@node Miscellaneous Pathnames, , Operations on Pathnames, Pathnames +@subsection Miscellaneous Pathname Procedures +@cindex directory, reading + +This section gives some standard operations on host objects, and some +procedures that return some useful pathnames. + +@defvr variable local-host +This variable has as its value the host object that describes the local +host's file system. +@end defvr + +@deffn procedure host? object +@cindex type predicate, for pathname host +Returns @code{#t} if @var{object} is a pathname host; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure host=? host1 host2 +@cindex equivalence predicate, for pathname host +Returns @code{#t} if @var{host1} and @var{host2} denote the same +pathname host; otherwise returns @code{#f}. +@end deffn + +@deffn procedure init-file-pathname [host] +@cindex home directory, as pathname +Returns a pathname for the user's initialization file on @var{host}. +The @var{host} argument defaults to the value of @code{local-host}. If +the initialization file does not exist this procedure returns @code{#f}. + +Under unix, the init file is called @file{.scheme.init}; under Windows +and OS/2, the init file is called @file{scheme.ini}. In either +case, it is located in the user's home directory, which is computed by +@code{user-homedir-pathname}. +@end deffn + +@deffn procedure user-homedir-pathname [host] +@cindex home directory, as pathname +Returns a pathname for the user's ``home directory'' on @var{host}. The +@var{host} argument defaults to the value of @code{local-host}. The +concept of a ``home directory'' is itself somewhat +implementation-dependent, but it should be the place where the user +keeps personal files, such as initialization files and mail. + +Under unix, the user's home directory is specified by the @code{HOME} +environment variable. If this variable is undefined, the user name is +computed using the @code{getlogin} system call, or if that fails, the +@code{getuid} system call. The resulting user name is passed to the +@code{getpwnam} system call to obtain the home directory. + +Under OS/2, several heuristics are tried to find the user's home +directory. First, if the environment variable @code{HOME} is defined, +that is the home directory. If @code{HOME} is undefined, but the +@code{USERDIR} and @code{USER} environment variables are defined and +the directory @file{%USERDIR%\%USER%} exists, then it is used. Failing +that, if the directory @file{%USER%} exists on the OS/2 system +drive, then it is used. As a last resort, the OS/2 system drive is +the home directory. + +Like OS/2, the Windows implementation uses heuristics based on +environment variables. The user's home directory is computed by +examining several environment variables, in the following order: + +@itemize @bullet +@item +@code{HOMEDRIVE} and @code{HOMEPATH} are both defined and +@file{%HOMEDRIVE%%HOMEPATH%} is an existing directory. (These variables +are automatically defined by Windows NT.) + +@item +@code{HOME} is defined and @file{%HOME%} is an existing directory. + +@item +@code{USERDIR} and @code{USERNAME} are defined and +@file{%USERDIR%\%USERNAME%} is an existing directory. + +@item +@code{USERDIR} and @code{USER} are defined and +@file{%USERDIR%\%USER%} is an existing directory. + +@item +@code{USERNAME} is defined and @file{%USERNAME%} is an existing +directory on the Windows system drive. + +@item +@code{USER} is defined and @file{%USER%} is an existing directory on the +Windows system drive. + +@item +Finally, if all else fails, the Windows system drive is used as the home +directory. +@end itemize +@end deffn + +@deffn procedure system-library-pathname pathname +@cindex library, system pathname +Locates @var{pathname} in MIT/GNU Scheme's system library directory. An +error of type @code{condition-type:file-operation-error} is signalled if +@var{pathname} cannot be located on the library search path. +@findex condition-type:file-operation-error + +@example +@group +(system-library-pathname "compiler.com") + @result{} #[pathname 45 "/usr/local/lib/mit-scheme/compiler.com"] +@end group +@end example +@end deffn + +@deffn procedure system-library-directory-pathname pathname +@cindex library, system pathname +Locates the pathname of an MIT/GNU Scheme system library directory. An +error of type @code{condition-type:file-operation-error} is signalled if +@var{pathname} cannot be located on the library search path. + +@example +@group +(system-library-directory-pathname "options") + @result{} #[pathname 44 "/usr/local/lib/mit-scheme/options/"] +@end group +@end example +@end deffn + +@node Working Directory, File Manipulation, Pathnames, Operating-System Interface +@section Working Directory + +@cindex absolute pathname (defn) +@cindex pathname, absolute (defn) +@cindex relative pathname (defn) +@cindex pathname, relative (defn) +@cindex directory, current working (defn) +@cindex current working directory (defn) +@cindex working directory (see current working directory) +When MIT/GNU Scheme is started, the @dfn{current working directory} (or +simply, @dfn{working directory}) is initialized in an operating-system +dependent manner; usually, it is the directory in which Scheme was +invoked. The working directory can be determined from within Scheme by +calling the @code{pwd} procedure, and changed by calling the @code{cd} +procedure. Each @acronym{REP} loop has its own working directory, and +inferior @acronym{REP} loops initialize their working directory from the +value in effect in their superior at the time they are created. + +@deffn procedure working-directory-pathname +@deffnx procedure pwd +Returns the current working directory as a pathname that has no name, +type, or version components, just host, device, and directory +components. @code{pwd} is an alias for +@code{working-directory-pathname}; the long name is intended for +programs and the short name for interactive use. +@end deffn + +@deffn procedure set-working-directory-pathname! filename +@deffnx procedure cd filename +@findex ->pathname +@findex pathname-as-directory +Makes @var{filename} the current working directory and returns the new +current working directory as a pathname. @var{Filename} is coerced to a +pathname using @code{pathname-as-directory}. @code{cd} is an alias for +@code{set-working-directory-pathname!}; the long name is intended for +programs and the short name for interactive use. + +Additionally, @code{set-working-directory-pathname!} modifies the value +of@* @code{*default-pathname-defaults*} by merging the new working +directory into it. + +When this procedure is executed in the top-level @acronym{REP} loop, it +changes the working directory of the running Scheme executable. + +@example +@group +(set-working-directory-pathname! "/usr/morris/blisp") + @result{} #[pathname "/usr/morris/blisp/"] +(set-working-directory-pathname! "~") + @result{} #[pathname "/usr/morris/"] +@end group +@end example + +This procedure signals an error if @var{filename} does not refer to an +existing directory. + +If @var{filename} describes a relative rather than absolute pathname, +this procedure interprets it as relative to the current working +directory, before changing the working directory. + +@example +@group +(working-directory-pathname) + @result{} #[pathname "/usr/morris/"] +(set-working-directory-pathname! "foo") + @result{} #[pathname "/usr/morris/foo/"] +@end group +@end example +@end deffn + +@deffn procedure with-working-directory-pathname filename thunk +This procedure temporarily rebinds the current working directory to +@var{filename}, invokes @var{thunk} (a procedure of no arguments), then +restores the previous working directory and returns the value yielded by +@var{thunk}. @var{Filename} is coerced to a pathname using +@code{pathname-as-directory}. In addition to binding the working +directory, @code{with-working-directory-pathname} also binds the +variable @code{*default-pathname-defaults*}, merging the old value of +that variable with the new working directory pathname. Both bindings +are performed in exactly the same way as dynamic binding of a variable +(@pxref{Dynamic Binding}). +@end deffn + +@node File Manipulation, Directory Reader, Working Directory, Operating-System Interface +@section File Manipulation + +This section describes procedures that manipulate files and directories. +Any of these procedures can signal a number of errors for many reasons. +The specifics of these errors are much too operating-system dependent to +document here. However, if such an error is signalled by one of +these procedures, it will be of type +@code{condition-type:file-operation-error}. +@findex condition-type:file-operation-error + +@deffn procedure file-exists? filename +@deffnx procedure file-exists-direct? filename +@deffnx procedure file-exists-indirect? filename +@cindex existence, testing of file +These procedures return @code{#t} if @var{filename} is an existing file +or directory; otherwise they return @code{#f}. In operating systems +that support symbolic links, if the file is a symbolic link, +@code{file-exists-direct?} tests for the existence of the link, while +@code{file-exists-indirect?} and @code{file-exists?} test for the +existence of the file pointed to by the link. +@end deffn + +@deffn procedure copy-file source-filename target-filename +@cindex copying, of file +Makes a copy of the file named by @var{source-filename}. The copy is +performed by creating a new file called @var{target-filename}, and +filling it with the same data as @var{source-filename}. +@end deffn + +@deffn procedure rename-file source-filename target-filename +@cindex renaming, of file +@cindex name, of file +Changes the name of @var{source-filename} to be @var{target-filename}. +In the unix implementation, this will not rename across file systems. +@end deffn + +@deffn procedure delete-file filename +@cindex deletion, of file +Deletes the file named @var{filename}. +@end deffn + +@deffn procedure delete-file-no-errors filename +Like @code{delete-file}, but returns a boolean value indicating whether +an error occurred during the deletion. If no errors occurred, @code{#t} +is returned. If an error of type @code{condition-type:file-error} or +@code{condition-type:port-error} is signalled, @code{#f} is returned. +@end deffn + +@deffn procedure hard-link-file source-filename target-filename +@cindex linking (hard), of file +@cindex hard linking, of file +Makes a hard link from @var{source-filename} to @var{target-filename}. +This operation gives the file specified by @var{source-filename} a new +name, in addition to the old name. + +This currently works only on unix systems. It is further restricted to +work only when @var{source-filename} and @var{target-filename} refer to +names in the same file system. +@end deffn + +@deffn procedure soft-link-file source-filename target-filename +@cindex linking (soft), of file +@cindex soft linking, of file +@cindex symbolic linking, of file +Creates a new soft link called @var{target-filename} that points at the +file @var{source-filename}. (Soft links are also sometimes called +@dfn{symbolic} links.) Note that @var{source-filename} will be +interpreted as a string (although you may specify it as a pathname +object, if you wish). The contents of this string will be stored in the +file system as the soft link. When a file operation attempts to open +the link, the contents of the link are interpreted relative to the +link's location at that time. + +This currently works only on unix systems. +@end deffn + +@deffn procedure make-directory filename +Creates a new directory named @var{filename}. Signals an error if +@var{filename} already exists, or if the directory cannot be created. +@end deffn + +@deffn procedure delete-directory filename +Deletes the directory named @var{filename}. Signals an error if +the directory does not exist, is not a directory, or contains any files +or subdirectories. +@end deffn + +@deffn procedure ->truename filename +@cindex truename, of input file +This procedure attempts to discover and return the ``true name'' of the +file associated with @var{filename} within the file system. An error of +type @code{condition-type:file-operation-error} is signalled if the +appropriate file cannot be located within the file system. +@findex condition-type:file-operation-error +@end deffn + +@deffn procedure call-with-temporary-file-pathname procedure +Calls @code{temporary-file-pathname} to create a temporary file, then +calls @var{procedure} with one argument, the pathname referring to that +file. When @var{procedure} returns, if the temporary file still exists, +it is deleted; then, the value yielded by @var{procedure} is returned. +If @var{procedure} escapes from its continuation, and the file still +exists, it is deleted. +@end deffn + +@deffn procedure temporary-file-pathname [directory] +Creates a new empty temporary file and returns a pathname referring to +it. The temporary file is created with Scheme's default permissions, so +barring unusual circumstances it can be opened for input and/or output +without error. The temporary file will remain in existence until +explicitly deleted. If the file still exists when the Scheme process +terminates, it will be deleted. + +If @var{directory} is specified, the temporary file will be stored +there. If it is not specified, or if it is @code{#f}, the temporary +file will be stored in the directory returned by +@code{temporary-directory-pathname}. +@end deffn + +@deffn procedure temporary-directory-pathname +Returns the pathname of an existing directory that can be used to store +temporary files. These directory names are tried, in order, until a +writeable directory is found: + +@itemize @bullet +@item +The directories specified by the environment variables @code{TMPDIR}, +@code{TEMP}, or @code{TMP}. + +@item +Under unix, the directories @file{/var/tmp}, @file{/usr/tmp}, or +@file{/tmp}. + +@item +Under OS/2 or Windows, the following directories on the system drive: +@file{\temp}, @file{\tmp}, or @file{\}. + +@item +Under OS/2 or Windows, the current directory, as specified by +@code{*default-pathname-defaults*}. +@end itemize +@end deffn + +@deffn procedure file-directory? filename +@cindex directory, predicate for +Returns @code{#t} if the file named @var{filename} exists and is a +directory. Otherwise returns @code{#f}. In operating systems that +support symbolic links, if @var{filename} names a symbolic link, this +examines the file linked to, not the link itself. + +This is equivalent to + +@example +(eq? 'directory (file-type-indirect @var{filename})) +@end example +@end deffn + +@deffn procedure file-regular? filename +@cindex file (regular), predicate for +@cindex regular file, predicate for +Returns @code{#t} if the file named @var{filename} exists and is a +regular file (i.e.@: not a directory, symbolic link, device file, etc.). +Otherwise returns @code{#f}. In operating systems that support symbolic +links, if @var{filename} names a symbolic link, this examines the file +linked to, not the link itself. + +This is equivalent to + +@example +(eq? 'regular (file-type-indirect @var{filename})) +@end example +@end deffn + +@deffn procedure file-symbolic-link? filename +@cindex symbolic link, predicate for +In operating systems that support symbolic links, if the file named +@var{filename} exists and is a symbolic link, this procedure returns the +contents of the symbolic link as a newly allocated string. The returned +value is the name of the file that the symbolic link points to and must +be interpreted relative to the directory of @var{filename}. If +@var{filename} either does not exist or is not a symbolic link, or if +the operating system does not support symbolic links, this procedure +returns @code{#f}. +@end deffn + +@deffn procedure file-type-direct filename +@deffnx procedure file-type-indirect filename +@cindex file type, procedure for +If the file named @var{filename} exists, @code{file-type-direct} returns +a symbol specifying what type of file it is. For example, if +@var{filename} refers to a directory, the symbol @code{directory} is +returned. If @var{filename} doesn't refer to an existing file, +@code{#f} is returned. + +If @var{filename} refers to a symbolic link, @code{file-type-direct} +returns the type of the link itself, while @code{file-type-indirect} +returns the type of the file linked to. + +At this time, the symbols that can be returned are the following. The +names are intended to be self-explanatory. Most of these names can only +be returned on particular operating systems, and so the operating-system +name is prefixed to the name. + +@example +regular +directory +unix-symbolic-link +unix-character-device +unix-block-device +unix-named-pipe +unix-socket +os2-named-pipe +win32-named-pipe +@end example +@end deffn + +@deffn procedure file-readable? filename +Returns @code{#t} if @var{filename} names a file that can be opened for +input; i.e.@: a @dfn{readable} file. Otherwise returns @code{#f}. +@end deffn + +@deffn procedure file-writeable? filename +Returns @code{#t} if @var{filename} names a file that can be opened for +output; i.e.@: a @dfn{writeable} file. Otherwise returns @code{#f}. +@end deffn + +@deffn procedure file-executable? filename +Returns @code{#t} if @var{filename} names a file that can be executed. +Otherwise returns @code{#f}. Under unix, an executable file is +identified by its mode bits. Under OS/2, an executable file has +one of the file extensions @file{.exe}, @file{.com}, @file{.cmd}, or +@file{.bat}. Under Windows, an executable file has one of the file +extensions @file{.exe}, @file{.com}, or @file{.bat}. +@end deffn + +@deffn procedure file-access filename mode +@var{Mode} must be an exact integer between @code{0} and @code{7} +inclusive; it is a bitwise-encoded predicate selector with @code{1} +meaning ``executable'', @code{2} meaning ``writeable'', and @code{4} +meaning ``readable''. @code{file-access} returns @code{#t} if +@var{filename} exists and satisfies the predicates selected by +@var{mode}. For example, if @var{mode} is @code{5}, then @var{filename} +must be both readable and executable. If @var{filename} doesn't exist, +or if it does not satisfy the selected predicates, @code{#f} is +returned. +@end deffn + +@deffn procedure file-eq? filename1 filename2 +Determines whether @var{filename1} and @var{filename2} refer to the same +file. Under unix, this is done by comparing the inodes and devices of +the two files. Under OS/2 and Windows, this is done by comparing +the filename strings. +@end deffn + +@deffn procedure file-modes filename +If @var{filename} names an existing file, @code{file-modes} returns an +exact non-negative integer encoding the file's permissions. The +encoding of this integer is operating-system dependent. Under unix, it +is the least-significant 12 bits of the @code{st_mode} element of the +@code{struct stat} structure. Under OS/2 and Windows, it is the file +attribute bits, which are described below. If @var{filename} does not +name an existing file, @code{#f} is returned. +@end deffn + +@deffn procedure set-file-modes! filename modes +@var{Filename} must name an existing file. @var{Modes} must be an exact +non-negative integer that could have been returned by a call to +@code{file-modes}. @code{set-file-modes!} modifies the file's +permissions to be those encoded by @var{modes}. +@end deffn + +@defvr variable os2-file-mode/read-only +@defvrx variable os2-file-mode/hidden +@defvrx variable os2-file-mode/system +@defvrx variable os2-file-mode/directory +@defvrx variable os2-file-mode/archived +The values of these variables are the ``mode bits'' that comprise the +value returned by @code{file-modes} under OS/2. These bits are small +integers that are combined by adding to form a complete set of modes. +The integer zero represents a set of modes in which none of these bits +are set. +@end defvr + +@defvr variable nt-file-mode/read-only +@defvrx variable nt-file-mode/hidden +@defvrx variable nt-file-mode/system +@defvrx variable nt-file-mode/directory +@defvrx variable nt-file-mode/archive +@defvrx variable nt-file-mode/normal +@defvrx variable nt-file-mode/temporary +@defvrx variable nt-file-mode/compressed +The values of these variables are the ``mode bits'' that comprise the +value returned by @code{file-modes} under Windows. These bits are small +integers that are combined by adding to form a complete set of modes. +The integer zero represents a set of modes in which none of these bits +are set. +@end defvr + +@deffn procedure file-modification-time filename +@cindex modification time, of file +Returns the modification time of @var{filename} as an exact non-negative +integer. The result may be compared to other file times using ordinary +integer arithmetic. If @var{filename} names a file that does not exist, +@code{file-modification-time} returns @code{#f}. + +@findex file-modification-time-direct +@findex file-modification-time-indirect +In operating systems that support symbolic links, if @var{filename} +names a symbolic link, @code{file-modification-time} returns the +modification time of the file linked to. An alternate procedure, +@code{file-modification-time-direct}, returns the modification time of +the link itself; in all other respects it is identical to +@code{file-modification-time}. For symmetry, +@code{file-modification-time-indirect} is a synonym of +@code{file-modification-time}. +@end deffn + +@deffn procedure file-access-time filename +@cindex access time, of file +Returns the access time of @var{filename} as an exact non-negative +integer. The result may be compared to other file times using ordinary +integer arithmetic. If @var{filename} names a file that does not exist, +@code{file-access-time} returns @code{#f}. + +@findex file-access-time-direct +@findex file-access-time-indirect +In operating systems that support symbolic links, if @var{filename} +names a symbolic link, @code{file-access-time} returns the access time +of the file linked to. An alternate procedure, +@code{file-access-time-direct}, returns the access time of the link +itself; in all other respects it is identical to +@code{file-access-time}. For symmetry, @code{file-access-time-indirect} +is a synonym of @code{file-access-time}. +@end deffn + +@deffn procedure set-file-times! filename access-time modification-time +@var{Filename} must name an existing file, while @var{access-time} and +@var{modification-time} must be valid file times that might have been +returned by @code{file-access-time} and @code{file-modification-time}, +respectively. @code{set-file-times!} alters the access and modification +times of the file specified by @var{filename} to the values given by +@var{access-time} and @var{modification-time}, respectively. For +convenience, either of the time arguments may be specified as @code{#f}; +in this case the corresponding time is not changed. +@code{set-file-times!} returns an unspecified value. +@end deffn + +@deffn procedure current-file-time +Returns the current time as an exact non-negative integer, in the same +format used by the above file-time procedures. This number can be +compared to other file times using ordinary arithmetic operations. +@end deffn + +@deffn procedure file-touch filename +@dfn{Touches} the file named @var{filename}. If the file already +exists, its modification time is set to the current file time and +@code{#f} is returned. Otherwise, the file is created and @code{#t} is +returned. This is an atomic test-and-set operation, so it is useful as +a synchronization mechanism. +@end deffn + +@deffn procedure file-length filename +Returns the length, in bytes, of the file named @var{filename} as an +exact non-negative integer. +@end deffn + +@deffn procedure file-attributes filename +@cindex attribute, of file +This procedure determines if the file named @var{filename} exists, and +returns information about it if so; if the file does not exist, it +returns @code{#f}. + +@findex file-attributes-direct +@findex file-attributes-indirect +In operating systems that support symbolic links, if @var{filename} +names a symbolic link, @code{file-attributes} returns the attributes of +the link itself. An alternate procedure, +@code{file-attributes-indirect}, returns the attributes of the file +linked to; in all other respects it is identical to +@code{file-attributes}. For symmetry, @code{file-attributes-direct} is +a synonym of @code{file-attributes}. +@end deffn + +The information returned by @code{file-attributes} is decoded by +accessor procedures. The following accessors are defined in all +operating systems: + +@deffn procedure file-attributes/type attributes +The file type: @code{#t} if the file is a directory, a character string +(the name linked to) if a symbolic link, or @code{#f} for all other +types of file. +@end deffn + +@deffn procedure file-attributes/access-time attributes +The last access time of the file, an exact non-negative integer. +@end deffn + +@deffn procedure file-attributes/modification-time attributes +The last modification time of the file, an exact non-negative integer. +@end deffn + +@deffn procedure file-attributes/change-time attributes +The last change time of the file, an exact non-negative integer. +@end deffn + +@deffn procedure file-attributes/length attributes +The length of the file in bytes. +@end deffn + +@deffn procedure file-attributes/mode-string attributes +The mode string of the file, a newly allocated string showing the file's +mode bits. Under unix, this string is in unix format. Under OS/2 and +Windows, this string shows the standard ``DOS'' attributes in their +usual format. +@end deffn + +@deffn procedure file-attributes/n-links attributes +The number of links to the file, an exact positive integer. Under +Windows and OS/2, this is always @code{1}. +@end deffn + +The following additional accessors are defined under unix: + +@deffn procedure file-attributes/uid attributes +The user id of the file's owner, an exact non-negative integer. +@end deffn + +@deffn procedure file-attributes/gid attributes +The group id of the file's group, an exact non-negative integer. +@end deffn + +@deffn procedure file-attributes/inode-number attributes +The inode number of the file, an exact non-negative integer. +@end deffn + +The following additional accessor is defined under OS/2 and Windows: + +@deffn procedure file-attributes/modes attributes +The attribute bits of the file. This is an exact non-negative integer +containing the file's attribute bits, exactly as specified by the +operating system's API. +@end deffn + +The following additional accessor is defined under OS/2: + +@deffn procedure file-attributes/allocated-length attributes +The allocated length of the file, which can be larger than the length of +the file due to fixed-length allocation units. +@end deffn + +@node Directory Reader, Date and Time, File Manipulation, Operating-System Interface +@section Directory Reader +@cindex directory, reading + +@deffn procedure directory-read directory [sort?] +@var{Directory} must be an object that can be converted into a pathname +by@* @code{->pathname}. The directory specified by @var{directory} is +read, and the contents of the directory is returned as a newly allocated +list of absolute pathnames. The result is sorted according to the usual +sorting conventions for directories, unless @var{sort?} is specified as +@code{#f}. If @var{directory} has name, type, or version components, +the returned list contains only those pathnames whose name, type, and +version components match those of @var{directory}; @code{wild} or +@code{#f} as one of these components means ``match anything''. + +The OS/2 and Windows implementations support ``globbing'', in which the +characters @code{*} and @code{?} are interpreted to mean ``match +anything'' and ``match any character'', respectively. This ``globbing'' +is supported only in the file part of @var{directory}. +@end deffn + +@node Date and Time, Machine Time, Directory Reader, Operating-System Interface +@section Date and Time + +MIT/GNU Scheme provides a simple set of procedures for manipulating date +and time information. There are four time representations, each of +which serves a different purpose. Each representation may be +converted to any of the others. + +@cindex universal time +@cindex time, universal +The primary time representation, @dfn{universal time}, is an exact +non-negative integer counting the number of seconds that have elapsed +since midnight January 1, 1900 UTC. (UTC stands for @dfn{Coordinated +Universal Time}, and is the modern name for Greenwich Mean Time.) This +format is produced by @code{get-universal-time} and +@code{decoded-time->universal-time}. + +@cindex decoded time +@cindex time, decoded +The second representation, @dfn{decoded time}, is a record structure in +which the time is broken down into components, such as month, minute, +etc. Decoded time is always relative to a particular time zone, which +is a component of the structure. This format is produced by +@code{global-decoded-time} and @code{local-decoded-time}. + +@cindex file time +@cindex time, file +The third representation, @dfn{file time}, is an exact non-negative +integer that is larger for increasing time. Unlike universal time, +this representation is operating-system dependent. This format is +produced by all of the file-attribute procedures, for example +@code{file-modification-time} and @code{file-attributes}. + +@cindex time, string +The fourth representation, the @dfn{time string}, is an external +representation for time. This format is defined by RFC-822, +@cite{Standard for the format of ARPA Internet text messages}, with the +modification that years are represented as four-digit numbers rather +than two-digit numbers. This format is the standard format for Internet +email and numerous other network protocols. + +Within this section, argument variables named @var{universal-time}, +@var{decoded-time}, @var{file-time}, and @var{time-string} are +respectively required to be of the corresponding format. + +@menu +* Universal Time:: +* Decoded Time:: +* File Time:: +* Time-Format Conversion:: +* External Representation of Time:: +@end menu + +@node Universal Time, Decoded Time, Date and Time, Date and Time +@subsection Universal Time + +@deffn procedure get-universal-time +Return the current time in universal format. + +@example +(get-universal-time) @result{} 3131453078 +@end example +@end deffn + +@defvr variable epoch +@code{epoch} is the representation of midnight January 1, 1970 UTC in +universal-time format. + +@example +epoch @result{} 2208988800 +@end example +@end defvr + +@node Decoded Time, File Time, Universal Time, Date and Time +@subsection Decoded Time + +Objects representing standard time components, such as seconds and +minutes, are required to be exact non-negative integers. Seconds and +minutes must be inclusively between @code{0} and @code{59}; hours +between @code{0} and @code{23}; days between @code{1} and @code{31}; +months between @code{1} and @code{12}; years are represented in +``four-digit'' form, in which 1999 is represented as @code{1999} --- +@emph{not} @code{99}. + +@deffn procedure local-decoded-time +Return the current time in decoded format. The decoded time is +represented in the local time zone. + +@example +@group +(pp (local-decoded-time)) +@print{} #[decoded-time 76] +@print{} (second 2) +@print{} (minute 12) +@print{} (hour 11) +@print{} (day 27) +@print{} (month 4) +@print{} (year 1999) +@print{} (day-of-week 1) +@print{} (daylight-savings-time 1) +@print{} (zone 5) +@end group +@end example +@end deffn + +@deffn procedure global-decoded-time +Return the current time in decoded format. The decoded time is +represented in UTC. + +@example +@group +(pp (global-decoded-time)) +@print{} #[decoded-time 77] +@print{} (second 8) +@print{} (minute 12) +@print{} (hour 15) +@print{} (day 27) +@print{} (month 4) +@print{} (year 1999) +@print{} (day-of-week 1) +@print{} (daylight-savings-time 0) +@print{} (zone 0) +@end group +@end example +@end deffn + +@deffn procedure make-decoded-time second minute hour day month year [zone] +Return a new decoded-time object representing the given time. The +arguments must be valid components according to the above rules, and +must form a valid date. + +If @var{zone} is not supplied or is @code{#f}, the resulting decoded +time will be represented in the local time zone. Otherwise, @var{zone} +must be a valid time zone, and the result will be represented in that +zone. + +@strong{Warning}: because this procedure depends on the operating +system's runtime library, it is not capable of representing all dates. +In particular, on most unix systems, it is not possible to encode dates +that occur prior to midnight, January 1, 1970 UTC. Attempting to do +this will signal an error. + +@example +@group +(pp (make-decoded-time 0 9 11 26 3 1999)) +@print{} #[decoded-time 19] +@print{} (second 0) +@print{} (minute 9) +@print{} (hour 11) +@print{} (day 26) +@print{} (month 3) +@print{} (year 1999) +@print{} (day-of-week 4) +@print{} (daylight-savings-time 0) +@print{} (zone 5) +@end group + +@group +(pp (make-decoded-time 0 9 11 26 3 1999 3)) +@print{} #[decoded-time 80] +@print{} (second 0) +@print{} (minute 9) +@print{} (hour 11) +@print{} (day 26) +@print{} (month 3) +@print{} (year 1999) +@print{} (day-of-week 4) +@print{} (daylight-savings-time 0) +@print{} (zone 3) +@end group +@end example +@end deffn + +@deffn procedure decoded-time/second decoded-time +@deffnx procedure decoded-time/minute decoded-time +@deffnx procedure decoded-time/hour decoded-time +@deffnx procedure decoded-time/day decoded-time +@deffnx procedure decoded-time/month decoded-time +@deffnx procedure decoded-time/year decoded-time +Return the corresponding component of @var{decoded-time}. + +@example +@group +(decoded-time/second (local-decoded-time)) @result{} 17 +(decoded-time/year (local-decoded-time)) @result{} 1999 +(decoded-time/day (local-decoded-time)) @result{} 26 +@end group +@end example +@end deffn + +@deffn procedure decoded-time/day-of-week decoded-time +Return the day of the week on which @var{decoded-time} falls, encoded +as an exact integer between @code{0} (Monday) and @code{6} (Sunday), +inclusive. + +@example +(decoded-time/day-of-week (local-decoded-time)) @result{} 4 +@end example +@end deffn + +@deffn procedure decoded-time/daylight-savings-time? decoded-time +Return @code{#t} if @var{decoded-time} is represented using daylight +savings time. Otherwise return @code{#f}. + +@example +(decoded-time/daylight-savings-time? (local-decoded-time)) + @result{} #f +@end example +@end deffn + +@deffn procedure decoded-time/zone decoded-time +Return the time zone in which @var{decoded-time} is represented. This +is an exact rational number between @code{-24} and @code{+24} inclusive, +that when multiplied by @code{3600} is an integer. The value is the +number of hours west of UTC. + +@example +(decoded-time/zone (local-decoded-time)) @result{} 5 +@end example +@end deffn + +@deffn procedure time-zone? object +Returns @code{#t} if @var{object} is an exact number between @code{-24} +and @code{+24} inclusive, that when multiplied by @code{3600} is an +integer. + +@example +@group +(time-zone? -5) @result{} #t +(time-zone? 11/2) @result{} #t +(time-zone? 11/7) @result{} #f +@end group +@end example +@end deffn + +@deffn procedure month/max-days month +Returns the maximum number of days possible in @var{month}. @var{Month} +must be an exact integer between @code{1} and @code{12} inclusive. + +@example +@group +(month/max-days 2) @result{} 29 +(month/max-days 3) @result{} 31 +(month/max-days 4) @result{} 30 +@end group +@end example +@end deffn + +@node File Time, Time-Format Conversion, Decoded Time, Date and Time +@subsection File Time + +As stated above, file time is operating-system dependent. As of this +writing, two formats are used. For unix and Windows systems, file time +is the number of seconds since midnight January 1, 1970 UTC (the +standard unix time convention). + +OS/2 represents file time as a 32-bit unsigned integer, in which the +time components are broken down into unsigned bit fields. The +components are always stated in local time. The fields, from MSB to +LSB, are: + +@itemize @bullet +@item +7 bits representing the year, relative to 1900. + +@item +4 bits representing the month, numbered 1 to 12. + +@item +5 bits representing the day of the month, numbered 1 to 31. + +@item +5 bits representing the hour of the day, numbered 0 to 23. + +@item +6 bits representing the minute, numbered 0 to 59. + +@item +5 bits representing the second. This field is unusual in that it counts +units of two seconds, so it is a number between 0 and 29, representing +second counts corresponding to 0 through 58. +@end itemize + +The following procedures generate their results in file-time format: + +@example +@group +file-access-time +file-access-time-direct +file-access-time-indirect +file-modification-time +file-modification-time-direct +file-modification-time-indirect +file-attributes/access-time +file-attributes/modification-time +file-attributes/change-time +@end group +@end example + +@noindent +Additionally, @code{set-file-times!} accepts its time arguments in +file-time format. + +@node Time-Format Conversion, External Representation of Time, File Time, Date and Time +@subsection Time-Format Conversion + +The procedures described in this section convert times from one format +to another. + +@deffn procedure universal-time->local-decoded-time universal-time +@deffnx procedure universal-time->global-decoded-time universal-time +Converts an argument in universal-time format to decoded-time format. +The result is in the local time zone or UTC, respectively. + +@example +@group +(pp (universal-time->local-decoded-time (get-universal-time))) +@print{} #[decoded-time 21] +@print{} (second 23) +@print{} (minute 57) +@print{} (hour 17) +@print{} (day 29) +@print{} (month 4) +@print{} (year 1999) +@print{} (day-of-week 3) +@print{} (daylight-savings-time 1) +@print{} (zone 5) +@end group + +@group +(pp (universal-time->global-decoded-time + (get-universal-time))) +@print{} #[decoded-time 22] +@print{} (second 27) +@print{} (minute 57) +@print{} (hour 21) +@print{} (day 29) +@print{} (month 4) +@print{} (year 1999) +@print{} (day-of-week 3) +@print{} (daylight-savings-time 0) +@print{} (zone 0) +@end group +@end example +@end deffn + +@deffn procedure universal-time->file-time universal-time +Converts an argument in universal-time format to file-time format. + +@example +@group +(universal-time->file-time (get-universal-time)) + @result{} 925422988 +@end group +@end example +@end deffn + +@deffn procedure universal-time->local-time-string universal-time +@deffnx procedure universal-time->global-time-string universal-time +Converts an argument in universal-time format to a time string. The +result is in the local time zone or UTC, respectively. + +@example +@group +(universal-time->local-time-string (get-universal-time)) + @result{} "Thu, 29 Apr 1999 17:55:31 -0400" +(universal-time->global-time-string (get-universal-time)) + @result{} "Thu, 29 Apr 1999 21:55:51 +0000" +@end group +@end example +@end deffn + +@deffn procedure decoded-time->universal-time decoded-time +Converts an argument in decoded-time format to universal-time format. + +@example +@group +(decoded-time->universal-time (local-decoded-time)) + @result{} 3134411942 +(decoded-time->universal-time (global-decoded-time)) + @result{} 3134411947 +@end group +@end example +@end deffn + +@deffn procedure decoded-time->file-time decoded-time +Converts an argument in decoded-time format to file-time format. + +@example +@group +(decoded-time->file-time (local-decoded-time)) + @result{} 925423191 +(decoded-time->file-time (global-decoded-time)) + @result{} 925423195 +@end group +@end example +@end deffn + +@deffn procedure decoded-time->string decoded-time +Convert an argument in decoded-time format to a time string. + +@example +@group +(decoded-time->string (local-decoded-time)) + @result{} "Thu, 29 Apr 1999 18:00:43 -0400" +(decoded-time->string (global-decoded-time)) + @result{} "Thu, 29 Apr 1999 22:00:46 +0000" +@end group +@end example +@end deffn + +@deffn procedure file-time->universal-time file-time +Converts an argument in universal-time format to file-time format. + +@example +@group +(file-time->universal-time (file-modification-time "/")) + @result{} 3133891907 +@end group +@end example +@end deffn + +@deffn procedure file-time->local-decoded-time file-time +@deffnx procedure file-time->global-decoded-time file-time +Converts an argument in file-time format to decoded-time format. The +result is in the local time zone or UTC, respectively. + +@example +@group +(pp (file-time->local-decoded-time + (file-modification-time "/"))) +@print{} #[decoded-time 26] +@print{} (second 47) +@print{} (minute 31) +@print{} (hour 17) +@print{} (day 23) +@print{} (month 4) +@print{} (year 1999) +@print{} (day-of-week 4) +@print{} (daylight-savings-time 1) +@print{} (zone 5) +@end group + +@group +(pp (file-time->global-decoded-time + (file-modification-time "/"))) +@print{} #[decoded-time 27] +@print{} (second 47) +@print{} (minute 31) +@print{} (hour 21) +@print{} (day 23) +@print{} (month 4) +@print{} (year 1999) +@print{} (day-of-week 4) +@print{} (daylight-savings-time 0) +@print{} (zone 0) +@end group +@end example +@end deffn + +@deffn procedure file-time->local-time-string file-time +@deffnx procedure file-time->global-time-string file-time +Converts an argument in file-time format to a time string. The result +is in the local time zone or UTC, respectively. + +@example +@group +(file-time->local-time-string (file-modification-time "/")) + @result{} "Fri, 23 Apr 1999 17:31:47 -0400" +(file-time->global-time-string (file-modification-time "/")) + @result{} "Fri, 23 Apr 1999 21:31:47 +0000" +@end group +@end example +@end deffn + +@deffn procedure string->universal-time time-string +Converts a time-string argument to universal-time format. + +@example +@group +(string->universal-time "Fri, 23 Apr 1999 21:31:47 +0000") + @result{} 3133888307 +(string->universal-time "Fri, 23 Apr 1999 17:31:47 -0400") + @result{} 3133888307 +@end group +@end example +@end deffn + +@deffn procedure string->decoded-time time-string +Converts a time-string argument to decoded-time format. + +@example +@group +(pp (string->decoded-time "Fri, 23 Apr 1999 17:31:47 -0400")) +@print{} #[decoded-time 30] +@print{} (second 47) +@print{} (minute 31) +@print{} (hour 17) +@print{} (day 23) +@print{} (month 4) +@print{} (year 1999) +@print{} (day-of-week 4) +@print{} (daylight-savings-time 0) +@print{} (zone 4) +@end group +@end example +@end deffn + +@deffn procedure string->file-time time-string +Converts a time-string argument to file-time format. + +@example +@group +(string->file-time "Fri, 23 Apr 1999 17:31:47 -0400") + @result{} 924899507 +@end group +@end example +@end deffn + +@node External Representation of Time, , Time-Format Conversion, Date and Time +@subsection External Representation of Time + +The normal external representation for time is the time string, as +described above. The procedures in this section generate alternate +external representations of time which are more verbose and may be more +suitable for presentation to human readers. + +@deffn procedure decoded-time/date-string decoded-time +@deffnx procedure decoded-time/time-string decoded-time +These procedures return strings containing external representations of +the date and time, respectively, represented by @var{decoded-time}. The +results are implicitly in local time. + +@example +@group +(decoded-time/date-string (local-decoded-time)) + @result{} "Tuesday March 30, 1999" +(decoded-time/time-string (local-decoded-time)) + @result{} "11:22:38 AM" +@end group +@end example +@end deffn + +@deffn procedure day-of-week/long-string day-of-week +@deffnx procedure day-of-week/short-string day-of-week +Returns a string representing the given @var{day-of-week}. The argument +must be an exact non-negative integer between @code{0} and @code{6} +inclusive. @code{day-of-week/long-string} returns a long string that +fully spells out the name of the day. @code{day-of-week/short-string} +returns a shortened string that abbreviates the day to three letters. + +@example +@group +(day-of-week/long-string 0) @result{} "Monday" +(day-of-week/short-string 0) @result{} "Mon" +(day-of-week/short-string 3) @result{} "Thu" +@end group +@end example +@end deffn + +@deffn procedure month/long-string month +@deffnx procedure month/short-string month +Returns a string representing the given @var{month}. The argument must +be an exact non-negative integer between @code{1} and @code{12} +inclusive. @code{month/long-string} returns a long string that fully +spells out the name of the month. @code{month/short-string} returns a +shortened string that abbreviates the month to three letters. + +@example +@group +(month/long-string 1) @result{} "January" +(month/short-string 1) @result{} "Jan" +(month/short-string 10) @result{} "Oct" +@end group +@end example +@end deffn + +@deffn procedure time-zone->string +Returns a string corresponding to the given time zone. This string is +the same string that is used to generate RFC-822 time strings. + +@example +@group +(time-zone->string 5) @result{} "-0500" +(time-zone->string -4) @result{} "+0400" +(time-zone->string 11/2) @result{} "-0530" +@end group +@end example +@end deffn + +@node Machine Time, Subprocesses, Date and Time, Operating-System Interface +@section Machine Time + +The previous section dealt with procedures that manipulate clock time. +This section describes procedures that deal with computer time: elapsed +CPU time, elapsed real time, and so forth. These procedures are useful +for measuring the amount of time it takes to execute code. + +@cindex tick +Some of the procedures in this section manipulate a time representation +called @dfn{ticks}. A tick is a unit of time that is unspecified here +but can be converted to and from seconds by supplied procedures. A +count in ticks is represented as an exact integer. At present each tick +is one millisecond, but this may change in the future. + +@deffn procedure process-time-clock +Returns the amount of process time, in ticks, that has elapsed since +Scheme was started. Process time is measured by the operating system +and is time during which the Scheme process is computing. It does not +include time in system calls, but depending on the operating system it +may include time used by subprocesses. + +@example +(process-time-clock) @result{} 21290 +@end example +@end deffn + +@deffn procedure real-time-clock +Returns the amount of real time, in ticks, that has elapsed since Scheme +was started. Real time is the time measured by an ordinary clock. + +@example +(real-time-clock) @result{} 33474836 +@end example +@end deffn + +@deffn procedure internal-time/ticks->seconds ticks +Returns the number of seconds corresponding to @var{ticks}. The result +is always a real number. + +@example +@group +(internal-time/ticks->seconds 21290) @result{} 21.29 +(internal-time/ticks->seconds 33474836) @result{} 33474.836 +@end group +@end example +@end deffn + +@deffn procedure internal-time/seconds->ticks seconds +Returns the number of ticks corresponding to @var{seconds}. +@var{Seconds} must be a real number. + +@example +@group +(internal-time/seconds->ticks 20.88) @result{} 20880 +(internal-time/seconds->ticks 20.83) @result{} 20830 +@end group +@end example +@end deffn + +@deffn procedure system-clock +Returns the amount of process time, in seconds, that has elapsed since +Scheme was started. Roughly equivalent to: + +@example +(internal-time/ticks->seconds (process-time-clock)) +@end example + +@noindent +Example: + +@example +(system-clock) @result{} 20.88 +@end example +@end deffn + +@deffn procedure runtime +Returns the amount of process time, in seconds, that has elapsed since +Scheme was started. However, it does not include time spent in garbage +collection. + +@example +(runtime) @result{} 20.83 +@end example +@end deffn + +@deffn procedure with-timings thunk receiver +Calls @var{thunk} with no arguments. After @var{thunk} returns, +@var{receiver} is called with three arguments describing the time spent +while computing @var{thunk}: the elapsed run time, the amount of time +spent in the garbage collector, and the elapsed real time. All three +times are in ticks. + +This procedure is most useful for doing performance measurements, and is +designed to have relatively low overhead. + +@example +@group +(with-timings + (lambda () @r{@dots{} hairy computation @dots{}}) + (lambda (run-time gc-time real-time) + (write (internal-time/ticks->seconds run-time)) + (write-char #\space) + (write (internal-time/ticks->seconds gc-time)) + (write-char #\space) + (write (internal-time/ticks->seconds real-time)) + (newline))) +@end group +@end example +@end deffn + +@deffn procedure measure-interval runtime? procedure +Calls @var{procedure}, passing it the current process time, in seconds, +as an argument. The result of this call must be another procedure. +When @var{procedure} returns, the resulting procedure is +tail-recursively called with the ending time, in seconds, as an +argument. + +If @var{runtime?} is @code{#f}, the elapsed time is deducted from the +elapsed system time returned by @code{runtime}. + +While this procedure can be used for time measurement, its interface is +somewhat clumsy for that purpose. We recommend that you use +@code{with-timings} instead, because it is more convenient and has lower +overhead. + +@example +@group +(measure-interval #t + (lambda (start-time) + (let ((v @r{@dots{} hairy computation @dots{}})) + (lambda (end-time) + (write (- end-time start-time)) + (newline) + v)))) +@end group +@end example +@end deffn + +@node Subprocesses, TCP Sockets, Machine Time, Operating-System Interface +@section Subprocesses + +@cindex subprocess +@cindex synchronous subprocess +MIT/GNU Scheme provides the ability to run and control subprocesses. This +support is divided into two parts: a low-level set of primitives that +maps onto the underlying operating system's process-control primitives, +and a high-level set of procedures for starting a subprocess and running +it to completion in a single call. Subprocesses that are run in the +latter fashion are referred to as @dfn{synchronous}, because they are +started and stopped in synchrony with a Scheme procedure call. + +This chapter documents Scheme's high-level synchronous-subprocess +support. The low-level support is not documented but is available for +those who are willing to read the source code. + +Synchronous-subprocess support is a run-time-loadable option. To use +it, execute + +@example +(load-option 'synchronous-subprocess) +@end example + +@noindent +once before calling it. + +@menu +* Subprocess Procedures:: +* Subprocess Conditions:: +* Subprocess Options:: +@end menu + +@node Subprocess Procedures, Subprocess Conditions, Subprocesses, Subprocesses +@subsection Subprocess Procedures + +There are two commands for running synchronous subprocesses under +Scheme. @code{run-shell-command} is very simple to use, provides access +to all shell features, and is to be preferred in most situations. +@code{run-synchronous-subprocess} allows direct execution of a program +and precise control of the command-line arguments passed to the program, +but does not provide file globbing, I/O redirection, or other shell +features. + +@deffn procedure run-shell-command command option @dots{} +Runs @var{command}, which must be a string. @var{Command} is passed to +a command shell for interpretation; how the shell is chosen is detailed +below. + +The @var{option}s are a sequence of keyword/value pairs that specify +optional behavior. See below for more information about options. + +@code{run-shell-command} waits until the subprocess completes its +execution and returns the exit code from the subprocess. If the +subprocess is killed or stopped, an error is signalled and the procedure +does not return. +@end deffn + +@deffn procedure run-synchronous-subprocess program arguments option @dots{} +Runs @var{program}, passing it the given command-line @var{arguments}. +@var{Program} must be either the name of a program on the path, or else +a pathname to a specific program. @var{Arguments} must be a list of +strings; each string is a single command-line argument to the program. + +The @var{option}s are a sequence of keyword/value pairs that specify +optional behavior. See below for more information about options. + +@code{run-synchronous-subprocess} waits until the subprocess completes +its execution and returns the exit code from the subprocess. If the +subprocess is killed or stopped, an error is signalled and the procedure +does not return. +@end deffn + +@node Subprocess Conditions, Subprocess Options, Subprocess Procedures, Subprocesses +@subsection Subprocess Conditions + +If a subprocess spawned by one of the above procedures is killed or +suspended, then one of the following errors will be signalled. + +@deffn {condition type} condition-type:subprocess-signalled subprocess reason +This condition type is a subtype of +@code{condition-type:subprocess-abnormal-termination}. It is signalled +when the subprocess is killed. + +@var{Subprocess} is an object that represents the subprocess involved. +The internals of this object can be accessed but the interface is not +documented at this time; see the source code for details. + +@var{Reason} is interesting only on unix systems, where it is the signal +that killed the process. On other systems it has a fixed value that +conveys no useful information. +@end deffn + +@deffn {condition type} condition-type:subprocess-stopped subprocess reason +This condition type is a subtype of +@code{condition-type:subprocess-abnormal-termination}. It is signalled +when the subprocess is stopped or suspended. + +@var{Subprocess} is an object that represents the subprocess involved. +The internals of this object can be accessed but the interface is not +documented at this time; see the source code for details. + +@var{Reason} is interesting only on unix systems, where it is the signal +that stopped the process. On other systems it has a fixed value that +conveys no useful information. +@end deffn + +@deffn {condition type} condition-type:subprocess-abnormal-termination subprocess reason +This condition type is a subtype of @code{condition-type:error}. This +is an abstract type that is never signalled. It is provided so that +condition handlers can be bound to it. +@end deffn + +@node Subprocess Options, , Subprocess Conditions, Subprocesses +@subsection Subprocess Options + +The following subprocess options may be passed to +@code{run-shell-command} or @code{run-synchronous-subprocess}. These +options are passed as alternating keyword/value pairs, for example: + +@example +@group +(run-shell-command "ls /" + 'output my-output-port + 'output-buffer-size 8192) +@end group +@end example + +@noindent +The example shows a shell command being run with two options specified: +@code{output} and @code{output-buffer-size}. + +@deffn {subprocess option} input port +Specifies the standard input of the subprocess. @var{Port} may be an +input port, in which case characters are read from @var{port} and fed to +the subprocess until @var{port} reaches end-of-file. Alternatively, +@var{port} may be @code{#f}, indicating that the subprocess has no +standard input. + +The default value of this option is @code{#f}. + +@example +@group +(call-with-input-file "foo.in" + (lambda (port) + (run-shell-command "cat > /dev/null" 'input port))) +@end group +@end example +@end deffn + +@deffn {subprocess option} input-line-translation line-ending +Specifies how line-endings should be translated when writing characters +to the subprocess. Ignored if the @code{input} option is @code{#f}. +@var{Line-ending} must be either a string specifying the line ending, or +the symbol @code{default}, meaning to use the operating system's +standard line ending. In either case, newline characters to be written +to the @code{input} port are translated to the specified line ending +before being written. + +The default value of this option is @code{default}. + +@example +@group +(call-with-input-file "foo.in" + (lambda (port) + (run-shell-command "cat > /dev/null" + 'input port + 'input-line-translation "\r\n"))) +@end group +@end example +@end deffn + +@deffn {subprocess option} input-buffer-size n +Specifies the size of the input buffer for the standard input of the +subprocess. (This is the buffer on the Scheme side, and has nothing to +do with any buffering done on the subprocess side.) Ignored if the +@code{input} option is @code{#f}. @var{N} must be an exact positive +integer specifying the number of characters the buffer can hold. + +The default value of this option is @code{512}. + +@example +@group +(call-with-input-file "foo.in" + (lambda (port) + (run-shell-command "cat > /dev/null" + 'input port + 'input-buffer-size 4096))) +@end group +@end example +@end deffn + +@deffn {subprocess option} output port +Specifies the standard output and standard error of the subprocess. +@var{Port} may be an output port, in which case characters are read from +the subprocess and fed to @var{port} until the subprocess finishes. +Alternatively, @var{port} may be @code{#f}, indicating that the +subprocess has no standard output or standard error. + +The default value of this option is the value of +@code{(current-output-port)}. + +@example +@group +(call-with-output-file "foo.out" + (lambda (port) + (run-shell-command "ls -la /etc" 'output port))) +@end group +@end example +@end deffn + +@deffn {subprocess option} output-line-translation line-ending +Specifies how line-endings should be translated when reading characters +from the standard output of the subprocess. Ignored if the +@code{output} option is @code{#f}. @var{Line-ending} must be either a +string specifying the line ending, or the symbol @code{default}, meaning +to use the operating system's standard line ending. In either case, +newline characters read from the subprocess port are translated to the +specified line ending. + +The default value of this option is @code{default}. + +@example +@group +(call-with-output-file "foo.out" + (lambda (port) + (run-shell-command "ls -la /etc" + 'output port + 'output-line-translation "\r\n"))) +@end group +@end example +@end deffn + +@deffn {subprocess option} output-buffer-size n +Specifies the size of the output buffer for the standard output of the +subprocess. (This is the buffer on the Scheme side, and has nothing to +do with any buffering done on the subprocess side.) Ignored if the +@code{output} option is @code{#f}. @var{N} must be an exact positive +integer specifying the number of characters the buffer can hold. + +The default value of this option is @code{512}. + +@example +@group +(call-with-output-file "foo.out" + (lambda (port) + (run-shell-command "ls -la /etc" + 'output port + 'output-buffer-size 4096))) +@end group +@end example +@end deffn + +@deffn {subprocess option} redisplay-hook thunk +Specifies that @var{thunk} is to be run periodically when output from +the subprocess is available. @var{Thunk} must be a procedure of no +arguments, or @code{#f} indicating that no hook is supplied. This +option is mostly useful for interactive systems. For example, the Edwin +text editor uses this to update output buffers when running some +subprocesses. + +The default value of this option is @code{#f}. + +@example +@group +(run-shell-command "ls -la /etc" + 'redisplay-hook + (lambda () + (update-buffer-contents buffer))) +@end group +@end example +@end deffn + +@deffn {subprocess option} environment environment +Specifies the environment variables that are to be used for the +subprocess. @var{Environment} must be either a vector of strings or +@code{#f} indicating the default environment. If it is a vector of +strings, each string must be a name/value pair where the name and value +are separated by an equal sign, for example, @code{"foo=bar"}. To +define a variable with no value, just omit the value, as in @code{"foo="}. + +@vindex scheme-subprocess-environment +Note that the variable @code{scheme-subprocess-environment} is bound to +the default subprocess environment. + +The default value of this option is @code{#f}. + +@example +@group +(run-shell-command "ls -la /etc" + 'environment + (let* ((v scheme-subprocess-environment) + (n (vector-length v)) + (v (vector-grow v (+ n 1)))) + (vector-set! v n "TERM=none") + v)) +@end group +@end example +@end deffn + +@deffn {subprocess option} working-directory pathname +Specifies the working directory in which the subprocess will run. + +The default value of this option is @code{(working-directory-pathname)}. + +@example +@group +(run-shell-command "ls -la" 'working-directory "/etc/") +@end group +@end example +@end deffn + +@deffn {subprocess option} use-pty? boolean +This option is meaningful only on unix systems; on other systems it is +ignored. Specifies whether to communicate with the subprocess using +@sc{pty} devices; if true, @sc{pty}s will be used, otherwise pipes will +be used. + +The default value of this option is @code{#f}. + +@example +@group +(run-shell-command "ls -la /etc" 'use-pty? #t) +@end group +@end example +@end deffn + +@deffn {subprocess option} shell-file-name pathname +Specifies the shell program to use for @code{run-shell-command}. + +The default value of this option is @code{(os/shell-file-name)}. This +is the value of the environment variable @code{SHELL}, or if +@code{SHELL} is not set, the value is operating-system dependent as +follows: + +@itemize @bullet +@item +On unix systems, @file{/bin/sh} is used. + +@item +On OS/2 systems, the value of the environment variable @code{COMSPEC} is +used, or if that is not set, @file{cmd.exe} on the current path. + +@item +On Windows systems, the value of the environment variable @code{COMSPEC} +is used. If that is not set, @file{cmd.exe} is used for Windows NT, or +@file{command.com} is used for Windows 9x; in each case the shell is +found by searching the path. +@end itemize + +@example +@group +(run-shell-command "ls -la /etc" + 'shell-file-name "/usr/local/bin/bash") +@end group +@end example +@end deffn + +@node TCP Sockets, Miscellaneous OS Facilities, Subprocesses, Operating-System Interface +@section TCP Sockets + +@cindex socket +MIT/GNU Scheme provides access to @dfn{sockets}, which are a mechanism for +inter-process communication. @sc{tcp} stream sockets are supported, +which communicate between computers over a @sc{tcp/ip} network. +@sc{tcp} sockets are supported on all operating systems. + +@cindex client socket +@cindex server socket +@sc{tcp} sockets have two distinct interfaces: one interface to +implement a @dfn{client} and another to implement a @dfn{server}. The +basic protocol is that servers set up a listening port and wait for +connections from clients. Implementation of clients is simpler and will +be treated first. + +@cindex hostname, TCP +The socket procedures accept two special arguments, called +@var{host-name} and @var{service}. @var{Host-name} is a string which +must be the name of an internet host. It is looked up using the +ordinary lookup rules for your computer. For example, if your host is +@code{foo.mit.edu} and @var{host-name} is @code{"bar"}, then it +specifies @code{bar.mit.edu}. + +@cindex service, TCP +@cindex port number, TCP +@var{Service} specifies the service to which you will connect. A +networked computer normally provides several different services, such as +telnet or @acronym{FTP}. Each service is associated with a unique +@dfn{port number}; for example, the @code{"www"} service is associated +with port @code{80}. The @var{service} argument specifies the port +number, either as a string, or directly as an exact non-negative +integer. Port strings are decoded by the operating system using a +table; for example, on unix the table is in @file{/etc/services}. +Usually you will use a port string rather than a number. + +@deffn procedure open-tcp-stream-socket host-name service [buffer-size [line-translation]] +@code{open-tcp-stream-socket} opens a connection to the host specified +by @var{host-name}. @var{Host-name} is looked up using the ordinary +lookup rules for your computer. The connection is established to the +service specified by @var{service}. The returned value is an +@acronym{I/O} port, to which you can read and write characters using +ordinary Scheme @acronym{I/O} procedures such as @code{read-char} and +@code{write-char}. + +@var{Buffer-size} specifies the size of the read and write buffers used +by the port; if this is unspecified or @code{#f}, the buffers will hold +@code{4096} bytes. + +@var{Line-translation} specifies how end-of-line characters will be +translated when reading or writing to the socket. If this is +unspecified or @code{#f}, then lines will be terminated by @sc{cr-lf}, +which is the standard for most internet protocols. Otherwise, it must +be a string, which specifies the line-ending character sequence to use. + +When you wish to close the connection, just use @code{close-port}. + +As an example, here is how you can open a connection to a web server: + +@example +(open-tcp-stream-socket "web.mit.edu" "www") +@end example +@end deffn + +@cindex server socket +Next we will treat setting up a @sc{tcp} server, which is slightly more +complicated. Creating a server is a two-part process. First, you must +open a @dfn{server socket}, which causes the operating system to listen +to the network on a port that you specify. Once the server socket is +opened, the operating system will allow clients to connect to your +computer on that port. + +In the second step of the process, you @dfn{accept} the connection, +which completes the connection initiated by the client, and allows you +to communicate with the client. Accepting a connection does not affect +the server socket; it continues to listen for additional client +connections. You can have multiple client connections to the same +server socket open simultaneously. + +@deffn procedure open-tcp-server-socket service [address] +This procedure opens a server socket that listens for connections to +@var{service}; the socket will continue to listen until you close it. +The returned value is a server socket object. + +An error is signalled if another process is already listening on the +service. Additionally, ports whose number is less than @code{1024} are +privileged on many operating systems, and cannot be used by +non-privileged processes; if @var{service} specifies such a port and you +do not have administrative privileges, an error may be signalled. + +The optional argument @var{address} specifies the @acronym{IP} address +on which the socket will listen. If this argument is not supplied or is +given as @code{#f}, then the socket listens on all @acronym{IP} +addresses for this machine. (This is equivalent to passing the result +of calling @code{host-address-any}.) +@end deffn + +@deffn procedure tcp-server-connection-accept server-socket block? peer-address [line-translation] +Checks to see if a client has connected to @var{server-socket}. If +so, an @acronym{I/O} port is returned. The returned port can be read +and written using ordinary Scheme @acronym{I/O} procedures such as +@code{read-char} and @code{write-char}. + +The argument @var{block?} says what to do if no client has connected at +the time of the call. If @code{#f}, it says to return immediately with +two values of @code{#f}. Otherwise, the call waits until a client +connects. + +The argument @var{peer-address} is either @code{#f} or an @acronym{IP} +address as allocated by @code{allocate-host-address}. If it is an +@acronym{IP} address, the address is modified to be the address of the +client making the connection. + +The optional argument @var{line-translation} specifies how end-of-line +characters will be translated when reading or writing to the returned +socket. If this is unspecified or @code{#f}, then lines will be +terminated by @sc{cr-lf}, which is the standard for most internet +protocols. Otherwise, it must be a string, which specifies the +line-ending character sequence to use. + +Note that closing the port returned by this procedure does not affect +@var{server-socket}; it just closes the particular client connection +that was opened by the call. To close @var{server-socket}, use +@code{close-tcp-server-socket}. +@end deffn + +@deffn procedure close-tcp-server-socket server-socket +Closes the server socket @var{server-socket}. The operating system will +cease listening for network connections to that service. Client +connections to @var{server-socket} that have already been accepted will +not be affected. +@end deffn + +@node Miscellaneous OS Facilities, , TCP Sockets, Operating-System Interface +@section Miscellaneous OS Facilities + +This section contains assorted operating-system facilities that don't +fit into other categories. + +@defvr variable microcode-id/operating-system +@defvrx variable microcode-id/operating-system-name +@code{microcode-id/operating-system} is bound to a symbol that specifies +the type of operating system that Scheme is running under. There are +three possible values: @code{unix}, @code{os/2}, or @code{nt}. + +@code{microcode-id/operating-system-name} is a string containing the +same name as @code{microcode-id/operating-system}; the latter is created +by interning the former as a symbol. +@end defvr + +@defvr variable microcode-id/operating-system-variant +This variable is a string that identifies the particular variant of the +operating system that Scheme is running under. Here are some of the +possible values: + +@example +@group +"GNU/Linux" +"FreeBSD" +"HP-UX" +"SunOS" +"OS/2 2.1" +"OS/2 4.0" +"Microsoft Windows NT 4.0 (Build 1381; Service Pack 3)" +"Microsoft Windows 98 (Build 410)" +@end group +@end example + +@noindent +For Windows systems, it is recommended that you match on the prefix of +this string and ignore the @code{"Build"} suffix. This is because the +suffix may contain information about service packs or fixes, while the +prefix will be constant for a particular version of Windows. +@end defvr + +The next few procedures provide access to the @dfn{domain name service} +(@acronym{DNS}), which maintains associations between internet host +names such as @code{"www.swiss.ai.mit.edu"} and @acronym{IP} addresses, +such as @code{18.23.0.16}. In MIT/GNU Scheme, we represent an internet host +name as a string, and an @acronym{IP} address as a byte vector of length +4 (byte vectors are just character strings that are accessed using +@code{vector-8b-ref} rather than @code{string-ref}). The bytes in an +@acronym{IP} address read in the same order as they do when written out: + +@example +(get-host-by-name "www.swiss") @result{} #("\022\027\000\020") +@end example + +@deffn procedure get-host-by-name host-name +Looks up the internet host name @var{host-name} using the @acronym{DNS}, +returning a vector of @acronym{IP} addresses for the corresponding host, +or @code{#f} if there is no such host. Usually the returned vector has +only one element, but if a host has more than one network interface, the +vector might have more than one element. + +@example +(get-host-by-name "www.swiss") @result{} #("\022\027\000\020") +@end example +@end deffn + +@deffn procedure get-host-by-address ip-address +Does a reverse @acronym{DNS} lookup on @var{ip-address}, returning the +internet host name corresponding to that address, or @code{#f} if there +is no such host. + +@example +(get-host-by-address "\022\027\000\020") @result{} "swissnet.ai.mit.edu" +@end example +@end deffn + +@deffn procedure canonical-host-name host-name +Finds the ``canonical'' internet host name for @var{host-name}. For +example: + +@example +@group +(canonical-host-name "zurich") @result{} "zurich.ai.mit.edu" +(canonical-host-name "www.swiss") @result{} "swissnet.ai.mit.edu" +@end group +@end example + +@noindent +In both examples, the default internet domain @samp{ai.mit.edu} is added +to @var{host-name}. In the second example, @code{"www.swiss"} is an +alias for another computer named @code{"swissnet"}. +@end deffn + +@deffn procedure get-host-name +Returns the string that identifies the computer that MIT/GNU Scheme is +running on. Usually this is an unqualified internet host name, i.e.@: +the host name without the domain suffix: + +@example +(get-host-name) @result{} "aarau" +@end example +@end deffn + +@deffn procedure os/hostname +Returns the canonical internet host name of the computer that MIT/GNU Scheme +is running on. So, in contrast to the example for @code{get-host-name}: + +@example +(os/hostname) @result{} "aarau.ai.mit.edu" +@end example +@end deffn + +@deffn procedure allocate-host-address +Allocates and returns an @acronym{IP} address object. This is just a +string of a fixed length (current 4 bytes) into which an @acronym{IP} +address may be stored. This procedure is used to generate an +appropriate argument to be passed to +@code{tcp-server-connection-accept}. + +@example +(allocate-host-address) @result{} "Xe\034\241" +@end example +@end deffn + +@deffn procedure host-address-any +Return an @acronym{IP} address object that specifies ``any host''. This +object is useful only when passed as the @var{address} argument to +@code{open-tcp-server-socket}. + +@example +(host-address-any) @result{} "\000\000\000\000" +@end example +@end deffn + +@deffn procedure host-address-loopback +@cindex loopback interface +Return an @acronym{IP} address object that specifies the local +@dfn{loopback} network interface. The loopback interface is a software +network interface that can be used only for communicating between +processes on the same computer. This address object is useful only when +passed as the @var{address} argument to @code{open-tcp-server-socket}. + +@example +(host-address-loopback) @result{} "\177\000\000\001" +@end example +@end deffn diff --git a/v7/doc/ref-manual/overview.texi b/v7/doc/ref-manual/overview.texi new file mode 100644 index 000000000..c85ac42ee --- /dev/null +++ b/v7/doc/ref-manual/overview.texi @@ -0,0 +1,1092 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: overview.texi,v 1.1 2003/04/15 03:30:04 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Overview, Special Forms, Acknowledgements, Top +@chapter Overview + +@cindex runtime system +This manual is a detailed description of the MIT/GNU Scheme runtime system. +It is intended to be a reference document for programmers. It does not +describe how to run Scheme or how to interact with it --- that is the +subject of the @cite{MIT/GNU Scheme User's Manual}. + +This chapter summarizes the semantics of Scheme, briefly describes the +MIT/GNU Scheme programming environment, and explains the syntactic and +lexical conventions of the language. Subsequent chapters describe +special forms, numerous data abstractions, and facilities for input and +output. + +@cindex standard Scheme (defn) +@cindex Scheme standard +@cindex R4RS +Throughout this manual, we will make frequent references to +@dfn{standard Scheme}, which is the language defined by the document +@cite{Revised^4 Report on the Algorithmic Language Scheme}, by William +Clinger, Jonathan Rees, et al.@:, or by @sc{ieee} Std.@: 1178-1990, +@cite{IEEE Standard for the Scheme Programming Language} (in fact, +several parts of this document are copied from the @cite{Revised +Report}). MIT/GNU Scheme is an extension of standard Scheme. + +These are the significant semantic characteristics of the Scheme +language: + +@table @asis +@item Variables are statically scoped +@cindex static scoping (defn) +@cindex scope (see region) +Scheme is a @dfn{statically scoped} programming language, which means that +each use of a variable is associated with a lexically apparent binding +of that variable. Algol is another statically scoped language. + +@item Types are latent +@cindex latent types (defn) +@cindex manifest types (defn) +@cindex weak types (defn) +@cindex strong types (defn) +@cindex dynamic types (defn) +@cindex static types (defn) +@cindex types, latent (defn) +@cindex types, manifest (defn) +Scheme has @dfn{latent} types as opposed to @dfn{manifest} types, which +means that Scheme associates types with values (or objects) rather than +with variables. Other languages with latent types (also referred to as +@dfn{weakly} typed or @dfn{dynamically} typed languages) include APL, +Snobol, and other dialects of Lisp. Languages with manifest types +(sometimes referred to as @dfn{strongly} typed or @dfn{statically} typed +languages) include Algol 60, Pascal, and C. + +@item Objects have unlimited extent +@cindex extent, of objects +All objects created during a Scheme computation, including procedures +and continuations, have unlimited extent; no Scheme object is ever +destroyed. The system doesn't run out of memory because the garbage +collector reclaims the storage occupied by an object when the object +cannot possibly be needed by a future computation. Other languages in +which most objects have unlimited extent include APL and other Lisp +dialects. + +@item Proper tail recursion +@cindex proper tail recursion (defn) +@cindex tail recursion (defn) +@cindex recursion (see tail recursion) +Scheme is @dfn{properly tail-recursive}, which means that iterative +computation can occur in constant space, even if the iterative +computation is described by a syntactically recursive procedure. With a +tail-recursive implementation, you can express iteration using the +ordinary procedure-call mechanics; special iteration expressions are +provided only for syntactic convenience. + +@item Procedures are objects +Scheme procedures are objects, which means that you can create them +dynamically, store them in data structures, return them as the results +of other procedures, and so on. Other languages with such procedure +objects include Common Lisp and ML. + +@item Continuations are explicit +In most other languages, continuations operate behind the scenes. In +Scheme, continuations are objects; you can use continuations for +implementing a variety of advanced control constructs, including +non-local exits, backtracking, and coroutines. + +@item Arguments are passed by value +Arguments to Scheme procedures are passed by value, which means that +Scheme evaluates the argument expressions before the procedure gains +control, whether or not the procedure needs the result of the +evaluations. ML, C, and APL are three other languages that pass +arguments by value. In languages such as SASL and Algol 60, argument +expressions are not evaluated unless the values are needed by the +procedure. +@end table + +@findex read +Scheme uses a parenthesized-list Polish notation to describe programs +and (other) data. The syntax of Scheme, like that of most Lisp +dialects, provides for great expressive power, largely due to its +simplicity. An important consequence of this simplicity is the +susceptibility of Scheme programs and data to uniform treatment by other +Scheme programs. As with other Lisp dialects, the @code{read} primitive +parses its input; that is, it performs syntactic as well as lexical +decomposition of what it reads. + +@menu +* Notational Conventions:: +* Scheme Concepts:: +* Lexical Conventions:: +* Expressions:: +@end menu + +@node Notational Conventions, Scheme Concepts, Overview, Overview +@section Notational Conventions +@cindex notational conventions +@cindex conventions, notational + +This section details the notational conventions used throughout the rest +of this document. + +@menu +* Errors:: +* Examples:: +* Entry Format:: +@end menu + +@node Errors, Examples, Notational Conventions, Notational Conventions +@subsection Errors +@cindex errors, notational conventions + +@cindex signal an error (defn) +@cindex must be, notational convention +@findex error +When this manual uses the phrase ``an error will be signalled,'' it +means that Scheme will call @code{error}, which normally halts execution +of the program and prints an error message. + +When this manual uses the phrase ``it is an error,'' it means that the +specified action is not valid in Scheme, but the system may or may not +signal the error. When this manual says that something ``must be,'' it +means that violating the requirement is an error. + +@node Examples, Entry Format, Errors, Notational Conventions +@subsection Examples +@cindex examples + +@cindex => notational convention +@cindex result of evaluation, in examples +@cindex evaluation, in examples +@cindex specified result, in examples +This manual gives many examples showing the evaluation of expressions. +The examples have a common format that shows the expression being +evaluated on the left hand side, an ``arrow'' in the middle, and the +value of the expression written on the right. For example: + +@example +(+ 1 2) @result{} 3 +@end example + +Sometimes the arrow and value will be moved under the expression, due to +lack of space. Occasionally we will not care what the value is, in +which case both the arrow and the value are omitted. + +@cindex error--> notational convention +@cindex error, in examples +If an example shows an evaluation that results in an error, an error +message is shown, prefaced by @samp{@error{}}: + +@example +(+ 1 'foo) @error{} Illegal datum +@end example + +@cindex -| notational convention +@cindex printed output, in examples +An example that shows printed output marks it with @samp{@print{}}: + +@example +@group +(begin (write 'foo) 'bar) + @print{} foo + @result{} bar +@end group +@end example + +@cindex unspecified result (defn) +@cindex result, unspecified (defn) +When this manual indicates that the value returned by some expression is +@dfn{unspecified}, it means that the expression will evaluate to some +object without signalling an error, but that programs should not depend +on the value in any way. + +@node Entry Format, , Examples, Notational Conventions +@subsection Entry Format +@cindex entry format +@cindex format, entry + +Each description of an MIT/GNU Scheme variable, special form, or +procedure begins with one or more header lines in this format: + +@deffn @var{category} @var{template} +@end deffn + +@noindent +where @var{category} specifies the kind of item (``variable'', +``special form'', or ``procedure''). The form of @var{template} is +interpreted depending on @var{category}. + +@table @asis +@item Variable +@var{Template} consists of the variable's name. +@cindex variable, entry category + +@item Special Form +@var{Template} starts with the syntactic keyword of the special form, +followed by a description of the special form's syntax. The description +is written using the following conventions. +@cindex special form, entry category + +@findex else +@findex cond +Named components are italicized in the printed manual, and uppercase in +the Info file. ``Noise'' keywords, such as the @code{else} keyword in +the @code{cond} special form, are set in a fixed width font in the +printed manual; in the Info file they are not distinguished. +Parentheses indicate themselves. + +@cindex ellipsis, in entries +@cindex ... in entries +A horizontal ellipsis (@dots{}) is describes repeated components. +Specifically, + +@display +@var{thing} @dots{} +@end display + +@noindent +indicates @emph{zero} or more occurrences of @var{thing}, while + +@display +@var{thing} @var{thing} @dots{} +@end display + +@noindent +indicates @emph{one} or more occurrences of @var{thing}. + +@cindex bracket, in entries +@cindex [ in entries +@cindex ] in entries +@cindex optional component, in entries +Brackets, @code{[ ]}, enclose optional components. + +@cindex body, of special form (defn) +@findex lambda +Several special forms (e.g.@: @code{lambda}) have an internal component +consisting of a series of expressions; usually these expressions are +evaluated sequentially under conditions that are specified in the +description of the special form. This sequence of expressions is commonly +referred to as the @dfn{body} of the special form. + +@item Procedure +@var{Template} starts with the name of the variable to which the +procedure is bound, followed by a description of the procedure's +arguments. The arguments are described using ``lambda list'' notation +(@pxref{Lambda Expressions}), except that brackets are used to denote +optional arguments, and ellipses are used to denote ``rest'' arguments. +@cindex procedure, entry format + +The names of the procedure's arguments are italicized in the printed +manual, and uppercase in the Info file. + +When an argument names a Scheme data type, it indicates that the +argument must be that type of data object. For example, + +@deffn procedure cdr pair +@end deffn + +@noindent +indicates that the standard Scheme procedure @code{cdr} takes one argument, +which must be a pair. + +Many procedures signal an error when an argument is of the wrong type; +usually this error is a condition of type +@code{condition-type:wrong-type-argument}. +@findex condition-type:wrong-type-argument + +In addition to the standard data-type names (@var{pair}, @var{list}, +@var{boolean}, @var{string}, etc.), the following names as arguments +also imply type restrictions: + +@itemize @bullet +@item +@var{object}: any object +@item +@var{thunk}: a procedure of no arguments +@item +@var{x}, @var{y}: real numbers +@item +@var{q}, @var{n}: integers +@item +@var{k}: an exact non-negative integer +@end itemize +@end table + +Some examples: + +@deffn procedure list object @dots{} +@end deffn + +@noindent +indicates that the standard Scheme procedure @code{list} takes zero or +more arguments, each of which may be any Scheme object. + +@deffn procedure write-char char [output-port] +@end deffn + +@noindent +indicates that the standard Scheme procedure @code{write-char} must be +called with a character, @var{char}, and may also be called with a +character and an output port. + +@node Scheme Concepts, Lexical Conventions, Notational Conventions, Overview +@section Scheme Concepts +@cindex scheme concepts + +@menu +* Variable Bindings:: +* Environment Concepts:: +* Initial and Current Environments:: +* Static Scoping:: +* True and False:: +* External Representations:: +* Disjointness of Types:: +* Storage Model:: +@end menu + +@node Variable Bindings, Environment Concepts, Scheme Concepts, Scheme Concepts +@subsection Variable Bindings +@cindex variable binding +@cindex binding, of variable + +@cindex bound variable (defn) +@cindex value, of variable (defn) +@cindex name, of value (defn) +@cindex location, of variable +Any identifier that is not a syntactic keyword may be used as a variable +(@pxref{Identifiers}). A variable may name a location where a value can +be stored. A variable that does so is said to be @dfn{bound} to the +location. The value stored in the location to which a variable is bound +is called the variable's @dfn{value}. (The variable is sometimes said +to @dfn{name} the value or to be @dfn{bound to} the value.) + +@cindex unassigned variable (defn) +@cindex error, unassigned variable +A variable may be bound but still not have a value; such a variable is +said to be @dfn{unassigned}. Referencing an unassigned variable is an +error. When this error is signalled, it is a condition of type +@code{condition-type:unassigned-variable}; sometimes the compiler does +not generate code to signal the error. Unassigned variables are useful +only in combination with side effects (@pxref{Assignments}). +@findex condition-type:unassigned-variable + +@node Environment Concepts, Initial and Current Environments, Variable Bindings, Scheme Concepts +@subsection Environment Concepts + +@cindex environment (defn) +@cindex unbound variable (defn) +@cindex error, unbound variable (defn) +An @dfn{environment} is a set of variable bindings. If an environment +has no binding for a variable, that variable is said to be @dfn{unbound} +in that environment. Referencing an unbound variable signals a +condition of type @code{condition-type:unbound-variable}. +@findex condition-type:unbound-variable + +@cindex extension, of environment (defn) +@cindex environment, extension (defn) +@cindex shadowing, of variable binding (defn) +@cindex parent, of environment (defn) +@cindex child, of environment (defn) +@cindex inheritance, of environment bindings (defn) +A new environment can be created by @dfn{extending} an existing +environment with a set of new bindings. Note that ``extending an +environment'' does @strong{not} modify the environment; rather, it +creates a new environment that contains the new bindings and the old +ones. The new bindings @dfn{shadow} the old ones; that is, if an +environment that contains a binding for @code{x} is extended with a new +binding for @code{x}, then only the new binding is seen when @code{x} is +looked up in the extended environment. Sometimes we say that the +original environment is the @dfn{parent} of the new one, or that the new +environment is a @dfn{child} of the old one, or that the new environment +@dfn{inherits} the bindings in the old one. + +@findex let +@findex let* +@findex letrec +@findex do +@findex define +Procedure calls extend an environment, as do @code{let}, @code{let*}, +@code{letrec}, and @code{do} expressions. Internal definitions +(@pxref{Internal Definitions}) also extend an environment. (Actually, +all the constructs that extend environments can be expressed in terms of +procedure calls, so there is really just one fundamental mechanism for +environment extension.) A top-level definition (@pxref{Top-Level +Definitions}) may add a binding to an existing environment. + +@node Initial and Current Environments, Static Scoping, Environment Concepts, Scheme Concepts +@subsection Initial and Current Environments + +@cindex initial environment (defn) +@cindex environment, initial (defn) +MIT/GNU Scheme provides an @dfn{initial environment} that contains all +of the variable bindings described in this manual. Most environments +are ultimately extensions of this initial environment. In Scheme, the +environment in which your programs execute is actually a child +(extension) of the environment containing the system's bindings. Thus, +system names are visible to your programs, but your names do not +interfere with system programs. + +@cindex current environment (defn) +@cindex environment, current (defn) +@cindex REP loop (defn) +@cindex REP loop, environment of +@findex user-initial-environment +@findex ge +The environment in effect at some point in a program is called the +@dfn{current environment} at that point. In particular, every +@acronym{REP} loop has a current environment. (@acronym{REP} stands for +``read-eval-print''; the @acronym{REP} loop is the Scheme program that +reads your input, evaluates it, and prints the result.) The environment +of the top-level @acronym{REP} loop (the one you are in when Scheme +starts up) starts as @code{user-initial-environment}, although it can be +changed by the @code{ge} procedure. When a new @acronym{REP} loop is +created, its environment is determined by the program that creates it. + +@node Static Scoping, True and False, Initial and Current Environments, Scheme Concepts +@subsection Static Scoping +@cindex scoping, static +@cindex static scoping + +@cindex dynamic binding, versus static scoping +Scheme is a statically scoped language with block structure. In this +respect, it is like Algol and Pascal, and unlike most other dialects of +Lisp except for Common Lisp. + +@cindex binding expression (defn) +@cindex expression, binding (defn) +The fact that Scheme is statically scoped (rather than +dynamically bound) means that the environment that is extended (and +becomes current) when a procedure is called is the environment in which +the procedure was created (i.e.@: in which the procedure's defining +lambda expression was evaluated), not the environment in which the +procedure is called. Because all the other Scheme @dfn{binding +expressions} can be expressed in terms of procedures, this determines +how all bindings behave. + +Consider the following definitions, made at the top-level @acronym{REP} +loop (in the initial environment): + +@example +@group +(define x 1) +(define (f x) (g 2)) +(define (g y) (+ x y)) +(f 5) @result{} 3 @r{; not} 7 +@end group +@end example + +Here @code{f} and @code{g} are bound to procedures created in the +initial environment. Because Scheme is statically scoped, the call to +@code{g} from @code{f} extends the initial environment (the one in which +@code{g} was created) with a binding of @code{y} to @code{2}. In this +extended environment, @code{y} is @code{2} and @code{x} is @code{1}. +(In a dynamically bound Lisp, the call to @code{g} would extend the +environment in effect during the call to @code{f}, in which @code{x} is +bound to @code{5} by the call to @code{f}, and the answer would be +@code{7}.) + +@cindex lexical scoping (defn) +@cindex scoping, lexical (defn) +@cindex region, of variable binding (defn) +@cindex variable, binding region (defn) +@findex lambda +Note that with static scoping, you can tell what binding a variable +reference refers to just from looking at the text of the program; the +referenced binding cannot depend on how the program is used. That is, +the nesting of environments (their parent-child relationship) +corresponds to the nesting of binding expressions in program text. +(Because of this connection to the text of the program, static scoping +is also called @dfn{lexical} scoping.) For each place where a variable +is bound in a program there is a corresponding @dfn{region} of the +program text within which the binding is effective. For example, the +region of a binding established by a @code{lambda} expression is the +entire body of the @code{lambda} expression. The documentation of each +binding expression explains what the region of the bindings it makes is. +A use of a variable (that is, a reference to or assignment of a +variable) refers to the innermost binding of that variable whose region +contains the variable use. If there is no such region, the use refers +to the binding of the variable in the global environment (which is an +ancestor of all other environments, and can be thought of as a region in +which all your programs are contained). + +@node True and False, External Representations, Static Scoping, Scheme Concepts +@subsection True and False + +@cindex boolean object +@cindex true, boolean object +@cindex false, boolean object +@findex #t +@findex #f +In Scheme, the boolean values true and false are denoted by @code{#t} +and @code{#f}. However, any Scheme value can be treated as a boolean +for the purpose of a conditional test. This manual uses the word +@dfn{true} to refer to any Scheme value that counts as true, and the +word @dfn{false} to refer to any Scheme value that counts as false. In +conditional tests, all values count as true except for @code{#f}, which +counts as false (@pxref{Conditionals}). + +Implementation note: In MIT/GNU Scheme, @code{#f} and the empty list are the +same object, and the printed representation of @code{#f} is always +@samp{()}. As this contradicts the Scheme standard, MIT/GNU Scheme will be +changed to make @code{#f} and the empty list different objects. + +@node External Representations, Disjointness of Types, True and False, Scheme Concepts +@subsection External Representations + +@cindex external representation (defn) +@cindex representation, external (defn) +An important concept in Scheme is that of the +@dfn{external representation} of an object as a sequence of characters. +For example, an external representation of the integer 28 is the +sequence of characters @samp{28}, and an external representation of a +list consisting of the integers 8 and 13 is the sequence of characters +@samp{(8 13)}. + +The external representation of an object is not necessarily unique. The +integer 28 also has representations @samp{#e28.000} and @samp{#x1c}, and +the list in the previous paragraph also has the representations @samp{( +08 13 )} and @samp{(8 . (13 . ( )))}. + +Many objects have standard external representations, but some, such as +procedures and circular data structures, do not have standard +representations (although particular implementations may define +representations for them). + +An external representation may be written in a program to obtain the +corresponding object (@pxref{Quoting}). + +@findex read +@findex write +External representations can also be used for input and output. The +procedure @code{read} parses external representations, and the procedure +@code{write} generates them. Together, they provide an elegant and +powerful input/output facility. + +Note that the sequence of characters @samp{(+ 2 6)} is @emph{not} an +external representation of the integer 8, even though it @emph{is} an +expression that evaluates to the integer 8; rather, it is an external +representation of a three-element list, the elements of which are the +symbol @code{+} and the integers @code{2} and @code{6}. Scheme's syntax +has the property that any sequence of characters that is an expression +is also the external representation of some object. This can lead to +confusion, since it may not be obvious out of context whether a given +sequence of characters is intended to denote data or program, but it is +also a source of power, since it facilitates writing programs such as +interpreters and compilers that treat programs as data or data as +programs. + +@node Disjointness of Types, Storage Model, External Representations, Scheme Concepts +@subsection Disjointness of Types + +Every object satisfies at most one of the following predicates (but see +@ref{True and False}, for an exception): + +@example +@group +bit-string? environment? port? symbol? +boolean? null? procedure? vector? +cell? number? promise? weak-pair? +char? pair? string? +condition? +@end group +@end example + +@node Storage Model, , Disjointness of Types, Scheme Concepts +@subsection Storage Model + +This section describes a model that can be used to understand Scheme's +use of storage. + +@cindex location +@findex string-set! +Variables and objects such as pairs, vectors, and strings implicitly +denote locations or sequences of locations. A string, for example, +denotes as many locations as there are characters in the string. (These +locations need not correspond to a full machine word.) A new value may +be stored into one of these locations using the @code{string-set!} +procedure, but the string continues to denote the same locations as +before. + +@findex car +@findex vector-ref +@findex string-ref +@findex eqv? +An object fetched from a location, by a variable reference or by a +procedure such as @code{car}, @code{vector-ref}, or @code{string-ref}, +is equivalent in the sense of @code{eqv?} to the object last stored in +the location before the fetch. + +Every location is marked to show whether it is in use. No variable or +object ever refers to a location that is not in use. Whenever this +document speaks of storage being allocated for a variable or object, +what is meant is that an appropriate number of locations are chosen from +the set of locations that are not in use, and the chosen locations are +marked to indicate that they are now in use before the variable or +object is made to denote them. + +@cindex constant +@cindex mutable +@cindex immutable +@findex symbol->string +In many systems it is desirable for constants (i.e.@: the values of +literal expressions) to reside in read-only memory. To express this, it +is convenient to imagine that every object that denotes locations is +associated with a flag telling whether that object is mutable or +immutable. The constants and the strings returned by +@code{symbol->string} are then the immutable objects, while all objects +created by other procedures are mutable. It is an error to attempt to +store a new value into a location that is denoted by an immutable +object. Note that the MIT/GNU Scheme compiler takes advantage of this +property to share constants, but that these constants are not immutable. +Instead, two constants that are @code{equal?} may be @code{eq?} in +compiled code. + +@node Lexical Conventions, Expressions, Scheme Concepts, Overview +@section Lexical Conventions +@cindex lexical conventions +@cindex conventions, lexical + +This section describes Scheme's lexical conventions. + +@menu +* Whitespace:: +* Delimiters:: +* Identifiers:: +* Uppercase and Lowercase:: +* Naming Conventions:: +* Comments:: +* Additional Notations:: +@end menu + +@node Whitespace, Delimiters, Lexical Conventions, Lexical Conventions +@subsection Whitespace + +@cindex whitespace, in programs (defn) +@cindex token, in programs (defn) +@dfn{Whitespace} characters are spaces, newlines, tabs, and page breaks. +Whitespace is used to improve the readability of your programs and to +separate tokens from each other, when necessary. (A @dfn{token} is an +indivisible lexical unit such as an identifier or number.) Whitespace +is otherwise insignificant. Whitespace may occur between any two +tokens, but not within a token. Whitespace may also occur inside a +string, where it is significant. + +@node Delimiters, Identifiers, Whitespace, Lexical Conventions +@subsection Delimiters + +@cindex delimiter, in programs (defn) +All whitespace characters are @dfn{delimiters}. In addition, the +following characters act as delimiters: + +@example +( ) ; " ' ` | +@end example + +Finally, these next characters act as delimiters, despite the fact that +Scheme does not define any special meaning for them: + +@example +[ ] @{ @} +@end example + +For example, if the value of the variable @code{name} is +@code{"max"}: + +@example +(list"Hi"name(+ 1 2)) @result{} ("Hi" "max" 3) +@end example + +@node Identifiers, Uppercase and Lowercase, Delimiters, Lexical Conventions +@subsection Identifiers + +@cindex identifier (defn) +An @dfn{identifier} is a sequence of one or more non-delimiter +characters. Identifiers are used in several ways in Scheme +programs: + +@itemize @bullet +@item +An identifier can be used as a variable or as a syntactic keyword. +@cindex variable, identifier as +@cindex syntactic keyword, identifier as + +@item +When an identifier appears as a literal or within a literal, it denotes +a symbol. +@cindex literal, identifier as +@end itemize + +Scheme accepts most of the identifiers that other programming languages +allow. MIT/GNU Scheme allows all of the identifiers that standard +Scheme does, plus many more. + +MIT/GNU Scheme defines a potential identifier to be a sequence of +non-delimiter characters that does not begin with either of the +characters @samp{#} or @samp{,}. Any such sequence of characters that +is not a syntactically valid number (@pxref{Numbers}) is considered to +be a valid identifier. Note that, although it is legal for @samp{#} and +@samp{,} to appear in an identifier (other than in the first character +position), it is poor programming practice. + +Here are some examples of identifiers: + +@example +@group +lambda q +list->vector soup ++ V17a +<=? a34kTMNs +the-word-recursion-has-many-meanings +@end group +@end example + +@node Uppercase and Lowercase, Naming Conventions, Identifiers, Lexical Conventions +@subsection Uppercase and Lowercase +@cindex uppercase +@cindex lowercase + +@cindex alphabetic case-insensitivity of programs (defn) +@cindex case-insensitivity of programs (defn) +@cindex sensitivity, to case in programs (defn) +@cindex insensitivity, to case in programs (defn) +Scheme doesn't distinguish uppercase and lowercase forms of a letter +except within character and string constants; in other words, Scheme is +@dfn{case-insensitive}. For example, @samp{Foo} is the same identifier +as @samp{FOO}, and @samp{#x1AB} is the same number as @samp{#X1ab}. But +@samp{#\a} and @samp{#\A} are different characters. + +@node Naming Conventions, Comments, Uppercase and Lowercase, Lexical Conventions +@subsection Naming Conventions +@cindex naming conventions +@cindex conventions, naming + +@cindex predicate (defn) +@cindex ? in predicate names +A @dfn{predicate} is a procedure that always returns a boolean value +(@code{#t} or @code{#f}). By convention, predicates usually have names +that end in @samp{?}. + +@cindex mutation procedure (defn) +@cindex ! in mutation procedure names +A @dfn{mutation procedure} is a procedure that alters a data structure. +By convention, mutation procedures usually have names that end in +@samp{!}. + +@node Comments, Additional Notations, Naming Conventions, Lexical Conventions +@subsection Comments + +@cindex comment, in programs (defn) +@cindex semicolon, as external representation +@cindex ; as external representation +The beginning of a comment is indicated with a semicolon (@code{;}). +Scheme ignores everything on a line in which a semicolon appears, from +the semicolon until the end of the line. The entire comment, including +the newline character that terminates it, is treated as +whitespace. + +@cindex extended comment, in programs (defn) +@cindex comment, extended, in programs (defn) +@cindex #| as external representation +An alternative form of comment (sometimes called an @dfn{extended +comment}) begins with the characters @samp{#|} and ends with the +characters @samp{|#}. This alternative form is an MIT/GNU Scheme extension. +As with ordinary comments, all of the characters in an extended comment, +including the leading @samp{#|} and trailing @samp{|#}, are treated as +whitespace. Comments of this form may extend over multiple lines, and +additionally may be nested (unlike the comments of the programming +language C, which have a similar syntax). + +@example +@group +;;; This is a comment about the FACT procedure. Scheme +;;; ignores all of this comment. The FACT procedure computes +;;; the factorial of a non-negative integer. +@end group + +@group +#| +This is an extended comment. +Such comments are useful for commenting out code fragments. +|# +@end group + +@group +(define fact + (lambda (n) + (if (= n 0) ;This is another comment: + 1 ;Base case: return 1 + (* n (fact (- n 1)))))) +@end group +@end example + +@node Additional Notations, , Comments, Lexical Conventions +@subsection Additional Notations + +@cindex characters, special, in programs +@cindex special characters, in programs +The following list describes additional notations used in Scheme. +@xref{Numbers}, for a description of the notations used for numbers. + +@table @code +@item + - . +The plus sign, minus sign, and period are used in numbers, and may also +occur in an identifier. A delimited period (not occurring within a +number or identifier) is used in the notation for pairs and to indicate +a ``rest'' parameter in a formal parameter list +(@pxref{Lambda Expressions}). + +@item ( ) +Parentheses are used for grouping and to notate lists (@pxref{Lists}). + +@item " +The double quote delimits strings (@pxref{Strings}). + +@item \ +The backslash is used in the syntax for character constants +(@pxref{Characters}) and as an escape character within string constants +(@pxref{Strings}). + +@item ; +The semicolon starts a comment. + +@item ' +The single quote indicates literal data; it suppresses evaluation +(@pxref{Quoting}). + +@item ` +The backquote indicates almost-constant data (@pxref{Quoting}). + +@item , +The comma is used in conjunction with the backquote (@pxref{Quoting}). + +@item ,@@ +A comma followed by an at-sign is used in conjunction with the backquote +(@pxref{Quoting}). + +@item # +The sharp (or pound) sign has different uses, depending on the character +that immediately follows it: + +@item #t #f +These character sequences denote the boolean constants +(@pxref{Booleans}). + +@item #\ +This character sequence introduces a character constant +(@pxref{Characters}). + +@item #( +This character sequence introduces a vector constant (@pxref{Vectors}). +A close parenthesis, @samp{)}, terminates a vector constant. + +@item #e #i #b #o #d #l #s #x +These character sequences are used in the notation for numbers +(@pxref{Numbers}). + +@item #| +This character sequence introduces an extended comment. The comment is +terminated by the sequence @samp{|#}. This notation is an MIT/GNU Scheme +extension. + +@item #! +This character sequence is used to denote a small set of named +constants. Currently there are only two of these, @code{#!optional} and +@code{#!rest}, both of which are used in the @code{lambda} special form +to mark certain parameters as being ``optional'' or ``rest'' parameters. +This notation is an MIT/GNU Scheme extension. +@findex #!optional +@findex #!rest +@findex lambda + +@item #* +This character sequence introduces a bit string (@pxref{Bit Strings}). +This notation is an MIT/GNU Scheme extension. + +@item #[ +This character sequence is used to denote objects that do not have a +readable external representation (@pxref{Custom Output}). A close +bracket, @samp{]}, terminates the object's notation. This notation is +an MIT/GNU Scheme extension. + +@item #@@ +This character sequence is a convenient shorthand used to refer to +objects by their hash number (@pxref{Custom Output}). This notation is +an MIT/GNU Scheme extension. + +@item #= +@itemx ## +These character sequences introduce a notation used to show circular +structures in printed output, or to denote them in input. The notation +works much like that in Common Lisp, and is an MIT/GNU Scheme extension. +@end table + +@node Expressions, , Lexical Conventions, Overview +@section Expressions + +@cindex expression (defn) +A Scheme @dfn{expression} is a construct that returns a value. An +expression may be a @emph{literal}, a @emph{variable reference}, a +@emph{special form}, or a @emph{procedure call}. + +@menu +* Literal Expressions:: +* Variable References:: +* Special Form Syntax:: +* Procedure Call Syntax:: +@end menu + +@node Literal Expressions, Variable References, Expressions, Expressions +@subsection Literal Expressions + +@cindex literal expression (defn) +@cindex constant expression (defn) +@cindex expression, literal (defn) +@cindex expression, constant (defn) +@dfn{Literal} constants may be written by using an external +representation of the data. In general, the external representation +must be @emph{quoted} (@pxref{Quoting}); but some external +representations can be used without quotation. + +@example +@group +"abc" @result{} "abc" +145932 @result{} 145932 +#t @result{} #t +#\a @result{} #\a +@end group +@end example + +The external representation of numeric constants, string constants, +character constants, and boolean constants evaluate to the constants +themselves. Symbols, pairs, lists, and vectors require quoting. + +@node Variable References, Special Form Syntax, Literal Expressions, Expressions +@subsection Variable References + +@cindex variable reference (defn) +@cindex reference, variable (defn) +@cindex unbound variable +@cindex unassigned variable +An expression consisting of an identifier (@pxref{Identifiers}) is a +@dfn{variable reference}; the identifier is the name of the variable +being referenced. The value of the variable reference is the value +stored in the location to which the variable is bound. An error is +signalled if the referenced variable is unbound or unassigned. + +@example +@group +(define x 28) +x @result{} 28 +@end group +@end example + +@node Special Form Syntax, Procedure Call Syntax, Variable References, Expressions +@subsection Special Form Syntax + +@example +(@var{keyword} @var{component} @dots{}) +@end example + +@cindex expression, special form (defn) +@cindex special form (defn) +@cindex form, special (defn) +@cindex keyword, of special form (defn) +@cindex syntactic keyword (defn) +A parenthesized expression that starts with a @dfn{syntactic keyword} is +a @dfn{special form}. Each special form has its own syntax, which is +described later in the manual. + +Note that syntactic keywords and variable bindings share the same +namespace. A local variable binding may shadow a syntactic keyword, and +a local syntactic-keyword definition may shadow a variable binding. + +The following list contains all of the syntactic keywords that are +defined when MIT/GNU Scheme is initialized: + +@multitable @columnfractions .33 .33 .33 +@item access +@tab and +@tab begin +@item case +@tab cond +@tab cons-stream +@item declare +@tab default-object? +@tab define +@item define-integrable +@tab define-structure +@tab define-syntax +@item delay +@tab do +@tab er-macro-transformer +@item fluid-let +@tab if +@tab lambda +@item let +@tab let* +@tab let*-syntax +@item let-syntax +@tab letrec +@tab letrec-syntax +@item local-declare +@tab named-lambda +@tab non-hygienic-macro-transformer +@item or +@tab quasiquote +@tab quote +@item rsc-macro-transformer +@tab sc-macro-transformer +@tab set! +@item syntax-rules +@tab the-environment +@end multitable + +@node Procedure Call Syntax, , Special Form Syntax, Expressions +@subsection Procedure Call Syntax + +@example +(@var{operator} @var{operand} @dots{}) +@end example + +@cindex expression, procedure call (defn) +@cindex procedure call (defn) +@cindex operator, of procedure call (defn) +@cindex operand, of procedure call (defn) +A @dfn{procedure call} is written by simply enclosing in parentheses +expressions for the procedure to be called (the @dfn{operator}) and the +arguments to be passed to it (the @dfn{operands}). The @var{operator} +and @var{operand} expressions are evaluated and the resulting procedure +is passed the resulting arguments. @xref{Lambda Expressions}, for a +more complete description of this. + +@cindex combination (defn) +Another name for the procedure call expression is @dfn{combination}. +This word is more specific in that it always refers to the expression; +``procedure call'' sometimes refers to the @emph{process} of calling a +procedure. + +@cindex order, of argument evaluation +@cindex evaluation order, of arguments +@cindex argument evaluation order +Unlike some other dialects of Lisp, Scheme always evaluates the operator +expression and the operand expressions with the same evaluation rules, +and the order of evaluation is unspecified. + +@example +@group +(+ 3 4) @result{} 7 +((if #f = *) 3 4) @result{} 12 +@end group +@end example + +@findex + +@findex * +@findex lambda +A number of procedures are available as the values of variables in the +initial environment; for example, the addition and multiplication +procedures in the above examples are the values of the variables +@code{+} and @code{*}. New procedures are created by evaluating +@code{lambda} expressions. + +@cindex syntactic keyword +If the @var{operator} is a syntactic keyword, then the expression is not +treated as a procedure call: it is a special form. diff --git a/v7/doc/ref-manual/procedures.texi b/v7/doc/ref-manual/procedures.texi new file mode 100644 index 000000000..1489fce44 --- /dev/null +++ b/v7/doc/ref-manual/procedures.texi @@ -0,0 +1,487 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: procedures.texi,v 1.1 2003/04/15 03:30:08 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Procedures, Environments, Associations, Top +@chapter Procedures + +@cindex procedure +@cindex primitive procedure (defn) +@cindex built-in procedure +@findex lambda +@cindex application hook (defn) +@cindex hook, application (defn) +Procedures are created by evaluating @code{lambda} expressions +(@pxref{Lambda Expressions}); the @code{lambda} may either be explicit +or may be implicit as in a ``procedure @code{define}'' +(@pxref{Definitions}). Also there are special built-in procedures, +called @dfn{primitive procedures}, such as @code{car}; these procedures +are not written in Scheme but in the language used to implement the +Scheme system. MIT/GNU Scheme also provides @dfn{application hooks}, which +support the construction of data structures that act like procedures. + +@cindex procedure, type +@cindex procedure, primitive +@cindex procedure, interpreted +@cindex procedure, compiled +@cindex type, of procedure +@cindex primitive, procedure type +@cindex interpreted, procedure type +@cindex compiled, procedure type +@cindex external representation, for procedure +In MIT/GNU Scheme, the written representation of a procedure tells you +the type of the procedure (compiled, interpreted, or primitive): + +@example +@group +pp + @result{} #[compiled-procedure 56 ("pp" #x2) #x10 #x307578] +(lambda (x) x) + @result{} #[compound-procedure 57] +(define (foo x) x) +foo + @result{} #[compound-procedure 58 foo] +car + @result{} #[primitive-procedure car] +(call-with-current-continuation (lambda (x) x)) + @result{} #[continuation 59] +@end group +@end example + +@noindent +@cindex compound procedure +@cindex procedure, compound +Note that interpreted procedures are called ``compound'' procedures +(strictly speaking, compiled procedures are also compound procedures). +The written representation makes this distinction for historical +reasons, and may eventually change. + +@menu +* Procedure Operations:: +* Primitive Procedures:: +* Continuations:: +* Application Hooks:: +@end menu + +@node Procedure Operations, Primitive Procedures, Procedures, Procedures +@section Procedure Operations + +@deffn procedure apply procedure object object @dots{} +@cindex application, of procedure +Calls @var{procedure} with the elements of the following list as +arguments: + +@example +(cons* @var{object} @var{object} @dots{}) +@end example + +@noindent +The initial @var{object}s may be any objects, but the last @var{object} +(there must be at least one @var{object}) must be a list. + +@example +@group +(apply + (list 3 4 5 6)) @result{} 18 +(apply + 3 4 '(5 6)) @result{} 18 + +(define compose + (lambda (f g) + (lambda args + (f (apply g args))))) +((compose sqrt *) 12 75) @result{} 30 +@end group +@end example +@end deffn + +@deffn procedure procedure? object +@cindex type predicate, for procedure +Returns @code{#t} if @var{object} is a procedure; otherwise returns +@code{#f}. If @code{#t} is returned, exactly one of the following +predicates is satisfied by @var{object}: @code{compiled-procedure?}, +@code{compound-procedure?}, or @code{primitive-procedure?}. +@end deffn + +@deffn procedure compiled-procedure? object +@cindex type predicate, for compiled procedure +Returns @code{#t} if @var{object} is a compiled procedure; otherwise +returns @code{#f}. +@end deffn + +@deffn procedure compound-procedure? object +@cindex type predicate, for compound procedure +Returns @code{#t} if @var{object} is a compound (i.e.@: interpreted) +procedure; otherwise returns @code{#f}. +@end deffn + +@deffn procedure primitive-procedure? object +@cindex type predicate, for primitive procedure +Returns @code{#t} if @var{object} is a primitive procedure; otherwise +returns @code{#f}. +@end deffn + +The following two procedures test the @dfn{arity} of a procedure, that +is, the number of arguments that the procedure accepts. The results of +the test may be less restrictive than the effect of calling the +procedure. In other words, these procedures may indicate that the +procedure will accept a given number of arguments, but if you call the +procedure it may signal a +@code{condition-type:wrong-number-of-arguments} error. This is because +these procedures examine the apparent arity of a procedure. For +example, here is a procedure that appears to accept any number of +arguments, but when called will signal an error if the number of +arguments is not one: +@findex condition-type:wrong-number-of-arguments + +@example +(lambda arguments (apply car arguments)) +@end example + +@deffn procedure procedure-arity-valid? procedure k +Returns @code{#t} if @var{procedure} accepts @var{k} arguments; +otherwise returns @code{#f}. +@end deffn + +@deffn procedure procedure-arity procedure +Returns a description of the number of arguments that @var{procedure} +accepts. The result is a newly allocated pair whose car field is the +minimum number of arguments, and whose cdr field is the maximum +number of arguments. The minimum is an exact non-negative integer. The +maximum is either an exact non-negative integer, or @code{#f} meaning +that the procedure has no maximum number of arguments. + +@example +@group +(procedure-arity (lambda () 3)) @result{} (0 . 0) +(procedure-arity (lambda (x) x)) @result{} (1 . 1) +(procedure-arity car) @result{} (1 . 1) +(procedure-arity (lambda x x)) @result{} (0 . #f) +(procedure-arity (lambda (x . y) x)) @result{} (1 . #f) +(procedure-arity (lambda (x #!optional y) x)) + @result{} (1 . 2) +@end group +@end example +@end deffn + +@deffn procedure procedure-environment procedure +Returns the closing environment of @var{procedure}. Signals an error if +@var{procedure} is a primitive procedure, or if @var{procedure} is a +compiled procedure for which the debugging information is unavailable. +@end deffn + +@node Primitive Procedures, Continuations, Procedure Operations, Procedures +@section Primitive Procedures + +@deffn procedure make-primitive-procedure name [arity] +@var{Name} must be a symbol. @var{Arity} must be an exact non-negative +integer, @code{-1}, @code{#f}, or @code{#t}; if not supplied it defaults +to @code{#f}. Returns the primitive procedure called @var{name}. May +perform further actions depending on @var{arity}: + +@table @asis +@item @code{#f} +If the primitive procedure is not implemented, signals an error. + +@item @code{#t} +If the primitive procedure is not implemented, returns @code{#f}. + +@item integer +If the primitive procedure is implemented, signals an error if its arity +is not equal to @var{arity}. If the primitive procedure is not +implemented, returns an unimplemented primitive procedure object that +accepts @var{arity} arguments. An @var{arity} of @code{-1} means it +accepts any number of arguments. +@end table +@end deffn + +@deffn procedure primitive-procedure-name primitive-procedure +Returns the name of @var{primitive-procedure}, a symbol. + +@example +(primitive-procedure-name car) @result{} car +@end example +@end deffn + +@deffn procedure implemented-primitive-procedure? primitive-procedure +Returns @code{#t} if @var{primitive-procedure} is implemented; otherwise +returns @code{#f}. Useful because the code that implements a particular +primitive procedure is not necessarily linked into the executable Scheme +program. +@end deffn + +@node Continuations, Application Hooks, Primitive Procedures, Procedures +@section Continuations + +@deffn procedure call-with-current-continuation procedure +@cindex continuation +@cindex construction, of continuation +@cindex procedure, escape (defn) +@cindex escape procedure (defn) +@var{Procedure} must be a procedure of one argument. Packages up the +current continuation (see below) as an @dfn{escape procedure} and passes +it as an argument to @var{procedure}. The escape procedure is a Scheme +procedure of one argument that, if it is later passed a value, will +ignore whatever continuation is in effect at that later time and will +give the value instead to the continuation that was in effect when the +escape procedure was created. The escape procedure created by +@code{call-with-current-continuation} has unlimited extent just like any +other procedure in Scheme. It may be stored in variables or data +structures and may be called as many times as desired. + +The following examples show only the most common uses of this procedure. +If all real programs were as simple as these examples, there would be no +need for a procedure with the power of +@code{call-with-current-continuation}. + +@example +@group +(call-with-current-continuation + (lambda (exit) + (for-each (lambda (x) + (if (negative? x) + (exit x))) + '(54 0 37 -3 245 19)) + #t)) @result{} -3 +@end group + +@group +(define list-length + (lambda (obj) + (call-with-current-continuation + (lambda (return) + (letrec ((r + (lambda (obj) + (cond ((null? obj) 0) + ((pair? obj) (+ (r (cdr obj)) 1)) + (else (return #f)))))) + (r obj)))))) +(list-length '(1 2 3 4)) @result{} 4 +(list-length '(a b . c)) @result{} #f +@end group +@end example + +@cindex non-local exit +@cindex exit, non-local +A common use of @code{call-with-current-continuation} is for structured, +non-local exits from loops or procedure bodies, but in fact +@code{call-with-current-continuation} is quite useful for implementing a +wide variety of advanced control structures. + +Whenever a Scheme expression is evaluated a continuation exists that +wants the result of the expression. The continuation represents an +entire (default) future for the computation. If the expression is +evaluated at top level, for example, the continuation will take the +result, print it on the screen, prompt for the next input, evaluate it, +and so on forever. Most of the time the continuation includes actions +specified by user code, as in a continuation that will take the result, +multiply it by the value stored in a local variable, add seven, and give +the answer to the top-level continuation to be printed. Normally these +ubiquitous continuations are hidden behind the scenes and programmers +don't think much about them. On the rare occasions that you may need to +deal explicitly with continuations, +@code{call-with-current-continuation} lets you do so by creating a +procedure that acts just like the current continuation. +@end deffn + +@deffn procedure continuation? object +@cindex type predicate, for continuation +Returns @code{#t} if @var{object} is a continuation; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure within-continuation continuation thunk +@cindex continuation, alternate invocation +@cindex escape procedure, alternate invocation +@var{Thunk} must be a procedure of no arguments. Conceptually,@* +@code{within-continuation} invokes @var{continuation} on the result of +invoking @var{thunk}, but @var{thunk} is executed in the dynamic context +of @var{continuation}. In other words, the ``current'' continuation is +abandoned before @var{thunk} is invoked. +@end deffn + +@deffn procedure dynamic-wind before thunk after +Calls @var{thunk} without arguments, returning the result(s) of this +call. @var{Before} and @var{after} are called, also without arguments, +as required by the following rules (note that in the absence of calls to +continuations captured using @code{call-with-current-continuation} the +three arguments are called once each, in order). @var{Before} is called +whenever execution enters the dynamic extent of the call to @var{thunk} +and @var{after} is called whenever it exits that dynamic extent. The +dynamic extent of a procedure call is the period between when the call +is initiated and when it returns. In Scheme, because of +@code{call-with-current-continuation}, the dynamic extent of a call may +not be a single, connected time period. It is defined as follows: + +@itemize @bullet +@item +The dynamic extent is entered when execution of the body of the called +procedure begins. + +@item +The dynamic extent is also entered when execution is not within the +dynamic extent and a continuation is invoked that was captured (using +@code{call-with-current-continuation}) during the dynamic extent. + +@item +It is exited when the called procedure returns. + +@item +It is also exited when execution is within the dynamic extent and a +continuation is invoked that was captured while not within the dynamic +extent. +@end itemize + +If a second call to @code{dynamic-wind} occurs within the dynamic extent +of the call to @var{thunk} and then a continuation is invoked in such a +way that the @var{after}s from these two invocations of +@code{dynamic-wind} are both to be called, then the @var{after} +associated with the second (inner) call to @code{dynamic-wind} is called +first. + +If a second call to @code{dynamic-wind} occurs within the dynamic extent +of the call to @var{thunk} and then a continuation is invoked in such a +way that the @var{before}s from these two invocations of +@code{dynamic-wind} are both to be called, then the @var{before} +associated with the first (outer) call to @code{dynamic-wind} is called +first. + +If invoking a continuation requires calling the @var{before} from one +call to @code{dynamic-wind} and the @var{after} from another, then the +@var{after} is called first. + +The effect of using a captured continuation to enter or exit the dynamic +extent of a call to @var{before} or @var{after} is undefined. + +@example +@group +(let ((path '()) + (c #f)) + (let ((add (lambda (s) + (set! path (cons s path))))) + (dynamic-wind + (lambda () (add 'connect)) + (lambda () + (add (call-with-current-continuation + (lambda (c0) + (set! c c0) + 'talk1)))) + (lambda () (add 'disconnect))) + (if (< (length path) 4) + (c 'talk2) + (reverse path)))) + +@result{} (connect talk1 disconnect connect talk2 disconnect) +@end group +@end example +@end deffn + +The following two procedures support multiple values. + +@deffn procedure call-with-values thunk procedure +@cindex multiple values, from procedure +@cindex values, multiple +@var{Thunk} must be a procedure of no arguments, and @var{procedure} +must be a procedure. @var{Thunk} is invoked with a continuation that +expects to receive multiple values; specifically, the continuation +expects to receive the same number of values that @var{procedure} +accepts as arguments. @var{Thunk} must return multiple values using the +@code{values} procedure. Then @var{procedure} is called with the +multiple values as its arguments. The result yielded by @var{procedure} +is returned as the result of @code{call-with-values}. +@end deffn + +@deffn procedure values object @dots{} +Returns multiple values. The continuation in effect when this procedure +is called must be a multiple-value continuation that was created by +@code{call-with-values}. Furthermore it must accept as many values as +there are @var{object}s. +@end deffn + +@node Application Hooks, , Continuations, Procedures +@section Application Hooks + +@cindex application hook (defn) +@cindex procedure, of application hook +@cindex extra object, of application hook +@dfn{Application hooks} are objects that can be applied like procedures. +Each application hook has two parts: a @dfn{procedure} that specifies +what to do when the application hook is applied, and an arbitrary +object, called @dfn{extra}. Often the procedure uses the extra object +to determine what to do. + +@cindex apply hook (defn) +@cindex entity (defn) +There are two kinds of application hooks, which differ in what arguments +are passed to the procedure. When an @dfn{apply hook} is applied, the +procedure is passed exactly the same arguments that were passed to the +apply hook. When an @dfn{entity} is applied, the entity itself is +passed as the first argument, followed by the other arguments that were +passed to the entity. + +Both apply hooks and entities satisfy the predicate @code{procedure?}. +Each satisfies either @code{compiled-procedure?}, +@code{compound-procedure?}, or @code{primitive-procedure?}, depending on +its procedure component. An apply hook is considered to accept the same +number of arguments as its procedure, while an entity is considered to +accept one less argument than its procedure. + +@deffn procedure make-apply-hook procedure object +Returns a newly allocated apply hook with a procedure component of +@var{procedure} and an extra component of @var{object}. +@end deffn + +@deffn procedure apply-hook? object +@cindex type predicate, for apply hook +Returns @code{#t} if @var{object} is an apply hook; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure apply-hook-procedure apply-hook +Returns the procedure component of @var{apply-hook}. +@end deffn + +@deffn procedure set-apply-hook-procedure! apply-hook procedure +Changes the procedure component of @var{apply-hook} to be +@var{procedure}. Returns an unspecified value. +@end deffn + +@deffn procedure apply-hook-extra apply-hook +Returns the extra component of @var{apply-hook}. +@end deffn + +@deffn procedure set-apply-hook-extra! apply-hook object +Changes the extra component of @var{apply-hook} to be @var{object}. +Returns an unspecified value. +@end deffn + +@deffn procedure make-entity procedure object +Returns a newly allocated entity with a procedure component of +@var{procedure} and an extra component of @var{object}. +@end deffn + +@deffn procedure entity? object +@cindex type predicate, for entity +Returns @code{#t} if @var{object} is an entity; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure entity-procedure entity +Returns the procedure component of @var{entity}. +@end deffn + +@deffn procedure set-entity-procedure! entity procedure +Changes the procedure component of @var{entity} to be @var{procedure}. +Returns an unspecified value. +@end deffn + +@deffn procedure entity-extra entity +Returns the extra component of @var{entity}. +@end deffn + +@deffn procedure set-entity-extra! entity object +Changes the extra component of @var{entity} to be @var{object}. Returns +an unspecified value. +@end deffn diff --git a/v7/doc/ref-manual/scheme.texinfo b/v7/doc/ref-manual/scheme.texinfo index 78e92be6b..e652b4c8c 100644 --- a/v7/doc/ref-manual/scheme.texinfo +++ b/v7/doc/ref-manual/scheme.texinfo @@ -2,7 +2,7 @@ @iftex @finalout @end iftex -@comment $Id: scheme.texinfo,v 1.122 2003/03/08 02:10:44 cph Exp $ +@comment $Id: scheme.texinfo,v 1.123 2003/04/15 03:30:11 cph Exp $ @comment %**start of header (This is for running Texinfo on a region.) @setfilename scheme.info @settitle MIT/GNU Scheme Reference @@ -37,7 +37,9 @@ @ifinfo This file documents the MIT/GNU Scheme system. -Copyright @copyright{} 1988-2002 Massachusetts Institute of Technology +Copyright @copyright{} 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +Copyright @copyright{} 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +Copyright @copyright{} 2002,2003 Massachusetts Institute of Technology Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or @@ -49,9 +51,9 @@ Free Documentation License". @titlepage @title{MIT/GNU Scheme Reference Manual} -@subtitle Edition 1.98 -@subtitle for Scheme Release 7.7.2 -@subtitle 7 March 2003 +@subtitle Edition 1.99 +@subtitle for Scheme Release 7.8.0 +@subtitle 14 April 2003 @author by Chris Hanson @author the MIT Scheme Team @author and a cast of thousands @@ -59,7 +61,9 @@ Free Documentation License". @page @vskip 0pt plus 1filll -Copyright @copyright{} 1988-2002 Massachusetts Institute of Technology +Copyright @copyright{} 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +Copyright @copyright{} 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +Copyright @copyright{} 2002,2003 Massachusetts Institute of Technology Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or @@ -468,22947 +472,24 @@ Massachusetts Institute of Technology. Support for this research is provided in part by the Advanced Research Projects Agency of the Department of Defense and by the National Science Foundation. -@node Overview, Special Forms, Acknowledgements, Top -@chapter Overview - -@cindex runtime system -This manual is a detailed description of the MIT/GNU Scheme runtime system. -It is intended to be a reference document for programmers. It does not -describe how to run Scheme or how to interact with it --- that is the -subject of the @cite{MIT/GNU Scheme User's Manual}. - -This chapter summarizes the semantics of Scheme, briefly describes the -MIT/GNU Scheme programming environment, and explains the syntactic and -lexical conventions of the language. Subsequent chapters describe -special forms, numerous data abstractions, and facilities for input and -output. - -@cindex standard Scheme (defn) -@cindex Scheme standard -@cindex R4RS -Throughout this manual, we will make frequent references to -@dfn{standard Scheme}, which is the language defined by the document -@cite{Revised^4 Report on the Algorithmic Language Scheme}, by William -Clinger, Jonathan Rees, et al.@:, or by @sc{ieee} Std.@: 1178-1990, -@cite{IEEE Standard for the Scheme Programming Language} (in fact, -several parts of this document are copied from the @cite{Revised -Report}). MIT/GNU Scheme is an extension of standard Scheme. - -These are the significant semantic characteristics of the Scheme -language: - -@table @asis -@item Variables are statically scoped -@cindex static scoping (defn) -@cindex scope (see region) -Scheme is a @dfn{statically scoped} programming language, which means that -each use of a variable is associated with a lexically apparent binding -of that variable. Algol is another statically scoped language. - -@item Types are latent -@cindex latent types (defn) -@cindex manifest types (defn) -@cindex weak types (defn) -@cindex strong types (defn) -@cindex dynamic types (defn) -@cindex static types (defn) -@cindex types, latent (defn) -@cindex types, manifest (defn) -Scheme has @dfn{latent} types as opposed to @dfn{manifest} types, which -means that Scheme associates types with values (or objects) rather than -with variables. Other languages with latent types (also referred to as -@dfn{weakly} typed or @dfn{dynamically} typed languages) include APL, -Snobol, and other dialects of Lisp. Languages with manifest types -(sometimes referred to as @dfn{strongly} typed or @dfn{statically} typed -languages) include Algol 60, Pascal, and C. - -@item Objects have unlimited extent -@cindex extent, of objects -All objects created during a Scheme computation, including procedures -and continuations, have unlimited extent; no Scheme object is ever -destroyed. The system doesn't run out of memory because the garbage -collector reclaims the storage occupied by an object when the object -cannot possibly be needed by a future computation. Other languages in -which most objects have unlimited extent include APL and other Lisp -dialects. - -@item Proper tail recursion -@cindex proper tail recursion (defn) -@cindex tail recursion (defn) -@cindex recursion (see tail recursion) -Scheme is @dfn{properly tail-recursive}, which means that iterative -computation can occur in constant space, even if the iterative -computation is described by a syntactically recursive procedure. With a -tail-recursive implementation, you can express iteration using the -ordinary procedure-call mechanics; special iteration expressions are -provided only for syntactic convenience. - -@item Procedures are objects -Scheme procedures are objects, which means that you can create them -dynamically, store them in data structures, return them as the results -of other procedures, and so on. Other languages with such procedure -objects include Common Lisp and ML. - -@item Continuations are explicit -In most other languages, continuations operate behind the scenes. In -Scheme, continuations are objects; you can use continuations for -implementing a variety of advanced control constructs, including -non-local exits, backtracking, and coroutines. - -@item Arguments are passed by value -Arguments to Scheme procedures are passed by value, which means that -Scheme evaluates the argument expressions before the procedure gains -control, whether or not the procedure needs the result of the -evaluations. ML, C, and APL are three other languages that pass -arguments by value. In languages such as SASL and Algol 60, argument -expressions are not evaluated unless the values are needed by the -procedure. -@end table - -@findex read -Scheme uses a parenthesized-list Polish notation to describe programs -and (other) data. The syntax of Scheme, like that of most Lisp -dialects, provides for great expressive power, largely due to its -simplicity. An important consequence of this simplicity is the -susceptibility of Scheme programs and data to uniform treatment by other -Scheme programs. As with other Lisp dialects, the @code{read} primitive -parses its input; that is, it performs syntactic as well as lexical -decomposition of what it reads. - -@menu -* Notational Conventions:: -* Scheme Concepts:: -* Lexical Conventions:: -* Expressions:: -@end menu - -@node Notational Conventions, Scheme Concepts, Overview, Overview -@section Notational Conventions -@cindex notational conventions -@cindex conventions, notational - -This section details the notational conventions used throughout the rest -of this document. - -@menu -* Errors:: -* Examples:: -* Entry Format:: -@end menu - -@node Errors, Examples, Notational Conventions, Notational Conventions -@subsection Errors -@cindex errors, notational conventions - -@cindex signal an error (defn) -@cindex must be, notational convention -@findex error -When this manual uses the phrase ``an error will be signalled,'' it -means that Scheme will call @code{error}, which normally halts execution -of the program and prints an error message. - -When this manual uses the phrase ``it is an error,'' it means that the -specified action is not valid in Scheme, but the system may or may not -signal the error. When this manual says that something ``must be,'' it -means that violating the requirement is an error. - -@node Examples, Entry Format, Errors, Notational Conventions -@subsection Examples -@cindex examples - -@cindex => notational convention -@cindex result of evaluation, in examples -@cindex evaluation, in examples -@cindex specified result, in examples -This manual gives many examples showing the evaluation of expressions. -The examples have a common format that shows the expression being -evaluated on the left hand side, an ``arrow'' in the middle, and the -value of the expression written on the right. For example: - -@example -(+ 1 2) @result{} 3 -@end example - -Sometimes the arrow and value will be moved under the expression, due to -lack of space. Occasionally we will not care what the value is, in -which case both the arrow and the value are omitted. - -@cindex error--> notational convention -@cindex error, in examples -If an example shows an evaluation that results in an error, an error -message is shown, prefaced by @samp{@error{}}: - -@example -(+ 1 'foo) @error{} Illegal datum -@end example - -@cindex -| notational convention -@cindex printed output, in examples -An example that shows printed output marks it with @samp{@print{}}: - -@example -@group -(begin (write 'foo) 'bar) - @print{} foo - @result{} bar -@end group -@end example - -@cindex unspecified result (defn) -@cindex result, unspecified (defn) -When this manual indicates that the value returned by some expression is -@dfn{unspecified}, it means that the expression will evaluate to some -object without signalling an error, but that programs should not depend -on the value in any way. - -@node Entry Format, , Examples, Notational Conventions -@subsection Entry Format -@cindex entry format -@cindex format, entry - -Each description of an MIT/GNU Scheme variable, special form, or -procedure begins with one or more header lines in this format: - -@deffn @var{category} @var{template} -@end deffn - -@noindent -where @var{category} specifies the kind of item (``variable'', -``special form'', or ``procedure''). The form of @var{template} is -interpreted depending on @var{category}. - -@table @asis -@item Variable -@var{Template} consists of the variable's name. -@cindex variable, entry category - -@item Special Form -@var{Template} starts with the syntactic keyword of the special form, -followed by a description of the special form's syntax. The description -is written using the following conventions. -@cindex special form, entry category - -@findex else -@findex cond -Named components are italicized in the printed manual, and uppercase in -the Info file. ``Noise'' keywords, such as the @code{else} keyword in -the @code{cond} special form, are set in a fixed width font in the -printed manual; in the Info file they are not distinguished. -Parentheses indicate themselves. - -@cindex ellipsis, in entries -@cindex ... in entries -A horizontal ellipsis (@dots{}) is describes repeated components. -Specifically, - -@display -@var{thing} @dots{} -@end display - -@noindent -indicates @emph{zero} or more occurrences of @var{thing}, while - -@display -@var{thing} @var{thing} @dots{} -@end display - -@noindent -indicates @emph{one} or more occurrences of @var{thing}. - -@cindex bracket, in entries -@cindex [ in entries -@cindex ] in entries -@cindex optional component, in entries -Brackets, @code{[ ]}, enclose optional components. - -@cindex body, of special form (defn) -@findex lambda -Several special forms (e.g.@: @code{lambda}) have an internal component -consisting of a series of expressions; usually these expressions are -evaluated sequentially under conditions that are specified in the -description of the special form. This sequence of expressions is commonly -referred to as the @dfn{body} of the special form. - -@item Procedure -@var{Template} starts with the name of the variable to which the -procedure is bound, followed by a description of the procedure's -arguments. The arguments are described using ``lambda list'' notation -(@pxref{Lambda Expressions}), except that brackets are used to denote -optional arguments, and ellipses are used to denote ``rest'' arguments. -@cindex procedure, entry format - -The names of the procedure's arguments are italicized in the printed -manual, and uppercase in the Info file. - -When an argument names a Scheme data type, it indicates that the -argument must be that type of data object. For example, - -@deffn procedure cdr pair -@end deffn - -@noindent -indicates that the standard Scheme procedure @code{cdr} takes one argument, -which must be a pair. - -Many procedures signal an error when an argument is of the wrong type; -usually this error is a condition of type -@code{condition-type:wrong-type-argument}. -@findex condition-type:wrong-type-argument - -In addition to the standard data-type names (@var{pair}, @var{list}, -@var{boolean}, @var{string}, etc.), the following names as arguments -also imply type restrictions: - -@itemize @bullet -@item -@var{object}: any object -@item -@var{thunk}: a procedure of no arguments -@item -@var{x}, @var{y}: real numbers -@item -@var{q}, @var{n}: integers -@item -@var{k}: an exact non-negative integer -@end itemize -@end table - -Some examples: - -@deffn procedure list object @dots{} -@end deffn - -@noindent -indicates that the standard Scheme procedure @code{list} takes zero or -more arguments, each of which may be any Scheme object. - -@deffn procedure write-char char [output-port] -@end deffn - -@noindent -indicates that the standard Scheme procedure @code{write-char} must be -called with a character, @var{char}, and may also be called with a -character and an output port. - -@node Scheme Concepts, Lexical Conventions, Notational Conventions, Overview -@section Scheme Concepts -@cindex scheme concepts - -@menu -* Variable Bindings:: -* Environment Concepts:: -* Initial and Current Environments:: -* Static Scoping:: -* True and False:: -* External Representations:: -* Disjointness of Types:: -* Storage Model:: -@end menu - -@node Variable Bindings, Environment Concepts, Scheme Concepts, Scheme Concepts -@subsection Variable Bindings -@cindex variable binding -@cindex binding, of variable - -@cindex bound variable (defn) -@cindex value, of variable (defn) -@cindex name, of value (defn) -@cindex location, of variable -Any identifier that is not a syntactic keyword may be used as a variable -(@pxref{Identifiers}). A variable may name a location where a value can -be stored. A variable that does so is said to be @dfn{bound} to the -location. The value stored in the location to which a variable is bound -is called the variable's @dfn{value}. (The variable is sometimes said -to @dfn{name} the value or to be @dfn{bound to} the value.) - -@cindex unassigned variable (defn) -@cindex error, unassigned variable -A variable may be bound but still not have a value; such a variable is -said to be @dfn{unassigned}. Referencing an unassigned variable is an -error. When this error is signalled, it is a condition of type -@code{condition-type:unassigned-variable}; sometimes the compiler does -not generate code to signal the error. Unassigned variables are useful -only in combination with side effects (@pxref{Assignments}). -@findex condition-type:unassigned-variable - -@node Environment Concepts, Initial and Current Environments, Variable Bindings, Scheme Concepts -@subsection Environment Concepts - -@cindex environment (defn) -@cindex unbound variable (defn) -@cindex error, unbound variable (defn) -An @dfn{environment} is a set of variable bindings. If an environment -has no binding for a variable, that variable is said to be @dfn{unbound} -in that environment. Referencing an unbound variable signals a -condition of type @code{condition-type:unbound-variable}. -@findex condition-type:unbound-variable - -@cindex extension, of environment (defn) -@cindex environment, extension (defn) -@cindex shadowing, of variable binding (defn) -@cindex parent, of environment (defn) -@cindex child, of environment (defn) -@cindex inheritance, of environment bindings (defn) -A new environment can be created by @dfn{extending} an existing -environment with a set of new bindings. Note that ``extending an -environment'' does @strong{not} modify the environment; rather, it -creates a new environment that contains the new bindings and the old -ones. The new bindings @dfn{shadow} the old ones; that is, if an -environment that contains a binding for @code{x} is extended with a new -binding for @code{x}, then only the new binding is seen when @code{x} is -looked up in the extended environment. Sometimes we say that the -original environment is the @dfn{parent} of the new one, or that the new -environment is a @dfn{child} of the old one, or that the new environment -@dfn{inherits} the bindings in the old one. - -@findex let -@findex let* -@findex letrec -@findex do -@findex define -Procedure calls extend an environment, as do @code{let}, @code{let*}, -@code{letrec}, and @code{do} expressions. Internal definitions -(@pxref{Internal Definitions}) also extend an environment. (Actually, -all the constructs that extend environments can be expressed in terms of -procedure calls, so there is really just one fundamental mechanism for -environment extension.) A top-level definition (@pxref{Top-Level -Definitions}) may add a binding to an existing environment. - -@node Initial and Current Environments, Static Scoping, Environment Concepts, Scheme Concepts -@subsection Initial and Current Environments - -@cindex initial environment (defn) -@cindex environment, initial (defn) -MIT/GNU Scheme provides an @dfn{initial environment} that contains all -of the variable bindings described in this manual. Most environments -are ultimately extensions of this initial environment. In Scheme, the -environment in which your programs execute is actually a child -(extension) of the environment containing the system's bindings. Thus, -system names are visible to your programs, but your names do not -interfere with system programs. - -@cindex current environment (defn) -@cindex environment, current (defn) -@cindex REP loop (defn) -@cindex REP loop, environment of -@findex user-initial-environment -@findex ge -The environment in effect at some point in a program is called the -@dfn{current environment} at that point. In particular, every -@acronym{REP} loop has a current environment. (@acronym{REP} stands for -``read-eval-print''; the @acronym{REP} loop is the Scheme program that -reads your input, evaluates it, and prints the result.) The environment -of the top-level @acronym{REP} loop (the one you are in when Scheme -starts up) starts as @code{user-initial-environment}, although it can be -changed by the @code{ge} procedure. When a new @acronym{REP} loop is -created, its environment is determined by the program that creates it. - -@node Static Scoping, True and False, Initial and Current Environments, Scheme Concepts -@subsection Static Scoping -@cindex scoping, static -@cindex static scoping - -@cindex dynamic binding, versus static scoping -Scheme is a statically scoped language with block structure. In this -respect, it is like Algol and Pascal, and unlike most other dialects of -Lisp except for Common Lisp. - -@cindex binding expression (defn) -@cindex expression, binding (defn) -The fact that Scheme is statically scoped (rather than -dynamically bound) means that the environment that is extended (and -becomes current) when a procedure is called is the environment in which -the procedure was created (i.e.@: in which the procedure's defining -lambda expression was evaluated), not the environment in which the -procedure is called. Because all the other Scheme @dfn{binding -expressions} can be expressed in terms of procedures, this determines -how all bindings behave. - -Consider the following definitions, made at the top-level @acronym{REP} -loop (in the initial environment): - -@example -@group -(define x 1) -(define (f x) (g 2)) -(define (g y) (+ x y)) -(f 5) @result{} 3 @r{; not} 7 -@end group -@end example - -Here @code{f} and @code{g} are bound to procedures created in the -initial environment. Because Scheme is statically scoped, the call to -@code{g} from @code{f} extends the initial environment (the one in which -@code{g} was created) with a binding of @code{y} to @code{2}. In this -extended environment, @code{y} is @code{2} and @code{x} is @code{1}. -(In a dynamically bound Lisp, the call to @code{g} would extend the -environment in effect during the call to @code{f}, in which @code{x} is -bound to @code{5} by the call to @code{f}, and the answer would be -@code{7}.) - -@cindex lexical scoping (defn) -@cindex scoping, lexical (defn) -@cindex region, of variable binding (defn) -@cindex variable, binding region (defn) -@findex lambda -Note that with static scoping, you can tell what binding a variable -reference refers to just from looking at the text of the program; the -referenced binding cannot depend on how the program is used. That is, -the nesting of environments (their parent-child relationship) -corresponds to the nesting of binding expressions in program text. -(Because of this connection to the text of the program, static scoping -is also called @dfn{lexical} scoping.) For each place where a variable -is bound in a program there is a corresponding @dfn{region} of the -program text within which the binding is effective. For example, the -region of a binding established by a @code{lambda} expression is the -entire body of the @code{lambda} expression. The documentation of each -binding expression explains what the region of the bindings it makes is. -A use of a variable (that is, a reference to or assignment of a -variable) refers to the innermost binding of that variable whose region -contains the variable use. If there is no such region, the use refers -to the binding of the variable in the global environment (which is an -ancestor of all other environments, and can be thought of as a region in -which all your programs are contained). - -@node True and False, External Representations, Static Scoping, Scheme Concepts -@subsection True and False - -@cindex boolean object -@cindex true, boolean object -@cindex false, boolean object -@findex #t -@findex #f -In Scheme, the boolean values true and false are denoted by @code{#t} -and @code{#f}. However, any Scheme value can be treated as a boolean -for the purpose of a conditional test. This manual uses the word -@dfn{true} to refer to any Scheme value that counts as true, and the -word @dfn{false} to refer to any Scheme value that counts as false. In -conditional tests, all values count as true except for @code{#f}, which -counts as false (@pxref{Conditionals}). - -Implementation note: In MIT/GNU Scheme, @code{#f} and the empty list are the -same object, and the printed representation of @code{#f} is always -@samp{()}. As this contradicts the Scheme standard, MIT/GNU Scheme will be -changed to make @code{#f} and the empty list different objects. - -@node External Representations, Disjointness of Types, True and False, Scheme Concepts -@subsection External Representations - -@cindex external representation (defn) -@cindex representation, external (defn) -An important concept in Scheme is that of the -@dfn{external representation} of an object as a sequence of characters. -For example, an external representation of the integer 28 is the -sequence of characters @samp{28}, and an external representation of a -list consisting of the integers 8 and 13 is the sequence of characters -@samp{(8 13)}. - -The external representation of an object is not necessarily unique. The -integer 28 also has representations @samp{#e28.000} and @samp{#x1c}, and -the list in the previous paragraph also has the representations @samp{( -08 13 )} and @samp{(8 . (13 . ( )))}. - -Many objects have standard external representations, but some, such as -procedures and circular data structures, do not have standard -representations (although particular implementations may define -representations for them). - -An external representation may be written in a program to obtain the -corresponding object (@pxref{Quoting}). - -@findex read -@findex write -External representations can also be used for input and output. The -procedure @code{read} parses external representations, and the procedure -@code{write} generates them. Together, they provide an elegant and -powerful input/output facility. - -Note that the sequence of characters @samp{(+ 2 6)} is @emph{not} an -external representation of the integer 8, even though it @emph{is} an -expression that evaluates to the integer 8; rather, it is an external -representation of a three-element list, the elements of which are the -symbol @code{+} and the integers @code{2} and @code{6}. Scheme's syntax -has the property that any sequence of characters that is an expression -is also the external representation of some object. This can lead to -confusion, since it may not be obvious out of context whether a given -sequence of characters is intended to denote data or program, but it is -also a source of power, since it facilitates writing programs such as -interpreters and compilers that treat programs as data or data as -programs. - -@node Disjointness of Types, Storage Model, External Representations, Scheme Concepts -@subsection Disjointness of Types - -Every object satisfies at most one of the following predicates (but see -@ref{True and False}, for an exception): - -@example -@group -bit-string? environment? port? symbol? -boolean? null? procedure? vector? -cell? number? promise? weak-pair? -char? pair? string? -condition? -@end group -@end example - -@node Storage Model, , Disjointness of Types, Scheme Concepts -@subsection Storage Model - -This section describes a model that can be used to understand Scheme's -use of storage. - -@cindex location -@findex string-set! -Variables and objects such as pairs, vectors, and strings implicitly -denote locations or sequences of locations. A string, for example, -denotes as many locations as there are characters in the string. (These -locations need not correspond to a full machine word.) A new value may -be stored into one of these locations using the @code{string-set!} -procedure, but the string continues to denote the same locations as -before. - -@findex car -@findex vector-ref -@findex string-ref -@findex eqv? -An object fetched from a location, by a variable reference or by a -procedure such as @code{car}, @code{vector-ref}, or @code{string-ref}, -is equivalent in the sense of @code{eqv?} to the object last stored in -the location before the fetch. - -Every location is marked to show whether it is in use. No variable or -object ever refers to a location that is not in use. Whenever this -document speaks of storage being allocated for a variable or object, -what is meant is that an appropriate number of locations are chosen from -the set of locations that are not in use, and the chosen locations are -marked to indicate that they are now in use before the variable or -object is made to denote them. - -@cindex constant -@cindex mutable -@cindex immutable -@findex symbol->string -In many systems it is desirable for constants (i.e.@: the values of -literal expressions) to reside in read-only memory. To express this, it -is convenient to imagine that every object that denotes locations is -associated with a flag telling whether that object is mutable or -immutable. The constants and the strings returned by -@code{symbol->string} are then the immutable objects, while all objects -created by other procedures are mutable. It is an error to attempt to -store a new value into a location that is denoted by an immutable -object. Note that the MIT/GNU Scheme compiler takes advantage of this -property to share constants, but that these constants are not immutable. -Instead, two constants that are @code{equal?} may be @code{eq?} in -compiled code. - -@node Lexical Conventions, Expressions, Scheme Concepts, Overview -@section Lexical Conventions -@cindex lexical conventions -@cindex conventions, lexical - -This section describes Scheme's lexical conventions. - -@menu -* Whitespace:: -* Delimiters:: -* Identifiers:: -* Uppercase and Lowercase:: -* Naming Conventions:: -* Comments:: -* Additional Notations:: -@end menu - -@node Whitespace, Delimiters, Lexical Conventions, Lexical Conventions -@subsection Whitespace - -@cindex whitespace, in programs (defn) -@cindex token, in programs (defn) -@dfn{Whitespace} characters are spaces, newlines, tabs, and page breaks. -Whitespace is used to improve the readability of your programs and to -separate tokens from each other, when necessary. (A @dfn{token} is an -indivisible lexical unit such as an identifier or number.) Whitespace -is otherwise insignificant. Whitespace may occur between any two -tokens, but not within a token. Whitespace may also occur inside a -string, where it is significant. - -@node Delimiters, Identifiers, Whitespace, Lexical Conventions -@subsection Delimiters - -@cindex delimiter, in programs (defn) -All whitespace characters are @dfn{delimiters}. In addition, the -following characters act as delimiters: - -@example -( ) ; " ' ` | -@end example - -Finally, these next characters act as delimiters, despite the fact that -Scheme does not define any special meaning for them: - -@example -[ ] @{ @} -@end example - -For example, if the value of the variable @code{name} is -@code{"max"}: - -@example -(list"Hi"name(+ 1 2)) @result{} ("Hi" "max" 3) -@end example - -@node Identifiers, Uppercase and Lowercase, Delimiters, Lexical Conventions -@subsection Identifiers - -@cindex identifier (defn) -An @dfn{identifier} is a sequence of one or more non-delimiter -characters. Identifiers are used in several ways in Scheme -programs: - -@itemize @bullet -@item -An identifier can be used as a variable or as a syntactic keyword. -@cindex variable, identifier as -@cindex syntactic keyword, identifier as - -@item -When an identifier appears as a literal or within a literal, it denotes -a symbol. -@cindex literal, identifier as -@end itemize - -Scheme accepts most of the identifiers that other programming languages -allow. MIT/GNU Scheme allows all of the identifiers that standard -Scheme does, plus many more. - -MIT/GNU Scheme defines a potential identifier to be a sequence of -non-delimiter characters that does not begin with either of the -characters @samp{#} or @samp{,}. Any such sequence of characters that -is not a syntactically valid number (@pxref{Numbers}) is considered to -be a valid identifier. Note that, although it is legal for @samp{#} and -@samp{,} to appear in an identifier (other than in the first character -position), it is poor programming practice. - -Here are some examples of identifiers: - -@example -@group -lambda q -list->vector soup -+ V17a -<=? a34kTMNs -the-word-recursion-has-many-meanings -@end group -@end example - -@node Uppercase and Lowercase, Naming Conventions, Identifiers, Lexical Conventions -@subsection Uppercase and Lowercase -@cindex uppercase -@cindex lowercase - -@cindex alphabetic case-insensitivity of programs (defn) -@cindex case-insensitivity of programs (defn) -@cindex sensitivity, to case in programs (defn) -@cindex insensitivity, to case in programs (defn) -Scheme doesn't distinguish uppercase and lowercase forms of a letter -except within character and string constants; in other words, Scheme is -@dfn{case-insensitive}. For example, @samp{Foo} is the same identifier -as @samp{FOO}, and @samp{#x1AB} is the same number as @samp{#X1ab}. But -@samp{#\a} and @samp{#\A} are different characters. - -@node Naming Conventions, Comments, Uppercase and Lowercase, Lexical Conventions -@subsection Naming Conventions -@cindex naming conventions -@cindex conventions, naming - -@cindex predicate (defn) -@cindex ? in predicate names -A @dfn{predicate} is a procedure that always returns a boolean value -(@code{#t} or @code{#f}). By convention, predicates usually have names -that end in @samp{?}. - -@cindex mutation procedure (defn) -@cindex ! in mutation procedure names -A @dfn{mutation procedure} is a procedure that alters a data structure. -By convention, mutation procedures usually have names that end in -@samp{!}. - -@node Comments, Additional Notations, Naming Conventions, Lexical Conventions -@subsection Comments - -@cindex comment, in programs (defn) -@cindex semicolon, as external representation -@cindex ; as external representation -The beginning of a comment is indicated with a semicolon (@code{;}). -Scheme ignores everything on a line in which a semicolon appears, from -the semicolon until the end of the line. The entire comment, including -the newline character that terminates it, is treated as -whitespace. - -@cindex extended comment, in programs (defn) -@cindex comment, extended, in programs (defn) -@cindex #| as external representation -An alternative form of comment (sometimes called an @dfn{extended -comment}) begins with the characters @samp{#|} and ends with the -characters @samp{|#}. This alternative form is an MIT/GNU Scheme extension. -As with ordinary comments, all of the characters in an extended comment, -including the leading @samp{#|} and trailing @samp{|#}, are treated as -whitespace. Comments of this form may extend over multiple lines, and -additionally may be nested (unlike the comments of the programming -language C, which have a similar syntax). - -@example -@group -;;; This is a comment about the FACT procedure. Scheme -;;; ignores all of this comment. The FACT procedure computes -;;; the factorial of a non-negative integer. -@end group - -@group -#| -This is an extended comment. -Such comments are useful for commenting out code fragments. -|# -@end group - -@group -(define fact - (lambda (n) - (if (= n 0) ;This is another comment: - 1 ;Base case: return 1 - (* n (fact (- n 1)))))) -@end group -@end example - -@node Additional Notations, , Comments, Lexical Conventions -@subsection Additional Notations - -@cindex characters, special, in programs -@cindex special characters, in programs -The following list describes additional notations used in Scheme. -@xref{Numbers}, for a description of the notations used for numbers. - -@table @code -@item + - . -The plus sign, minus sign, and period are used in numbers, and may also -occur in an identifier. A delimited period (not occurring within a -number or identifier) is used in the notation for pairs and to indicate -a ``rest'' parameter in a formal parameter list -(@pxref{Lambda Expressions}). - -@item ( ) -Parentheses are used for grouping and to notate lists (@pxref{Lists}). - -@item " -The double quote delimits strings (@pxref{Strings}). - -@item \ -The backslash is used in the syntax for character constants -(@pxref{Characters}) and as an escape character within string constants -(@pxref{Strings}). - -@item ; -The semicolon starts a comment. - -@item ' -The single quote indicates literal data; it suppresses evaluation -(@pxref{Quoting}). - -@item ` -The backquote indicates almost-constant data (@pxref{Quoting}). - -@item , -The comma is used in conjunction with the backquote (@pxref{Quoting}). - -@item ,@@ -A comma followed by an at-sign is used in conjunction with the backquote -(@pxref{Quoting}). - -@item # -The sharp (or pound) sign has different uses, depending on the character -that immediately follows it: - -@item #t #f -These character sequences denote the boolean constants -(@pxref{Booleans}). - -@item #\ -This character sequence introduces a character constant -(@pxref{Characters}). - -@item #( -This character sequence introduces a vector constant (@pxref{Vectors}). -A close parenthesis, @samp{)}, terminates a vector constant. - -@item #e #i #b #o #d #l #s #x -These character sequences are used in the notation for numbers -(@pxref{Numbers}). - -@item #| -This character sequence introduces an extended comment. The comment is -terminated by the sequence @samp{|#}. This notation is an MIT/GNU Scheme -extension. - -@item #! -This character sequence is used to denote a small set of named -constants. Currently there are only two of these, @code{#!optional} and -@code{#!rest}, both of which are used in the @code{lambda} special form -to mark certain parameters as being ``optional'' or ``rest'' parameters. -This notation is an MIT/GNU Scheme extension. -@findex #!optional -@findex #!rest -@findex lambda - -@item #* -This character sequence introduces a bit string (@pxref{Bit Strings}). -This notation is an MIT/GNU Scheme extension. - -@item #[ -This character sequence is used to denote objects that do not have a -readable external representation (@pxref{Custom Output}). A close -bracket, @samp{]}, terminates the object's notation. This notation is -an MIT/GNU Scheme extension. - -@item #@@ -This character sequence is a convenient shorthand used to refer to -objects by their hash number (@pxref{Custom Output}). This notation is -an MIT/GNU Scheme extension. - -@item #= -@itemx ## -These character sequences introduce a notation used to show circular -structures in printed output, or to denote them in input. The notation -works much like that in Common Lisp, and is an MIT/GNU Scheme extension. -@end table - -@node Expressions, , Lexical Conventions, Overview -@section Expressions - -@cindex expression (defn) -A Scheme @dfn{expression} is a construct that returns a value. An -expression may be a @emph{literal}, a @emph{variable reference}, a -@emph{special form}, or a @emph{procedure call}. - -@menu -* Literal Expressions:: -* Variable References:: -* Special Form Syntax:: -* Procedure Call Syntax:: -@end menu - -@node Literal Expressions, Variable References, Expressions, Expressions -@subsection Literal Expressions - -@cindex literal expression (defn) -@cindex constant expression (defn) -@cindex expression, literal (defn) -@cindex expression, constant (defn) -@dfn{Literal} constants may be written by using an external -representation of the data. In general, the external representation -must be @emph{quoted} (@pxref{Quoting}); but some external -representations can be used without quotation. - -@example -@group -"abc" @result{} "abc" -145932 @result{} 145932 -#t @result{} #t -#\a @result{} #\a -@end group -@end example - -The external representation of numeric constants, string constants, -character constants, and boolean constants evaluate to the constants -themselves. Symbols, pairs, lists, and vectors require quoting. - -@node Variable References, Special Form Syntax, Literal Expressions, Expressions -@subsection Variable References - -@cindex variable reference (defn) -@cindex reference, variable (defn) -@cindex unbound variable -@cindex unassigned variable -An expression consisting of an identifier (@pxref{Identifiers}) is a -@dfn{variable reference}; the identifier is the name of the variable -being referenced. The value of the variable reference is the value -stored in the location to which the variable is bound. An error is -signalled if the referenced variable is unbound or unassigned. - -@example -@group -(define x 28) -x @result{} 28 -@end group -@end example - -@node Special Form Syntax, Procedure Call Syntax, Variable References, Expressions -@subsection Special Form Syntax - -@example -(@var{keyword} @var{component} @dots{}) -@end example - -@cindex expression, special form (defn) -@cindex special form (defn) -@cindex form, special (defn) -@cindex keyword, of special form (defn) -@cindex syntactic keyword (defn) -A parenthesized expression that starts with a @dfn{syntactic keyword} is -a @dfn{special form}. Each special form has its own syntax, which is -described later in the manual. - -Note that syntactic keywords and variable bindings share the same -namespace. A local variable binding may shadow a syntactic keyword, and -a local syntactic-keyword definition may shadow a variable binding. - -The following list contains all of the syntactic keywords that are -defined when MIT/GNU Scheme is initialized: - -@multitable @columnfractions .33 .33 .33 -@item access -@tab and -@tab begin -@item case -@tab cond -@tab cons-stream -@item declare -@tab default-object? -@tab define -@item define-integrable -@tab define-structure -@tab define-syntax -@item delay -@tab do -@tab er-macro-transformer -@item fluid-let -@tab if -@tab lambda -@item let -@tab let* -@tab let*-syntax -@item let-syntax -@tab letrec -@tab letrec-syntax -@item local-declare -@tab named-lambda -@tab non-hygienic-macro-transformer -@item or -@tab quasiquote -@tab quote -@item rsc-macro-transformer -@tab sc-macro-transformer -@tab set! -@item syntax-rules -@tab the-environment -@end multitable - -@node Procedure Call Syntax, , Special Form Syntax, Expressions -@subsection Procedure Call Syntax - -@example -(@var{operator} @var{operand} @dots{}) -@end example - -@cindex expression, procedure call (defn) -@cindex procedure call (defn) -@cindex operator, of procedure call (defn) -@cindex operand, of procedure call (defn) -A @dfn{procedure call} is written by simply enclosing in parentheses -expressions for the procedure to be called (the @dfn{operator}) and the -arguments to be passed to it (the @dfn{operands}). The @var{operator} -and @var{operand} expressions are evaluated and the resulting procedure -is passed the resulting arguments. @xref{Lambda Expressions}, for a -more complete description of this. - -@cindex combination (defn) -Another name for the procedure call expression is @dfn{combination}. -This word is more specific in that it always refers to the expression; -``procedure call'' sometimes refers to the @emph{process} of calling a -procedure. - -@cindex order, of argument evaluation -@cindex evaluation order, of arguments -@cindex argument evaluation order -Unlike some other dialects of Lisp, Scheme always evaluates the operator -expression and the operand expressions with the same evaluation rules, -and the order of evaluation is unspecified. - -@example -@group -(+ 3 4) @result{} 7 -((if #f = *) 3 4) @result{} 12 -@end group -@end example - -@findex + -@findex * -@findex lambda -A number of procedures are available as the values of variables in the -initial environment; for example, the addition and multiplication -procedures in the above examples are the values of the variables -@code{+} and @code{*}. New procedures are created by evaluating -@code{lambda} expressions. - -@cindex syntactic keyword -If the @var{operator} is a syntactic keyword, then the expression is not -treated as a procedure call: it is a special form. - -@node Special Forms, Equivalence Predicates, Overview, Top -@chapter Special Forms - -@cindex special form -A special form is an expression that follows special evaluation rules. -This chapter describes the basic Scheme special forms. - -@menu -* Lambda Expressions:: -* Lexical Binding:: -* Dynamic Binding:: -* Definitions:: -* Assignments:: -* Quoting:: -* Conditionals:: -* Sequencing:: -* Iteration:: -* Structure Definitions:: -* Macros:: -* SRFI syntax:: -@end menu - -@node Lambda Expressions, Lexical Binding, Special Forms, Special Forms -@section Lambda Expressions - -@deffn {special form} lambda formals expression expression @dots{} -@cindex lambda expression (defn) -@cindex procedure, construction -@cindex procedure, closing environment (defn) -@cindex procedure, invocation environment (defn) -@cindex construction, of procedure -@cindex closing environment, of procedure (defn) -@cindex invocation environment, of procedure (defn) -@cindex environment, of procedure -@cindex environment, procedure closing (defn) -@cindex environment, procedure invocation (defn) -A @code{lambda} expression evaluates to a procedure. The environment in -effect when the @code{lambda} expression is evaluated is remembered as -part of the procedure; it is called the @dfn{closing environment}. When -the procedure is later called with some arguments, the closing -environment is extended by binding the variables in the formal parameter -list to fresh locations, and the locations are filled with the arguments -according to rules about to be given. The new environment created by -this process is referred to as the @dfn{invocation environment}. - -@cindex region of variable binding, lambda -@cindex variable binding, lambda -Once the invocation environment has been constructed, the -@var{expression}s in the body of the @code{lambda} expression are -evaluated sequentially in it. This means that the region of the -variables bound by the @code{lambda} expression is all of the -@var{expression}s in the body. The result of evaluating the last -@var{expression} in the body is returned as the result of the procedure -call. - -@cindex lambda list (defn) -@cindex parameter list, of lambda (defn) -@cindex formal parameter list, of lambda (defn) -@var{Formals}, the formal parameter list, is often referred to as a -@dfn{lambda list}. - -The process of matching up formal parameters with arguments is somewhat -involved. There are three types of parameters, and the matching treats -each in sequence: - -@need 1000 -@table @asis -@item Required -All of the @dfn{required} parameters are matched against the arguments -first. If there are fewer arguments than required parameters, an error -of type @code{condition-type:wrong-number-of-arguments} is signalled; -this error is also signalled if there are more arguments than required -parameters and there are no further parameters. -@cindex required parameter (defn) -@cindex parameter, required (defn) -@findex condition-type:wrong-number-of-arguments - -@item Optional -Once the required parameters have all been matched, the @dfn{optional} -parameters are matched against the remaining arguments. If there are -fewer arguments than optional parameters, the unmatched parameters are -bound to special objects called @dfn{default objects}. If there are -more arguments than optional parameters, and there are no further -parameters, an error of type -@code{condition-type:wrong-number-of-arguments} is signalled. -@cindex optional parameter (defn) -@cindex parameter, optional (defn) -@cindex default object (defn) -@findex condition-type:wrong-number-of-arguments - -@findex default-object? -The predicate @code{default-object?}, which is true only of default -objects, can be used to determine which optional parameters were -supplied, and which were defaulted. - -@item Rest -Finally, if there is a @dfn{rest} parameter (there can only be one), any -remaining arguments are made into a list, and the list is bound to the -rest parameter. (If there are no remaining arguments, the rest -parameter is bound to the empty list.) -@cindex rest parameter (defn) -@cindex parameter, rest (defn) - -In Scheme, unlike some other Lisp implementations, the list to which a -rest parameter is bound is always freshly allocated. It has infinite -extent and may be modified without affecting the procedure's caller. -@end table - -@findex #!optional -@findex #!rest -Specially recognized keywords divide the @var{formals} parameters into -these three classes. The keywords used here are @samp{#!optional}, -@samp{.}, and @samp{#!rest}. Note that only @samp{.} is defined by -standard Scheme --- the other keywords are MIT/GNU Scheme extensions. -@samp{#!rest} has the same meaning as @samp{.} in @var{formals}. - -The use of these keywords is best explained by means of examples. The -following are typical lambda lists, followed by descriptions of which -parameters are required, optional, and rest. We will use @samp{#!rest} -in these examples, but anywhere it appears @samp{.} could be used -instead. - -@table @code -@item (a b c) -@code{a}, @code{b}, and @code{c} are all required. The procedure must -be passed exactly three arguments. - -@item (a b #!optional c) -@code{a} and @code{b} are required, @code{c} is optional. The procedure -may be passed either two or three arguments. - -@item (#!optional a b c) -@code{a}, @code{b}, and @code{c} are all optional. The procedure may be -passed any number of arguments between zero and three, inclusive. - -@item a -@itemx (#!rest a) -These two examples are equivalent. @code{a} is a rest parameter. The -procedure may be passed any number of arguments. Note: this is the only -case in which @samp{.} cannot be used in place of @samp{#!rest}. - -@item (a b #!optional c d #!rest e) -@code{a} and @code{b} are required, @code{c} and @code{d} are optional, -and @code{e} is rest. The procedure may be passed two or more -arguments. -@end table - -Some examples of @code{lambda} expressions: - -@example -@group -(lambda (x) (+ x x)) @result{} #[compound-procedure 53] - -((lambda (x) (+ x x)) 4) @result{} 8 - -(define reverse-subtract - (lambda (x y) - (- y x))) -(reverse-subtract 7 10) @result{} 3 - -(define foo - (let ((x 4)) - (lambda (y) (+ x y)))) -(foo 6) @result{} 10 -@end group -@end example -@end deffn - -@deffn {special form} named-lambda formals expression expression @dots{} -@cindex named lambda (defn) -The @code{named-lambda} special form is similar to @code{lambda}, except -that the first ``required parameter'' in @var{formals} is not a -parameter but the @dfn{name} of the resulting procedure; thus -@var{formals} must have at least one required parameter. This name has -no semantic meaning, but is included in the external representation of -the procedure, making it useful for debugging. In MIT/GNU Scheme, -@code{lambda} is implemented as @code{named-lambda}, with a special name -that means ``unnamed''. - -@example -@group -(named-lambda (f x) (+ x x)) @result{} #[compound-procedure 53 f] -((named-lambda (f x) (+ x x)) 4) @result{} 8 -@end group -@end example -@end deffn - -@node Lexical Binding, Dynamic Binding, Lambda Expressions, Special Forms -@section Lexical Binding - -@cindex lexical binding expression -@cindex binding expression, lexical -@cindex block structure -The three binding constructs @code{let}, @code{let*}, and @code{letrec}, -give Scheme block structure. The syntax of the three constructs is -identical, but they differ in the regions they establish for their -variable bindings. In a @code{let} expression, the initial values are -computed before any of the variables become bound. In a @code{let*} -expression, the evaluations and bindings are sequentially interleaved. -And in a @code{letrec} expression, all the bindings are in effect while -the initial values are being computed (thus allowing mutually recursive -definitions). - -@deffn {special form} let ((@var{variable} @var{init}) @dots{}) expression expression @dots{} -@cindex region of variable binding, let -@cindex variable binding, let -The @var{init}s are evaluated in the current environment (in some -unspecified order), the @var{variable}s are bound to fresh locations -holding the results, the @var{expression}s are evaluated sequentially in -the extended environment, and the value of the last @var{expression} is -returned. Each binding of a @var{variable} has the @var{expression}s as -its region. - -MIT/GNU Scheme allows any of the @var{init}s to be omitted, in which -case the corresponding @var{variable}s are unassigned. - -@cindex lambda, implicit in let -Note that the following are equivalent: - -@example -@group -(let ((@var{variable} @var{init}) @dots{}) @var{expression} @var{expression} @dots{}) -((lambda (@var{variable} @dots{}) @var{expression} @var{expression} @dots{}) @var{init} @dots{}) -@end group -@end example - -Some examples: - -@example -@group -(let ((x 2) (y 3)) - (* x y)) @result{} 6 -@end group - -@group -(let ((x 2) (y 3)) - (let ((foo (lambda (z) (+ x y z))) - (x 7)) - (foo 4))) @result{} 9 -@end group -@end example - -@xref{Iteration}, for information on ``named @code{let}''. -@end deffn - -@deffn {special form} let* ((@var{variable} @var{init}) @dots{}) expression expression @dots{} -@cindex region of variable binding, let* -@cindex variable binding, let* -@code{let*} is similar to @code{let}, but the bindings are performed -sequentially from left to right, and the region of a binding is that -part of the @code{let*} expression to the right of the binding. Thus -the second binding is done in an environment in which the first binding -is visible, and so on. - -Note that the following are equivalent: - -@example -@group -(let* ((@var{variable1} @var{init1}) - (@var{variable2} @var{init2}) - @dots{} - (@var{variableN} @var{initN})) - @var{expression} - @var{expression} @dots{}) -@end group - -@group -(let ((@var{variable1} @var{init1})) - (let ((@var{variable2} @var{init2})) - @dots{} - (let ((@var{variableN} @var{initN})) - @var{expression} - @var{expression} @dots{}) - @dots{})) -@end group -@end example - -An example: - -@example -@group -(let ((x 2) (y 3)) - (let* ((x 7) - (z (+ x y))) - (* z x))) @result{} 70 -@end group -@end example -@end deffn - -@deffn {special form} letrec ((@var{variable} @var{init}) @dots{}) expression expression @dots{} -@cindex region of variable binding, letrec -@cindex variable binding, letrec -The @var{variable}s are bound to fresh locations holding unassigned -values, the @var{init}s are evaluated in the extended environment (in -some unspecified order), each @var{variable} is assigned to the result -of the corresponding @var{init}, the @var{expression}s are evaluated -sequentially in the extended environment, and the value of the last -@var{expression} is returned. Each binding of a @var{variable} has the -entire @code{letrec} expression as its region, making it possible to -define mutually recursive procedures. - -MIT/GNU Scheme allows any of the @var{init}s to be omitted, in which -case the corresponding @var{variable}s are unassigned. - -@example -@group -(letrec ((even? - (lambda (n) - (if (zero? n) - #t - (odd? (- n 1))))) - (odd? - (lambda (n) - (if (zero? n) - #f - (even? (- n 1)))))) - (even? 88)) @result{} #t -@end group -@end example - -@findex lambda -@findex delay -One restriction on @code{letrec} is very important: it shall be possible -to evaluated each @var{init} without assigning or referring to the value -of any @var{variable}. If this restriction is violated, then it is an -error. The restriction is necessary because Scheme passes arguments by -value rather than by name. In the most common uses of @code{letrec}, -all the @var{init}s are @code{lambda} or @code{delay} expressions and -the restriction is satisfied automatically. -@end deffn - -@node Dynamic Binding, Definitions, Lexical Binding, Special Forms -@section Dynamic Binding - -@deffn {special form} fluid-let ((@var{variable} @var{init}) @dots{}) expression expression @dots{} -@cindex binding expression, dynamic (or fluid) -@cindex fluid binding -@cindex dynamic binding -@cindex variable binding, fluid-let -The @var{init}s are evaluated in the current environment (in some -unspecified order), the current values of the @var{variable}s are saved, -the results are assigned to the @var{variable}s, the @var{expression}s -are evaluated sequentially in the current environment, the -@var{variable}s are restored to their original values, and the value of -the last @var{expression} is returned. - -@findex let -The syntax of this special form is similar to that of @code{let}, but -@code{fluid-let} temporarily rebinds existing variables. Unlike -@code{let}, @code{fluid-let} creates no new bindings; instead it -@emph{assigns} the value of each @var{init} to the binding (determined -by the rules of lexical scoping) of its corresponding @var{variable}. - -@cindex unassigned variable, and dynamic bindings -MIT/GNU Scheme allows any of the @var{init}s to be omitted, in which -case the corresponding @var{variable}s are temporarily unassigned. - -An error of type @code{condition-type:unbound-variable} is signalled if -any of the @var{variable}s are unbound. However, because -@code{fluid-let} operates by means of side effects, it is valid for any -@var{variable} to be unassigned when the form is entered. -@findex condition-type:unbound-variable - -Here is an example showing the difference between @code{fluid-let} and -@code{let}. First see how @code{let} affects the binding of a variable: - -@example -@group -(define variable #t) -(define (access-variable) variable) -variable @result{} #t -(let ((variable #f)) - (access-variable)) @result{} #t -variable @result{} #t -@end group -@end example - -@code{access-variable} returns @code{#t} in this case because it -is defined in an environment with @code{variable} bound to -@code{#t}. @code{fluid-let}, on the other hand, temporarily reuses an -existing variable: - -@example -@group -variable @result{} #t -(fluid-let ((variable #f)) @r{;reuses old binding} - (access-variable)) @result{} #f -variable @result{} #t -@end group -@end example - -@cindex extent, of dynamic binding (defn) -The @dfn{extent} of a dynamic binding is defined to be the time period -during which the variable contains the new value. Normally this time -period begins when the body is entered and ends when it is exited; on a -sequential machine it is normally a contiguous time period. However, -because Scheme has first-class continuations, it is possible to leave -the body and then reenter it, as many times as desired. In this -situation, the extent becomes non-contiguous. - -@cindex dynamic binding, and continuations -@cindex continuation, and dynamic binding -When the body is exited by invoking a continuation, the new value is -saved, and the variable is set to the old value. Then, if the body is -reentered by invoking a continuation, the old value is saved, and the -variable is set to the new value. In addition, side effects to the -variable that occur both inside and outside of body are preserved, even -if continuations are used to jump in and out of body repeatedly. -@end deffn - -Here is a complicated example that shows the interaction between dynamic -binding and continuations: - -@example -@group -(define (complicated-dynamic-binding) - (let ((variable 1) - (inside-continuation)) - (write-line variable) - (call-with-current-continuation - (lambda (outside-continuation) - (fluid-let ((variable 2)) - (write-line variable) - (set! variable 3) - (call-with-current-continuation - (lambda (k) - (set! inside-continuation k) - (outside-continuation #t))) - (write-line variable) - (set! inside-continuation #f)))) - (write-line variable) - (if inside-continuation - (begin - (set! variable 4) - (inside-continuation #f))))) -@end group -@end example - -@noindent -Evaluating @samp{(complicated-dynamic-binding)} writes the following on -the console: - -@example -@group -1 -2 -1 -3 -4 -@end group -@end example - -@noindent -Commentary: the first two values written are the initial binding of -@code{variable} and its new binding after the @code{fluid-let}'s body is -entered. Immediately after they are written, @code{variable} is set to -@samp{3}, and then @code{outside-continuation} is invoked, causing us to -exit the body. At this point, @samp{1} is written, demonstrating that -the original value of @code{variable} has been restored, because we have -left the body. Then we set @code{variable} to @samp{4} and reenter the -body by invoking @code{inside-continuation}. At this point, @samp{3} is -written, indicating that the side effect that previously occurred within -the body has been preserved. Finally, we exit body normally, and write -@samp{4}, demonstrating that the side effect that occurred outside of -the body was also preserved. - -@node Definitions, Assignments, Dynamic Binding, Special Forms -@section Definitions -@cindex definition - -@deffn {special form} define variable [expression] -@deffnx {special form} define @var{formals} expression expression @dots{} -@cindex variable, adding to environment -@cindex definition, top-level (defn) -@cindex definition, internal (defn) -@cindex top-level definition (defn) -@cindex internal definition (defn) -@findex lambda -@findex let -@findex let* -@findex letrec -@findex fluid-let -Definitions are valid in some but not all contexts where expressions are -allowed. Definitions may only occur at the top level of a program and -at the beginning of a lambda body (that is, the body of a @code{lambda}, -@code{let}, @code{let*}, @code{letrec}, @code{fluid-let}, or ``procedure -@code{define}'' expression). A definition that occurs at the top level -of a program is called a @dfn{top-level definition}, and a definition -that occurs at the beginning of a body is called an @dfn{internal -definition}. - -@cindex lambda, implicit in define -@cindex procedure define (defn) -@cindex define, procedure (defn) -@findex named-lambda -In the second form of @code{define} (called ``@dfn{procedure -@code{define}}''), the component @var{formals} is identical to the -component of the same name in a @code{named-lambda} expression. In -fact, these two expressions are equivalent: - -@example -@group -(define (@var{name1} @var{name2} @dots{}) - @var{expression} - @var{expression} @dots{}) -@end group - -@group -(define @var{name1} - (named-lambda (@var{name1} @var{name2} @dots{}) - @var{expression} - @var{expression} @dots{})) -@end group -@end example -@end deffn - -@menu -* Top-Level Definitions:: -* Internal Definitions:: -@end menu - -@node Top-Level Definitions, Internal Definitions, Definitions, Definitions -@subsection Top-Level Definitions -@cindex top-level definition -@cindex definition, top-level - -@cindex variable binding, top-level definition -A top-level definition, - -@example -(define @var{variable} @var{expression}) -@end example - -@noindent -has essentially the same effect as this assignment expression, if -@var{variable} is bound: - -@example -(set! @var{variable} @var{expression}) -@end example - -@cindex unassigned variable, and definition -@findex set! -If @var{variable} is not bound, however, @code{define} binds -@var{variable} to a new location in the current environment before -performing the assignment (it is an error to perform a @code{set!} on an -unbound variable). If you omit @var{expression}, the variable becomes -unassigned; an attempt to reference such a variable is an error. - -@example -@group -(define add3 - (lambda (x) (+ x 3))) @result{} @r{unspecified} -(add3 3) @result{} 6 - -(define first car) @result{} @r{unspecified} -(first '(1 2)) @result{} 1 - -(define bar) @result{} @r{unspecified} -bar @error{} Unassigned variable -@end group -@end example - -@node Internal Definitions, , Top-Level Definitions, Definitions -@subsection Internal Definitions - -@cindex internal definition -@cindex definition, internal -@cindex region of variable binding, internal definition -@cindex variable binding, internal definition -@findex lambda -@findex let -@findex let* -@findex letrec -@findex fluid-let -@findex define -An @dfn{internal definition} is a definition that occurs at the -beginning of a @var{body} (that is, the body of a @code{lambda}, -@code{let}, @code{let*}, @code{letrec}, @code{fluid-let}, or ``procedure -@code{define}'' expression), rather than at the top level of a program. -The variable defined by an internal definition is local to the -@var{body}. That is, @var{variable} is bound rather than assigned, and -the region of the binding is the entire @var{body}. For example, - -@example -@group -(let ((x 5)) - (define foo (lambda (y) (bar x y))) - (define bar (lambda (a b) (+ (* a b) a))) - (foo (+ x 3))) @result{} 45 -@end group -@end example - -@findex letrec -A @var{body} containing internal definitions can always be converted -into a completely equivalent @code{letrec} expression. For example, the -@code{let} expression in the above example is equivalent to - -@cindex letrec, implicit in define -@example -@group -(let ((x 5)) - (letrec ((foo (lambda (y) (bar x y))) - (bar (lambda (a b) (+ (* a b) a)))) - (foo (+ x 3)))) -@end group -@end example - -@need 1000 -@node Assignments, Quoting, Definitions, Special Forms -@section Assignments -@cindex assignment - -@deffn {special form} set! variable [expression] -@cindex variable, assigning values to -@cindex unassigned variable, and assignment -If @var{expression} is specified, evaluates @var{expression} and stores -the resulting value in the location to which @var{variable} is bound. -If @var{expression} is omitted, @var{variable} is altered to be -unassigned; a subsequent reference to such a @var{variable} is an error. -In either case, the value of the @code{set!} expression is unspecified. - -@var{Variable} must be bound either in some region enclosing the -@code{set!} expression, or at the top level. However, @var{variable} is -permitted to be unassigned when the @code{set!} form is entered. - -@example -@group -(define x 2) @result{} @r{unspecified} -(+ x 1) @result{} 3 -(set! x 4) @result{} @r{unspecified} -(+ x 1) @result{} 5 -@end group -@end example - -@cindex access, used with set! -@findex access -@var{Variable} may be an @code{access} expression -(@pxref{Environments}). This allows you to assign variables in an -arbitrary environment. For example, - -@example -@group -(define x (let ((y 0)) (the-environment))) -(define y 'a) -y @result{} a -(access y x) @result{} 0 -(set! (access y x) 1) @result{} @r{unspecified} -y @result{} a -(access y x) @result{} 1 -@end group -@end example -@end deffn - -@node Quoting, Conditionals, Assignments, Special Forms -@section Quoting -@cindex quoting - -This section describes the expressions that are used to modify or -prevent the evaluation of objects. - -@deffn {special form} quote datum -@cindex external representation, and quote -@cindex literal, and quote -@cindex constant, and quote -@code{(quote @var{datum})} evaluates to @var{datum}. @var{Datum} may be -any external representation of a Scheme object -(@pxref{External Representations}). -Use @code{quote} to include literal constants in -Scheme code. - -@example -@group -(quote a) @result{} a -(quote #(a b c)) @result{} #(a b c) -(quote (+ 1 2)) @result{} (+ 1 2) -@end group -@end example - -@cindex ' as external representation -@cindex apostrophe, as external representation -@cindex quote, as external representation -@findex ' -@code{(quote @var{datum})} may be abbreviated as @code{'@var{datum}}. -The two notations are equivalent in all respects. - -@example -@group -'a @result{} a -'#(a b c) @result{} #(a b c) -'(+ 1 2) @result{} (+ 1 2) -'(quote a) @result{} (quote a) -''a @result{} (quote a) -@end group -@end example - -Numeric constants, string constants, character constants, and boolean -constants evaluate to themselves, so they don't need to be quoted. - -@example -@group -'"abc" @result{} "abc" -"abc" @result{} "abc" -'145932 @result{} 145932 -145932 @result{} 145932 -'#t @result{} #t -#t @result{} #t -'#\a @result{} #\a -#\a @result{} #\a -@end group -@end example -@end deffn - -@deffn {special form} quasiquote template -@cindex external representation, and quasiquote -@cindex literal, and quasiquote -@cindex constant, and quasiquote -@findex equal? -``Backquote'' or ``quasiquote'' expressions are useful for constructing -a list or vector structure when most but not all of the desired -structure is known in advance. If no commas appear within the -@var{template}, the result of evaluating @code{`@var{template}} is -equivalent (in the sense of @code{equal?}) to the result of evaluating -@code{'@var{template}}. If a comma appears within the @var{template}, -however, the expression following the comma is evaluated (``unquoted'') -and its result is inserted into the structure instead of the comma and -the expression. If a comma appears followed immediately by an at-sign -(@@), then the following expression shall evaluate to a list; the -opening and closing parentheses of the list are then ``stripped away'' -and the elements of the list are inserted in place of the comma at-sign -expression sequence. - -@example -@group -`(list ,(+ 1 2) 4) @result{} (list 3 4) - -(let ((name 'a)) `(list ,name ',name)) @result{} (list a 'a) - -`(a ,(+ 1 2) ,@@(map abs '(4 -5 6)) b) @result{} (a 3 4 5 6 b) - -`((foo ,(- 10 3)) ,@@(cdr '(c)) . ,(car '(cons))) - @result{} ((foo 7) . cons) - -`#(10 5 ,(sqrt 4) ,@@(map sqrt '(16 9)) 8) - @result{} #(10 5 2 4 3 8) - -`,(+ 2 3) @result{} 5 -@end group -@end example - -@cindex nesting, of quasiquote expressions -Quasiquote forms may be nested. Substitutions are made only for -unquoted components appearing at the same nesting level as the outermost -backquote. The nesting level increases by one inside each successive -quasiquotation, and decreases by one inside each unquotation. - -@example -@group -`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f) - @result{} (a `(b ,(+ 1 2) ,(foo 4 d) e) f) - -(let ((name1 'x) - (name2 'y)) - `(a `(b ,,name1 ,',name2 d) e)) - @result{} (a `(b ,x ,'y d) e) -@end group -@end example - -@cindex backquote, as external representation -@cindex ` as external representation -@cindex comma, as external representation -@cindex , as external representation -@cindex ,@@ as external representation -@findex unquote -@findex unquote-splicing -@findex ` -@findex , -@findex ,@@ -The notations @code{`@var{template}} and (@code{quasiquote -@var{template}}) are identical in all respects. -@code{,@var{expression}} is identical to @code{(unquote -@var{expression})} and @code{,@@@var{expression}} is identical to -@code{(unquote-splicing @var{expression})}. - -@example -@group -(quasiquote (list (unquote (+ 1 2)) 4)) - @result{} (list 3 4) - -'(quasiquote (list (unquote (+ 1 2)) 4)) - @result{} `(list ,(+ 1 2) 4) - @emph{i.e.,} (quasiquote (list (unquote (+ 1 2)) 4)) -@end group -@end example - -Unpredictable behavior can result if any of the symbols -@code{quasiquote}, @code{unquote}, or @code{unquote-splicing} appear in -a @var{template} in ways otherwise than as described above. -@end deffn - -@node Conditionals, Sequencing, Quoting, Special Forms -@section Conditionals - -@cindex expression, conditional (defn) -@cindex conditional expression (defn) -@cindex true, in conditional expression (defn) -@cindex false, in conditional expression (defn) -@findex #f -@findex #t -The behavior of the @dfn{conditional expressions} is determined by -whether objects are true or false. The conditional expressions count -only @code{#f} as false. They count everything else, including -@code{#t}, pairs, symbols, numbers, strings, vectors, and procedures as -true (but @pxref{True and False}). - -In the descriptions that follow, we say that an object has ``a true -value'' or ``is true'' when the conditional expressions treat it as -true, and we say that an object has ``a false value'' or ``is false'' -when the conditional expressions treat it as false. - -@deffn {special form} if predicate consequent [alternative] -@var{Predicate}, @var{consequent}, and @var{alternative} are -expressions. An @code{if} expression is evaluated as follows: first, -@var{predicate} is evaluated. If it yields a true value, then -@var{consequent} is evaluated and its value is returned. Otherwise -@var{alternative} is evaluated and its value is returned. If -@var{predicate} yields a false value and no @var{alternative} is -specified, then the result of the expression is unspecified. - -An @code{if} expression evaluates either @var{consequent} or -@var{alternative}, never both. Programs should not depend on the value -of an @code{if} expression that has no @var{alternative}. - -@example -@group -(if (> 3 2) 'yes 'no) @result{} yes -(if (> 2 3) 'yes 'no) @result{} no -(if (> 3 2) - (- 3 2) - (+ 3 2)) @result{} 1 -@end group -@end example -@end deffn - -@deffn {special form} cond clause clause @dots{} -@cindex cond clause -@cindex clause, of cond expression -Each @var{clause} has this form: - -@example -(@var{predicate} @var{expression} @dots{}) -@end example - -@noindent -@cindex else clause, of cond expression (defn) -@findex else -where @var{predicate} is any expression. The last @var{clause} may be -an @dfn{@code{else} clause}, which has the form: - -@example -(else @var{expression} @var{expression} @dots{}) -@end example - -A @code{cond} expression does the following: - -@enumerate -@item -Evaluates the @var{predicate} expressions of successive @var{clause}s in -order, until one of the @var{predicate}s evaluates to a true -value. - -@item -When a @var{predicate} evaluates to a true value, @code{cond} evaluates -the @var{expression}s in the associated @var{clause} in left to right -order, and returns the result of evaluating the last @var{expression} in -the @var{clause} as the result of the entire @code{cond} expression. - -If the selected @var{clause} contains only the @var{predicate} and no -@var{expression}s, @code{cond} returns the value of the @var{predicate} -as the result. - -@item -If all @var{predicate}s evaluate to false values, and there is no -@code{else} clause, the result of the conditional expression is -unspecified; if there is an @code{else} clause, @code{cond} evaluates -its @var{expression}s (left to right) and returns the value of the last -one. -@end enumerate - -@example -@group -(cond ((> 3 2) 'greater) - ((< 3 2) 'less)) @result{} greater - -(cond ((> 3 3) 'greater) - ((< 3 3) 'less) - (else 'equal)) @result{} equal -@end group -@end example - -Normally, programs should not depend on the value of a @code{cond} -expression that has no @code{else} clause. However, some Scheme -programmers prefer to write @code{cond} expressions in which at least -one of the @var{predicate}s is always true. In this style, the final -@var{clause} is equivalent to an @code{else} clause. - -@cindex => in cond clause -@findex => -Scheme supports an alternative @var{clause} syntax: - -@example -(@var{predicate} => @var{recipient}) -@end example - -@noindent -where @var{recipient} is an expression. If @var{predicate} evaluates to -a true value, then @var{recipient} is evaluated. Its value must be a -procedure of one argument; this procedure is then invoked on the value -of the @var{predicate}. - -@example -@group -(cond ((assv 'b '((a 1) (b 2))) => cadr) - (else #f)) @result{} 2 -@end group -@end example -@end deffn - -@deffn {special form} case key clause clause @dots{} -@cindex case clause -@cindex clause, of case expression -@var{Key} may be any expression. Each @var{clause} has this -form: - -@example -((@var{object} @dots{}) @var{expression} @var{expression} @dots{}) -@end example - -@cindex else clause, of case expression (defn) -@findex else -No @var{object} is evaluated, and all the @var{object}s must be -distinct. The last @var{clause} may be an @dfn{@code{else} clause}, -which has the form: - -@example -(else @var{expression} @var{expression} @dots{}) -@end example - -A @code{case} expression does the following: - -@enumerate -@item -Evaluates @var{key} and compares the result with each -@var{object}. - -@item -If the result of evaluating @var{key} is equivalent (in the sense of -@code{eqv?}; @pxref{Equivalence Predicates}) to an @var{object}, -@code{case} evaluates the @var{expression}s in the corresponding -@var{clause} from left to right and returns the result of evaluating the -last @var{expression} in the @var{clause} as the result of the -@code{case} expression. -@findex eqv? - -@item -If the result of evaluating @var{key} is different from every -@var{object}, and if there's an @code{else} clause, @code{case} -evaluates its @var{expression}s and returns the result of the last one -as the result of the @code{case} expression. If there's no @code{else} -clause, @code{case} returns an unspecified result. Programs should not -depend on the value of a @code{case} expression that has no @code{else} -clause. -@end enumerate - -For example, - -@example -@group -(case (* 2 3) - ((2 3 5 7) 'prime) - ((1 4 6 8 9) 'composite)) @result{} composite - -(case (car '(c d)) - ((a) 'a) - ((b) 'b)) @result{} @r{unspecified} - -(case (car '(c d)) - ((a e i o u) 'vowel) - ((w y) 'semivowel) - (else 'consonant)) @result{} consonant -@end group -@end example -@end deffn - -@deffn {special form} and expression @dots{} -The @var{expression}s are evaluated from left to right, and the value of -the first @var{expression} that evaluates to a false value is returned. -Any remaining @var{expression}s are not evaluated. If all the -@var{expression}s evaluate to true values, the value of the last -@var{expression} is returned. If there are no @var{expression}s then -@code{#t} is returned. - -@example -@group -(and (= 2 2) (> 2 1)) @result{} #t -(and (= 2 2) (< 2 1)) @result{} #f -(and 1 2 'c '(f g)) @result{} (f g) -(and) @result{} #t -@end group -@end example -@end deffn - -@deffn {special form} or expression @dots{} -The @var{expression}s are evaluated from left to right, and the value of -the first @var{expression} that evaluates to a true value is returned. -Any remaining @var{expression}s are not evaluated. If all -@var{expression}s evaluate to false values, the value of the last -@var{expression} is returned. If there are no @var{expression}s then -@code{#f} is returned. - -@example -@group -(or (= 2 2) (> 2 1)) @result{} #t -(or (= 2 2) (< 2 1)) @result{} #t -(or #f #f #f) @result{} #f -(or (memq 'b '(a b c)) (/ 3 0)) @result{} (b c) -@end group -@end example -@end deffn - -@node Sequencing, Iteration, Conditionals, Special Forms -@section Sequencing -@cindex sequencing expressions - -The @code{begin} special form is used to evaluate expressions in a -particular order. - -@deffn {special form} begin expression expression @dots{} -The @var{expression}s are evaluated sequentially from left to right, and -the value of the last @var{expression} is returned. This expression -type is used to sequence side effects such as input and output. - -@example -@group -(define x 0) -(begin (set! x 5) - (+ x 1)) @result{} 6 - -(begin (display "4 plus 1 equals ") - (display (+ 4 1))) - @print{} 4 plus 1 equals 5 - @result{} @r{unspecified} -@end group -@end example - -@cindex implicit begin -Often the use of @code{begin} is unnecessary, because many special forms -already support sequences of expressions (that is, they have an implicit -@code{begin}). Some of these special forms are: - -@example -@group -case -cond -define @r{;``procedure @code{define}'' only} -do -fluid-let -lambda -let -let* -letrec -named-lambda -@end group -@end example -@findex case -@findex cond -@findex define -@findex do -@findex fluid-let -@findex lambda -@findex let -@findex let* -@findex letrec -@findex named-lambda - -@findex sequence -The obsolete special form @code{sequence} is identical to @code{begin}. -It should not be used in new code. -@end deffn - -@node Iteration, Structure Definitions, Sequencing, Special Forms -@section Iteration - -@cindex expression, iteration (defn) -@cindex iteration expression (defn) -@cindex looping (see iteration expressions) -@cindex tail recursion, vs. iteration expression -The @dfn{iteration expressions} are: ``named @code{let}'' and @code{do}. -They are also binding expressions, but are more commonly referred to as -iteration expressions. Because Scheme is properly tail-recursive, you -don't need to use these special forms to express iteration; you can -simply use appropriately written ``recursive'' procedure calls. - -@deffn {special form} let name ((@var{variable} @var{init}) @dots{}) expression expression @dots{} -@cindex named let (defn) -MIT/GNU Scheme permits a variant on the syntax of @code{let} called -``named @code{let}'' which provides a more general looping construct -than @code{do}, and may also be used to express recursions. - -Named @code{let} has the same syntax and semantics as ordinary -@code{let} except that @var{name} is bound within the @var{expression}s -to a procedure whose formal arguments are the @var{variable}s and whose -body is the @var{expression}s. Thus the execution of the -@var{expression}s may be repeated by invoking the procedure named by -@var{name}. - -@cindex unassigned variable, and named let -MIT/GNU Scheme allows any of the @var{init}s to be omitted, in which -case the corresponding @var{variable}s are unassigned. - -Note: the following expressions are equivalent: - -@example -@group -(let @var{name} ((@var{variable} @var{init}) @dots{}) - @var{expression} - @var{expression} @dots{}) - -((letrec ((@var{name} - (named-lambda (@var{name} @var{variable} @dots{}) - @var{expression} - @var{expression} @dots{}))) - @var{name}) - @var{init} @dots{}) -@end group -@end example - -Here is an example: - -@example -@group -(let loop - ((numbers '(3 -2 1 6 -5)) - (nonneg '()) - (neg '())) - (cond ((null? numbers) - (list nonneg neg)) - ((>= (car numbers) 0) - (loop (cdr numbers) - (cons (car numbers) nonneg) - neg)) - (else - (loop (cdr numbers) - nonneg - (cons (car numbers) neg))))) - - @result{} ((6 1 3) (-5 -2)) -@end group -@end example -@end deffn - -@deffn {special form} do ((@var{variable} @var{init} @var{step}) @dots{}) (@var{test} @var{expression} @dots{}) command @dots{} -@code{do} is an iteration construct. It specifies a set of variables to -be bound, how they are to be initialized at the start, and how they are -to be updated on each iteration. When a termination condition is met, -the loop exits with a specified result value. - -@code{do} expressions are evaluated as follows: The @var{init} -expressions are evaluated (in some unspecified order), the -@var{variable}s are bound to fresh locations, the results of the -@var{init} expressions are stored in the bindings of the -@var{variable}s, and then the iteration phase begins. - -Each iteration begins by evaluating @var{test}; if the result is false, -then the @var{command} expressions are evaluated in order for effect, -the @var{step} expressions are evaluated in some unspecified order, the -@var{variable}s are bound to fresh locations, the results of the -@var{step}s are stored in the bindings of the @var{variable}s, and the -next iteration begins. - -If @var{test} evaluates to a true value, then the @var{expression}s are -evaluated from left to right and the value of the last @var{expression} -is returned as the value of the @code{do} expression. If no -@var{expression}s are present, then the value of the @code{do} -expression is unspecified in standard Scheme; in MIT/GNU Scheme, the -value of @var{test} is returned. - -@cindex region of variable binding, do -@cindex variable binding, do -The region of the binding of a @var{variable} consists of the entire -@code{do} expression except for the @var{init}s. It is an error for a -@var{variable} to appear more than once in the list of @code{do} -variables. - -A @var{step} may be omitted, in which case the effect is the same as if -@code{(@var{variable} @var{init} @var{variable})} had been written -instead of @code{(@var{variable} @var{init})}. - -@example -@group -(do ((vec (make-vector 5)) - (i 0 (+ i 1))) - ((= i 5) vec) - (vector-set! vec i i)) @result{} #(0 1 2 3 4) -@end group - -@group -(let ((x '(1 3 5 7 9))) - (do ((x x (cdr x)) - (sum 0 (+ sum (car x)))) - ((null? x) sum))) @result{} 25 -@end group -@end example -@end deffn - -@node Structure Definitions, Macros, Iteration, Special Forms -@section Structure Definitions - -This section provides examples and describes the options and syntax of -@code{define-structure}, an MIT/GNU Scheme macro that is very similar to -@code{defstruct} in Common Lisp. The differences between them are -summarized at the end of this section. For more information, see -Steele's Common Lisp book. - -@deffn {special form} define-structure (name structure-option @dots{}) slot-description @dots{} -Each @var{slot-description} takes one of the following forms: - -@example -@group -@var{slot-name} -(@var{slot-name} @var{default-init} [@var{slot-option} @var{value}]*) -@end group -@end example - -@cindex keyword constructor -@cindex BOA constructor -The fields @var{name} and @var{slot-name} must both be symbols. The -field @var{default-init} is an expression for the initial value of the -slot. It is evaluated each time a new instance is constructed. If it -is not specified, the initial content of the slot is undefined. Default -values are only useful with a @sc{boa} constructor with argument list or -a keyword constructor (see below). - -Evaluation of a @code{define-structure} expression defines a structure -descriptor and a set of procedures to manipulate instances of the -structure. These instances are represented as records by default -(@pxref{Records}) but may alternately be lists or vectors. The -accessors and modifiers are marked with compiler declarations so that -calls to them are automatically transformed into appropriate references. -Often, no options are required, so a simple call to -@code{define-structure} looks like: - -@example -(define-structure foo a b c) -@end example - -This defines a type descriptor @code{foo}, a constructor -@code{make-foo}, a predicate @code{foo?}, accessors @code{foo-a}, -@code{foo-b}, and @code{foo-c}, and modifiers @code{set-foo-a!}, -@code{set-foo-b!}, and @code{set-foo-c!}. - -In general, if no options are specified, @code{define-structure} defines -the following (using the simple call above as an example): - -@table @asis -@item type descriptor -The name of the type descriptor is the same as the name of the -structure, e.g.@: @samp{foo}. The type descriptor satisfies the -predicate @code{record-type?}. - -@item constructor -The name of the constructor is @code{"make-"} followed by the name of -the structure, e.g.@: @samp{make-foo}. The number of arguments accepted -by the constructor is the same as the number of slots; the arguments are -the initial values for the slots, and the order of the arguments matches -the order of the slot definitions. - -@item predicate -The name of the predicate is the name of the structure followed by -@code{"?"}, e.g.@: @samp{foo?}. The predicate is a procedure of one -argument, which returns @code{#t} if its argument is a record of the -type defined by this structure definition, and @code{#f} otherwise. - -@item accessors -For each slot, an accessor is defined. The name of the accessor is -formed by appending the name of the structure, a hyphen, and the name of -the slot, e.g.@: @samp{foo-a}. The accessor is a procedure of one -argument, which must be a record of the type defined by this structure -definition. The accessor extracts the contents of the corresponding -slot in that record and returns it. - -@item modifiers -For each slot, a modifier is defined. The name of the modifier is -formed by appending @code{"set-"}, the name of the accessor, and -@code{"!"}, e.g.@: @samp{set-foo-a!}. The modifier is a procedure of -two arguments, the first of which must be a record of the type defined -by this structure definition, and the second of which may be any object. -The modifier modifies the contents of the corresponding slot in that -record to be that object, and returns an unspecified value. -@end table - -When options are not supplied, @code{(@var{name})} may be abbreviated to -@var{name}. This convention holds equally for @var{structure-options} -and @var{slot-options}. Hence, these are equivalent: - -@example -@group -(define-structure foo a b c) -(define-structure (foo) (a) b (c)) -@end group -@end example - -@noindent -as are - -@example -@group -(define-structure (foo keyword-constructor) a b c) -(define-structure (foo (keyword-constructor)) a b c) -@end group -@end example - -When specified as option values, @code{false} and @code{nil} are -equivalent to @code{#f}, and @code{true} and @code{t} are equivalent to -@code{#t}. -@end deffn - -Possible @var{slot-options} are: - -@deffn {slot option} read-only value -When given a @var{value} other than @code{#f}, this specifies that no -modifier should be created for the slot. -@end deffn - -@deffn {slot option} type type-descriptor -This is accepted but not presently used. -@end deffn - -Possible @var{structure-options} are: - -@deffn {structure option} predicate [name] -This option controls the definition of a predicate procedure for the -structure. If @var{name} is not given, the predicate is defined with -the default name (see above). If @var{name} is @code{#f}, the predicate -is not defined at all. Otherwise, @var{name} must be a symbol, and -the predicate is defined with that symbol as its name. -@end deffn - -@deffn {structure option} copier [name] -This option controls the definition of a procedure to copy instances of -the structure. This is a procedure of one argument, a structure -instance, that makes a newly allocated copy of the structure and returns -it. If @var{name} is not given, the copier is defined, and the name -of the copier is @code{"copy-"} followed by the structure name (e.g.@: -@samp{copy-foo}). If @var{name} is @code{#f}, the copier is not -defined. Otherwise, @var{name} must be a symbol, and the copier is -defined with that symbol as its name. -@end deffn - -@deffn {structure option} print-procedure expression -Evaluating @var{expression} must yield a procedure of two arguments, -which is used to print instances of the structure. The procedure is an -@dfn{unparser method} (@pxref{Custom Output}). If the structure -instances are records, this option has the same effect as calling -@code{set-record-type-unparser-method!}. -@findex set-record-type-unparser-method! -@end deffn - -@deffn {structure option} constructor [name [argument-list]] -@cindex BOA constructor (defn) -This option controls the definition of constructor procedures. These -constructor procedures are called ``@sc{boa} constructors'', for ``By -Order of Arguments'', because the arguments to the constructor specify -the initial contents the structure's slots by the order in which they -are given. This is as opposed to ``keyword constructors'', which -specify the initial contents using keywords, and in which the order of -arguments is irrelevant. - -If @var{name} is not given, a constructor is defined with the default -name and arguments (see above). If @var{name} is @code{#f}, no -constructor is defined; @var{argument-list} may not be specified in this -case. Otherwise, @var{name} must be a symbol, and a constructor is -defined with that symbol as its name. If @var{name} is a symbol, -@var{argument-list} is optionally allowed; if it is omitted, the -constructor accepts one argument for each slot in the structure -definition, in the same order in which the slots appear in the -definition. Otherwise, @var{argument-list} must be a lambda list -(@pxref{Lambda Expressions}), and each of the parameters of the lambda -list must be the name of a slot in the structure. The arguments -accepted by the constructor are defined by this lambda list. Any slot -that is not specified by the lambda list is initialized to the -@var{default-init} as specified above; likewise for any slot specified -as an optional parameter when the corresponding argument is not -supplied. - -If the @code{constructor} option is specified, the default constructor -is not defined. Additionally, the @code{constructor} option may be -specified multiple times to define multiple constructors with -different names and argument lists. - -@example -@group -(define-structure (foo - (constructor make-foo (#!optional a b))) - (a 6 read-only #t) - (b 9)) -@end group -@end example -@end deffn - -@deffn {structure option} keyword-constructor [name] -@cindex keyword constructor (defn) -This option controls the definition of keyword constructor procedures. -A @dfn{keyword constructor} is a procedure that accepts arguments that -are alternating slot names and values. If @var{name} is omitted, a -keyword constructor is defined, and the name of the constructor is -@code{"make-"} followed by the name of the structure (e.g.@: -@samp{make-foo}). Otherwise, @var{name} must be a symbol, and a keyword -constructor is defined with this symbol as its name. - -If the @code{keyword-constructor} option is specified, the default -constructor is not defined. Additionally, the -@code{keyword-constructor} option may be specified multiple times to -define multiple keyword constructors; this is usually not done since -such constructors would all be equivalent. - -@example -@group -(define-structure (foo (keyword-constructor make-bar)) a b) -(foo-a (make-bar 'b 20 'a 19)) @result{} 19 -@end group -@end example -@end deffn - -@deffn {structure option} type-descriptor name -This option cannot be used with the @code{type} or @code{named} options. - -By default, structures are implemented as records. The name of the -structure is defined to hold the type descriptor of the record defined -by the structure. The @code{type-descriptor} option specifies a -different name to hold the type descriptor. - -@example -@group -(define-structure foo a b) -foo @result{} #[record-type 18] - -(define-structure (bar (type-descriptor )) a b) -bar @error{} Unbound variable: bar - @result{} #[record-type 19] -@end group -@end example -@end deffn - -@deffn {structure option} conc-name [name] -By default, the prefix for naming accessors and modifiers is the name of -the structure followed by a hyphen. The @code{conc-name} option can be -used to specify an alternative. If @var{name} is not given, the prefix -is the name of the structure followed by a hyphen (the default). If -@var{name} is @code{#f}, the slot names are used directly, without -prefix. Otherwise, @var{name} must a symbol, and that symbol is used as -the prefix. - -@example -@code{(define-structure (foo (conc-name moby/)) a b)} -@end example - -@noindent -defines accessors @code{moby/a} and @code{moby/b}, and modifiers -@code{set-moby/a!} and @code{set-moby/b!}. - -@example -@code{(define-structure (foo (conc-name #f)) a b)} -@end example - -@noindent -defines accessors @code{a} and @code{b}, and modifiers @code{set-a!} and -@code{set-b!}. -@end deffn - -@deffn {structure option} type representation-type -This option cannot be used with the @code{type-descriptor} option. - -By default, structures are implemented as records. The @code{type} -option overrides this default, allowing the programmer to specify that -the structure be implemented using another data type. The option value -@var{representation-type} specifies the alternate data type; it is -allowed to be one of the symbols @code{vector} or @code{list}, and the -data type used is the one corresponding to the symbol. - -If this option is given, and the @code{named} option is not specified, -the representation will not be tagged, and neither a predicate nor a -type descriptor will be defined; also, the @code{print-procedure} -option may not be given. - -@example -@group -(define-structure (foo (type list)) a b) -(make-foo 1 2) @result{} (1 2) -@end group -@end example -@end deffn - -@deffn {structure option} named [expression] -This is valid only in conjunction with the @code{type} option and -specifies that the structure instances be tagged to make them -identifiable as instances of this structure type. This option cannot be -used with the @code{type-descriptor} option. - -In the usual case, where @var{expression} is not given, the @code{named} -option causes a type descriptor and predicate to be defined for the -structure (recall that the @code{type} option without @code{named} -suppresses their definition), and also defines a default unparser method -for the structure instances (which can be overridden by the -@code{print-procedure} option). If the default unparser method is not -wanted then the @code{print-procedure} option should be specified as -@code{#F}. This causes the structure to be printed in its native -representation, as a list or vector, which includes the type descriptor. -The type descriptor is a unique object, @emph{not} a record type, that -describes the structure instances and is additionally stored in the -structure instances to identify them: if the representation type is -@code{vector}, the type descriptor is stored in the zero-th slot of the -vector, and if the representation type is @code{list}, it is stored as -the first element of the list. - - -@example -@group -(define-structure (foo (type vector) named) a b c) -(vector-ref (make-foo 1 2 3) 0) @result{} #[structure-type 52] -@end group -@end example - -If @var{expression} is specified, it is an expression that is evaluated -to yield a tag object. The @var{expression} is evaluated once when the -structure definition is evaluated (to specify the unparser method), and -again whenever a predicate or constructor is called. Because of this, -@var{expression} is normally a variable reference or a constant. The -value yielded by @var{expression} may be any object at all. That object -is stored in the structure instances in the same place that the type -descriptor is normally stored, as described above. If @var{expression} -is specified, no type descriptor is defined, only a predicate. - -@example -@group -(define-structure (foo (type vector) (named 'foo)) a b c) -(vector-ref (make-foo 1 2 3) 0) @result{} foo -@end group -@end example -@end deffn - -@deffn {structure option} safe-accessors [boolean] -This option allows the programmer to have some control over the safety -of the slot accessors (and modifiers) generated by -@code{define-structure}. If @code{safe-accessors} is not specified, or -if @var{boolean} is @code{#f}, then the accessors are optimized for -speed at the expense of safety; when compiled, the accessors will turn -into very fast inline sequences, usually one to three machine -instructions in length. However, if @code{safe-accessors} is specified -and @var{boolean} is either omitted or @code{#t}, then the accessors are -optimized for safety, will check the type and structure of their -argument, and will be close-coded. - -@example -@group -(define-structure (foo safe-accessors) a b c) -@end group -@end example -@end deffn - -@deffn {structure option} initial-offset offset -This is valid only in conjunction with the @code{type} option. -@var{Offset} must be an exact non-negative integer and specifies the -number of slots to leave open at the beginning of the structure instance -before the specified slots are allocated. Specifying an @var{offset} of -zero is equivalent to omitting the @code{initial-offset} option. - -If the @code{named} option is specified, the structure tag appears in -the first slot, followed by the ``offset'' slots, and then the regular -slots. Otherwise, the ``offset'' slots come first, followed by the -regular slots. - -@example -@group -(define-structure (foo (type vector) (initial-offset 3)) - a b c) -(make-foo 1 2 3) @result{} #(() () () 1 2 3) -@end group -@end example -@end deffn - -The essential differences between MIT/GNU Scheme's @code{define-structure} -and Common Lisp's @code{defstruct} are: - -@itemize @bullet -@item -The default constructor procedure takes positional arguments, in the -same order as specified in the definition of the structure. A keyword -constructor may be specified by giving the option -@code{keyword-constructor}. - -@item -@sc{boa} constructors are described using Scheme lambda lists. Since there -is nothing corresponding to @code{&aux} in Scheme lambda lists, this -functionality is not implemented. - -@item -By default, no @code{copier} procedure is defined. - -@item -The side-effect procedure corresponding to the accessor @code{foo} is -given the name @code{set-foo!}. - -@item -Keywords are ordinary symbols -- use @code{foo} instead of @code{:foo}. - -@item -The option values @code{false}, @code{nil}, @code{true}, and @code{t} -are treated as if the appropriate boolean constant had been specified -instead. - -@item -The @code{print-function} option is named @code{print-procedure}. Its -argument is a procedure of two arguments (the unparser state and the -structure instance) rather than three as in Common Lisp. - -@item -By default, named structures are tagged with a unique object of some -kind. In Common Lisp, the structures are tagged with symbols. This -depends on the Common Lisp package system to help generate unique tags; -MIT/GNU Scheme has no such way to generate unique symbols. - -@item -The @code{named} option may optionally take an argument, which is -normally the name of a variable (any expression may be used, but it is -evaluated whenever the tag name is needed). If used, structure -instances will be tagged with that variable's value. The variable must -be defined when @code{define-structure} is evaluated. - -@item -The @code{type} option is restricted to the values @code{vector} and -@code{list}. - -@item -The @code{include} option is not implemented. -@end itemize - -@node Macros, SRFI syntax, Structure Definitions, Special Forms -@section Macros - -(This section is largely taken from the @cite{Revised^4 Report on the -Algorithmic Language Scheme}. The section on Syntactic Closures is -derived from a document written by Chris Hanson. The section on -Explicit Renaming is derived from a document written by William -Clinger.) - -@cindex macro -Scheme programs can define and use new derived expression types, called -@dfn{macros}. Program-defined expression types have the syntax - -@example -(@var{keyword} @var{datum} @dots{}) -@end example - -@noindent -@cindex syntactic keyword -@cindex keyword -@cindex macro keyword -where @var{keyword} is an identifier that uniquely determines the -expression type. This identifier is called the @dfn{syntactic keyword}, -or simply @dfn{keyword}, of the macro. The number of the @var{datum}s, -and their syntax, depends on the expression type. - -@cindex macro use -@cindex macro transformer -Each instance of a macro is called a @dfn{use} of the macro. The set of -rules that specifies how a use of a macro is transcribed into a more -primitive expression is called the @dfn{transformer} of the macro. - -@cindex anonymous syntactic keyword -MIT/GNU Scheme also supports @dfn{anonymous syntactic keywords}. This means -that it's not necessary to bind a macro transformer to a syntactic -keyword before it is used. Instead, any macro-transformer expression -can appear as the first element of a form, and the form will be expanded -by the transformer. - -The macro definition facility consists of these parts: - -@itemize @bullet -@item -A set of expressions used to establish that certain identifiers are -macro keywords, associate them with macro transformers, and control the -scope within which a macro is defined. - -@item -A standard high-level pattern language for specifying macro -transformers, introduced by the @code{syntax-rules} special form. - -@item -Two non-standard low-level languages for specifying macro transformers, -@dfn{syntactic closures} and @dfn{explicit renaming}. -@end itemize - -@cindex hygienic -@cindex referentially transparent -The syntactic keyword of a macro may shadow variable bindings, and local -variable bindings may shadow keyword bindings. All macros defined using -the pattern language are ``hygienic'' and ``referentially transparent'' -and thus preserve Scheme's lexical scoping: - -@itemize @bullet -@item -If a macro transformer inserts a binding for an identifier (variable or -keyword), the identifier will in effect be renamed throughout its scope -to avoid conflicts with other identifiers. - -@item -If a macro transformer inserts a free reference to an identifier, the -reference refers to the binding that was visible where the transformer -was specified, regardless of any local bindings that may surround the -use of the macro. -@end itemize - -@menu -* Syntactic Binding Constructs:: -* Pattern Language:: -* Syntactic Closures:: -* Explicit Renaming:: -@end menu - -@node Syntactic Binding Constructs, Pattern Language, Macros, Macros -@subsection Binding Constructs for Syntactic Keywords - -@code{let-syntax}, @code{letrec-syntax}, @code{let*-syntax} and -@code{define-syntax} are analogous to @code{let}, @code{letrec}, -@code{let*} and @code{define}, but they bind syntactic keywords to macro -transformers instead of binding variables to locations that contain -values. - -@deffn {special form} let-syntax bindings expression expression @dots{} -@var{Bindings} should have the form - -@example -((@var{keyword} @var{transformer-spec}) @dots{}) -@end example - -@noindent -Each @var{keyword} is an identifier, each @var{transformer-spec} is a -a macro-transformer expression, and the body is a sequence of -one or more expressions. It is an error for a @var{keyword} to appear -more than once in the list of keywords being bound. - -The @var{expression}s are expanded in the syntactic environment obtained -by extending the syntactic environment of the @code{let-syntax} -expression with macros whose keywords are the @var{keyword}s, bound to -the specified transformers. Each binding of a @var{keyword} has the -@var{expression}s as its region. - -@example -@group -(let-syntax ((when (syntax-rules () - ((when test stmt1 stmt2 ...) - (if test - (begin stmt1 - stmt2 ...)))))) - (let ((if #t)) - (when if (set! if 'now)) - if)) @result{} now - -(let ((x 'outer)) - (let-syntax ((m (syntax-rules () ((m) x)))) - (let ((x 'inner)) - (m)))) @result{} outer -@end group -@end example -@end deffn - -@deffn {special form} letrec-syntax bindings expression expression @dots{} -The syntax of @code{letrec-syntax} is the same as for @code{let-syntax}. - -The @var{expression}s are expanded in the syntactic environment obtained -by extending the syntactic environment of the @code{letrec-syntax} -expression with macros whose keywords are the @var{keyword}s, bound to -the specified transformers. Each binding of a @var{keyword} has the -@var{bindings} as well as the @var{expression}s within its region, so -the transformers can transcribe expressions into uses of the macros -introduced by the @code{letrec-syntax} expression. - -@example -@group -(letrec-syntax - ((my-or (syntax-rules () - ((my-or) #f) - ((my-or e) e) - ((my-or e1 e2 ...) - (let ((temp e1)) - (if temp - temp - (my-or e2 ...))))))) - (let ((x #f) - (y 7) - (temp 8) - (let odd?) - (if even?)) - (my-or x - (let temp) - (if y) - y))) @result{} 7 -@end group -@end example -@end deffn - -@deffn {special form} let*-syntax bindings expression expression @dots{} -The syntax of @code{let*-syntax} is the same as for @code{let-syntax}. - -The @var{expression}s are expanded in the syntactic environment obtained -by extending the syntactic environment of the @code{letrec-syntax} -expression with macros whose keywords are the @var{keyword}s, bound to -the specified transformers. Each binding of a @var{keyword} has the -subsequent @var{bindings} as well as the @var{expression}s within its -region. Thus - -@example -@group -(let*-syntax - ((a (syntax-rules @dots{})) - (b (syntax-rules @dots{}))) - @dots{}) -@end group -@end example - -@noindent -is equivalent to - -@example -@group -(let-syntax ((a (syntax-rules @dots{}))) - (let-syntax ((b (syntax-rules @dots{}))) - @dots{})) -@end group -@end example -@end deffn - -@deffn {special form} define-syntax keyword transformer-spec -@var{Keyword} is an identifier, and @var{transformer-spec} is a macro -transformer expression. The syntactic environment is extended by -binding the @var{keyword} to the specified transformer. - -The region of the binding introduced by @code{define-syntax} is the -entire block in which it appears. However, the @var{keyword} may only -be used after it has been defined. - -MIT/GNU Scheme permits @code{define-syntax} to appear both at top level and -within @code{lambda} bodies. The Revised^4 Report permits only -top-level uses of @code{define-syntax}. - -When compiling a program, a top-level instance of @code{define-syntax} -both defines the syntactic keyword and generates code that will redefine -the keyword when the program is loaded. This means that the same syntax -can be used for defining macros that will be used during compilation -and for defining macros to be used at run time. - -Although macros may expand into definitions and syntax definitions in -any context that permits them, it is an error for a definition or syntax -definition to shadow a syntactic keyword whose meaning is needed to -determine whether some form in the group of forms that contains the -shadowing definition is in fact a definition, or, for internal definitions, -is needed to determine the boundary between the group and the expressions -that follow the group. For example, the following are errors: - -@example -(define define 3) - -(begin (define begin list)) - -(let-syntax - ((foo (syntax-rules () - ((foo (proc args ...) body ...) - (define proc - (lambda (args ...) - body ...)))))) - (let ((x 3)) - (foo (plus x y) (+ x y)) - (define foo x) - (plus foo x))) -@end example -@end deffn - -@node Pattern Language, Syntactic Closures, Syntactic Binding Constructs, Macros -@subsection Pattern Language - -MIT/GNU Scheme supports a high-level pattern language for specifying macro -transformers. This pattern language is defined by the Revised^4 Report -and is portable to other conforming Scheme implementations. To use the -pattern language, specify a @var{transformer-spec} as a -@code{syntax-rules} form: - -@deffn {special form} syntax-rules literals syntax-rule @dots{} -@var{Literals} is a list of identifiers and each @var{syntax-rule} -should be of the form - -@example -(@var{pattern} @var{template}) -@end example - -The @var{pattern} in a @var{syntax-rule} is a list @var{pattern} that -begins with the keyword for the macro. - -A @var{pattern} is either an identifier, a constant, or one of the -following - -@example -(@var{pattern} @dots{}) -(@var{pattern} @var{pattern} @dots{} . @var{pattern}) -(@var{pattern} @dots{} @var{pattern} @var{ellipsis}) -@end example - -@noindent -and a template is either an identifier, a constant, or one of the -following - -@example -(@var{element} @dots{}) -(@var{element} @var{element} @dots{} . @var{template}) -@end example - -@vindex ... -where an @var{element} is a @var{template} optionally followed by an -@var{ellipsis} and an @var{ellipsis} is the identifier @samp{...} (which -cannot be used as an identifier in either a template or a pattern). - -An instance of @code{syntax-rules} produces a new macro transformer by -specifying a sequence of hygienic rewrite rules. A use of a macro whose -keyword is associated with a transformer specified by -@code{syntax-rules} is matched against the patterns contained in the -@var{syntax-rule}s, beginning with the leftmost @var{syntax-rule}. When -a match is found, the macro use is transcribed hygienically according to -the template. - -An identifier that appears in the pattern of a @var{syntax-rule} is a -@dfn{pattern-variable}, unless it is the keyword that begins the -pattern, is listed in @var{literals}, or is the identifier @samp{...}. -Pattern variables match arbitrary input elements and are used to refer -to elements of the input in the template. It is an error for the same -pattern variable to appear more than once in a @var{pattern}. - -The keyword at the beginning of the pattern in a @var{syntax-rule} is -not involved in the matching and is not considered a pattern variable or -literal identifier. - -Identifiers that appear in @var{literals} are interpreted as literal -identifiers to be matched against corresponding subforms of the input. -A subform in the input matches a literal identifier if and only if it is -an identifier and either both its occurrence in the macro expression and -its occurrence in the macro definition have the same lexical binding, or -the two identifiers are equal and both have no lexical binding. - -A subpattern followed by @samp{...} can match zero or more elements of -the input. It is an error for @samp{...} to appear in @var{literals}. -Within a pattern the identifier @samp{...} must follow the last element -of a nonempty sequence of subpatterns. - -More formally, an input form @var{F} matches a pattern @var{P} if and -only if: - -@itemize @bullet -@item -@var{P} is a non-literal identifier; or - -@item -@var{P} is a literal identifier and @var{F} is an identifier with the -same binding; or - -@item -@var{P} is a list @code{(@var{P_1} @dots{} @var{P_n})} and @var{F} is a -list of @var{n} forms that match @var{P_1} through @var{P_n}, -respectively; or - -@item -@var{P} is an improper list @code{(@var{P_1} @var{P_2} @dots{} @var{P_n} -. @var{P_n+1})} and @var{F} is a list or improper list of @var{n} or -more forms that match @var{P_1} through @var{P_n}, respectively, and -whose @var{n}th ``cdr'' matches @var{P_n+1}; or - -@item -@var{P} is of the form @code{(@var{P_1} @dots{} @var{P_n} @var{P_n+1} -@var{ellipsis})} where @var{ellipsis} is the identifier @samp{...} and -@var{F} is a proper list of at least @var{n} forms, the first @var{n} of -which match @var{P_1} through @var{P_n}, respectively, and each -remaining element of @var{F} matches @var{P_n+1}; or - -@item -@var{P} is a datum and @var{F} is equal to @var{P} in the sense of the -@code{equal?} procedure. -@end itemize - -It is an error to use a macro keyword, within the scope of its -binding, in an expression that does not match any of the patterns. - -When a macro use is transcribed according to the template of the -matching @var{syntax rule}, pattern variables that occur in the template -are replaced by the subforms they match in the input. Pattern variables -that occur in subpatterns followed by one or more instances of the -identifier @samp{...} are allowed only in subtemplates that are followed -by as many instances of @samp{...}. They are replaced in the output by -all of the subforms they match in the input, distributed as indicated. -It is an error if the output cannot be built up as specified. - -Identifiers that appear in the template but are not pattern variables or -the identifier @samp{...} are inserted into the output as literal -identifiers. If a literal identifier is inserted as a free identifier -then it refers to the binding of that identifier within whose scope the -instance of @code{syntax-rules} appears. If a literal identifier is -inserted as a bound identifier then it is in effect renamed to prevent -inadvertent captures of free identifiers. - -@example -@group -(let ((=> #f)) - (cond (#t => 'ok))) @result{} ok -@end group -@end example - -The macro transformer for @code{cond} recognizes @code{=>} -as a local variable, and hence an expression, and not as the -top-level identifier @code{=>}, which the macro transformer treats -as a syntactic keyword. Thus the example expands into - -@example -@group -(let ((=> #f)) - (if #t (begin => 'ok))) -@end group -@end example - -instead of - -@example -@group -(let ((=> #f)) - (let ((temp #t)) - (if temp - ('ok temp)))) -@end group -@end example - -which would result in an invalid procedure call. -@end deffn - -@node Syntactic Closures, Explicit Renaming, Pattern Language, Macros -@subsection Syntactic Closures - -@cindex syntactic closures -MIT/GNU Scheme's syntax-transformation engine is an implementation of -@dfn{syntactic closures}, a mechanism invented by Alan Bawden and -Jonathan Rees. The main feature of the syntactic-closures mechanism is -its simplicity and its close relationship to the environment models -commonly used with Scheme. Using the mechanism to write macro -transformers is somewhat cumbersome and can be confusing for the newly -initiated, but it is easily mastered. - -@menu -* Syntax Terminology:: -* SC Transformer Definition:: -* SC Identifiers:: -@end menu - -@node Syntax Terminology, SC Transformer Definition, Syntactic Closures, Syntactic Closures -@subsubsection Syntax Terminology - -This section defines the concepts and data types used by the syntactic -closures facility. - -@itemize @bullet -@item -@cindex form -@dfn{Forms} are the syntactic entities out of which programs are -recursively constructed. A form is any expression, any definition, any -syntactic keyword, or any syntactic closure. The variable name that -appears in a @code{set!} special form is also a form. Examples of -forms: - -@example -@group -17 -#t -car -(+ x 4) -(lambda (x) x) -(define pi 3.14159) -if -define -@end group -@end example - -@item -@cindex alias -@cindex identifier -@cindex synthetic identifier -An @dfn{alias} is an alternate name for a given symbol. It can appear -anywhere in a form that the symbol could be used, and when quoted it is -replaced by the symbol; however, it does not satisfy the predicate -@code{symbol?}. Macro transformers rarely distinguish symbols from -aliases, referring to both as @dfn{identifiers}. Another name for an -alias is @dfn{synthetic identifier}; this document uses both names. - -@item -@cindex syntactic environment -A @dfn{syntactic environment} maps identifiers to their meanings. More -precisely, it determines whether an identifier is a syntactic keyword -or a variable. If it is a keyword, the meaning is an interpretation -for the form in which that keyword appears. If it is a variable, the -meaning identifies which binding of that variable is referenced. In -short, syntactic environments contain all of the contextual information -necessary for interpreting the meaning of a particular form. - -@item -@cindex syntactic closure -A @dfn{syntactic closure} consists of a form, a syntactic environment, -and a list of identifiers. All identifiers in the form take their -meaning from the syntactic environment, except those in the given list. -The identifiers in the list are to have their meanings determined -later. - -A syntactic closure may be used in any context in which its form could -have been used. Since a syntactic closure is also a form, it may not -be used in contexts where a form would be illegal. For example, a form -may not appear as a clause in the @code{cond} special form. - -A syntactic closure appearing in a quoted structure is replaced by its -form. -@end itemize - -@node SC Transformer Definition, SC Identifiers, Syntax Terminology, Syntactic Closures -@subsubsection Transformer Definition - -This section describes the special forms for defining syntactic-closures -macro transformers, and the associated procedures for manipulating -syntactic closures and syntactic environments. - -@deffn {special form} sc-macro-transformer expression -The @var{expression} is expanded in the syntactic environment of the -@code{sc-macro-transformer} expression, and the expanded expression is -evaluated in the transformer environment to yield a macro transformer as -described below. This macro transformer is bound to a macro keyword by -the special form in which the @code{transformer} expression appears (for -example, @code{let-syntax}). - -@cindex macro transformer -@cindex input form -@cindex usage environment -@cindex output form -@cindex transformer environment -In the syntactic closures facility, a @dfn{macro transformer} is a -procedure that takes two arguments, a form and a syntactic environment, -and returns a new form. The first argument, the @dfn{input form}, is -the form in which the macro keyword occurred. The second argument, the -@dfn{usage environment}, is the syntactic environment in which the input -form occurred. The result of the transformer, the @dfn{output form}, is -automatically closed in the @dfn{transformer environment}, which is the -syntactic environment in which the @code{transformer} expression -occurred. - -For example, here is a definition of a @code{push} macro using -@code{syntax-rules}: - -@example -@group -(define-syntax push - (syntax-rules () - ((push item list) - (set! list (cons item list))))) -@end group -@end example - -@noindent -Here is an equivalent definition using @code{sc-macro-transformer}: - -@example -@group -(define-syntax push - (sc-macro-transformer - (lambda (exp env) - (let ((item (make-syntactic-closure env '() (cadr exp))) - (list (make-syntactic-closure env '() (caddr exp)))) - `(set! ,list (cons ,item ,list)))))) -@end group -@end example - -@noindent -In this example, the identifiers @code{set!} and @code{cons} are closed -in the transformer environment, and thus will not be affected by the -meanings of those identifiers in the usage environment @code{env}. - -Some macros may be non-hygienic by design. For example, the following -defines a @code{loop} macro that implicitly binds @code{exit} to an -escape procedure. The binding of @code{exit} is intended to capture -free references to @code{exit} in the body of the loop, so @code{exit} -must be left free when the body is closed: - -@example -@group -(define-syntax loop - (sc-macro-transformer - (lambda (exp env) - (let ((body (cdr exp))) - `(call-with-current-continuation - (lambda (exit) - (let f () - ,@@(map (lambda (exp) - (make-syntactic-closure env '(exit) - exp)) - body) - (f)))))))) -@end group -@end example -@end deffn - -@deffn {special form} rsc-macro-transformer expression -This form is an alternative way to define a syntactic-closures macro -transformer. Its syntax and usage are identical to -@code{sc-macro-transformer}, except that the roles of the usage -environment and transformer environment are reversed. (Hence -@acronym{RSC} stands for @dfn{Reversed Syntactic Closures}.) In other -words, the procedure specified by @var{expression} still accepts two -arguments, but its second argument will be the transformer environment -rather than the usage environment, and the returned expression is closed -in the usage environment rather than the transformer environment. - -The advantage of this arrangement is that it allows a simpler definition -style in some situations. For example, here is the @code{push} macro -from above, rewritten in this style: - -@example -@group -(define-syntax push - (rsc-macro-transformer - (lambda (exp env) - `(,(make-syntactic-closure env '() 'SET!) - ,(caddr exp) - (,(make-syntactic-closure env '() 'CONS) - ,(cadr exp) - ,(caddr exp)))))) -@end group -@end example - -@noindent -In this style only the introduced keywords are closed, while everything -else remains open. - -Note that @code{rsc-macro-transformer} and @code{sc-macro-transformer} -are easily interchangeable. Here is how to emulate -@code{rsc-macro-transformer} using @code{sc-macro-transformer}. (This -technique can be used to effect the opposite emulation as well.) - -@example -@group -(define-syntax push - (sc-macro-transformer - (lambda (exp usage-env) - (capture-syntactic-environment - (lambda (env) - (make-syntactic-closure usage-env '() - `(,(make-syntactic-closure env '() 'SET!) - ,(caddr exp) - (,(make-syntactic-closure env '() 'CONS) - ,(cadr exp) - ,(caddr exp))))))))) -@end group -@end example -@end deffn - -To assign meanings to the identifiers in a form, use -@code{make-syntactic-closure} to close the form in a syntactic -environment. - -@deffn procedure make-syntactic-closure environment free-names form -@var{Environment} must be a syntactic environment, @var{free-names} -must be a list of identifiers, and @var{form} must be a form. -@code{make-syntactic-closure} constructs and returns a syntactic -closure of @var{form} in @var{environment}, which can be used anywhere -that @var{form} could have been used. All the identifiers used in -@var{form}, except those explicitly excepted by @var{free-names}, -obtain their meanings from @var{environment}. - -Here is an example where @var{free-names} is something other than the -empty list. It is instructive to compare the use of @var{free-names} -in this example with its use in the @code{loop} example above: the -examples are similar except for the source of the identifier being left -free. - -@example -@group -(define-syntax let1 - (sc-macro-transformer - (lambda (exp env) - (let ((id (cadr exp)) - (init (caddr exp)) - (exp (cadddr exp))) - `((lambda (,id) - ,(make-syntactic-closure env (list id) exp)) - ,(make-syntactic-closure env '() init)))))) -@end group -@end example - -@noindent -@code{let1} is a simplified version of @code{let} that only binds a -single identifier, and whose body consists of a single expression. -When the body expression is syntactically closed in its original -syntactic environment, the identifier that is to be bound by -@code{let1} must be left free, so that it can be properly captured by -the @code{lambda} in the output form. -@end deffn - -In most situations, the @var{free-names} argument to -@code{make-syntactic-closure} is the empty list. In those cases, the -more succinct @code{close-syntax} can be used: - -@deffn procedure close-syntax form environment -@var{Environment} must be a syntactic environment and @var{form} must be -a form. Returns a new syntactic closure of @var{form} in -@var{environment}, with no free names. Entirely equivalent to - -@example -(make-syntactic-closure @var{environment} '() @var{form}) -@end example -@end deffn - -To obtain a syntactic environment other than the usage environment, -use @code{capture-syntactic-environment}. - -@deffn procedure capture-syntactic-environment procedure -@code{capture-syntactic-environment} returns a form that will, when -transformed, call @var{procedure} on the current syntactic environment. -@var{Procedure} should compute and return a new form to be transformed, -in that same syntactic environment, in place of the form. - -An example will make this clear. Suppose we wanted to define a simple -@code{loop-until} keyword equivalent to - -@example -@group -(define-syntax loop-until - (syntax-rules () - ((loop-until id init test return step) - (letrec ((loop - (lambda (id) - (if test return (loop step))))) - (loop init))))) -@end group -@end example - -@noindent -The following attempt at defining @code{loop-until} has a subtle -bug: - -@example -@group -(define-syntax loop-until - (sc-macro-transformer - (lambda (exp env) - (let ((id (cadr exp)) - (init (caddr exp)) - (test (cadddr exp)) - (return (cadddr (cdr exp))) - (step (cadddr (cddr exp))) - (close - (lambda (exp free) - (make-syntactic-closure env free exp)))) - `(letrec ((loop - (lambda (,id) - (if ,(close test (list id)) - ,(close return (list id)) - (loop ,(close step (list id))))))) - (loop ,(close init '()))))))) -@end group -@end example - -@noindent -This definition appears to take all of the proper precautions to -prevent unintended captures. It carefully closes the subexpressions in -their original syntactic environment and it leaves the @code{id} -identifier free in the @code{test}, @code{return}, and @code{step} -expressions, so that it will be captured by the binding introduced by -the @code{lambda} expression. Unfortunately it uses the identifiers -@code{if} and @code{loop} @emph{within} that @code{lambda} expression, -so if the user of @code{loop-until} just happens to use, say, @code{if} -for the identifier, it will be inadvertently captured. - -The syntactic environment that @code{if} and @code{loop} want to be -exposed to is the one just outside the @code{lambda} expression: before -the user's identifier is added to the syntactic environment, but after -the identifier @code{loop} has been added. -@code{capture-syntactic-environment} captures exactly that environment -as follows: - -@example -@group -(define-syntax loop-until - (sc-macro-transformer - (lambda (exp env) - (let ((id (cadr exp)) - (init (caddr exp)) - (test (cadddr exp)) - (return (cadddr (cdr exp))) - (step (cadddr (cddr exp))) - (close - (lambda (exp free) - (make-syntactic-closure env free exp)))) - `(letrec ((loop - ,(capture-syntactic-environment - (lambda (env) - `(lambda (,id) - (,(make-syntactic-closure env '() `if) - ,(close test (list id)) - ,(close return (list id)) - (,(make-syntactic-closure env '() `loop) - ,(close step (list id))))))))) - (loop ,(close init '()))))))) -@end group -@end example - -@noindent -In this case, having captured the desired syntactic environment, it is -convenient to construct syntactic closures of the identifiers @code{if} -and the @code{loop} and use them in the body of the -@code{lambda}. - -A common use of @code{capture-syntactic-environment} is to get the -transformer environment of a macro transformer: - -@example -@group -(sc-macro-transformer - (lambda (exp env) - (capture-syntactic-environment - (lambda (transformer-env) - @dots{})))) -@end group -@end example -@end deffn - -@node SC Identifiers, , SC Transformer Definition, Syntactic Closures -@subsubsection Identifiers - -This section describes the procedures that create and manipulate -identifiers. The identifier data type extends the syntactic closures -facility to be compatible with the high-level @code{syntax-rules} -facility. - -@cindex alias -As discussed earlier, an identifier is either a symbol or an -@dfn{alias}. An alias is implemented as a syntactic closure whose -@var{form} is an identifier: - -@example -@group -(make-syntactic-closure env '() 'a) @result{} @r{an alias} -@end group -@end example - -@noindent -Aliases are implemented as syntactic closures because they behave just -like syntactic closures most of the time. The difference is that an -alias may be bound to a new value (for example by @code{lambda} or -@code{let-syntax}); other syntactic closures may not be used this way. -If an alias is bound, then within the scope of that binding it is looked -up in the syntactic environment just like any other identifier. - -Aliases are used in the implementation of the high-level facility -@code{syntax-rules}. A macro transformer created by @code{syntax-rules} -uses a template to generate its output form, substituting subforms of -the input form into the template. In a syntactic closures -implementation, all of the symbols in the template are replaced by -aliases closed in the transformer environment, while the output form -itself is closed in the usage environment. This guarantees that the -macro transformation is hygienic, without requiring the transformer to -know the syntactic roles of the substituted input subforms. - -@deffn procedure identifier? object -Returns @code{#t} if @var{object} is an identifier, otherwise returns -@code{#f}. Examples: - -@example -@group -(identifier? 'a) @result{} #t -(identifier? (make-syntactic-closure env '() 'a)) - @result{} #t - -(identifier? "a") @result{} #f -(identifier? #\a) @result{} #f -(identifier? 97) @result{} #f -(identifier? #f) @result{} #f -(identifier? '(a)) @result{} #f -(identifier? '#(a)) @result{} #f -@end group -@end example -@end deffn - -The predicate @code{eq?} is used to determine if two identifers are -``the same''. Thus @code{eq?} can be used to compare identifiers -exactly as it would be used to compare symbols. Often, though, it is -useful to know whether two identifiers ``mean the same thing''. For -example, the @code{cond} macro uses the symbol @code{else} to identify -the final clause in the conditional. A macro transformer for -@code{cond} cannot just look for the symbol @code{else}, because the -@code{cond} form might be the output of another macro transformer that -replaced the symbol @code{else} with an alias. Instead the transformer -must look for an identifier that ``means the same thing'' in the usage -environment as the symbol @code{else} means in the transformer -environment. - -@deffn procedure identifier=? environment1 identifier1 environment2 identifier2 -@var{Environment1} and @var{environment2} must be syntactic -environments, and @var{identifier1} and @var{identifier2} must be -identifiers. @code{identifier=?} returns @code{#t} if the meaning of -@var{identifier1} in @var{environment1} is the same as that of -@var{identifier2} in @var{environment2}, otherwise it returns @code{#f}. -Examples: - -@example -@group -(let-syntax - ((foo - (sc-macro-transformer - (lambda (form env) - (capture-syntactic-environment - (lambda (transformer-env) - (identifier=? transformer-env 'x env 'x))))))) - (list (foo) - (let ((x 3)) - (foo)))) - @result{} (#t #f) -@end group - -@group -(let-syntax ((bar foo)) - (let-syntax - ((foo - (sc-macro-transformer - (lambda (form env) - (capture-syntactic-environment - (lambda (transformer-env) - (identifier=? transformer-env 'foo - env (cadr form)))))))) - (list (foo foo) - (foo bar)))) - @result{} (#f #t) -@end group -@end example -@end deffn - -Sometimes it is useful to be able to introduce a new identifier that is -guaranteed to be different from any existing identifier, similarly to -the way that @code{generate-uninterned-symbol} is used. - -@deffn procedure make-synthetic-identifier identifier -Creates and returns and new synthetic identifier (alias) that is -guaranteed to be different from all existing identifiers. -@var{Identifier} is any existing identifier, which is used in deriving -the name of the new identifier. - -This is implemented by syntactically closing @var{identifier} in a -special empty environment. -@end deffn - -@node Explicit Renaming, , Syntactic Closures, Macros -@subsection Explicit Renaming - -@cindex explicit renaming -@dfn{Explicit renaming} is an alternative facility for defining macro -transformers. In the MIT/GNU Scheme implementation, explicit-renaming -transformers are implemented as an abstraction layer on top of syntactic -closures. An explicit-renaming macro transformer is defined by an -instance of the @code{er-macro-transformer} keyword: - -@deffn {special form} er-macro-transformer expression -The @var{expression} is expanded in the syntactic environment of the -@code{er-macro-transformer} expression, and the expanded expression is -evaluated in the transformer environment to yield a macro transformer as -described below. This macro transformer is bound to a macro keyword by -the special form in which the @code{transformer} expression appears (for -example, @code{let-syntax}). - -@cindex macro transformer -@cindex input form, to macro -In the explicit-renaming facility, a @dfn{macro transformer} is a -procedure that takes three arguments, a form, a renaming procedure, and -a comparison predicate, and returns a new form. The first argument, the -@dfn{input form}, is the form in which the macro keyword occurred. - -@cindex renaming procedure -The second argument to a transformation procedure is a @dfn{renaming -procedure} that takes the representation of an identifier as its -argument and returns the representation of a fresh identifier that -occurs nowhere else in the program. For example, the transformation -procedure for a simplified version of the @code{let} macro might be -written as - -@example -@group -(lambda (exp rename compare) - (let ((vars (map car (cadr exp))) - (inits (map cadr (cadr exp))) - (body (cddr exp))) - `((lambda ,vars ,@@body) - ,@@inits))) -@end group -@end example - -@noindent -This would not be hygienic, however. A hygienic @code{let} macro must -rename the identifier @code{lambda} to protect it from being captured by -a local binding. The renaming effectively creates an fresh alias for -@code{lambda}, one that cannot be captured by any subsequent binding: - -@example -@group -(lambda (exp rename compare) - (let ((vars (map car (cadr exp))) - (inits (map cadr (cadr exp))) - (body (cddr exp))) - `((,(rename 'lambda) ,vars ,@@body) - ,@@inits))) -@end group -@end example - -The expression returned by the transformation procedure will be expanded -in the syntactic environment obtained from the syntactic environment of -the macro application by binding any fresh identifiers generated by the -renaming procedure to the denotations of the original identifiers in the -syntactic environment in which the macro was defined. This means that a -renamed identifier will denote the same thing as the original identifier -unless the transformation procedure that renamed the identifier placed -an occurrence of it in a binding position. - -The renaming procedure acts as a mathematical function in the sense that -the identifiers obtained from any two calls with the same argument will -be the same in the sense of @code{eqv?}. It is an error if the renaming -procedure is called after the transformation procedure has returned. - -@cindex comparison predicate -The third argument to a transformation procedure is a @dfn{comparison -predicate} that takes the representations of two identifiers as its -arguments and returns true if and only if they denote the same thing in -the syntactic environment that will be used to expand the transformed -macro application. For example, the transformation procedure for a -simplified version of the @code{cond} macro can be written as - -@example -@group -(lambda (exp rename compare) - (let ((clauses (cdr exp))) - (if (null? clauses) - `(,(rename 'quote) unspecified) - (let* ((first (car clauses)) - (rest (cdr clauses)) - (test (car first))) - (cond ((and (identifier? test) - (compare test (rename 'else))) - `(,(rename 'begin) ,@@(cdr first))) - (else `(,(rename 'if) - ,test - (,(rename 'begin) ,@@(cdr first)) - (cond ,@@rest)))))))))) -@end group -@end example - -@noindent -In this example the identifier @code{else} is renamed before being passed -to the comparison predicate, so the comparison will be true if and -only if the test expression is an identifier that denotes the same -thing in the syntactic environment of the expression being transformed -as @code{else} denotes in the syntactic environment in which the @code{cond} -macro was defined. If @code{else} were not renamed before being passed to -the comparison predicate, then it would match a local variable that -happened to be named @code{else}, and the macro would not be hygienic. - -Some macros are non-hygienic by design. For example, the following -defines a @code{loop} macro that implicitly binds @code{exit} to an -escape procedure. The binding of @code{exit} is intended to capture -free references to @code{exit} in the body of the loop, so @code{exit} -is not renamed. - -@example -@group -(define-syntax loop - (er-macro-transformer - (lambda (x r c) - (let ((body (cdr x))) - `(,(r 'call-with-current-continuation) - (,(r 'lambda) (exit) - (,(r 'let) ,(r 'f) () ,@@body (,(r 'f))))))))) -@end group -@end example - -Suppose a @code{while} macro is implemented using @code{loop}, with the -intent that @code{exit} may be used to escape from the @code{while} -loop. The @code{while} macro cannot be written as - -@example -@group -(define-syntax while - (syntax-rules () - ((while test body ...) - (loop (if (not test) (exit #f)) - body ...)))) -@end group -@end example - -@noindent -because the reference to @code{exit} that is inserted by the -@code{while} macro is intended to be captured by the binding of -@code{exit} that will be inserted by the @code{loop} macro. In other -words, this @code{while} macro is not hygienic. Like @code{loop}, it -must be written using the @code{er-macro-transformer} syntax: - -@example -@group -(define-syntax while - (er-macro-transformer - (lambda (x r c) - (let ((test (cadr x)) - (body (cddr x))) - `(,(r 'loop) - (,(r 'if) (,(r 'not) ,test) (exit #f)) - ,@@body))))) -@end group -@end example -@end deffn - -@node SRFI syntax, , Macros, Special Forms -@section SRFI syntax - -@cindex SRFI syntax -Several special forms have been introduced to support some of the -@uref{http://srfi.schemers.org/,Scheme Requests for Implementation} -(@acronym{SRFI}). Note that MIT/GNU Scheme has for some time supported -@uref{http://srfi.schemers.org/srfi-23/srfi-23.html,@acronym{SRFI} 23} -(error-reporting mechanism) and -@uref{http://srfi.schemers.org/srfi-30/srfi-30.html,@acronym{SRFI} 30} -(nested multi-line comments), since these @acronym{SRFI}s reflect -existing practice rather than introducing new functionality. - -@menu -* cond-expand (SRFI 0):: -* receive (SRFI 8):: -* define-record-type (SRFI 9):: -@end menu - -@node cond-expand (SRFI 0), receive (SRFI 8), SRFI syntax, SRFI syntax -@subsection cond-expand (SRFI 0) - -@cindex SRFI 0 -@uref{http://srfi.schemers.org/srfi-0/srfi-0.html,@acronym{SRFI} 0} -is a mechanism for portably determining the availability of -@uref{http://srfi.schemers.org/,@acronym{SRFI}} @dfn{features}. -The @code{cond-expand} special form conditionally expands according to -the features available. - -@deffn {special form} cond-expand clause clause dots{} -Each @var{clause} has the form - -@example -(@var{feature-requirement} @var{expression} @dots{}) -@end example - -where @var{feature-requirement} can have one of the following forms: - -@example -@group -@var{feature-identifier} -(and @var{feature-requirement} @dots{}) -(or @var{feature-requirement} @dots{}) -(not @var{feature-requirement}) -else -@end group -@end example - -(Note that at most one @code{else} clause may be present, and it must -always be the last clause.) - -The @code{cond-expand} special form tests for the existence of features -at macro-expansion time. It either expands into the body of one of its -@var{clause}s or signals an error during syntactic processing. -@code{cond-expand} expands into the body of the first @var{clause} whose -@var{feature-requirement} is currently satisfied (an @code{else} -@var{clause}, if present, is selected if none of the previous -@var{clauses} is selected). - -A @var{feature-requirement} has an obvious interpretation as a logical -formula, where the @var{feature-identifier} variables have meaning true -if the feature corresponding to the @var{feature-identifier}, as -specified in the @acronym{SRFI} registry, is in effect at the location -of the @code{cond-expand} form, and false otherwise. A -@var{feature-requirement} is satisfied if its formula is true under this -interpretation. - -@example -@group -(cond-expand - ((and srfi-1 srfi-10) - (write 1)) - ((or srfi-1 srfi-10) - (write 2)) - (else)) - -(cond-expand - (command-line - (define (program-name) (car (argv))))) -@end group -@end example - -The second example assumes that @code{command-line} is an alias for some -feature which gives access to command line arguments. Note that an -error will be signaled at macro-expansion time if this feature is not -present. - -Note that MIT/GNU Scheme allows @code{cond-expand} in any context where a -special form is allowed. This is an extension of the semantics defined -by @acronym{SRFI 0}, which only allows @code{cond-expand} at top level. -@end deffn - -@node receive (SRFI 8), define-record-type (SRFI 9), cond-expand (SRFI 0), SRFI syntax -@subsection receive (SRFI 8) - -@cindex SRFI 8 -@uref{http://srfi.schemers.org/srfi-8/srfi-8.html,@acronym{SRFI} 8} -defines a convenient syntax to bind an identifier to each of the values -of a multiple-valued expression and then evaluate an expression in the -scope of the bindings. As an instance of this pattern, consider the -following excerpt from a @samp{quicksort} procedure: - -@example -@group -(call-with-values - (lambda () - (partition (precedes pivot) others)) - (lambda (fore aft) - (append (qsort fore) (cons pivot (qsort aft))))) -@end group -@end example - -Here @samp{partition} is a multiple-valued procedure that takes two -arguments, a predicate and a list, and returns two lists, one comprising -the list elements that satisfy the predicate, the other those that do -not. The purpose of the expression shown is to partition the list -@samp{others}, sort each of the sublists, and recombine the results into -a sorted list. - -For our purposes, the important step is the binding of the identifiers -@samp{fore} and @samp{aft} to the values returned by @samp{partition}. -Expressing the construction and use of these bindings with the -call-by-values primitive is cumbersome: One must explicitly embed the -expression that provides the values for the bindings in a parameterless -procedure, and one must explicitly embed the expression to be evaluated -in the scope of those bindings in another procedure, writing as its -parameters the identifiers that are to be bound to the values received. - -These embeddings are boilerplate, exposing the underlying binding -mechanism but not revealing anything relevant to the particular program -in which it occurs. So the use of a syntactic abstraction that exposes -only the interesting parts -- the identifiers to be bound, the -multiple-valued expression that supplies the values, and the body of the -receiving procedure -- makes the code more concise and more readable: - -@example -@group -(receive (fore aft) (partition (precedes pivot) others) - (append (qsort fore) (cons pivot (qsort aft)))) -@end group -@end example - -The advantages are similar to those of a @samp{let} expression over a -procedure call with a @samp{lambda} expression as its operator. In both -cases, cleanly separating a ``header'' in which the bindings are -established from a ``body'' in which they are used makes it easier to -follow the code. - -@deffn {special form} receive formals expression body -@var{Formals} and @var{body} are defined as for @samp{lambda} -(@pxref{Lambda Expressions}). Specifically, @var{formals} can have the -following forms (the use of @samp{#!optional} and @samp{#!rest} is also -allowed in @var{formals} but is omitted for brevity): - -@table @samp -@item (@var{ident1} @dots{} @var{identN}) -The environment in which the @samp{receive} expression is evaluated is -extended by binding @var{ident1}, @dots{}, @var{identN} to fresh -locations. The @var{expression} is evaluated, and its values are stored -into those locations. (It is an error if @var{expression} does not have -exactly @var{N} values.) - -@item @var{ident} -The environment in which the @samp{receive} expression is evaluated is -extended by binding @var{ident} to a fresh location. The -@var{expression} is evaluated, its values are converted into a newly -allocated list, and the list is stored in the location bound to -@var{ident}. - -@item (@var{ident1} @dots{} @var{identN} . @var{identN+1}) -The environment in which the @samp{receive} expression is evaluated is -extended by binding @var{ident1}, @dots{}, @var{identN+1} to fresh -locations. The @var{expression} is evaluated. Its first @var{N} values -are stored into the locations bound to @var{ident1} @dots{} @var{identN}. -Any remaining values are converted into a newly allocated list, which is -stored into the location bound to @var{identN+1}. (It is an error if -@var{expression} does not have at least @var{N} values.) -@end table - -In any case, the expressions in @var{body} are evaluated sequentially in -the extended environment. The results of the last expression in the -body are the values of the @samp{receive} expression. -@end deffn - -@node define-record-type (SRFI 9), , receive (SRFI 8), SRFI syntax -@subsection define-record-type (SRFI 9) - -@cindex SRFI 9 -The @samp{define-record-type} syntax described in -@uref{http://srfi.schemers.org/srfi-9/srfi-9.html,@acronym{SRFI} 9} is a -slight simplification of one written for Scheme 48 by Jonathan Rees. -Unlike many record-defining special forms, it does not create any new -identifiers. Instead, the names of the record type, predicate, -constructor, and so on are all listed explicitly in the source. This -has the following advantages: - -@itemize @bullet -@item -It can be defined using a simple macro in Scheme implementations that -provide a procedural interface for creating record types. - -@item -It does not restrict users to a particular naming convention. - -@item -Tools like @command{grep} and the GNU Emacs tag facility will see the -defining occurance of each identifier. -@end itemize - -@deffn {special form} define-record-type type-name (constructor-name field-tag @dots{}) predicate-name field-spec @dots{} -@var{Type-name}, @var{contructor-name}, @var{field-tag}, and -@var{predicate-name} are identifiers. @var{Field-spec} has one of these -two forms: - -@example -@group -(@var{field-tag} @var{accessor-name}) -(@var{field-tag} @var{accessor-name} @var{modifier-name}) -@end group -@end example - -@noindent -where @var{field-tag}, @var{accessor-name}, and @var{modifier-name} are -each identifiers. - -@code{define-record-type} is generative: each use creates a new record -type that is distinct from all existing types, including other record -types and Scheme's predefined types. Record-type definitions may only -occur at top-level (there are two possible semantics for ``internal'' -record-type definitions, generative and nongenerative, and no consensus -as to which is better). - -An instance of @code{define-record-type} is equivalent to the following -definitions: - -@itemize @bullet -@item -@var{Type-name} is bound to a representation of the record type itself. -Operations on record types, such as defining print methods, reflection, -etc.@: are left to other SRFIs. - -@item -@var{constructor-name} is bound to a procedure that takes as many -arguments as there are @var{field-tag}s in the (@var{constructor-name} -@dots{}) subform and returns a new @var{type-name} record. Fields whose -tags are listed with @var{constructor-name} have the corresponding -argument as their initial value. The initial values of all other fields -are unspecified. - -@item -@var{predicate-name} is a predicate that returns @code{#t} when given a -value returned by @var{constructor-name} and @code{#f} for everything -else. - -@item -Each @var{accessor-name} is a procedure that takes a record of type -@var{type-name} and returns the current value of the corresponding -field. It is an error to pass an accessor a value which is not a record -of the appropriate type. - -@item -Each @var{modifier-name} is a procedure that takes a record of type -@var{type-name} and a value which becomes the new value of the -corresponding field; an unspecified value is returned. It is an error -to pass a modifier a first argument which is not a record of the -appropriate type. -@end itemize - -Assigning the value of any of these identifiers has no effect on the -behavior of any of their original values. -@end deffn - -The following - -@example -@group -(define-record-type :pare - (kons x y) - pare? - (x kar set-kar!) - (y kdr)) -@end group -@end example - -@noindent -defines @samp{kons} to be a constructor, @samp{kar} and @samp{kdr} to be -accessors, @samp{set-kar!} to be a modifier, and @samp{pare?} to be a -predicate for objects of type @samp{:pare}. - -@example -@group -(pare? (kons 1 2)) @result{} #t -(pare? (cons 1 2)) @result{} #f -(kar (kons 1 2)) @result{} 1 -(kdr (kons 1 2)) @result{} 2 -(let ((k (kons 1 2))) - (set-kar! k 3) - (kar k)) @result{} 3 -@end group -@end example - -@node Equivalence Predicates, Numbers, Special Forms, Top -@chapter Equivalence Predicates - -@cindex predicate (defn) -@cindex predicate, equivalence (defn) -@cindex equivalence predicate (defn) -@cindex comparison, for equivalence -@findex eq? -@findex eqv? -@findex equal? -A @dfn{predicate} is a procedure that always returns a boolean value -(@code{#t} or @code{#f}). An @dfn{equivalence predicate} is the -computational analogue of a mathematical equivalence relation (it is -symmetric, reflexive, and transitive). Of the equivalence predicates -described in this section, @code{eq?} is the finest or most -discriminating, and @code{equal?} is the coarsest. @code{eqv?} is -slightly less discriminating than @code{eq?}. - -@deffn procedure eqv? obj1 obj2 -The @code{eqv?} procedure defines a useful equivalence relation on -objects. Briefly, it returns @code{#t} if @var{obj1} and @var{obj2} -should normally be regarded as the same object. - -The @code{eqv?} procedure returns @code{#t} if: - -@itemize @bullet -@item -@var{obj1} and @var{obj2} are both @code{#t} or both @code{#f}. - -@item -@var{obj1} and @var{obj2} are both interned symbols and - -@example -@group -(string=? (symbol->string @var{obj1}) - (symbol->string @var{obj2})) - @result{} #t -@end group -@end example -@findex string=? -@findex symbol->string - -@item -@var{obj1} and @var{obj2} are both numbers, are numerically equal -according to the @code{=} procedure, and are either both exact or both -inexact (@pxref{Numbers}). -@findex = - -@item -@var{obj1} and @var{obj2} are both characters and are the same character -according to the @code{char=?} procedure (@pxref{Characters}). -@findex char=? - -@item -both @var{obj1} and @var{obj2} are the empty list. - -@item -@var{obj1} and @var{obj2} are procedures whose location tags are equal. - -@item -@var{obj1} and @var{obj2} are pairs, vectors, strings, bit strings, -records, cells, or weak pairs that denote the same locations in the -store. -@end itemize - -@noindent -The @code{eqv?} procedure returns @code{#f} if: - -@itemize @bullet -@item -@var{obj1} and @var{obj2} are of different types. - -@item -one of @var{obj1} and @var{obj2} is @code{#t} but the other is -@code{#f}. - -@item -@var{obj1} and @var{obj2} are symbols but - -@example -@group -(string=? (symbol->string @var{obj1}) - (symbol->string @var{obj2})) - @result{} #f -@end group -@end example -@findex string=? -@findex symbol->string - -@item -one of @var{obj1} and @var{obj2} is an exact number but the other is an -inexact number. - -@item -@var{obj1} and @var{obj2} are numbers for which the @code{=} procedure -returns @code{#f}. -@findex = - -@item -@var{obj1} and @var{obj2} are characters for which the @code{char=?} -procedure returns @code{#f}. -@findex char=? - -@item -one of @var{obj1} and @var{obj2} is the empty list but the other is not. - -@item -@var{obj1} and @var{obj2} are procedures that would behave differently -(return a different value or have different side effects) for some -arguments. - -@item -@var{obj1} and @var{obj2} are pairs, vectors, strings, bit strings, -records, cells, or weak pairs that denote distinct locations. -@end itemize - -Some examples: - -@example -@group -(eqv? 'a 'a) @result{} #t -(eqv? 'a 'b) @result{} #f -(eqv? 2 2) @result{} #t -(eqv? '() '()) @result{} #t -(eqv? 100000000 100000000) @result{} #t -(eqv? (cons 1 2) (cons 1 2)) @result{} #f -(eqv? (lambda () 1) - (lambda () 2)) @result{} #f -(eqv? #f 'nil) @result{} #f -(let ((p (lambda (x) x))) - (eqv? p p)) @result{} #t -@end group -@end example - -The following examples illustrate cases in which the above rules do not -fully specify the behavior of @code{eqv?}. All that can be said about -such cases is that the value returned by @code{eqv?} must be a boolean. - -@example -@group -(eqv? "" "") @result{} @r{unspecified} -(eqv? '#() '#()) @result{} @r{unspecified} -(eqv? (lambda (x) x) - (lambda (x) x)) @result{} @r{unspecified} -(eqv? (lambda (x) x) - (lambda (y) y)) @result{} @r{unspecified} -@end group -@end example - -The next set of examples shows the use of @code{eqv?} with procedures -that have local state. @code{gen-counter} must return a distinct -procedure every time, since each procedure has its own internal counter. -@code{gen-loser}, however, returns equivalent procedures each time, -since the local state does not affect the value or side effects of the -procedures. - -@example -@group -(define gen-counter - (lambda () - (let ((n 0)) - (lambda () (set! n (+ n 1)) n)))) -(let ((g (gen-counter))) - (eqv? g g)) @result{} #t -(eqv? (gen-counter) (gen-counter)) - @result{} #f -@end group - -@group -(define gen-loser - (lambda () - (let ((n 0)) - (lambda () (set! n (+ n 1)) 27)))) -(let ((g (gen-loser))) - (eqv? g g)) @result{} #t -(eqv? (gen-loser) (gen-loser)) - @result{} @r{unspecified} -@end group - -@group -(letrec ((f (lambda () (if (eqv? f g) 'both 'f))) - (g (lambda () (if (eqv? f g) 'both 'g))) - (eqv? f g)) - @result{} @r{unspecified} - -(letrec ((f (lambda () (if (eqv? f g) 'f 'both))) - (g (lambda () (if (eqv? f g) 'g 'both))) - (eqv? f g)) - @result{} #f -@end group -@end example - -Objects of distinct types must never be regarded as the same object. - -Since it is an error to modify constant objects (those returned by -literal expressions), the implementation may share structure between -constants where appropriate. Thus the value of @code{eqv?} on constants -is sometimes unspecified. - -@example -@group -(let ((x '(a))) - (eqv? x x)) @result{} #t -(eqv? '(a) '(a)) @result{} @r{unspecified} -(eqv? "a" "a") @result{} @r{unspecified} -(eqv? '(b) (cdr '(a b))) @result{} @r{unspecified} -@end group -@end example - -Rationale: The above definition of @code{eqv?} allows implementations -latitude in their treatment of procedures and literals: implementations -are free either to detect or to fail to detect that two procedures or -two literals are equivalent to each other, and can decide whether or not -to merge representations of equivalent objects by using the same pointer -or bit pattern to represent both. -@end deffn - -@page -@deffn procedure eq? obj1 obj2 -@code{eq?} is similar to @code{eqv?} except that in some cases it is -capable of discerning distinctions finer than those detectable by -@code{eqv?}. - -@code{eq?} and @code{eqv?} are guaranteed to have the same behavior on -symbols, booleans, the empty list, pairs, records, and non-empty strings -and vectors. @code{eq?}'s behavior on numbers and characters is -implementation-dependent, but it will always return either true or -false, and will return true only when @code{eqv?} would also return -true. @code{eq?} may also behave differently from @code{eqv?} on empty -vectors and empty strings. - -@example -@group -(eq? 'a 'a) @result{} #t -(eq? '(a) '(a)) @result{} @r{unspecified} -(eq? (list 'a) (list 'a)) @result{} #f -(eq? "a" "a") @result{} @r{unspecified} -(eq? "" "") @result{} @r{unspecified} -(eq? '() '()) @result{} #t -(eq? 2 2) @result{} @r{unspecified} -(eq? #\A #\A) @result{} @r{unspecified} -(eq? car car) @result{} #t -(let ((n (+ 2 3))) - (eq? n n)) @result{} @r{unspecified} -(let ((x '(a))) - (eq? x x)) @result{} #t -(let ((x '#())) - (eq? x x)) @result{} #t -(let ((p (lambda (x) x))) - (eq? p p)) @result{} #t -@end group -@end example - -Rationale: It will usually be possible to implement @code{eq?} much more -efficiently than @code{eqv?}, for example, as a simple pointer -comparison instead of as some more complicated operation. One reason is -that it may not be possible to compute @code{eqv?} of two numbers in -constant time, whereas @code{eq?} implemented as pointer comparison will -always finish in constant time. @code{eq?} may be used like @code{eqv?} -in applications using procedures to implement objects with state since -it obeys the same constraints as @code{eqv?}. -@end deffn - -@page -@deffn procedure equal? obj1 obj2 -@cindex circular structure -@code{equal?} recursively compares the contents of pairs, vectors, and -strings, applying @code{eqv?} on other objects such as numbers, symbols, -and records. A rule of thumb is that objects are generally -@code{equal?} if they print the same. @code{equal?} may fail to -terminate if its arguments are circular data structures. - -@example -@group -(equal? 'a 'a) @result{} #t -(equal? '(a) '(a)) @result{} #t -(equal? '(a (b) c) - '(a (b) c)) @result{} #t -(equal? "abc" "abc") @result{} #t -(equal? 2 2) @result{} #t -(equal? (make-vector 5 'a) - (make-vector 5 'a)) @result{} #t -(equal? (lambda (x) x) - (lambda (y) y)) @result{} @r{unspecified} -@end group -@end example -@end deffn - -@node Numbers, Characters, Equivalence Predicates, Top -@chapter Numbers -@cindex number - -(This section is largely taken from the @cite{Revised^4 Report on the -Algorithmic Language Scheme}.) - -Numerical computation has traditionally been neglected by the Lisp -community. Until Common Lisp there was no carefully thought out -strategy for organizing numerical computation, and with the exception of -the MacLisp system little effort was made to execute numerical code -efficiently. This report recognizes the excellent work of the Common -Lisp committee and accepts many of their recommendations. In some ways -this report simplifies and generalizes their proposals in a manner -consistent with the purposes of Scheme. - -It is important to distinguish between the mathematical numbers, the -Scheme numbers that attempt to model them, the machine representations -used to implement the Scheme numbers, and notations used to write -numbers. This report uses the types @emph{number}, @emph{complex}, -@emph{real}, @emph{rational}, and @emph{integer} to refer to both -mathematical numbers and Scheme numbers. Machine representations such -as fixed point and floating point are referred to by names such as -@emph{fixnum} and @emph{flonum}. - -@menu -* Numerical types:: -* Exactness:: -* Implementation restrictions:: -* Syntax of numerical constants:: -* Numerical operations:: -* Numerical input and output:: -* Fixnum and Flonum Operations:: -* Random Numbers:: -@end menu - -@node Numerical types, Exactness, Numbers, Numbers -@section Numerical types -@cindex numerical types - -Mathematically, numbers may be arranged into a tower of subtypes in -which each level is a subset of the level above it: - -@display -@group -number -complex -real -rational -integer -@end group -@end display - -For example, 3 is an integer. Therefore 3 is also a rational, a real, -and a complex. The same is true of the Scheme numbers that model 3. -For Scheme numbers, these types are defined by the predicates -@code{number?}, @code{complex?}, @code{real?}, @code{rational?}, and -@code{integer?}. - -There is no simple relationship between a number's type and its -representation inside a computer. Although most implementations of -Scheme will offer at least two different representations of 3, these -different representations denote the same integer. - -Scheme's numerical operations treat numbers as abstract data, as -independent of their representation as possible. Although an -implementation of Scheme may use fixnum, flonum, and perhaps other -representations for numbers, this should not be apparent to a casual -programmer writing simple programs. - -It is necessary, however, to distinguish between numbers that are -represented exactly and those that may not be. For example, indexes -into data structures must be known exactly, as must some polynomial -coefficients in a symbolic algebra system. On the other hand, the -results of measurements are inherently inexact, and irrational numbers -may be approximated by rational and therefore inexact approximations. -In order to catch uses of inexact numbers where exact numbers are -required, Scheme explicitly distinguishes exact from inexact numbers. -This distinction is orthogonal to the dimension of type. - -@node Exactness, Implementation restrictions, Numerical types, Numbers -@section Exactness -@cindex exactness - -Scheme numbers are either @emph{exact} or @emph{inexact}. A number is -exact if it was written as an exact constant or was derived from exact -numbers using only exact operations. A number is inexact if it was -written as an inexact constant, if it was derived using inexact -ingredients, or if it was derived using inexact operations. Thus -inexactness is a contagious property of a number. - -If two implementations produce exact results for a computation that did -not involve inexact intermediate results, the two ultimate results will -be mathematically equivalent. This is generally not true of -computations involving inexact numbers since approximate methods such as -floating point arithmetic may be used, but it is the duty of each -implementation to make the result as close as practical to the -mathematically ideal result. - -@findex + -Rational operations such as @code{+} should always produce exact results -when given exact arguments. If the operation is unable to produce an -exact result, then it may either report the violation of an -implementation restriction or it may silently coerce its result to an -inexact value. @xref{Implementation restrictions}. - -@findex inexact->exact -With the exception of @code{inexact->exact}, the operations described in -this section must generally return inexact results when given any -inexact arguments. An operation may, however, return an exact result if -it can prove that the value of the result is unaffected by the -inexactness of its arguments. For example, multiplication of any number -by an exact zero may produce an exact zero result, even if the other -argument is inexact. - -@node Implementation restrictions, Syntax of numerical constants, Exactness, Numbers -@section Implementation restrictions -@cindex implementation restriction - -Implementations of Scheme are not required to implement the whole tower -of subtypes (@pxref{Numerical types}), but they must implement a -coherent subset consistent with both the purposes of the implementation -and the spirit of the Scheme language. For example, an implementation -in which all numbers are real may still be quite useful.@footnote{MIT/GNU -Scheme implements the whole tower of numerical types. It has -unlimited-precision exact integers and exact rationals. Flonums are -used to implement all inexact reals; on machines that support @sc{ieee} -floating-point arithmetic these are double-precision floating-point -numbers.} - -Implementations may also support only a limited range of numbers of any -type, subject to the requirements of this section. The supported range -for exact numbers of any type may be different from the supported range -for inexact numbers of that type. For example, an implementation that -uses flonums to represent all its inexact real numbers may support a -practically unbounded range of exact integers and rationals while -limiting the range of inexact reals (and therefore the range of inexact -integers and rationals) to the dynamic range of the flonum format. -Furthermore the gaps between the representable inexact integers and -rationals are likely to be very large in such an implementation as the -limits of this range are approached. - -@findex length -@findex vector-length -@findex string-length -An implementation of Scheme must support exact integers throughout the -range of numbers that may be used for indexes of lists, vectors, and -strings or that may result from computing the length of a list, vector, -or string. The @code{length}, @code{vector-length}, and -@code{string-length} procedures must return an exact integer, and it is -an error to use anything but an exact integer as an index. Furthermore -any integer constant within the index range, if expressed by an exact -integer syntax, will indeed be read as an exact integer, regardless of -any implementation restrictions that may apply outside this range. -Finally, the procedures listed below will always return an exact integer -result provided all their arguments are exact integers and the -mathematically expected result is representable as an exact integer -within the implementation: - -@example -@group -* gcd modulo -+ imag-part numerator -- inexact->exact quotient -abs lcm rationalize -angle magnitude real-part -ceiling make-polar remainder -denominator make-rectangular round -expt max truncate -floor min -@end group -@end example - -@findex / -Implementations are encouraged, but not required, to support exact -integers and exact rationals of practically unlimited size and -precision, and to implement the above procedures and the @code{/} -procedure in such a way that they always return exact results when given -exact arguments. If one of these procedures is unable to deliver an -exact result when given exact arguments, then it may either report a -violation of an implementation restriction or it may silently coerce its -result to an inexact number. Such a coercion may cause an error -later. - -An implementation may use floating point and other approximate -representation strategies for inexact numbers. This report recommends, -but does not require, that the @sc{ieee} 32-bit and 64-bit floating -point standards be followed by implementations that use flonum -representations, and that implementations using other representations -should match or exceed the precision achievable using these floating -point standards. - -@findex sqrt -In particular, implementations that use flonum representations must -follow these rules: A flonum result must be represented with at least as -much precision as is used to express any of the inexact arguments to -that operation. It is desirable (but not required) for potentially -inexact operations such as @code{sqrt}, when applied to exact arguments, -to produce exact answers whenever possible (for example the square root -of an exact 4 ought to be an exact 2). If, however, an exact number is -operated upon so as to produce an inexact result (as by @code{sqrt}), -and if the result is represented as a flonum, then the most precise -flonum format available must be used; but if the result is represented -in some other way then the representation must have at least as much -precision as the most precise flonum format available. - -Although Scheme allows a variety of written notations for numbers, any -particular implementation may support only some of them.@footnote{MIT/GNU -Scheme implements all of the written notations for numbers.} For -example, an implementation in which all numbers are real need not -support the rectangular and polar notations for complex numbers. If an -implementation encounters an exact numerical constant that it cannot -represent as an exact number, then it may either report a violation of -an implementation restriction or it may silently represent the constant -by an inexact number. - -@node Syntax of numerical constants, Numerical operations, Implementation restrictions, Numbers -@section Syntax of numerical constants -@cindex number, external representation -@cindex external representation, for number - -@findex #b -@findex #o -@findex #d -@findex #x -@cindex #b as external representation -@cindex #o as external representation -@cindex #d as external representation -@cindex #x as external representation -A number may be written in binary, octal, decimal, or hexadecimal by the -use of a radix prefix. The radix prefixes are @code{#b} (binary), -@code{#o} (octal), @code{#d} (decimal), and @code{#x} (hexadecimal). -With no radix prefix, a number is assumed to be expressed in -decimal. - -@findex #e -@findex #i -@findex # -@cindex #e as external representation -@cindex #i as external representation -@cindex # in external representation of number -A numerical constant may be specified to be either exact or inexact by a -prefix. The prefixes are @code{#e} for exact, and @code{#i} for -inexact. An exactness prefix may appear before or after any radix -prefix that is used. If the written representation of a number has no -exactness prefix, the constant may be either inexact or exact. It is -inexact if it contains a decimal point, an exponent, or a @code{#} -character in the place of a digit, otherwise it is exact. - -@cindex s, as exponent marker in number -@cindex f, as exponent marker in number -@cindex d, as exponent marker in number -@cindex l, as exponent marker in number -@cindex e, as exponent marker in number -@cindex exponent marker (defn) -@cindex precision, of inexact number -@cindex numeric precision, inexact -@cindex internal representation, for inexact number -@cindex short precision, of inexact number -@cindex single precision, of inexact number -@cindex double precision, of inexact number -@cindex long precision, of inexact number -In systems with inexact numbers of varying precisions it may be useful -to specify the precision of a constant. For this purpose, numerical -constants may be written with an @dfn{exponent marker} that indicates -the desired precision of the inexact representation. The letters -@code{s}, @code{f}, @code{d}, and @code{l} specify the use of -@emph{short}, @emph{single}, @emph{double}, and @emph{long} precision, -respectively. (When fewer than four internal inexact representations -exist, the four size specifications are mapped onto those available. -For example, an implementation with two internal representations may map -short and single together and long and double together.) In addition, -the exponent marker @code{e} specifies the default precision for the -implementation. The default precision has at least as much precision as -@emph{double}, but implementations may wish to allow this default to be -set by the user. - -@example -@group -3.14159265358979F0 - @r{Round to single ---} 3.141593 -0.6L0 - @r{Extend to long ---} .600000000000000 -@end group -@end example - -@node Numerical operations, Numerical input and output, Syntax of numerical constants, Numbers -@section Numerical operations -@cindex numerical operations - -@xref{Entry Format}, for a summary of the naming conventions used to -specify restrictions on the types of arguments to numerical routines. -The examples used in this section assume that any numerical constant -written using an exact notation is indeed represented as an exact -number. Some examples also assume that certain numerical constants -written using an inexact notation can be represented without loss of -accuracy; the inexact constants were chosen so that this is likely to be -true in implementations that use flonums to represent inexact -numbers. - -@deffn procedure number? object -@deffnx procedure complex? object -@deffnx procedure real? object -@deffnx procedure rational? object -@deffnx procedure integer? object -@cindex type predicate, for number -These numerical type predicates can be applied to any kind of argument, -including non-numbers. They return @code{#t} if the object is of the -named type, and otherwise they return @code{#f}. In general, if a type -predicate is true of a number then all higher type predicates are also -true of that number. Consequently, if a type predicate is false of a -number, then all lower type predicates are also false of that -number.@footnote{In MIT/GNU Scheme the @code{rational?} procedure is the -same as @code{real?}, and the @code{complex?} procedure is the same as -@code{number?}.} - -@findex zero? -@findex = -If @var{z} is an inexact complex number, then @code{(real? @var{z})} is -true if and only if @code{(zero? (imag-part @var{z}))} is true. If -@var{x} is an inexact real number, then @code{(integer? @var{x})} is -true if and only if @code{(= @var{x} (round @var{x}))}. - -@example -@group -(complex? 3+4i) @result{} #t -(complex? 3) @result{} #t -(real? 3) @result{} #t -(real? -2.5+0.0i) @result{} #t -(real? #e1e10) @result{} #t -(rational? 6/10) @result{} #t -(rational? 6/3) @result{} #t -(integer? 3+0i) @result{} #t -(integer? 3.0) @result{} #t -(integer? 8/4) @result{} #t -@end group -@end example - -Note: The behavior of these type predicates on inexact numbers is -unreliable, since any inaccuracy may affect the result. - -@end deffn - -@deffn procedure exact? z -@deffnx procedure inexact? z -These numerical predicates provide tests for the exactness of a -quantity. For any Scheme number, precisely one of these predicates is -true. -@end deffn - -@deffn procedure exact-integer? object -@deffnx procedure exact-nonnegative-integer? object -@deffnx procedure exact-rational? object -These procedures test for some very common types of numbers. These -tests could be written in terms of simpler predicates, but are more -efficient. -@end deffn - -@deffn procedure = z1 z2 z3 @dots{} -@deffnx procedure < x1 x2 x3 @dots{} -@deffnx procedure > x1 x2 x3 @dots{} -@deffnx procedure <= x1 x2 x3 @dots{} -@deffnx procedure >= x1 x2 x3 @dots{} -@cindex ordering, of numbers -@cindex comparison, of numbers -@cindex equivalence predicate, for numbers -These procedures return @code{#t} if their arguments are (respectively): -equal, monotonically increasing, monotonically decreasing, monotonically -nondecreasing, or monotonically nonincreasing. - -These predicates are transitive. Note that the traditional -implementations of these predicates in Lisp-like languages are not -transitive. - -Note: While it is not an error to compare inexact numbers using these -predicates, the results may be unreliable because a small inaccuracy may -affect the result; this is especially true of @code{=} and @code{zero?}. -When in doubt, consult a numerical analyst. -@end deffn - -@deffn procedure zero? z -@deffnx procedure positive? x -@deffnx procedure negative? x -@deffnx procedure odd? x -@deffnx procedure even? x -@cindex zero -@cindex positive number -@cindex negative number -@cindex odd number -@cindex even number -These numerical predicates test a number for a particular property, -returning @code{#t} or @code{#f}. See note above regarding inexact -numbers. -@end deffn - -@deffn procedure max x1 x2 @dots{} -@deffnx procedure min x1 x2 @dots{} -@cindex minimum, of numbers -@cindex maximum, of numbers -These procedures return the maximum or minimum of their -arguments. - -@example -@group -(max 3 4) @result{} 4 @r{; exact} -(max 3.9 4) @result{} 4.0 @r{; inexact} -@end group -@end example - -Note: If any argument is inexact, then the result will also be inexact -(unless the procedure can prove that the inaccuracy is not large enough -to affect the result, which is possible only in unusual -implementations). If @code{min} or @code{max} is used to compare -numbers of mixed exactness, and the numerical value of the result cannot -be represented as an inexact number without loss of accuracy, then the -procedure may report a violation of an implementation -restriction.@footnote{MIT/GNU Scheme signals an error of type -@code{condition-type:bad-range-argument} in this case.} -@findex condition-type:bad-range-argument -@end deffn - -@deffn procedure + z1 @dots{} -@deffnx procedure * z1 @dots{} -@cindex addition, of numbers -@cindex sum, of numbers -@cindex identity, additive -@cindex multiplication, of numbers -@cindex product, of numbers -@cindex identity, multiplicative -These procedures return the sum or product of their arguments. - -@example -@group -(+ 3 4) @result{} 7 -(+ 3) @result{} 3 -(+) @result{} 0 -(* 4) @result{} 4 -(*) @result{} 1 -@end group -@end example -@end deffn - -@deffn procedure - z1 z2 @dots{} -@deffnx procedure / z1 z2 @dots{} -@cindex subtraction, of numbers -@cindex difference, of numbers -@cindex inverse, additive, of number -@cindex division, of numbers -@cindex quotient, of numbers -@cindex inverse, multiplicative, of number -With two or more arguments, these procedures return the difference or -quotient of their arguments, associating to the left. With one -argument, however, they return the additive or multiplicative inverse of -their argument. - -@example -@group -(- 3 4) @result{} -1 -(- 3 4 5) @result{} -6 -(- 3) @result{} -3 -(/ 3 4 5) @result{} 3/20 -(/ 3) @result{} 1/3 -@end group -@end example -@end deffn - -@deffn procedure 1+ z -@deffnx procedure -1+ z -@code{(1+ z)} is equivalent to @code{(+ z 1)}; @code{(-1+ z)} is -equivalent to @code{(- z 1)}. -@end deffn - -@deffn procedure abs x -@cindex absolute value, of number -@cindex magnitude, of real number -@code{abs} returns the magnitude of its argument. - -@example -(abs -7) @result{} 7 -@end example -@end deffn - -@deffn procedure quotient n1 n2 -@deffnx procedure remainder n1 n2 -@deffnx procedure modulo n1 n2 -@cindex division, of integers -@cindex quotient, of integers -@cindex remainder, of integers -@cindex modulus, of integers -@cindex integer division -These procedures implement number-theoretic (integer) division: for -positive integers @var{n1} and @var{n2}, if @var{n3} and @var{n4} are -integers such that -@tex -$$n_1=n_2n_3+n_4$$ -$$0\leq n_4inexact (/ 6 4))) @result{} 2.0 -@end group -@end example -@end deffn - -@deffn procedure floor x -@deffnx procedure ceiling x -@deffnx procedure truncate x -@deffnx procedure round x -These procedures return integers. @code{floor} returns the largest -integer not larger than @var{x}. @code{ceiling} returns the smallest -integer not smaller than @var{x}. @code{truncate} returns the integer -closest to @var{x} whose absolute value is not larger than the absolute -value of @var{x}. @code{round} returns the closest integer to @var{x}, -rounding to even when @var{x} is halfway between two integers. - -Rationale: @code{round} rounds to even for consistency with the rounding -modes required by the @sc{ieee} floating point standard. - -Note: If the argument to one of these procedures is inexact, then the -result will also be inexact. If an exact value is needed, the result -should be passed to the @code{inexact->exact} procedure (or use one of -the procedures below). - -@example -@group -(floor -4.3) @result{} -5.0 -(ceiling -4.3) @result{} -4.0 -(truncate -4.3) @result{} -4.0 -(round -4.3) @result{} -4.0 - -(floor 3.5) @result{} 3.0 -(ceiling 3.5) @result{} 4.0 -(truncate 3.5) @result{} 3.0 -(round 3.5) @result{} 4.0 @r{; inexact} - -(round 7/2) @result{} 4 @r{; exact} -(round 7) @result{} 7 -@end group -@end example -@end deffn - -@deffn procedure floor->exact x -@deffnx procedure ceiling->exact x -@deffnx procedure truncate->exact x -@deffnx procedure round->exact x -These procedures are similar to the preceding procedures except that -they always return an exact result. For example, the following are -equivalent - -@example -@group -(floor->exact x) -(inexact->exact (floor x)) -@end group -@end example - -@noindent -except that the former is faster and has fewer range restrictions. -@end deffn - -@deffn procedure rationalize x y -@deffnx procedure rationalize->exact x y -@cindex simplest rational (defn) -@cindex rational, simplest (defn) -@code{rationalize} returns the @emph{simplest} rational number differing -from @var{x} by no more than @var{y}. A rational number @var{r1} is -@emph{simpler} than another rational number @var{r2} if -@t{@var{r1}=@var{p1}/@var{q1}} and @t{@var{r2}=@var{p2}/@var{q2}} (both -in lowest terms) and @t{|@var{p1}|<=|@var{p2}|} and -@t{|@var{q1}|<=|@var{q2}|}. Thus @t{3/5} is simpler than @t{4/7}. -Although not all rationals are comparable in this ordering (consider -@t{2/7} and @t{3/5}) any interval contains a rational number that is -simpler than every other rational number in that interval (the simpler -@t{2/5} lies between @t{2/7} and @t{3/5}). Note that @t{0=0/1} is the -simplest rational of all. - -@example -@group -(rationalize (inexact->exact .3) 1/10) @result{} 1/3 @r{; exact} -(rationalize .3 1/10) @result{} #i1/3 @r{; inexact} -@end group -@end example - -@code{rationalize->exact} is similar to @code{rationalize} except that -it always returns an exact result. -@end deffn - -@deffn procedure simplest-rational x y -@deffnx procedure simplest-exact-rational x y -@code{simplest-rational} returns the simplest rational number between -@var{x} and @var{y} inclusive; @code{simplest-exact-rational} is similar -except that it always returns an exact result. - -These procedures implement the same functionality as @code{rationalize} -and @code{rationalize->exact}, except that they specify the input range -by its endpoints; @code{rationalize} specifies the range by its center -point and its (half-) width. -@end deffn - -@deffn procedure exp z -@deffnx procedure log z -@deffnx procedure sin z -@deffnx procedure cos z -@deffnx procedure tan z -@deffnx procedure asin z -@deffnx procedure acos z -@deffnx procedure atan z -@deffnx procedure atan y x -@findex angle -@findex make-rectangular -These procedures compute the usual transcendental functions. @code{log} -computes the natural logarithm of @var{z} (not the base ten logarithm). -@code{asin}, @code{acos}, and @code{atan} compute arcsine, arccosine, -and arctangent, respectively. The two-argument variant of @code{atan} -computes @code{(angle (make-rectangular @var{x} @var{y}))} (see -below). - -In general, the mathematical functions log, arcsine, arccosine, and -arctangent are multiply defined. For nonzero real @var{x}, the value of -log @var{x} is defined to be the one whose imaginary part lies in the -range minus @var{pi} (exclusive) to @var{pi} (inclusive). log 0 is -undefined. The value of log @var{z} when @var{z} is complex is defined -according to the formula -@tex -$$\log z = \log {\rm magnitude}(z) + i {\rm angle} (z)$$ -@end tex -@ifinfo - -@example -log @var{z} = log magnitude(@var{z}) + i angle(@var{z}) -@end example - -@end ifinfo -With log defined this way, the values of arcsine, arccosine, and -arctangent are according to the following formulae: -@tex -$$\sin^{-1} z = -i \log (i z + \sqrt{1 - z^2})$$ -$$\cos^{-1} z = \pi / 2 - \sin^{-1} z$$ -$$\tan^{-1} z = (\log (1 + i z) - \log (1 - i z)) / (2 i)$$ -@end tex -@ifinfo - -@example -@group -arcsin(@var{z}) = -i log(i @var{z} + sqrt(1 - @var{z}^2)) -arccos(@var{z}) = pi/2 - arcsin(@var{z}) -arctan(@var{z}) = (log(1 + i @var{z}) + log(1 - i @var{z})) / (2 i) -@end group -@end example - -@end ifinfo -The above specification follows @cite{Common Lisp: the Language}, which -in turn cites @cite{Principal Values and Branch Cuts in Complex APL}; -refer to these sources for more detailed discussion of branch cuts, -boundary conditions, and implementation of these functions. When it is -possible these procedures produce a real result from a real -argument. -@end deffn - -@deffn procedure sqrt z -Returns the principal square root of @var{z}. The result will have -either positive real part, or zero real part and non-negative imaginary -part. -@end deffn - -@deffn procedure expt z1 z2 -Returns @var{z1} raised to the power @var{z2}: -@tex -$${z_1}^{z_2} = e^{z_2 \log {z_1}}$$ -$0^0$ is defined to be equal to 1. -@end tex -@ifinfo - -@example -@var{z1}^@var{z2} = e^(@var{z2} log @var{z1}) -@end example - -@noindent -0^0 is defined to be equal to 1. -@end ifinfo -@end deffn - -@deffn procedure make-rectangular x1 x2 -@deffnx procedure make-polar x3 x4 -@deffnx procedure real-part z -@deffnx procedure imag-part z -@deffnx procedure magnitude z -@deffnx procedure angle z -@deffnx procedure conjugate z -Suppose @var{x1}, @var{x2}, @var{x3}, and @var{x4} are real numbers and -@var{z} is a complex number such that -@tex - $$ z = x_1 + x_2\hbox{$i$} - = x_3 \cdot e^{{\displaystyle{\hbox{$i$}} x_4}}$$ -@end tex -@ifinfo - -@example -@var{z} = @var{x1} + @var{x2} i = @var{x3} e^(i @var{x4}) -@end example - -@end ifinfo -@noindent -Then @code{make-rectangular} and @code{make-polar} return @var{z}, -@code{real-part} returns @var{x1}, @code{imag-part} returns @var{x2}, -@code{magnitude} returns @var{x3}, and @code{angle} returns @var{x4}. -In the case of @code{angle}, whose value is not uniquely determined by -the preceding rule, the value returned will be the one in the range -minus @var{pi} (exclusive) to @var{pi} (inclusive). - -@code{conjugate} returns the complex conjugate of @var{z}. -@end deffn - -@deffn procedure exact->inexact z -@deffnx procedure inexact->exact z -@code{exact->inexact} returns an inexact representation of @var{z}. The -value returned is the inexact number that is numerically closest to the -argument. If an exact argument has no reasonably close inexact -equivalent, then a violation of an implementation restriction may be -reported; MIT/GNU Scheme signals an error of type -@code{condition-type:bad-range-argument} in this case. -@findex condition-type:bad-range-argument - -@code{inexact->exact} returns an exact representation of @var{z}. The -value returned is the exact number that is numerically closest to the -argument. If an inexact argument has no reasonably close exact -equivalent, then a violation of an implementation restriction may be -reported; in MIT/GNU Scheme this case does not occur because all inexact -numbers are representable as exact numbers. - -These procedures implement the natural one-to-one correspondence between -exact and inexact integers throughout an implementation-dependent range. -@xref{Implementation restrictions}. -@end deffn - -@node Numerical input and output, Fixnum and Flonum Operations, Numerical operations, Numbers -@section Numerical input and output -@cindex numerical input and output - -@deffn procedure number->string number [radix] -@var{Radix} must be an exact integer, either 2, 8, 10, or 16. If -omitted, @var{radix} defaults to 10. The procedure -@code{number->string} takes a number and a radix and returns as a string -an external representation of the given number in the given radix such -that - -@example -@group -(let ((number @var{number}) - (radix @var{radix})) - (eqv? number - (string->number (number->string number radix) - radix))) -@end group -@end example - -@noindent -is true. It is an error if no possible result makes this expression -true. - -If @var{number} is inexact, the radix is 10, and the above expression -can be satisfied by a result that contains a decimal point, then the -result contains a decimal point and is expressed using the minimum -number of digits (exclusive of exponent and trailing zeroes) needed to -make the above expression true; otherwise the format of the result is -unspecified. - -The result returned by @code{number->string} never contains an explicit -radix prefix. - -Note: The error case can occur only when @var{number} is not a complex -number or is a complex number with an non-rational real or imaginary -part. - -Rationale: If @var{number} is an inexact number represented using -flonums, and the radix is 10, then the above expression is normally -satisfied by a result containing a decimal point. The unspecified case -allows for infinities, NaNs, and non-flonum representations. -@end deffn - -@defvr variable flonum-parser-fast? -This variable controls the behavior of @code{string->number} when -parsing inexact numbers. Specifically, it allows the user to trade off -accuracy against speed. - -When set to its default value, @code{#f}, the parser provides maximal -accuracy, as required by the Scheme standard. If set to @code{#t}, the -parser uses faster algorithms that will sometimes introduce small errors -in the result. The errors affect a few of the least-significant bits of -the result, and consequently can be tolerated by many applications. -@end defvr - -@defvr variable flonum-unparser-cutoff -This variable controls the action of @code{number->string} when -@var{number} is a flonum (and consequently controls all printing of -flonums). The value of this variable is normally a list of three items: - -@table @var -@item rounding-type -One of the following symbols: @code{normal}, @code{relative}, or -@code{absolute}. The symbol @code{normal} means that the number should -be printed with full precision. The symbol @code{relative} means that -the number should be rounded to a specific number of digits. The symbol -@code{absolute} means that the number should be rounded so that there -are a specific number of digits to the right of the decimal point. - -@item precision -An exact integer. If @var{rounding-type} is @code{normal}, -@var{precision} is ignored. If @var{rounding-type} is @code{relative}, -@var{precision} must be positive, and it specifies the number of digits -to which the printed representation will be rounded. If -@var{rounding-type} is @code{absolute}, the printed representation will -be rounded @var{precision} digits to the right of the decimal point; if -@var{precision} is negative, the representation is rounded @code{(- -@var{precision})} digits to the left of the decimal point. - -@item format-type -One of the symbols: @code{normal}, @code{scientific}, or -@code{engineering}. This specifies the format in which the number will -be printed.@* @code{scientific} specifies that the number will be printed -using scientific notation: @code{@var{x}.@var{xxx}e@var{yyy}}. In other -words, the number is printed as a mantissa between zero inclusive and -ten exclusive, and an exponent. @code{engineering} is like -@code{scientific}, except that the exponent is always a power of three, -and the mantissa is constrained to be between zero inclusive and 1000 -exclusive. If @code{normal} is specified, the number will be printed in -positional notation if it is ``small enough'', otherwise it is printed -in scientific notation. A number is ``small enough'' when the number of -digits that would be printed using positional notation does not exceed -the number of digits of precision in the underlying floating-point -number representation; @sc{ieee} double-precision floating-point numbers -have 17 digits of precision. -@end table - -@noindent -This three-element list may be abbreviated in two ways. First, the -symbol @code{normal} may be used, which is equivalent to the list -@code{(normal 0 normal)}. Second, the third element of the list, -@var{format-type}, may be omitted, in which case it defaults to -@code{normal}. - -@noindent -The default value for @code{flonum-unparser-cutoff} is @code{normal}. -If it is bound to a value different from those described here, -@code{number->string} issues a warning and acts as though the value had -been @code{normal}. -@end defvr - -@noindent -Some examples of @code{flonum-unparser-cutoff}: - -@example -(number->string (* 4 (atan 1 1))) - @result{} "3.141592653589793" -(fluid-let ((flonum-unparser-cutoff '(relative 5))) - (number->string (* 4 (atan 1 1)))) - @result{} "3.1416" -(fluid-let ((flonum-unparser-cutoff '(relative 5))) - (number->string (* 4000 (atan 1 1)))) - @result{} "3141.6" -(fluid-let ((flonum-unparser-cutoff '(relative 5 scientific))) - (number->string (* 4000 (atan 1 1)))) - @result{} "3.1416e3" -(fluid-let ((flonum-unparser-cutoff '(relative 5 scientific))) - (number->string (* 40000 (atan 1 1)))) - @result{} "3.1416e4" -(fluid-let ((flonum-unparser-cutoff '(relative 5 engineering))) - (number->string (* 40000 (atan 1 1)))) - @result{} "31.416e3" -(fluid-let ((flonum-unparser-cutoff '(absolute 5))) - (number->string (* 4 (atan 1 1)))) - @result{} "3.14159" -(fluid-let ((flonum-unparser-cutoff '(absolute 5))) - (number->string (* 4000 (atan 1 1)))) - @result{} "3141.59265" -(fluid-let ((flonum-unparser-cutoff '(absolute -4))) - (number->string (* 4e10 (atan 1 1)))) - @result{} "31415930000." -(fluid-let ((flonum-unparser-cutoff '(absolute -4 scientific))) - (number->string (* 4e10 (atan 1 1)))) - @result{} "3.141593e10" -(fluid-let ((flonum-unparser-cutoff '(absolute -4 engineering))) - (number->string (* 4e10 (atan 1 1)))) - @result{} "31.41593e9" -(fluid-let ((flonum-unparser-cutoff '(absolute -5))) - (number->string (* 4e10 (atan 1 1)))) - @result{} "31415900000." -@end example - -@deffn procedure string->number string [radix] -Returns a number of the maximally precise representation expressed by -the given @var{string}. @var{Radix} must be an exact integer, either 2, -8, 10, or 16. If supplied, @var{radix} is a default radix that may be -overridden by an explicit radix prefix in @var{string} (e.g.@: -@code{"#o177"}). If @var{radix} is not supplied, then the default radix -is 10. If @var{string} is not a syntactically valid notation for a -number, then @code{string->number} returns @code{#f}. - -@example -@group -(string->number "100") @result{} 100 -(string->number "100" 16) @result{} 256 -(string->number "1e2") @result{} 100.0 -(string->number "15##") @result{} 1500.0 -@end group -@end example - -@noindent -Note that a numeric representation using a decimal point or an exponent -marker is not recognized unless @var{radix} is @code{10}. -@end deffn - -@node Fixnum and Flonum Operations, Random Numbers, Numerical input and output, Numbers -@section Fixnum and Flonum Operations - -This section describes numerical operations that are restricted forms of -the operations described above. These operations are useful because -they compile very efficiently. However, care should be exercised: if -used improperly, these operations can return incorrect answers, or even -malformed objects that confuse the garbage collector. - -@menu -* Fixnum Operations:: -* Flonum Operations:: -@end menu - -@node Fixnum Operations, Flonum Operations, Fixnum and Flonum Operations, Fixnum and Flonum Operations -@subsection Fixnum Operations - -@cindex fixnum (defn) -A @dfn{fixnum} is an exact integer that is small enough to fit in a -machine word. In MIT/GNU Scheme, fixnums are typically 24 or 26 bits, -depending on the machine; it is reasonable to assume that fixnums are at -least 24 bits. Fixnums are signed; they are encoded using 2's -complement. - -All exact integers that are small enough to be encoded as fixnums are -always encoded as fixnums --- in other words, any exact integer that is -not a fixnum is too big to be encoded as such. For this reason, small -constants such as @code{0} or @code{1} are guaranteed to be fixnums. - -@deffn procedure fix:fixnum? object -@cindex type predicate, for fixnum -Returns @code{#t} if @var{object} is a fixnum; otherwise returns -@code{#f}. -@end deffn - -Here is an expression that determines the largest fixnum: - -@example -@group -(let loop ((n 1)) - (if (fix:fixnum? n) - (loop (* n 2)) - (- n 1))) -@end group -@end example - -@noindent -A similar expression determines the smallest fixnum. - -@deffn procedure fix:= fixnum fixnum -@deffnx procedure fix:< fixnum fixnum -@deffnx procedure fix:> fixnum fixnum -@deffnx procedure fix:<= fixnum fixnum -@deffnx procedure fix:>= fixnum fixnum -@cindex equivalence predicate, for fixnums -These are the standard order and equality predicates on fixnums. When -compiled, they do not check the types of their arguments. -@end deffn - -@deffn procedure fix:zero? fixnum -@deffnx procedure fix:positive? fixnum -@deffnx procedure fix:negative? fixnum -These procedures compare their argument to zero. When compiled, they do -not check the type of their argument. The code produced by the -following expressions is identical: - -@example -@group -(fix:zero? @var{fixnum}) -(fix:= @var{fixnum} 0) -@end group -@end example - -@noindent -Similarly, @code{fix:positive?} and @code{fix:negative?} produce code -identical to equivalent expressions using @code{fix:>} and @code{fix:<}. -@end deffn - -@deffn procedure fix:+ fixnum fixnum -@deffnx procedure fix:- fixnum fixnum -@deffnx procedure fix:* fixnum fixnum -@deffnx procedure fix:quotient fixnum fixnum -@deffnx procedure fix:remainder fixnum fixnum -@deffnx procedure fix:gcd fixnum fixnum -@deffnx procedure fix:1+ fixnum -@deffnx procedure fix:-1+ fixnum -These procedures are the standard arithmetic operations on fixnums. -When compiled, they do not check the types of their arguments. -Furthermore, they do not check to see if the result can be encoded as a -fixnum. If the result is too large to be encoded as a fixnum, a -malformed object is returned, with potentially disastrous effect on the -garbage collector. -@end deffn - -@deffn procedure fix:divide fixnum fixnum -@findex integer-divide -@findex integer-divide-quotient -@findex integer-divide-remainder -This procedure is like @code{integer-divide}, except that its arguments -and its results must be fixnums. It should be used in conjunction with -@code{integer-divide-quotient} and @code{integer-divide-remainder}. -@end deffn - -@cindex logical operations, on fixnums -@cindex bitwise-logical operations, on fixnums -The following are @dfn{bitwise-logical} operations on fixnums. - -@deffn procedure fix:not fixnum -This returns the bitwise-logical inverse of its argument. When -compiled, it does not check the type of its argument. - -@example -@group -(fix:not 0) @result{} -1 -(fix:not -1) @result{} 0 -(fix:not 1) @result{} -2 -(fix:not -34) @result{} 33 -@end group -@end example -@end deffn - -@deffn procedure fix:and fixnum fixnum -This returns the bitwise-logical ``and'' of its arguments. When -compiled, it does not check the types of its arguments. - -@example -@group -(fix:and #x43 #x0f) @result{} 3 -(fix:and #x43 #xf0) @result{} #x40 -@end group -@end example -@end deffn - -@deffn procedure fix:andc fixnum fixnum -Returns the bitwise-logical ``and'' of the first argument with the -bitwise-logical inverse of the second argument. When compiled, it does -not check the types of its arguments. - -@example -@group -(fix:andc #x43 #x0f) @result{} #x40 -(fix:andc #x43 #xf0) @result{} 3 -@end group -@end example -@end deffn - -@deffn procedure fix:or fixnum fixnum -This returns the bitwise-logical ``inclusive or'' of its arguments. -When compiled, it does not check the types of its arguments. - -@example -@group -(fix:or #x40 3) @result{} #x43 -(fix:or #x41 3) @result{} #x43 -@end group -@end example -@end deffn - -@deffn procedure fix:xor fixnum fixnum -This returns the bitwise-logical ``exclusive or'' of its arguments. -When compiled, it does not check the types of its arguments. - -@example -@group -(fix:xor #x40 3) @result{} #x43 -(fix:xor #x41 3) @result{} #x42 -@end group -@end example -@end deffn - -@deffn procedure fix:lsh fixnum1 fixnum2 -This procedure returns the result of logically shifting @var{fixnum1} by -@var{fixnum2} bits. If @var{fixnum2} is positive, @var{fixnum1} is -shifted left; if negative, it is shifted right. When compiled, it does -not check the types of its arguments, nor the validity of its result. - -@example -@group -(fix:lsh 1 10) @result{} #x400 -(fix:lsh #x432 -10) @result{} 1 -(fix:lsh -1 3) @result{} -8 -(fix:lsh -128 -4) @result{} #x3FFFF8 -@end group -@end example -@end deffn - -@node Flonum Operations, , Fixnum Operations, Fixnum and Flonum Operations -@subsection Flonum Operations - -@cindex flonum (defn) -A @dfn{flonum} is an inexact real number that is implemented as a -floating-point number. In MIT/GNU Scheme, all inexact real numbers are -flonums. For this reason, constants such as @code{0.} and @code{2.3} -are guaranteed to be flonums. - -@deffn procedure flo:flonum? object -@cindex type predicate, for flonum -Returns @code{#t} if @var{object} is a flonum; otherwise returns @code{#f}. -@end deffn - -@deffn procedure flo:= flonum1 flonum2 -@deffnx procedure flo:< flonum1 flonum2 -@deffnx procedure flo:> flonum1 flonum2 -@cindex equivalence predicate, for flonums -These procedures are the standard order and equality predicates on -flonums. When compiled, they do not check the types of their arguments. -@end deffn - -@deffn procedure flo:zero? flonum -@deffnx procedure flo:positive? flonum -@deffnx procedure flo:negative? flonum -Each of these procedures compares its argument to zero. When compiled, -they do not check the type of their argument. -@end deffn - -@deffn procedure flo:+ flonum1 flonum2 -@deffnx procedure flo:- flonum1 flonum2 -@deffnx procedure flo:* flonum1 flonum2 -@deffnx procedure flo:/ flonum1 flonum2 -These procedures are the standard arithmetic operations on flonums. -When compiled, they do not check the types of their arguments. -@end deffn - -@deffn procedure flo:finite? flonum -@vindex +inf -@vindex -inf -@vindex NaN -@cindex positive infinity (@code{+inf}) -@cindex negative infinity (@code{-inf}) -@cindex not a number (@code{NaN}) -The @acronym{IEEE} floating-point number specification supports three -special ``numbers'': positive infinity (@code{+inf}), negative infinity -(@code{-inf}), and not-a-number (@code{NaN}). This predicate returns -@code{#f} if @var{flonum} is one of these objects, and @code{#t} if it -is any other floating-point number. -@end deffn - -@deffn procedure flo:negate flonum -This procedure returns the negation of its argument. When compiled, it -does not check the type of its argument. Equivalent to @code{(flo:- 0. -@var{flonum})}. -@end deffn - -@deffn procedure flo:abs flonum -@deffnx procedure flo:exp flonum -@deffnx procedure flo:log flonum -@deffnx procedure flo:sin flonum -@deffnx procedure flo:cos flonum -@deffnx procedure flo:tan flonum -@deffnx procedure flo:asin flonum -@deffnx procedure flo:acos flonum -@deffnx procedure flo:atan flonum -@deffnx procedure flo:sqrt flonum -@deffnx procedure flo:expt flonum1 flonum2 -@deffnx procedure flo:floor flonum -@deffnx procedure flo:ceiling flonum -@deffnx procedure flo:truncate flonum -@deffnx procedure flo:round flonum -@deffnx procedure flo:floor->exact flonum -@deffnx procedure flo:ceiling->exact flonum -@deffnx procedure flo:truncate->exact flonum -@deffnx procedure flo:round->exact flonum -These procedures are flonum versions of the corresponding procedures. -When compiled, they do not check the types of their arguments. -@end deffn - -@deffn procedure flo:atan2 flonum1 flonum2 -@findex atan -This is the flonum version of @code{atan} with two arguments. When -compiled, it does not check the types of its arguments. -@end deffn - -@node Random Numbers, , Fixnum and Flonum Operations, Numbers -@section Random Numbers -@cindex random number -@cindex pseudo-random number -@cindex number, pseudo-random - -MIT/GNU Scheme provides a facility for generating pseudo-random numbers. -The current implementation is a ``subtract-with-carry'' random-number -generator, based on the algorithm from @cite{A New Class of Random -Number Generators}, George Marsaglia and Arif Zaman, @cite{The Annals of -Applied Probability}, Vol.@: 1, No.@: 3, 1991. At the time it was -implemented, this was a good algorithm for general purposes, but the -state of the art in random-number generation is constantly changing. If -necessary, the implementation will be updated to use a new algorithm -while retaining the same interface. - -The interface described here is very similar to that of Common Lisp. - -@deffn procedure random modulus [state] -@var{Modulus} must be a positive real number. @code{random} returns a -pseudo-random number between zero (inclusive) and @var{modulus} -(exclusive). The exactness of the returned number is the same as the -exactness of @var{modulus}. Additionally, if @var{modulus} is an exact -integer, the returned number will be also. Usually, @var{modulus} is -either an exact integer or an inexact real; the current implementation -has been tuned to make these two cases fast. - -If @var{state} is given and not @code{#f}, it must be a random-state -object; otherwise, it defaults to the value of the variable -@code{*random-state*}. This object is used to maintain the state of the -pseudo-random-number generator and is altered as a side effect of the -@code{random} procedure. - -@example -@group -(random 1.0) @result{} .32744744667719056 -(random 1.0) @result{} .01668326768172354 -(random 10) @result{} 3 -(random 10) @result{} 8 -(random 100) @result{} 38 -(random 100) @result{} 63 -(random 100/3) @result{} 130501475769920525/6755399441055744 -(random 100/3) @result{} 170571694016427575/13510798882111488 -@end group -@end example -@end deffn - -@deffn procedure flo:random-unit state -@var{State} must be a random-state object. @code{flo:random-unit} -returns a pseudo-random number between zero inclusive and one exclusive; -the returned number is always a flonum and therefore an inexact real -number. @code{flo:random-unit} is equivalent to @code{random} with a -@var{modulus} of @code{1.0}, except that it is faster. -@end deffn - -The next three definitions concern random-state objects. In addition to -these definitions, it is important to know that random-state objects are -specifically designed so that they can be saved to disk using the -@code{fasdump} procedure, and later restored using the @code{fasload} -procedure. This allows a particular random-state object to be saved in -order to replay a particular pseudo-random sequence. - -@defvr variable *random-state* -This variable holds a data structure, a random-state object, that -encodes the internal state of the random-number generator that -@code{random} uses by default. A call to @code{random} will perform a -side effect on this data structure. This variable may be changed, using -@code{set!} or @code{fluid-let}, to hold a new random-state object. -@end defvr - -@deffn procedure make-random-state [state] -This procedure returns a new random-state object, suitable for use as -the value of the variable @code{*random-state*}, or as the @var{state} -argument to @code{random}. If @var{state} is not given or @code{#f}, -@code{make-random-state} returns a @emph{copy} of the current -random-number state object (the value of the variable -@code{*random-state*}). If @var{state} is a random-state object, a copy -of that object is returned. If @var{state} is @code{#t}, then a new -random-state object is returned that has been ``randomly'' initialized -by some means (such as by a time-of-day clock). -@end deffn - -@deffn procedure random-state? object -Returns @code{#t} if @var{object} is a random-state object, otherwise -returns @code{#f}. -@end deffn - -@node Characters, Strings, Numbers, Top -@chapter Characters - -@cindex character (defn) -Characters are objects that represent printed characters, such as -letters and digits.@footnote{Some of the details in this section depend -on the fact that the underlying operating system uses the -@acronym{ASCII} character set. This may change when someone ports MIT/GNU -Scheme to a non-@acronym{ASCII} operating system.} - -@menu -* External Representation of Characters:: -* Comparison of Characters:: -* Miscellaneous Character Operations:: -* Internal Representation of Characters:: -* ISO-8859-1 Characters:: -* Character Sets:: -* Unicode:: -@end menu - -@node External Representation of Characters, Comparison of Characters, Characters, Characters -@section External Representation of Characters -@cindex external representation, for character - -@cindex #\ as external representation -@findex #\ -Characters are written using the notation @code{#\@var{character}} or -@code{#\@var{character-name}}. For example: - -@example -@group -#\a @r{; lowercase letter} -#\A @r{; uppercase letter} -#\( @r{; left parenthesis} -#\space @r{; the space character} -#\newline @r{; the newline character} -@end group -@end example -@findex #\space -@findex #\newline - -@noindent -Case is significant in @code{#\@var{character}}, but not in -@code{#\@var{character-name}}. If @var{character} in -@code{#\@var{character}} is a letter, @var{character} must be followed -by a delimiter character such as a space or parenthesis. Characters -written in the @code{#\} notation are self-evaluating; you don't need to -quote them. - -@cindex bucky bit, prefix (defn) -@cindex control, bucky bit prefix (defn) -@cindex meta, bucky bit prefix (defn) -@cindex super, bucky bit prefix (defn) -@cindex hyper, bucky bit prefix (defn) -@cindex top, bucky bit prefix (defn) -A character name may include one or more @dfn{bucky bit} prefixes to -indicate that the character includes one or more of the keyboard shift -keys Control, Meta, Super, Hyper, or Top (note that the Control bucky -bit prefix is not the same as the @acronym{ASCII} control key). The -bucky bit prefixes and their meanings are as follows (case is not -significant): - -@example -@group -Key Bucky bit prefix Bucky bit ---- ---------------- --------- - -Meta M- or Meta- 1 -Control C- or Control- 2 -Super S- or Super- 4 -Hyper H- or Hyper- 8 -Top T- or Top- 16 -@end group -@end example - -@noindent -For example, - -@example -@group -#\c-a @r{; Control-a} -#\meta-b @r{; Meta-b} -#\c-s-m-h-a @r{; Control-Meta-Super-Hyper-A} -@end group -@end example - -@cindex character, named (defn) -@cindex name, of character -The following @var{character-name}s are supported, shown here with their -@acronym{ASCII} equivalents: - -@example -@group -Character Name ASCII Name --------------- ---------- - -altmode ESC -backnext US -backspace BS -call SUB -linefeed LF -page FF -return CR -rubout DEL -space -tab HT -@end group -@end example -@findex #\altmode -@findex #\backnext -@findex #\backspace -@findex #\call -@findex #\linefeed -@findex #\page -@findex #\return -@findex #\rubout -@findex #\space -@findex #\tab - -@noindent -@cindex newline character (defn) -@findex #\newline -In addition, @code{#\newline} is the same as @code{#\linefeed} (but this -may change in the future, so you should not depend on it). All of the -standard @acronym{ASCII} names for non-printing characters are supported: - -@example -@group -NUL SOH STX ETX EOT ENQ ACK BEL -BS HT LF VT FF CR SO SI -DLE DC1 DC2 DC3 DC4 NAK SYN ETB -CAN EM SUB ESC FS GS RS US -DEL -@end group -@end example - -@deffn procedure char->name char [slashify?] -Returns a string corresponding to the printed representation of -@var{char}. This is the @var{character} or @var{character-name} -component of the external representation, combined with the appropriate -bucky bit prefixes. - -@example -@group -(char->name #\a) @result{} "a" -(char->name #\space) @result{} "Space" -(char->name #\c-a) @result{} "C-a" -(char->name #\control-a) @result{} "C-a" -@end group -@end example - -@findex read -@var{Slashify?}, if specified and true, says to insert the necessary -backslash characters in the result so that @code{read} will parse it -correctly. In other words, the following generates the external -representation of @var{char}: - -@example -(string-append "#\\" (char->name @var{char} #t)) -@end example - -@noindent -If @var{slashify?} is not specified, it defaults to @code{#f}. -@end deffn - -@deffn procedure name->char string -Converts a string that names a character into the character specified. -If @var{string} does not name any character, @code{name->char} signals -an error. - -@example -@group -(name->char "a") @result{} #\a -(name->char "space") @result{} #\Space -(name->char "c-a") @result{} #\C-a -(name->char "control-a") @result{} #\C-a -@end group -@end example -@end deffn - -@node Comparison of Characters, Miscellaneous Character Operations, External Representation of Characters, Characters -@section Comparison of Characters -@cindex ordering, of characters -@cindex comparison, of characters -@cindex equivalence predicates, for characters - -@deffn procedure char=? char1 char2 -@deffnx procedure char? char1 char2 -@deffnx procedure char<=? char1 char2 -@deffnx procedure char>=? char1 char2 -@deffnx {procedure} char-ci=? char1 char2 -@deffnx {procedure} char-ci? char1 char2 -@deffnx {procedure} char-ci<=? char1 char2 -@deffnx {procedure} char-ci>=? char1 char2 -@cindex equivalence predicate, for characters -Returns @code{#t} if the specified characters are have the appropriate -order relationship to one another; otherwise returns @code{#f}. The -@code{-ci} procedures don't distinguish uppercase and lowercase letters. - -Character ordering follows these rules: - -@itemize @bullet -@item -The digits are in order; for example, @code{(chardigit char [radix] -If @var{char} is a character representing a digit in the given -@var{radix}, returns the corresponding integer value. If you specify -@var{radix} (which must be an exact integer between 2 and 36 inclusive), -the conversion is done in that base, otherwise it is done in base 10. -If @var{char} doesn't represent a digit in base @var{radix}, -@code{char->digit} returns @code{#f}. - -Note that this procedure is insensitive to the alphabetic case of -@var{char}. - -@example -@group -(char->digit #\8) @result{} 8 -(char->digit #\e 16) @result{} 14 -(char->digit #\e) @result{} #f -@end group -@end example -@end deffn - -@deffn procedure digit->char digit [radix] -Returns a character that represents @var{digit} in the radix given by -@var{radix}. @var{Radix} must be an exact integer between 2 and 36 -(inclusive), and defaults to 10. @var{Digit}, which must be an -exact non-negative integer, should be less than @var{radix}; if -@var{digit} is greater than or equal to @var{radix}, @code{digit->char} -returns @code{#f}. - -@example -@group -(digit->char 8) @result{} #\8 -(digit->char 14 16) @result{} #\E -@end group -@end example -@end deffn - -@node Internal Representation of Characters, ISO-8859-1 Characters, Miscellaneous Character Operations, Characters -@section Internal Representation of Characters -@cindex internal representation, for character - -@cindex character code (defn) -@cindex character bits (defn) -@cindex code, of character (defn) -@cindex bucky bit, of character (defn) -@cindex ASCII character -An MIT/GNU Scheme character consists of a @dfn{code} part and a @dfn{bucky -bits} part. The MIT/GNU Scheme set of characters can represent more -characters than @acronym{ASCII} can; it includes characters with Super, -Hyper, and Top bucky bits, as well as Control and Meta. Every -@acronym{ASCII} character corresponds to some MIT/GNU Scheme character, but not -vice versa.@footnote{Note that the Control bucky bit is different from -the @acronym{ASCII} control key. This means that @code{#\SOH} (@acronym{ASCII} -ctrl-A) is different from @code{#\C-A}. In fact, the Control bucky bit -is completely orthogonal to the @acronym{ASCII} control key, making possible -such characters as @code{#\C-SOH}.} - -MIT/GNU Scheme uses a 16-bit character code with 5 bucky bits. Normally, -Scheme uses the least significant 8 bits of the character code to -contain the @acronym{ISO-8859-1} representation for the character. The -representation is expanded in order to allow for the use of -@acronym{UTF-16} in the future. - -@deffn procedure make-char code bucky-bits -@cindex construction, of character -Builds a character from @var{code} and @var{bucky-bits}. Both -@var{code} and @var{bucky-bits} must be exact non-negative integers in -the appropriate range. Use @code{char-code} and @code{char-bits} to -extract the code and bucky bits from the character. If @code{0} is -specified for @var{bucky-bits}, @code{make-char} produces an ordinary -character; otherwise, the appropriate bits are turned on as follows: - -@example -@group -1 Meta -2 Control -4 Super -8 Hyper -16 Top -@end group -@end example - -For example, - -@example -@group -(make-char 97 0) @result{} #\a -(make-char 97 1) @result{} #\M-a -(make-char 97 2) @result{} #\C-a -(make-char 97 3) @result{} #\C-M-a -@end group -@end example -@end deffn - -@deffn procedure char-bits char -@cindex selection, of character component -@cindex component selection, of character -Returns the exact integer representation of @var{char}'s bucky bits. -For example, - -@example -@group -(char-bits #\a) @result{} 0 -(char-bits #\m-a) @result{} 1 -(char-bits #\c-a) @result{} 2 -(char-bits #\c-m-a) @result{} 3 -@end group -@end example -@end deffn - -@deffn procedure char-code char -Returns the character code of @var{char}, an exact integer. For -example, - -@example -@group -(char-code #\a) @result{} 97 -(char-code #\c-a) @result{} 97 -@end group -@end example -@end deffn - -@defvr variable char-code-limit -@defvrx variable char-bits-limit -These variables define the (exclusive) upper limits for the character -code and bucky bits (respectively). The character code and bucky bits -are always exact non-negative integers, and are strictly less than the -value of their respective limit variable. -@end defvr - -@deffn procedure char->integer char -@deffnx procedure integer->char k -@code{char->integer} returns the character code representation for -@var{char}. @code{integer->char} returns the character whose character -code representation is @var{k}. - -@findex char-ascii? -@findex char->ascii -In MIT/GNU Scheme, if @code{(char-ascii? @var{char})} is true, then - -@example -(eqv? (char->ascii @var{char}) (char->integer @var{char})) -@end example - -@noindent -However, this behavior is not required by the Scheme standard, and -code that depends on it is not portable to other implementations. - -@findex char<=? -@findex <= -These procedures implement order isomorphisms between the set of -characters under the @code{char<=?} ordering and some subset of the -integers under the @code{<=} ordering. That is, if - -@example -(char<=? a b) @result{} #t @r{and} (<= x y) @result{} #t -@end example - -and @code{x} and @code{y} are in the range of @code{char->integer}, -then - -@example -@group -(<= (char->integer a) - (char->integer b)) @result{} #t -(char<=? (integer->char x) - (integer->char y)) @result{} #t -@end group -@end example - -Note: If the argument to @code{char->integer} or @code{integer->char} is -a constant, the compiler will constant-fold the call, replacing it with -the corresponding result. This is a very useful way to denote unusual -character constants or @acronym{ASCII} codes. -@end deffn - -@defvr variable char-integer-limit -The range of @code{char->integer} is defined to be the exact -non-negative integers that are less than the value of this variable -(exclusive). -@end defvr - -@node ISO-8859-1 Characters, Character Sets, Internal Representation of Characters, Characters -@section ISO-8859-1 Characters - -MIT/GNU Scheme internally uses @acronym{ISO-8859-1} codes for -@acronym{I/O}, and stores character objects in a fashion that makes it -convenient to convert between @acronym{ISO-8859-1} codes and -characters. Also, character strings are implemented as byte vectors -whose elements are @acronym{ISO-8859-1} codes; these codes are -converted to character objects when accessed. For these reasons it is -sometimes desirable to be able to convert between @acronym{ISO-8859-1} -codes and characters. - -@cindex ISO-8859-1 character (defn) -@cindex character, ISO-8859-1 (defn) -Not all characters can be represented as @acronym{ISO-8859-1} codes. A -character that has an equivalent @acronym{ISO-8859-1} representation is -called an @dfn{ISO-8859-1 character}. - -For historical reasons, the procedures that manipulate -@acronym{ISO-8859-1} characters use the word ``@acronym{ASCII}'' rather -than ``@acronym{ISO-8859-1}''. - -@deffn procedure char-ascii? char -Returns the @acronym{ISO-8859-1} code for @var{char} if @var{char} has an -@acronym{ISO-8859-1} representation; otherwise returns @code{#f}. - -In the current implementation, the characters that satisfy this -predicate are those in which the bucky bits are turned off, and for -which the character code is less than 256. -@end deffn - -@deffn procedure char->ascii char -Returns the @acronym{ISO-8859-1} code for @var{char}. An error -@code{condition-type:bad-range-argument} is signalled if @var{char} -doesn't have an @acronym{ISO-8859-1} representation. -@findex condition-type:bad-range-argument -@end deffn - -@deffn procedure ascii->char code -@var{Code} must be the exact integer representation of an -@acronym{ISO-8859-1} code. This procedure returns the character -corresponding to @var{code}. -@end deffn - -@node Character Sets, Unicode, ISO-8859-1 Characters, Characters -@section Character Sets -@cindex character set -@cindex set, of characters - -MIT/GNU Scheme's character-set abstraction is used to represent groups of -characters, such as the letters or digits. Character sets may contain -only @acronym{ISO-8859-1} characters; in the future this may be changed -to allow the full range of characters. - -There is no meaningful external representation for character sets; use -@code{char-set-members} to examine their contents. There is (at -present) no specific equivalence predicate for character sets; use -@code{equal?} for this purpose. - -@deffn procedure char-set? object -@cindex type predicate, for character set -Returns @code{#t} if @var{object} is a character set; otherwise returns -@code{#f}. -@end deffn - -@defvr variable char-set:upper-case -@defvrx variable char-set:lower-case -@defvrx variable char-set:alphabetic -@defvrx variable char-set:numeric -@defvrx variable char-set:alphanumeric -@defvrx variable char-set:whitespace -@defvrx variable char-set:not-whitespace -@defvrx variable char-set:graphic -@defvrx variable char-set:not-graphic -@defvrx variable char-set:standard -These variables contain predefined character sets. -To see the contents of one of these sets, use @code{char-set-members}. - -@cindex alphabetic character (defn) -@cindex character, alphabetic (defn) -@cindex numeric character (defn) -@cindex character, numeric (defn) -@cindex alphanumeric character (defn) -@cindex character, alphanumeric (defn) -@cindex whitespace character (defn) -@cindex character, whitespace (defn) -@cindex graphic character (defn) -@cindex character, graphic (defn) -@cindex standard character (defn) -@cindex character, standard (defn) -@findex #\space -@findex #\tab -@findex #\page -@findex #\linefeed -@findex #\return -@findex #\newline -@dfn{Alphabetic} characters are the 52 upper and lower case letters. -@dfn{Numeric} characters are the 10 decimal digits. @dfn{Alphanumeric} -characters are those in the union of these two sets. @dfn{Whitespace} -characters are @code{#\space}, @code{#\tab}, @code{#\page}, -@code{#\linefeed}, and @code{#\return}. @var{Graphic} characters are -the printing characters and @code{#\space}. @var{Standard} characters -are the printing characters, @code{#\space}, and @code{#\newline}. -These are the printing characters: - -@example -@group -! " # $ % & ' ( ) * + , - . / -0 1 2 3 4 5 6 7 8 9 -: ; < = > ? @@ -A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -[ \ ] ^ _ ` -a b c d e f g h i j k l m n o p q r s t u v w x y z -@{ | @} ~ -@end group -@end example -@end defvr - -@deffn {procedure} char-upper-case? char -@deffnx {procedure} char-lower-case? char -@deffnx {procedure} char-alphabetic? char -@deffnx {procedure} char-numeric? char -@deffnx procedure char-alphanumeric? char -@deffnx {procedure} char-whitespace? char -@deffnx procedure char-graphic? char -@deffnx procedure char-standard? object -These predicates are defined in terms of the respective character sets -defined above. -@end deffn - -@deffn procedure char-set-members char-set -Returns a newly allocated list of the characters in @var{char-set}. -@end deffn - -@deffn procedure char-set-member? char-set char -Returns @code{#t} if @var{char} is in @var{char-set}; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure char-set char @dots{} -@cindex construction, of character set -Returns a character set consisting of the specified @acronym{ISO-8859-1} -characters. With no arguments, @code{char-set} returns an empty -character set. -@end deffn - -@deffn procedure chars->char-set chars -Returns a character set consisting of @var{chars}, which must be a list -of @acronym{ISO-8859-1} characters. This is equivalent to @code{(apply -char-set @var{chars})}. -@end deffn - -@deffn procedure string->char-set string -Returns a character set consisting of all the characters that occur in -@var{string}. -@end deffn - -@deffn procedure ascii-range->char-set lower upper -@var{Lower} and @var{upper} must be exact non-negative integers -representing @acronym{ISO-8859-1} character codes, and @var{lower} must -be less than or equal to @var{upper}. This procedure creates and -returns a new character set consisting of the characters whose -@acronym{ISO-8859-1} codes are between @var{lower} (inclusive) and -@var{upper} (exclusive). - -For historical reasons, the name of this procedure refers to -``@acronym{ASCII}'' rather than ``@acronym{ISO-8859-1}''. -@end deffn - -@deffn procedure predicate->char-set predicate -@var{Predicate} must be a procedure of one argument. -@code{predicate->char-set} creates and returns a character set -consisting of the @acronym{ISO-8859-1} characters for which -@var{predicate} is true. -@end deffn - -@deffn procedure char-set-difference char-set1 char-set2 -Returns a character set consisting of the characters that are in -@var{char-set1} but aren't in @var{char-set2}. -@end deffn - -@deffn procedure char-set-intersection char-set @dots{} -Returns a character set consisting of the characters that are in all of -the @var{char-set}s. -@end deffn - -@deffn procedure char-set-union char-set @dots{} -Returns a character set consisting of the characters that are in at -least one o the @var{char-set}s. -@end deffn - -@deffn procedure char-set-invert char-set -Returns a character set consisting of the @acronym{ISO-8859-1} -characters that are not in @var{char-set}. -@end deffn - -@node Unicode, , Character Sets, Characters -@section Unicode - -@cindex Unicode -MIT/GNU Scheme provides rudimentary support for Unicode characters. In an -ideal world, Unicode would be the base character set for MIT/GNU Scheme, -but this implementation predates the invention of Unicode. And -converting an application of this size is a considerable undertaking. -So for the time being, the base character set is @acronym{ISO-8859-1} -and Unicode support is grafted on. - -This Unicode support was implemented as a part of the @acronym{XML} -parser (@pxref{XML Parser}) implementation. @acronym{XML} uses -Unicode as its base character set, and any @acronym{XML} -implementation @emph{must} support Unicode. - -The Unicode implementation consists of two parts: @acronym{I/O} -procedures that read and write @acronym{UTF-8} characters, and an -@dfn{alphabet} abstraction, which is an efficient implementation of -sets of Unicode code points (similar to the @code{char-set} -abstraction). - -@cindex Code point, Unicode -The basic unit in a Unicode implementation is the @dfn{code point}. - -@deffn procedure unicode-code-point? object -Returns @code{#t} if @var{object} is a Unicode code point. Code -points are implemented as exact non-negative integers. Code points -are further limited, by the Unicode standard, to be strictly less than -@code{#x80000000}. -@end deffn - -The next few procedures do @acronym{I/O} on code points. - -@deffn procedure read-utf8-code-point port -Reads and returns a @acronym{UTF-8}-encoded code point from -@var{port}. Returns an end-of-file object if there are no more -characters available from @var{port}. Signals an error if the input -stream isn't a valid @acronym{UTF-8} encoding. -@end deffn - -@deffn procedure write-utf8-code-point code-point port -Writes @var{code-point} to @var{port} in the @acronym{UTF-8} encoding. -@end deffn - -@deffn procedure utf8-string->code-point string -Reads and returns a @acronym{UTF-8}-encoded code point from -@var{string}. Equivalent to - -@example -(read-utf8-code-point (string->input-port @var{string})) -@end example -@end deffn - -@deffn procedure code-point->utf8-string code-point -Returns a newly-allocated string containing the @acronym{UTF-8} -encoding of @var{code-point}. Equivalent to - -@example -@group -(with-string-output-port - (lambda (port) - (write-utf8-code-point @var{code-point} port))) -@end group -@end example -@end deffn - -@cindex Alphabet, Unicode -Applications often need to manipulate sets of characters, such as the -set of alphabetic characters or the set of whitespace characters. The -@dfn{alphabet} abstraction provides an efficient implementation of -sets of Unicode code points. - -@deffn procedure alphabet? object -Returns @code{#t} if @var{object} is a Unicode alphabet, otherwise -returns @code{#f}. -@end deffn - -@deffn procedure code-points->alphabet items -Returns a Unicode alphabet containing the code points described by -@var{items}. @var{Items} must satisfy -@code{well-formed-code-points-list?}. -@end deffn - -@deffn procedure alphabet->code-points alphabet -Returns a well-formed code-points list that describes the code points -represented by @var{alphabet}. -@end deffn - -@deffn procedure well-formed-code-points-list? object -Returns @code{#t} if @var{object} is a well-formed code-points list, -otherwise returns @code{#f}. A well-formed code-points list is a -proper list, each element of which is either a code point or a pair of -code points. A pair of code points represents a contiguous range of -code points. The @sc{car} of the pair is the lower limit, and the -@sc{cdr} is the upper limit. Both limits are inclusive, and the lower -limit must be strictly less than the upper limit. -@end deffn - -@deffn procedure code-point-in-alphabet? code-point alphabet -Returns @code{#t} if @var{code-point} is a member of @var{alphabet}, -otherwise returns @code{#f}. -@end deffn - -@deffn procedure char-in-alphabet? char alphabet -Returns @code{#t} if @var{char} is a member of @var{alphabet}, -otherwise returns @code{#f}. Equivalent to - -@example -(code-point-in-alphabet? (char-code @var{char}) @var{alphabet}) -@end example -@end deffn - -Character sets and alphabets can be converted to one another, provided -that the alphabet contains only 8-bit code points. This is true -because 8-bit code points in Unicode map directly to -@acronym{ISO-8859-1} characters, which is what character sets contain. - -@deffn procedure char-set->alphabet char-set -Returns a Unicode alphabet containing the code points that correspond -to characters that are members of @var{char-set}. -@end deffn - -@deffn procedure alphabet->char-set alphabet -Returns a character set containing the characters that correspond to -8-bit code points that are members of @var{alphabet}. (Code points -outside the 8-bit range are ignored.) -@end deffn - -@deffn procedure string->alphabet string -Returns a Unicode alphabet containing the code points corresponding to -the characters in @var{string}. Equivalent to - -@example -(char-set->alphabet (string->char-set @var{string})) -@end example -@end deffn - -@deffn procedure alphabet->string alphabet -Returns a newly-allocated string containing the characters -corresponding to the 8-bit code points in @var{alphabet}. (Code -points outside the 8-bit range are ignored.) -@end deffn - -@deffn procedure 8-bit-alphabet? alphabet -Returns @code{#t} if @var{alphabet} contains only 8-bit code points, -otherwise returns @code{#f}. -@end deffn - -@deffn procedure alphabet+ alphabet @dots{} -Returns a Unicode alphabet that contains each code point that is a -member of any of the @var{alphabet} arguments. -@end deffn - -@deffn procedure alphabet- alphabet1 alphabet2 -Returns a Unicode alphabet that contains each code point that is a -member of @var{alphabet1} and is not a member of @var{alphabet2}. -@end deffn - -@node Strings, Lists, Characters, Top -@chapter Strings - -@cindex string, character (defn) -@findex char-ascii? -A @dfn{string} is a mutable sequence of characters. In the current -implementation of MIT/GNU Scheme, the elements of a string must all -satisfy the predicate @code{char-ascii?}; if someone ports MIT/GNU -Scheme to a non-@acronym{ASCII} operating system this requirement will -change. - -@cindex external representation, for string -@cindex " as external representation -@cindex double quote, as external representation -@cindex \ as escape character in string -@cindex backslash, as escape character in string -@cindex escape character, for string -@findex " -@findex \ -A string is written as a sequence of characters enclosed within double -quotes @code{" "}. To include a double quote inside a string, precede -the double quote with a backslash @code{\} (escape it), as in - -@example -"The word \"recursion\" has many meanings." -@end example - -@noindent -The printed representation of this string is - -@example -The word "recursion" has many meanings. -@end example - -@noindent -To include a backslash inside a string, precede it with another -backslash; for example, - -@example -"Use #\\Control-q to quit." -@end example - -@noindent -The printed representation of this string is - -@example -Use #\Control-q to quit. -@end example - -@findex \t -@findex \n -@findex \f -@findex #\tab -@findex #\newline -@findex #\page -The effect of a backslash that doesn't precede a double quote or -backslash is unspecified in standard Scheme, but MIT/GNU Scheme specifies -the effect for three other characters: @code{\t}, @code{\n}, and -@code{\f}. These escape sequences are respectively translated into the -following characters: @code{#\tab}, @code{#\newline}, and @code{#\page}. -Finally, a backslash followed by exactly three octal digits is -translated into the character whose @acronym{ISO-8859-1} code is those -digits. - -If a string literal is continued from one line to another, the string -will contain the newline character (@code{#\newline}) at the line break. -Standard Scheme does not specify what appears in a string literal at a -line break. - -@cindex length, of string (defn) -@cindex index, of string (defn) -@cindex valid index, of string (defn) -@cindex string length (defn) -@cindex string index (defn) -The @dfn{length} of a string is the number of characters that it -contains. This number is an exact non-negative integer that is -established when the string is created -(but @pxref{Variable-Length Strings}). -Each character in a string has an @dfn{index}, which is a -number that indicates the character's position in the string. The index -of the first (leftmost) character in a string is 0, and the index of the -last character is one less than the length of the string. The -@dfn{valid indexes} of a string are the exact non-negative integers less -than the length of the string. - -@cindex substring (defn) -@cindex start, of substring (defn) -@cindex end, of substring (defn) -A number of the string procedures operate on substrings. A -@dfn{substring} is a segment of a @var{string}, which is specified by -two integers @var{start} and @var{end} satisfying these relationships: - -@example -0 <= @var{start} <= @var{end} <= (string-length @var{string}) -@end example - -@noindent -@var{Start} is the index of the first character in the substring, and -@var{end} is one greater than the index of the last character in the -substring. Thus if @var{start} and @var{end} are equal, they refer to -an empty substring, and if @var{start} is zero and @var{end} is the -length of @var{string}, they refer to all of @var{string}. - -@cindex case sensitivity, of string operations -@cindex -ci, in string procedure name -Some of the procedures that operate on strings ignore the difference -between uppercase and lowercase. The versions that ignore case include -@samp{-ci} (for ``case insensitive'') in their names. - -@menu -* Construction of Strings:: -* Selecting String Components:: -* Comparison of Strings:: -* Alphabetic Case in Strings:: -* Cutting and Pasting Strings:: -* Searching Strings:: -* Matching Strings:: -* Regular Expressions:: -* Modification of Strings:: -* Variable-Length Strings:: -* Byte Vectors:: -@end menu - -@node Construction of Strings, Selecting String Components, Strings, Strings -@section Construction of Strings -@cindex construction, of string - -@deffn {procedure} make-string k [char] -Returns a newly allocated string of length @var{k}. If you specify -@var{char}, all elements of the string are initialized to @var{char}, -otherwise the contents of the string are unspecified. @var{Char} must -satisfy the predicate @code{char-ascii?}. - -@example -(make-string 10 #\x) @result{} "xxxxxxxxxx" -@end example -@end deffn - -@deffn procedure string char @dots{} -Returns a newly allocated string consisting of the specified characters. -The arguments must all satisfy @code{char-ascii?}. - -@example -@group -(string #\a) @result{} "a" -(string #\a #\b #\c) @result{} "abc" -(string #\a #\space #\b #\space #\c) @result{} "a b c" -(string) @result{} "" -@end group -@end example -@end deffn - -@deffn procedure list->string char-list -@cindex list, converting to string -@findex string->list -@var{Char-list} must be a list of @acronym{ISO-8859-1} characters. -@code{list->string} returns a newly allocated string formed from the -elements of @var{char-list}. This is equivalent to @code{(apply string -@var{char-list})}. The inverse of this operation is -@code{string->list}. - -@example -@group -(list->string '(#\a #\b)) @result{} "ab" -(string->list "Hello") @result{} (#\H #\e #\l #\l #\o) -@end group -@end example -@end deffn - -@deffn {procedure} string-copy string -@cindex copying, of string -Returns a newly allocated copy of @var{string}. - -Note regarding variable-length strings: the maximum length of the result -depends only on the length of @var{string}, not its maximum length. If -you wish to copy a string and preserve its maximum length, do the -following: - -@example -@group -(define (string-copy-preserving-max-length string) - (let ((length)) - (dynamic-wind - (lambda () - (set! length (string-length string)) - (set-string-length! string - (string-maximum-length string))) - (lambda () - (string-copy string)) - (lambda () - (set-string-length! string length))))) -@end group -@end example -@end deffn - -@node Selecting String Components, Comparison of Strings, Construction of Strings, Strings -@section Selecting String Components -@cindex selection, of string component -@cindex component selection, of string - -@deffn procedure string? object -@cindex type predicate, for string -Returns @code{#t} if @var{object} is a string; otherwise returns -@code{#f}. - -@example -@group -(string? "Hi") @result{} #t -(string? 'Hi) @result{} #f -@end group -@end example -@end deffn - -@deffn procedure string-length string -Returns the length of @var{string} as an exact non-negative integer. - -@example -@group -(string-length "") @result{} 0 -(string-length "The length") @result{} 10 -@end group -@end example -@end deffn - -@deffn procedure string-null? string -@cindex empty string, predicate for -@cindex null string, predicate for -Returns @code{#t} if @var{string} has zero length; otherwise returns -@code{#f}. - -@example -@group -(string-null? "") @result{} #t -(string-null? "Hi") @result{} #f -@end group -@end example -@end deffn - -@deffn procedure string-ref string k -Returns character @var{k} of @var{string}. @var{K} must be a valid index -of @var{string}. - -@example -@group -(string-ref "Hello" 1) @result{} #\e -(string-ref "Hello" 5) @error{} 5 not in correct range -@end group -@end example -@end deffn - -@deffn {procedure} string-set! string k char -Stores @var{char} in element @var{k} of @var{string} and returns an -unspecified value. @var{K} must be a valid index of @var{string}, and -@var{char} must satisfy the predicate @code{char-ascii?}. - -@example -@group -(define str "Dog") @result{} @r{unspecified} -(string-set! str 0 #\L) @result{} @r{unspecified} -str @result{} "Log" -(string-set! str 3 #\t) @error{} 3 not in correct range -@end group -@end example -@end deffn - -@need 1000 -@node Comparison of Strings, Alphabetic Case in Strings, Selecting String Components, Strings -@section Comparison of Strings -@cindex ordering, of strings -@cindex comparison, of strings - -@deffn procedure string=? string1 string2 -@deffnx procedure substring=? string1 start end string2 start end -@deffnx {procedure} string-ci=? string1 string2 -@deffnx procedure substring-ci=? string1 start end string2 start end -@cindex equivalence predicate, for strings -Returns @code{#t} if the two strings (substrings) are the same length -and contain the same characters in the same (relative) positions; -otherwise returns @code{#f}. @code{string-ci=?} and -@code{substring-ci=?} don't distinguish uppercase and lowercase letters, -but @code{string=?} and @code{substring=?} do. - -@example -@group -(string=? "PIE" "PIE") @result{} #t -(string=? "PIE" "pie") @result{} #f -(string-ci=? "PIE" "pie") @result{} #t -(substring=? "Alamo" 1 3 "cola" 2 4) @result{} #t @r{; compares "la"} -@end group -@end example -@end deffn - -@deffn procedure string? string1 string2 -@deffnx procedure string<=? string1 string2 -@deffnx procedure string>=? string1 string2 -@deffnx {procedure} string-ci? string1 string2 -@deffnx {procedure} string-ci<=? string1 string2 -@deffnx {procedure} string-ci>=? string1 string2 -These procedures compare strings (substrings) according to the order of -the characters they contain (also @pxref{Comparison of Characters}). -The arguments are compared using a lexicographic (or dictionary) order. -If two strings differ in length but are the same up to the length of the -shorter string, the shorter string is considered to be less than the -longer string. - -@example -@group -(string? "catkin" "cat") @result{} #t @r{; shorter is lesser} -@end group -@end example -@end deffn - -@deffn procedure string-compare string1 string2 if-eq if-lt if-gt -@deffnx procedure string-compare-ci string1 string2 if-eq if-lt if-gt -@var{If-eq}, @var{if-lt}, and @var{if-gt} are procedures of no arguments -(thunks). The two strings are compared; if they are equal, @var{if-eq} -is applied, if @var{string1} is less than @var{string2}, @var{if-lt} is -applied, else if @var{string1} is greater than @var{string2}, -@var{if-gt} is applied. The value of the procedure is the value of the -thunk that is applied. - -@code{string-compare} distinguishes uppercase and lowercase letters;@* -@code{string-compare-ci} does not. - -@example -@group -(define (cheer) (display "Hooray!")) -(define (boo) (display "Boo-hiss!")) -(string-compare "a" "b" cheer (lambda() 'ignore) boo) - @print{} Hooray! - @result{} @r{unspecified} -@end group -@end example -@end deffn - -@deffn procedure string-hash string -@deffnx procedure string-hash-mod string k -@cindex hashing, of string -@findex string=? -@findex = -@code{string-hash} returns an exact non-negative integer that can be used -for storing the specified @var{string} in a hash table. Equal strings -(in the sense of @code{string=?}) return equal (@code{=}) hash codes, -and non-equal but similar strings are usually mapped to distinct hash -codes. - -@code{string-hash-mod} is like @code{string-hash}, except that it limits -the result to a particular range based on the exact non-negative integer -@var{k}. The following are equivalent: - -@example -@group -(string-hash-mod @var{string} @var{k}) -(modulo (string-hash @var{string}) @var{k}) -@end group -@end example -@end deffn - -@node Alphabetic Case in Strings, Cutting and Pasting Strings, Comparison of Strings, Strings -@section Alphabetic Case in Strings -@cindex alphabetic case, of string -@cindex case, of string -@cindex capitalization, of string -@cindex uppercase, in string -@cindex lowercase, in string - -@deffn procedure string-capitalized? string -@deffnx procedure substring-capitalized? string start end -These procedures return @code{#t} if the first word in the string -(substring) is capitalized, and any subsequent words are either lower -case or capitalized. Otherwise, they return @code{#f}. A word is -defined as a non-null contiguous sequence of alphabetic characters, -delimited by non-alphabetic characters or the limits of the string -(substring). A word is capitalized if its first letter is upper case -and all its remaining letters are lower case. - -@example -@group -(map string-capitalized? '("" "A" "art" "Art" "ART")) - @result{} (#f #t #f #t #f) -@end group -@end example -@end deffn - -@deffn procedure string-upper-case? string -@deffnx procedure substring-upper-case? string start end -@deffnx procedure string-lower-case? string -@deffnx procedure substring-lower-case? string start end -These procedures return @code{#t} if all the letters in the string -(substring) are of the correct case, otherwise they return @code{#f}. -The string (substring) must contain at least one letter or the -procedures return @code{#f}. - -@example -@group -(map string-upper-case? '("" "A" "art" "Art" "ART")) - @result{} (#f #t #f #f #t) -@end group -@end example -@end deffn - -@deffn procedure string-capitalize string -@deffnx procedure string-capitalize! string -@deffnx procedure substring-capitalize! string start end -@code{string-capitalize} returns a newly allocated copy of @var{string} -in which the first alphabetic character is uppercase and the remaining -alphabetic characters are lowercase. For example, @code{"abcDEF"} -becomes @code{"Abcdef"}. @code{string-capitalize!} is the destructive -version of @code{string-capitalize}: it alters @var{string} and returns -an unspecified value. @code{substring-capitalize!} destructively -capitalizes the specified part of @var{string}. -@end deffn - -@deffn procedure string-downcase string -@deffnx procedure string-downcase! string -@deffnx procedure substring-downcase! string start end -@code{string-downcase} returns a newly allocated copy of @var{string} in -which all uppercase letters are changed to lowercase. -@code{string-downcase!} is the destructive version of -@code{string-downcase}: it alters @var{string} and returns an -unspecified value. @code{substring-downcase!} destructively changes the -case of the specified part of @var{string}. - -@example -@group -(define str "ABCDEFG") @result{} @r{unspecified} -(substring-downcase! str 3 5) @result{} @r{unspecified} -str @result{} "ABCdeFG" -@end group -@end example -@end deffn - -@deffn procedure string-upcase string -@deffnx procedure string-upcase! string -@deffnx procedure substring-upcase! string start end -@code{string-upcase} returns a newly allocated copy of @var{string} in -which all lowercase letters are changed to uppercase. -@code{string-upcase!} is the destructive version of -@code{string-upcase}: it alters @var{string} and returns an unspecified -value. @code{substring-upcase!} destructively changes the case of the -specified part of @var{string}. -@end deffn - -@node Cutting and Pasting Strings, Searching Strings, Alphabetic Case in Strings, Strings -@section Cutting and Pasting Strings -@cindex cutting, of string -@cindex pasting, of strings - -@deffn {procedure} string-append string @dots{} -@cindex appending, of strings -Returns a newly allocated string made from the concatenation of the given -strings. With no arguments, @code{string-append} returns the empty -string (@code{""}). - -@example -@group -(string-append) @result{} "" -(string-append "*" "ace" "*") @result{} "*ace*" -(string-append "" "" "") @result{} "" -(eq? str (string-append str)) @result{} #f @r{; newly allocated} -@end group -@end example -@end deffn - -@deffn procedure substring string start end -Returns a newly allocated string formed from the characters of -@var{string} beginning with index @var{start} (inclusive) and ending -with @var{end} (exclusive). - -@example -@group -(substring "" 0 0) @result{} "" -(substring "arduous" 2 5) @result{} "duo" -(substring "arduous" 2 8) @error{} 8 not in correct range - -(define (string-copy s) - (substring s 0 (string-length s))) -@end group -@end example -@end deffn - -@deffn procedure string-head string end -Returns a newly allocated copy of the initial substring of @var{string}, -up to but excluding @var{end}. It could have been defined by: - -@example -@group -(define (string-head string end) - (substring string 0 end)) -@end group -@end example -@end deffn - -@deffn procedure string-tail string start -Returns a newly allocated copy of the final substring of @var{string}, -starting at index @var{start} and going to the end of @var{string}. It -could have been defined by: - -@example -@group -(define (string-tail string start) - (substring string start (string-length string))) - -(string-tail "uncommon" 2) @result{} "common" -@end group -@end example -@end deffn - -@deffn procedure string-pad-left string k [char] -@deffnx procedure string-pad-right string k [char] -@cindex padding, of string -@findex #\space -These procedures return a newly allocated string created by padding -@var{string} out to length @var{k}, using @var{char}. If @var{char} is -not given, it defaults to @code{#\space}. If @var{k} is less than the -length of @var{string}, the resulting string is a truncated form of -@var{string}. @code{string-pad-left} adds padding characters or -truncates from the beginning of the string (lowest indices), while -@code{string-pad-right} does so at the end of the string (highest -indices). - -@example -@group -(string-pad-left "hello" 4) @result{} "ello" -(string-pad-left "hello" 8) @result{} " hello" -(string-pad-left "hello" 8 #\*) @result{} "***hello" -(string-pad-right "hello" 4) @result{} "hell" -(string-pad-right "hello" 8) @result{} "hello " -@end group -@end example -@end deffn - -@deffn procedure string-trim string [char-set] -@deffnx procedure string-trim-left string [char-set] -@deffnx procedure string-trim-right string [char-set] -@cindex trimming, of string -@findex char-set:whitespace -Returns a newly allocated string created by removing all characters that -are not in @var{char-set} from: (@code{string-trim}) both ends of -@var{string}; (@code{string-trim-left}) the beginning of @var{string}; -or (@code{string-trim-right}) the end of @var{string}. @var{Char-set} -defaults to @code{char-set:not-whitespace}. - -@example -@group -(string-trim " in the end ") @result{} "in the end" -(string-trim " ") @result{} "" -(string-trim "100th" char-set:numeric) @result{} "100" -(string-trim-left "-.-+-=-" (char-set #\+)) - @result{} "+-=-" -(string-trim "but (+ x y) is" (char-set #\( #\))) - @result{} "(+ x y)" -@end group -@end example -@end deffn - -@node Searching Strings, Matching Strings, Cutting and Pasting Strings, Strings -@section Searching Strings -@cindex searching, of string -@cindex character, searching string for -@cindex substring, searching string for - -The first few procedures in this section perform @dfn{string search}, in -which a given string (the @dfn{text}) is searched to see if it contains -another given string (the @dfn{pattern}) as a proper substring. At -present these procedures are implemented using a hybrid strategy. For -short patterns of less than 4 characters, the naive string-search -algorithm is used. For longer patterns, the Boyer-Moore string-search -algorithm is used. - -@deffn procedure string-search-forward pattern string -@deffnx procedure substring-search-forward pattern string start end -@var{Pattern} must be a string. Searches @var{string} for the leftmost -occurrence of the substring @var{pattern}. If successful, the index of -the first character of the matched substring is returned; otherwise, -@code{#f} is returned. - -@code{substring-search-forward} limits its search to the specified -substring of @var{string}; @code{string-search-forward} searches all of -@var{string}. - -@example -@group -(string-search-forward "rat" "pirate") - @result{} 2 -(string-search-forward "rat" "pirate rating") - @result{} 2 -(substring-search-forward "rat" "pirate rating" 4 13) - @result{} 7 -(substring-search-forward "rat" "pirate rating" 9 13) - @result{} #f -@end group -@end example -@end deffn - -@deffn procedure string-search-backward pattern string -@deffnx procedure substring-search-backward pattern string start end -@var{Pattern} must be a string. Searches @var{string} for the rightmost -occurrence of the substring @var{pattern}. If successful, the index to -the right of the last character of the matched substring is returned; -otherwise, @code{#f} is returned. - -@code{substring-search-backward} limits its search to the specified -substring of @var{string}; @code{string-search-backward} searches all of -@var{string}. - -@example -@group -(string-search-backward "rat" "pirate") - @result{} 5 -(string-search-backward "rat" "pirate rating") - @result{} 10 -(substring-search-backward "rat" "pirate rating" 1 8) - @result{} 5 -(substring-search-backward "rat" "pirate rating" 9 13) - @result{} #f -@end group -@end example -@end deffn - -@deffn procedure string-search-all pattern string -@deffnx procedure substring-search-all pattern string start end -@var{Pattern} must be a string. Searches @var{string} to find all -occurrences of the substring @var{pattern}. Returns a list of the -occurrences; each element of the list is an index pointing to the first -character of an occurrence. - -@code{substring-search-all} limits its search to the specified substring -of @var{string}; @code{string-search-all} searches all of @var{string}. - -@example -@group -(string-search-all "rat" "pirate") - @result{} (2) -(string-search-all "rat" "pirate rating") - @result{} (2 7) -(substring-search-all "rat" "pirate rating" 4 13) - @result{} (7) -(substring-search-all "rat" "pirate rating" 9 13) - @result{} () -@end group -@end example -@end deffn - -@deffn procedure substring? pattern string -@var{Pattern} must be a string. Searches @var{string} to see if it -contains the substring @var{pattern}. Returns @code{#t} if -@var{pattern} is a substring of @var{string}, otherwise returns -@code{#f}. - -@example -@group -(substring? "rat" "pirate") @result{} #t -(substring? "rat" "outrage") @result{} #f -(substring? "" any-string) @result{} #t -(if (substring? "moon" text) - (process-lunar text) - 'no-moon) -@end group -@end example -@end deffn - -@deffn procedure string-find-next-char string char -@deffnx procedure substring-find-next-char string start end char -@deffnx procedure string-find-next-char-ci string char -@deffnx procedure substring-find-next-char-ci string start end char -Returns the index of the first occurrence of @var{char} in the string -(substring); returns @code{#f} if @var{char} does not appear in the -string. For the substring procedures, the index returned is relative to -the entire string, not just the substring. The @code{-ci} procedures -don't distinguish uppercase and lowercase letters. - -@example -@group -(string-find-next-char "Adam" #\A) @result{} 0 -(substring-find-next-char "Adam" 1 4 #\A) @result{} #f -(substring-find-next-char-ci "Adam" 1 4 #\A) @result{} 2 -@end group -@end example -@end deffn - -@deffn procedure string-find-next-char-in-set string char-set -@deffnx procedure substring-find-next-char-in-set string start end char-set -Returns the index of the first character in the string (or substring) -that is also in @var{char-set}, or returns @code{#f} if none of the -characters in @var{char-set} occur in @var{string}. -For the substring procedure, only the substring is searched, but the -index returned is relative to the entire string, not just the substring. - -@example -@group -(string-find-next-char-in-set my-string char-set:alphabetic) - @result{} @r{start position of the first word in} my-string -@r{; Can be used as a predicate:} -(if (string-find-next-char-in-set my-string - (char-set #\( #\) )) - 'contains-parentheses - 'no-parentheses) -@end group -@end example -@end deffn - -@deffn procedure string-find-previous-char string char -@deffnx procedure substring-find-previous-char string start end char -@deffnx procedure string-find-previous-char-ci string char -@deffnx procedure substring-find-previous-char-ci string start end char -Returns the index of the last occurrence of @var{char} in the string -(substring); returns @code{#f} if @var{char} doesn't appear in the -string. For the substring procedures, the index returned is relative to -the entire string, not just the substring. The @code{-ci} procedures -don't distinguish uppercase and lowercase letters. -@end deffn - -@deffn procedure string-find-previous-char-in-set string char-set -@deffnx procedure substring-find-previous-char-in-set string start end char-set -Returns the index of the last character in the string (substring) that -is also in @var{char-set}. For the substring procedure, the index -returned is relative to the entire string, not just the substring. -@end deffn - -@node Matching Strings, Regular Expressions, Searching Strings, Strings -@section Matching Strings -@cindex matching, of strings - -@deffn procedure string-match-forward string1 string2 -@deffnx procedure substring-match-forward string1 start end string2 start end -@deffnx procedure string-match-forward-ci string1 string2 -@deffnx procedure substring-match-forward-ci string1 start end string2 start end -Compares the two strings (substrings), starting from the beginning, and -returns the number of characters that are the same. If the two strings -(substrings) start differently, returns 0. The @code{-ci} procedures -don't distinguish uppercase and lowercase letters. - -@example -@group -(string-match-forward "mirror" "micro") @result{} 2 @r{; matches "mi"} -(string-match-forward "a" "b") @result{} 0 @r{; no match} -@end group -@end example -@end deffn - -@deffn procedure string-match-backward string1 string2 -@deffnx procedure substring-match-backward string1 start end string2 start end -@deffnx procedure string-match-backward-ci string1 string2 -@deffnx procedure substring-match-backward-ci string1 start end string2 start end -Compares the two strings (substrings), starting from the end and -matching toward the front, returning the number of characters that are -the same. If the two strings (substrings) end differently, returns 0. -The @code{-ci} procedures don't distinguish uppercase and lowercase -letters. - -@example -@group -(string-match-backward-ci "BULBOUS" "fractious") - @result{} 3 @r{; matches "ous"} -@end group -@end example -@end deffn - -@deffn procedure string-prefix? string1 string2 -@deffnx procedure substring-prefix? string1 start1 end1 string2 start2 end2 -@deffnx procedure string-prefix-ci? string1 string2 -@deffnx procedure substring-prefix-ci? string1 start1 end1 string2 start2 end2 -@cindex prefix, of string -These procedures return @code{#t} if the first string (substring) forms -the prefix of the second; otherwise returns @code{#f}. The @code{-ci} -procedures don't distinguish uppercase and lowercase letters. - -@example -@group -(string-prefix? "abc" "abcdef") @result{} #t -(string-prefix? "" any-string) @result{} #t -@end group -@end example -@end deffn - -@deffn procedure string-suffix? string1 string2 -@deffnx procedure substring-suffix? string1 start1 end1 string2 start2 end2 -@deffnx procedure string-suffix-ci? string1 string2 -@deffnx procedure substring-suffix-ci? string1 start1 end1 string2 start2 end2 -@cindex suffix, of string -These procedures return @code{#t} if the first string (substring) forms -the suffix of the second; otherwise returns @code{#f}. The @code{-ci} -procedures don't distinguish uppercase and lowercase letters. - -@example -@group -(string-suffix? "ous" "bulbous") @result{} #t -(string-suffix? "" any-string) @result{} #t -@end group -@end example -@end deffn - -@node Regular Expressions, Modification of Strings, Matching Strings, Strings -@section Regular Expressions - -MIT/GNU Scheme provides support for using regular expressions to search and -match strings. This manual does not define regular expressions; instead -see @ref{Regexps, , Syntax of Regular Expressions, emacs, The Emacs -Editor}. - -In addition to providing standard regular-expression support, MIT/GNU -Scheme also provides the @acronym{REXP} abstraction. This is an -alternative way to write regular expressions that is easier to read -and understand than the standard notation. Regular expressions -written in this notation can be translated into the standard -notation. - -The regular-expression support is a run-time-loadable option. To use -it, execute - -@example -(load-option 'regular-expression) -@end example - -@noindent -once before calling any of the procedures defined here. - -@menu -* Regular-expression procedures:: -* REXP abstraction:: -@end menu - -@node Regular-expression procedures, REXP abstraction, Regular Expressions, Regular Expressions -@subsection Regular-expression procedures -@cindex searching, for regular expression -@cindex regular expression, searching string for - -Procedures that perform regular-expression match and search accept -standardized arguments. @var{Regexp} is the regular expression; it is a -string. @var{String} is the string being matched or searched. -Procedures that operate on substrings also accept @var{start} and -@var{end} index arguments with the usual meaning. The optional argument -@var{case-fold?} says whether the match/search is case-sensitive; if -@var{case-fold?} is @code{#f}, it is case-sensitive, otherwise it is -case-insensitive. The optional argument @var{syntax-table} is a -character syntax table that defines the character syntax, such as which -characters are legal word constituents. This feature is primarily for -Edwin, so character syntax tables will not be documented here. -Supplying @code{#f} for (or omitting) @var{syntax-table} will select the -default character syntax, equivalent to Edwin's @code{fundamental} -mode. - -@deffn procedure re-string-match regexp string [case-fold? [syntax-table]] -@deffnx procedure re-substring-match regexp string start end [case-fold? [syntax-table]] -These procedures match @var{regexp} against the respective string or -substring, returning @code{#f} for no match, or a set of match registers -(see below) if the match succeeds. Here is an example showing how to -extract the matched substring: - -@example -@group -(let ((r (re-substring-match @var{regexp} @var{string} @var{start} @var{end}))) - (and r - (substring @var{string} @var{start} (re-match-end-index 0 r)))) -@end group -@end example -@end deffn - -@deffn procedure re-string-search-forward regexp string [case-fold? [syntax-table]] -@deffnx procedure re-substring-search-forward regexp string start end [case-fold? [syntax-table]] -Searches @var{string} for the leftmost substring matching @var{regexp}. -Returns a set of match registers (see below) if the search is -successful, or @code{#f} if it is unsuccessful. - -@code{re-substring-search-forward} limits its search to the specified -substring of @var{string}; @code{re-string-search-forward} searches all -of @var{string}. -@end deffn - -@deffn procedure re-string-search-backward regexp string [case-fold? [syntax-table]] -@deffnx procedure re-substring-search-backward regexp string start end [case-fold? [syntax-table]] -Searches @var{string} for the rightmost substring matching @var{regexp}. -Returns a set of match registers (see below) if the search is -successful, or @code{#f} if it is unsuccessful. - -@code{re-substring-search-backward} limits its search to the specified -substring of @var{string}; @code{re-string-search-backward} searches all -of @var{string}. -@end deffn - -When a successful match or search occurs, the above procedures return a -set of @dfn{match registers}. The match registers are a set of index -registers that record indexes into the matched string. Each index -register corresponds to an instance of the regular-expression grouping -operator @samp{\(}, and records the start index (inclusive) and end -index (exclusive) of the matched group. These registers are numbered -from @code{1} to @code{9}, corresponding left-to-right to the grouping -operators in the expression. Additionally, register @code{0} -corresponds to the entire substring matching the regular expression. - -@deffn procedure re-match-start-index n registers -@deffnx procedure re-match-end-index n registers -@var{N} must be an exact integer between @code{0} and @code{9} -inclusive. @var{Registers} must be a match-registers object as returned -by one of the regular-expression match or search procedures above. -@code{re-match-start-index} returns the start index of the corresponding -regular-expression register, and @code{re-match-end-index} returns the -corresponding end index. -@end deffn - -@deffn procedure re-match-extract string registers n -@var{Registers} must be a match-registers object as returned by one of -the regular-expression match or search procedures above. @var{String} -must be the string that was passed as an argument to the procedure that -returned @var{registers}. @var{N} must be an exact integer between -@code{0} and @code{9} inclusive. If the matched regular expression -contained @var{m} grouping operators, then the value of this procedure -is undefined for @var{n} strictly greater than @var{m}. - -This procedure extracts the substring corresponding to the match -register specified by @var{registers} and @var{n}. This is equivalent -to the following expression: - -@example -@group -(substring @var{string} - (re-match-start-index @var{n} @var{registers}) - (re-match-end-index @var{n} @var{registers})) -@end group -@end example -@end deffn - -@deffn procedure regexp-group alternative @dots{} -Each @var{alternative} must be a regular expression. The returned value -is a new regular expression that consists of the @var{alternative}s -combined by a grouping operator. For example: - -@example -@group -(regexp-group "foo" "bar" "baz") - @result{} "\\(foo\\|bar\\|baz\\)" -@end group -@end example -@end deffn - -@node REXP abstraction, , Regular-expression procedures, Regular Expressions -@subsection REXP abstraction - -@cindex REXP abstraction -In addition to providing standard regular-expression support, MIT/GNU -Scheme also provides the @acronym{REXP} abstraction. This is an -alternative way to write regular expressions that is easier to read -and understand than the standard notation. Regular expressions -written in this notation can be translated into the standard notation. - -The @acronym{REXP} abstraction is a set of combinators that are -composed into a complete regular expression. Each combinator directly -corresponds to a particular piece of regular-expression notation. For -example, the expression @code{(rexp-any-char)} corresponds to the -@code{.} character in standard regular-expression notation, while -@code{(rexp* @var{rexp})} corresponds to the @code{*} character. - -The primary advantages of @acronym{REXP} are that it makes the nesting -structure of regular expressions explicit, and that it simplifies the -description of complex regular expressions by allowing them to be -built up using straightforward combinators. - -@deffn procedure rexp? object -Returns @code{#t} if @var{object} is a @acronym{REXP} expression, or -@code{#f} otherwise. A @acronym{REXP} is one of: a string, which -represents the pattern matching that string; a character set, which -represents the pattern matching a character in that set; or an object -returned by calling one of the procedures defined here. -@end deffn - -@deffn procedure rexp->regexp rexp -Converts @var{rexp} to standard regular-expression notation, returning -a newly-allocated string. -@end deffn - -@deffn procedure rexp-compile rexp -Converts @var{rexp} to standard regular-expression notation, then -compiles it and returns the compiled result. Equivalent to - -@example -(re-compile-pattern (rexp->regexp @var{rexp}) #f) -@end example -@end deffn - -@deffn procedure rexp-any-char -Returns a @acronym{REXP} that matches any single character except a -newline. This is equivalent to the @code{.} construct. -@end deffn - -@deffn procedure rexp-line-start -Returns a @acronym{REXP} that matches the start of a line. This is -equivalent to the @code{^} construct. -@end deffn - -@deffn procedure rexp-line-end -Returns a @acronym{REXP} that matches the end of a line. This is -equivalent to the @code{$} construct. -@end deffn - -@deffn procedure rexp-string-start -Returns a @acronym{REXP} that matches the start of the text being -matched. This is equivalent to the @code{\`} construct. -@end deffn - -@deffn procedure rexp-string-end -Returns a @acronym{REXP} that matches the end of the text being -matched. This is equivalent to the @code{\'} construct. -@end deffn - -@deffn procedure rexp-word-edge -Returns a @acronym{REXP} that matches the start or end of a word. -This is equivalent to the @code{\b} construct. -@end deffn - -@deffn procedure rexp-not-word-edge -Returns a @acronym{REXP} that matches anywhere that is not the start -or end of a word. This is equivalent to the @code{\B} construct. -@end deffn - -@deffn procedure rexp-word-start -Returns a @acronym{REXP} that matches the start of a word. -This is equivalent to the @code{\<} construct. -@end deffn - -@deffn procedure rexp-word-end -Returns a @acronym{REXP} that matches the end of a word. -This is equivalent to the @code{\>} construct. -@end deffn - -@deffn procedure rexp-word-char -Returns a @acronym{REXP} that matches any word-constituent character. -This is equivalent to the @code{\w} construct. -@end deffn - -@deffn procedure rexp-not-word-char -Returns a @acronym{REXP} that matches any character that isn't a word -constituent. This is equivalent to the @code{\W} construct. -@end deffn - -The next two procedures accept a @var{syntax-type} argument specifying -the syntax class to be matched against. This argument is a symbol -selected from the following list. Each symbol is followed by the -equivalent character used in standard regular-expression notation. -@code{whitespace} (space character), -@code{punctuation} (@code{.}), -@code{word} (@code{w}), -@code{symbol} (@code{_}), -@code{open} (@code{(}), -@code{close} (@code{)}), -@code{quote} (@code{'}), -@code{string-delimiter} (@code{"}), -@code{math-delimiter} (@code{$}), -@code{escape} (@code{\}), -@code{char-quote} (@code{/}), -@code{comment-start} (@code{<}), -@code{comment-end} (@code{>}). - -@deffn procedure rexp-syntax-char syntax-type -Returns a @acronym{REXP} that matches any character of type -@var{syntax-type}. This is equivalent to the @code{\s} construct. -@end deffn - -@deffn procedure rexp-not-syntax-char syntax-type -Returns a @acronym{REXP} that matches any character not of type -@var{syntax-type}. This is equivalent to the @code{\S} construct. -@end deffn - -@deffn procedure rexp-sequence rexp @dots{} -Returns a @acronym{REXP} that matches each @var{rexp} argument in -sequence. If no @var{rexp} argument is supplied, the result matches -the null string. This is equivalent to concatenating the regular -expressions corresponding to each @var{rexp} argument. -@end deffn - -@deffn procedure rexp-alternatives rexp @dots{} -Returns a @acronym{REXP} that matches any of the @var{rexp} -arguments. This is equivalent to concatenating the regular -expressions corresponding to each @var{rexp} argument, separating them -by the @code{\|} construct. -@end deffn - -@deffn procedure rexp-group rexp @dots{} -@code{rexp-group} is like @code{rexp-sequence}, except that the result -is marked as a match group. This is equivalent to the @code{\(} -@dots{} @code{\)} construct. -@end deffn - -The next three procedures in principal accept a single @acronym{REXP} -argument. For convenience, they accept multiple arguments, which are -converted into a single argument by @code{rexp-group}. Note, however, -that if only one @acronym{REXP} argument is supplied, and it's very -simple, no grouping occurs. - -@deffn procedure rexp* rexp @dots{} -Returns a @acronym{REXP} that matches zero or more instances of the -pattern matched by the @var{rexp} arguments. This is equivalent to -the @code{*} construct. -@end deffn - -@deffn procedure rexp+ rexp @dots{} -Returns a @acronym{REXP} that matches one or more instances of the -pattern matched by the @var{rexp} arguments. This is equivalent to -the @code{+} construct. -@end deffn - -@deffn procedure rexp-optional rexp @dots{} -Returns a @acronym{REXP} that matches zero or one instances of the -pattern matched by the @var{rexp} arguments. This is equivalent to -the @code{?} construct. -@end deffn - -@deffn procedure rexp-case-fold rexp -Returns a @acronym{REXP} that matches the same pattern as @var{rexp}, -but is insensitive to character case. This has no equivalent in -standard regular-expression notation. -@end deffn - -@node Modification of Strings, Variable-Length Strings, Regular Expressions, Strings -@section Modification of Strings -@cindex modification, of string -@cindex replacement, of string component -@cindex filling, of string -@cindex moving, of string elements - -@deffn procedure string-replace string char1 char2 -@deffnx procedure substring-replace string start end char1 char2 -@deffnx procedure string-replace! string char1 char2 -@deffnx procedure substring-replace! string start end char1 char2 -These procedures replace all occurrences of @var{char1} with @var{char2} -in the original string (substring). @code{string-replace} and -@code{substring-replace} return a newly allocated string containing the -result. @code{string-replace!} and @code{substring-replace!} -destructively modify @var{string} and return an unspecified value. - -@example -@group -(define str "a few words") @result{} @r{unspecified} -(string-replace str #\space #\-) @result{} "a-few-words" -(substring-replace str 2 9 #\space #\-) @result{} "a few-words" -str @result{} "a few words" -(string-replace! str #\space #\-) @result{} @r{unspecified} -str @result{} "a-few-words" -@end group -@end example -@end deffn - -@deffn {procedure} string-fill! string char -Stores @var{char} in every element of @var{string} and returns an -unspecified value. -@end deffn - -@deffn procedure substring-fill! string start end char -Stores @var{char} in elements @var{start} (inclusive) to @var{end} -(exclusive) of @var{string} and returns an unspecified value. - -@example -@group -(define s (make-string 10 #\space)) @result{} @r{unspecified} -(substring-fill! s 2 8 #\*) @result{} @r{unspecified} -s @result{} " ****** " -@end group -@end example -@end deffn - -@deffn procedure substring-move-left! string1 start1 end1 string2 start2 -@deffnx procedure substring-move-right! string1 start1 end1 string2 start2 -@findex eqv? -Copies the characters from @var{start1} to @var{end1} of @var{string1} -into @var{string2} at the @var{start2}-th position. The characters are -copied as follows (note that this is only important when @var{string1} -and @var{string2} are @code{eqv?}): - -@table @code -@item substring-move-left! -The copy starts at the left end and moves toward the right (from smaller -indices to larger). Thus if @var{string1} and @var{string2} are the -same, this procedure moves the characters toward the left inside the -string. - -@item substring-move-right! -The copy starts at the right end and moves toward the left (from larger -indices to smaller). Thus if @var{string1} and @var{string2} are the -same, this procedure moves the characters toward the right inside the -string. -@end table - -The following example shows how these procedures can be used to build up -a string (it would have been easier to use @code{string-append}): -@example -@group -(define answer (make-string 9 #\*)) @result{} @r{unspecified} -answer @result{} "*********" -(substring-move-left! "start" 0 5 answer 0) @result{} @r{unspecified} -answer @result{} "start****" -(substring-move-left! "-end" 0 4 answer 5) @result{} @r{unspecified} -answer @result{} "start-end" -@end group -@end example -@end deffn - -@deffn procedure reverse-string string -@deffnx procedure reverse-substring string start end -@deffnx procedure reverse-string! string -@deffnx procedure reverse-substring! string start end -Reverses the order of the characters in the given string or substring. -@code{reverse-string} and @code{reverse-substring} return newly -allocated strings; @code{reverse-string!} and @code{reverse-substring!} -modify their argument strings and return an unspecified value. - -@example -@group -(reverse-string "foo bar baz") @result{} "zab rab oof" -(reverse-substring "foo bar baz" 4 7) @result{} "rab" -(let ((foo "foo bar baz")) - (reverse-string! foo) - foo) @result{} "zab rab oof" -(let ((foo "foo bar baz")) - (reverse-substring! foo 4 7) - foo) @result{} "foo rab baz" -@end group -@end example -@end deffn - -@node Variable-Length Strings, Byte Vectors, Modification of Strings, Strings -@section Variable-Length Strings - -@cindex length, of string -@cindex maximum length, of string (defn) -MIT/GNU Scheme allows the length of a string to be dynamically adjusted in a -limited way. When a new string is allocated, by whatever method, it has -a specific length. At the time of allocation, it is also given a -@dfn{maximum length}, which is guaranteed to be at least as large as the -string's length. (Sometimes the maximum length will be slightly larger -than the length, but it is a bad idea to count on this. Programs should -assume that the maximum length is the same as the length at the time of -the string's allocation.) After the string is allocated, the operation -@code{set-string-length!} can be used to alter the string's length to -any value between 0 and the string's maximum length, inclusive. - -@deffn procedure string-maximum-length string -Returns the maximum length of @var{string}. The following is -guaranteed: - -@example -@group -(<= (string-length string) - (string-maximum-length string)) @result{} #t -@end group -@end example -@findex string-length - -The maximum length of a string never changes. -@end deffn - -@deffn procedure set-string-length! string k -Alters the length of @var{string} to be @var{k}, and returns an -unspecified value. @var{K} must be less than or equal to the maximum -length of @var{string}. @code{set-string-length!} does not change the -maximum length of @var{string}. -@end deffn - -@node Byte Vectors, , Variable-Length Strings, Strings -@section Byte Vectors -@cindex byte vector -@cindex vector, byte - -@findex string-ref -MIT/GNU Scheme implements strings as packed vectors of 8-bit -@acronym{ISO-8859-1} bytes. Most of the string operations, such as -@code{string-ref}, coerce these 8-bit codes into character objects. -However, some lower-level operations are made available for use. - -@deffn procedure vector-8b-ref string k -Returns character @var{k} of @var{string} as an @acronym{ISO-8859-1} -code. @var{K} must be a valid index of @var{string}. - -@example -@group -(vector-8b-ref "abcde" 2) @result{} 99 @r{;c} -@end group -@end example -@end deffn - -@deffn procedure vector-8b-set! string k code -Stores @var{code} in element @var{k} of @var{string} and returns an -unspecified value. @var{K} must be a valid index of @var{string}, and -@var{code} must be a valid @acronym{ISO-8859-1} code. -@end deffn - -@deffn procedure vector-8b-fill! string start end code -Stores @var{code} in elements @var{start} (inclusive) to @var{end} -(exclusive) of @var{string} and returns an unspecified value. -@var{Code} must be a valid @acronym{ISO-8859-1} code. -@end deffn - -@deffn procedure vector-8b-find-next-char string start end code -@deffnx procedure vector-8b-find-next-char-ci string start end code -Returns the index of the first occurrence of @var{code} in the given -substring; returns @code{#f} if @var{code} does not appear. The index -returned is relative to the entire string, not just the substring. -@var{Code} must be a valid @acronym{ISO-8859-1} code. - -@code{vector-8b-find-next-char-ci} doesn't distinguish uppercase and -lowercase letters. -@end deffn - -@deffn procedure vector-8b-find-previous-char string start end code -@deffnx procedure vector-8b-find-previous-char-ci string start end code -Returns the index of the last occurrence of @var{code} in the given -substring; returns @code{#f} if @var{code} does not appear. The index -returned is relative to the entire string, not just the substring. -@var{Code} must be a valid @acronym{ISO-8859-1} code. - -@code{vector-8b-find-previous-char-ci} doesn't distinguish uppercase and -lowercase letters. -@end deffn - -@node Lists, Vectors, Strings, Top -@chapter Lists - -@cindex pair (defn) -@cindex dotted pair (see pair) -@cindex car field, of pair (defn) -@cindex cdr field, of pair (defn) -A @dfn{pair} (sometimes called a @dfn{dotted pair}) is a data structure -with two fields called the @dfn{car} and @dfn{cdr} fields (for -historical reasons). Pairs are created by the procedure @code{cons}. -The car and cdr fields are accessed by the procedures @code{car} and -@code{cdr}. The car and cdr fields are assigned by the procedures -@code{set-car!} and @code{set-cdr!}. - -@cindex list (defn) -Pairs are used primarily to represent @dfn{lists}. A list can be -defined recursively as either the empty list or a pair whose cdr is -a list. More precisely, the set of lists is defined as the smallest set -@var{X} such that - -@itemize @bullet -@item -The empty list is in @var{X}. - -@item -If @var{list} is in @var{X}, then any pair whose cdr field contains -@var{list} is also in @var{X}. -@end itemize - -@cindex element, of list (defn) -@cindex length, of list (defn) -@cindex empty list (defn) -The objects in the car fields of successive pairs of a list are the -@dfn{elements} of the list. For example, a two-element list is a pair -whose car is the first element and whose cdr is a pair whose car is the -second element and whose cdr is the empty list. The @dfn{length} of a -list is the number of elements, which is the same as the number of -pairs. The @dfn{empty list} is a special object of its own type (it is -not a pair); it has no elements and its length is zero.@footnote{The -above definitions imply that all lists have finite length and are -terminated by the empty list.} - -@cindex dotted notation, for pair (defn) -@cindex notation, dotted (defn) -@cindex external representation, for pair -@cindex pair, external representation -@cindex ( as external representation -@cindex ) as external representation -@cindex . as external representation -@cindex parenthesis, as external representation -@cindex dot, as external representation -@cindex period, as external representation -@findex ( -@findex ) -@findex . -The most general notation (external representation) for Scheme pairs is -the ``dotted'' notation @code{(@var{c1} . @var{c2})} where @var{c1} is -the value of the car field and @var{c2} is the value of the cdr field. -For example, @code{(4 . 5)} is a pair whose car is @code{4} and whose -cdr is @code{5}. Note that @code{(4 . 5)} is the external -representation of a pair, not an expression that evaluates to a pair. - -@cindex external representation, for list -@cindex list, external representation -@cindex external representation, for empty list -@cindex empty list, external representation -@findex () -A more streamlined notation can be used for lists: the elements of the -list are simply enclosed in parentheses and separated by spaces. The -empty list is written @code{()}. For example, the following are -equivalent notations for a list of symbols: - -@example -@group -(a b c d e) -(a . (b . (c . (d . (e . ()))))) -@end group -@end example - -@findex set-cdr! -Whether a given pair is a list depends upon what is stored in the cdr -field. When the @code{set-cdr!} procedure is used, an object can be a -list one moment and not the next: - -@example -@group -(define x (list 'a 'b 'c)) -(define y x) -y @result{} (a b c) -(list? y) @result{} #t -(set-cdr! x 4) @result{} @r{unspecified} -x @result{} (a . 4) -(eqv? x y) @result{} #t -y @result{} (a . 4) -(list? y) @result{} #f -(set-cdr! x x) @result{} @r{unspecified} -(list? y) @result{} #f -@end group -@end example - -@cindex improper list (defn) -@cindex list, improper (defn) -A chain of pairs that doesn't end in the empty list is called an -@dfn{improper list}. Note that an improper list is not a list. The -list and dotted notations can be combined to represent improper lists, -as the following equivalent notations show: - -@example -@group -(a b c . d) -(a . (b . (c . d))) -@end group -@end example - -@findex quote -@findex quasiquote -@findex unquote -@findex unquote-splicing -@findex ' -@findex ` -@findex , -@findex ,@@ -@findex read -Within literal expressions and representations of objects read by the -@code{read} procedure, the forms @code{'@var{datum}}, -@code{`@var{datum}}, @code{,@var{datum}}, and @code{,@@@var{datum}} -denote two-element lists whose first elements are the symbols -@code{quote}, @code{quasiquote}, @code{unquote}, and -@code{unquote-splicing}, respectively. The second element in each case -is @var{datum}. This convention is supported so that arbitrary Scheme -programs may be represented as lists. Among other things, this permits -the use of the @code{read} procedure to parse Scheme programs. - -@menu -* Pairs:: -* Construction of Lists:: -* Selecting List Components:: -* Cutting and Pasting Lists:: -* Filtering Lists:: -* Searching Lists:: -* Mapping of Lists:: -* Reduction of Lists:: -* Miscellaneous List Operations:: -@end menu - -@node Pairs, Construction of Lists, Lists, Lists -@section Pairs - -This section describes the simple operations that are available for -constructing and manipulating arbitrary graphs constructed from pairs. - -@deffn procedure pair? object -@cindex type predicate, for pair -Returns @code{#t} if @var{object} is a pair; otherwise returns -@code{#f}. - -@example -@group -(pair? '(a . b)) @result{} #t -(pair? '(a b c)) @result{} #t -(pair? '()) @result{} #f -(pair? '#(a b)) @result{} #f -@end group -@end example -@end deffn - -@deffn procedure cons obj1 obj2 -@cindex construction, of pair -@findex eqv? -Returns a newly allocated pair whose car is @var{obj1} and whose cdr is -@var{obj2}. The pair is guaranteed to be different (in the sense of -@code{eqv?}) from every previously existing object. - -@example -@group -(cons 'a '()) @result{} (a) -(cons '(a) '(b c d)) @result{} ((a) b c d) -(cons "a" '(b c)) @result{} ("a" b c) -(cons 'a 3) @result{} (a . 3) -(cons '(a b) 'c) @result{} ((a b) . c) -@end group -@end example -@end deffn - -@deffn procedure car pair -@cindex selection, of pair component -@cindex component selection, of pair -Returns the contents of the car field of @var{pair}. Note that it is an -error to take the @code{car} of the empty list. - -@example -@group -(car '(a b c)) @result{} a -(car '((a) b c d)) @result{} (a) -(car '(1 . 2)) @result{} 1 -(car '()) @error{} Illegal datum -@end group -@end example -@end deffn - -@deffn procedure cdr pair -Returns the contents of the cdr field of @var{pair}. Note that it is an -error to take the @code{cdr} of the empty list. - -@example -@group -(cdr '((a) b c d)) @result{} (b c d) -(cdr '(1 . 2)) @result{} 2 -(cdr '()) @error{} Illegal datum -@end group -@end example -@end deffn - -@deffn procedure set-car! pair object -Stores @var{object} in the car field of @var{pair}. The value returned -by @code{set-car!} is unspecified. - -@example -@group -(define (f) (list 'not-a-constant-list)) -(define (g) '(constant-list)) -(set-car! (f) 3) @result{} @r{unspecified} -(set-car! (g) 3) @error{} Illegal datum -@end group -@end example -@end deffn - -@deffn procedure set-cdr! pair object -Stores @var{object} in the cdr field of @var{pair}. The value returned -by @code{set-cdr!} is unspecified. -@end deffn - -@deffn procedure caar pair -@deffnx procedure cadr pair -@deffnx procedure cdar pair -@deffnx procedure cddr pair -@deffnx procedure caaar pair -@deffnx procedure caadr pair -@deffnx procedure cadar pair -@deffnx procedure caddr pair -@deffnx procedure cdaar pair -@deffnx procedure cdadr pair -@deffnx procedure cddar pair -@deffnx procedure cdddr pair -@deffnx procedure caaaar pair -@deffnx procedure caaadr pair -@deffnx procedure caadar pair -@deffnx procedure caaddr pair -@deffnx procedure cadaar pair -@deffnx procedure cadadr pair -@deffnx procedure caddar pair -@deffnx procedure cadddr pair -@deffnx procedure cdaaar pair -@deffnx procedure cdaadr pair -@deffnx procedure cdadar pair -@deffnx procedure cdaddr pair -@deffnx procedure cddaar pair -@deffnx procedure cddadr pair -@deffnx procedure cdddar pair -@deffnx procedure cddddr pair -These procedures are compositions of @code{car} and @code{cdr}; for -example, @code{caddr} could be defined by - -@example -(define caddr (lambda (x) (car (cdr (cdr x))))) -@end example -@end deffn - -@deffn procedure general-car-cdr object path -This procedure is a generalization of @code{car} and @code{cdr}. -@var{Path} encodes a particular sequence of @code{car} and @code{cdr} -operations, which @code{general-car-cdr} executes on @var{object}. -@var{Path} is an exact non-negative integer that encodes the operations -in a bitwise fashion: a zero bit represents a @code{cdr} operation, and -a one bit represents a @code{car}. The bits are executed LSB to MSB, -and the most significant one bit, rather than being interpreted as an -operation, signals the end of the sequence.@footnote{Note that -@var{path} is restricted to a machine-dependent range, usually the size -of a machine word. On many machines, this means that the maximum length -of @var{path} will be 30 operations (32 bits, less the sign bit and the -``end-of-sequence'' bit).} - -For example, the following are equivalent: -@example -@group -(general-car-cdr @var{object} #b1011) -(cdr (car (car @var{object}))) -@end group -@end example - -Here is a partial table of path/operation equivalents: - -@example -@group -#b10 cdr -#b11 car -#b100 cddr -#b101 cdar -#b110 cadr -#b111 caar -#b1000 cdddr -@end group -@end example -@end deffn - -@deffn procedure tree-copy tree -@cindex copying, of tree -@cindex tree, copying -This copies an arbitrary @var{tree} constructed from pairs, copying both -the car and cdr elements of every pair. This could have been defined by - -@example -@group -(define (tree-copy tree) - (let loop ((tree tree)) - (if (pair? tree) - (cons (loop (car tree)) (loop (cdr tree))) - tree))) -@end group -@end example -@end deffn - -@node Construction of Lists, Selecting List Components, Pairs, Lists -@section Construction of Lists -@cindex construction, of list - -@deffn procedure list object @dots{} -Returns a list of its arguments. - -@example -@group -(list 'a (+ 3 4) 'c) @result{} (a 7 c) -(list) @result{} () -@end group -@end example - -These expressions are equivalent: - -@example -@group -(list @var{obj1} @var{obj2} @dots{} @var{objN}) -(cons @var{obj1} (cons @var{obj2} @dots{} (cons @var{objN} '()) @dots{})) -@end group -@end example -@end deffn - -@deffn procedure make-list k [element] -This procedure returns a newly allocated list of length @var{k}, -whose elements are all @var{element}. If @var{element} is not supplied, -it defaults to the empty list. -@end deffn - -@deffn procedure cons* object object @dots{} -@findex list -@code{cons*} is similar to @code{list}, except that @code{cons*} conses -together the last two arguments rather than consing the last argument -with the empty list. If the last argument is not a list the result is -an improper list. If the last argument is a list, the result is a list -consisting of the initial arguments and all of the items in the final -argument. If there is only one argument, the result is the argument. - -@example -@group -(cons* 'a 'b 'c) @result{} (a b . c) -(cons* 'a 'b '(c d)) @result{} (a b c d) -(cons* 'a) @result{} a -@end group -@end example - -These expressions are equivalent: - -@example -@group -(cons* @var{obj1} @var{obj2} @dots{} @var{objN-1} @var{objN}) -(cons @var{obj1} (cons @var{obj2} @dots{} (cons @var{objN-1} @var{objN}) @dots{})) -@end group -@end example -@end deffn - -@deffn procedure list-copy list -Returns a newly allocated copy of @var{list}. This copies each of the -pairs comprising @var{list}. This could have been defined by - -@example -@group -(define (list-copy list) - (if (null? list) - '() - (cons (car list) - (list-copy (cdr list))))) -@end group -@end example -@end deffn - -@deffn procedure vector->list vector -@deffnx procedure subvector->list vector start end -@cindex vector, converting to list -@findex list->vector -@code{vector->list} returns a newly allocated list of the elements of -@var{vector}.@* @code{subvector->list} returns a newly allocated list of -the elements of the given subvector. The inverse of @code{vector->list} -is @code{list->vector}. - -@example -(vector->list '#(dah dah didah)) @result{} (dah dah didah) -@end example -@end deffn - -@deffn {procedure} string->list string -@deffnx {procedure} substring->list string start end -@cindex string, converting to list -@findex list->string -@code{string->list} returns a newly allocated list of the character -elements of @var{string}.@* -@code{substring->list} returns a newly allocated list of the character -elements of the given substring. The inverse of @code{string->list} is -@code{list->string}. - -@example -@group -(string->list "abcd") @result{} (#\a #\b #\c #\d) -(substring->list "abcdef" 1 3) @result{} (#\b #\c) -@end group -@end example -@end deffn - -@node Selecting List Components, Cutting and Pasting Lists, Construction of Lists, Lists -@section Selecting List Components -@cindex selection, of list component -@cindex component selection, of list - -@deffn procedure list? object -@cindex type predicate, for list -@cindex circular list -Returns @code{#t} if @var{object} is a list, otherwise returns -@code{#f}. By definition, all lists have finite length and are -terminated by the empty list. This procedure returns an answer even for -circular structures. - -@findex pair? -@findex null? -Any @var{object} satisfying this predicate will also satisfy exactly one -of @code{pair?} or @code{null?}. - -@example -@group -(list? '(a b c)) @result{} #t -(list? '()) @result{} #t -(list? '(a . b)) @result{} #f -(let ((x (list 'a))) - (set-cdr! x x) - (list? x)) @result{} #f -@end group -@end example -@end deffn - -@deffn procedure length list -Returns the length of @var{list}. Signals an error if @var{list} isn't -a proper list. - -@example -@group -(length '(a b c)) @result{} 3 -(length '(a (b) (c d e))) @result{} 3 -(length '()) @result{} 0 -@end group -@end example -@end deffn - -@deffn procedure null? object -@cindex type predicate, for empty list -@cindex empty list, predicate for -Returns @code{#t} if @var{object} is the empty list; otherwise returns -@code{#f} (but @pxref{True and False}). - -@example -@group -(null? '(a . b)) @result{} #f -(null? '(a b c)) @result{} #f -(null? '()) @result{} #t -@end group -@end example -@end deffn - -@deffn procedure list-ref list k -@cindex index, of list (defn) -@cindex valid index, of list (defn) -@cindex list index (defn) -Returns the @var{k}th element of @var{list}, using zero-origin indexing. -The @dfn{valid indexes} of a list are the exact non-negative integers -less than the length of the list. The first element of a list has index -@code{0}, the second has index @code{1}, and so on. - -@example -@group -(list-ref '(a b c d) 2) @result{} c -(list-ref '(a b c d) - (inexact->exact (round 1.8))) - @result{} c -@end group -@end example - -@findex list-tail -@code{(list-ref @var{list} @var{k})} is equivalent to @code{(car -(list-tail @var{list} @var{k}))}. -@end deffn - -@deffn procedure first list -@deffnx procedure second list -@deffnx procedure third list -@deffnx procedure fourth list -@deffnx procedure fifth list -@deffnx procedure sixth list -@deffnx procedure seventh list -@deffnx procedure eighth list -@deffnx procedure ninth list -@deffnx procedure tenth list -Returns the specified element of @var{list}. It is an error if -@var{list} is not long enough to contain the specified element (for -example, if the argument to @code{seventh} is a list that contains only -six elements). -@end deffn - -@node Cutting and Pasting Lists, Filtering Lists, Selecting List Components, Lists -@section Cutting and Pasting Lists -@cindex cutting, of list -@cindex pasting, of lists - -@deffn procedure sublist list start end -@var{Start} and @var{end} must be exact integers satisfying - -@example -0 <= @var{start} <= @var{end} <= (length @var{list}) -@end example - -@code{sublist} returns a newly allocated list formed from the elements -of @var{list} beginning at index @var{start} (inclusive) and ending at -@var{end} (exclusive). -@end deffn - -@deffn procedure list-head list k -Returns a newly allocated list consisting of the first @var{k} elements of -@var{list}. @var{K} must not be greater than the length of -@var{list}. - -We could have defined @code{list-head} this way: - -@example -@group -(define (list-head list k) - (sublist list 0 k)) -@end group -@end example -@end deffn - -@deffn procedure list-tail list k -Returns the sublist of @var{list} obtained by omitting the first @var{k} -elements. The result, if it is not the empty list, shares structure -with @var{list}. @var{K} must not be greater than the length of -@var{list}. -@end deffn - -@deffn {procedure} append list @dots{} -@cindex appending, of lists -Returns a list consisting of the elements of the first @var{list} -followed by the elements of the other @var{list}s. - -@example -@group -(append '(x) '(y)) @result{} (x y) -(append '(a) '(b c d)) @result{} (a b c d) -(append '(a (b)) '((c))) @result{} (a (b) (c)) -(append) @result{} () -@end group -@end example - -The resulting list is always newly allocated, except that it shares -structure with the last @var{list} argument. The last argument may -actually be any object; an improper list results if the last argument is -not a proper list. - -@example -@group -(append '(a b) '(c . d)) @result{} (a b c . d) -(append '() 'a) @result{} a -@end group -@end example -@end deffn - -@deffn procedure append! list @dots{} -Returns a list that is the argument @var{list}s concatenated together. -The arguments are changed rather than copied. (Compare this with -@code{append}, which copies arguments rather than destroying them.) For -example: - -@example -@group -(define x '(a b c)) -(define y '(d e f)) -(define z '(g h)) -(append! x y z) @result{} (a b c d e f g h) -x @result{} (a b c d e f g h) -y @result{} (d e f g h) -z @result{} (g h) -@end group -@end example -@end deffn - -@deffn procedure last-pair list -Returns the last pair in @var{list}, which may be an improper list. -@code{last-pair} could have been defined this way: - -@example -@group -(define last-pair - (lambda (x) - (if (pair? (cdr x)) - (last-pair (cdr x)) - x))) -@end group -@end example -@end deffn - -@deffn procedure except-last-pair list -@deffnx procedure except-last-pair! list -These procedures remove the last pair from @var{list}. @var{List} may -be an improper list, except that it must consist of at least one pair. -@code{except-last-pair} returns a newly allocated copy of @var{list} -that omits the last pair. @code{except-last-pair!} destructively -removes the last pair from @var{list} and returns @var{list}. If the -cdr of @var{list} is not a pair, the empty list is returned by either -procedure. -@end deffn - -@node Filtering Lists, Searching Lists, Cutting and Pasting Lists, Lists -@section Filtering Lists -@cindex filtering, of list -@cindex deletion, of list element - -@deffn procedure keep-matching-items list predicate -@deffnx procedure delete-matching-items list predicate -These procedures return a newly allocated copy of @var{list} containing -only the elements for which @var{predicate} is (respectively) true or -false. @var{Predicate} must be a procedure of one argument. - -@example -@group -(keep-matching-items '(1 2 3 4 5) odd?) @result{} (1 3 5) -(delete-matching-items '(1 2 3 4 5) odd?) @result{} (2 4) -@end group -@end example - -@findex list-transform-positive -@findex list-transform-negative -For compatibility, the procedure @code{list-transform-positive} is an -alias for @code{keep-matching-items}, and @code{list-transform-negative} -is an alias for @code{delete-matching-items}. -@end deffn - -@deffn procedure keep-matching-items! list predicate -@deffnx procedure delete-matching-items! list predicate -These procedures are exactly like @code{keep-matching-items} and -@code{delete-matching-items}, respectively, except that they -destructively modify the @var{list} argument rather than allocating a -new result. -@end deffn - -@deffn procedure delq element list -@deffnx procedure delv element list -@deffnx procedure delete element list -@findex eq? -@findex eqv? -@findex equal? -Returns a newly allocated copy of @var{list} with all entries equal to -@var{element} removed. @code{delq} uses @code{eq?} to compare -@var{element} with the entries in @var{list}, @code{delv} uses -@code{eqv?}, and @code{delete} uses @code{equal?}. -@end deffn - -@deffn procedure delq! element list -@deffnx procedure delv! element list -@deffnx procedure delete! element list -@findex eq? -@findex eqv? -@findex equal? -Returns a list consisting of the top-level elements of @var{list} with -all entries equal to @var{element} removed. These procedures are like -@code{delq}, @code{delv}, and @code{delete} except that they -destructively modify @var{list}. @code{delq!} uses @code{eq?} to -compare element with the entries in @var{list}, @code{delv!} uses -@code{eqv?}, and @code{delete!} uses @code{equal?}. Because the result -may not be @code{eq?} to @var{list}, it is desirable to do something -like @code{(set! x (delete! x))}. - -@example -@group -(define x '(a b c b)) -(delete 'b x) @result{} (a c) -x @result{} (a b c b) - -(define x '(a b c b)) -(delete! 'b x) @result{} (a c) -x @result{} (a c) -@r{;; Returns correct result:} -(delete! 'a x) @result{} (c) - -@r{;; Didn't modify what x points to:} -x @result{} (a c) -@end group -@end example -@end deffn - -@deffn procedure delete-member-procedure deletor predicate -@findex list-deletor -@findex list-deletor! -@findex delv -@findex delete! -Returns a deletion procedure similar to @code{delv} or @code{delete!}. -@var{Deletor} should be one of the procedures @code{list-deletor} or -@code{list-deletor!}. @var{Predicate} must be an equivalence predicate. -The returned procedure accepts exactly two arguments: first, an object -to be deleted, and second, a list of objects from which it is to be -deleted. If @var{deletor} is @code{list-deletor}, the procedure -returns a newly allocated copy of the given list in which all entries -equal to the given object have been removed. If @var{deletor} is -@code{list-deletor!}, the procedure returns a list consisting of the -top-level elements of the given list with all entries equal to the given -object removed; the given list is destructively modified to produce the -result. In either case @var{predicate} is used to compare the given -object to the elements of the given list. - -Here are some examples that demonstrate how -@code{delete-member-procedure} could have been used to implement -@code{delv} and @code{delete!}: - -@example -@group -(define delv - (delete-member-procedure list-deletor eqv?)) -(define delete! - (delete-member-procedure list-deletor! equal?)) -@end group -@end example -@end deffn - -@deffn procedure list-deletor predicate -@deffnx procedure list-deletor! predicate -These procedures each return a procedure that deletes elements from -lists. @var{Predicate} must be a procedure of one argument. The -returned procedure accepts exactly one argument, which must be a proper -list, and applies @var{predicate} to each of the elements of the -argument, deleting those for which it is true. - -The procedure returned by @code{list-deletor} deletes elements -non-destructively, by returning a newly allocated copy of the argument -with the appropriate elements removed. The procedure returned by -@code{list-deletor!} performs a destructive deletion. -@end deffn - -@node Searching Lists, Mapping of Lists, Filtering Lists, Lists -@section Searching Lists -@cindex searching, of list - -@deffn procedure find-matching-item list predicate -Returns the first element in @var{list} for which @var{predicate} is -true; returns @code{#f} if it doesn't find such an element. (This means -that if @var{predicate} is true for @code{#f}, it may be impossible to -distinguish a successful result from an unsuccessful one.) -@var{Predicate} must be a procedure of one argument. - -@findex list-search-positive -@findex list-search-negative -For compatibility, @code{list-search-positive} is an alias for -@code{find-matching-item}. @code{list-search-negative} is similar but -the sense of the predicate is reversed. -@end deffn - -@deffn procedure memq object list -@deffnx procedure memv object list -@deffnx procedure member object list -@findex eq? -@findex eqv? -@findex equal? -These procedures return the first pair of @var{list} whose car is -@var{object}; the returned pair is always one from which @var{list} is -composed. If @var{object} does not occur in @var{list}, @code{#f} -(n.b.: not the empty list) is returned. @code{memq} uses @code{eq?} to -compare @var{object} with the elements of @var{list}, while @code{memv} -uses @code{eqv?} and @code{member} uses @code{equal?}.@footnote{Although -they are often used as predicates, @code{memq}, @code{memv}, and -@code{member} do not have question marks in their names because they -return useful values rather than just @code{#t} or @code{#f}.} - -@example -@group -(memq 'a '(a b c)) @result{} (a b c) -(memq 'b '(a b c)) @result{} (b c) -(memq 'a '(b c d)) @result{} #f -(memq (list 'a) '(b (a) c)) @result{} #f -(member (list 'a) '(b (a) c)) @result{} ((a) c) -(memq 101 '(100 101 102)) @result{} @r{unspecified} -(memv 101 '(100 101 102)) @result{} (101 102) -@end group -@end example -@end deffn - -@deffn procedure member-procedure predicate -Returns a procedure similar to @code{memq}, except that @var{predicate}, -which must be an equivalence predicate, is used instead of @code{eq?}. -This could be used to define @code{memv} as follows: - -@example -(define memv (member-procedure eqv?)) -@end example -@end deffn - -@need 1000 -@node Mapping of Lists, Reduction of Lists, Searching Lists, Lists -@section Mapping of Lists -@cindex mapping, of list - -@deffn {procedure} map procedure list list @dots{} -@var{Procedure} must be a procedure taking as many arguments as there -are @var{list}s. If more than one @var{list} is given, then they must -all be the same length. @code{map} applies @var{procedure} element-wise -to the elements of the @var{list}s and returns a list of the results, in -order from left to right. The dynamic order in which @var{procedure} is -applied to the elements of the @var{list}s is unspecified; use -@code{for-each} to sequence side effects. - -@example -@group -(map cadr '((a b) (d e) (g h))) @result{} (b e h) -(map (lambda (n) (expt n n)) '(1 2 3 4)) @result{} (1 4 27 256) -(map + '(1 2 3) '(4 5 6)) @result{} (5 7 9) -(let ((count 0)) - (map (lambda (ignored) - (set! count (+ count 1)) - count) - '(a b c))) @result{} @r{unspecified} -@end group -@end example -@end deffn - -@deffn procedure map* initial-value procedure list1 list2 @dots{} -Similar to @code{map}, except that the resulting list is terminated by -@var{initial-value} rather than the empty list. The following are -equivalent: - -@example -@group -(map @var{procedure} @var{list} @var{list} @dots{}) -(map* '() @var{procedure} @var{list} @var{list} @dots{}) -@end group -@end example -@end deffn - -@deffn procedure append-map procedure list list @dots{} -@deffnx procedure append-map* initial-value procedure list list @dots{} -@findex append -Similar to @code{map} and @code{map*}, respectively, except that the -results of applying @var{procedure} to the elements of @var{list}s are -concatenated together by @code{append} rather than by @code{cons}. The -following are equivalent, except that the former is more efficient: - -@example -@group -(append-map @var{procedure} @var{list} @var{list} @dots{}) -(apply append (map @var{procedure} @var{list} @var{list} @dots{})) -@end group -@end example -@end deffn - -@deffn procedure append-map! procedure list list @dots{} -@deffnx procedure append-map*! initial-value procedure list list @dots{} -@findex append! -Similar to @code{map} and @code{map*}, respectively, except that the -results of applying @var{procedure} to the elements of @var{list}s are -concatenated together by @code{append!} rather than by @code{cons}. The -following are equivalent, except that the former is more efficient: - -@example -@group -(append-map! @var{procedure} @var{list} @var{list} @dots{}) -(apply append! (map @var{procedure} @var{list} @var{list} @dots{})) -@end group -@end example -@end deffn - -@deffn {procedure} for-each procedure list list @dots{} -The arguments to @code{for-each} are like the arguments to @code{map}, -but @code{for-each} calls @var{procedure} for its side effects rather -than for its values. Unlike @code{map}, @code{for-each} is guaranteed -to call @var{procedure} on the elements of the @var{list}s in order from -the first element to the last, and the value returned by @code{for-each} -is unspecified. - -@example -@group -(let ((v (make-vector 5))) - (for-each (lambda (i) - (vector-set! v i (* i i))) - '(0 1 2 3 4)) - v) @result{} #(0 1 4 9 16) -@end group -@end example -@end deffn - -@node Reduction of Lists, Miscellaneous List Operations, Mapping of Lists, Lists -@section Reduction of Lists -@cindex reduction, of list - -@deffn procedure reduce procedure initial list -Combines all the elements of @var{list} using the binary operation -@var{procedure}. For example, using @code{+} one can add up all the -elements: - -@example -(reduce + 0 list-of-numbers) -@end example - -The argument @var{initial} is used only if @var{list} is empty; in this -case @var{initial} is the result of the call to @code{reduce}. If -@var{list} has a single argument, it is returned. Otherwise, the arguments -are reduced in a left-associative fashion. For example: - -@example -@group -(reduce + 0 '(1 2 3 4)) @result{} 10 -(reduce + 0 '(1 2)) @result{} 3 -(reduce + 0 '(1)) @result{} 1 -(reduce + 0 '()) @result{} 0 -(reduce + 0 '(foo)) @result{} foo -(reduce list '() '(1 2 3 4)) @result{} (((1 2) 3) 4) -@end group -@end example -@end deffn - -@deffn procedure reduce-right procedure initial list -Like @code{reduce} except that it is right-associative. - -@example -(reduce-right list '() '(1 2 3 4)) @result{} (1 (2 (3 4))) -@end example -@end deffn - -@deffn procedure fold-right procedure initial list -Combines all of the elements of @var{list} using the binary operation -@var{procedure}. Unlike @code{reduce} and @code{reduce-right}, -@var{initial} is always used: - -@example -@group -(fold-right + 0 '(1 2 3 4)) @result{} 10 -(fold-right + 0 '(foo)) @error{} Illegal datum -(fold-right list '() '(1 2 3 4)) @result{} (1 (2 (3 (4 ())))) -@end group -@end example - -@code{Fold-right} has interesting properties because it establishes a -homomorphism between (@code{cons}, @code{()}) and (@var{procedure}, -@var{initial}). It can be thought of as replacing the pairs in the -spine of the list with @var{procedure} and replacing the @code{()} at -the end with @var{initial}. Many of the classical list-processing -procedures can be expressed in terms of @code{fold-right}, at least for -the simple versions that take a fixed number of arguments: - -@example -@group -(define (copy-list list) - (fold-right cons '() list)) - -(define (append list1 list2) - (fold-right cons list2 list1)) - -(define (map p list) - (fold-right (lambda (x r) (cons (p x) r)) '() list)) - -(define (reverse items) - (fold-right (lambda (x r) (append r (list x))) '() items)) -@end group -@end example -@end deffn - -@deffn procedure fold-left procedure initial list -Combines all the elements of @var{list} using the binary operation -@var{procedure}. Elements are combined starting with @var{initial} and -then the elements of @var{list} from left to right. Whereas -@code{fold-right} is recursive in nature, capturing the essence of -@code{cdr}-ing down a list and then computing a result, @var{fold-left} -is iterative in nature, combining the elements as the list is traversed. - -@example -@group -(fold-left list '() '(1 2 3 4)) @result{} ((((() 1) 2) 3) 4) - -(define (length list) - (fold-left (lambda (sum element) (+ sum 1)) 0 list)) - -(define (reverse items) - (fold-left (lambda (x y) (cons y x)) () items)) -@end group -@end example -@end deffn - -@deffn procedure there-exists? list predicate -@var{Predicate} must be a procedure of one argument. Applies -@var{predicate} to each element of @var{list}, in order from left to -right. If @var{predicate} is true for any element of @var{list}, the -value yielded by @var{predicate} is immediately returned as the value of -@code{there-exists?}; @var{predicate} will not be applied to the -remaining elements of @var{list}. If @var{predicate} returns @code{#f} -for all of the elements of @var{list}, then @code{#f} is returned. -@end deffn - -@deffn procedure for-all? list predicate -@var{Predicate} must be a procedure of one argument. Applies -@var{predicate} to each element of @var{list}, in order from left to -right. If @var{predicate} returns @code{#f} for any element of -@var{list}, @code{#f} is immediately returned as the value of -@code{for-all?}; @var{predicate} will not be applied to the remaining -elements of @var{list}. If @var{predicate} is true for all of the -elements of @var{list}, then @code{#t} is returned. -@end deffn - -@node Miscellaneous List Operations, , Reduction of Lists, Lists -@section Miscellaneous List Operations - -@deffn procedure circular-list object @dots{} -@deffnx procedure make-circular-list k [element] -@cindex circular list -@cindex construction, of circular list -@findex list -@findex make-list -These procedures are like @code{list} and @code{make-list}, -respectively, except that the returned lists are circular. -@code{circular-list} could have been defined like this: - -@example -@group -(define (circular-list . objects) - (append! objects objects)) -@end group -@end example -@end deffn - -@deffn procedure reverse list -@cindex reversal, of list -Returns a newly allocated list consisting of the top-level elements of -@var{list} in reverse order. - -@example -@group -(reverse '(a b c)) @result{} (c b a) -(reverse '(a (b c) d (e (f)))) @result{} ((e (f)) d (b c) a) -@end group -@end example -@end deffn - -@deffn procedure reverse! list -Returns a list consisting of the top-level elements of @var{list} in -reverse order. @code{reverse!} is like @code{reverse}, except that it -destructively modifies @var{list}. Because the result may not be -@code{eqv?} to @var{list}, it is desirable to do something like -@code{(set! x (reverse! x))}. -@end deffn - -@deffn procedure sort sequence procedure -@deffnx procedure merge-sort sequence procedure -@deffnx procedure quick-sort sequence procedure -@cindex total ordering (defn) -@var{Sequence} must be either a list or a vector. @var{Procedure} must be a -procedure of two arguments that defines a @dfn{total ordering} on the -elements of @var{sequence}. In other words, if @var{x} and @var{y} are two -distinct elements of @var{sequence}, then it must be the case that - -@example -@group -(and (@var{procedure} @var{x} @var{y}) - (@var{procedure} @var{y} @var{x})) - @result{} #f -@end group -@end example - -If @var{sequence} is a list (vector), @code{sort} returns a newly -allocated list (vector) whose elements are those of @var{sequence}, -except that they are rearranged to be sorted in the order defined by -@var{procedure}. So, for example, if the elements of @var{sequence} are -numbers, and @var{procedure} is @code{<}, then the resulting elements -are sorted in monotonically nondecreasing order. Likewise, if -@var{procedure} is @code{>}, the resulting elements are sorted in -monotonically nonincreasing order. To be precise, if @var{x} and -@var{y} are any two adjacent elements in the result, where @var{x} -precedes @var{y}, it is the case that - -@example -@group -(@var{procedure} @var{y} @var{x}) - @result{} #f -@end group -@end example - -Two sorting algorithms are implemented: @code{merge-sort} and -@code{quick-sort}. The procedure @code{sort} is an alias for -@code{merge-sort}. - -See also the definition of @code{sort!}. -@end deffn - -@node Vectors, Bit Strings, Lists, Top -@chapter Vectors - -@cindex vector (defn) -@dfn{Vectors} are heterogenous structures whose elements are indexed by -exact non-negative integers. A vector typically occupies less space -than a list of the same length, and the average time required to access -a randomly chosen element is typically less for the vector than for the -list. - -@cindex length, of vector (defn) -@cindex index, of vector (defn) -@cindex valid index, of vector (defn) -@cindex vector length (defn) -@cindex vector index (defn) -The @dfn{length} of a vector is the number of elements that it contains. -This number is an exact non-negative integer that is fixed when the -vector is created. The @dfn{valid indexes} of a vector are the exact -non-negative integers less than the length of the vector. The first -element in a vector is indexed by zero, and the last element is indexed -by one less than the length of the vector. - -@cindex external representation, for vector -@cindex #( as external representation -@cindex parenthesis, as external representation -@findex #( -Vectors are written using the notation @code{#(@var{object} @dots{})}. -For example, a vector of length 3 containing the number zero in element -0, the list @code{(2 2 2 2)} in element 1, and the string @code{"Anna"} -in element 2 can be written as - -@example -#(0 (2 2 2 2) "Anna") -@end example - -@noindent -Note that this is the external representation of a vector, not an -expression evaluating to a vector. Like list constants, vector -constants must be quoted: - -@example -'#(0 (2 2 2 2) "Anna") @result{} #(0 (2 2 2 2) "Anna") -@end example - -@cindex subvector (defn) -@cindex start, of subvector (defn) -@cindex end, of subvector (defn) -@cindex index, of subvector (defn) -@cindex valid index, of subvector (defn) -A number of the vector procedures operate on subvectors. A -@dfn{subvector} is a segment of a vector that is specified by two exact -non-negative integers, @var{start} and @var{end}. @var{Start} is the -index of the first element that is included in the subvector, and -@var{end} is one greater than the index of the last element that is -included in the subvector. Thus if @var{start} and @var{end} are the -same, they refer to a null subvector, and if @var{start} is zero and -@var{end} is the length of the vector, they refer to the entire vector. -The @dfn{valid indexes} of a subvector are the exact integers between -@var{start} inclusive and @var{end} exclusive. - -@menu -* Construction of Vectors:: -* Selecting Vector Components:: -* Cutting Vectors:: -* Modifying Vectors:: -@end menu - -@node Construction of Vectors, Selecting Vector Components, Vectors, Vectors -@section Construction of Vectors -@cindex construction, of vector - -@deffn {procedure} make-vector k [object] -Returns a newly allocated vector of @var{k} elements. If @var{object} -is specified, @code{make-vector} initializes each element of the vector -to @var{object}. Otherwise the initial elements of the result are -unspecified. -@end deffn - -@deffn procedure vector object @dots{} -@findex list -Returns a newly allocated vector whose elements are the given arguments. -@code{vector} is analogous to @code{list}. - -@example -(vector 'a 'b 'c) @result{} #(a b c) -@end example -@end deffn - -@deffn procedure vector-copy vector -@cindex copying, of vector -Returns a newly allocated vector that is a copy of @var{vector}. -@end deffn - -@deffn procedure list->vector list -@cindex list, converting to vector -@findex vector->list -Returns a newly allocated vector initialized to the elements of -@var{list}. The inverse of @code{list->vector} is @code{vector->list}. - -@example -(list->vector '(dididit dah)) @result{} #(dididit dah) -@end example -@end deffn - -@deffn procedure make-initialized-vector k initialization -Similar to @code{make-vector}, except that the elements of the result -are determined by calling the procedure @var{initialization} on the -indices. For example: - -@example -@group -(make-initialized-vector 5 (lambda (x) (* x x))) - @result{} #(0 1 4 9 16) -@end group -@end example -@end deffn - -@deffn procedure vector-grow vector k -@cindex growing, of vector -@var{K} must be greater than or equal to the length of @var{vector}. -Returns a newly allocated vector of length @var{k}. The first -@code{(vector-length @var{vector})} elements of the result are -initialized from the corresponding elements of @var{vector}. The -remaining elements of the result are unspecified. -@end deffn - -@deffn procedure vector-map procedure vector -@cindex mapping, of vector -@var{Procedure} must be a procedure of one argument. @code{vector-map} -applies @var{procedure} element-wise to the elements of @var{vector} and -returns a newly allocated vector of the results, in order from left to -right. The dynamic order in which @var{procedure} is applied to the -elements of @var{vector} is unspecified. - -@example -@group -(vector-map cadr '#((a b) (d e) (g h))) @result{} #(b e h) -(vector-map (lambda (n) (expt n n)) '#(1 2 3 4)) - @result{} #(1 4 27 256) -(vector-map + '#(5 7 9)) @result{} #(5 7 9) -@end group -@end example -@end deffn - -@node Selecting Vector Components, Cutting Vectors, Construction of Vectors, Vectors -@section Selecting Vector Components -@cindex selection, of vector component -@cindex component selection, of vector - -@deffn procedure vector? object -@cindex type predicate, for vector -Returns @code{#t} if @var{object} is a vector; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure vector-length vector -Returns the number of elements in @var{vector}. -@end deffn - -@deffn procedure vector-ref vector k -Returns the contents of element @var{k} of @var{vector}. @var{K} must -be a valid index of @var{vector}. - -@example -(vector-ref '#(1 1 2 3 5 8 13 21) 5) @result{} 8 -@end example -@end deffn - -@deffn procedure vector-set! vector k object -Stores @var{object} in element @var{k} of @var{vector} and returns an -unspecified value. @var{K} must be a valid index of -@var{vector}. - -@example -@group -(let ((vec (vector 0 '(2 2 2 2) "Anna"))) - (vector-set! vec 1 '("Sue" "Sue")) - vec) - @result{} #(0 ("Sue" "Sue") "Anna") -@end group -@end example -@end deffn - -@deffn procedure vector-first vector -@deffnx procedure vector-second vector -@deffnx procedure vector-third vector -@deffnx procedure vector-fourth vector -@deffnx procedure vector-fifth vector -@deffnx procedure vector-sixth vector -@deffnx procedure vector-seventh vector -@deffnx procedure vector-eighth vector -These procedures access the first several elements of @var{vector} in -the obvious way. It is an error if the implicit index of one of these -procedurs is not a valid index of @var{vector}. -@end deffn - -@deffn procedure vector-binary-search vector keybit-string length integer -Both @var{length} and @var{integer} must be exact non-negative integers. -Converts @var{integer} into a newly allocated bit string of @var{length} -bits. Signals an error of type @code{condition-type:bad-range-argument} -if @var{integer} is too large to be represented in @var{length} bits. -@findex condition-type:bad-range-argument -@end deffn - -@deffn procedure signed-integer->bit-string length integer -@var{Length} must be an exact non-negative integer, and @var{integer} -may be any exact integer. Converts @var{integer} into a newly allocated -bit string of @var{length} bits, using two's complement encoding for -negative numbers. Signals an error of type -@code{condition-type:bad-range-argument} if @var{integer} is too large -to be represented in @var{length} bits. -@findex condition-type:bad-range-argument -@end deffn - -@deffn procedure bit-string->unsigned-integer bit-string -@deffnx procedure bit-string->signed-integer bit-string -Converts @var{bit-string} into an exact integer. -@code{bit-string->signed-integer} regards @var{bit-string} as a two's -complement representation of a signed integer, and produces an integer -of like sign and absolute value. @code{bit-string->unsigned-integer} -regards @var{bit-string} as an unsigned quantity and converts to an -integer accordingly. -@end deffn - -@node Miscellaneous Datatypes, Associations, Bit Strings, Top -@chapter Miscellaneous Datatypes - -@menu -* Booleans:: -* Symbols:: -* Cells:: -* Records:: -* Promises:: -* Streams:: -* Weak Pairs:: -@end menu - -@node Booleans, Symbols, Miscellaneous Datatypes, Miscellaneous Datatypes -@section Booleans - -@findex #t -@findex #f -@cindex #t as external representation -@cindex #f as external representation -@cindex boolean object (defn) -@cindex true, boolean object (defn) -@cindex false, boolean object (defn) -The @dfn{boolean objects} are @dfn{true} and @dfn{false}. The boolean -constant true is written as @samp{#t}, and the boolean constant false is -written as @samp{#f}. - -@findex if -@findex cond -@findex and -@findex or -The primary use for boolean objects is in the conditional expressions -@code{if}, @code{cond}, @code{and}, and @code{or}; the behavior of these -expressions is determined by whether objects are true or false. These -expressions count only @code{#f} as false. They count everything else, -including @code{#t}, pairs, symbols, numbers, strings, vectors, and -procedures as true (but @pxref{True and False}). - -@findex t -@findex nil -Programmers accustomed to other dialects of Lisp should note that Scheme -distinguishes @code{#f} and the empty list from the symbol @code{nil}. -Similarly, @code{#t} is distinguished from the symbol @code{t}. In -fact, the boolean objects (and the empty list) are not symbols at all. - -Boolean constants evaluate to themselves, so you don't need to quote -them. - -@example -@group -#t @result{} #t -#f @result{} #f -'#f @result{} #f -t @error{} Unbound variable -@end group -@end example - -@defvr variable false -@defvrx variable true -These variables are bound to the objects @code{#f} and @code{#t} -respectively. The compiler, given the @code{usual-integrations} -declaration, replaces references to these variables with their -respective values. - -Note that the symbol @code{true} is not equivalent to @code{#t}, and the -symbol @code{false} is not equivalent to @code{#f}. -@end defvr - -@deffn procedure boolean? object -@cindex type predicate, for boolean -Returns @code{#t} if @var{object} is either @code{#t} or @code{#f}; -otherwise returns @code{#f}. - -@example -@group -(boolean? #f) @result{} #t -(boolean? 0) @result{} #f -@end group -@end example -@end deffn - -@deffn procedure not object -@deffnx procedure false? object -@cindex false, predicate for -@cindex inverse, of boolean object -These procedures return @code{#t} if @var{object} is false; otherwise -they return @code{#f}. In other words they @emph{invert} boolean -values. These two procedures have identical semantics; their names are -different to give different connotations to the test. - -@example -@group -(not #t) @result{} #f -(not 3) @result{} #f -(not (list 3)) @result{} #f -(not #f) @result{} #t -@end group -@end example -@end deffn - -@deffn procedure boolean=? obj1 obj2 -@cindex boolean object, equivalence predicate -@cindex equivalence predicate, for boolean objects -@cindex comparison, of boolean objects -This predicate is true iff @var{obj1} and @var{obj2} are either both true -or both false. -@end deffn - -@deffn procedure boolean/and object @dots{} -This procedure returns @code{#t} if none of its arguments are @code{#f}. -Otherwise it returns @code{#f}. -@end deffn - -@deffn procedure boolean/or object @dots{} -This procedure returns @code{#f} if all of its arguments are @code{#f}. -Otherwise it returns @code{#t}. -@end deffn - -@node Symbols, Cells, Booleans, Miscellaneous Datatypes -@section Symbols - -@cindex symbol (defn) -@cindex interned symbol (defn) -@cindex uninterned symbol (defn) -@cindex property list, of symbol -@cindex disembodied property list -@findex read -MIT/GNU Scheme provides two types of symbols: @dfn{interned} and -@dfn{uninterned}. Interned symbols are far more common than uninterned -symbols, and there are more ways to create them. Interned symbols have -an external representation that is recognized by the procedure -@code{read}; uninterned symbols do not.@footnote{In older dialects of -Lisp, uninterned symbols were fairly important. This was true because -symbols were complicated data structures: in addition to having value -cells (and sometimes, function cells), these structures contained -@dfn{property lists}. Because of this, uninterned symbols were often -used merely for their property lists --- sometimes an uninterned symbol -used this way was referred to as a @dfn{disembodied property list}. In -MIT/GNU Scheme, symbols do not have property lists, or any other components -besides their names. There is a different data structure similar to -disembodied property lists: one-dimensional tables (@pxref{1D Tables}). -For these reasons, uninterned symbols are not very useful in MIT/GNU Scheme. -In fact, their primary purpose is to simplify the generation of unique -variable names in programs that generate Scheme code.} - -@findex string=? -@findex eq? -Interned symbols have an extremely useful property: any two interned -symbols whose names are the same, in the sense of @code{string=?}, are -the same object (i.e.@: they are @code{eq?} to one another). The term -@dfn{interned} refers to the process of @dfn{interning} by which this is -accomplished. Uninterned symbols do not share this property. - -@cindex case, of interned symbol -@cindex alphabetic case, of interned symbol -@findex write -The names of interned symbols are not distinguished by their alphabetic -case. Because of this, MIT/GNU Scheme converts all alphabetic -characters in the name of an interned symbol to a specific case (lower -case) when the symbol is created. When the name of an interned symbol -is referenced (using @code{symbol->string}) or written (using -@code{write}) it appears in this case. It is a bad idea to depend on -the name being lower case. In fact, it is preferable to take this one -step further: don't depend on the name of a symbol being in a uniform -case. - -@cindex external representation, for symbol -@findex read -@findex write -The rules for writing an interned symbol are the same as the rules for -writing an identifier (@pxref{Identifiers}). Any interned symbol that -has been returned as part of a literal expression, or read using the -@code{read} procedure and subsequently written out using the -@code{write} procedure, will read back in as the identical symbol (in -the sense of @code{eq?}). - -Usually it is also true that reading in an interned symbol that was -previously written out produces the same symbol. An exception are -symbols created by the procedures @code{string->symbol} and -@code{intern}; they can create symbols for which this write/read -invariance may not hold because the symbols' names contain special -characters or letters in the non-standard case.@footnote{MIT/GNU Scheme -reserves a specific set of interned symbols for its own use. If you use -these reserved symbols it is possible that you could break specific -pieces of software that depend on them. The reserved symbols all have -names beginning with the characters @samp{#[} and ending with the -character @samp{]}; thus none of these symbols can be read by the -procedure @code{read} and hence are not likely to be used by accident. -For example, @code{(intern "#[unnamed-procedure]")} produces a reserved -symbol.} - -@findex read -The external representation for uninterned symbols is special, to -distinguish them from interned symbols and prevent them from being -recognized by the @code{read} procedure: - -@example -@group -(string->uninterned-symbol "foo") - @result{} #[uninterned-symbol 30 foo] -@end group -@end example - -In this section, the procedures that return symbols as values will -either always return interned symbols, or always return uninterned -symbols. The procedures that accept symbols as arguments will always -accept either interned or uninterned symbols, and do not distinguish the -two. - -@deffn procedure symbol? object -@cindex type predicate, for symbol -Returns @code{#t} if @var{object} is a symbol, otherwise returns -@code{#f}. - -@example -@group -(symbol? 'foo) @result{} #t -(symbol? (car '(a b))) @result{} #t -(symbol? "bar") @result{} #f -@end group -@end example -@end deffn - -@deffn procedure symbol->string symbol -@cindex name, of symbol -@cindex print name, of symbol -@findex string=? -@findex string-set! -Returns the name of @var{symbol} as a string. If @var{symbol} was -returned by @code{string->symbol}, the value of this procedure will be -identical (in the sense of @code{string=?}) to the string that was -passed to @code{string->symbol}. It is an error to apply mutation -procedures such as @code{string-set!} to strings returned by this -procedure. - -@example -@group -(symbol->string 'flying-fish) @result{} "flying-fish" -(symbol->string 'Martin) @result{} "martin" -(symbol->string (string->symbol "Malvina")) - @result{} "Malvina" -@end group -@end example - -Note that two distinct uninterned symbols can have the same name. -@end deffn - -@deffn procedure intern string -@cindex interning, of symbols -@cindex construction, of symbols -Returns the interned symbol whose name is @var{string}. Converts -@var{string} to the standard alphabetic case before generating the -symbol. This is the preferred way to create interned symbols, as it -guarantees the following independent of which case the implementation -uses for symbols' names: - -@example -(eq? 'bitBlt (intern "bitBlt")) @result{} #t -@end example - -The user should take care that @var{string} obeys the rules for -identifiers (@pxref{Identifiers}), otherwise the resulting symbol cannot -be read as itself. -@end deffn - -@deffn procedure intern-soft string -Returns the interned symbol whose name is @var{string}. Converts -@var{string} to the standard alphabetic case before generating the -symbol. If no such interned symbol exists, returns @code{#f}. - -This is exactly like @code{intern}, except that it will not create an -interned symbol, but only returns symbols that already exist. -@end deffn - -@deffn procedure string->symbol string -@cindex string, interning as symbol -Returns the interned symbol whose name is @var{string}. Although you -can use this procedure to create symbols with names containing special -characters or lowercase letters, it's usually a bad idea to create such -symbols because they cannot be read as themselves. See -@code{symbol->string}. - -@example -@group -(eq? 'mISSISSIppi 'mississippi) @result{} #t -(string->symbol "mISSISSIppi") - @result{} @r{the symbol with the name} "mISSISSIppi" -(eq? 'bitBlt (string->symbol "bitBlt")) @result{} #f -(eq? 'JollyWog - (string->symbol - (symbol->string 'JollyWog))) @result{} #t -(string=? "K. Harper, M.D." - (symbol->string - (string->symbol - "K. Harper, M.D."))) @result{} #t -@end group -@end example -@end deffn - -@deffn procedure string->uninterned-symbol string -Returns a newly allocated uninterned symbol whose name is @var{string}. -It is unimportant what case or characters are used in -@var{string}. - -Note: this is the fastest way to make a symbol. -@end deffn - -@deffn procedure generate-uninterned-symbol [object] -@cindex gensym (see uninterned symbol) -@findex eq? -Returns a newly allocated uninterned symbol that is guaranteed to be -different from any other object. The symbol's name consists of a prefix -string followed by the (exact non-negative integer) value of an internal -counter. The counter is initially zero, and is incremented after each -call to this procedure. - -The optional argument @var{object} is used to control how the symbol is -generated. It may take one of the following values: - -@itemize @bullet -@item -If @var{object} is omitted or @code{#f}, the prefix is @code{"G"}. - -@item -If @var{object} is an exact non-negative integer, the internal counter -is set to that integer prior to generating the result. - -@item -If @var{object} is a string, it is used as the prefix. - -@item -If @var{object} is a symbol, its name is used as the prefix. -@end itemize - -@example -@group -(generate-uninterned-symbol) - @result{} #[uninterned-symbol 31 G0] -(generate-uninterned-symbol) - @result{} #[uninterned-symbol 32 G1] -(generate-uninterned-symbol 'this) - @result{} #[uninterned-symbol 33 this2] -(generate-uninterned-symbol) - @result{} #[uninterned-symbol 34 G3] -(generate-uninterned-symbol 100) - @result{} #[uninterned-symbol 35 G100] -(generate-uninterned-symbol) - @result{} #[uninterned-symbol 36 G101] -@end group -@end example -@end deffn - -@deffn procedure symbol-append symbol @dots{} -@cindex appending, of symbols -@cindex pasting, of symbols -Returns the interned symbol whose name is formed by concatenating the -names of the given symbols. This procedure preserves the case of the -names of its arguments, so if one or more of the arguments' names has -non-standard case, the result will also have non-standard case. - -@example -@group -(symbol-append 'foo- 'bar) @result{} foo-bar -@r{;; the arguments may be uninterned:} -(symbol-append 'foo- (string->uninterned-symbol "baz")) - @result{} foo-baz -@r{;; the result has the same case as the arguments:} -(symbol-append 'foo- (string->symbol "BAZ")) @result{} foo-BAZ -@end group -@end example -@end deffn - -@deffn procedure symbol-hash symbol -@cindex hashing, of symbol -@findex string-hash -Returns a hash number for @var{symbol}, which is computed by calling -@code{string-hash} on @var{symbol}'s name. The hash number is an exact -non-negative integer. -@end deffn - -@deffn procedure symbol-hash-mod symbol modulus -@var{Modulus} must be an exact positive integer. Equivalent to - -@example -@group -(modulo (symbol-hash @var{symbol}) @var{modulus}) -@end group -@end example - -This procedure is provided for convenience in constructing hash tables. -However, it is normally preferable to use @code{make-eq-hash-table} to -build hash tables keyed by symbols, because @code{eq?} hash tables are -much faster. -@end deffn - -@deffn procedure symbolstring @var{symbol1}) - (symbol->string @var{symbol2})) -@end group -@end example -@end deffn - -@node Cells, Records, Symbols, Miscellaneous Datatypes -@section Cells - -@cindex cell (defn) -@dfn{Cells} are data structures similar to pairs except that they have -only one element. They are useful for managing state. - -@deffn procedure cell? object -@cindex type predicate, for cell -Returns @code{#t} if @var{object} is a cell; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure make-cell object -@cindex construction, of cell -Returns a newly allocated cell whose contents is @var{object}. -@end deffn - -@deffn procedure cell-contents cell -@cindex selection, of cell component -@cindex component selection, of cell -Returns the current contents of @var{cell}. -@end deffn - -@deffn procedure set-cell-contents! cell object -Alters the contents of @var{cell} to be @var{object}. Returns an -unspecified value. -@end deffn - -@deffn procedure bind-cell-contents! cell object thunk -Alters the contents of @var{cell} to be @var{object}, calls @var{thunk} -with no arguments, then restores the original contents of @var{cell} and -returns the value returned by @var{thunk}. This is completely -equivalent to dynamic binding of a variable, including the behavior when -continuations are used (@pxref{Dynamic Binding}). -@end deffn - -@node Records, Promises, Cells, Miscellaneous Datatypes -@section Records - -MIT/GNU Scheme provides a @dfn{record} abstraction, which is a simple and -flexible mechanism for building structures with named components. -Records can be defined and accessed using the procedures defined in this -section. A less flexible but more concise way to manipulate records is -to use the @code{define-structure} special form (@pxref{Structure -Definitions}). -@findex define-structure - -@deffn procedure make-record-type type-name field-names -@cindex record-type descriptor (defn) -Returns a @dfn{record-type descriptor}, a value representing a new data -type, disjoint from all others. The @var{type-name} argument must be a -string, but is only used for debugging purposes (such as the printed -representation of a record of the new type). The @var{field-names} -argument is a list of symbols naming the @dfn{fields} of a record of the -new type. It is an error if the list contains any duplicates. It is -unspecified how record-type descriptors are represented. -@end deffn - -@deffn procedure record-constructor record-type [field-names] -Returns a procedure for constructing new members of the type represented -by @var{record-type}. The returned procedure accepts exactly as many -arguments as there are symbols in the given list, @var{field-names}; -these are used, in order, as the initial values of those fields in a new -record, which is returned by the constructor procedure. The values of -any fields not named in the list of @var{field-names} are unspecified. -The @var{field-names} argument defaults to the list of field-names in -the call to @code{make-record-type} that created the type represented by -@var{record-type}; if the @var{field-names} argument is provided, it is -an error if it contains any duplicates or any symbols not in the default -list. -@end deffn - -@deffn procedure record-predicate record-type -Returns a procedure for testing membership in the type represented by -@var{record-type}. The returned procedure accepts exactly one argument -and returns @code{#t} if the argument is a member of the indicated -record type; it returns @code{#f} otherwise. -@end deffn - -@deffn procedure record-accessor record-type field-name -Returns a procedure for reading the value of a particular field of a -member of the type represented by @var{record-type}. The returned -procedure accepts exactly one argument which must be a record of the -appropriate type; it returns the current value of the field named by the -symbol @var{field-name} in that record. The symbol @var{field-name} -must be a member of the list of field names in the call to -@code{make-record-type} that created the type represented by -@var{record-type}. -@end deffn - -@deffn procedure record-modifier record-type field-name -Returns a procedure for writing the value of a particular field of a -member of the type represented by @var{record-type}. The returned -procedure accepts exactly two arguments: first, a record of the -appropriate type, and second, an arbitrary Scheme value; it modifies the -field named by the symbol @var{field-name} in that record to contain the -given value. The returned value of the modifier procedure is -unspecified. The symbol @var{field-name} must be a member of the list -of field names in the call to @code{make-record-type} that created the -type represented by @var{record-type}. -@end deffn - -@deffn procedure record? object -@cindex type predicate, for record -Returns @code{#t} if @var{object} is a record of any type and @code{#f} -otherwise. Note that @code{record?} may be true of any Scheme value; of -course, if it returns @code{#t} for some particular value, then -@code{record-type-descriptor} is applicable to that value and returns an -appropriate descriptor. -@end deffn - -@deffn procedure record-type-descriptor record -Returns the record-type descriptor representing the type of -@var{record}. That is, for example, if the returned descriptor were -passed to @code{record-predicate}, the resulting predicate would return -@code{#t} when passed @var{record}. Note that it is not necessarily the -case that the returned descriptor is the one that was passed to -@code{record-constructor} in the call that created the constructor -procedure that created @var{record}. -@end deffn - -@deffn procedure record-type? object -@cindex type predicate, for record type -Returns @code{#t} if @var{object} is a record-type descriptor; otherwise -returns @code{#f}. -@end deffn - -@deffn procedure record-type-name record-type -Returns the type name associated with the type represented by -@var{record-type}. The returned value is @code{eqv?} to the -@var{type-name} argument given in the call to @code{make-record-type} -that created the type represented by @var{record-type}. -@end deffn - -@deffn procedure record-type-field-names record-type -Returns a list of the symbols naming the fields in members of the type -represented by @var{record-type}. The returned value is @code{equal?} -to the @var{field-names} argument given in the call to -@code{make-record-type} that created the type represented by -@var{record-type}.@footnote{In MIT/GNU Scheme, the returned list is always -newly allocated.} -@end deffn - -@node Promises, Streams, Records, Miscellaneous Datatypes -@section Promises - -@deffn {special form} delay expression -@cindex promise (defn) -@cindex promise, construction -@cindex construction, of promise -@cindex lazy evaluation (defn) -@cindex call by need evaluation (defn) -@cindex evaluation, lazy (defn) -@cindex evaluation, call by need (defn) -The @code{delay} construct is used together with the procedure -@code{force} to implement @dfn{lazy evaluation} or @dfn{call by need}. -@code{(delay @var{expression})} returns an object called a @dfn{promise} -which at some point in the future may be asked (by the @code{force} -procedure) to evaluate @var{expression} and deliver the resulting value. -@end deffn - -@deffn procedure force promise -@cindex promise, forcing -@cindex forcing, of promise -@cindex memoization, of promise -Forces the value of @emph{promise}. If no value has been computed for -the promise, then a value is computed and returned. The value of the -promise is cached (or ``memoized'') so that if it is forced a second -time, the previously computed value is returned without any -recomputation. - -@example -@group -(force (delay (+ 1 2))) @result{} 3 - -(let ((p (delay (+ 1 2)))) - (list (force p) (force p))) @result{} (3 3) -@end group - -@group -(define head car) - -(define tail - (lambda (stream) - (force (cdr stream)))) -@end group - -@group -(define a-stream - (letrec ((next - (lambda (n) - (cons n (delay (next (+ n 1))))))) - (next 0))) - -(head (tail (tail a-stream))) @result{} 2 -@end group -@end example -@end deffn - -@deffn procedure promise? object -@cindex type predicate, for promise -Returns @code{#t} if @var{object} is a promise; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure promise-forced? promise -Returns @code{#t} if @var{promise} has been forced and its value cached; -otherwise returns @code{#f}. -@end deffn - -@deffn procedure promise-value promise -If @var{promise} has been forced and its value cached, this procedure -returns the cached value. Otherwise, an error is signalled. -@end deffn - -@code{force} and @code{delay} are mainly intended for programs written -in functional style. The following examples should not be considered to -illustrate good programming style, but they illustrate the property that -the value of a promise is computed at most once. - -@example -@group -(define count 0) - -(define p - (delay - (begin - (set! count (+ count 1)) - (* x 3)))) - -(define x 5) -@end group - -@group -count @result{} 0 -p @result{} #[promise 54] -(force p) @result{} 15 -p @result{} #[promise 54] -count @result{} 1 -(force p) @result{} 15 -count @result{} 1 -@end group -@end example - -Here is a possible implementation of @code{delay} and @code{force}. We -define the expression - -@example -(delay @var{expression}) -@end example - -@noindent -to have the same meaning as the procedure call - -@example -(make-promise (lambda () @var{expression})) -@end example - -@noindent -where @code{make-promise} is defined as follows: - -@example -@group -(define make-promise - (lambda (proc) - (let ((already-run? #f) - (result #f)) - (lambda () - (cond ((not already-run?) - (set! result (proc)) - (set! already-run? #t))) - result)))) -@end group -@end example - -Promises are implemented here as procedures of no arguments, and -@code{force} simply calls its argument. - -@example -@group -(define force - (lambda (promise) - (promise))) -@end group -@end example - -Various extensions to this semantics of @code{delay} and @code{force} -are supported in some implementations (none of these are currently -supported in MIT/GNU Scheme): - -@itemize @bullet -@item -Calling @code{force} on an object that is not a promise may simply -return the object. - -@item -It may be the case that there is no means by which a promise can be -operationally distinguished from its forced value. That is, expressions -like the following may evaluate to either @code{#t} or @code{#f}, -depending on the implementation: - -@example -@group -(eqv? (delay 1) 1) @result{} @r{unspecified} -(pair? (delay (cons 1 2))) @result{} @r{unspecified} -@end group -@end example - -@item -Some implementations will implement ``implicit forcing'', where the -value of a promise is forced by primitive procedures like @code{car} and -@code{+}: - -@example -(+ (delay (* 3 7)) 13) @result{} 34 -@end example -@end itemize - -@node Streams, Weak Pairs, Promises, Miscellaneous Datatypes -@section Streams - -@cindex stream (defn) -In addition to promises, MIT/GNU Scheme supports a higher-level abstraction -called @dfn{streams}. Streams are similar to lists, except that the -tail of a stream is not computed until it is referred to. -This allows streams to be used to represent infinitely long lists. - -@deffn procedure stream object @dots{} -@cindex construction, of stream -Returns a newly allocated stream whose elements are the arguments. Note -that the expression @code{(stream)} returns the empty stream, or -end-of-stream marker. -@end deffn - -@deffn procedure list->stream list -@cindex list, converting to stream -Returns a newly allocated stream whose elements are the elements of -@var{list}. Equivalent to @code{(apply stream @var{list})}. -@end deffn - -@deffn procedure stream->list stream -@cindex stream, converting to list -Returns a newly allocated list whose elements are the elements of -@var{stream}. If @var{stream} has infinite length this procedure will -not terminate. This could have been defined by - -@example -@group -(define (stream->list stream) - (if (stream-null? stream) - '() - (cons (stream-car stream) - (stream->list (stream-cdr stream))))) -@end group -@end example -@end deffn - -@deffn {special form} cons-stream object expression -Returns a newly allocated stream pair. Equivalent to @code{(cons -@var{object} (delay @var{expression}))}. -@end deffn - -@deffn procedure stream-pair? object -@cindex type predicate, for stream pair -Returns @code{#t} if @var{object} is a pair whose cdr contains a -promise. Otherwise returns @code{#f}. This could have been defined by - -@example -@group -(define (stream-pair? object) - (and (pair? object) - (promise? (cdr object)))) -@end group -@end example -@end deffn - -@deffn procedure stream-car stream -@deffnx procedure stream-first stream -@findex car -Returns the first element in @var{stream}. @code{stream-car} is -equivalent to @code{car}. @code{stream-first} is a synonym for -@code{stream-car}. -@end deffn - -@deffn procedure stream-cdr stream -@deffnx procedure stream-rest stream -@findex force -@findex cdr -Returns the first tail of @var{stream}. Equivalent to @code{(force (cdr -@var{stream}))}. @code{stream-rest} is a synonym for @code{stream-cdr}. -@end deffn - -@deffn procedure stream-null? stream -@cindex empty stream, predicate for -@findex null? -Returns @code{#t} if @var{stream} is the end-of-stream marker; otherwise -returns @code{#f}. This is equivalent to @code{null?}, but should be -used whenever testing for the end of a stream. -@end deffn - -@deffn procedure stream-length stream -@cindex length, of stream -Returns the number of elements in @var{stream}. If @var{stream} has an -infinite number of elements this procedure will not terminate. Note -that this procedure forces all of the promises that comprise -@var{stream}. -@end deffn - -@deffn procedure stream-ref stream k -@cindex selecting, of stream component -@cindex component selection, of stream -Returns the element of @var{stream} that is indexed by @var{k}; that is, -the @var{k}th element. @var{K} must be an exact non-negative integer -strictly less than the length of @var{stream}. -@end deffn - -@deffn procedure stream-head stream k -Returns the first @var{k} elements of @var{stream} as a list. @var{K} -must be an exact non-negative integer strictly less than the length of -@var{stream}. -@end deffn - -@deffn procedure stream-tail stream k -Returns the tail of @var{stream} that is indexed by @var{k}; that is, -the @var{k}th tail. This is equivalent to performing @code{stream-cdr} -@var{k} times. @var{K} must be an exact non-negative integer strictly -less than the length of @var{stream}. -@end deffn - -@deffn procedure stream-map procedure stream stream @dots{} -@cindex mapping, of stream -Returns a newly allocated stream, each element being the result of -invoking @var{procedure} with the corresponding elements of the -@var{stream}s as its arguments. -@end deffn - -@node Weak Pairs, , Streams, Miscellaneous Datatypes -@section Weak Pairs - -@cindex weak pair (defn) -@cindex pair, weak (defn) -@dfn{Weak pairs} are a mechanism for building data structures that point -at objects without protecting them from garbage collection. The car of -a weak pair holds its pointer weakly, while the cdr holds its pointer in -the normal way. If the object in the car of a weak pair is not held -normally by any other data structure, it will be garbage-collected. - -@findex pair? -Note: weak pairs are @emph{not} pairs; that is, they do not satisfy the -predicate @code{pair?}. - -@deffn procedure weak-pair? object -@cindex type predicate, for weak pair -Returns @code{#t} if @var{object} is a weak pair; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure weak-cons car cdr -@cindex construction, of weak pair -Allocates and returns a new weak pair, with components @var{car} and -@var{cdr}. The @var{car} component is held weakly. -@end deffn - -@deffn procedure weak-pair/car? weak-pair -This predicate returns @code{#f} if the car of @var{weak-pair} has been -garbage-collected; otherwise returns @code{#t}. In other words, it is -true if @var{weak-pair} has a valid car component. -@end deffn - -@deffn procedure weak-car weak-pair -@cindex selection, of weak pair component -@cindex component selection, of weak pair -Returns the car component of @var{weak-pair}. If the car component has -been garbage-collected, this operation returns @code{#f}, but it can -also return @code{#f} if that is the value that was stored in the car. -@end deffn - -Normally, @code{weak-pair/car?} is used to determine if @code{weak-car} -would return a valid value. An obvious way of doing this would be: - -@example -@group -(if (weak-pair/car? x) - (weak-car x) - @dots{}) -@end group -@end example - -@noindent -However, since a garbage collection could occur between the call to -@code{weak-pair/car?} and @code{weak-car}, this would not always work -correctly. Instead, the following should be used, which always works: - -@example -@group -(or (weak-car x) - (and (not (weak-pair/car? x)) - @dots{})) -@end group -@end example - -The reason that the latter expression works is that @code{weak-car} -returns @code{#f} in just two instances: when the car component is -@code{#f}, and when the car component has been garbage-collected. In -the former case, if a garbage collection happens between the two calls, -it won't matter, because @code{#f} will never be garbage-collected. And -in the latter case, it also won't matter, because the car component no -longer exists and cannot be affected by the garbage collector. - -@deffn procedure weak-set-car! weak-pair object -Sets the car component of @var{weak-pair} to @var{object} and returns an -unspecified result. -@end deffn - -@deffn procedure weak-cdr weak-pair -Returns the cdr component of @var{weak-cdr}. -@end deffn - -@deffn procedure weak-set-cdr! weak-pair object -Sets the cdr component of @var{weak-pair} to @var{object} and returns an -unspecified result. -@end deffn - -@node Associations, Procedures, Miscellaneous Datatypes, Top -@chapter Associations - -MIT/GNU Scheme provides several mechanisms for associating objects with -one another. Each of these mechanisms creates a link between one or -more objects, called @dfn{keys}, and some other object, called a -@dfn{datum}. Beyond this common idea, however, each of the mechanisms -has various different properties that make it appropriate in different -situations: - -@itemize @bullet -@item -@dfn{Association lists} are one of Lisp's oldest association mechanisms. -Because they are made from ordinary pairs, they are easy to build and -manipulate, and very flexible in use. However, the average lookup time -for an association list is linear in the number of associations. - -@item -@dfn{1D tables} have a very simple interface, making them easy to use, -and offer the feature that they do not prevent their keys from being -reclaimed by the garbage collector. Like association lists, their -average lookup time is linear in the number of associations; but 1D -tables aren't as flexible. - -@item -@cindex property list -@dfn{The association table} is MIT/GNU Scheme's equivalent to the -@dfn{property lists} of Lisp. It has the advantages that the keys may -be any type of object and that it does not prevent the keys from being -reclaimed by the garbage collector. However, two linear-time lookups -must be performed, one for each key, whereas for traditional property -lists only one lookup is required for both keys. - -@item -@dfn{Hash tables} are a powerful mechanism with constant-time access to -large amounts of data. Hash tables are not as flexible as association -lists, but because their access times are independent of the number of -associations in the table, for most applications they are the mechanism -of choice. - -@item -@dfn{Balanced binary trees} are another association mechanism that is -useful for applications in which the keys are ordered. Binary trees -have access times that are proportional to the logarithm of the number -of associations in the tree. While they aren't as fast as hash tables, -they offer the advantage that the contents of the tree can be converted -to a sorted alist in linear time. Additionally, two trees can be -compared for equality in worst-case linear time. - -@item -@dfn{Red-Black trees} are a kind of balanced binary tree. The -implementation supports destructive insertion and deletion operations -with a good constant factor. - -@item -@dfn{Weight-Balanced trees} are a kind of balanced binary tree. The -implementation provides non-destructive operations. There is a -comprehensive set of operations, including: a constant-time size -operation; many high-level operations such as the set operations union, -intersection and difference; and indexing of elements by position. - -@end itemize - -@menu -* Association Lists:: -* 1D Tables:: -* The Association Table:: -* Hash Tables:: -* Object Hashing:: -* Red-Black Trees:: -* Weight-Balanced Trees:: -@end menu - -@node Association Lists, 1D Tables, Associations, Associations -@section Association Lists - -@comment **** begin CLTL **** -@cindex association list (defn) -@cindex list, association (defn) -@cindex alist (defn) -@cindex key, of association list element (defn) -An @dfn{association list}, or @dfn{alist}, is a data structure used very -frequently in Scheme. An alist is a list of pairs, each of which is -called an @dfn{association}. The car of an association is called the -@dfn{key}. - -An advantage of the alist representation is that an alist can be -incrementally augmented simply by adding new entries to the front. -Moreover, because the searching procedures @code{assv} et al.@: search the -alist in order, new entries can ``shadow'' old entries. If an alist is -viewed as a mapping from keys to data, then the mapping can be not only -augmented but also altered in a non-destructive manner by adding new -entries to the front of the alist.@footnote{This introduction is taken -from @cite{Common Lisp, The Language}, second edition, p.@: 431.} -@comment **** end CLTL **** - -@deffn procedure alist? object -@cindex type predicate, for alist -@findex list? -Returns @code{#t} if @var{object} is an association list (including the -empty list); otherwise returns @code{#f}. Any @var{object} satisfying this -predicate also satisfies @code{list?}. -@end deffn - -@deffn procedure assq object alist -@deffnx procedure assv object alist -@deffnx procedure assoc object alist -@cindex searching, of alist -@findex eq? -@findex eqv? -@findex equal? -These procedures find the first pair in @var{alist} whose car field is -@var{object}, and return that pair; the returned pair is always an -@emph{element} of @var{alist}, @emph{not} one of the pairs from which -@var{alist} is composed. If no pair in @var{alist} has @var{object} as -its car, @code{#f} (n.b.: not the empty list) is returned. @code{assq} -uses @code{eq?} to compare @var{object} with the car fields of the pairs -in @var{alist}, while @code{assv} uses @code{eqv?} and @code{assoc} uses -@code{equal?}.@footnote{Although they are often used as predicates, -@code{assq}, @code{assv}, and @code{assoc} do not have question marks in -their names because they return useful values rather than just @code{#t} -or @code{#f}.} - -@example -@group -(define e '((a 1) (b 2) (c 3))) -(assq 'a e) @result{} (a 1) -(assq 'b e) @result{} (b 2) -(assq 'd e) @result{} #f -(assq (list 'a) '(((a)) ((b)) ((c)))) @result{} #f -(assoc (list 'a) '(((a)) ((b)) ((c)))) @result{} ((a)) -(assq 5 '((2 3) (5 7) (11 13))) @result{} @r{unspecified} -(assv 5 '((2 3) (5 7) (11 13))) @result{} (5 7) -@end group -@end example -@end deffn - -@deffn procedure association-procedure predicate selector -Returns an association procedure that is similar to @code{assv}, except -that @var{selector} (a procedure of one argument) is used to select the -key from the association, and @var{predicate} (an equivalence predicate) -is used to compare the key to the given item. This can be used to make -association lists whose elements are, say, vectors instead of pairs -(also @pxref{Searching Lists}). - -For example, here is how @code{assv} could be implemented: - -@example -(define assv (association-procedure eqv? car)) -@end example - -Another example is a ``reverse association'' procedure: - -@example -(define rassv (association-procedure eqv? cdr)) -@end example -@end deffn - -@deffn procedure del-assq object alist -@deffnx procedure del-assv object alist -@deffnx procedure del-assoc object alist -@cindex deletion, of alist element -@findex eq? -@findex eqv? -@findex equal? -These procedures return a newly allocated copy of @var{alist} in which -all associations with keys equal to @var{object} have been removed. -Note that while the returned copy is a newly allocated list, the -association pairs that are the elements of the list are shared with -@var{alist}, not copied. @code{del-assq} uses @code{eq?} to compare -@var{object} with the keys, while @code{del-assv} uses @code{eqv?} and -@code{del-assoc} uses @code{equal?}. - -@example -@group -(define a - '((butcher . "231 e22nd St.") - (baker . "515 w23rd St.") - (hardware . "988 Lexington Ave."))) - -(del-assq 'baker a) - @result{} - ((butcher . "231 e22nd St.") - (hardware . "988 Lexington Ave.")) -@end group -@end example -@end deffn - -@deffn procedure del-assq! object alist -@deffnx procedure del-assv! object alist -@deffnx procedure del-assoc! object alist -@findex eq? -@findex eqv? -@findex equal? -These procedures remove from @var{alist} all associations with keys -equal to @var{object}. They return the resulting list. -@code{del-assq!} uses @code{eq?} to compare @var{object} with the keys, -while @code{del-assv!} uses @code{eqv?} and @code{del-assoc!} uses -@code{equal?}. These procedures are like @code{del-assq}, -@code{del-assv}, and @code{del-assoc}, respectively, except that they -destructively modify @var{alist}. -@end deffn - -@deffn procedure delete-association-procedure deletor predicate selector -@findex list-deletor -@findex list-deletor! -This returns a deletion procedure similar to @code{del-assv} or -@code{del-assq!}. The @var{predicate} and @var{selector} arguments are -the same as those for @code{association-procedure}, while the -@var{deletor} argument should be either the procedure -@code{list-deletor} (for non-destructive deletions), or the procedure -@code{list-deletor!} (for destructive deletions). - -For example, here is a possible implementation of @code{del-assv}: - -@example -@group -(define del-assv - (delete-association-procedure list-deletor eqv? car)) -@end group -@end example -@end deffn - -@deffn procedure alist-copy alist -@cindex copying, of alist -@findex list-copy -Returns a newly allocated copy of @var{alist}. This is similar to -@code{list-copy} except that the ``association'' pairs, i.e.@: the -elements of the list @var{alist}, are also copied. @code{alist-copy} -could have been implemented like this: - -@example -@group -(define (alist-copy alist) - (if (null? alist) - '() - (cons (cons (car (car alist)) (cdr (car alist))) - (alist-copy (cdr alist))))) -@end group -@end example -@end deffn - -@node 1D Tables, The Association Table, Association Lists, Associations -@section 1D Tables - -@cindex 1D table (defn) -@cindex one-dimensional table (defn) -@cindex table, one-dimensional (defn) -@cindex weak pair, and 1D table -@dfn{1D tables} (``one-dimensional'' tables) are similar to association -lists. In a 1D table, unlike an association list, the keys of the table -are held @dfn{weakly}: if a key is garbage-collected, its associated -value in the table is removed. 1D tables compare their keys for -equality using @code{eq?}. - -@cindex property list -1D tables can often be used as a higher-performance alternative to the -two-dimensional association table (@pxref{The Association Table}). If -one of the keys being associated is a compound object such as a vector, -a 1D table can be stored in one of the vector's slots. Under these -circumstances, accessing items in a 1D table will be comparable in -performance to using a property list in a conventional Lisp. - -@deffn procedure make-1d-table -Returns a newly allocated empty 1D table. -@end deffn - -@deffn procedure 1d-table? object -@cindex type predicate, for 1D table -@findex list? -Returns @code{#t} if @var{object} is a 1D table, otherwise returns -@code{#f}. Any object that satisfies this predicate also satisfies -@code{list?}. -@end deffn - -@deffn procedure 1d-table/put! 1d-table key datum -Creates an association between @var{key} and @var{datum} in -@var{1d-table}. Returns an unspecified value. -@end deffn - -@deffn procedure 1d-table/remove! 1d-table key -Removes any association for @var{key} in @var{1d-table} and returns an -unspecified value. -@end deffn - -@deffn procedure 1d-table/get 1d-table key default -Returns the @var{datum} associated with @var{key} in @var{1d-table}. If -there is no association for @var{key}, @var{default} is returned. -@end deffn - -@deffn procedure 1d-table/lookup 1d-table key if-found if-not-found -@var{If-found} must be a procedure of one argument, and -@var{if-not-found} must be a procedure of no arguments. If -@var{1d-table} contains an association for @var{key}, @var{if-found} is -invoked on the @var{datum} of the association. Otherwise, -@var{if-not-found} is invoked with no arguments. In either case, the -result of the invoked procedure is returned as the result of -@code{1d-table/lookup}. -@end deffn - -@deffn procedure 1d-table/alist 1d-table -Returns a newly allocated association list that contains the same -information as @var{1d-table}. -@end deffn - -@node The Association Table, Hash Tables, 1D Tables, Associations -@section The Association Table - -@cindex association table (defn) -@cindex table, association (defn) -@cindex property list -@findex eq? -MIT/GNU Scheme provides a generalization of the property-list mechanism -found in most other implementations of Lisp: a global two-dimensional -@dfn{association table}. This table is indexed by two keys, called -@var{x-key} and @var{y-key} in the following procedure descriptions. -These keys and the datum associated with them can be arbitrary objects. -@code{eq?} is used to discriminate keys. - -Think of the association table as a matrix: a single datum can be -accessed using both keys, a column using @var{x-key} only, and a row -using @var{y-key} only. - -@deffn procedure 2d-put! x-key y-key datum -Makes an entry in the association table that associates @var{datum} with -@var{x-key} and @var{y-key}. Returns an unspecified result. -@end deffn - -@deffn procedure 2d-remove! x-key y-key -If the association table has an entry for @var{x-key} and @var{y-key}, -it is removed. Returns an unspecified result. -@end deffn - -@deffn procedure 2d-get x-key y-key -Returns the @var{datum} associated with @var{x-key} and @var{y-key}. -Returns @code{#f} if no such association exists. -@end deffn - -@deffn procedure 2d-get-alist-x x-key -Returns an association list of all entries in the association table that -are associated with @var{x-key}. The result is a list of -@code{(@var{y-key} . @var{datum})} pairs. Returns the empty list if no -entries for @var{x-key} exist. - -@example -@group -(2d-put! 'foo 'bar 5) -(2d-put! 'foo 'baz 6) -(2d-get-alist-x 'foo) @result{} ((baz . 6) (bar . 5)) -@end group -@end example -@end deffn - -@deffn procedure 2d-get-alist-y y-key -Returns an association list of all entries in the association table that -are associated with @var{y-key}. The result is a list of -@code{(@var{x-key} . @var{datum})} pairs. Returns the empty list if no -entries for @var{y-key} exist. - -@example -@group -(2d-put! 'bar 'foo 5) -(2d-put! 'baz 'foo 6) -(2d-get-alist-y 'foo) @result{} ((baz . 6) (bar . 5)) -@end group -@end example -@end deffn - -@node Hash Tables, Object Hashing, The Association Table, Associations -@section Hash Tables - -@cindex hash table -Hash tables are a fast, powerful mechanism for storing large numbers of -associations. MIT/GNU Scheme's hash tables feature automatic resizing, -customizable growth parameters, and customizable hash procedures. - -The average times for the insertion, deletion, and lookup operations on -a hash table are bounded by a constant. The space required by the table -is proportional to the number of associations in the table; the -constant of proportionality is described below (@pxref{Resizing of Hash -Tables}). - -(Previously, the hash-table implementation was a run-time-loadable -option, but as of release 7.7.0 it is loaded by default. It's no longer -necessary to call @code{load-option} prior to using hash tables.) - -@menu -* Construction of Hash Tables:: -* Basic Hash Table Operations:: -* Resizing of Hash Tables:: -* Address Hashing:: -* Low-Level Hash Table Operations:: -@end menu - -@node Construction of Hash Tables, Basic Hash Table Operations, Hash Tables, Hash Tables -@subsection Construction of Hash Tables - -@cindex construction, of hash table -The next few procedures are hash-table constructors. All hash table -constructors are procedures that accept one optional argument, -@var{initial-size}, and return a newly allocated hash table. If -@var{initial-size} is given, it must be an exact non-negative integer or -@code{#f}. The meaning of @var{initial-size} is discussed below -(@pxref{Resizing of Hash Tables}). - -@cindex equivalence predicate, of hash table -@cindex strongly held keys, of hash table -@cindex weakly held keys, of hash table -Hash tables are normally characterized by two things: the equivalence -predicate that is used to compare keys, and whether or not the table -allows its keys to be reclaimed by the garbage collector. If a table -prevents its keys from being reclaimed by the garbage collector, it is -said to hold its keys @dfn{strongly}; otherwise it holds its keys -@dfn{weakly} (@pxref{Weak Pairs}). - -@deffn procedure make-eq-hash-table [initial-size] -@findex eq? -Returns a newly allocated hash table that accepts arbitrary objects as -keys, and compares those keys with @code{eq?}. The keys are held -weakly. These are the fastest of the standard hash tables. -@end deffn - -@deffn procedure make-eqv-hash-table [initial-size] -@findex eqv? -Returns a newly allocated hash table that accepts arbitrary objects as -keys, and compares those keys with @code{eqv?}. The keys are held -weakly, except that booleans, characters, and numbers are held strongly. -These hash tables are a little slower than those made by -@code{make-eq-hash-table}. -@end deffn - -@deffn procedure make-equal-hash-table [initial-size] -@findex equal? -Returns a newly allocated hash table that accepts arbitrary objects as -keys, and compares those keys with @code{equal?}. The keys are held -strongly. These hash tables are quite a bit slower than those made by -@code{make-eq-hash-table}. -@end deffn - -@deffn procedure make-string-hash-table [initial-size] -@findex string=? -Returns a newly allocated hash table that accepts character strings as -keys, and compares them with @code{string=?}. The keys are held -strongly. -@end deffn - -The next two procedures are used to create new hash-table constructors. -All of the above hash table constructors, with the exception of -@code{make-eqv-hash-table}, could have been created by calls to these -``constructor-constructors''; see the examples below. - -@deffn procedure strong-hash-table/constructor key-hash key=? [rehash-after-gc?] -@deffnx procedure weak-hash-table/constructor key-hash key=? [rehash-after-gc?] -@cindex hashing, of key in hash table -@cindex modulus, of hashing procedure -Each of these procedures accepts two arguments and returns a hash-table -constructor. The @var{key=?} argument is an equivalence predicate for -the keys of the hash table. The @var{key-hash} argument is a procedure -that computes a hash number. Specifically, @var{key-hash} accepts two -arguments, a key and an exact positive integer (the @dfn{modulus}), and -returns an exact non-negative integer that is less than the modulus. - -The optional argument @var{rehash-after-gc?}, if true, says that the -values returned by @var{key-hash} might change after a garbage -collection. If so, the hash-table implementation arranges for the table -to be rehashed when necessary. (@xref{Address Hashing}, for -information about hash procedures that have this property.) Otherwise, -it is assumed that @var{key-hash} always returns the same value for the -same arguments. The default value of this argument is @code{#f}. - -The constructors returned by @code{strong-hash-table/constructor} make -hash tables that hold their keys strongly. The constructors returned by -@code{weak-hash-table/constructor} make hash tables that hold their keys -weakly. -@end deffn - -Some examples showing how some standard hash-table constructors could have -been defined: - -@findex eq-hash-mod -@findex eq? -@findex equal-hash-mod -@findex equal? -@findex string-hash-mod -@findex string=? -@example -@group -(define make-eq-hash-table - (weak-hash-table/constructor eq-hash-mod eq? #t)) - -(define make-equal-hash-table - (strong-hash-table/constructor equal-hash-mod equal? #t)) - -(define make-string-hash-table - (strong-hash-table/constructor string-hash-mod string=? #f)) -@end group -@end example - -The following procedure is sometimes useful in conjunction with weak -hash tables. Normally it is not needed, because such hash tables clean -themselves automatically as they are used. - -@deffn procedure hash-table/clean! hash-table -If @var{hash-table} is a type of hash table that holds its @var{key}s -weakly, this procedure recovers any space that was being used to record -associations for objects that have been reclaimed by the garbage -collector. Otherwise, this procedure does nothing. In either case, it -returns an unspecified result. -@end deffn - -@node Basic Hash Table Operations, Resizing of Hash Tables, Construction of Hash Tables, Hash Tables -@subsection Basic Hash Table Operations - -The procedures described in this section are the basic operations on -hash tables. They provide the functionality most often needed by -programmers. Subsequent sections describe other operations that provide -additional functionality needed by some applications. - -@deffn procedure hash-table? object -@cindex type predicate, for hash table -Returns @code{#t} if @var{object} is a hash table, otherwise returns -@code{#f}. -@end deffn - -@deffn procedure hash-table/put! hash-table key datum -Associates @var{datum} with @var{key} in @var{hash-table} and returns an -unspecified result. The average time required by this operation is -bounded by a constant. -@end deffn - -@deffn procedure hash-table/get hash-table key default -Returns the datum associated with @var{key} in @var{hash-table}. If -there is no association for @var{key}, @var{default} is returned. The -average time required by this operation is bounded by a constant. -@end deffn - -@deffn procedure hash-table/remove! hash-table key -If @var{hash-table} has an association for @var{key}, removes it. -Returns an unspecified result. The average time required by this -operation is bounded by a constant. -@end deffn - -@deffn procedure hash-table/clear! hash-table -Removes all associations in @var{hash-table} and returns an unspecified -result. The average and worst-case times required by this operation are -bounded by a constant. -@end deffn - -@deffn procedure hash-table/count hash-table -Returns the number of associations in @var{hash-table} as an exact -non-negative integer. If @var{hash-table} holds its keys weakly, this -is a conservative upper bound that may count some associations whose -keys have recently been reclaimed by the garbage collector. The average -and worst-case times required by this operation are bounded by a -constant. -@end deffn - -@deffn procedure hash-table->alist hash-table -Returns the contents of @var{hash-table} as a newly allocated alist. -Each element of the alist is a pair @code{(@var{key} . @var{datum})} -where @var{key} is one of the keys of @var{hash-table}, and @var{datum} -is its associated datum. The average and worst-case times required by -this operation are linear in the number of associations -in the table. -@end deffn - -@deffn procedure hash-table/key-list hash-table -Returns a newly allocated list of the keys in @var{hash-table}. The -average and worst-case times required by this operation are linear in -the number of associations in the table. -@end deffn - -@deffn procedure hash-table/datum-list hash-table -Returns a newly allocated list of the datums in @var{hash-table}. Each -element of the list corresponds to one of the associations in -@var{hash-table}; if the table contains multiple associations with the -same datum, so will this list. The average and worst-case times -required by this operation are linear in the number of associations in -the table. -@end deffn - -@deffn procedure hash-table/for-each hash-table procedure -@var{Procedure} must be a procedure of two arguments. Invokes -@var{procedure} once for each association in @var{hash-table}, passing -the association's @var{key} and @var{datum} as arguments, in that order. -Returns an unspecified result. @var{Procedure} must not modify -@var{hash-table}, with one exception: it is permitted to call -@code{hash-table/remove!} to remove the association being processed. -@end deffn - -The following procedure is an alternate form of @code{hash-table/get} -that is useful in some situations. Usually, @code{hash-table/get} is -preferable because it is faster. - -@deffn procedure hash-table/lookup hash-table key if-found if-not-found -@var{If-found} must be a procedure of one argument, and -@var{if-not-found} must be a procedure of no arguments. If -@var{hash-table} contains an association for @var{key}, @var{if-found} -is invoked on the datum of the association. Otherwise, -@var{if-not-found} is invoked with no arguments. In either case, the -result yielded by the invoked procedure is returned as the result of -@code{hash-table/lookup} (@code{hash-table/lookup} @emph{reduces} into -the invoked procedure, i.e.@: calls it tail-recursively). The average -time required by this operation is bounded by a constant. -@end deffn - -@node Resizing of Hash Tables, Address Hashing, Basic Hash Table Operations, Hash Tables -@subsection Resizing of Hash Tables - -@cindex resizing, of hash table -@cindex size, of hash table (defn) -Normally, hash tables automatically resize themselves according to need. -Because of this, the programmer need not be concerned with management of -the table's size. However, some limited control over the table's size -is provided, which will be discussed below. This discussion involves -two concepts, @dfn{usable size} and @dfn{physical size}, which we will -now define. - -@cindex usable size, of hash table (defn) -The @dfn{usable size} of a hash table is the number of associations that -the table can hold at a given time. If the number of associations in -the table exceeds the usable size, the table will automatically grow, -increasing the usable size to a new value that is sufficient to hold the -associations. - -@cindex physical size, of hash table (defn) -The @dfn{physical size} is an abstract measure of a hash table that -specifies how much space is allocated to hold the associations of the -table. The physical size is always greater than or equal to the usable -size. The physical size is not interesting in itself; it is interesting -only for its effect on the performance of the hash table. While the -average performance of a hash-table lookup is bounded by a constant, the -worst-case performance is not. For a table containing a given number of -associations, increasing the physical size of the table decreases the -probability that worse-than-average performance will occur. - -The physical size of a hash table is statistically related to the number -of associations. However, it is possible to place bounds on the -physical size, and from this to estimate the amount of space used by the -table: - -@example -@group -(define (hash-table-space-bounds count rehash-size rehash-threshold) - (let ((tf (/ 1 rehash-threshold))) - (values (if (exact-integer? rehash-size) - (- (* count (+ 4 tf)) - (* tf (+ rehash-size rehash-size))) - (* count (+ 4 (/ tf (* rehash-size rehash-size))))) - (* count (+ 4 tf))))) -@end group -@end example - -@noindent -What this formula shows is that, for a ``normal'' rehash size (that is, -not an exact integer), the amount of space used by the hash table is -proportional to the number of associations in the table. The constant -of proportionality varies statistically, with the low bound being - -@example -(+ 4 (/ (/ 1 rehash-threshold) (* rehash-size rehash-size))) -@end example - -@noindent -and the high bound being - -@example -(+ 4 (/ 1 rehash-threshold)) -@end example - -@noindent -which, for the default values of these parameters, are @code{4.25} and -@code{5}, respectively. Reducing the rehash size will tighten these -bounds, but increases the amount of time spent resizing, so you can see -that the rehash size gives some control over the time-space tradeoff of -the table. - -The programmer can control the size of a hash table by means of three -parameters: - -@itemize @bullet -@item -Each table's @var{initial-size} may be specified when the table is -created. - -@item -Each table has a @dfn{rehash size} that specifies how the size of the -table is changed when it is necessary to grow or shrink the table. - -@item -Each table has a @dfn{rehash threshold} that specifies the relationship -of the table's physical size to its usable size. -@end itemize - -@cindex initial size, of hash table -If the programmer knows that the table will initially contain a specific -number of items, @var{initial-size} can be given when the table is -created. If @var{initial-size} is an exact non-negative integer, it -specifies the initial usable size of the hash table; the table will not -change size until the number of items in the table exceeds -@var{initial-size}, after which automatic resizing is enabled and -@var{initial-size} no longer has any effect. Otherwise, if -@var{initial-size} is not given or is @code{#f}, the table is -initialized to an unspecified size and automatic resizing is immediately -enabled. - -@cindex rehash size, of hash table (defn) -The @dfn{rehash size} specifies how much to increase the usable size of -the hash table when it becomes full. It is either an exact positive -integer, or a real number greater than one. If it is an integer, the -new size is the sum of the old size and the rehash size. Otherwise, it -is a real number, and the new size is the product of the old size and -the rehash size. Increasing the rehash size decreases the average cost -of an insertion, but increases the average amount of space used by the -table. The rehash size of a table may be altered dynamically by the -application in order to optimize the resizing of the table; for example, -if the table will grow quickly for a known period and afterwards will -not change size, performance might be improved by using a large rehash -size during the growth phase and a small one during the static phase. -The default rehash size of a newly constructed hash table is @code{2.0}. - -@strong{Warning}: The use of an exact positive integer for a rehash -size is almost always undesirable; this option is provided solely for -compatibility with the Common Lisp hash-table mechanism. The reason for -this has to do with the time penalty for resizing the hash table. The -time needed to resize a hash table is proportional to the -number of associations in the table. This resizing cost is -@dfn{amortized} across the insertions required to fill the table to the -point where it needs to grow again. If the table grows by an amount -proportional to the number of associations, then the cost of -resizing and the increase in size are both proportional to the -number of associations, so the @dfn{amortized cost} of an insertion -operation is still bounded by a constant. However, if the table grows -by a constant amount, this is not true: the amortized cost of an -insertion is not bounded by a constant. Thus, using a constant rehash -size means that the average cost of an insertion increases -proportionally to the number of associations in the hash table. - -@cindex rehash threshold, of hash table (defn) -The @dfn{rehash threshold} is a real number, between zero exclusive and -one inclusive, that specifies the ratio between a hash table's usable -size and its physical size. Decreasing the rehash threshold decreases -the probability of worse-than-average insertion, deletion, and lookup -times, but increases the physical size of the table for a given usable -size. The default rehash threshold of a newly constructed hash table is -@code{1}. - -@deffn procedure hash-table/size hash-table -Returns the usable size of @var{hash-table} as an exact positive -integer. This is the number of associations that @var{hash-table} can -hold before it will grow. -@end deffn - -@deffn procedure hash-table/rehash-size hash-table -Returns the rehash size of @var{hash-table}. -@end deffn - -@deffn procedure set-hash-table/rehash-size! hash-table x -@var{X} must be either an exact positive integer, or a real number that -is greater than one. Sets the rehash size of @var{hash-table} to -@var{x} and returns an unspecified result. This operation adjusts the -``shrink threshold'' of the table; the table might shrink if the number -of associations is less than the new threshold. -@end deffn - -@deffn procedure hash-table/rehash-threshold hash-table -Returns the rehash threshold of @var{hash-table}. -@end deffn - -@deffn procedure set-hash-table/rehash-threshold! hash-table x -@var{X} must be a real number between zero exclusive and one inclusive. -Sets the rehash threshold of @var{hash-table} to @var{x} and returns an -unspecified result. This operation does not change the usable size of -the table, but it usually changes the physical size of the table, which -causes the table to be rehashed. -@end deffn - -@node Address Hashing, Low-Level Hash Table Operations, Resizing of Hash Tables, Hash Tables -@subsection Address Hashing -@cindex address hashing - -The procedures described in this section may be used to make very -efficient key-hashing procedures for arbitrary objects. All of these -procedures are based on @dfn{address hashing}, which uses the address of -an object as its hash number. The great advantage of address hashing is -that converting an arbitrary object to a hash number is extremely fast -and takes the same amount of time for any object. - -The disadvantage of address hashing is that the garbage collector -changes the addresses of most objects. The hash-table implementation -compensates for this disadvantage by automatically rehashing tables that -use address hashing when garbage collections occur. Thus, in order to -use these procedures for key hashing, it is necessary to tell the -hash-table implementation (by means of the @var{rehash-after-gc?} -argument to the ``constructor-constructor'' procedure) that the hash -numbers computed by your key-hashing procedure must be recomputed after -a garbage collection. - -@deffn procedure eq-hash object -@deffnx procedure eqv-hash object -@deffnx procedure equal-hash object -These procedures return a hash number for @var{object}. The result is -always a non-negative integer, and in the case of @code{eq-hash}, a -non-negative fixnum. Two objects that are equivalent according to -@code{eq?}, @code{eqv?}, or @code{equal?}, respectively, will produce the -same hash number when passed as arguments to these procedures, provided -that the garbage collector does not run during or between the two calls. -@end deffn - -The following procedures are the key-hashing procedures used by the -standard address-hash-based hash tables. - -@deffn procedure eq-hash-mod object modulus -This procedure is the key-hashing procedure used by -@code{make-eq-hash-table}. -@end deffn - -@deffn procedure eqv-hash-mod object modulus -This procedure is the key-hashing procedure used by -@code{make-eqv-hash-table}. -@end deffn - -@deffn procedure equal-hash-mod object modulus -This procedure is the key-hashing procedure used by -@code{make-equal-hash-table}. -@end deffn - -@node Low-Level Hash Table Operations, , Address Hashing, Hash Tables -@subsection Low-Level Hash Table Operations - -The procedures in this section allow the programmer to control some of -the internal structure of a hash table. Normally, hash tables maintain -associations between keys and datums using pairs or weak pairs. These -procedures allow the programmer to specify the use of some other data -structure to maintain the association. In this section, the data -structure that represents an association in a hash table is called an -@dfn{entry}. - -@deffn procedure hash-table/constructor key-hash key=? make-entry entry-valid? entry-key entry-datum set-entry-datum! [rehash-after-gc?] -Creates and returns a hash-table constructor procedure -(@pxref{Construction of Hash Tables}). The arguments define the -characteristics of the hash table as follows: - -@table @var -@item key-hash -The hashing procedure. A procedure that accepts two arguments, a key and -an exact positive integer (the @dfn{modulus}), and returns an exact -non-negative integer that is less than the modulus. - -@item key=? -A equivalence predicate that accepts two keys and is true iff they are -the same key. If this predicate is true of two keys, then -@var{key-hash} must return the same value for each of these keys (given -the same modulus in both cases). - -@item make-entry -A procedure that accepts a key and a datum as arguments and returns a -newly allocated entry. - -@item entry-valid? -A procedure that accepts an entry and returns @code{#f} iff the entry's -key has been reclaimed by the garbage collector. Instead of a -procedure, this may be @code{#t}, which is equivalent to @code{(lambda -(entry) #t)}. -@findex weak-pair/car? - -@item entry-key -A procedure that accepts an entry as an argument and returns the entry's -key. - -@item entry-datum -A procedure that accepts an entry as an argument and returns the entry's -datum. - -@item set-entry-datum! -A procedure that accepts an entry and an object as arguments, modifies -the entry's datum to be the object, and returns an unspecified -result. - -@item rehash-after-gc? -An optional argument that, if true, says the values returned by -@var{key-hash} might change after a garbage collection. If so, the -hash-table implementation arranges for the table to be rehashed when -necessary. (@xref{Address Hashing}, for information about hash -procedures that have this property.) Otherwise, it is assumed that -@var{key-hash} always returns the same value for the same arguments. -The default value of this argument is @code{#f}. -@end table -@end deffn - -@noindent -For example, here is how the constructors for ordinary hash tables could -be defined: - -@example -@group -(define (strong-hash-table/constructor key-hash key=? - #!optional rehash-after-gc?) - (hash-table/constructor key-hash key=? - cons #t car cdr set-cdr! - (if (default-object? rehash-after-gc?) - #f - rehash-after-gc?))) -@end group - -@group -(define (weak-hash-table/constructor key-hash key=? - #!optional rehash-after-gc?) - (hash-table/constructor key-hash key=? weak-cons weak-pair/car? - weak-car weak-cdr weak-set-cdr! - (if (default-object? rehash-after-gc?) - #f - rehash-after-gc?))) -@end group -@end example - -@deffn procedure hash-table/key-hash hash-table -@deffnx procedure hash-table/key=? hash-table -@deffnx procedure hash-table/make-entry hash-table -@deffnx procedure hash-table/entry-valid? hash-table -@deffnx procedure hash-table/entry-key hash-table -@deffnx procedure hash-table/entry-datum hash-table -@deffnx procedure hash-table/set-entry-datum! hash-table -Each procedure returns the value of the corresponding argument that was -used to construct @var{hash-table}. -@end deffn - -The following procedures return the contents of a hash table as a -collection of entries. While the data structure holding the entries is -newly allocated, the entries themselves are not copied. Since hash -table operations can modify these entries, the entries should be copied -if it is desired to keep them while continuing to modify the table. - -@deffn procedure hash-table/entries-list hash-table -Returns a newly allocated list of the entries in @var{hash-table}. -@end deffn - -@deffn procedure hash-table/entries-vector hash-table -Returns a newly allocated vector of the entries in @var{hash-table}. -Equivalent to - -@example -(list->vector (hash-table/entries-list @var{hash-table})) -@end example -@end deffn - -@node Object Hashing, Red-Black Trees, Hash Tables, Associations -@section Object Hashing - -@cindex object hashing -@cindex hashing, of object -The MIT/GNU Scheme object-hashing facility provides a mechanism for -generating a unique hash number for an arbitrary object. This hash -number, unlike an object's address, is unchanged by garbage collection. -The object-hashing facility is useful in conjunction with hash tables, -but it may be used for other things as well. In particular, it is used -in the generation of the written representation for many objects -(@pxref{Custom Output}). - -All of these procedures accept an optional argument called @var{table}; -this table contains the object-integer associations. If given, this -argument must be an object-hash table as constructed by -@code{hash-table/make} (see below). If not given, a default table is -used. - -@deffn procedure hash object [table] -@findex eq? -@code{hash} associates an exact non-negative integer with @var{object} -and returns that integer. If @code{hash} was previously called with -@var{object} as its argument, the integer returned is the same as was -returned by the previous call. @code{hash} guarantees that distinct -objects (in the sense of @code{eq?}) are associated with distinct -integers. -@end deffn - -@deffn procedure unhash k [table] -@code{unhash} takes an exact non-negative integer @var{k} and returns -the object associated with that integer. If there is no object -associated with @var{k}, or if the object previously associated with -@var{k} has been reclaimed by the garbage collector, an error of type -@code{condition-type:bad-range-argument} is signalled. In other words, -if @code{hash} previously returned @var{k} for some object, and that -object has not been reclaimed, it is the value of the call to -@code{unhash}. -@findex condition-type:bad-range-argument -@end deffn - -An object that is passed to @code{hash} as an argument is not protected -from being reclaimed by the garbage collector. If all other references -to that object are eliminated, the object will be reclaimed. -Subsequently calling @code{unhash} with the hash number of the (now -reclaimed) object will signal an error. - -@example -@group -(define x (cons 0 0)) @result{} @r{unspecified} -(hash x) @result{} 77 -(eqv? (hash x) (hash x)) @result{} #t -(define x 0) @result{} @r{unspecified} -(gc-flip) @r{;force a garbage collection} -(unhash 77) @error{} -@end group -@end example - -@deffn procedure object-hashed? object [table] -This predicate is true if @var{object} has an associated hash number. -Otherwise it is false. -@end deffn - -@deffn procedure valid-hash-number? k [table] -This predicate is true if @var{k} is the hash number associated with -some object. Otherwise it is false. -@end deffn - -The following two procedures provide a lower-level interface to the -object-hashing mechanism. - -@deffn procedure object-hash object [table [insert?]] -@findex eq? -@code{object-hash} is like @code{hash}, except that it accepts an -additional optional argument, @var{insert?}. If @var{insert?}@: is -supplied and is @code{#f}, @code{object-hash} will return an integer for -@var{object} only if there is already an association in the table; -otherwise, it will return @code{#f}. If @var{insert?} is not supplied, -or is not @code{#f}, @code{object-hash} always returns an integer, -creating an association in the table if necessary. - -@code{object-hash} additionally treats @code{#f} differently than does -@code{hash}. Calling @code{object-hash} with @code{#f} as its argument -will return an integer that, when passed to @code{unhash}, will signal -an error rather than returning @code{#f}. Likewise, -@code{valid-hash-number?} will return @code{#f} for this integer. -@end deffn - -@deffn procedure object-unhash k [table] -@code{object-unhash} is like @code{unhash}, except that when @var{k} is -not associated with any object or was previously associated with an -object that has been reclaimed, @code{object-unhash} returns @code{#f}. -This means that there is an ambiguity in the value returned by -@code{object-unhash}: if @code{#f} is returned, there is no way to -tell if @var{k} is associated with @code{#f} or is not associated with -any object at all. -@end deffn - -Finally, this procedure makes new object-hash tables: - -@deffn procedure hash-table/make -This procedure creates and returns a new, empty object-hash table that -is suitable for use as the optional @var{table} argument to the above -procedures. The returned table contains no associations. -@end deffn - -@node Red-Black Trees, Weight-Balanced Trees, Object Hashing, Associations -@section Red-Black Trees - -@cindex trees, balanced binary -@cindex balanced binary trees -@cindex binary trees -@cindex red-black binary trees -Balanced binary trees are a useful data structure for maintaining large -sets of associations whose keys are ordered. While most applications -involving large association sets should use hash tables, some -applications can benefit from the use of binary trees. Binary trees -have two advantages over hash tables: - -@itemize @bullet -@item -The contents of a binary tree can be converted to an alist, sorted by -key, in time proportional to the number of associations in the -tree. A hash table can be converted into an unsorted alist in linear -time; sorting it requires additional time. - -@item -Two binary trees can be compared for equality in linear time. Hash -tables, on the other hand, cannot be compared at all; they must be -converted to alists before comparison can be done, and alist comparison -is quadratic unless the alists are sorted. -@end itemize - -MIT/GNU Scheme provides an implementation of @dfn{red-black} trees. The -red-black tree-balancing algorithm provides generally good performance -because it doesn't try to keep the tree very closely balanced. At any -given node in the tree, one side of the node can be twice as high as the -other in the worst case. With typical data the tree will remain fairly -well balanced anyway. - -A red-black tree takes space that is proportional to the number of -associations in the tree. For the current implementation, the constant -of proportionality is eight words per association. - -Red-black trees hold their keys @dfn{strongly}. In other words, if a -red-black tree contains an association for a given key, that key cannot -be reclaimed by the garbage collector. - -@cindex run-time-loadable option -@cindex option, run-time-loadable -The red-black tree implementation is a run-time-loadable option. To use -red-black trees, execute - -@example -(load-option 'rb-tree) -@end example -@findex load-option - -@noindent -once before calling any of the procedures defined here. - -@deffn procedure make-rb-tree key=? keyalist rb-tree -Returns the contents of @var{rb-tree} as a newly allocated alist. Each -element of the alist is a pair @code{(@var{key} . @var{datum})} where -@var{key} is one of the keys of @var{rb-tree}, and @var{datum} is its -associated datum. The alist is sorted by key according to the -@var{keyalist rb-tree))) -@end example -@end deffn - -@deffn procedure rb-tree/equal? rb-tree-1 rb-tree-2 datum=? -Compares @var{rb-tree-1} and @var{rb-tree-2} for equality, returning -@code{#t} iff they are equal and @code{#f} otherwise. The trees must -have been constructed with the same equality and order predicates (same -in the sense of @code{eq?}). The keys of the trees are compared using -the @var{key=?} predicate used to build the trees, while the datums of -the trees are compared using the equivalence predicate @var{datum=?}. -The worst-case time required by this operation is proportional to the -number of associations in the tree. -@end deffn - -@deffn procedure rb-tree/empty? rb-tree -Returns @code{#t} iff @var{rb-tree} contains no associations. Otherwise -returns @code{#f}. -@end deffn - -@deffn procedure rb-tree/size rb-tree -Returns the number of associations in @var{rb-tree}, an exact -non-negative integer. The average and worst-case times required by this -operation are proportional to the number of associations in the tree. -@end deffn - -@deffn procedure rb-tree/height rb-tree -Returns the height of @var{rb-tree}, an exact non-negative integer. -This is the length of the longest path from a leaf of the tree to the -root. The average and worst-case times required by this operation are -proportional to the number of associations in the tree. - -The returned value satisfies the following: - -@example -@group -(lambda (rb-tree) - (let ((size (rb-tree/size rb-tree)) - (lg (lambda (x) (/ (log x) (log 2))))) - (<= (lg size) - (rb-tree/height rb-tree) - (* 2 (lg (+ size 1)))))) -@end group -@end example -@end deffn - -@deffn procedure rb-tree/copy rb-tree -Returns a newly allocated copy of @var{rb-tree}. The copy is identical -to @var{rb-tree} in all respects, except that changes to @var{rb-tree} -do not affect the copy, and vice versa. The time required by this -operation is proportional to the number of associations in the tree. -@end deffn - -@deffn procedure alist->rb-tree alist key=? keywt-tree tree-type alist -Returns a newly allocated weight-balanced tree that contains the same -associations as @var{alist}. This procedure is equivalent to: - -@example -@group -(lambda (type alist) - (let ((tree (make-wt-tree type))) - (for-each (lambda (association) - (wt-tree/add! tree - (car association) - (cdr association))) - alist) - tree)) -@end group -@end example -@end deffn - -@node Basic Operations on Weight-Balanced Trees, Advanced Operations on Weight-Balanced Trees, Construction of Weight-Balanced Trees, Weight-Balanced Trees -@subsection 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. - -@deffn procedure wt-tree? object -Returns @code{#t} if @var{object} is a weight-balanced tree, otherwise -returns @code{#f}. -@end deffn - -@deffn procedure wt-tree/empty? wt-tree -Returns @code{#t} if @var{wt-tree} contains no associations, otherwise -returns @code{#f}. -@end deffn - -@deffn procedure wt-tree/size wt-tree -Returns the number of associations in @var{wt-tree}, an exact -non-negative integer. This operation takes constant time. -@end deffn - -@deffn procedure wt-tree/add wt-tree key datum -Returns a new tree containing all the associations in @var{wt-tree} and -the association of @var{datum} with @var{key}. If @var{wt-tree} already -had an association for @var{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 -@var{wt-tree}. -@end deffn - -@deffn procedure wt-tree/add! wt-tree key datum -Associates @var{datum} with @var{key} in @var{wt-tree} and returns an -unspecified value. If @var{wt-tree} already has an association for -@var{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 @var{wt-tree}. -@end deffn - -@deffn procedure wt-tree/member? key wt-tree -Returns @code{#t} if @var{wt-tree} contains an association for -@var{key}, otherwise returns @code{#f}. The average and worst-case -times required by this operation are proportional to the logarithm of -the number of associations in @var{wt-tree}. -@end deffn - -@deffn procedure wt-tree/lookup wt-tree key default -Returns the datum associated with @var{key} in @var{wt-tree}. If -@var{wt-tree} doesn't contain an association for @var{key}, -@var{default} is returned. The average and worst-case times required by -this operation are proportional to the logarithm of the number of -associations in @var{wt-tree}. -@end deffn - -@deffn procedure wt-tree/delete wt-tree key -Returns a new tree containing all the associations in @var{wt-tree}, -except that if @var{wt-tree} contains an association for @var{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 @var{wt-tree}. -@end deffn - -@deffn procedure wt-tree/delete! wt-tree key -If @var{wt-tree} contains an association for @var{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 @var{wt-tree}. -@end deffn - -@node Advanced Operations on Weight-Balanced Trees, Indexing Operations on Weight-Balanced Trees, Basic Operations on Weight-Balanced Trees, Weight-Balanced Trees -@subsection Advanced Operations on Weight-Balanced Trees - -In the following the @emph{size} of a tree is the number of associations -that the tree contains, and a @emph{smaller} tree contains fewer -associations. - -@deffn procedure wt-tree/split< wt-tree bound -Returns a new tree containing all and only the associations in -@var{wt-tree} that have a key that is less than @var{bound} in the -ordering relation of the tree type of @var{wt-tree}. The average and -worst-case times required by this operation are proportional to the -logarithm of the size of @var{wt-tree}. -@end deffn - -@deffn procedure wt-tree/split> wt-tree bound -Returns a new tree containing all and only the associations in -@var{wt-tree} that have a key that is greater than @var{bound} in the -ordering relation of the tree type of @var{wt-tree}. The average and -worst-case times required by this operation are proportional to the -logarithm of the size of @var{wt-tree}. -@end deffn - -@deffn 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 @var{wt-tree-2} -with the key. Thus if the trees are viewed as discrete maps then -@code{wt-tree/union} computes the map override of @var{wt-tree-1} by -@var{wt-tree-2}. If the trees are viewed as sets the result is the set -union of the arguments. -The worst-case time required by this operation -is proportional to the sum of the sizes of both trees. -If the minimum key of one tree is greater than the maximum key of -the other tree then the worst-case time required is proportional to -the logarithm of the size of the larger tree. -@end deffn - -@deffn procedure wt-tree/intersection wt-tree-1 wt-tree-2 -Returns a new tree containing all and only those associations from -@var{wt-tree-1} that have keys appearing as the key of an association -in @var{wt-tree-2}. Thus the associated data in the result are those -from @var{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, -@code{wt-tree/intersection} computes the domain restriction of -@var{wt-tree-1} to (the domain of) @var{wt-tree-2}. -The worst-case time required by this operation is proportional to -the sum of the sizes of the trees. -@end deffn - -@deffn procedure wt-tree/difference wt-tree-1 wt-tree-2 -Returns a new tree containing all and only those associations from -@var{wt-tree-1} that have keys that @emph{do not} appear as the key of -an association in @var{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 @var{wt-tree-1} to -the complement of (the domain of) @var{wt-tree-2}. -The worst-case time required by this operation is proportional to -the sum of the sizes of the trees. -@end deffn - -@deffn procedure wt-tree/subset? wt-tree-1 wt-tree-2 -Returns @code{#t} iff the key of each association in @var{wt-tree-1} is -the key of some association in @var{wt-tree-2}, otherwise returns @code{#f}. -Viewed as a set operation, @code{wt-tree/subset?} is the improper subset -predicate. -A proper subset predicate can be constructed: - -@example -@group -(define (proper-subset? s1 s2) - (and (wt-tree/subset? s1 s2) - (< (wt-tree/size s1) (wt-tree/size s2)))) -@end group -@end example - -As a discrete map operation, @code{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 -@var{wt-tree-1}. -@end deffn - -@deffn procedure wt-tree/set-equal? wt-tree-1 wt-tree-2 -Returns @code{#t} iff for every association in @var{wt-tree-1} there is -an association in @var{wt-tree-2} that has the same key, and @emph{vice -versa}. - -Viewing the arguments as sets, @code{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 - -@example -@group -(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))) -@end group -@end example - -In the worst case the time required by this operation is proportional to -the size of the smaller tree. -@end deffn - -@deffn procedure wt-tree/fold combiner initial wt-tree -This procedure reduces @var{wt-tree} by combining all the associations, -using an reverse in-order traversal, so the associations are visited in -reverse order. @var{Combiner} is a procedure of three arguments: a key, -a datum and the accumulated result so far. Provided @var{combiner} -takes time bounded by a constant, @code{wt-tree/fold} takes time -proportional to the size of @var{wt-tree}. - -A sorted association list can be derived simply: - -@example -@group -(wt-tree/fold (lambda (key datum list) - (cons (cons key datum) list)) - '() - @var{wt-tree})) -@end group -@end example - -The data in the associations can be summed like this: - -@example -@group -(wt-tree/fold (lambda (key datum sum) (+ sum datum)) - 0 - @var{wt-tree}) -@end group -@end example -@end deffn - -@deffn procedure wt-tree/for-each action wt-tree -This procedure traverses @var{wt-tree} in order, applying @var{action} to -each association. -The associations are processed in increasing order of their keys. -@var{Action} is a procedure of two arguments that takes the key and -datum respectively of the association. -Provided @var{action} takes time bounded by a constant, -@code{wt-tree/for-each} takes time proportional to the size of -@var{wt-tree}. -The example prints the tree: - -@example -@group -(wt-tree/for-each (lambda (key value) - (display (list key value))) - @var{wt-tree})) -@end group -@end example -@end deffn - -@deffn procedure wt-tree/union-merge wt-tree-1 wt-tree-2 merge -Returns a new tree containing all the associations from both trees. If -both trees have an association for the same key, the datum associated -with that key in the result tree is computed by applying the procedure -@var{merge} to the key, the value from @var{wt-tree-1} and the value -from @var{wt-tree-2}. @var{Merge} is of the form - -@example -(lambda (@var{key} @var{datum-1} @var{datum-2}) @dots{}) -@end example - -If some key occurs only in one tree, that association will appear in the -result tree without being processed by @var{merge}, so for this -operation to make sense, either @var{merge} must have both a right and -left identity that correspond to the association being absent in one of -the trees, or some guarantee must be made, for example, all the keys in -one tree are known to occur in the other. - -These are all reasonable procedures for @var{merge} - -@example -@group -(lambda (key val1 val2) (+ val1 val2)) -(lambda (key val1 val2) (append val1 val2)) -(lambda (key val1 val2) (wt-tree/union val1 val2)) -@end group -@end example - -However, a procedure like - -@example -(lambda (key val1 val2) (- val1 val2)) -@end example - -would result in a subtraction of the data for all associations with keys -occuring in both trees but associations with keys occuring in only the -second tree would be copied, not negated, as is presumably be intent. -The programmer might ensure that this never happens. - -This procedure has the same time behavior as @code{wt-tree/union} but -with a slightly worse constant factor. Indeed, @code{wt-tree/union} -might have been defined like this: - -@example -@group -(define (wt-tree/union tree1 tree2) - (wt-tree/union-merge tree1 tree2 - (lambda (key val1 val2) val2))) -@end group -@end example -@end deffn - -The @var{merge} procedure takes the @var{key} as a parameter in case the -data are not independent of the key. - - -@node Indexing Operations on Weight-Balanced Trees, , Advanced Operations on Weight-Balanced Trees, Weight-Balanced Trees -@subsection 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. - -@deffn procedure wt-tree/index wt-tree index -@deffnx procedure wt-tree/index-datum wt-tree index -@deffnx procedure wt-tree/index-pair wt-tree index -Returns the 0-based @var{index}th association of @var{wt-tree} in the -sorted sequence under the tree's ordering relation on the keys. -@code{wt-tree/index} returns the @var{index}th key, -@code{wt-tree/index-datum} returns the datum associated with the -@var{index}th key and @code{wt-tree/index-pair} returns a new pair -@code{(@var{key} . @var{datum})} which is the @code{cons} of the -@var{index}th key and its datum. The average and worst-case times -required by this operation are proportional to the logarithm of the -number of associations in the tree. - -These operations signal a condition of type -@code{condition-type:bad-range-argument} if @var{index}@code{<0} or if -@var{index} is greater than or equal to the number of associations in -the tree. If the tree is empty, they signal an anonymous error. - -Indexing can be used to find the median and maximum keys in the tree as -follows: - -@example -@group -median: (wt-tree/index @var{wt-tree} - (quotient (wt-tree/size @var{wt-tree}) - 2)) -maximum: (wt-tree/index @var{wt-tree} - (- (wt-tree/size @var{wt-tree}) - 1)) -@end group -@end example -@end deffn - -@deffn procedure wt-tree/rank wt-tree key -Determines the 0-based position of @var{key} in the sorted sequence of -the keys under the tree's ordering relation, or @code{#f} if the tree -has no association with for @var{key}. This procedure returns either an -exact non-negative integer or @code{#f}. The average and worst-case -times required by this operation are proportional to the logarithm of -the number of associations in the tree. -@end deffn - -@deffn procedure wt-tree/min wt-tree -@deffnx procedure wt-tree/min-datum wt-tree -@deffnx procedure wt-tree/min-pair wt-tree -Returns the association of @var{wt-tree} that has the least key under the tree's ordering relation. -@code{wt-tree/min} returns the least key, -@code{wt-tree/min-datum} returns the datum associated with the -least key and @code{wt-tree/min-pair} returns a new pair -@code{(key . datum)} which is the @code{cons} of the minimum key and its datum. -The average and worst-case times required by this operation are -proportional to the logarithm of the number of associations in the tree. - -These operations signal an error if the tree is empty. -They could have been written - -@example -@group -(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)) -@end group -@end example -@end deffn - -@deffn procedure wt-tree/delete-min wt-tree -Returns a new tree containing all of the associations in @var{wt-tree} -except the association with the least key under the @var{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 - -@example -(wt-tree/delete @var{wt-tree} (wt-tree/min @var{wt-tree})) -@end example -@end deffn - -@deffn procedure wt-tree/delete-min! wt-tree -Removes the association with the least key under the @var{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 - -@example -(wt-tree/delete! @var{wt-tree} (wt-tree/min @var{wt-tree})) -@end example -@end deffn - - -@node Procedures, Environments, Associations, Top -@chapter Procedures - -@cindex procedure -@cindex primitive procedure (defn) -@cindex built-in procedure -@findex lambda -@cindex application hook (defn) -@cindex hook, application (defn) -Procedures are created by evaluating @code{lambda} expressions -(@pxref{Lambda Expressions}); the @code{lambda} may either be explicit -or may be implicit as in a ``procedure @code{define}'' -(@pxref{Definitions}). Also there are special built-in procedures, -called @dfn{primitive procedures}, such as @code{car}; these procedures -are not written in Scheme but in the language used to implement the -Scheme system. MIT/GNU Scheme also provides @dfn{application hooks}, which -support the construction of data structures that act like procedures. - -@cindex procedure, type -@cindex procedure, primitive -@cindex procedure, interpreted -@cindex procedure, compiled -@cindex type, of procedure -@cindex primitive, procedure type -@cindex interpreted, procedure type -@cindex compiled, procedure type -@cindex external representation, for procedure -In MIT/GNU Scheme, the written representation of a procedure tells you -the type of the procedure (compiled, interpreted, or primitive): - -@example -@group -pp - @result{} #[compiled-procedure 56 ("pp" #x2) #x10 #x307578] -(lambda (x) x) - @result{} #[compound-procedure 57] -(define (foo x) x) -foo - @result{} #[compound-procedure 58 foo] -car - @result{} #[primitive-procedure car] -(call-with-current-continuation (lambda (x) x)) - @result{} #[continuation 59] -@end group -@end example - -@noindent -@cindex compound procedure -@cindex procedure, compound -Note that interpreted procedures are called ``compound'' procedures -(strictly speaking, compiled procedures are also compound procedures). -The written representation makes this distinction for historical -reasons, and may eventually change. - -@menu -* Procedure Operations:: -* Primitive Procedures:: -* Continuations:: -* Application Hooks:: -@end menu - -@node Procedure Operations, Primitive Procedures, Procedures, Procedures -@section Procedure Operations - -@deffn procedure apply procedure object object @dots{} -@cindex application, of procedure -Calls @var{procedure} with the elements of the following list as -arguments: - -@example -(cons* @var{object} @var{object} @dots{}) -@end example - -@noindent -The initial @var{object}s may be any objects, but the last @var{object} -(there must be at least one @var{object}) must be a list. - -@example -@group -(apply + (list 3 4 5 6)) @result{} 18 -(apply + 3 4 '(5 6)) @result{} 18 - -(define compose - (lambda (f g) - (lambda args - (f (apply g args))))) -((compose sqrt *) 12 75) @result{} 30 -@end group -@end example -@end deffn - -@deffn procedure procedure? object -@cindex type predicate, for procedure -Returns @code{#t} if @var{object} is a procedure; otherwise returns -@code{#f}. If @code{#t} is returned, exactly one of the following -predicates is satisfied by @var{object}: @code{compiled-procedure?}, -@code{compound-procedure?}, or @code{primitive-procedure?}. -@end deffn - -@deffn procedure compiled-procedure? object -@cindex type predicate, for compiled procedure -Returns @code{#t} if @var{object} is a compiled procedure; otherwise -returns @code{#f}. -@end deffn - -@deffn procedure compound-procedure? object -@cindex type predicate, for compound procedure -Returns @code{#t} if @var{object} is a compound (i.e.@: interpreted) -procedure; otherwise returns @code{#f}. -@end deffn - -@deffn procedure primitive-procedure? object -@cindex type predicate, for primitive procedure -Returns @code{#t} if @var{object} is a primitive procedure; otherwise -returns @code{#f}. -@end deffn - -The following two procedures test the @dfn{arity} of a procedure, that -is, the number of arguments that the procedure accepts. The results of -the test may be less restrictive than the effect of calling the -procedure. In other words, these procedures may indicate that the -procedure will accept a given number of arguments, but if you call the -procedure it may signal a -@code{condition-type:wrong-number-of-arguments} error. This is because -these procedures examine the apparent arity of a procedure. For -example, here is a procedure that appears to accept any number of -arguments, but when called will signal an error if the number of -arguments is not one: -@findex condition-type:wrong-number-of-arguments - -@example -(lambda arguments (apply car arguments)) -@end example - -@deffn procedure procedure-arity-valid? procedure k -Returns @code{#t} if @var{procedure} accepts @var{k} arguments; -otherwise returns @code{#f}. -@end deffn - -@deffn procedure procedure-arity procedure -Returns a description of the number of arguments that @var{procedure} -accepts. The result is a newly allocated pair whose car field is the -minimum number of arguments, and whose cdr field is the maximum -number of arguments. The minimum is an exact non-negative integer. The -maximum is either an exact non-negative integer, or @code{#f} meaning -that the procedure has no maximum number of arguments. - -@example -@group -(procedure-arity (lambda () 3)) @result{} (0 . 0) -(procedure-arity (lambda (x) x)) @result{} (1 . 1) -(procedure-arity car) @result{} (1 . 1) -(procedure-arity (lambda x x)) @result{} (0 . #f) -(procedure-arity (lambda (x . y) x)) @result{} (1 . #f) -(procedure-arity (lambda (x #!optional y) x)) - @result{} (1 . 2) -@end group -@end example -@end deffn - -@deffn procedure procedure-environment procedure -Returns the closing environment of @var{procedure}. Signals an error if -@var{procedure} is a primitive procedure, or if @var{procedure} is a -compiled procedure for which the debugging information is unavailable. -@end deffn - -@node Primitive Procedures, Continuations, Procedure Operations, Procedures -@section Primitive Procedures - -@deffn procedure make-primitive-procedure name [arity] -@var{Name} must be a symbol. @var{Arity} must be an exact non-negative -integer, @code{-1}, @code{#f}, or @code{#t}; if not supplied it defaults -to @code{#f}. Returns the primitive procedure called @var{name}. May -perform further actions depending on @var{arity}: - -@table @asis -@item @code{#f} -If the primitive procedure is not implemented, signals an error. - -@item @code{#t} -If the primitive procedure is not implemented, returns @code{#f}. - -@item integer -If the primitive procedure is implemented, signals an error if its arity -is not equal to @var{arity}. If the primitive procedure is not -implemented, returns an unimplemented primitive procedure object that -accepts @var{arity} arguments. An @var{arity} of @code{-1} means it -accepts any number of arguments. -@end table -@end deffn - -@deffn procedure primitive-procedure-name primitive-procedure -Returns the name of @var{primitive-procedure}, a symbol. - -@example -(primitive-procedure-name car) @result{} car -@end example -@end deffn - -@deffn procedure implemented-primitive-procedure? primitive-procedure -Returns @code{#t} if @var{primitive-procedure} is implemented; otherwise -returns @code{#f}. Useful because the code that implements a particular -primitive procedure is not necessarily linked into the executable Scheme -program. -@end deffn - -@node Continuations, Application Hooks, Primitive Procedures, Procedures -@section Continuations - -@deffn procedure call-with-current-continuation procedure -@cindex continuation -@cindex construction, of continuation -@cindex procedure, escape (defn) -@cindex escape procedure (defn) -@var{Procedure} must be a procedure of one argument. Packages up the -current continuation (see below) as an @dfn{escape procedure} and passes -it as an argument to @var{procedure}. The escape procedure is a Scheme -procedure of one argument that, if it is later passed a value, will -ignore whatever continuation is in effect at that later time and will -give the value instead to the continuation that was in effect when the -escape procedure was created. The escape procedure created by -@code{call-with-current-continuation} has unlimited extent just like any -other procedure in Scheme. It may be stored in variables or data -structures and may be called as many times as desired. - -The following examples show only the most common uses of this procedure. -If all real programs were as simple as these examples, there would be no -need for a procedure with the power of -@code{call-with-current-continuation}. - -@example -@group -(call-with-current-continuation - (lambda (exit) - (for-each (lambda (x) - (if (negative? x) - (exit x))) - '(54 0 37 -3 245 19)) - #t)) @result{} -3 -@end group - -@group -(define list-length - (lambda (obj) - (call-with-current-continuation - (lambda (return) - (letrec ((r - (lambda (obj) - (cond ((null? obj) 0) - ((pair? obj) (+ (r (cdr obj)) 1)) - (else (return #f)))))) - (r obj)))))) -(list-length '(1 2 3 4)) @result{} 4 -(list-length '(a b . c)) @result{} #f -@end group -@end example - -@cindex non-local exit -@cindex exit, non-local -A common use of @code{call-with-current-continuation} is for structured, -non-local exits from loops or procedure bodies, but in fact -@code{call-with-current-continuation} is quite useful for implementing a -wide variety of advanced control structures. - -Whenever a Scheme expression is evaluated a continuation exists that -wants the result of the expression. The continuation represents an -entire (default) future for the computation. If the expression is -evaluated at top level, for example, the continuation will take the -result, print it on the screen, prompt for the next input, evaluate it, -and so on forever. Most of the time the continuation includes actions -specified by user code, as in a continuation that will take the result, -multiply it by the value stored in a local variable, add seven, and give -the answer to the top-level continuation to be printed. Normally these -ubiquitous continuations are hidden behind the scenes and programmers -don't think much about them. On the rare occasions that you may need to -deal explicitly with continuations, -@code{call-with-current-continuation} lets you do so by creating a -procedure that acts just like the current continuation. -@end deffn - -@deffn procedure continuation? object -@cindex type predicate, for continuation -Returns @code{#t} if @var{object} is a continuation; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure within-continuation continuation thunk -@cindex continuation, alternate invocation -@cindex escape procedure, alternate invocation -@var{Thunk} must be a procedure of no arguments. Conceptually,@* -@code{within-continuation} invokes @var{continuation} on the result of -invoking @var{thunk}, but @var{thunk} is executed in the dynamic context -of @var{continuation}. In other words, the ``current'' continuation is -abandoned before @var{thunk} is invoked. -@end deffn - -@deffn procedure dynamic-wind before thunk after -Calls @var{thunk} without arguments, returning the result(s) of this -call. @var{Before} and @var{after} are called, also without arguments, -as required by the following rules (note that in the absence of calls to -continuations captured using @code{call-with-current-continuation} the -three arguments are called once each, in order). @var{Before} is called -whenever execution enters the dynamic extent of the call to @var{thunk} -and @var{after} is called whenever it exits that dynamic extent. The -dynamic extent of a procedure call is the period between when the call -is initiated and when it returns. In Scheme, because of -@code{call-with-current-continuation}, the dynamic extent of a call may -not be a single, connected time period. It is defined as follows: - -@itemize @bullet -@item -The dynamic extent is entered when execution of the body of the called -procedure begins. - -@item -The dynamic extent is also entered when execution is not within the -dynamic extent and a continuation is invoked that was captured (using -@code{call-with-current-continuation}) during the dynamic extent. - -@item -It is exited when the called procedure returns. - -@item -It is also exited when execution is within the dynamic extent and a -continuation is invoked that was captured while not within the dynamic -extent. -@end itemize - -If a second call to @code{dynamic-wind} occurs within the dynamic extent -of the call to @var{thunk} and then a continuation is invoked in such a -way that the @var{after}s from these two invocations of -@code{dynamic-wind} are both to be called, then the @var{after} -associated with the second (inner) call to @code{dynamic-wind} is called -first. - -If a second call to @code{dynamic-wind} occurs within the dynamic extent -of the call to @var{thunk} and then a continuation is invoked in such a -way that the @var{before}s from these two invocations of -@code{dynamic-wind} are both to be called, then the @var{before} -associated with the first (outer) call to @code{dynamic-wind} is called -first. - -If invoking a continuation requires calling the @var{before} from one -call to @code{dynamic-wind} and the @var{after} from another, then the -@var{after} is called first. - -The effect of using a captured continuation to enter or exit the dynamic -extent of a call to @var{before} or @var{after} is undefined. - -@example -@group -(let ((path '()) - (c #f)) - (let ((add (lambda (s) - (set! path (cons s path))))) - (dynamic-wind - (lambda () (add 'connect)) - (lambda () - (add (call-with-current-continuation - (lambda (c0) - (set! c c0) - 'talk1)))) - (lambda () (add 'disconnect))) - (if (< (length path) 4) - (c 'talk2) - (reverse path)))) - -@result{} (connect talk1 disconnect connect talk2 disconnect) -@end group -@end example -@end deffn - -The following two procedures support multiple values. - -@deffn procedure call-with-values thunk procedure -@cindex multiple values, from procedure -@cindex values, multiple -@var{Thunk} must be a procedure of no arguments, and @var{procedure} -must be a procedure. @var{Thunk} is invoked with a continuation that -expects to receive multiple values; specifically, the continuation -expects to receive the same number of values that @var{procedure} -accepts as arguments. @var{Thunk} must return multiple values using the -@code{values} procedure. Then @var{procedure} is called with the -multiple values as its arguments. The result yielded by @var{procedure} -is returned as the result of @code{call-with-values}. -@end deffn - -@deffn procedure values object @dots{} -Returns multiple values. The continuation in effect when this procedure -is called must be a multiple-value continuation that was created by -@code{call-with-values}. Furthermore it must accept as many values as -there are @var{object}s. -@end deffn - -@node Application Hooks, , Continuations, Procedures -@section Application Hooks - -@cindex application hook (defn) -@cindex procedure, of application hook -@cindex extra object, of application hook -@dfn{Application hooks} are objects that can be applied like procedures. -Each application hook has two parts: a @dfn{procedure} that specifies -what to do when the application hook is applied, and an arbitrary -object, called @dfn{extra}. Often the procedure uses the extra object -to determine what to do. - -@cindex apply hook (defn) -@cindex entity (defn) -There are two kinds of application hooks, which differ in what arguments -are passed to the procedure. When an @dfn{apply hook} is applied, the -procedure is passed exactly the same arguments that were passed to the -apply hook. When an @dfn{entity} is applied, the entity itself is -passed as the first argument, followed by the other arguments that were -passed to the entity. - -Both apply hooks and entities satisfy the predicate @code{procedure?}. -Each satisfies either @code{compiled-procedure?}, -@code{compound-procedure?}, or @code{primitive-procedure?}, depending on -its procedure component. An apply hook is considered to accept the same -number of arguments as its procedure, while an entity is considered to -accept one less argument than its procedure. - -@deffn procedure make-apply-hook procedure object -Returns a newly allocated apply hook with a procedure component of -@var{procedure} and an extra component of @var{object}. -@end deffn - -@deffn procedure apply-hook? object -@cindex type predicate, for apply hook -Returns @code{#t} if @var{object} is an apply hook; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure apply-hook-procedure apply-hook -Returns the procedure component of @var{apply-hook}. -@end deffn - -@deffn procedure set-apply-hook-procedure! apply-hook procedure -Changes the procedure component of @var{apply-hook} to be -@var{procedure}. Returns an unspecified value. -@end deffn - -@deffn procedure apply-hook-extra apply-hook -Returns the extra component of @var{apply-hook}. -@end deffn - -@deffn procedure set-apply-hook-extra! apply-hook object -Changes the extra component of @var{apply-hook} to be @var{object}. -Returns an unspecified value. -@end deffn - -@deffn procedure make-entity procedure object -Returns a newly allocated entity with a procedure component of -@var{procedure} and an extra component of @var{object}. -@end deffn - -@deffn procedure entity? object -@cindex type predicate, for entity -Returns @code{#t} if @var{object} is an entity; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure entity-procedure entity -Returns the procedure component of @var{entity}. -@end deffn - -@deffn procedure set-entity-procedure! entity procedure -Changes the procedure component of @var{entity} to be @var{procedure}. -Returns an unspecified value. -@end deffn - -@deffn procedure entity-extra entity -Returns the extra component of @var{entity}. -@end deffn - -@deffn procedure set-entity-extra! entity object -Changes the extra component of @var{entity} to be @var{object}. Returns -an unspecified value. -@end deffn - -@node Environments, Input/Output, Procedures, Top -@chapter Environments - -@menu -* Environment Operations:: -* Environment Variables:: -* REPL Environment:: -* Top-level Environments:: -@end menu - -@node Environment Operations, Environment Variables, Environments, Environments -@section Environment Operations - -Environments are first-class objects in MIT/GNU Scheme. An environment -consists of some bindings and possibly a parent environment, from which -other bindings are inherited. The operations in this section reveal the -frame-like structure of environments by permitting you to examine the -bindings of a particular environment separately from those of its -parent. - -@cindex variable binding -@cindex binding, variable -@cindex unassigned binding -@cindex binding, unassigned -@findex condition-type:unassigned-variable -There are several types of bindings that can occur in an environment. -The most common is the simple variable binding, which associates a value -(any Scheme object) with an identifier (a symbol). A variable binding -can also be @dfn{unassigned}, which means that it has no value. An -unassigned variable is bound, in that is will shadow other bindings of -the same name in ancestor environments, but a reference to that variable -will signal an error of type @code{condition-type:unassigned-variable}. -An unassigned variable can be @dfn{assigned} (using @code{set!} or -@code{environment-assign!}) to give it a value. - -@cindex keyword binding -@cindex syntactic keyword binding -@cindex binding, syntactic keyword -@findex condition-type:macro-binding -In addition to variable bindings, an environment can also have -@dfn{keyword bindings}. A keyword binding associates a syntactic -keyword (usually a macro transformer) with an identifier. Keyword -bindings are special in that they are considered ``bound'', but ordinary -variable references don't work on them. So an attempt to reference or -assign a keyword binding results in an error of type -@code{condition-type:macro-binding}. However, keyword bindings can be -redefined using @code{define} or @code{environment-define}. - -@deffn procedure environment? object -@cindex type predicate, for environment -Returns @code{#t} if @var{object} is an environment; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure environment-has-parent? environment -Returns @code{#t} if @var{environment} has a parent environment; -otherwise returns @code{#f}. -@end deffn - -@deffn procedure environment-parent environment -Returns the parent environment of @var{environment}. It is an error if -@var{environment} has no parent. -@end deffn - -@deffn procedure environment-bound-names environment -Returns a newly allocated list of the names (symbols) that are bound by -@var{environment}. This does not include the names that are bound by -the parent environment of @var{environment}. It does include names that -are unassigned or keywords in @var{environment}. -@end deffn - -@deffn procedure environment-macro-names environment -Returns a newly allocated list of the names (symbols) that are bound to -syntactic keywords in @var{environment}. -@end deffn - -@deffn procedure environment-bindings environment -Returns a newly allocated list of the bindings of @var{environment}; -does not include the bindings of the parent environment. Each element -of this list takes one of two forms: @code{(@var{symbol})} indicates -that @var{symbol} is bound but unassigned, while @code{(@var{symbol} -@var{object})} indicates that @var{symbol} is bound, and its value is -@var{object}. -@end deffn - -@deffn procedure environment-reference-type environment symbol -Returns a symbol describing the @dfn{reference type} of @var{symbol} in -@var{environment} or one of its ancestor environments. The result is -one of the following: - -@table @code -@item normal -means @var{symbol} is a variable binding with a normal value. - -@item unassigned -means @var{symbol} is a variable binding with no value. - -@item macro -means @var{symbol} is a keyword binding. - -@item unbound -means @var{symbol} has no associated binding. -@end table -@end deffn - -@deffn procedure environment-bound? environment symbol -Returns @code{#t} if @var{symbol} is bound in @var{environment} or one -of its ancestor environments; otherwise returns @code{#f}. This is -equivalent to - -@example -(not (eq? 'unbound - (environment-reference-type @var{environment} @var{symbol}))) -@end example -@end deffn - -@deffn procedure environment-assigned? environment symbol -Returns @code{#t} if @var{symbol} is bound in @var{environment} or one -of its ancestor environments, and has a normal value. Returns @code{#f} -if it is bound but unassigned. Signals an error if it is unbound or is -bound to a keyword. -@end deffn - -@deffn procedure environment-lookup environment symbol -@var{Symbol} must be bound to a normal value in @var{environment} or one -of its ancestor environments. Returns the value to which it is bound. -Signals an error if unbound, unassigned, or a keyword. -@end deffn - -@deffn procedure environment-lookup-macro environment symbol -If @var{symbol} is a keyword binding in @var{environment} or one of its -ancestor environments, returns the value of the binding. Otherwise, -returns @code{#f}. Does not signal any errors other than argument-type -errors. -@end deffn - -@deffn procedure environment-assignable? environment symbol -@var{Symbol} must be bound in @var{environment} or one of its ancestor -environments. Returns @code{#t} if the binding may be modified by side -effect. -@end deffn - -@deffn procedure environment-assign! environment symbol object -@var{Symbol} must be bound in @var{environment} or one of its ancestor -environments, and must be assignable. Modifies the binding to have -@var{object} as its value, and returns an unspecified result. -@end deffn - -@deffn procedure environment-definable? environment symbol -Returns @code{#t} if @var{symbol} is definable in @var{environment}, and -@code{#f} otherwise. At present, this is false for environments -generated by application of compiled procedures, and true for all other -environments. -@end deffn - -@deffn procedure environment-define environment symbol object -Defines @var{symbol} to be bound to @var{object} in @var{environment}, -and returns an unspecified value. Signals an error if @var{symbol} -isn't definable in @var{environment}. -@end deffn - -@deffn procedure environment-define-macro environment symbol transformer -Defines @var{symbol} to be a keyword bound to @var{transformer} in -@var{environment}, and returns an unspecified value. Signals an error -if @var{symbol} isn't definable in @var{environment}. The type of -@var{transformer} is defined by the syntax engine and is not checked by -this procedure. If the type is incorrect this will subsequently signal -an error during syntax expansion. -@end deffn - -@deffn procedure eval expression environment -@cindex s-expression -@cindex evaluation, of s-expression -Evaluates @var{expression}, a list-structure representation (sometimes -called s-expression representation) of a Scheme expression, in -@var{environment}. You rarely need @code{eval} in ordinary programs; it -is useful mostly for evaluating expressions that have been created ``on -the fly'' by a program. @code{eval} is relatively expensive because it -must convert @var{expression} to an internal form before it is executed. - -@example -@group -(define foo (list '+ 1 2)) -(eval foo (the-environment)) @result{} 3 -@end group -@end example -@end deffn - -@node Environment Variables, REPL Environment, Environment Operations, Environments -@section Environment Variables - -@findex define -The @code{user-initial-environment} is where the top-level -read-eval-print (@acronym{REP}) loop evaluates expressions and binds -definitions. It is a child of @code{system-global-environment}, which -is where all of the Scheme system definitions are bound. All of the -bindings in @code{system-global-environment} are available when the -current environment is @code{user-initial-environment}. However, any -new bindings that you create in the @acronym{REP} loop (with -@code{define} forms or by loading files containing @code{define} forms) -occur in @code{user-initial-environment}. - -@defvr variable system-global-environment -The variable @code{system-global-environment} is bound to the -distinguished environment that's the ancestor of most other environments -(except for those created by @code{make-root-top-level-environment}). -It is the parent environment of @code{user-initial-environment}. -Primitives, system procedures, and most syntactic keywords are bound -(and sometimes closed) in this environment. -@end defvr - -@defvr variable user-initial-environment -The variable @code{user-initial-environment} is bound to the default -environment in which typed expressions are evaluated by the top-level -@acronym{REP} loop. - -Although all bindings in @code{system-global-environment} are visible to -the @acronym{REP} loop, definitions that are typed at, or loaded by, the -@acronym{REP} loop occur in the @code{user-initial-environment}. This -is partly a safety measure: if you enter a definition that happens to -have the same name as a critical system procedure, your definition will -be visible only to the procedures you define in the -@code{user-initial-environment}; the MIT/GNU Scheme system procedures, which -are defined in @code{system-global-environment}, will continue to see -the original definition. -@end defvr - -@node REPL Environment, Top-level Environments, Environment Variables, Environments -@section REPL Environment - -@deffn procedure nearest-repl/environment -@findex user-initial-environment -Returns the current @acronym{REP} loop environment (i.e.@: the current -environment of the closest enclosing @acronym{REP} loop). When Scheme -first starts up, this is the same as @code{user-initial-environment}. -@end deffn - -@deffn procedure ge environment -Changes the current @acronym{REP} loop environment to @var{environment}. -@var{Environment} can be either an environment or a procedure object. -If it's a procedure, the environment in which that procedure was closed -is the new environment. -@end deffn - -@node Top-level Environments, , REPL Environment, Environments -@section Top-level Environments - -@cindex top-level environment -@cindex interpreter environment -@cindex environment, top-level -@cindex environment, interpreter -The operations in this section manipulate @dfn{top-level environments}, -as opposed to environments created by the application of procedures. -For historical reasons, top-level environments are referred to as -@dfn{interpreter environments}. - -@deffn {special form} the-environment -@cindex current environment -@cindex environment, current -Returns the current environment. This form may only be evaluated in a -top-level environment. An error is signalled if it appears elsewhere. -@end deffn - -@deffn procedure top-level-environment? object -@deffnx procedure interpreter-environment? object -@cindex type predicate, for top-level environment -Returns @code{#t} if @var{object} is an top-level environment; otherwise -returns @code{#f}. - -@code{interpreter-environment?} is an alias for -@code{top-level-environment?}. -@end deffn - -@deffn procedure extend-top-level-environment environment [names [values]] -@deffnx procedure make-root-top-level-environment [names [values]] -Returns a newly allocated top-level environment. -@code{extend-top-level-environment} creates an environment that has -parent @var{environment}, while @code{make-root-top-level-environment} -creates an environment that has no parent. - -The optional arguments @var{names} and @var{values} are used to specify -initial bindings in the new environment. If specified, @var{names} must -be a list of symbols, and @var{values} must be a list of objects. If -only @var{names} is specified, each name in @var{names} will be bound in -the environment, but unassigned. If @var{names} and @var{values} are -both specified, they must be the same length, and each name in -@var{names} will be bound to the corresponding value in @var{values}. -If neither @var{names} nor @var{values} is specified, the environment -will have no initial bindings. -@end deffn - -@deffn procedure link-variables environment1 symbol1 environment2 symbol2 -Defines @var{symbol1} in @var{environment1} to have the same binding as -@var{symbol2} in @var{environment2}, and returns an unspecified value. -Prior to the call, @var{symbol2} must be bound in @var{environment2}, -but the type of binding is irrelevant; it may be a normal binding, an -unassigned binding, or a keyword binding. Signals an error if -@var{symbol1} isn't definable in @var{environment1}, or if @var{symbol2} -is unbound in @var{environment2}. - -By ``the same binding'', we mean that the value cell is shared between -the two environments. If a value is assigned to @var{symbol1} in -@var{environment1}, a subsequent reference to @var{symbol2} in -@var{environment2} will see that value, and vice versa. -@end deffn - -@deffn procedure unbind-variable environment symbol -If @var{symbol} is bound in @var{environment} or one of its ancestor -environments, removes the binding, so that subsequent accesses to that -symbol behave as if the binding never existed. Returns @code{#t} if there -was a binding prior to the call, and @code{#f} if there wasn't. -@end deffn - -@node Input/Output, Operating-System Interface, Environments, Top -@chapter Input/Output - -@cindex input -@cindex output -@cindex port -This chapter describes the procedures that are used for input and -output (@acronym{I/O}). The chapter first describes @dfn{ports} and -how they are manipulated, then describes the @acronym{I/O} operations. -Finally, some low-level procedures are described that permit the -implementation of custom ports and high-performance @acronym{I/O}. - -@menu -* Ports:: -* File Ports:: -* String Ports:: -* Input Procedures:: -* Output Procedures:: -* Format:: -* Custom Output:: -* Prompting:: -* Port Primitives:: -* Parser Buffers:: -* Parser Language:: -* XML Parser:: -@end menu - -@node Ports, File Ports, Input/Output, Input/Output -@section Ports - -@cindex port (defn) -@findex console-i/o-port -Scheme uses ports for @acronym{I/O}. A @dfn{port}, which can be -treated like any other Scheme object, serves as a source or sink for -data. A port must be open before it can be read from or written to. -The standard @acronym{I/O} port, @code{console-i/o-port}, is opened -automatically when you start Scheme. When you use a file for input or -output, you need to explicitly open and close a port to the file (with -procedures described in this chapter). Additional procedures let you -open ports to strings. - -@cindex current input port (defn) -@cindex input port, current (defn) -@cindex port, current -@findex read-char -@findex read -Many input procedures, such as @code{read-char} and @code{read}, read -data from the current input port by default, or from a port that you -specify. The current input port is initially @code{console-i/o-port}, -but Scheme provides procedures that let you change the current input -port to be a file or string. - -@cindex current output port (defn) -@cindex output port, current (defn) -@findex write-char -@findex display -Similarly, many output procedures, such as @code{write-char} and -@code{display}, write data to the current output port by default, or to -a port that you specify. The current output port is initially -@code{console-i/o-port}, but Scheme provides procedures that let you -change the current output port to be a file or string. - -All ports read or write only @acronym{ISO-8859-1} characters. - -Every port is either an input port, an output port, or both. The -following predicates distinguish all of the possible cases. - -@deffn procedure port? object -@cindex type predicate, for port -Returns @code{#t} if @var{object} is a port, otherwise returns -@code{#f}. -@end deffn - -@deffn procedure input-port? object -Returns @code{#t} if @var{object} is an input port, otherwise returns -@code{#f}. Any object satisfying this predicate also satisfies -@code{port?}. -@end deffn - -@deffn procedure output-port? object -Returns @code{#t} if @var{object} is an output port, otherwise returns -@code{#f}. Any object satisfying this predicate also satisfies -@code{port?}. -@end deffn - -@deffn procedure i/o-port? object -Returns @code{#t} if @var{object} is both an input port and an output -port, otherwise returns @code{#f}. Any object satisfying this predicate -also satisfies @code{port?}, @code{input-port?}, and -@code{output-port?}. -@end deffn - -@deffn procedure guarantee-port object -@deffnx procedure guarantee-input-port object -@deffnx procedure guarantee-output-port object -@deffnx procedure guarantee-i/o-port object -These procedures check the type of @var{object}, signalling an error -of type@* @code{condition-type:wrong-type-argument} if it is not a -port, input port, output port, or @acronym{I/O} port, respectively. -Otherwise they return @var{object}. -@findex condition-type:wrong-type-argument -@end deffn - -@cindex standard ports -The next five procedures return the runtime system's @dfn{standard -ports}. All of the standard ports are dynamically bound by the -@acronym{REP} loop; this means that when a new @acronym{REP} loop is -started, for example by an error, each of these ports is dynamically -bound to the @acronym{I/O} port of the @acronym{REP} loop. When the -@acronym{REP} loop exits, the ports revert to their original values. - -@deffn procedure current-input-port -@findex console-input-port -Returns the current input port. This is the default port used by many -input procedures. Initially, @code{current-input-port} returns the -value of @code{console-i/o-port}. -@end deffn - -@deffn procedure current-output-port -@findex console-output-port -Returns the current output port. This is the default port used by many -output procedures. Initially, @code{current-output-port} returns the -value of @code{console-i/o-port}. -@end deffn - -@deffn procedure notification-output-port -Returns an output port suitable for generating ``notifications'', that -is, messages to the user that supply interesting information about the -execution of a program. For example, the @code{load} procedure writes -messages to this port informing the user that a file is being loaded. -Initially, @code{notification-output-port} returns the value of -@code{console-i/o-port}. -@end deffn - -@deffn procedure trace-output-port -Returns an output port suitable for generating ``tracing'' information -about a program's execution. The output generated by the @code{trace} -procedure is sent to this port. Initially, @code{trace-output-port} -returns the value of @code{console-i/o-port}. -@end deffn - -@deffn procedure interaction-i/o-port -Returns an @acronym{I/O} port suitable for querying or prompting the -user. The standard prompting procedures use this port by default -(@pxref{Prompting}). Initially, @code{interaction-i/o-port} returns -the value of @code{console-i/o-port}. -@end deffn - -@deffn procedure with-input-from-port input-port thunk -@deffnx procedure with-output-to-port output-port thunk -@deffnx procedure with-notification-output-port output-port thunk -@deffnx procedure with-trace-output-port output-port thunk -@deffnx procedure with-interaction-i/o-port i/o-port thunk -@var{Thunk} must be a procedure of no arguments. Each of these -procedures binds one of the standard ports to its first argument, calls -@var{thunk} with no arguments, restores the port to its original value, -and returns the result that was yielded by @var{thunk}. This temporary -binding is performed the same way as dynamic binding of a variable, -including the behavior in the presence of continuations (@pxref{Dynamic -Binding}). - -@code{with-input-from-port} binds the current input port, -@code{with-output-to-port} binds the current output port, -@code{with-notification-output-port} binds the ``notification'' output -port, @code{with-trace-output-port} binds the ``trace'' output port, -and @code{with-interaction-i/o-port} binds the ``interaction'' -@acronym{I/O} port. -@end deffn - -@deffn procedure set-current-input-port! input-port -@deffnx procedure set-current-output-port! output-port -@deffnx procedure set-notification-output-port! output-port -@deffnx procedure set-trace-output-port! output-port -@deffnx procedure set-interaction-i/o-port! i/o-port -Each of these procedures alters the binding of one of the standard ports -and returns an unspecified value. The binding that is modified -corresponds to the name of the procedure. -@end deffn - -@defvr variable console-i/o-port -@cindex port, console -@cindex console, port -@cindex input port, console -@cindex output port, console -@code{console-i/o-port} is an @acronym{I/O} port that communicates -with the ``console''. Under unix, the console is the controlling -terminal of the Scheme process. Under Windows and OS/2, the console -is the window that is created when Scheme starts up. - -This variable is rarely used; instead programs should use one of the -standard ports defined above. This variable should not be modified. -@end defvr - -@deffn procedure close-port port -@cindex closing, of port -Closes @var{port} and returns an unspecified value. If @var{port} is a -file port, the file is closed. -@end deffn - -@deffn procedure close-input-port port -Closes @var{port} and returns an unspecified value. @var{Port} must -be an input port or an @acronym{I/O} port; if it is an @acronym{I/O} -port, then only the input side of the port is closed. -@end deffn - -@deffn procedure close-output-port port -Closes @var{port} and returns an unspecified value. @var{Port} must -be an output port or an @acronym{I/O} port; if it is an @acronym{I/O} -port, then only the output side of the port is closed. -@end deffn - -@node File Ports, String Ports, Ports, Input/Output -@section File Ports - -@cindex file, input and output ports -@cindex port, file -@cindex input port, file -@cindex output port, file -@cindex I/O, to files -Before Scheme can access a file for reading or writing, it is necessary -to open a port to the file. This section describes procedures used to -open ports to files. Such ports are closed (like any other port) by -@code{close-port}. File ports are automatically closed if and when they -are reclaimed by the garbage collector. - -@findex merge-pathnames -Before opening a file for input or output, by whatever method, the -@var{filename} argument is converted to canonical form by calling the -procedure @code{merge-pathnames} with @var{filename} as its sole -argument. Thus, @var{filename} can be either a string or a pathname, -and it is merged with the current pathname defaults to produce the -pathname that is then opened. - -@cindex binary file ports -@cindex newline translation -Any file can be opened in one of two modes, @dfn{normal} or -@dfn{binary}. Normal mode is for accessing text files, and binary mode -is for accessing other files. Unix does not distinguish these modes, -but Windows and OS/2 do: in normal mode, their file ports perform -@dfn{newline translation}, mapping between the carriage-return/linefeed -sequence that terminates text lines in files, and the @code{#\newline} -that terminates lines in Scheme. In binary mode, such ports do not -perform newline translation. Unless otherwise mentioned, the procedures -in this section open files in normal mode. - -@deffn procedure open-input-file filename -@cindex construction, of file input port -Takes a filename referring to an existing file and returns an input port -capable of delivering characters from the file. If the file cannot be -opened, an error of type @code{condition-type:file-operation-error} is -signalled. -@findex condition-type:file-operation-error -@end deffn - -@deffn procedure open-output-file filename [append?] -@cindex construction, of file output port -Takes a filename referring to an output file to be created and returns -an output port capable of writing characters to a new file by that name. -If the file cannot be opened, an error of type -@code{condition-type:file-operation-error} is signalled. -@findex condition-type:file-operation-error - -@cindex appending, to output file -The optional argument @var{append?} is an MIT/GNU Scheme extension. If -@var{append?} is given and not @code{#f}, the file is opened in -@dfn{append} mode. In this mode, the contents of the file are not -overwritten; instead any characters written to the file are appended to -the end of the existing contents. If the file does not exist, append -mode creates the file and writes to it in the normal way. -@end deffn - -@deffn procedure open-i/o-file filename -@cindex construction, of file input port -Takes a filename referring to an existing file and returns an -@acronym{I/O} port capable of both reading and writing the file. If -the file cannot be opened, an error of type -@code{condition-type:file-operation-error} is signalled. -@findex condition-type:file-operation-error - -This procedure is often used to open special files. For example, under -unix this procedure can be used to open terminal device files, @sc{pty} -device files, and named pipes. -@end deffn - -@deffn procedure open-binary-input-file filename -@deffnx procedure open-binary-output-file filename [append?] -@deffnx procedure open-binary-i/o-file filename -These procedures open files in binary mode. In all other respects they -are identical to @code{open-input-file}, @code{open-output-file}, and -@code{open-i/o-file}, respectively. -@end deffn - -@deffn procedure close-all-open-files -@cindex closing, of file port -This procedure closes all file ports that are open at the time that it -is called, and returns an unspecified value. -@end deffn - -@deffn procedure call-with-input-file filename procedure -@deffnx procedure call-with-output-file filename procedure -These procedures call @var{procedure} with one argument: the port -obtained by opening the named file for input or output, respectively. -If the file cannot be opened, an error of type -@code{condition-type:file-operation-error} is signalled. If -@var{procedure} returns, then the port is closed automatically and the -value yielded by @var{procedure} is returned. If @var{procedure} does -not return, then the port will not be closed automatically unless it is -reclaimed by the garbage collector.@footnote{Because Scheme's escape -procedures have unlimited extent, it is possible to escape from the -current continuation but later to escape back in. If implementations -were permitted to close the port on any escape from the current -continuation, then it would be impossible to write portable code using -both @code{call-with-current-continuation} and -@code{call-with-input-file} or @code{call-with-output-file}.} -@end deffn - -@deffn procedure call-with-binary-input-file filename procedure -@deffnx procedure call-with-binary-output-file filename procedure -These procedures open files in binary mode. In all other respects they -are identical to @code{call-with-input-file} and -@code{call-with-output-file}, respectively. -@end deffn - -@deffn procedure with-input-from-file filename thunk -@deffnx procedure with-output-to-file filename thunk -@cindex current input port, rebinding -@cindex current output port, rebinding -@findex current-input-port -@findex current-output-port -@var{Thunk} must be a procedure of no arguments. -The file is opened for input or output, an input or output port -connected to it is made the default value returned by -@code{current-input-port} or @code{current-output-port}, and the -@var{thunk} is called with no arguments. When the @var{thunk} returns, -the port is closed and the previous default is restored. -@code{with-input-from-file} and @code{with-output-to-file} return the -value yielded by @var{thunk}. If an escape procedure is used to escape -from the continuation of these procedures, their behavior is -implementation-dependent; in that situation MIT/GNU Scheme leaves the files -open. -@end deffn - -@deffn procedure with-input-from-binary-file filename thunk -@deffnx procedure with-output-to-binary-file filename thunk -These procedures open files in binary mode. In all other respects they -are identical to @code{with-input-from-file} and -@code{with-output-to-file}, respectively. -@end deffn - -@node String Ports, Input Procedures, File Ports, Input/Output -@section String Ports - -@cindex string, input and output ports -@cindex port, string -@cindex input port, string -@cindex output port, string -@cindex I/O, to strings -This section describes the simplest kinds of ports: input ports that -read their input from given strings, and output ports that accumulate -their output and return it as a string. It also describes -``truncating'' output ports, which can limit the length of the resulting -string to a given value. - -@deffn procedure string->input-port string [start [end]] -@cindex string, converting to input port -@cindex construction, of string input port -Returns a new string port that delivers characters from @var{string}. -The optional arguments @var{start} and @var{end} may be used to specify -that the string port delivers characters from a substring of -@var{string}; if not given, @var{start} defaults to @code{0} and -@var{end} defaults to @code{(string-length @var{string})}. -@end deffn - -@deffn procedure with-input-from-string string thunk -@cindex current input port, rebinding -@var{Thunk} must be a procedure of no arguments. -@code{with-input-from-string} creates a new input port that reads from -@var{string}, makes that port the current input port, and calls -@var{thunk}. When @var{thunk} returns, @code{with-input-from-string} -restores the previous current input port and returns the result yielded -by @var{thunk}. - -@example -(with-input-from-string "(a b c) (d e f)" read) @result{} (a b c) -@end example - -Note: this procedure is equivalent to: - -@example -(with-input-from-port (string->input-port @var{string}) @var{thunk}) -@end example -@end deffn - -@deffn procedure with-string-output-port procedure -@var{Procedure} is called with one argument, an output port. The value -yielded by @var{procedure} is ignored. When @var{procedure} returns, -@code{with-string-output-port} returns the port's accumulated output as -a newly allocated string. -@end deffn - -@deffn procedure with-output-to-string thunk -@cindex current output port, rebinding -@cindex construction, of string output port -@findex current-output-port -@var{Thunk} must be a procedure of no arguments. -@code{with-output-to-string} creates a new output port that accumulates -output, makes that port the default value returned by -@code{current-output-port}, and calls @var{thunk} with no arguments. -When @var{thunk} returns, @code{with-output-to-string} restores the -previous default and returns the accumulated output as a newly allocated -string. - -@example -@group -(with-output-to-string - (lambda () - (write 'abc))) @result{} "abc" -@end group -@end example - -Note: this procedure is equivalent to: - -@example -@group -(with-string-output-port - (lambda (port) - (with-output-to-port port @var{thunk}))) -@end group -@end example -@end deffn - -@deffn procedure with-output-to-truncated-string k thunk -Similar to @code{with-output-to-string}, except that the output is -limited to @var{k} characters. If @var{thunk} attempts to write more -than @var{k} characters, it will be aborted by invoking an escape -procedure that returns from @code{with-output-to-truncated-string}. - -The value of this procedure is a pair; the car of the pair is @code{#t} -if @var{thunk} attempted to write more than @var{k} characters, and -@code{#f} otherwise. The cdr of the pair is a newly allocated string -containing the accumulated output. - -This procedure is helpful for displaying circular lists, as shown in this -example: - -@example -@group -(define inf (list 'inf)) -(with-output-to-truncated-string 40 - (lambda () - (write inf))) @result{} (#f . "(inf)") -(set-cdr! inf inf) -(with-output-to-truncated-string 40 - (lambda () - (write inf))) - @result{} (#t . "(inf inf inf inf inf inf inf inf inf inf") -@end group -@end example -@end deffn - -@deffn procedure write-to-string object [k] -Writes @var{object} to a string output port, and returns the resulting -newly allocated string. If @var{k} is supplied and not @code{#f}, this -procedure is equivalent to - -@example -@group -(with-output-to-truncated-string @var{k} - (lambda () - (write @var{object}))) -@end group -@end example - -otherwise it is equivalent to - -@example -@group -(with-output-to-string - (lambda () - (write @var{object}))) -@end group -@end example -@end deffn - -@node Input Procedures, Output Procedures, String Ports, Input/Output -@section Input Procedures -@cindex input operations - -This section describes the procedures that read input. Input procedures -can read either from the current input port or from a given port. -Remember that to read from a file, you must first open a port to the -file. - -@cindex interactive input ports (defn) -Input ports can be divided into two types, called @dfn{interactive} and -@dfn{non-interactive}. Interactive input ports are ports that read -input from a source that is time-dependent; for example, a port that -reads input from a terminal or from another program. Non-interactive -input ports read input from a time-independent source, such as an -ordinary file or a character string. - -All optional arguments called @var{input-port}, if not supplied, default -to the current input port. - -@deffn procedure read-char [input-port] -@cindex character, input from port -Returns the next character available from @var{input-port}, updating -@var{input-port} to point to the following character. If no more -characters are available, an end-of-file object is returned. - -In MIT/GNU Scheme, if @var{input-port} is an interactive input port and no -characters are immediately available, @code{read-char} will hang waiting -for input, even if the port is in non-blocking mode. -@end deffn - -@deffn procedure peek-char [input-port] -Returns the next character available from @var{input-port}, -@emph{without} updating @var{input-port} to point to the following -character. If no more characters are available, an end-of-file object -is returned.@footnote{The value returned by a call to @code{peek-char} -is the same as the value that would have been returned by a call to -@code{read-char} on the same port. The only difference is that the very -next call to @code{read-char} or @code{peek-char} on that -@var{input-port} will return the value returned by the preceding call to -@code{peek-char}. In particular, a call to @code{peek-char} on an -interactive port will hang waiting for input whenever a call to -@code{read-char} would have hung.} - -In MIT/GNU Scheme, if @var{input-port} is an interactive input port and no -characters are immediately available, @code{peek-char} will hang waiting -for input, even if the port is in non-blocking mode. -@end deffn - -@deffn procedure char-ready? [input-port] -@findex read-char -Returns @code{#t} if a character is ready on @var{input-port} and -returns @code{#f} otherwise. If @code{char-ready?} returns @code{#t} -then the next @code{read-char} operation on @var{input-port} is -guaranteed not to hang. If @var{input-port} is a file port at end of -file then @code{char-ready?} returns -@code{#t}.@footnote{@code{char-ready?} exists to make it possible for a -program to accept characters from interactive ports without getting -stuck waiting for input. Any input editors associated with such ports -must make sure that characters whose existence has been asserted by -@code{char-ready?} cannot be rubbed out. If @code{char-ready?} were to -return @code{#f} at end of file, a port at end of file would be -indistinguishable from an interactive port that has no ready -characters.} -@end deffn - -@deffn procedure read [input-port] -@cindex expression, input from port -@cindex external representation, parsing -@cindex parsing, of external representation -Converts external representations of Scheme objects into the objects -themselves. @code{read} returns the next object parsable from -@var{input-port}, updating @var{input-port} to point to the first -character past the end of the written representation of the object. If -an end of file is encountered in the input before any characters are -found that can begin an object, @code{read} returns an end-of-file -object. The @var{input-port} remains open, and further attempts to read -will also return an end-of-file object. If an end of file is -encountered after the beginning of an object's written representation, -but the written representation is incomplete and therefore not parsable, -an error is signalled. -@end deffn - -@deffn procedure eof-object? object -@cindex type predicate, for EOF object -@cindex EOF object, predicate for -@cindex end of file object (see EOF object) -@cindex file, end-of-file marker (see EOF object) -Returns @code{#t} if @var{object} is an end-of-file object; otherwise -returns @code{#f}. -@end deffn - -@deffn procedure read-char-no-hang [input-port] -If @var{input-port} can deliver a character without blocking, this -procedure acts exactly like @code{read-char}, immediately returning that -character. Otherwise, @code{#f} is returned, unless @var{input-port} is -a file port at end of file, in which case an end-of-file object is -returned. In no case will this procedure block waiting for input. -@end deffn - -@deffn procedure read-string char-set [input-port] -@cindex string, input from port -Reads characters from @var{input-port} until it finds a terminating -character that is a member of @var{char-set} (@pxref{Character Sets}) or -encounters end of file. The port is updated to point to the terminating -character, or to end of file if no terminating character was found. -@code{read-string} returns the characters, up to but excluding the -terminating character, as a newly allocated string. - -This procedure ignores the blocking mode of the port, blocking -unconditionally until it sees either a delimiter or eof of file. If end -of file is encountered before any characters are read, an end-of-file -object is returned. - -@findex read-char -On many input ports, this operation is significantly faster than the -following equivalent code using @code{peek-char} and @code{read-char}: - -@example -@group -(define (read-string char-set input-port) - (let ((char (peek-char input-port))) - (if (eof-object? char) - char - (list->string - (let loop ((char char)) - (if (or (eof-object? char) - (char-set-member? char-set char)) - '() - (begin - (read-char input-port) - (cons char - (loop (peek-char input-port)))))))))) -@end group -@end example -@end deffn - -@deffn procedure read-line [input-port] -@code{read-line} reads a single line of text from @var{input-port}, and -returns that line as a newly allocated string. The @code{#\newline} -terminating the line, if any, is discarded and does not appear in the -returned string. - -This procedure ignores the blocking mode of the port, blocking -unconditionally until it has read an entire line. If end of file is -encountered before any characters are read, an end-of-file object is -returned. -@end deffn - -@deffn procedure read-string! string [input-port] -@deffnx procedure read-substring! string start end [input-port] -@code{read-string!} and @code{read-substring!} fill the specified region -of @var{string} with characters read from @var{input-port} until the -region is full or else there are no more characters available from the -port. For @code{read-string!}, the region is all of @var{string}, and -for @code{read-substring!}, the region is that part of @var{string} -specified by @var{start} and @var{end}. - -The returned value is the number of characters filled into the region. -However, there are several interesting cases to consider: - -@itemize @bullet -@item -If @code{read-string!} (@code{read-substring!}) is called when -@var{input-port} is at ``end-of-file'', then the returned value is -@code{0}. Note that ``end-of-file'' can mean a file port that is at the -file's end, a string port that is at the string's end, or any other port -that will never produce more characters. - -@item -If @var{input-port} is an interactive port (e.g.@: a terminal), and one -or more characters are immediately available, the region is filled using -the available characters. The procedure then returns immediately, -without waiting for further characters, even if the number of available -characters is less than the size of the region. The returned value is -the number of characters actually filled in. - -@item -If @var{input-port} is an interactive port and no characters are -immediately available, the result of the operation depends on the -blocking mode of the port. If the port is in non-blocking mode, -@code{read-string!} (@code{read-substring!}) immediately returns the -value @code{#f}. Otherwise, the operation blocks until a character is -available. As soon as at least one character is available, the region -is filled using the available characters. The procedure then returns -immediately, without waiting for further characters, even if the number -of available characters is less than the size of the region. The -returned value is the number of characters actually filled in. -@end itemize - -The importance of @code{read-string!} and @code{read-substring!} are -that they are both flexible and extremely fast, especially for large -amounts of data. -@end deffn - -The following variables may be dynamically bound to change the behavior -of the @code{read} procedure. - -@defvr variable *parser-radix* -This variable defines the radix used by the reader when it parses -numbers. This is similar to passing a radix argument to -@code{string->number}. The value of this variable must be one of -@code{2}, @code{8}, @code{10}, or @code{16}; any other value is ignored, -and the reader uses radix @code{10}. - -Note that much of the number syntax is invalid for radixes other than -@code{10}. The reader detects cases where such invalid syntax is used -and signals an error. However, problems can still occur when -@code{*parser-radix*} is set to @code{16}, because syntax that normally -denotes symbols can now denote numbers (e.g.@: @code{abc}). Because of -this, it is usually undesirable to set this variable to anything other -than the default. - -The default value of this variable is @code{10}. -@end defvr - -@defvr variable *parser-canonicalize-symbols?* -This variable controls how the parser handles case-sensitivity of -symbols. If it is bound to its default value of @code{#t}, symbols read -by the parser are converted to lower case before being interned. -Otherwise, symbols are interned without case conversion. - -In general, it is a bad idea to use this feature, as it doesn't really -make Scheme case-sensitive, and therefore can break features of the -Scheme runtime that depend on case-insensitive symbols. -@end defvr - -@node Output Procedures, Format, Input Procedures, Input/Output -@section Output Procedures -@cindex output procedures - -@cindex buffering, of output -@cindex flushing, of buffered output -Output ports may or may not support @dfn{buffering} of output, in which -output characters are collected together in a buffer and then sent to -the output device all at once. (Most of the output ports implemented by -the runtime system support buffering.) Sending all of the characters in -the buffer to the output device is called @dfn{flushing} the buffer. In -general, output procedures do not flush the buffer of an output port -unless the buffer is full. - -@cindex discretionary flushing, of buffered output -@findex discretionary-flush-output -However, the standard output procedures described in this section -perform what is called @dfn{discretionary} flushing of the buffer. -Discretionary output flushing works as follows. After a procedure -performs its output (writing characters to the output buffer), it checks -to see if the port implements an operation called -@code{discretionary-flush-output}. If so, then that operation is -invoked to flush the buffer. At present, only the console port defines -@code{discretionary-flush-output}; this is used to guarantee that output -to the console appears immediately after it is written, without -requiring calls to @code{flush-output}. - -All optional arguments called @var{output-port}, if not supplied, -default to the current output port. - -@deffn procedure write-char char [output-port] -@cindex character, output to port -Writes @var{char} (the character itself, not a written representation of -the character) to @var{output-port}, performs discretionary output -flushing, and returns an unspecified value. -@end deffn - -@deffn procedure write-string string [output-port] -@cindex string, output to port -Writes @var{string} to @var{output-port}, performs discretionary output -flushing, and returns an unspecified value. This is equivalent to -writing the contents of @var{string}, one character at a time using -@code{write-char}, except that it is usually much faster. -@end deffn - -@deffn procedure write-substring string start end [output-port] -@cindex string, output to port -Writes the substring defined by @var{string}, @var{start}, and @var{end} -to @var{output-port}, performs discretionary output flushing, and -returns an unspecified value. This is equivalent to writing the -contents of the substring, one character at a time using -@code{write-char}, except that it is usually much faster. -@end deffn - -@deffn procedure write object [output-port] -@cindex expression, output to port -Writes a written representation of @var{object} to @var{output-port}, -and returns an unspecified value. If @var{object} has a standard -external representation, then the written representation generated by -@code{write} shall be parsable by @code{read} into an equivalent object. -Thus strings that appear in the written representation are enclosed in -doublequotes, and within those strings backslash and doublequote are -escaped by backslashes. @code{write} performs discretionary output -flushing and returns an unspecified value. -@end deffn - -@deffn procedure display object [output-port] -@cindex external representation, generating -@cindex generating, external representation -Writes a representation of @var{object} to @var{output-port}. Strings -appear in the written representation as if written by -@code{write-string} instead of by @code{write}. Character objects -appear in the representation as if written by @code{write-char} instead -of by @code{write}. @code{display} performs discretionary output -flushing and returns an unspecified value.@footnote{@code{write} is -intended for producing machine-readable output and @code{display} is for -producing human-readable output.} -@end deffn - -@deffn procedure newline [output-port] -@cindex newline character, output to port -Writes an end-of-line to @var{output-port}, performs discretionary -output flushing, and returns an unspecified value. Equivalent to -@code{(write-char #\newline @var{output-port})}. -@end deffn - -@deffn procedure fresh-line [output-port] -Most output ports are able to tell whether or not they are at the -beginning of a line of output. If @var{output-port} is such a port, -this procedure writes an end-of-line to the port only if the port is not -already at the beginning of a line. If @var{output-port} is not such a -port, this procedure is identical to @code{newline}. In either case, -@code{fresh-line} performs discretionary output flushing and returns an -unspecified value. -@end deffn - -@deffn procedure write-line object [output-port] -Like @code{write}, except that it writes an end-of-line to -@var{output-port} after writing @var{object}'s representation. This -procedure performs discretionary output flushing and returns an -unspecified value. -@end deffn - -@deffn procedure flush-output [output-port] -If @var{output-port} is buffered, this causes the contents of its buffer -to be written to the output device. Otherwise it has no effect. -Returns an unspecified value. -@end deffn - -@deffn procedure beep [output-port] -@cindex console, ringing the bell -@cindex ringing the console bell -@cindex bell, ringing on console -Performs a ``beep'' operation on @var{output-port}, performs -discretionary output flushing, and returns an unspecified value. On the -console port, this usually causes the console bell to beep, but more -sophisticated interactive ports may take other actions, such as flashing -the screen. On most output ports, e.g.@: file and string output ports, -this does nothing. -@end deffn - -@deffn procedure clear [output-port] -@cindex console, clearing -@cindex display, clearing -@cindex screen, clearing -@cindex terminal screen, clearing -@cindex clearing the console screen -``Clears the screen'' of @var{output-port}, performs discretionary -output flushing, and returns an unspecified value. On a terminal or -window, this has a well-defined effect. On other output ports, e.g.@: -file and string output ports, this does nothing. -@end deffn - -@deffn procedure pp object [output-port [as-code?]] -@cindex pretty printer -@code{pp} prints @var{object} in a visually appealing and structurally -revealing manner on @var{output-port}. If object is a procedure, -@code{pp} attempts to print the source text. If the optional argument -@var{as-code?} is true, @code{pp} prints lists as Scheme code, providing -appropriate indentation; by default this argument is false. @code{pp} -performs discretionary output flushing and returns an unspecified value. -@end deffn - -The following variables may be dynamically bound to change the behavior -of the @code{write} and @code{display} procedures. - -@defvr variable *unparser-radix* -This variable specifies the default radix used to print numbers. Its -value must be one of the exact integers @code{2}, @code{8}, @code{10}, -or @code{16}; the default is @code{10}. If @code{*unparser-radix*} is -not @code{10}, numbers are prefixed to indicate their radix. -@end defvr - -@defvr variable *unparser-list-breadth-limit* -This variable specifies a limit on the length of the printed -representation of a list or vector; for example, if the limit is -@code{4}, only the first four elements of any list are printed, followed -by ellipses to indicate any additional elements. The value of this -variable must be an exact non-negative integer, or @code{#f} meaning no -limit; the default is @code{#f}. - -@example -@group -(fluid-let ((*unparser-list-breadth-limit* 4)) - (write-to-string '(a b c d))) - @result{} "(a b c d)" -(fluid-let ((*unparser-list-breadth-limit* 4)) - (write-to-string '(a b c d e))) - @result{} "(a b c d ...)" -@end group -@end example -@end defvr - -@defvr variable *unparser-list-depth-limit* -This variable specifies a limit on the nesting of lists and vectors in -the printed representation. If lists (or vectors) are more deeply -nested than the limit, the part of the representation that exceeds the -limit is replaced by ellipses. The value of this variable must be an -exact non-negative integer, or @code{#f} meaning no limit; the default -is @code{#f}. - -@example -@group -(fluid-let ((*unparser-list-depth-limit* 4)) - (write-to-string '((((a))) b c d))) - @result{} "((((a))) b c d)" -(fluid-let ((*unparser-list-depth-limit* 4)) - (write-to-string '(((((a)))) b c d))) - @result{} "((((...))) b c d)" -@end group -@end example -@end defvr - -@defvr variable *unparser-string-length-limit* -This variable specifies a limit on the length of the printed -representation of strings. If a string's length exceeds this limit, the -part of the printed representation for the characters exceeding the -limit is replaced by ellipses. The value of this variable must be an -exact non-negative integer, or @code{#f} meaning no limit; the default -is @code{#f}. - -@example -@group -(fluid-let ((*unparser-string-length-limit* 4)) - (write-to-string "abcd")) - @result{} "\"abcd\"" -(fluid-let ((*unparser-string-length-limit* 4)) - (write-to-string "abcde")) - @result{} "\"abcd...\"" -@end group -@end example -@end defvr - -@defvr variable *unparse-with-maximum-readability?* -This variable, which takes a boolean value, tells the printer to use a -special printed representation for objects that normally print in a form -that cannot be recognized by @code{read}. These objects are printed -using the representation @code{#@@@var{n}}, where @var{n} is the result -of calling @code{hash} on the object to be printed. The reader -recognizes this syntax, calling @code{unhash} on @var{n} to get back the -original object. Note that this printed representation can only be -recognized by the Scheme program in which it was generated, because -these hash numbers are different for each invocation of Scheme. -@end defvr - -@node Format, Custom Output, Output Procedures, Input/Output -@section Format - -@comment **** begin CLTL **** - -The procedure @code{format} is very useful for producing nicely -formatted text, producing good-looking messages, and so on. MIT/GNU -Scheme's implementation of @code{format} is similar to that of Common -Lisp, except that Common Lisp defines many more -directives.@footnote{This description of @code{format} is adapted from -@cite{Common Lisp, The Language}, second edition, section 22.3.3.} - -@cindex run-time-loadable option -@cindex option, run-time-loadable -@code{format} is a run-time-loadable option. To use it, execute - -@example -(load-option 'format) -@end example -@findex load-option - -@noindent -once before calling it. - -@deffn procedure format destination control-string argument @dots{} -@findex write-string -@cindex format directive (defn) -@cindex directive, format (defn) -Writes the characters of @var{control-string} to @var{destination}, -except that a tilde (@code{~}) introduces a @dfn{format directive}. The -character after the tilde, possibly preceded by prefix parameters and -modifiers, specifies what kind of formatting is desired. Most -directives use one or more @var{argument}s to create their output; the -typical directive puts the next @var{argument} into the output, -formatted in some special way. It is an error if no argument remains -for a directive requiring an argument, but it is not an error if one or -more arguments remain unprocessed by a directive. - -The output is sent to @var{destination}. If @var{destination} is -@code{#f}, a string is created that contains the output; this string is -returned as the value of the call to @code{format}. In all other cases -@code{format} returns an unspecified value. If @var{destination} is -@code{#t}, the output is sent to the current output port. Otherwise, -@var{destination} must be an output port, and the output is sent there. - -This procedure performs discretionary output flushing (@pxref{Output -Procedures}). - -A @code{format} directive consists of a tilde (@code{~}), optional -prefix parameters separated by commas, optional colon (@code{:}) and -at-sign (@code{@@}) modifiers, and a single character indicating what -kind of directive this is. The alphabetic case of the directive -character is ignored. The prefix parameters are generally integers, -notated as optionally signed decimal numbers. If both the colon and -at-sign modifiers are given, they may appear in either order. - -@cindex V as format parameter -@cindex # as format parameter -In place of a prefix parameter to a directive, you can put the letter -@samp{V} (or @samp{v}), which takes an @var{argument} for use as a -parameter to the directive. Normally this should be an exact integer. -This feature allows variable-width fields and the like. You can also -use the character @samp{#} in place of a parameter; it represents the -number of arguments remaining to be processed. - -It is an error to give a format directive more parameters than it is -described here as accepting. It is also an error to give colon or -at-sign modifiers to a directive in a combination not specifically -described here as being meaningful. - -@table @code -@item ~A -The next @var{argument}, which may be any object, is printed as if by -@code{display}. @code{~@var{mincol}A} inserts spaces on the right, if -necessary, to make the width at least @var{mincol} columns. The -@code{@@} modifier causes the spaces to be inserted on the left rather -than the right. - -@item ~S -The next @var{argument}, which may be any object, is printed as if by -@code{write}. @code{~@var{mincol}S} inserts spaces on the right, if -necessary, to make the width at least @var{mincol} columns. The -@code{@@} modifier causes the spaces to be inserted on the left rather -than the right. - -@item ~% -This outputs a @code{#\newline} character. @code{~@var{n}%} outputs -@var{n} newlines. No @var{argument} is used. Simply putting a newline -in @var{control-string} would work, but @code{~%} is often used because -it makes the control string look nicer in the middle of a program. - -@item ~~ -This outputs a tilde. @code{~@var{n}~} outputs @var{n} tildes. - -@item ~@var{newline} -Tilde immediately followed by a newline ignores the newline and any -following non-newline whitespace characters. With an @code{@@}, the -newline is left in place, but any following whitespace is ignored. This -directive is typically used when @var{control-string} is too long to fit -nicely into one line of the program: - -@example -@group -(define (type-clash-error procedure arg spec actual) - (format - #t - "~%Procedure ~S~%requires its %A argument ~ - to be of type ~S,~%but it was called with ~ - an argument of type ~S.~%" - procedure arg spec actual)) -@end group -@end example - -@example -@group -(type-clash-error 'vector-ref - "first" - 'integer - 'vector) - -@r{prints} - -Procedure vector-ref -requires its first argument to be of type integer, -but it was called with an argument of type vector. -@end group -@end example - -@noindent -Note that in this example newlines appear in the output only as -specified by the @code{~%} directives; the actual newline characters in -the control string are suppressed because each is preceded by a tilde. -@end table -@end deffn - -@comment **** end CLTL **** - -@node Custom Output, Prompting, Format, Input/Output -@section Custom Output - -MIT/GNU Scheme provides hooks for specifying that certain kinds of objects -have special written representations. There are no restrictions on the -written representations, but only a few kinds of objects may have custom -representation specified for them, specifically: records -(@pxref{Records}), vectors that have special tags in their zero-th -elements (@pxref{Vectors}), and pairs that have special tags in their -car fields (@pxref{Lists}). There is a different procedure for -specifying the written representation of each of these types. - -@deffn procedure set-record-type-unparser-method! record-type unparser-method -Changes the unparser method of the type represented by @var{record-type} -to be @var{unparser-method}, and returns an unspecified value. -Subsequently, when the unparser encounters a record of this type, it -will invoke @var{unparser-method} to generate the written -representation. -@end deffn - -@deffn procedure unparser/set-tagged-vector-method! tag unparser-method -Changes the unparser method of the vector type represented by @var{tag} -to be @var{unparser-method}, and returns an unspecified value. -Subsequently, when the unparser encounters a vector with @var{tag} as -its zero-th element, it will invoke @var{unparser-method} to generate -the written representation. -@end deffn - -@deffn procedure unparser/set-tagged-pair-method! tag unparser-method -Changes the unparser method of the pair type represented by @var{tag} to -be @var{unparser-method}, and returns an unspecified value. -Subsequently, when the unparser encounters a pair with @var{tag} in its -car field, it will invoke @var{unparser-method} to generate the written -representation. -@end deffn - -@cindex unparser method (defn) -@cindex method, unparser (defn) -An @dfn{unparser method} is a procedure that is invoked with two -arguments: an unparser state and an object. An unparser method -generates a written representation for the object, writing it to the -output port specified by the unparser state. The value yielded by an -unparser method is ignored. Note that an unparser state is not an -output port, rather it is an object that contains an output port as one -of its components. Application programs generally do not construct or -examine unparser state objects, but just pass them along. - -There are two ways to create an unparser method (which is then -registered by one of the above procedures). The first, and easiest, is -to use @code{standard-unparser-method}. The second is to define your -own method using the procedure @code{with-current-unparser-state}. We -encourage the use of the first method, as it results in a more uniform -appearance for objects. Many predefined datatypes, for example -procedures and environments, already have this appearance. - -@deffn procedure standard-unparser-method name procedure -Returns a standard unparser method. @var{Name} may be any object, and -is used as the name of the type with which the unparser method is -associated; @var{name} is usually a symbol. @var{Procedure} must be -@code{#f} or a procedure of two arguments. - -@cindex #[ as external representation -If @var{procedure} is @code{#f}, the returned method generates an -external representation of this form: - -@example -#[@var{name} @var{hash}] -@end example - -@noindent -@findex write -@findex write-string -@findex hash -Here @var{name} is the external representation of the argument -@var{name}, as generated by @code{write},@footnote{Except that if the -argument @var{name} is a string, its external representation is -generated by @code{write-string}.} and @var{hash} is the external -representation of an exact non-negative integer unique to the object -being printed (specifically, it is the result of calling @code{hash} on -the object). Subsequently, the expression - -@example -#@@@var{hash} -@end example - -@noindent -is notation for the object. - -If @var{procedure} is supplied, the returned method generates a slightly -different external representation: - -@example -#[@var{name} @var{hash} @var{output}] -@end example - -@noindent -Here @var{name} and @var{hash} are as above, and @var{output} is the -output generated by @var{procedure}. The representation is constructed -in three stages: - -@enumerate -@item -The first part of the format (up to @var{output}) is written to the -output port specified by the unparser state. This is @code{"#["}, -@var{name}, @code{" "}, and @var{hash}. - -@item -@var{Procedure} is invoked on two arguments: the object and an output -port. - -@item -The closing bracket is written to the output port. -@end enumerate -@end deffn - -The following procedure is useful for writing more general kinds of -unparser methods. - -@deffn procedure with-current-unparser-state unparser-state procedure -This procedure calls @var{procedure} with one argument, the output port -from @var{unparser-state}. Additionally, it arranges for the remaining -components of @var{unparser-state} to be given to the printer when they -are needed. The @var{procedure} generates some output by writing to the -output port using the usual output operations, and the value yielded by -@var{procedure} is returned from @code{with-current-unparser-state}. - -The port passed to @var{procedure} should only be used within the -dynamic extent of @var{procedure}. -@end deffn - -@node Prompting, Port Primitives, Custom Output, Input/Output -@section Prompting -@cindex prompting - -This section describes procedures that prompt the user for input. Why -should the programmer use these procedures when it is possible to do -prompting using ordinary input and output procedures? One reason is -that the prompting procedures are more succinct. However, a second and -better reason is that the prompting procedures can be separately -customized for each user interface, providing more natural interaction. -The interfaces for Edwin and for GNU Emacs have already been customized -in this fashion; because Edwin and Emacs are very similar editors, their -customizations provide very similar behavior. - -@findex interaction-i/o-port -Each of these procedure accepts an optional argument called -@var{port}, which if given must be an @acronym{I/O} port. If not -given, this port defaults to the value of -@code{(interaction-i/o-port)}; this is initially the console -@acronym{I/O} port. - -@deffn procedure prompt-for-command-expression prompt [port] -Prompts the user for an expression that is to be executed as a command. -This is the procedure called by the @acronym{REP} loop to read the -user's expressions. - -If @var{prompt} is a string, it is used verbatim as the prompt string. -Otherwise, it must be a pair whose car is @code{standard} and whose cdr -is a string; in this case the prompt string is formed by prepending to -the string the current @acronym{REP} loop ``level number'' and a space. -Also, a space is appended to the string, unless it already ends in a -space or is an empty string. - -The default behavior of this procedure is to print a fresh line, a -newline, and the prompt string; flush the output buffer; then read an -object and return it. - -Under Edwin and Emacs, before the object is read, the interaction buffer -is put into a mode that allows expressions to be edited and submitted -for input using specific editor commands. The first expression that is -submitted is returned as the value of this procedure. -@end deffn - -@deffn procedure prompt-for-command-char prompt [port] -@findex char-graphic? -Prompts the user for a single character that is to be executed as a -command; the returned character is guaranteed to satisfy -@code{char-graphic?}. If at all possible, the character is read from -the user interface using a mode that reads the character as a single -keystroke; in other words, it should not be necessary for the user to -follow the character with a carriage return or something similar. - -@findex debug -@findex where -This is the procedure called by @code{debug} and @code{where} to read -the user's commands. - -If @var{prompt} is a string, it is used verbatim as the prompt string. -Otherwise, it must be a pair whose car is @code{standard} and whose cdr -is a string; in this case the prompt string is formed by prepending to -the string the current @acronym{REP} loop ``level number'' and a space. -Also, a space is appended to the string, unless it already ends in a -space or is an empty string. - -The default behavior of this procedure is to print a fresh line, a -newline, and the prompt string; flush the output buffer; read a -character in raw mode, echo that character, and return it. - -Under Edwin and Emacs, instead of reading a character, the interaction -buffer is put into a mode in which graphic characters submit themselves -as input. After this mode change, the first such character submitted is -returned as the value of this procedure. -@end deffn - -@deffn procedure prompt-for-expression prompt [port] -Prompts the user for an expression. - -The prompt string is formed by appending a colon and a space to -@var{prompt}, unless @var{prompt} already ends in a space or is the null -string. - -The default behavior of this procedure is to print a fresh line, a -newline, and the prompt string; flush the output buffer; then read an -object and return it. - -Under Edwin and Emacs, the expression is read in the minibuffer. -@end deffn - -@deffn procedure prompt-for-evaluated-expression prompt [environment [port]] -Prompts the user for an evaluated expression. Calls -@code{prompt-for-expression} to read an expression, then evaluates the -expression using @var{environment}; if @var{environment} is not given, -the @acronym{REP} loop environment is used. -@end deffn - -@deffn procedure prompt-for-confirmation prompt [port] -Prompts the user for confirmation. The result yielded by this procedure -is a boolean. - -The prompt string is formed by appending the string @code{" (y or n)? "} -to @var{prompt}, unless @var{prompt} already ends in a space or is the -null string. - -The default behavior of this procedure is to print a fresh line, a -newline, and the prompt string; flush the output buffer; then read a -character in raw mode. If the character is @code{#\y}, @code{#\Y}, or -@code{#\space}, the procedure returns @code{#t}; If the character is -@code{#\n}, @code{#\N}, or @code{#\rubout}, the procedure returns -@code{#f}. Otherwise the prompt is repeated. - -Under Edwin or Emacs, the confirmation is read in the minibuffer. -@end deffn - -@node Port Primitives, Parser Buffers, Prompting, Input/Output -@section Port Primitives -@cindex port primitives - -This section describes the low-level operations that can be used to -build and manipulate @acronym{I/O} ports. - -The purpose of these operations is twofold: to allow programmers to -construct new kinds of @acronym{I/O} ports, and to provide faster -@acronym{I/O} operations than those supplied by the standard high -level procedures. The latter is useful because the standard -@acronym{I/O} operations provide defaulting and error checking, and -sometimes other features, which are often unnecessary. This interface -provides the means to bypass such features, thus improving -performance. - -The abstract model of an @acronym{I/O} port, as implemented here, is a -combination of a set of named operations and a state. The state is an -arbitrary object, the meaning of which is determined by the -operations. The operations are defined by a mapping from names to -procedures. - -@cindex port type -The set of named operations is represented by an object called a -@dfn{port type}. A port type is constructed from a set of named -operations, and is subsequently used to construct a port. The port type -completely specifies the behavior of the port. Port types also support -a simple form of inheritance, allowing you to create new ports that are -similar to existing ports. - -The port operations are divided into two classes: - -@table @asis -@item Standard operations -There is a specific set of standard operations for input ports, and a -different set for output ports. Applications can assume that the -standard input operations are implemented for all input ports, and -likewise the standard output operations are implemented for all output -ports. -@cindex standard operations, on port - -@item Custom operations -Some ports support additional operations. For example, ports that -implement output to terminals (or windows) may define an operation named -@code{y-size} that returns the height of the terminal in characters. -Because only some ports will implement these operations, programs that -use custom operations must test each port for their existence, and be -prepared to deal with ports that do not implement them. -@cindex custom operations, on port -@findex y-size -@end table - -@menu -* Port Types:: -* Constructors and Accessors for Ports:: -* Input Port Operations:: -* Output Port Operations:: -* Blocking Mode:: -* Terminal Mode:: -@end menu - -@node Port Types, Constructors and Accessors for Ports, Port Primitives, Port Primitives -@subsection Port Types - -The procedures in this section provide means for constructing port types -with standard and custom operations, and accessing their operations. - -@deffn procedure make-port-type operations port-type -@cindex construction, of port type -Creates and returns a new port type. -@var{Operations} must be a list; each element is a list of two elements, -the name of the operation (a symbol) and the procedure that implements -it. @var{Port-type} is either @code{#f} or a port type; if it is a port -type, any operations implemented by @var{port-type} but not specified in -@var{operations} will be implemented by the resulting port type. - -@var{Operations} need not contain definitions for all of the standard -operations; the procedure will provide defaults for any standard -operations that are not defined. At a minimum, the following operations -must be defined: for input ports, @code{read-char} and @code{peek-char}; -for output ports, either @code{write-char} or @code{write-substring}. -@acronym{I/O} ports must supply the minimum operations for both input and -output. - -If an operation in @var{operations} is defined to be @code{#f}, then the -corresponding operation in @var{port-type} is @emph{not} inherited. - -If @code{read-char} is defined in @var{operations}, then any standard -input operations defined in @var{port-type} are ignored. Likewise, if -@code{write-char} or @code{write-substring} is defined in -@var{operations}, then any standard output operations defined in -@var{port-type} are ignored. This feature allows overriding the -standard operations without having to enumerate them. -@end deffn - -@deffn procedure port-type? object -@deffnx procedure input-port-type? object -@deffnx procedure output-port-type? object -@deffnx procedure i/o-port-type? object -These predicates return @code{#t} if @var{object} is a port type, -input-port type, output-port type, or @acronym{I/O}-port type, -respectively. Otherwise, they return @code{#f}. -@end deffn - -@deffn procedure port-type/operations port-type -Returns a newly allocated list containing all of the operations -implemented by @var{port-type}. Each element of the list is a list of -two elements --- the name and its associated operation. -@end deffn - -@deffn procedure port-type/operation-names port-type -Returns a newly allocated list whose elements are the names of the -operations implemented by @var{port-type}. -@end deffn - -@deffn procedure port-type/operation port-type symbol -Returns the operation named @var{symbol} in @var{port-type}. If -@var{port-type} has no such operation, returns @code{#f}. -@end deffn - -@node Constructors and Accessors for Ports, Input Port Operations, Port Types, Port Primitives -@subsection Constructors and Accessors for Ports - -The procedures in this section provide means for constructing ports, -accessing the type of a port, and manipulating the state of a port. - -@deffn procedure make-port port-type state -Returns a new port with type @var{port-type} and the given -@var{state}. The port will be an input, output, or @acronym{I/O} port -according to @var{port-type}. -@end deffn - -@deffn procedure port/type port -Returns the port type of @var{port}. -@end deffn - -@deffn procedure port/state port -Returns the state component of @var{port}. -@end deffn - -@deffn procedure set-port/state! port object -Changes the state component of @var{port} to be @var{object}. -Returns an unspecified value. -@end deffn - -@deffn procedure port/operation port symbol -Equivalent to - -@example -(port-type/operation (port/type @var{port}) @var{symbol}) -@end example -@end deffn - -@deffn procedure port/operation-names port -Equivalent to - -@example -(port-type/operation-names (port/type @var{port})) -@end example -@end deffn - -@deffn procedure make-eof-object input-port -@cindex EOF object, construction -@cindex construction, of EOF object -@findex eof-object? -Returns an object that satisfies the predicate @code{eof-object?}. This -is sometimes useful when building input ports. -@end deffn - -@node Input Port Operations, Output Port Operations, Constructors and Accessors for Ports, Port Primitives -@subsection Input Port Operations -@cindex input port operations - -This section describes the standard operations on input ports. -Following that, some useful custom operations are described. - -@defop operation {input port} read-char input-port -@cindex character, input from port -Removes the next character available from @var{input-port} and returns -it. If @var{input-port} has no more characters and will never have any -(e.g.@: at the end of an input file), this operation returns an -end-of-file object. If @var{input-port} has no more characters but will -eventually have some more (e.g.@: a terminal where nothing has been -typed recently), and it is in non-blocking mode, @code{#f} is returned; -otherwise the operation hangs until input is available. -@end defop - -@defop operation {input port} peek-char input-port -Reads the next character available from @var{input-port} and returns it. -The character is @emph{not} removed from @var{input-port}, and a -subsequent attempt to read from the port will get that character again. -In other respects this operation behaves like @code{read-char}. -@end defop - -@defop operation {input port} discard-char input-port -Discards the next character available from @var{input-port} and returns -an unspecified value. In other respects this operation behaves like -@code{read-char}. -@end defop - -@defop operation {input port} char-ready? input-port k -@code{char-ready?} returns @code{#t} if at least one character is -available to be read from @var{input-port}. If no characters are -available, the operation waits up to @var{k} milliseconds before -returning @code{#f}, returning immediately if any characters become -available while it is waiting. -@end defop - -@defop operation {input port} read-string input-port char-set -@defopx operation {input port} discard-chars input-port char-set -@cindex string, input from port -These operations are like @code{read-char} and @code{discard-char}, -except that they read or discard multiple characters at once. This can -have a marked performance improvement on buffered input ports. All -characters up to, but excluding, the first character in @var{char-set} -(or end of file) are read from @var{input-port}. @code{read-string} -returns these characters as a newly allocated string, while -@code{discard-chars} discards them and returns an unspecified value. -These operations hang until sufficient input is available, even if -@var{input-port} is in non-blocking mode. If end of file is encountered -before any input characters, @code{read-string} returns an end-of-file -object. -@end defop - -@defop operation {input port} read-substring input-port string start end -Reads characters from @var{input-port} into the substring defined by -@var{string}, @var{start}, and @var{end} until either the substring has -been filled or there are no more characters available. Returns the -number of characters written to the substring. - -If @var{input-port} is an interactive port, and at least one character -is immediately available, the available characters are written to the -substring and this operation returns immediately. If no characters are -available, and @var{input-port} is in blocking mode, the operation -blocks until at least one character is available. Otherwise, the -operation returns @code{#f} immediately. - -This is an extremely fast way to read characters from a port. -@end defop - -@deffn procedure input-port/read-char input-port -@deffnx procedure input-port/peek-char input-port -@deffnx procedure input-port/discard-char input-port -@deffnx procedure input-port/char-ready? input-port k -@deffnx procedure input-port/read-string input-port char-set -@deffnx procedure input-port/discard-chars input-port char-set -@deffnx procedure input-port/read-substring input-port string start end -Each of these procedures invokes the respective operation on -@var{input-port}. For example, the following are equivalent: - -@example -@group -(input-port/read-char @var{input-port}) -((input-port/operation @var{input-port} 'read-char) @var{input-port}) -@end group -@end example -@end deffn - -The following custom operations are implemented for input ports to -files, and will also work with some other kinds of input ports: - -@defop operation {input port} eof? input-port -Returns @code{#t} if @var{input-port} is known to be at end of file, -otherwise it returns @code{#f}. -@end defop - -@defop operation {input port} chars-remaining input-port -Returns an estimate of the number of characters remaining to be read -from @var{input-port}. This is useful only when @var{input-port} is a -file port in binary mode; in other cases, it returns @code{#f}. -@end defop - -@defop operation {input port} buffered-input-chars input-port -Returns the number of unread characters that are stored in -@var{input-port}'s buffer. This will always be less than or equal to -the buffer's size. -@end defop - -@defop operation {input port} input-buffer-size input-port -Returns the maximum number of characters that @var{input-port}'s buffer -can hold. -@end defop - -@defop operation {input port} set-input-buffer-size input-port size -Resizes @var{input-port}'s buffer so that it can hold at most @var{size} -characters. Characters in the buffer are discarded. @var{Size} must be -an exact non-negative integer. -@end defop - -@node Output Port Operations, Blocking Mode, Input Port Operations, Port Primitives -@subsection Output Port Operations -@cindex output port operations - -This section describes the standard operations on output ports. -Following that, some useful custom operations are described. - -@defop operation {output port} write-char output-port char -@cindex character, output to port -Writes @var{char} to @var{output-port} and returns an unspecified value. -@end defop - -@defop operation {output port} write-substring output-port string start end -@cindex substring, output to port -Writes the substring specified by @var{string}, @var{start}, and -@var{end} to @var{output-port} and returns an unspecified value. -Equivalent to writing the characters of the substring, one by one, to -@var{output-port}, but is implemented very efficiently. -@end defop - -@defop operation {output port} fresh-line output-port -Most output ports are able to tell whether or not they are at the -beginning of a line of output. If @var{output-port} is such a port, -end-of-line is written to the port only if the port is not already at -the beginning of a line. If @var{output-port} is not such a port, an -end-of-line is unconditionally written to the port. Returns an -unspecified value. -@end defop - -@defop operation {output port} flush-output output-port -If @var{output-port} is buffered, this causes its buffer to be written -out. Otherwise it has no effect. Returns an unspecified value. -@end defop - -@defop operation {output port} discretionary-flush-output output-port -Normally, this operation does nothing. However, ports that support -discretionary output flushing implement this operation identically to @code{flush-output}. -@end defop - -@deffn procedure output-port/write-char output-port char -@deffnx procedure output-port/write-substring output-port string start end -@deffnx procedure output-port/fresh-line output-port -@deffnx procedure output-port/flush-output output-port -@deffnx procedure output-port/discretionary-flush-output output-port -Each of these procedures invokes the respective operation on -@var{output-port}. For example, the following are equivalent: - -@example -@group -(output-port/write-char @var{output-port} @var{char}) -((output-port/operation @var{output-port} 'write-char) - @var{output-port} @var{char}) -@end group -@end example -@end deffn - -@deffn procedure output-port/write-string output-port string -Writes @var{string} to @var{output-port}. Equivalent to - -@example -@group -(output-port/write-substring @var{output-port} - @var{string} - 0 - (string-length @var{string})) -@end group -@end example -@end deffn - -The following custom operations are generally useful. - -@defop operation {output port} buffered-output-chars output-port -Returns the number of unwritten characters that are stored in -@var{output-port}'s buffer. This will always be less than or equal to -the buffer's size. -@end defop - -@defop operation {output port} output-buffer-size output-port -Returns the maximum number of characters that @var{output-port}'s buffer -can hold. -@end defop - -@defop operation {output port} set-output-buffer-size output-port size -Resizes @var{output-port}'s buffer so that it can hold at most @var{size} -characters. Characters in the buffer are discarded. @var{Size} must be -an exact non-negative integer. -@end defop - -@defop operation {output port} x-size output-port -Returns an exact positive integer that is the width of @var{output-port} -in characters. If @var{output-port} has no natural width, e.g.@: if it is -a file port, @code{#f} is returned. -@end defop - -@defop operation {output port} y-size output-port -Returns an exact positive integer that is the height of -@var{output-port} in characters. If @var{output-port} has no natural -height, e.g.@: if it is a file port, @code{#f} is returned. -@end defop - -@deffn procedure output-port/x-size output-port -This procedure invokes the custom operation whose name is the symbol -@code{x-size}, if it exists. If the @code{x-size} operation is both -defined and returns a value other than @code{#f}, that value is returned -as the result of this procedure. Otherwise, @code{output-port/x-size} -returns a default value (currently @code{80}). - -@code{output-port/x-size} is useful for programs that tailor their -output to the width of the display (a fairly common practice). If the -output device is not a display, such programs normally want some -reasonable default width to work with, and this procedure provides -exactly that. -@end deffn - -@deffn procedure output-port/y-size output-port -This procedure invokes the custom operation whose name is the symbol -@code{y-size}, if it exists. If the @code{y-size} operation is defined, -the value it returns is returned as the result of this procedure; -otherwise, @code{#f} is returned. -@end deffn - -@node Blocking Mode, Terminal Mode, Output Port Operations, Port Primitives -@subsection Blocking Mode - -@cindex blocking mode, of port -An interactive port is always in one of two modes: @dfn{blocking} or -@dfn{non-blocking}. This mode is independent of the terminal mode: -each can be changed independent of the other. Furthermore, if it is -an interactive @acronym{I/O} port, there are separate blocking modes -for input and for output. - -If an input port is in blocking mode, attempting to read from it when no -input is available will cause Scheme to ``block'', i.e.@: suspend -itself, until input is available. If an input port is in non-blocking -mode, attempting to read from it when no input is available will cause -the reading procedure to return immediately, indicating the lack of -input in some way (exactly how this situation is indicated is separately -specified for each procedure or operation). - -An output port in blocking mode will block if the output device is not -ready to accept output. In non-blocking mode it will return immediately -after performing as much output as the device will allow (again, each -procedure or operation reports this situation in its own way). - -Interactive ports are initially in blocking mode; this can be changed at -any time with the procedures defined in this section. - -These procedures represent blocking mode by the symbol @code{blocking}, -and non-blocking mode by the symbol @code{nonblocking}. An argument -called @var{mode} must be one of these symbols. A @var{port} argument -to any of these procedures may be any port, even if that port does not -support blocking mode; in that case, the port is not modified in any -way. - -@deffn procedure port/input-blocking-mode port -Returns the input blocking mode of @var{port}. -@end deffn - -@deffn procedure port/set-input-blocking-mode port mode -Changes the input blocking mode of @var{port} to be @var{mode}. Returns -an unspecified value. -@end deffn - -@deffn procedure port/with-input-blocking-mode port mode thunk -@var{Thunk} must be a procedure of no arguments. -@code{port/with-input-blocking-mode} -binds the input blocking mode of @var{port} to be @var{mode}, executes -@var{thunk}, restores the input blocking mode of @var{port} to what it -was when @code{port/with-input-blocking-mode} was called, and returns -the value that was yielded by @var{thunk}. This binding is performed -by @code{dynamic-wind}, which guarantees that the input blocking mode is -restored if @var{thunk} escapes from its continuation. -@end deffn - -@deffn procedure port/output-blocking-mode port -Returns the output blocking mode of @var{port}. -@end deffn - -@deffn procedure port/set-output-blocking-mode port mode -Changes the output blocking mode of @var{port} to be @var{mode}. -Returns an unspecified value. -@end deffn - -@deffn procedure port/with-output-blocking-mode port mode thunk -@var{Thunk} must be a procedure of no arguments. -@code{port/with-output-blocking-mode} -binds the output blocking mode of @var{port} to be @var{mode}, executes -@var{thunk}, restores the output blocking mode of @var{port} to what it -was when @code{port/with-output-blocking-mode} was called, and returns -the value that was yielded by @var{thunk}. This binding is performed -by @code{dynamic-wind}, which guarantees that the output blocking mode -is restored if @var{thunk} escapes from its continuation. -@end deffn - -@node Terminal Mode, , Blocking Mode, Port Primitives -@subsection Terminal Mode - -@cindex terminal mode, of port -A port that reads from or writes to a terminal has a @dfn{terminal -mode}; this is either @dfn{cooked} or @dfn{raw}. This mode is -independent of the blocking mode: each can be changed independent of -the other. Furthermore, a terminal @acronym{I/O} port has independent -terminal modes both for input and for output. - -@cindex cooked mode, of terminal port -A terminal port in cooked mode provides some standard processing to make -the terminal easy to communicate with. For example, under unix, cooked -mode on input reads from the terminal a line at a time and provides -rubout processing within the line, while cooked mode on output might -translate linefeeds to carriage-return/linefeed pairs. In general, the -precise meaning of cooked mode is operating-system dependent, and -furthermore might be customizable by means of operating system -utilities. The basic idea is that cooked mode does whatever is -necessary to make the terminal handle all of the usual user-interface -conventions for the operating system, while keeping the program's -interaction with the port as normal as possible. - -@cindex raw mode, of terminal port -A terminal port in raw mode disables all of that processing. In raw -mode, characters are directly read from and written to the device -without any translation or interpretation by the operating system. On -input, characters are available as soon as they are typed, and are not -echoed on the terminal by the operating system. In general, programs -that put ports in raw mode have to know the details of interacting with -the terminal. In particular, raw mode is used for writing programs such -as text editors. - -Terminal ports are initially in cooked mode; this can be changed at any -time with the procedures defined in this section. - -These procedures represent cooked mode by the symbol @code{cooked}, and -raw mode by the symbol @code{raw}. Additionally, the value @code{#f} -represents ``no mode''; it is the terminal mode of a port that is not a -terminal. An argument called @var{mode} must be one of these three -values. A @var{port} argument to any of these procedures may be any -port, even if that port does not support terminal mode; in that case, -the port is not modified in any way. - -@deffn procedure port/input-terminal-mode port -Returns the input terminal mode of @var{port}. -@end deffn - -@deffn procedure port/set-input-terminal-mode port mode -Changes the input terminal mode of @var{port} to be @var{mode}. -Returns an unspecified value. -@end deffn - -@deffn procedure port/with-input-terminal-mode port mode thunk -@var{Thunk} must be a procedure of no arguments. -@code{port/with-input-terminal-mode} -binds the input terminal mode of @var{port} to be @var{mode}, executes -@var{thunk}, restores the input terminal mode of @var{port} to what it -was when @code{port/with-input-terminal-mode} was called, and returns -the value that was yielded by @var{thunk}. This binding is performed -by @code{dynamic-wind}, which guarantees that the input terminal mode is -restored if @var{thunk} escapes from its continuation. -@end deffn - -@deffn procedure port/output-terminal-mode port -Returns the output terminal mode of @var{port}. -@end deffn - -@deffn procedure port/set-output-terminal-mode port mode -Changes the output terminal mode of @var{port} to be @var{mode}. -Returns an unspecified value. -@end deffn - -@deffn procedure port/with-output-terminal-mode port mode thunk -@var{Thunk} must be a procedure of no arguments. -@code{port/with-output-terminal-mode} -binds the output terminal mode of @var{port} to be @var{mode}, executes -@var{thunk}, restores the output terminal mode of @var{port} to what it -was when @code{port/with-output-terminal-mode} was called, and returns -the value that was yielded by @var{thunk}. This binding is performed -by @code{dynamic-wind}, which guarantees that the output terminal mode is -restored if @var{thunk} escapes from its continuation. -@end deffn - -@node Parser Buffers, Parser Language, Port Primitives, Input/Output -@section Parser Buffers - -@cindex Parser buffer -The @dfn{parser buffer} mechanism facilitates construction of parsers -for complex grammars. It does this by providing an input stream with -unbounded buffering and backtracking. The amount of buffering is -under program control. The stream can backtrack to any position in -the buffer. - -@cindex Parser-buffer pointer -The mechanism defines two data types: the @dfn{parser buffer} and the -@dfn{parser-buffer pointer}. A parser buffer is like an input port -with buffering and backtracking. A parser-buffer pointer is a pointer -into the stream of characters provided by a parser buffer. - -Note that all of the procedures defined here consider a parser buffer -to contain a stream of 8-bit characters in the @acronym{ISO-8859-1} -character set, except for @code{match-utf8-char-in-alphabet} which -treats it as a stream of Unicode characters encoded as 8-bit bytes in -the @acronym{UTF-8} encoding. - -There are several constructors for parser buffers: - -@deffn procedure input-port->parser-buffer port -Returns a parser buffer that buffers characters read from @var{port}. -@end deffn - -@deffn procedure substring->parser-buffer string start end -Returns a parser buffer that buffers the characters in the argument -substring. This is equivalent to creating a string input port and -calling @code{input-port->parser-buffer}, but it runs faster and uses -less memory. -@end deffn - -@deffn procedure string->parser-buffer string -Like @code{substring->parser-buffer} but buffers the entire string. -@end deffn - -@deffn procedure source->parser-buffer source -Returns a parser buffer that buffers the characters returned by -calling @var{source}. @var{Source} is a procedure of three arguments: -a string, a start index, and an end index (in other words, a substring -specifier). Each time @var{source} is called, it writes some -characters in the substring, and returns the number of characters -written. When there are no more characters available, it returns -zero. It must not return zero in any other circumstance. -@end deffn - -Parser buffers and parser-buffer pointers may be distinguished from -other objects: - -@deffn procedure parser-buffer? object -Returns @code{#t} if @var{object} is a parser buffer, otherwise -returns @code{#f}. -@end deffn - -@deffn procedure parser-buffer-pointer? object -Returns @code{#t} if @var{object} is a parser-buffer pointer, -otherwise returns @code{#f}. -@end deffn - -Characters can be read from a parser buffer much as they can be read -from an input port. The parser buffer maintains an internal pointer -indicating its current position in the input stream. Additionally, -the buffer remembers all characters that were previously read, and can -look at characters arbitrarily far ahead in the stream. It is this -buffering capability that facilitates complex matching and -backtracking. - -@deffn procedure read-parser-buffer-char buffer -Returns the next character in @var{buffer}, advancing the internal -pointer past that character. If there are no more characters -available, returns @code{#f} and leaves the internal pointer -unchanged. -@end deffn - -@deffn procedure peek-parser-buffer-char buffer -Returns the next character in @var{buffer}, or @code{#f} if no -characters are available. Leaves the internal pointer unchanged. -@end deffn - -@deffn procedure parser-buffer-ref buffer index -Returns a character in @var{buffer}. @var{Index} is a non-negative -integer specifying the character to be returned. If @var{index} is -zero, returns the next available character; if it is one, returns the -character after that, and so on. If @var{index} specifies a position -after the last character in @var{buffer}, returns @code{#f}. Leaves -the internal pointer unchanged. -@end deffn - -The internal pointer of a parser buffer can be read or written: - -@deffn procedure get-parser-buffer-pointer buffer -Returns a parser-buffer pointer object corresponding to the internal -pointer of @var{buffer}. -@end deffn - -@deffn procedure set-parser-buffer-pointer! buffer pointer -Sets the internal pointer of @var{buffer} to the position specified by -@var{pointer}. @var{Pointer} must have been returned from a previous -call of @code{get-parser-buffer-pointer} on @var{buffer}. -Additionally, if some of @var{buffer}'s characters have been discarded -by @code{discard-parser-buffer-head!}, @var{pointer} must be outside -the range that was discarded. -@end deffn - -@deffn procedure get-parser-buffer-tail buffer pointer -Returns a newly-allocated string consisting of all of the characters -in @var{buffer} that fall between @var{pointer} and @var{buffer}'s -internal pointer. @var{Pointer} must have been returned from a -previous call of @code{get-parser-buffer-pointer} on @var{buffer}. -Additionally, if some of @var{buffer}'s characters have been discarded -by @code{discard-parser-buffer-head!}, @var{pointer} must be outside -the range that was discarded. -@end deffn - -@deffn procedure discard-parser-buffer-head! buffer -Discards all characters in @var{buffer} that have already been read; -in other words, all characters prior to the internal pointer. After -this operation has completed, it is no longer possible to move the -internal pointer backwards past the current position by calling -@code{set-parser-buffer-pointer!}. -@end deffn - -The next rather large set of procedures does conditional matching -against the contents of a parser buffer. All matching is performed -relative to the buffer's internal pointer, so the first character to -be matched against is the next character that would be returned by -@code{peek-parser-buffer-char}. The returned value is always -@code{#t} for a successful match, and @code{#f} otherwise. For -procedures whose names do not end in @samp{-no-advance}, a successful -match also moves the internal pointer of the buffer forward to the end -of the matched text; otherwise the internal pointer is unchanged. - -@deffn procedure match-parser-buffer-char buffer char -@deffnx procedure match-parser-buffer-char-ci buffer char -@deffnx procedure match-parser-buffer-not-char buffer char -@deffnx procedure match-parser-buffer-not-char-ci buffer char -@deffnx procedure match-parser-buffer-char-no-advance buffer char -@deffnx procedure match-parser-buffer-char-ci-no-advance buffer char -@deffnx procedure match-parser-buffer-not-char-no-advance buffer char -@deffnx procedure match-parser-buffer-not-char-ci-no-advance buffer char -Each of these procedures compares a single character in @var{buffer} -to @var{char}. The basic comparison @code{match-parser-buffer-char} -compares the character to @var{char} using @code{char=?}. The -procedures whose names contain the @samp{-ci} modifier do -case-insensitive comparison (i.e.@: they use @code{char-ci=?}). The -procedures whose names contain the @samp{not-} modifier are successful -if the character @emph{doesn't} match @var{char}. -@end deffn - -@deffn procedure match-parser-buffer-char-in-set buffer char-set -@deffnx procedure match-parser-buffer-char-in-set-no-advance buffer char-set -These procedures compare the next character in @var{buffer} against -@var{char-set} using @code{char-set-member?}. -@end deffn - -@deffn procedure match-parser-buffer-string buffer string -@deffnx procedure match-parser-buffer-string-ci buffer string -@deffnx procedure match-parser-buffer-string-no-advance buffer string -@deffnx procedure match-parser-buffer-string-ci-no-advance buffer string -These procedures match @var{string} against @var{buffer}'s contents. -The @samp{-ci} procedures do case-insensitive matching. -@end deffn - -@deffn procedure match-parser-buffer-substring buffer string start end -@deffnx procedure match-parser-buffer-substring-ci buffer string start end -@deffnx procedure match-parser-buffer-substring-no-advance buffer string start end -@deffnx procedure match-parser-buffer-substring-ci-no-advance buffer string start end -These procedures match the specified substring against @var{buffer}'s -contents. The @samp{-ci} procedures do case-insensitive matching. -@end deffn - -@deffn procedure match-utf8-char-in-alphabet buffer alphabet -This procedure treats @var{buffer}'s contents as @acronym{UTF-8} -encoded Unicode characters and matches the next such character against -@var{alphabet}, which must be a Unicode alphabet (@pxref{Unicode}). -@acronym{UTF-8} represents characters with 1 to 6 bytes, so a -successful match can move the internal pointer forward by as many as 6 -bytes. -@end deffn - -The remaining procedures provide information that can be used to -identify locations in a parser buffer's stream. - -@deffn procedure parser-buffer-position-string pointer -Returns a string describing the location of @var{pointer} in terms of -its character and line indexes. This resulting string is meant to be -presented to an end user in order to direct their attention to a -feature in the input stream. In this string, the indexes are -presented as one-based numbers. - -@var{Pointer} may alternatively be a parser buffer, in which case it -is equivalent to having specified the buffer's internal pointer. -@end deffn - -@deffn procedure parser-buffer-pointer-index pointer -@deffnx procedure parser-buffer-pointer-line pointer -Returns the character or line index, respectively, of @var{pointer}. -Both indexes are zero-based. -@end deffn - -@node Parser Language, XML Parser, Parser Buffers, Input/Output -@section Parser Language - -@cindex Parser language -Although it is possible to write parsers using the parser-buffer -abstraction (@pxref{Parser Buffers}), it is tedious. The problem is -that the abstraction isn't closely matched to the way that people -think about syntactic structures. In this section, we introduce a -higher-level mechanism that greatly simplifies the implementation of a -parser. - -The @dfn{parser language} described here allows the programmer to -write @acronym{BNF}-like specifications that are translated into -efficient Scheme code at compile time. The language is declarative, -but it can be freely mixed with Scheme code; this allows the parsing -of grammars that aren't conveniently described in the language. - -@cindex Backtracking, in parser language -The language also provides backtracking. For example, this expression -matches any sequence of alphanumeric characters followed by a single -alphabetic character: - -@example -@group -(*matcher - (seq (* (char-set char-set:alphanumeric)) - (char-set char-set:alphabetic))) -@end group -@end example - -@noindent -The way that this works is that the matcher matches alphanumeric -characters in the input stream until it finds a non-alphanumeric -character. It then tries to match an alphabetic character, which of -course fails. At this point, if it matched at least one alphanumeric -character, it @emph{backtracks}: the last matched alphanumeric is -``unmatched'', and it again attempts to match an alphabetic -character. The backtracking can be arbitrarily deep; the matcher will -continue to back up until it finds a way to match the remainder of the -expression. - -So far, this sounds a lot like regular-expression matching -(@pxref{Regular Expressions}). However, there are some important -differences. - -@itemize @bullet -@item -The parser language uses a Scheme-like syntax that is easier to read -and write than regular-expression notation. - -@item -The language provides macros so that common syntactic constructs can -be abstracted. - -@item -The language mixes easily with Scheme code, allowing the full power of -Scheme to be applied to program around limitations in the parser -language. - -@item -The language provides expressive facilities for converting syntax into -parsed structure. It also makes it easy to convert parsed strings -into meaningful objects (e.g.@: numbers). - -@item -The language is compiled into machine language; regular expressions -are usually interpreted. -@end itemize - -Here is an example that shows off several of the features of the -parser language. The example is a parser for @acronym{XML} start -tags: - -@anchor{with-pointer example} -@example -@group -(*parser - (with-pointer p - (seq "<" - parse-name - parse-attribute-list - (alt (match ">") - (match "/>") - (sexp - (lambda (b) - (error - (string-append - "Unterminated start tag at " - (parser-buffer-position-string p))))))))) -@end group -@end example - -@noindent -This shows that the basic description of a start tag is very similar -to its @acronym{BNF}. Non-terminal symbols @code{parse-name} and -@code{parse-attribute-list} do most of the work, and the noise strings -@code{"<"} and @code{">"} are the syntactic markers delimiting the -form. There are two alternate endings for start tags, and if the -parser doesn't find either of the endings, the Scheme code (wrapped in -@code{sexp}) is run to signal an error. The error procedure -@code{perror} takes a pointer @code{p}, which it uses to indicate the -position in the input stream at which the error occurred. In this -case, that is the beginning of the start tag, i.e.@: the position of -the leading @code{"<"} marker. - -This example still looks pretty complicated, mostly due to the -error-signalling code. In practice, this is abstracted into a macro, -after which the expression is quite succinct: - -@example -@group -(*parser - (bracket "start tag" - (seq (noise (string "<")) parse-name) - (match (alt (string ">") (string "/>"))) - parse-attribute-list)) -@end group -@end example - -@noindent -The @code{bracket} macro captures the pattern of a bracketed item, and -hides much of the detail. - -The parser language actually consists of two languages: one for -defining matchers, and one for defining parsers. The languages are -intentionally very similar, and are meant to be used together. Each -sub-language is described below in its own section. - -@cindex run-time-loadable option -@cindex option, run-time-loadable -The parser language is a run-time-loadable option; to use it, execute - -@example -(load-option '*parser) -@end example -@findex load-option - -@noindent -once before compiling any code that uses the language. - -@menu -* *Matcher:: -* *Parser:: -* Parser-language Macros:: -@end menu - -@node *Matcher, *Parser, Parser Language, Parser Language -@subsection *Matcher - -@cindex Matcher language -@cindex Matcher procedure -The @dfn{matcher language} is a declarative language for specifying a -@dfn{matcher procedure}. A matcher procedure is a procedure that -accepts a single parser-buffer argument and returns a boolean value -indicating whether the match it performs was successful. If the match -succeeds, the internal pointer of the parser buffer is moved forward -over the matched text. If the match fails, the internal pointer is -unchanged. - -For example, here is a matcher procedure that matches the character -@samp{a}: - -@example -(lambda (b) (match-parser-buffer-char b #\a)) -@end example - -@noindent -Here is another example that matches two given characters, @var{c1} -and @var{c2}, in sequence: - -@example -@group -(lambda (b) - (let ((p (get-parser-buffer-pointer b))) - (if (match-parser-buffer-char b @var{c1}) - (if (match-parser-buffer-char b @var{c2}) - #t - (begin - (set-parser-buffer-pointer! b p) - #f)) - #f))) -@end group -@end example - -@noindent -This is code is clear, but has lots of details that get in the way of -understanding what it is doing. Here is the same example in the -matcher language: - -@example -(*matcher (seq (char @var{c1}) (char @var{c2}))) -@end example - -@noindent -This is much simpler and more intuitive. And it generates virtually -the same code: - -@example -@group -(pp (*matcher (seq (char c1) (char c2)))) -@print{} (lambda (#[b1]) -@print{} (let ((#[p1] (get-parser-buffer-pointer #[b1]))) -@print{} (and (match-parser-buffer-char #[b1] c1) -@print{} (if (match-parser-buffer-char #[b1] c2) -@print{} #t -@print{} (begin -@print{} (set-parser-buffer-pointer! #[b1] #[p1]) -@print{} #f))))) -@end group -@end example - -Now that we have seen an example of the language, it's time to look at -the detail. The @code{*matcher} special form is the interface between -the matcher language and Scheme. - -@deffn {special form} *matcher mexp -The operand @var{mexp} is an expression in the matcher language. The -@code{*matcher} expression expands into Scheme code that implements a -matcher procedure. -@end deffn - -Here are the predefined matcher expressions. New matcher expressions -can be defined using the macro facility (@pxref{Parser-language -Macros}). We will start with the primitive expressions. - -@deffn {matcher expression} char expression -@deffnx {matcher expression} char-ci expression -@deffnx {matcher expression} not-char expression -@deffnx {matcher expression} not-char-ci expression -These expressions match a given character. In each case, the -@var{expression} operand is a Scheme expression that must evaluate to -a character at run time. The @samp{-ci} expressions do -case-insensitive matching. The @samp{not-} expressions match any -character other than the given one. -@end deffn - -@deffn {matcher expression} string expression -@deffnx {matcher expression} string-ci expression -These expressions match a given string. The @var{expression} operand -is a Scheme expression that must evaluate to a string at run time. -The @code{string-ci} expression does case-insensitive matching. -@end deffn - -@deffn {matcher expression} char-set expression -These expressions match a single character that is a member of a given -character set. The @var{expression} operand is a Scheme expression -that must evaluate to a character set at run time. -@end deffn - -@deffn {matcher expression} alphabet expression -These expressions match a single character that is a member of a given -Unicode alphabet (@pxref{Unicode}). The @var{expression} operand is a -Scheme expression that must evaluate to an alphabet at run time. -@end deffn - -@deffn {matcher expression} end-of-input -The @code{end-of-input} expression is successful only when there are -no more characters available to be matched. -@end deffn - -@deffn {matcher expression} discard-matched -The @code{discard-matched} expression always successfully matches the -null string. However, it isn't meant to be used as a matching -expression; it is used for its effect. @code{discard-matched} causes -all of the buffered text prior to this point to be discarded (i.e.@: -it calls @code{discard-parser-buffer-head!} on the parser buffer). - -Note that @code{discard-matched} may not be used in certain places in -a matcher expression. The reason for this is that it deliberately -discards information needed for backtracking, so it may not be used in -a place where subsequent backtracking will need to back over it. As a -rule of thumb, use @code{discard-matched} only in the last operand of -a @code{seq} or @code{alt} expression (including any @code{seq} or -@code{alt} expressions in which it is indirectly contained). -@end deffn - -In addition to the above primitive expressions, there are two -convenient abbreviations. A character literal (e.g.@: @samp{#\A}) is -a legal primitive expression, and is equivalent to a @code{char} -expression with that literal as its operand (e.g.@: @samp{(char -#\A)}). Likewise, a string literal is equivalent to a @code{string} -expression (e.g.@: @samp{(string "abc")}). - -Next there are several combinator expressions. These closely -correspond to similar combinators in regular expressions. Parameters -named @var{mexp} are arbitrary expressions in the matcher language. - -@deffn {matcher expression} seq mexp @dots{} -This matches each @var{mexp} operand in sequence. For example, - -@example -@group -(seq (char-set char-set:alphabetic) - (char-set char-set:numeric)) -@end group -@end example - -@noindent -matches an alphabetic character followed by a numeric character, such -as @samp{H4}. - -Note that if there are no @var{mexp} operands, the @code{seq} -expression successfully matches the null string. -@end deffn - -@deffn {matcher expression} alt mexp @dots{} -This attempts to match each @var{mexp} operand in order from left to -right. The first one that successfully matches becomes the match for -the entire @code{alt} expression. - -The @code{alt} expression participates in backtracking. If one of the -@var{mexp} operands matches, but the overall match in which this -expression is embedded fails, the backtracking mechanism will cause -the @code{alt} expression to try the remaining @var{mexp} operands. -For example, if the expression - -@example -(seq (alt "ab" "a") "b") -@end example - -@noindent -is matched against the text @samp{abc}, the @code{alt} expression will -initially match its first operand. But it will then fail to match the -second operand of the @code{seq} expression. This will cause the -@code{alt} to be restarted, at which time it will match @samp{a}, and -the overall match will succeed. - -Note that if there are no @var{mexp} operands, the @code{alt} match -will always fail. -@end deffn - -@deffn {matcher expression} * mexp -This matches zero or more occurrences of the @var{mexp} operand. -(Consequently this match always succeeds.) - -The @code{*} expression participates in backtracking; if it matches -@var{N} occurrences of @var{mexp}, but the overall match fails, it -will backtrack to @var{N-1} occurrences and continue. If the overall -match continues to fail, the @code{*} expression will continue to -backtrack until there are no occurrences left. -@end deffn - -@deffn {matcher expression} + mexp -This matches one or more occurrences of the @var{mexp} operand. It is -equivalent to - -@example -(seq @var{mexp} (* @var{mexp})) -@end example -@end deffn - -@deffn {matcher expression} ? mexp -This matches zero or one occurrences of the @var{mexp} operand. It is -equivalent to - -@example -(alt @var{mexp} (seq)) -@end example -@end deffn - -@deffn {matcher expression} sexp expression -The @code{sexp} expression allows arbitrary Scheme code to be embedded -inside a matcher. The @var{expression} operand must evaluate to a -matcher procedure at run time; the procedure is called to match the -parser buffer. For example, - -@example -@group -(*matcher - (seq "a" - (sexp parse-foo) - "b")) -@end group -@end example - -@noindent -expands to - -@example -@group -(lambda (#[b1]) - (let ((#[p1] (get-parser-buffer-pointer #[b1]))) - (and (match-parser-buffer-char #[b1] #\a) - (if (parse-foo #[b1]) - (if (match-parser-buffer-char #[b1] #\b) - #t - (begin - (set-parser-buffer-pointer! #[b1] #[p1]) - #f)) - (begin - (set-parser-buffer-pointer! #[b1] #[p1]) - #f))))) -@end group -@end example - -The case in which @var{expression} is a symbol is so common that it -has an abbreviation: @samp{(sexp @var{symbol})} may be abbreviated as -just @var{symbol}. -@end deffn - -@deffn {matcher expression} with-pointer identifier mexp -The @code{with-pointer} expression fetches the parser buffer's -internal pointer (using @code{get-parser-buffer-pointer}), binds it to -@var{identifier}, and then matches the pattern specified by -@var{mexp}. @var{Identifier} must be a symbol. - -This is meant to be used on conjunction with @code{sexp}, as a way to -capture a pointer to a part of the input stream that is outside the -@code{sexp} expression. An example of the use of @code{with-pointer} -appears above (@pxref{with-pointer example}). -@end deffn - -@node *Parser, Parser-language Macros, *Matcher, Parser Language -@subsection *Parser - -@cindex Parser language -@cindex Parser procedure -The @dfn{parser language} is a declarative language for specifying a -@dfn{parser procedure}. A parser procedure is a procedure that -accepts a single parser-buffer argument and parses some of the input -from the buffer. If the parse is successful, the procedure returns a -vector of objects that are the result of the parse, and the internal -pointer of the parser buffer is advanced past the input that was -parsed. If the parse fails, the procedure returns @code{#f} and the -internal pointer is unchanged. This interface is much like that of a -matcher procedure, except that on success the parser procedure returns -a vector of values rather than @code{#t}. - -The @code{*parser} special form is the interface between the parser -language and Scheme. - -@deffn {special form} *parser pexp -The operand @var{pexp} is an expression in the parser language. The -@code{*parser} expression expands into Scheme code that implements a -parser procedure. -@end deffn - -There are several primitive expressions in the parser language. The -first two provide a bridge to the matcher language (@pxref{*Matcher}): - -@deffn {parser expression} match mexp -The @code{match} expression performs a match on the parser buffer. -The match to be performed is specified by @var{mexp}, which is an -expression in the matcher language. If the match is successful, the -result of the @code{match} expression is a vector of one element: a -string containing that text. -@end deffn - -@deffn {parser expression} noise mexp -The @code{noise} expression performs a match on the parser buffer. -The match to be performed is specified by @var{mexp}, which is an -expression in the matcher language. If the match is successful, the -result of the @code{noise} expression is a vector of zero elements. -(In other words, the text is matched and then thrown away.) - -The @var{mexp} operand is often a known character or string, so in the -case that @var{mexp} is a character or string literal, the -@code{noise} expression can be abbreviated as the literal. In other -words, @samp{(noise "foo")} can be abbreviated just @samp{"foo"}. -@end deffn - -@deffn {parser expression} values expression @dots{} -Sometimes it is useful to be able to insert arbitrary values into the -parser result. The @code{values} expression supports this. The -@var{expression} arguments are arbitrary Scheme expressions that are -evaluated at run time and returned in a vector. The @code{values} -expression always succeeds and never modifies the internal pointer of -the parser buffer. -@end deffn - -@deffn {parser expression} discard-matched -The @code{discard-matched} expression always succeeds, returning a -vector of zero elements. In all other respects it is identical to the -@code{discard-matched} expression in the matcher language. -@end deffn - -Next there are several combinator expressions. Parameters named -@var{pexp} are arbitrary expressions in the parser language. The -first few combinators are direct equivalents of those in the matcher -language. - -@deffn {parser expression} seq pexp @dots{} -The @code{seq} expression parses each of the @var{pexp} operands in -order. If all of the @var{pexp} operands successfully match, the -result is the concatenation of their values (by @code{vector-append}). -@end deffn - -@deffn {parser expression} alt pexp @dots{} -The @code{alt} expression attempts to parse each @var{pexp} operand in -order from left to right. The first one that successfully parses -produces the result for the entire @code{alt} expression. - -Like the @code{alt} expression in the matcher language, this -expression participates in backtracking. -@end deffn - -@deffn {parser expression} * pexp -The @code{*} expression parses zero or more occurrences of @var{pexp}. -The results of the parsed occurrences are concatenated together (by -@code{vector-append}) to produce the expression's result. - -Like the @code{*} expression in the matcher language, this expression -participates in backtracking. -@end deffn - -@deffn {parser expression} + pexp -The @code{*} expression parses one or more occurrences of @var{pexp}. -It is equivalent to - -@example -(seq @var{pexp} (* @var{pexp})) -@end example -@end deffn - -@deffn {parser expression} ? pexp -The @code{*} expression parses zero or one occurrences of @var{pexp}. -It is equivalent to - -@example -(alt @var{pexp} (seq)) -@end example -@end deffn - -The next three expressions do not have equivalents in the matcher -language. Each accepts a single @var{pexp} argument, which is parsed -in the usual way. These expressions perform transformations on the -returned values of a successful match. - -@deffn {parser expression} transform expression pexp -The @code{transform} expression performs an arbitrary transformation -of the values returned by parsing @var{pexp}. @var{Expression} is a -Scheme expression that must evaluate to a procedure at run time. If -@var{pexp} is successfully parsed, the procedure is called with the -vector of values as its argument, and must return a vector or -@code{#f}. If it returns a vector, the parse is successful, and those -are the resulting values. If it returns @code{#f}, the parse fails -and the internal pointer of the parser buffer is returned to what it -was before @var{pexp} was parsed. - -For example: - -@example -(transform (lambda (v) (if (= 0 (vector-length v)) #f v)) @dots{}) -@end example -@end deffn - -@deffn {parser expression} encapsulate expression pexp -The @code{encapsulate} expression transforms the values returned by -parsing @var{pexp} into a single value. @var{Expression} is a Scheme -expression that must evaluate to a procedure at run time. If -@var{pexp} is successfully parsed, the procedure is called with the -vector of values as its argument, and may return any Scheme object. -The result of the @code{encapsulate} expression is a vector of length -one containing that object. (And consequently @code{encapsulate} -doesn't change the success or failure of @var{pexp}, only its value.) - -For example: - -@example -(encapsulate vector->list @dots{}) -@end example -@end deffn - -@deffn {parser expression} map expression pexp -The @code{map} expression performs a per-element transform on the -values returned by parsing @var{pexp}. @var{Expression} is a Scheme -expression that must evaluate to a procedure at run time. If -@var{pexp} is successfully parsed, the procedure is mapped (by -@code{vector-map}) over the values returned from the parse. The -mapped values are returned as the result of the @code{map} expression. -(And consequently @code{map} doesn't change the success or failure of -@var{pexp}, nor the number of values returned.) - -For example: - -@example -(map string->symbol @dots{}) -@end example -@end deffn - -Finally, as in the matcher language, we have @code{sexp} and -@code{with-pointer} to support embedding Scheme code in the parser. - -@deffn {parser expression} sexp expression -The @code{sexp} expression allows arbitrary Scheme code to be embedded -inside a parser. The @var{expression} operand must evaluate to a -parser procedure at run time; the procedure is called to parse the -parser buffer. This is the parser-language equivalent of the -@code{sexp} expression in the matcher language. - -The case in which @var{expression} is a symbol is so common that it -has an abbreviation: @samp{(sexp @var{symbol})} may be abbreviated as -just @var{symbol}. -@end deffn - -@deffn {parser expression} with-pointer identifier pexp -The @code{with-pointer} expression fetches the parser buffer's -internal pointer (using @code{get-parser-buffer-pointer}), binds it to -@var{identifier}, and then parses the pattern specified by @var{pexp}. -@var{Identifier} must be a symbol. This is the parser-language -equivalent of the @code{with-pointer} expression in the matcher -language. -@end deffn - -@node Parser-language Macros, , *Parser, Parser Language -@subsection Parser-language Macros - -The parser and matcher languages provide a macro facility so that -common patterns can be abstracted. The macro facility allows new -expression types to be independently defined in the two languages. -The macros are defined in heirarchically organized tables, so that -different applications can have private macro bindings. - -@deffn {special form} define-*matcher-macro formals expression -@deffnx {special form} define-*parser-macro formals expression -These special forms are used to define macros in the matcher and -parser language, respectively. @var{Formals} is like the -@var{formals} list of a @code{define} special form, and -@var{expression} is a Scheme expression. - -If @var{formals} is a list (or improper list) of symbols, the first -symbol in the list is the name of the macro, and the remaining symbols -are interpreted as the @var{formals} of a lambda expression. A lambda -expression is formed by combining the latter @var{formals} with the -@var{expression}, and this lambda expression, when evaluated, becomes -the @dfn{expander}. The defined macro accepts the same number of -operands as the expander. A macro instance is expanded by applying -the expander to the list of operands; the result of the application is -interpreted as a replacement expression for the macro instance. - -If @var{formals} is a symbol, it is the name of the macro. In this -case, the expander is a procedure of no arguments whose body is -@var{expression}. When the @var{formals} symbol appears by itself as -an expression in the language, the expander is called with no -arguments, and the result is interpreted as a replacement expression -for the symbol. -@end deffn - -@deffn procedure define-*matcher-expander identifier expander -@deffnx procedure define-*parser-expander identifier expander -These procedures provide a procedural interface to the -macro-definition mechanism. @var{Identifier} must be a symbol, and -@var{expander} must be an expander procedure, as defined above. -Instances of the @code{define-*matcher-macro} and -@code{define-*parser-macro} special forms expand into calls to these -procedures. -@end deffn - -The remaining procedures define the interface to the parser-macros -table abstraction. Each parser-macro table has a separate binding -space for macros in the matcher and parser languages. However, the -table inherits bindings from one specified table; it's not possible to -inherit matcher-language bindings from one table and parser-language -bindings from another. - -@deffn procedure make-parser-macros parent-table -Create and return a new parser-macro table that inherits from -@var{parent-table}. @var{Parent-table} must be either a parser-macro -table, or @code{#f}; usually it is specified as the value of -@code{global-parser-macros}. -@end deffn - -@deffn procedure parser-macros? object -This is a predicate for parser-macro tables. -@end deffn - -@deffn procedure global-parser-macros -Return the global parser-macro table. This table is predefined and -contains all of the bindings documented here. -@end deffn - -There is a ``current'' table at all times, and macro definitions are -always placed in this table. By default, the current table is the -global macro table, but the following procedures allow this to be -changed. - -@deffn procedure current-parser-macros -Return the current parser-macro table. -@end deffn - -@deffn procedure set-current-parser-macros! table -Change the current parser-macro table to @var{table}, which must -satisfy @code{parser-macros?}. -@end deffn - -@deffn procedure with-current-parser-macros table thunk -Bind the current parser-macro table to @var{table}, call @var{thunk} -with no arguments, then restore the original table binding. The value -returned by @var{thunk} is the returned as the value of this -procedure. @var{Table} must satisfy @code{parser-macros?}, and -@var{thunk} must be a procedure of no arguments. -@end deffn - -@node XML Parser, , Parser Language, Input/Output -@section XML Parser - -@cindex XML parser -@cindex parser, XML -MIT/GNU Scheme provides a simple non-validating @acronym{XML} parser. -This parser is mostly conformant, with the exception that it doesn't -support @acronym{UTF-16}. The parser also does not support external -document type declarations (@acronym{DTD}s). The output of the parser -is a record tree that closely reflects the structure of the -@acronym{XML} document. - -@cindex XML output -@cindex output, XML -There is also an output mechanism that writes an @acronym{XML} record -tree to a port. There is no guarantee that parsing an @acronym{XML} -document and writing it back out will make a verbatim copy of the -document. The output will be semantically identical but may have -small syntactic differences. For example, comments are discarded by -the parser, and entities are substituted during the parsing process. - -The purpose of the @acronym{XML} support is to provide a mechanism for -reading and writing simple @acronym{XML} documents. In the future -this support may be further developed to support a standard interface -such as @acronym{DOM} or @acronym{SAX}. - -@cindex run-time-loadable option -@cindex option, run-time-loadable -The @acronym{XML} support is a run-time-loadable option; to use it, -execute - -@example -(load-option 'xml) -@end example -@findex load-option - -@noindent -once before compiling any code that uses it. - -The @acronym{XML} interface consists of an input procedure, an output -procedure, and a set of record types. - -@deffn procedure parse-xml-document buffer -This procedure parses an @acronym{XML} input stream and returns a -newly-allocated @acronym{XML} record tree. The @var{buffer} argument -must be a parser buffer (@pxref{Parser Buffers}). Most errors in the -input stream are detected and signalled, with information identifying -the location of the error where possible. Note that the input stream -is assumed to be @acronym{UTF-8}. -@end deffn - -@deffn procedure write-xml xml-document port -This procedure writes an @acronym{XML} record tree to @var{port}. The -@var{xml-document} argument must be a record of type -@code{xml-document}, which is the root record of an @acronym{XML} -record tree. The output is encoded in @acronym{UTF-8}. -@end deffn - -@cindex XML names -@cindex names, XML -@acronym{XML} names are represented in memory as symbols. All symbols -appearing within @acronym{XML} records are @acronym{XML} names. -Because @acronym{XML} names are case sensitive, there is a procedure -to intern these symbols: - -@deffn procedure xml-intern string -@cindex XML name -Returns the @acronym{XML} name called @var{string}. @acronym{XML} -names are represented as symbols, but unlike ordinary Scheme symbols, -they are case sensitive. The following is true for any two strings -@var{string1} and @var{string2}: - -@example -@group -(let ((name1 (xml-intern @var{string1})) - (name2 (xml-intern @var{string2}))) - (if (string=? @var{string1} @var{string2}) - (eq? name1 name2) - (not (eq? name1 name2)))) -@end group -@end example -@end deffn - -The output from the @acronym{XML} parser and the input to the -@acronym{XML} output procedure is a complex data structure composed of -a heirarchy of typed components. Each component is a record whose -fields correspond to parts of the @acronym{XML} structure that the -record represents. There are no special operations on these records; -each is a tuple with named subparts. The root record type is -@code{xml-document}, which represents a complete @acronym{XML} -document. - -Each record type @var{type} has the following associated bindings: - -@table @code -@item <@var{type}> -is a variable bound to the record-type descriptor for @var{type}. The -record-type descriptor may be used as a specializer in @acronym{SOS} -method definitions, which greatly simplifies code to dispatch on these -types. - -@item @var{type}? -is a predicate for records of type @var{type}. It accepts one -argument, which can be any object, and returns @code{#t} if the object -is a record of this type, or @code{#f} otherwise. - -@item make-@var{type} -is a constructor for records of type @var{type}. It accepts one -argument for each field of @var{type}, in the same order that they are -written in the type description, and returns a newly-allocated record -of that type. - -@item @var{type}-@var{field} -is an accessor procedure for the field @var{field} in records of type -@var{type}. It accepts one argument, which must be a record of that -type, and returns the contents of the corresponding field in the -record. - -@item set-@var{type}-@var{field}! -is a modifier procedure for the field @var{field} in records of type -@var{type}. It accepts two arguments: the first must be a record of -that type, and the second is a new value for the corresponding field. -The record's field is modified to have the new value. -@end table - -@deftp {record type} xml-document declaration misc-1 dtd misc-2 root misc-3 -@vindex -@findex xml-document? -@findex make-xml-document -@findex xml-document-declaration -@findex xml-document-misc-1 -@findex xml-document-dtd -@findex xml-document-misc-2 -@findex xml-document-root -@findex xml-document-misc-3 -@findex set-xml-document-declaration! -@findex set-xml-document-misc-1! -@findex set-xml-document-dtd! -@findex set-xml-document-misc-2! -@findex set-xml-document-root! -@findex set-xml-document-misc-3! -The @code{xml-document} record is the top-level record representing a -complete @acronym{XML} document. @var{Declaration} is either an -@code{xml-declaration} object or @code{#f}. @var{Dtd} is either an -@code{xml-dtd} object or @code{#f}. @var{Root} is an @code{xml-element} -object. @var{Misc-1}, @var{misc-2}, and @var{misc-3} are lists of -miscellaneous items; a miscellaneous item is either an -@code{xml-comment} object, an @code{xml-processing-instructions} object, -or a string of whitespace. -@end deftp - -@deftp {record type} xml-declaration version encoding standalone -@vindex -@findex xml-declaration? -@findex make-xml-declaration -@findex xml-declaration-version -@findex xml-declaration-encoding -@findex xml-declaration-standalone -@findex set-xml-declaration-version! -@findex set-xml-declaration-encoding! -@findex set-xml-declaration-standalone! -The @code{xml-declaration} record represents the @samp{} declaration that optionally appears at the beginning of an -@acronym{XML} document. @var{Version} is a version string, typically -@code{"1.0"}. @var{Encoding} is either an encoding string or -@code{#f}. @var{Standalone} is either @code{"yes"}, @code{"no"}, or -@code{#f}. -@end deftp - -@deftp {record type} xml-element name attributes contents -@vindex -@findex xml-element? -@findex make-xml-element -@findex xml-element-name -@findex xml-element-attributes -@findex xml-element-contents -@findex set-xml-element-name! -@findex set-xml-element-attributes! -@findex set-xml-element-contents! -The @code{xml-element} record represents general @acronym{XML} -elements; the bulk of a typical @acronym{XML} document consists of -these elements. @var{Name} is the element name (a symbol). -@var{Attributes} is a list of attributes; each attribute is a pair -whose @sc{car} is the attribute name (a symbol), and whose @sc{cdr} is -the attribute value (a string). @var{Contents} is a list of the -contents of the element. Each element of this list is either a -string, an @code{xml-element} record, an -@code{xml-processing-instructions} record, or an -@code{xml-uninterpreted} record. -@end deftp - -@deftp {record type} xml-processing-instructions name text -@vindex -@findex xml-processing-instructions? -@findex make-xml-processing-instructions -@findex xml-processing-instructions-name -@findex xml-processing-instructions-text -@findex set-xml-processing-instructions-name! -@findex set-xml-processing-instructions-text! -The @code{xml-processing-instructions} record represents processing -instructions, which have the form @samp{}. -These instructions are intended to contain non-@acronym{XML} data that -will be processed by another interpreter; for example they might -contain @acronym{PHP} programs. The @var{name} field is the processor -name (a symbol), and the @var{text} field is the body of the -instructions (a string). -@end deftp - -@deftp {record type} xml-uninterpreted text -@vindex -@findex xml-uninterpreted? -@findex make-xml-uninterpreted -@findex xml-uninterpreted-text -@findex set-xml-uninterpreted-text! -Some documents contain entity references that can't be expanded by the -parser, perhaps because the document requires an external -@acronym{DTD}. Such references are left uninterpreted in the output -by wrapping them in @code{xml-uninterpreted} records. In some -situations, for example when they are embedded in attribute values, -the surrounding text is also included in the @code{xml-uninterpreted} -record. The @var{text} field contains the uninterpreted @acronym{XML} -text (a string). -@end deftp - -@deftp {record type} xml-dtd root external internal -@vindex -@findex xml-dtd? -@findex make-xml-dtd -@findex xml-dtd-root -@findex xml-dtd-external -@findex xml-dtd-internal -@findex set-xml-dtd-root! -@findex set-xml-dtd-external! -@findex set-xml-dtd-internal! -The @code{xml-dtd} record represents a document type declaration. The -@var{root} field is an @acronym{XML} name for the root element of the -document. @var{External} is either an @code{xml-external-id} record -or @code{#f}. @var{Internal} is a list of @acronym{DTD} element -records (e.g.@: @code{xml-!element}, @code{xml-!attlist}, etc.). -@end deftp - -The remaining record types are valid only within a @acronym{DTD}. - -@deftp {record type} xml-!element name content-type -@vindex -@findex xml-!element? -@findex make-xml-!element -@findex xml-!element-name -@findex xml-!element-content-type -@findex set-xml-!element-name! -@findex set-xml-!element-content-type! -The @code{xml-!element} record represents an element-type -declaration. @var{Name} is the @acronym{XML} name of the type being -declared (a symbol). @var{Content-type} describes the type and can -have several different values, as follows: - -@itemize @bullet -@item -The @acronym{XML} names @samp{EMPTY} and @samp{ANY} correspond to the -@acronym{XML} keywords of the same name. - -@item -A list @samp{(MIX @var{type} @dots{})} corresponds to the -@samp{(#PCDATA | @var{type} | @dots{})} syntax. -@end itemize -@end deftp - -@deftp {record type} xml-!attlist name definitions -@vindex -@findex xml-!attlist? -@findex make-xml-!attlist -@findex xml-!attlist-name -@findex xml-!attlist-definitions -@findex set-xml-!attlist-name! -@findex set-xml-!attlist-definitions! -The @code{xml-!attlist} record represents an attribute-list -declaration. @var{Name} is the @acronym{XML} name of the type for -which attributes are being declared (a symbol). @var{Definitions} is -a list of attribute definitions, each of which is a list of three -elements @code{(@var{name} @var{type} @var{default})}. @var{Name} is -an @acronym{XML} name for the name of the attribute (a symbol). -@var{Type} describes the attribute type, and can have one of the -following values: - -@itemize @bullet -@item -The @acronym{XML} names @samp{CDATA}, @samp{IDREFS}, @samp{IDREF}, -@samp{ID}, @samp{ENTITY}, @samp{ENTITIES}, @samp{NMTOKENS}, and -@samp{NMTOKEN} correspond to the @acronym{XML} keywords of the same -names. - -@item -A list @samp{(NOTATION @var{name1} @var{name2} @dots{})} corresponds -to the @samp{NOTATION (@var{name1} | @var{name2} @dots{})} syntax. - -@item -A list @samp{(ENUMERATED @var{name1} @var{name2} @dots{})} corresponds -to the @samp{(@var{name1} | @var{name2} @dots{})} syntax. -@end itemize - -@var{Default} describes the default value for the attribute, and can -have one of the following values: - -@itemize @bullet -@item -The @acronym{XML} names @samp{#REQUIRED} and @samp{#IMPLIED} -correspond to the @acronym{XML} keywords of the same names. - -@item -A list @samp{(#FIXED @var{value})} corresponds to the @samp{#FIXED -"@var{value}"} syntax. @var{Value} is represented as a string, but -might also be an @code{xml-uninterpreted} record. - -@item -A list @samp{(DEFAULT @var{value})} corresponds to the -@samp{"@var{value}"} syntax. @var{Value} is represented as a string, -but might also be an @code{xml-uninterpreted} record. -@end itemize -@end deftp - -@deftp {record type} xml-!entity name value -@vindex -@findex xml-!entity? -@findex make-xml-!entity -@findex xml-!entity-name -@findex xml-!entity-value -@findex set-xml-!entity-name! -@findex set-xml-!entity-value! -The @code{xml-!entity} record represents a general entity -declaration. @var{Name} is an @acronym{XML} name for the entity. -@var{Value} is the entity's value, either a string, an -@code{xml-uninterpreted} record, or an @code{xml-external-id} record. -@end deftp - -@deftp {record type} xml-parameter-!entity name value -@vindex -@findex xml-parameter-!entity? -@findex make-xml-parameter-!entity -@findex xml-parameter-!entity-name -@findex xml-parameter-!entity-value -@findex set-xml-parameter-!entity-name! -@findex set-xml-parameter-!entity-value! -The @code{xml-parameter-!entity} record represents a parameter entity -declaration. @var{Name} is an @acronym{XML} name for the entity. -@var{Value} is the entity's value, either a string, an -@code{xml-uninterpreted} record, or an @code{xml-external-id} record. -@end deftp - -@deftp {record type} xml-unparsed-!entity name id notation -@vindex -@findex xml-unparsed-!entity? -@findex make-xml-unparsed-!entity -@findex xml-unparsed-!entity-name -@findex xml-unparsed-!entity-id -@findex xml-unparsed-!entity-notation -@findex set-xml-unparsed-!entity-name! -@findex set-xml-unparsed-!entity-id! -@findex set-xml-unparsed-!entity-notation! -The @code{xml-unparsed-!entity} record represents an unparsed entity -declaration. @code{Name} is an @acronym{XML} name for the entity. -@var{Id} is an @code{xml-external-id} record. @var{Notation} is an -@acronym{XML} name for the notation. -@end deftp - -@deftp {record type} xml-!notation name id -@vindex -@findex xml-!notation? -@findex make-xml-!notation -@findex xml-!notation-name -@findex xml-!notation-id -@findex set-xml-!notation-name! -@findex set-xml-!notation-id! -The @code{xml-!notation} record represents a notation declaration. -@code{Name} is an @acronym{XML} name for the notation. @var{Id} is an -@code{xml-external-id} record. -@end deftp - -@deftp {record type} xml-external-id id uri -@vindex -@findex xml-external-id? -@findex make-xml-external-id -@findex xml-external-id-id -@findex xml-external-id-uri -@findex set-xml-external-id-id! -@findex set-xml-external-id-uri! -The @code{xml-external-id} record is a reference to an external -@acronym{DTD}. This reference consists of two parts: @var{id} is a -public @acronym{ID} literal, corresponding to the @samp{PUBLIC} -keyword, while @var{uri} is a system literal, corresponding to the -@samp{SYSTEM} keyword. Either or both may be present, depending on -the context. Each is represented as a string. -@end deftp - -@node Operating-System Interface, Error System, Input/Output, Top -@chapter Operating-System Interface -@cindex Operating-System Interface - -The Scheme standard provides a simple mechanism for reading and writing -files: file ports. MIT/GNU Scheme provides additional tools for -dealing with other aspects of the operating system: - -@itemize @bullet -@item -@dfn{Pathnames} are a reasonably operating-system independent tool for -manipulating the component parts of file names. This can be useful for -implementing defaulting of file name components. -@cindex pathname - -@item -Control over the @dfn{current working directory}: the place in the file -system from which relative file names are interpreted. -@cindex current working directory - -@item -Procedures that rename, copy, delete, and test for the existence of -files. Also, procedures that return detailed information about a -particular file, such as its type (directory, link, etc.) or length. - -@item -Procedures for reading the contents of a directory. - -@item -Procedures for obtaining times in various formats, converting between -the formats, and generating human-readable time strings. - -@item -Procedures to run other programs as subprocesses of Scheme, to read -their output, and write input to them. - -@item -A means to determine the operating system Scheme is running under. -@end itemize - -@menu -* Pathnames:: -* Working Directory:: -* File Manipulation:: -* Directory Reader:: -* Date and Time:: -* Machine Time:: -* Subprocesses:: -* TCP Sockets:: -* Miscellaneous OS Facilities:: -@end menu - -@node Pathnames, Working Directory, Operating-System Interface, Operating-System Interface -@section Pathnames - -@comment **** begin CLTL **** -@cindex file name -MIT/GNU Scheme programs need to use names to designate files. The main -difficulty in dealing with names of files is that different file systems -have different naming formats for files. For example, here is a table -of several file systems (actually, operating systems that provide file -systems) and what equivalent file names might look like for each one: - -@example -@group -System File Name ------- --------- -TOPS-20 FORMAT.FASL.13 -TOPS-10 FORMAT.FAS[1,4] -ITS LISPIO;FORMAT FASL -MULTICS >udd>LispIO>format.fasl -TENEX FORMAT.FASL;13 -VAX/VMS [LISPIO]FORMAT.FAS;13 -UNIX /usr/lispio/format.fasl -DOS C:\USR\LISPIO\FORMAT.FAS -@end group -@end example - -@cindex filename (defn) -@cindex pathname (defn) -It would be impossible for each program that deals with file names to -know about each different file name format that exists; a new operating -system to which Scheme was ported might use a format different from any -of its predecessors. Therefore, MIT/GNU Scheme provides @emph{two} ways to -represent file names: @dfn{filenames} (also called @dfn{namestrings}), -which are strings in the implementation-dependent form customary for the -file system, and @dfn{pathnames}, which are special abstract data -objects that represent file names in an implementation-independent way. -Procedures are provided to convert between these two representations, -and all manipulations of files can be expressed in machine-independent -terms by using pathnames. - -@cindex host, in filename -In order to allow MIT/GNU Scheme programs to operate in a network -environment that may have more than one kind of file system, the -pathname facility allows a file name to specify which file system is to -be used. In this context, each file system is called a @dfn{host}, in -keeping with the usual networking terminology.@footnote{This -introduction is adapted from @cite{Common Lisp, The Language}, second -edition, section 23.1.} -@comment **** end CLTL **** - -Note that the examples given in this section are specific to unix -pathnames. Pathnames for other operating systems have different -external representations. - -@menu -* Filenames and Pathnames:: -* Components of Pathnames:: -* Operations on Pathnames:: -* Miscellaneous Pathnames:: -@end menu - -@node Filenames and Pathnames, Components of Pathnames, Pathnames, Pathnames -@subsection Filenames and Pathnames - -Pathname objects are usually created by parsing filenames (character -strings) into component parts. MIT/GNU Scheme provides operations that -convert filenames into pathnames and vice versa. - -@deffn procedure ->pathname object -@cindex construction, of pathname -Returns a pathname that is the equivalent of @var{object}. @var{Object} -must be a pathname or a string. If @var{object} is a pathname, it is -returned. If @var{object} is a string, this procedure returns the -pathname that corresponds to the string; in this case it is equivalent -to @code{(parse-namestring @var{object} #f #f)}. - -@example -@group -(->pathname "foo") @result{} #[pathname 65 "foo"] -(->pathname "/usr/morris") @result{} #[pathname 66 "/usr/morris"] -@end group -@end example -@end deffn - - -@deffn procedure parse-namestring thing [host [defaults]] -@cindex construction, of pathname -This turns @var{thing} into a pathname. -@var{Thing} must be a pathname or a string. -If @var{thing} is a pathname, it is returned. If @var{thing} is a -string, this procedure returns the pathname that corresponds to the -string, parsed according to the syntax of the file system specified by -@var{host}. - -This procedure @emph{does not} do defaulting of pathname components. - -The optional arguments are used to determine what syntax should be used -for parsing the string. In general this is only really useful if your -implementation of MIT/GNU Scheme supports more than one file system, -otherwise you would use @code{->pathname}. If given, @var{host} must be -a host object or @code{#f}, and @var{defaults} must be a pathname. -@var{Host} specifies the syntax used to parse the string. If @var{host} -is not given or @code{#f}, the host component from @var{defaults} is -used instead; if @var{defaults} is not given, the host component from -@code{*default-pathname-defaults*} is used. -@end deffn - -@deffn procedure ->namestring pathname -@cindex conversion, pathname to string -@code{->namestring} returns a newly allocated string that is the -filename corresponding to @var{pathname}. -@example -@group -(->namestring (->pathname "/usr/morris/minor.van")) - @result{} "/usr/morris/minor.van" -@end group -@end example -@end deffn - - -@deffn procedure pathname-simplify pathname -@cindex simplification, of pathname -Returns a pathname that locates the same file or directory as -@var{pathname}, but is in some sense simpler. Note that -@code{pathname-simplify} might not always be able to simplify the -pathname, e.g.@: on unix with symbolic links the directory -@file{/usr/morris/../} need not be the same as @file{/usr/}. In cases -of uncertainty the behavior is conservative, returning the original or a -partly simplified pathname. - -@example -@group -(pathname-simplify "/usr/morris/../morris/dance") - @result{} #[pathname "/usr/morris/dance"] -@end group -@end example -@end deffn - -@node Components of Pathnames, Operations on Pathnames, Filenames and Pathnames, Pathnames -@subsection Components of Pathnames -@cindex components, of pathname -@cindex pathname components - -@comment **** begin CLTL **** -A pathname object always has six components, described below. These -components are the common interface that allows programs to work the -same way with different file systems; the mapping of the pathname -components into the concepts peculiar to each file system is taken care -of by the Scheme implementation. - -@table @var -@item host -The name of the file system on which the file resides. In the current -implementation, this component is always a host object that is filled in -automatically by the runtime system. When specifying the host -component, use either @code{#f} or the value of the variable -@code{local-host}. -@cindex host, pathname component - -@item device -Corresponds to the ``device'' or ``file structure'' concept in many host -file systems: the name of a (logical or physical) device containing -files. This component is the drive letter for PC file systems, and is -unused for unix file systems. -@cindex device, pathname component - -@item directory -Corresponds to the ``directory'' concept in many host file systems: the -name of a group of related files (typically those belonging to a single -user or project). This component is always used for all file systems. -@cindex directory, pathname component - -@item name -The name of a group of files that can be thought of as conceptually the -``same'' file. This component is always used for all file systems. -@cindex name, pathname component - -@item type -Corresponds to the ``filetype'' or ``extension'' concept in many host -file systems. This says what kind of file this is. Files with the same -name but different type are usually related in some specific way, such -as one being a source file, another the compiled form of that source, -and a third the listing of error messages from the compiler. This -component is currently used for all file systems, and is formed by -taking the characters that follow the last dot in the namestring. -@cindex type, pathname component - -@item version -Corresponds to the ``version number'' concept in many host file systems. -Typically this is a number that is incremented every time the file is -modified. This component is currently unused for all file systems. -@cindex version, pathname component -@end table - -Note that a pathname is not necessarily the name of a specific file. -Rather, it is a specification (possibly only a partial specification) of -how to access a file. A pathname need not correspond to any file that -actually exists, and more than one pathname can refer to the same file. -For example, the pathname with a version of @code{newest} may refer to -the same file as a pathname with the same components except a certain -number as the version. Indeed, a pathname with version @code{newest} -may refer to different files as time passes, because the meaning of such -a pathname depends on the state of the file system. In file systems -with such facilities as ``links'', multiple file names, logical devices, -and so on, two pathnames that look quite different may turn out to -address the same file. To access a file given a pathname, one must do a -file-system operation such as @code{open-input-file}. - -Two important operations involving pathnames are @dfn{parsing} and -@dfn{merging}. Parsing is the conversion of a filename (which might be -something supplied interactively by the users when asked to supply the -name of a file) into a pathname object. This operation is -implementation-dependent, because the format of filenames is -implementation-dependent. Merging takes a pathname with missing -components and supplies values for those components from a source of -default values. - -Not all of the components of a pathname need to be specified. If a -component of a pathname is missing, its value is @code{#f}. -Before the file system interface can do anything interesting with a -file, such as opening the file, all the missing components of a pathname -must be filled in. Pathnames with missing components are used -internally for various purposes; in particular, parsing a namestring -that does not specify certain components will result in a pathname with -missing components. - -Any component of a pathname may be the symbol @code{unspecific}, meaning -that the component simply does not exist, for file systems in which such -a value makes no sense. For example, unix, Windows, and OS/2 file -systems usually do not support version numbers, so the version component -for such a host might be @code{unspecific}.@footnote{This description is -adapted from @cite{Common Lisp, The Language}, second edition, section -23.1.1.} -@comment **** end CLTL **** - -In addition to @code{#f} and @code{unspecific}, the components of a -pathname may take on the following meaningful values: - -@table @var -@item host -An implementation-defined type which may be tested for using the -@code{host?} predicate. - -@item device -On systems that support this component (Windows and OS/2), it may be -specified as a string containing a single alphabetic character, for -which the alphabetic case is ignored. - -@item directory -A non-empty list, which represents a @dfn{directory path}: a sequence of -directories, each of which has a name in the previous directory, the -last of which is the directory specified by the entire path. Each -element in such a path specifies the name of the directory relative to -the directory specified by the elements to its left. The first element -of the list is either the symbol @code{absolute} or the symbol -@code{relative}. If the first element in the list is the symbol -@code{absolute}, then the directory component (and subsequently the -pathname) is @dfn{absolute}; the first component in the sequence is to -be found at the ``root'' of the file system. If the directory is -@dfn{relative} then the first component is to be found in some as yet -unspecified directory; typically this is later specified to be the -@dfn{current working directory}. -@cindex root, as pathname component -@cindex directory path (defn) -@cindex path, directory (defn) - -@cindex up, as pathname component -@cindex parent, of directory -Aside from @code{absolute} and @code{relative}, which may only appear as -the first element of the list, each subsequent element in the list is -either: a string, which is a literal component; the symbol @code{wild}, -meaningful only when used in conjunction with the directory reader; or -the symbol @code{up}, meaning the next directory is the ``parent'' of -the previous one. @code{up} corresponds to the file @file{..} in unix -and PC file systems. - -(The following note does not refer to any file system currently -supported by MIT/GNU Scheme, but is included for completeness.) In file -systems that do not have ``hierarchical'' structure, a specified -directory component will always be a list whose first element is -@code{absolute}. If the system does not support directories other than -a single global directory, the list will have no other elements. If the -system supports ``flat'' directories, i.e.@: a global set of directories -with no subdirectories, then the list will contain a second element, -which is either a string or @code{wild}. In other words, a -non-hierarchical file system is treated as if it were hierarchical, but -the hierarchical features are unused. This representation is somewhat -inconvenient for such file systems, but it discourages programmers from -making code depend on the lack of a file hierarchy. - -@item name -A string, which is a literal component; or the symbol @code{wild}, -meaningful only when used in conjunction with the directory reader. - -@item type -A string, which is a literal component; or the symbol @code{wild}, -meaningful only when used in conjunction with the directory reader. - -@item version -An exact positive integer, which is a literal component; the symbol -@code{newest}, which means to choose the largest available version -number for that file; the symbol @code{oldest}, which means to choose -the smallest version number; or the symbol @code{wild}, meaningful only -when used in conjunction with the directory reader. In the future some -other possible values may be added, e.g.@: @code{installed}. Note that -currently no file systems support version numbers; thus this component -is not used and should be specified as @code{#f}. -@cindex newest, as pathname component -@cindex oldest, as pathname component -@cindex installed, as pathname component -@end table - -@deffn procedure make-pathname host device directory name type version -@cindex construction, of pathname -Returns a pathname object whose components are the respective arguments. -Each argument must satisfy the restrictions for the corresponding -component, which were outlined above. - -@example -@group -(make-pathname #f - #f - '(absolute "usr" "morris") - "foo" - "scm" - #f) - @result{} #[pathname 67 "/usr/morris/foo.scm"] -@end group -@end example -@end deffn - -@deffn procedure pathname-host pathname -@deffnx procedure pathname-device pathname -@deffnx procedure pathname-directory pathname -@deffnx procedure pathname-name pathname -@deffnx procedure pathname-type pathname -@deffnx procedure pathname-version pathname -Returns a particular component of @var{pathname}. - -@example -@group -(define x (->pathname "/usr/morris/foo.scm")) -(pathname-host x) @result{} #[host 1] -(pathname-device x) @result{} unspecific -(pathname-directory x) @result{} (absolute "usr" "morris") -(pathname-name x) @result{} "foo" -(pathname-type x) @result{} "scm" -(pathname-version x) @result{} unspecific -@end group -@end example -@end deffn - -@deffn procedure pathname-new-device pathname device -@deffnx procedure pathname-new-directory pathname directory -@deffnx procedure pathname-new-name pathname name -@deffnx procedure pathname-new-type pathname type -@deffnx procedure pathname-new-version pathname version -Returns a new copy of @var{pathname} with the respective component -replaced by the second argument. @var{Pathname} is unchanged. -Portable programs should not explicitly replace a component with -@code{unspecific} because this might not be permitted in some -situations. - -@example -@group -(define p (->pathname "/usr/blisp/rel15")) -p - @result{} #[pathname 71 "/usr/blisp/rel15"] -(pathname-new-name p "rel100") - @result{} #[pathname 72 "/usr/blisp/rel100"] -(pathname-new-directory p '(relative "test" "morris")) - @result{} #[pathname 73 "test/morris/rel15"] -p - @result{} #[pathname 71 "/usr/blisp/rel15"] -@end group -@end example -@end deffn - -@deffn procedure pathname-default-device pathname device -@deffnx procedure pathname-default-directory pathname directory -@deffnx procedure pathname-default-name pathname name -@deffnx procedure pathname-default-type pathname type -@deffnx procedure pathname-default-version pathname version -These operations are similar to the @code{pathname-new-@var{component}} -operations, except that they only change the specified @var{component} -if it has the value @code{#f} in @var{pathname}. -@end deffn - -@node Operations on Pathnames, Miscellaneous Pathnames, Components of Pathnames, Pathnames -@subsection Operations on Pathnames - -@deffn procedure pathname? object -@cindex type predicate, for pathname -Returns @code{#t} if @var{object} is a pathname; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure pathname=? pathname1 pathname2 -@cindex equivalence predicate, for pathnames -Returns @code{#t} if @var{pathname1} is equivalent to @var{pathname2}; -otherwise returns @code{#f}. -Pathnames are equivalent if all of their components are equivalent, -hence two pathnames that are equivalent must identify the same file or -equivalent partial pathnames. -However, the converse is not true: non-equivalent pathnames may specify -the same file (e.g.@: via absolute and relative directory components), -and pathnames that specify no file at all (e.g.@: name and directory -components unspecified) may be equivalent. -@end deffn - -@deffn procedure pathname-absolute? pathname -Returns @code{#t} if @var{pathname} is an absolute rather than relative -pathname object; otherwise returns @code{#f}. Specifically, this -procedure returns @code{#t} when the directory component of -@var{pathname} is a list starting with the symbol @code{absolute}, and -returns @code{#f} in all other cases. All pathnames are either absolute -or relative, so if this procedure returns @code{#f}, the argument is a -relative pathname. -@end deffn - -@deffn procedure directory-pathname? pathname -Returns @code{#t} if @var{pathname} has only directory components and no -file components. This is roughly equivalent to - -@example -@group -(define (directory-pathname? pathname) - (string-null? (file-namestring pathname))) -@end group -@end example - -@noindent -except that it is faster. -@end deffn - -@deffn procedure pathname-wild? pathname -Returns @code{#t} if @var{pathname} contains any wildcard components; -otherwise returns @code{#f}. -@end deffn - -@deffn procedure merge-pathnames pathname [defaults [default-version]] -@cindex merging, of pathnames -@cindex defaulting, of pathname -Returns a pathname whose components are obtained by combining those of -@var{pathname} and @var{defaults}. @var{Defaults} defaults to the value -of @code{*default-pathname-defaults*} and @var{default-version} defaults -to @code{newest}. - -The pathnames are combined by components: if @var{pathname} has a -non-missing component, that is the resulting component, otherwise the -component from @var{defaults} is used. -The default version can be @code{#f} to preserve the information that -the component was missing from @var{pathname}. -The directory component is handled specially: if both pathnames have -directory components that are lists, and the directory component from -@var{pathname} is relative (i.e.@: starts with @code{relative}), then the -resulting directory component is formed by appending @var{pathname}'s -component to @var{defaults}'s component. -For example: - -@example -@group -(define path1 (->pathname "scheme/foo.scm")) -(define path2 (->pathname "/usr/morris")) -path1 - @result{} #[pathname 74 "scheme/foo.scm"] -path2 - @result{} #[pathname 75 "/usr/morris"] -(merge-pathnames path1 path2) - @result{} #[pathname 76 "/usr/scheme/foo.scm"] -(merge-pathnames path2 path1) - @result{} #[pathname 77 "/usr/morris.scm"] -@end group -@end example - -The merging rules for the version are more complex and depend on whether -@var{pathname} specifies a name. If @var{pathname} does not specify a -name, then the version, if not provided, will come from @var{defaults}. -However, if @var{pathname} does specify a name then the version is not -affected by @var{defaults}. The reason is that the version ``belongs -to'' some other file name and is unlikely to have anything to do with -the new one. Finally, if this process leaves the version missing, then -@var{default-version} is used. - -The net effect is that if the user supplies just a name, then the host, -device, directory and type will come from @var{defaults}, but the -version will come from @var{default-version}. If the user supplies -nothing, or just a directory, the name, type and version will come over -from @var{defaults} together. -@end deffn - -@defvr variable *default-pathname-defaults* -@cindex defaulting, of pathname -This is the default pathname-defaults pathname; if any pathname -primitive that needs a set of defaults is not given one, it uses this -one. @code{set-working-directory-pathname!} sets this variable to a new -value, computed by merging the new working directory with the variable's -old value. -@end defvr - -@deffn procedure pathname-default pathname device directory name type version -This procedure defaults all of the components of @var{pathname} -simultaneously. It could have been defined by: - -@example -@group -(define (pathname-default pathname - device directory name type version) - (make-pathname (pathname-host pathname) - (or (pathname-device pathname) device) - (or (pathname-directory pathname) directory) - (or (pathname-name pathname) name) - (or (pathname-type pathname) type) - (or (pathname-version pathname) version))) -@end group -@end example -@end deffn - -@deffn procedure file-namestring pathname -@deffnx procedure directory-namestring pathname -@deffnx procedure host-namestring pathname -@deffnx procedure enough-namestring pathname [defaults] -@cindex conversion, pathname to string -These procedures return a string corresponding to a subset of the -@var{pathname} information. @code{file-namestring} returns a string -representing just the @var{name}, @var{type} and @var{version} -components of @var{pathname}; the result of @code{directory-namestring} -represents just the @var{host}, @var{device}, and @var{directory} -components; and @code{host-namestring} returns a string for just the -@var{host} portion. - -@code{enough-namestring} takes another argument, @var{defaults}. -It returns an abbreviated namestring that is just sufficient to identify -the file named by @var{pathname} when considered relative to the -@var{defaults} (which defaults to @code{*default-pathname-defaults*}). - -@example -@group -(file-namestring "/usr/morris/minor.van") - @result{} "minor.van" -(directory-namestring "/usr/morris/minor.van") - @result{} "/usr/morris/" -(enough-namestring "/usr/morris/men") - @result{} "men" @r{;perhaps} -@end group -@end example -@end deffn - -@deffn procedure file-pathname pathname -@deffnx procedure directory-pathname pathname -@deffnx procedure enough-pathname pathname [defaults] -@cindex selection, components of pathname -These procedures return a pathname corresponding to a subset of the -@var{pathname} information. -@code{file-pathname} returns a pathname with just the -@var{name}, @var{type} and @var{version} components of @var{pathname}. -The result of @code{directory-pathname} is a pathname containing the -@var{host}, @var{device} and @var{directory} components of @var{pathname}. - -@code{enough-pathname} takes another argument, @var{defaults}. -It returns an abbreviated pathname that is just sufficient to identify -the file named by @var{pathname} when considered relative to the -@var{defaults} (which defaults to @code{*default-pathname-defaults*}). - -These procedures are similar to @code{file-namestring}, -@code{directory-namestring} and @code{enough-namestring}, but they -return pathnames instead of strings. -@end deffn - -@deffn procedure directory-pathname-as-file pathname -@cindex file, converting pathname directory to -Returns a pathname that is equivalent to @var{pathname}, but in which -the directory component is represented as a file. -The last directory is removed from the directory component and converted -into name and type components. -This is the inverse operation to @code{pathname-as-directory}. - -@example -@group -(directory-pathname-as-file (->pathname "/usr/blisp/")) - @result{} #[pathname "/usr/blisp"] -@end group -@end example -@end deffn - -@deffn procedure pathname-as-directory pathname -@cindex directory, converting pathname to -Returns a pathname that is equivalent to @var{pathname}, but in which -any file components have been converted to a directory component. If -@var{pathname} does not have name, type, or version components, it is -returned without modification. Otherwise, these file components are -converted into a string, and the string is added to the end of the list -of directory components. This is the inverse operation to -@code{directory-pathname-as-file}. - -@example -@group -(pathname-as-directory (->pathname "/usr/blisp/rel5")) - @result{} #[pathname "/usr/blisp/rel5/"] -@end group -@end example -@end deffn - - -@node Miscellaneous Pathnames, , Operations on Pathnames, Pathnames -@subsection Miscellaneous Pathname Procedures -@cindex directory, reading - -This section gives some standard operations on host objects, and some -procedures that return some useful pathnames. - -@defvr variable local-host -This variable has as its value the host object that describes the local -host's file system. -@end defvr - -@deffn procedure host? object -@cindex type predicate, for pathname host -Returns @code{#t} if @var{object} is a pathname host; otherwise returns -@code{#f}. -@end deffn - -@deffn procedure host=? host1 host2 -@cindex equivalence predicate, for pathname host -Returns @code{#t} if @var{host1} and @var{host2} denote the same -pathname host; otherwise returns @code{#f}. -@end deffn - -@deffn procedure init-file-pathname [host] -@cindex home directory, as pathname -Returns a pathname for the user's initialization file on @var{host}. -The @var{host} argument defaults to the value of @code{local-host}. If -the initialization file does not exist this procedure returns @code{#f}. - -Under unix, the init file is called @file{.scheme.init}; under Windows -and OS/2, the init file is called @file{scheme.ini}. In either -case, it is located in the user's home directory, which is computed by -@code{user-homedir-pathname}. -@end deffn - -@deffn procedure user-homedir-pathname [host] -@cindex home directory, as pathname -Returns a pathname for the user's ``home directory'' on @var{host}. The -@var{host} argument defaults to the value of @code{local-host}. The -concept of a ``home directory'' is itself somewhat -implementation-dependent, but it should be the place where the user -keeps personal files, such as initialization files and mail. - -Under unix, the user's home directory is specified by the @code{HOME} -environment variable. If this variable is undefined, the user name is -computed using the @code{getlogin} system call, or if that fails, the -@code{getuid} system call. The resulting user name is passed to the -@code{getpwnam} system call to obtain the home directory. - -Under OS/2, several heuristics are tried to find the user's home -directory. First, if the environment variable @code{HOME} is defined, -that is the home directory. If @code{HOME} is undefined, but the -@code{USERDIR} and @code{USER} environment variables are defined and -the directory @file{%USERDIR%\%USER%} exists, then it is used. Failing -that, if the directory @file{%USER%} exists on the OS/2 system -drive, then it is used. As a last resort, the OS/2 system drive is -the home directory. - -Like OS/2, the Windows implementation uses heuristics based on -environment variables. The user's home directory is computed by -examining several environment variables, in the following order: - -@itemize @bullet -@item -@code{HOMEDRIVE} and @code{HOMEPATH} are both defined and -@file{%HOMEDRIVE%%HOMEPATH%} is an existing directory. (These variables -are automatically defined by Windows NT.) - -@item -@code{HOME} is defined and @file{%HOME%} is an existing directory. - -@item -@code{USERDIR} and @code{USERNAME} are defined and -@file{%USERDIR%\%USERNAME%} is an existing directory. - -@item -@code{USERDIR} and @code{USER} are defined and -@file{%USERDIR%\%USER%} is an existing directory. - -@item -@code{USERNAME} is defined and @file{%USERNAME%} is an existing -directory on the Windows system drive. - -@item -@code{USER} is defined and @file{%USER%} is an existing directory on the -Windows system drive. - -@item -Finally, if all else fails, the Windows system drive is used as the home -directory. -@end itemize -@end deffn - -@deffn procedure system-library-pathname pathname -@cindex library, system pathname -Locates @var{pathname} in MIT/GNU Scheme's system library directory. An -error of type @code{condition-type:file-operation-error} is signalled if -@var{pathname} cannot be located on the library search path. -@findex condition-type:file-operation-error - -@example -@group -(system-library-pathname "compiler.com") - @result{} #[pathname 45 "/usr/local/lib/mit-scheme/compiler.com"] -@end group -@end example -@end deffn - -@deffn procedure system-library-directory-pathname pathname -@cindex library, system pathname -Locates the pathname of an MIT/GNU Scheme system library directory. An -error of type @code{condition-type:file-operation-error} is signalled if -@var{pathname} cannot be located on the library search path. - -@example -@group -(system-library-directory-pathname "options") - @result{} #[pathname 44 "/usr/local/lib/mit-scheme/options/"] -@end group -@end example -@end deffn - -@node Working Directory, File Manipulation, Pathnames, Operating-System Interface -@section Working Directory - -@cindex absolute pathname (defn) -@cindex pathname, absolute (defn) -@cindex relative pathname (defn) -@cindex pathname, relative (defn) -@cindex directory, current working (defn) -@cindex current working directory (defn) -@cindex working directory (see current working directory) -When MIT/GNU Scheme is started, the @dfn{current working directory} (or -simply, @dfn{working directory}) is initialized in an operating-system -dependent manner; usually, it is the directory in which Scheme was -invoked. The working directory can be determined from within Scheme by -calling the @code{pwd} procedure, and changed by calling the @code{cd} -procedure. Each @acronym{REP} loop has its own working directory, and -inferior @acronym{REP} loops initialize their working directory from the -value in effect in their superior at the time they are created. - -@deffn procedure working-directory-pathname -@deffnx procedure pwd -Returns the current working directory as a pathname that has no name, -type, or version components, just host, device, and directory -components. @code{pwd} is an alias for -@code{working-directory-pathname}; the long name is intended for -programs and the short name for interactive use. -@end deffn - -@deffn procedure set-working-directory-pathname! filename -@deffnx procedure cd filename -@findex ->pathname -@findex pathname-as-directory -Makes @var{filename} the current working directory and returns the new -current working directory as a pathname. @var{Filename} is coerced to a -pathname using @code{pathname-as-directory}. @code{cd} is an alias for -@code{set-working-directory-pathname!}; the long name is intended for -programs and the short name for interactive use. - -Additionally, @code{set-working-directory-pathname!} modifies the value -of@* @code{*default-pathname-defaults*} by merging the new working -directory into it. - -When this procedure is executed in the top-level @acronym{REP} loop, it -changes the working directory of the running Scheme executable. - -@example -@group -(set-working-directory-pathname! "/usr/morris/blisp") - @result{} #[pathname "/usr/morris/blisp/"] -(set-working-directory-pathname! "~") - @result{} #[pathname "/usr/morris/"] -@end group -@end example - -This procedure signals an error if @var{filename} does not refer to an -existing directory. - -If @var{filename} describes a relative rather than absolute pathname, -this procedure interprets it as relative to the current working -directory, before changing the working directory. - -@example -@group -(working-directory-pathname) - @result{} #[pathname "/usr/morris/"] -(set-working-directory-pathname! "foo") - @result{} #[pathname "/usr/morris/foo/"] -@end group -@end example -@end deffn - -@deffn procedure with-working-directory-pathname filename thunk -This procedure temporarily rebinds the current working directory to -@var{filename}, invokes @var{thunk} (a procedure of no arguments), then -restores the previous working directory and returns the value yielded by -@var{thunk}. @var{Filename} is coerced to a pathname using -@code{pathname-as-directory}. In addition to binding the working -directory, @code{with-working-directory-pathname} also binds the -variable @code{*default-pathname-defaults*}, merging the old value of -that variable with the new working directory pathname. Both bindings -are performed in exactly the same way as dynamic binding of a variable -(@pxref{Dynamic Binding}). -@end deffn - -@node File Manipulation, Directory Reader, Working Directory, Operating-System Interface -@section File Manipulation - -This section describes procedures that manipulate files and directories. -Any of these procedures can signal a number of errors for many reasons. -The specifics of these errors are much too operating-system dependent to -document here. However, if such an error is signalled by one of -these procedures, it will be of type -@code{condition-type:file-operation-error}. -@findex condition-type:file-operation-error - -@deffn procedure file-exists? filename -@deffnx procedure file-exists-direct? filename -@deffnx procedure file-exists-indirect? filename -@cindex existence, testing of file -These procedures return @code{#t} if @var{filename} is an existing file -or directory; otherwise they return @code{#f}. In operating systems -that support symbolic links, if the file is a symbolic link, -@code{file-exists-direct?} tests for the existence of the link, while -@code{file-exists-indirect?} and @code{file-exists?} test for the -existence of the file pointed to by the link. -@end deffn - -@deffn procedure copy-file source-filename target-filename -@cindex copying, of file -Makes a copy of the file named by @var{source-filename}. The copy is -performed by creating a new file called @var{target-filename}, and -filling it with the same data as @var{source-filename}. -@end deffn - -@deffn procedure rename-file source-filename target-filename -@cindex renaming, of file -@cindex name, of file -Changes the name of @var{source-filename} to be @var{target-filename}. -In the unix implementation, this will not rename across file systems. -@end deffn - -@deffn procedure delete-file filename -@cindex deletion, of file -Deletes the file named @var{filename}. -@end deffn - -@deffn procedure delete-file-no-errors filename -Like @code{delete-file}, but returns a boolean value indicating whether -an error occurred during the deletion. If no errors occurred, @code{#t} -is returned. If an error of type @code{condition-type:file-error} or -@code{condition-type:port-error} is signalled, @code{#f} is returned. -@end deffn - -@deffn procedure hard-link-file source-filename target-filename -@cindex linking (hard), of file -@cindex hard linking, of file -Makes a hard link from @var{source-filename} to @var{target-filename}. -This operation gives the file specified by @var{source-filename} a new -name, in addition to the old name. - -This currently works only on unix systems. It is further restricted to -work only when @var{source-filename} and @var{target-filename} refer to -names in the same file system. -@end deffn - -@deffn procedure soft-link-file source-filename target-filename -@cindex linking (soft), of file -@cindex soft linking, of file -@cindex symbolic linking, of file -Creates a new soft link called @var{target-filename} that points at the -file @var{source-filename}. (Soft links are also sometimes called -@dfn{symbolic} links.) Note that @var{source-filename} will be -interpreted as a string (although you may specify it as a pathname -object, if you wish). The contents of this string will be stored in the -file system as the soft link. When a file operation attempts to open -the link, the contents of the link are interpreted relative to the -link's location at that time. - -This currently works only on unix systems. -@end deffn - -@deffn procedure make-directory filename -Creates a new directory named @var{filename}. Signals an error if -@var{filename} already exists, or if the directory cannot be created. -@end deffn - -@deffn procedure delete-directory filename -Deletes the directory named @var{filename}. Signals an error if -the directory does not exist, is not a directory, or contains any files -or subdirectories. -@end deffn - -@deffn procedure ->truename filename -@cindex truename, of input file -This procedure attempts to discover and return the ``true name'' of the -file associated with @var{filename} within the file system. An error of -type @code{condition-type:file-operation-error} is signalled if the -appropriate file cannot be located within the file system. -@findex condition-type:file-operation-error -@end deffn - -@deffn procedure call-with-temporary-file-pathname procedure -Calls @code{temporary-file-pathname} to create a temporary file, then -calls @var{procedure} with one argument, the pathname referring to that -file. When @var{procedure} returns, if the temporary file still exists, -it is deleted; then, the value yielded by @var{procedure} is returned. -If @var{procedure} escapes from its continuation, and the file still -exists, it is deleted. -@end deffn - -@deffn procedure temporary-file-pathname [directory] -Creates a new empty temporary file and returns a pathname referring to -it. The temporary file is created with Scheme's default permissions, so -barring unusual circumstances it can be opened for input and/or output -without error. The temporary file will remain in existence until -explicitly deleted. If the file still exists when the Scheme process -terminates, it will be deleted. - -If @var{directory} is specified, the temporary file will be stored -there. If it is not specified, or if it is @code{#f}, the temporary -file will be stored in the directory returned by -@code{temporary-directory-pathname}. -@end deffn - -@deffn procedure temporary-directory-pathname -Returns the pathname of an existing directory that can be used to store -temporary files. These directory names are tried, in order, until a -writeable directory is found: - -@itemize @bullet -@item -The directories specified by the environment variables @code{TMPDIR}, -@code{TEMP}, or @code{TMP}. - -@item -Under unix, the directories @file{/var/tmp}, @file{/usr/tmp}, or -@file{/tmp}. - -@item -Under OS/2 or Windows, the following directories on the system drive: -@file{\temp}, @file{\tmp}, or @file{\}. - -@item -Under OS/2 or Windows, the current directory, as specified by -@code{*default-pathname-defaults*}. -@end itemize -@end deffn - -@deffn procedure file-directory? filename -@cindex directory, predicate for -Returns @code{#t} if the file named @var{filename} exists and is a -directory. Otherwise returns @code{#f}. In operating systems that -support symbolic links, if @var{filename} names a symbolic link, this -examines the file linked to, not the link itself. - -This is equivalent to - -@example -(eq? 'directory (file-type-indirect @var{filename})) -@end example -@end deffn - -@deffn procedure file-regular? filename -@cindex file (regular), predicate for -@cindex regular file, predicate for -Returns @code{#t} if the file named @var{filename} exists and is a -regular file (i.e.@: not a directory, symbolic link, device file, etc.). -Otherwise returns @code{#f}. In operating systems that support symbolic -links, if @var{filename} names a symbolic link, this examines the file -linked to, not the link itself. - -This is equivalent to - -@example -(eq? 'regular (file-type-indirect @var{filename})) -@end example -@end deffn - -@deffn procedure file-symbolic-link? filename -@cindex symbolic link, predicate for -In operating systems that support symbolic links, if the file named -@var{filename} exists and is a symbolic link, this procedure returns the -contents of the symbolic link as a newly allocated string. The returned -value is the name of the file that the symbolic link points to and must -be interpreted relative to the directory of @var{filename}. If -@var{filename} either does not exist or is not a symbolic link, or if -the operating system does not support symbolic links, this procedure -returns @code{#f}. -@end deffn - -@deffn procedure file-type-direct filename -@deffnx procedure file-type-indirect filename -@cindex file type, procedure for -If the file named @var{filename} exists, @code{file-type-direct} returns -a symbol specifying what type of file it is. For example, if -@var{filename} refers to a directory, the symbol @code{directory} is -returned. If @var{filename} doesn't refer to an existing file, -@code{#f} is returned. - -If @var{filename} refers to a symbolic link, @code{file-type-direct} -returns the type of the link itself, while @code{file-type-indirect} -returns the type of the file linked to. - -At this time, the symbols that can be returned are the following. The -names are intended to be self-explanatory. Most of these names can only -be returned on particular operating systems, and so the operating-system -name is prefixed to the name. - -@example -regular -directory -unix-symbolic-link -unix-character-device -unix-block-device -unix-named-pipe -unix-socket -os2-named-pipe -win32-named-pipe -@end example -@end deffn - -@deffn procedure file-readable? filename -Returns @code{#t} if @var{filename} names a file that can be opened for -input; i.e.@: a @dfn{readable} file. Otherwise returns @code{#f}. -@end deffn - -@deffn procedure file-writeable? filename -Returns @code{#t} if @var{filename} names a file that can be opened for -output; i.e.@: a @dfn{writeable} file. Otherwise returns @code{#f}. -@end deffn - -@deffn procedure file-executable? filename -Returns @code{#t} if @var{filename} names a file that can be executed. -Otherwise returns @code{#f}. Under unix, an executable file is -identified by its mode bits. Under OS/2, an executable file has -one of the file extensions @file{.exe}, @file{.com}, @file{.cmd}, or -@file{.bat}. Under Windows, an executable file has one of the file -extensions @file{.exe}, @file{.com}, or @file{.bat}. -@end deffn - -@deffn procedure file-access filename mode -@var{Mode} must be an exact integer between @code{0} and @code{7} -inclusive; it is a bitwise-encoded predicate selector with @code{1} -meaning ``executable'', @code{2} meaning ``writeable'', and @code{4} -meaning ``readable''. @code{file-access} returns @code{#t} if -@var{filename} exists and satisfies the predicates selected by -@var{mode}. For example, if @var{mode} is @code{5}, then @var{filename} -must be both readable and executable. If @var{filename} doesn't exist, -or if it does not satisfy the selected predicates, @code{#f} is -returned. -@end deffn - -@deffn procedure file-eq? filename1 filename2 -Determines whether @var{filename1} and @var{filename2} refer to the same -file. Under unix, this is done by comparing the inodes and devices of -the two files. Under OS/2 and Windows, this is done by comparing -the filename strings. -@end deffn - -@deffn procedure file-modes filename -If @var{filename} names an existing file, @code{file-modes} returns an -exact non-negative integer encoding the file's permissions. The -encoding of this integer is operating-system dependent. Under unix, it -is the least-significant 12 bits of the @code{st_mode} element of the -@code{struct stat} structure. Under OS/2 and Windows, it is the file -attribute bits, which are described below. If @var{filename} does not -name an existing file, @code{#f} is returned. -@end deffn - -@deffn procedure set-file-modes! filename modes -@var{Filename} must name an existing file. @var{Modes} must be an exact -non-negative integer that could have been returned by a call to -@code{file-modes}. @code{set-file-modes!} modifies the file's -permissions to be those encoded by @var{modes}. -@end deffn - -@defvr variable os2-file-mode/read-only -@defvrx variable os2-file-mode/hidden -@defvrx variable os2-file-mode/system -@defvrx variable os2-file-mode/directory -@defvrx variable os2-file-mode/archived -The values of these variables are the ``mode bits'' that comprise the -value returned by @code{file-modes} under OS/2. These bits are small -integers that are combined by adding to form a complete set of modes. -The integer zero represents a set of modes in which none of these bits -are set. -@end defvr - -@defvr variable nt-file-mode/read-only -@defvrx variable nt-file-mode/hidden -@defvrx variable nt-file-mode/system -@defvrx variable nt-file-mode/directory -@defvrx variable nt-file-mode/archive -@defvrx variable nt-file-mode/normal -@defvrx variable nt-file-mode/temporary -@defvrx variable nt-file-mode/compressed -The values of these variables are the ``mode bits'' that comprise the -value returned by @code{file-modes} under Windows. These bits are small -integers that are combined by adding to form a complete set of modes. -The integer zero represents a set of modes in which none of these bits -are set. -@end defvr - -@deffn procedure file-modification-time filename -@cindex modification time, of file -Returns the modification time of @var{filename} as an exact non-negative -integer. The result may be compared to other file times using ordinary -integer arithmetic. If @var{filename} names a file that does not exist, -@code{file-modification-time} returns @code{#f}. - -@findex file-modification-time-direct -@findex file-modification-time-indirect -In operating systems that support symbolic links, if @var{filename} -names a symbolic link, @code{file-modification-time} returns the -modification time of the file linked to. An alternate procedure, -@code{file-modification-time-direct}, returns the modification time of -the link itself; in all other respects it is identical to -@code{file-modification-time}. For symmetry, -@code{file-modification-time-indirect} is a synonym of -@code{file-modification-time}. -@end deffn - -@deffn procedure file-access-time filename -@cindex access time, of file -Returns the access time of @var{filename} as an exact non-negative -integer. The result may be compared to other file times using ordinary -integer arithmetic. If @var{filename} names a file that does not exist, -@code{file-access-time} returns @code{#f}. - -@findex file-access-time-direct -@findex file-access-time-indirect -In operating systems that support symbolic links, if @var{filename} -names a symbolic link, @code{file-access-time} returns the access time -of the file linked to. An alternate procedure, -@code{file-access-time-direct}, returns the access time of the link -itself; in all other respects it is identical to -@code{file-access-time}. For symmetry, @code{file-access-time-indirect} -is a synonym of @code{file-access-time}. -@end deffn - -@deffn procedure set-file-times! filename access-time modification-time -@var{Filename} must name an existing file, while @var{access-time} and -@var{modification-time} must be valid file times that might have been -returned by @code{file-access-time} and @code{file-modification-time}, -respectively. @code{set-file-times!} alters the access and modification -times of the file specified by @var{filename} to the values given by -@var{access-time} and @var{modification-time}, respectively. For -convenience, either of the time arguments may be specified as @code{#f}; -in this case the corresponding time is not changed. -@code{set-file-times!} returns an unspecified value. -@end deffn - -@deffn procedure current-file-time -Returns the current time as an exact non-negative integer, in the same -format used by the above file-time procedures. This number can be -compared to other file times using ordinary arithmetic operations. -@end deffn - -@deffn procedure file-touch filename -@dfn{Touches} the file named @var{filename}. If the file already -exists, its modification time is set to the current file time and -@code{#f} is returned. Otherwise, the file is created and @code{#t} is -returned. This is an atomic test-and-set operation, so it is useful as -a synchronization mechanism. -@end deffn - -@deffn procedure file-length filename -Returns the length, in bytes, of the file named @var{filename} as an -exact non-negative integer. -@end deffn - -@deffn procedure file-attributes filename -@cindex attribute, of file -This procedure determines if the file named @var{filename} exists, and -returns information about it if so; if the file does not exist, it -returns @code{#f}. - -@findex file-attributes-direct -@findex file-attributes-indirect -In operating systems that support symbolic links, if @var{filename} -names a symbolic link, @code{file-attributes} returns the attributes of -the link itself. An alternate procedure, -@code{file-attributes-indirect}, returns the attributes of the file -linked to; in all other respects it is identical to -@code{file-attributes}. For symmetry, @code{file-attributes-direct} is -a synonym of @code{file-attributes}. -@end deffn - -The information returned by @code{file-attributes} is decoded by -accessor procedures. The following accessors are defined in all -operating systems: - -@deffn procedure file-attributes/type attributes -The file type: @code{#t} if the file is a directory, a character string -(the name linked to) if a symbolic link, or @code{#f} for all other -types of file. -@end deffn - -@deffn procedure file-attributes/access-time attributes -The last access time of the file, an exact non-negative integer. -@end deffn - -@deffn procedure file-attributes/modification-time attributes -The last modification time of the file, an exact non-negative integer. -@end deffn - -@deffn procedure file-attributes/change-time attributes -The last change time of the file, an exact non-negative integer. -@end deffn - -@deffn procedure file-attributes/length attributes -The length of the file in bytes. -@end deffn - -@deffn procedure file-attributes/mode-string attributes -The mode string of the file, a newly allocated string showing the file's -mode bits. Under unix, this string is in unix format. Under OS/2 and -Windows, this string shows the standard ``DOS'' attributes in their -usual format. -@end deffn - -@deffn procedure file-attributes/n-links attributes -The number of links to the file, an exact positive integer. Under -Windows and OS/2, this is always @code{1}. -@end deffn - -The following additional accessors are defined under unix: - -@deffn procedure file-attributes/uid attributes -The user id of the file's owner, an exact non-negative integer. -@end deffn - -@deffn procedure file-attributes/gid attributes -The group id of the file's group, an exact non-negative integer. -@end deffn - -@deffn procedure file-attributes/inode-number attributes -The inode number of the file, an exact non-negative integer. -@end deffn - -The following additional accessor is defined under OS/2 and Windows: - -@deffn procedure file-attributes/modes attributes -The attribute bits of the file. This is an exact non-negative integer -containing the file's attribute bits, exactly as specified by the -operating system's API. -@end deffn - -The following additional accessor is defined under OS/2: - -@deffn procedure file-attributes/allocated-length attributes -The allocated length of the file, which can be larger than the length of -the file due to fixed-length allocation units. -@end deffn - -@node Directory Reader, Date and Time, File Manipulation, Operating-System Interface -@section Directory Reader -@cindex directory, reading - -@deffn procedure directory-read directory [sort?] -@var{Directory} must be an object that can be converted into a pathname -by@* @code{->pathname}. The directory specified by @var{directory} is -read, and the contents of the directory is returned as a newly allocated -list of absolute pathnames. The result is sorted according to the usual -sorting conventions for directories, unless @var{sort?} is specified as -@code{#f}. If @var{directory} has name, type, or version components, -the returned list contains only those pathnames whose name, type, and -version components match those of @var{directory}; @code{wild} or -@code{#f} as one of these components means ``match anything''. - -The OS/2 and Windows implementations support ``globbing'', in which the -characters @code{*} and @code{?} are interpreted to mean ``match -anything'' and ``match any character'', respectively. This ``globbing'' -is supported only in the file part of @var{directory}. -@end deffn - -@node Date and Time, Machine Time, Directory Reader, Operating-System Interface -@section Date and Time - -MIT/GNU Scheme provides a simple set of procedures for manipulating date -and time information. There are four time representations, each of -which serves a different purpose. Each representation may be -converted to any of the others. - -@cindex universal time -@cindex time, universal -The primary time representation, @dfn{universal time}, is an exact -non-negative integer counting the number of seconds that have elapsed -since midnight January 1, 1900 UTC. (UTC stands for @dfn{Coordinated -Universal Time}, and is the modern name for Greenwich Mean Time.) This -format is produced by @code{get-universal-time} and -@code{decoded-time->universal-time}. - -@cindex decoded time -@cindex time, decoded -The second representation, @dfn{decoded time}, is a record structure in -which the time is broken down into components, such as month, minute, -etc. Decoded time is always relative to a particular time zone, which -is a component of the structure. This format is produced by -@code{global-decoded-time} and @code{local-decoded-time}. - -@cindex file time -@cindex time, file -The third representation, @dfn{file time}, is an exact non-negative -integer that is larger for increasing time. Unlike universal time, -this representation is operating-system dependent. This format is -produced by all of the file-attribute procedures, for example -@code{file-modification-time} and @code{file-attributes}. - -@cindex time, string -The fourth representation, the @dfn{time string}, is an external -representation for time. This format is defined by RFC-822, -@cite{Standard for the format of ARPA Internet text messages}, with the -modification that years are represented as four-digit numbers rather -than two-digit numbers. This format is the standard format for Internet -email and numerous other network protocols. - -Within this section, argument variables named @var{universal-time}, -@var{decoded-time}, @var{file-time}, and @var{time-string} are -respectively required to be of the corresponding format. - -@menu -* Universal Time:: -* Decoded Time:: -* File Time:: -* Time-Format Conversion:: -* External Representation of Time:: -@end menu - -@node Universal Time, Decoded Time, Date and Time, Date and Time -@subsection Universal Time - -@deffn procedure get-universal-time -Return the current time in universal format. - -@example -(get-universal-time) @result{} 3131453078 -@end example -@end deffn - -@defvr variable epoch -@code{epoch} is the representation of midnight January 1, 1970 UTC in -universal-time format. - -@example -epoch @result{} 2208988800 -@end example -@end defvr - -@node Decoded Time, File Time, Universal Time, Date and Time -@subsection Decoded Time - -Objects representing standard time components, such as seconds and -minutes, are required to be exact non-negative integers. Seconds and -minutes must be inclusively between @code{0} and @code{59}; hours -between @code{0} and @code{23}; days between @code{1} and @code{31}; -months between @code{1} and @code{12}; years are represented in -``four-digit'' form, in which 1999 is represented as @code{1999} --- -@emph{not} @code{99}. - -@deffn procedure local-decoded-time -Return the current time in decoded format. The decoded time is -represented in the local time zone. - -@example -@group -(pp (local-decoded-time)) -@print{} #[decoded-time 76] -@print{} (second 2) -@print{} (minute 12) -@print{} (hour 11) -@print{} (day 27) -@print{} (month 4) -@print{} (year 1999) -@print{} (day-of-week 1) -@print{} (daylight-savings-time 1) -@print{} (zone 5) -@end group -@end example -@end deffn - -@deffn procedure global-decoded-time -Return the current time in decoded format. The decoded time is -represented in UTC. - -@example -@group -(pp (global-decoded-time)) -@print{} #[decoded-time 77] -@print{} (second 8) -@print{} (minute 12) -@print{} (hour 15) -@print{} (day 27) -@print{} (month 4) -@print{} (year 1999) -@print{} (day-of-week 1) -@print{} (daylight-savings-time 0) -@print{} (zone 0) -@end group -@end example -@end deffn - -@deffn procedure make-decoded-time second minute hour day month year [zone] -Return a new decoded-time object representing the given time. The -arguments must be valid components according to the above rules, and -must form a valid date. - -If @var{zone} is not supplied or is @code{#f}, the resulting decoded -time will be represented in the local time zone. Otherwise, @var{zone} -must be a valid time zone, and the result will be represented in that -zone. - -@strong{Warning}: because this procedure depends on the operating -system's runtime library, it is not capable of representing all dates. -In particular, on most unix systems, it is not possible to encode dates -that occur prior to midnight, January 1, 1970 UTC. Attempting to do -this will signal an error. - -@example -@group -(pp (make-decoded-time 0 9 11 26 3 1999)) -@print{} #[decoded-time 19] -@print{} (second 0) -@print{} (minute 9) -@print{} (hour 11) -@print{} (day 26) -@print{} (month 3) -@print{} (year 1999) -@print{} (day-of-week 4) -@print{} (daylight-savings-time 0) -@print{} (zone 5) -@end group - -@group -(pp (make-decoded-time 0 9 11 26 3 1999 3)) -@print{} #[decoded-time 80] -@print{} (second 0) -@print{} (minute 9) -@print{} (hour 11) -@print{} (day 26) -@print{} (month 3) -@print{} (year 1999) -@print{} (day-of-week 4) -@print{} (daylight-savings-time 0) -@print{} (zone 3) -@end group -@end example -@end deffn - -@deffn procedure decoded-time/second decoded-time -@deffnx procedure decoded-time/minute decoded-time -@deffnx procedure decoded-time/hour decoded-time -@deffnx procedure decoded-time/day decoded-time -@deffnx procedure decoded-time/month decoded-time -@deffnx procedure decoded-time/year decoded-time -Return the corresponding component of @var{decoded-time}. - -@example -@group -(decoded-time/second (local-decoded-time)) @result{} 17 -(decoded-time/year (local-decoded-time)) @result{} 1999 -(decoded-time/day (local-decoded-time)) @result{} 26 -@end group -@end example -@end deffn - -@deffn procedure decoded-time/day-of-week decoded-time -Return the day of the week on which @var{decoded-time} falls, encoded -as an exact integer between @code{0} (Monday) and @code{6} (Sunday), -inclusive. - -@example -(decoded-time/day-of-week (local-decoded-time)) @result{} 4 -@end example -@end deffn - -@deffn procedure decoded-time/daylight-savings-time? decoded-time -Return @code{#t} if @var{decoded-time} is represented using daylight -savings time. Otherwise return @code{#f}. - -@example -(decoded-time/daylight-savings-time? (local-decoded-time)) - @result{} #f -@end example -@end deffn - -@deffn procedure decoded-time/zone decoded-time -Return the time zone in which @var{decoded-time} is represented. This -is an exact rational number between @code{-24} and @code{+24} inclusive, -that when multiplied by @code{3600} is an integer. The value is the -number of hours west of UTC. - -@example -(decoded-time/zone (local-decoded-time)) @result{} 5 -@end example -@end deffn - -@deffn procedure time-zone? object -Returns @code{#t} if @var{object} is an exact number between @code{-24} -and @code{+24} inclusive, that when multiplied by @code{3600} is an -integer. - -@example -@group -(time-zone? -5) @result{} #t -(time-zone? 11/2) @result{} #t -(time-zone? 11/7) @result{} #f -@end group -@end example -@end deffn - -@deffn procedure month/max-days month -Returns the maximum number of days possible in @var{month}. @var{Month} -must be an exact integer between @code{1} and @code{12} inclusive. - -@example -@group -(month/max-days 2) @result{} 29 -(month/max-days 3) @result{} 31 -(month/max-days 4) @result{} 30 -@end group -@end example -@end deffn - -@node File Time, Time-Format Conversion, Decoded Time, Date and Time -@subsection File Time - -As stated above, file time is operating-system dependent. As of this -writing, two formats are used. For unix and Windows systems, file time -is the number of seconds since midnight January 1, 1970 UTC (the -standard unix time convention). - -OS/2 represents file time as a 32-bit unsigned integer, in which the -time components are broken down into unsigned bit fields. The -components are always stated in local time. The fields, from MSB to -LSB, are: - -@itemize @bullet -@item -7 bits representing the year, relative to 1900. - -@item -4 bits representing the month, numbered 1 to 12. - -@item -5 bits representing the day of the month, numbered 1 to 31. - -@item -5 bits representing the hour of the day, numbered 0 to 23. - -@item -6 bits representing the minute, numbered 0 to 59. - -@item -5 bits representing the second. This field is unusual in that it counts -units of two seconds, so it is a number between 0 and 29, representing -second counts corresponding to 0 through 58. -@end itemize - -The following procedures generate their results in file-time format: - -@example -@group -file-access-time -file-access-time-direct -file-access-time-indirect -file-modification-time -file-modification-time-direct -file-modification-time-indirect -file-attributes/access-time -file-attributes/modification-time -file-attributes/change-time -@end group -@end example - -@noindent -Additionally, @code{set-file-times!} accepts its time arguments in -file-time format. - -@node Time-Format Conversion, External Representation of Time, File Time, Date and Time -@subsection Time-Format Conversion - -The procedures described in this section convert times from one format -to another. - -@deffn procedure universal-time->local-decoded-time universal-time -@deffnx procedure universal-time->global-decoded-time universal-time -Converts an argument in universal-time format to decoded-time format. -The result is in the local time zone or UTC, respectively. - -@example -@group -(pp (universal-time->local-decoded-time (get-universal-time))) -@print{} #[decoded-time 21] -@print{} (second 23) -@print{} (minute 57) -@print{} (hour 17) -@print{} (day 29) -@print{} (month 4) -@print{} (year 1999) -@print{} (day-of-week 3) -@print{} (daylight-savings-time 1) -@print{} (zone 5) -@end group - -@group -(pp (universal-time->global-decoded-time - (get-universal-time))) -@print{} #[decoded-time 22] -@print{} (second 27) -@print{} (minute 57) -@print{} (hour 21) -@print{} (day 29) -@print{} (month 4) -@print{} (year 1999) -@print{} (day-of-week 3) -@print{} (daylight-savings-time 0) -@print{} (zone 0) -@end group -@end example -@end deffn - -@deffn procedure universal-time->file-time universal-time -Converts an argument in universal-time format to file-time format. - -@example -@group -(universal-time->file-time (get-universal-time)) - @result{} 925422988 -@end group -@end example -@end deffn - -@deffn procedure universal-time->local-time-string universal-time -@deffnx procedure universal-time->global-time-string universal-time -Converts an argument in universal-time format to a time string. The -result is in the local time zone or UTC, respectively. - -@example -@group -(universal-time->local-time-string (get-universal-time)) - @result{} "Thu, 29 Apr 1999 17:55:31 -0400" -(universal-time->global-time-string (get-universal-time)) - @result{} "Thu, 29 Apr 1999 21:55:51 +0000" -@end group -@end example -@end deffn - -@deffn procedure decoded-time->universal-time decoded-time -Converts an argument in decoded-time format to universal-time format. - -@example -@group -(decoded-time->universal-time (local-decoded-time)) - @result{} 3134411942 -(decoded-time->universal-time (global-decoded-time)) - @result{} 3134411947 -@end group -@end example -@end deffn - -@deffn procedure decoded-time->file-time decoded-time -Converts an argument in decoded-time format to file-time format. - -@example -@group -(decoded-time->file-time (local-decoded-time)) - @result{} 925423191 -(decoded-time->file-time (global-decoded-time)) - @result{} 925423195 -@end group -@end example -@end deffn - -@deffn procedure decoded-time->string decoded-time -Convert an argument in decoded-time format to a time string. - -@example -@group -(decoded-time->string (local-decoded-time)) - @result{} "Thu, 29 Apr 1999 18:00:43 -0400" -(decoded-time->string (global-decoded-time)) - @result{} "Thu, 29 Apr 1999 22:00:46 +0000" -@end group -@end example -@end deffn - -@deffn procedure file-time->universal-time file-time -Converts an argument in universal-time format to file-time format. - -@example -@group -(file-time->universal-time (file-modification-time "/")) - @result{} 3133891907 -@end group -@end example -@end deffn - -@deffn procedure file-time->local-decoded-time file-time -@deffnx procedure file-time->global-decoded-time file-time -Converts an argument in file-time format to decoded-time format. The -result is in the local time zone or UTC, respectively. - -@example -@group -(pp (file-time->local-decoded-time - (file-modification-time "/"))) -@print{} #[decoded-time 26] -@print{} (second 47) -@print{} (minute 31) -@print{} (hour 17) -@print{} (day 23) -@print{} (month 4) -@print{} (year 1999) -@print{} (day-of-week 4) -@print{} (daylight-savings-time 1) -@print{} (zone 5) -@end group - -@group -(pp (file-time->global-decoded-time - (file-modification-time "/"))) -@print{} #[decoded-time 27] -@print{} (second 47) -@print{} (minute 31) -@print{} (hour 21) -@print{} (day 23) -@print{} (month 4) -@print{} (year 1999) -@print{} (day-of-week 4) -@print{} (daylight-savings-time 0) -@print{} (zone 0) -@end group -@end example -@end deffn - -@deffn procedure file-time->local-time-string file-time -@deffnx procedure file-time->global-time-string file-time -Converts an argument in file-time format to a time string. The result -is in the local time zone or UTC, respectively. - -@example -@group -(file-time->local-time-string (file-modification-time "/")) - @result{} "Fri, 23 Apr 1999 17:31:47 -0400" -(file-time->global-time-string (file-modification-time "/")) - @result{} "Fri, 23 Apr 1999 21:31:47 +0000" -@end group -@end example -@end deffn - -@deffn procedure string->universal-time time-string -Converts a time-string argument to universal-time format. - -@example -@group -(string->universal-time "Fri, 23 Apr 1999 21:31:47 +0000") - @result{} 3133888307 -(string->universal-time "Fri, 23 Apr 1999 17:31:47 -0400") - @result{} 3133888307 -@end group -@end example -@end deffn - -@deffn procedure string->decoded-time time-string -Converts a time-string argument to decoded-time format. - -@example -@group -(pp (string->decoded-time "Fri, 23 Apr 1999 17:31:47 -0400")) -@print{} #[decoded-time 30] -@print{} (second 47) -@print{} (minute 31) -@print{} (hour 17) -@print{} (day 23) -@print{} (month 4) -@print{} (year 1999) -@print{} (day-of-week 4) -@print{} (daylight-savings-time 0) -@print{} (zone 4) -@end group -@end example -@end deffn - -@deffn procedure string->file-time time-string -Converts a time-string argument to file-time format. - -@example -@group -(string->file-time "Fri, 23 Apr 1999 17:31:47 -0400") - @result{} 924899507 -@end group -@end example -@end deffn - -@node External Representation of Time, , Time-Format Conversion, Date and Time -@subsection External Representation of Time - -The normal external representation for time is the time string, as -described above. The procedures in this section generate alternate -external representations of time which are more verbose and may be more -suitable for presentation to human readers. - -@deffn procedure decoded-time/date-string decoded-time -@deffnx procedure decoded-time/time-string decoded-time -These procedures return strings containing external representations of -the date and time, respectively, represented by @var{decoded-time}. The -results are implicitly in local time. - -@example -@group -(decoded-time/date-string (local-decoded-time)) - @result{} "Tuesday March 30, 1999" -(decoded-time/time-string (local-decoded-time)) - @result{} "11:22:38 AM" -@end group -@end example -@end deffn - -@deffn procedure day-of-week/long-string day-of-week -@deffnx procedure day-of-week/short-string day-of-week -Returns a string representing the given @var{day-of-week}. The argument -must be an exact non-negative integer between @code{0} and @code{6} -inclusive. @code{day-of-week/long-string} returns a long string that -fully spells out the name of the day. @code{day-of-week/short-string} -returns a shortened string that abbreviates the day to three letters. - -@example -@group -(day-of-week/long-string 0) @result{} "Monday" -(day-of-week/short-string 0) @result{} "Mon" -(day-of-week/short-string 3) @result{} "Thu" -@end group -@end example -@end deffn - -@deffn procedure month/long-string month -@deffnx procedure month/short-string month -Returns a string representing the given @var{month}. The argument must -be an exact non-negative integer between @code{1} and @code{12} -inclusive. @code{month/long-string} returns a long string that fully -spells out the name of the month. @code{month/short-string} returns a -shortened string that abbreviates the month to three letters. - -@example -@group -(month/long-string 1) @result{} "January" -(month/short-string 1) @result{} "Jan" -(month/short-string 10) @result{} "Oct" -@end group -@end example -@end deffn - -@deffn procedure time-zone->string -Returns a string corresponding to the given time zone. This string is -the same string that is used to generate RFC-822 time strings. - -@example -@group -(time-zone->string 5) @result{} "-0500" -(time-zone->string -4) @result{} "+0400" -(time-zone->string 11/2) @result{} "-0530" -@end group -@end example -@end deffn - -@node Machine Time, Subprocesses, Date and Time, Operating-System Interface -@section Machine Time - -The previous section dealt with procedures that manipulate clock time. -This section describes procedures that deal with computer time: elapsed -CPU time, elapsed real time, and so forth. These procedures are useful -for measuring the amount of time it takes to execute code. - -@cindex tick -Some of the procedures in this section manipulate a time representation -called @dfn{ticks}. A tick is a unit of time that is unspecified here -but can be converted to and from seconds by supplied procedures. A -count in ticks is represented as an exact integer. At present each tick -is one millisecond, but this may change in the future. - -@deffn procedure process-time-clock -Returns the amount of process time, in ticks, that has elapsed since -Scheme was started. Process time is measured by the operating system -and is time during which the Scheme process is computing. It does not -include time in system calls, but depending on the operating system it -may include time used by subprocesses. - -@example -(process-time-clock) @result{} 21290 -@end example -@end deffn - -@deffn procedure real-time-clock -Returns the amount of real time, in ticks, that has elapsed since Scheme -was started. Real time is the time measured by an ordinary clock. - -@example -(real-time-clock) @result{} 33474836 -@end example -@end deffn - -@deffn procedure internal-time/ticks->seconds ticks -Returns the number of seconds corresponding to @var{ticks}. The result -is always a real number. - -@example -@group -(internal-time/ticks->seconds 21290) @result{} 21.29 -(internal-time/ticks->seconds 33474836) @result{} 33474.836 -@end group -@end example -@end deffn - -@deffn procedure internal-time/seconds->ticks seconds -Returns the number of ticks corresponding to @var{seconds}. -@var{Seconds} must be a real number. - -@example -@group -(internal-time/seconds->ticks 20.88) @result{} 20880 -(internal-time/seconds->ticks 20.83) @result{} 20830 -@end group -@end example -@end deffn - -@deffn procedure system-clock -Returns the amount of process time, in seconds, that has elapsed since -Scheme was started. Roughly equivalent to: - -@example -(internal-time/ticks->seconds (process-time-clock)) -@end example - -@noindent -Example: - -@example -(system-clock) @result{} 20.88 -@end example -@end deffn - -@deffn procedure runtime -Returns the amount of process time, in seconds, that has elapsed since -Scheme was started. However, it does not include time spent in garbage -collection. - -@example -(runtime) @result{} 20.83 -@end example -@end deffn - -@deffn procedure with-timings thunk receiver -Calls @var{thunk} with no arguments. After @var{thunk} returns, -@var{receiver} is called with three arguments describing the time spent -while computing @var{thunk}: the elapsed run time, the amount of time -spent in the garbage collector, and the elapsed real time. All three -times are in ticks. - -This procedure is most useful for doing performance measurements, and is -designed to have relatively low overhead. - -@example -@group -(with-timings - (lambda () @r{@dots{} hairy computation @dots{}}) - (lambda (run-time gc-time real-time) - (write (internal-time/ticks->seconds run-time)) - (write-char #\space) - (write (internal-time/ticks->seconds gc-time)) - (write-char #\space) - (write (internal-time/ticks->seconds real-time)) - (newline))) -@end group -@end example -@end deffn - -@deffn procedure measure-interval runtime? procedure -Calls @var{procedure}, passing it the current process time, in seconds, -as an argument. The result of this call must be another procedure. -When @var{procedure} returns, the resulting procedure is -tail-recursively called with the ending time, in seconds, as an -argument. - -If @var{runtime?} is @code{#f}, the elapsed time is deducted from the -elapsed system time returned by @code{runtime}. - -While this procedure can be used for time measurement, its interface is -somewhat clumsy for that purpose. We recommend that you use -@code{with-timings} instead, because it is more convenient and has lower -overhead. - -@example -@group -(measure-interval #t - (lambda (start-time) - (let ((v @r{@dots{} hairy computation @dots{}})) - (lambda (end-time) - (write (- end-time start-time)) - (newline) - v)))) -@end group -@end example -@end deffn - -@node Subprocesses, TCP Sockets, Machine Time, Operating-System Interface -@section Subprocesses - -@cindex subprocess -@cindex synchronous subprocess -MIT/GNU Scheme provides the ability to run and control subprocesses. This -support is divided into two parts: a low-level set of primitives that -maps onto the underlying operating system's process-control primitives, -and a high-level set of procedures for starting a subprocess and running -it to completion in a single call. Subprocesses that are run in the -latter fashion are referred to as @dfn{synchronous}, because they are -started and stopped in synchrony with a Scheme procedure call. - -This chapter documents Scheme's high-level synchronous-subprocess -support. The low-level support is not documented but is available for -those who are willing to read the source code. - -Synchronous-subprocess support is a run-time-loadable option. To use -it, execute - -@example -(load-option 'synchronous-subprocess) -@end example - -@noindent -once before calling it. - -@menu -* Subprocess Procedures:: -* Subprocess Conditions:: -* Subprocess Options:: -@end menu - -@node Subprocess Procedures, Subprocess Conditions, Subprocesses, Subprocesses -@subsection Subprocess Procedures - -There are two commands for running synchronous subprocesses under -Scheme. @code{run-shell-command} is very simple to use, provides access -to all shell features, and is to be preferred in most situations. -@code{run-synchronous-subprocess} allows direct execution of a program -and precise control of the command-line arguments passed to the program, -but does not provide file globbing, I/O redirection, or other shell -features. - -@deffn procedure run-shell-command command option @dots{} -Runs @var{command}, which must be a string. @var{Command} is passed to -a command shell for interpretation; how the shell is chosen is detailed -below. - -The @var{option}s are a sequence of keyword/value pairs that specify -optional behavior. See below for more information about options. - -@code{run-shell-command} waits until the subprocess completes its -execution and returns the exit code from the subprocess. If the -subprocess is killed or stopped, an error is signalled and the procedure -does not return. -@end deffn - -@deffn procedure run-synchronous-subprocess program arguments option @dots{} -Runs @var{program}, passing it the given command-line @var{arguments}. -@var{Program} must be either the name of a program on the path, or else -a pathname to a specific program. @var{Arguments} must be a list of -strings; each string is a single command-line argument to the program. - -The @var{option}s are a sequence of keyword/value pairs that specify -optional behavior. See below for more information about options. - -@code{run-synchronous-subprocess} waits until the subprocess completes -its execution and returns the exit code from the subprocess. If the -subprocess is killed or stopped, an error is signalled and the procedure -does not return. -@end deffn - -@node Subprocess Conditions, Subprocess Options, Subprocess Procedures, Subprocesses -@subsection Subprocess Conditions - -If a subprocess spawned by one of the above procedures is killed or -suspended, then one of the following errors will be signalled. - -@deffn {condition type} condition-type:subprocess-signalled subprocess reason -This condition type is a subtype of -@code{condition-type:subprocess-abnormal-termination}. It is signalled -when the subprocess is killed. - -@var{Subprocess} is an object that represents the subprocess involved. -The internals of this object can be accessed but the interface is not -documented at this time; see the source code for details. - -@var{Reason} is interesting only on unix systems, where it is the signal -that killed the process. On other systems it has a fixed value that -conveys no useful information. -@end deffn - -@deffn {condition type} condition-type:subprocess-stopped subprocess reason -This condition type is a subtype of -@code{condition-type:subprocess-abnormal-termination}. It is signalled -when the subprocess is stopped or suspended. - -@var{Subprocess} is an object that represents the subprocess involved. -The internals of this object can be accessed but the interface is not -documented at this time; see the source code for details. - -@var{Reason} is interesting only on unix systems, where it is the signal -that stopped the process. On other systems it has a fixed value that -conveys no useful information. -@end deffn - -@deffn {condition type} condition-type:subprocess-abnormal-termination subprocess reason -This condition type is a subtype of @code{condition-type:error}. This -is an abstract type that is never signalled. It is provided so that -condition handlers can be bound to it. -@end deffn - -@node Subprocess Options, , Subprocess Conditions, Subprocesses -@subsection Subprocess Options - -The following subprocess options may be passed to -@code{run-shell-command} or @code{run-synchronous-subprocess}. These -options are passed as alternating keyword/value pairs, for example: - -@example -@group -(run-shell-command "ls /" - 'output my-output-port - 'output-buffer-size 8192) -@end group -@end example - -@noindent -The example shows a shell command being run with two options specified: -@code{output} and @code{output-buffer-size}. - -@deffn {subprocess option} input port -Specifies the standard input of the subprocess. @var{Port} may be an -input port, in which case characters are read from @var{port} and fed to -the subprocess until @var{port} reaches end-of-file. Alternatively, -@var{port} may be @code{#f}, indicating that the subprocess has no -standard input. - -The default value of this option is @code{#f}. - -@example -@group -(call-with-input-file "foo.in" - (lambda (port) - (run-shell-command "cat > /dev/null" 'input port))) -@end group -@end example -@end deffn - -@deffn {subprocess option} input-line-translation line-ending -Specifies how line-endings should be translated when writing characters -to the subprocess. Ignored if the @code{input} option is @code{#f}. -@var{Line-ending} must be either a string specifying the line ending, or -the symbol @code{default}, meaning to use the operating system's -standard line ending. In either case, newline characters to be written -to the @code{input} port are translated to the specified line ending -before being written. - -The default value of this option is @code{default}. - -@example -@group -(call-with-input-file "foo.in" - (lambda (port) - (run-shell-command "cat > /dev/null" - 'input port - 'input-line-translation "\r\n"))) -@end group -@end example -@end deffn - -@deffn {subprocess option} input-buffer-size n -Specifies the size of the input buffer for the standard input of the -subprocess. (This is the buffer on the Scheme side, and has nothing to -do with any buffering done on the subprocess side.) Ignored if the -@code{input} option is @code{#f}. @var{N} must be an exact positive -integer specifying the number of characters the buffer can hold. - -The default value of this option is @code{512}. - -@example -@group -(call-with-input-file "foo.in" - (lambda (port) - (run-shell-command "cat > /dev/null" - 'input port - 'input-buffer-size 4096))) -@end group -@end example -@end deffn - -@deffn {subprocess option} output port -Specifies the standard output and standard error of the subprocess. -@var{Port} may be an output port, in which case characters are read from -the subprocess and fed to @var{port} until the subprocess finishes. -Alternatively, @var{port} may be @code{#f}, indicating that the -subprocess has no standard output or standard error. - -The default value of this option is the value of -@code{(current-output-port)}. - -@example -@group -(call-with-output-file "foo.out" - (lambda (port) - (run-shell-command "ls -la /etc" 'output port))) -@end group -@end example -@end deffn - -@deffn {subprocess option} output-line-translation line-ending -Specifies how line-endings should be translated when reading characters -from the standard output of the subprocess. Ignored if the -@code{output} option is @code{#f}. @var{Line-ending} must be either a -string specifying the line ending, or the symbol @code{default}, meaning -to use the operating system's standard line ending. In either case, -newline characters read from the subprocess port are translated to the -specified line ending. - -The default value of this option is @code{default}. - -@example -@group -(call-with-output-file "foo.out" - (lambda (port) - (run-shell-command "ls -la /etc" - 'output port - 'output-line-translation "\r\n"))) -@end group -@end example -@end deffn - -@deffn {subprocess option} output-buffer-size n -Specifies the size of the output buffer for the standard output of the -subprocess. (This is the buffer on the Scheme side, and has nothing to -do with any buffering done on the subprocess side.) Ignored if the -@code{output} option is @code{#f}. @var{N} must be an exact positive -integer specifying the number of characters the buffer can hold. - -The default value of this option is @code{512}. - -@example -@group -(call-with-output-file "foo.out" - (lambda (port) - (run-shell-command "ls -la /etc" - 'output port - 'output-buffer-size 4096))) -@end group -@end example -@end deffn - -@deffn {subprocess option} redisplay-hook thunk -Specifies that @var{thunk} is to be run periodically when output from -the subprocess is available. @var{Thunk} must be a procedure of no -arguments, or @code{#f} indicating that no hook is supplied. This -option is mostly useful for interactive systems. For example, the Edwin -text editor uses this to update output buffers when running some -subprocesses. - -The default value of this option is @code{#f}. - -@example -@group -(run-shell-command "ls -la /etc" - 'redisplay-hook - (lambda () - (update-buffer-contents buffer))) -@end group -@end example -@end deffn - -@deffn {subprocess option} environment environment -Specifies the environment variables that are to be used for the -subprocess. @var{Environment} must be either a vector of strings or -@code{#f} indicating the default environment. If it is a vector of -strings, each string must be a name/value pair where the name and value -are separated by an equal sign, for example, @code{"foo=bar"}. To -define a variable with no value, just omit the value, as in @code{"foo="}. - -@vindex scheme-subprocess-environment -Note that the variable @code{scheme-subprocess-environment} is bound to -the default subprocess environment. - -The default value of this option is @code{#f}. - -@example -@group -(run-shell-command "ls -la /etc" - 'environment - (let* ((v scheme-subprocess-environment) - (n (vector-length v)) - (v (vector-grow v (+ n 1)))) - (vector-set! v n "TERM=none") - v)) -@end group -@end example -@end deffn - -@deffn {subprocess option} working-directory pathname -Specifies the working directory in which the subprocess will run. - -The default value of this option is @code{(working-directory-pathname)}. - -@example -@group -(run-shell-command "ls -la" 'working-directory "/etc/") -@end group -@end example -@end deffn - -@deffn {subprocess option} use-pty? boolean -This option is meaningful only on unix systems; on other systems it is -ignored. Specifies whether to communicate with the subprocess using -@sc{pty} devices; if true, @sc{pty}s will be used, otherwise pipes will -be used. - -The default value of this option is @code{#f}. - -@example -@group -(run-shell-command "ls -la /etc" 'use-pty? #t) -@end group -@end example -@end deffn - -@deffn {subprocess option} shell-file-name pathname -Specifies the shell program to use for @code{run-shell-command}. - -The default value of this option is @code{(os/shell-file-name)}. This -is the value of the environment variable @code{SHELL}, or if -@code{SHELL} is not set, the value is operating-system dependent as -follows: - -@itemize @bullet -@item -On unix systems, @file{/bin/sh} is used. - -@item -On OS/2 systems, the value of the environment variable @code{COMSPEC} is -used, or if that is not set, @file{cmd.exe} on the current path. - -@item -On Windows systems, the value of the environment variable @code{COMSPEC} -is used. If that is not set, @file{cmd.exe} is used for Windows NT, or -@file{command.com} is used for Windows 9x; in each case the shell is -found by searching the path. -@end itemize - -@example -@group -(run-shell-command "ls -la /etc" - 'shell-file-name "/usr/local/bin/bash") -@end group -@end example -@end deffn - -@node TCP Sockets, Miscellaneous OS Facilities, Subprocesses, Operating-System Interface -@section TCP Sockets - -@cindex socket -MIT/GNU Scheme provides access to @dfn{sockets}, which are a mechanism for -inter-process communication. @sc{tcp} stream sockets are supported, -which communicate between computers over a @sc{tcp/ip} network. -@sc{tcp} sockets are supported on all operating systems. - -@cindex client socket -@cindex server socket -@sc{tcp} sockets have two distinct interfaces: one interface to -implement a @dfn{client} and another to implement a @dfn{server}. The -basic protocol is that servers set up a listening port and wait for -connections from clients. Implementation of clients is simpler and will -be treated first. - -@cindex hostname, TCP -The socket procedures accept two special arguments, called -@var{host-name} and @var{service}. @var{Host-name} is a string which -must be the name of an internet host. It is looked up using the -ordinary lookup rules for your computer. For example, if your host is -@code{foo.mit.edu} and @var{host-name} is @code{"bar"}, then it -specifies @code{bar.mit.edu}. - -@cindex service, TCP -@cindex port number, TCP -@var{Service} specifies the service to which you will connect. A -networked computer normally provides several different services, such as -telnet or @acronym{FTP}. Each service is associated with a unique -@dfn{port number}; for example, the @code{"www"} service is associated -with port @code{80}. The @var{service} argument specifies the port -number, either as a string, or directly as an exact non-negative -integer. Port strings are decoded by the operating system using a -table; for example, on unix the table is in @file{/etc/services}. -Usually you will use a port string rather than a number. - -@deffn procedure open-tcp-stream-socket host-name service [buffer-size [line-translation]] -@code{open-tcp-stream-socket} opens a connection to the host specified -by @var{host-name}. @var{Host-name} is looked up using the ordinary -lookup rules for your computer. The connection is established to the -service specified by @var{service}. The returned value is an -@acronym{I/O} port, to which you can read and write characters using -ordinary Scheme @acronym{I/O} procedures such as @code{read-char} and -@code{write-char}. - -@var{Buffer-size} specifies the size of the read and write buffers used -by the port; if this is unspecified or @code{#f}, the buffers will hold -@code{4096} bytes. - -@var{Line-translation} specifies how end-of-line characters will be -translated when reading or writing to the socket. If this is -unspecified or @code{#f}, then lines will be terminated by @sc{cr-lf}, -which is the standard for most internet protocols. Otherwise, it must -be a string, which specifies the line-ending character sequence to use. - -When you wish to close the connection, just use @code{close-port}. - -As an example, here is how you can open a connection to a web server: - -@example -(open-tcp-stream-socket "web.mit.edu" "www") -@end example -@end deffn - -@cindex server socket -Next we will treat setting up a @sc{tcp} server, which is slightly more -complicated. Creating a server is a two-part process. First, you must -open a @dfn{server socket}, which causes the operating system to listen -to the network on a port that you specify. Once the server socket is -opened, the operating system will allow clients to connect to your -computer on that port. - -In the second step of the process, you @dfn{accept} the connection, -which completes the connection initiated by the client, and allows you -to communicate with the client. Accepting a connection does not affect -the server socket; it continues to listen for additional client -connections. You can have multiple client connections to the same -server socket open simultaneously. - -@deffn procedure open-tcp-server-socket service [address] -This procedure opens a server socket that listens for connections to -@var{service}; the socket will continue to listen until you close it. -The returned value is a server socket object. - -An error is signalled if another process is already listening on the -service. Additionally, ports whose number is less than @code{1024} are -privileged on many operating systems, and cannot be used by -non-privileged processes; if @var{service} specifies such a port and you -do not have administrative privileges, an error may be signalled. - -The optional argument @var{address} specifies the @acronym{IP} address -on which the socket will listen. If this argument is not supplied or is -given as @code{#f}, then the socket listens on all @acronym{IP} -addresses for this machine. (This is equivalent to passing the result -of calling @code{host-address-any}.) -@end deffn - -@deffn procedure tcp-server-connection-accept server-socket block? peer-address [line-translation] -Checks to see if a client has connected to @var{server-socket}. If -so, an @acronym{I/O} port is returned. The returned port can be read -and written using ordinary Scheme @acronym{I/O} procedures such as -@code{read-char} and @code{write-char}. - -The argument @var{block?} says what to do if no client has connected at -the time of the call. If @code{#f}, it says to return immediately with -two values of @code{#f}. Otherwise, the call waits until a client -connects. - -The argument @var{peer-address} is either @code{#f} or an @acronym{IP} -address as allocated by @code{allocate-host-address}. If it is an -@acronym{IP} address, the address is modified to be the address of the -client making the connection. - -The optional argument @var{line-translation} specifies how end-of-line -characters will be translated when reading or writing to the returned -socket. If this is unspecified or @code{#f}, then lines will be -terminated by @sc{cr-lf}, which is the standard for most internet -protocols. Otherwise, it must be a string, which specifies the -line-ending character sequence to use. - -Note that closing the port returned by this procedure does not affect -@var{server-socket}; it just closes the particular client connection -that was opened by the call. To close @var{server-socket}, use -@code{close-tcp-server-socket}. -@end deffn - -@deffn procedure close-tcp-server-socket server-socket -Closes the server socket @var{server-socket}. The operating system will -cease listening for network connections to that service. Client -connections to @var{server-socket} that have already been accepted will -not be affected. -@end deffn - -@node Miscellaneous OS Facilities, , TCP Sockets, Operating-System Interface -@section Miscellaneous OS Facilities - -This section contains assorted operating-system facilities that don't -fit into other categories. - -@defvr variable microcode-id/operating-system -@defvrx variable microcode-id/operating-system-name -@code{microcode-id/operating-system} is bound to a symbol that specifies -the type of operating system that Scheme is running under. There are -three possible values: @code{unix}, @code{os/2}, or @code{nt}. - -@code{microcode-id/operating-system-name} is a string containing the -same name as @code{microcode-id/operating-system}; the latter is created -by interning the former as a symbol. -@end defvr - -@defvr variable microcode-id/operating-system-variant -This variable is a string that identifies the particular variant of the -operating system that Scheme is running under. Here are some of the -possible values: - -@example -@group -"GNU/Linux" -"FreeBSD" -"HP-UX" -"SunOS" -"OS/2 2.1" -"OS/2 4.0" -"Microsoft Windows NT 4.0 (Build 1381; Service Pack 3)" -"Microsoft Windows 98 (Build 410)" -@end group -@end example - -@noindent -For Windows systems, it is recommended that you match on the prefix of -this string and ignore the @code{"Build"} suffix. This is because the -suffix may contain information about service packs or fixes, while the -prefix will be constant for a particular version of Windows. -@end defvr - -The next few procedures provide access to the @dfn{domain name service} -(@acronym{DNS}), which maintains associations between internet host -names such as @code{"www.swiss.ai.mit.edu"} and @acronym{IP} addresses, -such as @code{18.23.0.16}. In MIT/GNU Scheme, we represent an internet host -name as a string, and an @acronym{IP} address as a byte vector of length -4 (byte vectors are just character strings that are accessed using -@code{vector-8b-ref} rather than @code{string-ref}). The bytes in an -@acronym{IP} address read in the same order as they do when written out: - -@example -(get-host-by-name "www.swiss") @result{} #("\022\027\000\020") -@end example - -@deffn procedure get-host-by-name host-name -Looks up the internet host name @var{host-name} using the @acronym{DNS}, -returning a vector of @acronym{IP} addresses for the corresponding host, -or @code{#f} if there is no such host. Usually the returned vector has -only one element, but if a host has more than one network interface, the -vector might have more than one element. - -@example -(get-host-by-name "www.swiss") @result{} #("\022\027\000\020") -@end example -@end deffn - -@deffn procedure get-host-by-address ip-address -Does a reverse @acronym{DNS} lookup on @var{ip-address}, returning the -internet host name corresponding to that address, or @code{#f} if there -is no such host. - -@example -(get-host-by-address "\022\027\000\020") @result{} "swissnet.ai.mit.edu" -@end example -@end deffn - -@deffn procedure canonical-host-name host-name -Finds the ``canonical'' internet host name for @var{host-name}. For -example: - -@example -@group -(canonical-host-name "zurich") @result{} "zurich.ai.mit.edu" -(canonical-host-name "www.swiss") @result{} "swissnet.ai.mit.edu" -@end group -@end example - -@noindent -In both examples, the default internet domain @samp{ai.mit.edu} is added -to @var{host-name}. In the second example, @code{"www.swiss"} is an -alias for another computer named @code{"swissnet"}. -@end deffn - -@deffn procedure get-host-name -Returns the string that identifies the computer that MIT/GNU Scheme is -running on. Usually this is an unqualified internet host name, i.e.@: -the host name without the domain suffix: - -@example -(get-host-name) @result{} "aarau" -@end example -@end deffn - -@deffn procedure os/hostname -Returns the canonical internet host name of the computer that MIT/GNU Scheme -is running on. So, in contrast to the example for @code{get-host-name}: - -@example -(os/hostname) @result{} "aarau.ai.mit.edu" -@end example -@end deffn - -@deffn procedure allocate-host-address -Allocates and returns an @acronym{IP} address object. This is just a -string of a fixed length (current 4 bytes) into which an @acronym{IP} -address may be stored. This procedure is used to generate an -appropriate argument to be passed to -@code{tcp-server-connection-accept}. - -@example -(allocate-host-address) @result{} "Xe\034\241" -@end example -@end deffn - -@deffn procedure host-address-any -Return an @acronym{IP} address object that specifies ``any host''. This -object is useful only when passed as the @var{address} argument to -@code{open-tcp-server-socket}. - -@example -(host-address-any) @result{} "\000\000\000\000" -@end example -@end deffn - -@deffn procedure host-address-loopback -@cindex loopback interface -Return an @acronym{IP} address object that specifies the local -@dfn{loopback} network interface. The loopback interface is a software -network interface that can be used only for communicating between -processes on the same computer. This address object is useful only when -passed as the @var{address} argument to @code{open-tcp-server-socket}. - -@example -(host-address-loopback) @result{} "\177\000\000\001" -@end example -@end deffn - -@node Error System, Graphics, Operating-System Interface, Top -@chapter Error System - -@findex error -The MIT/GNU Scheme error system provides a uniform mechanism for the -signalling of errors and other exceptional conditions. The simplest and -most generally useful procedures in the error system are: - -@table @code -@item error -is used to signal simple errors, specifying a message and some irritant -objects (@pxref{Condition Signalling}). Errors are usually handled by -stopping the computation and putting the user in an error @sc{repl}. - -@item warn -is used to signal warnings (@pxref{Condition Signalling}). Warnings are -usually handled by printing a message on the console and continuing the -computation normally. - -@item ignore-errors -is used to suppress the normal handling of errors within a given dynamic -extent (@pxref{Condition Handling}). Any error that occurs within the -extent is trapped, returning immediately to the caller of -@code{ignore-errors}. -@end table - -More demanding applications require more powerful facilities. To give a -concrete example, suppose you want floating-point division to return a very -large number whenever the denominator is zero. This behavior can be -implemented using the error system. - -The Scheme arithmetic system can signal many different kinds of errors, -including floating-point divide by zero. In our example, we would like to -handle this particular condition specially, allowing the system to handle -other arithmetic errors in its usual way. - -The error system supports this kind of application by providing -mechanisms for distinguishing different types of error conditions and -for specifying where control should be transferred should a given -condition arise. In this example, there is a specific object that -represents the ``floating-point divide by zero'' condition type, and it -is possible to dynamically specify an arbitrary Scheme procedure to be -executed when a condition of that type is signalled. This procedure -then finds the stack frame containing the call to the division operator, -and returns the appropriate value from that frame. - -Another useful kind of behavior is the ability to specify uniform -handling for related classes of conditions. For example, it might be -desirable, when opening a file for input, to gracefully handle a variety of -different conditions associated with the file system. One such condition -might be that the file does not exist, in which case the program will try -some other action, perhaps opening a different file instead. Another -related condition is that the file exists, but is read protected, so it -cannot be opened for input. If these or any other related conditions -occur, the program would like to skip this operation and move on to -something else. - -At the same time, errors unrelated to the file system should be treated in -their usual way. For example, calling @code{car} on the argument @code{3} -should signal an error. Or perhaps the name given for the file is -syntactically incorrect, a condition that probably wants to be handled -differently from the case of the file not existing. - -@cindex taxonomical link, of condition type (defn) -@cindex specialization, of condition types (defn) -@cindex generalization, of condition types (defn) -To facilitate the handling of classes of conditions, the error system -taxonomically organizes all condition types. The types are related to one -another by @dfn{taxonomical links}, which specify that one type is a ``kind -of'' another type. If two types are linked this way, one is considered to -be a @dfn{specialization} of the other; or vice-versa, the second is a -@dfn{generalization} of the first. In our example, all of the errors -associated with opening an input file would be specializations of the -condition type ``cannot open input file''. - -@vindex condition-type:simple-condition -@vindex condition-type:warning -@vindex condition-type:breakpoint -@vindex condition-type:serious-condition -The taxonomy of condition types permits any condition type to have no -more than one immediate generalization. Thus, the condition types form -a forest (set of trees). While users can create new trees, the standard -taxonomy (@pxref{Taxonomy}) is rooted at -@code{condition-type:serious-condition}, @code{condition-type:warning}, -@code{condition-type:simple-condition}, and -@code{condition-type:breakpoint}; users are encouraged to add new -subtypes to these condition types rather than create new trees in the -forest. - -To summarize, the error system provides facilities for the following tasks. -The sections that follow will describe these facilities in more -detail. - -@table @asis -@item Signalling a condition -@findex signal-condition -A condition may be signalled in a number of different ways. Simple -errors may be signalled, without explicitly defining a condition type, -using @code{error}. The @code{signal-condition} procedure provides the -most general signalling mechanism. - -@item Handling a condition -@findex bind-condition-handler -The programmer can dynamically specify handlers for particular condition -types or for classes of condition types, by means of the -@code{bind-condition-handler} procedure. Individual handlers have -complete control over the handling of a condition, and additionally may -decide not to handle a particular condition, passing it on to previously -bound handlers. - -@item Restarting from a handler -@findex with-restart -The @code{with-restart} procedure provides a means for -condition-signalling code to communicate to condition-handling code what -must be done to proceed past the condition. Handlers can examine the -restarts in effect when a condition was signalled, allowing a structured -way to continue an interrupted computation. - -@item Packaging condition state -Each condition is represented by an explicit object. Condition objects -contain information about the nature of the condition, information that -describes the state of the computation from which the condition arose, -and information about the ways the computation can be restarted. - -@item Classification of conditions -@cindex condition type -@cindex type, condition -@cindex specialization, of condition types -@cindex generalization, of condition types -Each condition has a type, represented by a condition type object. Each -condition type may be a specialization of some other condition types. A -group of types that share a common generalization can be handled -uniformly by specifying a handler for the generalization. -@end table - -@menu -* Condition Signalling:: -* Error Messages:: -* Condition Handling:: -* Restarts:: -* Condition Instances:: -* Condition Types:: -* Taxonomy:: -@end menu - -@node Condition Signalling, Error Messages, Error System, Error System -@section Condition Signalling - -@cindex condition signalling (defn) -@cindex signalling, of condition (defn) -@findex make-condition -Once a condition instance has been created using @code{make-condition} -(or any condition constructor), it can be @dfn{signalled}. The act of -signalling a condition is separated from the act of creating the -condition to allow more flexibility in how conditions are handled. For -example, a condition instance could be returned as the value of a -procedure, indicating that something unusual has happened, to allow the -caller to clean up some state. The caller could then signal the -condition once it is ready. - -A more important reason for having a separate condition-signalling -mechanism is that it allows @emph{resignalling}. When a signalled -condition has been caught by a particular handler, and the handler decides -that it doesn't want to process that particular condition, it can signal -the condition again. This is one way to allow other handlers to get a -chance to see the condition. - -@deffn procedure error reason argument @dots{} -@cindex REP loop -@findex signal-condition -@findex warn -This is the simplest and most common way to signal a condition that -requires intervention before a computation can proceed (when -intervention is not required, @code{warn} is more appropriate). -@code{error} signals a condition (using @code{signal-condition}), and if -no handler for that condition alters the flow of control (by invoking a -restart, for example) it calls the procedure -@code{standard-error-handler}, which normally prints an error message -and stops the computation, entering an error @sc{repl}. Under normal -circumstances @code{error} will not return a value (although an -interactive debugger can be used to force this to occur). - -@findex make-condition -@vindex condition-type:simple-error -Precisely what condition is signalled depends on the first argument to -@code{error}. If @var{reason} is a condition, then that condition is -signalled and the @var{argument}s are ignored. If @var{reason} is a -condition type, then a new instance of this type is generated and -signalled; the @var{argument}s are used to generate the values of the -fields for this condition type (they are passed as the @var{field-plist} -argument to @code{make-condition}). In the most common case, however, -@var{reason} is neither a condition nor a condition type, but rather a -string or symbol. In this case a condition of type -@code{condition-type:simple-error} is created with the @var{message} -field containing the @var{reason} and the @var{irritants} field -containing the @var{argument}s. -@end deffn - -@deffn procedure warn reason argument @dots{} -@findex error -@findex signal-condition -@vindex condition-type:simple-warning -When a condition is not severe enough to warrant intervention, it is -appropriate to signal the condition with @code{warn} rather than -@code{error}. As with @code{error}, @code{warn} first calls -@code{signal-condition}; the condition that is signalled is chosen -exactly as in @code{error} except that a condition of type -@code{condition-type:simple-warning} is signalled if @var{reason} is -neither a condition nor a condition type. If the condition is not -handled, @code{warn} calls the procedure -@code{standard-warning-handler}, which normally prints a warning message -and continues the computation by returning from @code{warn}. - -@findex muffle-warning -@code{warn} establishes a restart named @code{muffle-warning} before -calling @code{signal-condition}. This allows a signal handler to -prevent the generation of the warning message by calling -@code{muffle-warning}. The value of a call to @code{warn} is -unspecified. -@end deffn - -@deffn procedure signal-condition condition -@cindex generalization, of condition types -@cindex specialization, of condition types -@findex break-on-signals -@findex bind-default-condition-handler -@findex bind-condition-handler -This is the fundamental operation for signalling a condition. The -precise operation of @code{signal-condition} depends on the condition -type of which @var{condition} is an instance, the condition types set by -@code{break-on-signals}, and the handlers established by -@code{bind-condition-handler} and @code{bind-default-condition-handler}. - -@cindex REP loop -If the @var{condition} is an instance of a type that is a specialization -of any of the types specified by @code{break-on-signals}, then a -breakpoint @sc{repl} is initiated. Otherwise (or when that @sc{repl} -returns), the handlers established by @code{bind-condition-handler} are -checked, most recent first. Each applicable handler is invoked, and the -search for a handler continues if the handler returns normally. If all -applicable handlers return, then the applicable handlers established by -@code{bind-default-condition-handler} are checked, again most recent -first. Finally, if no handlers apply (or all return in a normal -manner), @code{signal-condition} returns an unspecified value. - -@emph{Note:} unlike many other systems, the MIT/GNU Scheme runtime library -does @emph{not} establish handlers of any kind. (However, the Edwin -text editor uses condition handlers extensively.) Thus, calls to -@code{signal-condition} will return to the caller unless there are user -supplied condition handlers, as the following example shows: - -@example -@group -(signal-condition - (make-condition - condition-type:error - (call-with-current-continuation (lambda (x) x)) - '() @r{; no restarts} - '())) @r{; no fields} -@result{} @r{unspecified} -@end group -@end example -@end deffn - -@node Error Messages, Condition Handling, Condition Signalling, Error System -@section Error Messages - -@cindex error messages, conventions -@cindex conventions for error messages -By convention, error messages (and in general, the reports generated by -@code{write-condition-report}) should consist of one or more complete -sentences. The usual rules for sentences should be followed: the first -word of the sentence should be capitalized, and the sentence should be -terminated by a period. The message should not contain extraneous -whitespace such as line breaks or indentation. - - -The error system provides a simple formatting language that allows the -programmer to have some control over the printing of error messages. -This formatting language will probably be redesigned in a future -release. - -@findex display -@findex write -Error messages typically consist of a string describing the error, -followed by some irritant objects. The string is printed using -@code{display}, and the irritants are printed using @code{write}, -typically with a space between each irritant. To allow simple -formatting, we introduce a @dfn{noise} object, printed using -@code{display}. The irritant list may contain ordinary objects -interspersed with noise objects. Each noise object is printed using -@code{display}, with no extra whitespace, while each normal object is -printed using @code{write}, prefixed by a single space character. - -Here is an example: - -@example -@group -(define (error-within-procedure message irritant procedure) - (error message - irritant - (error-irritant/noise "within procedure") - procedure - (error-irritant/noise "."))) -@end group -@end example - -@noindent -This would format as follows: - -@example -@group -(error-within-procedure "Bad widget" 'widget-32 'invert-widget) @error{} - -Bad widget widget-32 within procedure invert-widget. -@end group -@end example - -Here are the operations supporting error messages: - -@deffn procedure format-error-message message irritants port -@var{Message} is typically a string (although this is not required), -@var{irritants} a list of irritant objects, and @var{port} an output -port. Formats @var{message} and @var{irritants} to @var{port} in the -standard way. Note that, during the formatting process, the depth and -breadth to which lists are printed are each limited to small numbers, to -guarantee that the output from each irritant is not arbitrarily large. -@end deffn - -@deffn procedure error-irritant/noise value -Creates and returns a noise object whose value is @var{value}. -@end deffn - -@node Condition Handling, Restarts, Error Messages, Error System -@section Condition Handling - -@cindex handler, condition (defn) -@cindex condition handler (defn) -@findex bind-condition-handler -@findex bind-default-condition-handler -The occurrence of a condition is signalled using -@code{signal-condition}. @code{signal-condition} attempts to locate and -invoke a @dfn{condition handler} that is prepared to deal with the type -of condition that has occurred. A condition handler is a procedure of -one parameter, the condition that is being signalled. A procedure is -installed as a condition handler by calling -@code{bind-condition-handler} (to establish a handler that is in effect -only while a particular thunk is executing) or -@code{bind-default-condition-handler} (to establish a handler that is in -effect permanently). As implied by the name, handlers created by -@code{bind-default-condition-handler} are invoked only after all other -applicable handlers have been invoked. - -A @var{handler} may process a signal in any way it deems appropriate, -but the common patterns are: - -@table @asis -@item Ignore the condition. -By returning from the handler in the usual manner. - -@item Handle the condition. -By doing some processing and then invoking a restart (or, less -preferably, a continuation) that was established at some point prior to -the call to @code{signal-condition}. - -@item Resignal a condition. -By doing some processing and calling @code{signal-condition} with either -the same condition or a newly created one. In order to support this, -@code{signal-condition} runs @var{handler} in such a way that a -subsequent call to @code{signal-condition} sees only the handlers that -were established prior to this one. -@end table - -@cindex REP loop -@findex break-on-signals -As an aid to debugging condition handlers, Scheme maintains a set of -condition types that will cause an interactive breakpoint to occur prior -to normal condition signalling. That is, @code{signal-condition} -creates a new @sc{repl} prior to its normal operation when its argument -is a condition that is a specialization of any of these types. The -procedure @code{break-on-signals} establishes this set of condition -types. - -@deffn procedure ignore-errors thunk -@findex error -@vindex condition-type:error -Executes @var{thunk} with a condition handler that intercepts the -signalling of any specialization of @code{condition-type:error} -(including those produced by calls to @code{error}) and immediately -terminates the execution of @var{thunk} and returns from the call to -@code{ignore-errors} with the signalled condition as its value. If -@var{thunk} returns normally, its value is returned from -@code{ignore-errors}. - -Notice that @code{ignore-errors} does not ``turn off signalling'' or -condition handling. Condition handling takes place in the normal manner -but conditions specialized from @code{condition-type:error} are trapped -rather than propogated as they would be by default. -@end deffn - -@deffn procedure bind-condition-handler condition-types handler thunk -@findex signal-condition -Invokes @var{thunk} after adding @var{handler} as a condition handler -for the conditions specified by @var{condition-types}. -@var{Condition-types} must be a list of condition types; signalling a -condition whose type is a specialization of any of these types will -cause the @var{handler} to be invoked. See @code{signal-condition} for -a description of the mechanism used to invoke handlers. - -By special extension, if @var{condition-types} is the empty list then -the @var{handler} is called for all conditions. -@end deffn - -@deffn procedure bind-default-condition-handler condition-types handler -@findex signal-condition -Installs @var{handler} as a (permanent) condition handler for the -conditions specified by @var{condition-types}. @var{Condition-types} -must be a list of condition types; signalling a condition whose type is -a specialization of any of these types will cause the @var{handler} to -be invoked. See @code{signal-condition} for a description of the -mechanism used to invoke handlers. - -By special extension, if @var{condition-types} is the empty list then -the @var{handler} is called for all conditions. -@end deffn - -@deffn procedure break-on-signals condition-types -@findex signal-condition -@cindex REP loop -Arranges for @code{signal-condition} to create an interactive @sc{repl} -before it signals a condition that is a specialization of any of the -types in the list of @var{condition-types}. This can be extremely -helpful when trying to debug code that uses custom condition handlers. -In order to create a @sc{repl} when @emph{any} condition type is -signalled it is best to actually put a breakpoint on entry to -@code{signal-condition}. -@end deffn - -@deffn procedure standard-error-handler condition -@findex error -@findex ignore-error -@vindex standard-error-hook -@cindex REP loop -Called internally by @code{error} after it calls -@code{signal-condition}. Normally creates creates a new @sc{repl} with -the prompt @code{"error>"} (but see @code{standard-error-hook}). In -order to simulate the effect of calling @code{error}, code may call -@code{signal-condition} directly and then call -@code{standard-error-handler} if @code{signal-condition} returns. -@end deffn - -@defvr variable standard-error-hook -@findex standard-error-handler -@cindex fluid binding -@cindex dynamic binding -@cindex REP loop -This variable controls the behavior of the procedure -@code{standard-error-handler}, and hence @code{error}. It is intended -to be bound with @code{fluid-let} and is normally @code{#f}. It may be -changed to a procedure of one argument and will then be invoked (with -@code{standard-error-hook} rebound to @code{#f}) by -@code{standard-error-handler} just prior to starting the error -@sc{repl}. It is passed one argument, the condition being signalled. -@end defvr - -@deffn procedure standard-warning-handler condition -@vindex standard-warning-hook -@findex signal-condition -@findex notification-output-port -@findex write-condition-report -This is the procedure called internally by @code{warn} after it calls -@code{signal-condition}. The normal behavior of -@code{standard-warning-handler} is to print a message (but see -@code{standard-warning-hook}). More precisely, the message is printed -to the port returned by @code{notification-output-port}. The message is -formed by first printing the string @code{"Warning: "} to this port, and -then calling @code{write-condition-report} on @var{condition} and the port. - -@findex muffle-warning -In order to simulate the effect of calling @code{warn}, code may call -@code{signal-condition} directly and then call -@code{standard-warning-handler} if @code{signal-condition} returns. -(This is not sufficient to implement the @code{muffle-warning} protocol, -however. For that purpose an explicit restart must be provided.) -@end deffn - -@defvr variable standard-warning-hook -@findex standard-warning-handler -@cindex fluid binding -@cindex dynamic binding -This variable controls the behavior of the procedure -@code{standard-warning-handler}, and hence @code{warn}. It is intended -to be bound with @code{fluid-let} and is normally @code{#f}. It may be -changed to a procedure of one argument and will then be invoked (with -@code{standard-warning-hook} rebound to @code{#f}) by -@code{standard-warning-handler} in lieu of writing the warning message. -It is passed one argument, the condition being signalled. -@end defvr - -@node Restarts, Condition Instances, Condition Handling, Error System -@section Restarts - -@cindex restart effector (defn) -@cindex effector, restart (defn) -@cindex restart (defn) -@findex with-restart -@findex with-simple-restart -The Scheme error system provides a mechanism, known as @dfn{restarts}, -that helps coordinate condition-signalling code with condition-handling -code. A module of code that detects and signals conditions can provide -procedures (using @code{with-simple-restart} or @code{with-restart}) to -be invoked by handlers that wish to continue, abort, or restart the -computation. These procedures, called @dfn{restart effectors}, are -encapsulated in restart objects. - -@findex find-restart -@findex invoke-restart -@findex invoke-restart-interactively -When a condition object is created, it contains a set of restart -objects, each of which contains a restart effector. Condition handlers -can inspect the condition they are handling (using @code{find-restart} -to find restarts by name, or @code{condition/restarts} to see the entire -set), and they can invoke the associated effectors (using -@code{invoke-restart} or @code{invoke-restart-interactively}). -Effectors can take arguments, and these may be computed directly by the -condition-handling code or by gathering them interactively from the -user. - -@findex abort -@findex continue -@findex muffle-warning -@findex retry -@findex store-value -@findex use-value -@cindex protocol, restart (defn) -@cindex restart protocol -The names of restarts can be chosen arbitrarily, but the choice of name -is significant. These names are used to coordinate between the -signalling code (which supplies names for restarts) and the handling -code (which typically chooses a restart effector by the name of its -restart). Thus, the names specify the @dfn{restart protocol} -implemented by the signalling code and invoked by the handling code. -The protocol indicates the number of arguments required by the effector -code as well as the semantics of the arguments. - -Scheme provides a conventional set of names (hence, protocols) for -common use. By choosing the names of restarts from this set, signalling -code can indicate that it is able to perform a small set of fairly -common actions (@code{abort}, @code{continue}, @code{muffle-warning}, -@code{retry}, @code{store-value}, @code{use-value}). In turn, simple -condition-handling code can look for the kind of action it wishes to -perform and simply invoke it by name. All of Scheme's conventional -names are symbols, although in general restart names are not restricted -to any particular data type. In addition, the object @code{#f} is -reserved to indicate the ``not for automated use'' protocol: these -restarts should be activated only under human control. - -@findex with-simple-restart -Restarts themselves are first-class objects. They encapsulate their -name, a procedure (known as the @var{effector}) to be executed if they -are invoked, and a thunk (known as the @var{reporter}) that can be -invoked to display a description of the restart (used, for example, by -the interactive debugger). Invoking a restart is an indication that a -handler has chosen to accept control for a condition; as a consequence, -the @var{effector} of the restart should not return, since this would -indicate that the handler declined to handle the condition. Thus, the -@var{effector} should call a continuation captured before the -condition-signalling process began. The most common pattern of usage by -signalling code is encapsulated in @code{with-simple-restart}. - -Within this chapter, a parameter named @var{restarts} will accept any of -the following values: - -@itemize @bullet -@item -A list of restart objects. - -@item -A condition. The procedure @code{condition/restarts} is called on the -condition, and the resulting list of restarts is used in place of the -condition. - -@item -The symbol @code{bound-restarts}. The procedure @code{bound-restarts} -is called (with no arguments), and the resulting list of restarts is -used in place of the symbol. - -@item -If the @var{restarts} parameter is optional and is not supplied, it is -equivalent to having specified the symbol @code{bound-restarts}. -@end itemize - -@menu -* Establishing Restart Code:: -* Invoking Standard Restart Code:: -* Finding and Invoking General Restart Code:: -* The Named Restart Abstraction:: -@end menu - -@node Establishing Restart Code, Invoking Standard Restart Code, Restarts, Restarts -@subsection Establishing Restart Code - -@deffn procedure with-simple-restart name reporter thunk -Invokes @var{thunk} in a dynamic environment created by adding a restart -named @var{name} to the existing named restarts. @var{Reporter} may be -used during the execution of @var{thunk} to produce a description of the -newly created restart; it must either be a procedure of one argument (a -port) or a string. By convention, the description generated by -@var{reporter} should be a short complete sentence, with first word -capitalized and terminated by a period. The sentence should fit on one -line with a little room to spare (see the examples below); usually this -means that the sentence should be 70 characters or less in length. - -If the restart created by @code{with-simple-restart} is invoked it -simply aborts the computation in progress by returning an unspecified -value from the call to @code{with-simple-restart}. Otherwise -@code{with-simple-restart} returns the value computed by @var{thunk}. -@end deffn - -@example -@group -(with-simple-restart 'george "This restart is named george." - (lambda () 3)) @result{} 3 - -(with-simple-restart 'george "This restart is named george." - (lambda () - (invoke-restart (find-restart 'george)))) @result{} @code{unspecific} - -(with-simple-restart 'george "This restart is named george." - (lambda () (car 3))) -;The object 3, passed as the first argument to car, -; is not the correct type. -;To continue, call RESTART with an option number: -; (RESTART 3) => Specify an argument to use in its place. -; (RESTART 2) => This restart is named george. -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn procedure with-restart name reporter effector interactor thunk -@findex invoke-restart -Invokes @var{thunk} in a dynamic environment created by adding a restart -named @var{name} to the existing named restarts. @var{Reporter} may be -used during the execution of @var{thunk} to produce a description of the -newly created restart; it must either be a procedure of one argument (a -port) or a string. @var{Effector} is a procedure which will be called -when the restart is invoked by @code{invoke-restart}. @var{Interactor} -specifies the arguments that are to be passed to @var{effector} when it -is invoked interactively; it may be either a procedure of no arguments, -or @code{#f}. If @var{interactor} is @code{#f}, this restart is not -meant to be invoked interactively. - -The value returned by @code{with-restart} is the value returned by -@var{thunk}. Should the restart be invoked by a condition handler, -however, the @var{effector} will not return back to the handler that -invoked it. Instead, the @var{effector} should call a continuation -created before the condition-signalling process began, and -@code{with-restart} will therefore not return in the normal manner. -@end deffn - -@example -@group -(define (by-george! thunk) - @r{; This code handles conditions that arise while executing @var{thunk}} - @r{; by invoking the GEORGE restart, passing 1 and 2 to the restart's} - @r{; @var{effector} code.} - (bind-condition-handler '() ; All conditions - (lambda (condition) - (invoke-restart (find-restart 'george) 1 2)) - thunk)) -@end group - -@group -(define (can-george! thunk) - @r{; This code provides a way of handling errors: the GEORGE restart.} - @r{; In order to GEORGE you must supply two values.} - (lambda () - (call-with-current-continuation - (lambda (kappa) - (with-restart - 'george @r{; Name} - "This restart is named george." @r{; Reporter} - (lambda (a b) @r{; Effector} - (kappa (list 'george a b))) - values @r{; Interactor} - thunk))))) @r{; Thunk} -@end group - -@group -(by-george! (can-george! (lambda () -3)) @result{} -3 -(by-george! (can-george! (lambda () (car 'x)))) @result{} (george 1 2) -@end group -@end example - -@node Invoking Standard Restart Code, Finding and Invoking General Restart Code, Establishing Restart Code, Restarts -@subsection Invoking Standard Restart Code - -Scheme supports six standard protocols for restarting from a condition, -each encapsulated using a named restart (for use by condition-signalling -code) and a simple procedure (for use by condition-handling code). -Unless otherwise specified, if one of these procedures is unable to find -its corresponding restart, it returns immediately with an unspecified -value. - -Each of these procedures accepts an optional argument @var{restarts}, -which is described above in @ref{Restarts}. - -@deffn procedure abort [restarts] -@cindex REP loop -Abort the computation, using the restart named @code{abort}. The -corresponding effector takes no arguments and abandons the current line -of computation. This is the restart provided by Scheme's @sc{repl}. - -@vindex condition-type:no-such-restart -If there is no restart named @code{abort}, this procedure signals an -error of type @code{condition-type:no-such-restart}. -@end deffn - -@deffn procedure continue [restarts] -Continue the current computation, using the restart named -@code{continue}. The corresponding effector takes no arguments and -continues the computation beyond the point at which the condition was -signalled. -@end deffn - -@deffn procedure muffle-warning [restarts] -@findex warn -Continue the current computation, using the restart named -@code{muffle-warning}. The corresponding effector takes no arguments -and continues the computation beyond the point at which any warning -message resulting from the condition would be presented to the user. -The procedure @code{warn} establishes a @code{muffle-warning} restart -for this purpose. - -@vindex condition-type:no-such-restart -If there is no restart named @code{muffle-warning}, this procedure -signals an error of type @code{condition-type:no-such-restart}. -@end deffn - -@deffn procedure retry [restarts] -Retry the current computation, using the restart named @code{retry}. -The corresponding effector takes no arguments and simply retries the -same computation that triggered the condition. The condition may -reoccur, of course, if the root cause has not been eliminated. The code -that signals a ``file does not exist'' error can be expected to supply a -@code{retry} restart. The restart would be invoked after first creating -the missing file, since the computation is then likely to succeed if it -is simply retried. -@end deffn - -@deffn procedure store-value new-value [restarts] -Retry the current computation, using the restart named -@code{store-value}, after first storing @var{new-value}. The -corresponding effector takes one argument, @var{new-value}, and stores -it away in a restart-dependent location, then retries the same -computation that triggered the condition. The condition may reoccur, of -course, if the root cause has not been eliminated. The code that -signals an ``unassigned variable'' error can be expected to supply a -@code{store-value} restart; this would store the value in the variable -and continue the computation. -@end deffn - -@deffn procedure use-value new-value [restarts] -@findex retry -@findex store-value -Retry the current computation, using the restart named @code{use-value}, -but substituting @var{new-value} for a value that previously caused a -failure. The corresponding effector takes one argument, -@var{new-value}, and retries the same computation that triggered the -condition with the new value substituted for the failing value. The -condition may reoccur, of course, if the new value also induces the -condition. - -The code that signals an ``unassigned variable'' error can be expected -to supply a @code{use-value} restart; this would simply continue the -computation with @var{new-value} instead of the value of the variable. -Contrast this with the @code{retry} and @code{store-value} restarts. If -the @code{retry} restart is used it will fail because the variable still -has no value. The @code{store-value} restart could be used, but it -would alter the value of the variable, so that future references to the -variable would not be detected. -@end deffn - -@node Finding and Invoking General Restart Code, The Named Restart Abstraction, Invoking Standard Restart Code, Restarts -@subsection Finding and Invoking General Restart Code - -@findex with-restart -@findex with-simple-restart -@findex bound-restart -@findex find-restart -@findex invoke-restart -@findex invoke-restart-interactively -Restarts are a general mechanism for establishing a protocol between -condition-signalling and condition-handling code. The Scheme error -system provides ``packaging'' for a number of common protocols. It also -provides lower-level hooks that are intended for implementing customized -protocols. The mechanism used by signalling code (@code{with-restart} -and @code{with-simple-restart}) is used for both purposes. - -Four additional operations are provided for the use of -condition-handling code. Two operations (@code{bound-restarts} and -@code{find-restart}) allow condition-handling code to locate active -restarts. The other two operations (@code{invoke-restart} and -@code{invoke-restart-interactively}) allow restart effectors to be -invoked once the restart object has been located. - -In addition, there is a data abstraction that provides access to the -information encapsulated in restart objects. - -@deffn procedure bound-restarts -Returns a list of all currently active restart objects, most recently -installed first. @code{bound-restarts} should be used with caution by -condition-handling code, since it reveals all restarts that are active -at the time it is called, rather than at the time the condition was -signalled. It is useful, however, for collecting the list of restarts -for inclusion in newly generated condition objects or for inspecting the -current state of the system. -@end deffn - -@deffn procedure find-restart name [restarts] -Returns the first restart object named @var{name} in the list of -@var{restarts} (permissible values for @var{restarts} are described -above in @ref{Restarts}). When used in a condition handler, -@code{find-restart} is usually passed the name of a particular restart -@emph{and} the condition object that has been signalled. In this way -the handler finds only restarts that were available when the condition -was created (usually the same as when it was signalled). If -@var{restarts} is omitted, the currently active restarts would be used, -and these often include restarts added after the condition ocurred. -@end deffn - -@deffn procedure invoke-restart restart argument @dots{} -@findex invoke-restart-interactively -Calls the restart effector encapsulated in @var{restart}, passing the -specified @var{argument}s to it. @code{invoke-restart} is intended for -use by condition-handling code that understands the protocol implemented -by @var{restart}, and can therefore calculate and pass an appropriate -set of arguments. - -If a condition handler needs to interact with a user to gather the -arguments for an effector (e.g.@: if it does not understand the protocol -implemented by @var{restart}) @code{invoke-restart-interactively} should -be used instead of @code{invoke-restart}. -@end deffn - -@deffn procedure invoke-restart-interactively restart -First calls the interactor encapsulated in @var{restart} to -interactively gather the arguments needed for @var{restart}'s effector. -It then calls the effector, passing these arguments to it. - -@findex restart/interactor -@code{invoke-restart-interactively} is intended for calling interactive -restarts (those for which @code{restart/interactor} is not @code{#f}). -For convenience, @code{invoke-restart-interactively} will call the -restart's effector with no arguments if the restart has no interactor; -this behavior may change in the future. -@end deffn - -@node The Named Restart Abstraction, , Finding and Invoking General Restart Code, Restarts -@subsection The Named Restart Abstraction - -A restart object is very simple, since it encapsulates only a name, -effector, interactor, and description. - -@deffn procedure restart? object -Returns @code{#f} if and only if @var{object} is not a restart. -@end deffn - -@deffn procedure restart/name restart -@findex eq? -Returns the name of @var{restart}. While the Scheme error system uses -only symbols and the object @code{#f} for its predefined names, programs -may use arbitrary objects (name equivalence is tested using @code{eq?}). -@end deffn - -@deffn procedure restart/effector restart -@findex invoke-restart -@findex invoke-restart-interactively -Returns the effector encapsulated in @var{restart}. Normally this -procedure is not used since @code{invoke-restart} and -@code{invoke-restart-interactively} capture the most common invocation -patterns. -@end deffn - -@deffn procedure restart/interactor restart -@findex invoke-restart-interactively -Returns the interactor encapsulated in @var{restart}. This is either a -procedure of no arguments or the object @code{#f}. Normally this -procedure is not used since @code{invoke-restart-interactively} captures -the most common usage. Thus @code{restart/interactor} is most useful as -a predicate to determine if @var{restart} is intended to be invoked -interactively. -@end deffn - -@deffn procedure write-restart-report restart port -Writes a description of @var{restart} to @var{port}. This works by -either displaying (if it is a string) or calling (if it is a procedure) -the @var{reporter} that was supplied when the restart was created. -@end deffn - -@node Condition Instances, Condition Types, Restarts, Error System -@section Condition Instances - -@cindex condition (defn) -@cindex condition instance (defn) -@cindex instance, of condition (defn) -A @dfn{condition}, in addition to the information associated with its -type, usually contains other information that is not shared with other -conditions of the same type. For example, the condition type associated -with ``unbound variable'' errors does not specify the name of the -variable that was unbound. The additional information is captured in a -@dfn{condition} object, also called a @dfn{condition instance}. - -In addition to information that is specific to a given type of condition -(such as the variable name for ``unbound variable'' conditions), every -condition instance also contains a continuation that encapsulates the -state of the computation in which the condition occurred. This -continuation is used for analyzing the computation to learn more about -the context in which the condition occurred. It is @emph{not} intended -to provide a mechanism for continuing the computation; that mechanism is -provided by restarts. - -@menu -* Generating Operations on Conditions:: -* Condition State:: -* Simple Condition Instance Operations:: -@end menu - -@node Generating Operations on Conditions, Condition State, Condition Instances, Condition Instances -@subsection Generating Operations on Conditions - -@findex condition-constructor -@findex condition-accessor -@findex condition-signaller -@findex condition-predicate -Scheme provides four procedures that take a condition type as input and -produce operations on the corresponding condition object. These are -reminiscent of the operations on record types that produce record -operators (@pxref{Records}). Given a condition type it is possible to -generate: a constructor for instances of the type (using -@code{condition-constructor}); an accessor to extract the contents of a -field in instances of the type (using @code{condition-accessor}); a -predicate to test for instances of the type (using -@code{condition-predicate}); and a procedure to create and signal an -instance of the type (using @code{condition-signaller}). - -Notice that the creation of a condition object is distinct from -signalling an occurrence of the condition. Condition objects are -first-class; they may be created and never signalled, or they may be -signalled more than once. Further notice that there are no procedures -for modifying conditions; once created, a condition cannot be altered. - -@deffn procedure condition-constructor condition-type field-names -@findex condition/restarts -@cindex bound-restarts -@cindex restarts, bound -Returns a constructor procedure that takes as arguments values for the -fields specified in @var{field-names} and creates a condition of type -@var{condition-type}. @var{Field-names} must be a list of symbols that -is a subset of the @var{field-names} in @var{condition-type}. The -constructor procedure returned by @code{condition-constructor} has -signature - -@example -(lambda (@var{continuation} @var{restarts} . @var{field-values}) @dots{}) -@end example - -@noindent -where the @var{field-names} correspond to the @var{field-values}. The -constructor argument @var{restarts} is described in @ref{Restarts}. -Conditions created by the constructor procedure have @code{#f} for the -values of all fields other than those specified by @var{field-names}. - -For example, the following procedure @code{make-simple-warning} -constructs a condition of type @code{condition-type:simple-warning} -given a continuation (where the condition occurred), a description of -the restarts to be made available, a warning message, and a list of -irritants that caused the warning: - -@example -@group -(define make-simple-warning - (condition-constructor condition-type:simple-warning - '(message irritants))) -@end group -@end example -@end deffn - -@deffn procedure condition-accessor condition-type field-name -@cindex specialization, of condition types -Returns a procedure that takes as input a condition object of type -@var{condition-type} and extracts the contents of the specified -@var{field-name}. @code{condition-accessor} signals -@code{error:bad-range-argument} if the @var{field-name} isn't one of the -named fields of @var{condition-type}; the returned procedure will signal -@code{error:wrong-type-argument} if passed an object other than a -condition of type @var{condition-type} or one of its specializations. - -@findex access-condition -If it is known in advance that a particular field of a condition will be -accessed repeatedly it is worth constructing an accessor for the field -using @code{condition-accessor} rather than using the (possibly more -convenient, but slower) @code{access-condition} procedure. -@end deffn - -@deffn procedure condition-predicate condition-type -@cindex specialization, of condition types -Returns a predicate procedure for testing whether an object is a -condition of type @var{condition-type} or one of its specializations -(there is no predefined way to test for a condition of a given type but -@emph{not} a specialization of that type). -@end deffn - -@deffn procedure condition-signaller condition-type field-names default-handler -Returns a signalling procedure with parameters @var{field-names}. When -the signalling procedure is called it creates and signals a condition of -type @var{condition-type}. If the condition isn't handled (i.e.@: if no -handler is invoked that causes an escape from the current continuation) -the signalling procedure reduces to a call to @var{default-handler} with -the condition as its argument. - -There are several standard procedures that are conventionally used for -@var{default-handler}. If @var{condition-type} is a specialization of -@code{condition-type:error}, @var{default-handler} should be the -procedure@* @code{standard-error-handler}. If @var{condition-type} is a -specialization of @code{condition-type:warning}, @var{default-handler} -should be the procedure @code{standard-warning-handler}. If -@var{condition-type} is a specialization of -@code{condition-type:breakpoint}, @var{default-handler} should be the -procedure @code{standard-breakpoint-handler}. -@end deffn - -@node Condition State, Simple Condition Instance Operations, Generating Operations on Conditions, Condition Instances -@subsection Condition Abstraction - -The condition data type is abstracted through a predicate -@code{condition?} and a set of accessor procedures. - -@deffn procedure condition? object -Returns @code{#f} if and only if @var{object} is not a condition. -@end deffn - -@deffn procedure condition/type condition -Returns the condition type of which @var{condition} is an instance. -@end deffn - -@deffn procedure condition/error? condition -@vindex condition-type:error -@cindex specialization, of condition types -Returns @code{#t} if the @var{condition} is an instance of condition -type @code{condition-type:error} or a specialization of it, @code{#f} -otherwise. -@end deffn - -@deffn procedure condition/restarts condition -Returns the list of restarts specified when @var{condition} was created. -@end deffn - -@deffn procedure condition/continuation condition -Returns the continuation specified when @var{condition} was created. -This is provided for inspecting the state of the system when the -condition occurred, @emph{not} for continuing or restarting the -computation. -@end deffn - -@deffn procedure write-condition-report condition port -Writes a description of @var{condition} to @var{port}, using the -reporter function from the condition type associated with -@var{condition}. See also @code{condition/report-string}. -@end deffn - -@node Simple Condition Instance Operations, , Condition State, Condition Instances -@subsection Simple Operations on Condition Instances - -The simple procedures described in this section are built on top of the -more detailed abstraction of condition objects described above. While -these procedures are sometimes easier to use, they are often less -efficient. - -@deffn procedure make-condition condition-type continuation restarts field-plist -@findex condition/restarts -@cindex bound-restarts -@cindex restarts, bound -Create a new condition object as an instance of @var{condition-type}, -associated with @var{continuation}. The @var{continuation} is provided -for inspection purposes only, @emph{not} for restarting the computation. -The @var{restarts} argument is described in @ref{Restarts}. The -@var{field-plist} is an alternating list of field names and values for -those fields, where the field names are those that would be returned by -@code{(condition-type/field-names @var{condition-type})}. It is used to -provide values for fields in the condition object; fields with no value -specified are set to @code{#f}. Once a condition object has been -created there is no way to alter the values of these fields. -@end deffn - -@deffn procedure access-condition condition field-name -@findex condition-accessor -Returns the value stored in the field @var{field-name} within -@var{condition}. @var{Field-name} must be one of the names returned by -@code{(condition-type/field-names (condition/type @var{condition}))}. -@code{access-condition} looks up the @var{field-name} at runtime, so it -is more efficient to use @code{condition-accessor} to create an access -function if the same field is to be extracted from several instances of -the same condition type. -@end deffn - -@deffn procedure condition/report-string condition -@findex write-condition-report -Returns a string containing a report of the @var{condition}. This is -generated by calling @code{write-condition-report} on @var{condition} -and a string output port, and returning the output collected by the port -as a string. -@end deffn - -@node Condition Types, Taxonomy, Condition Instances, Error System -@section Condition Types - -@cindex condition type -@cindex type, of condition -Each condition has a @dfn{condition type} object associated with it. -These objects are used as a means of focusing on related classes of -conditions, first by concentrating all of the information about a -specific class of condition in a single place, and second by specifying -an inheritance relationship between types. This inheritance -relationship forms the taxonomic structure of the condition hierarchy -(@pxref{Taxonomy}). - -The following procedures consititute the abstraction for condition -types. - -@deffn procedure make-condition-type name generalization field-names reporter -@cindex generalization, of condition types -Creates and returns a (new) condition type that is a specialization of -@var{generalization} (if it is a condition type) or is the root of a new -tree of condition types (if @var{generalization} is @code{#f}). For -debugging purposes, the condition type has a @var{name}, and instances -of this type contain storage for the fields specified by -@var{field-names} (a list of symbols) in addition to the fields common -to all conditions (@var{type}, @var{continuation} and @var{restarts}). - -@var{Reporter} is used to produce a description of a particular -condition of this type. It may be a string describing the condition, a -procedure of arity two (the first argument will be a condition of this -type and the second a port) that will @code{write} the message to the -given port, or @code{#f} to specify that the reporter should be taken -from the condition type @var{generalization} (or produce an -``undocumented condition of type @dots{}'' message if @var{generalization} -is @code{#f}). The conventions used to form descriptions are spelled -out in @ref{Error Messages}. -@end deffn - -@deffn procedure condition-type/error? condition-type -@vindex condition-type:error -@cindex specialization, of condition types -Returns @code{#t} if the @var{condition-type} is -@code{condition-type:error} or a specialization of it, @code{#f} -otherwise. -@end deffn - -@deffn procedure condition-type/field-names condition-type -@cindex generalization, of condition types -Returns a list of all of the field names for a condition of type -@var{condition-type}. This is the set union of the fields specified -when this @var{condition-type} was created with the -@code{condition-type/field-names} of the generalization of this -@var{condition-type}. -@end deffn - -@deffn procedure condition-type/generalizations condition-type -@cindex generalization, of condition types -Returns a list of all of the generalizations of @var{condition-type}. -Notice that every condition type is considered a generalization of -itself. -@end deffn - -@deffn procedure condition-type? object -Returns @code{#f} if and only if @var{object} is not a condition type. -@end deffn - -@node Taxonomy, , Condition Types, Error System -@section Condition-Type Taxonomy - -The MIT/GNU Scheme error system provides a rich set of predefined condition -types. These are organized into a forest through taxonomic links -providing the relationships for ``specializes'' and ``generalizes''. -The chart appearing below shows these relationships by indenting all the -specializations of a given type relative to the type. Note that the -variables that are bound to these condition types are prefixed by -@samp{condition-type:}; for example, the type appearing in the following -table as @samp{simple-error} is stored in the variable -@code{condition-type:simple-error}. Users are encouraged to add new -condition types by creating specializations of existing ones. - -Following the chart are detailed descriptions of the predefined -condition types. Some of these types are marked as @dfn{abstract} -types. Abstract types are not intended to be used directly as the type -of a condition; they are to be used as generalizations of other types, -and for binding condition handlers. Types that are not marked as -abstract are @dfn{concrete}; they are intended to be explicitly used as -a condition's type. - -@page -@example -@group -serious-condition - error - simple-error - illegal-datum - wrong-type-datum - wrong-type-argument - wrong-number-of-arguments - datum-out-of-range - bad-range-argument - inapplicable-object - file-error - file-operation-error - derived-file-error - port-error - derived-port-error - variable-error - unbound-variable - unassigned-variable - arithmetic-error - divide-by-zero - floating-point-overflow - floating-point-underflow - control-error - no-such-restart - not-loading - primitive-procedure-error - system-call-error -warning - simple-warning -simple-condition -breakpoint -@end group -@end example - -@deffn {condition type} condition-type:serious-condition -This is an abstract type. All serious conditions that require some form -of intervention should inherit from this type. In particular, all -errors inherit from this type. -@end deffn - -@deffn {condition type} condition-type:error -This is an abstract type. All errors should inherit from this type. -@end deffn - -@deffn {condition type} condition-type:simple-error message irritants -This is the condition generated by the @code{error} procedure when its -first argument is not a condition or condition type. The fields -@var{message} and @var{irritants} are taken directly from the arguments -to @code{error}; @var{message} contains an object (usually a string) and -@var{irritants} contains a list of objects. The reporter for this type -uses @code{format-error-message} to generate its output from -@var{message} and @var{irritants}. -@end deffn - -@deffn {condition type} condition-type:illegal-datum datum -This is an abstract type. This type indicates the class of errors in -which a program discovers an object that lacks specific required -properties. Most commonly, the object is of the wrong type or is -outside a specific range. The @var{datum} field contains the offending -object. -@end deffn - -@deffn {condition type} condition-type:wrong-type-datum datum type -This type indicates the class of errors in which a program discovers an -object that is of the wrong type. The @var{type} field contains a -string describing the type that was expected, and the @var{datum} field -contains the object that is of the wrong type. -@end deffn - -@example -@group -(error:wrong-type-datum 3.4 "integer") @error{} -;The object 3.4 is not an integer. -;To continue, call RESTART with an option number: -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn procedure error:wrong-type-datum datum type -This procedure signals a condition of type -@code{condition-type:wrong-type-datum}. The @var{datum} and @var{type} -fields of the condition are filled in from the corresponding arguments -to the procedure. -@end deffn - -@deffn {condition type} condition-type:wrong-type-argument datum type operator operand -This type indicates that a procedure was passed an argument of the wrong -type. The @var{operator} field contains the procedure (or a symbol -naming the procedure), the @var{operand} field indicates the argument -position that was involved (this field contains either a symbol, a -non-negative integer, or @code{#f}), the @var{type} field contains a -string describing the type that was expected, and the @var{datum} field -contains the offending argument. -@end deffn - -@example -@group -(+ 'a 3) @error{} -;The object a, passed as the first argument to integer-add, -; is not the correct type. -;To continue, call RESTART with an option number: -; (RESTART 2) => Specify an argument to use in its place. -; (RESTART 1) => Return to read-eval-print level 1. -@end group - -@group -(list-copy 3) -;The object 3, passed as an argument to list-copy, is not a list. -;To continue, call RESTART with an option number: -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn procedure error:wrong-type-argument datum type operator -This procedure signals a condition of type -@code{condition-type:wrong-type-argument}. The @var{datum}, @var{type} -and @var{operator} fields of the condition are filled in from the -corresponding arguments to the procedure; the @var{operand} field of the -condition is set to @code{#f}. -@end deffn - -@deffn {condition type} condition-type:wrong-number-of-arguments datum type operands -This type indicates that a procedure was called with the wrong number of -arguments. The @var{datum} field contains the procedure being called, -the @var{type} field contains the number of arguments that the procedure -accepts, and the @var{operands} field contains a list of the arguments -that were passed to the procedure. -@end deffn - -@example -@group -(car 3 4) @error{} -;The procedure car has been called with 2 arguments; -; it requires exactly 1 argument. -;To continue, call RESTART with an option number: -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn procedure error:wrong-number-of-arguments datum type operands -This procedure signals a condition of type -@code{condition-type:wrong-number-of-arguments}. The @var{datum}, -@var{type} and @var{operands} fields of the condition are filled in from -the corresponding arguments to the procedure. -@end deffn - -@deffn {condition type} condition-type:datum-out-of-range datum -This type indicates the class of errors in which a program discovers an -object that is of the correct type but is otherwise out of range. Most -often, this type indicates that an index to some data structure is -outside of the range of indices for that structure. The @var{datum} -field contains the offending object. -@end deffn - -@example -@group -(error:datum-out-of-range 3) @error{} -;The object 3 is not in the correct range. -;To continue, call RESTART with an option number: -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn procedure error:datum-out-of-range datum -This procedure signals a condition of type -@code{condition-type:datum-out-of-range}. The @var{datum} field of the -condition is filled in from the corresponding argument to the procedure. -@end deffn - -@deffn {condition type} condition-type:bad-range-argument datum operator operand -This type indicates that a procedure was passed an argument that is of -the correct type but is otherwise out of range. Most often, this type -indicates that an index to some data structure is outside of the range -of indices for that structure. The @var{operator} field contains the -procedure (or a symbol naming the procedure), the @var{operand} field -indicates the argument position that was involved (this field contains -either a symbol, a non-negative integer, or @code{#f}), and the -@var{datum} field is the offending argument. -@end deffn - -@example -@group -(string-ref "abc" 3) @error{} -;The object 3, passed as the second argument to string-ref, -; is not in the correct range. -;To continue, call RESTART with an option number: -; (RESTART 2) => Specify an argument to use in its place. -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn procedure error:bad-range-argument datum operator -This procedure signals a condition of type -@code{condition-type:bad-range-argument}. The @var{datum} and -@var{operator} fields of the condition are filled in from the -corresponding arguments to the procedure; the @var{operand} field of the -condition is set to @code{#f}. -@end deffn - -@deffn {condition type} condition-type:inapplicable-object datum operands -This type indicates an error in which a program attempted to apply an -object that is not a procedure. The object being applied is saved in -the @var{datum} field, and the arguments being passed to the object are -saved as a list in the @var{operands} field. -@end deffn - -@example -@group -(3 4) @error{} -;The object 3 is not applicable. -;To continue, call RESTART with an option number: -; (RESTART 2) => Specify a procedure to use in its place. -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn {condition type} condition-type:file-error filename -This is an abstract type. It indicates that an error associated with a -file has occurred. For example, attempting to delete a nonexistent file -will signal an error. The @var{filename} field contains a filename or -pathname associated with the operation that failed. -@end deffn - -@deffn {condition type} condition-type:file-operation-error filename verb noun reason operator operands -This is the most common condition type for file system errors. The -@var{filename} field contains the filename or pathname that was being -operated on. The @var{verb} field contains a string which is the verb -or verb phrase describing the operation being performed, and the -@var{noun} field contains a string which is a noun or noun phrase -describing the object being operated on. The @var{reason} field -contains a string describing the error that occurred. The -@var{operator} field contains the procedure performing the operation (or -a symbol naming that procedure), and the @var{operands} field contains a -list of the arguments that were passed to that procedure. For example, -an attempt to delete a nonexistent file would have the following field -values: - -@example -@group -filename "/zu/cph/tmp/no-such-file" -verb "delete" -noun "file" -reason "no such file or directory" -operator file-remove -operands ("/zu/cph/tmp/no-such-file") -@end group -@end example - -@noindent -and would generate a message like this: - -@example -@group -(delete-file "/zu/cph/tmp/no-such-file") @error{} -;Unable to delete file "/zu/cph/tmp/no-such-file" because: -; No such file or directory. -;To continue, call RESTART with an option number: -; (RESTART 3) => Try to delete the same file again. -; (RESTART 2) => Try to delete a different file. -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example -@end deffn - -@deffn procedure error:file-operation-error filename verb noun reason operator operands -This procedure signals a condition of type -@code{condition-type:file-operation-error}. The fields of the condition -are filled in from the corresponding arguments to the procedure. -@end deffn - -@deffn {condition type} condition-type:derived-file-error filename condition -This is another kind of file error, which is generated by obscure -file-system errors that do not fit into the standard categories. The -@var{filename} field contains the filename or pathname that was being -operated on, and the @var{condition} field contains a condition -describing the error in more detail. Usually the @var{condition} field -contains a condition of type @code{condition-type:system-call-error}. -@end deffn - -@deffn procedure error:derived-file filename condition -This procedure signals a condition of type -@code{condition-type:derived-file-error}. The @var{filename} and -@var{condition} fields of the condition are filled in from the -corresponding arguments to the procedure. -@end deffn - -@deffn {condition type} condition-type:port-error port -This is an abstract type. It indicates that an error associated with a -I/O port has occurred. For example, writing output to a file port can -signal an error if the disk containing the file is full; that error -would be signalled as a port error. The @var{port} field contains the -associated port. -@end deffn - -@deffn {condition type} condition-type:derived-port-error port condition -This is a concrete type that is signalled when port errors occur. The -@var{port} field contains the port associated with the error, and the -@var{condition} field contains a condition object that describes the -error in more detail. Usually the @var{condition} field contains a -condition of type @code{condition-type:system-call-error}. -@end deffn - -@deffn procedure error:derived-port port condition -This procedure signals a condition of type -@code{condition-type:derived-port-error}. The @var{port} and -@var{condition} fields of the condition are filled in from the -corresponding arguments to the procedure. -@end deffn - -@deffn {condition type} condition-type:variable-error location environment -This is an abstract type. It indicates that an error associated with a -variable has occurred. The @var{location} field contains the name of -the variable, and the @var{environment} field contains the environment -in which the variable was referenced. -@end deffn - -@deffn {condition type} condition-type:unbound-variable location environment -This type is generated when a program attempts to access or modify a -variable that is not bound. The @var{location} field contains the name -of the variable, and the @var{environment} field contains the -environment in which the reference occurred. -@end deffn - -@example -@group -foo @error{} -;Unbound variable: foo -;To continue, call RESTART with an option number: -; (RESTART 3) => Specify a value to use instead of foo. -; (RESTART 2) => Define foo to a given value. -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn {condition type} condition-type:unassigned-variable location environment -This type is generated when a program attempts to access a variable that -is not assigned. The @var{location} field contains the name of the -variable, and the @var{environment} field contains the environment in -which the reference occurred. -@end deffn - -@example -@group -foo @error{} -;Unassigned variable: foo -;To continue, call RESTART with an option number: -; (RESTART 3) => Specify a value to use instead of foo. -; (RESTART 2) => Set foo to a given value. -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn {condition type} condition-type:arithmetic-error operator operands -This is an abstract type. It indicates that a numerical operation was -unable to complete because of an arithmetic error. (For example, -division by zero.) The @var{operator} field contains the procedure that -implements the operation (or a symbol naming the procedure), and the -@var{operands} field contains a list of the arguments that were passed -to the procedure. -@end deffn - -@deffn {condition type} condition-type:divide-by-zero operator operands -This type is generated when a program attempts to divide by zero. The -@var{operator} field contains the procedure that implements the failing -operation (or a symbol naming the procedure), and the @var{operands} -field contains a list of the arguments that were passed to the -procedure. -@end deffn - -@example -@group -(/ 1 0) -;Division by zero signalled by /. -;To continue, call RESTART with an option number: -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn procedure error:divide-by-zero operator operands -This procedure signals a condition of type -@code{condition-type:divide-by-zero}. The @var{operator} and -@var{operands} fields of the condition are filled in from the -corresponding arguments to the procedure. -@end deffn - -@deffn {condition type} condition-type:floating-point-overflow operator operands -This type is generated when a program performs an arithmetic operation -that results in a floating-point overflow. The @var{operator} field -contains the procedure that implements the operation (or a symbol naming -the procedure), and the @var{operands} field contains a list of the -arguments that were passed to the procedure. -@end deffn - -@deffn {condition type} condition-type:floating-point-underflow operator operands -This type is generated when a program performs an arithmetic operation -that results in a floating-point underflow. The @var{operator} field -contains the procedure that implements the operation (or a symbol naming -the procedure), and the @var{operands} field contains a list of the -arguments that were passed to the procedure. -@end deffn - -@deffn {condition type} condition-type:primitive-procedure-error operator operands -This is an abstract type. It indicates that an error was generated by a -primitive procedure call. Primitive procedures are distinguished from -ordinary procedures in that they are not written in Scheme but instead -in the underlying language of the Scheme implementation. The -@var{operator} field contains the procedure that implements the -operation (or a symbol naming the procedure), and the @var{operands} -field contains a list of the arguments that were passed to the -procedure. -@end deffn - -@deffn {condition type} condition-type:system-call-error operator operands system-call error-type -This is the most common condition type generated by primitive -procedures. A condition of this type indicates that the primitive made -a system call to the operating system, and that the system call -signalled an error. The system-call error is reflected back to Scheme -as a condition of this type, except that many common system-call errors -are automatically translated by the Scheme implementation into more -useful forms; for example, a system-call error that occurs while trying -to delete a file will be translated into a condition of type -@code{condition-type:file-operation-error}. The @var{operator} field -contains the procedure that implements the operation (or a symbol naming -the procedure), and the @var{operands} field contains a list of the -arguments that were passed to the procedure. The @var{system-call} and -@var{error-type} fields contain symbols that describe the specific -system call that was being made and the error that occurred, -respectively; these symbols are completely operating-system dependent. -@end deffn - -@deffn {condition type} condition-type:control-error -This is an abstract type. It describes a class of errors relating to -program control flow. -@end deffn - -@deffn {condition type} condition-type:no-such-restart name -This type indicates that a named restart was not active when it was -expected to be. Conditions of this type are signalled by several -procedures that look for particular named restarts, for example -@code{muffle-warning}. The @var{name} field contains the name that was -being searched for. -@end deffn - -@example -@group -(muffle-warning) @error{} -;The restart named muffle-warning is not bound. -;To continue, call RESTART with an option number: -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn procedure error:no-such-restart name -This procedure signals a condition of type -@code{condition-type:no-such-restart}. The @var{name} field of the -condition is filled in from the corresponding argument to the procedure. -@end deffn - -@deffn {condition type} condition-type:not-loading -A condition of this type is generated when the procedure -@code{current-load-pathname} is called from somewhere other than inside -a file being loaded. -@end deffn - -@example -@group -(current-load-pathname) @error{} -;No file being loaded. -;To continue, call RESTART with an option number: -; (RESTART 1) => Return to read-eval-print level 1. -@end group -@end example - -@deffn {condition type} condition-type:warning -This is an abstract type. All warnings should inherit from this type. -Warnings are a class of conditions that are usually handled by informing -the user of the condition and proceeding the computation normally. -@end deffn - -@deffn {condition type} condition-type:simple-warning message irritants -This is the condition generated by the @code{warn} procedure. The -fields @var{message} and @var{irritants} are taken directly from the -arguments to @code{warn}; @var{message} contains an object (usually a -string) and @var{irritants} contains a list of objects. The reporter -for this type uses @code{format-error-message} to generate its output -from @var{message} and @var{irritants}. -@end deffn - -@deffn {condition type} condition-type:simple-condition message irritants -This is an unspecialized condition that does not fall into any of the -standard condition classes. The @var{message} field contains an object -(usually a string) and @var{irritants} contains a list of objects. The -reporter for this type uses @code{format-error-message} to generate its -output from @var{message} and @var{irritants}. -@end deffn - -@deffn {condition type} condition-type:breakpoint environment message prompt -A condition of this type is generated by the breakpoint mechanism. The -contents of its fields are beyond the scope of this document. -@end deffn - -@node Graphics, Win32 Package Reference, Error System, Top -@chapter Graphics -@cindex graphics - -MIT/GNU Scheme has a simple two-dimensional line-graphics interface -that is suitable for many graphics applications. In particular it is -often used for plotting data points from experiments. The interface is -generic in that it can support different types of graphics devices in a -uniform manner. At the present time only one type of graphics device -is implemented on each operating system. - -Procedures are available for drawing points, lines, and text; defining -the coordinate system; clipping graphics output; controlling some of the -drawing characteristics; and controlling the output buffer (for devices -that perform buffering). Additionally, devices may support custom -operations, such as control of colors. - -There are some constraints on the arguments to the procedures described -in this chapter. Any argument named @var{graphics-device} must be a -graphics device object that was returned from a call to -@code{make-graphics-device}. Any argument that is a coordinate must be -either an exact integer or an inexact real. - -@menu -* Opening and Closing of Graphics Devices:: -* Coordinates for Graphics:: -* Drawing Graphics:: -* Characteristics of Graphics Output:: -* Buffering of Graphics Output:: -* Clipping of Graphics Output:: -* Custom Graphics Operations:: -* Images:: -* X Graphics:: Graphics on the X Window System -* Win32 Graphics:: Graphics on Microsoft Windows and Windows NT -* OS/2 Graphics:: Graphics on IBM OS/2 -@end menu - -@node Opening and Closing of Graphics Devices, Coordinates for Graphics, Graphics, Graphics -@section Opening and Closing of Graphics Devices -@cindex graphics, opening and closing devices - -@deffn procedure graphics-type-available? graphics-device-type -This predicate returns @code{#t} if the graphics system named by the -symbol @var{graphics-device-type} is implemented by the Scheme system. -Otherwise it returns @code{#f}, in which case it is an error to attempt -to make a graphics device using @var{graphics-device-type}. -@end deffn - -@deffn procedure enumerate-graphics-types -This procedure returns a list of symbols which are the names of all the -graphics device types that are supported by the Scheme system. The -result is useful in deciding what additional arguments to supply to -@code{make-graphics-device}, as each device type typically has a unique -way of specifying the initial size, shape and other attributes. -@end deffn - -@deffn procedure make-graphics-device graphics-device-type object @dots{} -This operation creates and returns a graphics device object. -@var{Graphics-device-type} is a symbol naming a graphics device type, -and both the number and the meaning of the remaining arguments is -determined by that type (see the description of each device type for -details); @var{graphics-device-type} must satisfy -@code{graphics-type-available?}. @var{Graphics-device-type} may also be -@code{#f}, in which case the graphics device type is chosen by the -system from what is available. This allows completely portable graphics -programs to be written provided no custom graphics operations are used. -When @var{graphics-device-type} is @code{#f} no further arguments may be -given; each graphics device type will use some ``sensible'' defaults. -If more control is required then the program should use one of the two -procedures above to dispatch on the available types. - -This procedure opens and initializes the device, which remains valid -until explicitly closed by the procedure @code{graphics-close}. -Depending on the implementation of the graphics device, if this object -is reclaimed by the garbage collector, the graphics device may remain -open or it may be automatically closed. While a graphics device remains -open the resources associated with it are not released. -@end deffn - -@deffn procedure graphics-close graphics-device -Closes @var{graphics-device}, releasing its resources. Subsequently it -is an error to use @var{graphics-device}. -@end deffn - -@node Coordinates for Graphics, Drawing Graphics, Opening and Closing of Graphics Devices, Graphics -@section Coordinates for Graphics -@cindex graphics, coordinate systems - -@cindex coordinates, graphics -@cindex device coordinates, graphics (defn) -@cindex graphics, device coordinates (defn) -@cindex virtual coordinates, graphics (defn) -@cindex graphics, virtual coordinates (defn) -Each graphics device has two different coordinate systems associated -with it: @dfn{device coordinates} and @dfn{virtual coordinates}. Device -coordinates are generally defined by low-level characteristics of the -device itself, and often cannot be changed. Most device coordinate -systems are defined in terms of pixels, and usually the upper-left-hand -corner is the origin of the coordinate system, with @var{x} coordinates -increasing to the right and @var{y} coordinates increasing downwards. - -In contrast, virtual coordinates are more flexible in the units -employed, the position of the origin, and even the direction in which -the coordinates increase. A virtual coordinate system is defined by -assigning coordinates to the edges of a device. Because these edge -coordinates are arbitrary real numbers, any Cartesian coordinate system -can be defined. - -All graphics procedures that use coordinates are defined on virtual -coordinates. For example, to draw a line at a particular place on a -device, the virtual coordinates for the endpoints of that line are -given. - -When a graphics device is initialized, its virtual coordinate system is -reset so that the left edge corresponds to an x-coordinate of @code{-1}, -the right edge to x-coordinate @code{1}, the bottom edge to y-coordinate -@code{-1}, and the top edge to y-coordinate @code{1}. - -@deffn procedure graphics-device-coordinate-limits graphics-device -Returns (as multiple values) the device coordinate limits for -@var{graphics-device}. The values, which are exact non-negative -integers, are: @var{x-left}, @var{y-bottom}, @var{x-right}, and -@var{y-top}. -@end deffn - -@deffn procedure graphics-coordinate-limits graphics-device -Returns (as multiple values) the virtual coordinate limits for -@var{graphics-device}. The values, which are real numbers, are: -@var{x-left}, @var{y-bottom}, @var{x-right}, and @var{y-top}. -@end deffn - -@deffn procedure graphics-set-coordinate-limits graphics-device x-left y-bottom x-right y-top -Changes the virtual coordinate limits of @var{graphics-device} to the -given arguments. @var{X-left}, @var{y-bottom}, @var{x-right}, and -@var{y-top} must be real numbers. Subsequent calls to -@code{graphics-coordinate-limits} will return the new limits. This -operation has no effect on the device's displayed contents. - -Note: This operation usually resets the clip rectangle, although it is -not guaranteed to do so. If a clip rectangle is in effect when this -procedure is called, it is necessary to redefine the clip rectangle -afterwards. -@end deffn - -@node Drawing Graphics, Characteristics of Graphics Output, Coordinates for Graphics, Graphics -@section Drawing Graphics -@cindex graphics, drawing - -The procedures in this section provide the basic drawing capabilities of -Scheme's graphics system. - -@deffn procedure graphics-clear graphics-device -Clears the display of @var{graphics-device}. Unaffected by the current -drawing mode. -@end deffn - -@deffn procedure graphics-draw-point graphics-device x y -Draws a single point on @var{graphics-device} at the virtual coordinates -given by @var{x} and @var{y}, using the current drawing mode. -@end deffn - -@deffn procedure graphics-erase-point graphics-device x y -Erases a single point on @var{graphics-device} at the virtual -coordinates given by @var{x} and @var{y}. This procedure is unaffected -by the current drawing mode. -@end deffn - -@noindent -This is equivalent to - -@example -@group -(lambda (device x y) - (graphics-bind-drawing-mode device 0 - (lambda () - (graphics-draw-point device x y)))) -@end group -@end example - -@deffn procedure graphics-draw-line graphics-device x-start y-start x-end y-end -@var{X-start}, @var{y-start}, @var{x-end}, and @var{y-end} must be real -numbers. Draws a line on @var{graphics-device} that connects the points -(@var{x-start}, @var{y-start}) and (@var{x-end}, @var{y-end}). The line -is drawn using the current drawing mode and line style. -@end deffn - -@deffn procedure graphics-draw-text graphics-device x y string -Draws the characters of @var{string} at the point (@var{x}, @var{y}) on -@var{graphics-device}, using the current drawing mode. The -characteristics of the characters drawn are device-dependent, but all -devices are initialized so that the characters are drawn upright, from -left to right, with the leftmost edge of the leftmost character at -@var{x}, and the baseline of the characters at @var{y}. -@end deffn - -@cindex graphics, cursor (defn) -@cindex cursor, graphics (defn) -The following two procedures provide an alternate mechanism for drawing -lines, which is more akin to using a plotter. They maintain a -@dfn{cursor}, which can be positioned to a particular point and then -dragged to another point, producing a line. Sequences of connected line -segments can be drawn by dragging the cursor from point to point. - -Many graphics operations have an unspecified effect on the cursor. The -following exceptions are guaranteed to leave the cursor unaffected: - -@example -@group -graphics-device-coordinate-limits -graphics-coordinate-limits -graphics-enable-buffering -graphics-disable-buffering -graphics-flush -graphics-bind-drawing-mode -graphics-set-drawing-mode -graphics-bind-line-style -graphics-set-line-style -@end group -@end example - -The initial state of the cursor is unspecified. - -@deffn procedure graphics-move-cursor graphics-device x y -Moves the cursor for @var{graphics-device} to the point (@var{x}, -@var{y}). The contents of the device's display are unchanged. -@end deffn - -@deffn procedure graphics-drag-cursor graphics-device x y -Draws a line from @var{graphics-device}'s cursor to the point (@var{x}, -@var{y}), simultaneously moving the cursor to that point. The line is -drawn using the current drawing mode and line style. -@end deffn - -@node Characteristics of Graphics Output, Buffering of Graphics Output, Drawing Graphics, Graphics -@section Characteristics of Graphics Output - -@cindex graphics, output characteristics -Two characteristics of graphics output are so useful that they are -supported uniformly by all graphics devices: @dfn{drawing mode} and -@dfn{line style}. A third characteristic, @dfn{color}, is equally -useful (if not more so), but implementation restrictions prohibit a -uniform interface. - -@cindex drawing mode, graphics (defn) -@cindex graphics, drawing mode (defn) -The @dfn{drawing mode}, an exact integer in the range @code{0} to -@code{15} inclusive, determines how the figure being drawn is combined -with the background over which it is drawn to generate the final result. -Initially the drawing mode is set to ``source'', so that the new output -overwrites whatever appears in that place. Useful alternative drawing -modes can, for example, erase what was already there, or invert it. - -Altogether 16 boolean operations are available for combining the source -(what is being drawn) and the destination (what is being drawn over). -The source and destination are combined by the device on a -pixel-by-pixel basis as follows: - -@example -@group -Mode Meaning ----- ------- -0 ZERO @r{[erase; use background color]} -1 source AND destination -2 source AND (NOT destination) -3 source -4 (NOT source) AND destination -5 destination -6 source XOR destination -7 source OR destination -8 NOT (source OR destination) -9 NOT (source XOR destination) -10 NOT destination -11 source OR (NOT destination) -12 NOT source -13 (NOT source) OR destination -14 (NOT source) OR (NOT destination) -15 ONE @r{[use foreground color]} -@end group -@end example - -@cindex line style, graphics (defn) -@cindex graphics, line style (defn) -The @dfn{line style}, an exact integer in the range @code{0} to @code{7} -inclusive, determines which parts of a line are drawn in the foreground -color, and which in the background color. The default line style, -``solid'', draws the entire line in the foreground color. -Alternatively, the ``dash'' style alternates between foreground and -background colors to generate a dashed line. This capability is useful -for plotting several things on the same graph. - -Here is a table showing the name and approximate pattern of the -different styles. A @samp{1} in the pattern represents a foreground -pixel, while a @samp{-} represents a background pixel. Note that the -precise output for each style will vary from device to device. The only -style that is guaranteed to be the same for every device is ``solid''. - -@example -@group -Style Name Pattern ------ ------- ------- -0 solid 1111111111111111 -1 dash 11111111-------- -2 dot 1-1-1-1-1-1-1-1- -3 dash dot 1111111111111-1- -4 dash dot dot 11111111111-1-1- -5 long dash 11111111111----- -6 center dash 111111111111-11- -7 center dash dash 111111111-11-11- -@end group -@end example - -@deffn procedure graphics-bind-drawing-mode graphics-device drawing-mode thunk -@deffnx procedure graphics-bind-line-style graphics-device line-style thunk -These procedures bind the drawing mode or line style, respectively, of -@var{graphics-device}, invoke the procedure @var{thunk} with no -arguments, then undo the binding when @var{thunk} returns. The value of -each procedure is the value returned by @var{thunk}. Graphics -operations performed during @var{thunk}'s dynamic extent will see the -newly bound mode or style as current. -@end deffn - -@deffn procedure graphics-set-drawing-mode graphics-device drawing-mode -@deffnx procedure graphics-set-line-style graphics-device line-style -These procedures change the drawing mode or line style, respectively, of -@var{graphics-device}. The mode or style will remain in effect until -subsequent changes or bindings. -@end deffn - -@node Buffering of Graphics Output, Clipping of Graphics Output, Characteristics of Graphics Output, Graphics -@section Buffering of Graphics Output -@cindex buffering, of graphics output -@cindex graphics, buffering of output - -To improve performance of graphics output, most graphics devices provide -some form of buffering. By default, Scheme's graphics procedures flush -this buffer after every drawing operation. The procedures in this -section allow the user to control the flushing of the output -buffer. - -@deffn procedure graphics-enable-buffering graphics-device -Enables buffering for @var{graphics-device}. In other words, after this -procedure is called, graphics operations are permitted to buffer their -drawing requests. This usually means that the drawing is delayed until -the buffer is flushed explicitly by the user, or until it fills up and -is flushed by the system. -@end deffn - -@deffn procedure graphics-disable-buffering graphics-device -Disables buffering for @var{graphics-device}. By default, all graphics -devices are initialized with buffering disabled. After this procedure -is called, all drawing operations perform their output immediately, -before returning. - -Note: @code{graphics-disable-buffering} flushes the output buffer if -necessary. -@end deffn - -@deffn procedure graphics-flush graphics-device -Flushes the graphics output buffer for @var{graphics-device}. This -operation has no effect for devices that do not support buffering, or if -buffering is disabled for the device. -@end deffn - -@node Clipping of Graphics Output, Custom Graphics Operations, Buffering of Graphics Output, Graphics -@section Clipping of Graphics Output -@cindex graphics, clipping -@cindex clipping, of graphics - -@cindex clip rectangle, graphics (defn) -Scheme provides a rudimentary mechanism for restricting graphics output -to a given rectangular subsection of a graphics device. By default, -graphics output that is drawn anywhere within the device's virtual -coordinate limits will appear on the device. When a @dfn{clip -rectangle} is specified, however, output that would have appeared -outside the clip rectangle is not drawn. - -Note that changing the virtual coordinate limits for a device will -usually reset the clip rectangle for that device, as will any operation -that affects the size of the device (such as a window resizing -operation). However, programs should not depend on this. - -@deffn procedure graphics-set-clip-rectangle graphics-device x-left y-bottom x-right y-top -Specifies the clip rectangle for @var{graphics-device} in virtual -coordinates. @var{X-left}, @var{y-bottom}, @var{x-right}, and -@var{y-top} must be real numbers. Subsequent graphics output is clipped -to the intersection of this rectangle and the device's virtual -coordinate limits. -@end deffn - -@deffn procedure graphics-reset-clip-rectangle graphics-device -Eliminates the clip rectangle for @var{graphics-device}. Subsequent -graphics output is clipped to the virtual coordinate limits of the -device. -@end deffn - -@node Custom Graphics Operations, Images, Clipping of Graphics Output, Graphics -@section Custom Graphics Operations -@cindex custom operations, on graphics device -@cindex graphics, custom operations - -In addition to the standard operations, a graphics device may support -@dfn{custom operations}. For example, most devices have custom -operations to control color. @code{graphics-operation} is used to -invoke custom operations. - -@deffn procedure graphics-operation graphics-device name object @dots{} -Invokes the graphics operation on @var{graphics-device} whose name is -the symbol @var{name}, passing it the remaining arguments. This -procedure can be used to invoke the standard operations, as well as -custom operations that are specific to a particular graphics device -type. The names of the standard graphics operations are formed by -removing the @code{graphics-} prefix from the corresponding procedure. -For example, the following are equivalent: - -@example -@group -(graphics-draw-point device x y) -(graphics-operation device 'draw-point x y) -@end group -@end example - -For information on the custom operations for a particular device, see -the documentation for its type. -@end deffn - -@node Images, X Graphics, Custom Graphics Operations, Graphics -@section Images -@cindex graphics, images -@cindex images, graphics -@cindex graphics, bitmaps -@cindex bitmaps, graphics - -Some graphics device types support images, which are rectangular pieces -of picture that may be drawn into a graphics device. Images are often -called something else in the host graphics system, such as bitmaps or -pixmaps. The operations supported vary between devices, so look under -the different device types to see what operations are available. All -devices that support images support the following operations. - -@defop operation graphics-device create-image width height -Images are created using the @code{create-image} graphics operation, -specifying the @var{width} and @var{height} of the image in device -coordinates (pixels). - -@example -(graphics-operation device 'create-image 200 100) -@end example - -@noindent -The initial contents of an image are unspecified. - -@code{create-image} is a graphics operation rather than a procedure -because the kind of image returned depends on the kind of graphics -device used and the options specified in its creation. The image may be -used freely with other graphics devices created with the same -attributes, but the effects of using an image with a graphics device -with different attributes (for example, different colors) is undefined. -Under X, the image is display dependent. -@end defop - -@defop operation graphics-device draw-image x y image -The image is copied into the graphics device at the specified position. -@end defop - -@defop operation graphics-device draw-subimage x y image im-x im-y w h -Part of the image is copied into the graphics device at the specified -(@var{x}, @var{y}) position. The part of the image that is copied is the -rectangular region at @var{im-x} and @var{im-y} and of width @var{w} and -height @var{h}. These four numbers are given in device coordinates -(pixels). -@end defop - -@deffn procedure image? object -Returns @code{#t} if @var{object} is an image, otherwise returns -@code{#f}. -@end deffn - -@deffn procedure image/destroy image -This procedure destroys @var{image}, returning storage to the system. -Programs should destroy images after they have been used because even -modest images may use large amounts of memory. Images are reclaimed by -the garbage collector, but they may be implemented using memory outside -of Scheme's heap. If an image is reclaimed before being destroyed, the -implementation might not deallocate that non-heap memory, which can -cause a subsequent call to @code{create-image} to fail because it is -unable to allocate enough memory. -@end deffn - -@c @deffn procedure image/descriptor image -@c The procedure returns the implementation dependent image. Its use is -@c discouraged as it is non-portable. -@c @end deffn - -@deffn procedure image/height image -Returns the height of the image in device coordinates. -@end deffn - -@deffn procedure image/width image -Returns the width of the image in device coordinates. -@end deffn - -@deffn procedure image/fill-from-byte-vector image bytes -The contents of @var{image} are set in a device-dependent way, using one -byte per pixel from @var{bytes} (a string). Pixels are filled row by -row from the top of the image to the bottom, with each row being filled -from left to right. There must be at least @code{(* (image/height -@var{image}) (image/width @var{image}))} bytes in @var{bytes}. -@end deffn - -@node X Graphics, Win32 Graphics, Images, Graphics -@section X Graphics -@cindex X graphics - -@cindex X window system -MIT/GNU Scheme supports graphics in the X window system (version 11). -Arbitrary numbers of displays may be opened, and arbitrary numbers of -graphics windows may be created for each display. A variety of -operations is available to manipulate various aspects of the windows, to -control their size, position, colors, and mapping. The X graphics -device type supports images, which are implemented as Xlib @code{XImage} -objects. X display, window, and image objects are automatically closed -if they are reclaimed by the garbage collector. - -@menu -* X Graphics Type:: -* Utilities for X Graphics:: -* Custom Operations on X Graphics Devices:: -@end menu - -@node X Graphics Type, Utilities for X Graphics, X Graphics, X Graphics -@subsection X Graphics Type - - -A graphics device for X windows is created by passing the symbol -@code{x} as the graphics device type name to -@code{make-graphics-device}: - -@example -(make-graphics-device 'x #!optional @var{display} @var{geometry} @var{suppress-map?}) -@end example - -@noindent -where @var{display} is either a display object, @code{#f}, or a string; -@var{geometry} is either @code{#f} or a string; and @var{suppress-map?} -is a boolean or a vector (see below). A new window is created on the -appropriate display, and a graphics device representing that window is -returned. - -@findex x-open-display -@var{Display} specifies which X display the window is to be opened on; -if it is @code{#f} or a string, it is passed as an argument to -@code{x-open-display}, and the value returned by that procedure is used -in place of the original argument. @var{Geometry} is an X geometry -string, or @code{#f} which means to use the default geometry (which is -specified as a resource). - -@var{Suppress-map?}, if given, may take two forms. First, it may be a -boolean: if @code{#f} (the default), the window is automatically mapped -after it is created; otherwise, @code{#t} means to suppress this -automatic mapping. The second form is a vector of three elements. The -first element is a boolean with the same meaning as the boolean form of -@var{suppress-map?}. The second element is a string, which specifies an -alternative resource name to be used for looking up the window's -resources. The third element is also a string, which specifies a class -name for looking up the window's resources. The default value for -@var{suppress-map?} is @code{#f}. - -The default resource and class names are @code{"schemeGraphics"} and -@code{"SchemeGraphics"} respectively. - -@cindex resources, X graphics -@cindex X resources, graphics -The window is initialized using the resource and class names specified -by @var{suppress-map?}, and is sensitive to the following resource -properties: - -@example -@group -Property Class Default --------- ----- ------- -geometry Geometry 512x384+0+0 -font Font fixed -borderWidth BorderWidth 2 -internalBorder BorderWidth @r{[border width]} -background Background white -foreground Foreground black -borderColor BorderColor @r{[foreground color]} -cursorColor Foreground @r{[foreground color]} -pointerColor Foreground @r{[foreground color]} -@end group -@end example - -The window is created with a @code{backing_store} attribute of -@code{Always}. The window's name and icon name are initialized to -@code{"scheme-graphics"}. - - -@node Utilities for X Graphics, Custom Operations on X Graphics Devices, X Graphics Type, X Graphics -@subsection Utilities for X Graphics - -@deffn procedure x-graphics/open-display display-name -@cindex display, X graphics -@cindex X display, graphics -Opens a connection to the display whose name is @var{display-name}, -returning a display object. If unable to open a connection, @code{#f} -is returned. @var{Display-name} is normally a string, which is an X -display name in the usual form; however, @code{#f} is also allowed, -meaning to use the value of the unix environment variable -@code{DISPLAY}. -@end deffn - -@deffn procedure x-graphics/close-display display -Closes @var{display}; after calling this procedure, it is an error to -use @var{display} for any purpose. Any windows that were previously -opened on @var{display} are destroyed and their resources returned to -the operating system. -@end deffn - -@deffn procedure x-close-all-displays -Closes all open connections to X displays. Equivalent to calling -@code{x-close-display} on all open displays. -@end deffn - -@deffn procedure x-geometry-string x y width height -@cindex geometry string, X graphics -@cindex X geometry string, graphics -This procedure creates and returns a standard X geometry string from the -given arguments. @var{X} and @var{y} must be either exact integers or -@code{#f}, while @var{width} and @var{height} must be either exact -non-negative integers or @code{#f}. Usually either @var{x} and @var{y} -are both specified or both @code{#f}; similarly for @var{width} and -@var{height}. If only one of the elements of such a pair is specified, -it is ignored. - -Examples: - -@example -@group -(x-geometry-string #f #f 100 200) @result{} "100x200" -(x-geometry-string 2 -3 100 200) @result{} "100x200+2-3" -(x-geometry-string 2 -3 #f #f) @result{} "+2-3" -@end group -@end example - -Note that the @var{x} and @var{y} arguments cannot distinguish between -@code{+0} and @code{-0}, even though these have different meanings in X. -If either of those arguments is @code{0}, it means @code{+0} in X -terminology. If you need to distinguish these two cases you must create -your own geometry string using Scheme's string and number primitives. -@end deffn - -@node Custom Operations on X Graphics Devices, , Utilities for X Graphics, X Graphics -@subsection Custom Operations on X Graphics Devices - -Custom operations are invoked using the procedure -@code{graphics-operation}. For example, - -@example -(graphics-operation device 'set-foreground-color "blue") -@end example - -@defop operation x-graphics-device set-background-color color-name -@defopx operation x-graphics-device set-foreground-color color-name -@defopx operation x-graphics-device set-border-color color-name -@defopx operation x-graphics-device set-mouse-color color-name -@findex graphics-clear -These operations change the colors associated with a window. -@var{Color-name} must be a string, which is the X server's name for the -desired color. @code{set-border-color} and @code{set-mouse-color} -immediately change the border and mouse-cursor colors. -@code{set-background-color} and @code{set-foreground-color} change the -colors to be used when drawing, but have no effect on anything drawn -prior to their invocation. Because changing the background color -affects the entire window, we recommend calling @code{graphics-clear} on -the window's device afterwards. Color names include both mnemonic -names, like @code{"red"}, and intensity names specified in the -@code{"#@var{rrggbb}"} notation. -@end defop - -@defop operation x-graphics-device draw-arc x y radius-x radius-y angle-start angle-sweep fill? -@cindex drawing arcs and circles, graphics -@cindex graphics, drawing arcs and circles -@cindex circles, drawing -@findex draw-arc - -Operation @code{draw-arc} draws or fills an arc. An arc is a segment of -a circle, which may have been stretched along the x- or y- axis to form -an ellipse. - -The parameters @var{x}, @var{y}, @var{radius-x} and @var{radius-y} -describe the circle and @var{angle-start} and @var{angle-sweep} choose -which part of the circle is drawn. The arc is drawn on the graphics -device with the center of the circle at the virtual coordinates given by -@var{x} and @var{y}. @var{radius-x} and @var{radius-y} determine the -size of the circle in virtual coordinate units. - -The parameter @var{angle-start} determines where the arc starts. It is -measured in degrees in an anti-clockwise direction, starting at 3 -o'clock. @var{angle-sweep} determines how much of the circle is drawn. -It too is measured anti-clockwise in degrees. A negative value means -the measurement is in a clockwise direction. - -Note that the angles are determined on a unit circle before it is -stretched into an ellipse, so the actual angles that you will see on the -computer screen depends on all of: @var{radius-x} and @var{radius-y}, -the window size, and the virtual coordinates. - -If @var{fill?} is @code{#f} then just the segment of the circle is -drawn, otherwise the arc is filled in a pie-slice fashion. - -This draws a quarter circle pie slice, standing on its point, with point -at virtual coordinates (3,5): - -@example -(graphics-opereration g 'draw-arc 3 5 .5 .5 45 90 #t) -@end example - -@end defop - -@defop operation x-graphics-device draw-circle x y radius -@defopx operation x-graphics-device fill-circle x y radius -@cindex drawing arcs and circles, graphics -@cindex graphics, drawing arcs and circles -@cindex circles, drawing -@findex draw-circle -@findex fill-circle -These operations draw a circle (outline) or a filled circle (solid) at -on the graphics device at the virtual coordinates given by @var{x} and -@var{y}. These operations could be implemented trivially interms of the -@code{draw-arc} operation. -@end defop - -@defop operation x-graphics-device set-border-width width -@defopx operation x-graphics-device set-internal-border-width width -@findex graphics-clear -These operations change the external and internal border widths of a -window. @var{Width} must be an exact non-negative integer, specified in -pixels. The change takes place immediately. Note that changing the -internal border width can cause displayed graphics to be garbled; we -recommend calling @code{graphics-clear} on the window's device after -doing so. -@end defop - -@defop operation x-graphics-device set-font font-name -Changes the font used when drawing text in a window. @var{Font-name} -must be a string that is a font name known to the X server. This -operation does not affect text drawn prior to its invocation. -@end defop - -@defop operation x-graphics-device set-mouse-shape shape-number -Changes the shape of the mouse cursor. @var{Shape-number} is an exact -non-negative integer that is used as an index into the mouse-shape font; -when multiplied by 2 this number corresponds to an index in the file@* -@file{/usr/include/X11/cursorfont.h}. -@end defop - -@defop operation x-graphics-device map-window -@defopx operation x-graphics-device withdraw-window -These operations control the mapping of windows. They correspond -directly to Xlib's @code{XMapWindow} and @code{XWithdrawWindow}. -@end defop - -@defop operation x-graphics-device resize-window width height -Changes the size of a window. @var{Width} and @var{height} must be -exact non-negative integers. The operation corresponds directly to -Xlib's @code{XResizeWindow}. - -This operation resets the virtual coordinate system and the clip -rectangle. -@end defop - -@defop operation x-graphics-device move-window x y -Changes the position of a window on the display. @var{X} and @var{y} -must be exact integers. The operation corresponds directly to Xlib's -@code{XMoveWindow}. Note that the coordinates @var{x} and @var{y} do -not take the external border into account, and therefore will not -position the window as you might like. The only reliable way to -position a window is to ask a window manager to do it for you. -@end defop - -@defop operation x-graphics-device get-default resource property -This operation corresponds directly to Xlib's @code{XGetDefault}. -@var{Resource} and @var{property} must be strings. The operation -returns the character string corresponding to the association of -@var{resource} and @var{property}; if no such association exists, -@code{#f} is returned. -@end defop - -@defop operation x-graphics-device copy-area source-x-left source-y-top width height destination-x-left destination-y-top -This operation copies the contents of the rectangle specified by -@var{source-x-left}, @var{source-y-top}, @var{width}, and @var{height} to -the rectangle of the same dimensions at @var{destination-x-left} and -@var{destination-y-top}. -@end defop - -@defop operation x-graphics-device font-structure font-name -Returns a Scheme equivalent of the X font structure for the font named -@var{font-name}. If the string @var{font-name} does not name a font -known to the X server, or names a 16-bit font, @code{#f} is returned. -@end defop - -@deffn procedure x-font-structure/name font-structure -@deffnx procedure x-font-structure/direction font-structure -@deffnx procedure x-font-structure/all-chars-exist font-structure -@deffnx procedure x-font-structure/default-char font-structure -@deffnx procedure x-font-structure/min-bounds font-structure -@deffnx procedure x-font-structure/max-bounds font-structure -@deffnx procedure x-font-structure/start-index font-structure -@deffnx procedure x-font-structure/character-bounds font-structure -@deffnx procedure x-font-structure/max-ascent font-structure -@deffnx procedure x-font-structure/max-descent font-structure -These procedures extract the components of the font description -structure returned by the X graphics operation @code{font-structure}. A -more complete description of these components appears in documentation -of the @code{XLoadQueryFont} Xlib call. @code{start-index} is the index -of the first character available in the font. The @code{min-bounds} and -@code{max-bounds} components are structures of type -@code{x-character-bounds}, and the @code{character-bounds} component is -a vector of the same type. -@end deffn - -@deffn procedure x-character-bounds/lbearing character-bounds -@deffnx procedure x-character-bounds/rbearing character-bounds -@deffnx procedure x-character-bounds/width character-bounds -@deffnx procedure x-character-bounds/ascent character-bounds -@deffnx procedure x-character-bounds/descent character-bounds -These procedures extract components of objects of type -@code{x-character-bounds}. A more complete description of them appears -in documentation of the@* @code{XLoadQueryFont} Xlib call. -@end deffn - -@node Win32 Graphics, OS/2 Graphics, X Graphics, Graphics -@section Win32 Graphics -@cindex Win32 graphics - -MIT/GNU Scheme supports graphics on Microsoft Windows 95, Windows 98, and -Windows NT. In addition to the usual operations, there are operations -to control the size, position and colors of a graphics window. Win32 -devices support images, which are implemented as device independent -bitmaps (@sc{dib}s). - -The Win32 graphics device type is implemented as a top level window. -@code{graphics-enable-buffering} is implemented and gives a 2x to 4x -speedup on many graphics operations. As a convenience, when buffering -is enabled clicking on the graphics window's title bar effects a -@code{graphics-flush} operation. The user has the benefit of the -increased performance and the ability to view the progress in drawing at -the click of a mouse button. - - -@menu -* Win32 Graphics Type:: -* Custom Operations for Win32 Graphics:: Custom Operations for Win32 Graphics Devices -@end menu - -@node Win32 Graphics Type, Custom Operations for Win32 Graphics, Win32 Graphics, Win32 Graphics -@subsection Win32 Graphics Type - -Win32 graphics devices are created by specifying the symbol @code{win32} -as the @var{graphics-device-type} argument to -@code{make-graphics-device}. The Win32 graphics device type is -implemented as a top-level window and supports color drawing in addition -to the standard Scheme graphics operations. - -Graphics devices are opened as follows: - -@example -(make-graphics-device 'win32 #!optional @var{width} @var{height} @var{palette}) -@end example - -@noindent -where @var{width} and @var{height} specify the size, in pixels, of the -drawing area in the graphics window (i.e.@: excluding the frame). -@var{Palette} determines the colors available for drawing in the window. - -When a color is specified for drawing, the nearest color available in -the palette is used. Permitted values for @var{palette} are - -@table @asis -@item @code{'grayscale} -The window allocates colors from a grayscale palette -of approximately 236 shades of gray. - -@item @code{'grayscale-128} -The window allocates colors from a grayscale palette of 128 shades of -gray. - -@item @code{'standard} -The standard palette has good selection of colors and grays. - -@item @code{#f} or @code{'system} -The colors available are those in the system palette. There are usually -16 to 20 colors in the system palette and these are usually sufficent -for simple applications like line drawings and x-vs-y graphs of -mathematical functions. Drawing with the system palette can be more -efficient. - -@end table -@noindent -If @var{palette} is not specified then the @code{standard} palette is -used. - - - -@node Custom Operations for Win32 Graphics, , Win32 Graphics Type, Win32 Graphics -@subsection Custom Operations for Win32 Graphics - -Custom operations are invoked using the procedure -@code{graphics-operation}. For example, - -@example -(graphics-operation device 'set-foreground-color "blue") -@end example - -@defop operation win32-graphics-device set-background-color color-name -@defopx operation win32-graphics-device set-foreground-color color-name -@findex set-background-color -@findex set-foreground-color -@cindex color -These operations change the colors associated with a window. -@var{Color-name} must be of one of the valid color specification forms -listed below. @code{set-background-color} and -@code{set-foreground-color} change the colors to be used when drawing, -but have no effect on anything drawn prior to their invocation. Because -changing the background color affects the entire window, we recommend -calling @code{graphics-clear} on the window's device afterwards. - -The foreground color affects the drawing of text, points, lines, -ellipses and filled polygons. - -Colors are specified in one of three ways: - -@table @asis -@item An integer -This is the Win32 internal RGB value. - -@item By name -A limited number of names are understood by the system. -Names are strings, e.g.@: @code{"red"}, @code{"blue"}, @code{"black"}. -More names can be registered with the @code{define-color} operation. - -@item RGB (Red-Green-Blue) triples -A triple is either a vector or list of three integers in the range -0--255 inclusive which specify the intensity of the red, green and blue -components of the color. Thus @code{#(0 0 0)} is black, @code{(0 0 -128)} is dark blue and @code{#(255 255 255)} is white. -@end table - -@noindent -If the color is not available in the graphics device then the nearest -available color is used instead. -@end defop - - -@defop operation win32-graphics-device define-color name spec -Define the string @var{name} to be the color specified by @var{spec}. -@var{Spec} may be any acceptable color specification. Note that the -color names defined this way are available to any Win32 graphics device, -and the names do @emph{not} have to be defined for each device. - - -Color names defined by this interface may also be used when setting the -colors of the Scheme console window, or the colors of Edwin editor -windows. -@end defop - -@defop operation win32-graphics-device find-color name -Looks up a color previously defined by @code{define-color}. This returns -the color in its most efficient form for operations -@code{set-foreground-color} or @code{set-background-color}. -@end defop - - -@defop operation win32-graphics-device draw-ellipse left top right bottom -@cindex ellipse, graphics -@cindex circle, graphics -@cindex graphics, ellipse -@cindex graphics, circle -Draw an ellipse. @var{Left}, @var{top}, @var{right} and @var{bottom} -indicate the coordinates of the bounding rectangle of the ellipse. -Circles are merely ellipses with equal width and height. Note that the -bounding rectangle has horizontal and vertical sides. Ellipses with -rotated axes cannot be drawn. The rectangle applies to the center of the -line used to draw the ellipse; if the line width has been set to greater -than 1 then the ellipse will spill outside the bounding rectange by half -of the line width. -@end defop - - -@defop operation win32-graphics-device fill-polygon points -@findex fill-polygon -Draws a filled polygon using the current foreground color. -@var{Points} is a vector of real numbers. -The numbers are in the order x1 y1 x2 y2 @dots{} xn yn. -For example, - -@example -(graphics-operation device 'fill-polygon #(0 0 0 1 1 0)) -@end example - -@noindent -draws a solid triangular region between the points (0, 0), (0, 1) and -(1, 0). -@end defop - - -@defop operation win32-graphics-device load-bitmap pathname -@cindex bitmaps -The graphics device contents and size are initialized from the windows -bitmap file specified by @var{pathname}. If no file type is supplied -then a @code{".BMP"} extension is added. If a clip rectangle is in -effect when this procedure is called, it is necessary to redefine the -clip rectangle afterwards. -@end defop - -@defop operation win32-graphics-device save-bitmap pathname -@cindex printing graphics output -The graphics device contents are saved as a bitmap to the file specified -by @var{pathname}. If no file type is supplied then a @code{".BMP"} -extension is added. The saved bitmap may be incorporated into documents -or printed. -@end defop - -@defop operation win32-graphics-device move-window x y -The graphics device window is moved to the screen position specified by -@var{x} and @var{y}. -@end defop - -@defop operation win32-graphics-device resize-window width height -The graphics device window is resized to the specified @var{width} and -@var{height} in device coordinates (pixels). If a clip rectangle is in effect -when this procedure is called, it is necessary to redefine the clip -rectangle afterwards. -@end defop - -@defop operation win32-graphics-device set-line-width width -This operation sets the line width for future drawing of lines, points -and ellipses. It does not affect existing lines and has no effect on -filled polygons. The line width is specified in device units. The -default and initial value of this parameter is 1 pixel. -@end defop - -@defop operation win32-graphics-device set-window-name name -This sets the window title to the string @var{name}. The window is -given the name @code{"Scheme Graphics"} at creation. -@end defop - -@defop operation win32-graphics-device set-font handle -Sets the font for drawing text. Currently not well supported. If you -can get a Win32 font handle it can be used here. -@end defop - -@defop operation win32-graphics-device copy-area source-x-left source-y-top width height destination-x-left destination-y-top -This operation copies the contents of the rectangle specified by -@var{source-x-left}, @var{source-y-top}, @var{width}, and @var{height} -to the rectangle of the same dimensions at @var{destination-x-left} and -@var{destination-y-top}. -@end defop - -@node OS/2 Graphics, , Win32 Graphics, Graphics -@section OS/2 Graphics -@cindex OS/2 graphics - -MIT/GNU Scheme supports graphics under the OS/2 Presentation Manager in -OS/2 version 2.1 and later. The OS/2 graphics device type is -implemented as a top level window. In addition to the usual operations, -there are operations to control the size, position, and colors of a -graphics window. OS/2 graphics devices support images, which are -implemented as memory presentation spaces. - -The custom graphics operations defined in this section are invoked using -the procedure @code{graphics-operation}. For example, - -@example -(graphics-operation device 'set-foreground-color "blue") -@end example - -@menu -* OS/2 Graphics Type:: -* Color Operations for OS/2 Graphics:: -* Window Operations for OS/2 Graphics:: -* Event Operations for OS/2 Graphics:: -* Miscellaneous Operations for OS/2 Graphics:: -@end menu - -@node OS/2 Graphics Type, Color Operations for OS/2 Graphics, OS/2 Graphics, OS/2 Graphics -@subsection OS/2 Graphics Type - -OS/2 graphics devices are created by specifying the symbol -@code{os/2} as the @var{graphics-device-type} argument to -@code{make-graphics-device}. The OS/2 graphics device type is -implemented as a top-level window and supports color drawing in addition -to the standard Scheme graphics operations. - -Graphics devices are opened as follows: - -@example -(make-graphics-device 'os/2 #!optional @var{width} @var{height}) -@end example - -@noindent -where @var{width} and @var{height} specify the size, in pixels, of the -drawing area in the graphics window (i.e.@: excluding the frame). - -@node Color Operations for OS/2 Graphics, Window Operations for OS/2 Graphics, OS/2 Graphics Type, OS/2 Graphics -@subsection Color Operations for OS/2 Graphics - -These operations control the colors used when drawing on an OS/2 -graphics device. - -@defop operation os2-graphics-device color? -@findex color? -This operation returns @code{#t} if the display supports color. -@end defop - -@defop operation os2-graphics-device set-background-color color-name -@defopx operation os2-graphics-device set-foreground-color color-name -@findex set-background-color -@findex set-foreground-color -@cindex color -These operations change the colors associated with a window. -@var{Color-name} must be one of the valid color specification forms -listed below. @code{set-background-color} and -@code{set-foreground-color} change the colors to be used when drawing, -but have no effect on anything drawn prior to their invocation. Because -changing the background color affects the entire window, we recommend -calling @code{graphics-clear} on the window's device afterwards. - -The foreground color affects the drawing of text, points, and lines. -Colors are specified in one of these ways: - -@table @asis -@item An integer between @code{0} and @code{#xffffff} inclusive -This is the OS/2 internal RGB value. - -@item By name -A limited number of names are understood by the system. Names are -strings, e.g.@: @code{"red"}, @code{"blue"}, @code{"black"}. More names -can be registered with the @code{define-color} operation. - -@item RGB (Red-Green-Blue) triples -A triple is a list of three integers between @code{0} and @code{#xff} -inclusive which specify the intensity of the red, green and blue -components of the color. Thus @code{(0 0 0)} is black, @code{(0 0 128)} -is dark blue and @code{(255 255 255)} is white. -@end table - -@noindent -If the color is not available in the graphics device then the nearest -available color is used instead. -@end defop - -@defop operation os2-graphics-device define-color name spec -Define the string @var{name} to be the color specified by @var{spec}. -@var{Spec} may be any acceptable color specification. Note that the -color names defined this way are available to any OS/2 graphics -device, and the names do @emph{not} have to be defined for each device. - -Color names defined by this interface may also be used when setting the -colors of the Scheme console window, or the colors of Edwin editor -windows. -@end defop - -@defop operation os2-graphics-device find-color name -Looks up a color previously defined by @code{define-color}. This -returns the color in its most efficient form for operations -@code{set-foreground-color} or @code{set-background-color}. -@end defop - -@node Window Operations for OS/2 Graphics, Event Operations for OS/2 Graphics, Color Operations for OS/2 Graphics, OS/2 Graphics -@subsection Window Operations for OS/2 Graphics - -These operations control the window that contains the OS/2 graphics -device. They provide facilities to change the window's size and -position; to raise and lower the window relative to other windows on the -desktop; to hide or minimize the window, and to restore it from the -hidden or minimized state; to activate or deactivate the window (that -is, control the keyboard focus); and to control the text that appears in -the window's title bar. - -@defop operation os2-graphics-device window-position -This operation returns the position of the graphics-device window on the -desktop. The position is returned as two values -(@pxref{Continuations}), which are the x and y coordinates of the -position. These coordinates are in units of pels (pixels), and measure -the distance between the lower left hand corner of the desktop and the -lower left hand corner of the graphics device window's frame. -@end defop - -@defop operation os2-graphics-device set-window-position x y -The graphics-device window is moved to the screen position specified by -@var{x} and @var{y}. The coordinates @var{x} and @var{y} are in units -of pels (pixels), and measure the distance between the lower left hand -corner of the desktop and the lower left hand corner of the graphics -device window's frame. -@end defop - -@defop operation os2-graphics-device window-size -This operation returns the size of the client area of the -graphics-device window. The client area is the part of the window that -you draw on; it does not include the window frame, title bar, etc. The -size is returned as two values (@pxref{Continuations}), which are the -width and height of the client area in units of pels (pixels). -@end defop - -@defop operation os2-graphics-device set-window-size width height -This operation sets the size of the client area of the graphics-device -window to the specified @var{width} and @var{height}, which are in units -of pels (pixels). The client area is the part of the window that you -draw on; it does not include the window frame, title bar, etc. -@end defop - -@defop operation os2-graphics-device window-frame-size -This operation returns the size of the graphics-device window's frame. -This includes the client area, as well as the border, title bar, etc. -The size is returned as two values (@pxref{Continuations}), which are -the width and height of the frame in units of pels (pixels). - -The frame size is useful in conjunction with the window position and the -desktop size to determine relative placement of the window or to -guarantee that the entire window is visible on the desktop. -@end defop - -@defop operation os2-graphics-device desktop-size -This operation returns the size of the OS/2 desktop. The size is -returned as two values (@pxref{Continuations}), which are the width and -height of the frame in units of pels (pixels). -@end defop - -@defop operation os2-graphics-device raise-window -This operation raises the graphics-device window so that it is on top of -any other windows on the desktop. -@end defop - -@defop operation os2-graphics-device lower-window -This operation lowers the graphics-device window so that it is below all -other windows on the desktop. -@end defop - -@defop operation os2-graphics-device hide-window -This operation hides the graphics-device window. The window disappears -from the desktop, but still appears in the window list. -@end defop - -@defop operation os2-graphics-device minimize-window -This operation minimizes the graphics-device window. The window -disappears from the desktop, but still appears in the window list. -Depending on how you have configured your desktop, the window may appear -as an icon, either on the desktop or in the minimized window viewer. -@end defop - -@defop operation os2-graphics-device maximize-window -This operation maximizes the graphics-device window. This causes the -window to fill the entire desktop. -@end defop - -@defop operation os2-graphics-device restore-window -This operation restores the graphics-device window to its normal state. -If the window is hidden or minimized, it is shown again, at its former -position on the desktop. If the window is maximized, it is returned to -its normal size. -@end defop - -@defop operation os2-graphics-device activate-window -This operation makes the graphics-device window be the active window. -This causes the window to be put in front of all other windows on the -desktop, highlights its frame, and gives it the keyboard focus. -@end defop - -@defop operation os2-graphics-device deactivate-window -This operation deactivates the graphics-device window if it was active -(otherwise it has no effect). This causes some other window to be -chosen to be active in its place. -@end defop - -@defop operation os2-graphics-device set-window-title title -This operation changes the text that appears in the graphics device -window's title bar. The new text is given by @var{title}, which must be -a string. -@end defop - -@node Event Operations for OS/2 Graphics, Miscellaneous Operations for OS/2 Graphics, Window Operations for OS/2 Graphics, OS/2 Graphics -@subsection Event Operations for OS/2 Graphics - -These operations allow you to read some of the events that are generated -by the Presentation Manager and put in the message queue of a -graphics-device window. - -@defop operation os2-graphics-device read-button -This operation waits for the user to push a mouse button inside the -client area of the graphics-device window. It then returns four values -(@pxref{Continuations}) which are: the button number; the x and y -coordinates of the mouse pointer at the time the button was pressed, in -pels (pixels) relative to the lower left hand corner of the client area; -and the graphics device that the mouse pointer was over at the time the -button was pressed. - -Note that this operation only works when button events are selected -(which is the default). -@end defop - -@defop operation os2-graphics-device select-user-events mask -This operation sets the event-selection mask for the graphics device to -@var{mask}. The event-selection mask is an exact non-negative integer -that specifies which types of incoming events are to be saved in the -user-event queue for later retrieval by the @code{read-user-event} -operation. The mask is specified by setting the bits corresponding to -the event types that you are interested in, as follows: - -@example -@group -Number Mask Description ------- ----- ----------- -0 #x001 Button press/release -1 #x002 Close (close the window) [WM_CLOSE] -2 #x004 Focus change [WM_SETFOCUS] -3 #x008 Key press/release [WM_CHAR] -4 #x010 Paint [WM_PAINT] -5 #x020 Size change [WM_SIZE] -6 #x040 Visibility change [WM_SHOW] -7 #x080 Command [WM_COMMAND] -8 #x100 Help [WM_HELP] -9 #x200 Mouse-move [WM_MOUSEMOVE] -@end group -@end example - -@noindent -Note that this operation does not affect any events that are already in -the user-event queue. Changing the mask only affects what events will -be added to the queue in the future. -@end defop - -@defop operation os2-graphics-device read-user-event -This operation returns the next user event available from the user-event -queue. If there are no events in the queue, the operation waits for an -event to arrive before returning. -@end defop - -An event is a vector whose first element is the event-type number, whose -second element is the graphics device that the event refers to, and -whose remaining elements provide information about the event. Here is a -table of the possible event types and their vector layout: - -@table @code -@item #(0 @var{device} @var{number} @var{type} @var{x} @var{y} @var{flags}) -A button event. @var{Number} is the button number, for example button -number @code{0} is usually the left mouse button, @code{1} is usually -the right button, etc. @var{Type} specifies what occurred: @code{0} -means the button was pressed, @code{1} means the button was released, -@code{2} means the button was clicked, and @code{3} means the button was -double clicked. @var{X} and @var{y} are the position of the mouse -pointer at the time of the event, in units of pels (pixels) measured -from the lower left corner of the client area of the associated window. -Finally, @var{flags} specifies what shift keys were pressed at the time -of the button event; it is a mask word created by combining zero or more -of the following flags: @code{#x08} means the shift key was pressed, -@code{#x10} means the control key was pressed, and @code{#x20} means the -alt key was pressed. - -@item #(1 @var{device}) -A close event. The user has selected the close button from the system -menu, or typed @key{Alt-f4}. - -@item #(2 @var{device} @var{gained?}) -A focus event. If @var{gained?} is @code{#t}, the keyboard focus is -being gained, and if @var{gained?} is @code{#f}, it is being lost. - -@item #(3 @var{device} @var{code} @var{flags} @var{repeat}) -A keyboard event. This is much too complicated to describe here. See -the OS/2 toolkit documentation for details. - -@item #(4 @var{device} @var{xl} @var{xh} @var{yl} @var{yh}) -A paint event. Part of the graphics-device window that was obscured has -been revealed and the Presentation Manager is informing the window that -it must repaint that area. Scheme will take care of the painting for -you, so this event isn't very useful. - -@item #(5 @var{device} @var{width} @var{height}) -A size-change event. The size of the graphics-device window has -changed, and @var{width} and @var{height} specify the new size in pels -(pixels). - -@item #(6 @var{device} @var{shown?}) -A visibility event. Indicates that the graphics-device window has been -hidden or revealed. If @var{shown?} is @code{#f}, the window is hidden, -and if it is @code{#t}, the window is shown. - -@item #(7 @var{device} @var{source} @var{mouse?}) -@itemx #(8 @var{device} @var{source} @var{mouse?}) -A menu command. @var{Source} specifies which menu item was selected to -cause this event, and @var{mouse?} is a boolean indicating whether the -item was selected with the mouse or the keyboard. The event-type number -@code{7} indicates a command from a @samp{WM_COMMAND} message, while -@code{8} is a command from a @samp{WM_HELP} message. - -@item #(9 @var{device} @var{x} @var{y} @var{hit-test} @var{flags}) -The mouse was moved. @var{X} and @var{y} specify the position of the -mouse, @var{hit-test} contains the hit-test information, and @var{flags} -specifies the modifier keys that were pressed at the time. -@end table - -@defop operation os2-graphics-device discard-events -This operation discards any events that are in the user-event queue. -This is sometimes useful when you want to prompt the user for some input -and don't want to consider any previous input. -@end defop - -@node Miscellaneous Operations for OS/2 Graphics, , Event Operations for OS/2 Graphics, OS/2 Graphics -@subsection Miscellaneous Operations for OS/2 Graphics - -These operations allow you to: change the font used for drawing text in -a graphics-device window; take a snapshot of a graphics-device window -and return it as an image object; and draw multiple lines efficiently. - -@defop operation os2-graphics-device set-font font-name -This operation sets the font used for drawing text in the -graphics-device window. @var{Font-name} is a string describing the -font; this string is in the form ".", for -example, @code{"10.Courier"}. You may specify any fixed-pitch font -family, in any point size that is supported for that font family. This -includes both image fonts and outline fonts. -@end defop - -@defop operation os2-graphics-device capture-image x-left y-bottom x-right y-top -This operation creates and returns an image that contains part of the -client area of the graphics-device window. The portion of the client -area that is selected is specified by the four coordinate arguments, -which are given in the current virtual coordinates for the device. -@xref{Images}, for more information about manipulating images. -@end defop - -@defop operation os2-graphics-device draw-lines xv yv -This operation draws multiple disjoint lines; it is like multiple calls -to @code{graphics-draw-line} but much faster. The arguments @var{xv} -and @var{yv} are vectors of coordinates; these vectors must be the same -length, and the length must be a multiple of two. The contents of the -vectors are alternating start/end pairs. For example, the following are -equivalent: - -@example -@group -(graphics-draw-line device xs ys xe ye) -(graphics-operation device 'draw-lines - (vector xs xe) - (vector ys ye)) -@end group -@end example -@end defop - -@node Win32 Package Reference, GNU Free Documentation License, Graphics, Top -@chapter Win32 Package Reference - -@ifinfo -The Win32 implementation is still in a state of development. It is -expected that changes will be necessary when MIT/GNU Scheme is ported to -Windows NT on the DEC Alpha architecture. In particular, the -current system is not arranged in a way that adequately distinguishes -between issues that are a consequence of the NT operating system and -those which are a consequence of the Intel x86 architecture. -@end ifinfo - -@menu -* Win32 Package Overview:: -* Foreign function interface:: -* Device Independent Bitmap Utilities:: -@end menu - - -@node Win32 Package Overview, Foreign function interface, Win32 Package Reference, Win32 Package Reference -@section Overview - - -The Win32 implementation is still in a state of development. It is -expected that changes will be necessary when MIT/GNU Scheme is ported to -Windows NT on the DEC Alpha architecture. In particular, the -current system is not arranged in a way that adequately distinguishes -between issues that are a consequence of the NT operating system and -those which are a consequence of the Intel x86 architecture. -@cindex limitations - -Thus this documentation is not definitive, it merely outlines how the -current system works. Parts of the system will change and any project -implemented using the win32 system must plan for a re-implementation -stage. - - -The Win32 implementation has several components: - -@itemize @bullet - -@item -Special microcode primitives. - -@item -A foreign function interface (FFI) for calling procedures in dynamically -linked libraries (DLLs). - -@item -An interface for Edwin. - -@item -The Win32 package provides support for using the features of the -Windows 3.1 and Windows NT 3.1 environments. - -@item -Device Independent Bitmap utilities. These are used by the win32 Scheme -Graphics implementation. (The Scheme Graphics implementation is -described in the Reference Manual). - -@end itemize - -Note that all the names in the Win32 support are part of the -@code{win32} package. The names are bound in the @code{(win32)} -environment, and do not appear as bindings in the user or root -environments. -An effect of this is that it is far easier to develop Win32 software in -the @code{(win32)} package environment or a child environment. - -@node Foreign function interface, Device Independent Bitmap Utilities, Win32 Package Overview, Win32 Package Reference -@section Foreign Function Interface - -The Win32 foreign function interface (FFI) is a primitive and fairly -simple system for calling procedures written in C in a -dynamically linked library (DLL). Both user's procedures from a custom -DLL and system procedures (e.g.@: MessageBox) are called using the same -mechanism. - -@cindex limitations -@strong{Warning}: The FFI as it stands has several flaws which make it -difficult to use reliably. It is expected that both the interface to -and the mechanisms used by the FFI will be changed in the future. We -provide it, and this documentation, only to give people an early start -in accessing some of the features of Win32 from Scheme. Should you use -it in an experiment we welcome any feedback. - -The FFI is designed for calling C procedures that use C data types -rather than Scheme data objects. Thus it is not possible to write and -call a C procedure that returns, for example, a Scheme list. The object -returned will always be an integer (which may represent the address of a -C data structure). - -@cindex warning -@strong{Warning}: It is extremely dangerous to try to pass Scheme -callback procedures to C procedures. It is only possible by passing -integer `handles' rather than the actual procedures, and even so, if a -garbage collection occurs during the execution of the callback procedure -objects in Scheme's heap will have moved. Thus in a foreign procedure -that has a callback and a string, after calling the callback the string -value may no longer be valid. Playing this game requires a profound -knowledge of the implementation. - - -The interface to the FFI has two main components: a language for -declaring the types of values passed to and returned from the foreign -procedures and a form for declaring foreign procedures. - -@menu -* Windows Types:: -* Windows Foreign Procedures:: -* Win32 API names and procedures:: -@end menu - -@node Windows Types, Windows Foreign Procedures, Foreign function interface, Foreign function interface -@subsection Windows Types - -@cindex Windows types -@cindex foreign type declarations -@cindex types, Windows -@cindex defining foreign types -Foreign types are designed to represent a correspondence between a -Scheme data type that is used to represent an object within the Scheme -world and a C data type that represents the data object in the C world. -Thus we cannot manipulate true C objects in Scheme, nor can we -manipulate Scheme objects in C. - -Each foreign type has four aspects that together ensure that the -correspondence between the Scheme and C objects is maintained. These -aspects are all encoded as procedures that either check for validity or -convert between representations. Thus a foreign type is not a -declarative type so much as a procedural description of how to pass the -type. The underlying foreign procedure call mechanism can pass integers -and vector-like Scheme objects, and returns integer values. All other -objects must be translated into integers or some other basic type, and -must be recovered from integers. - -The aspects are: - -@table @var - -@item check -A predicate that returns @code{#t} if the argument is of an acceptable -Scheme type, otherwise returns @code{#f}. -The @var{check} procedure is used for type-checking. - -@item convert -A procedure of one argument which returns a Scheme object of one of the -basic types. -It is used to convert an object into a `simpler' object that will -eventually be converted into a C object. -The legal simpler objects are integers and strings. - -@item return-convert -A procedure of one argument that, given an integer, returns a Scheme -object of a type satisfying @var{check}. -Its purpose is to convert the result returned by the foreign procedure -into a Scheme value. - -@item revert -Some C procedures modify one or more of their arguments. These -arguments are passed by reference, i.e.@: as a pointer to their address. -Since a Scheme object might have a different memory layout and storage -conventions, it must be passed by copy-in and copy-out rather than by -reference. -@var{Revert} is a procedure of two parameters, the original object -passed and the result of @var{convert} on that object. -@var{Revert} may then inspect the converted object and copy back the -changes to the original. - -@end table - -@deffn {special form} define-windows-type name check convert return revert -@deffnx {special form} define-similar-windows-type name model [check [convert [return [revert]]]] -@cindex defining foreign types -Both forms define a windows type. -The first form defines a type in terms of its aspects as described -above. -The second defines the type as being like another type, except for -certain aspects, which are redefined. -@var{Name} is the name of the type. -@var{Model} is the name of a type. -@var{Check}, @var{convert}, @var{return} and @var{revert} are -procedures or the value @code{#f}. -A @code{#f} means use the default value, which in the second form means -use the definition provided for @var{model}. -The defaults are - -@table @var -@item check -@code{(lambda (x) #t)}, i.e.@: unchecked. -@item convert -@code{(lambda (x) x)}, i.e.@: no translation performed. -@item return -@code{(lambda (x) x)}, i.e.@: no translation performed. -@item revert -@code{(lambda (x y) unspecific)}, i.e.@: no update performed -@end table - -The @code{unchecked} windows type (see below) is defined as: - -@example -(define-windows-type unchecked #f #f #f #f) -@end example - -Windows types are @emph{not} first class values, so they cannot be -stored in variables or defined using @code{define}: - -@example -@group -(define my-type unchecked) @error{} Unbound variable -(define-similar-windows-type my-type unchecked) - @r{;; the correct way} -@end group -@end example - -Scheme characters must be converted to integers. This is accomplished -as follows: - -@example -@group -(define-windows-type char - char? @r{; check} - char->integer @r{; convert} - integer->char @r{; convert return value} - #f @r{; cannot be passed by reference} -) -@end group -@end example -@end deffn - -@deffn {windows type} unchecked -The type which is not checked and undergoes only the basic conversion -from a Scheme integer to a C integer or from a Scheme string to a C -pointer to the first byte of the string. -Returned @code{unchecked} values are returned as integers. -@end deffn - -@deffn {windows type} bool -Scheme booleans are analogous to C integers @code{0} and @code{1}. -Windows type @code{bool} have been defined as: - -@example -@group -(define-windows-type bool - boolean? - (lambda (x) (if x 1 0)) - (lambda (x) (if (eq? x 0) #f #t)) - #f) -@end group -@end example -@end deffn - -@deffn {windows type} char -Scheme characters are converted into C objects of type @code{char}, -which are indistinguishable from small integers. -@end deffn - -@deffn {windows type} int -@deffnx {windows type} uint -@deffnx {windows type} long -@deffnx {windows type} ulong -@deffnx {windows type} short -@deffnx {windows type} ushort -@deffnx {windows type} word -@deffnx {windows type} byte -Various integer types that are passed without conversion. -@end deffn - -@deffn {windows type} string -A string that is passed as a C pointer of type @code{char*} to the first -character in the string. -@end deffn - -@deffn {windows type} char* -A string or @code{#f}. The string is passed as a pointer to characters. -The string is correctly null-terminated. @code{#f} is passed as the null -pointer. This is an example where there is a more complex mapping -between C objects and Scheme objects. C's @code{char*} type is -represented as one of two Scheme types depending on its value. This -allows us us to distinguish between the C string (pointer) that points -to the empty sequence of characters and the null pointer (which doesnt -point anywhere). -@end deffn - -@deffn {windows type} handle -@deffnx {windows type} hbitmap -@deffnx {windows type} hbrush -@deffnx {windows type} hcursor -@deffnx {windows type} hdc -@deffnx {windows type} hicon -@deffnx {windows type} hinstance -@deffnx {windows type} hmenu -@deffnx {windows type} hpalette -@deffnx {windows type} hpen -@deffnx {windows type} hrgn -@deffnx {windows type} hwnd -Various kinds of Win32 handle. These names correspond to the same, but -all uppercase, names in the Windows C language header files. Win32 API -calls are the source of values of this type and the values are -meaningless except as arguments to other Win32 API calls. Currently -these values are represented as integers but we expect that Win32 -handles will in future be represented by allocated Scheme objects -(e.g.@: records) that will allow predicates (e.g.@: @code{hmenu?}) and -sensible interlocking with the garbage collector to free the programmer -of the current tedious allocation and deallocation of handles. -@end deffn - -@deffn {windows type} resource-id -A Windows resource identifier is either a small integer or a string. -In C, this distinction is possible because pointers look like -larger integers, so a machine word representing a small integer can be -distinguished from a machine word that is a pointer to the text of the -name of the resource. -@end deffn - - -@node Windows Foreign Procedures, Win32 API names and procedures, Windows Types, Foreign function interface -@subsection Windows Foreign Procedures - -Foreign procedures are declared as callable entry-points in a module, -usually a dynamically linked library (DLL). - - -@deffn procedure find-module name -@cindex loading DLLs -@cindex DLL, loading -Returns a module suitable for use in creating procedures with -@code{windows-procedure}. @var{Name} is a string which is the name of a -DLL file. Internally, @code{find-module} uses the @code{LoadLibrary} -Win32 API, so @var{name} should conform to the specifications for this -call. @var{Name} should be either a full path name of a DLL, or the -name of a DLL that resides in the same directory as the Scheme binary -@file{SCHEME.EXE} or in the system directory. - -The module returned is a description for the DLL, and the DLL need not -necessarily be linked at or immediately after this call. DLL modules -are linked on need and unlinked before Scheme exits and when there -are no remaining references to entry points after a garbage-collection. -This behavior ensures that the Scheme system can run when a DLL is -absent, provided the DLL is not actually used (i.e.@: no attempt is made -to call a procedure in the DLL). -@end deffn - - -@defvr variable gdi32.dll -@cindex DLL, GDI32.DLL -This variable is bound to the module describing the @file{GDI32.DLL} -library, which contains the Win32 API graphics calls, e.g.@: -@code{LineTo}. -@end defvr - -@defvr variable kernel32.dll -@cindex DLL, KERNEL32.DLL -This variable is bound to the module describing the @file{KERNEL32.DLL} -library. -@end defvr - -@defvr variable user32.dll -@cindex DLL, USER32.DLL -This variable is bound to the module describing the @file{USER32.DLL} -library. This module contains many useful Win32 API procedures, like -@code{MessageBox} and @code{SetWindowText}. -@end defvr - - -@deffn {special form} windows-procedure (name (parameter type) @dots{}) return-type module entry-name [options] -@cindex defining foreign procedures -This form creates a procedure, and could be thought of as -``foreign-named-lambda''. The form creates a Scheme procedure that -calls the C procedure identified by the exported entry point -@var{entry-name} in the module identified by the value of @var{module}. -Both @var{entry-name} and @var{module} are evaluated at procedure -creation time, so either may be expression. @var{Entry-name} must -evaluate to a string and @var{module} must evaluate to a module as -returned by @code{find-module}. -These are the only parts of the form that are evaluated at procedure -creation time. - -@var{Name} is the name of the procedure and is for documentation -purposes only. This form @emph{does not} define a procedure called -@var{name}. It is more like @code{lambda}. The name might be used for -debugging and pretty-printing. - -A windows procedure has a fixed number of parameters (i.e.@: no `rest' -parameters or `varargs'), each of which is named and associated with a -windows type @var{type}. Both the name @var{parameter} and the windows -type @var{type} must be symbols and are not evaluated. The procedure -returns a value of the windows type @var{return-type}. - -The following example creates a procedure that takes a window handle -(@code{hwnd}) and a string and returns a boolean (@code{bool}) result. -The procedure does this by calling the @code{SetWindowText} entry in the -module that is the value of the variable @code{user32.dll}. The -variable @code{set-window-title} is defined to have this procedure as -it's value. - -@example -@group -(define set-window-title - (windows-procedure - (set-window-text (window hwnd) (text string)) - bool user32.dll "SetWindowText")) - -(set-window-title my-win "Hi") - @result{} #t - @r{;; Changes window's title/text} - -set-window-title @result{} #[compiled-procedure @dots{}] -set-window-text @error{} Unbound variable -@end group -@end example - - -When there are no @var{options} the created procedure will (a) check its -arguments against the types, (b) convert the arguments, (c) call the C -procedure and (d) convert the returned value. No reversion is -performed, even if one of the @var{types} has a reversion defined. -(Reverted types are rare [I have never used one], so paying a cost for -this unless it is used seems silly). - -The following options are allowed: - -@table @asis -@item @code{with-reversions} -The reversions are included in the type conversions. - -@item @code{expand} -A synonym for @code{with-reversions}. - -@item @var{Scheme code} -The @var{Scheme code} is placed between steps (a) and (b) in the default -process. The Scheme code can enforce constraints on the arguments, -including constraints between arguments such as checking that an index -refers to a valid position in a string. -@end table - -If both options (i.e.@: @code{with-reversions} and Scheme code) are used, -@code{with-reversions} must appear first. There can be arbitrarily many -Scheme expression. -@end deffn - -@node Win32 API names and procedures, , Windows Foreign Procedures, Foreign function interface -@subsection Win32 API names and procedures - -This section is a moving target. -@cindex Win32 API names -@cindex naming conventions - -The @code{#define} values from @file{wingdi.h} and @file{winuser.h} are -available as bindings in the @code{(win32)} package environment. The -@code{#define} symbols are all uppercase; these have been translated to -all lowercase Scheme identifiers, thus @code{WM_LBUTTONUP} is the scheme -variable @code{wm_lbuttonup}. As Scheme is case insensitive, the -upper-case version may be used and probably should to make the code look -more like conventional Windows code. The Scheme bindings have been -produced automagically. Most of the @code{#define}-symbols contain an -underscore so there are not many name clashes. There is one very -notable name clash, however: @code{ERROR} is @code{#define}d to 0, which -shadows the scheme procedure @code{error} in the root package -environment. To signal an error, use @code{access} to get @code{error} -from the system global environment: - -@example -@group -(declare (usual-integrations)) -@dots{} -((access error system-global-environment) "Complain" @dots{}) -@end group -@end example - - -The set of procedures is incomplete because procedures have been added -on a by-need basis for the implementation of other parts of the system, -e.g.@: Scheme Graphics. Look in the implementation for further details. - -Win32 API procedure names have been uniformly converted into Scheme -identifiers as follows: - -@itemize @bullet -@item -A leading uppercase letter is translated into a lowercase letter. -@item -Subsequent sequences of uppercase letters are translated into lowercase -letters preceeded by a hyphen (minus symbol), i.e.@: hyphens are inserted -at a lowercase to uppercase transition. -@item -Predicates beginning with @code{Is} finally have a -question-mark appended. -@end itemize - -@noindent -Example: applying these rules to @code{IsWindow} yields -@code{is-window?}, and @code{GetDC} is translated into @code{get-dc}. - - -@c [It might be worthwhile just keeping the same names. As the -@c Win32 API procedure names are uniformly `WordWordWordACRONYMWord', case -@c insensitivity is unlikely to be a problem. The only problem is the -@c potential for a clash between a procedure name and a type -@c name.] - - -@node Device Independent Bitmap Utilities, , Foreign function interface, Win32 Package Reference -@section Device Independent Bitmap Utilities - - -The Device Independent Bitmap (DIB) utilities library @file{DIBUTILS.DLL} -and the associated procedures in @file{dib.scm} in the Win32 system -source is an example of how to use the foreign function interface to -access and manipulate non-Scheme objects. -@cindex DLL, DIBUTILS.DLL - -@deffn {windows type} dib -In the C world a DIB is a @dfn{handle} to a piece of memory containing -the bits that represent information about the image and the pixels of -the image. The handle is a machine-word sized piece of data which may -be thought of as a 32 bit integer. The handle may be null (i.e.@: zero), -indicating that there is no block of memory describing the DIB. The -null value is usually returned by C functions that are supposed to -create a DIB but failed, for some reason like the memory could not be -allocated or a file could not be opened. - -In the Scheme world a DIB is a structure containing information -about the bitmap (specifically the integer that represents the handle). -We also include @code{#f} in the @code{dib} windows type to mirror the -null handle error value. - -@example -@group -(define dib-result - (lambda (handle) - (if (= handle 0) - #f - (make-dib handle)))) - -(define dib-arg - (lambda (dib) - (if dib - (cell-contents (dib-handle dib)) - 0))) - -(define-windows-type dib - (lambda (thing) (or (dib? thing) (eq? thing #f))) - dib-arg - dib-result) -@end group -@end example -@end deffn - - -@menu -* DIB procedures:: -* Other parts of the DIB Utilities implementation:: -@end menu - -@node DIB procedures, Other parts of the DIB Utilities implementation, Device Independent Bitmap Utilities, Device Independent Bitmap Utilities -@subsection DIB procedures - -The following procedures have typed parameters, using the same -convention as @code{windows-procedure}. - -@deffn procedure open-dib (filename string) -Return type: @var{dib}. Calls the @code{OpenDIB} entry of -@file{DIBUTILS.DLL}. If the return value is not @code{#f} then the file -@var{filename} was found, successfully opened, and the contents were -suitable for loading into memory as a device independent bitmap. -@end deffn - -@deffn procedure write-dib (filename string) (dib dib) -Return type: @var{bool}. Calls the @code{WriteDIB} entry of -@file{DIBUTILS.DLL}. Returns @code{#t} if the file @var{filename} could -be opened and written to. After this operation the file contains the -bitmap data in a standard format that is understood by @code{open-dib} -and various system utilities like the bitmap editor. Any problems -resulting in failure are signalled by a @code{#f} return value. -@end deffn - -@deffn procedure bitmap-from-dib (dib dib) (palette hpalette) -Return type: @var{hbitmap}. -Calls the @code{BitmapFromDib} entry of @file{DIBUTILS.DLL}. The returned -value is a device dependent bitmap. The colours from the DIB are -matched against colors in @var{palette}. -@end deffn - -@deffn procedure dib-from-bitmap (bitmap hbitmap) (style dword) (bits word) (palette hpalette) -Return type: @var{dib}. -Returns a DIB containing the same image as the device dependent bitmap -@var{bitmap}. -@var{Style} determines the kind of DIB, e.g.@: compression style. -Calls the @code{DibFromBitmap} entry of @file{DIBUTILS.DLL}. -@end deffn - -@deffn procedure dib-blt (dest hdc) (x int) (y int) (w int) (h int) (src dib) (src-x int) (src-y int) (raster-op long) -Return type: @var{bool}. Calls the @code{DibBlt} entry of -@file{DIBUTILS.DLL}. Similar to the Win32 API @code{BitBlt} call, but -draws a DIB rather than a piece of another device context. Draws the -@var{dib} on device context @var{hdc} at position (@var{x},@var{y}). A -rectangle of width @var{w} and height @var{h} is copied from position -(@var{src-x},@var{src-y}) of @var{dib}. -@var{Raster-op} is supposed to allow the source and destination to be -combined but I don't think I got this right so stick to @code{SRCCOPY}. -@end deffn - -@deffn procedure %delete-dib (dib-handle handle) -Return type: @var{bool}. -Calls the @code{DeleteDIB} entry of @file{DIBUTILS.DLL}. -Note that the parameter is a @var{handle}, and not a @var{dib}. -This allows us to destroy a DIB and reclaim its memory by knowing only -the handle value, and not needing the @code{dib} record. -The importance of this is that if the @code{dib} record is GC-ed then a -GC hook can reclaim the storage knowing only the handle. -@end deffn - -@deffn procedure delete-dib (dib dib) -Return type: @var{bool}. -This procedure calls @code{%delete-dib} to reclaim the storage occupied -by a DIB. -After being deleted, the DIB should not be used. -This procedure allows the programmer to reclaim external heap storage -rather than risking it running out before the next garbage collection. -@end deffn - -@deffn procedure dib-height (dib dib) -Return type: @var{int}. -Calls the @code{DibHeight} expand entry of @file{DIBUTILS.DLL}, which returns -the height of the bitmap in pixels. -@end deffn - -@deffn procedure dib-width (dib dib) -Return type: @var{int}. -Calls the @code{DibWidth} entry of @file{DIBUTILS.DLL}, which returns -the width of the bitmap in pixels. -@end deffn - -@deffn procedure copy-bitmap (bm hbitmap) -Return type: @var{hbitmap}. -Calls the @code{CopyBitmap} of @file{DIBUTILS.DLL}, which creates a new -bitmap with the same size and contents as the original. -@end deffn - -@deffn procedure create-dib (width int) (height int) (style int) (depth int) (palette hpalette) -Return type: @var{dib}. -Calls the @code{CreateDIB} entry of @file{DIBUTILS.DLL}. -Creates a DIB of @var{width} by @var{height} pixels and @var{depth} bits -of colour information. -The @var{style} parameter determines how the bitmap is stored. -I have only ever used @code{BI_RGB}. -If @var{depth}<=8 then the @var{palette} determines the DIB's colour table. -@end deffn - -@deffn procedure crop-bitmap (bm hbitmap) (left int) (top int) (right int) (bottom int) -Return type: @var{hbitmap}. -Calls the @code{CropBitmap} entry of @file{DIBUTILS.DLL}. -Returns a new bitmap containing the image from a region of the original. -@end deffn - -@deffn procedure dib-set-pixels-unaligned dib (pixels string) -Return type: @var{bool}. -Calls the @code{DIBSetPixelsUnaligned} entry of@* @file{DIBUTILS.DLL}. Stuffs -bytes from @var{pixels} into the bitmap. There are no alignment -constraints on @var{pixels} (the usual way of doing this is to use the -@code{SetDIBits} function which requires that every scan line of the -bitmap is 32-bit word aligned, even if the scan lines are not a multiple -of 4 bytes long). doing this -@end deffn - -@node Other parts of the DIB Utilities implementation, , DIB procedures, Device Independent Bitmap Utilities -@subsection Other parts of the DIB Utilities implementation - - -The @file{DIBUTILS.DLL} library is an ordinary DLL. See the standard -Microsoft Windows documentation on how to create DLLs. Look at the code -in the @file{WIN32/DIBUTILS} directory of the Scheme source. - -Please note: -@itemize @bullet -@item -@cindex DLL, exports -For the foreign function interface to find the procedures they must be -declared as exports in the @file{.DEF} definition file. - -@item -To load the @file{.DLL} file use the @code{find-module} Scheme function. -Look at @file{WIN32/DIB.SCM} to see how this is done. - -@item -The current system works with C procedures with the @code{__stdcall} and -@code{__cdecl} calling conventions but @emph{not} the @code{__fastcall} -calling convention. -@end itemize - +@include overview.texi +@include special-forms.texi +@include equivalence.texi +@include numbers.texi +@include characters.texi +@include strings.texi +@include lists.texi +@include vectors.texi +@include bit-strings.texi +@include misc-datatypes.texi +@include associations.texi +@include procedures.texi +@include environments.texi +@include io.texi +@include os-interface.texi +@include error.texi +@include graphics.texi +@include win32-packaging.texi @node GNU Free Documentation License, Binding Index, Win32 Package Reference, Top @appendix GNU Free Documentation License @include gfdl.texinfo diff --git a/v7/doc/ref-manual/special-forms.texi b/v7/doc/ref-manual/special-forms.texi new file mode 100644 index 000000000..071f4f749 --- /dev/null +++ b/v7/doc/ref-manual/special-forms.texi @@ -0,0 +1,3039 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: special-forms.texi,v 1.1 2003/04/15 03:30:15 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Special Forms, Equivalence Predicates, Overview, Top +@chapter Special Forms + +@cindex special form +A special form is an expression that follows special evaluation rules. +This chapter describes the basic Scheme special forms. + +@menu +* Lambda Expressions:: +* Lexical Binding:: +* Dynamic Binding:: +* Definitions:: +* Assignments:: +* Quoting:: +* Conditionals:: +* Sequencing:: +* Iteration:: +* Structure Definitions:: +* Macros:: +* SRFI syntax:: +@end menu + +@node Lambda Expressions, Lexical Binding, Special Forms, Special Forms +@section Lambda Expressions + +@deffn {special form} lambda formals expression expression @dots{} +@cindex lambda expression (defn) +@cindex procedure, construction +@cindex procedure, closing environment (defn) +@cindex procedure, invocation environment (defn) +@cindex construction, of procedure +@cindex closing environment, of procedure (defn) +@cindex invocation environment, of procedure (defn) +@cindex environment, of procedure +@cindex environment, procedure closing (defn) +@cindex environment, procedure invocation (defn) +A @code{lambda} expression evaluates to a procedure. The environment in +effect when the @code{lambda} expression is evaluated is remembered as +part of the procedure; it is called the @dfn{closing environment}. When +the procedure is later called with some arguments, the closing +environment is extended by binding the variables in the formal parameter +list to fresh locations, and the locations are filled with the arguments +according to rules about to be given. The new environment created by +this process is referred to as the @dfn{invocation environment}. + +@cindex region of variable binding, lambda +@cindex variable binding, lambda +Once the invocation environment has been constructed, the +@var{expression}s in the body of the @code{lambda} expression are +evaluated sequentially in it. This means that the region of the +variables bound by the @code{lambda} expression is all of the +@var{expression}s in the body. The result of evaluating the last +@var{expression} in the body is returned as the result of the procedure +call. + +@cindex lambda list (defn) +@cindex parameter list, of lambda (defn) +@cindex formal parameter list, of lambda (defn) +@var{Formals}, the formal parameter list, is often referred to as a +@dfn{lambda list}. + +The process of matching up formal parameters with arguments is somewhat +involved. There are three types of parameters, and the matching treats +each in sequence: + +@need 1000 +@table @asis +@item Required +All of the @dfn{required} parameters are matched against the arguments +first. If there are fewer arguments than required parameters, an error +of type @code{condition-type:wrong-number-of-arguments} is signalled; +this error is also signalled if there are more arguments than required +parameters and there are no further parameters. +@cindex required parameter (defn) +@cindex parameter, required (defn) +@findex condition-type:wrong-number-of-arguments + +@item Optional +Once the required parameters have all been matched, the @dfn{optional} +parameters are matched against the remaining arguments. If there are +fewer arguments than optional parameters, the unmatched parameters are +bound to special objects called @dfn{default objects}. If there are +more arguments than optional parameters, and there are no further +parameters, an error of type +@code{condition-type:wrong-number-of-arguments} is signalled. +@cindex optional parameter (defn) +@cindex parameter, optional (defn) +@cindex default object (defn) +@findex condition-type:wrong-number-of-arguments + +@findex default-object? +The predicate @code{default-object?}, which is true only of default +objects, can be used to determine which optional parameters were +supplied, and which were defaulted. + +@item Rest +Finally, if there is a @dfn{rest} parameter (there can only be one), any +remaining arguments are made into a list, and the list is bound to the +rest parameter. (If there are no remaining arguments, the rest +parameter is bound to the empty list.) +@cindex rest parameter (defn) +@cindex parameter, rest (defn) + +In Scheme, unlike some other Lisp implementations, the list to which a +rest parameter is bound is always freshly allocated. It has infinite +extent and may be modified without affecting the procedure's caller. +@end table + +@findex #!optional +@findex #!rest +Specially recognized keywords divide the @var{formals} parameters into +these three classes. The keywords used here are @samp{#!optional}, +@samp{.}, and @samp{#!rest}. Note that only @samp{.} is defined by +standard Scheme --- the other keywords are MIT/GNU Scheme extensions. +@samp{#!rest} has the same meaning as @samp{.} in @var{formals}. + +The use of these keywords is best explained by means of examples. The +following are typical lambda lists, followed by descriptions of which +parameters are required, optional, and rest. We will use @samp{#!rest} +in these examples, but anywhere it appears @samp{.} could be used +instead. + +@table @code +@item (a b c) +@code{a}, @code{b}, and @code{c} are all required. The procedure must +be passed exactly three arguments. + +@item (a b #!optional c) +@code{a} and @code{b} are required, @code{c} is optional. The procedure +may be passed either two or three arguments. + +@item (#!optional a b c) +@code{a}, @code{b}, and @code{c} are all optional. The procedure may be +passed any number of arguments between zero and three, inclusive. + +@item a +@itemx (#!rest a) +These two examples are equivalent. @code{a} is a rest parameter. The +procedure may be passed any number of arguments. Note: this is the only +case in which @samp{.} cannot be used in place of @samp{#!rest}. + +@item (a b #!optional c d #!rest e) +@code{a} and @code{b} are required, @code{c} and @code{d} are optional, +and @code{e} is rest. The procedure may be passed two or more +arguments. +@end table + +Some examples of @code{lambda} expressions: + +@example +@group +(lambda (x) (+ x x)) @result{} #[compound-procedure 53] + +((lambda (x) (+ x x)) 4) @result{} 8 + +(define reverse-subtract + (lambda (x y) + (- y x))) +(reverse-subtract 7 10) @result{} 3 + +(define foo + (let ((x 4)) + (lambda (y) (+ x y)))) +(foo 6) @result{} 10 +@end group +@end example +@end deffn + +@deffn {special form} named-lambda formals expression expression @dots{} +@cindex named lambda (defn) +The @code{named-lambda} special form is similar to @code{lambda}, except +that the first ``required parameter'' in @var{formals} is not a +parameter but the @dfn{name} of the resulting procedure; thus +@var{formals} must have at least one required parameter. This name has +no semantic meaning, but is included in the external representation of +the procedure, making it useful for debugging. In MIT/GNU Scheme, +@code{lambda} is implemented as @code{named-lambda}, with a special name +that means ``unnamed''. + +@example +@group +(named-lambda (f x) (+ x x)) @result{} #[compound-procedure 53 f] +((named-lambda (f x) (+ x x)) 4) @result{} 8 +@end group +@end example +@end deffn + +@node Lexical Binding, Dynamic Binding, Lambda Expressions, Special Forms +@section Lexical Binding + +@cindex lexical binding expression +@cindex binding expression, lexical +@cindex block structure +The three binding constructs @code{let}, @code{let*}, and @code{letrec}, +give Scheme block structure. The syntax of the three constructs is +identical, but they differ in the regions they establish for their +variable bindings. In a @code{let} expression, the initial values are +computed before any of the variables become bound. In a @code{let*} +expression, the evaluations and bindings are sequentially interleaved. +And in a @code{letrec} expression, all the bindings are in effect while +the initial values are being computed (thus allowing mutually recursive +definitions). + +@deffn {special form} let ((@var{variable} @var{init}) @dots{}) expression expression @dots{} +@cindex region of variable binding, let +@cindex variable binding, let +The @var{init}s are evaluated in the current environment (in some +unspecified order), the @var{variable}s are bound to fresh locations +holding the results, the @var{expression}s are evaluated sequentially in +the extended environment, and the value of the last @var{expression} is +returned. Each binding of a @var{variable} has the @var{expression}s as +its region. + +MIT/GNU Scheme allows any of the @var{init}s to be omitted, in which +case the corresponding @var{variable}s are unassigned. + +@cindex lambda, implicit in let +Note that the following are equivalent: + +@example +@group +(let ((@var{variable} @var{init}) @dots{}) @var{expression} @var{expression} @dots{}) +((lambda (@var{variable} @dots{}) @var{expression} @var{expression} @dots{}) @var{init} @dots{}) +@end group +@end example + +Some examples: + +@example +@group +(let ((x 2) (y 3)) + (* x y)) @result{} 6 +@end group + +@group +(let ((x 2) (y 3)) + (let ((foo (lambda (z) (+ x y z))) + (x 7)) + (foo 4))) @result{} 9 +@end group +@end example + +@xref{Iteration}, for information on ``named @code{let}''. +@end deffn + +@deffn {special form} let* ((@var{variable} @var{init}) @dots{}) expression expression @dots{} +@cindex region of variable binding, let* +@cindex variable binding, let* +@code{let*} is similar to @code{let}, but the bindings are performed +sequentially from left to right, and the region of a binding is that +part of the @code{let*} expression to the right of the binding. Thus +the second binding is done in an environment in which the first binding +is visible, and so on. + +Note that the following are equivalent: + +@example +@group +(let* ((@var{variable1} @var{init1}) + (@var{variable2} @var{init2}) + @dots{} + (@var{variableN} @var{initN})) + @var{expression} + @var{expression} @dots{}) +@end group + +@group +(let ((@var{variable1} @var{init1})) + (let ((@var{variable2} @var{init2})) + @dots{} + (let ((@var{variableN} @var{initN})) + @var{expression} + @var{expression} @dots{}) + @dots{})) +@end group +@end example + +An example: + +@example +@group +(let ((x 2) (y 3)) + (let* ((x 7) + (z (+ x y))) + (* z x))) @result{} 70 +@end group +@end example +@end deffn + +@deffn {special form} letrec ((@var{variable} @var{init}) @dots{}) expression expression @dots{} +@cindex region of variable binding, letrec +@cindex variable binding, letrec +The @var{variable}s are bound to fresh locations holding unassigned +values, the @var{init}s are evaluated in the extended environment (in +some unspecified order), each @var{variable} is assigned to the result +of the corresponding @var{init}, the @var{expression}s are evaluated +sequentially in the extended environment, and the value of the last +@var{expression} is returned. Each binding of a @var{variable} has the +entire @code{letrec} expression as its region, making it possible to +define mutually recursive procedures. + +MIT/GNU Scheme allows any of the @var{init}s to be omitted, in which +case the corresponding @var{variable}s are unassigned. + +@example +@group +(letrec ((even? + (lambda (n) + (if (zero? n) + #t + (odd? (- n 1))))) + (odd? + (lambda (n) + (if (zero? n) + #f + (even? (- n 1)))))) + (even? 88)) @result{} #t +@end group +@end example + +@findex lambda +@findex delay +One restriction on @code{letrec} is very important: it shall be possible +to evaluated each @var{init} without assigning or referring to the value +of any @var{variable}. If this restriction is violated, then it is an +error. The restriction is necessary because Scheme passes arguments by +value rather than by name. In the most common uses of @code{letrec}, +all the @var{init}s are @code{lambda} or @code{delay} expressions and +the restriction is satisfied automatically. +@end deffn + +@node Dynamic Binding, Definitions, Lexical Binding, Special Forms +@section Dynamic Binding + +@deffn {special form} fluid-let ((@var{variable} @var{init}) @dots{}) expression expression @dots{} +@cindex binding expression, dynamic (or fluid) +@cindex fluid binding +@cindex dynamic binding +@cindex variable binding, fluid-let +The @var{init}s are evaluated in the current environment (in some +unspecified order), the current values of the @var{variable}s are saved, +the results are assigned to the @var{variable}s, the @var{expression}s +are evaluated sequentially in the current environment, the +@var{variable}s are restored to their original values, and the value of +the last @var{expression} is returned. + +@findex let +The syntax of this special form is similar to that of @code{let}, but +@code{fluid-let} temporarily rebinds existing variables. Unlike +@code{let}, @code{fluid-let} creates no new bindings; instead it +@emph{assigns} the value of each @var{init} to the binding (determined +by the rules of lexical scoping) of its corresponding @var{variable}. + +@cindex unassigned variable, and dynamic bindings +MIT/GNU Scheme allows any of the @var{init}s to be omitted, in which +case the corresponding @var{variable}s are temporarily unassigned. + +An error of type @code{condition-type:unbound-variable} is signalled if +any of the @var{variable}s are unbound. However, because +@code{fluid-let} operates by means of side effects, it is valid for any +@var{variable} to be unassigned when the form is entered. +@findex condition-type:unbound-variable + +Here is an example showing the difference between @code{fluid-let} and +@code{let}. First see how @code{let} affects the binding of a variable: + +@example +@group +(define variable #t) +(define (access-variable) variable) +variable @result{} #t +(let ((variable #f)) + (access-variable)) @result{} #t +variable @result{} #t +@end group +@end example + +@code{access-variable} returns @code{#t} in this case because it +is defined in an environment with @code{variable} bound to +@code{#t}. @code{fluid-let}, on the other hand, temporarily reuses an +existing variable: + +@example +@group +variable @result{} #t +(fluid-let ((variable #f)) @r{;reuses old binding} + (access-variable)) @result{} #f +variable @result{} #t +@end group +@end example + +@cindex extent, of dynamic binding (defn) +The @dfn{extent} of a dynamic binding is defined to be the time period +during which the variable contains the new value. Normally this time +period begins when the body is entered and ends when it is exited; on a +sequential machine it is normally a contiguous time period. However, +because Scheme has first-class continuations, it is possible to leave +the body and then reenter it, as many times as desired. In this +situation, the extent becomes non-contiguous. + +@cindex dynamic binding, and continuations +@cindex continuation, and dynamic binding +When the body is exited by invoking a continuation, the new value is +saved, and the variable is set to the old value. Then, if the body is +reentered by invoking a continuation, the old value is saved, and the +variable is set to the new value. In addition, side effects to the +variable that occur both inside and outside of body are preserved, even +if continuations are used to jump in and out of body repeatedly. +@end deffn + +Here is a complicated example that shows the interaction between dynamic +binding and continuations: + +@example +@group +(define (complicated-dynamic-binding) + (let ((variable 1) + (inside-continuation)) + (write-line variable) + (call-with-current-continuation + (lambda (outside-continuation) + (fluid-let ((variable 2)) + (write-line variable) + (set! variable 3) + (call-with-current-continuation + (lambda (k) + (set! inside-continuation k) + (outside-continuation #t))) + (write-line variable) + (set! inside-continuation #f)))) + (write-line variable) + (if inside-continuation + (begin + (set! variable 4) + (inside-continuation #f))))) +@end group +@end example + +@noindent +Evaluating @samp{(complicated-dynamic-binding)} writes the following on +the console: + +@example +@group +1 +2 +1 +3 +4 +@end group +@end example + +@noindent +Commentary: the first two values written are the initial binding of +@code{variable} and its new binding after the @code{fluid-let}'s body is +entered. Immediately after they are written, @code{variable} is set to +@samp{3}, and then @code{outside-continuation} is invoked, causing us to +exit the body. At this point, @samp{1} is written, demonstrating that +the original value of @code{variable} has been restored, because we have +left the body. Then we set @code{variable} to @samp{4} and reenter the +body by invoking @code{inside-continuation}. At this point, @samp{3} is +written, indicating that the side effect that previously occurred within +the body has been preserved. Finally, we exit body normally, and write +@samp{4}, demonstrating that the side effect that occurred outside of +the body was also preserved. + +@node Definitions, Assignments, Dynamic Binding, Special Forms +@section Definitions +@cindex definition + +@deffn {special form} define variable [expression] +@deffnx {special form} define @var{formals} expression expression @dots{} +@cindex variable, adding to environment +@cindex definition, top-level (defn) +@cindex definition, internal (defn) +@cindex top-level definition (defn) +@cindex internal definition (defn) +@findex lambda +@findex let +@findex let* +@findex letrec +@findex fluid-let +Definitions are valid in some but not all contexts where expressions are +allowed. Definitions may only occur at the top level of a program and +at the beginning of a lambda body (that is, the body of a @code{lambda}, +@code{let}, @code{let*}, @code{letrec}, @code{fluid-let}, or ``procedure +@code{define}'' expression). A definition that occurs at the top level +of a program is called a @dfn{top-level definition}, and a definition +that occurs at the beginning of a body is called an @dfn{internal +definition}. + +@cindex lambda, implicit in define +@cindex procedure define (defn) +@cindex define, procedure (defn) +@findex named-lambda +In the second form of @code{define} (called ``@dfn{procedure +@code{define}}''), the component @var{formals} is identical to the +component of the same name in a @code{named-lambda} expression. In +fact, these two expressions are equivalent: + +@example +@group +(define (@var{name1} @var{name2} @dots{}) + @var{expression} + @var{expression} @dots{}) +@end group + +@group +(define @var{name1} + (named-lambda (@var{name1} @var{name2} @dots{}) + @var{expression} + @var{expression} @dots{})) +@end group +@end example +@end deffn + +@menu +* Top-Level Definitions:: +* Internal Definitions:: +@end menu + +@node Top-Level Definitions, Internal Definitions, Definitions, Definitions +@subsection Top-Level Definitions +@cindex top-level definition +@cindex definition, top-level + +@cindex variable binding, top-level definition +A top-level definition, + +@example +(define @var{variable} @var{expression}) +@end example + +@noindent +has essentially the same effect as this assignment expression, if +@var{variable} is bound: + +@example +(set! @var{variable} @var{expression}) +@end example + +@cindex unassigned variable, and definition +@findex set! +If @var{variable} is not bound, however, @code{define} binds +@var{variable} to a new location in the current environment before +performing the assignment (it is an error to perform a @code{set!} on an +unbound variable). If you omit @var{expression}, the variable becomes +unassigned; an attempt to reference such a variable is an error. + +@example +@group +(define add3 + (lambda (x) (+ x 3))) @result{} @r{unspecified} +(add3 3) @result{} 6 + +(define first car) @result{} @r{unspecified} +(first '(1 2)) @result{} 1 + +(define bar) @result{} @r{unspecified} +bar @error{} Unassigned variable +@end group +@end example + +@node Internal Definitions, , Top-Level Definitions, Definitions +@subsection Internal Definitions + +@cindex internal definition +@cindex definition, internal +@cindex region of variable binding, internal definition +@cindex variable binding, internal definition +@findex lambda +@findex let +@findex let* +@findex letrec +@findex fluid-let +@findex define +An @dfn{internal definition} is a definition that occurs at the +beginning of a @var{body} (that is, the body of a @code{lambda}, +@code{let}, @code{let*}, @code{letrec}, @code{fluid-let}, or ``procedure +@code{define}'' expression), rather than at the top level of a program. +The variable defined by an internal definition is local to the +@var{body}. That is, @var{variable} is bound rather than assigned, and +the region of the binding is the entire @var{body}. For example, + +@example +@group +(let ((x 5)) + (define foo (lambda (y) (bar x y))) + (define bar (lambda (a b) (+ (* a b) a))) + (foo (+ x 3))) @result{} 45 +@end group +@end example + +@findex letrec +A @var{body} containing internal definitions can always be converted +into a completely equivalent @code{letrec} expression. For example, the +@code{let} expression in the above example is equivalent to + +@cindex letrec, implicit in define +@example +@group +(let ((x 5)) + (letrec ((foo (lambda (y) (bar x y))) + (bar (lambda (a b) (+ (* a b) a)))) + (foo (+ x 3)))) +@end group +@end example + +@need 1000 +@node Assignments, Quoting, Definitions, Special Forms +@section Assignments +@cindex assignment + +@deffn {special form} set! variable [expression] +@cindex variable, assigning values to +@cindex unassigned variable, and assignment +If @var{expression} is specified, evaluates @var{expression} and stores +the resulting value in the location to which @var{variable} is bound. +If @var{expression} is omitted, @var{variable} is altered to be +unassigned; a subsequent reference to such a @var{variable} is an error. +In either case, the value of the @code{set!} expression is unspecified. + +@var{Variable} must be bound either in some region enclosing the +@code{set!} expression, or at the top level. However, @var{variable} is +permitted to be unassigned when the @code{set!} form is entered. + +@example +@group +(define x 2) @result{} @r{unspecified} +(+ x 1) @result{} 3 +(set! x 4) @result{} @r{unspecified} +(+ x 1) @result{} 5 +@end group +@end example + +@cindex access, used with set! +@findex access +@var{Variable} may be an @code{access} expression +(@pxref{Environments}). This allows you to assign variables in an +arbitrary environment. For example, + +@example +@group +(define x (let ((y 0)) (the-environment))) +(define y 'a) +y @result{} a +(access y x) @result{} 0 +(set! (access y x) 1) @result{} @r{unspecified} +y @result{} a +(access y x) @result{} 1 +@end group +@end example +@end deffn + +@node Quoting, Conditionals, Assignments, Special Forms +@section Quoting +@cindex quoting + +This section describes the expressions that are used to modify or +prevent the evaluation of objects. + +@deffn {special form} quote datum +@cindex external representation, and quote +@cindex literal, and quote +@cindex constant, and quote +@code{(quote @var{datum})} evaluates to @var{datum}. @var{Datum} may be +any external representation of a Scheme object +(@pxref{External Representations}). +Use @code{quote} to include literal constants in +Scheme code. + +@example +@group +(quote a) @result{} a +(quote #(a b c)) @result{} #(a b c) +(quote (+ 1 2)) @result{} (+ 1 2) +@end group +@end example + +@cindex ' as external representation +@cindex apostrophe, as external representation +@cindex quote, as external representation +@findex ' +@code{(quote @var{datum})} may be abbreviated as @code{'@var{datum}}. +The two notations are equivalent in all respects. + +@example +@group +'a @result{} a +'#(a b c) @result{} #(a b c) +'(+ 1 2) @result{} (+ 1 2) +'(quote a) @result{} (quote a) +''a @result{} (quote a) +@end group +@end example + +Numeric constants, string constants, character constants, and boolean +constants evaluate to themselves, so they don't need to be quoted. + +@example +@group +'"abc" @result{} "abc" +"abc" @result{} "abc" +'145932 @result{} 145932 +145932 @result{} 145932 +'#t @result{} #t +#t @result{} #t +'#\a @result{} #\a +#\a @result{} #\a +@end group +@end example +@end deffn + +@deffn {special form} quasiquote template +@cindex external representation, and quasiquote +@cindex literal, and quasiquote +@cindex constant, and quasiquote +@findex equal? +``Backquote'' or ``quasiquote'' expressions are useful for constructing +a list or vector structure when most but not all of the desired +structure is known in advance. If no commas appear within the +@var{template}, the result of evaluating @code{`@var{template}} is +equivalent (in the sense of @code{equal?}) to the result of evaluating +@code{'@var{template}}. If a comma appears within the @var{template}, +however, the expression following the comma is evaluated (``unquoted'') +and its result is inserted into the structure instead of the comma and +the expression. If a comma appears followed immediately by an at-sign +(@@), then the following expression shall evaluate to a list; the +opening and closing parentheses of the list are then ``stripped away'' +and the elements of the list are inserted in place of the comma at-sign +expression sequence. + +@example +@group +`(list ,(+ 1 2) 4) @result{} (list 3 4) + +(let ((name 'a)) `(list ,name ',name)) @result{} (list a 'a) + +`(a ,(+ 1 2) ,@@(map abs '(4 -5 6)) b) @result{} (a 3 4 5 6 b) + +`((foo ,(- 10 3)) ,@@(cdr '(c)) . ,(car '(cons))) + @result{} ((foo 7) . cons) + +`#(10 5 ,(sqrt 4) ,@@(map sqrt '(16 9)) 8) + @result{} #(10 5 2 4 3 8) + +`,(+ 2 3) @result{} 5 +@end group +@end example + +@cindex nesting, of quasiquote expressions +Quasiquote forms may be nested. Substitutions are made only for +unquoted components appearing at the same nesting level as the outermost +backquote. The nesting level increases by one inside each successive +quasiquotation, and decreases by one inside each unquotation. + +@example +@group +`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f) + @result{} (a `(b ,(+ 1 2) ,(foo 4 d) e) f) + +(let ((name1 'x) + (name2 'y)) + `(a `(b ,,name1 ,',name2 d) e)) + @result{} (a `(b ,x ,'y d) e) +@end group +@end example + +@cindex backquote, as external representation +@cindex ` as external representation +@cindex comma, as external representation +@cindex , as external representation +@cindex ,@@ as external representation +@findex unquote +@findex unquote-splicing +@findex ` +@findex , +@findex ,@@ +The notations @code{`@var{template}} and (@code{quasiquote +@var{template}}) are identical in all respects. +@code{,@var{expression}} is identical to @code{(unquote +@var{expression})} and @code{,@@@var{expression}} is identical to +@code{(unquote-splicing @var{expression})}. + +@example +@group +(quasiquote (list (unquote (+ 1 2)) 4)) + @result{} (list 3 4) + +'(quasiquote (list (unquote (+ 1 2)) 4)) + @result{} `(list ,(+ 1 2) 4) + @emph{i.e.,} (quasiquote (list (unquote (+ 1 2)) 4)) +@end group +@end example + +Unpredictable behavior can result if any of the symbols +@code{quasiquote}, @code{unquote}, or @code{unquote-splicing} appear in +a @var{template} in ways otherwise than as described above. +@end deffn + +@node Conditionals, Sequencing, Quoting, Special Forms +@section Conditionals + +@cindex expression, conditional (defn) +@cindex conditional expression (defn) +@cindex true, in conditional expression (defn) +@cindex false, in conditional expression (defn) +@findex #f +@findex #t +The behavior of the @dfn{conditional expressions} is determined by +whether objects are true or false. The conditional expressions count +only @code{#f} as false. They count everything else, including +@code{#t}, pairs, symbols, numbers, strings, vectors, and procedures as +true (but @pxref{True and False}). + +In the descriptions that follow, we say that an object has ``a true +value'' or ``is true'' when the conditional expressions treat it as +true, and we say that an object has ``a false value'' or ``is false'' +when the conditional expressions treat it as false. + +@deffn {special form} if predicate consequent [alternative] +@var{Predicate}, @var{consequent}, and @var{alternative} are +expressions. An @code{if} expression is evaluated as follows: first, +@var{predicate} is evaluated. If it yields a true value, then +@var{consequent} is evaluated and its value is returned. Otherwise +@var{alternative} is evaluated and its value is returned. If +@var{predicate} yields a false value and no @var{alternative} is +specified, then the result of the expression is unspecified. + +An @code{if} expression evaluates either @var{consequent} or +@var{alternative}, never both. Programs should not depend on the value +of an @code{if} expression that has no @var{alternative}. + +@example +@group +(if (> 3 2) 'yes 'no) @result{} yes +(if (> 2 3) 'yes 'no) @result{} no +(if (> 3 2) + (- 3 2) + (+ 3 2)) @result{} 1 +@end group +@end example +@end deffn + +@deffn {special form} cond clause clause @dots{} +@cindex cond clause +@cindex clause, of cond expression +Each @var{clause} has this form: + +@example +(@var{predicate} @var{expression} @dots{}) +@end example + +@noindent +@cindex else clause, of cond expression (defn) +@findex else +where @var{predicate} is any expression. The last @var{clause} may be +an @dfn{@code{else} clause}, which has the form: + +@example +(else @var{expression} @var{expression} @dots{}) +@end example + +A @code{cond} expression does the following: + +@enumerate +@item +Evaluates the @var{predicate} expressions of successive @var{clause}s in +order, until one of the @var{predicate}s evaluates to a true +value. + +@item +When a @var{predicate} evaluates to a true value, @code{cond} evaluates +the @var{expression}s in the associated @var{clause} in left to right +order, and returns the result of evaluating the last @var{expression} in +the @var{clause} as the result of the entire @code{cond} expression. + +If the selected @var{clause} contains only the @var{predicate} and no +@var{expression}s, @code{cond} returns the value of the @var{predicate} +as the result. + +@item +If all @var{predicate}s evaluate to false values, and there is no +@code{else} clause, the result of the conditional expression is +unspecified; if there is an @code{else} clause, @code{cond} evaluates +its @var{expression}s (left to right) and returns the value of the last +one. +@end enumerate + +@example +@group +(cond ((> 3 2) 'greater) + ((< 3 2) 'less)) @result{} greater + +(cond ((> 3 3) 'greater) + ((< 3 3) 'less) + (else 'equal)) @result{} equal +@end group +@end example + +Normally, programs should not depend on the value of a @code{cond} +expression that has no @code{else} clause. However, some Scheme +programmers prefer to write @code{cond} expressions in which at least +one of the @var{predicate}s is always true. In this style, the final +@var{clause} is equivalent to an @code{else} clause. + +@cindex => in cond clause +@findex => +Scheme supports an alternative @var{clause} syntax: + +@example +(@var{predicate} => @var{recipient}) +@end example + +@noindent +where @var{recipient} is an expression. If @var{predicate} evaluates to +a true value, then @var{recipient} is evaluated. Its value must be a +procedure of one argument; this procedure is then invoked on the value +of the @var{predicate}. + +@example +@group +(cond ((assv 'b '((a 1) (b 2))) => cadr) + (else #f)) @result{} 2 +@end group +@end example +@end deffn + +@deffn {special form} case key clause clause @dots{} +@cindex case clause +@cindex clause, of case expression +@var{Key} may be any expression. Each @var{clause} has this +form: + +@example +((@var{object} @dots{}) @var{expression} @var{expression} @dots{}) +@end example + +@cindex else clause, of case expression (defn) +@findex else +No @var{object} is evaluated, and all the @var{object}s must be +distinct. The last @var{clause} may be an @dfn{@code{else} clause}, +which has the form: + +@example +(else @var{expression} @var{expression} @dots{}) +@end example + +A @code{case} expression does the following: + +@enumerate +@item +Evaluates @var{key} and compares the result with each +@var{object}. + +@item +If the result of evaluating @var{key} is equivalent (in the sense of +@code{eqv?}; @pxref{Equivalence Predicates}) to an @var{object}, +@code{case} evaluates the @var{expression}s in the corresponding +@var{clause} from left to right and returns the result of evaluating the +last @var{expression} in the @var{clause} as the result of the +@code{case} expression. +@findex eqv? + +@item +If the result of evaluating @var{key} is different from every +@var{object}, and if there's an @code{else} clause, @code{case} +evaluates its @var{expression}s and returns the result of the last one +as the result of the @code{case} expression. If there's no @code{else} +clause, @code{case} returns an unspecified result. Programs should not +depend on the value of a @code{case} expression that has no @code{else} +clause. +@end enumerate + +For example, + +@example +@group +(case (* 2 3) + ((2 3 5 7) 'prime) + ((1 4 6 8 9) 'composite)) @result{} composite + +(case (car '(c d)) + ((a) 'a) + ((b) 'b)) @result{} @r{unspecified} + +(case (car '(c d)) + ((a e i o u) 'vowel) + ((w y) 'semivowel) + (else 'consonant)) @result{} consonant +@end group +@end example +@end deffn + +@deffn {special form} and expression @dots{} +The @var{expression}s are evaluated from left to right, and the value of +the first @var{expression} that evaluates to a false value is returned. +Any remaining @var{expression}s are not evaluated. If all the +@var{expression}s evaluate to true values, the value of the last +@var{expression} is returned. If there are no @var{expression}s then +@code{#t} is returned. + +@example +@group +(and (= 2 2) (> 2 1)) @result{} #t +(and (= 2 2) (< 2 1)) @result{} #f +(and 1 2 'c '(f g)) @result{} (f g) +(and) @result{} #t +@end group +@end example +@end deffn + +@deffn {special form} or expression @dots{} +The @var{expression}s are evaluated from left to right, and the value of +the first @var{expression} that evaluates to a true value is returned. +Any remaining @var{expression}s are not evaluated. If all +@var{expression}s evaluate to false values, the value of the last +@var{expression} is returned. If there are no @var{expression}s then +@code{#f} is returned. + +@example +@group +(or (= 2 2) (> 2 1)) @result{} #t +(or (= 2 2) (< 2 1)) @result{} #t +(or #f #f #f) @result{} #f +(or (memq 'b '(a b c)) (/ 3 0)) @result{} (b c) +@end group +@end example +@end deffn + +@node Sequencing, Iteration, Conditionals, Special Forms +@section Sequencing +@cindex sequencing expressions + +The @code{begin} special form is used to evaluate expressions in a +particular order. + +@deffn {special form} begin expression expression @dots{} +The @var{expression}s are evaluated sequentially from left to right, and +the value of the last @var{expression} is returned. This expression +type is used to sequence side effects such as input and output. + +@example +@group +(define x 0) +(begin (set! x 5) + (+ x 1)) @result{} 6 + +(begin (display "4 plus 1 equals ") + (display (+ 4 1))) + @print{} 4 plus 1 equals 5 + @result{} @r{unspecified} +@end group +@end example + +@cindex implicit begin +Often the use of @code{begin} is unnecessary, because many special forms +already support sequences of expressions (that is, they have an implicit +@code{begin}). Some of these special forms are: + +@example +@group +case +cond +define @r{;``procedure @code{define}'' only} +do +fluid-let +lambda +let +let* +letrec +named-lambda +@end group +@end example +@findex case +@findex cond +@findex define +@findex do +@findex fluid-let +@findex lambda +@findex let +@findex let* +@findex letrec +@findex named-lambda + +@findex sequence +The obsolete special form @code{sequence} is identical to @code{begin}. +It should not be used in new code. +@end deffn + +@node Iteration, Structure Definitions, Sequencing, Special Forms +@section Iteration + +@cindex expression, iteration (defn) +@cindex iteration expression (defn) +@cindex looping (see iteration expressions) +@cindex tail recursion, vs. iteration expression +The @dfn{iteration expressions} are: ``named @code{let}'' and @code{do}. +They are also binding expressions, but are more commonly referred to as +iteration expressions. Because Scheme is properly tail-recursive, you +don't need to use these special forms to express iteration; you can +simply use appropriately written ``recursive'' procedure calls. + +@deffn {special form} let name ((@var{variable} @var{init}) @dots{}) expression expression @dots{} +@cindex named let (defn) +MIT/GNU Scheme permits a variant on the syntax of @code{let} called +``named @code{let}'' which provides a more general looping construct +than @code{do}, and may also be used to express recursions. + +Named @code{let} has the same syntax and semantics as ordinary +@code{let} except that @var{name} is bound within the @var{expression}s +to a procedure whose formal arguments are the @var{variable}s and whose +body is the @var{expression}s. Thus the execution of the +@var{expression}s may be repeated by invoking the procedure named by +@var{name}. + +@cindex unassigned variable, and named let +MIT/GNU Scheme allows any of the @var{init}s to be omitted, in which +case the corresponding @var{variable}s are unassigned. + +Note: the following expressions are equivalent: + +@example +@group +(let @var{name} ((@var{variable} @var{init}) @dots{}) + @var{expression} + @var{expression} @dots{}) + +((letrec ((@var{name} + (named-lambda (@var{name} @var{variable} @dots{}) + @var{expression} + @var{expression} @dots{}))) + @var{name}) + @var{init} @dots{}) +@end group +@end example + +Here is an example: + +@example +@group +(let loop + ((numbers '(3 -2 1 6 -5)) + (nonneg '()) + (neg '())) + (cond ((null? numbers) + (list nonneg neg)) + ((>= (car numbers) 0) + (loop (cdr numbers) + (cons (car numbers) nonneg) + neg)) + (else + (loop (cdr numbers) + nonneg + (cons (car numbers) neg))))) + + @result{} ((6 1 3) (-5 -2)) +@end group +@end example +@end deffn + +@deffn {special form} do ((@var{variable} @var{init} @var{step}) @dots{}) (@var{test} @var{expression} @dots{}) command @dots{} +@code{do} is an iteration construct. It specifies a set of variables to +be bound, how they are to be initialized at the start, and how they are +to be updated on each iteration. When a termination condition is met, +the loop exits with a specified result value. + +@code{do} expressions are evaluated as follows: The @var{init} +expressions are evaluated (in some unspecified order), the +@var{variable}s are bound to fresh locations, the results of the +@var{init} expressions are stored in the bindings of the +@var{variable}s, and then the iteration phase begins. + +Each iteration begins by evaluating @var{test}; if the result is false, +then the @var{command} expressions are evaluated in order for effect, +the @var{step} expressions are evaluated in some unspecified order, the +@var{variable}s are bound to fresh locations, the results of the +@var{step}s are stored in the bindings of the @var{variable}s, and the +next iteration begins. + +If @var{test} evaluates to a true value, then the @var{expression}s are +evaluated from left to right and the value of the last @var{expression} +is returned as the value of the @code{do} expression. If no +@var{expression}s are present, then the value of the @code{do} +expression is unspecified in standard Scheme; in MIT/GNU Scheme, the +value of @var{test} is returned. + +@cindex region of variable binding, do +@cindex variable binding, do +The region of the binding of a @var{variable} consists of the entire +@code{do} expression except for the @var{init}s. It is an error for a +@var{variable} to appear more than once in the list of @code{do} +variables. + +A @var{step} may be omitted, in which case the effect is the same as if +@code{(@var{variable} @var{init} @var{variable})} had been written +instead of @code{(@var{variable} @var{init})}. + +@example +@group +(do ((vec (make-vector 5)) + (i 0 (+ i 1))) + ((= i 5) vec) + (vector-set! vec i i)) @result{} #(0 1 2 3 4) +@end group + +@group +(let ((x '(1 3 5 7 9))) + (do ((x x (cdr x)) + (sum 0 (+ sum (car x)))) + ((null? x) sum))) @result{} 25 +@end group +@end example +@end deffn + +@node Structure Definitions, Macros, Iteration, Special Forms +@section Structure Definitions + +This section provides examples and describes the options and syntax of +@code{define-structure}, an MIT/GNU Scheme macro that is very similar to +@code{defstruct} in Common Lisp. The differences between them are +summarized at the end of this section. For more information, see +Steele's Common Lisp book. + +@deffn {special form} define-structure (name structure-option @dots{}) slot-description @dots{} +Each @var{slot-description} takes one of the following forms: + +@example +@group +@var{slot-name} +(@var{slot-name} @var{default-init} [@var{slot-option} @var{value}]*) +@end group +@end example + +@cindex keyword constructor +@cindex BOA constructor +The fields @var{name} and @var{slot-name} must both be symbols. The +field @var{default-init} is an expression for the initial value of the +slot. It is evaluated each time a new instance is constructed. If it +is not specified, the initial content of the slot is undefined. Default +values are only useful with a @sc{boa} constructor with argument list or +a keyword constructor (see below). + +Evaluation of a @code{define-structure} expression defines a structure +descriptor and a set of procedures to manipulate instances of the +structure. These instances are represented as records by default +(@pxref{Records}) but may alternately be lists or vectors. The +accessors and modifiers are marked with compiler declarations so that +calls to them are automatically transformed into appropriate references. +Often, no options are required, so a simple call to +@code{define-structure} looks like: + +@example +(define-structure foo a b c) +@end example + +This defines a type descriptor @code{foo}, a constructor +@code{make-foo}, a predicate @code{foo?}, accessors @code{foo-a}, +@code{foo-b}, and @code{foo-c}, and modifiers @code{set-foo-a!}, +@code{set-foo-b!}, and @code{set-foo-c!}. + +In general, if no options are specified, @code{define-structure} defines +the following (using the simple call above as an example): + +@table @asis +@item type descriptor +The name of the type descriptor is the same as the name of the +structure, e.g.@: @samp{foo}. The type descriptor satisfies the +predicate @code{record-type?}. + +@item constructor +The name of the constructor is @code{"make-"} followed by the name of +the structure, e.g.@: @samp{make-foo}. The number of arguments accepted +by the constructor is the same as the number of slots; the arguments are +the initial values for the slots, and the order of the arguments matches +the order of the slot definitions. + +@item predicate +The name of the predicate is the name of the structure followed by +@code{"?"}, e.g.@: @samp{foo?}. The predicate is a procedure of one +argument, which returns @code{#t} if its argument is a record of the +type defined by this structure definition, and @code{#f} otherwise. + +@item accessors +For each slot, an accessor is defined. The name of the accessor is +formed by appending the name of the structure, a hyphen, and the name of +the slot, e.g.@: @samp{foo-a}. The accessor is a procedure of one +argument, which must be a record of the type defined by this structure +definition. The accessor extracts the contents of the corresponding +slot in that record and returns it. + +@item modifiers +For each slot, a modifier is defined. The name of the modifier is +formed by appending @code{"set-"}, the name of the accessor, and +@code{"!"}, e.g.@: @samp{set-foo-a!}. The modifier is a procedure of +two arguments, the first of which must be a record of the type defined +by this structure definition, and the second of which may be any object. +The modifier modifies the contents of the corresponding slot in that +record to be that object, and returns an unspecified value. +@end table + +When options are not supplied, @code{(@var{name})} may be abbreviated to +@var{name}. This convention holds equally for @var{structure-options} +and @var{slot-options}. Hence, these are equivalent: + +@example +@group +(define-structure foo a b c) +(define-structure (foo) (a) b (c)) +@end group +@end example + +@noindent +as are + +@example +@group +(define-structure (foo keyword-constructor) a b c) +(define-structure (foo (keyword-constructor)) a b c) +@end group +@end example + +When specified as option values, @code{false} and @code{nil} are +equivalent to @code{#f}, and @code{true} and @code{t} are equivalent to +@code{#t}. +@end deffn + +Possible @var{slot-options} are: + +@deffn {slot option} read-only value +When given a @var{value} other than @code{#f}, this specifies that no +modifier should be created for the slot. +@end deffn + +@deffn {slot option} type type-descriptor +This is accepted but not presently used. +@end deffn + +Possible @var{structure-options} are: + +@deffn {structure option} predicate [name] +This option controls the definition of a predicate procedure for the +structure. If @var{name} is not given, the predicate is defined with +the default name (see above). If @var{name} is @code{#f}, the predicate +is not defined at all. Otherwise, @var{name} must be a symbol, and +the predicate is defined with that symbol as its name. +@end deffn + +@deffn {structure option} copier [name] +This option controls the definition of a procedure to copy instances of +the structure. This is a procedure of one argument, a structure +instance, that makes a newly allocated copy of the structure and returns +it. If @var{name} is not given, the copier is defined, and the name +of the copier is @code{"copy-"} followed by the structure name (e.g.@: +@samp{copy-foo}). If @var{name} is @code{#f}, the copier is not +defined. Otherwise, @var{name} must be a symbol, and the copier is +defined with that symbol as its name. +@end deffn + +@deffn {structure option} print-procedure expression +Evaluating @var{expression} must yield a procedure of two arguments, +which is used to print instances of the structure. The procedure is an +@dfn{unparser method} (@pxref{Custom Output}). If the structure +instances are records, this option has the same effect as calling +@code{set-record-type-unparser-method!}. +@findex set-record-type-unparser-method! +@end deffn + +@deffn {structure option} constructor [name [argument-list]] +@cindex BOA constructor (defn) +This option controls the definition of constructor procedures. These +constructor procedures are called ``@sc{boa} constructors'', for ``By +Order of Arguments'', because the arguments to the constructor specify +the initial contents the structure's slots by the order in which they +are given. This is as opposed to ``keyword constructors'', which +specify the initial contents using keywords, and in which the order of +arguments is irrelevant. + +If @var{name} is not given, a constructor is defined with the default +name and arguments (see above). If @var{name} is @code{#f}, no +constructor is defined; @var{argument-list} may not be specified in this +case. Otherwise, @var{name} must be a symbol, and a constructor is +defined with that symbol as its name. If @var{name} is a symbol, +@var{argument-list} is optionally allowed; if it is omitted, the +constructor accepts one argument for each slot in the structure +definition, in the same order in which the slots appear in the +definition. Otherwise, @var{argument-list} must be a lambda list +(@pxref{Lambda Expressions}), and each of the parameters of the lambda +list must be the name of a slot in the structure. The arguments +accepted by the constructor are defined by this lambda list. Any slot +that is not specified by the lambda list is initialized to the +@var{default-init} as specified above; likewise for any slot specified +as an optional parameter when the corresponding argument is not +supplied. + +If the @code{constructor} option is specified, the default constructor +is not defined. Additionally, the @code{constructor} option may be +specified multiple times to define multiple constructors with +different names and argument lists. + +@example +@group +(define-structure (foo + (constructor make-foo (#!optional a b))) + (a 6 read-only #t) + (b 9)) +@end group +@end example +@end deffn + +@deffn {structure option} keyword-constructor [name] +@cindex keyword constructor (defn) +This option controls the definition of keyword constructor procedures. +A @dfn{keyword constructor} is a procedure that accepts arguments that +are alternating slot names and values. If @var{name} is omitted, a +keyword constructor is defined, and the name of the constructor is +@code{"make-"} followed by the name of the structure (e.g.@: +@samp{make-foo}). Otherwise, @var{name} must be a symbol, and a keyword +constructor is defined with this symbol as its name. + +If the @code{keyword-constructor} option is specified, the default +constructor is not defined. Additionally, the +@code{keyword-constructor} option may be specified multiple times to +define multiple keyword constructors; this is usually not done since +such constructors would all be equivalent. + +@example +@group +(define-structure (foo (keyword-constructor make-bar)) a b) +(foo-a (make-bar 'b 20 'a 19)) @result{} 19 +@end group +@end example +@end deffn + +@deffn {structure option} type-descriptor name +This option cannot be used with the @code{type} or @code{named} options. + +By default, structures are implemented as records. The name of the +structure is defined to hold the type descriptor of the record defined +by the structure. The @code{type-descriptor} option specifies a +different name to hold the type descriptor. + +@example +@group +(define-structure foo a b) +foo @result{} #[record-type 18] + +(define-structure (bar (type-descriptor )) a b) +bar @error{} Unbound variable: bar + @result{} #[record-type 19] +@end group +@end example +@end deffn + +@deffn {structure option} conc-name [name] +By default, the prefix for naming accessors and modifiers is the name of +the structure followed by a hyphen. The @code{conc-name} option can be +used to specify an alternative. If @var{name} is not given, the prefix +is the name of the structure followed by a hyphen (the default). If +@var{name} is @code{#f}, the slot names are used directly, without +prefix. Otherwise, @var{name} must a symbol, and that symbol is used as +the prefix. + +@example +@code{(define-structure (foo (conc-name moby/)) a b)} +@end example + +@noindent +defines accessors @code{moby/a} and @code{moby/b}, and modifiers +@code{set-moby/a!} and @code{set-moby/b!}. + +@example +@code{(define-structure (foo (conc-name #f)) a b)} +@end example + +@noindent +defines accessors @code{a} and @code{b}, and modifiers @code{set-a!} and +@code{set-b!}. +@end deffn + +@deffn {structure option} type representation-type +This option cannot be used with the @code{type-descriptor} option. + +By default, structures are implemented as records. The @code{type} +option overrides this default, allowing the programmer to specify that +the structure be implemented using another data type. The option value +@var{representation-type} specifies the alternate data type; it is +allowed to be one of the symbols @code{vector} or @code{list}, and the +data type used is the one corresponding to the symbol. + +If this option is given, and the @code{named} option is not specified, +the representation will not be tagged, and neither a predicate nor a +type descriptor will be defined; also, the @code{print-procedure} +option may not be given. + +@example +@group +(define-structure (foo (type list)) a b) +(make-foo 1 2) @result{} (1 2) +@end group +@end example +@end deffn + +@deffn {structure option} named [expression] +This is valid only in conjunction with the @code{type} option and +specifies that the structure instances be tagged to make them +identifiable as instances of this structure type. This option cannot be +used with the @code{type-descriptor} option. + +In the usual case, where @var{expression} is not given, the @code{named} +option causes a type descriptor and predicate to be defined for the +structure (recall that the @code{type} option without @code{named} +suppresses their definition), and also defines a default unparser method +for the structure instances (which can be overridden by the +@code{print-procedure} option). If the default unparser method is not +wanted then the @code{print-procedure} option should be specified as +@code{#F}. This causes the structure to be printed in its native +representation, as a list or vector, which includes the type descriptor. +The type descriptor is a unique object, @emph{not} a record type, that +describes the structure instances and is additionally stored in the +structure instances to identify them: if the representation type is +@code{vector}, the type descriptor is stored in the zero-th slot of the +vector, and if the representation type is @code{list}, it is stored as +the first element of the list. + + +@example +@group +(define-structure (foo (type vector) named) a b c) +(vector-ref (make-foo 1 2 3) 0) @result{} #[structure-type 52] +@end group +@end example + +If @var{expression} is specified, it is an expression that is evaluated +to yield a tag object. The @var{expression} is evaluated once when the +structure definition is evaluated (to specify the unparser method), and +again whenever a predicate or constructor is called. Because of this, +@var{expression} is normally a variable reference or a constant. The +value yielded by @var{expression} may be any object at all. That object +is stored in the structure instances in the same place that the type +descriptor is normally stored, as described above. If @var{expression} +is specified, no type descriptor is defined, only a predicate. + +@example +@group +(define-structure (foo (type vector) (named 'foo)) a b c) +(vector-ref (make-foo 1 2 3) 0) @result{} foo +@end group +@end example +@end deffn + +@deffn {structure option} safe-accessors [boolean] +This option allows the programmer to have some control over the safety +of the slot accessors (and modifiers) generated by +@code{define-structure}. If @code{safe-accessors} is not specified, or +if @var{boolean} is @code{#f}, then the accessors are optimized for +speed at the expense of safety; when compiled, the accessors will turn +into very fast inline sequences, usually one to three machine +instructions in length. However, if @code{safe-accessors} is specified +and @var{boolean} is either omitted or @code{#t}, then the accessors are +optimized for safety, will check the type and structure of their +argument, and will be close-coded. + +@example +@group +(define-structure (foo safe-accessors) a b c) +@end group +@end example +@end deffn + +@deffn {structure option} initial-offset offset +This is valid only in conjunction with the @code{type} option. +@var{Offset} must be an exact non-negative integer and specifies the +number of slots to leave open at the beginning of the structure instance +before the specified slots are allocated. Specifying an @var{offset} of +zero is equivalent to omitting the @code{initial-offset} option. + +If the @code{named} option is specified, the structure tag appears in +the first slot, followed by the ``offset'' slots, and then the regular +slots. Otherwise, the ``offset'' slots come first, followed by the +regular slots. + +@example +@group +(define-structure (foo (type vector) (initial-offset 3)) + a b c) +(make-foo 1 2 3) @result{} #(() () () 1 2 3) +@end group +@end example +@end deffn + +The essential differences between MIT/GNU Scheme's @code{define-structure} +and Common Lisp's @code{defstruct} are: + +@itemize @bullet +@item +The default constructor procedure takes positional arguments, in the +same order as specified in the definition of the structure. A keyword +constructor may be specified by giving the option +@code{keyword-constructor}. + +@item +@sc{boa} constructors are described using Scheme lambda lists. Since there +is nothing corresponding to @code{&aux} in Scheme lambda lists, this +functionality is not implemented. + +@item +By default, no @code{copier} procedure is defined. + +@item +The side-effect procedure corresponding to the accessor @code{foo} is +given the name @code{set-foo!}. + +@item +Keywords are ordinary symbols -- use @code{foo} instead of @code{:foo}. + +@item +The option values @code{false}, @code{nil}, @code{true}, and @code{t} +are treated as if the appropriate boolean constant had been specified +instead. + +@item +The @code{print-function} option is named @code{print-procedure}. Its +argument is a procedure of two arguments (the unparser state and the +structure instance) rather than three as in Common Lisp. + +@item +By default, named structures are tagged with a unique object of some +kind. In Common Lisp, the structures are tagged with symbols. This +depends on the Common Lisp package system to help generate unique tags; +MIT/GNU Scheme has no such way to generate unique symbols. + +@item +The @code{named} option may optionally take an argument, which is +normally the name of a variable (any expression may be used, but it is +evaluated whenever the tag name is needed). If used, structure +instances will be tagged with that variable's value. The variable must +be defined when @code{define-structure} is evaluated. + +@item +The @code{type} option is restricted to the values @code{vector} and +@code{list}. + +@item +The @code{include} option is not implemented. +@end itemize + +@node Macros, SRFI syntax, Structure Definitions, Special Forms +@section Macros + +(This section is largely taken from the @cite{Revised^4 Report on the +Algorithmic Language Scheme}. The section on Syntactic Closures is +derived from a document written by Chris Hanson. The section on +Explicit Renaming is derived from a document written by William +Clinger.) + +@cindex macro +Scheme programs can define and use new derived expression types, called +@dfn{macros}. Program-defined expression types have the syntax + +@example +(@var{keyword} @var{datum} @dots{}) +@end example + +@noindent +@cindex syntactic keyword +@cindex keyword +@cindex macro keyword +where @var{keyword} is an identifier that uniquely determines the +expression type. This identifier is called the @dfn{syntactic keyword}, +or simply @dfn{keyword}, of the macro. The number of the @var{datum}s, +and their syntax, depends on the expression type. + +@cindex macro use +@cindex macro transformer +Each instance of a macro is called a @dfn{use} of the macro. The set of +rules that specifies how a use of a macro is transcribed into a more +primitive expression is called the @dfn{transformer} of the macro. + +@cindex anonymous syntactic keyword +MIT/GNU Scheme also supports @dfn{anonymous syntactic keywords}. This means +that it's not necessary to bind a macro transformer to a syntactic +keyword before it is used. Instead, any macro-transformer expression +can appear as the first element of a form, and the form will be expanded +by the transformer. + +The macro definition facility consists of these parts: + +@itemize @bullet +@item +A set of expressions used to establish that certain identifiers are +macro keywords, associate them with macro transformers, and control the +scope within which a macro is defined. + +@item +A standard high-level pattern language for specifying macro +transformers, introduced by the @code{syntax-rules} special form. + +@item +Two non-standard low-level languages for specifying macro transformers, +@dfn{syntactic closures} and @dfn{explicit renaming}. +@end itemize + +@cindex hygienic +@cindex referentially transparent +The syntactic keyword of a macro may shadow variable bindings, and local +variable bindings may shadow keyword bindings. All macros defined using +the pattern language are ``hygienic'' and ``referentially transparent'' +and thus preserve Scheme's lexical scoping: + +@itemize @bullet +@item +If a macro transformer inserts a binding for an identifier (variable or +keyword), the identifier will in effect be renamed throughout its scope +to avoid conflicts with other identifiers. + +@item +If a macro transformer inserts a free reference to an identifier, the +reference refers to the binding that was visible where the transformer +was specified, regardless of any local bindings that may surround the +use of the macro. +@end itemize + +@menu +* Syntactic Binding Constructs:: +* Pattern Language:: +* Syntactic Closures:: +* Explicit Renaming:: +@end menu + +@node Syntactic Binding Constructs, Pattern Language, Macros, Macros +@subsection Binding Constructs for Syntactic Keywords + +@code{let-syntax}, @code{letrec-syntax}, @code{let*-syntax} and +@code{define-syntax} are analogous to @code{let}, @code{letrec}, +@code{let*} and @code{define}, but they bind syntactic keywords to macro +transformers instead of binding variables to locations that contain +values. + +@deffn {special form} let-syntax bindings expression expression @dots{} +@var{Bindings} should have the form + +@example +((@var{keyword} @var{transformer-spec}) @dots{}) +@end example + +@noindent +Each @var{keyword} is an identifier, each @var{transformer-spec} is a +a macro-transformer expression, and the body is a sequence of +one or more expressions. It is an error for a @var{keyword} to appear +more than once in the list of keywords being bound. + +The @var{expression}s are expanded in the syntactic environment obtained +by extending the syntactic environment of the @code{let-syntax} +expression with macros whose keywords are the @var{keyword}s, bound to +the specified transformers. Each binding of a @var{keyword} has the +@var{expression}s as its region. + +@example +@group +(let-syntax ((when (syntax-rules () + ((when test stmt1 stmt2 ...) + (if test + (begin stmt1 + stmt2 ...)))))) + (let ((if #t)) + (when if (set! if 'now)) + if)) @result{} now + +(let ((x 'outer)) + (let-syntax ((m (syntax-rules () ((m) x)))) + (let ((x 'inner)) + (m)))) @result{} outer +@end group +@end example +@end deffn + +@deffn {special form} letrec-syntax bindings expression expression @dots{} +The syntax of @code{letrec-syntax} is the same as for @code{let-syntax}. + +The @var{expression}s are expanded in the syntactic environment obtained +by extending the syntactic environment of the @code{letrec-syntax} +expression with macros whose keywords are the @var{keyword}s, bound to +the specified transformers. Each binding of a @var{keyword} has the +@var{bindings} as well as the @var{expression}s within its region, so +the transformers can transcribe expressions into uses of the macros +introduced by the @code{letrec-syntax} expression. + +@example +@group +(letrec-syntax + ((my-or (syntax-rules () + ((my-or) #f) + ((my-or e) e) + ((my-or e1 e2 ...) + (let ((temp e1)) + (if temp + temp + (my-or e2 ...))))))) + (let ((x #f) + (y 7) + (temp 8) + (let odd?) + (if even?)) + (my-or x + (let temp) + (if y) + y))) @result{} 7 +@end group +@end example +@end deffn + +@deffn {special form} let*-syntax bindings expression expression @dots{} +The syntax of @code{let*-syntax} is the same as for @code{let-syntax}. + +The @var{expression}s are expanded in the syntactic environment obtained +by extending the syntactic environment of the @code{letrec-syntax} +expression with macros whose keywords are the @var{keyword}s, bound to +the specified transformers. Each binding of a @var{keyword} has the +subsequent @var{bindings} as well as the @var{expression}s within its +region. Thus + +@example +@group +(let*-syntax + ((a (syntax-rules @dots{})) + (b (syntax-rules @dots{}))) + @dots{}) +@end group +@end example + +@noindent +is equivalent to + +@example +@group +(let-syntax ((a (syntax-rules @dots{}))) + (let-syntax ((b (syntax-rules @dots{}))) + @dots{})) +@end group +@end example +@end deffn + +@deffn {special form} define-syntax keyword transformer-spec +@var{Keyword} is an identifier, and @var{transformer-spec} is a macro +transformer expression. The syntactic environment is extended by +binding the @var{keyword} to the specified transformer. + +The region of the binding introduced by @code{define-syntax} is the +entire block in which it appears. However, the @var{keyword} may only +be used after it has been defined. + +MIT/GNU Scheme permits @code{define-syntax} to appear both at top level and +within @code{lambda} bodies. The Revised^4 Report permits only +top-level uses of @code{define-syntax}. + +When compiling a program, a top-level instance of @code{define-syntax} +both defines the syntactic keyword and generates code that will redefine +the keyword when the program is loaded. This means that the same syntax +can be used for defining macros that will be used during compilation +and for defining macros to be used at run time. + +Although macros may expand into definitions and syntax definitions in +any context that permits them, it is an error for a definition or syntax +definition to shadow a syntactic keyword whose meaning is needed to +determine whether some form in the group of forms that contains the +shadowing definition is in fact a definition, or, for internal definitions, +is needed to determine the boundary between the group and the expressions +that follow the group. For example, the following are errors: + +@example +(define define 3) + +(begin (define begin list)) + +(let-syntax + ((foo (syntax-rules () + ((foo (proc args ...) body ...) + (define proc + (lambda (args ...) + body ...)))))) + (let ((x 3)) + (foo (plus x y) (+ x y)) + (define foo x) + (plus foo x))) +@end example +@end deffn + +@node Pattern Language, Syntactic Closures, Syntactic Binding Constructs, Macros +@subsection Pattern Language + +MIT/GNU Scheme supports a high-level pattern language for specifying macro +transformers. This pattern language is defined by the Revised^4 Report +and is portable to other conforming Scheme implementations. To use the +pattern language, specify a @var{transformer-spec} as a +@code{syntax-rules} form: + +@deffn {special form} syntax-rules literals syntax-rule @dots{} +@var{Literals} is a list of identifiers and each @var{syntax-rule} +should be of the form + +@example +(@var{pattern} @var{template}) +@end example + +The @var{pattern} in a @var{syntax-rule} is a list @var{pattern} that +begins with the keyword for the macro. + +A @var{pattern} is either an identifier, a constant, or one of the +following + +@example +(@var{pattern} @dots{}) +(@var{pattern} @var{pattern} @dots{} . @var{pattern}) +(@var{pattern} @dots{} @var{pattern} @var{ellipsis}) +@end example + +@noindent +and a template is either an identifier, a constant, or one of the +following + +@example +(@var{element} @dots{}) +(@var{element} @var{element} @dots{} . @var{template}) +@end example + +@vindex ... +where an @var{element} is a @var{template} optionally followed by an +@var{ellipsis} and an @var{ellipsis} is the identifier @samp{...} (which +cannot be used as an identifier in either a template or a pattern). + +An instance of @code{syntax-rules} produces a new macro transformer by +specifying a sequence of hygienic rewrite rules. A use of a macro whose +keyword is associated with a transformer specified by +@code{syntax-rules} is matched against the patterns contained in the +@var{syntax-rule}s, beginning with the leftmost @var{syntax-rule}. When +a match is found, the macro use is transcribed hygienically according to +the template. + +An identifier that appears in the pattern of a @var{syntax-rule} is a +@dfn{pattern-variable}, unless it is the keyword that begins the +pattern, is listed in @var{literals}, or is the identifier @samp{...}. +Pattern variables match arbitrary input elements and are used to refer +to elements of the input in the template. It is an error for the same +pattern variable to appear more than once in a @var{pattern}. + +The keyword at the beginning of the pattern in a @var{syntax-rule} is +not involved in the matching and is not considered a pattern variable or +literal identifier. + +Identifiers that appear in @var{literals} are interpreted as literal +identifiers to be matched against corresponding subforms of the input. +A subform in the input matches a literal identifier if and only if it is +an identifier and either both its occurrence in the macro expression and +its occurrence in the macro definition have the same lexical binding, or +the two identifiers are equal and both have no lexical binding. + +A subpattern followed by @samp{...} can match zero or more elements of +the input. It is an error for @samp{...} to appear in @var{literals}. +Within a pattern the identifier @samp{...} must follow the last element +of a nonempty sequence of subpatterns. + +More formally, an input form @var{F} matches a pattern @var{P} if and +only if: + +@itemize @bullet +@item +@var{P} is a non-literal identifier; or + +@item +@var{P} is a literal identifier and @var{F} is an identifier with the +same binding; or + +@item +@var{P} is a list @code{(@var{P_1} @dots{} @var{P_n})} and @var{F} is a +list of @var{n} forms that match @var{P_1} through @var{P_n}, +respectively; or + +@item +@var{P} is an improper list @code{(@var{P_1} @var{P_2} @dots{} @var{P_n} +. @var{P_n+1})} and @var{F} is a list or improper list of @var{n} or +more forms that match @var{P_1} through @var{P_n}, respectively, and +whose @var{n}th ``cdr'' matches @var{P_n+1}; or + +@item +@var{P} is of the form @code{(@var{P_1} @dots{} @var{P_n} @var{P_n+1} +@var{ellipsis})} where @var{ellipsis} is the identifier @samp{...} and +@var{F} is a proper list of at least @var{n} forms, the first @var{n} of +which match @var{P_1} through @var{P_n}, respectively, and each +remaining element of @var{F} matches @var{P_n+1}; or + +@item +@var{P} is a datum and @var{F} is equal to @var{P} in the sense of the +@code{equal?} procedure. +@end itemize + +It is an error to use a macro keyword, within the scope of its +binding, in an expression that does not match any of the patterns. + +When a macro use is transcribed according to the template of the +matching @var{syntax rule}, pattern variables that occur in the template +are replaced by the subforms they match in the input. Pattern variables +that occur in subpatterns followed by one or more instances of the +identifier @samp{...} are allowed only in subtemplates that are followed +by as many instances of @samp{...}. They are replaced in the output by +all of the subforms they match in the input, distributed as indicated. +It is an error if the output cannot be built up as specified. + +Identifiers that appear in the template but are not pattern variables or +the identifier @samp{...} are inserted into the output as literal +identifiers. If a literal identifier is inserted as a free identifier +then it refers to the binding of that identifier within whose scope the +instance of @code{syntax-rules} appears. If a literal identifier is +inserted as a bound identifier then it is in effect renamed to prevent +inadvertent captures of free identifiers. + +@example +@group +(let ((=> #f)) + (cond (#t => 'ok))) @result{} ok +@end group +@end example + +The macro transformer for @code{cond} recognizes @code{=>} +as a local variable, and hence an expression, and not as the +top-level identifier @code{=>}, which the macro transformer treats +as a syntactic keyword. Thus the example expands into + +@example +@group +(let ((=> #f)) + (if #t (begin => 'ok))) +@end group +@end example + +instead of + +@example +@group +(let ((=> #f)) + (let ((temp #t)) + (if temp + ('ok temp)))) +@end group +@end example + +which would result in an invalid procedure call. +@end deffn + +@node Syntactic Closures, Explicit Renaming, Pattern Language, Macros +@subsection Syntactic Closures + +@cindex syntactic closures +MIT/GNU Scheme's syntax-transformation engine is an implementation of +@dfn{syntactic closures}, a mechanism invented by Alan Bawden and +Jonathan Rees. The main feature of the syntactic-closures mechanism is +its simplicity and its close relationship to the environment models +commonly used with Scheme. Using the mechanism to write macro +transformers is somewhat cumbersome and can be confusing for the newly +initiated, but it is easily mastered. + +@menu +* Syntax Terminology:: +* SC Transformer Definition:: +* SC Identifiers:: +@end menu + +@node Syntax Terminology, SC Transformer Definition, Syntactic Closures, Syntactic Closures +@subsubsection Syntax Terminology + +This section defines the concepts and data types used by the syntactic +closures facility. + +@itemize @bullet +@item +@cindex form +@dfn{Forms} are the syntactic entities out of which programs are +recursively constructed. A form is any expression, any definition, any +syntactic keyword, or any syntactic closure. The variable name that +appears in a @code{set!} special form is also a form. Examples of +forms: + +@example +@group +17 +#t +car +(+ x 4) +(lambda (x) x) +(define pi 3.14159) +if +define +@end group +@end example + +@item +@cindex alias +@cindex identifier +@cindex synthetic identifier +An @dfn{alias} is an alternate name for a given symbol. It can appear +anywhere in a form that the symbol could be used, and when quoted it is +replaced by the symbol; however, it does not satisfy the predicate +@code{symbol?}. Macro transformers rarely distinguish symbols from +aliases, referring to both as @dfn{identifiers}. Another name for an +alias is @dfn{synthetic identifier}; this document uses both names. + +@item +@cindex syntactic environment +A @dfn{syntactic environment} maps identifiers to their meanings. More +precisely, it determines whether an identifier is a syntactic keyword +or a variable. If it is a keyword, the meaning is an interpretation +for the form in which that keyword appears. If it is a variable, the +meaning identifies which binding of that variable is referenced. In +short, syntactic environments contain all of the contextual information +necessary for interpreting the meaning of a particular form. + +@item +@cindex syntactic closure +A @dfn{syntactic closure} consists of a form, a syntactic environment, +and a list of identifiers. All identifiers in the form take their +meaning from the syntactic environment, except those in the given list. +The identifiers in the list are to have their meanings determined +later. + +A syntactic closure may be used in any context in which its form could +have been used. Since a syntactic closure is also a form, it may not +be used in contexts where a form would be illegal. For example, a form +may not appear as a clause in the @code{cond} special form. + +A syntactic closure appearing in a quoted structure is replaced by its +form. +@end itemize + +@node SC Transformer Definition, SC Identifiers, Syntax Terminology, Syntactic Closures +@subsubsection Transformer Definition + +This section describes the special forms for defining syntactic-closures +macro transformers, and the associated procedures for manipulating +syntactic closures and syntactic environments. + +@deffn {special form} sc-macro-transformer expression +The @var{expression} is expanded in the syntactic environment of the +@code{sc-macro-transformer} expression, and the expanded expression is +evaluated in the transformer environment to yield a macro transformer as +described below. This macro transformer is bound to a macro keyword by +the special form in which the @code{transformer} expression appears (for +example, @code{let-syntax}). + +@cindex macro transformer +@cindex input form +@cindex usage environment +@cindex output form +@cindex transformer environment +In the syntactic closures facility, a @dfn{macro transformer} is a +procedure that takes two arguments, a form and a syntactic environment, +and returns a new form. The first argument, the @dfn{input form}, is +the form in which the macro keyword occurred. The second argument, the +@dfn{usage environment}, is the syntactic environment in which the input +form occurred. The result of the transformer, the @dfn{output form}, is +automatically closed in the @dfn{transformer environment}, which is the +syntactic environment in which the @code{transformer} expression +occurred. + +For example, here is a definition of a @code{push} macro using +@code{syntax-rules}: + +@example +@group +(define-syntax push + (syntax-rules () + ((push item list) + (set! list (cons item list))))) +@end group +@end example + +@noindent +Here is an equivalent definition using @code{sc-macro-transformer}: + +@example +@group +(define-syntax push + (sc-macro-transformer + (lambda (exp env) + (let ((item (make-syntactic-closure env '() (cadr exp))) + (list (make-syntactic-closure env '() (caddr exp)))) + `(set! ,list (cons ,item ,list)))))) +@end group +@end example + +@noindent +In this example, the identifiers @code{set!} and @code{cons} are closed +in the transformer environment, and thus will not be affected by the +meanings of those identifiers in the usage environment @code{env}. + +Some macros may be non-hygienic by design. For example, the following +defines a @code{loop} macro that implicitly binds @code{exit} to an +escape procedure. The binding of @code{exit} is intended to capture +free references to @code{exit} in the body of the loop, so @code{exit} +must be left free when the body is closed: + +@example +@group +(define-syntax loop + (sc-macro-transformer + (lambda (exp env) + (let ((body (cdr exp))) + `(call-with-current-continuation + (lambda (exit) + (let f () + ,@@(map (lambda (exp) + (make-syntactic-closure env '(exit) + exp)) + body) + (f)))))))) +@end group +@end example +@end deffn + +@deffn {special form} rsc-macro-transformer expression +This form is an alternative way to define a syntactic-closures macro +transformer. Its syntax and usage are identical to +@code{sc-macro-transformer}, except that the roles of the usage +environment and transformer environment are reversed. (Hence +@acronym{RSC} stands for @dfn{Reversed Syntactic Closures}.) In other +words, the procedure specified by @var{expression} still accepts two +arguments, but its second argument will be the transformer environment +rather than the usage environment, and the returned expression is closed +in the usage environment rather than the transformer environment. + +The advantage of this arrangement is that it allows a simpler definition +style in some situations. For example, here is the @code{push} macro +from above, rewritten in this style: + +@example +@group +(define-syntax push + (rsc-macro-transformer + (lambda (exp env) + `(,(make-syntactic-closure env '() 'SET!) + ,(caddr exp) + (,(make-syntactic-closure env '() 'CONS) + ,(cadr exp) + ,(caddr exp)))))) +@end group +@end example + +@noindent +In this style only the introduced keywords are closed, while everything +else remains open. + +Note that @code{rsc-macro-transformer} and @code{sc-macro-transformer} +are easily interchangeable. Here is how to emulate +@code{rsc-macro-transformer} using @code{sc-macro-transformer}. (This +technique can be used to effect the opposite emulation as well.) + +@example +@group +(define-syntax push + (sc-macro-transformer + (lambda (exp usage-env) + (capture-syntactic-environment + (lambda (env) + (make-syntactic-closure usage-env '() + `(,(make-syntactic-closure env '() 'SET!) + ,(caddr exp) + (,(make-syntactic-closure env '() 'CONS) + ,(cadr exp) + ,(caddr exp))))))))) +@end group +@end example +@end deffn + +To assign meanings to the identifiers in a form, use +@code{make-syntactic-closure} to close the form in a syntactic +environment. + +@deffn procedure make-syntactic-closure environment free-names form +@var{Environment} must be a syntactic environment, @var{free-names} +must be a list of identifiers, and @var{form} must be a form. +@code{make-syntactic-closure} constructs and returns a syntactic +closure of @var{form} in @var{environment}, which can be used anywhere +that @var{form} could have been used. All the identifiers used in +@var{form}, except those explicitly excepted by @var{free-names}, +obtain their meanings from @var{environment}. + +Here is an example where @var{free-names} is something other than the +empty list. It is instructive to compare the use of @var{free-names} +in this example with its use in the @code{loop} example above: the +examples are similar except for the source of the identifier being left +free. + +@example +@group +(define-syntax let1 + (sc-macro-transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (exp (cadddr exp))) + `((lambda (,id) + ,(make-syntactic-closure env (list id) exp)) + ,(make-syntactic-closure env '() init)))))) +@end group +@end example + +@noindent +@code{let1} is a simplified version of @code{let} that only binds a +single identifier, and whose body consists of a single expression. +When the body expression is syntactically closed in its original +syntactic environment, the identifier that is to be bound by +@code{let1} must be left free, so that it can be properly captured by +the @code{lambda} in the output form. +@end deffn + +In most situations, the @var{free-names} argument to +@code{make-syntactic-closure} is the empty list. In those cases, the +more succinct @code{close-syntax} can be used: + +@deffn procedure close-syntax form environment +@var{Environment} must be a syntactic environment and @var{form} must be +a form. Returns a new syntactic closure of @var{form} in +@var{environment}, with no free names. Entirely equivalent to + +@example +(make-syntactic-closure @var{environment} '() @var{form}) +@end example +@end deffn + +To obtain a syntactic environment other than the usage environment, +use @code{capture-syntactic-environment}. + +@deffn procedure capture-syntactic-environment procedure +@code{capture-syntactic-environment} returns a form that will, when +transformed, call @var{procedure} on the current syntactic environment. +@var{Procedure} should compute and return a new form to be transformed, +in that same syntactic environment, in place of the form. + +An example will make this clear. Suppose we wanted to define a simple +@code{loop-until} keyword equivalent to + +@example +@group +(define-syntax loop-until + (syntax-rules () + ((loop-until id init test return step) + (letrec ((loop + (lambda (id) + (if test return (loop step))))) + (loop init))))) +@end group +@end example + +@noindent +The following attempt at defining @code{loop-until} has a subtle +bug: + +@example +@group +(define-syntax loop-until + (sc-macro-transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (test (cadddr exp)) + (return (cadddr (cdr exp))) + (step (cadddr (cddr exp))) + (close + (lambda (exp free) + (make-syntactic-closure env free exp)))) + `(letrec ((loop + (lambda (,id) + (if ,(close test (list id)) + ,(close return (list id)) + (loop ,(close step (list id))))))) + (loop ,(close init '()))))))) +@end group +@end example + +@noindent +This definition appears to take all of the proper precautions to +prevent unintended captures. It carefully closes the subexpressions in +their original syntactic environment and it leaves the @code{id} +identifier free in the @code{test}, @code{return}, and @code{step} +expressions, so that it will be captured by the binding introduced by +the @code{lambda} expression. Unfortunately it uses the identifiers +@code{if} and @code{loop} @emph{within} that @code{lambda} expression, +so if the user of @code{loop-until} just happens to use, say, @code{if} +for the identifier, it will be inadvertently captured. + +The syntactic environment that @code{if} and @code{loop} want to be +exposed to is the one just outside the @code{lambda} expression: before +the user's identifier is added to the syntactic environment, but after +the identifier @code{loop} has been added. +@code{capture-syntactic-environment} captures exactly that environment +as follows: + +@example +@group +(define-syntax loop-until + (sc-macro-transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (test (cadddr exp)) + (return (cadddr (cdr exp))) + (step (cadddr (cddr exp))) + (close + (lambda (exp free) + (make-syntactic-closure env free exp)))) + `(letrec ((loop + ,(capture-syntactic-environment + (lambda (env) + `(lambda (,id) + (,(make-syntactic-closure env '() `if) + ,(close test (list id)) + ,(close return (list id)) + (,(make-syntactic-closure env '() `loop) + ,(close step (list id))))))))) + (loop ,(close init '()))))))) +@end group +@end example + +@noindent +In this case, having captured the desired syntactic environment, it is +convenient to construct syntactic closures of the identifiers @code{if} +and the @code{loop} and use them in the body of the +@code{lambda}. + +A common use of @code{capture-syntactic-environment} is to get the +transformer environment of a macro transformer: + +@example +@group +(sc-macro-transformer + (lambda (exp env) + (capture-syntactic-environment + (lambda (transformer-env) + @dots{})))) +@end group +@end example +@end deffn + +@node SC Identifiers, , SC Transformer Definition, Syntactic Closures +@subsubsection Identifiers + +This section describes the procedures that create and manipulate +identifiers. The identifier data type extends the syntactic closures +facility to be compatible with the high-level @code{syntax-rules} +facility. + +@cindex alias +As discussed earlier, an identifier is either a symbol or an +@dfn{alias}. An alias is implemented as a syntactic closure whose +@var{form} is an identifier: + +@example +@group +(make-syntactic-closure env '() 'a) @result{} @r{an alias} +@end group +@end example + +@noindent +Aliases are implemented as syntactic closures because they behave just +like syntactic closures most of the time. The difference is that an +alias may be bound to a new value (for example by @code{lambda} or +@code{let-syntax}); other syntactic closures may not be used this way. +If an alias is bound, then within the scope of that binding it is looked +up in the syntactic environment just like any other identifier. + +Aliases are used in the implementation of the high-level facility +@code{syntax-rules}. A macro transformer created by @code{syntax-rules} +uses a template to generate its output form, substituting subforms of +the input form into the template. In a syntactic closures +implementation, all of the symbols in the template are replaced by +aliases closed in the transformer environment, while the output form +itself is closed in the usage environment. This guarantees that the +macro transformation is hygienic, without requiring the transformer to +know the syntactic roles of the substituted input subforms. + +@deffn procedure identifier? object +Returns @code{#t} if @var{object} is an identifier, otherwise returns +@code{#f}. Examples: + +@example +@group +(identifier? 'a) @result{} #t +(identifier? (make-syntactic-closure env '() 'a)) + @result{} #t + +(identifier? "a") @result{} #f +(identifier? #\a) @result{} #f +(identifier? 97) @result{} #f +(identifier? #f) @result{} #f +(identifier? '(a)) @result{} #f +(identifier? '#(a)) @result{} #f +@end group +@end example +@end deffn + +The predicate @code{eq?} is used to determine if two identifers are +``the same''. Thus @code{eq?} can be used to compare identifiers +exactly as it would be used to compare symbols. Often, though, it is +useful to know whether two identifiers ``mean the same thing''. For +example, the @code{cond} macro uses the symbol @code{else} to identify +the final clause in the conditional. A macro transformer for +@code{cond} cannot just look for the symbol @code{else}, because the +@code{cond} form might be the output of another macro transformer that +replaced the symbol @code{else} with an alias. Instead the transformer +must look for an identifier that ``means the same thing'' in the usage +environment as the symbol @code{else} means in the transformer +environment. + +@deffn procedure identifier=? environment1 identifier1 environment2 identifier2 +@var{Environment1} and @var{environment2} must be syntactic +environments, and @var{identifier1} and @var{identifier2} must be +identifiers. @code{identifier=?} returns @code{#t} if the meaning of +@var{identifier1} in @var{environment1} is the same as that of +@var{identifier2} in @var{environment2}, otherwise it returns @code{#f}. +Examples: + +@example +@group +(let-syntax + ((foo + (sc-macro-transformer + (lambda (form env) + (capture-syntactic-environment + (lambda (transformer-env) + (identifier=? transformer-env 'x env 'x))))))) + (list (foo) + (let ((x 3)) + (foo)))) + @result{} (#t #f) +@end group + +@group +(let-syntax ((bar foo)) + (let-syntax + ((foo + (sc-macro-transformer + (lambda (form env) + (capture-syntactic-environment + (lambda (transformer-env) + (identifier=? transformer-env 'foo + env (cadr form)))))))) + (list (foo foo) + (foo bar)))) + @result{} (#f #t) +@end group +@end example +@end deffn + +Sometimes it is useful to be able to introduce a new identifier that is +guaranteed to be different from any existing identifier, similarly to +the way that @code{generate-uninterned-symbol} is used. + +@deffn procedure make-synthetic-identifier identifier +Creates and returns and new synthetic identifier (alias) that is +guaranteed to be different from all existing identifiers. +@var{Identifier} is any existing identifier, which is used in deriving +the name of the new identifier. + +This is implemented by syntactically closing @var{identifier} in a +special empty environment. +@end deffn + +@node Explicit Renaming, , Syntactic Closures, Macros +@subsection Explicit Renaming + +@cindex explicit renaming +@dfn{Explicit renaming} is an alternative facility for defining macro +transformers. In the MIT/GNU Scheme implementation, explicit-renaming +transformers are implemented as an abstraction layer on top of syntactic +closures. An explicit-renaming macro transformer is defined by an +instance of the @code{er-macro-transformer} keyword: + +@deffn {special form} er-macro-transformer expression +The @var{expression} is expanded in the syntactic environment of the +@code{er-macro-transformer} expression, and the expanded expression is +evaluated in the transformer environment to yield a macro transformer as +described below. This macro transformer is bound to a macro keyword by +the special form in which the @code{transformer} expression appears (for +example, @code{let-syntax}). + +@cindex macro transformer +@cindex input form, to macro +In the explicit-renaming facility, a @dfn{macro transformer} is a +procedure that takes three arguments, a form, a renaming procedure, and +a comparison predicate, and returns a new form. The first argument, the +@dfn{input form}, is the form in which the macro keyword occurred. + +@cindex renaming procedure +The second argument to a transformation procedure is a @dfn{renaming +procedure} that takes the representation of an identifier as its +argument and returns the representation of a fresh identifier that +occurs nowhere else in the program. For example, the transformation +procedure for a simplified version of the @code{let} macro might be +written as + +@example +@group +(lambda (exp rename compare) + (let ((vars (map car (cadr exp))) + (inits (map cadr (cadr exp))) + (body (cddr exp))) + `((lambda ,vars ,@@body) + ,@@inits))) +@end group +@end example + +@noindent +This would not be hygienic, however. A hygienic @code{let} macro must +rename the identifier @code{lambda} to protect it from being captured by +a local binding. The renaming effectively creates an fresh alias for +@code{lambda}, one that cannot be captured by any subsequent binding: + +@example +@group +(lambda (exp rename compare) + (let ((vars (map car (cadr exp))) + (inits (map cadr (cadr exp))) + (body (cddr exp))) + `((,(rename 'lambda) ,vars ,@@body) + ,@@inits))) +@end group +@end example + +The expression returned by the transformation procedure will be expanded +in the syntactic environment obtained from the syntactic environment of +the macro application by binding any fresh identifiers generated by the +renaming procedure to the denotations of the original identifiers in the +syntactic environment in which the macro was defined. This means that a +renamed identifier will denote the same thing as the original identifier +unless the transformation procedure that renamed the identifier placed +an occurrence of it in a binding position. + +The renaming procedure acts as a mathematical function in the sense that +the identifiers obtained from any two calls with the same argument will +be the same in the sense of @code{eqv?}. It is an error if the renaming +procedure is called after the transformation procedure has returned. + +@cindex comparison predicate +The third argument to a transformation procedure is a @dfn{comparison +predicate} that takes the representations of two identifiers as its +arguments and returns true if and only if they denote the same thing in +the syntactic environment that will be used to expand the transformed +macro application. For example, the transformation procedure for a +simplified version of the @code{cond} macro can be written as + +@example +@group +(lambda (exp rename compare) + (let ((clauses (cdr exp))) + (if (null? clauses) + `(,(rename 'quote) unspecified) + (let* ((first (car clauses)) + (rest (cdr clauses)) + (test (car first))) + (cond ((and (identifier? test) + (compare test (rename 'else))) + `(,(rename 'begin) ,@@(cdr first))) + (else `(,(rename 'if) + ,test + (,(rename 'begin) ,@@(cdr first)) + (cond ,@@rest)))))))))) +@end group +@end example + +@noindent +In this example the identifier @code{else} is renamed before being passed +to the comparison predicate, so the comparison will be true if and +only if the test expression is an identifier that denotes the same +thing in the syntactic environment of the expression being transformed +as @code{else} denotes in the syntactic environment in which the @code{cond} +macro was defined. If @code{else} were not renamed before being passed to +the comparison predicate, then it would match a local variable that +happened to be named @code{else}, and the macro would not be hygienic. + +Some macros are non-hygienic by design. For example, the following +defines a @code{loop} macro that implicitly binds @code{exit} to an +escape procedure. The binding of @code{exit} is intended to capture +free references to @code{exit} in the body of the loop, so @code{exit} +is not renamed. + +@example +@group +(define-syntax loop + (er-macro-transformer + (lambda (x r c) + (let ((body (cdr x))) + `(,(r 'call-with-current-continuation) + (,(r 'lambda) (exit) + (,(r 'let) ,(r 'f) () ,@@body (,(r 'f))))))))) +@end group +@end example + +Suppose a @code{while} macro is implemented using @code{loop}, with the +intent that @code{exit} may be used to escape from the @code{while} +loop. The @code{while} macro cannot be written as + +@example +@group +(define-syntax while + (syntax-rules () + ((while test body ...) + (loop (if (not test) (exit #f)) + body ...)))) +@end group +@end example + +@noindent +because the reference to @code{exit} that is inserted by the +@code{while} macro is intended to be captured by the binding of +@code{exit} that will be inserted by the @code{loop} macro. In other +words, this @code{while} macro is not hygienic. Like @code{loop}, it +must be written using the @code{er-macro-transformer} syntax: + +@example +@group +(define-syntax while + (er-macro-transformer + (lambda (x r c) + (let ((test (cadr x)) + (body (cddr x))) + `(,(r 'loop) + (,(r 'if) (,(r 'not) ,test) (exit #f)) + ,@@body))))) +@end group +@end example +@end deffn + +@node SRFI syntax, , Macros, Special Forms +@section SRFI syntax + +@cindex SRFI syntax +Several special forms have been introduced to support some of the +@uref{http://srfi.schemers.org/,Scheme Requests for Implementation} +(@acronym{SRFI}). Note that MIT/GNU Scheme has for some time supported +@uref{http://srfi.schemers.org/srfi-23/srfi-23.html,@acronym{SRFI} 23} +(error-reporting mechanism) and +@uref{http://srfi.schemers.org/srfi-30/srfi-30.html,@acronym{SRFI} 30} +(nested multi-line comments), since these @acronym{SRFI}s reflect +existing practice rather than introducing new functionality. + +@menu +* cond-expand (SRFI 0):: +* receive (SRFI 8):: +* define-record-type (SRFI 9):: +@end menu + +@node cond-expand (SRFI 0), receive (SRFI 8), SRFI syntax, SRFI syntax +@subsection cond-expand (SRFI 0) + +@cindex SRFI 0 +@uref{http://srfi.schemers.org/srfi-0/srfi-0.html,@acronym{SRFI} 0} +is a mechanism for portably determining the availability of +@uref{http://srfi.schemers.org/,@acronym{SRFI}} @dfn{features}. +The @code{cond-expand} special form conditionally expands according to +the features available. + +@deffn {special form} cond-expand clause clause dots{} +Each @var{clause} has the form + +@example +(@var{feature-requirement} @var{expression} @dots{}) +@end example + +where @var{feature-requirement} can have one of the following forms: + +@example +@group +@var{feature-identifier} +(and @var{feature-requirement} @dots{}) +(or @var{feature-requirement} @dots{}) +(not @var{feature-requirement}) +else +@end group +@end example + +(Note that at most one @code{else} clause may be present, and it must +always be the last clause.) + +The @code{cond-expand} special form tests for the existence of features +at macro-expansion time. It either expands into the body of one of its +@var{clause}s or signals an error during syntactic processing. +@code{cond-expand} expands into the body of the first @var{clause} whose +@var{feature-requirement} is currently satisfied (an @code{else} +@var{clause}, if present, is selected if none of the previous +@var{clauses} is selected). + +A @var{feature-requirement} has an obvious interpretation as a logical +formula, where the @var{feature-identifier} variables have meaning true +if the feature corresponding to the @var{feature-identifier}, as +specified in the @acronym{SRFI} registry, is in effect at the location +of the @code{cond-expand} form, and false otherwise. A +@var{feature-requirement} is satisfied if its formula is true under this +interpretation. + +@example +@group +(cond-expand + ((and srfi-1 srfi-10) + (write 1)) + ((or srfi-1 srfi-10) + (write 2)) + (else)) + +(cond-expand + (command-line + (define (program-name) (car (argv))))) +@end group +@end example + +The second example assumes that @code{command-line} is an alias for some +feature which gives access to command line arguments. Note that an +error will be signaled at macro-expansion time if this feature is not +present. + +Note that MIT/GNU Scheme allows @code{cond-expand} in any context where a +special form is allowed. This is an extension of the semantics defined +by @acronym{SRFI 0}, which only allows @code{cond-expand} at top level. +@end deffn + +@node receive (SRFI 8), define-record-type (SRFI 9), cond-expand (SRFI 0), SRFI syntax +@subsection receive (SRFI 8) + +@cindex SRFI 8 +@uref{http://srfi.schemers.org/srfi-8/srfi-8.html,@acronym{SRFI} 8} +defines a convenient syntax to bind an identifier to each of the values +of a multiple-valued expression and then evaluate an expression in the +scope of the bindings. As an instance of this pattern, consider the +following excerpt from a @samp{quicksort} procedure: + +@example +@group +(call-with-values + (lambda () + (partition (precedes pivot) others)) + (lambda (fore aft) + (append (qsort fore) (cons pivot (qsort aft))))) +@end group +@end example + +Here @samp{partition} is a multiple-valued procedure that takes two +arguments, a predicate and a list, and returns two lists, one comprising +the list elements that satisfy the predicate, the other those that do +not. The purpose of the expression shown is to partition the list +@samp{others}, sort each of the sublists, and recombine the results into +a sorted list. + +For our purposes, the important step is the binding of the identifiers +@samp{fore} and @samp{aft} to the values returned by @samp{partition}. +Expressing the construction and use of these bindings with the +call-by-values primitive is cumbersome: One must explicitly embed the +expression that provides the values for the bindings in a parameterless +procedure, and one must explicitly embed the expression to be evaluated +in the scope of those bindings in another procedure, writing as its +parameters the identifiers that are to be bound to the values received. + +These embeddings are boilerplate, exposing the underlying binding +mechanism but not revealing anything relevant to the particular program +in which it occurs. So the use of a syntactic abstraction that exposes +only the interesting parts -- the identifiers to be bound, the +multiple-valued expression that supplies the values, and the body of the +receiving procedure -- makes the code more concise and more readable: + +@example +@group +(receive (fore aft) (partition (precedes pivot) others) + (append (qsort fore) (cons pivot (qsort aft)))) +@end group +@end example + +The advantages are similar to those of a @samp{let} expression over a +procedure call with a @samp{lambda} expression as its operator. In both +cases, cleanly separating a ``header'' in which the bindings are +established from a ``body'' in which they are used makes it easier to +follow the code. + +@deffn {special form} receive formals expression body +@var{Formals} and @var{body} are defined as for @samp{lambda} +(@pxref{Lambda Expressions}). Specifically, @var{formals} can have the +following forms (the use of @samp{#!optional} and @samp{#!rest} is also +allowed in @var{formals} but is omitted for brevity): + +@table @samp +@item (@var{ident1} @dots{} @var{identN}) +The environment in which the @samp{receive} expression is evaluated is +extended by binding @var{ident1}, @dots{}, @var{identN} to fresh +locations. The @var{expression} is evaluated, and its values are stored +into those locations. (It is an error if @var{expression} does not have +exactly @var{N} values.) + +@item @var{ident} +The environment in which the @samp{receive} expression is evaluated is +extended by binding @var{ident} to a fresh location. The +@var{expression} is evaluated, its values are converted into a newly +allocated list, and the list is stored in the location bound to +@var{ident}. + +@item (@var{ident1} @dots{} @var{identN} . @var{identN+1}) +The environment in which the @samp{receive} expression is evaluated is +extended by binding @var{ident1}, @dots{}, @var{identN+1} to fresh +locations. The @var{expression} is evaluated. Its first @var{N} values +are stored into the locations bound to @var{ident1} @dots{} @var{identN}. +Any remaining values are converted into a newly allocated list, which is +stored into the location bound to @var{identN+1}. (It is an error if +@var{expression} does not have at least @var{N} values.) +@end table + +In any case, the expressions in @var{body} are evaluated sequentially in +the extended environment. The results of the last expression in the +body are the values of the @samp{receive} expression. +@end deffn + +@node define-record-type (SRFI 9), , receive (SRFI 8), SRFI syntax +@subsection define-record-type (SRFI 9) + +@cindex SRFI 9 +The @samp{define-record-type} syntax described in +@uref{http://srfi.schemers.org/srfi-9/srfi-9.html,@acronym{SRFI} 9} is a +slight simplification of one written for Scheme 48 by Jonathan Rees. +Unlike many record-defining special forms, it does not create any new +identifiers. Instead, the names of the record type, predicate, +constructor, and so on are all listed explicitly in the source. This +has the following advantages: + +@itemize @bullet +@item +It can be defined using a simple macro in Scheme implementations that +provide a procedural interface for creating record types. + +@item +It does not restrict users to a particular naming convention. + +@item +Tools like @command{grep} and the GNU Emacs tag facility will see the +defining occurance of each identifier. +@end itemize + +@deffn {special form} define-record-type type-name (constructor-name field-tag @dots{}) predicate-name field-spec @dots{} +@var{Type-name}, @var{contructor-name}, @var{field-tag}, and +@var{predicate-name} are identifiers. @var{Field-spec} has one of these +two forms: + +@example +@group +(@var{field-tag} @var{accessor-name}) +(@var{field-tag} @var{accessor-name} @var{modifier-name}) +@end group +@end example + +@noindent +where @var{field-tag}, @var{accessor-name}, and @var{modifier-name} are +each identifiers. + +@code{define-record-type} is generative: each use creates a new record +type that is distinct from all existing types, including other record +types and Scheme's predefined types. Record-type definitions may only +occur at top-level (there are two possible semantics for ``internal'' +record-type definitions, generative and nongenerative, and no consensus +as to which is better). + +An instance of @code{define-record-type} is equivalent to the following +definitions: + +@itemize @bullet +@item +@var{Type-name} is bound to a representation of the record type itself. +Operations on record types, such as defining print methods, reflection, +etc.@: are left to other SRFIs. + +@item +@var{constructor-name} is bound to a procedure that takes as many +arguments as there are @var{field-tag}s in the (@var{constructor-name} +@dots{}) subform and returns a new @var{type-name} record. Fields whose +tags are listed with @var{constructor-name} have the corresponding +argument as their initial value. The initial values of all other fields +are unspecified. + +@item +@var{predicate-name} is a predicate that returns @code{#t} when given a +value returned by @var{constructor-name} and @code{#f} for everything +else. + +@item +Each @var{accessor-name} is a procedure that takes a record of type +@var{type-name} and returns the current value of the corresponding +field. It is an error to pass an accessor a value which is not a record +of the appropriate type. + +@item +Each @var{modifier-name} is a procedure that takes a record of type +@var{type-name} and a value which becomes the new value of the +corresponding field; an unspecified value is returned. It is an error +to pass a modifier a first argument which is not a record of the +appropriate type. +@end itemize + +Assigning the value of any of these identifiers has no effect on the +behavior of any of their original values. +@end deffn + +The following + +@example +@group +(define-record-type :pare + (kons x y) + pare? + (x kar set-kar!) + (y kdr)) +@end group +@end example + +@noindent +defines @samp{kons} to be a constructor, @samp{kar} and @samp{kdr} to be +accessors, @samp{set-kar!} to be a modifier, and @samp{pare?} to be a +predicate for objects of type @samp{:pare}. + +@example +@group +(pare? (kons 1 2)) @result{} #t +(pare? (cons 1 2)) @result{} #f +(kar (kons 1 2)) @result{} 1 +(kdr (kons 1 2)) @result{} 2 +(let ((k (kons 1 2))) + (set-kar! k 3) + (kar k)) @result{} 3 +@end group +@end example diff --git a/v7/doc/ref-manual/strings.texi b/v7/doc/ref-manual/strings.texi new file mode 100644 index 000000000..db2c5711c --- /dev/null +++ b/v7/doc/ref-manual/strings.texi @@ -0,0 +1,1327 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: strings.texi,v 1.1 2003/04/15 03:30:18 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Strings, Lists, Characters, Top +@chapter Strings + +@cindex string, character (defn) +@findex char-ascii? +A @dfn{string} is a mutable sequence of characters. In the current +implementation of MIT/GNU Scheme, the elements of a string must all +satisfy the predicate @code{char-ascii?}; if someone ports MIT/GNU +Scheme to a non-@acronym{ASCII} operating system this requirement will +change. + +@cindex external representation, for string +@cindex " as external representation +@cindex double quote, as external representation +@cindex \ as escape character in string +@cindex backslash, as escape character in string +@cindex escape character, for string +@findex " +@findex \ +A string is written as a sequence of characters enclosed within double +quotes @code{" "}. To include a double quote inside a string, precede +the double quote with a backslash @code{\} (escape it), as in + +@example +"The word \"recursion\" has many meanings." +@end example + +@noindent +The printed representation of this string is + +@example +The word "recursion" has many meanings. +@end example + +@noindent +To include a backslash inside a string, precede it with another +backslash; for example, + +@example +"Use #\\Control-q to quit." +@end example + +@noindent +The printed representation of this string is + +@example +Use #\Control-q to quit. +@end example + +@findex \t +@findex \n +@findex \f +@findex #\tab +@findex #\newline +@findex #\page +The effect of a backslash that doesn't precede a double quote or +backslash is unspecified in standard Scheme, but MIT/GNU Scheme specifies +the effect for three other characters: @code{\t}, @code{\n}, and +@code{\f}. These escape sequences are respectively translated into the +following characters: @code{#\tab}, @code{#\newline}, and @code{#\page}. +Finally, a backslash followed by exactly three octal digits is +translated into the character whose @acronym{ISO-8859-1} code is those +digits. + +If a string literal is continued from one line to another, the string +will contain the newline character (@code{#\newline}) at the line break. +Standard Scheme does not specify what appears in a string literal at a +line break. + +@cindex length, of string (defn) +@cindex index, of string (defn) +@cindex valid index, of string (defn) +@cindex string length (defn) +@cindex string index (defn) +The @dfn{length} of a string is the number of characters that it +contains. This number is an exact non-negative integer that is +established when the string is created +(but @pxref{Variable-Length Strings}). +Each character in a string has an @dfn{index}, which is a +number that indicates the character's position in the string. The index +of the first (leftmost) character in a string is 0, and the index of the +last character is one less than the length of the string. The +@dfn{valid indexes} of a string are the exact non-negative integers less +than the length of the string. + +@cindex substring (defn) +@cindex start, of substring (defn) +@cindex end, of substring (defn) +A number of the string procedures operate on substrings. A +@dfn{substring} is a segment of a @var{string}, which is specified by +two integers @var{start} and @var{end} satisfying these relationships: + +@example +0 <= @var{start} <= @var{end} <= (string-length @var{string}) +@end example + +@noindent +@var{Start} is the index of the first character in the substring, and +@var{end} is one greater than the index of the last character in the +substring. Thus if @var{start} and @var{end} are equal, they refer to +an empty substring, and if @var{start} is zero and @var{end} is the +length of @var{string}, they refer to all of @var{string}. + +@cindex case sensitivity, of string operations +@cindex -ci, in string procedure name +Some of the procedures that operate on strings ignore the difference +between uppercase and lowercase. The versions that ignore case include +@samp{-ci} (for ``case insensitive'') in their names. + +@menu +* Construction of Strings:: +* Selecting String Components:: +* Comparison of Strings:: +* Alphabetic Case in Strings:: +* Cutting and Pasting Strings:: +* Searching Strings:: +* Matching Strings:: +* Regular Expressions:: +* Modification of Strings:: +* Variable-Length Strings:: +* Byte Vectors:: +@end menu + +@node Construction of Strings, Selecting String Components, Strings, Strings +@section Construction of Strings +@cindex construction, of string + +@deffn {procedure} make-string k [char] +Returns a newly allocated string of length @var{k}. If you specify +@var{char}, all elements of the string are initialized to @var{char}, +otherwise the contents of the string are unspecified. @var{Char} must +satisfy the predicate @code{char-ascii?}. + +@example +(make-string 10 #\x) @result{} "xxxxxxxxxx" +@end example +@end deffn + +@deffn procedure string char @dots{} +Returns a newly allocated string consisting of the specified characters. +The arguments must all satisfy @code{char-ascii?}. + +@example +@group +(string #\a) @result{} "a" +(string #\a #\b #\c) @result{} "abc" +(string #\a #\space #\b #\space #\c) @result{} "a b c" +(string) @result{} "" +@end group +@end example +@end deffn + +@deffn procedure list->string char-list +@cindex list, converting to string +@findex string->list +@var{Char-list} must be a list of @acronym{ISO-8859-1} characters. +@code{list->string} returns a newly allocated string formed from the +elements of @var{char-list}. This is equivalent to @code{(apply string +@var{char-list})}. The inverse of this operation is +@code{string->list}. + +@example +@group +(list->string '(#\a #\b)) @result{} "ab" +(string->list "Hello") @result{} (#\H #\e #\l #\l #\o) +@end group +@end example +@end deffn + +@deffn {procedure} string-copy string +@cindex copying, of string +Returns a newly allocated copy of @var{string}. + +Note regarding variable-length strings: the maximum length of the result +depends only on the length of @var{string}, not its maximum length. If +you wish to copy a string and preserve its maximum length, do the +following: + +@example +@group +(define (string-copy-preserving-max-length string) + (let ((length)) + (dynamic-wind + (lambda () + (set! length (string-length string)) + (set-string-length! string + (string-maximum-length string))) + (lambda () + (string-copy string)) + (lambda () + (set-string-length! string length))))) +@end group +@end example +@end deffn + +@node Selecting String Components, Comparison of Strings, Construction of Strings, Strings +@section Selecting String Components +@cindex selection, of string component +@cindex component selection, of string + +@deffn procedure string? object +@cindex type predicate, for string +Returns @code{#t} if @var{object} is a string; otherwise returns +@code{#f}. + +@example +@group +(string? "Hi") @result{} #t +(string? 'Hi) @result{} #f +@end group +@end example +@end deffn + +@deffn procedure string-length string +Returns the length of @var{string} as an exact non-negative integer. + +@example +@group +(string-length "") @result{} 0 +(string-length "The length") @result{} 10 +@end group +@end example +@end deffn + +@deffn procedure string-null? string +@cindex empty string, predicate for +@cindex null string, predicate for +Returns @code{#t} if @var{string} has zero length; otherwise returns +@code{#f}. + +@example +@group +(string-null? "") @result{} #t +(string-null? "Hi") @result{} #f +@end group +@end example +@end deffn + +@deffn procedure string-ref string k +Returns character @var{k} of @var{string}. @var{K} must be a valid index +of @var{string}. + +@example +@group +(string-ref "Hello" 1) @result{} #\e +(string-ref "Hello" 5) @error{} 5 not in correct range +@end group +@end example +@end deffn + +@deffn {procedure} string-set! string k char +Stores @var{char} in element @var{k} of @var{string} and returns an +unspecified value. @var{K} must be a valid index of @var{string}, and +@var{char} must satisfy the predicate @code{char-ascii?}. + +@example +@group +(define str "Dog") @result{} @r{unspecified} +(string-set! str 0 #\L) @result{} @r{unspecified} +str @result{} "Log" +(string-set! str 3 #\t) @error{} 3 not in correct range +@end group +@end example +@end deffn + +@need 1000 +@node Comparison of Strings, Alphabetic Case in Strings, Selecting String Components, Strings +@section Comparison of Strings +@cindex ordering, of strings +@cindex comparison, of strings + +@deffn procedure string=? string1 string2 +@deffnx procedure substring=? string1 start end string2 start end +@deffnx {procedure} string-ci=? string1 string2 +@deffnx procedure substring-ci=? string1 start end string2 start end +@cindex equivalence predicate, for strings +Returns @code{#t} if the two strings (substrings) are the same length +and contain the same characters in the same (relative) positions; +otherwise returns @code{#f}. @code{string-ci=?} and +@code{substring-ci=?} don't distinguish uppercase and lowercase letters, +but @code{string=?} and @code{substring=?} do. + +@example +@group +(string=? "PIE" "PIE") @result{} #t +(string=? "PIE" "pie") @result{} #f +(string-ci=? "PIE" "pie") @result{} #t +(substring=? "Alamo" 1 3 "cola" 2 4) @result{} #t @r{; compares "la"} +@end group +@end example +@end deffn + +@deffn procedure string? string1 string2 +@deffnx procedure string<=? string1 string2 +@deffnx procedure string>=? string1 string2 +@deffnx {procedure} string-ci? string1 string2 +@deffnx {procedure} string-ci<=? string1 string2 +@deffnx {procedure} string-ci>=? string1 string2 +These procedures compare strings (substrings) according to the order of +the characters they contain (also @pxref{Comparison of Characters}). +The arguments are compared using a lexicographic (or dictionary) order. +If two strings differ in length but are the same up to the length of the +shorter string, the shorter string is considered to be less than the +longer string. + +@example +@group +(string? "catkin" "cat") @result{} #t @r{; shorter is lesser} +@end group +@end example +@end deffn + +@deffn procedure string-compare string1 string2 if-eq if-lt if-gt +@deffnx procedure string-compare-ci string1 string2 if-eq if-lt if-gt +@var{If-eq}, @var{if-lt}, and @var{if-gt} are procedures of no arguments +(thunks). The two strings are compared; if they are equal, @var{if-eq} +is applied, if @var{string1} is less than @var{string2}, @var{if-lt} is +applied, else if @var{string1} is greater than @var{string2}, +@var{if-gt} is applied. The value of the procedure is the value of the +thunk that is applied. + +@code{string-compare} distinguishes uppercase and lowercase letters;@* +@code{string-compare-ci} does not. + +@example +@group +(define (cheer) (display "Hooray!")) +(define (boo) (display "Boo-hiss!")) +(string-compare "a" "b" cheer (lambda() 'ignore) boo) + @print{} Hooray! + @result{} @r{unspecified} +@end group +@end example +@end deffn + +@deffn procedure string-hash string +@deffnx procedure string-hash-mod string k +@cindex hashing, of string +@findex string=? +@findex = +@code{string-hash} returns an exact non-negative integer that can be used +for storing the specified @var{string} in a hash table. Equal strings +(in the sense of @code{string=?}) return equal (@code{=}) hash codes, +and non-equal but similar strings are usually mapped to distinct hash +codes. + +@code{string-hash-mod} is like @code{string-hash}, except that it limits +the result to a particular range based on the exact non-negative integer +@var{k}. The following are equivalent: + +@example +@group +(string-hash-mod @var{string} @var{k}) +(modulo (string-hash @var{string}) @var{k}) +@end group +@end example +@end deffn + +@node Alphabetic Case in Strings, Cutting and Pasting Strings, Comparison of Strings, Strings +@section Alphabetic Case in Strings +@cindex alphabetic case, of string +@cindex case, of string +@cindex capitalization, of string +@cindex uppercase, in string +@cindex lowercase, in string + +@deffn procedure string-capitalized? string +@deffnx procedure substring-capitalized? string start end +These procedures return @code{#t} if the first word in the string +(substring) is capitalized, and any subsequent words are either lower +case or capitalized. Otherwise, they return @code{#f}. A word is +defined as a non-null contiguous sequence of alphabetic characters, +delimited by non-alphabetic characters or the limits of the string +(substring). A word is capitalized if its first letter is upper case +and all its remaining letters are lower case. + +@example +@group +(map string-capitalized? '("" "A" "art" "Art" "ART")) + @result{} (#f #t #f #t #f) +@end group +@end example +@end deffn + +@deffn procedure string-upper-case? string +@deffnx procedure substring-upper-case? string start end +@deffnx procedure string-lower-case? string +@deffnx procedure substring-lower-case? string start end +These procedures return @code{#t} if all the letters in the string +(substring) are of the correct case, otherwise they return @code{#f}. +The string (substring) must contain at least one letter or the +procedures return @code{#f}. + +@example +@group +(map string-upper-case? '("" "A" "art" "Art" "ART")) + @result{} (#f #t #f #f #t) +@end group +@end example +@end deffn + +@deffn procedure string-capitalize string +@deffnx procedure string-capitalize! string +@deffnx procedure substring-capitalize! string start end +@code{string-capitalize} returns a newly allocated copy of @var{string} +in which the first alphabetic character is uppercase and the remaining +alphabetic characters are lowercase. For example, @code{"abcDEF"} +becomes @code{"Abcdef"}. @code{string-capitalize!} is the destructive +version of @code{string-capitalize}: it alters @var{string} and returns +an unspecified value. @code{substring-capitalize!} destructively +capitalizes the specified part of @var{string}. +@end deffn + +@deffn procedure string-downcase string +@deffnx procedure string-downcase! string +@deffnx procedure substring-downcase! string start end +@code{string-downcase} returns a newly allocated copy of @var{string} in +which all uppercase letters are changed to lowercase. +@code{string-downcase!} is the destructive version of +@code{string-downcase}: it alters @var{string} and returns an +unspecified value. @code{substring-downcase!} destructively changes the +case of the specified part of @var{string}. + +@example +@group +(define str "ABCDEFG") @result{} @r{unspecified} +(substring-downcase! str 3 5) @result{} @r{unspecified} +str @result{} "ABCdeFG" +@end group +@end example +@end deffn + +@deffn procedure string-upcase string +@deffnx procedure string-upcase! string +@deffnx procedure substring-upcase! string start end +@code{string-upcase} returns a newly allocated copy of @var{string} in +which all lowercase letters are changed to uppercase. +@code{string-upcase!} is the destructive version of +@code{string-upcase}: it alters @var{string} and returns an unspecified +value. @code{substring-upcase!} destructively changes the case of the +specified part of @var{string}. +@end deffn + +@node Cutting and Pasting Strings, Searching Strings, Alphabetic Case in Strings, Strings +@section Cutting and Pasting Strings +@cindex cutting, of string +@cindex pasting, of strings + +@deffn {procedure} string-append string @dots{} +@cindex appending, of strings +Returns a newly allocated string made from the concatenation of the given +strings. With no arguments, @code{string-append} returns the empty +string (@code{""}). + +@example +@group +(string-append) @result{} "" +(string-append "*" "ace" "*") @result{} "*ace*" +(string-append "" "" "") @result{} "" +(eq? str (string-append str)) @result{} #f @r{; newly allocated} +@end group +@end example +@end deffn + +@deffn procedure substring string start end +Returns a newly allocated string formed from the characters of +@var{string} beginning with index @var{start} (inclusive) and ending +with @var{end} (exclusive). + +@example +@group +(substring "" 0 0) @result{} "" +(substring "arduous" 2 5) @result{} "duo" +(substring "arduous" 2 8) @error{} 8 not in correct range + +(define (string-copy s) + (substring s 0 (string-length s))) +@end group +@end example +@end deffn + +@deffn procedure string-head string end +Returns a newly allocated copy of the initial substring of @var{string}, +up to but excluding @var{end}. It could have been defined by: + +@example +@group +(define (string-head string end) + (substring string 0 end)) +@end group +@end example +@end deffn + +@deffn procedure string-tail string start +Returns a newly allocated copy of the final substring of @var{string}, +starting at index @var{start} and going to the end of @var{string}. It +could have been defined by: + +@example +@group +(define (string-tail string start) + (substring string start (string-length string))) + +(string-tail "uncommon" 2) @result{} "common" +@end group +@end example +@end deffn + +@deffn procedure string-pad-left string k [char] +@deffnx procedure string-pad-right string k [char] +@cindex padding, of string +@findex #\space +These procedures return a newly allocated string created by padding +@var{string} out to length @var{k}, using @var{char}. If @var{char} is +not given, it defaults to @code{#\space}. If @var{k} is less than the +length of @var{string}, the resulting string is a truncated form of +@var{string}. @code{string-pad-left} adds padding characters or +truncates from the beginning of the string (lowest indices), while +@code{string-pad-right} does so at the end of the string (highest +indices). + +@example +@group +(string-pad-left "hello" 4) @result{} "ello" +(string-pad-left "hello" 8) @result{} " hello" +(string-pad-left "hello" 8 #\*) @result{} "***hello" +(string-pad-right "hello" 4) @result{} "hell" +(string-pad-right "hello" 8) @result{} "hello " +@end group +@end example +@end deffn + +@deffn procedure string-trim string [char-set] +@deffnx procedure string-trim-left string [char-set] +@deffnx procedure string-trim-right string [char-set] +@cindex trimming, of string +@findex char-set:whitespace +Returns a newly allocated string created by removing all characters that +are not in @var{char-set} from: (@code{string-trim}) both ends of +@var{string}; (@code{string-trim-left}) the beginning of @var{string}; +or (@code{string-trim-right}) the end of @var{string}. @var{Char-set} +defaults to @code{char-set:not-whitespace}. + +@example +@group +(string-trim " in the end ") @result{} "in the end" +(string-trim " ") @result{} "" +(string-trim "100th" char-set:numeric) @result{} "100" +(string-trim-left "-.-+-=-" (char-set #\+)) + @result{} "+-=-" +(string-trim "but (+ x y) is" (char-set #\( #\))) + @result{} "(+ x y)" +@end group +@end example +@end deffn + +@node Searching Strings, Matching Strings, Cutting and Pasting Strings, Strings +@section Searching Strings +@cindex searching, of string +@cindex character, searching string for +@cindex substring, searching string for + +The first few procedures in this section perform @dfn{string search}, in +which a given string (the @dfn{text}) is searched to see if it contains +another given string (the @dfn{pattern}) as a proper substring. At +present these procedures are implemented using a hybrid strategy. For +short patterns of less than 4 characters, the naive string-search +algorithm is used. For longer patterns, the Boyer-Moore string-search +algorithm is used. + +@deffn procedure string-search-forward pattern string +@deffnx procedure substring-search-forward pattern string start end +@var{Pattern} must be a string. Searches @var{string} for the leftmost +occurrence of the substring @var{pattern}. If successful, the index of +the first character of the matched substring is returned; otherwise, +@code{#f} is returned. + +@code{substring-search-forward} limits its search to the specified +substring of @var{string}; @code{string-search-forward} searches all of +@var{string}. + +@example +@group +(string-search-forward "rat" "pirate") + @result{} 2 +(string-search-forward "rat" "pirate rating") + @result{} 2 +(substring-search-forward "rat" "pirate rating" 4 13) + @result{} 7 +(substring-search-forward "rat" "pirate rating" 9 13) + @result{} #f +@end group +@end example +@end deffn + +@deffn procedure string-search-backward pattern string +@deffnx procedure substring-search-backward pattern string start end +@var{Pattern} must be a string. Searches @var{string} for the rightmost +occurrence of the substring @var{pattern}. If successful, the index to +the right of the last character of the matched substring is returned; +otherwise, @code{#f} is returned. + +@code{substring-search-backward} limits its search to the specified +substring of @var{string}; @code{string-search-backward} searches all of +@var{string}. + +@example +@group +(string-search-backward "rat" "pirate") + @result{} 5 +(string-search-backward "rat" "pirate rating") + @result{} 10 +(substring-search-backward "rat" "pirate rating" 1 8) + @result{} 5 +(substring-search-backward "rat" "pirate rating" 9 13) + @result{} #f +@end group +@end example +@end deffn + +@deffn procedure string-search-all pattern string +@deffnx procedure substring-search-all pattern string start end +@var{Pattern} must be a string. Searches @var{string} to find all +occurrences of the substring @var{pattern}. Returns a list of the +occurrences; each element of the list is an index pointing to the first +character of an occurrence. + +@code{substring-search-all} limits its search to the specified substring +of @var{string}; @code{string-search-all} searches all of @var{string}. + +@example +@group +(string-search-all "rat" "pirate") + @result{} (2) +(string-search-all "rat" "pirate rating") + @result{} (2 7) +(substring-search-all "rat" "pirate rating" 4 13) + @result{} (7) +(substring-search-all "rat" "pirate rating" 9 13) + @result{} () +@end group +@end example +@end deffn + +@deffn procedure substring? pattern string +@var{Pattern} must be a string. Searches @var{string} to see if it +contains the substring @var{pattern}. Returns @code{#t} if +@var{pattern} is a substring of @var{string}, otherwise returns +@code{#f}. + +@example +@group +(substring? "rat" "pirate") @result{} #t +(substring? "rat" "outrage") @result{} #f +(substring? "" any-string) @result{} #t +(if (substring? "moon" text) + (process-lunar text) + 'no-moon) +@end group +@end example +@end deffn + +@deffn procedure string-find-next-char string char +@deffnx procedure substring-find-next-char string start end char +@deffnx procedure string-find-next-char-ci string char +@deffnx procedure substring-find-next-char-ci string start end char +Returns the index of the first occurrence of @var{char} in the string +(substring); returns @code{#f} if @var{char} does not appear in the +string. For the substring procedures, the index returned is relative to +the entire string, not just the substring. The @code{-ci} procedures +don't distinguish uppercase and lowercase letters. + +@example +@group +(string-find-next-char "Adam" #\A) @result{} 0 +(substring-find-next-char "Adam" 1 4 #\A) @result{} #f +(substring-find-next-char-ci "Adam" 1 4 #\A) @result{} 2 +@end group +@end example +@end deffn + +@deffn procedure string-find-next-char-in-set string char-set +@deffnx procedure substring-find-next-char-in-set string start end char-set +Returns the index of the first character in the string (or substring) +that is also in @var{char-set}, or returns @code{#f} if none of the +characters in @var{char-set} occur in @var{string}. +For the substring procedure, only the substring is searched, but the +index returned is relative to the entire string, not just the substring. + +@example +@group +(string-find-next-char-in-set my-string char-set:alphabetic) + @result{} @r{start position of the first word in} my-string +@r{; Can be used as a predicate:} +(if (string-find-next-char-in-set my-string + (char-set #\( #\) )) + 'contains-parentheses + 'no-parentheses) +@end group +@end example +@end deffn + +@deffn procedure string-find-previous-char string char +@deffnx procedure substring-find-previous-char string start end char +@deffnx procedure string-find-previous-char-ci string char +@deffnx procedure substring-find-previous-char-ci string start end char +Returns the index of the last occurrence of @var{char} in the string +(substring); returns @code{#f} if @var{char} doesn't appear in the +string. For the substring procedures, the index returned is relative to +the entire string, not just the substring. The @code{-ci} procedures +don't distinguish uppercase and lowercase letters. +@end deffn + +@deffn procedure string-find-previous-char-in-set string char-set +@deffnx procedure substring-find-previous-char-in-set string start end char-set +Returns the index of the last character in the string (substring) that +is also in @var{char-set}. For the substring procedure, the index +returned is relative to the entire string, not just the substring. +@end deffn + +@node Matching Strings, Regular Expressions, Searching Strings, Strings +@section Matching Strings +@cindex matching, of strings + +@deffn procedure string-match-forward string1 string2 +@deffnx procedure substring-match-forward string1 start end string2 start end +@deffnx procedure string-match-forward-ci string1 string2 +@deffnx procedure substring-match-forward-ci string1 start end string2 start end +Compares the two strings (substrings), starting from the beginning, and +returns the number of characters that are the same. If the two strings +(substrings) start differently, returns 0. The @code{-ci} procedures +don't distinguish uppercase and lowercase letters. + +@example +@group +(string-match-forward "mirror" "micro") @result{} 2 @r{; matches "mi"} +(string-match-forward "a" "b") @result{} 0 @r{; no match} +@end group +@end example +@end deffn + +@deffn procedure string-match-backward string1 string2 +@deffnx procedure substring-match-backward string1 start end string2 start end +@deffnx procedure string-match-backward-ci string1 string2 +@deffnx procedure substring-match-backward-ci string1 start end string2 start end +Compares the two strings (substrings), starting from the end and +matching toward the front, returning the number of characters that are +the same. If the two strings (substrings) end differently, returns 0. +The @code{-ci} procedures don't distinguish uppercase and lowercase +letters. + +@example +@group +(string-match-backward-ci "BULBOUS" "fractious") + @result{} 3 @r{; matches "ous"} +@end group +@end example +@end deffn + +@deffn procedure string-prefix? string1 string2 +@deffnx procedure substring-prefix? string1 start1 end1 string2 start2 end2 +@deffnx procedure string-prefix-ci? string1 string2 +@deffnx procedure substring-prefix-ci? string1 start1 end1 string2 start2 end2 +@cindex prefix, of string +These procedures return @code{#t} if the first string (substring) forms +the prefix of the second; otherwise returns @code{#f}. The @code{-ci} +procedures don't distinguish uppercase and lowercase letters. + +@example +@group +(string-prefix? "abc" "abcdef") @result{} #t +(string-prefix? "" any-string) @result{} #t +@end group +@end example +@end deffn + +@deffn procedure string-suffix? string1 string2 +@deffnx procedure substring-suffix? string1 start1 end1 string2 start2 end2 +@deffnx procedure string-suffix-ci? string1 string2 +@deffnx procedure substring-suffix-ci? string1 start1 end1 string2 start2 end2 +@cindex suffix, of string +These procedures return @code{#t} if the first string (substring) forms +the suffix of the second; otherwise returns @code{#f}. The @code{-ci} +procedures don't distinguish uppercase and lowercase letters. + +@example +@group +(string-suffix? "ous" "bulbous") @result{} #t +(string-suffix? "" any-string) @result{} #t +@end group +@end example +@end deffn + +@node Regular Expressions, Modification of Strings, Matching Strings, Strings +@section Regular Expressions + +MIT/GNU Scheme provides support for using regular expressions to search and +match strings. This manual does not define regular expressions; instead +see @ref{Regexps, , Syntax of Regular Expressions, emacs, The Emacs +Editor}. + +In addition to providing standard regular-expression support, MIT/GNU +Scheme also provides the @acronym{REXP} abstraction. This is an +alternative way to write regular expressions that is easier to read +and understand than the standard notation. Regular expressions +written in this notation can be translated into the standard +notation. + +The regular-expression support is a run-time-loadable option. To use +it, execute + +@example +(load-option 'regular-expression) +@end example + +@noindent +once before calling any of the procedures defined here. + +@menu +* Regular-expression procedures:: +* REXP abstraction:: +@end menu + +@node Regular-expression procedures, REXP abstraction, Regular Expressions, Regular Expressions +@subsection Regular-expression procedures +@cindex searching, for regular expression +@cindex regular expression, searching string for + +Procedures that perform regular-expression match and search accept +standardized arguments. @var{Regexp} is the regular expression; it is a +string. @var{String} is the string being matched or searched. +Procedures that operate on substrings also accept @var{start} and +@var{end} index arguments with the usual meaning. The optional argument +@var{case-fold?} says whether the match/search is case-sensitive; if +@var{case-fold?} is @code{#f}, it is case-sensitive, otherwise it is +case-insensitive. The optional argument @var{syntax-table} is a +character syntax table that defines the character syntax, such as which +characters are legal word constituents. This feature is primarily for +Edwin, so character syntax tables will not be documented here. +Supplying @code{#f} for (or omitting) @var{syntax-table} will select the +default character syntax, equivalent to Edwin's @code{fundamental} +mode. + +@deffn procedure re-string-match regexp string [case-fold? [syntax-table]] +@deffnx procedure re-substring-match regexp string start end [case-fold? [syntax-table]] +These procedures match @var{regexp} against the respective string or +substring, returning @code{#f} for no match, or a set of match registers +(see below) if the match succeeds. Here is an example showing how to +extract the matched substring: + +@example +@group +(let ((r (re-substring-match @var{regexp} @var{string} @var{start} @var{end}))) + (and r + (substring @var{string} @var{start} (re-match-end-index 0 r)))) +@end group +@end example +@end deffn + +@deffn procedure re-string-search-forward regexp string [case-fold? [syntax-table]] +@deffnx procedure re-substring-search-forward regexp string start end [case-fold? [syntax-table]] +Searches @var{string} for the leftmost substring matching @var{regexp}. +Returns a set of match registers (see below) if the search is +successful, or @code{#f} if it is unsuccessful. + +@code{re-substring-search-forward} limits its search to the specified +substring of @var{string}; @code{re-string-search-forward} searches all +of @var{string}. +@end deffn + +@deffn procedure re-string-search-backward regexp string [case-fold? [syntax-table]] +@deffnx procedure re-substring-search-backward regexp string start end [case-fold? [syntax-table]] +Searches @var{string} for the rightmost substring matching @var{regexp}. +Returns a set of match registers (see below) if the search is +successful, or @code{#f} if it is unsuccessful. + +@code{re-substring-search-backward} limits its search to the specified +substring of @var{string}; @code{re-string-search-backward} searches all +of @var{string}. +@end deffn + +When a successful match or search occurs, the above procedures return a +set of @dfn{match registers}. The match registers are a set of index +registers that record indexes into the matched string. Each index +register corresponds to an instance of the regular-expression grouping +operator @samp{\(}, and records the start index (inclusive) and end +index (exclusive) of the matched group. These registers are numbered +from @code{1} to @code{9}, corresponding left-to-right to the grouping +operators in the expression. Additionally, register @code{0} +corresponds to the entire substring matching the regular expression. + +@deffn procedure re-match-start-index n registers +@deffnx procedure re-match-end-index n registers +@var{N} must be an exact integer between @code{0} and @code{9} +inclusive. @var{Registers} must be a match-registers object as returned +by one of the regular-expression match or search procedures above. +@code{re-match-start-index} returns the start index of the corresponding +regular-expression register, and @code{re-match-end-index} returns the +corresponding end index. +@end deffn + +@deffn procedure re-match-extract string registers n +@var{Registers} must be a match-registers object as returned by one of +the regular-expression match or search procedures above. @var{String} +must be the string that was passed as an argument to the procedure that +returned @var{registers}. @var{N} must be an exact integer between +@code{0} and @code{9} inclusive. If the matched regular expression +contained @var{m} grouping operators, then the value of this procedure +is undefined for @var{n} strictly greater than @var{m}. + +This procedure extracts the substring corresponding to the match +register specified by @var{registers} and @var{n}. This is equivalent +to the following expression: + +@example +@group +(substring @var{string} + (re-match-start-index @var{n} @var{registers}) + (re-match-end-index @var{n} @var{registers})) +@end group +@end example +@end deffn + +@deffn procedure regexp-group alternative @dots{} +Each @var{alternative} must be a regular expression. The returned value +is a new regular expression that consists of the @var{alternative}s +combined by a grouping operator. For example: + +@example +@group +(regexp-group "foo" "bar" "baz") + @result{} "\\(foo\\|bar\\|baz\\)" +@end group +@end example +@end deffn + +@node REXP abstraction, , Regular-expression procedures, Regular Expressions +@subsection REXP abstraction + +@cindex REXP abstraction +In addition to providing standard regular-expression support, MIT/GNU +Scheme also provides the @acronym{REXP} abstraction. This is an +alternative way to write regular expressions that is easier to read +and understand than the standard notation. Regular expressions +written in this notation can be translated into the standard notation. + +The @acronym{REXP} abstraction is a set of combinators that are +composed into a complete regular expression. Each combinator directly +corresponds to a particular piece of regular-expression notation. For +example, the expression @code{(rexp-any-char)} corresponds to the +@code{.} character in standard regular-expression notation, while +@code{(rexp* @var{rexp})} corresponds to the @code{*} character. + +The primary advantages of @acronym{REXP} are that it makes the nesting +structure of regular expressions explicit, and that it simplifies the +description of complex regular expressions by allowing them to be +built up using straightforward combinators. + +@deffn procedure rexp? object +Returns @code{#t} if @var{object} is a @acronym{REXP} expression, or +@code{#f} otherwise. A @acronym{REXP} is one of: a string, which +represents the pattern matching that string; a character set, which +represents the pattern matching a character in that set; or an object +returned by calling one of the procedures defined here. +@end deffn + +@deffn procedure rexp->regexp rexp +Converts @var{rexp} to standard regular-expression notation, returning +a newly-allocated string. +@end deffn + +@deffn procedure rexp-compile rexp +Converts @var{rexp} to standard regular-expression notation, then +compiles it and returns the compiled result. Equivalent to + +@example +(re-compile-pattern (rexp->regexp @var{rexp}) #f) +@end example +@end deffn + +@deffn procedure rexp-any-char +Returns a @acronym{REXP} that matches any single character except a +newline. This is equivalent to the @code{.} construct. +@end deffn + +@deffn procedure rexp-line-start +Returns a @acronym{REXP} that matches the start of a line. This is +equivalent to the @code{^} construct. +@end deffn + +@deffn procedure rexp-line-end +Returns a @acronym{REXP} that matches the end of a line. This is +equivalent to the @code{$} construct. +@end deffn + +@deffn procedure rexp-string-start +Returns a @acronym{REXP} that matches the start of the text being +matched. This is equivalent to the @code{\`} construct. +@end deffn + +@deffn procedure rexp-string-end +Returns a @acronym{REXP} that matches the end of the text being +matched. This is equivalent to the @code{\'} construct. +@end deffn + +@deffn procedure rexp-word-edge +Returns a @acronym{REXP} that matches the start or end of a word. +This is equivalent to the @code{\b} construct. +@end deffn + +@deffn procedure rexp-not-word-edge +Returns a @acronym{REXP} that matches anywhere that is not the start +or end of a word. This is equivalent to the @code{\B} construct. +@end deffn + +@deffn procedure rexp-word-start +Returns a @acronym{REXP} that matches the start of a word. +This is equivalent to the @code{\<} construct. +@end deffn + +@deffn procedure rexp-word-end +Returns a @acronym{REXP} that matches the end of a word. +This is equivalent to the @code{\>} construct. +@end deffn + +@deffn procedure rexp-word-char +Returns a @acronym{REXP} that matches any word-constituent character. +This is equivalent to the @code{\w} construct. +@end deffn + +@deffn procedure rexp-not-word-char +Returns a @acronym{REXP} that matches any character that isn't a word +constituent. This is equivalent to the @code{\W} construct. +@end deffn + +The next two procedures accept a @var{syntax-type} argument specifying +the syntax class to be matched against. This argument is a symbol +selected from the following list. Each symbol is followed by the +equivalent character used in standard regular-expression notation. +@code{whitespace} (space character), +@code{punctuation} (@code{.}), +@code{word} (@code{w}), +@code{symbol} (@code{_}), +@code{open} (@code{(}), +@code{close} (@code{)}), +@code{quote} (@code{'}), +@code{string-delimiter} (@code{"}), +@code{math-delimiter} (@code{$}), +@code{escape} (@code{\}), +@code{char-quote} (@code{/}), +@code{comment-start} (@code{<}), +@code{comment-end} (@code{>}). + +@deffn procedure rexp-syntax-char syntax-type +Returns a @acronym{REXP} that matches any character of type +@var{syntax-type}. This is equivalent to the @code{\s} construct. +@end deffn + +@deffn procedure rexp-not-syntax-char syntax-type +Returns a @acronym{REXP} that matches any character not of type +@var{syntax-type}. This is equivalent to the @code{\S} construct. +@end deffn + +@deffn procedure rexp-sequence rexp @dots{} +Returns a @acronym{REXP} that matches each @var{rexp} argument in +sequence. If no @var{rexp} argument is supplied, the result matches +the null string. This is equivalent to concatenating the regular +expressions corresponding to each @var{rexp} argument. +@end deffn + +@deffn procedure rexp-alternatives rexp @dots{} +Returns a @acronym{REXP} that matches any of the @var{rexp} +arguments. This is equivalent to concatenating the regular +expressions corresponding to each @var{rexp} argument, separating them +by the @code{\|} construct. +@end deffn + +@deffn procedure rexp-group rexp @dots{} +@code{rexp-group} is like @code{rexp-sequence}, except that the result +is marked as a match group. This is equivalent to the @code{\(} +@dots{} @code{\)} construct. +@end deffn + +The next three procedures in principal accept a single @acronym{REXP} +argument. For convenience, they accept multiple arguments, which are +converted into a single argument by @code{rexp-group}. Note, however, +that if only one @acronym{REXP} argument is supplied, and it's very +simple, no grouping occurs. + +@deffn procedure rexp* rexp @dots{} +Returns a @acronym{REXP} that matches zero or more instances of the +pattern matched by the @var{rexp} arguments. This is equivalent to +the @code{*} construct. +@end deffn + +@deffn procedure rexp+ rexp @dots{} +Returns a @acronym{REXP} that matches one or more instances of the +pattern matched by the @var{rexp} arguments. This is equivalent to +the @code{+} construct. +@end deffn + +@deffn procedure rexp-optional rexp @dots{} +Returns a @acronym{REXP} that matches zero or one instances of the +pattern matched by the @var{rexp} arguments. This is equivalent to +the @code{?} construct. +@end deffn + +@deffn procedure rexp-case-fold rexp +Returns a @acronym{REXP} that matches the same pattern as @var{rexp}, +but is insensitive to character case. This has no equivalent in +standard regular-expression notation. +@end deffn + +@node Modification of Strings, Variable-Length Strings, Regular Expressions, Strings +@section Modification of Strings +@cindex modification, of string +@cindex replacement, of string component +@cindex filling, of string +@cindex moving, of string elements + +@deffn procedure string-replace string char1 char2 +@deffnx procedure substring-replace string start end char1 char2 +@deffnx procedure string-replace! string char1 char2 +@deffnx procedure substring-replace! string start end char1 char2 +These procedures replace all occurrences of @var{char1} with @var{char2} +in the original string (substring). @code{string-replace} and +@code{substring-replace} return a newly allocated string containing the +result. @code{string-replace!} and @code{substring-replace!} +destructively modify @var{string} and return an unspecified value. + +@example +@group +(define str "a few words") @result{} @r{unspecified} +(string-replace str #\space #\-) @result{} "a-few-words" +(substring-replace str 2 9 #\space #\-) @result{} "a few-words" +str @result{} "a few words" +(string-replace! str #\space #\-) @result{} @r{unspecified} +str @result{} "a-few-words" +@end group +@end example +@end deffn + +@deffn {procedure} string-fill! string char +Stores @var{char} in every element of @var{string} and returns an +unspecified value. +@end deffn + +@deffn procedure substring-fill! string start end char +Stores @var{char} in elements @var{start} (inclusive) to @var{end} +(exclusive) of @var{string} and returns an unspecified value. + +@example +@group +(define s (make-string 10 #\space)) @result{} @r{unspecified} +(substring-fill! s 2 8 #\*) @result{} @r{unspecified} +s @result{} " ****** " +@end group +@end example +@end deffn + +@deffn procedure substring-move-left! string1 start1 end1 string2 start2 +@deffnx procedure substring-move-right! string1 start1 end1 string2 start2 +@findex eqv? +Copies the characters from @var{start1} to @var{end1} of @var{string1} +into @var{string2} at the @var{start2}-th position. The characters are +copied as follows (note that this is only important when @var{string1} +and @var{string2} are @code{eqv?}): + +@table @code +@item substring-move-left! +The copy starts at the left end and moves toward the right (from smaller +indices to larger). Thus if @var{string1} and @var{string2} are the +same, this procedure moves the characters toward the left inside the +string. + +@item substring-move-right! +The copy starts at the right end and moves toward the left (from larger +indices to smaller). Thus if @var{string1} and @var{string2} are the +same, this procedure moves the characters toward the right inside the +string. +@end table + +The following example shows how these procedures can be used to build up +a string (it would have been easier to use @code{string-append}): +@example +@group +(define answer (make-string 9 #\*)) @result{} @r{unspecified} +answer @result{} "*********" +(substring-move-left! "start" 0 5 answer 0) @result{} @r{unspecified} +answer @result{} "start****" +(substring-move-left! "-end" 0 4 answer 5) @result{} @r{unspecified} +answer @result{} "start-end" +@end group +@end example +@end deffn + +@deffn procedure reverse-string string +@deffnx procedure reverse-substring string start end +@deffnx procedure reverse-string! string +@deffnx procedure reverse-substring! string start end +Reverses the order of the characters in the given string or substring. +@code{reverse-string} and @code{reverse-substring} return newly +allocated strings; @code{reverse-string!} and @code{reverse-substring!} +modify their argument strings and return an unspecified value. + +@example +@group +(reverse-string "foo bar baz") @result{} "zab rab oof" +(reverse-substring "foo bar baz" 4 7) @result{} "rab" +(let ((foo "foo bar baz")) + (reverse-string! foo) + foo) @result{} "zab rab oof" +(let ((foo "foo bar baz")) + (reverse-substring! foo 4 7) + foo) @result{} "foo rab baz" +@end group +@end example +@end deffn + +@node Variable-Length Strings, Byte Vectors, Modification of Strings, Strings +@section Variable-Length Strings + +@cindex length, of string +@cindex maximum length, of string (defn) +MIT/GNU Scheme allows the length of a string to be dynamically adjusted in a +limited way. When a new string is allocated, by whatever method, it has +a specific length. At the time of allocation, it is also given a +@dfn{maximum length}, which is guaranteed to be at least as large as the +string's length. (Sometimes the maximum length will be slightly larger +than the length, but it is a bad idea to count on this. Programs should +assume that the maximum length is the same as the length at the time of +the string's allocation.) After the string is allocated, the operation +@code{set-string-length!} can be used to alter the string's length to +any value between 0 and the string's maximum length, inclusive. + +@deffn procedure string-maximum-length string +Returns the maximum length of @var{string}. The following is +guaranteed: + +@example +@group +(<= (string-length string) + (string-maximum-length string)) @result{} #t +@end group +@end example +@findex string-length + +The maximum length of a string never changes. +@end deffn + +@deffn procedure set-string-length! string k +Alters the length of @var{string} to be @var{k}, and returns an +unspecified value. @var{K} must be less than or equal to the maximum +length of @var{string}. @code{set-string-length!} does not change the +maximum length of @var{string}. +@end deffn + +@node Byte Vectors, , Variable-Length Strings, Strings +@section Byte Vectors +@cindex byte vector +@cindex vector, byte + +@findex string-ref +MIT/GNU Scheme implements strings as packed vectors of 8-bit +@acronym{ISO-8859-1} bytes. Most of the string operations, such as +@code{string-ref}, coerce these 8-bit codes into character objects. +However, some lower-level operations are made available for use. + +@deffn procedure vector-8b-ref string k +Returns character @var{k} of @var{string} as an @acronym{ISO-8859-1} +code. @var{K} must be a valid index of @var{string}. + +@example +@group +(vector-8b-ref "abcde" 2) @result{} 99 @r{;c} +@end group +@end example +@end deffn + +@deffn procedure vector-8b-set! string k code +Stores @var{code} in element @var{k} of @var{string} and returns an +unspecified value. @var{K} must be a valid index of @var{string}, and +@var{code} must be a valid @acronym{ISO-8859-1} code. +@end deffn + +@deffn procedure vector-8b-fill! string start end code +Stores @var{code} in elements @var{start} (inclusive) to @var{end} +(exclusive) of @var{string} and returns an unspecified value. +@var{Code} must be a valid @acronym{ISO-8859-1} code. +@end deffn + +@deffn procedure vector-8b-find-next-char string start end code +@deffnx procedure vector-8b-find-next-char-ci string start end code +Returns the index of the first occurrence of @var{code} in the given +substring; returns @code{#f} if @var{code} does not appear. The index +returned is relative to the entire string, not just the substring. +@var{Code} must be a valid @acronym{ISO-8859-1} code. + +@code{vector-8b-find-next-char-ci} doesn't distinguish uppercase and +lowercase letters. +@end deffn + +@deffn procedure vector-8b-find-previous-char string start end code +@deffnx procedure vector-8b-find-previous-char-ci string start end code +Returns the index of the last occurrence of @var{code} in the given +substring; returns @code{#f} if @var{code} does not appear. The index +returned is relative to the entire string, not just the substring. +@var{Code} must be a valid @acronym{ISO-8859-1} code. + +@code{vector-8b-find-previous-char-ci} doesn't distinguish uppercase and +lowercase letters. +@end deffn diff --git a/v7/doc/ref-manual/vectors.texi b/v7/doc/ref-manual/vectors.texi new file mode 100644 index 000000000..b6e693804 --- /dev/null +++ b/v7/doc/ref-manual/vectors.texi @@ -0,0 +1,311 @@ +@c This file is part of the MIT/GNU Scheme Reference Manual. +@c $Id: vectors.texi,v 1.1 2003/04/15 03:30:22 cph Exp $ + +@c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology +@c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology +@c Copyright 2002,2003 Massachusetts Institute of Technology +@c See file scheme.texinfo for copying conditions. + +@node Vectors, Bit Strings, Lists, Top +@chapter Vectors + +@cindex vector (defn) +@dfn{Vectors} are heterogenous structures whose elements are indexed by +exact non-negative integers. A vector typically occupies less space +than a list of the same length, and the average time required to access +a randomly chosen element is typically less for the vector than for the +list. + +@cindex length, of vector (defn) +@cindex index, of vector (defn) +@cindex valid index, of vector (defn) +@cindex vector length (defn) +@cindex vector index (defn) +The @dfn{length} of a vector is the number of elements that it contains. +This number is an exact non-negative integer that is fixed when the +vector is created. The @dfn{valid indexes} of a vector are the exact +non-negative integers less than the length of the vector. The first +element in a vector is indexed by zero, and the last element is indexed +by one less than the length of the vector. + +@cindex external representation, for vector +@cindex #( as external representation +@cindex parenthesis, as external representation +@findex #( +Vectors are written using the notation @code{#(@var{object} @dots{})}. +For example, a vector of length 3 containing the number zero in element +0, the list @code{(2 2 2 2)} in element 1, and the string @code{"Anna"} +in element 2 can be written as + +@example +#(0 (2 2 2 2) "Anna") +@end example + +@noindent +Note that this is the external representation of a vector, not an +expression evaluating to a vector. Like list constants, vector +constants must be quoted: + +@example +'#(0 (2 2 2 2) "Anna") @result{} #(0 (2 2 2 2) "Anna") +@end example + +@cindex subvector (defn) +@cindex start, of subvector (defn) +@cindex end, of subvector (defn) +@cindex index, of subvector (defn) +@cindex valid index, of subvector (defn) +A number of the vector procedures operate on subvectors. A +@dfn{subvector} is a segment of a vector that is specified by two exact +non-negative integers, @var{start} and @var{end}. @var{Start} is the +index of the first element that is included in the subvector, and +@var{end} is one greater than the index of the last element that is +included in the subvector. Thus if @var{start} and @var{end} are the +same, they refer to a null subvector, and if @var{start} is zero and +@var{end} is the length of the vector, they refer to the entire vector. +The @dfn{valid indexes} of a subvector are the exact integers between +@var{start} inclusive and @var{end} exclusive. + +@menu +* Construction of Vectors:: +* Selecting Vector Components:: +* Cutting Vectors:: +* Modifying Vectors:: +@end menu + +@node Construction of Vectors, Selecting Vector Components, Vectors, Vectors +@section Construction of Vectors +@cindex construction, of vector + +@deffn {procedure} make-vector k [object] +Returns a newly allocated vector of @var{k} elements. If @var{object} +is specified, @code{make-vector} initializes each element of the vector +to @var{object}. Otherwise the initial elements of the result are +unspecified. +@end deffn + +@deffn procedure vector object @dots{} +@findex list +Returns a newly allocated vector whose elements are the given arguments. +@code{vector} is analogous to @code{list}. + +@example +(vector 'a 'b 'c) @result{} #(a b c) +@end example +@end deffn + +@deffn procedure vector-copy vector +@cindex copying, of vector +Returns a newly allocated vector that is a copy of @var{vector}. +@end deffn + +@deffn procedure list->vector list +@cindex list, converting to vector +@findex vector->list +Returns a newly allocated vector initialized to the elements of +@var{list}. The inverse of @code{list->vector} is @code{vector->list}. + +@example +(list->vector '(dididit dah)) @result{} #(dididit dah) +@end example +@end deffn + +@deffn procedure make-initialized-vector k initialization +Similar to @code{make-vector}, except that the elements of the result +are determined by calling the procedure @var{initialization} on the +indices. For example: + +@example +@group +(make-initialized-vector 5 (lambda (x) (* x x))) + @result{} #(0 1 4 9 16) +@end group +@end example +@end deffn + +@deffn procedure vector-grow vector k +@cindex growing, of vector +@var{K} must be greater than or equal to the length of @var{vector}. +Returns a newly allocated vector of length @var{k}. The first +@code{(vector-length @var{vector})} elements of the result are +initialized from the corresponding elements of @var{vector}. The +remaining elements of the result are unspecified. +@end deffn + +@deffn procedure vector-map procedure vector +@cindex mapping, of vector +@var{Procedure} must be a procedure of one argument. @code{vector-map} +applies @var{procedure} element-wise to the elements of @var{vector} and +returns a newly allocated vector of the results, in order from left to +right. The dynamic order in which @var{procedure} is applied to the +elements of @var{vector} is unspecified. + +@example +@group +(vector-map cadr '#((a b) (d e) (g h))) @result{} #(b e h) +(vector-map (lambda (n) (expt n n)) '#(1 2 3 4)) + @result{} #(1 4 27 256) +(vector-map + '#(5 7 9)) @result{} #(5 7 9) +@end group +@end example +@end deffn + +@node Selecting Vector Components, Cutting Vectors, Construction of Vectors, Vectors +@section Selecting Vector Components +@cindex selection, of vector component +@cindex component selection, of vector + +@deffn procedure vector? object +@cindex type predicate, for vector +Returns @code{#t} if @var{object} is a vector; otherwise returns +@code{#f}. +@end deffn + +@deffn procedure vector-length vector +Returns the number of elements in @var{vector}. +@end deffn + +@deffn procedure vector-ref vector k +Returns the contents of element @var{k} of @var{vector}. @var{K} must +be a valid index of @var{vector}. + +@example +(vector-ref '#(1 1 2 3 5 8 13 21) 5) @result{} 8 +@end example +@end deffn + +@deffn procedure vector-set! vector k object +Stores @var{object} in element @var{k} of @var{vector} and returns an +unspecified value. @var{K} must be a valid index of +@var{vector}. + +@example +@group +(let ((vec (vector 0 '(2 2 2 2) "Anna"))) + (vector-set! vec 1 '("Sue" "Sue")) + vec) + @result{} #(0 ("Sue" "Sue") "Anna") +@end group +@end example +@end deffn + +@deffn procedure vector-first vector +@deffnx procedure vector-second vector +@deffnx procedure vector-third vector +@deffnx procedure vector-fourth vector +@deffnx procedure vector-fifth vector +@deffnx procedure vector-sixth vector +@deffnx procedure vector-seventh vector +@deffnx procedure vector-eighth vector +These procedures access the first several elements of @var{vector} in +the obvious way. It is an error if the implicit index of one of these +procedurs is not a valid index of @var{vector}. +@end deffn + +@deffn procedure vector-binary-search vector keyinteger @r{; convert} + integer->char @r{; convert return value} + #f @r{; cannot be passed by reference} +) +@end group +@end example +@end deffn + +@deffn {windows type} unchecked +The type which is not checked and undergoes only the basic conversion +from a Scheme integer to a C integer or from a Scheme string to a C +pointer to the first byte of the string. +Returned @code{unchecked} values are returned as integers. +@end deffn + +@deffn {windows type} bool +Scheme booleans are analogous to C integers @code{0} and @code{1}. +Windows type @code{bool} have been defined as: + +@example +@group +(define-windows-type bool + boolean? + (lambda (x) (if x 1 0)) + (lambda (x) (if (eq? x 0) #f #t)) + #f) +@end group +@end example +@end deffn + +@deffn {windows type} char +Scheme characters are converted into C objects of type @code{char}, +which are indistinguishable from small integers. +@end deffn + +@deffn {windows type} int +@deffnx {windows type} uint +@deffnx {windows type} long +@deffnx {windows type} ulong +@deffnx {windows type} short +@deffnx {windows type} ushort +@deffnx {windows type} word +@deffnx {windows type} byte +Various integer types that are passed without conversion. +@end deffn + +@deffn {windows type} string +A string that is passed as a C pointer of type @code{char*} to the first +character in the string. +@end deffn + +@deffn {windows type} char* +A string or @code{#f}. The string is passed as a pointer to characters. +The string is correctly null-terminated. @code{#f} is passed as the null +pointer. This is an example where there is a more complex mapping +between C objects and Scheme objects. C's @code{char*} type is +represented as one of two Scheme types depending on its value. This +allows us us to distinguish between the C string (pointer) that points +to the empty sequence of characters and the null pointer (which doesnt +point anywhere). +@end deffn + +@deffn {windows type} handle +@deffnx {windows type} hbitmap +@deffnx {windows type} hbrush +@deffnx {windows type} hcursor +@deffnx {windows type} hdc +@deffnx {windows type} hicon +@deffnx {windows type} hinstance +@deffnx {windows type} hmenu +@deffnx {windows type} hpalette +@deffnx {windows type} hpen +@deffnx {windows type} hrgn +@deffnx {windows type} hwnd +Various kinds of Win32 handle. These names correspond to the same, but +all uppercase, names in the Windows C language header files. Win32 API +calls are the source of values of this type and the values are +meaningless except as arguments to other Win32 API calls. Currently +these values are represented as integers but we expect that Win32 +handles will in future be represented by allocated Scheme objects +(e.g.@: records) that will allow predicates (e.g.@: @code{hmenu?}) and +sensible interlocking with the garbage collector to free the programmer +of the current tedious allocation and deallocation of handles. +@end deffn + +@deffn {windows type} resource-id +A Windows resource identifier is either a small integer or a string. +In C, this distinction is possible because pointers look like +larger integers, so a machine word representing a small integer can be +distinguished from a machine word that is a pointer to the text of the +name of the resource. +@end deffn + + +@node Windows Foreign Procedures, Win32 API names and procedures, Windows Types, Foreign function interface +@subsection Windows Foreign Procedures + +Foreign procedures are declared as callable entry-points in a module, +usually a dynamically linked library (DLL). + + +@deffn procedure find-module name +@cindex loading DLLs +@cindex DLL, loading +Returns a module suitable for use in creating procedures with +@code{windows-procedure}. @var{Name} is a string which is the name of a +DLL file. Internally, @code{find-module} uses the @code{LoadLibrary} +Win32 API, so @var{name} should conform to the specifications for this +call. @var{Name} should be either a full path name of a DLL, or the +name of a DLL that resides in the same directory as the Scheme binary +@file{SCHEME.EXE} or in the system directory. + +The module returned is a description for the DLL, and the DLL need not +necessarily be linked at or immediately after this call. DLL modules +are linked on need and unlinked before Scheme exits and when there +are no remaining references to entry points after a garbage-collection. +This behavior ensures that the Scheme system can run when a DLL is +absent, provided the DLL is not actually used (i.e.@: no attempt is made +to call a procedure in the DLL). +@end deffn + + +@defvr variable gdi32.dll +@cindex DLL, GDI32.DLL +This variable is bound to the module describing the @file{GDI32.DLL} +library, which contains the Win32 API graphics calls, e.g.@: +@code{LineTo}. +@end defvr + +@defvr variable kernel32.dll +@cindex DLL, KERNEL32.DLL +This variable is bound to the module describing the @file{KERNEL32.DLL} +library. +@end defvr + +@defvr variable user32.dll +@cindex DLL, USER32.DLL +This variable is bound to the module describing the @file{USER32.DLL} +library. This module contains many useful Win32 API procedures, like +@code{MessageBox} and @code{SetWindowText}. +@end defvr + + +@deffn {special form} windows-procedure (name (parameter type) @dots{}) return-type module entry-name [options] +@cindex defining foreign procedures +This form creates a procedure, and could be thought of as +``foreign-named-lambda''. The form creates a Scheme procedure that +calls the C procedure identified by the exported entry point +@var{entry-name} in the module identified by the value of @var{module}. +Both @var{entry-name} and @var{module} are evaluated at procedure +creation time, so either may be expression. @var{Entry-name} must +evaluate to a string and @var{module} must evaluate to a module as +returned by @code{find-module}. +These are the only parts of the form that are evaluated at procedure +creation time. + +@var{Name} is the name of the procedure and is for documentation +purposes only. This form @emph{does not} define a procedure called +@var{name}. It is more like @code{lambda}. The name might be used for +debugging and pretty-printing. + +A windows procedure has a fixed number of parameters (i.e.@: no `rest' +parameters or `varargs'), each of which is named and associated with a +windows type @var{type}. Both the name @var{parameter} and the windows +type @var{type} must be symbols and are not evaluated. The procedure +returns a value of the windows type @var{return-type}. + +The following example creates a procedure that takes a window handle +(@code{hwnd}) and a string and returns a boolean (@code{bool}) result. +The procedure does this by calling the @code{SetWindowText} entry in the +module that is the value of the variable @code{user32.dll}. The +variable @code{set-window-title} is defined to have this procedure as +it's value. + +@example +@group +(define set-window-title + (windows-procedure + (set-window-text (window hwnd) (text string)) + bool user32.dll "SetWindowText")) + +(set-window-title my-win "Hi") + @result{} #t + @r{;; Changes window's title/text} + +set-window-title @result{} #[compiled-procedure @dots{}] +set-window-text @error{} Unbound variable +@end group +@end example + + +When there are no @var{options} the created procedure will (a) check its +arguments against the types, (b) convert the arguments, (c) call the C +procedure and (d) convert the returned value. No reversion is +performed, even if one of the @var{types} has a reversion defined. +(Reverted types are rare [I have never used one], so paying a cost for +this unless it is used seems silly). + +The following options are allowed: + +@table @asis +@item @code{with-reversions} +The reversions are included in the type conversions. + +@item @code{expand} +A synonym for @code{with-reversions}. + +@item @var{Scheme code} +The @var{Scheme code} is placed between steps (a) and (b) in the default +process. The Scheme code can enforce constraints on the arguments, +including constraints between arguments such as checking that an index +refers to a valid position in a string. +@end table + +If both options (i.e.@: @code{with-reversions} and Scheme code) are used, +@code{with-reversions} must appear first. There can be arbitrarily many +Scheme expression. +@end deffn + +@node Win32 API names and procedures, , Windows Foreign Procedures, Foreign function interface +@subsection Win32 API names and procedures + +This section is a moving target. +@cindex Win32 API names +@cindex naming conventions + +The @code{#define} values from @file{wingdi.h} and @file{winuser.h} are +available as bindings in the @code{(win32)} package environment. The +@code{#define} symbols are all uppercase; these have been translated to +all lowercase Scheme identifiers, thus @code{WM_LBUTTONUP} is the scheme +variable @code{wm_lbuttonup}. As Scheme is case insensitive, the +upper-case version may be used and probably should to make the code look +more like conventional Windows code. The Scheme bindings have been +produced automagically. Most of the @code{#define}-symbols contain an +underscore so there are not many name clashes. There is one very +notable name clash, however: @code{ERROR} is @code{#define}d to 0, which +shadows the scheme procedure @code{error} in the root package +environment. To signal an error, use @code{access} to get @code{error} +from the system global environment: + +@example +@group +(declare (usual-integrations)) +@dots{} +((access error system-global-environment) "Complain" @dots{}) +@end group +@end example + + +The set of procedures is incomplete because procedures have been added +on a by-need basis for the implementation of other parts of the system, +e.g.@: Scheme Graphics. Look in the implementation for further details. + +Win32 API procedure names have been uniformly converted into Scheme +identifiers as follows: + +@itemize @bullet +@item +A leading uppercase letter is translated into a lowercase letter. +@item +Subsequent sequences of uppercase letters are translated into lowercase +letters preceeded by a hyphen (minus symbol), i.e.@: hyphens are inserted +at a lowercase to uppercase transition. +@item +Predicates beginning with @code{Is} finally have a +question-mark appended. +@end itemize + +@noindent +Example: applying these rules to @code{IsWindow} yields +@code{is-window?}, and @code{GetDC} is translated into @code{get-dc}. + + +@c [It might be worthwhile just keeping the same names. As the +@c Win32 API procedure names are uniformly `WordWordWordACRONYMWord', case +@c insensitivity is unlikely to be a problem. The only problem is the +@c potential for a clash between a procedure name and a type +@c name.] + + +@node Device Independent Bitmap Utilities, , Foreign function interface, Win32 Package Reference +@section Device Independent Bitmap Utilities + + +The Device Independent Bitmap (DIB) utilities library @file{DIBUTILS.DLL} +and the associated procedures in @file{dib.scm} in the Win32 system +source is an example of how to use the foreign function interface to +access and manipulate non-Scheme objects. +@cindex DLL, DIBUTILS.DLL + +@deffn {windows type} dib +In the C world a DIB is a @dfn{handle} to a piece of memory containing +the bits that represent information about the image and the pixels of +the image. The handle is a machine-word sized piece of data which may +be thought of as a 32 bit integer. The handle may be null (i.e.@: zero), +indicating that there is no block of memory describing the DIB. The +null value is usually returned by C functions that are supposed to +create a DIB but failed, for some reason like the memory could not be +allocated or a file could not be opened. + +In the Scheme world a DIB is a structure containing information +about the bitmap (specifically the integer that represents the handle). +We also include @code{#f} in the @code{dib} windows type to mirror the +null handle error value. + +@example +@group +(define dib-result + (lambda (handle) + (if (= handle 0) + #f + (make-dib handle)))) + +(define dib-arg + (lambda (dib) + (if dib + (cell-contents (dib-handle dib)) + 0))) + +(define-windows-type dib + (lambda (thing) (or (dib? thing) (eq? thing #f))) + dib-arg + dib-result) +@end group +@end example +@end deffn + + +@menu +* DIB procedures:: +* Other parts of the DIB Utilities implementation:: +@end menu + +@node DIB procedures, Other parts of the DIB Utilities implementation, Device Independent Bitmap Utilities, Device Independent Bitmap Utilities +@subsection DIB procedures + +The following procedures have typed parameters, using the same +convention as @code{windows-procedure}. + +@deffn procedure open-dib (filename string) +Return type: @var{dib}. Calls the @code{OpenDIB} entry of +@file{DIBUTILS.DLL}. If the return value is not @code{#f} then the file +@var{filename} was found, successfully opened, and the contents were +suitable for loading into memory as a device independent bitmap. +@end deffn + +@deffn procedure write-dib (filename string) (dib dib) +Return type: @var{bool}. Calls the @code{WriteDIB} entry of +@file{DIBUTILS.DLL}. Returns @code{#t} if the file @var{filename} could +be opened and written to. After this operation the file contains the +bitmap data in a standard format that is understood by @code{open-dib} +and various system utilities like the bitmap editor. Any problems +resulting in failure are signalled by a @code{#f} return value. +@end deffn + +@deffn procedure bitmap-from-dib (dib dib) (palette hpalette) +Return type: @var{hbitmap}. +Calls the @code{BitmapFromDib} entry of @file{DIBUTILS.DLL}. The returned +value is a device dependent bitmap. The colours from the DIB are +matched against colors in @var{palette}. +@end deffn + +@deffn procedure dib-from-bitmap (bitmap hbitmap) (style dword) (bits word) (palette hpalette) +Return type: @var{dib}. +Returns a DIB containing the same image as the device dependent bitmap +@var{bitmap}. +@var{Style} determines the kind of DIB, e.g.@: compression style. +Calls the @code{DibFromBitmap} entry of @file{DIBUTILS.DLL}. +@end deffn + +@deffn procedure dib-blt (dest hdc) (x int) (y int) (w int) (h int) (src dib) (src-x int) (src-y int) (raster-op long) +Return type: @var{bool}. Calls the @code{DibBlt} entry of +@file{DIBUTILS.DLL}. Similar to the Win32 API @code{BitBlt} call, but +draws a DIB rather than a piece of another device context. Draws the +@var{dib} on device context @var{hdc} at position (@var{x},@var{y}). A +rectangle of width @var{w} and height @var{h} is copied from position +(@var{src-x},@var{src-y}) of @var{dib}. +@var{Raster-op} is supposed to allow the source and destination to be +combined but I don't think I got this right so stick to @code{SRCCOPY}. +@end deffn + +@deffn procedure %delete-dib (dib-handle handle) +Return type: @var{bool}. +Calls the @code{DeleteDIB} entry of @file{DIBUTILS.DLL}. +Note that the parameter is a @var{handle}, and not a @var{dib}. +This allows us to destroy a DIB and reclaim its memory by knowing only +the handle value, and not needing the @code{dib} record. +The importance of this is that if the @code{dib} record is GC-ed then a +GC hook can reclaim the storage knowing only the handle. +@end deffn + +@deffn procedure delete-dib (dib dib) +Return type: @var{bool}. +This procedure calls @code{%delete-dib} to reclaim the storage occupied +by a DIB. +After being deleted, the DIB should not be used. +This procedure allows the programmer to reclaim external heap storage +rather than risking it running out before the next garbage collection. +@end deffn + +@deffn procedure dib-height (dib dib) +Return type: @var{int}. +Calls the @code{DibHeight} expand entry of @file{DIBUTILS.DLL}, which returns +the height of the bitmap in pixels. +@end deffn + +@deffn procedure dib-width (dib dib) +Return type: @var{int}. +Calls the @code{DibWidth} entry of @file{DIBUTILS.DLL}, which returns +the width of the bitmap in pixels. +@end deffn + +@deffn procedure copy-bitmap (bm hbitmap) +Return type: @var{hbitmap}. +Calls the @code{CopyBitmap} of @file{DIBUTILS.DLL}, which creates a new +bitmap with the same size and contents as the original. +@end deffn + +@deffn procedure create-dib (width int) (height int) (style int) (depth int) (palette hpalette) +Return type: @var{dib}. +Calls the @code{CreateDIB} entry of @file{DIBUTILS.DLL}. +Creates a DIB of @var{width} by @var{height} pixels and @var{depth} bits +of colour information. +The @var{style} parameter determines how the bitmap is stored. +I have only ever used @code{BI_RGB}. +If @var{depth}<=8 then the @var{palette} determines the DIB's colour table. +@end deffn + +@deffn procedure crop-bitmap (bm hbitmap) (left int) (top int) (right int) (bottom int) +Return type: @var{hbitmap}. +Calls the @code{CropBitmap} entry of @file{DIBUTILS.DLL}. +Returns a new bitmap containing the image from a region of the original. +@end deffn + +@deffn procedure dib-set-pixels-unaligned dib (pixels string) +Return type: @var{bool}. +Calls the @code{DIBSetPixelsUnaligned} entry of@* @file{DIBUTILS.DLL}. Stuffs +bytes from @var{pixels} into the bitmap. There are no alignment +constraints on @var{pixels} (the usual way of doing this is to use the +@code{SetDIBits} function which requires that every scan line of the +bitmap is 32-bit word aligned, even if the scan lines are not a multiple +of 4 bytes long). doing this +@end deffn + +@node Other parts of the DIB Utilities implementation, , DIB procedures, Device Independent Bitmap Utilities +@subsection Other parts of the DIB Utilities implementation + + +The @file{DIBUTILS.DLL} library is an ordinary DLL. See the standard +Microsoft Windows documentation on how to create DLLs. Look at the code +in the @file{WIN32/DIBUTILS} directory of the Scheme source. + +Please note: +@itemize @bullet +@item +@cindex DLL, exports +For the foreign function interface to find the procedures they must be +declared as exports in the @file{.DEF} definition file. + +@item +To load the @file{.DLL} file use the @code{find-module} Scheme function. +Look at @file{WIN32/DIB.SCM} to see how this is done. + +@item +The current system works with C procedures with the @code{__stdcall} and +@code{__cdecl} calling conventions but @emph{not} the @code{__fastcall} +calling convention. +@end itemize