Go to the first, previous, next, last section, table of contents.


The Language

Standards Compliance

Scm conforms to the [IEEE], IEEE Standard 1178-1990. IEEE Standard for the Scheme Programming Language. and [R4RS], Revised(4) Report on the Algorithmic Language Scheme. All the required features of these specifications are supported. Many of the optional features are supported as well.

Optionals of [R4RS] Supported by SCM

two clause if: (if <test> <consequent>)
See section `Conditionals' in Revised(4) Scheme.
let*
named let
See section `Binding constructs' in Revised(4) Scheme.
do
See section `Iteration' in Revised(4) Scheme.
All varieties of define
See section `Definitions' in Revised(4) Scheme.
list-tail
See section `Pairs and lists' in Revised(4) Scheme.
string-copy
string-fill!
See section `Strings' in Revised(4) Scheme.
make-vector of two arguments
vector-fill!
See section `Vectors' in Revised(4) Scheme.
apply of more than 2 arguments
See section `Control features' in Revised(4) Scheme.
- and / of more than 2 arguments
exp
log
sin
cos
tan
asin
acos
atan
sqrt
expt
make-rectangular
make-polar
real-part
imag-part
magnitude
angle
exact->inexact
inexact->exact
See section `Numerical operations' in Revised(4) Scheme.
delay
force
See section `Control features' in Revised(4) Scheme.
with-input-from-file
with-output-to-file
See section `Ports' in Revised(4) Scheme.
char-ready?
See section `Input' in Revised(4) Scheme.
transcript-on
transcript-off
See section `System interface' in Revised(4) Scheme.

Optionals of [R4RS] not Supported by SCM

numerator
denominator
rationalize
See section `Numerical operations' in Revised(4) Scheme.
[R4RS] appendix Macros
See section `Macros' in Revised(4) Scheme.

[SLIB] Features of SCM and SCMLIT

delay
full-continuation
ieee-p1178
object-hash
rev4-report
source
See SLIB file `Template.scm'.
current-time
See section `Time' in SLIB.
defmacro
See section `Defmacro' in SLIB.
dynamic-wind
See section `Dynamic-Wind' in SLIB.
eval
See section `System' in SLIB.
getenv
system
See section `System Interface' in SLIB.
hash
See section `Hashing' in SLIB.
logical
See section `Bit-Twiddling' in SLIB.
multiarg-apply
See section `Multi-argument Apply' in SLIB.
multiarg/and-
See section `Multi-argument / and -' in SLIB.
rev4-optional-procedures
See section `Rev4 Optional Procedures' in SLIB.
string-port
See section `String Ports' in SLIB.
tmpnam
See section `Input/Output' in SLIB.
transcript
See section `Transcripts' in SLIB.
vicinity
See section `Vicinity' in SLIB.
with-file
See section `With-File' in SLIB.

[SLIB] Features of SCM

array
See section `Arrays' in SLIB.
array-for-each
See section `Array Mapping' in SLIB.
bignum
complex
inexact
rational
real
See section `Require' in SLIB.

Miscellaneous Procedures

Function: try-load filename
If the string filename names an existing file, the try-load procedure reads Scheme source code expressions and definitions from the file and evaluates them sequentially and returns #t. If not, try-load returns #f. The try-load procedure does not affect the values returned by current-input-port and current-output-port.

Variable: *load-pathname*
Is set to the pathname given as argument to load, try-load, and dyn:link (see section Compiling And Linking). *load-pathname* is used to compute the value of section `Vicinity' in SLIB.

Function: line-number
Returns the current line number of the file currently being loaded.

Function: eval obj
Alias for section `System' in SLIB.

Function: eval-string str
Returns the result of reading an expression from str and evaluating it. eval-string does not change *load-pathname* or line-number.

Function: load-string str
Reads and evaluates all the expressions from str. As with load, the value returned is unspecified. eval-string does not change *load-pathname* or line-number.

Function: vector-set-length! object length
Change the length of string, vector, bit-vector, or uniform-array object to length. If this shortens object then the remaining contents are lost. If it enlarges object then the contents of the extended part are undefined but the original part is unchanged. It is an error to change the length of literal datums. The new object is returned.

Function: copy-tree obj
Function: @copy-tree obj
See section `Tree Operations' in SLIB. This extends the SLIB version by also copying vectors. Use @copy-tree if you depend on this feature; copy-tree could get redefined.

Function: acons obj1 obj2 obj3
Returns (cons (cons obj1 obj2) obj3). The expression (set! a-list (acons key datum a-list)) adds a new association to a-list.

Function: terms
This command displays the GNU General Public License.

Function: list-file filename
Displays the text contents of filename.

Procedure: print arg1 ...
Print writes all its arguments, separated by spaces. Print outputs a newline at the end and returns the value of the last argument.

Time

Constant: internal-time-units-per-second

Is the integer number of internal time units in a second.

Function: get-internal-run-time
Returns the integer run time in internal time units from an unspecified starting time. The difference of two calls to get-internal-run-time divided by internal-time-units-per-second will give elapsed run time in seconds.

Function: get-internal-real-time
Returns the integer time in internal time units from an unspecified starting time. The difference of two calls to get-internal-real-time divided by interal-time-units-per-second will give elapsed real time in seconds.

Function: current-time
Returns the time since 00:00:00 GMT, January 1, 1970, measured in seconds. See section `Time' in SLIB. current-time is used in section `Time' in SLIB.

Interrupts

Function: ticks n
Returns the number of ticks remaining till the next tick interrupt. Ticks are an arbitrary unit of evaluation. Ticks can vary greatly in the amount of time they represent.

If n is 0, any ticks request is canceled. Otherwise a ticks-interrupt will be signaled n from the current time. ticks is supported if SCM is compiled with the ticks flag defined.

Callback procedure: ticks-interrupt ...
Establishes a response for tick interrupts. Another tick interrupt will not occur unless ticks is called again. Program execution will resume if the handler returns. This procedure should (abort) or some other action which does not return if it does not want processing to continue.

Function: alarm secs
Returns the number of seconds remaining till the next alarm interrupt. If secs is 0, any alarm request is canceled. Otherwise an alarm-interrupt will be signaled secs from the current time. ALARM is not supported on all systems.

Function: milli-alarm millisecs interval
Function: virtual-alarm millisecs interval
Function: profile-alarm millisecs interval
milli-alarm is similar to alarm, except that the first argument millisecs, and the return value are measured in milliseconds rather than seconds. If the optional argument interval is supplied then alarm interrupts will be scheduled every interval milliseconds until turned off by a call to milli-alarm or alarm.

virtual-alarm and profile-alarm are similar. virtual-alarm decrements process execution time rather than real time, and causes SIGVTALRM to be signaled. profile-alarm decrements both process execution time and system execution time on behalf of the process, and causes SIGPROF to be signaled.

milli-alarm, virtual-alarm, and profile-alarm are supported only on systems providing the setitimer system call.

Callback procedure: user-interrupt ...
Callback procedure: alarm-interrupt ...
Callback procedure: virtual-alarm-interrupt ...
Callback procedure: profile-alarm-interrupt ...
Establishes a response for SIGINT (control-C interrupt) and SIGALRM, SIGVTALRM, and SIGPROF interrupts. Program execution will resume if the handler returns. This procedure should (abort) or some other action which does not return if it does not want processing to continue after it returns.

Interrupt handlers are disabled during execution system and ed procedures.

To unestablish a response for an interrupt set the handler symbol to #f. For instance, (set! user-interrupt #f).

Callback procedure: out-of-storage ...
Callback procedure: could-not-open ...
Callback procedure: end-of-program ...
Callback procedure: hang-up ...
Callback procedure: arithmetic-error ...
Establishes a response for storage allocation error, file opening error, end of program, SIGHUP (hang up interrupt) and arithmetic errors respectively. This procedure should (abort) or some other action which does not return if it does not want the default error message to also be displayed. If no procedure is defined for hang-up then end-of-program (if defined) will be called.

To unestablish a response for an error set the handler symbol to #f. For instance, (set! could-not-open #f).

Process Synchronization

Function: make-arbiter name

Returns an object of type arbiter and name name. Its state is initially unlocked.

Function: try-arbiter arbiter

Returns #t and locks arbiter if arbiter was unlocked. Otherwise, returns #f.

Function: release-arbiter arbiter

Returns #t and unlocks arbiter if arbiter was locked. Otherwise, returns #f.

Files and Ports

These procedures generalize and extend the standard capabilities in section `Ports' in Revised(4) Scheme.

Function: open-file string modes
Function: try-open-file string modes
Returns a port capable of receiving or delivering characters as specified by the modes string. If a file cannot be opened #f is returned.

Internal functions opening files callback to the SCM function open-file. You can extend open-file by redefining it. try-open-file is the primitive procedure; Do not redefine try-open-file!

Constant: open_read
Constant: open_write
Constant: open_both
Contain modes strings specifying that a file is to be opened for reading, writing, and both reading and writing respectively.

Function: _ionbf modestr
Returns a version of modestr which when open-file is called with it as the second argument will return an unbuffered port. A non-file input-port must be unbuffered in order for char-ready? to work correctly on it. The initial value of (current-input-port) is unbuffered if the platform supports it.

Function: close-port port
Closes port. The same as close-input-port and close-output-port.

Function: open-io-file filename
Function: close-io-port port
These functions are analogous to the standard scheme file functions. The ports are open to filename in read/write mode. Both input and output functions can be used with io-ports. An end of file must be read or a file-set-position done on the port between a read operation and a write operation or vice-versa.

Function: current-error-port
Returns the current port to which diagnostic output is directed.

Function: with-error-to-file string thunk
thunk must be a procedure of no arguments, and string must be a string naming a file. The file is opened for output, an output port connected to it is made the default value returned by current-error-port, and the thunk is called with no arguments. When the thunk returns, the port is closed and the previous default is restored. With-error-to-file returns the value yielded by thunk.

Function: with-input-from-port port thunk
Function: with-output-to-port port thunk
Function: with-error-to-port port thunk
These routines differ from with-input-from-file, with-output-to-file, and with-error-to-file in that the first argument is a port, rather than a string naming a file.

procedure: char-ready?
procedure: char-ready? port

Returns #t if a character is ready on the input port and returns #f otherwise. If char-ready? returns #t then the next read-char operation on the given port is guaranteed not to hang. If the port is at end of file then char-ready? returns #t. Port may be omitted, in which case it defaults to the value returned by current-input-port.

Rationale: 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 ensure that characters whose existence has been asserted by char-ready? cannot be rubbed out. If char-ready? were to return #f at end of file, a port at end of file would be indistinguishable from an interactive port that has no ready characters.

Function: isatty? port
Returns #t if port is input or output to a serial non-file device.

Soft Ports

A soft-port is a port based on a vector of procedures capable of accepting or delivering characters. It allows emulation of I/O ports.

Function: make-soft-port vector modes
Returns a port capable of receiving or delivering characters as specified by the modes string (see section Files and Ports). vector must be a vector of length 6. Its components are as follows:

  1. procedure accepting one character for output
  2. procedure accepting a string for output
  3. thunk for flushing output
  4. thunk for getting one character
  5. thunk for closing port (not by garbage collection)

For an output-only port only elements 0, 1, 2, and 4 need be procedures. For an input-only port only elements 3 and 4 need be procedures. Thunks 2 and 4 can instead be #f if there is no useful operation for them to perform.

If thunk 3 returns #f or an eof-object (see section `Input' in Revised(4) Scheme) it indicates that the port has reached end-of-file. For example:

(define stdout (current-output-port))
(define p (make-soft-port
           (vector
            (lambda (c) (write c stdout))
            (lambda (s) (display s stdout))
            (lambda () (display "." stdout))
            (lambda () (char-upcase (read-char)))
            (lambda () (display "@" stdout)))
           "rw"))

(write p p) => #<input-output-soft#\space45d10#\>

Syntax Extensions

procedure: procedure-documentation proc
Returns the documentation string of proc if it exists, or #f if not.

If the body of a lambda (or the definition of a procedure) has more than one expression, and the first expression (preceeding any internal definitions) is a string, then that string is the documentation string of that procedure.

(procedure-documentation (lambda (x) "Identity" x)) => "Identity"
(define (square x)
    "Return the square of X."
    (* x x))
=> #<unspecified>
(procedure-documentation square) => "Return the square of X."

Read syntax: #. expression
Is read as the object resulting from the evaluation of expression. This substitution occurs even inside quoted structure.

In order to allow compiled code to work with #. it is good practice to define those symbols used inside of expression with #.(define ...). For example:

#.(define foo 9)                        => #<unspecified>
'(#.foo #.(+ foo foo))                  => (9 18)

Read syntax: #+ feature form
If feature is provided? (by *features*) then form is read as a scheme expression. If not, then form is treated as whitespace.

Feature is a boolean expression composed of symbols and and, or, and not of boolean expressions.

For more information on provided? and *features*, See section `Require' in SLIB.

Read syntax: #- feature form
is equivalent to #+(not feature) expression.

Read syntax: #' form
is equivalent to form (for compatibility with common-lisp).

Read syntax: #| any thing |#
Is a balanced comment. Everything up to the matching |# is ignored by the read. Nested #|...|# can occur inside any thing.

A similar read syntax #! (exclamation rather than vertical bar) is supported for Posix shell-scripts (see section Shell Scripts).

Read syntax: #\token
If token is a sequence of two or more digits, then this syntax is equivalent to #.(integer->char (string->number token 8)).

If token is C-, c-, or ^ followed by a character, then this syntax is read as a control character. If token is M- or m- followed by a character, then a meta character is read. c- and m- prefixes may be combined.

Special Form: defined? symbol
Equivalent to #t if symbol is a syntactic keyword (such as if) or a symbol with a value in the top level environment (see section `Variables and regions' in Revised(4) Scheme). Otherwise equivalent to #f.

Special Form: defvar identifier initial-value
If identifier is unbound in the top level environment, then identifier is defined to the result of evaluating the form initial-value as if the defvar form were instead the form (define identifier initial-value) . If identifier already has a value, then initial-value is not evaluated and identifier's value is not changed. defconst is valid only when used at top-level.

Special Form: defconst identifier value
If identifier is unbound in the top level environment, then identifier is defined to the result of evaluating the form value as if the defconst form were instead the form (define identifier value) . If identifier already has a value, then value is not evaluated, identifier's value is not changed, and an error is signaled. defconst is valid only when used at top-level.

Special Form: casev key clause1 clause2 ...
casev is an extension of standard Scheme case: Each clause of a casev statement must have as first element a list containing elements which are:

A casev statement is equivalent to a case statement in which these symbolic constants preceded by commas have been replaced by the values of the constants, and all symbolic constants preceded by comma-at-signs have been replaced by the elements of the list values of the constants. This use of comma, (or, equivalently, unquote) is similar to that of quasiquote except that the unquoted expressions must be symbolic constants.

Symbolic constants are defined using defconst, their values are substituted in the head of each casev clause during macro expansion. defconst constants should be defined before use. casev can be substituted for any correct use of case.

(defconst unit '1)
(defconst semivowels '(w y))
(casev (* 2 3)
  ((2 3 5 7) 'prime)
  ((,unit 4 6 8 9) 'composite))        ==>  composite
(casev (car '(c d))
  ((a) 'a)
  ((b) 'b))                            ==>  unspecified
(casev (car '(c d))
  ((a e i o u) 'vowel)
  ((,@semivowels) 'semivowel)
  (else 'consonant))                   ==>  consonant

SCM also supports the following constructs from Common Lisp: defmacro, macroexpand, macroexpand-1, and gentemp. See section `Defmacro' in SLIB.

Low Level Syntactic Hooks

Callback procedure: read:sharp c port
If a # followed by a character (for a non-standard syntax) is encountered by read, read will call the value of the symbol read:sharp with arguments the character and the port being read from. The value returned by this function will be the value of read for this expression unless the function returns #<unspecified> in which case the expression will be treated as whitespace. #<unspecified> is the value returned by the expression (if #f #f).

Callback procedure: read:sharp-char token
If the sequence #\ followed by a non-standard character name is encountered by read, read will call the value of the symbol read:sharp-char with the token (a string of length at least two) as argument. If the value returned is a character, then that will be the value of read for this expression, otherwise an error will be signaled.

Note: When adding new # syntaxes, have your code save the previous value of read:sharp or read:sharp-char when defining it. Call this saved value if an invocation's syntax is not recognized. This will allow #+, #-, #!, and section Uniform Arrays to still be supported (as they use read:sharp).

Function: procedure->syntax proc
Returns a macro which, when a symbol defined to this value appears as the first symbol in an expression, returns the result of applying proc to the expression and the environment.

Function: procedure->macro proc
Function: procedure->memoizing-macro proc
Returns a macro which, when a symbol defined to this value appears as the first symbol in an expression, evaluates the result of applying proc to the expression and the environment. The value returned from proc which has been passed to PROCEDURE->MEMOIZING-MACRO replaces the form passed to proc. For example:

(define trace
  (procedure->macro
   (lambda (x env) `(set! ,(cadr x) (tracef ,(cadr x) ',(cadr x))))))

(trace foo) == (set! foo (tracef foo 'foo)).

Function: environment->tree env
An environment is an opaque object representing lexical bindings. environment->tree returns a representation of the environment env as a list of environment frames. There are 2 types of environment frames:

((lambda (variable1 ...) ...) value1 ...)
(let ((variable1 value1) (variable2 value2) ...) ...)
(letrec ((variable1 value1) ...) ...)
result in a single enviroment frame:
((variable1 ...) value1 ...)
(let ((variable1 value1)) ...)
(let* ((variable1 value1) ...) ...)
result in an environment frame for each variable:
(variable1 . value1) (variable2 .  value2) ...

Special Form: @apply procedure argument-list
Returns the result of applying procedure to argument-list. @apply differs from apply when the identifiers bound by the closure being applied are set!; setting affects argument-list.

(define lst (list 'a 'b 'c))
(@apply (lambda (v1 v2 v3) (set! v1 (cons v2 v3))) lst)
lst           => ((b . c) b c)

Thus a mutable environment can be treated as both a list and local bindings.

Special Form: @call-with-current-continuation procedure
Returns the result of applying procedure to the current continuation. A continuation is a SCM object of type contin (see section Continuations). The procedure (call-with-current-continuation procedure) is defined to have the same effect as (@call-with-current-continuation procedure).

Syntactic Hooks for Hygienic Macros

SCM provides a synthetic identifier type for efficient implementation of hygienic macros (for example, syntax-rules see section `Macros' in Revised(4) Scheme) A synthetic identifier may be inserted in Scheme code by a macro expander in any context where a symbol would normally be used. Collectively, symbols and synthetic identifiers are identifiers.

Function: identifier? obj
Returns #t if obj is a symbol or a synthetic identifier, and #f otherwise.

If it is necessary to distinguish between symbols and synthetic identifiers, use the predicate symbol?.

A synthetic identifier includes two data: a parent, which is an identifier, and an environment, which is either #f or a lexical environment which has been passed to a macro expander (a procedure passed as an argument to procedure->macro, procedure->memoizing-macro, or procedure->syntax).

Function: renamed-identifier parent env
Returns a synthetic identifier. parent must be an identifier, and env must either be #f or a lexical environment passed to a macro expander. renamed-identifier returns a distinct object for each call, even if passed identical arguments.

There is no direct way to access the data internal to a synthetic identifier, those data are used during variable lookup. If a synthetic identifier is inserted as quoted data then during macro expansion it will be repeatedly replaced by its parent, until a symbol is obtained.

Use of synthetic identifiers

renamed-identifier may be used as a replacement for gentemp:

(define gentemp
  (let ((name (string->symbol "An unlikely variable")))
    (lambda ()
      (renamed-identifier name #f))))

If an identifier returned by this version of gentemp is inserted in a binding position as the name of a variable then it is guaranteed that no other identifier may denote that variable. If an identifier returned by gentemp is inserted free, then it will denote the top-level value bound to its parent, the symbol named "An unlikely variable". This behavior, of course, is meant to be put to good use:

(define top-level-foo
  (procedure->memoizing-macro
   (lambda (exp env)
     (renamed-identifier 'foo #f))))

Defines a macro which may always be used to refer to the top-level binding of foo.

(define foo 'top-level)
(let ((foo 'local))
  (top-level-foo))  => top-level

In other words, we can avoid capturing foo.

If a lexical environment is passed as the second argument to renamed-identifier then if the identifier is inserted free its parent will be looked up in that environment, rather than in the top-level environment. The use of such an identifier must be restricted to the lexical scope of its environment.

There is another restriction imposed for implementation convenience: Macros passing their lexical environments to renamed-identifier may be lexically bound only by the special forms @let-syntax or @letrec-syntax. No error is signaled if this restriction is not met, but synthetic identifier lookup will not work properly.

Special Form: @let-syntax
Special Form: @letrec-syntax
Behave as let and letrec, but may also put extra information in the lexical environment so that renamed-identifier will work properly during expansion of the macros bound by these forms.

In order to maintain referential transparency it is necessary to determine whether two identifiers have the same denotation. With synthetic identifiers it is not necessary that two identifiers be eq? in order to denote the same binding.

Function: identifier-equal? id1 id2 env
Returns #t if identifiers id1 and id2 denote the same binding in lexical environment env, and #f otherwise. env must be a lexical environment passed to a macro transformer during macro expansion.

For example,

(define top-level-foo?
  (procedure->memoizing-macro
   (let ((foo-name (renamed-identifier 'foo #f)))
     (lambda (exp env)
       (identifier-equal? (cadr exp) foo-name env)))))

(top-level-foo? foo)  => #t

(let ((foo 'local))
  (top-level-foo? foo))  => #f

Special Form: syntax-quote obj
Synthetic identifiers are converted to their parent symbols by quote and quasiquote so that literal data in macro definitions will be properly transcribed. syntax-quote behaves like quote, but preserves synthetic identifier intact.

Special Form: the-macro mac
the-macro is the simplest of all possible macro transformers: mac may be a syntactic keyword (macro name) or an expression evaluating to a macro, otherwise an error is signaled. mac is evaluated and returned once only, after which the same memoizied value is returned.

the-macro may be used to protect local copies of macros against redefinition, for example:

(@let-syntax ((let (the-macro let)))
   ;; code that will continue to work even if LET is redefined.
        ...)


Go to the first, previous, next, last section, table of contents.