This document is a manual for Sagittarius, an R6RS/R7RS Scheme implementation. This is for version 0.9.12.
This is a users' guide and reference manual of Sagittarius Scheme system. Here I tried to describe the points which are not conformed to R6RS.
The target readers are those who already know Scheme and want to write useful programs in Sagittarius.
Sagittarius is a Scheme script engine; it reads Scheme programs, compiles it on-the-fly and executes it on a virtual machine. Sagittarius conforms the language standard "Revised^6 Report on the Algorithmic Language Scheme" (R6RS), "Revised^7 Report on the Algorithmic Language Scheme" (R7RS), and supports various common libraries defined in "Scheme Requests for Implementation" (SRFI)s.
There are a lot of Scheme implementations and they have different strong and weak points. Sagittarius focuses on "Flexibility" and "Easy to Use". R6RS specifies strict requirements, but sometimes you may think this is too much. For that purpose, Sagittarius has less strictness. There are invocation options that make Sagittarius run on strict RnRS mode.
To avoid to lose portability or write miss-working code, you may want to know what are the non conformed points.
Basically reader has 3 modes. One is R6RS mode, one is R7RS mode and the
last one is compatible mode. Although, user can modify reader with reader
macro. These modes can be switched via #!r6rs
, #!r7rs
or
#!compatible
. For more details, see
Predefined reader macros.
Redefinition of exported values are allowed on script file. This can be
restricted by -r6
option to run the script strict R6RS mode.
Multiple import of the same identifier is allowed. The value which
imported at the last will be used.
In this manual, each entry is represented like this.
[spec] Description foo ...
Category denotes category of the entry foo. The following category will appear in this manual.
A command line program
A Scheme function
A syntax
A auxiliary syntax
A macro
A auxiliary macro
A library
A condition type
A reader macro
A CLOS class
A generic function
A method
For functions, syntaxes, or macros, the the entry may be followed by one or more arguments. In the arguments list, following notations may appear.
Indicates zero or more arguments
Indicates is may take up to three optional arguments. The second form specifies default values for x, y and z.
The description of the entry follows the entry line. If the specification of the entry comes from some standard or implementation, its origin is noted in the bracket at the beginning of the description. The following origins are noted:
The entry works as specified in "Revised^6 Report on the Algorithmic Language Scheme.". If it is marked as "[R6RS+]", the entry has additional functionality.
The entry works as specified in "Revised^7 Report on the Algorithmic Language Scheme.".
The entry works as specified in SRFI-n. If it is marked as "[SRFI-n+]", the entry has additional functionality.
Sagittarius can be used as an independent Scheme interpreter. The interpreter
which comes with Sagittarius distribution is a program named sagittarius
on Unix like environment and sash
on Windows environment.
Invoking sagittarius. If scheme-file is not given, it runs with interactive mode.
Specifying -r
option with Scheme standard number, currently 6
and
7
are supported, forces to run Sagittarius on strict standard
mode. For example, entire script is read then evaluated on R6RS (-r6
option) mode. Thus macros can be located below the main script.
Detail options are given with option "-h"
.
For backward compatibility, symbolic link sash
is also provided
on Unix like environment. However this may not exist if Sagittarius is built
with disabling symbolic link option.
When a Scheme file is given to sagittarius
, it bounds an internal
variable to list of the remaining command-line arguments which you can get with
the command-line
procedure, then loads the Scheme program. If the first
line of scheme-file begins with "#!"
, then Sagittarius ignores the
entire line. This is useful to write a Scheme program that works as an
executable script in unix-like systems.
Typical Sagittarius script has the first line like this:
#!/usr/local/bin/sagittarius
or
#!/bin/env sagittarius
The second form uses "shell trampoline" technique so that the script works as
far as sagittarius
is in the PATH.
After the script file is successfully loaded, then Sagittarius will process all toplevel expression the same as Perl.
Now I show a simple example below. This script works like cat(1)
, without
any command-line option processing and error handling.
#!/usr/local/bin/sagittarius
(import (rnrs))
(let ((args (command-line)))
(unless (null? (cdr args))
(for-each (lambda (file)
(call-with-input-file file
(lambda (in)
(display (get-string-all in)))))
(cdr args)))
0)
If you need to add extra load path in the executing script file, you can also write like this:
#!/bin/bash
#|
# Adding lib directory located in the same directory as this script
# is located
DIR=$(dirname "$0")
exec sagittarius -L${DIR}/lib $0 "$@"
|#
;; Scheme script
(import (rnrs))
If the script file contains main
procedure, then Sagittarius execute
it as well with one argument which contains all command line arguments. This
feature is defined in
SRFI-22. So the
above example can also be written like the following:
#!/usr/local/bin/sagittarius
(import (rnrs))
(define (main args)
(unless (null? (cdr args))
(for-each (lambda (file)
(call-with-input-file file
(lambda (in)
(display (get-string-all in)))))
(cdr args)))
0)
NOTE: the main
procedure is called after all toplevel expressions
are executed.
If sagittarius
does not get any script file to process, then it will
go in to REPL (read-eval-print-loop). For developers' convenience, REPL
imports some libraries by default such as (rnrs)
.
If .sashrc
file is located in the directory indicated HOME
or
USERPROFILE
environment variable, then REPL reads it before evaluating
user input. So developer can pre-load some more libraries, instead of typing
each time.
NOTE: .sashrc
is only for REPL, it is developers duty to load all
libraries on script file.
Sagittarius provides 2 styles to write a library, one is R6RS style and other one is R7RS style. Both styles are processed the same and users can use it without losing code portability.
Following example is written in R6RS style, for the detail of
library
syntax please see the R6RS document described in bellow
sections.
(library (foo)
(export bar)
(import (rnrs))
(define bar 'bar) )
The library named (foo)
must be saved the file
named foo.scm
, foo.ss
, foo.sls
or foo.sld
(I use
.scm
for all examples) and located on the loading path, the value is
returned by calling add-load-path
with 0 length string.
The file extension also controls the reader mode.
.ss
and .sls
When a file with one of the extensions is loaded during library importing,
then #!r6rs
directive is applied to the target file by default.
.sld
When a file has this extensions, then #!r7rs
directive is applied to the
target file by default.
.scm
This file extension uses #!compatible
directive.
If the loading file contains other directive, then the default directive is overwritten.
If you want to write portable code yet want to use Sagittarius specific
functionality, then you can write implementation specific code separately using
.sagittarius.scm
, .sagittarius.ss
, .sagittarius.sls
or
.sagittarius.sld
extensions. This functionality is implemented almost
all R6RS implementation. If you use R7RS style library syntax, then you can
also use cond-expand
to separate implementation specific
functionalities.
If you don't want to share a library but only used in specific one, you can write both in one file and name the file you want to show. For example;
(library (not showing)
;; exports all internal use procedures
(export ...)
(import (rnrs))
;; write procedures
...
)
(library (shared)
(export shared-procedure ...)
(import (rnrs) (not showing))
;; write shared procedures here
)
Above script must be saved the file named shared.scm
. The order of
libraries are important. Top most dependency must be the first and next is
second most, so on.
Note: This style can hide some private procedures however if you want to write portable code, some implementations do not allow you to write this style.
For better starting time, Sagittarius caches compiled libraries. The cache files are stored in one of the following environment variables;
For Unix like (POSIX) environment:
SAGITTARIUS_CACHE_DIR
HOME
For Windows environment:
SAGITTARIUS_CACHE_DIR
TEMP
TMP
Sagittarius will use the variables respectively, so if the
SAGITTARIUS_CACHE_DIR
is found then it will be used.
The caching compiled file is carefully designed however the cache file might be
stored in broken state. In that case use -c
option with
sagittarius
, then it will wipe all cache files. If you don't want to use
it, pass -d
option then Sagittarius won't use it.
Adding #!nocache
directive to a library file would disable caching of
the file. This is sometimes useful especially if you need importing time
information, e.g. loading path, which is not available if the library is
loaded from a cache.
Some of the behaviours are not compliant or deviate from other implementations. Here, we list some of them.
The following code will print #t
instead of #f
with -r6
command line option or doing it on a library:
(import (rnrs) (for (rnrs eval) expand))
(define-syntax foo
(lambda(ctx)
(syntax-case ctx ()
((_ id)
(free-identifier=?
#'id
(eval '(datum->syntax #'k 'bar) (environment '(rnrs))))))))
(define bar)
(display (foo bar))
This is because, Sagittarius doesn't have separated phases of macro expansion
and compilation. When foo
is expanded, then the bar
is not defined
yet or at least it's not visible during the macro expansion. So, both _bar_s
are not bound, then free-identifier=?
will consider them the same
identifiers.
On R6RS, symbol starts with #!
is ignored, however this is not the case
on R7RS. Sagittarius ignores these symbols on both mode.
Sagittarius works with library even toplevel expressions are belong to a library
named "user"
. Here I list up all R6RS libraries. Some libraries contain
the same procedure ie. assoc which is in (rnrs (6))
and
(srfi :1 lists)
. In this case I will put a pointer to other library's
section.
If library specifies its version, Sagittarius, however, ignores it. This behaviour may change in future.
Declare a library named name.
name uniquely identifies a library and is globally visible in the
import
clauses of all other libraries. It must have the following form:
(_identifier1 identifier2_ ... _version_)
where version is empty or has the following form:
(_sub-version_ ...)
An export-clause names a set of imported and locally defined bindings to
be exported. It must have following form:
(export _export-spec_ ...)
export-spec must have one of the following forms:
_identifier_
(rename (_identifier1 identifier2_) ...)
In an export-spec, an identifier names a single binding defined
within or imported into the library, where the external name for the export is
the same as the name of the binding within the library. A rename
spec
exports the binding named by identifier1 in each
(_identifier1 identifier2_)
pairing, using identifier2 as
the external name.
import-clause specifies a set of bindings to be imported into the library. It must have the following form:
(import _import-spec_ ...)
Each import-spec specifies a set of bindings to be imported into the library. An import-spec must be one of the following:
import-set
(for _import-set_ _import-level_ ...)
An import-level is one of the following:
run
expand
(meta _level_)
where level represents an exact integer object.
Note: The levels will be ignored on Sagittarius. The macro expansion phase will be automatically resolved. For portable code, it is better to specify the proper level.
An import-set names a set of bindings from another library and possibly specifies local names for the imported bindings. It must be one of the following:
reference
(library _reference_)
(only _import-set_ _identifier_ ...)
(except _import-set_ _identifier_ ...)
(prefix _import-set_ _identifier_)
(rename _import-set_ (_identifier1 identifier2_) ...)
A reference identifies a library by its name and optionally by its version. It must have one of the following forms:
(_identifier1 identifier2_ ...)
(_identifier1 identifier2_ ... _version_)
Note: Sagittarius ignores version.
A reference whose first identifier is
for, library, only, except, prefix
or rename
is permitted only
within a library
import-set. The import-set(library _reference_)
is otherwise equivalent to reference.
By default, all of an imported library's exported bindings are made visible
within an importing library using the names given to the bindings by the
imported library. The precise set of bindings to be imported and the names of
those bindings can be adjusted with the only, except, prefix
and
rename
forms described below.
An only
form produces a subset of the bindings from another
import-set, including only the listed _identifier_s. The included
_identifier_s should be in the original import-set.
An except
form produces a subset of the bindings from another
import-set, including all but the listed _identifier_s. All of the
excluded _identifier_s should be in the original import-set.
A prefix
form adds the identifier prefix to each name from
another import-set.
A rename
form (rename _identifier1 identifier2_ ...)
,
removes the bindings for identifier1 ... to form an intermediate
import-set, then adds the bindings back for the corresponding
identifier2 ... to form the final import-set. Each
identifier1 should be the original import-set, each
identifier2 should not be int the intermediate import-set, and
the identifier2's must be distinct.
Note: Sagittarius does not check importing or exporting non-existing or duplicated bindings. So the following code is actually valid.
(library (foo)
(export bar)
(import (rename (rnrs) (define def) (not-exist define) (define def)))
(def bar)
)
[R6RS] The library (rnrs (6))
is required by R6RS. It just export
all symbols from the libraries which are listed below.
Most of these libraries documentations are from R6RS specification.
[R6RS] This library exports many of the procedure and syntax bindings that are traditionally associated with Scheme.
[R6RS] The define
form is a definition used to create variable
bindings and may appear anywhere other definitions may appear.
The first from of define
binds variable to a new location before
assigning the value of expression to it.
(define add3 (lambda (x) (+ x 3)))
(add3 3)
6
(define first car)
(first '(1 2))
1
The second form of define
is equivalent to
(define _variable_ _unspecified_)
where unspecified is a side-effect-free expression returning an unspecified value.
In the third form of define
, formals must be either a sequence of
zero or more variables, or a sequence of one or more variables followed by a dot
.
and another variable. This form is equivalent to
(define _variable_ (lambda (_formals_) _body ..._))
In the fourth form of define
, formal must be a single variable.
This form is equivalent to
(define _variable_ (lambda _formal_ _body ..._))
[R6RS] The define-syntax
form is a definition used to create keyword
bindings and may appear anywhere other definitions may appear.
Binds keyword to the value of expression, which must evaluate, at macro-expansion time, to a transformer.
[R6RS] quote
evaluates to the datum value represented by datum.
(quote a)
a
(quote #(a b c))
#(a b c)
(quote (+ 1 2))
(+ 1 2)
[R6RS+]A lambda
expression evaluates to a procedure. The
environment in effect when the lambda expression is evaluated is remembered as
part of the procedure. When the procedure is later called with some arguments,
the environment in which the lambda
expression was evaluated is extended
by binding the variables in the parameter list to fresh locations, and the
resulting argument values are stored in those locations. Then, the expressions
in the body of the lambda
expression are evaluated sequentially in
the extended environment. The results of the last expression in the body are
returned as the results of the procedure call.
(lambda (x) (+ x x))
a procedure
((lambda (x) (+ x x)) 4)
8
((lambda (x)
(define (p y) (+ y 1))
(+ (p x) x)) 5)
11
(define reverse-subtract (lambda (x y) (- y x)))
(reverse-subtract 7 10)
3
(define add4 (let ((x 4)) (lambda (y) (+ x y))))
(add4 6)
10
Formals must have one of the following forms:
(<variable1> ...) The procedure takes a fixed number of arguments; when the procedure is called, the arguments are stored in the bindings of the corresponding variables.
<variable> The procedure takes any number of arguments; when the procedure is called, the sequence of arguments is converted into a newly allocated list, and the list is stored in the binding of the <variable>.
(<variable1> ... <variablen> . <variablen+1>)
If a period .
precedes the last variable, then the procedure takes
n or more arguments, where n is the number of parameters before
the period (there must be at least one). The value stored in the binding of
the last variable is a newly allocated list of the arguments left over after
all the other arguments have been matched up against the other
parameters.
((lambda x x) 3 4 5 6)
(3 4 5 6)
((lambda (x y . z) z) 3 4 5 6)
(5 6)
(<variable> ... <extended-spec> ...)
Extended argument specification. Zero or more variables that specifies
required formal argument, followed by an <extended-spec>, a list
begginning with a keyword :optional
, :key
or :rest
.
The <extended-spec> part consists of the optional argument spec, the
keyword argument spec and the rest argument spec. They can appear in any
combinations.
:optional _optspec_ ...
ecifies optional arguments. Each optspec can be either one of the following forms:
_variable_
(_variable_ _init-expr_)
The variable names the formal argument, which is bound to the value
of the actual argument if given, or the value of the expression
init-expr otherwise. If optspec is just a variable, and the
actual argument is not given, then it will be unspecified value.
The expression init-expr is only evaluated if the actual argument is
not given. The scope in which init-expr is evaluated includes the
preceding formal arguments.
((lambda (a b :optional (c (+ a b))) (list a b c)) 1 2)
(1 2 3)
((lambda (a b :optional (c (+ a b))) (list a b c)) 1 2 -1)
(1 2 -1)
((lambda (a b :optional c) (list a b c)) 1 2)
(1 2 #\<unspecified>)
((lambda (:optional (a 0) (b (+ a 1))) (list a b)))
(1 2)
&serious
if more actual arguments than the
number of required and optional arguments are given, unless it also has
:key
or :rest
arguments spec.
((lambda (:optional a b) (list a b)) 1 2 3)
&serious
((lambda (:optional a b :rest r) (list a b r)) 1 2 3)
(1 2 (3))
:key _keyspec_ ... [:allow-other-keys [_variable_]]
ecifies keyword arguments. Each keyspec can be one of the following forms.
_variable_
(_variable_ _init-expr_)
((_keyword_ _variable_) _init-expr_)
(_variable_ _keyword_ _init-expr_)
The variable names the formal argument, which is bound to the actual
argument given with the keyword of the same name as variable. When
the actual is not given, init-expr is evaluated and the result is
bound to variable in the second, third and fourth form, or
unspecified value is bound in the first form.
(define f (lambda (a :key (b (+ a 1)) (c (+ b 1)))
(list a b c)))
(f 10)
(10 11 12)
(f 10 :b 4)
(10 4 5)
(f 10 :c 8)
(10 11 8)
(f 10 :c 1 :b 3)
(10 3 1)
((lambda (:key ((:aa a) -1)) a) ::aa 2)
2
((lambda (:key (a :aa -1)) a) ::aa 2)
2
&serious
if a keyword argument with an unrecognized keyword is
given. Giving :allow-other-keys
in the formals suppresses this
behaviour. If you give variable after :allow-other-keys
, the
list of unrecognized keywords and their arguments are bound to it.
((lambda (:key a) a) :a 1 :b 2)
&serious
((lambda (:key a :allow-other-keys) a) :a 1 :b 2)
1
((lambda (:key a :allow-other-keys z) (list a z)) :a 1 :b 2)
(1 (b 2))
:optional
argument spec, the keyword arguments are
searched after all the optional arguments are bound.
((lambda (:optional a b :key c) (list a b c)) 1 2 :c 3)
(1 2 3)
((lambda (:optional a b :key c) (list a b c)) :c 3)
(c 3 #\<unspecified>)
((lambda (:optional a b :key c) (list a b c)) 1 :c 3)
&serious
:rest _variable_
ecifies the rest argument. If specified without :optional
argument spec, a list of remaining arguments after required arguments are
taken is bound to variable. If specified with :optional
argument spec, the actual arguments are first bound to required and all
optional arguments, and the remaining arguments are bound to
variable.
((lambda (a b :rest z) (list a b z)) 1 2 3 4 5)
(1 2 (3 4 5))
((lambda (a b :optional c d :rest z) (list a b z)) 1 2 3 4 5)
(1 2 3 4 (5))
((lambda (a b :optional c d :rest z) (list a b z)) 1 2 3)
(1 2 3 #\<unspecified> ())
((lambda (:optional a :rest r :key k) (list a r k)) 1 :k 3)
(1 (k 3) 3)
[R6RS]An if
expression is evaluated as follows: first, _test_is evaluated. If it yields a true value, then consequent is evaluated and
its values are returned. Otherwise alternate is evaluated and its values
are returned. If test yields #f and no alternate is specified, then
the result of the expression is unspecified.
[R6RS] Expression is evaluated, and the resulting value is stored in
the location to which variable is bound. Variable must be bound either in
some region enclosing the set!
expression or at the top level. The result
of the set!
expression is unspecified.
Note: R6RS requires to throw syntax violation if variable refers immutable binding. In Sagittarius, however, it won't throw any error.
[R6RS] Each clause must be the form
(_test_ _expression_ ...)
(_test_ => _expression_)
(else _expression_ ...)
The last form can appear only in the last clause.
A cond
expression is evaluated by evaluating the test expressions of
successive clauses in order until one of them evaluates to a true value.
When a test evaluates to a true value, then the remaining expressions in
its clause are evaluated in order, and the results of the last expression
in the clause are returned as the results of the entire cond
expression.
If the selected clause contains only the test and no expressions,
then the value of the test is returned as the result. If the selected
clause uses the =>
alternate form, then the expression is evaluated.
Its value must be a procedure. This procedure should accept one argument; it is
called on the value of the test and the values returned by this procedure
are returned by the cond
expression. If all tests evaluate to #f,
and there is no else
clause, then the conditional expression returns
unspecified values; if there is an else
clause, then its expressions are
evaluated, and the values of the last one are returned.
[R6RS] Key must be an expression. Each clause must have one of the following forms:
((_datum_ ...) _expression_ ...)
(else _expression_ ...)
The last form can appear only in the last clause.
A case
expression is evaluated as follows. Key is evaluated and its
result is compared using eqv?
against the data represented by the _datums_of each clause in turn, proceeding in order from left to right through
the set of clauses. If the result of evaluating key is equivalent to a datum
of a clause, the corresponding expressions are evaluated from left to right
and the results of the last expression in the clause are returned as the
results of the case
expression. Otherwise, the comparison process continues.
If the result of evaluating key is different from every datum in each set,
then if there is an else
clause its expressions are evaluated and the
results of the last are the results of the case
expression; otherwise the
case
expression returns unspecified values.
[R6RS] If there are no tests, #t is returned. Otherwise, the test expressions are evaluated from left to right until a _test_returns #f or the last test is reached. In the former case, the and expression returns #f without evaluating the remaining expressions. In the latter case, the last expression is evaluated and its values are returned.
(and (= 2 2) (> 2 1))
#t
(and (= 2 2) (< 2 1))
(and 1 2 'c '(f g))
(f g)
(and)
#t
[R6RS] If there are no tests, #f is returned. Otherwise, the _test_expressions are evaluated from left to right until a test returns a true value or the last test is reached. In the former case, the or expression returns val without evaluating the remaining expressions. In the latter case, the last expression is evaluated and its values are returned.
(or (= 2 2) (> 2 1))
#t
(or (= 2 2) (< 2 1))
#t
(or #f #f #f)
(or '(b c) (/ 3 0))
(b c)
[R6RS] Bindings must have the form
((_variable1_ _init1_) ...)
where each init is an expression. Any variable must not appear more than once in the variables.
The inits are evaluated in the current environment, the variables are bound to fresh locations holding the results, the body is evaluated in the extended environment, and the values of the last expression of body are returned. Each binding of a variable has body as its region.
[R6RS] Bindings must have the form
((_variable1_ _init1_) ...)
The let*
form is similar to let
, but the inits are evaluated
and bindings created sequentially from left to right, with the region of each
binding including the bindings to its right as well as body. Thus the second
init is evaluated in an environment in which the first binding is visible
and initialized, and so on.
[R6RS] Bindings must have the form
((_variable1_ _init1_) ...)
where each init is an expression. Any variable must not appear more than once in the variables.
The variables are bound to fresh locations, the inits are evaluated
in the resulting environment, each variable is assigned to the result of
the corresponding init, the body is evaluated in the resulting environment,
and the values of the last expression in body are returned. Each binding of
a variable has the entire letrec
expression as its region, making it
possible to define mutually recursive procedures.
In the most common uses of letrec
, all the inits are lambda
expressions and the restriction is satisfied automatically.
[R6RS] Bindings must have the form
((_variable1_ _init1_) ...)
where each init is an expression. Any variable must not appear more than once in the variables.
The variables are bound to fresh locations, each variable is assigned
in left-to-right order to the result of evaluating the corresponding init,
the body is evaluated in the resulting environment, and the values of the
last expression in body are returned. Despite the left-to-right evaluation
and assignment order, each binding of a variable has the entire letrec*
expression as its region, making it possible to define mutually recursive procedures.
[R6RS] Mv-bindings must have the form
((_formals_ _init1_) ...)
where each init is an expression. Any variable must not appear more than once in the set of formals.
The inits are evaluated in the current environment, and the variables
occurring in the formals are bound to fresh locations containing the values
returned by the inits, where the formals are matched to the return
values in the same way that the formals in a lambda
expression are
matched to the arguments in a procedure call. Then, the body is evaluated
in the extended environment, and the values of the last expression of _body_are returned. Each binding of a variable has body as its region. If the
formals do not match, an exception with condition type &assertion
is raised.
[R6RS] Mv-bindings must have the form
((_formals_ _init1_) ...)
where each init is an expression. In each formals, any variable must not appear more than once.
The let*-values
form is similar to let-values
, but the _inits_are evaluated and bindings created sequentially from left to right, with the
region of the bindings of each formals including the bindings to its right
as well as body. Thus the second init is evaluated in an environment
in which the bindings of the first formals is visible and initialized, and
so on.
[R6RS]The begin keyword has two different roles, depending on its context:
It may appear as a form in a body , library body, or top-level body, or directly nested in a begin form that appears in a body. In this case, the begin form must have the shape specified in the first header line. This use of begin acts as a splicing form - the forms inside the body are spliced into the surrounding body, as if the begin wrapper were not actually present. A begin form in a body or library body must be non-empty if it appears after the first expression within the body.
It may appear as an ordinary expression and must have the shape specified in the second header line. In this case, the expressions are evaluated sequentially from left to right, and the values of the last expression are returned. This expression type is used to sequence side effects such as assignments or input and output.
A predicate
is a procedure that always returns a boolean value (#t or #f).
An equivalence predicate
is the computational analogue of a mathematical
equivalence relation (it is symmetric, reflexive, and transitive). Of the
equivalence predicates described in this section, eq?
is the finest or
most discriminating, and equal?
is the coarsest. The eqv?
predicate
is slightly less discriminating than eq?
.
[R6RS] eq?
only sees if the given two objects are the same object
or not, eqv?
compares numbers. equal?
compares the values
equivalence.
On Sagittarius Scheme interned symbol, keyword(only compatible mode), character,
literal string, boolean, fixnum, and '() are used as the same objects. If these
objects indicates the same value then eq?
returns #t.
The following examples are not specified R6RS. But it is always good to know how it works.
(let ((p (lambda (x) x))) (eqv? p p))
#t
(eqv? "" "")
#t
(eqv? "abc" "abc") ;; literal string are the same object
#t
(eqv? "abc" (list->string '(#\a #\b #\c)))
(eqv? '#() '#())
(eqv? (lambda (x) x) (lambda (x) x))
(eqv? (lambda (x) x) (lambda (y) y))
(eqv? +nan.0 +nan.0)
[R6RS] Returns #t if obj is a procedure, otherwise returns #f.
[R6RS] These numerical type predicates can be applied to any kind of argument. They return #t if the object is a number object of the named type, and #f otherwise. In general, if a type predicate is true of a number object then all higher type predicates are also true of that number object. Consequently, if a type predicate is false of a number object, then all lower type predicates are also false of that number object.
If z is a complex number object, then (real? _z_)
is true if and
only if (zero? (imag-part _z_))
and (exact? (imag-part _z_))
are both true.
If x is a real number object, then (rational? _x_)
is true if
and only if there exist exact integer objects k1 and k2 such that
(= _x_ (/ _k1_ _k2_))
and (= (numerator _x_) _k1_)
and (= (denominator _x_) _k2_)
are all true. Thus infinities and
NaNs are not rational number objects.
If q is a rational number objects, then (integer? _q_)
is true
if and only if (= (denominator _q_) 1)
is true. If q is not a rational
number object, then (integer? _q_)
is #f.
[R6RS] These numerical type predicates can be applied to any kind of argument.
The real-valued?
procedure returns #t if the object is a number object and
is equal in the sense of =
to some real number object, or if the object is
a NaN, or a complex number object whose real part is a NaN and whose imaginary part
is zero in the sense of zero?. The rational-valued?
and integer-valued?
procedures return #t if the object is a number object and is equal in the sense
of =
to some object of the named type, and otherwise they return #f.
[R6RS] These numerical predicates provide tests for the exactness of a quantity. For any number object, precisely one of these predicates is true.
[R6RS] The inexact
procedure returns an inexact representation of
z. If inexact number objects of the appropriate type have bounded precision,
then the value returned is an inexact number object that is nearest to the argument.
The exact
procedure returns an exact representation of z. The value
returned is the exact number object that is numerically closest to the argument;
in most cases, the result of this procedure should be numerically equal to its argument.
[R6RS] These procedures return #t if their arguments are (respectively): equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing, and #f otherwise.
[R6RS] These numerical predicates test a number object for a particular property, returning #t or #f.
The zero?
procedure tests if the number object is =
to zero.
The positive?
tests whether it is greater than zero.
The negative?
tests whether it is less than zero.
The odd?
tests whether it is odd.
The even?
tests whether it is even
The finite?
tests whether it is not an infinity and not a NaN.
The infinite?
tests whether it is an infinity.
The nan?
tests whether it is a NaN.
[R6RS] These procedures return the maximum or minimum of their arguments.
[R6RS] These procedures return the sum or product of their arguments.
[R6RS] With two or more arguments, this procedures returns the difference of its arguments, associating to the left. With one argument, however, it returns the additive inverse of its argument.
If this procedure is applied to mixed non-rational real and non-real complex arguments, it returns an unspecified number object.
[R6RS+] If all of the arguments are exact, then the divisors must all be nonzero. With two or more arguments, this procedure returns the quotient of its arguments, associating to the left. With one argument, however, it returns the multiplicative inverse of its argument.
If this procedure is applied to mixed non-rational real and non-real complex arguments, it returns an unspecified number object.
In R6RS, it requires to raise &assertion
when the divisor was 0, on
Sagittarius, however, it returns NaN or infinite number when it is running with
compatible mode. In R6RS mode it raises &assertion
.
[R6RS] Returns the absolute value of its argument.
[R6RS] These procedures implement number-theoretic integer division and
return the results of the corresponding mathematical operations. In each case,
x1 must be neither infinite nor a NaN, and x2 must be nonzero;
otherwise, an exception with condition type &assertion
is raised.
[R6RS] These procedures return the greatest common divisor or least common multiple of their arguments. The result is always non-negative.
[R6RS] These procedures return the numerator or denominator of their argument; the result is computed as if the argument was represented as a fraction in lowest terms. The denominator is always positive. The denominator of 0 is defined to be 1.
[R6RS] These procedures return inexact integer objects for inexact arguments
that are not infinities or NaNs, and exact integer objects for exact rational
arguments. For such arguments, floor
returns the largest integer object
not larger than x. The ceiling
procedure returns the smallest
integer object not smaller than x. The truncate
procedure returns
the integer object closest to x whose absolute value is not larger than
the absolute value of x. The round
procedure returns the closest
integer object to x, rounding to even when x represents a number
halfway between two integers.
Although infinities and NaNs are not integer objects, these procedures return an infinity when given an infinity as an argument, and a NaN when given a NaN.
[R6RS] The rationalize
procedure returns the a number object
representing the simplest rational number differing from x1 by no more than
x2. A rational number r1 is simpler than another rational number
r2 if r1 = p1/q1 and r2 = p2/q2 (in
lowest terms) and |p1| ≤ |p2| and |q1| ≤ |q2|. Thus 3/5
is simpler than 4/7. Although not all rationals are comparable in this ordering
(consider 2/7 and 3/5) any interval contains a rational number that is simpler
than every other rational number in that interval (the simpler 2/5 lies between
2/7 and 3/5). Note that 0 = 0/1 is the simplest rational of all.
[R6RS] These procedures compute the usual transcendental functions. The
exp
procedure computes the base-e exponential of z.
The log
procedure with a single argument computes the natural logarithm
of z (not the base-ten logarithm); (log _z1_ _z2_)
computes
the base-z2 logarithm of z1.
The asin
, acos
, and atan
procedures compute arcsine,
arccosine, and arctangent, respectively.
The two-argument variant of atan
computes
(angle (make-rectangular _x2_ _x1_))
.
[R6RS] Returns the principal square root of z. For rational z, the result has either positive real part, or zero real part and non-negative imaginary part.
The sqrt procedure may return an inexact result even when given an exact argument.
[R6RS] Returns z1 raised to the power z2. For nonzero z1,
this is e^{z2 log z1}. 0.0z is 1.0 if z = 0.0, and 0.0 if (real-part _z_)
is
positive. For other cases in which the first argument is zero, an unspecified
number object(+nan.0+nan.0i
) is returned.
For an exact real number object z1 and an exact integer object z2,
(expt _z1_ _z2_)
must return an exact result. For all other values
of z1 and z2, (expt _z1_ _z2_)
may return an inexact
result, even when both z1 and z2 are exact.
[R6RS] Suppose a1, a2, a3, and a4 are real numbers, and c is a complex number such that the following holds:
_c = a1 + a2 ^ i = a3 e ^ ia4_Then, if x1, x2, x3, and x4 are number objects representing
a1, a2, a3, and a4, respectively,
(make-rectangular _x1_ _x2_)
returns c, and
(make-polar _x3_ _x4_)
returns c.
[R6RS+] Radix must be an exact integer object, between 2, and 32. If
omitted, radix defaults to 10. In Sagittarius precision will be
ignored. The number->string
procedure takes a number object and a radix
and returns as a string an external representation of the given number object in
the given radix such that
(let ((number _z_) (radix _radix_))
(eqv? (string->number
(number->string number radix)
radix)
number))
is true.
[R6RS+] Returns a number object with maximally precise representation
expressed by the given string. Radix must be an exact integer object,
between 2, and 32. If supplied, radix is a default radix that may be
overridden by an explicit radix prefix in string (e.g., "#o177"). If
radix is not supplied, then the default radix is 10. If string is
not a syntactically valid notation for a number object or a notation for a
rational number object with a zero denominator, then string->number
returns #f.
These number->string
and string->number
's resolutions of radix are
taken from Gauche.
[R6RS] Returns #t if obj is #f, and returns #f otherwise.
[R6RS] Returns #t if obj is either #t or #f and returns #f otherwise.
[R6RS] Returns #t if the booleans are the same.
A pair is a compound structure with two fields called the car and cdr fields
(for historical reasons). Pairs are created by the procedure cons
. The car
and cdr fields are accessed by the procedures car
and cdr
.
Pairs are used primarily to represent lists. A list can be defined recursively as either the empty list or a pair whose cdr is a list. More precisely, the set of lists is defined as the smallest set X such that
The empty list is in
If list is in X, then any pair whose cdr field contains _list_is also in X.
The objects in the car fields of successive pairs of a list are the elements of the list. For example, a two-element list is a pair whose car is the first element and whose cdr is a pair whose car is the second element and whose cdr is the empty list. The length of a list is the number of elements, which is the same as the number of pairs.
The empty listis a special object of its own type. It is not a pair. It has no elements and its length is zero.
A chain of pairs not ending in the empty list is called an improper list. Note that an improper list is not a list. The list and dotted notations can be combined to represent improper lists:
(a b c . d)
is equivalent to
(a . (b . (c . d)))
Whether a given pair is a list depends upon what is stored in the cdr field.
[R6RS] Returns #t if obj is a pair, and otherwise returns #f.
[R6RS] Returns a newly allocated pair whose car is obj1 and whose
cdr is obj2. The pair is guaranteed to be different (in the sense of
eqv?
) from every existing object.
[R6RS] Returns the contents of the car/cdr field of pair.
:
[R6RS] These procedures are compositions of car
and cdr
,
where for example caddr
could be defined by
(define caddr (lambda (x) (car (cdr (cdr x)))))
.
Arbitrary compositions, up to four deep, are provided. There are twenty-eight of these procedures in all.
[R6RS] Returns #t if obj is the empty list, #f otherwise.
[R6RS] Returns #t if obj is a list, #f otherwise. By definition, all lists are chains of pairs that have finite length and are terminated by the empty list.
[R6RS] Returns a newly allocated list of its arguments.
[R6RS+] Returns the length of list. If the list is improper list, it returns -1 If the list is infinite list , it returns -2.
[R6RS] Returns a possibly improper list consisting of the elements of the first list followed by the elements of the other lists, with _obj_as the cdr of the final pair. An improper list results if obj is not a list.
[R6RS] Returns a newly allocated list consisting of the elements of list in reverse order.
[R6RS+] The list-tail
procedure returns the subchain of pairs of
list obtained by omitting the first k elements. If _fallback_is given and k is out of range, it returns fallback otherwise
&assertion
is raised.
[R6RS+] The list-ref
procedure returns the _k_th element of
list. If fallback is given and k is out of range, it returns
fallback otherwise &assertion
is raised.
[R6RS+ SRFI-1] The map
procedure applies proc element-wise to
the elements of the lists and returns a list of the results, in order. The
order in which proc is applied to the elements of the lists is unspecified.
If multiple returns occur from map
, the values returned by earlier returns
are not mutated. If the given lists are not the same length, when the
shortest list is processed the map
will stop.
[R6RS+ SRFI-1] The for-each
procedure applies proc element-wise
to the elements of the lists for its side effects, in order from the first
elements to the last. The return values of for-each
are unspecified. If
the given lists are not the same length, when the shortest list is
processed the for-each
will stop.
[R6RS] Returns #t if obj is a symbol, otherwise returns #f.
[R6RS] Returns the name of symbol as an immutable string.
[R6RS] Returns #t if the symbols are the same, i.e., if their names are spelled the same.
[R6RS] Returns the symbol whose name is string.
Characters are objects that represent Unicode scalar values.
[R6RS] Returns #t if obj is a character, otherwise returns #f.
[R6RS] Sv must be a Unicode scalar value, i.e., a non-negative exact integer object in [0, #xD7FF] ∪ [#xE000, #x10FFFF].
Given a character, char->integer
returns its Unicode scalar value as an
exact integer object. For a Unicode scalar value sv, integer->char
returns its associated character.
[R6RS] These procedures impose a total ordering on the set of characters according to their Unicode scalar values.
Strings are sequences of characters. The length of a string is the number of characters that it contains. This number is fixed when the string is created. The valid indices of a string are the integers less than the length of the string. The first character of a string has index 0, the second has index 1, and so on.
[R6RS] Returns #t if obj is a string, otherwise returns #f.
[R6RS] Returns a newly allocated string of length k. If _char_is given, then all elements of the string are initialized to char, otherwise
the contents of the string are #\space
.
These are equivalence:
(make-string 10)
(code (make-string 10 #\\space))
[R6RS] Returns a newly allocated string composed of the arguments.
[R6RS] Returns the number of characters in the given string as an exact integer object.
[R6RS+] The string-ref
procedure returns character. If a third
argument is given ant k is not a valid index, it returns fallback,
otherwise raises &assertion
.
k of string using zero-origin indexing.
[R6RS] Returns #t if the strings are the same length and contain the
same characters in the same positions. Otherwise, the string=?
procedure
returns #f.
[R6RS] These procedures are the lexicographic extensions to strings of the
corresponding orderings on characters. For example, string<?
is the
lexicographic ordering on strings induced by the ordering char<?
on
characters. If two strings differ in length but are the same up to the length of
the shorter string, the shorter string is considered to be lexicographically less
than the longer string.
[R6RS] String must be a string, and start and end must be exact integer objects satisfying
0 ≤ start ≤ end ≤ (string-length _string_)
.
The substring
procedure returns a newly allocated string formed from the
characters of string beginning with index start (inclusive) and ending with
index end (exclusive).
[R6RS] Returns a newly allocated string whose characters form the concatenation of the given strings.
[R6RS+] List must be a list of characters.
The string->list
procedure returns a newly allocated list of the
characters that make up the given string.
The list->string
procedure returns a newly allocated string formed from
the characters in list.
The string->list
and list->string
procedures are inverses so far
as equal?
is concerned.
If optional argument start and end are given, it restrict the conversion range. It convert from start (inclusive) to end(exclusive).
If only start is given, then the end is the length of given string.
[R6RS+] Proc should accept as many arguments as there are strings.
The string-for-each
procedure applies proc element-wise to the
characters of the strings for its side effects, in order from the first
characters to the last. The return values of string-for-each
are unspecified.
Analogous to for-each.
[R6RS+] Returns a newly allocated copy of the given string.
If optional argument start was given, the procedure copies from the given start index.
If optional argument end was given, the procedure copies to the given end index (exclusive).
Vectors are heterogeneous structures whose elements are indexed by integers. A vector typically occupies less space than a list of the same length, and the average time needed to access a randomly chosen element is typically less for the vector than for the list.
The length of a vector is the number of elements that it contains. This number is a non-negative integer that is fixed when the vector is created. The valid indices of a vector are the exact non-negative integer objects less than the length of the vector. The first element in a vector is indexed by zero, and the last element is indexed by one less than the length of the vector.
[R6RS] Returns #t if obj is a vector. Otherwise returns #f.
[R6RS] Returns a newly allocated vector of k elements. If a second argument is given, then each element is initialized to fill. Otherwise the initial contents of each element is unspecified.
[R6RS] Returns a newly allocated vector whose elements contain the given
arguments. Analogous to list
.
[R6RS] Returns the number of elements in vector as an exact integer object.
[R6RS+] The vector-ref
procedure returns the contents of element
k of vector. If a third argument is given and k is not a valid
index, it returns fallback, otherwise raises &assertion
.
[R6RS] K must be a valid index of vector. The vector-set!
procedure stores obj in element k of vector, and returns
unspecified values.
It raises &assertion
when it attempt to modify immutable vector on R6RS
mode.
[R6RS+] The vector->list
procedure returns a newly allocated list
of the objects contained in the elements of vector. The list->vector
procedure returns a newly created vector initialized to the elements of the list
list. The optional start and end arguments limit the range of
the source.
(vector->list '#(1 2 3 4 5))
(1 2 3 4 5)
(list->vector '(1 2 3 4 5))
#(1 2 3 4 5)
(vector->list '#(1 2 3 4 5) 2 4)
(3 4)
(list->vector (circular-list 'a 'b 'c) 1 6)
#(b c a b c)
[R6RS+] Stores fill in every element of vector and returns unspecified values. Optional start and end limits the range of effect between start-th index (inclusive) to end-th index (exclusive). Start defaults to zero, and end defaults to the length of vector.
[R6RS+] Proc should accept as many arguments as there are vectors.
The vector-map
procedure applies proc element-wise to the elements
of the vectors and returns a vector of the results, in order. If multiple
returns occur from vector-map
, the return values returned by earlier
returns are not mutated.
Analogous to map
.
[R6RS+] Proc should accept as many arguments as there are vectors.
The vector-for-each
procedure applies proc element-wise to the
elements of the vectors for its side effects, in order from the first
elements to the last. The return values of vector-for-each
are unspecified.
Analogous to for-each
.
[R6RS] Who must be a string or a symbol or #f. Message must be a string. The irritants are arbitrary objects.
These procedures raise an exception. The error
procedure should be called
when an error has occurred, typically caused by something that has gone wrong in
the interaction of the program with the external world or the user. The
assertion-violation
procedure should be called when an invalid call to a
procedure was made, either passing an invalid number of arguments, or passing an
argument that it is not specified to handle.
The who argument should describe the procedure or operation that detected the exception. The message argument should describe the exceptional situation. The irritants should be the arguments to the operation that detected the operation.
[R6RS] Rest-args must be a list. Proc should accept n arguments,
where n is number of args plus the length of rest-args. The apply
procedure calls proc with the elements of the list
(append (list _arg1_ ...) _rest-args_)
as the actual arguments.
If a call to apply
occurs in a tail context, the call to proc
is
also in a tail context.
[R6RS] Proc should accept one argument. The procedure
call-with-current-continuation
(which is the same as the procedure
call/cc
) packages the current continuation as an "escape procedure" and
passes it as an argument to proc. The escape procedure is a Scheme procedure
that, if it is later called, will abandon whatever continuation is in effect a
that later time and will instead reinstate the continuation that was in effect
when the escape procedure was created. Calling the escape procedure may cause
the invocation of before and after procedures installed using
dynamic-wind
.
The escape procedure accepts the same number of arguments as the continuation
of the original call to call-with-current-continuation
.
[R6RS] Returns objs as multiple values.
[R6RS] Producer must be a procedure and should accept zero arguments.
Consumer must be a procedure and should accept as many values as
producer returns. The call-with-values
procedure calls _producer_with no arguments and a continuation that, when passed some values, calls the
consumer procedure with those values as arguments. The continuation for
the call to consumer is the continuation of the call to call-with-values
.
If a call to call-with-values
occurs in a tail context, the call to
consumer is also in a tail context.
[R6RS] Before, thunk, and after must be procedures, and
each should accept zero arguments. These procedures may return any number of
values. The dynamic-wind
procedure calls thunk without arguments,
returning the results of this call. Moreover, dynamic-wind
calls _before_without arguments whenever the dynamic extent of the call to thunk is
entered, and after without arguments whenever the dynamic extent of the
call to thunk is exited. Thus, in the absence of calls to escape procedures
created by call-with-current-continuation
, dynamic-wind
calls
before, thunk, and after, in that order.
[R6RS] “Named let” is a variant on the syntax of let
that provides
a general looping construct and may also be used to express recursion. It has
the same syntax and semantics as ordinary let
except that _variable_is bound within body to a procedure whose parameters are the bound variables
and whose body is body. Thus the execution of body may be repeated
by invoking the procedure named by variable.
[R6RS] "Quasiquote" expressions is useful for constructing a list or vector structure when some but not all of the desired structure is known in advance.
Qq-template should be as specified by the grammar at the end of this entry.
If no unquote
or unquote-splicing
forms appear within the
qq-template, the result of evaluating (quasiquote _qq-template_)
is equivalent to the result of evaluating (quote _qq-template_)
.
If an (unquote _expression_ ...)
form appears inside a qq-template,
however, the expressions are evaluated ("unquoted")
and their results are
inserted into the structure instead of the unquote
form.
If an (unquote-splicing _expression_ ...)
form appears inside a
qq-template, then the expressions must evaluate to lists; the opening and
closing parentheses of the lists are then "stripped away" and the elements of
the lists are inserted in place of the unquote-splicing
form.
Any unquote-splicing
or multi-operand unquote form must appear only within
a list or vector qq-template.
Note: even though unquote
and unquote-splicing
are bounded, however
it does not work with import prefix nor renamed import. This may be fixed in future.
The let-syntax
and letrec-syntax
forms bind keywords. On R6RS mode
it works like a begin
form, a let-syntax
or letrec-syntax
form may appear in a definition context, in which case it is treated as a
definition, and the forms in the body must also be definitions. A let-syntax
or letrec-syntax
form may also appear in an expression context, in which
case the forms within their bodies must be expressions.
[R6RS] Bindings must have the form
((_keyword_ _expression_) ...)
Each keyword is an identifier, and each expression is an expression
that evaluates, at macro-expansion time, to a transformer. Transformers may be
created by syntax-rules
or identifier-syntax
or by one of the other
mechanisms described in library chapter on "syntax-case".
It is a syntax violation for keyword to appear more than once in the list
of keywords being bound.
The forms are expanded in the syntactic environment obtained by extending
the syntactic environment of the let-syntax
form with macros whose keywords
are the keywords, bound to the specified transformers. Each binding of a
keyword has the forms as its region.
[R6RS] Bindings must have the form
((_keyword_ _expression_) ...)
Each keyword is an identifier, and each expression is an expression
that evaluates, at macro-expansion time, to a transformer. Transformers may be
created by syntax-rules
or identifier-syntax
or by one of the other
mechanisms described in library chapter on "syntax-case".
It is a syntax violation for keyword to appear more than once in the list
of keywords being bound.
The forms are expanded in the syntactic environment obtained by extending
the syntactic environment of the letrec-syntax
form with macros whose
keywords are the keywords, bound to the specified transformers. Each
binding of a keyword has the bindings as well as the forms within its
region, so the transformers can transcribe forms into uses of the macros
introduced by the letrec-syntax
form.
Note: The forms of a let-syntax
and a letrec-syntax
form are
treated, whether in definition or expression context, as if wrapped in an implicit
begin
on R6RS mode, it is, then, treated as if wrapped in an implicit
let
on compatible mode. Thus on compatible mode, it creates a scope.
In R6RS, it requires '_'
'...'
as bounded symbols but in Sagittarius
these are not bound. And if import clause has rename or prefix these auxiliary
syntax are not be renamed or prefixed. This behaivour may be fixed in future.
[R6RS] Each literal must be an identifier. Each rule must have the following form:
(srpattern template)
An srpattern is a restricted form of pattern, namely, a nonempty
pattern in one of four parenthesized forms below whose first subform is
an identifier or an underscore _
. A pattern is an identifier,
constant, or one of the following.
(pattern ...)
(pattern pattern ... . pattern)
(pattern ... pattern ellipsis pattern ...)
(pattern ... pattern ellipsis pattern ... . pattern)
#(pattern ...)
#(pattern ... pattern ellipsis pattern ...)
An ellipsis is the identifier "..."
(three periods).
A template is a pattern variable, an identifier that is not a pattern variable, a pattern datum, or one of the following.
(subtemplate ...)
(subtemplate ... . template)
#(subtemplate ...)
A subtemplate is a template followed by zero or more ellipses.
An instance of syntax-rules
evaluates, at macro-expansion time, to a new
macro transformer by specifying a sequence of hygienic rewrite rules. A use of a
macro whose keyword is associated with a transformer specified by syntax-rules
is matched against the patterns contained in the rules, beginning with the
leftmost rule. When a match is found, the macro use is transcribed hygienically
according to the template. It is a syntax violation when no match is found.
[R6RS] The ids must be identifiers. The templates must be as
for syntax-rules
.
When a keyword is bound to a transformer produced by the first form of
identifier-syntax
, references to the keyword within the scope of the
binding are replaced by template.
(define p (cons 4 5))
(define-syntax p.car (identifier-syntax (car p)))
p.car
4
(set! p.car 15)
&syntax exception
The second, more general, form of identifier-syntax
permits the transformer
to determine what happens when set!
is used. In this case, uses of the
identifier by itself are replaced by template1, and uses of set!
with
the identifier are replaced by template2
(define p (cons 4 5))
(define-syntax p.car
(identifier-syntax
(_ (car p))
((set! _ e) (set-car! p e))))
(set! p.car 15)
p.car
15
p
(15 5)
[R6RS] The procedures exported by the (rnrs unicode (6))
library
provide access to some aspects of the Unicode semantics for characters and strings:
category information, case-independent comparisons, case mappings, and normalization.
Some of the procedures that operate on characters or strings ignore the difference between upper case and lower case. These procedures have "-ci" (for "case insensitive") embedded in their names.
[R6RS] These procedures take a character argument and return a character
result. If the argument is an upper-case or title-case character, and if there
is a single character that is its lower-case form, then char-downcase
returns that character. If the argument is a lower-case or title-case character,
and there is a single character that is its upper-case form, then char-upcase
returns that character. If the argument is a lower-case or upper-case character,
and there is a single character that is its title-case form, then char-titlecase
returns that character. If the argument is not a title-case character and there
is no single character that is its title-case form, then char-titlecase
returns the upper-case form of the argument. Finally, if the character has a
case-folded character, then char-foldcase
returns that character. Otherwise
the character returned is the same as the argument. For Turkic characters İ (#\x130)
and ı (#\x131), char-foldcase
behaves as the identity function; otherwise
char-foldcase
is the same as char-downcase
composed with
char-upcase
.
[R6RS] These procedures are similar to char=?
, etc., but operate on
the case-folded versions of the characters.
[R6RS] These procedures return #t if their arguments are alphabetic, numeric, whitespace, upper-case, lower-case, or title-case characters, respectively; otherwise they return #f.
A character is alphabetic if it has the Unicode "Alphabetic" property. A character is numeric if it has the Unicode "Numeric" property. A character is whitespace if has the Unicode "White_Space" property. A character is upper case if it has the Unicode "Uppercase" property, lower case if it has the "Lowercase" property, and title case if it is in the Lt general category.
[R6RS] Returns a symbol representing the Unicode general category of char, one of Lu, Ll, Lt, Lm, Lo, Mn, Mc, Me, Nd, Nl, No, Ps, Pe, Pi, Pf, Pd, Pc, Po, Sc, Sm, Sk, So, Zs, Zp, Zl, Cc, Cf, Cs, Co, or Cn.
[R6RS+][SRFI-13] These procedures take a string argument and return a
string result. They are defined in terms of Unicode's locale-independent case
mappings from Unicode scalar-value sequences to scalar-value sequences. In
particular, the length of the result string can be different from the length of
the input string. When the specified result is equal in the sense of
string=?
to the argument, these procedures may return the argument
instead of a newly allocated string.
The string-upcase
procedure converts a string to upper case;
string-downcase
converts a string to lower case.
The string-foldcase
procedure converts the string to its case-folded
counterpart, using the full case-folding mapping, but without the special
mappings for Turkic languages.
The string-titlecase
procedure converts the first cased character of each
word via char-titlecase
, and downcases all other cased characters.
If the optional argument start and end are given, these must be exact integer and the procedures will first substring the given string with range start and end then convert it.
[R6RS] These procedures are similar to string=?
, etc., but operate
on the case-folded versions of the strings.
[R6RS] These procedures take a string argument and return a string result,
which is the input string normalized to Unicode normalization form D, KD, C, or KC,
respectively. When the specified result is equal in the sense of string=?
to the argument, these procedures may return the argument instead of a newly
allocated string.
Many applications deal with blocks of binary data by accessing them in various
ways-extracting signed or unsigned numbers of various sizes. Therefore, the
(rnrs bytevectors (6))
library provides a single type for blocks of binary
data with multiple ways to access that data. It deals with integers and
floating-point representations in various sizes with specified endianness.
Bytevectorsare objects of a disjoint type. Conceptually, a bytevector represents a sequence of 8-bit bytes. The description of bytevectors uses the term byte for an exact integer object in the interval { - 128, ..., 127} and the term octet for an exact integer object in the interval {0, ..., 255}. A byte corresponds to its two's complement representation as an octet.
The length of a bytevector is the number of bytes it contains. This number is fixed. A valid index into a bytevector is an exact, non-negative integer object less than the length of the bytevector. The first byte of a bytevector has index 0; the last byte has an index one less than the length of the bytevector.
Generally, the access procedures come in different flavors according to the size of the represented integer and the endianness of the representation. The procedures also distinguish signed and unsigned representations. The signed representations all use two's complement.
Like string literals, literals representing bytevectors do not need to be quoted:
#vu8(12 23 123)
#vu8(12 23 123)
[R6RS] This library provides a single type for blocks of binary data with multiple ways to access that data.
[R6RS] The name of symbol must be a symbol describing an endianness.
(endianness _symbol_)
evaluates to the symbol named symbol.
Whenever one of the procedures operating on bytevectors accepts an endianness as
an argument, that argument must be one of these symbols. It is a syntax violation
for symbol to be anything other than an endianness symbol supported by the Sagittarius.
Currently, Sagittarius supports these symbols; big
, little
and native
.
[R6RS] Returns the endianness symbol associated platform endianness. This may be a symbol either big or little.
[R6RS] Returns #t if obj is a bytevector, otherwise returns #f.
[R6RS] Returns a newly allocated bytevector of k bytes.
If the fill argument is missing, the initial contents of the returned bytevector are 0.
If the fill argument is present, it must be an exact integer object in the interval {-128, ..., 255} that specifies the initial value for the bytes of the bytevector: If fill is positive, it is interpreted as an octet; if it is negative, it is interpreted as a byte.
[R6RS] Returns, as an exact integer object, the number of bytes in bytevector.
[R6RS] Returns #t if bytevector1 and bytevector2 are equal-that is, if they have the same length and equal bytes at all valid indices. It returns #f otherwise.
[R6RS+] The fill argument is as in the description of the
make-bytevector
procedure. The bytevector-fill!
procedure stores
fill in every element of bytevector and returns unspecified values.
Analogous to vector-fill!
.
If optional arguments start or end is given, then the procedure restricts the range of filling from start to end (exclusive) index of bytevector. When end is omitted then it uses the length of the given bytevector.
[R6RS] Source and target must be bytevectors. Source-start, target-start, and k must be non-negative exact integer objects that satisfy
0 <= source-start <= source-start + k <= _source-length_0 <= target-start <= target-start + k <= _target-length_where source-length is the length of source and _target-length_is the length of target.
The bytevector-copy!
procedure copies the bytes from source at indices
source-start, ... source-start + k - 1
to consecutive indices in target starting at target-index.
This returns unspecified values.
_ :optional (start 0) (end -1)
[R6RS+] Returns a newly allocated copy of bytevector.
If optional argument start was given, the procedure copies from the given start index.
If optional argument end was given, the procedure copies to the given end index (exclusive).
[R6RS] K must be a valid index of bytevector.
The bytevector-u8-ref
procedure returns the byte at index k of
bytevector, as an octet.
The bytevector-s8-ref
procedure returns the byte at index k of
bytevector, as a (signed) byte.
[R6RS] K must be a valid index of bytevector.
The bytevector-u8-set!
procedure stores octet in element _k_of bytevector.
The bytevector-s8-set!
procedure stores the two's-complement
representation of byte in element k of bytevector.
Both procedures return unspecified values.
[R6RS] List must be a list of octets.
The bytevector->u8-list
procedure returns a newly allocated list of the
octets of bytevector in the same order.
The u8-list->bytevector
procedure returns a newly allocated bytevector
whose elements are the elements of list list, in the same order. It is
analogous to list->vector
.
[R6RS] Size must be a positive exact integer object. K, ..., k + size - 1 must be valid indices of bytevector.
The bytevector-uint-ref
procedure retrieves the exact integer object
corresponding to the unsigned representation of size size and specified
by endianness at indices k, ..., k + size - 1.
The bytevector-sint-ref
procedure retrieves the exact integer object
corresponding to the two's-complement representation of size size and
specified by endianness at indices k, ..., k + size - 1.
For bytevector-uint-set!
, n must be an exact integer object in the
interval _{0, ..., 256 ^ "size" - 1}_The bytevector-uint-set!
procedure stores the unsigned representation of
size size and specified by endianness into bytevector at indices
k, ..., k + size - 1.
For bytevector-sint-set!
, n must be an exact integer object in the
interval {-256 ^ "size" / 2, ..., 256 ^ "size" / 2 - 1}.
bytevector-sint-set!
stores the two's-complement representation of size
size and specified by endianness into bytevector at indices
k, ..., k + size - 1.
The ...-set!
procedures return unspecified values.
[R6RS] Size must be a positive exact integer object. For
uint-list->bytevector
, list must be a list of exact integer objects
in the interval {0, ..., 256 ^ "size" - 1}. For sint-list->bytevector
,
list must be a list of exact integer objects in the interval
{-256 ^ "size"/2, ..., 256 ^ "size"/2 - 1}. The length of _bytevector_or, respectively, of list must be divisible by size.
These procedures convert between lists of integer objects and their consecutive
representations according to size and endianness in the _bytevector_objects in the same way as bytevector->u8-list
and u8-list->bytevector
do for one-byte representations.
[R6RS] K must be a valid index of bytevector; so must k + 1.
For bytevector-u16-set!
and bytevector-u16-native-set!
, _n_must be an exact integer object in the interval {0, ..., 2 ^ 16 - 1}.
For bytevector-s16-set!
and bytevector-s16-native-set!
, _n_must be an exact integer object in the interval {-2 ^ 15, ..., 2 ^ 15 - 1}.
These retrieve and set two-byte representations of numbers at indices _k_and k + 1, according to the endianness specified by endianness.
The procedures with u16
in their names deal with the unsigned representation;
those with s16
in their names deal with the two's-complement representation.
The procedures with native
in their names employ the native endianness,
and work only at aligned indices: k must be a multiple of 2.
The ...-set!
procedures return unspecified values.
[R6RS] K must be a valid index of bytevector; so must k + 3.
For bytevector-u32-set!
and bytevector-u32-native-set!
, _n_must be an exact integer object in the interval {0, ..., 2 ^ 32 - 1}.
For bytevector-s32-set!
and bytevector-s32-native-set!
, _n_must be an exact integer object in the interval {-2 ^ 31, ..., 2 ^ 32 - 1}.
These retrieve and set two-byte representations of numbers at indices _k_and k + 3, according to the endianness specified by endianness.
The procedures with u32
in their names deal with the unsigned representation;
those with s32
in their names deal with the two's-complement representation.
The procedures with native
in their names employ the native endianness,
and work only at aligned indices: k must be a multiple of 4.
The ...-set!
procedures return unspecified values.
[R6RS] K must be a valid index of bytevector; so must k + 7.
For bytevector-u64-set!
and bytevector-u64-native-set!
, _n_must be an exact integer object in the interval {0, ..., 2 ^ 64 - 1}.
For bytevector-s64-set!
and bytevector-s64-native-set!
, _n_must be an exact integer object in the interval {-2 ^ 63, ..., 2 ^ 64 - 1}.
These retrieve and set two-byte representations of numbers at indices _k_and k + 7, according to the endianness specified by endianness.
The procedures with u64
in their names deal with the unsigned representation;
those with s64
in their names deal with the two's-complement representation.
The procedures with native
in their names employ the native endianness,
and work only at aligned indices: k must be a multiple of 8.
The ...-set!
procedures return unspecified values.
[R6RS] K, …, k + 3 must be valid indices of bytevector.
For bytevector-ieee-single-native-ref
, k must be a multiple of 4.
These procedures return the inexact real number object that best represents the IEEE-754 single-precision number represented by the four bytes beginning at index k.
[R6RS] K, …, k + 7 must be valid indices of bytevector.
For bytevector-ieee-double-native-ref
, k must be a multiple of 8.
These procedures return the inexact real number object that best represents the IEEE-754 double-precision number represented by the four bytes beginning at index k.
[R6RS] K, …, k + 3 must be valid indices of bytevector.
For bytevector-ieee-single-native-set!
, k must be a multiple of 4.
These procedures store an IEEE-754 single-precision representation of _x_into elements k through k + 3 of bytevector, and return unspecified values.
[R6RS] K, …, k + 7 must be valid indices of bytevector.
For bytevector-ieee-double-native-set!
, k must be a multiple of 8.
These procedures store an IEEE-754 double-precision representation of _x_into elements k through k + 7 of bytevector, and return unspecified values.
This section describes procedures that convert between strings and bytevectors containing Unicode encodings of those strings. When decoding bytevectors, encoding errors are handled as with the replace semantics of textual I/O: If an invalid or incomplete character encoding is encountered, then the replacement character U+FFFD is appended to the string being generated, an appropriate number of bytes are ignored, and decoding continues with the following bytes.
[R6RS+] [R7RS] Returns a newly allocated (unless empty) bytevector that contains the UTF-8 encoding of the given string.
If the optional argument start is given, the procedure converts given string from start index (inclusive).
If the optional argument end is given, the procedure converts given string to end index (exclusive).
These optional arguments must be fixnum if it's given.
[R6RS] If endianness is specified, it must be the symbol big
or the symbol little
. The string->utf16
procedure returns a newly
allocated (unless empty) bytevector that contains the UTF-16BE or UTF-16LE
encoding of the given string (with no byte-order mark). If _endianness_is not specified or is big
, then UTF-16BE is used. If endianness is
little
, then UTF-16LE is used.
[R6RS] If endianness is specified, it must be the symbol big
or the symbol little
. The string->utf32
procedure returns a newly
allocated (unless empty) bytevector that contains the UTF-32BE or UTF-32LE
encoding of the given string (with no byte-order mark). If _endianness_is not specified or is big
, then UTF-32BE is used. If endianness is
little
, then UTF-32LE is used.
[R6RS] Returns a newly allocated (unless empty) string whose character sequence is encoded by the given bytevector.
If the optional argument start is given, the procedure converts given string from start index (inclusive).
If the optional argument end is given, the procedure converts given string to end index (exclusive).
These optional arguments must be fixnum if it's given.
[R6RS] Endianness must be the symbol big
or the symbol
little
. The utf16->string
procedure returns a newly allocated
(unless empty) string whose character sequence is encoded by the given
bytevector. Bytevector is decoded according to UTF-16BE or UTF-16LE:
If endianness-mandatory? is absent or #f, utf16->string
determines
the endianness according to a UTF-16 BOM at the beginning of _bytevector_if a BOM is present; in this case, the BOM is not decoded as a character. Also
in this case, if no UTF-16 BOM is present, endianness specifies the endianness
of the encoding. If endianness-mandatory? is a true value, _endianness_specifies the endianness of the encoding, and any UTF-16 BOM in the encoding is
decoded as a regular character.
[R6RS] Endianness must be the symbol big
or the symbol
little
. The utf32->string
procedure returns a newly allocated
(unless empty) string whose character sequence is encoded by the given
bytevector. Bytevector is decoded according to UTF-32BE or UTF-32LE:
If endianness-mandatory? is absent or #f, utf32->string
determines
the endianness according to a UTF-32 BOM at the beginning of _bytevector_if a BOM is present; in this case, the BOM is not decoded as a character. Also
in this case, if no UTF-32 BOM is present, endianness specifies the endianness
of the encoding. If endianness-mandatory? is a true value, _endianness_specifies the endianness of the encoding, and any UTF-32 BOM in the encoding is
decoded as a regular character.
[R6RS] The (rnrs lists (6))
library, which contains various useful
procedures that operate on lists.
[R6RS] Proc should accept one argument and return a single value.
Proc should not mutate list. The find
procedure applies _proc_to the elements of list in order. If proc returns a true value for
an element, find immediately returns that element. If proc returns #f for
all elements of the list, find returns #f.
[R6RS+] Applies pred across each element of lists, and returns
#f as soon as pred returns #f. If all application of pred return a
non-false value, for-all
returns the last result of the applications.
[R6RS+] Applies pred across each element of lists, and returns as soon as pred returns a non-false value. The return value of any is the non-false value pred returned. If lists are exhausted before _pred_returns a non-false value, #f is returned.
Note: R6RS requires the same length list for for-all
and exists
.
On Sagittarius, however, these can accept different length list and it will
finish to process when the shortest list is finish to process.
[R6RS] Proc should accept one argument and return a single value.
The filter
procedure applies proc to each element of list and
returns a list of the elements of list for which proc returned a true
value. The partition
procedure also applies proc to each element of
list, but returns two values, the first one a list of the elements of _list_for which proc returned a true value, and the second a list of the elements
of list for which proc returned #f. In both cases, the elements of the
result list(s) are in the same order as they appear in the input list. If multiple
returns occur from filter
or partitions
, the return values returned
by earlier returns are not mutated.
[R6RS+] Combine must be a procedure. It should accept one more argument
than there are lists and return a single value. It should not mutate the
list arguments. The fold-left
procedure iterates the _combine_procedure over an accumulator value and the elements of the lists from left
to right, starting with an accumulator value of nil. More specifically,
fold-left
returns nil if the lists are empty. If they are not
empty, combine is first applied to nil and the respective first
elements of the lists in order. The result becomes the new accumulator
value, and combine is applied to the new accumulator value and the respective
next elements of the list. This step is repeated until the end of the
list is reached; then the accumulator value is returned.
[R6RS+] Combine must be a procedure. It should accept one more argument
than there are lists and return a single value. Combine should not
mutate the list arguments. The fold-right
procedure iterates the
combine procedure over the elements of the lists from right to left
and an accumulator value, starting with an accumulator value of nil. More
specifically, fold-right
returns nil if the lists are empty. If they
are not empty, combine is first applied to the respective last elements of
the lists in order and nil. The result becomes the new accumulator
value, and combine is applied to the respective previous elements of the
lists and the new accumulator value. This step is repeated until the beginning
of the list is reached; then the accumulator value is returned.
Note: R6RS requires the same length list for fold-left
and fold-right
.
On Sagittarius, however, these can accept different length list and it will finish
to process when the shortest list is finish to process.
[R6RS] Proc should accept one argument and return a single value. _Proc_should not mutate list.
Each of these procedures returns a list of the elements of list that do not
satisfy a given condition. The remp
procedure applies proc to each
element of list and returns a list of the elements of list for which
proc returned #f. The remove
, remv
, and remq
procedures
return a list of the elements that are not obj. The remq
procedure
uses eq?
to compare obj with the elements of list, while
remv
uses eqv?
and remove
uses equal?
. The elements
of the result list are in the same order as they appear in the input list. If
multiple returns occur from remp
, the return values returned by earlier
returns are not mutated.
[R6RS+] Proc should accept one argument and return a single value. Proc should not mutate list.
These procedures return the first sublist of list whose car satisfies a
given condition, where the sublists of lists are the lists returned by
(list-tail _list_ _k_)
for k less than the length of list.
The memp
procedure applies proc to the cars of the sublists of
list until it finds one for which proc returns a true value. The
member
, memv
, and memq
procedures look for the first
occurrence of obj. If list does not contain an element satisfying the
condition, then #f (not the empty list) is returned. The member
procedure
uses equal?
or if = is given use it to compare obj with the
elements of list, while memv
uses eqv?
and memq
uses
eq?
.
[R6RS+] Alist (for "association list") should be a list of pairs. Proc should accept one argument and return a single value. _Proc_should not mutate alist.
These procedures find the first pair in alist whose car field satisfies
a given condition, and returns that pair without traversing alist further.
If no pair in alist satisfies the condition, then #f is returned. The
assp
procedure successively applies proc to the car fields of
alist and looks for a pair for which it returns a true value. The
assoc
, assv
, and assq
procedures look for a pair that has
obj as its car. The assoc
procedure uses equal?
or if _=_is given use it to compare obj with the car fields of the pairs in alist,
while assv
uses eqv?
and assq
uses eq?
.
Note: member
and assoc
procedures are the same behaviour as SRFI-1.
[R6RS] Like list
, but the last argument provides the tail of the
constructed list.
The (rnrs sorting (6))
library provides procedures for sorting lists
and vectors.
[R6RS+][SRFI-132] Proc should accept any two elements of list or vector. Proc should return a true value when its first argument is strictly less than its second, and #f otherwise.
The list-sort
and vector-sort
procedures perform a stable sort
of list or vector in ascending order according to proc, without
changing list or vector in any way. The list-sort
procedure
returns a list, and vector-sort
returns a vector. The results may be
eq?
to the argument when the argument is already sorted, and the result
of list-sort
may share structure with a tail of the original list. The
sorting algorithm performs O(n lg n) calls to proc where n is the length
of list or vector, and all arguments passed to proc are
elements of the list or vector being sorted, but the pairing of
arguments and the sequencing of calls to proc are not specified. If
multiple returns occur from list-sort
or vector-sort
, the
return values returned by earlier returns are not mutated.
If the optional argument start and end for vector-sort
is specified, then the sorting range is restricted by the given start(inclusive) and end (exclusive).
[R6RS+][SRFI-132] Proc should accept any two elements of the vector, and should not have any side effects. Proc should return a true value when its first argument is strictly less than its second, and #f otherwise.
The vector-sort!
procedure destructively sorts vector in
ascending order according to proc.
If the optional argument start and end is specified, then the sorting range is restricted by the given start (inclusive) and end (exclusive).
The (rnrs control (6))
library, which provides useful control structures.
[R6RS] Test must be an expression.
A when
expression is evaluated by evaluating the test expression.
If test evaluates to a true value, the remaining expressions are
evaluated in order, and the results of the last expression are returned as
the results of the entire when
expression. Otherwise, the when
expression returns unspecified values. An unless
expression is evaluated
by evaluating the test expression. If test evaluates to #f, the
remaining expressions are evaluated in order, and the results of the last
expression are returned as the results of the entire unless
expression. Otherwise, the unless
expression returns unspecified values.
[R6RS] The inits, steps, tests, and commands must be expressions. The variables must be pairwise distinct variables.
The do
expression is an iteration construct. It specifies a set of variables
to be bound, how they are to be initialized at the start, and how they are to be
updated on each iteration.
A do
expression is evaluated as follows: The init expressions are
evaluated (in some unspecified order), the variables are bound to fresh
locations, the results of the init expressions are stored in the bindings
of the variables, and then the iteration phase begins.
Each iteration begins by evaluating test if the result is #f, then the commands are evaluated in order for effect, the step expressions are evaluated in some unspecified order, the variables are bound to fresh locations holding the results, and the next iteration begins.
If test evaluates to a true value, the expressions are evaluated from
left to right and the values of the last expression are returned. If no
expressions are present, then the do
expression returns unspecified
values.
The region of the binding of a variable consists of the entire do
expression except for the inits.
A step may be omitted, in which case the effect is the same as if (variable init variable) had been written instead of (variable init).
(do ((vec (make-vector 5))
(i 0 (+ i 1)))
((= i 5) vec)
(vector-set! vec i i))
#(0 1 2 3 4)
(let ((x '(1 3 5 7 9)))
(do ((x x (cdr x))
(sum 0 (+ sum (car x))))
((null? x) sum)))
25
[R6RS] Each case-lambda-clause must be of the form
(_formals_ _body_)
Formals must be as in a lambda
form.
A case-lambda
expression evaluates to a procedure. This procedure, when
applied, tries to match its arguments to the case-lambda-clauses
in order.
The arguments match a clause if one of the following conditions is fulfilled:
Formals has the form (_variable_ ...)
and the number of
arguments is the same as the number of formal parameters in formals.
Formals has the form
(_variable1_ ... _variablen_ . _variablen+1_)
and the number of arguments is at least n.
Formals has the form variable.
For the first clause matched by the arguments, the variables of the _formals_are bound to fresh locations containing the argument values in the same arrangement
as with lambda
.
The last expression of a body in a case-lambda
expression is in tail context.
If the arguments match none of the clauses, an exception with condition type
&assertion
is raised.
The (rnrs records syntactic (6))
library. Some details of the
specification are explained in terms of the specification of the procedural
layer below.
[R6RS] A define-record-type
form defines a record type along with
associated constructor descriptor and constructor, predicate, field accessors,
and field mutators. The define-record-type
form expands into a set of
definitions in the environment where define-record-type
appears; hence,
it is possible to refer to the bindings (except for that of the record type
itself) recursively.
The name-spec specifies the names of the record type, constructor, and predicate. It must take one of the following forms:
(_record-name_ _constructor-name_ _predicate-name_)
_record-name_
Record-name, constructor-name, and predicate-name must all be
identifiers.
Record-name, taken as a symbol, becomes the name of the record type.
(See the description of make-record-type-descriptor
.) Additionally, it is
bound by this definition to an expand-time or run-time representation of the
record type and can be used as parent name in syntactic record-type definitions
that extend this definition. It can also be used as a handle to gain access to
the underlying record-type descriptor and constructor descriptor
(see record-type-descriptor
and record-constructor-descriptor
).
Constructor-name is defined by this definition to be a constructor for the
defined record type, with a protocol specified by the protocol
clause, or,
in its absence, using a default protocol. For details, see the description of the
protocol
clause below.
Predicate-name is defined by this definition to a predicate for the defined record type.
The second form of name-spec is an abbreviation for the first form, where
the name of the constructor is generated by prefixing the record name with
make-
, and the predicate name is generated by adding a question mark
(?
) to the end of the record name. For example, if the record name is
frob
, the name of the constructor is make-frob
, and the predicate
name is frob?
.
Each record-clause must take one of the auxiliary syntax forms; it is a
syntax violation if multiple record-clauses of the same kind appear in a
define-record-type
form.
(fields _field-spec_*)
Each field-spec has one of the following forms
(immutable _field-name_ _accessor-name_)
(mutable _field-name_ _accessor-name_ _mutator-name_)
(immutable _field-name_)
(mutable _field-name_)
_field-name_
Field-name, accessor-name, and mutator-name must all be identifiers. The first form declares an immutable field called field-name>, with the corresponding accessor named accessor-name. The second form declares a mutable field called field-name, with the corresponding accessor named accessor-name, and with the corresponding mutator named mutator-name.
If field-spec takes the third or fourth form, the accessor name is generated
by appending the record name and field name with a hyphen separator, and the mutator
name (for a mutable field) is generated by adding a -set!
suffix to the
accessor name. For example, if the record name is frob
and the field name
is widget
, the accessor name is frob-widget
and the mutator name is
frob-widget-set!
.
If field-spec is just a field-name form, it is an abbreviation for
(immutable _field-name_)
.
The field-names become, as symbols, the names of the fields in the
record-type
descriptor being created, in the same order.
The fields
clause may be absent; this is equivalent to an empty fields
clause.
(parent _parent-name_)
Specifies that the record type is to have parent type parent-name, where
parent-name is the record-name of a record type previously defined
using define-record-type
. The record-type definition associated with
parent-name must not be sealed. If no parent clause and no parent-rtd
(see below) clause is present, the record type is a base type.
(protocol _expression_)
Expression is evaluated in the same environment as the define-record-type
form, and must evaluate to a protocol appropriate for the record type being defined.
The protocol is used to create a record-constructor descriptor as described below.
If no protocol
clause is specified, a constructor descriptor is still created
using a default protocol. The clause can be absent only if the record type being
defined has no parent type, or if the parent definition does not specify a protocol.
(sealed _boolean_)
If this option is specified with operand #t, the defined record type is sealed, i.e., no extensions of the record type can be created. If this option is specified with operand #f, or is absent, the defined record type is not sealed.
(opaque _boolean_)
If this option is specified with operand #t, or if an opaque parent record type is specified, the defined record type is opaque. Otherwise, the defined record type is not opaque. See the specification of record-rtd below for details.
(nongenerative _uid_)
(nongenerative)
This specifies that the record type is nongenerative with uid uid, which must
be an identifier. If uid is absent, a unique uid is generated at macro-expansion
time. If two record-type definitions specify the same uid, then the record-type
definitions should be equivalent, i.e., the implied arguments to
make-record-type-descriptor
must be equivalent as described under
make-record-type-descriptor
. If this condition is not met, it is either
considered a syntax violation or an exception with condition type &assertion
is raised. If the condition is met, a single record type is generated for both
definitions.
In the absence of a nongenerative
clause, a new record type is generated
every time a define-record-type
form is evaluated:
(let ((f (lambda (x)
(define-record-type r ...)
(if x r? (make-r ...)))))
((f #t) (f #f)))
(parent-rtd _parent-rtd_ _parent-cd_)
Specifies that the record type is to have its parent type specified by
parent-rtd, which should be an expression evaluating to a record-type
descriptor, and parent-cd, which should be an expression evaluating to a
constructor descriptor. The record-type definition associated with the value of
parent-rtd must not be sealed. Moreover, a record-type definition must not
have both a parent
and a parent-rtd
clause.
All bindings created by define-record-typ
e (for the record type, the
constructor, the predicate, the accessors, and the mutators) must have names that
are pairwise distinct.
The constructor created by a define-record-type
form is a procedure as
follows:
If there is no parent
clause and no protocol
clause, the
constructor accepts as many arguments as there are fields, in the same order
as they appear in the fields
clause, and returns a record object with
the fields initialized to the corresponding arguments.
If there is no parent
or parent-rtd
clause and a protocol
clause, the protocol expression must evaluate to a procedure that accepts a
single argument. The protocol procedure is called once during the evaluation of
the define-record-type
form with a procedure p as its argument. It
should return a procedure, which will become the constructor bound to
constructor-name. The procedure p accepts as many arguments as there
are fields, in the same order as they appear in the fields clause, and returns
a record object with the fields initialized to the corresponding arguments.
The constructor returned by the protocol procedure can accept an arbitrary number
of arguments, and should call p once to construct a record object, and
return that record object.
For example, the following protocol expression for a record-type definition with
three fields creates a constructor that accepts values for all fields, and
initialized them in the reverse order of the arguments:
(lambda (p)
(lambda (v1 v2 v3)
(p v3 v2 v1)))
If there is both a parent
clause and a protocol
clause, then
the protocol procedure is called once with a procedure _n_as its argument.
As in the previous case, the protocol procedure should return a procedure, which
will become the constructor bound to constructor-name. However, n is
different from p in the previous case: It accepts arguments corresponding
to the arguments of the constructor of the parent type. It then returns a procedure
p that accepts as many arguments as there are (additional) fields in this
type, in the same order as in the fields
clause, and returns a record object
with the fields of the parent record types initialized according to their constructors
and the arguments to n, and the fields of this record type initialized to
its arguments of p.
The constructor returned by the protocol procedure can accept an arbitrary number
of arguments, and should call n once to construct the procedure p,
and call p once to create the record object, and finally return that record
object.
For example, the following protocol expression assumes that the constructor of
the parent type takes three arguments:
(lambda (n)
(lambda (v1 v2 v3 x1 x2 x3 x4)
(let ((p (n v1 v2 v3)))
(p x1 x2 x3 x4))))
The resulting constructor accepts seven arguments, and initializes the fields of
the parent types according to the constructor of the parent type, with v1
,
v2
, and v3
as arguments. It also initializes the fields of this
record type to the values of x1
, ..., x4
.
If there is a parent
clause, but no protocol
clause, then the
parent type must not have a protocol
clause itself. The constructor bound
to constructor-name is a procedure that accepts arguments corresponding to
the parent types' constructor first, and then one argument for each field in the
same order as in the fields
clause. The constructor returns a record object
with the fields initialized to the corresponding arguments.
If there is a parent-rtd
clause, then the constructor is as with a
parent
clause, except that the constructor of the parent type is determined
by the constructor descriptor of the parent-rtd
clause.
A protocol may perform other actions consistent with the requirements described above, including mutation of the new record or other side effects, before returning the record.
Any definition that takes advantage of implicit naming for the constructor, predicate, accessor, and mutator names can be rewritten trivially to a definition that specifies all names explicitly. For example, the implicit-naming record definition:
(define-record-type frob
(fields (mutable widget))
(protocol
(lambda (p)
(lambda (n) (p (make-widget n))))))
is equivalent to the following explicit-naming record definition.
(define-record-type (frob make-frob frob?)
(fields (mutable widget
frob-widget
frob-widget-set!))
(protocol
(lambda (p)
(lambda (n) (p (make-widget n))))))
Also, the implicit-naming record definition:
(define-record-type point (fields x y))
is equivalent to the following explicit-naming record definition:
(define-record-type (point make-point point?)
(fields
(immutable x point-x)
(immutable y point-y)))
With implicit naming, it is still possible to specify some of the names explicitly; for example, the following overrides the choice of accessor and mutator names for the widget field.
(define-record-type frob
(fields (mutable widget getwid setwid!))
(protocol
(lambda (p)
(lambda (n) (p (make-widget n))))))
[R6RS] Evaluates to the record-type descriptor (see Records procedural layer) associated with the type specified by record-name.
[R6RS] Evaluates to the record-type constructor (see Records procedural layer) associated with the type specified by record-name.
The following example uses the record?
procedure from the
(rnrs records inspection (6))
library:
(define-record-type (point make-point point?)
(fields (immutable x point-x)
(mutable y point-y set-point-y!))
(nongenerative point-4893d957-e00b-11d9-817f-00111175eb9e))
(define-record-type (cpoint make-cpoint cpoint?)
(parent point)
(protocol (lambda (n)
(lambda (x y c)
((n x y) (color->rgb c)))))
(fields (mutable rgb cpoint-rgb cpoint-rgb-set!)))
(define (color->rgb c) (cons 'rgb c))
(define p1 (make-point 1 2))
(define p2 (make-cpoint 3 4 'red))
(point? p1)
#t
(point? p2)
#t
(point? (vector))
(point? (cons 'a 'b))
(cpoint? p1)
(cpoint? p2)
#t
(point-x p1)
1
(point-y p1)
2
(point-x p2)
3
(point-y p2)
4
(cpoint-rgb p2)
(rgb . red)
(set-point-y! p1 17)
unspecified
(point-y p1)
17
(record-rtd p1)
(record-type-descriptor point)
(define-record-type (ex1 make-ex1 ex1?)
(protocol (lambda (p) (lambda a (p a))))
(fields (immutable f ex1-f)))
(define ex1-i1 (make-ex1 1 2 3))
(ex1-f ex1-i1)
(1 2 3)
(define-record-type (ex2 make-ex2 ex2?)
(protocol
(lambda (p) (lambda (a . b) (p a b))))
(fields (immutable a ex2-a)
(immutable b ex2-b)))
(define ex2-i1 (make-ex2 1 2 3))
(ex2-a ex2-i1)
1
(ex2-b ex2-i1)
(2 3)
(define-record-type (unit-vector make-unit-vector unit-vector?)
(protocol (lambda (p)
(lambda (x y z)
(let ((length (sqrt (+ (* x x) (* y y) (* z z)))))
(p (/ x length) (/ y length) (/ z length))))))
(fields (immutable x unit-vector-x)
(immutable y unit-vector-y)
(immutable z unit-vector-z)))
(define *ex3-instance* #f)
(define-record-type ex3
(parent cpoint)
(protocol (lambda (n)
(lambda (x y t)
(let ((r ((n x y 'red) t)))
(set! *ex3-instance* r)
r))))
(fields (mutable thickness))
(sealed #t) (opaque #t))
(define ex3-i1 (make-ex3 1 2 17))
(ex3? ex3-i1)
#t
(cpoint-rgb ex3-i1)
(rgb . red)
(ex3-thickness ex3-i1)
17
(ex3-thickness-set! ex3-i1 18)
unspecified
(ex3-thickness ex3-i1)
18
*ex3-instance*
ex3-i1
(record? ex3-i1)
The procedural layer is provided by the (rnrs records procedural (6))
library.
[R6RS] Returns a record-type descriptor (rtd).
The name argument must be a symbol. It names the record type, and is intended purely for informational purposes.
The parent argument must be either #f or an rtd. If it is an rtd, the returned
record type, t, extends the record type p represented by parent. An
exception with condition type &assertion
is raised if parent is sealed
(see below).
The uid argument must be either #f or a symbol. If uid is a symbol,
the record-creation operation is nongenerative i.e., a new record type is created
only if no previous call to make-record-type-descriptor
was made with the
uid. If uid is #f, the record-creation operation is generative,
.e., a new record type is created even if a previous call to
make-record-type-descriptor
was made with the same arguments.
If make-record-type-descriptor
is called twice with the same _uid_symbol, the parent arguments in the two calls must be eqv?
, the
fields arguments equal?
, the sealed? arguments boolean-equivalent
(both #f or both true), and the opaque? arguments boolean-equivalent. If
these conditions are not met, an exception with condition type &assertion
is raised when the second call occurs. If they are met, the second call returns,
without creating a new record type, the same record-type descriptor (in the
sense of eqv?
) as the first call.
The sealed? flag must be a boolean. If true, the returned record type is sealed, i.e., it cannot be extended.
The opaque? flag must be a boolean. If true, the record type is opaque. If
passed an instance of the record type, record? returns #f. Moreover, if
record-rtd
(see (rnrs records inspection (6)))
is called with an instance of the record type, an exception with condition
type &assertion
is raised. The record type is also opaque if an opaque
parent is supplied. If opaque? is #f and an opaque parent is not supplied,
the record is not opaque.
The fields argument must be a vector of field specifiers. Each field specifier
must be a list of the form (mutable _name_)
or a list of the form
(immutable _name_)
. Each name must be a symbol and names the corresponding
field of the record type; the names need not be distinct. A field identified as
mutable may be modified, whereas, when a program attempts to obtain a mutator for
a field identified as immutable, an exception with condition type &assertion
is raised. Where field order is relevant, e.g., for record construction and field
access, the fields are considered to be ordered as specified, although no particular
order is required for the actual representation of a record instance.
The specified fields are added to the parent fields, if any, to determine the
complete set of fields of the returned record type. If fields is modified after
make-record-type-descriptor
has been called, the effect on the returned
rtd is unspecified.
A generative record-type descriptor created by a call to
make-record-type-descriptor
is not eqv?
to any record-type descriptor
(generative or nongenerative) created by another call to
make-record-type-descriptor
. A generative record-type descriptor is eqv?
only to itself, i.e., (eqv? rtd1 rtd2) iff (eq? rtd1 rtd2). Also, two nongenerative
record-type descriptors are eqv?
if they were created by calls to
make-record-type-descriptor
with the same uid arguments.
[R6RS] Returns #t if the argument is a record-type descriptor, #f otherwise.
[R6RS] Returns a record-constructor descriptor (or
var{constructor descriptor} for short) that specifies a record constructor(or constructor for short), that can be used to construct record values of
the type specified by rtd, and which can be obtained via record-constructor
.
A constructor descriptor can also be used to create other constructor descriptors
for subtypes of its own record type. Rtd must be a record-type descriptor.
Protocol must be a procedure or #f. If it is #f, a default protocol procedure
is supplied.
If protocol is a procedure, it is handled analogously to the protocol
expression in a define-record-type
form.
If rtd is a base record type and protocol is a procedure,
parent-constructor-descriptor must be #f. In this case, _protocol_is called by record-constructor
with a single argument p. _P_is a procedure that expects one argument for every field of rtd and returns
a record with the fields of rtd initialized to these arguments. The
procedure returned by protocol should call p once with the number of
arguments p expects and return the resulting record as shown in the
simple example below:
(lambda (p)
(lambda (v1 v2 v3)
(p v1 v2 v3)))
Here, the call to p returns a record whose fields are initialized with
the values of v1
, v2
, and v3
. The expression above is
equivalent to (lambda (p) p)
. Note that the procedure returned by protocol
is otherwise unconstrained; specifically, it can take any number of arguments.
If rtd is an extension of another record type parent-rtd and protocol is a procedure, parent-constructor-descriptor must be a constructor descriptor of parent-rtd or #f. If parent-constructor-descriptor is a constructor descriptor, _protocol_it is called by record-constructor with a single argument n, which is a procedure that accepts the same number of arguments as the constructor of parent-constructor-descriptor and returns a procedure p that, when called, constructs the record itself. The p procedure expects one argument for every field of rtd (not including parent fields) and returns a record with the fields of rtd initialized to these arguments, and the fields of parent-rtd and its parents initialized as specified by parent-constructor-descriptor.
The procedure returned by protocol should call n once with the number of arguments n expects, call the procedure p it returns once with the number of arguments p expects and return the resulting record. A simple protocol in this case might be written as follows:
(lambda (n)
(lambda (v1 v2 v3 x1 x2 x3 x4)
(let ((p (n v1 v2 v3)))
(p x1 x2 x3 x4))))
This passes arguments v1
, v2
, v3
to n for
parent-constructor-descriptor and calls p with x1
, ...,
x4
to initialize the fields of rtd itself.
Thus, the constructor descriptors for a record type form a sequence of protocols parallel to the sequence of record-type parents. Each constructor descriptor in the chain determines the field values for the associated record type. Child record constructors need not know the number or contents of parent fields, only the number of arguments accepted by the parent constructor.
Protocol may be #f, specifying a default constructor that accepts one
argument for each field of rtd (including the fields of its parent type,
if any). Specifically, if rtd is a base type, the default protocol procedure
behaves as if it were (lambda (p) p)
. If rtd is an extension of
another type, then parent-constructor-descriptor must be either #f or
itself specify a default constructor, and the default protocol procedure behaves
as if it were:
(lambda (n)
(lambda (v1 ... vj x1 ... xk)
(let ((p (n v1 ... vj)))
(p x1 ... xk))))
The resulting constructor accepts one argument for each of the record type's complete set of fields (including those of the parent record type, the parent's parent record type, etc.) and returns a record with the fields initialized to those arguments, with the field values for the parent coming before those of the extension in the argument list. (In the example, j is the complete number of fields of the parent type, and k is the number of fields of rtd itself.)
If rtd is an extension of another record type, and _parent-constructor-descriptor_or the protocol of parent-constructor-descriptor is #f, protocol must also be #f, and a default constructor descriptor as described above is also assumed.
[R6RS] Calls the protocol of constructor-descriptor (as described
for make-record-constructor-descriptor
) and returns the resulting constructor
constructor for records of the record type associated with
constructor-descriptor.
[R6RS] Returns a procedure that, given an object obj, returns #t if obj is a record of the type represented by rtd, and #f otherwise.
[R6RS] K must be a valid field index of rtd. The
record-accessor
procedure returns a one-argument procedure whose argument
must be a record of the type represented by rtd. This procedure returns
the value of the selected field of that record.
The field selected corresponds to the _k_th element (0-based) of the fields
argument to the invocation of make-record-type-descriptor
that created
rtd. Note that k cannot be used to specify a field of any type
rtd extends.
[R6RS] K must be a valid field index of rtd. The
record-mutator
procedure returns a two-argument procedure whose arguments
must be a record record r of the type represented by rtd and an
object obj. This procedure stores obj within the field of _r_specified by k. The k argument is as in record-accessor
. If
k specifies an immutable field, an exception with condition type
&assertion
is raised. The mutator returns unspecified values.
The (rnrs records inspection (6))
library provides procedures for
inspecting records and their record-type descriptors. These procedures are designed
to allow the writing of portable printers and inspectors.
[R6RS] Returns #t if obj is a record, and its record type is not opaque, and returns #f otherwise.
[R6RS] Returns the rtd representing the type of record if the type
is not opaque. The rtd of the most precise type is returned; that is, the type
t such that record is of type t but not of any type that
extends t. If the type is opaque, an exception is raised with condition
type &assertion
.
[R6RS] Returns the name/parent/uid of the record-type descriptor rtd.
[R6RS] Returns #t if the record-type descriptor is generative/sealed/opaque, and #f if not.
[R6RS] Returns a vector of symbols naming the fields of the type represented
by rtd (not including the fields of parent types) where the fields are
ordered as described under make-record-type-descriptor
.
[R6RS] Returns #t if the field specified by k of the type represented
by rtd is mutable, and #f if not. K is as in record-accessor
.
This section describes exception-handling and exception-raising constructs
provided by the (rnrs exceptions (6))
library.
[R6RS] Handler must be a procedure and should accept one argument.
Thunk must be a procedure that accepts zero arguments. The
with-exception-handler
procedure returns the results of invoking
thunk. When an exception is raised, handler will be invoked with
the exception.
[R6RS] Each cond-clause is as in the specification of cond
.
and else
are the same as in the (rnrs base (6))
library.
Evaluating a guard
form evaluates body with an exception handler
that binds the raised object to variable and within the scope of that
binding evaluates the clauses as if they were the clauses of a cond
expression. If every cond-clause's test evaluates to #f and there is
no else
clause, then raise is re-invoked on the raised object.
[R6RS] Raises a non-continuable exception by invoking the current exception handler on obj.
[R6RS] Raises a continuable exception by invoking the current exception handler on obj.
The section describes (rnrs conditions (6))
library for creating and
inspecting condition types and values. A condition value encapsulates information
about an exceptional situation.
[R6RS] The condition
procedure returns a condition object with the
components of the conditions as its components, in the same order. The
returned condition is compound if the total number of components is zero or
greater than one. Otherwise, it may be compound or simple.
[R6RS] The simple-conditions
procedure returns a list of the
components of condition, in the same order as they appeared in the
construction of condition.
[R6RS] Returns #t if obj is a (simple or compound) condition, otherwise returns #f.
[R6RS] Rtd must be a record-type descriptor of a subtype of
&condition
. The condition-predicate
procedure returns a procedure
that takes one argument. This procedure returns #t if its argument is a condition
of the condition type represented by rtd, i.e., if it is either a simple
condition of that record type (or one of its subtypes) or a compound conditition
with such a simple condition as one of its components, and #f otherwise.
[R6RS] Rtd must be a record-type descriptor of a subtype of
&condition
. Proc should accept one argument, a record of the
record type of rtd. The condition-accessor
procedure returns a
procedure that accepts a single argument, which must be a condition of the type
represented by rtd. This procedure extracts the first component of the
condition of the type represented by rtd, and returns the result of
applying proc to that component.
[R6RS] Condition-type, supertypes, constructor, and predicate must all be identifiers. Each field-spec must be of the form
(_field_ _accessor_)
where both field and accessor must be identifiers.
The define-condition-type
form expands into a record-type definition for
a record type condition-type. The record type will be non-opaque, non-sealed,
and its fields will be immutable. It will have supertype has its parent type.
The remaining identifiers will be bound as follows:
Constructor is bound to a default constructor for the type : It accepts one argument for each of the record type's complete set of fields (including parent types, with the fields of the parent coming before those of the extension in the arguments) and returns a condition object initialized to those arguments.
Predicate is bound to a predicate that identifies conditions of type condition-type or any of its subtypes.
Each accessor is bound to a procedure that extracts the corresponding field from a condition of type condition-type.
Hierarchy of standard condition types:
+ &condition
+ &warning
+ &serious
+ &error
+ &violation
+ &assertion
+ &non-continuable
+ &implementation-restriction
+ &lexical
+ &syntax
+ &undefined
+ &message
+ &irritants
[R6RS] It carries a message further describing the nature of the condition to humans.
[R6RS] This type describes conditions that do not, in principle, prohibit immediate continued execution of the program, but may interfere with the program's execution later.
[R6RS] This type describes conditions serious enough that they cannot safely be ignored. This condition type is primarily intended as a supertype of other condition types.
[R6RS] This type describes errors, typically caused by something that has gone wrong in the interaction of the program with the external world or the user.
[R6RS] This type describes violations of the language standard or a library standard, typically caused by a programming error.
[R6RS] This type describes an invalid call to a procedure, either passing an invalid number of arguments, or passing an argument of the wrong type.
[R6RS] Irritants should be a list of objects. This condition provides
additional information about a condition, typically the argument list of a
procedure that detected an exception. Conditions of this type are created by the
error
and assertion-violation
procedures.
[R6RS] Who should be a symbol or string identifying the entity
reporting the exception. Conditions of this type are created by the error
and assertion-violation
procedures, and the syntax-violation
procedure.
[R6RS] This type indicates that an exception handler invoked via raise has returned.
[R6RS] This type describes a violation of an implementation restriction allowed by the specification, such as the absence of representations for NaNs and infinities.
[R6RS] This type describes syntax violations at the level of the datum syntax.
[R6RS] This type describes syntax violations. Form should be the erroneous syntax object or a datum representing the code of the erroneous form. Subform should be an optional syntax object or datum within the erroneous form that more precisely locates the violation. It can be #f to indicate the absence of more precise information.
[R6RS] This type describes unbound identifiers in the program.
The condition types and corresponding predicates and accessors are exported by
both the (rnrs io ports (6))
and (rnrs io simple (6))
libraries.
They are also exported by the (rnrs files (6))
library.
[R6RS] This is a supertype for a set of more specific I/O errors.
[R6RS] This condition type describes read errors that occurred during an I/O operation.
[R6RS] This condition type describes write errors that occurred during an I/O operation.
[R6RS] This condition type describes attempts to set the file position to an invalid position. Position should be the file position that the program intended to set. This condition describes a range error, but not an assertion violation.
[R6RS] This condition type describes an I/O error that occurred during an operation on a named file. Filename should be the name of the file.
[R6RS] A condition of this type specifies that an operation tried to operate on a named file with insufficient access rights.
[R6RS] A condition of this type specifies that an operation tried to operate on a named read-only file under the assumption that it is writeable.
[R6RS] A condition of this type specifies that an operation tried to operate on an existing named file under the assumption that it did not exist.
[R6RS] A condition of this type specifies that an operation tried to operate on an non-existent named file under the assumption that it existed.
[R6RS] This condition type specifies the port with which an I/O error
is associated. Port should be the port. Conditions raised by procedures
accepting a port as an argument should include an &i/o-port-error
condition.
Here I describe the conditions hierarchy.
+ &error([See (rnrs conditions (6))](#rnrs.conditions.6))
+ &i/o
+ &i/o-read
+ &i/o-write
+ &i/o-invalid-position
+ &i/o-filename
+ &i/o-file-protection
+ &i/o-file-is-read-only
+ &i/o-file-already-exists
+ &i/o-file-does-not-exist
+ &i/o-port-error
The (rnrs io ports (6))
library defines an I/O layer for
conventional, imperative buffered input and output. A port represents
a buffered access object for a data sink or source or both simultaneously.
The library allows ports to be created from arbitrary data sources and sinks.
The (rnrs io ports (6))
library distinguishes between _input ports_and output ports. An input port is a source for data, whereas an output
port is a sink for data. A port may be both an input port and an output port;
such a port typically provides simultaneous read and write access to a file or
other data.
The (rnrs io ports (6))
library also distinguishes between
binary ports, which are sources or sinks for uninterpreted bytes,
and textual ports, which are sources or sinks for characters and strings.
This section uses input-port, output-port, binary-port, textual-port, binary-input-port, textual-input-port, binary-output-port, textual-output-port, and port as parameter names for arguments that must be input ports (or combined input/output ports), output ports (or combined input/output ports), binary ports, textual ports, binary input ports, textual input ports, binary output ports, textual output ports, or any kind of port, respectively.
In this world, unfortunately there are a lot of operating systems. However, as far as I know there are only two file separators, one is Windows style back slash, the other is UNIX style slash. On Sagittarius both of it can be used as file path. Inside of the resolution of file path, Sagittarius replaces those file separators to OS specific one. Even though programmer does not have to care about it, I think it's better to use slash as file separator on script files.
A filename parameter name means that the corresponding argument must be a file name.
When opening a file, the various procedures in this library accept a
file-options
object that encapsulates flags to specify how the file is to
be opened. A file-options
object is an enum-set
(see (rnrs enums (6))) over the symbols constituting
valid file options. A file-options parameter name means that the
corresponding argument must be a file-options object.
[R6RS+] Each file-option-symbol must be a symbol. The file-options macro returns a file-options object that encapsulates the specified options.
When supplied to an operation that opens a file for output, the file-options
object returned by (file-options)
specifies that the file is created if
it does not exist and an exception with condition type
&i/o-file-already-exists
is raised if it does exist. The following
standard options can be included to modify the default behaviour.
no-create
If the file does not already exist, it is not created;
instead, an exception with condition type &i/o-file-does-not-exist
is
raised. If the file already exists, the exception with condition type
&i/o-file-already-exists
is not raised and the file is truncated to zero
length.
no-fail
If the file already exists, the exception with condition
type &i/o-file-already-exists
is not raised, even if no-create
is
not included, and the file is truncated to zero length.
no-truncate
If the file already exists and the exception with
condition type &i/o-file-already-exists
has been inhibited by inclusion
of no-create
or no-fail
, the file is not truncated, but the port's
current position is still set to the beginning of the file.
append
Among with no-truncate
, set the opened port's
position the end of the file. This is not a part of R6RS specification.
Each port has an associated buffer mode. For an output port, the buffer mode defines when an output operation flushes the buffer associated with the output port. For an input port, the buffer mode defines how much data will be read to satisfy read operations. The possible buffer modes are the symbols none for no buffering, line for flushing upon line endings and reading up to line endings, or other implementation-dependent behavior, and block for arbitrary buffering. This section uses the parameter name buffer-mode for arguments that must be buffer-mode symbols.
If two ports are connected to the same mutable source, both ports are unbuffered, and reading a byte or character from that shared source via one of the two ports would change the bytes or characters seen via the other port, a lookahead operation on one port will render the peeked byte or character inaccessible via the other port, while a subsequent read operation on the peeked port will see the peeked byte or character even though the port is otherwise unbuffered.
In other words, the semantics of buffering is defined in terms of side effects on shared mutable sources, and a lookahead operation has the same side effect on the shared source as a read operation.
[R6RS] Buffer-mode-symbol must be a symbol whose name is one of
none
, line
, and block
. The result is the corresponding
symbol, and specifies the associated buffer mode.
Returns #t if the argument is a valid buffer-mode symbol, and returns #f otherwise.
Several different Unicode encoding schemes describe standard ways to encode characters and strings as byte sequences and to decode those sequences. Within this document, a codec is an immutable Scheme object that represents a Unicode or similar encoding scheme.
An end-of-line style is a symbol that, if it is not none, describes how a textual port transcodes representations of line endings.
A transcoder is an immutable Scheme object that combines a codec with an end-of-line style and a method for handling decoding errors. Each transcoder represents some specific bidirectional (but not necessarily lossless), possibly stateful translation between byte sequences and Unicode characters and strings. Every transcoder can operate in the input direction (bytes to characters) or in the output direction (characters to bytes). A transcoder parameter name means that the corresponding argument must be a transcoder.
A binary port is a port that supports binary I/O, does not have an associated transcoder and does not support textual I/O. A textual port is a port that supports textual I/O, and does not support binary I/O. A textual port may or may not have an associated transcoder.
[R6RS] These are predefined codecs for the ISO 8859-1, UTF-8, and UTF-16 encoding schemes.
A call to any of these procedures returns a value that is equal in the sense
of eqv?
to the result of any other call to the same procedure.
[R6RS] Eol-style-symbol should be a symbol whose name is one of
lf
, cr
, crlf
, nel
, crnel
, ls
, and
none
. The form evaluates to the corresponding symbol. If the name of
eol-style-symbol is not one of these symbols, it still returns given
symbol, however make-transcoder
does not accept it.
[R6RS] Returns the default end-of-line style of the underlying platform.
[R6RS] An exception with this type is raised when one of the operations for textual input from a port encounters a sequence of bytes that cannot be translated into a character or string by the input direction of the port's transcoder.
When such an exception is raised, the port's position is past the invalid encoding.
[R6RS] An exception with this type is raised when one of the operations for textual output to a port encounters a character that cannot be translated into bytes by the output direction of the port's transcoder. Char is the character that could not be encoded.
[R6RS] Error-handling-mode-symbol should be a symbol whose name is
one of ignore
, raise
, and replace
. The form evaluates to
the corresponding symbol.
The error-handling
mode of a transcoder specifies the behavior of textual
I/O operations in the presence of encoding or decoding errors.
If a textual input operation encounters an invalid or incomplete character
encoding, and the error-handling mode is ignore
, an appropriate number
of bytes of the invalid encoding are ignored and decoding continues with the
following bytes. If the error-handling mode is replace
, the replacement
character U+FFFD is injected into the data stream, an appropriate number of
bytes are ignored, and decoding continues with the following bytes. If the
error-handling mode is raise
, an exception with condition type
&i/o-decoding
is raised.
If a textual output operation encounters a character it cannot encode, and the
error-handling mode is ignore
, the character is ignored and encoding
continues with the next character. If the error-handling mode is replace
,
a codec-specific replacement character is emitted by the transcoder, and
encoding continues with the next character. The replacement character is U+FFFD
for transcoders whose codec is one of the Unicode encodings, but is the ?
character for the Latin-1 encoding. If the error-handling mode is raise
,
an exception with condition type &i/o-encoding
is raised.
[R6RS] Codec must be a codec; eol-style, if present, an
eol-style symbol; and handling-mode, if present, an error-handling-mode
symbol. Eol-style may be omitted, in which case it defaults to the native
end-of-line style of the underlying platform. Handling-mode may be
omitted, in which case it defaults to replace
. The result is a
transcoder with the behaviour specified by its arguments.
[R6RS] Returns platform dependent transcoder.
[R6RS] These are accessors for transcoder objects; when applied to a
transcoder returned by make-transcoder
, they return the codec,
eol-style, and handling-mode arguments, respectively.
[R6RS+] Returns the string that results from transcoding the bytevector according to the input direction of the transcoder.
If the optional argument start is given, the procedure converts given string from start index (inclusive).
If the optional argument end is given, the procedure converts given string to end index (exclusive).
These optional arguments must be fixnum if it's given.
[R6RS] Returns the bytevector that results from transcoding the string according to the output direction of the transcoder.
If the optional argument start is given, the procedure converts given string from start index (inclusive).
If the optional argument end is given, the procedure converts given string to end index (exclusive).
These optional arguments must be fixnum if it's given.
The end-of-file object is returned by various I/O procedures when they reach end of file.
[R6RS] Returns the end-of-file object
Returns #t if obj is the end-of-file object, #f otherwise.
The operations described in this section are common to input and output ports, both binary and textual. A port may also have an associated position that specifies a particular place within its data sink or source, and may also provide operations for inspecting and setting that place.
Returns #t if the argument is a port, and returns #f otherwise.
[R6RS] Returns the transcoder associated with port if port is textual and has an associated transcoder, and returns #f if port is binary or does not have an associated transcoder.
[R6RS+] [R7RS] The textual-port?
procedure returns #t if _obj_is textual port, otherwise #f.
The binary-port?
procedure returns #t if obj is binary port,
otherwise #f.
[R6RS] The transcoded-port
procedure returns a new textual port
with the specified transcoder. Otherwise the new textual port's state is
largely the same as that of binary-port. If binary-port is an input
port, the new textual port will be an input port and will transcode the bytes
that have not yet been read from binary-port. If binary-port is an
output port, the new textual port will be an output port and will transcode
output characters into bytes that are written to the byte sink represented by
binary-port.
[R6RS] The port-has-port-position?
procedure returns #t if the
port supports the port-position operation, and #f otherwise.
The port-position procedure returns the index of the position at which the next position would be read from or written to the port as an exact non-negative integer object.
[R6RS+] The port-has-set-port-position!?
procedure returns #t if the
port supports the set-port-position!
operation, and #f otherwise.
The set-port-position!
procedure raises an exception with condition type
&assertion
if the port does not support the operation, and an exception
with condition type &i/o-invalid-position
if pos is not in the range of
valid positions of port. Otherwise, it sets the current position of the
port to pos. If port is an output port,
set-port-position! first flushes port.
The optional argument whence must be one of the following symbols;
begin
Set position from the beginning of the given port.
current
Set position from the current position of the given port.
end
Set position from the end of the given port.
NOTE: for R6RS custom port, the procedure doesn't accept the optional argument,
so it will be always considered begin
even though user specified it
as current
or end
.
[R6RS] Closes the port, rendering the port incapable of
delivering or accepting data. If port is an output port, it is flushed
before being closed. This has no effect if the port has already been closed. A
closed port is still a port. The close-port
procedure returns unspecified
values.
[R6RS] Proc must accept one argument. The call-with-port
procedure calls proc with port as an argument. If _proc_returns, port is closed automatically and the values returned by
proc are returned. If proc does not return, port is not
closed automatically, except perhaps when it is possible to prove that
port will never again be used for an input or output operation.
An input port allows the reading of an infinite sequence of bytes or characters punctuated by end-of-file objects. An input port connected to a finite data source ends in an infinite sequence of end-of-file objects.
It is unspecified whether a character encoding consisting of several bytes may
have an end of file between the bytes. If, for example, get-char
raises
an &i/o-decoding
exception because the character encoding at the port's
position is incomplete up to the next end of file, a subsequent call to
get-char
may successfully decode a character if bytes completing the
encoding are available after the end of file.
Returns #t if the argument is an input port (or a combined input and output port), and returns #f otherwise.
[R6RS] Returns #t if the lookahead-u8
procedure (if
input-port is a binary port) or the lookahead-char
procedure (if
input-port is a textual port) would return the end-of-file object, and
#f otherwise.
[R6RS] Maybe-transcoder must be either a transcoder or #f.
The file-options argument, which may determine various aspects of the
returned port, defaults to the value of (file-options)
.
The buffer-mode argument, if supplied, must be one of the symbols that
name a buffer mode. The buffer-mode argument defaults to block
.
If maybe-transcoder is a transcoder, it becomes the transcoder associated with the returned port.
If maybe-transcoder is #f or absent, the port will be a binary port, otherwise the port will be textual port.
_ (start 0) (end (bytevector-length bytevector))
[R6RS+] transcoder must be either a transcoder or #f.
The open-bytevector-input-port
procedure returns an input port whose
bytes are drawn from bytevector. If transcoder is specified, it
becomes the transcoder associated with the returned port.
If transcoder is #f or absent, the port will be a binary port, otherwise the port will be textual port.
Optional arguments start and end restricts the range of input bytevector. It is almost the same as following code but doesn't allocate extra memory;
(open-bytevector-input-port (bytevector-copy bytevector start end))
[R6RS+] Returns a textual input port whose characters are drawn from string.
Optional arguments start and end restricts the range of input string. It is almost the same as following code but doesn't allocate extra memory;
(open-string-input-port (substring string start end))
These procedures reuse the given arguments, thus if bytevector is modified
after open-bytevector-input-port
has been called, it affects the result
of the port. So does open-string-input-port
.
[R6RS] Returns a fresh binary input port connected to standard input.
[R6RS+] If port is given, the current-input-port
sets the
port as a default port for input. Otherwise it returns a default input
port.
[R6RS+] Returns a newly created binary input port whose byte source is an arbitrary algorithm represented by the read! procedure. Id must be a string naming the new port, provided for informational purposes only. Read! must be a procedure and should behave as specified below; it will be called by operations that perform binary input.
Each of the remaining arguments may be #f; if any of those arguments is not #f, it must be a procedure and should behave as specified below.
(read! bytevector start count) Start will be a non-negative exact integer object, count will be a positive exact integer object, and bytevector will be a bytevector whose length is at least start + count. The read! procedure should obtain up to count bytes from the byte source, and should write those bytes into bytevector starting at index start. The _read!_procedure should return an exact integer object. This integer object should represent the number of bytes that it has read. To indicate an end of file, the read! procedure should write no bytes and return 0.
(get-position)
The get-position procedure (if supplied) should return an exact integer
object representing the current position of the input port. If not supplied, the
custom port will not support the port-position
operation.
(set-position! pos) Pos will be a non-negative exact integer object. The set-position! procedure (if supplied) should set the position of the input port to pos. If not supplied, the custom port will not support the set-port-position! operation.
(close) The close procedure (if supplied) should perform any actions that are necessary when the input port is closed.
(ready) The ready procedure (if supplied) should indicate the port data are ready or not.
[R6RS+] Returns a newly created textual input port whose character source is an arbitrary algorithm represented by the read! procedure. _Id_must be a string naming the new port, provided for informational purposes only. Read! must be a procedure and should behave as specified below; it will be called by operations that perform textual input.
Each of the remaining arguments may be #f; if any of those arguments is not #f, it must be a procedure and should behave as specified below.
(read! string start count) Start will be a non-negative exact integer object, count will be a positive exact integer object, and string will be a string whose length is at least start + count. The read! procedure should obtain up to count characters from the character source, and should write those characters into string starting at index start. The _read!_procedure should return an exact integer object representing the number of characters that it has written. To indicate an end of file, the _read!_procedure should write no bytes and return 0.
(get-position)
The get-position procedure (if supplied) should return a single value.
The return value should represent the current position of the input port. If not
supplied, the custom port will not support the port-position
operation.
(set-position! pos)
The set-position! procedure (if supplied) should set the position of
the input port to pos if pos is the return value of a call to
get-position. If not supplied, the custom port will not support the
set-port-position!
operation.
(close) The close procedure (if supplied) should perform any actions that are necessary when the input port is closed.
(ready) The ready procedure (if supplied) should indicate the port characters are ready or not.
[R6RS] Reads from binary-input-port, blocking as necessary, until a byte is available from binary-input-port or until an end of file is reached.
If a byte becomes available, get-u8
returns the byte as an octet and
updates binary-input-port to point just past that byte. If no input byte
is seen before an end of file is reached, the end-of-file object is returned.
[R6RS] The lookahead-u8
procedure is like get-u8
, but it
does not update binary-input-port to point past the byte.
[R6RS+] Count must be an exact, non-negative integer object representing the number of bytes to be read.
The get-bytevector-n
procedure reads from binary-input-port,
blocking as necessary, until count bytes are available from
binary-input-port or until an end of file is reached. If _count_bytes are available before an end of file, get-bytevector-n
returns a
bytevector of size count.
If fewer bytes are available before an end of file, get-bytevector-n
returns a bytevector containing those bytes. In either case, the input port is
updated to point just past the bytes read. If an end of file is reached before
any bytes are available, get-bytevector-n
returns the end-of-file object.
[R6RS+] Count must be an exact, non-negative integer object, representing the number of bytes to be read. bytevector must be a bytevector with at least start + count elements.
The get-bytevector-n!
procedure reads from binary-input-port,
blocking as necessary, until count bytes are available from
binary-input-port or until an end of file is reached. If count bytes
are available before an end of file, they are written into _bytevector_starting at index start, and the result is count. If fewer bytes are
available before the next end of file, the available bytes are written into
bytevector starting at index start, and the result is a number object
representing the number of bytes actually read. In either case, the input port is
updated to point just past the bytes read. If an end of file is reached before
any bytes are available, get-bytevector-n!
returns the end-of-file object.
[R6RS+] Reads from binary-input-port, blocking as necessary, until
bytes are available from binary-input-port or until an end of file is
reached. If bytes become available, get-bytevector-some
returns a freshly
allocated bytevector containing the initial available bytes (at least one and
maximum 512 bytes), and it updates binary-input-port to point just past
these bytes. If no input bytes are seen before an end of file is reached, the
end-of-file object is returned.
[R6RS+] Attempts to read all bytes until the next end of file, blocking
as necessary. If one or more bytes are read, get-bytevector-all
returns a
bytevector containing all bytes up to the next end of file. Otherwise,
get-bytevector-all
returns the end-of-file object.
These procedures can take optional argument reckless. If this is given, these procedures can read bytes from textual port. This optional argument is for socket programming. Users needs to make sure that the given port can be read as textual port after reading port recklessly.
[R6RS] Reads from textual-input-port, blocking as necessary, until a complete character is available from textual-input-port, or until an end of file is reached.
If a complete character is available before the next end of file, get-char
returns that character and updates the input port to point past the character.
If an end of file is reached before any character is read, get-char
returns the end-of-file object.
[R6RS] The lookahead-char
procedure is like get-char
, but it
does not update textual-input-port to point past the character.
[R6RS] Count must be an exact, non-negative integer object, representing the number of characters to be read.
The get-string-n
procedure reads from textual-input-port, blocking
as necessary, until count characters are available, or until an end of
file is reached.
If count characters are available before end of file, get-string-n
returns a string consisting of those count characters. If fewer characters
are available before an end of file, but one or more characters can be read,
get-string-n
returns a string containing those characters. In either case,
the input port is updated to point just past the characters read. If no characters
can be read before an end of file, the end-of-file object is returned.
[R6RS] Start and count must be exact, non-negative integer objects, with count representing the number of characters to be read. String must be a string with at least start + count characters.
The get-string-n!
procedure reads from textual-input-port in the
same manner as get-string-n
. If count characters are available before
an end of file, they are written into string starting at index start,
and count is returned. If fewer characters are available before an end of
file, but one or more can be read, those characters are written into string
starting at index start and the number of characters actually read is
returned as an exact integer object. If no characters can be read before an end
of file, the end-of-file object is returned.
[R6RS] Reads from textual-input-port until an end of file, decoding
characters in the same manner as get-string-n
and get-string-n!
.
If characters are available before the end of file, a string containing all the characters decoded from that data are returned. If no character precedes the end of file, the end-of-file object is returned.
[R6RS] Reads from textual-input-port up to and including the linefeed
character or end of file, decoding characters in the same manner as
get-string-n
and get-string-n!
.
If a linefeed character is read, a string containing all of the text up to (but not including) the linefeed character is returned, and the port is updated to point just past the linefeed character. If an end of file is encountered before any linefeed character is read, but some characters have been read and decoded as characters, a string containing those characters is returned. If an end of file is encountered before any characters are read, the end-of-file object is returned.
[R6RS] Reads an external representation from textual-input-port and
returns the datum it represents. The get-datum
procedure returns the next
datum that can be parsed from the given textual-input-port, updating
textual-input-port to point exactly past the end of the external
representation of the object.
If a character inconsistent with an external representation is encountered in
the input, an exception with condition types &lexical
and &i/o-read
is raised. Also, if the end of file is encountered after the beginning of an
external representation, but the external representation is incomplete and
therefore cannot be parsed, an exception with condition types &lexical
and &i/o-read
is raised.
An output port is a sink to which bytes or characters are written. The written data may control external devices or may produce files and other objects that may subsequently be opened for input.
[R6RS] Returns #t if obj is an output port (or a combined input and output port), #f otherwise.
[R6RS+][R7RS] Flushes any buffered output from the buffer of
output-port to the underlying file, device, or object. The
flush-output-port
procedure returns unspecified values.
If the optional argument is omitted then (current-output-port)
will be
used.
[R6RS] Returns the symbol that represents the buffer mode of output-port.
[R6RS] Maybe-transcoder must be either a transcoder or #f.
The open-file-output-port
procedure returns an output port for the named
file.
The file-options argument, which may determine various aspects of the
returned port, defaults to the value of (file-options)
.
The buffer-mode argument, if supplied, must be one of the symbols that
name a buffer mode. The buffer-mode argument defaults to block
.
If maybe-transcoder is a transcoder, it becomes the transcoder associated with the port.
If maybe-transcoder is #f or absent, the port will be a binary port, otherwise the port will be textual port.
[R6RS] Maybe-transcoder must be either a transcoder or #f.
The open-bytevector-output-port
procedure returns two values: an output
port and an extraction procedure. The output port accumulates the bytes written
to it for later extraction by the procedure.
If maybe-transcoder is a transcoder, it becomes the transcoder associated with the port. If maybe-transcoder is #f or absent, the port will be a binary port, otherwise the port will be textual port.
The extraction procedure takes no arguments. When called, it returns a bytevector consisting of all the port's accumulated bytes (regardless of the port's current position), removes the accumulated bytes from the port, and resets the port's position.
[R6RS] Proc must accept one argument. Maybe-transcoder must be either a transcoder or #f.
The call-with-bytevector-output-port
procedure creates an output port that
accumulates the bytes written to it and calls proc with that output port as
an argument. Whenever proc returns, a bytevector consisting of all of the
port's accumulated bytes (regardless of the port's current position) is returned
and the port is closed.
The transcoder associated with the output port is determined as for a call to
open-bytevector-output-port
.
[R6RS] Returns two values: a textual output port and an extraction procedure. The output port accumulates the characters written to it for later extraction by the procedure.
The extraction procedure takes no arguments. When called, it returns a string consisting of all of the port's accumulated characters (regardless of the current position), removes the accumulated characters from the port, and resets the port's position.
[R6RS] Proc must accept one argument.
The call-with-string-output-port
procedure creates a textual output port
that accumulates the characters written to it and calls proc with that
output port as an argument. Whenever proc returns, a string consisting of all of
the port's accumulated characters (regardless of the port's current position) is
returned and the port is closed.
[R6RS] Returns a fresh binary output port connected to the standard output or standard error respectively.
[R6RS+] If port is given, these procedures set the port as a default port for output and error. These return default ports for regular output and error output.
[R6RS] Returns a newly created binary output port whose byte sink is an arbitrary algorithm represented by the write! procedure. Id must be a string naming the new port, provided for informational purposes only. _Write!_must be a procedure and should behave as specified below; it will be called by operations that perform binary output.
Each of the remaining arguments may be #f; if any of those arguments is not #f,
it must be a procedure and should behave as specified in the description of
make-custom-binary-input-port
.
(write! bytevector start count) Start and count will be non-negative exact integer objects, and bytevector will be a bytevector whose length is at least start + count. The write! procedure should write up to count bytes from bytevector starting at index start to the byte sink. If count is 0, the write! procedure should have the effect of passing an end-of-file object to the byte sink. In any case, the write! procedure should return the number of bytes that it wrote, as an exact integer object.
[R6RS] Returns a newly created textual output port whose byte sink is an arbitrary algorithm represented by the write! procedure. Id must be a string naming the new port, provided for informational purposes only. _Write!_must be a procedure and should behave as specified below; it will be called by operations that perform textual output.
Each of the remaining arguments may be #f; if any of those arguments is not #f,
it must be a procedure and should behave as specified in the description of
make-custom-textual-input-port
.
(write! string start count) Start and count will be non-negative exact integer objects, and string will be a string whose length is at least start + count. The write! procedure should write up to count characters from string starting at index start to the character sink. If _count_is 0, the write! procedure should have the effect of passing an end-of-file object to the character sink. In any case, the write! procedure should return the number of characters that it wrote, as an exact integer object.
[R6RS] Writes octet to the output port and returns unspecified values.
[R6RS] Start and count must be non-negative exact integer
objects that default to 0 and (bytevector-length _bytevector_)
- start,
respectively. Bytevector must have a length of at least start + count.
The put-bytevector
procedure writes the count bytes of the bytevector
bytevector starting at index start to the output port. The
put-bytevector
procedure returns unspecified values.
[R6RS] Writes char to the port and returns unspecified values.
[R6RS] Start and count must be non-negative exact integer
objects. String must have a length of at least start + count.
Start defaults to 0. Count defaults to
(string-length _string_)
- start. The put-string
procedure
writes the count characters of string starting at index start to the
port. The put-string
procedure returns unspecified values.
[R6RS] Datum should be a datum value. The put-datum
procedure
writes an external representation of datum to textual-output-port.
[R6RS] Returns a single port that is both an input port and an output port
for the named file. The optional arguments default as described in the
specification of open-file-output-port
. If the input/output port supports
port-position
and/or set-port-position!
, the same port position
is used for both input and output.
[R6RS+] Returns a newly created binary input/output port whose byte source
and sink are arbitrary algorithms represented by the read! and
write! procedures. Id must be a string naming the new port,
provided for informational purposes only. Read! and write! must
be procedures, and should behave as specified for the
make-custom-binary-input-port
and
make-custom-binary-output-port
procedures.
Each of the remaining arguments may be #f; if any of those arguments is not #f,
it must be a procedure and should behave as specified in the description of
make-custom-binary-input-port
.
[R6RS+] Returns a newly created textual input/output port whose byte
source and sink are arbitrary algorithms represented by the _read!_and write! procedures. Id must be a string naming the new port,
provided for informational purposes only. Read! and write! must
be procedures, and should behave as specified for the
make-custom-textual-input-port
and
make-custom-textual-output-port
procedures.
Each of the remaining arguments may be #f; if any of those arguments is not #f,
it must be a procedure and should behave as specified in the description of
make-custom-textual-input-port
.
This section describes the (rnrs io simple (6))
library, which provides
a somewhat more convenient interface for performing textual I/O on ports.
This library also exports the same procedures as
(rnrs io posts (6))
library. I do not write the documentation of it, if
you want to import only this library, make sure which procedures are exported.
You can see it on R6RS.
[R6RS+] Proc should accept one argument.
These procedures open the file named by filename for input or for output, with no specified file options, and call proc with the obtained port as an argument. If proc returns, the port is closed automatically and the values returned by proc are returned. If proc does not return, the port is not closed automatically, unless it is possible to prove that the port will never again be used for an I/O operation.
NOTE: opt will be passed to open-input-file
or
open-output-file
.
[R6RS+] Thunk must be a procedure and must accept zero arguments.
The file is opened for input or output using empty file options, and _thunk_is called with no arguments. These procedure replace current input/output port during thunk is being called. When thunk returns, the port is closed automatically. The values returned by thunk are returned.
NOTE: opt will be passed to open-input-file
or
open-output-file
.
[R6RS+] Opens filename for input/output, with empty file options, and returns the obtained port.
If keyword argument transcoder is given, it must be an transcoder or #f and will be used to specify the transcoder to open input/output port. If it is #f, then returned port will be binary port.
[R6RS] Closes input-port or output-port, respectively.
[R6RS] These work the same as get-char
and lookahead-char
.
If textual-input-port is omitted, it defaults to the value returned by
current-input-port
.
[R6RS] Reads an external representation from _textual-input-port_and returns the datum it represents. The read procedure operates in the same way as get-datum.
If textual-input-port is omitted, it defaults to the value returned by
current-input-port
.
[R6RS] Writes an encoding of the character char to the textual-output-port, and returns unspecified values.
If textual-output-port is omitted, it defaults to the value returned by
current-output-port
.
[R6RS] This is equivalent to using write-char
to write
#\linefeed
to textual-output-port.
If textual-output-port is omitted, it defaults to the value returned by
current-output-port
.
[R6RS] Writes a representation of obj to the given textual-output-port. Strings that appear in the written representation are not enclosed in double quotes, and no characters are escaped within those strings. Character objects appear in the representation as if written by write-char instead of by write. The display procedure returns unspecified values.
If textual-output-port is omitted, it defaults to the value returned by
current-output-port
.
[R6RS] Writes the external representation of obj to
textual-output-port. The write
procedure operates in the same way
as put-datum
.
If textual-output-port is omitted, it defaults to the value returned by
current-output-port
.
This library, in addition to the procedures described here, also exports the I/O condition types described in I/O condition types.
[R6RS] Filename must be a file name (see Port I/O).
The file-exists?
procedure returns #t if the named file exists at the time
the procedure is called, #f otherwise.
[R6RS] Filename must be a file name (see Port I/O).
The delete-file
procedure deletes the named file if it exists and can be
deleted, and returns unspecified values. If the file does not exist or cannot be
deleted, an exception with condition type &i/o-filename
is raised.
This library provides command-line arguments access and exit procedures.
[R6RS] Returns a nonempty list of strings. The first element is the running script file name or '() on REPL. The remaining elements are command-line arguments according to the operating system's conventions.
[R6RS] Exits the running program and communicates an exit value to the operating system. If no argument is supplied, the exit procedure should communicate to the operating system that the program exited normally. If an argument is supplied and if it is fixnum, the exit procedure translates it into an appropriate exit value for the operating system. Otherwise the exit is assumed to be abnormal.
This section describes Scheme's libraries for more specialized numerical operations: fixnum and flonum arithmetic, as well as bitwise operations on exact integer objects.
A number of procedures operate on the binary two's-complement representations of exact integer objects: Bit positions within an exact integer object are counted from the right, i.e. bit 0 is the least significant bit. Some procedures allow extracting bit fields, i.e., number objects representing subsequences of the binary representation of an exact integer object. Bit fields are always positive, and always defined using a finite number of bits.
On Sagittarius Scheme, fixnum is 30 bits or 62 bits depending on platform. On 32 bits platform it fixnum is 30 bits, and 64 bits platform it is 62 bits. However, non 32 bits platform is not well tested so if you find a bug please send a report.
This section uses fx, fx1 fx2, etc., as parameter names for arguments that must be fixnums.
[R6RS] Returns #t if obj is an exact integer object within the fixnum range, #f otherwise.
[R6RS] These procedures returns bit size of fixnum, minimum and maximum value of the fixnum range, respectively.
[R6RS] These procedures return #t if their arguments are: equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing, #f otherwise.
[R6RS] These numerical predicates test a fixnum for a particular property, returning #t or #f. The five properties tested by these procedures are: whether the number object is zero, greater than zero, less than zero, odd, or even.
[R6RS] These procedures return the maximum or minimum of their arguments.
[R6RS] These procedures return the sum or product of their arguments,
provided that sum or product is a fixnum. An exception with condition type
&implementation-restriction
is raised if that sum or product is not a
fixnum.
[R6RS] With two arguments, this procedure returns the difference fx1- fx2, provided that difference is a fixnum.
With one argument, this procedure returns the additive inverse of its argument, provided that integer object is a fixnum.
An exception with condition type &implementation-restriction
is raised if
the mathematically correct result of this procedure is not a fixnum.
NOTE: R6RS says it raises &assertion
if the result is not fixnum, however
Sagittarius raises &implementation-restriction
for consistency with
fx+
and fx*
.
[R6RS] Fx2 must be nonzero. These procedures implement number-theoretic
integer division and return the results of the corresponding mathematical operations
specified in
(rnrs base (6))
section.
[R6RS] Returns the two fixnum results of the following computation:
(let* ((s (+ _fx1_ _fx2_ _fx3_))
(s0 (mod0 s (expt 2 (fixnum-width))))
(s1 (div0 s (expt 2 (fixnum-width)))))
(values s0 s1))
[R6RS] Returns the two fixnum results of the following computation:
(let* ((d (- _fx1_ _fx2_ _fx3_))
(d0 (mod0 d (expt 2 (fixnum-width))))
(d1 (div0 d (expt 2 (fixnum-width)))))
(values d0 d1))
[R6RS] Returns the two fixnum results of the following computation:
(let* ((s (+ (* _fx1_ _fx2_) _fx3_))
(s0 (mod0 s (expt 2 (fixnum-width))))
(s1 (div0 s (expt 2 (fixnum-width)))))
(values s0 s1))
[R6RS] Returns bitwise not of fixnum fx.
[R6RS] These procedures return the fixnum that is the bit-wise "and", "inclusive or", or "exclusive or" of the two's complement representations of their arguments. If they are passed only one argument, they return that argument. If they are passed no arguments, they return the fixnum (either - 1 or 0) that acts as identity for the operation.
[R6RS] Returns the fixnum that is the bit-wise "if" of the two's complement representations of its arguments, i.e. for each bit, if it is 1 in fx1, the corresponding bit in fx2 becomes the value of the corresponding bit in the result, and if it is 0, the corresponding bit in fx3 becomes the corresponding bit in the value of the result. This is the fixnum result of the following computation:
(fxior (fxand _fx1_ _fx2_)
(fxand (fxnot _fx1_) _fx3_))
[R6RS] If fx is non-negative, this procedure returns the number of 1 bits in the two's complement representation of fx. Otherwise it returns the result of the following computation:
(fxnot (fxbit-count (fxnot _ei_)))
[R6RS] Returns the number of bits needed to represent fx if it is
positive, and the number of bits needed to represent (fxnot _fx_)
if
it is negative, which is the fixnum result of the following computation:
(do ((result 0 (+ result 1))
(bits (if (fxnegative? _fx_)
(fxnot _fx_)
_fx_)
(fxarithmetic-shift-right bits 1)))
((fxzero? bits)
result))
[R6RS] Returns the index of the least significant 1 bit in the two's complement representation of fx. If fx is 0, then - 1 is returned.
[R6RS] Fx2 must be non-negative and less than (fixnum-width)
.
The fxbit-set?
procedure returns #t if the _fx2_th bit is 1 in the
two's complement representation of fx1, and #f otherwise. This is the
fixnum result of the following computation:
(not
(fxzero?
(fxand _fx1_ (fxarithmetic-shift-left 1 _fx2_))))
[R6RS] Fx2 must be non-negative and less than (fixnum-width)
.
Fx3 must be 0 or 1. The fxcopy-bit
procedure returns the result of
replacing the _fx2_th bit of fx1 by fx3, which is the result of
the following computation:
(let* ((mask (fxarithmetic-shift-left 1 _fx2_)))
(fxif mask
(fxarithmetic-shift-left _fx3_ _fx2_)
_fx1_))
[R6RS] Fx2 and fx3 must be non-negative and less than
(fixnum-width)
. Moreover, fx2 must be less than or equal to
fx3. The fxbit-field
procedure returns the number represented by
the bits at the positions from fx2 (inclusive) to fx3 (exclusive),
which is the fixnum result of the following computation:
(let* ((mask (fxnot
(fxarithmetic-shift-left -1 _fx3_))))
(fxarithmetic-shift-right (fxand _fx1_ mask)
_fx2_))
[R6RS] Fx2 and fx3 must be non-negative and less than
(fixnum-width)
. Moreover, fx2 must be less than or equal to
fx3. The fxcopy-bit-field
procedure returns the result of replacing
in fx1 the bits at positions from fx2 (inclusive) to fx3(exclusive) by the corresponding bits in fx4, which is the fixnum result
of the following computation:
(let* ((to _fx1_)
(start _fx2_)
(end _fx3_)
(from _fx4_)
(mask1 (fxarithmetic-shift-left -1 start))
(mask2 (fxnot
(fxarithmetic-shift-left -1 end)))
(mask (fxand mask1 mask2)))
(fxif mask
(fxarithmetic-shift-left from start)
to))
[R6RS] The absolute value of fx2 must be less than
(fixnum-width)
. If
(floor (* _fx1_ (expt 2 _fx2_)))
is a fixnum, then that fixnum is returned. Otherwise an exception with condition
type &implementation-restriction
is raised.
[R6RS] Fx2 must be non-negative, and less than (fixnum-width)
.
The fxarithmetic-shift-left
procedure behaves the same as
fxarithmetic-shift
, and (fxarithmetic-shift-right _fx1_ _fx2_)
behaves the same as (fxarithmetic-shift _fx1_ (fx- _fx2_))
.
[R6RS] Fx2, fx3, and fx4 must be non-negative and less
than (fixnum-width)
. Fx2 must be less than or equal to fx3.
Fx4 must be less than the difference between fx3 and fx2. The
fxrotate-bit-field
procedure returns the result of cyclically permuting
in fx1 the bits at positions from fx2 (inclusive) to fx3(exclusive) by fx4 bits towards the more significant bits, which is the
result of the following computation:
(let* ((n _fx1_)
(start _fx2_)
(end _fx3_)
(count _fx4_)
(width (fx- end start)))
(if (fxpositive? width)
(let* ((count (fxmod count width))
(field0
(fxbit-field n start end))
(field1
(fxarithmetic-shift-left
field0 count))
(field2
(fxarithmetic-shift-right
field0 (fx- width count)))
(field (fxior field1 field2)))
(fxcopy-bit-field n start end field))
n))
[R6RS] Fx2 and fx3 must be non-negative and less than
(fixnum-width)
. Moreover, fx2 must be less than or equal to fx3.
The fxreverse-bit-field
procedure returns the fixnum obtained from
fx1 by reversing the order of the bits at positions from fx2(inclusive) to fx3 (exclusive).
This section describes the (rnrs arithmetic flonums (6))
library.
This section uses fl, fl1, fl2, etc., as parameter names for
arguments that must be flonums, and ifl as a name for arguments that must
be integer-valued flonums, i.e., flonums for which the integer-valued?
predicate returns true.
[R6RS] This library exports procedures for flonum operations.
[R6RS] Returns #t if obj is a flonum, #f otherwise.
[R6RS] These procedures return #t if their arguments are (respectively): equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing, #f otherwise.
[R6RS] These numerical predicates test a flonum for a particular property,
returning #t or #f. The flinteger?
procedure tests whether the number
object is an integer, flzero?
tests whether it is fl=?
to zero,
flpositive?
tests whether it is greater than zero, flnegative?
tests whether it is less than zero
, flodd?
tests whether it is
odd, fleven?
tests whether it is even, flfinite?
tests whether
it is not an infinity and not a NaN, flinfinite?
tests whether it is
an infinity, and flnan?
tests whether it is a NaN.
[R6RS] These procedures return the maximum or minimum of their arguments. They always return a NaN when one or more of the arguments is a NaN.
[R6RS] These procedures return the flonum sum or product of their flonum arguments. In general, they should return the flonum that best approximates the mathematical sum or product.
[R6RS] Returns the absolute value of fl.
[R6RS] These procedures implement number-theoretic integer division and
return the results of the corresponding mathematical operations (see
(rnrs base (6))
. For zero divisors, these
procedures may return a NaN or some unspecified flonum.
[R6RS] These procedures return the numerator or denominator of fl as a flonum; the result is computed as if fl was represented as a fraction in lowest terms. The denominator is always positive. The denominator of 0.0 is defined to be 1.0.
[R6RS] These procedures return integral flonums for flonum arguments that
are not infinities or NaNs. For such arguments, flfloor
returns the largest
integral flonum not larger than fl. The flceiling
procedure returns
the smallest integral flonum not smaller than fl. The fltruncate
procedure returns the integral flonum closest to fl whose absolute value
is not larger than the absolute value of fl. The flround
procedure
returns the closest integral flonum to fl, rounding to even when _fl_represents a number halfway between two integers.
Although infinities and NaNs are not integer objects, these procedures return an infinity when given an infinity as an argument, and a NaN when given a NaN.
[R6RS] These procedures compute the usual transcendental functions. The flexp
procedure computes the base-e exponential of fl. The fllog
procedure
with a single argument computes the natural logarithm of fl1
(not the base
ten logarithm); (fllog _fl1_ _fl2_)
computes the base-_fl2_logarithm of fl1. The flasin
, flacos
, and flatan
procedures compute arcsine, arccosine, and arctangent, respectively.
(flatan _fl1_ _fl2_)
computes the arc tangent of fl1/fl2.
[R6RS] Returns the principal square root of fl. For - 0.0, flsqrt
returns 0.0; for other negative arguments, the result unspecified flonum.
[R6RS] Either fl1 should be non-negative, or, if fl1 is negative,
fl2 should be an integer object. The flexpt
procedure returns _fl1_raised to the power fl2. If fl1 is negative and fl2 is not an
integer object, the result is a NaN. If fl1 is zero, then the result is zero.
[R6RS] These types describe that a program has executed an arithmetic operations that is specified to return an infinity or a NaN, respectively.
Here is the hierarchy of these conditions.
+ &implementation-restriction (see ["Conditions"](#rnrs.conditions.6))
+ &no-infinities
+ &no-nans
[R6RS] Returns a flonum that is numerically closest to fx.
This section describes the (rnrs arithmetic bitwise (6))
library.
The exact bitwise arithmetic provides generic operations on exact integer
objects. This section uses ei, ei1, ei2, etc., as parameter
names that must be exact integer objects.
[R6RS] This library exports procedures for exact bitwise arithmetic operations.
[R6RS] Returns the exact integer object whose two's complement representation is the one's complement of the two's complement representation of ei.
[R6RS] These procedures return the exact integer object that is the bit-wise "and", "inclusive or", or "exclusive or" of the two's complement representations of their arguments. If they are passed only one argument, they return that argument. If they are passed no arguments, they return the integer object (either - 1 or 0) that acts as identity for the operation.
[R6RS] Returns the exact integer object that is the bit-wise "if" of the two's complement representations of its arguments, i.e. for each bit, if it is 1 in ei1, the corresponding bit in ei2 becomes the value of the corresponding bit in the result, and if it is 0, the corresponding bit in ei3 becomes the corresponding bit in the value of the result. This is the result of the following computation:
(bitwise-ior (bitwise-and _ei1_ _ei2_)
(bitwise-and (bitwise-not _ei1_) _ei3_))
[R6RS] If ei is non-negative, this procedure returns the number of 1 bits in the two's complement representation of ei. Otherwise it returns the result of the following computation:
(bitwise-not (bitwise-bit-count (bitwise-not _ei_)))
[R6RS] Returns the number of bits needed to represent ei if it is
positive, and the number of bits needed to represent
(bitwise-not _ei_)
if it is negative, which is the exact integer
object that is the result of the following computation:
(do ((result 0 (+ result 1))
(bits (if (negative? _ei_)
(bitwise-not _ei_)
_ei_)
(bitwise-arithmetic-shift bits -1)))
((zero? bits)
result))
[R6RS] Returns the index of the least significant 1 bit in the two's complement representation of ei. If ei is 0, then - 1 is returned.
[R6RS] Ei2 must be non-negative. The bitwise-bit-set?
procedure returns #t if the _ei2_th bit is 1 in the two's complement
representation of ei1, and #f otherwise. This is the result of the
following computation:
(not (zero?
(bitwise-and
(bitwise-arithmetic-shift-left 1 _ei2_)
_ei1_)))
[R6RS] Ei2 must be non-negative, and ei3 must be either 0
or 1. The bitwise-copy-bit
procedure returns the result of replacing the
_ei2_th bit of ei1 by the _ei2_th bit of ei3, which is the
result of the following computation:
(let* ((mask (bitwise-arithmetic-shift-left 1 _ei2_)))
(bitwise-if mask
(bitwise-arithmetic-shift-left _ei3_ _ei2_)
_ei1_))
[R6RS] Ei2 and ei3 must be non-negative, and ei2 must be
less than or equal to ei3. The bitwise-bit-field
procedure returns
he number represented by the bits at the positions from ei2 (inclusive) to
ei3 (exclusive), which is the result of the following computation:
(let ((mask
(bitwise-not
(bitwise-arithmetic-shift-left -1 _ei3_))))
(bitwise-arithmetic-shift-right
(bitwise-and _ei1_ mask)
_ei2_))
[R6RS] Ei2 and ei3 must be non-negative, and ei2 must
be less than or equal to ei3. The bitwise-copy-bit-field
procedure
returns the result of replacing in ei1 the bits at positions from
var{ei2} (inclusive) to ei3 (exclusive) by the corresponding bits in
ei4, which is the fixnum result of the following computation:
(let* ((to _ei1_)
(start _ei2_)
(end _ei3_)
(from _ei4_)
(mask1
(bitwise-arithmetic-shift-left -1 start))
(mask2
(bitwise-not
(bitwise-arithmetic-shift-left -1 end)))
(mask (bitwise-and mask1 mask2)))
(bitwise-if mask
(bitwise-arithmetic-shift-left from
start)
to))
[R6RS] Returns the result of the following computation:
(floor (* _ei1_ (expt 2 _ei2_)))
ei2 must be a fixnum. This is implementation restriction.
[R6RS] Ei2 must be non-negative. The
bitwise-arithmetic-shift-left
procedure returns the same result as
bitwise-arithmetic-shift
, and
(bitwise-arithmetic-shift-right _ei1_ _ei2_)
returns the same result as
(bitwise-arithmetic-shift _ei1_ (- _ei2_))
.
ei2 must be a fixnum. This is implementation restriction.
[R6RS] Ei2, ei3, ei4 must be non-negative, _ei2_must be less than or equal to ei3, and ei4 must be non-negative.
The bitwise-rotate-bit-field
procedure returns the result of cyclically
permuting in ei1 the bits at positions from ei2 (inclusive) to
ei3 (exclusive) by ei4 bits towards the more significant bits,
which is the result of the following computation:
(let* ((n _ei1_)
(start _ei2_)
(end _ei3_)
(count _ei4_)
(width (- end start)))
(if (positive? width)
(let* ((count (mod count width))
(field0
(bitwise-bit-field n start end))
(field1 (bitwise-arithmetic-shift-left
field0 count))
(field2 (bitwise-arithmetic-shift-right
field0
(- width count)))
(field (bitwise-ior field1 field2)))
(bitwise-copy-bit-field n start end field))
n))
ei4 must be a fixnum. This is implementation restriction.
[R6RS] Ei2 and ei3 must be non-negative, and ei2 must be
less than or equal to ei3. The bitwise-reverse-bit-field
procedure
returns the result obtained from ei1 by reversing the order of the bits at
positions from ei2 (inclusive) to ei3 (exclusive).
[R6RS] The (rnrs syntax-case (6))
library provides support for
writing low-level macros in a high-level style, with automatic syntax checking,
input destructuring, output restructuring, maintenance of lexical scoping and
referential transparency (hygiene), and support for controlled identifier capture.
[R6RS] Each literal must be an identifier. Each clause must take one of the following two forms.
(_pattern_ _output-expression_)
(_pattern_ _fender_ _output-expression_)
Fender and output-expression must be expressions.
Pattern is the same as syntax-rules
. See
(rnrs base (6)) section.
A syntax-case
expression first evaluates expression. It then attempts to
match the pattern from the first clause against the resulting value,
which is unwrapped as necessary to perform the match. If the _pattern_matches the value and no fender is present, output-expression is
evaluated and its value returned as the value of the syntax-case
expression.
If the pattern does not match the value, syntax-case
tries the second
clause, then the third, and so on. It is a syntax violation if the value
does not match any of the patterns.
If the optional fender is present, it serves as an additional constraint on acceptance of a clause. If the pattern of a given clause matches the input value, the corresponding fender is evaluated. If fender evaluates to a true value, the clause is accepted; otherwise, the clause is rejected as if the pattern had failed to match the value. Fenders are logically a part of the matching process, i.e., they specify additional matching constraints beyond the basic structure of the input.
Pattern variables contained within a clause's pattern are bound to the corresponding pieces of the input value within the clause's fender (if present) and output-expression. Pattern variables can be referenced only within syntax expressions (see below). Pattern variables occupy the same name space as program variables and keywords.
If the syntax-case
form is in tail context, the output-expressions
are also in tail position.
[R6RS] A template is a pattern variable, an identifier that is not a pattern variable, a pattern datum, or one of the following.
(_subtemplate_ ...)
(_subtemplate_ ... . _template_)
#(_subtemplate_ ...)
A subtemplate is a template followed by zero or more ellipses.
The value of a syntax
form is a copy of template in which the
pattern variables appearing within the template are replaced with the input
subforms to which they are bound. Pattern data and identifiers that are not
pattern variables or ellipses are copied directly into the output. A
subtemplate followed by an ellipsis expands into zero or more occurrences
of the subtemplate. Pattern variables that occur in subpatterns followed
by one or more ellipses may occur only in subtemplates that are followed by
(at least) as many ellipses. These pattern variables are replaced in the output
by the input subforms to which they are bound, distributed as specified. If a
pattern variable is followed by more ellipses in the subtemplate than in
the associated subpattern, the input form is replicated as necessary. The
subtemplate must contain at least one pattern variable from a subpattern
followed by an ellipsis, and for at least one such pattern variable, the
subtemplate must be followed by exactly as many ellipses as the subpattern
in which the pattern variable appears.
[R6RS] Returns #t if obj is an identifier, i.e., a syntax object representing an identifier, and #f otherwise.
[R6RS] Id1 and id2 must be identifiers. The procedure
bound-identifier=?
returns #t if given arguments are exactly the same object.
The bound-identifier=? procedure can be used for detecting duplicate identifiers in a binding construct or for other preprocessing of a binding construct that requires detecting instances of the bound identifiers.
[R6RS] Id1 and id2 must be identifiers. The free-identifier=?
procedure returns #t if given arguments are indicating the same bindings.
[R6RS] Strips all syntactic information from a syntax object and returns the corresponding Scheme datum.
[R6RS] Template-id must be a template identifier and _datum_should be a datum value.
The datum->syntax
procedure returns a syntax-object representation of
datum that contains the same contextual information as template-id,
with the effect that the syntax object behaves as if it were introduced into the
code when template-id was introduced.
The datum->syntax
procedure allows a transformer to "bend" lexical scoping
rules by creating implicit identifiers that behave as if they were present in the
input form, thus permitting the definition of macros that introduce visible
bindings for or references to identifiers that do not appear explicitly in the
input form. For example, the following defines a loop
expression that uses
this controlled form of identifier capture to bind the variable break to an escape
procedure within the loop body.
(define-syntax loop
(lambda (x)
(syntax-case x ()
[(k e ...)
(with-syntax
([break (datum->syntax (syntax k) 'break)])
(syntax
(call-with-current-continuation
(lambda (break)
(let f () e ... (f))))))])))
(let ((n 3) (ls '()))
(loop
(if (= n 0) (break ls))
(set! ls (cons 'a ls))
(set! n (- n 1))))
(a a a)
[R6RS] L must be a list or syntax object representing a list-structured form. The number of temporaries generated is the number of elements in l. Each temporary is guaranteed to be unique.
NOTE: If you want to create just one temporary symbol and do not think about
portability, it's better to use gensym
in (sagittarius)
library.
[R6RS] The with-syntax
form is used to bind pattern variables, just
as let
is used to bind variables. This allows a transformer to construct
its output in separate pieces, then put the pieces together.
Each pattern is identical in form to a syntax-case
pattern. The
value of each expression is computed and destructured according to the
corresponding pattern, and pattern variables within the pattern are
bound as with syntax-case
to the corresponding portions of the value
within body.
[R6RS] The quasisyntax
form is similar to syntax
, but it
allows parts of the quoted text to be evaluated, in a manner similar to the
operation of quasiquote
.
Within a quasisyntax
template, subforms of unsyntax
and
unsyntax-splicing
forms are evaluated, and everything else is treated
as ordinary template material, as with syntax
. The value of each
unsyntax
subform is inserted into the output in place of the unsyntax
form, while the value of each unsyntax-splicing
subform is spliced into
the surrounding list or vector structure. Uses of unsyntax
and
unsyntax-splicing
are valid only within quasisyntax
expressions.
A quasisyntax
expression may be nested, with each quasisyntax
introducing a new level of syntax quotation and each unsyntax
or
unsyntax-splicing
taking away a level of quotation. An expression nested
within n quasisyntax
expressions must be within n unsyntax
or
unsyntax-splicing
expressions to be evaluated.
[R6RS] Who must be #f or a string or a symbol. Message must be a string. Form must be a syntax object or a datum value. Subform must be a syntax object or a datum value.
The syntax-violation
procedure raises an exception, reporting a syntax
violation. Who should describe the macro transformer that detected the
exception. The message argument should describe the violation. _Form_should be the erroneous source syntax object or a datum value representing a form.
The optional subform argument should be a syntax object or datum value
representing a form that more precisely locates the violation.
The (rnrs hashtables (6))
library provides a set of operations on
hashtables. A hashtable is a data structure that associates keys with
values. Any object can be used as a key, provided a hash function and a
suitable equivalence function is available. A hash function is a
procedure that maps keys to exact integer objects. It is the programmer's
responsibility to ensure that the hash function is compatible with the
equivalence function, which is a procedure that accepts two keys and returns
true if they are equivalent and #f otherwise. Standard hashtables for arbitrary
objects based on the eq?
and eqv?
predicates are provided. Also,
hash functions for arbitrary objects, strings, and symbols are provided.
This section uses the hashtable parameter name for arguments that must be hashtables, and the key parameter name for arguments that must be hashtable keys.
[R6RS] This library exports a set of operations on hashtables.
[R6RS+] Returns a newly allocated mutable hashtable that accepts arbitrary
objects as keys, and compares those keys with eq?
(make-eq-hashtable
) or eqv?
(make-eqv-hashtable
).
If optional argument k is given, it must be exact non-negative integer or
#f
. If it's #f
, then the procedure picks up default initial
capacity, otherwise the initial capacity of the hashtable is set to
approximately k elements.
If optional argument weakness is given, then it must be one of the
symbols key
, value
or both
, or #f
. If the value is
one of the symbols, then the procedure creates weak hashtable of given symbol's
weakness. If the symbol is key
, then entries whose keys are refered only
from this hashtable might be removed when garbage collection is
occurred. value
is for entry values. both
is for both.
[R6RS] Hash-function and equiv must be procedures.
Hash-function should accept a key as an argument and should return a non-negative exact integer object. Equiv should accept two keys as arguments and return a single value.
The make-hashtable
procedure returns a newly allocated mutable hashtable
using hash-function as the hash function and equiv as the
equivalence function used to compare keys.
If optional argument k and weakness are the same as
make-eq-hashtable
and make-eqv-hashtable
.
[R6RS] Returns #t if obj is a hashtable, #f otherwise.
[R6RS] Returns the number of keys contained in hashtable as an exact integer object.
[R6RS+] Returns the value in hashtable associated with key. If hashtable does not contain an association for key, default is returned.
Since Sagittarius version 0.3.4, this procedure's default argument is optional to implement SRFI-17 efficiently.
[R6RS] Changes hashtable to associate key with obj, adding a new association or replacing any existing association for key, and returns unspecified values.
[R6RS] Removes any association for key within hashtable and returns unspecified values.
[R6RS] Returns #t if hashtable contains an association for key, #f otherwise.
Note: On Sagittarius, hashtable-ref
and hashtable-contains?
do
not make any difference fot the performance.
desc{[R6RS] Proc should accept one argument, should return a single value.
The hashtable-update!
procedure applies proc to the value in
hashtable associated with key, or to default if
hashtable does not contain an association for key. The
hashtable is then changed to associate key with the value returned
by proc.
}
[R6RS] Returns a copy of hashtable. If the mutable argument is provided and is true, the returned hashtable is mutable; otherwise it is immutable.
[R6RS] Removes all associations from hashtable and returns unspecified values.
If a second argument is given, the current capacity of the hashtable is reset to approximately k elements.
[R6RS] Returns a vector of all keys or entries in hashtable, respectively. The order of the vector is unspecified.
[R6RS] Returns the equivalence or hash function used by _hashtable_respectively.
[R6RS] Returns #t if hashtable is mutable, otherwise #f.
[R6RS] Returns hash value of given argument. Each procedures return
the hash values suitable for equal?
and symbols.
[R6RS+][SRFI-13] Returns hash value of given argument. Each procedures
return the hash values suitable for string=?
and string-ci=?
.
If the optional argument start and end is given, then the given string will be substringed with start and end.
If the optional argument bound is given, it must be exact integer and hash function will also use the given value.
This section describes the (rnrs enums (6))
library for dealing with
enumerated values and sets of enumerated values. Enumerated values are represented
by ordinary symbols, while finite sets of enumerated values form a separate type,
known as the enumeration sets. The enumeration sets are further partitioned
into sets that share the same universe and enumeration type. These
universes and enumeration types are created by the make-enumeration
procedure. Each call to that procedure creates a new enumeration type.
[R6RS] This library interprets each enumeration set with respect to its specific universe of symbols and enumeration type. This facilitates efficient implementation of enumeration sets and enables the complement operation.
In the descriptions of the following procedures, enum-set ranges over the enumeration sets, which are defined as the subsets of the universes that can be defined using make-enumeration.
[R6RS] Symbol-list must be a list of symbols.
The make-enumeration
procedure creates a new enumeration type whose
universe consists of those symbols (in canonical order of their first appearance
in the list) and returns that universe as an enumeration set whose universe is
itself and whose enumeration type is the newly created enumeration type.
[R6RS] Returns the set of all symbols that comprise the universe of its argument, as an enumeration set.
[R6RS] Returns a unary procedure that, given a symbol that is in the universe of enum-set, returns its 0-origin index within the canonical ordering of the symbols in the universe; given a value not in the universe, the unary procedure returns #f.
[R6RS] Returns a unary procedure that, given a list of symbols that belong to the universe of enum-set, returns a subset of that universe that contains exactly the symbols in the list. The values in the list must all belong to the universe.
[R6RS] Returns a list of the symbols that belong to its argument, in the canonical order of the universe of enum-set.
[R6RS] The enum-set-member?
procedure returns #t if its first
argument is an element of its second argument, #f otherwise.
The enum-set-subset?
procedure returns #t if the universe of
enum-set1 is a subset of the universe of enum-set2 (considered as
sets of symbols) and every element of enum-set1 is a member of
enum-set2. It returns #f otherwise.
The enum-set=?
procedure returns #t if enum-set1 is a subset of
enum-set2 and vice versa, as determined by the enum-set-subset?
procedure. This implies that the universes of the two sets are equal as sets of
symbols, but does not imply that they are equal as enumeration types. Otherwise,
#f is returned.
[R6RS] Enum-set1 and enum-set2 must be enumeration sets that have the same enumeration type.
The enum-set-union
procedure returns the union of enum-set1 and
enum-set2.
The enum-set-intersection
procedure returns the intersection of
enum-set1 and enum-set2.
The enum-set-difference
procedure returns the difference of _enum-set1_and enum-set2.
[R6RS] Returns enum-set's complement with respect to its universe.
[R6RS] Projects enum-set1 into the universe of enum-set2, dropping any elements of enum-set1 that do not belong to the universe of enum-set2. (If enum-set1 is a subset of the universe of its second, no elements are dropped, and the injection is returned.)
[R6RS] The define-enumeration
form defines an enumeration type and
provides two macros for constructing its members and sets of its members.
A define-enumeration
form is a definition and can appear anywhere any
other definition can appear.
Type-name is an identifier that is bound as a syntactic keyword; symbol ... are the symbols that comprise the universe of the enumeration (in order).
(_type-name_ _symbol_)
checks at macro-expansion time whether the
name of symbol is in the universe associated with type-name. If it is,
(_type-name_ _symbol_)
is equivalent to symbol. It is a syntax
violation if it is not.
Constructor-syntax is an identifier that is bound to a macro that, given any finite sequence of the symbols in the universe, possibly with duplicates, expands into an expression that evaluates to the enumeration set of those symbols.
(_constructor-syntax_ _symbol ..._)
checks at macro-expansion
time whether every symbol ... is in the universe associated with
type-name. It is a syntax violation if one or more is not. Otherwise
(_constructor-syntax_ _symbol ..._)
is equivalent to
((enum-set-constructor (_constructor-syntax_))
'(_symbol ..._))
.
[R6RS]The (rnrs eval (6))
library allows a program to create Scheme
expressions as data at run time and evaluate them.
[R6RS] Evaluates expression in the specified environment and returns its value. Expression must be a syntactically valid Scheme expression represented as a datum value.
R6RS requires envionment an envitonment which must be created by the
environment
procedure. However on Sagittarius, environment can be
anything. This behaviour might be fixed in future.
[R6RS] Import-spec must be a datum representing an import spec. The
environment
procedure returns an environment corresponding to import-spec.
[R6RS] This library exports set-car!
and set-cdr!
.
[R6RS] Store obj in the car/cdr field of pair. These procedures return unspecified value.
On Sagittarius Scheme, these procedures can modify immutable pairs.
[R6RS] This library exports string-set!
and string-fill!
.
[R6RS] K must be a valid index of string.
The string-set!
procedure stores char in element k of string
and returns unspecified values.
[R6RS+] Stores char in every element of the given string and returns unspecified values. Optional arguments start and end restrict the ragne of filling.
Passing an immutable string to these procedures cause an exception with condition
type &assertion
to be raised.
This library provides R5RS compatibility procedures such as
exact->inexact
.
[R6RS] These are the same as the inexact
and exact
procedures.
[R6RS] Returns the quotient, remainder and modulo of dividing an integer n1 by an integer n2, respectively. The result is an exact number only if both n1 and n2 are exact numbers.
[R6RS] The delay
construct is used together with the procedure
force
to implement lazy evaluation or call by need.
(delay _expression_)
returns an object called a promise which
at some point in the future may be asked (by the force
procedure) to
evaluate expression, and deliver the resulting value. The effect of expression
returning multiple values is unspecified.
[R6RS] Promise must be a promise.
The force
procedure forces the value of promise. If no value has
been computed for the promise, then a value is computed and returned. The value
of the promise is cached (or "memoized") so that if it is forced a second time,
the previously computed value is returned.
[R6RS] N must be the exact integer object 5. These procedures return
an environment which is suitable to use with eval
.
Sagittarius supports the latest Scheme standard R7RS. Even though the R7RS has incompatible from R6RS, however users can use both R6RS and R7RS libraries seamlessly.
On Sagittarius, user can call R7RS libraries on R6RS script and also other way around. However syntaxes are different. User can choose which syntax use.
[R7RS]name must be a list which can only contains symbol or exact integer.
clauses may be one of these:
(export
export-spec ...)
(import
import-set ...)
(begin
command-or-definition ...)
(include
filenames ...)
(include-ci
filenames ...)
(include-library-declarations
filenames ...)
(cond-expand
cond-expand-clause ...)
export
and import
are the same as R6RS. And on R7RS renaming
export syntax is different from R6RS, however on Sagittarius both can be
accepted.
begin
starts the library contents. However it can appear more than once.
include
and include-ci
includes the files which are specified
filenames. filenames must be string. This resolves file path from
current loading file. If the library file is /usr/local/lib/lib1.scm, then
search path will be /usr/local/lib. It can also take absolute path.
include-ci
reads the file case insensitive.
cond-exnpand
is the same as builtin syntax cond-expand
. For more
detail, see Builtin Syntax.
Sagittarius supports all R7RS libraries. However to avoid duplication, this section only describes the different procedures from R6RS. The same procedures are explicitly said 'the same as R6RS'.
[R7RS]R7RS base library.
These procedures/macros are the same as R6RS;
* + - ... / < <= = => > >=
abs and append apply assoc assq assv
begin binary-port? boolean=? boolean?
bytevector-copy bytevector-length bytevector-u8-ref
bytevector-u8-set! bytevector?
caar cadr call-with-current-continuation call-with-port
call-with-values call/cc car case cdar cddr cdr ceiling
char->integer char<=? char<? char=? char>=? char>? char?
close-input-port close-output-port close-port complex?
cond cons current-error-port current-input-port current-output-port
define define-record-type define-syntax denominator do dynamic-wind
else eof-object eof-object? eq? eqv? error even?
exact exact-integer-sqrt exact? expt
floor flush-output-port for-each
gcd guard
if inexact inexact? input-port? integer->char integer?
lambda lcm length let let* let*-values let-values
letrec letrec* list list->string list->vector
list-ref list-tail list?
make-bytevector make-string make-vector map max member memq memv min
modulo
negative? newline not null? number->string number? numerator
odd? or output-port?
pair? peek-char port? positive? procedure?
quasiquote quote quotient
raise raise-continuable rational? rationalize
read-char real? remainder reverse round
set! set-car! set-cdr!
string string->list string->number string->symbol string->utf8
string-append string-copy string-for-each string-length string-ref
string-fill! string-set!
string<=? string<? string=? string>=? string>? string? substring
symbol->string symbol=? symbol? syntax-rules
textual-port? truncate
unless unquote unquote-splicing utf8->string
values vector vector->list vector-fill! vector-for-each vector-length
vector-map vector-ref vector-set! vector?
when with-exception-handler write-char
zero?
This is defined in (sagittarius);
cond-expand
bytes must be a list of non negative exact integer and its value is up to 255.
Creates a bytevector whose content is values of bytes.
Returns a newly allocated bytevector whose contents are the concatenation of the contents in bytevectors.
NOTE: R6RS also has the same named procedure and does the same however the arguments lists are different.
to and from must be bytevectors. at must be a non negative exact integer in range of to size. Optional arguments start and end must be non negative exact integer in range of from and end must be bigger than end.
Copies content of from starting from start until end (exclusive) to to starting at. The operation is done destructively.
Returns a newly allocated copy of obj if it is a list. The list elements stays intact. So changing element's content affects original obj.
Stores value in element index of list.
Creates a list whose size is k.
If the optional argument fill is given then returning list is filled with fill, otherwise unspecified value is used.
vector must be a vector whose elements of range from _start_to end (exclusive) are characters.
Returns a string constructed with the above range of characters.
Returns a vector whose elements are characters of string in range of start and end (exclusive).
Returns a newly allocated vector whose contents are the concatenation of the contents in vectors.
Returns a vector whose elements are elements of given _vector_between start and end.
to and from must be vectors. at must be a non negative exact integer in range of to size. Optional arguments start and end must be non negative exact integer in range of from and end must be bigger than end.
Copies content of from starting from start until end (exclusive) to to starting at. The operation is done destructively.
to and from must be strings. at must be a non negative exact integer in range of to size. Optional arguments start and end must be non negative exact integer in range of from and end must be bigger than end.
Copies content of from starting from start until end (exclusive) to to starting at. The operation is done destructively.
Calls proc with given strings elements and returns a string whose content is constructed by the results of proc.
[SRFI-39] Returns a parameter object, which is an applicable object that can take zero or one argument.
The initial value is (_converter_ _init_)
if _converter_is given, otherwise init.
If the parameter object is applied without an argument, then it returns the value associated with the parameter object.
If the parameter object is applied with an argument, then it changes the associated value with the given value which may converted by _converter_if the parameter object is created with converter.
[SRFI-39] A parameterize
expression is used to change the
values returned by specified parameter objects during the evaluation of
body.
files must be strings.
Includes files as if it's written there. include-ci
reads
files case insensitively.
expression is evaluated and the formals are bound to the
return values in the same way that the formals in lambda
expression are matched to the arguments in a procedure call.
Returns #t if obj is exact integer. Otherwise #f.
These procedures implement number-theoretic (integer) division. It is an error if n2 is zero.
The procedure ending /
returns two integers; the other procedures
return an integer. All the procedures compute a quotient nq and
remainder nr such that _n1_ = _n2_*_nq_ + _nr_
.
for each of the division operators, there are three procedures defined as
follows;
(<operator>/ _n1_ _n2_)
nq nr
(<operator>-quotient _n1_ _n2_)
nq
(<operator>-remainder _n1_ _n2_)
nr
The remainder nr is determined by the choice of integer
_nq_:_nr_ = _n1_ - _n2_*_nq_
. Each set of
operations uses a different choice of nq:
floor
: _nq_ = [_n1_/_n2_]``truncate
: _nq_ = truncate(_n1_/_n2_)
Examples;
(floor/ 5 2)
2 1
(floor/ -5 2)
-3 1
(floor/ 5 -2)
-3 -1
(floor/ -5 -2)
2 -1
(truncate/ 5 2)
2 1
(truncate/ -5 2)
-2 -1
(truncate/ 5 -2)
-2 1
(truncate/ -5 -2)
2 -1
(truncate/ -5.0 -2)
2.0 -1.0
Returns the square of z.
Raises an &syntax
with syntax-violation
.
The macro is defined like this;
(define-syntax syntax-error
(syntax-rules ()
((_ msg args ...)
(syntax-violation 'syntax-error msg (quote args ...)))))
Returns #t if obj is condition object. This is a renaming
exported procedure of consition?
.
Returns irritants if the given err satisfies
irritants-condition?
. Otherwise #f.
Returns error message if the given err satisfies
message-condition?
. Otherwise #f.
Returns #t if obj is a file related condition, otherwise #f.
Renaming export of i/o-read-error?
.
Return #t if given input-port or output-port is open, respectively. Otherwise #f.
Renaming export of port-ready?
.
input-port must be a binary input port.
Peeks or reads a byte from given input-port.
input-port must be a binary input port.
Reads len from input-port and returns a bytevector.
_ _ _ (start 0) (end (bytevector-length bv))
input-port must be a binary input port.
Reads end - start size of data from input-port and put it into bv from start index.
u8 must be a byte. output-port must be a binary output port.
Writes u8 to output-port.
_ _ _ (start 0) (end (bytevector-length bv))
output-port must be a binary output port.
Writes bv from start to end (exclusive) to output-port.
input-port must be a textual input port.
Reads line from input-port. For convenience, \n
, \r
and \r\n
are considered end of line.
input-port must be a textual input port.
Reads k length of string from input-port.
_ _ _ (start 0) (end (string-length str))
output-port must be a binary output port.
Writes bv from start to end (exclusive) to output-port.
Returns binary or textual input port whose source is _bv_or string, respectively.
Returns binary or textual output port. The port is opened on memory.
Retrieves buffered bytevector or string from given output-ports, respectively.
Returns a list of the feature identifiers which cond-expand
treas as true.
The following procedures or macros are re-defined to strictly follow either R6RS or R7RS. It is users' responsibility to make sure proper ones are used in their script.
Returns #t if a and b are equivalent.
The difference between the one from (rnrs base)
is that this procedure
inspect record fields as well. For example:
(import (rnrs))
(define-record-type (<pare> kons pare?)
(fields (mutable a kar set-kar!)
(mutable d kdr set-kdr!)))
(let ((a (kons 'a 'b))
(b (kons 'a 'b)))
(equal? a b))
(import (scheme base))
(define-record-type (<pare> kons pare?)
(fields (mutable a kar set-kar!)
(mutable d kdr set-kdr!)))
(let ((a (kons 'a 'b))
(b (kons 'a 'b)))
(equal? a b))
#t
Binds macro transformer trans to var.
The difference between the one from (rnrs base)
and these macros is
that these macro create scope. Thus the following is unbound variable error:
(import (scheme base))
(let-syntax ()
(define foo 'foo))
foo
&undefined
[R7RS] This library exports the case-lambda
syntax.
Exported macro is the same as R6RS;
case-lambda
[R7RS]This library exports procedures for dealing with Unicode character operations.
These procedures are the same as R6RS;
char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>?
char-downcase char-foldcase char-lower-case? char-numeric? char-upcase
char-upper-case? char-whitespace? string-ci<=? string-ci<?
string-ci=? string-ci>=? string-ci>? string-downcase string-foldcase
string-upcase
[R7RS+] Converts given character to it's numeric value. If the given character does not have numeric value, then it returns #f.
This procedure is extended from R7RS definition.
(digit-value #\1)
1
(digit-value #\x0664)
4
(digit-value #\x0EA6)
#f
(digit-value #\xbc)
1/4
(digit-value #\xbf0)
10
[R7RS]This library exports procedures for complex numbers.
These procedures are the same as R6RS;
angle imag-part magnitude make-polar make-rectangular real-part
[R7RS]This library exports twenty-four procedures which are the compositions of from three to four car and cdr operations.
These procedures are the same as R6RS;
caaaar caaadr
caaar caadar
caaddr caadr
cadaar cadadr
cadar caddar
cadddr caddr
cdaaar cdaadr
cdaar cdadar
cdaddr cdadr
cddaar cddadr
cddar cdddar
cddddr cdddr
[R7RS]This library exports exports procedures for evaluating Scheme data as programs.
These procedures are the same as R6RS;
environment eval
[R7RS]This library exports procedures for accessing files.
These procedures are the same as R6RS;
call-with-input-file call-with-output-file
delete-file file-exists?
open-input-file open-output-file
with-input-from-file with-output-to-file
Returns file binary input or output port associated with given file, respectively.
[R7RS]This library exports procedures for inexact value.
These procedures are the same as R6RS;
acos asin atan cos exp finite? infinite? log nan? sin sqrt tan
[R7RS]This library exports procedures and syntax keywords for lazy evaluation.
These procedures/macros are the same as R6RS;
delay force make-promise promise?
The expression (delay-force _expression_)
is conceptually
similar to (delay (force _expression_))
, with the difference that
forcing the result of delay-force
will in effect result in a tail call
to (force _expression_)
, while forcing the result of
(delay (force _expression_))
might not.
[R7RS]This library exports procedures for loading Scheme expressions from files.
Reads expression in file and evaluates it until it gets to end of file. If environment is passed, then the evaluation is done in that environment. Otherwise it is done in current environment.
[R7RS] This library exports procedures for accessing with the program's calling context.
These procedures are the same as R6RS;
command-line exit
Exist process without any cleanup. The optional argument _obj_is given then it's translated to proper return value of the process.
name must be a string.
Retrieves environment variable associated to name.
Returns alist of environment variables.
[R7RS]This library exports procedures for reading Scheme objects.
Renaming export of read/ss
.
[R7RS]This library library exports the
interaction-environment
procedure.
Returns interaction environment.
[R7RS]This library provides access to time-related values.
Returns the number of jiffies as an exact integer.
Returns an exact integer representing the number of jiffies per SI second.
Returns an inexact number representing the current time on International Atomic Time (TAI) scale.
[R7RS]This library exports procedures for writing Scheme objects.
This procedures is the same as R6RS
display
Writes a representation of obj to output-port.
If the obj contains cyclic, the procedure writes with datum label.
Renaming export of write/ss
and write
, respectively.
[R7RS]The (scheme r5rs) library provides the identifiers defined
by R5RS, except that transcript-on
and transcript-off
are
not present. Note that the exact
and inexact
procedures
appear under their R5RS names inexact->exact
and
exact->inexact
respectively. However, if an implementation does
not provide a particular library such as the complex library, the
corresponding identifiers will not appear in this library either. This
library exports procedures for writing Scheme objects.
R7RS-large makes Scheme specification more practical. It contains lots of useful libraries as well. This section lists supporting R7RS-large libraries.
This library exports the procedures and macros defined in
SRFI-1 (srfi :1)
.
This library exports the procedures and macros defined in
SRFI-133 (srfi :133)
.
This library exports the procedures and macros defined in
SRFI-132 (srfi :132)
.
This library exports the procedures and macros defined in
SRFI-113 (srfi :113)
.
This library exports the procedures and macros defined in
SRFI-14 (srfi :14)
.
This library exports the procedures and macros defined in
SRFI-125 (srfi :125)
.
This library exports the procedures and macros defined in
SRFI-116 (srfi :116)
.
This library exports the procedures and macros defined in
SRFI-101 (srfi :101)
with the following exceptions:
make-list
is renamed to make-rlist
.
random-access-list->linear-access-list
is renamed to rlist->list
.
linear-access-list->random-access-list
is renamed to list->rlist
.
All other procedures are prefixed with r
. For example, pair?
exported from (srfi :101)
is rpair?
.
This library exports the procedures and macros defined in
SRFI-134 (srfi :134)
.
This library exports the procedures and macros defined in
SRFI-135 (srfi :135)
.
This library exports the procedures and macros defined in
SRFI-158 (srfi :158)
.
This library exports the procedures and macros defined in
SRFI-127 (srfi :127)
.
This library exports the procedures and macros defined in
SRFI-41 (srfi :41)
.
This library exports the procedures and macros defined in
SRFI-111 (srfi :111)
.
This library exports the procedures and macros defined in
SRFI-117 (srfi :117)
.
This library exports the procedures and macros defined in
SRFI-124 (srfi :124)
.
This library exports the procedures and macros defined in
SRFI-128 (srfi :128)
.
This library exports the procedures and macros defined in
SRFI-141 (srfi :141)
.
This library exports the procedures and macros defined in
SRFI-143 (srfi :143)
.
This library exports the procedures and macros defined in
SRFI-144 (srfi :144)
.
This library exports the procedures and macros defined in
SRFI-146 (srfi :146)
.
This library exports the procedures and macros defined in
SRFI-146 (srfi :146 hash)
.
This library exports the procedures and macros defined in
SRFI-151 (srfi :151)
.
This library exports the procedures and macros defined in
SRFI-159 (srfi :159)
.
This library exports the procedures and macros defined in
SRFI-160 (srfi :160 base)
.
This library exports the procedures and macros defined in
SRFI-160 (srfi :160 @)
. Where @
is one of
u8 s8 u16 s16 u32 s32 u64 s64 f32 f64 c64 c128
This library exports the procedures and macros defined in
R6RS bytevectors library (rnrs bytevectors)
.
NOTE: The exporting names may conflicts with the ones exported from R7RS
libraries (e.g. bytevector-copy!
from (scheme base)
).
Since Sagittarius version 0.3.0, we supports CLOS so that all Scheme objects
have its class. For example 1
is instance of <integer>
class.
However CLOS has huge features and I don't have intension to implement all of it.
This section does not describe CLOS itself.
User level CLOS API collection library.
Name must be symbol or identifier.
Supers must be list of class.
Slots must be following structure:
_slots_ ::= (_slot_ ...)
_slot_ ::= (_slot-name_ _specifiers_*)
_specifiers_ ::= `:init-keyword` _keyword_
| `:init-value` _value_
| `:init-form` _form_
| `:reader` _reader-function_
| `:writer` _writer-function_
Defines a new class.
Slot specifiers:
:init-keyword
This keyword specifies initialisation keyword argument used by the
make
procedure. Following code describes how to use:
(make <a-class> :slot-a 'slot-a-value)
<a-class>
has a slot which slot definition contains the keyword
:init-keyword
with the keyword :slot-a. The code initialises
an instance of the slot with given value slot-a-value.
:init-value
This keyword specifies an initial value of target slot.
:init-form
Similar with :init-keyword
but this keyword takes expression which
will be evaluated at initialiation time.
:reader
This keyword creates a procedure takes 1 argument an instance of the class
to access the slot, so users can read the slot without using slot-ref
procedure.
:writer
This keyword creates a procedure takes 2 argument an instance of the class
and object to set the slot value with given object, so users can set the
slot without using slot-set!
procedure.
opttions can specify the metaclass of this class with keyword
:metaclass
.
NOTE: Current implementation does not support :allocation
keyword
by default. If you need it, see
(sagittarius mop allocation).
Name must be symbol.
Creates a new generic function.
By specifying class keyword argument, users can customize the behaviour of the method specialization.
We provide <predicate-specializable-generic>
for memq
, memv
, member
and predicate
specializer.
Name must be symbol.
Specifiers must be following structure:
_specifiers_ ::= (_spec_ ... _rest_)
_spec_ ::= (_argument-name_ _class_)
| (_argument-name_)
| (_argument-name_ (_specializer_ value))
_rest_ ::= '() | symbol
_specializer_ ::= `eq` | `eql` | `equal` | `eq?` | `eqv?` | `equal?`
Adds defined method to name generic. If the generic does not exist, this will create a new generic function implicitly.
Returns the slot value specified slot-name.
Sets the slot value value with specified slot-name.
Returns #t if the slot value specified slot-name is bounded, otherwise #f.
Creates a new instance of class
Returns #t if object is an instance of class, otherwise #f.
Returns #t if class1 is a subclass of class2, otherwise #f.
This procedure is for MOP.
Returns the slot value got by accessor.
This procedure is for MOP.
Sets the slot value value to object using accessor.
This procedure is for MOP.
Returns the slot value according to the given class.
It is an error if the given slot-name doesn't exist in the class.
This procedure is for MOP.
Sets the slot value value to object accoring to the given class.
It is an error if the given slot-name doesn't exist in the class.
This procedure is for MOP.
Returns #t if the slot is bounded according to the given class, otherwise #f.
It is an error if the given slot-name doesn't exist in the class.
This method will be called when writing the given object.
Defines how user defined class should be written.
This method will be called when equal?
is called.
Defines how user defined class should be compared.
Low level CLOS API collection library.
Generic must be generic function. method must be method object.
Adds method to generic.
Returns a list of getter, setter and bound check for the given class's slot slot.
The returning list must have 3 elements, getter, setter and bound? respectively. Each element must be either #f or procedure. If #f is used then the default procedure will be used.
For the example code, see Sagittarius MOP.
Returns all getters and setters for the given class's slots.
The upper layer of compute-getter-and-setter
. This method should only
be used if users absolutely need to use accessor to access the target slots.
Returns slot name of given slot.
Returns slot options of given slot.
Returns slot option's value of given slot if it has the keyword.
If default is given, then it will be the fallback value when _keyword_is not found. Otherwise this procedure raises an error.
Sagittarius has its own extension libraries because even R6RS is huge however I know it is not sufficient to write practical program. To support to write it, Sagittarius provides some useful libraries.
This library has Sagittarius specific functionalities such as extra file system functions and so.
Similar to the define
however the define-constant
binds
variable as a constant value and the compiler try to fold it if it is
constant value i.e. literal string, literal vector, literal number and so.
If the defined variable is being overwritten, the VM shows a warning
message on the standard error. If overwriten is forbidden by
#!no-overwite
or other directives, then compiler raises an error.
[SRFI-8] formals and body are the same as lambda
.
Expression must be an expression.
receive
binds values which are generated by expressions to
formals.
The expressions in body are evaluated sequentially in the extended
environment. The results of the last expression in the body are the values of
the receive
-expression.
[R7RS][SRFI-0] Compile time condition. The cond-expand
resolves
platform dependencies such as C's #ifdef
preprocessor.
clauses must be one of these forms:
(feature-identifier body ...)
((version
(compare _version)) body ...)
((library
library-name) body ...)
((and
feature-identifier ...) body ...)
((or
feature-identifier ...) body ...)
(not
feature-identifier)
version
clause checks the Sagittarius version. The compare must be
one of >
, >=
, =
, <=
or <
. And version must be a string which
represents the target version.
This feature is since 0.9.12
and provides cond-expand.version
feature
identifier.
This is Sagittarius' extension. See the below example how to use it.
library
clause searches the given library-name and if it is found,
then compiles body.
and
, or
and not
are the same as usual syntax.
Users can check possible _feature-identifier_s via cond-features
procedure.
;; version clause example
(cond-expand
;; For backward compatible way among other Sagittarius versions
((and cond-expand.version (version (>= "0.9.12")))
;; Code for higher than or equal to the version 0.9.12
)
;; In case other Scheme implementations support the same thing
((and sagittarius cond-expand.version (version (>= "0.9.12")))
;; Sagittarius 0.9.12 or higher specific code
)
(else
;; Version lower than 0.9.12 code
))
Proc must be a procedure which accepts 3 arguments, form, rename and compare.
The input form of this macro. It is mere s-expression.
A procedure. It takes an object as its argument and
convert it to a syntax object. The procedure is similar with
datum->syntax
, it doesn't require template identifier.
A procedure. It takes 2 arguments and compares if they
are the same object in sense of free-identifier=?
. If the given
arguments are list or vector, then the procedure checks its elements.
The er-macro-transformer
returns explicit renaming macro transformer, so
you can write both hygine and non-hygine macro with it. For example:
(define-syntax loop
(er-macro-transformer
(lambda (form rename compare)
(let ((body (cdr form)))
`(,(rename 'call/cc)
(,(rename 'lambda) (break)
(,(rename 'let) ,(rename 'f) () ,@body (,(rename 'f)))))))))
(let ((n 3) (ls '()))
(loop
(if (= n 0) (break ls))
(set! ls (cons 'a ls))
(set! n (- n 1))))
(a a a)
This example has the same functionality as the example written in
datum->syntax
description. The basic of er-macro-transformer
is
the opposite way of the syntax-case
. The syntax-case
always makes
macro hygine, however the er-macro-transformer
can make macro hygine.
Moreover, if you do not use rename, it always makes it non-hygine.
The same as +
, *
, -
and /
. The difference is
these procedures converts given arguments inexact number.
x and m must be exact integer.
Returns _x_ ^ -1 mod _m_
x, e and m must be exact integer.
Returns _x_ ^ _e_ mod _m_
Returns file size of filename in bytes. If filename does not exist, it
raises &i/o
condition.
Returns file type or permission of given filename.
Returns file statistics time in nano sec.
The file-stat-ctime
procedure returns last change time of filename.
The file-stat-mtime
returns last modified time of filename.
The file-stat-atime
returns last accesse time of filename.
Changes given filename's access time and modify time.
atime specifies the access time of the filename.
mtime specifies the modify time of the filename.
If atime and/or mtime are time object, then the setting timestamp is the absolute time represented by the arguments.
If atime and/or mtime are real number, then the setting timestamp is the difference of the arguments from current time.
If atime and/or mtime are #f, then the timestamp is intact.
If atime and/or mtime are true value other then time or real number, then the timestamp is set to current time.
Changes given filename's file mode.
mode must be a fixnum encoded with POSIX file permission.
NOTE: On Windows, only the owner permission is considered.
Creates symbolic link of old-filename as new-filename.
Renames given old-filename to new-filename.
If old-filename does not exist, it raises &i/o
.
If new-filename exists, it overwrite the existing file.
Creates/deletes given directory. If it fails, it raises condition
&i/o
.
Reads directory and returns contents as a string list. If path does not exist, it returns #f.
src and dst must be string and src must indicate existing file path.
Copies given src file to dst and returns #t if it's copied otherwise #f.
If optional argument overwrite is #t then it will over write the file even if it exists.
Returns current working directory.
If optional argument path is given, the current-directory
sets
current working directory to path and returns unspecified value.
Sets current working directory to path.
path1 and path2 must be string.
Concatenate given parameter with platform dependent path separator.
Creates a hashtable.
The same as make-eq-hashtable
and
make-eqv-hashtable
. It uses equal?
or string=?
as
comparing procedure, respectively.
Returns all hashtable's values. This procedure is for consistancy of
hashtable-keys
.
Returns given hashtable's keys or values, respectively.
The R6RS required procedure hashtable-keys
and hashtable-values
are implemented with these procedures.
Returns hashtable's hash type as a symbol. The possible return
values are eq
, eqv
, equal
, string
and
general
.
Returns hashtable's hash weakness as a symbol if the given
hashtable is weak hashtable, otherwise #f. The possible return values are
key
, value
and both
.
Returns #t if given port is closed, otherwise #f.
out must be binary output port. endian must be a value
returned from endianness
macro.
Write v to out as unsigned/signed 16/32 bit integer.
in must be binary input port. endian must be a value
returned from endianness
macro.
Read a number from in as unsigned/signed 16/32.
NOTE: above put-*
and get-*
have only 16 and 32 bit integers.
This is because benchmark told us there's not much difference between C and
Scheme implementation. We may add 64 bit integers and floting number
versions in future if there's enough demand.
[SRFI-38] The read/ss
reads a datum from given port.
The write/ss
writes obj to given port.
These are the same as read
and write
procedure, but it can handle
circular list.
[SRFI-28+] Formats arg accoding to string. _Port_specifies the destination; if it is an output port, the formatted result is written to it; if it is #t, the result is written to current output port; if it is #f, the formatted result is returned as a string. Port can be omitted and the result is the same as when #f is given.
String is a string that contains format directives. A format directive is
a character sequence begins with tilda '~'
, and ends with some specific
characters. A format directive takes the corresponding arg and formats it. The
rest of string is copied to the output as is.
(format #f "the answer is ~a" 48)
the anser is 48
The format directive can take one or more parameters, separated by comma characters. A parameter may be an integer or a character; if it is a character, it should be preceded by a quote character. Parameter can be omitted, in such case the system default value is used. The interpretation of the parameters depends on the format directive.
Furthermore, a format directive can take two additional flags: atmark
'@'
and colon ':'
. One or both of them may modify the
behaviour of the format directive. Those flags must be placed immediately
before the directive character.
The following complete list of the supported directives. Either upper case or lower case character can be used for the format directive; usually they have no distinction, except noted.
Ascii output. The corresponding argument is printed by display
. If an
integer mincol is given, it specifies the minimum number of characters to
be output; if the formatted result is shorter than mincol, a whitespace is
padded to the right (i.e. the result is left justified).
The colinc, minpad and padchar parameters control, if given,
further padding. A character padchar replaces the padding character for the
whitespace. If an integer minpad is given and greater than 0, at least
minpad padding character is used, regardless of the resulting width. If an
integer colinc is given, the padding character is added (after minpad) in
chunk of colinc characters, until the entire width exceeds mincol.
If atmark-flag '@'
is given, the format result is right
justified, i.e. padding is added to the left.
The maxcol parameter, if given, limits the maximum number of characters to
be written. If the length of formatted string exceeds maxcol, only
maxcol characters are written. If colon-flag is given as well and the
length of formatted string exceeds maxcol, maxcol - 4 characters
are written and a string " ..."
is attached after it.
(format #f "|~a|" "oops")
|oops|
(format #f "|~10a|" "oops")
|oops |
(format #f "|~10@a|" "oops")
| oops|
(format #f "|~10,,,'*@a|" "oops")
|\*\*\*\*\*\*oops|
(format #f "|~,,,,10a|" '(abc def ghi jkl))
|abc def gh|
(format #f "|~,,,,10:a|" '(abc def ghi jkl))
|abc de ...|
S-expression output. The corresponding argument is printed by write
. The
semantics of parameters and flags are the same as ~A directive.
(format #f "|~s|" "oops")
|"oops"|
(format #f "|~10s|" "oops")
|"oops" |
(format #f "|~10@s|" "oops")
| "oops"|
(format #f "|~10,,,'*@s|" "oops")
|\*\*\*\*"oops"|
Decimal output. The argument is formatted as an decimal integer. If the argument is not an integer, all parameters are ignored and it is formatted by ~Adirective. If an integer parameter mincol is given, it specifies minimum width of the formatted result; if the result is shorter than it, padchar is padded on the left (i.e. the result is right justified). The default of padchar is a whitespace.
(format #f "|~d|" 12345)
|12345|
(format #f "|~10d|" 12345)
| 12345|
(format #f "|~10,'0d|" 12345)
|0000012345|
'+'
is printed for the positive
argument.
If colon-flag is given, every _interval_th digit of the result is grouped
and commachar is inserted between them. The default of commachar is
','
, and the default of interval is 3.
(format #f "|~:d|" 12345)
|12,345|
(format #f "|~,,'_,4:d|" -12345678)
|-1234_5678|
Binary output. The argument is formatted as a binary integer. The semantics of parameters and flags are the same as the ~D directive.
Octet output. The argument is formatted as a octal integer. The semantics of parameters and flags are the same as the ~D directive.
Hexadecimal output. The argument is formatted as a hexadecimal integer. If
'X'
is used, upper case alphabets are used for the digits larger than 10.
If 'x'
is used, lower case alphabets are used. The semantics of
parameters and flags are the same as the ~D directive.
(format #f "~8,'0x" 259847592)
0f7cf5a8
(format #f "~8,'0X" 259847592)
0F7CF5A8
Note: The format procedure's implementation and most of documentation is quoted from Gauche.
Returns #t when port data are ready, otherwise #f.
If the given port implementation does not support this functionality, the return value will be always #t. Following example describes when this always returns #t;
;; Assume read! is provided.
(define user-port (make-custom-binary-input-port "my-port" read! #f #f))
(port-ready user-port)
#t
port must be binary port.
Converts given port to buffered port if the port is not buffered port.
Buffered port is a type of port which does not read or write immediately
but uses internal buffer. For example, file port with
(buffer-mode block)
or (buffer-mode line)
uses the buffered
port. This is useful when actual I/O is more expensive than memory access.
The buffer-mode must be a symbol the macro buffer-mode
can
return. If the buffer-mode
is none
, then the procedure does not
convert the given port.
If the keyword argument buffer is specified, it must be
a bytevector, then the converted buffered port uses specified bytevector
as its internal buffer. If the bytevector size is zero or literal bytevector
then &assertion
is raised.
Creates a custom codec. Symbol is the name of the codec. _Getc_and putc must be procedures. Data is an user data used in _getc_and putc.
Getc must take 4 arguments, input-port, error-handling-mode,
check-bom? and userdata. Input-port is binary input port.
Error-handling-mode is symbol can be ignore
, raise
or
replace
depending on a transcoder which uses this custom codec.
Check-bom? is boolean, if getc is being called first time, it is #t,
otherwise #f. Userdata is user defined data which is given when the codec
is created.
The basic process of getc is reading binary data from input-port and converting the data to UCS4. Returning UCS4 must be integer and does not have to be 4 byte.
Putc must take 4 arguments, output-port, char,
error-handling-mode and userdata. Output-port is binary output
port. Char is character object which needs to be converted from UCS4.
Error-handling-mode is symbol can be ignore
, raise
or
replace
depending on a transcoder which uses this custom codec.
Userdata is user defined data which is given when the codec is created.
The basic process of putc is converting given UCS4 charactner to target encoding data and putting it to output-port as binary data.
For sample implementation, see sitelib/encoding directory. You can find some custom codecs.
Return #t if given symbol1 is less than, less than or equal to, greater than or greater than or equal to symbol2. If symbols are not null, then the procedures continue to compare until the given arguments are exhausted.
These procedures are analogy of string<?
, string<=?
,
string>?
and string>=?
.
These can also be implemented as follows:
(define (symbol<? . syms) (apply string<? (map symbol->string syms)))
However, this build-in version won't converts given symbols to strings.
Sagittarius has keyword objects which starts with ':'
. It has almost the
same feature as symbol, however it can not be bounded with any values. The
keyword objects are self quoting so users don't have to put '
explicitly.
The keyword notation is *NOT* available on R6RS or R7RS reader mode. Thus
#!r6rs
or #!r7rs
directive and -r6
or -r7
command line option disable it.
Creates a new keyword from symbol.
Creates a new keyword from string.
Returns #t if obj is keyword, otherwise #f.
Returns a symbol representation of given keyword keyword.
Returns a string representation of given keyword keyword.
Returns the element after given keyword from given list.
The elements count of the list should be even number, otherwise the
procedure might raise &error
when keyword is not found in
list.
If fallback is given and the procedure could not find the _keyword_from the list, the fallback will be return. Otherwise it raises
&error
.
(get-keyword :key '(a b c :key d))
d
(get-keyword :key '(a b c d e))
&error
(get-keyword :key '(a b c d e) 'fallback)
&error
(get-keyword :key '(a b c d e f) 'fallback)
fallback
A weak box is a reference to an object that doesn’t prevent the object from being garbage-collected.
Returns #t if obj is weak box otherwise #f.
Returns a weak box whose value is obj.
Returns #t if the value of given weak box wb is garbage collocted. Otherwise #f.
Returns the value of given weak box wb if it's not garbage collocted. Otherwise returns fallback.
Replace the value of given wb with obj.
A weak vector is like a vector of objects, except each object can be garbage collected if it is not referenced from objects other than weak vectors. If the object is collected, the entry of the weak vector is replaced to #f.
Returns #t if obj is weak vector otherwise #f.
Creates and returns a weak vector of size size.
Returns the length of given weak vector wvec
Returns k-th element of a weak vector wvec.
By default, weak-vector-ref
raise an &assertion
if k is
negative, or greater than or equal to the size of wvec. However, if an
optional argument fallback is given, it is returned for such case.
If the element has been garbage collected, this procedure returns _fallback_if it is given, #f otherwise.
Sets k-th element of the weak vector wvec to value. It
raises an &assertion
if k is negative or greater than or equal to
the size of wvec.
A weak hashtable contains references to an object that doesn't prevent the object from being garbage-collected the same as weak vector. A weak hashtable is like a hashtable, except each entry can be garbage collected if it is not referenced from objects other than weak hashtable according to the constructed condition.
Returns #t if obj is weak hashtable otherwise #f.
Make a weak hashtable with the hash procedure eq?
and eqv?
,
respectively.
The keyword argument init-size specifies the initial size of the weak hashtable.
The kwyword argument weakness specifies the place where the weak pointer
is. This must be one of the key
, value
and both
. If the
key
is specified, then weak hashtable's weak pointer will be the key
so is value
. If the both
is specified, then it will be both.
The keyword argument default specifies the default value when the entry is garbage collected. If this is not spceified, then undefined value will be used.
Returns the value in weak-hashtable associated with key. If weak-hashtable does not contain an association for key, default is returned.
Changes weak-hashtable to associate key with obj, adding a new association or replacing any existing association for key, and returns unspecified values.
Removes any association for key within weak-hashtable and returns unspecified values.
Returns a list of keys and values in the given weak-hashtable, respectively.
Returns a copy of weak-hashtable.
Shrink the given weak-hashtable and returns the number of removed entry. This is only for GC friendliness.
Converts given bytevector bytevector to exact integer. If optional argument start is given, conversion starts with index start. If optional argument end is given, convertion ends by index end. The conversion only happens in big endian.
The first form converts to signed integer and the rest convert to unsigned integer.
Ei must be exact integer. Converts exact integer ei to a bytevector.
The first form can accept signed integer and converts with two's complement form. The rest forms only accept unsigned integer and simply convert to bytes.
If optional argument size is given, then the procedure returns _size_size bytevector.
NOTE: The conversion is processed from right most byte so if the size is smaller than given ei bytes, then the rest of left bytes will be dropped.
NOTE: the endianness is always big endianness.
(integer->bytevector #x12345678 5)
#vu8(#x00 #x12 #x34 #x56 #x78)
(integer->bytevector #x12345678 3)
#vu8(#x34 #x56 #x78)
Returns a newly allocated bytevector that contains all elements in order from the subsequent locations in bvs ....
Appends each bytevectors in list-of-bytevectors. This is equivalent to:
(apply bytevector-append _list-of-bytevectors_)
[SRFI-1] Returns #t if list is circular or dotted list, respectively. Otherwise #f.
Returns (cons (cons _obj1_ _obj2_) _obj3_)
. Useful to
put an entry at the head of an associative list.
[SRFI-1] Returns a list consisting of the elements of the first _list_followed by the elements of the other lists. The cells in the lists except the last one may be reused to construct the result. The last argument may be any object.
[SRFI-1] Returns a list consisting of the elements of list in reverse order. The cells of list may be reused to construct the returned list.
[SRFI-43] Copies a vector vector. Optional start and _end_arguments can be used to limit the range of vector to be copied. If the range specified by start and end falls outside of the original vector, the fill value is used to fill the result vector.
(vector-copy '#(0 1 2 3 4) 1 4)
#(1 2 3)
(vector-copy '#(0 1 2 3 4) 4 6 #f)
#(4 #f)
(vector-copy '#() 0 2 #t)
#(#t #t)
[SRFI-43] Returns a newly allocated vector that contains all elements in order from the subsequent locations in vector ....
(vector-append '#(1 2) '#(a b) '#(5))
#(1 2 a b 5)
[SRFI-43] Appends each vectors in list-of-vectors. This is equivalent to:
(apply vector-append _list-of-vectors_)
[SRFI-43] Reverse the given vector's elements.
The second form reverses the given vector destructively.
Optional arguments start and end must be non negative integer if it's given. And it restricts the range of the target elements.
Scan item (either a string or a character) in string.
The return argument specified what value should be returned when item is found in string. It must be one of the following symbols;
index
Returns the index in string if item is found, or #f
.
This is the default behaviour.
before
Returns a substring of string before item, or #f
if
item is not found.
after
Returns a substring of string after item, or #f
if
item is not found.
before*
Returns a substring of string before item, and the substring
after it. If item is not found then return (values #f #f)
.
after*
Returns a substring of string up to the end of item, and the
rest. after it. If item is not found then return
(values #f #f)
.
both
Returns a substring of string before item and after
item. If item is not found, return (values #f #f)
.
[SRFI-13] Appends each strings in list-of-strings. This is equivalent to:
(apply string-append _list-of-strings_)
Returns #t if the given obj is an immutable string, otherwise #f.
Immutable strings are one of the followings:
String literals. (i.e. "abc"
)
Strings converted to immutable string by string->istring
Returns copy of the given string. The returning string is converted to immutable string.
The optional argument start and end are given, then the returing string is contains only the range of given string.
Add given path to current loading path list.
If keyword argument append is #t
, then given path is
appended to the current loading path list, otherwise prepend to the list.
Add given suffix to current suffix list.
If keyword argument append is #t
, then given suffix is
appended to the current suffix list, otherwise prepend to the list.
The suffix should contain .
as well.
Retrives/sets current loading path.
If the latter form is used, then the given path list paths is set to current loading path list. Otherwise retrieves the list.
The returning value is not copied, thus modifying the list may cause unexpected results.
Return a vector which contains the following information.
Operating system name. E.g. "Linux"
The name of the computer.
Release number of the system if availabel.
Version number of the system if availabel.
Machine architecture of the system.
On POSIX environment, this is the result of uname(2)
.
On Windows environment, this is the result of couple of Win32 API calls
and formatted to look like the result of uname(2)
.
Retrieves MAC address. The returning value is a bytevector which contains 6 elements.
If optional argument specifies which NIC's MAC address should be returned.
Returns a vector having 3 elements; user time, _system time_and tick.
The first procedure returns process CPU time, the second procedure returns thread CPU time. If the optional argument thread is given, then the procedure retrieves CPU time of given thread. Otherwise current thread.
tick is a clock tick. Users can compute CPU second Dividing user time or system time by this value.
NOTE: tick may not be the same even on the same platform. For example,
get-process-times
returns value of _SC_CLK_TCK
, and
get-thread-times
returns 1000000 (on OSX), 1000000000 (on other POSIX
environments which have pthread_getcpuclockid
), or _SC_CLK_TCK
(on other POSIX environments which don't have pthread_getcpuclockid
). So
users must not assume the value is one of them and calculate CPU second with
assumed value.
Invokes garbage collection manually.
Returns number of CPUs. The result contains hyperthreading, for example, if the CPU is Core i5 which have 2 cores and hyperthreading is enabled, then the returning value is 4.
On Linux environment, the procedure also considers taskset(1)
.
This procedure returns static value initialised during initialisation of
Sagittarius process. Thus, if the process is restricted after its
initialisation by taskset(1)
, for example the environment has 4 CPUs
but restricted to 1, then this process, however, returns 4.
Disassembles the compiled body of closure and print it.
Returns arity of given procedure.
It returns a pair whose car part is required arguments count and cdr part is boolean which indicates if the procedure accepts optional arguments or not.
Exports time
macro
Evaluate expr and shows time usage.
The macro return the result of expr.
This library provides some useful macros using Sagittarius specific functions.
Defines name to be a macro whose transformer is procedure. The second form is a shorthand notation of the following form:
(define-macro _name_ (lambda _formals_ _body_ ...))
Given a list of values restargs, binds variables according to var-spec, then evaluates body.
Var-spec can be either a symbol, or a list of two elements and its car is a symbol. The symbol is the bound variable name. The values in _restargs_are bound to the symbol in order. If there are not as many values in restargs as var-spec, the rest of symbols are bound to the default values, determined as follows:
If var-spec is just a symbol, the default value is undefined.
If var-spec is a list, the default value is the result of evaluation of the second element of the list.
In the latter case the second element is only evaluated when there are not enough arguments. The binding proceeds in the order of var-spec, so the second element may refer to the bindings of previous var-spec.
In the second form, restvar must be a symbol and bound to the list of values whatever left from restargs after binding to var-spec.
It is not an error if restarg has more values than var-specs. The extra values are simply ignored in the first form.
This is a short version of let-optionals*
where you have only one
optional argument. Given the optional argument list restargs, this macro
returns the value of optional argument if one is given, or the result of
default otherwise.
If latter form is used, test must be procedure which takes one argument
and it will be called to test the given argument. If the test failed, it raises
&error
condition.
Default is not evaluated unless restargs is an empty list.
This macro is for keyword arguments. Var-spec can be one of the following forms:
(_symbol_ _expr_)
If the restrag contains keyword which has the same name as symbol, binds symbol to the corresponding value. If such a keyword doesn't appear in restarg, binds symbol to the result of expr.
(_symbol_ _keyword_ _expr_)
If the restarg contains keyword keyword, binds symbol to the corresponding value. If such a keyword doesn't appear in restarg, binds symbol to the result of expr.
The default value expr is only evaluated when the keyword is not given to the restarg.
If you use the first form, let-keyword
raises &error
condition
when restarg contains a keyword argument that is not listed in
var-specs. When you want to allow keyword arguments other than listed in
var-specs, use the second form.
In the second form, restvar must be either a symbol or #f. If it is a symbol, it is bound to a list of keyword arguments that are not processed by var-specs. If it is #f, such keyword arguments are just ignored.
(define (proc x . options)
(let-keywords options ((a 'a)
(b :beta 'b)
(c 'c)
. rest)
(list x a b c rest)))
(proc 0)
(0 a b c ())
(proc 0 :a 1)
(0 1 b c ())
(proc 0 :beta 1)
(0 a 1 c ())
(proc 0 :beta 1 :c 3 :unknown 4)
(0 a 1 3 (unknown 4))
Like let-keywords
, but the binding is done in the order of
var-specs. So each expr can refer to the variables bound by
preceding var-specs.
These let-keywords and let-keywords* are originally from Gauche.
The define-with-key
is synonym of define
.
See more detail Variable definitions.
Evaluate exp0, exp1, ..., then returns the result(s) of exp0.
A convenient macro when you have only one variable. Expanded as follows:
(let ((_var_ _expr_)) _body_ ...)
A convenient macro when you have only one variable and is the returning value. Expanded as follows:
(let ((_var_ _expr_)) _body_ ... _var_)
Imported from Common List. These are equivalent to the following forms, respectively.
(dotimes (variable limit result) body ...)
=>
(do ((tlimit limit)
(variable 0 (+ variable 1)))
((>= variable tlimit) result)
body ...)
(dolist (variable lexpr result) body ...)
=>
(begin
(for-each (lambda (variable) body ...) lexpr)
(let ((variable '())) result))
Conses item and the value of place. The place must be
either a variable or a form (proc arg ...), as the second argument of
set!
. The result will be the same as set!
.
Retrieves the value of place, sets its cde back to place.
Check the given val satisfies pred. If the pred returns
#f then &assertion
is raised.
The proc should be the procedure name which uses this macro and is for debugging purpose.
library must be a library name. ex. (srfi :1 lists)
exprs must be expressions.
Evaluate given expressions one by one in the specified library and returns the last result of the expressions.
This should not be used casually however you want to use some procedures or variables which are not exported, such as a procedure written in C but not exported or non exported record accessor. For thoese purpose, this might be a quick solution.
Execute body then execute cleanups and returns the result(s) of body.
It is not guaranteed to invoke the cleanups only once if a continuation is captured in body and call it.
Short form of syntax->datum
.
The macro is similar with with-syntax
, the only difference is
that this macro can refer previous pattern of p as if let*
can.
This can reduce nest level when users need to write multiple
with-syntax
to refer bound syntax object.
The alias of lambda
.
Shortened notation of (lambda (c) body ...)
. Where c
can be any character of lower case of ASCII alphabet.
(map (^z (* z z)) '(1 2 3 4 5))
(1 4 9 16 25)
Shortened notation of (lambda c body ...)
. Where c
can be any character of lower case of ASCII alphabet.
(map (^z* z*) '(1 2 3 4 5))
((1) (2) (3) (4) (5))
This library provides FFI (Foreign Function Interface) procedures. The library is constructed on libffi.
This library makes user to be able to re-use existing useful C library. However it might cause SEGV or unexpected behaviours. It is users responsibility to avoid those errors.
Following is the simple example to use;
/* C file, must be compiled as a shared library and named 'my-quick-sort.so' */
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
# define EXPORT __declspec(dllexport)
#else
# define EXPORT
#endif
static void quicksort_(uintptr_t base,const size_t num,const size_t size,
void *temp,int (*compare)(const void *,const void *))
{
size_t pivot = 0,first2last = 0,last2first = num-1;
while(pivot+1 != num && !compare(base+size*pivot,base+size*(pivot+1))){
pivot++;
}
if(pivot+1 == num){
return;
}
if(0 > compare(base+size*pivot,base+size*(pivot+1))){
pivot++;
}
while(first2last < last2first){
while(0 < compare(base+size*pivot,base+size*first2last)
&& first2last != num-1){
first2last++;
}
while(0 >= compare(base+size*pivot,base+size*last2first)
&& last2first){
last2first--;
}
if(first2last < last2first){
if(pivot == first2last || pivot == last2first){
pivot = pivot^last2first^first2last;
}
memcpy(temp,base+size*first2last,size);
memcpy(base+size*first2last,base+size*last2first,size);
memcpy(base+size*last2first,temp,size);
}
}
quicksort_(base,first2last,size,temp,compare);
quicksort_(base+size*first2last,num-first2last,size,temp,compare);
}
EXPORT int quicksort(void *base, const size_t num, const size_t size,
int (*compare)(const void *, const void *))
{
void *temp = malloc(size);
if(!temp){
return -1;
}
quicksort_((uintptr_t)base,num,size,temp,compare);
free(temp);
return 0;
}
;; Scheme file
;; load shared library (on Windows the extension might be '.dll')
;; On Unix like environment, the shared library must be full path or
;; located in the same directory as the script.
;; On Windows it can be on PATH environment variable as well.
(define so-library (open-shared-library "my-quick-sort.so"))
(define quick-sort
(c-function so-library ;; shared library
void ;; return type
quicksort ;; exported symbol
;; argument types
;; if you need pass a callback procedure, 'callback' mark needs to
;; be passed to the arguments list
(void* size_t size_t callback)))
(let ((array (u8-list->bytevector '(9 3 7 5 2 6 1 4 8)))
;; callback procedure
(compare (c-callback int ;; return type
(void* void*) ;; argument types
(lambda (a b)
(- (pointer-ref-c-uint8 x 0)
(pointer-ref-c-uint8 y 0))))))
;; call c function. all loaded c functions are treated the same as
;; usual procedures.
(quick-sort array (bytevector-length array) 1 compare)
;; release callback procedure.
;; NOTE: callback won't be GCed so users need to release it manually
(free-c-callback compare)
array)
;; Close shared library.
(close-shared-library so-library)
#vu8(1 2 3 4 5 6 7 8 9)
The document describes higher APIs to lower APIs.
file must be a string.
Opens given file shared library and returns its pointer.
The internal process of open-shared-library
is depending on the
platform, for example if your platform is POSIX envirionment then it will use
dlopen
. So the resolving the file depends on it. If you know the
absolute path of the shared library, then it's always better to use it.
If then internal process of the procedure failed and raise is #f then it returns NULL pointer, if raise is #t then it raises an error.
Closes given shared library pointer and returns unspecified value.
If the given pointer does not indicate proper shared library, the behaviour is platform dependent. It might cause SEGV.
Returns platform specific shared library extension as a string value.
eg. ".dll"
in Windows, ".so"
in Linux or Unix.
This section describes more details to create a corresponding C functions.
Creates a c-function object and returns a Scheme procedure.
shared-library must be opened shared-library.
return-type must be one of the followings;
void
bool char
short int long long-long
unsigned-short unsigned-int unsigned-long unsigned-long-long
intptr_t uintptr_t
float double
void* char* wchar_t*
int8_t int16_t int32_t int64_t
uint8_t uint16_t uint32_t uint64_t
The return value will be converted corresponding Scheme value. Following describes the conversion;
bool
Scheme boolean
char*
Scheme string from UTF-8
wchar_t*
Scheme string from UTF-16 (Windows) or UTF-32.
char
short int long long-long
unsigned-short unsigned-int unsigned-long unsigned-long-long
intptr_t uintptr_t
int8_t int16_t int32_t int64_t
uint8_t uint16_t uint32_t uint64_t
Scheme integer
float double
Scheme flonum
void*
Scheme FFI pointer type
NOTE: char
returns a Scheme integer not Scheme character.
name must be a symbol indicating a exported C function name.
argument-types must be zero or more followings;
bool
char short int long long-long
unsigned-short unsigned-int unsigned-long unsigned-long-long
size_t
void* char* wchar_t*
float double
int8_t int16_t int32_t int64_t
uint8_t uint16_t uint32_t uint64_t
callback
___
When the C function is called, given Scheme arguments will be converted to corresponding C types. Following describes the conversion;
bool
Scheme boolean to C 0 (#f) or 1 (#t).
char short int long long-long unsigned-short
int8_t int16_t int32_t uint8_t uint16_t
Scheme integer to C signed long int
unsigned-int unsigned-long uint32_t size_t
Scheme integer to C unsigned long int
int64_t long-long
Scheme integer to C int64_t
uint64_t unsigned-long-long
Scheme integer to C uint64_t
float
Scheme flonum to C float
double
Scheme flonum to C double
void* char*
void*
and char*
are actually treated the same, internally.
The conversion will be like this;
Converts to UTF-8 C char*
Convert to C char*
Convert to C void*
wchar_t*
Wide character string conversion only happens when the given argument was Scheme string and depends on the platform. On Windows, more specifically size of wchar_t is 2 platform, it converts to UTF-16 string without BOM. On other platform, size of wchar_t is 4 platform, it converts to UTF-32. Both case detects endianness automatically. If the given argument was bytevector, it won't convert. This case is useful when users need to pass buffer to a C-function.
callback
Scheme FFI callback to C void*
Note: passing Scheme string needs to be careful when users want to use it as a buffer. It doesn't work like it. Use bytevector or FFI pointer object for that purpose.
___
is for variable length argument and it must be the last position
of the argument type list, otherwise it raises an error.
Creates C function. This procedure is underlying procedure for
c-function
macro. The arguments are the same as c-function
,
only argument-types must be a list of types.
Convenient macro for address passing.
When you need to pass an address of a pointer to C function, you can write like this;
(c-func (address _pointer_))
This is equivalent of following C code;
c_func(&pointer)
pointer can be a pointer object or a bytevector.
If the second form is used, then the passing address is offset of offset. It is user's responsibility to make sure the given pointer has enough space when offset is passed. If the pointer is a bytevector and offset is more than the bytevector size, then an error is signaled.
Creates a C callback.
return-type must be a symbol and the same as c-function
's
return-type.
argument-types must be zero or following;
bool
char short int long long-long intptr_t
unsigned-char unsigned-short unsigned-int unsigned-long-long uintptr_t
int8_t int16_t int32_t int64_t
uint8_t uint16_t uint32_t int64_t
float double
size_t
void*
The conversion of C to Scheme is the same as c-function
's
return-type.
NOTE: if the content of void*
won't be copied, thus if you modify it in
the callback procedure, corresponding C function will get affected.
NOTE: callback doesn't support char*
nor wchar_t*
. It is because
the conversion loses original pointer address and you might not want it. So
it is users responsibility to handle it.
proc must be a procedure takes the same number of arguments as argument-types list.
Created callbacks are stored intarnal static storage to avoid to get GCed.
This is because C functions which accept callback may hold the given callback
in their storage which could be outside of Sagittarius GC root. So it is
users' responsibility to release created callback to avoid memory leak. To
release callbacks, you need to use free-c-callback
.
Creates C callback. This procedure is underlying procedure for
c-callback
macro. The arguments are the same as c-callback
,
only argument-types must be a list of types.
Release callback.
Using C functions, users can not avoid to use raw pointers. This section describes how to create or convert a pointer.
Returns #t if obj is FFI pointer object, otherwise #f.
Converts given integer to pointer object.
To represents NULL pointer, you can write like this;
(integer->pointer 0)
#\<pointer 0x0>
Converts given pointer to integer/uinteger, respectively.
The optional argument bits must be an exact integer range of fixnum.
If the optional argument bits is specified, then the procedure mask the pointer value. If the bits is negative or more than pointer size bits then it returns non masked value.
This is useful when C procedure sets the pointer value however it only sets a half of bits and returning value is needed only a half of bits. For example, a C procedure takes 2 arguments, one is buffer pointer the other one is buffer size pointer. When buffer size is -1 then it allocates sufficient buffer and sets buffer size pointer the allocated size. In this case. In this case, if you are using 64 bit environment and buffer size pointer is 32 bit value's pointer returning value's upper 32 bit would be 0xFFFFFFFF. If the optional argument is specified to 32 then the procedure only returns lower 32 bit value.
Converts given pointer to Scheme string.
The given pointer must be terminated by 0 otherwise it won't stop until it reaches 0.
If NULL pointer is given, it raises &assertion
.
Size must be an exact integer.
Converts given pointer to Scheme bytevector from given offset.
If optional argument shared is #f, then the content of pointer won't be shared between pointer and bytevector. Default value is #t, thus if the given pointer is modified, then the created bytevector gets affected.
If NULL pointer is given, it raises &assertion
.
Converts given bytevector to pointer from given offset.
If optional argument shared is #f, then the content of bytevector won't be shared between bytevector and pointer. Default value is #t, thus if the given bv is modified, then the created pointer gets affected.
If NULL pointer is given, it raises &assertion
.
CAUTION: These operations are really dangerous especially
pointer->object
.
Converts Scheme object to pointer and pointer to Scheme object respectively. The operations are useful to pass Scheme object to callbacks and restore it.
offset must be a fixnum.
Returns a pointer offset offset of given pointer. The same as following C code;
void* deref(void **pointer, int offset) {
return pointer[offset];
}
If NULL pointer is given, it raises &assertion
.
Returns an address of given pointer.
If optional argument offset is given, then the returning address of pointer is the offset of given offset.
NOTE: This creates a newly allocated Scheme FFI pointer object.
NOTE: If the returned value is modified then given pointer will be affected.
size must be a fixnum.
Allocates a size of byte memory and returns an pointer object.
If optional argument fill is given, it must be a fixnum, then the
procedure fill the given fill into the allocated memory using
memset(3)
.
NOTE: the fill will be converted to an unsigned char by the
memset(3)
.
The allocated memory will be GCed.
size must be a fixnum.
Allocates a size of byte memory and returns an pointer object using
C's malloc
.
The allocated memory won't be GCed. So releasing the memory is users' responsibility.
pointer must be a pointer created by c-malloc.
Release the pointer.
The procedure won't check if the pointer is allocated by c-malloc or not. And the behaviour when GCable pointer is passed is undefined.
A pointer represents NULL.
This value is not a constant and if you modify this by using address
,
you might break some codes.
Returns #t when obj is a pointer representing NULL otherwise #f.
Creates a NULL pointer. This is for convenience.
offset must be a fixnum.
Returns an integer value of offset offset of pointer depending on the type.
Following type are supported;
int8 int16 int32 int64 uint8 uint16 uint32 uint64 char wchar short int long long-long unsigned-char unsigned-short unsigned-int unsigned-long unsigned-long-long intptr uintptr float double pointer
NOTE: if the type is flonum
or double
, then it returns
Scheme flonum
NOTE: if the type is pointer
, then it returns Scheme FFI pointer.
offset must be a fixnum.
Sets value to offset offset of pointer. Supporting _type_s
are the same as pointer-ref-c-_type_
The type conversion is the same as c-function
's return-type.
There is no direct procedures to handle C arrays. Following is an example of how to handle array of pointers;
(import (rnrs) (sagittarius ffi))
(define (string-vector->c-array sv)
(let ((c-array (allocate-pointer (* (vector-length sv) size-of-void*))))
(do ((i 0 (+ i 1)))
((= i (vector-length sv)) c-array)
;; pointer-set-c-pointer! handles Scheme string (converts to UTF-8)
;; If you need other encoding, then you need to write other conversion
;; procedure.
(pointer-set-c-pointer! c-array (* i size-of-void*) (vector-ref sv i)))))
;; how to use
(let ((p (string-vector->c-array #("abc" "def" "ghijklmn"))))
(do ((i 0 (+ i 1)))
((= i 3))
;; deref handles pointer offset.
;; it can be also (pointer-ref-c-pointer p (* i size-of-void*))
(print (pointer->string (deref p i)))))
Following is an example for Scheme string to UTF-16 bytevector;
(import (rnrs) (sagittarius ffi))
;; Converts to UTF16 big endian (on little endian environment)
(define (string->c-string s)
(let* ((bv (string->utf16 s (endianness big)))
;; add extra 2 bytes for null terminated string
(p (allocate-pointer (+ (bytevector-length bv) 2))))
(do ((i 0 (+ i 2)))
((= i (bytevector-length bv)) p)
;; pointer-set-c-uint16! uses native endianness to set the value
;; so this is platform dependent code.
(pointer-set-c-uint16! p i
(bytevector-u16-ref bv i (endianness little))))))
value must be exact integer up to size-of-void*
bytes.
Sets the pointer value. This is useful to reuse the existing pointer object.
CAUTION: this operation is really dangerous so be aware of it!
C's struct is mere memory chunk so it is possible to access its member directly, if you know exact offset of it. However it is convenient if you can operate similar structure. This section describes how to define C structure in Scheme world.
Defines C structure.
clauses must be following form;
(_type_ _name_)
(_type_ `array` _size_ _name_)
(`struct` _struct-name_ _name_)
(`bit-field` _type_ (_name_ _bit_) ...)
(`bit-field` (_type_ _endian_) (_name_ _bit_) ...)
name must be a symbol.
If the second form is used, then alignment
is an auxiliary syntax
and n must be an integer which must be either negative number or
one of 1
, 2
, 4
, 8
, or 16
. This form
specifies the alignemtn of the struct. If the n is negative number,
then it uses platform default alignment, if it's one of the above number,
then the alignment is according to the given number.
The first form is the simple C type form. type must be a symbol and the
same as one of the c-function
's return-types or callback
.
Following describes the concrete example and the equivalent C structure:
(define-c-struct st
(int foo)
(callback fn))
#|
struct st
{
int foo;
void* fn; /* function pointer */
};
|#
The second form is defining C type array with size. Following describes the concrete example and the equivalent C structure:
(define-c-struct st
(int array 10 foo))
#|
struct st
{
int foo[10];
};
|#
The third form is defining internal structure. Following describes the concrete example and the equivalent C structure:
(define-c-struct st1
(int array 10 foo))
(define-c-struct st2
(struct st1 st)
(int bar))
#|
struct st1
{
int foo[10];
};
struct st2
{
struct st1 st;
int bar;
};
|#
So far, we don't support direct internal structure so users always need to extract internal structures.
The forth and fifth forms are bit fields. type must be an integer
type such as unsigned-int
. If the given type is not an integer,
then &assertion
is raised.
Following describes the concrete example and the equivalent C structure:
(define-c-struct st1
(bit-field unsigned-int (a 10) (b 20)))
#|
struct st1
{
unsigned int a : 10;
unsigned int b : 20;
};
|#
If the fifth form is used, then endian must be an identifier which has
valid name for endianness
macro. Then the created structure packs
the value according to the given endian.
If the total amount of bits is greater than given type, then
&assertion
is raised.
NOTE: Even though, this can accept signed integer the returning value would not be signed. It is safe to specify unsigned type.
The macro also defines accessors for the c-struct. Following naming rules are applied;
For getter: name-member-name-ref
For setter: name-member-name-set!
The macro also defines size variable for the c-struct. If the name of the
c-struct if foo, then the variable name will be size-of-foo
.
struct must be a C structure defined by define-c-struct
.
Returns the size of given struct.
Allocates memory for struct and returns a pointer.
A getter/setter of struct-name c-struct.
This is automatically defined by define-c-struct
macro.
The optional argument inner-member-names can be passed to get inner struct values.
Following describes how it works.
(define-c-struct in
(int i)
(char c))
(define-c-struct out
(int i)
(struct in in0))
(define out (allocate-c-struct out))
(out-i-set! out 100 'i) ;; -> unspecified
(out-in0-set! out 200 'i) ;; -> unspecified
(out-i-ref out) ;; -> 100
(out-in0-ref out 'i) ;; -> 200
(out-in0-ref out) ;; -> pointer object (indicating the inner struct address)
struct must be a C structure defined with define-c-struct
.
name must be a symbol and struct has the same member.
pointer should be a pointer allocated by allocate-c-struct
with
struct.
Returns a member name's value of struct from pointer.
struct must be a C structure defined with define-c-struct
.
name must be a symbol and struct has the same member.
pointer should be a pointer allocated by allocate-c-struct
with
struct.
Sets value to pointer offset of member name of struct.
Convenient macro.
Defines other name of original with new-names.
new-names must be following forms;
()
((`*` _new-p_) _rest_ ...)
((`s*` _new-sp_) _rest_ ...)
(_new_ _rest_ ...)
The first for defines nothing.
If the rest of form is used and rest is not null, then it will recursively define.
The second form's *
defines new-p as void*
.
The third form's s*
defines new-sp as char*
.
The forth form defines new as original.
Following example describes how to will be expanded approximately.
(define-c-typedef char (* char_ptr) byte (s* string))
=>
(begin
(define char_ptr void*)
(define byte char)
(define string char*)
)
a size or align of type, respectively.
Following types are supported;
bool char
short int long long-long
unsigned-short unsigned-int unsigned-long unsigned-long-long
intptr_t uintptr_t size_t
float double
int8_t int16_t int32_t int64_t
uint8_t uint16_t uint32_t uint64_t
void*
The values are platform dependent.
Some of C resource must be released but if you can not decide or do not want to restrict when, then you can release it at GC time.
NOTE: GC might not happen if your script is very short, so it is better not to relay these procedures too much.
pointer must be a pointer allocated with GCable memory.
proc must be a procedure and accepts one argument. The argument will be the pointer.
Register proc as pointer's finalizer and returns pointer.
pointer must be a pointer allocated with GCable memory.
Remove finalizer form pointer and returns pointer.
Monitoring filesystem cannot be done efficiently without support of underlying operating system. This library provides unified interface of the mechanism.
The following simple tail (1)
like script shows how it works:
(import (rnrs) (getopt) (sagittarius filewatch) (prefix (binary io) binary:))
(define (tail file offset)
(define watcher (make-filesystem-watcher))
(define in (open-file-input-port file))
;; dump contents to stdout
(define (dump)
(let loop ()
(let ((line (binary:get-line in)))
(unless (eof-object? line)
(put-bytevector (standard-output-port) line)
(put-bytevector (standard-output-port) #vu8(10))
(loop)))))
(define size (file-size-in-bytes file))
;; move port position if the size if more than offset
(when (> size offset) (set-port-position! in (- size offset)))
;; dump first
(dump)
;; add path to file watcher
(filesystem-watcher-add-path! watcher file '(modify)
(lambda (path event) (dump)))
;; monitor on foreground.
(filesystem-watcher-start-monitoring! watcher :background #f))
;; this tail is not line oriented
;; it shows tail of the file from the given offset.
(define (main args)
(with-args (cdr args)
((offset (#\o "offset") #t "1024")
. rest)
(tail (car rest) (string->number offset))))
Creates and returns filesystem watcher object.
The keyword argument error-handler is specified, which must be a procedure accepts one argument, then it is called with a condition when monitoring handler raised an error.
Releasing the watcher.
Released filesystem watcher can not be reused.
Returns #t if the given o is a filesystem watcher object, otherwise #f.
Adds monitoring targets to the watcher.
The path must be a string and indicating existing path.
The flags must be one of the following symbols or list of the symbols:
access
Checks if the path is accessed.
modify
Checks if the path is modified.
delete
Checks if the path is deleted.
move
Checks if the path is moved.
attribute
Checks if the path's attribute is changed.
NOTE: The flags might not be supported depending on the platform. See implementation limitation section for more details.
The monitoring-handler must be a procedure accepts 2 arguments. The procedure is called if the path gets an event specified flags. When the monitoring-handler is invoked, then the path and a symbol of the invoking event are passed respectively. The possible event symbols are the followings:
accessed
Checks if the path is accessed.
modified
Checks if the path is modified.
deleted
Checks if the path is deleted.
moved
Checks if the path is moved.
attribute
Checks if the path's attribute is changed.
The procedure filesystem-watcher-add-path! returns the watcher.
If the watcher started monitoring, then the procedure raises
&assertion
.
Removes given path from the watcher. And returns watcher,
If the watcher started monitoring, then the procedure raises
&assertion
.
Starts monitoring filesystem on given watcher.
If the keyword argument background is true value, then the procedure
creates a thread and let the thread monitor the filesystem. (So the procedure
returns after the thread invocation.) Otherwise, the procedure blocks and
wait until other thread calls filesystem-watcher-stop-monitoring!
.
Stops monitoring of given watcher.
If the watcher is started on background, then the monitoring thread may not stop immediately.
Even the library provides unified APIs however users still should know the limitations per operating system to avoid unexpected behaviours. The following sections describes the known limitations.
On Linux, the library is constructed on top of inotify (7)
and
poll (2)
. If users add too many paths, then it may reach the
maximum number of watch descriptor.
The IN_MOVED_FROM
and IN_MOVED_TO
flags are passed as
moved
. So it is users responsibility to detect which file is
moved from and which file is moved to.
On BSD Unix, the library is constructed on top of kqueue (2)
. This
implementation contains 3 major issues. Possibility of number of file
descriptor explosion, not access
flag support, and no support of
directory monitoring.
The kqueue
requires file descriptor per monitoring path. Thus if
the number of paths is large, then it reaches the maxinum number of file
descriptors. (NB: kern.maxfiles
on FreeBSD).
kqueue
doesn't support path access monitoring (e.g. IN_ACCESS
on inotify
). So it is impossible to monitor file access.
Current implementation of (sagittarius filewatch)
using kqueue
doesn't allow users to monitor directory. This is because by default,
kqueue
doesn't provide facility to detect which file is added.
To do it, we need manual management. To keep our code as simple as possible,
we decided not to do it for now. This decision may be changed if there's
enough demands.
On OS X, the library is constructed on top of kqueue
, thus the
same limitation as BSD Unix is applied.
Staring Windows Vista, Microsoft decided not to change timestamp just accessing
the file or directory by default. So access
flag may or may not work on
Windows depending on the configuration of the platform.
Due to the lack of deletion detect, delete
and move
work the
same. Thus the monitoring handler may get both deleted
and moved
even though it's only specified delete
or move
.
This library provided extra IO related procedures.
Calls thunk. During evaluation of thunk, the current input port, current output port, current error port are set to port, respectively.
These utility functions are trivially defined as follows;
(define (call-with-input-string str proc)
(proc (open-input-string str)))
(define (call-with-output-string proc)
(let ((port (open-output-string)))
(proc port)
(get-output-string port)))
(define (with-input-from-string str thunk)
(with-input-from-port (open-input-string str) thunk))
(define (with-output-to-string thunk)
(let ((port (open-output-string)))
(with-output-to-port port thunk)
(get-output-string port)))
Re-export of buffered-port
and transcoded-port
.
Sagittarius provides means to create user defined ports. One of the ways is using R6RS custom port procedures. The other one is extending custom port class. The followings show how to extend it.
;; example for input port
(import (rnrs) (sagittarius io) (clos user))
;; make a custom binary input port with 'read slot
(get-u8 (make <custom-binary-input-port>
:read (lambda (bv start count)
(bytevector-u8-set! bv start 1)
1)))
;; example for output port
(import (rnrs) (sagittarius io) (clos user))
;; user defined custom binary output port
(define-class <my-port> (<custom-binary-output-port>)
;; this port has own buffer
((buffer :init-form (make-bytevector 5 0))))
;; create the port
(let ((out (make <my-port>)))
;; set 'write slot
(slot-set! out 'write
(lambda (bv start count)
;; just get the first element of given bytevector
;; and set it to own buffer
(bytevector-copy! bv start (slot-ref out 'buffer) 0 count)
count))
;;
(put-bytevector out #vu8(1 2 3 4 5))
(slot-ref out 'buffer))
;; -> #vu8(1 0 0 0 0)
Custom port classes. All of these classes have the following slots:
Identifier of the port. Must be string is specified.
All of them must be either procedure or #f.
position
procedure must accept 0 argument. The procedure should
return the position of the port.
set-position
procedure must accept 2 argument, position_and_whence. Whence shall be a symbol of begin
,
current
or end
. The procedure should set the position
of the port according to the given whence and position.
read
procedure must accept 3 argument. bv or string,
start and count. The first argument is decided by the port
type. If the port is binary port, then bytevector bv is passed.
If the port is textual port, then string string is passed.
The procedure should fill given bv or string in _count_data elements starting start. And return number of data filled.
write
procedure must accept 3 argument. bv or string,
start and count. The first argument is decided by the port
type. If the port is binary port, then bytevector bv is passed.
If the port is textual port, then string string is passed.
The procedure should retrieve data from given bv or _string_upto count data elements starting start. And return number
of data read.
ready
procedure must accept 0 argument. The procedure should
return true value if the port is ready to read. Otherwise #f.
flush
procedure must accept 0 argument. The procedure should
flush the port.
close
procedure must accept 0 argument. The procedure should
close the port.
If the creating port is input port, then read
must be set before
any port operation. If the creating port is output port, then write
must be set before any port operation. Other slots are optional.
MOP is "meta object protocol". As far as I know, there is no standard specification even the name is really famous and most of CLOS is implemented on MOP.
Then we decided to take the APIs and its behaviour from Tiny CLOS. The following libraries are implemented with the APIs and can be examples for Sagittarius' MOP.
Supporting :allocation
option for define-class
.
Meta class and mixin class to support :allocation
option for
class slot definition, respectively.
The meta class must be used with :metaclass
option of
define-class
.
The mixin class must be a parent class.
Currently, we only support :instance
and :class
keywords.
The following code is the whole definition of this classes.
(define-class <allocation-meta> (<class>) ())
(define-method compute-getter-and-setter ((class <allocation-meta>) slot)
(cond ((slot-definition-option slot :allocation :instance)
=> (lambda (type)
(case type
((:instance) '())
((:class)
(let* ((init-value (slot-definition-option
slot :init-value #f))
(init-thunk (slot-definition-option
slot :init-thunk #f))
(def (if init-thunk (init-thunk) init-value)))
(list
(lambda (o) def)
(lambda (o v) (set! def v)))))
(else
(assertion-violation '<allocation-meta>
"unknown :allocation type"
type)))))
(else (call-next-method))))
(define-class <allocation-mixin> () () :metaclass <allocation-meta>)
Supporting :validator
and observer
options for
define-class
.
Make user be able to add own validation mechanism to slots.
:validator
is for before set the value to the slot so that user can check
the value if it's correct or not.
:observer
is for after set the value to the slot so that user can check
which value is set to the slot.
The eql specializer is now builtin so this library is only for backward compatibility.
Supporting eql specializer methods.
The following code describes how to use;
(import (clos user) (sagittarius mop eql))
(define-generic eql-fact :class <eql-specializable-generic>)
(define-method eql-fact ((n (eql 0))) 1)
(define-method eql-fact ((n <integer>)) (* n (eql-fact (- n 1))))
(eql-fact 10)
3628800
Note: The eql specializer is really slow approximately 200 time slower than usual procedure call.
Subclass of <generic>
.
To use eql specializer, generic functions must have this class as a metaclass.
This library provides convenient procedures.
Returns given object's values associated with key. The default
implementation uses slot-ref
.
Following classes are specialised by default.
<hashtable>
uses hashtable-ref
<list>
uses list-ref
<string>
uses string-ref
<vector>
uses vector-ref
Returns string represented object.
Returns integer represented object.
Returns number represented object.
The default value is 0.
If the given object is number, it returns given object itself.
If the given object is string, it uses string->number
as a
conversion procedure.
If the given object is character, it uses char->integer
as a
conversion procedure.
In real world, there are a lot of useful programs and you want to re-use it rather than re-write it in Scheme. For that purpose, this library can be useful.
The concept of this library is similar with Java's Process class. Users can create process object and run/call whenever they want. However most of the time process can be invoked immediately, so there are high level APIs for that purpose.
This section describe from top to down.
Exports high level APIs and low level APIs for operating process.
name must be string and indicate the process name be called.
arg1 and the rest must be string which will be passed to process.
The run
procedure invokes name process and waits until it ends.
Then returns process' exit status.
The call
procedure invokes name process and continue the Scheme
process, so it does not wait the called process. Then returns process object.
If you need to finish the process, make sure you call the process-wait
procedure described below.
Both procedures' output will be redirects current-output-port
and
current-error-port
. If you need to redirect it other place use
create-process
described below.
_ :key (stdout #f) (stderr #f) (call? #t) reader (transcoder #f)
name must be string and indicate a process name.
args must be list of string will be passed to the process.
The create-process
procedure creates and invokes a process indicated
name. Keyword arguments decide how to invoke and where to redirect the
outputs.
If stdout is #f or non output-port and call? is #f then
create-process
raises &assertion
.
stdout keyword argument indicates the port where to redirect the standard output of the process. This can be either binary output port or textual output port.
stderr keyword argument indicates the port where to redirect the standard error of the process. This can be either binary output port or textual output port. If this argument is #f, then stdout will be used.
call? keyword argument decides the default behaviour. If this is #t and
reader is not a procedure, then the create-process
uses
async-process-read
. If this is #f and reader is not a procedure,
then it uses sync-process-read
. If reader is provided, then it
uses given reader.
reader keyword argument must be procedure which takes 4 arguments, process object, redirection of standard output and error, and transcoder respectively. This procedure decides how to handle the output.
Note: on Windows, both standard output end error has limitation. So if you replace the default behaviour, make sure you must read the output from the process, otherwise it can cause deat lock.
transcoder keyword argument must be transcoder or #f. This can be used in the procedure which specified reader keyword argument.
The procedure create-process
creates a process and call it. The
returning value is depending on the above keyword parameters. If _reader_and stdout is provided, then the result value is the value returned from
reader procedure. Otherwise the created process object.
Process output reader. This reader creates 2 threads to read standard ouput and standard error. The reader returns immediately after the threads are executed.
Process output reader. This reader creates 2 threads to read standard ouput and standard error. The reader waits until the given process is finished.
This section describe low level APIs however some of these might be used even
if you use call
described above.
Returns #f if obj is process object, otherwise #f.
name must be string and indicates the process name which will be invoked.
args must be empty list or list of strings and will be passed to the process.
Creates a process object.
process must be a process object.
Returns the binary output port which is redirected to the process' standard input.
process must be a process object.
Returns the binary input port which is redirected to the process' standard output.
process must be a process object.
Returns the binary input port which is redirected to the process' standard error.
process must be a process object.
Invokes the process and wait until it ends.
On POSIX envionment this procesure returns the result status of the process.
process must be a process object.
Invokes the process and continue the Scheme program.
process must be a process object.
Wait the given process until it ends and returns the exit status of the given process.
If the keyword argument timeout is specified, then it must be an
integer represents second or time object represents absolute time, then
the procedure waits either the given process is finished or until the
specified timeout period is passed. When the timeout period
has passed and yet the process is not finished, then the procedure returns
#f
.
NOTE: The exit status are platform dependent. On Windows, the value will be 32 bit integer. On POSIX, the value will be 8 bit unsigned integer.
NOTE: On POSIX environment, timeout only works if the given
process is created by make-process
related procedures. If the
process is created by pid->process
, then it raises an error with
ECHILD
.
process must be a process object.
Kill the given process and returns the exit status of the given
process. If the process is already terminated before the process-kill
is called, then returning value is its status code. Otherwise -1.
If the keyword argument children? is given and if it's true value, then
the procedure kills the child processes. The process of killing child processes
is not the same between Windows and POSIX. On Windows, the process seeks all
possible child processes. On POSIX, it simply calls killpg (2)
.
process must be a process object.
Return #t if the given process is still active. Otherwise #f.
On Windows, the procedure uses GetExitCodeProcess
which means
if the process returns STILL_ACTIVE(259)
, then this procedure
return #t even if the process itself is already terminated.
On POSIX, the procedure uses kill (2)
sending 0 to check the
existance of the process.
Returns pid of current Sagittarius process. The returning value is an integer.
pid must be an integer represents process id.
Creates a process form given pid.
NOTE: the created process doesn't have any ports. Those values are set to #f.
Users can choose how to communicate processes. One of the typical ways is
using socket. (sagittarius process)
provides shared memory for
simple IPC.
Returns #t if given obj is a shared memory object, otherwise #f.
Creates or opens shared memory named name.
name must be an string and must be a valid shared memory name. If there is already a shared memory with the same name, then this procedure maps to it and ignores the size argument.
size must be an integer. When a new shared memory is created, then its size is restricted to the given size.
Optional argument option must be an enumeration which created by
file-options. If no-create
is specified, and there is
no shared memory with given name, then &i/o-file-does-not-exist
is raised. If no-truncate
is specified, then the created shared
memory is intact, otherwise it is truncted.
Closes given shared-memory and invalidate the allocated memory.
This procedure also removes the given shared-memory. On some platform, for example Linux, if shared memory is not explicitly unliked, then it stays until the OS is restarted. To avoid it, users need to call this procedure.
NOTE: invalidation means that the bytevector returned by
shared-memory->bytevector
will be 0 length bytevector.
Returns actual instance of shared memory as a bytevector.
Modifying the returning bytevector also modifies the actual shared memory.
To do synchronisation of this, use semaphore provided by
(sagittarius threads)
.
Sagittarius provides functionalities to modify its reader like Common Lisp. It makes the reader programable. However it has some restriction to use. The following examples explain it.
Using reader macro
#!read-macro=sagittarius/regex
(import (sagittarius regex)) ;; usual import for procedures
#/regex/i ;; (sagittarius regex) defines #/regex/ form
;; reader macro in it. it converts it
;; (comple-regex "regex" CASE-INSENSITIVE)
Writing reader macro on toplevel
(import (rnrs) (sagittarius reader))
(set-macro-character #\$
(lambda (port c) (error '$-reader "invliad close paren appeared")))
(set-macro-character #\! (lambda (port c) (read-delimited-list #\$ port)))
!define test !lambda !$ !display "hello reader macro"$$$
!test$ ;; prints "hello reader macro"
Writing reader macro in library and export it
#!compatible ;; make sure Sagittarius can read keyword
(library (reader macro test)
;; :export-reader-macro keyword must be in export clause
(export :export-reader-macro)
(import (rnrs) (sagittarius reader))
(define-reader-macro $-reader #\$
(lambda (port c)
(error '$-reader "unexpected close paren appeared")))
(define-reader-macro !-reader #\!
(lambda (port c)
(read-delimited-list #\$ port)))
)
#!read-macro=reader/macro/test ;; imports reader macro
!define test !lambda !$ !display "hello reader macro"$$$
!test$ ;; prints "hello reader macro"
If you need to use reader macro in your library code, you need to define it outside of the library. The library syntax is just one huge list so Sagittarius can not execute the definition of reader macro inside during reading it.
This library provides reader macro procedures and macros.
Name must be self evaluated expression. Proc must accept 2 or 3 arguments, the first one is a port, the second one is a character which is defined as reader macro character, and the third one which is an optional argument is a read context.
define-reader-macro
macro associates char and proc as a
reader macro. Once it is associated and Sagittarius' reader reads it, then
dispatches to the proc with 2 arguments.
If non-term? argument is given and not #f, the char is marked as non terminated character. So reader reads as one identifier even it it contains the given char in it.
The first form is a convenient form. Users can write a reader macro without
explicitly writing lambda
. The form is expanded to like this:
(define-reader-macro #\$ ($-reader args ...) body ...)
;; -> (define-reader-macro $-reader #\$ (lambda (args ...) body ...))
Note: the name is only for error message. It does not affect anything.
Name must be self evaluated expression. Proc must accept three arguments, the first one is a port, the second one is a character which is defined as reader macro character and the third one is a macro parameter.
define-dispatch-macro
creates macro dispatch macro character
_char_if there is not dispatch macro yet, and associates subchar and
_proc_as a reader macro.
If non-term? argument is given and not #f, the char is marked as non terminated character. So reader reads as one identifier even it it contains the given char in it.
Note: the name is only for error message. It does not affect anything.
Returns 2 values if char is macro character; one is associated procedure other one is boolean if the char is terminated character or not. Otherwise returns 2 #f.
Mark given char as macro character and sets the proc as its reader. If non-term? is given and not #f, the char will be marked as non terminated macro character.
Creates a new dispatch macro character with given char if it is not a dispatch macro character yet. If non-term? is given and not #f, the char will be marked as non terminated macro character.
Returns a procedure which is associated with char and _subchar_as a reader macro. If nothing is associated, it returns #f.
Sets proc as a reader of subchar under the dispatch macro character of char.
Reads a list until given char appears.
The following table explains predefined reader macros.
Macro character | Terminated | Explanation |
---|---|---|
#\( | #t | Reads a list until reader reads #\). |
#\[ | #t | Reads a list until reader reads #\]. |
#\) | #t | Raises read error. |
#\] | #t | Raises read error. |
#\| | #t | Reads an escaped symbol until reader reads #\|. |
#\" | #t | Reads a string until reader reads #\". |
#\' | #t | Reads a symbol until reader reads delimited character. |
#\; | #t | Discards read characters until reader reads a linefeed. |
#\` | #t | Reads a next expression and returns (quasiquote _expr_) |
#\, | #t | Check next character if it is @ and reads a next expression.Returns (unquote-splicing _expr_) if next character was@ , otherwise (unquote _expr_) |
#\: | #f | Only compatible mode. Reads a next expression and returns a keyword. |
#\# | #t(R6RS mode) | Dispatch macro character. |
Sub character | Explanation |
---|---|
#\' | Reads a next expression and returns (syntax _expr_) . |
#\` | Reads a next expression and returns (quasisyntax _expr_) |
#\, | Check next character if it is @ and reads a next expression.Returns (unsyntax-splicing _expr_) if next character was@ , otherwise (unsyntax _expr_) |
#\! | Reads next expression and set flags. The details are described the below section |
#\v | Checks if the next 2 characters are u and 8 and readsa bytevector. |
#\u | Only compatible mode. Checks if the next character is 8 and readsa bytevector. |
#\t and #\T | Returns #t. |
#\f and #\F | Returns #f. |
#\b and #\B | Reads a binary number. |
#\o and #\O | Reads a octet number. |
#\d and #\D | Reads a decimal number. |
#\x and #\X | Reads a hex number. |
#\i and #\I | Reads a inexact number. |
#\e and #\E | Reads a exact number. |
#\( | Reads a next list and convert it to a vector. |
#\; | Reads a next expression and discards it. |
#\| | Discards the following characters until reader reads |# |
#\\ | Reads a character. |
#\= | Starts reading SRFI-38 style shared object. |
#\# | Refers SRFI-38 style shared object. |
Sagittarius has multiple reader and VM modes and users can switch these modes
with #!
. Following describes details of those modes;
#!r6rs
: R6RS modeSymbols are read according to R6RS specification and VM sets the
no-overwrite
and nounbound
flag. With this mode, keywords are
read as symbols; for example, :key
is just a symbol and users can
not use extended lambda
syntax.
#!r7rs
: R7RS modeThe mode for new specification of Scheme. This mode is
less strict than R6RS mode described above. The reader can read keyword and VM
sets the no-overwrite
flag.
#!compatible
: Compatible modeThis mode is least strict mode. In other words, it does not have any restrictions such as described above.
NOTE: If you import reader macro with #!read-macro=
form and let
reader reads above hash-bang, the read table will be reset. So
following code will raise a read error;
#!read-macro=sagittarius/regex
#!r6rs
#/regular expression/ ;; <- &lexical
Since 0.3.7, users can replace default reader. Following example describes how to replace reader.
#!reader=srfi/:49
define
fac n
if (zero? n) 1
* n
fac (- n 1)
(print (fac 10))
#!reader=
specifies which reader will be used. For this example, it will
use the one defined in (srfi :49)
library. For compatibility of the other
Scheme implementation, we chose not to use the library name itself but a bit
converted name.
This is the list of #!
flags:
#!r6rs
Switches to R6RS mode
#!r7rs
Switches to R7RS mode
#!compatible
Switches to compatible mode
#!no-overwrite
Sets no-overwrite flag that does not allow user to overwrite exported variables.
#!nocache
Sets disable cache flag on the current loading file
#!deprecated
Display warning message of deprecated library.
#!reader=name
Replace reader with library name. The name must be converted with the naming convention described below. For more details, see Naming convention
#!read-macro=name
name must be converted with the naming convention described below. For more details, see Naming convention
The naming convention is really easy. For example, replacing with
(srfi :49)
, first remove all parentheses or brackets then replace spaces
to /
. Then you get srfi/:49
.
This macro defines replaceable reader.
The forms are similar with define
. However if you use the first form
then expr must be lambda
and it accept one argument.
The defined reader will be used on read time, so it needs to return valid expression as a return value of the reader.
NOTE: Only one reader can be defined in one library. If you define more than once the later one will be used.
NOTE: If you want to export user defined reader to other library, you need to
put :export-reader
keyword to the library export clause.
This library provides extra record operations.
Returns #t if obj is record type, otherwise #f.
Name must be symbol. Rtd must be record type descriptor. Rcd must be record constructor descriptor.
Associates given rcd to gien rtd.
NOTE: this procedure doesn't create fresh record type but modifies given arguments destructively.
Record-type must be record type.
Returns associated rtd from record-type.
Record-type must be record type.
Returns associated rcd from record-type.
Note: These procedures are not for using casually.
As most of script language have own regular expression mechanism, Sagittarius also has own regular expression library. It is influenced by Java's regular expression, so there are a lot of differences between the most famous Perl regular expression(perlre).
This feature may be changed, if R7RS large requires Perl like regular expression.
Following examples show how to use Sagittarius's regular expression.
;; For Perl like
(cond ((looking-at (regex "^hello\\s*(.+)") "hello world!")
=> (lambda (m) (m 1))))
world!
;; For Java like
(cond ((matches (regex "(\\w+?)\\s*(.+)") "123hello world!")) ;; this won't match
(else "incovenient eh?"))
The matches
procedure is total match, so it ignores boundary matcher
'^'
and '$'
. The looking-at
procedure is partial match, so
it works as if perlre.
This library provides Sagittarius regular expression procedures.
String must be regular expression. Returns compiled regular expression. Flags' descriptions are the end of this section. The following table is the supported regular expression constructs.
Construct | Matches |
---|---|
Characters | < |
x
|
The character x |
\\
|
The backslash character |
\0n
|
The character with octal value 0n (0 <= n <= 7) |
\0nn
|
The character with octal value 0nn (0 <= n <= 7) |
\0mnn
|
The character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7) |
\xhh
|
The character with hexadecimal value 0xhh |
\uhhhh
|
The character with hexadecimal value 0xhhhh |
\Uhhhhhhhh
|
The character with hexadecimal value 0xhhhhhhhh. If the value exceed the maxinum fixnum value it rases an error. |
\t
|
The tab character ('\u0009') |
\n
|
The newline (line feed) character ('\u000A') |
\r
|
The carriage-return character ('\u000D') |
\f
|
The form-feed character ('\u000C') |
\a
|
The alert (bell) character ('\u0007') |
\e
|
The escape character ('\u001B') |
\cx
|
The control character corresponding to x |
Character classes | < |
[abc]
|
a, b, or c (simple class) |
[^abc]
|
Any character except a, b, or c (negation) |
[a-zA-Z]
|
a through z or A through Z, inclusive (range) |
[a-d[m-p]]
|
a through d, or m through p: [a-dm-p] (union) |
[a-z&&[def]]
|
d, e, or f (intersection) |
[a-z&&[^bc]]
|
a through z, except for b and c: [ad-z] (subtraction) |
[a-z&&[^m-p]]
|
a through z, and not m through p: a-lq-z |
Predefined character classes | < |
.
|
Any character (may or may not match line terminators) |
\d
|
A digit: [0-9] |
\D
|
A non-digit: [^0-9] |
\s
|
A whitespace character: [ \t\n\x0B\f\r] |
\S
|
A non-whitespace character: [^\s] |
\w
|
A word character: [a-zA-Z_0-9] |
\W
|
A non-word character: [^\w] |
Boundary matchers | < |
^
|
The beginning of a line |
$
|
The end of a line |
\b
|
A word boundary |
\B
|
A non-word boundary |
\A
|
The beginning of the input |
\G
|
The end of the previous match |
\Z
|
The end of the input but for the final terminator, if any |
\z
|
The end of the input |
Greedy quantifiers | < |
X?
|
X, once or not at all |
X*
|
X, zero or more times |
X+
|
X, one or more times |
X{n}
|
X, exactly n times |
X{n,}
|
X, at least n times |
X{n,m}
|
X, at least n but not more than m times |
Reluctant quantifiers | < |
X??
|
X, once or not at all |
X*?
|
X, zero or more times |
X+?
|
X, one or more times |
X{n}?
|
X, exactly n times |
X{n,}?
|
X, at least n times |
X{n,m}?
|
X, at least n but not more than m times |
Possessive quantifiers | < |
X?+
|
X, once or not at all |
X*+
|
X, zero or more times |
X++
|
X, one or more times |
X{n}+
|
X, exactly n times |
X{n,}+
|
X, at least n times |
X{n,m}+
|
X, at least n but not more than m times |
Logical operators | < |
XY
|
X followed by Y |
X|Y
|
Either X or Y |
(X)
|
X, as a capturing group |
Back references | < |
\n
|
Whatever the nth capturing group matched |
Quotation | < |
\
|
Nothing, but quotes the following character |
\Q
|
Nothing, but quotes all characters until \E |
\E
|
Nothing, but ends quoting started by \Q |
Special constructs (non-capturing) | < |
(?:X)
|
X, as a non-capturing group |
(?imsux-imsux)
|
Nothing, but turns match flags on - off |
(?imsux-imsux:X)
|
X, as a non-capturing group with the given flags on - off |
(?=X)
|
X, via zero-width positive lookahead |
(?!X)
|
X, via zero-width negative lookahead |
(?<=X)
|
X, via zero-width positive lookbehind |
(?<!X)
|
X, via zero-width negative lookbehind |
(?>X)
|
X, as an independent, non-capturing group |
(?#...)
|
comment. |
Since version 0.2.3, \p
and \P
are supported. It is cooporated
with SRFI-14 charset. However it is kind of tricky. For example regex parser
can reads \p{InAscii}
or \p{IsAscii}
and search charset named
char-set:ascii
from current library. It must have In
or Is
as its prefix.
This reader macro provides Perl like regular expression syntax.
It allows you to write regular expression like this #/\w+?/i
instead of
like this (regex "\\w+?" CASE-INSENSITIVE)
.
Regex must be regular expression object. Returns closure if regex matches input string.
The matches
procedure attempts to match the entire input string against
the pattern of regex.
The looking-at
procedure attempts to match the input string against the
pattern of regex.
Pattern must be pattern object.
The first form of these procedures are for convenience. It is implemented like this;
(define (regex-replace-all pattern text replacement)
(regex-replace-all (regex-matcher pattern text) replacement))
Text must be string.
Replacement must be either string or procedure which takes matcher object and string port as its arguments respectively.
Replaces part of text where regex matches with replacement.
If replacement is a string, the procedure replace text with given
string. Replacement can refer the match result with `$_n_
`.
n must be group number of given pattern or matcher.
If replacement is a procedure, then it must accept either one or two arguments. This is for backward compatibility.
The first argument is always current matcher.
If the procedure only accepts one argument, then it must return a string which will be used for replacement value.
If the procedure accepts two arguments, then the second one is string output port. User may write string to the given port and will be the replacement string.
The regex-replace-first
procedure replaces the first match.
The regex-replace-all
procedure replaces the all matches.
text must be a string.
pattern must be a string or regex-pattern object.
Split text accoding to pattern.
The above procedures are wrapped User level API. However, you might want to use low level API directory when you re-use matcher and recursively find pattern from input. For that purpose, you need to use low level APIs directly.
NOTE: This API might be changed in future depending on R7RS large.
Returns #f if obj is regular expression object, otherwise #f.
Returns #f if obj is matcher object, otherwise #f.
The same as regex
procedure.
Regex must be regular expression object. Returns matcher object.
Matcher must be matcher object. Returns #t if matcher matches the entire input string against input pattern, otherwise #f.
Matcher must be matcher object. Returns #t if matcher matches the input string against input pattern, otherwise #f.
Matcher must be matcher object. Resets matcher and then attempts to find the next subsequence of the input string that matches the pattern, starting at the specified index if optional argument is given otherwise from the beginning.
Matcher must be matcher object. Index must be non negative exact integer.
Retrieve captured group value from matcher.
Matcher must be matcher object.
Returns number of captured groups.
Regular expression compiler can take following flags.
Enables case-insensitive matching. i
as a
flag
Permits whitespace and comments in pattern. x
as a
flag
Enables multiline mode. m
as a flag
Enables literal parsing of the pattern.
Enables dotall mode. s
as a flag
Enables Unicode-aware case folding and pre defined charset.
u
as a flag.
NOTE: when this flag is set then pre defined charset, such as \d
or
\w
, expand it's content to Unicode characters. Following properties
are applied to charsets.
[[:lower:]]
The lower case charset contains Ll
and Other_Lowercase
.
[[:upper:]]
The upper case charset contains Lu
and Other_Uppercase
.
[[:title:]]
The upper case charset contains Lt
.
[[:alpha:]]
The upper case charset contains L
, Nl
and
Other_Alphabetic
.
[[:numeric:]]
The upper case charset contains Nd
.
[[:punct:]]
The upper case charset contains P
.
symbol
The upper case charset contains Sm
, Sc
, Sk
and
So
.
[[:space:]]
The upper case charset contains Zs
, Zl
and Zp
.
[[:cntrl:]]
The upper case charset contains Cc
, Cf
, Co
, Cs
,
and Cn
.
Above APIs can be used bytevectors as well. In this case, the regular expression engine treats given bytevectors as if it's ASCII strings. If users want to use this feature, users must give bytevectors instead of strings.
This section describes low level socket API on Sagittarius. The following example is simple echo server, it receives input from a client and just returns it to the client.
The example program is from example/socket/echo.scm.
(import (rnrs) (sagittarius socket))
;; creates echo server socket with port number 5000
(define echo-server-socket (make-server-socket "5000"))
;; addr is client socket
(let loop ((addr (socket-accept echo-server-socket)))
(call-with-socket addr
(lambda (sock)
;; socket-port creates binary input/output port
;; make it transcoded port for convenience.
(let ((p (transcoded-port (socket-port sock)
;; on Sagittarius Scheme native-transcoder
;; uses utf8 codec for ASCII compatibility.
;; For socket programming it might be better
;; to specify eol-style with crlf.
;; But this sample just shows how it goes.
(native-transcoder))))
(call-with-port p
(lambda (p)
(put-string p "please type something\n\r")
(put-string p "> ")
;; gets line from client.
(let lp2 ((r (get-line p)))
(unless (eof-object? r)
(print "received: " r)
;; just returns message from client.
;; NB: If client type nothing, it'll throw assertion-violation.
(put-string p r)
(put-string p "\r\n> ")
;; waits for next input.
(lp2 (get-line p)))))))))
;; echo server waits next connection.
(loop (socket-accept echo-server-socket)))
This library provides procedures for socket programming.
Node and service must be string or #f. Other optional arguments must be exact integer.
Returns a client socket connected to an Internet address. The Internet
address is identified by node and service. The
make-client-socket
uses getaddrinfo(3)
to look it up. The
arguments node, service, ai-family, ai-socktype, ai-flags
and ai-protocol are passed to getaddrinfo(3)
as corresponding
parameters. For more detail, see reference of getaddrinfo(3)
.
Node is a network address, ex) "www.w3.org", "localhost", "192.168.1.1".
Service is a network service, ex) "http", "ssh", "80", "22".
Ai-family is an address family specifier. Predefined specifiers are listed below.
AF_INET
AF_INET6
AF_UNSPEC
Ai-sockettype is a socket type specifier. Predefined specifiers are listed below.
SOCK_STREAM
SOCK_DGRAM
SOCK_RAW
Ai-flags is an additional options specifier. Predefined specifiers are listed below.
AI_ADDRCONFIG
AI_ALL
AI_CANONNAME
AI_NUMERICHOST
AI_NUMERICSERV
AI_PASSIVE
AI_V4MAPPED
Ai-protocol is a protocol specifier. Predefined specifiers are listed below.
IPPROTO_TCP
IPPROTO_UDP
IPPROTO_RAW
Service must be string or #f. Other optional arguments must be exact
integer. Returns a server socket waiting for connections. The argument details
are the same as the make-client-socket
.
Returns #t if obj is socket object, otherwise #f.
Socket must be a socket object. Returns a binary input/output port associated with socket.
If optional argument close? is #f then the port won't close socket when port is closing or being GCed.
[SRFI-106] Socket must be a socket object. Returns a binary input and output port associated with socket, respect