Scm conforms to the [IEEE], IEEE Standard 1178-1990. IEEE Standard for the Scheme Programming Language. and [R5RS], Revised(5) Report on the Algorithmic Language Scheme. All the required features of these specifications are supported. Many of the optional features are supported as well.
- 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
with-input-from-file
with-output-to-file
load
transcript-on
transcript-off
numerator
denominator
rationalize
delay
full-continuation
ieee-p1178
object-hash
rev4-report
source
current-time
defmacro
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
@copy-tree if you
depend on this feature; copy-tree could get redefined.
(set! a-list (acons key datum a-list))
Adds a new association to a-list.
To remove the gc-hook, (set! gc-hook #f).
#f or #t, See section Immediates. finalizer is
a thunk, or procedure taking no arguments.
finalizer will be invoked asynchronously exactly once some time after object becomes eligible for garbage collection. A reference to object in the environment of finalizer will not prevent finalization, but will delay the reclamation of object at least until the next garbage collection. A reference to object in some other object's finalizer will necessarily prevent finalization until both objects are eligible for garbage collection.
Finalizers are not run in any predictable order. All finalizers will be run by the time the program ends.
This facility was based on the paper by Simon Peyton Jones, et al, "Stretching the storage manager: weak pointers and stable names in Haskell", Proc. 11th International Workshop on the Implementation of Functional Languages, The Netherlands, September 7-10 1999, Springer-Verlag LNCS.
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 and Date' 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).
An exchanger is a procedure of one argument regulating mutually exclusive access to a resource. When a exchanger is called, its current content is returned, while being replaced by its argument in an atomic operation.
Returns a new exchanger with the argument obj as its initial content.
(define queue (make-exchanger (list a)))
A queue implemented as an exchanger holding a list can be protected from reentrant execution thus:
(define (pop queue)
(let ((lst #f))
(dynamic-wind
(lambda () (set! lst (queue #f)))
(lambda () (and lst (not (null? lst))
(let ((ret (car lst)))
(set! lst (cdr lst))
ret)))
(lambda () (and lst (queue lst))))))
(pop queue) => a
(pop queue) => #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(5) 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!
Both input and output functions can be used with io-ports. An end of file must be read or a two-argument file-position done on the port between a read operation and a write operation or vice-versa.
open-file is called
with it as the second argument will return an unbuffered port. An
input-port must be unbuffered in order for char-ready? and
wait-for-input to work correctly on it. The initial value of
(current-input-port) is unbuffered if the platform supports it.
open-file is called
with it as the second argument will return a tracked port. A tracked
port maintains current line and column numbers, which may be queried
with port-line and port-column.
open-file is called
with it as the second argument will return a port only if the named file
does not already exist. This functionality is provided by calling
try-create-file See section I/O-Extensions, which is not available
for all platforms.
#f is returned.
#f is returned. If port is open
to a non-file, then file-position returns #f.
#f. Line and column numbers begin with 1.
The column number applies to the next character to be read; if that
character is a newline, then the column number will be one more than
the length of the line.
current-output-port. If port is not a tracked port
freshline is equivalent to newline.
#t if port is input or output to a serial non-file
device.
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.
char-ready?.
If none of port1 ... become char-ready? within the time
interval of x seconds, then #f is returned. The
port1 ... arguments may be omitted, in which case they default
to the list of the value returned by current-input-port.
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(5) Scheme) it indicates
that the port has reached end-of-file. For example:
If it is necessary to explicitly close the port when it is garbage collected, (see section Interrupts).
(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#\>
#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' in Hobbit).
*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. load-string does
not change *load-pathname* or line-number.
Scheme code defined by load may optionally contain line number information. Currently this information is used only for reporting expansion time errors, but in the future run-time error messages may also include line number information.
read,
which is used if reader is not supplied or is false.
Line number objects are disjoint from integers or other Scheme types. When evaluated or loaded as Scheme code, an s-expression containing a line-number in the car is equivalent to the cdr of the s-expression. A pair consisting of a line-number in the car and a vector in the cdr is equivalent to the vector. The meaning of s-expressions with line-numbers in other positions is undefined.
read, except that
read, except that load syntaxes are enabled.
*load-reader* should be a value acceptable as
the second argument to try-load (note that #f is acceptable).
This value will be used to read code during calls to scm:load.
The value of *slib-load-reader* will similarly be used during
calls to slib:load and require.
In order to disable all line-numbering, it is sufficient to set!
*load-reader* and *slib-load-reader* to #f.
#.(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.
provided? 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?,
See section `Require' in SLIB.
#+(not feature) expression.
|# is
ignored by the read. Nested #|...|# can occur inside
any thing.
Load sytax is Read syntax enabled for read only when that
read is part of loading a file or string. This distinction was
made so that reading from a datafile would not be able to corrupt a
scheme program using `#.'.
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)
#! is the unix mechanism for executing scripts. See section Unix Scheme Scripts for the full description of how this comment supports scripting.
load, possibly with `.scm'
appended.
#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."
comment.
comment and empties the current string collection.
(comment "text-till-end-of-line").
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:sharp, but only during loads. The
read-syntaxes handled by load:sharp are a superset of those
handled by read:sharp. load:sharp calls
read:sharp if none of its syntaxes match c.
read, read will call the value of the
symbol char:sharp 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 load:sharp, read:sharp, or
char: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
dispatch from read:sharp).
SCM provides a native implementation of defmacro. See section `Defmacro' in SLIB.
When built with `-F macro' build option (see section Build Options) and
`*syntax-rules*' is non-false, SCM also supports [R5RS]
syntax-rules macros. See section `Macros' in Revised(5) Scheme.
Other Scheme Syntax Extension Packages from SLIB can be employed through the use of `macro:eval' and `macro:load'; Or by using the SLIB read-eval-print-loop:
(require 'repl) (repl:top-level macro:eval)
With the appropriate catalog entries (see section `Library Catalogs' in SLIB), files using macro packages will automatically use the correct macro loader when `require'd.
#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(5) Scheme). Otherwise
equivalent to #f.
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. defvar is valid only
when used at top-level.
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.
The identifiers variable1, variable2, ... must be bound either in some region enclosing the `set!' expression or at top level.
<Expression> is evaluated, and the elements of the resulting list are stored in the locations to which each corresponding variable is bound. The result of the `set!' expression is unspecified.
(define x 2) (define y 3) (+ x y) => 5 (set! (x y) (list 4 5)) => unspecified (+ x y) => 9
qase is an extension of standard Scheme case: Each
clause of a qase statement must have as first element a
list containing elements which are:
A qase 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 qase clause during macro
expansion. defconst constants should be defined before use.
qase can be substituted for any correct use of case.
(defconst unit '1) (defconst semivowels '(w y)) (qase (* 2 3) ((2 3 5 7) 'prime) ((,unit 4 6 8 9) 'composite)) ==> composite (qase (car '(c d)) ((a) 'a) ((b) 'b)) ==> unspecified (qase (car '(c d)) ((a e i o u) 'vowel) ((,@semivowels) 'semivowel) (else 'consonant)) ==> consonant
SCM supports the following constructs from Common Lisp:
defmacro, macroexpand, macroexpand-1, and
gentemp. See section `Defmacro' in SLIB.
SCM defmacro is extended over that described for SLIB:
(defmacro (macro-name . arguments) body)
is equivalent to
(defmacro macro-name arguments body)
As in Common Lisp, an element of the formal argument list for
defmacro may be a possibly nested list, in which case the
corresponding actual argument must be a list with as many members as the
formal argument. Rest arguments are indicated by improper lists, as in
Scheme. It is an error if the actual argument list does not have the
tree structure required by the formal argument list.
For example:
(defmacro (let1 ((name value)) . body)
`((lambda (,name) ,@body) ,value))
(let1 ((x (foo))) (print x) x) == ((lambda (x) (print x) x) (foo))
(let1 not legal syntax) error--> not "does not match" ((name value))
SCM supports [R5RS] syntax-rules macros
See section `Macros' in Revised(5) Scheme.
The pattern language is extended by the syntax (... <obj>), which
is identical to <obj> except that ellipses in <obj> are
treated as ordinary identifiers in a template, or as literals in a
pattern. In particular, (... ...) quotes the ellipsis token
... in a pattern or template.
For example:
(define-syntax check-tree
(syntax-rules ()
((_ (?pattern (... ...)) ?obj)
(let loop ((obj ?obj))
(or (null? obj)
(and (pair? obj)
(check-tree ?pattern (car obj))
(loop (cdr obj))))))
((_ (?first . ?rest) ?obj)
(let ((obj ?obj))
(and (pair? obj)
(check-tree ?first (car obj))
(check-tree ?rest (cdr obj)))))
((_ ?atom ?obj) #t)))
(check-tree ((a b) ...) '((1 2) (3 4) (5 6))) => #t
(check-tree ((a b) ...) '((1 2) (3 4) not-a-2list) => #f
Note that although the ellipsis is matched as a literal token in the
defined macro it is not included in the literals list for
syntax-rules.
The pattern language is also extended to support identifier macros. A reference to an identifier macro keyword that is not the first identifier in a form may expand into Scheme code, rather than raising a "keyword as variable" error. The pattern for expansion of such a bare macro keyword is a single identifier, as in other syntax rules the identifier is ignored.
For example:
(define-syntax eight
(syntax-rules ()
(_ 8)))
(+ 3 eight) => 11
(eight) => ERROR
(set! eight 9) => ERROR
PROCEDURE->MEMOIZING-MACRO replaces the form passed to
proc. For example:
(defsyntax trace (procedure->macro (lambda (x env) `(set! ,(cadr x) (tracef ,(cadr x) ',(cadr x)))))) (trace foo) == (set! foo (tracef foo 'foo)).
PROCEDURE->IDENTIFIER-MACRO is similar to
PROCEDURE->MEMOIZING-MACRO except that proc is also
called in case the symbol bound to the macro appears in an expression
but not as the first symbol, that is, when it looks like a
variable reference. In that case, the form passed to proc is
a single identifier.
define for this
purpose may not result in name being interpreted as a macro
keyword.
An environment is a list of frames representing lexical bindings. Only the names and scope of the bindings are included in environments passed to macro expanders -- run-time values are not included.
There are several types of environment frames:
((lambda (variable1 ...) ...) value1 ...)
(let ((variable1 value1) (variable2 value2) ...) ...)
(letrec ((variable1 value1) ...) ...)
(variable1 variable2 ...)
(let ((variable1 value1)) ...)
(let* ((variable1 value1) ...) ...)
variable1 variable2 ...
(let-syntax ((key1 macro1) (key2 macro2)) ...)
(letrec-syntax ((key1 value1) (key2 value2)) ...)
(<env-syntax-marker> (key1 . value1) (key2 . value2))Currently <env-syntax-marker> is the integer 6.
line numbers
#<line 8>
miscellaneous
<env-filename-marker> "foo.scm" <env-procedure-name-marker> foo ...Currently <env-filename-marker> is the integer 1 and <env-procedure-name-marker> the integer 2.
@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.
SCM provides a synthetic identifier type for efficient implementation of
hygienic macros (for example, syntax-rules
see section `Macros' in Revised(5) 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 all of 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 (except one produced by passing the first to
renamed-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.
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 either be a lexical environment passed to a macro transformer
during macro expansion or the empty list.
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
car of expr denotes a macro in env, then
if that macro is a primitive, expr will be returned, if the
macro was defined in Scheme, then a macro expansion will be returned.
If the car of expr does not denote a macro, the #f
is returned.
lambda expression. values
must be a list of objects long enough to provide a binding for each of
the identifiers in names. If names is an identifier or an
improper list then vals may be, respectively, any object or an
improper list of objects.
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.
...)
define-syntax, let-syntax, and letrec-syntax
using renaming-transformer instead of syntax-rules.
proc should evaluate to a procedure accepting three arguments:
expr, rename, and compare. expr is a
representation of Scheme code to be expanded, as list structure.
rename is a procedure accepting an identifier and returning an
identifier renamed in the definition environment of the new syntax.
compare accepts two identifiers and returns true if and only if
both denote the same binding in the usage environment of the new syntax.