This section describes features which are either present in all builds of SCM or which must be enabled when SCM is compiled.
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.
if
: (if <test> <consequent>)
let*
let
do
define
list-tail
string-copy
string-fill!
make-vector
of two arguments
vector-fill!
apply
of more than 2 arguments
-
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
delay
force
with-input-from-file
with-output-to-file
char-ready?
transcript-on
transcript-off
numerator
denominator
rationalize
delay
full-continuation
ieee-p1178
object-hash
rev4-report
source
current-time
defmacro
dynamic-wind
eval
getenv
system
hash
logical
multiarg-apply
multiarg/and-
rev4-optional-procedures
string-port
tmpnam
transcript
vicinity
with-file
array
array-for-each
bignum
complex
inexact
rational
real
For documentation of the procedures getenv
and system
See section `System Interface' in SLIB.
exit
(see section `System' in SLIB). On many
systems, SCM can also tail-call another program. See section I/O-Extensions.
ed
will invoke the editor with a
single the single argument filename.
EDITOR
(or just
ed
if it isn't defined) is invoked as a command with arguments
arg1 ....
errno
. When given an argument, errno
sets the system
variable errno
to n and returns the previous value of
errno
. (errno 0)
will clear outstanding errors. This is
recommended after try-load
returns #f
since this occurs
when the file could not be opened.
errno
and a newline. The value returned is unspecified.
A computer-language implementation designer faces choices of how reflexive to make the implementation in handling exceptions and errors; that is, how much of the error and exception routines should be written in the language itself. The design of a portable implementation is further constrained by the need to have (almost) all errors print meaningful messages, even when the implementation itself is not functioning correctly. Therefore, SCM implements much of its error response code in C.
The following common error and conditions are handled by C code. Those with callback names after them can also be handled by Scheme code (see section Interrupts). If the callback identifier is not defined at top level, the default error handler (C code) is invoked. There are many other error messages which are not treated specially.
(out-of-storage)
(end-of-program)
(hang-up)
(user-interrupt)
(arithmetic-error)
(alarm-interrupt)
error
does not set
errobj.
If SCM is built with the `CAUTIOUS' flag, then when an error occurs, a stack trace of certain pending calls are printed as part of the default error response. A (memoized) expression and newline are printed for each partially evaluated combination whose procedure is not builtin. See section Memoized Expressions for how to read memoized expressions.
Also as the result of the `CAUTIOUS' flag, both error
and
user-interrupt
(invoked by C-c) are defined to print stack
traces and conclude by calling breakpoint
(see section `Breakpoints' in SLIB). This allows the user to interract with SCM as with Lisp
systems.
stack-trace
returns #t
if any lines were
printed and #f
otherwise. See `Init.scm' for an example of
the use of stack-trace
.
SCM memoizes the address of each occurence of an identifier's value when first encountering it in a source expression. Subsequent executions of that memoized expression is faster because the memoized reference encodes where in the top-level or local environment its value is.
When procedures are displayed, the memoized locations appear in a format different from references which have not yet been executed. I find this a convenient aid to locating bugs and untested expressions.
For instance, open-input-file
is defined as follows in
`Init.scm':
(define (open-input-file str) (or (open-file str OPEN_READ) (and (procedure? could-not-open) (could-not-open) #f) (error "OPEN-INPUT-FILE couldn't open file " str)))
If open-input-file
has not yet been used, the displayed procedure
is similar to the original definition (lines wrapped for readability):
open-input-file => #<CLOSURE (str) (or (open-file str open_read) (and (procedure? could-not-open) (could-not-open) #f) (error "OPEN-INPUT-FILE couldn't open file " str))>
If we open a file using open-input-file
, the sections of code
used become memoized:
(open-input-file "r4rstest.scm") => #<input-port 3> open-input-file => #<CLOSURE (str) (#@or (#@open-file #@0+0 #@open_read) (and (procedure? could-not-open) (could-not-open) #f) (error "OPEN-INPUT-FILE couldn't open file " str))>
If we cause open-input-file
to execute other sections of code,
they too become memoized:
(open-input-file "foo.scm") => ERROR: No such file or directory ERROR: OPEN-INPUT-FILE couldn't open file "foo.scm" open-input-file => #<CLOSURE (str) (#@or (#@open-file #@0+0 #@open_read) (#@and (#@procedure? #@could-not-open) (could-not-open) #f) (#@error "OPEN-INPUT-FILE couldn't open file " #@0+0))>
Note: When running a saved executable (see section Dump),
restart
is redefined to be exec-self
.
exec-self
from restart
.
(room #t)
also gives the hexadecimal heap segment and stack bounds.
For other configuration constants and procedures See section `Configuration' in SLIB.
#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
.
load
,
try-load
, and dyn:link
(see section Compiling And Linking).
*load-pathname*
is used to compute the value of section `Vicinity' in SLIB.
eval-string
does not change
*load-pathname*
or line-number
.
load
, the value returned is unspecified. eval-string
does
not change *load-pathname*
or line-number
.
Print
writes all its arguments, separated by spaces.
Print
outputs a newline
at the end and returns the value
of the last argument.
Is the integer number of internal time units in a second.
get-internal-run-time
divided by
internal-time-units-per-second
will give elapsed run time in
seconds.
get-internal-real-time
divided by
interal-time-units-per-second
will give elapsed real time in
seconds.
current-time
is
used in section `Time' in SLIB.
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.
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.
alarm-interrupt
will be signaled secs from the current
time. ALARM is not supported on all systems.
SIGINT
(control-C interrupt) and
SIGALRM
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)
.
To unestablish a response for an error set the handler symbol to
#f
. For instance, (set! could-not-open #f)
.
Returns an object of type arbiter and name name. Its state is initially unlocked.
Returns #t
and locks arbiter if arbiter was unlocked.
Otherwise, returns #f
.
Returns #t
and unlocks arbiter if arbiter was locked.
Otherwise, returns #f
.
These procedures generalize and extend the standard capabilities in section `Ports' in Revised(4) Scheme.
#f
is returned.
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.
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.
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#\>
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)
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.
#+(not feature) expression
.
|#
is
ignored by the read
. Nested #|...|#
can occur inside
any thing.
#!/usr/local/bin/scm
When such a file is invoked it executes /usr/local/bin/scm with the name of this file as the first argument. The following shell script will print factorial of its argument:
#!/usr/local/bin/scm ;;; -*-scheme-*- tells emacs this is a scheme file. (define (fact n) (if (< n 2) 1 (* n (fact (+ -1 n))))) (display (fact (string->number (caddr (program-arguments))))) (newline) (quit)
This technique has some drawbacks:
The following approach solves both problems -- at the expense of
slightly slower startup. type;
should appear on every line to be
executed by the shell. These lines do not have the length restriction
mentioned above. Also, /bin/sh
searches the directories listed
in the `PATH' environment variable for `scm', eliminating the need
to know absolute locations in order to invoke a program.
#!/bin/sh type;exec scm $0 $* ;;; -*-scheme-*- tells emacs this is a scheme file. (define (fact n) (if (< n 2) 1 (* n (fact (+ -1 n))))) (display (fact (string->number (caddr (program-arguments))))) (newline) (quit)
#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
.
define
d 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.
SCM also supports the following constructs from Common Lisp:
defmacro
, macroexpand
, macroexpand-1
, and
gentemp
. See section `Defmacro' in SLIB.
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)
.
Note: When adding new # syntaxes, have your code save the
previous value of read:sharp
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
).
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)).
An environment is a list of environment frames. There are 2 types of environment frames:
((lambda (variable1 ...) ...) value1 ...)
(let ((variable1 value1) (variable2 value2) ...) ...)
(letrec ((variable1 value1) ...) ...)
((variable1 ...) value1 ...)
(let ((variable1 value1)) ...)
(let* ((variable1 value1) ...) ...)
(variable1 . value1) (variable2 . value2) ...
contin
(see section Continuations). The procedure
(call-with-current-continuation procedure)
is defined to
have the same effect as (@call-with-current-continuation
procedure)
.
The following procedures and special forms are used to implement hygienic and
referentially transparent macros. "Macro transformer" means
a procedure passed as the first argument to procedure->syntax
,
procedure->macro
, or procedure->memoizing-macro
.
#f
, which is equivalent to a null lexical environment. The
resulting macro must be bound either by a top level define
, or by
the special forms @let-syntax
or @letrec-syntax
. These
last two forms are used to implement let-syntax
and
letrec-syntax
. For almost all purposes the higher level forms
define-syntax
, let-syntax
, and letrec-syntax
See section `Macros' in Revised(4) Scheme. are to be preferred.
If a synthetic identifier is inserted bound, then no symbol, and no synthetic identifier not having the bound identifier as parent, may have the same denotation, and so may not be captured. If a synthetic identifier is inserted free, then it will denote the same object that parent did in env. It is an error to insert a synthetic identifier outside the lexical scope of the env used for its creation.
quote
and quasiquote
so that literal data in macro definitions will be
properly transcribed. syntax-quote
behaves like quote
, but
preserves synthetic identifier intact.
#t
if obj is a symbol or a synthetic
identifier, and #f
otherwise.
#t
if identifiers id1 and id2 would denote
the same binding in lexical environment env, and #f
otherwise.
let
and letrec
, but may also put extra
information in the lexical environment so that rename-identifier
will work properly during expansion of the macros bound by these forms.
Go to the first, previous, next, last section, table of contents.