SchemeDoc.tioga
Michael Plass, December 27, 1990 11:15 am PST
Last changed by Pavel on August 14, 1990 12:47 pm PDT
Cedar Scheme
Cedar Scheme
An implementation of a descendant of Lisp
Pavel Curtis and Michael F. Plass
© Copyright 1987, 1988, 1989, 1990 Xerox Corporation. All rights reserved.
Abstract: Scheme is an applicative order, statically scoped and properly tail-recursive descendant of the Lisp programming language. This package provides a Scheme interpreter in Cedar that supports all of the essential syntax and semantics described in the Revised3 Report on Scheme (except for bugs, of course). N.B. This is Cedar Scheme, an interpreted implementation of Scheme. This is not SchemeXerox, the PCR-based native-code implementation.
Created by: Michael F. Plass
Maintained by: Michael Plass:PARC:Xerox
Keywords: Interpreter, Language, LISP, programming tools, Scheme
XEROX Xerox Corporation
Palo Alto Research Center
3333 Coyote Hill Road
Palo Alto, California 94304
Introduction
As a reference for Scheme, refer to the "Revised3 Report on the Algorithmic Language Scheme" (Rees, Clinger, Ed. SIGPLAN Notices V21 #12 December 1986). (Michael has an unbound copy you can photocopy; also, Pavel has TEX sources). This Scheme implements all of the essential syntax and semantics described therein, along with most of the optional features and a fair number of local extensions.
Other Scheme packages:
There are many other Cedar Scheme functions that may be loaded beyond those described in this document. Refer to [CedarChest®]<Top>SchemeEnvironment.df for a collection of them.
Interactive help
When you print a procedure value, you will see the formal argument list, and in most cases, a short description as well. If you know what procedure you want, this is usually the easiest way to fifgure out how to call it.
When you don't know the full name of a procedure, but can make a guess about a part of it, then the
apropos procedure is what you want:
apropos
pattern-string [
list-result? ]
[Procedure]
Prints (or if list-result? is #t, returns a list of) all symbols in the environment that have a print-name that matches pattern-string. Example:
% Scheme
(user) (apropos "string*?")
string?
string-ci<?
string-ci>=?
string-ci>?
string-ci<=?
string-ci=?
string<?
string<=?
string>?
string=?
string>=?
string-match?
string-ci-match?
13
(user) string-ci<?
#<primitive string-ci<?: (a b . rest) n-ary case-insensitive string < test>
(user) (define syms (apropos "*" #t)) ; All symbols currently defined!
syms
(user) syms
(* + - / < <= = > >= abs acos and andmap angle . . .) ; [this has been fictionalized]
(user) (length syms)
439
(user) (quit)
%
Unimplemented Optionals
number->string* string->number
transcript-off transcript-on
*Not fully implemented. The given implementation simply prints the number to a string; it doesn't take any radix or other formatting options.
Extensions
Metalingual operations
Primitive syntax
The Cedar Scheme interpreter directly understands only a few, ``primitive'' kinds of Scheme expressions. All others are treated as ``syntactic extensions'' and are expanded into equivalent primitive expressions before evaluation. A special kind of data object, the
primitive syntax marker, is used as the first element of lists representing non-function-application primitive expressions. There is a fixed set of such markers, notated as follows:
#!lambda #!quote #!if
#!define #!begin #!set!
A set of procedures is defined for manipulating such markers:
primitive-syntax-marker?
object
[Procedure]
True is returned if and only if object is a primitive syntax marker.
primitive-syntax-marker->symbol
psm
[Procedure]
The symbol with the same name as the primitive syntax marker psm is returned.
symbol->primitive-syntax-marker
symbol
[Procedure]
The primitive syntax marker with the same name as symbol is returned.
Syntactic extension
expand
form
[Procedure]
A form equivalent in meaning to form is returned with all uses of derived expression types and syntactic extensions expanded into primitive Scheme syntax.
expand-file
file-name-base
[Procedure]
The Scheme code in the file named ``file-name-base.scheme'' is expanded into primitive Scheme syntax and the output is written to the file named ``file-name-base.$cheme''. This procedure is more-or-less obsolete in the presence of the procedure compile-file, described elsewhere in this manual.
expand-once
form
[Procedure]
A form equivalent in meaning to form is returned with one step in the expansion of its outermost expression having been performed.
extend-syntax (
name
keywords
...
)
clauses
...
[Syntax]
See
The Scheme Programming Language, by R. Kent Dybvig, for complete documentation of this facility. The Cedar Scheme implementation provides one extra feature beyond what is described there, though. The symbols
{ and
} can be used in patterns and expansion template to group sub-patterns and sub-templates for the application of ellipses. Thus, with these two definitions:
(extend-syntax (flat-let)
( (flat-let ({ var val } ...) body ...)
(let ((var val) ...) body ...)))
(extend-syntax (doublet)
( (doublet ((var1 var2 val1 val2) ...) body ...)
(let ({(var1 val1) (var2 val2)} ...) body ...)))
the following forms would have the indicated expansions:
(flat-let (a 1 b 2) body)
=> (let ((a 1) (b 2)) body)
(doublet ((a b 1 2) (c d 3 4)) body)
=> (let ((a 1) (b 2) (c 3) (d 4)) body)
Note that the characters "{" and "}" are simply Scheme symbols, so they must be written with spaces separating them from other symbols, as in the flat-let example above.
Note: In contrast to other implementations of Scheme and Lisp, syntactic extensions are not available in the file in which they are defined. To define a syntactic extension that is local to a given file (or other, smaller scope), use let-syntax, below.
let-syntax
bindings
body
...
[Syntax]
Extends the syntax of the language over the scope of the
body forms.
Bindings should be a list of lists, each in one of the following two forms:
(name procedure)
((name keywords ...) clauses ...)
Bindings of the first form establish procedure (as evaluated in the USER environment) as the syntax expander for forms whose car is name. Bindings of the second form similarly establish a syntax expander for name, but are interpreted as though the keywords and clauses had been given in an extend-syntax form.
macro
name
procedure
[Syntax]
Expressions beginning with the symbol name are enabled as a syntactic extension. Whenever an expression of this form is evaluated by the Scheme system, procedure will be applied to the form. Procedure should return a new form to be evaluated in its place. This form of syntactic extension facility is provided for compatibility with other Scheme implementations. Definitions using the extend-syntax facility, described above, are to be preferred in general.
make-syntax
procedure
[Procedure]
Creates and returns a
syntax object, the kind of value used by the interpreter to expand uses of syntactic extensions into more primitive expressions. If an expression of the form
(identifier args ...)
is seen and identifier is bound to a syntax object, then the corresponding procedure will be applied to the given args. It should return a new form to be evaluated in place of the one above.
The procedure make-syntax is not usually called directly by Scheme programmers. It is more usual for the macro or extend-syntax expressions to be used for the definition of new syntactic extensions.
syntax?
object
[Procedure]
Returns true if and only if object is a syntax object.
syntax-expander
syntax
[Procedure]
Extracts and returns the prcoedure passed to make-syntax when syntax was created.
Operations on Scheme expressions
kwote
value
[Procedure]
Returns a Scheme expression that evaluates to value. The expression will be simply ``value'' if it is self-evaluating and ``(quote value)'' otherwise.
Operations on procedures
procedure-environment
procedure
[Procedure]
Returns the lexical environment in which procedure is closed. This returns #f for primitive procedures.
procedure-name
procedure
[Procedure]
Returns, as a symbol, the name of the given procedure if it is a primitive, or #f if not.
Compilation into Cedar
compile-file
file-name-base
[Procedure]
The Scheme code in the file named ``file-name-base.scheme'' is compiled and the output is written to the file named ``file-name-base.$cheme'', along with other files needed to support the compiled code.
Compilation into bytecodes
hobbit-file
file-name-base
[Procedure]
The Scheme code in the file named ``file-name-base.scheme'' is compiled into bytecodes and the output is written to the file named ``file-name-base.$cheme''.
I/O facilities
String input/output ports
get-output-string
port
[Procedure]
Port should have been created by a call to open-output-string (see below). This returns all of the characters remembered by the port in the form of a string. It also causes the port to forget those characters.
open-input-string
string
[Procedure]
Returns a new input port ranging over the characters in string. Changes made to string after the port is created will not be seen by readers of the port.
open-output-string [Procedure]
Returns a new output port that remembers all characters written to it. The procedure get-output-string (see above) can be used to retrieve those characters as a string.
Customizing the printer
register-print-proc
proc
value
[Procedure]
Whenever a value of the same type as value is to be printed, proc will be called to do the printing. proc should accept three arguments: the port on which to print, the value to be printed, and a boolean which is true is the value is being printed by display and false if by write. The returned value is ignored.
value should not be a ``native'' Scheme value, such as a number, boolean, list, record, etc. There is another mechanism for specifying print procs for records; see make-record-type. The printed appearance of other native Scheme values cannot be customized.
Generic port operations
binary-write
object
[
port]
[Procedure]
Like write, but writes object in a binary representation that is understood by read, and which is not very human-readable or portable, but is fast to parse.
change-looks
string
[
port]
[Procedure]
The current Tioga ``looks'' of the given port are changed according to the characters in string. Lowercase letters turn on the associated looks and uppercase letters turn them off. This procedure is currently a no-op in PCedar.
format [
port]
string
args
...
[Procedure]
Uses string and args as specifications for formatted output to port. If port is #f or not given, a string containing the formatted output is returned; otherwise, the result is unspecified. If port is #t, the value of (current-output-port) is used instead.
string may contain normal characters, which are simply output unchanged, and
format directives, marked by a tilde (``
~'') followed by one of the following characters (case is not significant):
S The next argument in args is output as if by the write procedure. ``S'' is used for compatibility with Common Lisp, where it stands for ``s-expression''.
A The next argument in args is output as if by the display procedure. ``A'' is used for compatibility with Common Lisp, where it stands for ``ASCII''.
C The next argument in args, which should be a character, is output as if by the write-char procedure.
L The next argument in args, which should be a string, is interpreted as a set of changes to be made to the current Tioga ``looks'' of the port, as if by the change-looks procedure, described above.
% A newline is output, as if by the newline procedure.
~ A tilde is output.
newline
The newline character and all following whitespace characters in string are discarded. This is useful for situations in which a long format string appears in a program and needs to be broken (and then indented properly) without causing such formatting in the output.
unread-char
character [
port]
[Procedure]
Undoes the effect of the most recent call to read-char on port. Character should be the character most recently read from port. Port defaults to the result of (current-input-port).
Streams
These are as used in Ableson & Sussman
2
cons-stream
hd
tl
[Syntax]
Syntax for (cons hd (delay tl))
head
stream
[Procedure]
Gets the first element of a stream
tail
stream
[Procedure]
Returns the tail of a stream, which is also a stream
empty-stream?
stream
[Procedure]
Tests for the empty stream
the-empty-stream [Constant]
The empty stream
New data structures
Record types
make-record-type
type-id
field-names
[
parent
[
print-proc]]
[Procedure]
Creates a new data type and returns a ``descriptor'' object for the new type.
type-id should be a symbol; it has no semantic interest and is used only by the default printing procedure.
field-names should be a proper list of symbols. Every value of the new type is a ``record'', a tuple of values, one for each name in field-names. Each field can be set and/or referenced independently.
parent, if provided, should be either #f or a descriptor returned from a previous call to make-record-type. If it is a descriptor, then the new type is a ``subtype'' of that earlier type; that is, every value of the new type is also a member of the earlier type. Such a value has all of the fields of values of the earlier type in addition to the ones named in field-names.
print-proc is a procedure of three arguments: a port on which to print, a value to be printed, and a boolean which is true if and only if the value is being printed by display as opposed to write. print-proc will be called to print any value of the new type. If print-proc is not supplied, then the print-proc associated with parent will be used instead. If parent is #f, then the default printing procedure will be used.
record-constructor
descriptor
[Procedure]
Returns a procedure for constructing values of the type described by descriptor, which should have been returned from a call to make-record-type. The value-construction procedure takes one argument for each field, in the order given by field-names in the call to make-record-type. If parent was supplied and not #f in that call, then the fields for the parent type should be given before those of the child type.
record-predicate
descriptor
[Procedure]
Returns a procedure for deciding if a given value is of the type described by descriptor. The procedure takes one argument and returns #t if the argument has the appropriate type and #f otherwise.
record-accessor
descriptor
name
[Procedure]
Returns a procedure for reading one of the fields in values of the type described by descriptor. name should be one of the symbols in the list of field-names given when descriptor was created. The returned procedure takes one argument, a record value of the appropriate type, and returns the value of the named field in that record.
record-updater
descriptor
name
[Procedure]
Returns a procedure for modifying one of the fields in values of the type described by descriptor. name should be one of the symbols in the list of field-names given when descriptor was created. The returned procedure takes two arguments: a record value of the appropriate type and a new value for the named field in that record. The returned value is unspecified.
Examples
(define yow-descriptor (make-record-type 'yow '(a b c)))
(define make-yow (record-constructor yow-descriptor))
(define yow-b (record-accessor yow-descriptor 'b))
(define set-yow-b! (record-updater yow-descriptor 'b))
(define one-yow (make-yow 1 2 3))
one-yow
=> #<yow a: 1 b: 2 c: 3>
(yow-b one-yow)
=> 2
(set-yow-b! one-yow 17)
one-yow
=> #<yow a: 1 b: 17 c: 3>
(yow-b one-yow)
=> 17
(define pow-descriptor (make-record-type 'pow '(d e) yow-descriptor))
(define make-pow (record-constructor pow-descriptor))
(define yow? (record-predicate yow-descriptor))
(define pow? (record-predicate pow-descriptor))
(define one-pow (make-pow 'one 'two 'three 'four 'five))
one-pow
=> #<pow a: one b: two c: three d: four e: five>
(yow? one-pow)
=> #t
(pow? one-pow)
=> #t
(pow? one-yow)
=> #f
(define (print-meow port meow display?)
(format port "#<A cat named ~A>" (meow-name meow)))
(define meow-descriptor (make-record-type 'meow '(name) #f print-meow))
(define make-meow (record-constructor meow-descriptor))
(define meow-name (record-accessor meow-descriptor 'name))
(make-meow "Snookums")
=> #<A cat named Snookums>
Defining new types of objects
The define-structure facility is not supported currently. Use the make-record-type facility described above.
define-structure (
name
id
1,1
...
id
1,
k
) [Syntax]
[
((
id
2,1
expr
1
) ...
(
id
2,
n
expr
n
))]
Defines a new type of data object and several kinds of procedures for manipulating such objects. The symbol
name is the conceptual name of the type and appears in the names of the procedures that are defined. The identifiers are the names of the ``fields'' or ``slots'' in each
name object. The following procedures are defined:
make-
name
val
1
...
val
k
Create and return a new object of type name. The id1,i fields in the object will be initialized to the values of the corresponding arguments. The id2,i fields are initialized one-by-one to the values of the expri expressions. Each of these expressions is in the scope of all variables with the names of all earlier-appearing fields and may use the values of those fields.
Example:
(define-structure (foo vec)
((len (vector-length vec))
(big? (> len 1000))))
The expression (make-foo '#(1 2 3)) will create a foo object with the len field equal to 3 and the big? field equal to #f.
name
?
object
Returns true if and only if object is a value of type name.
name-
id
i,
j
object
Object should be a value of type name. The value of the idi,j field of that object is returned. There are (k+n) procedures of this kind defined, one for each field in a name object.
set-
name-
id
i,
j
!
object
value
Object should be a value of type name. The value of the idi,j field of that object is set to value. There are (k+n) procedures of this kind defined, one for each field in a name object.
Hash tables
eq-hash
object
[Procedure]
Returns an integer with the property that
(eq? a b)
implies
(= (eq-hash a) (eq-hash b))
The implementation attempts to make the converse true as well in as many cases as possible.
eqv-hash
object
[Procedure]
Returns an integer with the property that
(eqv? a b)
implies
(= (eqv-hash a) (eqv-hash b))
The implementation attempts to make the converse true as well in as many cases as possible.
make-table [
initial-size
{
comparison-fn
hash-fn}]
[Procedure]
Creates and returns a hash table with room initially (that is, before rehashing) for initial-size entries, using the given comparison-fn and hash-fn. Initial-size defaults to something reasonably small. Comparison-fn and hash-fn default to eqv? and eqv-hash, respectively.
table?
object
[Procedure]
Returns true if and only if object is a hash table.
table-ref
table
key
[Procedure]
Returns the value stored under key in table, returning #f if key has no entry in table.
table-remove!
table
key
[Procedure]
Remove the entry for key from table, if such an entry exists. Return a boolean indicating whether or not the entry existed.
table-set!
table
key
value
[Procedure]
Either change the current entry for key in table to refer to value, if such an entry exists, or add an entry mapping key to value.
table-size
table
[Procedure]
Returns the number of entries currently in table.
table-walk
fn
table
[Procedure]
Applies fn to the key and value for each entry in table. No changes should be made to the table during the walk.
Syntax
Lexical conventions
Cedar Scheme uses the syntax for the tokens given in the Revised3 Report on the Algorithmic Language Scheme, with a few minor extensions.
The set of ``character names'', aside from the standard ones of the form #\c, are as follows (case is insignificant in all cases):
#\onnn
The character whose ASCII code is, in octal, nnn. Note that this does not constitute a guarantee that (= (char->integer #\onnn) #onnn), though that is, in fact, the case at the moment.
#\OpenPar
#\OpenParen
The opening parenthesis character.
#\ClosePar
#\CloseParen
The closing parenthesis character.
#\Return
The ASCII carriage-return character. Identical to #\015.
#\LineFeed
The ASCII line-feed character. Identical to #\012.
#\Newline
The system-dependent end-of-line character.
#\Tab
The ASCII horizontal tab character. Identical to #\010.
#\Space
The ASCII space character. Identical to #\040.
#\FormFeed
The ASCII form-feed (new page) character. Identical to #\014.
The syntax of symbols is somewhat enhanced. The characters ``{'' and ``}'' are added to the set named <special initial> in the report and are thus legal constituents of the names of symbols. Also, any token made up of a string of more than one period (e.g., the token ``...'') is a valid symbol. Finally, the syntax #"characters" is also a legal syntax for symbols; the name of the symbol is precisely the set of characters between the quotes. This allows symbols with essentially arbitrary names to be input through the read procedure. Normal, unquoted symbols have the uppercase letters in their names mapped automatically to lowercase by the reader. Thus, the tokens foo and #"foo" are read identically.
See also the discussion of identifiers containing colons in the section on environments in SchemeObsoleteDoc.tioga.
New syntactic constructs
unless
expression
body ...
[Syntax]
The expression is evaluated. If a false value results, the body expressions are evaluated in order and the value of the unless expression is that of the last body expression. If expression evaluated to a true value, the body expressions are not evaluated and the value of the unless expression is unspecified.
when
expression
body ...
[Syntax]
The expression is evaluated. If a true value results, the body expressions are evaluated in order and the value of the when expression is that of the last body expression. If expression evaluated to a false value, the body expressions are not evaluated and the value of the when expression is unspecified.
export
(name ...)
defn ...
[Syntax]
This is used to provide a simple way of hiding implementation procedures. The defn ... must consist of a valid lambda body (normally just a sequence of internal definitions) that provides internal definitions of name ... ; the expansion will do top-level defines of name ... , and copy the values from the internal definitions.
export should be used only at top level.
Unless all definitions in a file are to be publicly accessible, export should normally be used to hide the private ones.
Because of the restricted nature of internal definitions, don't try to use definition-generating syntax like define-structure and extend-syntax inside of an export body.
Portable Tendrils into Cedar
The facilities described in this section provide access to a few Cedar system facilities.
Commander
The following procedure provides a modicum of access to the facilities of the Commander, but this is plenty of rope to hang yourself with:
do-command
string [
output-port]
[Procedure]
Assuming the process has a Cedar Commander, this procedure does the command line contained in string. If output-port is supplied, the command's standard output goes there instead of to the typescript.
install
component-name-string [
env]
[Procedure]
Looks for a corresponding .require file, and uses it to install the component. This is quick if the component has been previously installed. Initialization procedures are then called to register things in env [which defaults to the USER environment].
reinstall
component-name [
env]
[Procedure]
Like install, but forgets the installation name first.
installation-names [Procedure]
Returns a list of names of components that have been installed.
Viewers
eval-selection [Procedure]
Evaluate the contents of the Tioga selection. This is most useful when attached to a button in the Commander.
get-selection-contents [Procedure]
Returns the contents of the Tioga selection, as a string.
Timing/garbage collection
Timer objects allow programs to gather some statistics about elapsed time:
make-timer [Procedure]
Create a timer object.
timer-ref
timer
[Procedure]
Get the number of microseconds since the timer creation or start.
timer?
object
[Procedure]
Test for a Timer object
timer-start!
timer
[Procedure]
(Re)start a Timer
set-priority
priority-symbol
[Procedure]
Sets new process priority level, returns old priority level (often useful for getting more precise timings; refer to CedarProcess.mesa for the meaning of the priority levels).
words-allocated [Procedure]
Returns the total number of words of collectable memory that have been allocated.
gc [
trace-and-sweep?]
[Procedure]
Calls the garbage collector explicitly.
Information about the machine
this-machine-name [
namespace]
[Procedure]
Returns a string; namespace is 'arpa, 'xns, 'pup, ...
this-machine-address [
namespace]
[Procedure]
Returns a string; namespace is 'arpa, 'xns, 'pup, ...
this-machine-id [Procedure]
Returns a string like "1-435-140-188".
this-machine-type [Procedure]
Returns 'princops, 'sun3, 'sun4, ...
Miscellaneous
Dynamic binding
make-dynamic
obj
[Procedure]
Create and return a new ``dynamic variable'' whose initial global value is obj.
dynamic?
obj
[Procedure]
Returns true if and only if obj is a dynamic variable.
dynamic-ref
dvar
[Procedure]
Return the value of the given dynamic variable in the current dynamic environment.
dynamic-set!
dvar
obj
[Procedure]
Change the value of the given dynamic variable to obj in the current dynamic environment. The returned value is unspecified.
call-with-dynamic-binding
dvar
obj
thunk
[Procedure]
Invoke and return the value of thunk in a new, nested dynamic environment in which dvar has been bound to a new location whose initial contents are obj. This dynamic environment has precisely the same extent as the invocation of thunk and is thus captured by continuations created within that invocation and re-established by those continuations when they are invoked.
dynamic-bind ((
var-expr
val-expr
) ...
)
body
...
[Syntax]
Evaluates the var-exprs and val-exprs in an unspecified order; the var-exprs should yield dynamic variables. Returns the result of evaluating the body in a new, nested dynamic environment in which the given dynamic variables have new bindings, initialized to the given values. This dynamic environment has precisely the same extent as the evaluation of the body and is thus captured by continuations created within the body and re-established by those continuations on invocation.
fluid-let ((
id
expression
) ...
)
body
...
[Syntax]
This is like let except that the id's are not bound to the values of the expression's, they are set. Thus, the id's must already be bound by some other means. The new values for the id's remain in effect as long as control is in the body forms. When the fluid-let is exited, the id's are restored to the values they had upon entry. If control re-enters the fluid-let (by invoking a continuation made inside the body forms), the id's will re-acquire the values they had when the fluid-let was last exited.
In essence, fluid-let gives you a facility equivalent to dynamic binding (implemented by shallow binding). For more information and examples, see the description of the equivalent facility in Chez Scheme, found in Kent Dybvig's book on Scheme.
Control constructs
dynamic-wind
prelude
body
postlude
[Procedure]
Prelude,
body and
postlude should all be thunks (procedures of zero arguments).
Dynamic-wind behaves as if it were defined as follows:
(prelude)
(let ((value (body)))
(postlude)
value)
except that the postlude thunk is invoked even if control leaves the body by invocation of a continuation created outside. Furthermore, if control re-enters the body (by invocation of a continuation created inside), the prelude code will be re-invoked.
This is most frequently used in code that wishes some resource to be held whenever control is in the body; the prelude acquires the resource and the postlude releases it. For more information and examples, see the description of the equivalent facility in Chez Scheme, found in Kent Dybvig's book on Scheme.
Controlling the read-eval-print loop
set-rep-environment!
env
[Procedure]
Change the environment used by the read-eval-print loop to env. It will be reset to the USER environment if you terminate the loop and reinvoke the Scheme command.
quit [Procedure]
Terminates the real-eval-print loop immediately.
Operations on lists
any
pred
lists
...
[Procedure]
Returns the first true value of pred applied to successive elements of the given lists, or #f if pred never returns a true value.
every
pred
lists
...
[Procedure]
Return the last value of pred applied to successive elements of the given lists if none of the applications yielded false, and #f otherwise.
list*
args
...
[Procedure]
Like list, but uses the last argument, rather than (), as the tail of the resulting list.
pairwise
pred
args
...
[Procedure]
Applies the binary predicate pred to each consecutive pair of elements in args, returning #f if pred ever returns a false value and #t otherwise.
proper-list?
object
[Procedure]
Returns true if and only if object is a ()-terminated list of length greater than zero.
remove-if
predicate
list
[Procedure]
Return a list of the elements of list such that predicate is false of them.
remove-if-not
predicate
list
[Procedure]
Return a list of the elements of list such that predicate is true of them.
reverse!
list
[Procedure]
Destructively reverse and return list.
sort
list
pred
[
key-fn]
[Procedure]
Makes a sorted version of list according to the binary order predicate pred, using key-fn to extract the keys form the elements. Key-fn defaults to the identity function. The sort is not stable.
Example:
(user) (sort '(("f" x) ("o" y) ("b" z)) string<? car)
(("b" z) ("f" x) ("o" y))
Operations on symbols
gensym [
string]
[Procedure]
Returns a guaranteed-new symbol. If string is provided, it will be a part of the name of the new symbol.
Operations on numbers
random
n
[Procedure]
Returns a random integer in the range [0..n).
Operations on functions (combinators)
compose
fn
...
[Procedure]
Returns the function that is the functional composition of the given ones. All but the last argument should accept a single argument and all but the first should return a single value.
identity
x
[Procedure]
Returns x.
Pattern-matching
syntax-match?
keywords
pattern
s-expression
[Procedure]
This is the pattern-matcher used by expansion functions defined with extend-syntax, described above. Keywords is a list of symbols to be treated as constants in the given pattern. Pattern is a pattern in the style of extend-syntax. Syntax-match? returns true if and only if the given s-expression matches the pattern.
string-match?
pattern-string
target
[Procedure]
Returns a boolean indicating whether or not the pattern string matches the target. The pattern string may use "*" as a wildcard character. The target may be either a string or a symbol.
string-ci-match?
pattern-string
target
[Procedure]
Like string-match?, but case-insensitive. The target may be either a string or a symbol.
Signalling errors
error
name
culprit
message
[Procedure]
An error is signalled and the debugger is entered. Name should be a symbol naming the function signalling the error, message should be a string describing the problem, and culprit should be a Scheme object is some way ``responsible'' for the error.
Tracing procedures
trace
name
...
[Syntax]
Enables tracing on the procedures with the given names in the current environment. Returns a list of all currently-traced procedures.
untrace
name
...
[Syntax]
Restores the named procedures to their original, untraced state. If no names are given, untrace restores all currently-traced procedures to their original, untraced state.
It is an error to
1) Use trace or untrace anywhere other than at top-level in the read-eval-print loop.
2) Use trace on an unbound name, or a name bound to a non-procedure or an already traced procedure.
3) Redefine a traced procedure without first untrace-ing it.
Environments in Cedar Scheme
If Scheme is to grow and be used by more people, one of the problems it must solve is the robust isolation of different pieces of the system and user code from each other. Refer to SchemeObsoleteDoc.tioga for details of an attempt in this direction that did not work out very well. Be warned that names containing ":" are treated specially, and so should be avoided unless you know what you are doing.
Reserved variable names
The following top-level variables are used by the system; don't use, set or redefine them unless you know what you are doing. Also, top-level procedures that are vital to the system operation have names starting with "%"; don't redefine those, either. In addition, the Tidbit compiler litters the name space with its fluidly-bound variables; it's best to leave those alone, too.
& See section on Read-Eval-Print loop.
*load-note-taker* See section on the load procedure.
*load-notes* See section on the load procedure.
*read-eval-print-note-taker* See section on Read-Eval-Print loop.
*read-eval-print-prompt* See section on Read-Eval-Print loop.
*system-compiler* The compiler that the read-eval-print loop uses.
*system-error-handler* The system error handler; normally the debugger.
*system-syntax-expander* The syntax-expander that the read-eval-print loop uses.
Compilation
Currently there are two compilers that are part of Cedar Scheme. The Hobbit compiler (a halfling) is small and fast, and creates byte-coded procedures, which use a simple interpreter for evaluation. Hobbit is used by the read-eval-print loop, and for loading source files. The other compiler is called Tidbit, and is what you normally get when you call compile-file. Tidbit compiles Scheme into Cedar, and then invokes the Cedar compiler to produce native code.Compiling Foo.scheme will produce FooSchemeCode.mesa, FooSchemeCode.install and Foo.$cheme, and (if possible) will also compile FooSchemeCode.mesa to produce object code for the system that you are running on. The Foo.$cheme file is just a tiny one that causes the appropriate object code to get run and registered properly with Scheme.
It turns out, in fact, that the Tidbit-compiled code is only marginally faster than the Hobbit-compiled code, and the object code is quite bulky. Because of this, the routine use of Tidbit is not encouraged. Hence Tidbit is unbundled from the base system, so to use it, say
(load "Tidbit")
Details of the load procedure
The load procedure takes a file name string as a argument. By convention, scheme source files have the extension ".scheme", and files created by compile-file have the extension ".$cheme". Passing a name without an extension will cause load to choose either filename.scheme or filename.$cheme, whichever is more recent. If no such file is found in the current working directory and the given name does not contain a directory component, the ".$cheme" will be looked for in /PCedar/FamousFiles and in /CedarCommon/FamousFiles.
The expanded ".$cheme" file loads faster, but after that the performance should be about the same, since load expands the syntax in each expression of a ".scheme" file before it is evaluated. The ".$cheme" files are useful for bootstrapping the syntax expansion procedures.
After each evaluation, the proc bound to *load-note-taker* is applied to two values: a list describing the name and version of the file that was loaded (details are system-dependent) and the value of the load expression (currently a list of the names that were defined). The initial value of *load-note-taker* is a procedure that turns the two arguments into a list and conses it onto the variable *load-notes*; examining this variable will tell you what versions of which files have been loaded.
Read-Eval-Print loop
The Read-Eval-Print loop prompts the with the name of the active environment, reads a form, expands it into primitive syntax, evaluates that, and prints the resulting value. If ABORTED is raised during the evaluation phase, control stays in the read-eval-print loop. Aborting at other times gets you out of the read-eval-print loop.
After each evaluation, the proc bound to *read-eval-print-note-taker* is applied to two or three values: the form, the expanded form, and (if it exists) the value.
The default value of *read-eval-print-note-taker* records the unexpanded form in a list, and stores the value into the variable named &. This is useful for those circumstances where you have computed a huge value, but forgot to provide a surrounding define. The list of unexpanded forms may be obtained by calling read-eval-print-notes with no arguments. You may want to use PPrint on the result.
The value of *read-eval-print-prompt* is used to determine the prompt:
#t Prompt with the name of the top-level environment
#f No prompt
else the value is displayed
Executive Commands
Scheme
This command starts a read-eval-print loop in the Commander. To get out, hit STOP!, or say (quit). To get back in, use the Scheme command again; the Scheme environment is associated with the command tool, so you won't lose much state by aborting a computation.
The first Scheme command in a Commander initializes the Scheme environment with the registered primitives and the definitions in the file "/PCedar/FamousFiles/Scheme.$cheme".
If the remainder of the command line is non-empty, it is taken as the input to a read-eval-print loop, with prompts turned off. Use this to create a vanilla-looking Commander command that is implemented using Scheme.
Example:
% Scheme (expt 2 100) ; a one-liner in the command tool, without prompts
1267650600228229401496703205376
{0.25 seconds, 4700 words}
% Scheme
(user) (+ 1 2) ; comments start with a semicolon and go to the end of the line
3
(user) (define s (list 1 2.0 3 'a '(4 5)))
s
(user) s
(1 2.0 3 a (4 5))
(user) (map number? s)
(#t #t #t #f #f)
(user) (map symbol? s)
(#f #f #f #t #f)
(user) (map pair? s)
(#f #f #f #f #t)
(user) (define add-1 (lambda (x) (+ 1 x)))
add-1
(user) (add-1 3)
4
(user) (add-1 (add-1 'a))
Error in +: domain error
a
(Type '?' for help in using the debugger.)
Debug 1> :q
"Back to top level"
(user) add-1 ; printing a procedure tells you something about it
#<procedure add-1: (x)>
(user) + ; this is a primitive procedure
#<primitive +: ([ a b ] . rest) n-ary arithmetic addition>
(user) (trace +)
(+)
(user) (map add-1 '(1 2.0 3))
Entering: (+ 0 1)
Exiting + => 1
Entering: (+ 1 1)
Exiting + => 2
Entering: (+ 0 1)
Exiting + => 1
Entering: (+ 2 1)
Exiting + => 3
Entering: (+ 3 1)
Exiting + => 4
Entering: (+ 1 1)
Exiting + => 2
Entering: (+ 1 2.0)
Exiting + => 3.0
Entering: (+ 1 3)
Exiting + => 4
(2 3.0 4)
(user) (untrace)
Entering: (+ 0 1)
Exiting + => 1
Entering: (+ 0 1)
Exiting + => 1
Entering: (+ 1 1)
Exiting + => 2
Entering: (+ 0 1)
Exiting + => 1
Entering: (+ 2 1)
Exiting + => 3
Entering: (+ 3 1)
Exiting + => 4
Entering: (+ 0 1)
Exiting + => 1
Entering: (+ 4 1)
Exiting + => 5
Entering: (+ 2 1)
Exiting + => 3
Entering: (+ 0 1)
Exiting + => 1
#!unspecified
(user) (quit)
{00:01:17 seconds, 94956 words, 15 page faults}
%
Bugs, Problems: LifeIsHard
Because the Scheme read-eval-print loop just runs in the Commander, you will find that some Cedar hacks that are meant to talk to the Commander end up talking to Scheme instead. Noteworthy examples are the Commander buttons and things like "NoteNewUser".
SchemeImager
Refer to SchemeImagerDoc for documentation.
InterpressToScheme
Refer to InterpressToScheme.load for documentation.
Defining New Primitives
The easiest way to add new primitives is to use MixMaster. Refer to MixMaster on CedarChest for details.