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
#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
.
@copy-tree
if you
depend on this feature; copy-tree
could get redefined.
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.
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.
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)
.
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.
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
!
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.
#t
if port is input or output to a serial non-file device.
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#\>
#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."
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.
A similar read syntax #! (exclamation rather than vertical bar) is supported for Posix shell-scripts (see section Shell Scripts).
#.(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.
#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. defconst
is valid only
when used at top-level.
define
d 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.
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.
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)
.
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
).
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)).
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) ...) ...)
((variable1 ...) value1 ...)
(let ((variable1 value1)) ...)
(let* ((variable1 value1) ...) ...)
(variable1 . value1) (variable2 . value2) ...
@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.
contin
(see section Continuations). The procedure
(call-with-current-continuation procedure)
is defined to
have the same effect as (@call-with-current-continuation
procedure)
.
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.
#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
).
#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.
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.
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.
#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
quote
and quasiquote
so that literal data in macro definitions will be
properly transcribed. syntax-quote
behaves like quote
, but
preserves synthetic identifier intact.
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.