Sagittarius Users' Reference

This document is a manual for Sagittarius, an R6RS/R7RS Scheme implementation. This is for version 0.8.6.

1Introduction

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.

1.1Overview of 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.

Reader
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.
Miscellaneous
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.

1.2Notations

In this manual, each entry is represented like this.

Category foo arg1 arg2
[spec] Description foo ...

Category denotes category of the entry foo. The following category will appear in this manual.

Program
A command line program
Function
A Scheme function
Syntax
A syntax
Auxiliary Syntax
A auxiliary syntax
Macro
A macro
Auxiliary Macro
A auxiliary macro
Library
A library
Condition Type
A condition type
Reader Macro
A reader macro
Class
A CLOS class
Generic
A generic function
Method
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.

arg ...
Indicates zero or more arguments
:optional x y z
:optional (x x-default) (y y-default) (z z-default)
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:

[R6RS]
[R6RS+]
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.
[R7RS]
The entry works as specified in "Revised^7 Report on the Algorithmic Language Scheme.".
[SRFI-n]
[SRFI-n+]
The entry works as specified in SRFI-n. If it is marked as "[SRFI-n+]", the entry has additional functionality.

2Programming in Sagittarius

2.1Invoking Sagittarius

Sagittarius can be used as an independent Schame interpreter. The interpreter which comes with Sagittarius distribution is a program named sagittarius on Unix like environment and sash on Windows environment.

Program sagittarius [options] scheme-file arg ...
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.

2.2Writing Scheme scripts

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 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.

2.3Working on REPL

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.

2.4Writing a library

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.

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.

2.5Compiled cache

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.

2.5.1Precompiling cache file

Users can provide own library with precompile script. The script looks like this;

(import (the-library-1)
        (the-library-2))

When this script is run, then the libraries will be cached in the cache directory.

Note: The cache files are stored with the names converted from original library files' absolute path. So it is important that users' libraries are already installed before precompiling, otherwise Sagittarius won't use the precompiled cache files.

3R6RS Libraries

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.

3.1Library form

Syntax library name export-clause import-clause body
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 identifiers. The included identifiers 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 identifiers. All of the excluded identifiers 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)
)

3.2Top library

Library (rnrs (6))
[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.

3.3Base Library

[R6RS] This library exports many of the procedure and syntax bindings that are traditionally associated with Scheme.

3.3.1Variable definitions

Syntax define variable expression
Syntax define variable
Syntax define (variable formals) body ...
Syntax define (variable . formal) body ...
[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 ...))

3.3.2Syntax definitions

Syntax define-syntax keyword expression
[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.

3.3.3Quotation

Syntax quote datum
[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)

3.3.4Procedures

Syntax lambda formals body ...
[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)

    Any variable must not appear more than once in formals.

  • (<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 ...
    Specifies 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)

    The procedure raises an &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]]
    Specifies 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)

    With the third and fourth form you can name the formal argument differently from the keyword to specify the argument.

    ((lambda (:key ((:aa a) -1)) a) ::aa 2)
    => 2
    ((lambda (:key (a :aa -1)) a) ::aa 2)
    => 2

    By default, the procedure with keyword argument spec raises &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))

    When used with :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
    Specifies 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> ())

    When the rest argument spec is used with the keyword argument spec, both accesses the same list of actual argument -- the remaining arguments after required and optional arguments are taken

    ((lambda (:optional a :rest r :key k) (list a r k)) 1 :k 3)       
    => (1 (k 3) 3)

3.3.5Conditionals

Syntax if test consequent alternate
Syntax if test consequent
[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.

3.3.6Assignment

Syntax set! variable expression
[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.

3.3.7Derived conditionals

Syntax cond clause ...
[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.

Syntax case clause ...
[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.

Syntax and test ...
[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))
=> #f
(and 1 2 'c '(f g))
=> (f g)
(and)
=> #t

Syntax or test ...
[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)
=> #f
(or '(b c) (/ 3 0))
=> (b c)

3.3.8Binding constructs

Syntax let bindings body ...
[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.

Syntax let* bindings body ...
[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.

Syntax letrec bindings body ...
[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.

Syntax letrec* bindings body ...
[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.

Syntax let-values mv-bindings body ...
[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.

Syntax let*-values mv-bindings body ...
[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.

3.3.9Sequencing

Syntax begin form ...
Syntax begin expression ...
[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.

3.3.10Equivalence predicates

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?.

Function eq? obj1 obj2
Function eqv? obj1 obj2
Function equal? obj1 obj2
[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)))
=> #f
(eqv? '#() '#())
=> #f
(eqv? (lambda (x) x) (lambda (x) x))
=> #f
(eqv? (lambda (x) x) (lambda (y) y))
=> #f
(eqv? +nan.0 +nan.0)
=> #f

3.3.11Procedure predicate

Function procedure? obj
[R6RS] Returns #t if obj is a procedure, otherwise returns #f.

3.3.12Numerical type predicates

Function number? obj
Function complex? obj
Function real? obj
Function rational? obj
Function integer? obj
[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.

Function real-valued? obj
[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.

Function exact? obj
Function inexact? obj
[R6RS] These numerical predicates provide tests for the exactness of a quantity. For any number object, precisely one of these predicates is true.

3.3.13 Generic conversion

Function exact z
Function inexact z
[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.

3.3.14Arithmetic operations

Function = z1 z2 z3 ...
Function > x1 x2 x3 ...
Function < x1 x2 x3 ...
Function >= x1 x2 x3 ...
Function <= x1 x2 x3 ...
[R6RS] These procedures return #t if their arguments are (respectively): equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing, and #f otherwise.

Function zero? z
Function positive? z
Function negative? z
Function odd? z
Function even? z
Function finite? z
Function infinite? z
Function nan? z
[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.

Function max x1 x2 ...
Function min x1 x2 ...
[R6RS] These procedures return the maximum or minimum of their arguments.

Function + z ...
Function * z ...
[R6RS] These procedures return the sum or product of their arguments.

Function - z ...
Function - z1 z2 ...
[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.

Function / z ...
Function / z1 z2 ...
[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.

Function abs x
[R6RS] Returns the absolute value of its argument.

Function div-and-mod x1 x2
Function div x1 x2
Function mod x1 x2
Function div0-and-mod0 x1 x2
Function div0 x1 x2
Function mod0 x1 x2
[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.

Function gcd n1 ...
Function lcm n1 ...
[R6RS] These procedures return the greatest common divisor or least common multiple of their arguments. The result is always non-negative.

Function numerator q
Function denominator q
[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.

Function floor x
Function ceiling x
Function truncate x
Function round x
[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.

Function rationalize x1 x2
[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.

Function exp z
Function log z
Function log z1 z2
Function sin z
Function cos z
Function tan z
Function asin z
Function acos z
Function atan z
Function atan z1 z2
[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)).

Function sqrt z
[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.

Function expt z1 z2
[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.

Function make-rectangular x1 x2
Function make-polar x3 x4
Function real-part z
Function imag-part z
Function magnitude z
Function angle z
[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.

3.3.15 Numerical input and output

Function number->string z :optional radix precision
[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.

Function number->string string :optional radix
[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.

3.3.16Booleans

Function not obj
[R6RS] Returns #t if obj is #f, and returns #f otherwise.

Function boolean? obj
[R6RS] Returns #t if obj is either #t or #f and returns #f otherwise.

Function boolean=? bool1 bool2 bool3...
[R6RS] Returns #t if the booleans are the same.

3.3.17Pairs and lists

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.

Function pair? obj
[R6RS] Returns #t if obj is a pair, and otherwise returns #f.

Function cons obj1 obj2
[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.

Function car pair
Function cdr pair
[R6RS] Returns the contents of the car/cdr field of pair.

Function caar pair
Function cadr pair
:
Function cadddr pair
Function cddddr 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.

Function null? obj
[R6RS] Returns #t if obj is the empty list, #f otherwise.

Function list? obj
[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.

Function list obj ...
[R6RS] Returns a newly allocated list of its arguments.

Function length list
[R6RS+] Returns the length of list. If the list is improper list, it returns -1 If the list is infinite list , it returns -2.

Function append list ... obj
[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.

Function reverse list
[R6RS] Returns a newly allocated list consisting of the elements of list in reverse order.

Function list-tail list k :optaionl fallback
[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.

Function list-ref list k :optaionl fallback
[R6RS+] The list-ref procedure returns the kth element of list. If fallback is given and k is out of range, it returns fallback otherwise &assertion is raised.

Function map proc list1 list2 ...
[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.

Function for-each proc list1 list2 ...
[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.

3.3.18Symbols

Function symbol? obj
[R6RS] Returns #t if obj is a symbol, otherwise returns #f.

Function symbol->string symbol
[R6RS] Returns the name of symbol as an immutable string.

Function symbol=? symbol1 symbol2 symbol3 ...
[R6RS] Returns #t if the symbols are the same, i.e., if their names are spelled the same.

Function string->symbol string
[R6RS] Returns the symbol whose name is string.

3.3.19Characters

Characters are objects that represent Unicode scalar values.

Function char? obj
[R6RS] Returns #t if obj is a character, otherwise returns #f.

Function char->integer char
Function integer->char sv
[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.

Function char=? char1 char2 char3 ...
Function char<? char1 char2 char3 ...
Function char>? char1 char2 char3 ...
Function char<=? char1 char2 char3 ...
Function char>=? char1 char2 char3 ...
[R6RS] These procedures impose a total ordering on the set of characters according to their Unicode scalar values.

3.3.20Strings

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.

Function string? obj
[R6RS] Returns #t if obj is a string, otherwise returns #f.

Function make-string k :optional char
[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))

Function string char ...
[R6RS] Returns a newly allocated string composed of the arguments.

Function string-length string
[R6RS] Returns the number of characters in the given string as an exact integer object.

Function string-ref string k :optional fallback
[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.

Function string=? string1 string2 string3 ...
[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.

Function string<? string1 string2 string3 ...
Function string>? string1 string2 string3 ...
Function string<=? string1 string2 string3 ...
Function string>=? string1 string2 string3 ...
[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.

Function substring string start end
[R6RS] String must be a string, and start and end must be exact integer objects satisfying

0 ≤ startend(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).

Function string-append string ...
[R6RS] Returns a newly allocated string whose characters form the concatenation of the given strings.

Function string->list string :optional start end
Function list->string list :optional start end
[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.

Function string-for-each proc string1 string2 ...
[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.

Function string-copy string :optional (start 0) (end -1)
[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).

3.3.21Vectors

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.

Function vector? obj
[R6RS] Returns #t if obj is a vector. Otherwise returns #f.

Function make-vector k :optional fill
[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.

Function vector obj ...
[R6RS] Returns a newly allocated vector whose elements contain the given arguments. Analogous to list.

Function vector-length vector
[R6RS] Returns the number of elements in vector as an exact integer object.

Function vector-ref vector k :optional fallback
[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.

Function vector-ref vector k obj
[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.

Function vector->list vector :optional start end
Function list->vector list :optional start end
[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)

Function vector-fill! vector :optional start end
[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.

Function vector-map proc vector1 vactor2 ...
[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.

Function vector-for-each proc vector1 vactor2 ...
[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.

3.3.22Errors and violations

Function error who message irritant ...
Function assertion-violation who message irritant ...
[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.

3.3.23Control features

Function apply proc arg1 ... rest-args
[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.

Function call/cc proc
[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.

Function values obj ...
[R6RS] Returns objs as multiple values.

Function call-with-values producer consumer
[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.

Function dynamic-wind before thunk after
[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.

3.3.24Iteration

Syntax let variable bindings body ...
[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.

3.3.25Quasiquote

Syntax quasiquote qq-template
Auxiliary Syntax unquote qq-template
Auxiliary Syntax unquote-splicing qq-template
[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.

3.3.26Binding constructs for syntactic keywords

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.

Syntax let-syntax bindings form ...
[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.

Syntax letrec-syntax bindings form ...
[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.

3.3.27Macro transformers

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.

Syntax syntax-rules (literal ...) rule ...
[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.

Syntax identifier-syntax template
Syntax identifier-syntax (id1 template1) (set! id2 pattern) template2
[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)

3.4Unicode

[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.

3.4.1Characters

Function char-upcase char
Function char-downcase char
Function char-titlecase char
Function char-foldcase char
[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.

Function char-ci=? char1 char2 char3 ...
Function char-ci>? char1 char2 char3 ...
Function char-ci<? char1 char2 char3 ...
Function char-ci>=? char1 char2 char3 ...
Function char-ci<=? char1 char2 char3 ...
[R6RS] These procedures are similar to char=?, etc., but operate on the case-folded versions of the characters.

Function char-alphabetic? char
Function char-numeric? char
Function char-whitespace? char
Function char-upper-case? char
Function char-lower-case? char
Function char-title-case? char
[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.

3.4.2Strings

Function string-upcase string start end
Function string-downcase string start end
Function string-titlecase string start end
Function string-foldcase string start end
[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.

Function string-ci=? string1 string2 string3 ...
Function string-ci>? string1 string2 string3 ...
Function string-ci<? string1 string2 string3 ...
Function string-ci>=? string1 string2 string3 ...
Function string-ci<=? string1 string2 string3 ...
[R6RS] These procedures are similar to string=?, etc., but operate on the case-folded versions of the strings.

Function string-nfd string
Function string-nfkd string
Function string-nfc string
Function string-nfkc string
[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.

3.5Bytevectors

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.

3.5.1General operations

Macro endianness symbol
[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.

Function bytevector? obj
[R6RS] Returns #t if obj is a bytevector, otherwise returns #f.

Function make-bytevector k :optional fill
[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.

Function bytevector-length bytevector
[R6RS] Returns, as an exact integer object, the number of bytes in bytevector.

Function bytevector=? bytevector1 bytevector2
[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.

Function bytevector-fill! bytevector fill :optional start end
[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.

Function bytevector-copy! source source-start target target-start k
[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.

Function bytevector-copy bytevector :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).

3.5.2Operation on bytes and octets

Function bytevector-u8-ref bytevector k
Function bytevector-s8-ref bytevector k
[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.

Function bytevector-u8-set! bytevector k octet
Function bytevector-s8-set! bytevector k 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.

Function bytevector->u8-list bytevector
Function u8-list->bytevector bytevector
[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.

3.5.3Operations on integers of arbitary size

Function bytevector-uint-ref bytevector k endianness size
Function bytevector-sint-ref bytevector k endianness size
Function bytevector-uint-set! bytevector k n endianness size
Function bytevector-sint-set! bytevector k n endianness size
[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.

Function bytevector->uint-list bytevector endianness size
Function bytevector->sint-list bytevector endianness size
Function uint-list->bytevector list endianness size
Function sint-list->bytevector list endianness size
[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.

3.5.4Operation on 16-bit integers

Function bytevector-u16-ref bytevector k endianness
Function bytevector-s16-ref bytevector k endianness
Function bytevector-u16-native-ref bytevector k
Function bytevector-s16-native-ref bytevector k
Function bytevector-u16-set! bytevector k n endianness
Function bytevector-s16-set! bytevector k n endianness
Function bytevector-u16-native-set! bytevector k n
Function bytevector-s16-native-set! bytevector k n
[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.

3.5.5Operation on 32-bit integers

Function bytevector-u32-ref bytevector k endianness
Function bytevector-s32-ref bytevector k endianness
Function bytevector-u32-native-ref bytevector k
Function bytevector-s32-native-ref bytevector k
Function bytevector-u32-set! bytevector k n endianness
Function bytevector-s32-set! bytevector k n endianness
Function bytevector-u32-native-set! bytevector k n
Function bytevector-s32-native-set! bytevector k n
[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.

3.5.6Operation on 64-bit integers

Function bytevector-u64-ref bytevector k endianness
Function bytevector-s64-ref bytevector k endianness
Function bytevector-u64-native-ref bytevector k
Function bytevector-s64-native-ref bytevector k
Function bytevector-u64-set! bytevector k n endianness
Function bytevector-s64-set! bytevector k n endianness
Function bytevector-u64-native-set! bytevector k n
Function bytevector-s64-native-set! bytevector k n
[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.

3.5.7Operation on IEEE-754 representations

Function bytevector-ieee-single-ref bytevector k endianness
[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.

Function bytevector-ieee-double-ref bytevector k endianness
[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.

Function bytevector-ieee-single-set! bytevector k x endianness
[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.

Function bytevector-ieee-double-set! bytevector k x endianness
[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.

3.5.8Operation on strings

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.

Function string->utf8 string :optional start end
[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.

Function string->utf16 string :optional endianness
[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.

Function string->utf32 string :optional endianness
[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.

Function utf8->string bytevector :optional start end
[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.

Function utf16->string bytevector endianness :optional endianness-mandatory?
[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.

Function utf32->string bytevector endianness :optional endianness-mandatory?
[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.

3.6List utilities

[R6RS] The (rnrs lists (6))library, which contains various useful procedures that operate on lists.

Function find proc list
[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.

Function for-all pred list1 list2 ...
[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.

Function exists pred list1 list2 ...
[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.

Function filter proc list
Function partition proc list
[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.

Function fold-left combine nil list1 list2 ...
[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.

Function fold-right combine nil list1 list2 ...
[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.

Function remp proc list
Function remove obj list
Function remv obj list
Function remq obj list
[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.

Function memp proc list
Function member obj list :optional =
Function memv obj list
Function memq obj list
[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?.

Function assp proc alist
Function assc obj alist :optional =
Function assv obj alist
Function assq obj alist
[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.

Function cons* obj1 obj2 ...
[R6RS] Like list, but the last argument provides the tail of the constructed list.

3.7Sorting

The (rnrs sorting (6))library provides procedures for sorting lists and vectors.

Function list-sort proc list
Function vector-sort proc vector :optional (start 0) (end (vector-length vector))
[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).

Function vector-sort! proc vector :optional (start 0) (end (vector-length vector))
[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).

3.8Control structures

The (rnrs control (6))library, which provides useful control structures.

Syntax when test expression ...
Syntax unless test expression ...
[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.

Syntax do ((variable init step) ...) (test expression ...) commend
[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

Syntax case-lambda case-lambda-clause ...
[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.

3.9Records syntactic layer

The (rnrs records syntactic (6))library. Some details of the specification are explained in terms of the specification of the procedural layer below.

Macro define-record-type name-spec record-clase ...
Auxiliary syntax fields field-spec ...
Auxiliary syntax parent parent-name
Auxiliary syntax protocol expression
Auxiliary syntax sealed boolean
Auxiliary syntax opaque boolean
Auxiliary syntax nongenerative :optional uid
Auxiliary syntax parent-rtd parent-rtd parent-cd
[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)))
=> #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-type (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 nas 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))))))

Macro record-type-descriptor record-name
[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))
=> #f
(point? (cons 'a 'b))
=> #f
(cpoint? p1)
=> #f
(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)
=> #f

3.10Records procedural layer

The procedural layer is provided by the (rnrs records procedural (6)) library.

Function make-record-type-descriptor name parent uid sealed? opaque? fields
[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.

Function make-record-constructor-descriptor rtd parent-constructor-descriptor protocol
[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.

Function record-constructor constructor-descriptor
[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.

Function record-accessor rtd k
[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 kth 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.

Function record-mutator rtd k
[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.

3.11Records inspection

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.

Function record? obj
[R6RS] Returns #t if obj is a record, and its record type is not opaque, and returns #f otherwise.

Function record-rtd record
[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.

3.12Exceptions

This section describes exception-handling and exception-raising constructs provided by the (rnrs exceptions (6))library.

Function with-exception-handler handler thunk
[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.

Macro guard (variable cond-clause ...) body
[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.

Function raise obj
[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.

3.13Conditions

The section describes (rnrs conditions (6))library for creating and inspecting condition types and values. A condition value encapsulates information about an exceptional situation.

Function condition condition ...
[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.

Function simple-condition condition
[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.

Function condition? obj
[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.

Function condition-accessor rtd proc
[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.

Macro define-condition-type condition-type supertypes constructor predicate field-spec ...
[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.

3.13.1Standard condition types

Hierarchy of standard condition types:

+ &condition
    + &warning
    + &serious
          + &error
          + &violation
                + &assertion
                + &non-continuable
                + &implementation-restriction
                + &lexical
                + &syntax
                + &undefined
    + &message
    + &irritants

Condition Type &message
Function condition-message condition
[R6RS] It carries a message further describing the nature of the condition to humans.

Condition Type &warning
Function warning? obj
[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.

Condition Type &serious
[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.

Condition Type &error
Function make-error
Function error? obj
[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.

Condition Type &violation
Function violation? obj
[R6RS] This type describes violations of the language standard or a library standard, typically caused by a programming error.

Condition Type &assertion
[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.

Condition Type &irritants
Function condition-irritants condition
[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.

Condition Type &who
Function who-condition? obj
Function condition-who condition
[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.

Condition Type &non-continuable
[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.

Condition Type &lexical
[R6RS] This type describes syntax violations at the level of the datum syntax.

Condition Type &syntax
Function make-syntax-violation form subform
Function syntax-violation-form condition
[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.

Condition Type &undefined
[R6RS] This type describes unbound identifiers in the program.

3.14I/O condition types

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.

Condition Type &i/o
Function i/o-error? obj
[R6RS] This is a supertype for a set of more specific I/O errors.

Condition Type &i/o-read
[R6RS] This condition type describes read errors that occurred during an I/O operation.

Condition Type &i/o-write
[R6RS] This condition type describes write errors that occurred during an I/O operation.

Function i/o-error-position condition
[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.

Condition Type &i/o-filename
Function i/o-error-filename condition
[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.

Condition Type &i/o-file-protection
[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.

Condition Type &i/o-port
Function i/o-error-port condition
[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)))
    + &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

3.14.1Port I/O

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.

3.14.1.1Filename

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.

3.14.1.2File options

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.

Macro file-options file-options-symbol ...
[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.

3.14.1.3Buffer modes

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.

Macro buffer-mode buffer-mode-symbol
[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.

Function buffer-mode? obj
Returns #t if the argument is a valid buffer-mode symbol, and returns #f otherwise.

3.14.1.4Transcoders

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.

Function utf-8-codec
[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.

Macro eol-style eol-style-symbol
[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.

Condition Type &i/o-decoding
[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.

Condition Type &i/o-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.

Macro error-handling-mode error-handling-mode-symbol
[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.

Function make-transcoder codec :optional eol-style handling-mode
[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.

Function transcoder-codec transcoder
Function transcoder-eol-style 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.

Function bytevector->string bytevector transcoder :optional start end
[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.

Function string->bytevector string transcoder :optional start end
[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.

3.14.1.5End-of-file object

The end-of-file object is returned by various I/O procedures when they reach end of file.

Function eof-object
[R6RS] Returns the end-of-file object

Function eof-object? obj
Returns #t if obj is the end-of-file object, #f otherwise.

3.14.1.6Input and output ports

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.

Function port? obj
Returns #t if the argument is a port, and returns #f otherwise.

Function port-transcoder port
[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.

Function textual-port? obj
Function binary-port? obj
[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.

Function transcoded-port binary-port transcoder
[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.

Function port-position 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.

Function set-port-position! port pos :optional (whence 'begin)
[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.

Function close-port port
[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.

Function call-with-port port proc
[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.

3.14.1.7Input ports

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.

Function input-port? obj
Returns #t if the argument is an input port (or a combined input and output port), and returns #f otherwise.

Function port-eof? input-port
[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.

Function open-file-input-port filename :optiona file-options buffer-mode maybe-transcoder
[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.

Function open-bytevector-input-port bytevector :optional (transcoder #f) (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))

Function open-string-input-port string :optional (start 0) (end (string-length string))
[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.

Function current-input-port :optional port
[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.

Function make-custom-binary-input-port id read! get-position set-position! close :optional (ready #f)
[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.

Function make-custom-textual-input-port id read! get-position set-position! close :optional (ready #f)
[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.

3.14.1.8Binary input

Function get-u8 binary-input-port :optional reckless
[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.

Function lookahead-u8 binary-input-port :optional reckless
[R6RS] The lookahead-u8 procedure is like get-u8, but it does not update binary-input-port to point past the byte.

Function get-bytevector-n binary-input-port count :optional reckless
[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.

Function get-bytevector-n! binary-input-port bytevector start count :optional reckless
[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.

Function get-bytevector-some binary-input-port :optional reckless
[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.

Function get-bytevector-all binary-input-port :optional reckless
[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.

3.14.1.9Textual input

Function get-char textual-input-port
[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.

Function lookahead-char textual-input-port
[R6RS] The lookahead-char procedure is like get-char, but it does not update textual-input-port to point past the character.

Function get-string-n textual-input-port count
[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.

Function get-string-n! textual-input-port string start count
[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.

Function get-string-all textual-input-port
[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.

Function get-line textual-input-port
[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.

Function get-datum textual-input-port
[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.

3.14.1.10Output ports

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.

Function output-port? obj
[R6RS] Returns #t if obj is an output port (or a combined input and output port), #f otherwise.

Function flush-output-port :optional output-port
[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.

Function output-port-buffer-mode output-port
[R6RS] Returns the symbol that represents the buffer mode of output-port.

Function open-file-output-port filename :optional file-options buffer-mode maybe-transcoder
[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.

Function open-bytevector-output-port :optional maybe-transcoder
[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.

Function call-with-bytevector-output-port proc :optional maybe-transcoder
[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.

Function current-output-port :optional port
Function current-error-port :optional port
[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.

Function make-custom-binary-output-port id write! get-position set-position! close
[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.

Function make-custom-string-output-port id write! get-position set-position! close
[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.

3.14.1.11Binary output

Function put-u8 binary-output-port octet
[R6RS] Writes octet to the output port and returns unspecified values.

Function put-bytevector binary-output-port bytevector :optional start count
[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.

3.14.1.12Textual output

Function put-char textual-output-port char
[R6RS] Writes char to the port and returns unspecified values.

Function put-string textual-output-port string :optional start count
[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.

Function put-datum textual-output-port datum
[R6RS] Datum should be a datum value. The put-datum procedure writes an external representation of datum to textual-output-port.

3.14.1.13Input/output ports

Function open-file-input/output-port filename :optional file-options buffer-mode transcoder
[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.

Function make-custom-binary-input/output-port id read! write! get-position set-position! close :optional (ready #f)
[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.

Function make-custom-textual-input/output-port id read! write! get-position set-position! close :optional (ready #f)
[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.

3.14.2Simple I/O

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.

Function call-with-input-file filename proc . opt
Function call-with-output-file filename proc . opt
[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.

Function with-input-from-file filename thunk . opt
Function with-output-to-file filename thunk . opt
[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.

Function open-input-file filename :key (transcoder (native-transcoder))
Function open-output-file filename :key (transcoder (native-transcoder))
[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.

Function close-input-file port
[R6RS] Closes input-port or output-port, respectively.

Function read-char :optional textual-input-port
Function peak-char :optional textual-input-port
[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.

Function read :optional textual-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.

Function write-char char :optional textual-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.

Function newline :optional textual-input-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.

Function display obj :optional textual-input-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.

Function write obj :optional textual-input-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.

3.15File system

This library, in addition to the procedures described here, also exports the I/O condition types described in I/O condition types.

Function file-exists? filename
[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.

Function delete-file filename
[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.

3.16Command-line access and exit values

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.

Function exit :optional obj
[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.

3.17Arithmetic libraries

This section describes Scheme's libraries for more specialized numerical operations: fixnum and flonum arithmetic, as well as bitwise operations on exact integer objects.

3.17.1Bitwise operations

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.

3.17.2Fixnums

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.

Function fixnum? obj
[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.

Function fx=? fx1 fx2 fx3 ...
Function fx>? fx1 fx2 fx3 ...
Function fx<? fx1 fx2 fx3 ...
Function fx>=? fx1 fx2 fx3 ...
Function fx<=? fx1 fx2 fx3 ...
[R6RS] These procedures return #t if their arguments are: equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing, #f otherwise.

Function fxzero? fx
Function fxpositive? fx
Function fxnegative? fx
Function fxodd? fx
Function fxeven? fx
[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.

Function fxmax fx1 fx2 ...
Function fxmin fx1 fx2 ...
[R6RS] These procedures return the maximum or minimum of their arguments.

Function fx+ fx1 fx2
Function fx* fx1 fx2
[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.

Function fx- fx1 :optional fx2
[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*.

Function fxdiv-and-mod fx1 fx2
Function fxdiv fx1 fx2
Function fxmod fx1 fx2
Function fxdiv0-and-mod0 fx1 fx2
Function fxdiv0 fx1 fx2
Function fxmod0 fx1 fx2
[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.

Function fx+/carry fx1 fx2 fx3
[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))

Function fx-/carry fx1 fx2 fx3
[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))

Function fx*/carry fx1 fx2 fx3
[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))

Function fxnot fx
[R6RS] Returns bitwise not of fixnum fx.

Function fxand fx1 ...
Function fxior fx1 ...
Function fxxor fx1 ...
[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.

Function fxif fx1 fx2 fx3
[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))

Function fxbit-count fx
[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)))

Function fxlength fx
[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.

Function fxbit-set? fx1 fx2
[R6RS] Fx2 must be non-negative and less than (fixnum-width). The fxbit-set? procedure returns #t if the fx2th 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))))

Function fxcopy-bit fx1 fx2 fx3
[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 fx2th 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))

Function fxbit-field fx1 fx2 fx3
[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))

Function fxcopy-bit-field fx1 fx2 fx3 fx4
[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))

Function fxarithmetic-shift fx1 fx2
[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)).

Function fxrotate-bit-field fx1 fx2 fx3 fx4
[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))

Function fxreverse-bit-field fx1 fx2 fx3
[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).

3.17.3Flonums

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.

Function flonum? obj
[R6RS] Returns #t if obj is a flonum, #f otherwise.

Function fl=? fl1 fl2 fl3 ...
Function fl>? fl1 fl2 fl3 ...
Function fl<? fl1 fl2 fl3 ...
Function fl>=? fl1 fl2 fl3 ...
Function fl<=? fl1 fl2 fl3 ...
[R6RS] These procedures return #t if their arguments are (respectively): equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing, #f otherwise.

Function flinteger? fl
Function flzero? fl
Function flpositive? fl
Function flnegative? fl
Function flodd? fl
Function fleven? fl
Function flfinite? fl
Function flinfinite? fl
Function flnan? fl
[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.

Function flmax fl1 fl2 ...
Function flmin fl1 fl2 ...
[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.

Function fl+ fl1 ...
Function fl* fl1 ...
[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.

Function flabs fl
[R6RS] Returns the absolute value of fl.

Function fldiv-and-mod fl1 fl2
Function fldiv fl1 fl2
Function flmod fl1 fl2
Function fldiv0-and-mod0 fl1 fl2
Function fldiv0 fl1 fl2
Function flmod0 fl1 fl2
[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.

Function flnumerator fl
Function fldenominator fl
[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.

Function flfloor fl
Function flceiling fl
Function fltruncate fl
Function flround fl
[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.

Function flexp fl
Function fllog fl1 :optional fl2
Function flsin fl
Function flcos fl
Function fltan fl
Function flasin fl
Function flacos fl
Function flatan fl1 :optional fl2
[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.

Function flsqrt fl
[R6RS] Returns the principal square root of fl. For - 0.0, flsqrt returns 0.0; for other negative arguments, the result unspecified flonum.

Function flexpt fl1 fl2
[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.

Condition Type &no-infinities
Condition Type &no-nans
[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")
    + &no-infinities
    + &no-nans

[R6RS] Returns a flonum that is numerically closest to fx.

3.17.4Exact bitwise arithmetic

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.

Function bitwise-not ei
[R6RS] Returns the exact integer object whose two's complement representation is the one's complement of the two's complement representation of ei.

Function bitwise-and ei1 ...
Function bitwise-ior ei1 ...
Function bitwise-xor ei1 ...
[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.

Function bitwise-if ei1 ei2 ei3
[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.

Function bitwise-bit-set? ei1 ei2
[R6RS] Ei2 must be non-negative. The bitwise-bit-set? procedure returns #t if the ei2th 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)))

Function bitwise-copy-bit ei1 ei2 ei3
[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 ei2th bit of ei1 by the ei2th 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))

Function bitwise-bit-field ei1 ei2 ei3
[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))

Function bitwise-copy-bit-field ei1 ei2 ei3 ei4
[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.

Function bitwise-rotate-bit-field ei1 ei2 ei3 ei4
[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.

Function bitwise-reverse-bit-field ei1 ei2 ei3
[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).

3.18Syntax-case

[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.

Syntax syntax-case expression (literal ...) clause ...
[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.

Syntax syntax template
[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.

Function identifier? obj
[R6RS] Returns #t if obj is an identifier, i.e., a syntax object representing an identifier, and #f otherwise.

Function bound-identifier=? id1 id2
[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.

Function free-identifier=? id1 id2
[R6RS] Id1 and id2 must be identifiers. The free-identifier=? procedure returns #t if given arguments are indicating the same bindings.

Function syntax->datum syntax-object
[R6RS] Strips all syntactic information from a syntax object and returns the corresponding Scheme datum.

Function datum->syntax template-id 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.

Macro with-syntax ((pattern expression) ...) body
[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.

Macro quasisyntax template
Auxiliary Macro unsyntax
Auxiliary Macro unsyntax-splicing
[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.

Function syntax-violation who message form :optional subform
[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.

3.19Hashtables

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.

3.19.1Constructors

Function make-eq-hashtable :optional k weakness
Function make-eqv-hashtable :optional k weakness
[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.

Function make-hashtable hash-function equiv :optional k weakness
[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.

3.19.2Procedures

Function hashtable? obj
[R6RS] Returns #t if obj is a hashtable, #f otherwise.

Function hashtable-size hashtable
[R6RS] Returns the number of keys contained in hashtable as an exact integer object.

Function hashtable-ref hashtable key :optional (default #f)
[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.

Function hashtable-set! hashtable key obj
[R6RS] Changes hashtable to associate key with obj, adding a new association or replacing any existing association for key, and returns unspecified values.

Function hashtable-delete! hashtable key
[R6RS] Removes any association for key within hashtable and returns unspecified values.

Function hashtable-contains? hashtable key
[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.

Function hashtable-update! hashtable key proc default
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. }

Function hashtable-copy hashtable :optional mutable
[R6RS] Returns a copy of hashtable. If the mutable argument is provided and is true, the returned hashtable is mutable; otherwise it is immutable.

Function hashtable-clear hashtable :optional k
[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.

Function hashtable-keys hashtable
Function hashtable-entries hashtable
[R6RS] Returns a vector of all keys or entries in hashtable, respectively. The order of the vector is unspecified.

3.19.3Inspection

Function hashtable-hash-function hashtable
[R6RS] Returns the equivalence or hash function used by hashtable respectively.

Function hashtable-mutable? hashtable
[R6RS] Returns #t if hashtable is mutable, otherwise #f.

3.19.4Hash functions

Function equal-hash obj
Function symbol-hash symbol
[R6RS] Returns hash value of given argument. Each procedures return the hash values suitable for equal? and symbols.
Function string-hash string :optional bound start end
Function string-ci-hash string :optional bound start end
[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.

3.20Enumerations

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.

Function make-enumeration symbol-list
[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.

Function enum-set-universe enum-set
[R6RS] Returns the set of all symbols that comprise the universe of its argument, as an enumeration set.

Function enum-set-indexer enum-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.

Function enum-set-constructor enum-set
[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.

Function enum-set->list enum-set
[R6RS] Returns a list of the symbols that belong to its argument, in the canonical order of the universe of enum-set.

Function enum-set-member symbol enum-set
Function enum-set-subst? enum-set1 enum-set2
Function enum-set=? enum-set1 enum-set2
[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.

Function enum-set-union enum-set1 enum-set2
Function enum-set-intersection enum-set1 enum-set2
Function enum-set-difference enum-set1 enum-set2
[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.

Function enum-set-complement enum-set
[R6RS] Returns enum-set's complement with respect to its universe.

Function enum-set-projection enum-set1 enum-set2
[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.)

Macro define-enumeration type-name (symbol ...) constructor-syntax
[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 ...))
.

3.21Composite libraries

3.21.1eval

[R6RS]The (rnrs eval (6)) library allows a program to create Scheme expressions as data at run time and evaluate them.

Function eval expression environment
[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.

Function environment import-spec ...
[R6RS] Import-spec must be a datum representing an import spec. The environment procedure returns an environment corresponding to import-spec.

3.21.2Mutable pairs

[R6RS] This library exports set-car! and set-cdr!.

Function set-car! pair obj
Function set-cdr! pair obj
[R6RS] Store obj in the car/cdr field of pair. These procedures return unspecified value.

On Sagittarius Scheme, these procedures can modify immutable pairs.

3.21.3Mutable strings

[R6RS] This library exports string-set! and string-fill!.

Function string-set! string k char
[R6RS] K must be a valid index of string.

The string-set! procedure stores char in element k of string and returns unspecified values.

Function string-fill! string char :optional (start 0) (end (string-length string))
[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.

3.21.4R5RS compatibility

This library provides R5RS compatibility procedures such as exact->inexact.

[R6RS] These are the same as the inexact and exact procedures.

Function quotient n1 n2
Function remainder n1 n2
Function modulo n1 n2
[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.

Macro delay expression
[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.

Function force promise
[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.

4R7RS Support

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.

4.1R7RS library system

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.

Syntax define-library name clauses
[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.

4.2R7RS libraries

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'.

4.2.1Base library

[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

4.2.1.1Bytevectors

Function bytevector bytes
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.

Function bytevector-append bytevectors ...
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.

Function bytevector-copy! to at from :optional (start 0) (end (bytevector-length from))
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.

4.2.1.2Lists

Function list-copy obj
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.

Function list-set! list index value
Stores value in element index of list.

Function make-list k :optional fill
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.

4.2.1.3Vectors

Function vector->string vector :optional (start 0) (end (vector-length vector))
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.

Function string->vector string :optional (start 0) (end (string-length string))
Returns a vector whose elements are characters of string in range of start and end (exclusive).
Function vector-append vectors ...
Returns a newly allocated vector whose contents are the concatenation of the contents in vectors.
Function vector-copy vector :optional (start 0) (end (vector-length vector))
Returns a vector whose elements are elements of given vector between start and end.
Function vector-copy! to at from :optional (start 0) (end (vector-length from))
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.

4.2.1.4Strings

Function string-copy! to at from :optional (start 0) (end (vector-length from))
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.

Function string-map proc string strings ...
Calls proc with given strings elements and returns a string whose content is constructed by the results of proc.

4.2.1.5Parameters

Function make-parameter init :optional converter
[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.

Macro parameterize ((param1 value1) ...) body ...
[SRFI-39] A parameterize expression is used to change the values returned by specified parameter objects during the evaluation of body.

4.2.1.6Inclusion

Syntax include file files ...
Syntax include-ci file files ...
files must be strings.

Includes files as if it's written there. include-ci reads files case insensitively.

4.2.1.7Multiple-value definition

Macro define-values formals expression
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.

4.2.1.8Numerical operations
Function exact-integer? obj
Returns #t if obj is exact integer. Otherwise #f.

Function floor/ n1 n2
Function floor-quotient n1 n2
Function floor-remainder n1 n2
Function truncate/ n1 n2
Function truncate-quotient n1 n2
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

Function square z
Returns the square of z.

4.2.1.9Error objects

Macro syntax-error msg forms ...
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 ...)))))

Function error-object? obj
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.

4.2.1.10I/O

Function file-error? obj
Returns #t if obj is a file related condition, otherwise #f.
Function read-error? obj
Renaming export of i/o-read-error?.

Function input-port-open? input-port
Function output-port-open? output-port
Return #t if given input-port or output-port is open, respectively. Otherwise #f.

Function u8-ready? input-port
Renaming export of port-ready?.

Function peek-u8 :optional (input-port (current-input-port))
Function read-u8 :optional (input-port (current-input-port))
input-port must be a binary input port.

Peeks or reads a byte from given input-port.

Function read-bytevector len :optional (input-port (current-input-port))
input-port must be a binary input port.

Reads len from input-port and returns a bytevector.

Function read-bytevector! bv :optional (input-port (current-input-port)) (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.

Function write-u8 u8 :optional (output-port (current-output-port))
u8 must be a byte. output-port must be a binary output port.

Writes u8 to output-port.

Function write-bytevector bv :optional (output-port (current-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.

Function read-line :optional (input-port (current-input-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.

Function read-string k :optional (input-port (current-input-port))
input-port must be a textual input port.

Reads k length of string from input-port.

Function write-string str :optional (output-port (current-output-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.

Function open-input-string string
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.

Function get-output-bytevector output-port
Function get-output-string output-port
Retrieves buffered bytevector or string from given output-ports, respectively.

4.2.1.11System interface

Function features
Returns a list of the feature identifiers which cond-expand treas as true.

4.2.1.12Differ from R6RS

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.

Function equal? a b
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))
=> #f

(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

Macro let-syntax ((var trans) ...) expr ...
Macro letrec-syntax ((var trans) ...) expr ...
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

4.2.2Case-lambda library

[R7RS] This library exports the case-lambda syntax.

Exported macro is the same as R6RS;

case-lambda

4.2.3Char library

[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

Function digit-value c
[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

4.2.4Complex library

[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

4.2.5CxR library

[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

4.2.6Eval library

[R7RS]This library exports exports procedures for evaluating Scheme data as programs.

These procedures are the same as R6RS;

environment eval

4.2.7File library

[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.

4.2.8Inexact library

[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

4.2.9Lazy library

[R7RS]This library exports procedures and syntax keywords for lazy evaluation.

These procedures/macros are the same as R6RS;

delay force make-promise promise?

Macro delay-force expression
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.

4.2.10Load library

[R7RS]This library exports procedures for loading Scheme expressions from files.

Function load file :optional environment
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.

4.2.11Process-Context library

[R7RS] This library exports procedures for accessing with the program's calling context.

These procedures are the same as R6RS; command-line exit

Function emergency-exit :optional obj
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.

4.2.12Read library

[R7RS]This library exports procedures for reading Scheme objects.

Function read :optional port
Renaming export of read/ss.

4.2.13Repl library

[R7RS]This library library exports the interaction-environment procedure.

Returns interaction environment.

4.2.14Time library

[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.

4.2.15Write library

[R7RS]This library exports procedures for writing Scheme objects.

This procedures is the same as R6RS display

Function write obj :optional (output-port (current-output-port))
Writes a representation of obj to output-port.

If the obj contains cyclic, the procedure writes with datum label.

Function write-shared obj :optional (output-port (current-output-port))
Function write-simple obj :optional (output-port (current-output-port))
Renaming export of write/ss and write, respectively.

4.2.16R5RS library

[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.

4.3R7RS-large

R7RS-large makes Scheme specification more practical. It contains lots of useful libraries as well. This section lists supporting R7RS-large libraries.

4.3.1List library

This library exports the procedures and macros defined in SRFI-1 (srfi :1).

4.3.2Vector library

This library exports the procedures and macros defined in SRFI-133 (srfi :133).

4.3.3Sorting library

This library exports the procedures and macros defined in SRFI-132 (srfi :132).

4.3.4Set library

This library exports the procedures and macros defined in SRFI-113 (srfi :113).

4.3.5Character set library

This library exports the procedures and macros defined in SRFI-14 (srfi :14).

4.3.6Hashtable library

This library exports the procedures and macros defined in SRFI-125 (srfi :125).

4.3.7Immutable list library

This library exports the procedures and macros defined in SRFI-116 (srfi :116).

4.3.8Random access list library

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?.

4.3.9Immutable deque library

This library exports the procedures and macros defined in SRFI-134 (srfi :134).

4.3.10Immutable text library

This library exports the procedures and macros defined in SRFI-135 (srfi :135).

4.3.11Generator library

This library exports the procedures and macros defined in SRFI-121 (srfi :121).

4.3.12Lazy sequence library

This library exports the procedures and macros defined in SRFI-127 (srfi :127).

4.3.13Stream library

This library exports the procedures and macros defined in SRFI-41 (srfi :41).

4.3.14Box library

This library exports the procedures and macros defined in SRFI-111 (srfi :111).

4.3.15List queue library

This library exports the procedures and macros defined in SRFI-117 (srfi :117).

4.3.16Ephemeron library

This library exports the procedures and macros defined in SRFI-124 (srfi :124).

4.3.17Comparator library

This library exports the procedures and macros defined in SRFI-128 (srfi :128).

5CLOS

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.

5.1(clos user) -CLOS user APIs

User level CLOS API collection library.

Macro define-class name supers slots . options
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.

Macro define-method name specifiers body ...
Name must be symbol.

Specifiers must be following structure:

specifiers ::= (spec ... rest)
spec ::= (argument-name class) | (argument-name)
rest ::= '() | symbol

Adds defined method to name generic. If the generic does not exist, this will create a new generic function implicitly.

Function slot-ref obj slot-name
Returns the slot value specified slot-name.

Function slot-set! obj slot-name value
Sets the slot value value with specified slot-name.

Function slot-bound? obj slot-name
Returns #t if the slot value specified slot-name is bounded, otherwise #f.

Generic make class args ...
Creates a new instance of class

Function is-a? object class
Returns #t if object is an instance of class, otherwise #f.

Function subtype? class1 class2
Returns #t if class1 is a subclass of class2, otherwise #f.

Function slot-ref-using-accessor object accessor
This procedure is for MOP.

Returns the slot value got by accessor.

Function slot-set-using-accessor! object accessor value
This procedure is for MOP.

Sets the slot value value to object using accessor.

Function slot-ref-using-class class object slot-name
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.

Function slot-set-using-accessor! class object slot-name value
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.

Function slot-bound-using-class? class object slot-name
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.

Generic write-object object (out <port>)
This method will be called when writing the given object.

Defines how user defined class should be written.

Generic object-equal? object1 object2
This method will be called when equal? is called.

Defines how user defined class should be compared.

5.2(clos core) - CLOS core library

Low level CLOS API collection library.

Generic add-method generic method
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.
Function slot-definition-option slot keyword . default
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.

6Sagittarius extensions

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.

6.1(sagittarius) - builtin library

This library has Sagittarius specific functionalities such as extra file system functions and so.

6.1.1Builtin Syntax

Syntax define-constant variable expression
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.

Syntax receive formals expression body
[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.

Syntax cond-expand clauses ...
[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 ...)
  • ((library library-name) body ...)
  • ((and feature-identifier ...) body ...)
  • ((or feature-identifier ...) body ...)
  • (not feature-identifier)
library form 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-identifiers via cond-features procedure.

6.1.2Macro transformer

Proc must be a procedure which accepts 3 arguments, form, rename and compare.

form
The input form of this macro. It is mere s-expression.
rename
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.
compare
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.

6.1.3Arithmetic operations

Function +. z ...
Function *. z ...
Function -. z ...
Function -. z1 z2 ...
Function /. z ...
Function /. z1 z2 ...
The same as +, *, - and /. The difference is these procedures converts given arguments inexact number.

Function mod-inverse x m
x and m must be exact integer.

Returns x ^ -1 mod m

Function mod-expt x e m
x, e and m must be exact integer.

Returns x ^ e mod m

6.1.4File system operations

Function file-size-in-bytes filename
Returns file size of filename in bytes. If filename does not exist, it raises &i/o condition.

Function file-regular? filename
Function file-directory? filename
Function file-symbolic-link? filename
Function file-readable? filename
Function file-writable? filename
Function file-executable? filename
Returns file type or permission of given filename.

Function file-stat-ctime filename
Function file-stat-mtime filename
Function file-stat-atime 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.

Function create-symbolic-link old-filename new-filename
Creates symbolic link of old-filename as new-filename.

Function rename-file old-filename 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.

Function create-directory path
Function delete-directory path
Creates/deletes given directory. If it fails, it raises condition &i/o.

Function read-directory path
Reads directory and returns contents as a string list. If path does not exist, it returns #f.

Function copy-file src dst :optional overwrite
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.

Function current-directory :optional path
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.

Function build-path path1 path2
path1 and path2 must be string.

Concatenate given parameter with platform dependent path separator.

6.1.5Hashtables

Function make-equal-hashtable :optional k weakness
Function make-string-hashtable :optional k weakness
Creates a hashtable.

The same as make-eq-hashtable and make-eqv-hashtable. It uses equal? or string=? as comparing procedure, respectively.

Function hashtable-values hashtable
Returns all hashtable's values. This procedure is for consistancy of hashtable-keys.

Function hashtable-keys-list hashtable
Function hashtable-values-list hashtable
Returns given hashtable's keys or values, respectively.

The R6RS required procedure hashtable-keys and hashtable-values are implemented with these procedures.

Function hashtable-type hashtable
Returns hashtable's hash type as a symbol. The possible return values are eq, eqv, equal, string and general.

Function hashtable-weakness hashtable
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.

6.1.6I/O

Function port-closed? port
Returns #t if given port is closed, otherwise #f.

Function put-u16 out v endian
Function put-s16 out v endian
Function put-u32 out v endian
Function put-s32 out v endian
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.

Function get-u16 in endian
Function get-s16 in endian
Function get-u32 in endian
Function get-s32 in endian
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.

Function read/ss :optional (port (current-input-port))
Function write/ss obj :optional (port (current-output-port))
[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.

Function format port string arg ...
Function format string arg ...
[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.

~mincol,colinc,minpad,padchar,maxcolA
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 ...|
~mincol,colinc,minpad,padchar,maxcolS
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"|
~mincol,padchar,commachar,intervalD
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 ~A directive.

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|

If atmark-flag is given, the sign '+' is printed for the positive argument.

If colon-flag is given, every intervalth 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|
~mincol,padchar,commachar,intervalB
Binary output. The argument is formatted as a binary integer. The semantics of parameters and flags are the same as the ~D directive.
~mincol,padchar,commachar,intervalO
Octet output. The argument is formatted as a octal integer. The semantics of parameters and flags are the same as the ~D directive.
~mincol,padchar,commachar,intervalX
~mincol,padchar,commachar,intervalx
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.

Function port-ready? :optional (port (current-input-port))
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

Function buffered-port port buffer-mode :key buffer
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.

Function make-codec symbol getc putc data
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.

6.1.7Symbols

Function symbol<? symbol1 symbol2 symbols ...
Function symbol<=? symbol1 symbol2 symbols ...
Function symbol>? symbol1 symbol2 symbols ...
Function symbol>=? symbol1 symbol2 symbols ...
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.

6.1.8Keywords

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.

Function make-keyword symbol
Function symbol->keyword symbol
Creates a new keyword from symbol.

Function string->keyword string
Creates a new keyword from string.

Function keyword? obj
Returns #t if obj is keyword, otherwise #f.

Function keyword->symbol keyword
Returns a symbol representation of given keyword keyword.

Function keyword->string keyword
Returns a string representation of given keyword keyword.

Function get-keyword keyword list :optional fallback
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

6.1.9Weak box

A weak box is a reference to an object that doesn’t prevent the object from being garbage-collected.

Function weak-box? obj
Returns #t if obj is weak box otherwise #f.

Function make-weak-box obj
Returns a weak box whose value is obj.

Returns #t if the value of given weak box wb is garbage collocted. Otherwise #f.

Function weak-box-ref wb :optional (fallback #f)
Returns the value of given weak box wb if it's not garbage collocted. Otherwise returns fallback.

Function weak-box-set! wb obj
Replace the value of given wb with obj.

6.1.10Weak vector

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.

Function weak-vector? obj
Returns #t if obj is weak vector otherwise #f.

Function make-weak-vector size
Creates and returns a weak vector of size size.

Returns the length of given weak vector wvec

Function weak-vector-ref wvec k :optional fallback
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.

Function weak-vector-set! wvec k value
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.

6.1.11Weak hashtable

A weak hashtable is a reference 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.

Function make-weak-eq-hashtable :key (init-size 200) (weakness 'both) default
Function make-weak-eqv-hashtable :key (init-size 200) (weakness 'both) default
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.

Function weak-hashtable-ref weak-hashtable key :optional (default #f)
Returns the value in weak-hashtable associated with key. If weak-hashtable does not contain an association for key, default is returned.

Function weak-hashtable-set! weak-hashtable key obj
Changes weak-hashtable to associate key with obj, adding a new association or replacing any existing association for key, and returns unspecified values.

Function weak-hashtable-delete! weak-hashtable key
Removes any association for key within weak-hashtable and returns unspecified values.

Function weak-hashtable-keys-list weak-hashtable
Function weak-hashtable-values-list weak-hashtable
Returns a list of keys and values in the given weak-hashtable, respectively.

Function weak-hashtable-copy weak-hashtable
Returns a copy of weak-hashtable.

Function weak-hashtable-shrink weak-hashtable
Shrink the given weak-hashtable and returns the number of removed entry. This is only for GC friendliness.

6.1.12Bytevector operations

Function bytevector->sinteger bytevector :optional start end
Function bytevector->uinteger bytevector :optional start end
Function bytevector->integer bytevector :optional start end
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.

Function sinteger->bytevector ei :optional size
Function uinteger->bytevector ei :optional size
Function integer->bytevector ei :optional size
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 integer.

(integer->bytevector #x12345678 5)
=> #vu8(#x00 #x12 #x34 #x56 #x78)
(integer->bytevector #x12345678 3)
=> #vu8(#x34 #x56 #x78)

Function bytevector-append bvs ...
Returns a newly allocated bytevector that contains all elements in order from the subsequent locations in bvs ....

Function bytevector-concatenate list-of-bytevectors
Appends each bytevectors in list-of-bytevectors. This is equivalent to:

(apply bytevector-append list-of-bytevectors)

6.1.13List operations

Function circular-list? list
Function dotted-list? list
[SRFI-1] Returns #t if list is circular or dotted list, respectively. Otherwise #f.

Function acons obj1 obj2 obj3
Returns (cons (cons obj1 obj2) obj3). Useful to put an entry at the head of an associative list.

Function append! 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.

Function reverse! list ...
[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.

6.1.14Vector operations

Function vector-copy vector :optional start end fill
[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.

Function vector-append vector ...
[SRFI-43] Returns a newly allocated vector that contains all elements in order from the subsequent locations in vector ....

Function vector-concatenate list-of-vectors
[SRFI-43] Appends each vectors in list-of-vectors. This is equivalent to:

(apply vector-append list-of-vectors)

Function vector-reverse vector :optional start end
Function vector-reverse! vector :optional start end
[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.

6.1.15String operations

Function string-scan string item :optional return
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).

Function string-concatenate list-of-strings
[SRFI-13] Appends each strings in list-of-strings. This is equivalent to:

(apply string-append list-of-strings)

Function istring? obj
Returns #t if the given obj is an immutable string, otherwise #f.

Immutable strings are one of the followings:

  • String literals. (c.f. "abc")
  • Strings converted to immutable string by string->istring

Function string->istring string :optional start end
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.

6.1.16Load path

Function add-load-path path :key (append #f)
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.

Function add-load-suffix suffix :key (append #f)
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.

Function load-path
Function load-path paths
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.

6.1.17System and platform

Function uname
Return a vector which contains the following information.

System name
Operating system name. E.g. "Linux"
Node name
The name of the computer.
Release
Release number of the system if availabel.
Version
Version number of the system if availabel.
Machine
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).

Function get-mac-address :optional (position 0)
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.

Function get-thread-times :optional thread
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.

Function gc
Invokes garbage collection manually.

Function cpu-count
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.

6.1.18Debugging aid

Function disasm closure
Disassembles the compiled body of closure and print it.

Function arity procedure
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.

Library (time)
Exports time macro

Macro time expr
Evaluate expr and shows time usage.

The macro return the result of expr.

6.2(sagittarius control) - control library

This library provides some useful macros using Sagittarius specific functions.

Macro define-macro name procedure
Macro define-macro (name . formals) body ...
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 ...))

Macro let-optionals* restargs (var-spec ...) body ...
Macro let-optionals* restargs (var-spec ... . restvar) 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.

Macro get-optionals restargs default
Macro get-optionals restargs default test
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.

Macro let-keywords restargs (var-spec ...) body ...
Macro let-keywords restargs (var-spec ... . restvar) body ...
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))

Macro let-keywords* restargs (var-spec ...) body ...
Macro let-keywords* restargs (var-spec ... . restvar) body ...
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.

Macro define-with-key variable expression
Macro define-with-key variable
Macro define-with-key (variable formals) body ...
Macro define-with-key (variable . formals) body ...
The define-with-key is synonym of define.

See more detail Variable definitions.

Macro begin0 exp0 exp1 ...
Evaluate exp0, exp1, ..., then returns the result(s) of exp0.

Macro let1 var expr body ...
A convenient macro when you have only one variable. Expanded as follows:
(let ((var expr)) body ...)

Macro rlet1 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)

Macro dotimes (variable limit [result]) body ...
Macro dolist (variable lexpr [result]) body ...
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))

Macro push! place item
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!.

Macro pop! place
Retrieves the value of place, sets its cde back to place.

Macro check-arg pred val proc
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.

Macro with-library library exprs ...
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.

Macro unwind-protect body cleanups ...
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.

Macro datum x
Short form of syntax->datum.

Macro with-syntax* ((p e0) ...) e1 e2 ...
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.

Macro ^ formals body ...
The alias of lambda.

Macro ^c body ...
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)

Macro ^c* body ...
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))

6.3(sagittarius ffi) - Foreign Function Interface

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;

;; 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)

;; End of Scheme file

/* 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;
}

=> #vu8(1 2 3 4 5 6 7 8 9)
The document describes higher APIs to lower APIs.

6.3.1Shared library operations

Function open-shared-library file :optional (raise #f)
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.

Function close-shared-library pointer
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.

6.3.2Creating C functions

This section describes more details to create a corresponding C functions.

Macro c-function shared-library return-type name (argument-types ...)
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;
Scheme string
Converts to UTF-8 C char*
Scheme bytevector
Convert to C char*
Scheme FFI pointer
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.

Function make-c-function shared-library return-type name argument-types
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.

Macro address pointer
Macro address pointer offset
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.

Macro c-callback return-type (argument-types ...) proc
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.

Macro make-c-callback return-type argument-types proc
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.

Function free-c-callback callback
Release callback.

6.3.3Pointer operations

Using C functions, users can not avoid to use raw pointers. This section describes how to create or convert a pointer.

Function pointer? obj
Returns #t if obj is FFI pointer object, otherwise #f.

Function integer->pointer integer
Converts given integer to pointer object.

To represents NULL pointer, you can write like this;

(integer->pointer 0)
=> #<pointer 0x0>

Function pointer->integer pointer :optional bits
Function pointer->uinteger pointer :optional bits
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.

Function pointer->string pointer :optional (transcoder (native-transcoder))
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.

Function pointer->bytevector pointer size :optional (offset 0) (shared #t)
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.

Function bytevector->pointer bv :optional (offset 0) (shared #t)
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.

Function pointer->object pointer
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.

Function deref pointer offset
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.

Function pointer-address pointer :optional offset
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.

Function allocate-pointer size :optional (fill 0)
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.

Function c-malloc size
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.

Function c-free pointer
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.

Function null-pointer? obj
Returns #t when obj is a pointer representing NULL otherwise #f.

Creates a NULL pointer. This is for convenience.

Function pointer-ref-c-type pointer offset
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.

Function pointer-set-c-type! pointer offset value
offset must be a fixnum.

Sets value to offset offset of pointer. Supporting types 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))))))

Function set-pointer-value! pointer value
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!

6.3.4C struct operations

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.

Macro define-c-struct name clauses ...
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.

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!

Function size-of-c-struct struct
struct must be a C structure defined by define-c-struct.

Returns the size of given struct.

Function allocate-c-struct struct
Allocates memory for struct and returns a pointer.

Function struct-name-member-name-ref struct-pointer inner-member-names ...
Function struct-name-member-name-set! struct-pointer value inner-member-names ...
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)

6.3.4.1Low level C struct accessors

Function c-struct-ref pointer struct name
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.

Function c-struct-set! pointer struct name value
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.

6.3.5Typedef operations

Macro define-c-typedef original new-names ...
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*)
)

6.3.6Sizes and aligns

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.

6.3.7Finalizer operations

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.

Function register-ffi-finalizer pointer proc
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.

6.4(sagittarius filewatch) - Monitoring filesystem

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))))

Function make-filesystem-watcher :key error-handler
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.

Function filesystem-watcher-add-path! watcher path flags monitoring-handler
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.

Function filesystem-watcher-start-monitoring! watcher :key (background #t)
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.

6.4.1Implementation limitation

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.

6.4.1.1Linux

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.

6.4.1.2BSD Unix

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.

6.4.1.3OS X

On OS X, the library is constructed on top of kqueue, thus the same limitation as BSD Unix is applied.

6.4.1.4Windows

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.

6.5(sagittarius io) - Extra IO library

This library provided extra IO related procedures.

Function with-input-from-port port thunk
Function with-output-to-port port thunk
Function with-error-to-port port thunk
Calls thunk. During evaluation of thunk, the current input port, current output port, current error port are set to port, respectively.

Function call-with-input-string str proc
Function with-input-from-string str thunk
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)))

Function buffered-port port buffer-mode :key buffer
Function transcoded-port port transcoder
Re-export of buffered-port and transcoded-port.

6.5.1Custom ports

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:

Slot id
Identifier of the port. Must be string is specified.
Slot read
Slot write
Slot flush
Slot close
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 andwhence. 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.

6.6Sagittarius MOP

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.

6.6.1(sagittarius mop allocation)

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>)

6.6.2(sagittarius mop validator)

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.

6.6.3(sagittarius mop eql)

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.

6.7(sagittarius object) - Convenient refs and coercion procedures

This library provides convenient procedures.

Generic ref object key args ...
Generic (setter ref) object key value
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

Generic ->string object
Returns string represented object.

Generic ->integer object
Returns integer represented object.

Generic ->number 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.

6.8(sagittarius process) - Process library

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.

6.8.1High level APIs

Function run name arg1 ...
Function call name arg1 ...
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.

6.8.2Middle level APIs

Function create-process name args :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.

Function async-process-read process stdout stderr transcoder
Process output reader. This reader creates 2 threads to read standard ouput and standard error. The reader returns immediately after the threads are executed.

Function sync-process-read process stdout stderr transcoder
Process output reader. This reader creates 2 threads to read standard ouput and standard error. The reader waits until the given process is finished.

6.8.3Low level APIs

This section describe low level APIs however some of these might be used even if you use call described above.

Function process? obj
Returns #f if obj is process object, otherwise #f.

Function make-process name args
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.

Function process-input-port process
process must be a process object.

Returns the binary output port which is redirected to the process' standard input.

Function process-output-port process
process must be a process object.

Returns the binary input port which is redirected to the process' standard output.

Function process-error-port process
process must be a process object.

Returns the binary input port which is redirected to the process' standard error.

Function process-run process
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.

Function process-call process
process must be a process object.

Invokes the process and continue the Scheme program.

Function process-wait process :key timeout
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.

Function process-kill process :key children?
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).

Function process-active? process
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.

Function getpid
Returns pid of current Sagittarius process. The returning value is an integer.

Function pid->process pid
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.

6.8.4Inter-process communication (IPC)

Users can choose how to communicate processes. One of the typical ways is using socket. (sagittarius process) provides shared memory for simple IPC.

Function shared-memory? obj
Returns #t if given obj is a shared memory object, otherwise #f.

Function open-shared-memory name size :optional option
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.

Function close-shared-memory shared-memory
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.

Function shared-memory->bytevector shared-memory
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).

6.9(sagittarius reader) - reader macro library

Unlikely, Sagittarius provides functionalities to modify its reader like Common Lisp. It makes Sagittarius programable. However it has some restriction to use. The following examples explain it.

Using reader macro

;;#<(sagittarius regex)>       ;; this imports only reader macros
                               ;; This form is only for backward compatibility
;; portable way for other R6RS implementation's reader.
#!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.

Macro define-reader-macro char (name args ...) body ...
Macro define-reader-macro name char proc
Macro define-reader-macro name char proc non-term?

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.

Macro define-dispatch-macro name char subchar proc
Macro define-dispatch-macro name char proc subchar non-term?
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.

Function set-macro-character char proc :optional non-term?
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.

Function make-dispatch-macro-character char :optional non-term?
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.

Function get-dispatch-macro-character char subchar
Returns a procedure which is associated with char and subchar as a reader macro. If nothing is associated, it returns #f.

Function set-dispatch-macro-character char subchar proc
Sets proc as a reader of subchar under the dispatch macro character of char.

Function read-delimited-list char :optional (port (current-input-port))
Reads a list until given char appears.

6.9.1Predefined reader macros

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 described below.
#!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
The same as #< name > but this is more for compatibility. name must be converted with the naming convention described below. For more details, see Naming convention
#\v Checks if the next 2 characters are u and 8 and reads a bytevector.
#\u Only compatible mode. Checks if the next character is 8 and reads a 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.
#\< Reads expressions until '>' and imports reader macro from it. Note: if expressions contains symbol, which is illegal library name, at the end #<-reader can not detect the '>' because '>' can be symbol. So the error message might be a strange one.

6.9.1.1#! - Switching mode

Sagittarius has multiple reader and VM modes and users can switch these modes with #!. Following describes details of those modes;

R6RS mode
Symbols are read according to R6RS specification and VM sets the no-overwrite 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 mode
The 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 mode
This 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 #< (...) > form and let reader read 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

6.9.2Replacing reader

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.

6.9.2.1Naming convention

The naming convention is really easy. For example, replacing with (srfi :49), first remove all parentheses or brackets then replace spaces to /.

Macro define-reader name expr
Macro define-reader (name port) expr ...
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.

6.10(sagittarius record) - Extra record inspection library

This library provides extra record operations.

Function record-type? obj
Returns #t if obj is record type, otherwise #f.

Function make-record-type name rtd rcd
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.

Function record-type-rtd record-type
Record-type must be record type.

Returns associated rtd from record-type.

Function record-type-rtd record-type
Record-type must be record type.

Returns associated rcd from record-type.

Note: These procedures are not for using casually.

6.11(sagittarius regex) - regular expression library

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.

6.11.1User level APIs for regular expression

Function regex string :optional flags
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](subtraction)
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.

Reader Macro #/-reader
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).

Function looking-at regex string
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.

Function regex-replace-first pattern text replacement
Function regex-replace-first matcher replacement
Function regex-replace-all pattern text replacement
Function regex-replace-all matcher replacement
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.

Function string-split text pattern
text must be a string.

pattern must be a string or regex-pattern object.

Split text accoding to pattern.

6.11.2Low level APIs for regular expression

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.

Function regex-pattern? obj
Returns #f if obj is regular expression object, otherwise #f.

Function regex-matcher? obj
Returns #f if obj is matcher object, otherwise #f.

Function compile-regex string :optional flags
The same as regex procedure.

Function regex-matcher regex string
Regex must be regular expression object. Returns matcher object.

Function regex-matches matcher
Matcher must be matcher object. Returns #t if matcher matches the entire input string against input pattern, otherwise #f.

Function regex-looking-at matcher
Matcher must be matcher object. Returns #t if matcher matches the input string against input pattern, otherwise #f.

Function regex-find matcher :optional start
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.

Function regex-group matcher index
Matcher must be matcher object. Index must be non negative exact integer.

Retrieve captured group value from matcher.

Function regex-capture-count matcher
Matcher must be matcher object.

Returns number of captured groups.

6.11.3Regular expression flags

Regular expression compiler can take following flags.

CASE-INSENSITIVE
Enables case-insensitive matching. i as a flag
COMMENTS
Permits whitespace and comments in pattern. x as a flag
MULTILINE
Enables multiline mode. m as a flag
LITERAL
Enables literal parsing of the pattern.
DOTAIL
Enables dotall mode. s as a flag
UNICODE
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.

6.11.4Regular expression for bytevectors

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.

6.12(sagittarius socket) - socket library

This section describes low level socket API on Sagittarius. The APIs are mostly the same signature as Ypsilon and mosh. 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.

Function make-client-socket node srvice :opational (ai_family AF_INET) (ai_socktype SOCK_STREAM) (ai_flags (+ AI_V4MAPPED AI_ADDRCONFIG)) (ai_protocol 0)
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

Function make-server-socket service :optional (ai_family AF_INET) (ai_socktype SOCK_STREAM) (ai_protocol 0)
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.

Function socket? obj
Returns #t if obj is socket object, otherwise #f.

Function socket-port socket :optional (close? #t)
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.

Function socket-input-port socket
Function socket-output-port socket
[SRFI-106] Socket must be a socket object. Returns a binary input and output port associated with socket, respectively.

Function call-with-socket socket proc
Socket must be a socket object. Proc must accept one argument.

The call-with-socket calls a procedure with socket as an argument.

This procedure is analogy with call-with-port.

Function shutdown-port port how
Port must be associated with a socket.

Shutdowns associated port according to how.

Port must be associated with a socket.

The shutdown-output-port and shutdown-input-port shutdown output or input connection of a socket associated with port respectively.

Function socket-accept socket
Socket must be a socket object created by make-server-socket.

Wait for an incoming connection request and returns a fresh connected client socket.

This procedures is a thin wrapper of POSIX's accept(2).

If the calling thread is interrupted by thread-interrupt!, then the procedure returns #f.

Function socket-recv socket size :optional (flags 0)
Socket must be a socket object.

Receives a binary data block from given socket. If zero length bytevector is returned, it means the peer connection is closed.

This procedures is a thin wrapper of POSIX's recv(2).

Function socket-send socket bytevector :optional (flags 0)
Socket must be a socket object.

Sends a binary data block to given socket and returns the sent data size.

This procedures is a thin wrapper of POSIX's send(2).

Function socket-shutdown socket how
Socket must be a socket object. How must be one of the SHUT_RD, SHUT_WR or SHUT_RDWR.

The socket-shutdown shutdowns socket.

SHUT_RD
shutdowns input.
SHUT_WR
shutdowns output.
SHUT_RDWR
shutdowns input and output.

Function socket-close socket
Socket must be a socket object. Closes socket.

6.12.1Socket information

The socket information immutable class. This class has 3 slots

This slot has string value represents own or peer socket host.
This slot has ip-address object of own or peer socket.
Slot port
This slot has integer value of own or peer socket port number.

Function socket-peer socket
Socket must be a socket object.

Returns socket info object or #f. The socket info object contains hostname, IP address and port number. These information is retrieved from getpeername(2).

Function socket-name socket
Socket must be a socket object.

Returns the name string of socket or #f if the socket doesn't have name.

Function socket-info socket
Socket must be a socket object.

Returns socket info object or #f. The socket info object contains hostname, IP address and port number. These information is retrieved from getsockname(2).

Function socket-info-values socket :key (type 'peer)
Socket must be a socket object.

Returns 3 values; hostname, IP address and port number. This procedures is for convenience to handle socket info object.

The keyword argument specifies which socket info it should retrieve. If the type is peer then it uses socket-peer. If it is info, then it uses socket-info

6.12.2IP address operations

ip must be an IP address object returned from the second value of socket-info-values.

Converts given IP address object to human readable string.

ip must be an IP address object returned from the second value of socket-info-values.

Converts given IP address object to bytevector.

6.12.3Low level APIs

The low level socket APIs are almost compatible with BSD socket.

6.12.3.1Socket

Function socket-sendto socket bvtevector sockaddr :optional (flags 0)
Sends a binary data block to given sockaddr and returns the sent data size.

This procedures is a thin wrapper of POSIX's sendto (2).

Function socket-recvfrom socket sockaddr :optional (flags 0)
Receives a binary data block from given sockaddr. If zero length bytevector is returned, it means the peer connection is closed.

This procedures is a thin wrapper of POSIX's recvfrom (2).

Function make-socket ai-family ai-socktype ai-protocol
Creates socket object. The procedure returns #f if it couldn't create a socket. SO_NOSIGPIPE socket option is set to the created socket.

This procedure is a thin wrapper of socket (2).

Function socket-connect! socket addrinfo
Initiate connection on the given socket with given addrinfo addrinfo.

This procedure is a thin wrapper of connect (2).

Function socket-bind! socket addrinfo
Binds a name to the given socket socket with given addrinfo addrinfo.

This procedure is a thin wrapper of bind (2).

Function socket-listen! socket backlog
Listen for connections on the given socket socket.

This procedure is a thin wrapper of listen (2).

Function socket-setsockopt! socket level name value
Sets socket option on the given socket socket.

level must be an integer and should be one of the followings:

  • SOL_SOCKET
  • SOL_TCP
  • SOL_IP

name must be an integer and should be one of the followings:

  • SO_ACCEPTCONN
  • SO_BINDTODEVICE
  • SO_BROADCAST
  • SO_DEBUG
  • SO_DONTROUTE
  • SO_ERROR
  • SO_KEEPALIVE
  • SO_LINGER
  • SO_OOBINLINE
  • SO_PASSCRED
  • SO_PEERCRED
  • SO_PRIORITY
  • SO_RCVBUF
  • SO_RCVLOWAT
  • SO_RCVTIMEO
  • SO_REUSEADDR
  • SO_REUSEPORT
  • SO_SNDBUF
  • SO_SNDLOWAT
  • SO_SNDTIMEO
  • SO_TIMESTAMP
  • SO_TYPE
  • TCP_NODELAY
  • TCP_MAXSEG
  • TCP_CORK
  • IP_OPTIONS
  • IP_PKTINFO
  • IP_RECVTOS
  • IP_RECVTTL
  • IP_RECVOPTS
  • IP_TOS
  • IP_TTL
  • IP_HDRINCL
  • IP_RECVERR
  • IP_MTU_DISCOVER
  • IP_MTU
  • IP_ROUTER_ALERT
  • IP_MULTICAST_TTL
  • IP_MULTICAST_LOOP
  • IP_ADD_MEMBERSHIP
  • IP_DROP_MEMBERSHIP
  • IP_MULTICAST_IF

The value must be either bytevector or integer.

This procedure is a thin wrapper of setsockopt (2).

Function socket-getsockopt socket level name size
Gets socket option on the given socket socket.

The level and name are the same as socket-setsockopt!.

size must be an integer. If the value is positive number, then the returning value is a bytevector whose element count is size and contains the socket option converted to byte array. Otherwise it returns an integer value.

Function socket-nonblocking! socket
Function socket-blocking! socket
Converts given socket to nonblocking socket and blocking socket, respectively.

Function socket-select rfds wfds efds timeout
Function socket-select! rfds wfds efds timeout
Monitor given fdset.

rfds, wfds and efds must be fdset object.

timeout must be #f, integer, time object or pair of integers. If this value is not #f, then the procedure waits only specified amount of time or something interesting happens. Otherwise infinite time or something interesting happens.

This procedure blocks the calling thread, and it can be interrupted by thread-interrupt!.

This procedure is a thin wrapper of select (2).

Function socket-read-select timeout sockets ...
Function socket-write-select timeout sockets ...
Function socket-error-select timeout sockets ...
Waits until the given sockets sockets have something interesting. This is the convenient procedure for socket-select.

timeout is the same as socket-select.

socket-read-select can be used to detect if the given sockets have readable data.

socket-write-select can be used to detect if the given sockets are still active.

socket-error-select can be used to detect if the given sockets are readable data. This procedure might not be so interesting since it can be done by socket-read-select.

6.12.3.2Addrinfo

Function addrinfo? obj
Returns #t if given obj is an addrinfo, otherwise #f.

Creates empty addrinfo object.

The object has the following slots:

  • family
  • socktype
  • flags
  • protocol
  • sockaddr
  • next

Function make-hint-addrinfo family socktype flags protocol
Creates an addrinfo with given flags. This can be used as hint for get-addrinfo.

Function get-addrinfo addrinfo
Gets addrinfo of given hint addrinfo.

When the procedure fails, then &i/o is raised.

This procedure is a thin wrapper of getaddrinfo (3).

Function next-addrinfo addrinfo
Retrieves next addrinfo of given addrinfo if availalbe, otherwise returns #f.

Function addrinfo-sockaddr addrinfo
Retrieves sockaddr slot of given addrinfo.

The returning value can be used socket-recvfrom and socket-sendto.

Function sockaddr? obj
Returns #t if given obj is an sockaddr object, otherwise #f.

6.12.3.3FD sets

Function fdset? obj
Returns #t if given obj is a fdset object, otherwise #f.

Function make-fdset
Creates a empty fdset object.

Function sockets->fdset sockets
Creates a fdset from given socket list sockets.

Function fdset-ref fdset socket
Returns #t if the given socket is set to fdset, otherwise #f.

Function fdset-set! fdset socket flag
Sets/unsets the given socket socket on fdset.

If the flags is #f, then the procedure unsets the socket.

If the flags is #t, then the procedure sets the socket.

Function collect-sockets fdset
Returns a list of socket which are set on fdset.

6.12.3.4Socket conditions

Above APIs may raise either &socket or &host-not-found. The first condition is raised when socket related operation failed, for example socket-send. The latter condition is raised when get-addrinfo is failed.

NOTE: make-client-socket and make-server-socket may raise &host-not-found when the given node or service is not a valid value.

The condition hierarchy is the following:

&i/o
 + &host-not-found (node service)
 + &socket (socket)
    + &socket-connection
    + &socket-closed
    + &socket-port (port)

Condition Type &host-not-found
Function make-host-not-found-error node service
Function host-not-found-error-node host-not-found
Function host-not-found-error-service host-not-found
This condition describes the combination of node and service does not exist.

Condition Type &socket
Function socket-error? obj
Function make-socket-error socket
Function socket-error-socket socket-error
This condition describes general socket operation error.

Condition Type &socket-connection
This condition describes socket connection error.

Condition Type &socket-closed
This condition describes socket closed error.

Condition Type &socket-port
Function make-socket-port-error socket port
Function socket-error-port socket-port-error
This condition describes error of socket port operation. Particularly, when port-ready procedure is called on socket port and select (2) failed.

NOTE: Read or write failure of socket port raises &i/o-read or &i/o-write the same as other ports for compatibility.

NOTE2: This condition may be signalled when get-bytevector-all is called on socket port since it checks whether or not the given port is ready.

6.13(sagittarius threads) - Thread

The library provides thread related procedures. The procedures provided this library is based on SRFI-18 Multithreading support and Sagittarius specific procedures.

6.13.1Thread APIs

Function thread? obj
[SRFI-18] Returns #t if given obj is a thread, otherwise #f.

[SRFI-18] Returns the current thread.

Function make-thread thunk :optional name
[SRFI-18] Returns a new thread. The created thread is not executed. To run it, users must explicitly call the thread-start! procedure.

The optional argument name gives the thread a name. The name can be retrieved calling thread-name procedure. If the argument is not given, then the make-thread procedures creates an unique name.

Function thread-name thread
[SRFI-18] Returns the name of thread.

Function thread-state thread
Returns the current state of thread.

Function thread-specific thread
[SRFI-18] Returns the content of the thread's specific slot.

Function thread-specific-set! thread obj
[SRFI-18] Stores obj into the thread's specific slot and returns unspecified value.

Function thread-start! thread
[SRFI-18] Executes the given thread and returns thread

[SRFI-18] The current thread exits the running state if its quantum had expired.

Function thread-sleep! timeout
[SRFI-18] The current thread waits until the timeout is reached.

timeout must be either a time object or an exact integer. The first case, it represents absolute time of the future. The latter case represents second from current time.

Function thread-terminate! thread
[SRFI-18] Causes an abnormal termination of the thread. If the thread is not already terminated, all mutexes owned by the thread become unlocked/abandoned and a "terminated thread exception" object is stored in the thread's end-exception field. If thread is the current thread, thread-terminate! does not return. Otherwise thread-terminate! returns an unspecified value; the termination of the thread will occur before thread-terminate! returns.

Function thread-join! thread :optional timeout timeout-val
[SRFI-18] The current thread waits until the thread terminates (normal or not) or until the timeout is reached if timeout is specified. If the timeout is reached, thread-join! returns timeout-val if it is supplied, otherwise a "join timeout exception" is raised. If the thread terminated normally, the content of the end-result field is returned, otherwise the content of the end-exception field is raised.

Function thread-suspend! thread :optional timeout timeout-val
Suspends execution of the thread. Users can resume the thread by calling thread-resume!.

Function thread-resume! thread
Resumes execution of the thread.

If the caller thread is not the one stopped the target thread, then the procedure raises an error.

Function thread-interrupt! thread
Interrupts blocking system call.

This procedure causes EINTR and cancels blocking system call such as select (2). Currently the only relevant procedure for this is socket-select related procedures. See socket library - Low level APIs.

Currently the procedure uses SIGALRM on POSIX environment. This might be changed in future, so do not depend on the signal to interrupt the call from outside of Sagittarius process.

On Windows, the procedure uses combination of WSAEventSelect and WaitForMultipleObjects. So there is no way to interrupt from outside of Sagittarius process.

6.13.2Mutex APIs

Function mutex? obj
[SRFI-18] Returns #t if given obj is a mutex, otherwise #f.

Function make-mutex :optional name
[SRFI-18] Returns a new mutex.

The optional argument name gives the mutex a name. If it's not specified, then the procedure makes an unique name.

Function mutex-name mutex
[SRFI-18] Returns the name of given mutex.

Function mutex-specific mutex
[SRFI-18] Returns the content of specific slot of given mutex.

Function mutex-specific-set! mutex obj
[SRFI-18] Stores the obj to given mutex's specific slot.

Function mutex-state mutex obj
[SRFI-18] Returns the state of given mutex.

Function mutex-lock! mutex :optional timeout thread
[SRFI-18] Locks the given mutex. If the mutex is currently locked, the current thread waits the mutex is unlocked or until the timeout is reached. If timeout is reached, the procedure returns #f.

Function mutex-unlock! mutex :optional cv timeout
[SRFI-18] Unlocks the given mutex. If condition variable cv is specified, the current thread is blocked and added to the cv before unlocking mutex, the thread can unblock at any time but no later than when an appropriate call to condition-variable-signal! or condition-variable-broadcast! is performed, and no later than the timeout, if it's given.

6.13.3Condition variable APIs

[SRFI-18] Returns #t if given obj is a condition variable, otherwise #f.

Function make-condition-variable :optional name
[SRFI-18] Returns a new condition variable.

The optional argument name gives the condition variable a name. If it's not specified, then the procedure makes an unique name.

[SRFI-18] Returns the name of given cv.

[SRFI-18] Returns the content of specific slot of given cv.

[SRFI-18] Stores the obj to given cv's specific slot.

[SRFI-18] If there are thread blocked on cv, the scheduler selects a thread and unblocks it.

[SRFI-18] Unblocks all the threads blocked on the cv.

6.13.4Semaphore APIs

Function semaphore? obj
Returns #t if given obj is a semaphore, otherwise #f.

Function make-semaphore name initial
Creates a new semaphore with initial count initial

name must be either #f or string which represents semaphore name. If the value is #f, then the returning semaphore is memory based semaphore.

initial must be non negative integer.

If there is already the semaphore has the same name, then this procedure returns that semaphore instead of creating new one.

Function open-semaphore name
Opens semaphore which has name.

If there is no such semaphore, then the procedure raises &i/o-file-does-not-exist.

Function semaphore-name semaphore
Returns the name of given semaphore.

Function semaphore-wait! semaphore :optional timeout
Locks the semaphore. If the current count of semaphore is 0, then the procedure waits.

The optional argument timeout is specified, which it must be #f, integer or time object, then the procedure only waits the given timeout amount. #f means inifinite.

Function semaphore-post! semaphore
Unlock the semaphore. This procedure increase the count of semaphore.

Function semaphore-close! semaphore
Closes the semaphore.

Function semaphore-destroy! semaphore
Removes the semaphore.

NOTE: the semaphore-close! and semaphore-destroy! behaves the same on Windows.

6.14(sagittarius timezone) - Timezone

This library provides timezone related procedures. The timezone database is from IANA - Time Zone Database.

Function timezone? obj
Returns #t if given obj is a timezone object, otherwise #f.

Function timezone name
Retrieves timezone object related to name. The name must be a string and proper name of TZID such as Europe/Amsterdam. If the given name is not found, then GMT is returned as the fallback.

Function timezone-offset tz :optional when
Returns give offset of timezone tz.

If optional argument when is specified, it must be a time object, then the offset is calculated the specified time. Otherwise current-time, is used.

This procedure considers daylight saving time (DST). Means, if the timezone has DST, then the return value is depending on the when. For example, Europe/Amsterdam has DST so if the when is in DST, then the returning offset is 7200, otherwise 3600.

Function timezone-dst? tz :optional (when (current-time))
Returns #t if when is in DST, otherwise #f.

Function timezone-short-name tz :optional (when (current-time))
Returns the short name of given timezone tz.

This procedure considers DST. Means if when is in DST, then short name is DST name, otherwise standard name. For example, timezone Europe/Amsterdam has 2 names, CET and CEST. If the given when is in DST, then CEST is returned, otherwise CET is returned.

Function timezone-raw-offset tz :optional when
Returns GMT offset of given timezone tz.

If optional argument when is given and must be a time object, then the returning offset is the historical offset. If it's not given, then the procedure reutnrs current timezone offset.

Above procedures also considers when the timezone is started. Means, given timezone has histories, such as when the daylight saving time is starting or ending, when that timezone started, etc. It may return different value according to the when. Following is the example of timezone history:

(let ((tz (timezone "Europe/Dublin"))
      (now (date->time-utc (make-date 0 0 0 0 24 7 2015 0)))
      ;; 1:00	-	IST	1971 Oct 31  2:00u
      (no-rule-past (date->time-utc (make-date 0 0 0 0 24 7 1971 0)))
      ;; 0:00	GB-Eire	GMT/IST	1968 Oct 27
      (rule-past (date->time-utc (make-date 0 0 0 0 24 7 1968 0))))
  (timezone-short-name tz now)          ;; => "GMT/IST"
  (timezone-short-name tz no-rule-past) ;; => "IST

  ;; no DST
  (timezone-offset tz no-rule-past)     ;; => 3600 

  (timezone-raw-offset tz)              ;; => 0
  (timezone-raw-offset tz no-rule-past) ;; => 3600
  (timezone-raw-offset tz rule-past)    ;; => 0

  (timezone-short-name tz rule-past)    ;; => "GMT/IST"
  )

Function timezone-name tz
Returns TZID of given timezone tz.

Returns supported TZIDs.

6.15(sagittarius debug) - Debugging support

This library provides debugging support reader macro.

Reader Macro #?= expr
This reader macro reads the next expression as followings;

(debug-print expr)

debug-print is an internal macro of this library which prints the read expression and its result.

Following example shows how to enable this;

#!read-macro=sagittarius/debug
#!debug
(let ((a (+ 1 2)))
  #?=(expt a 2))

#|
#?=(expt a 2)
#?-    9
|#

#!debug enables the debug print.

Function macroexpand expr
Expands given expr. The returning value may or may not be used as proper Scheme expression.

Function macroexpand-1 expr
Function macroexpand-n expr n
Expands given expr n times. The first form's n is 1.

This procedure expands only globally defined macro and the result of expansion is other macro such as next rule of syntax-rules. It doesn't consider locally bound macros.

The returning value may or may not be used as proper Scheme expression.

Above 2 procedures are no more than debug aid. Depending on the result of expansion is not guaranteed to work.

6.16(sagittarius generators) - Generators

This library provides procedures for generator.

A generator is simply a procedure with no arguments that works as a source of a series of values. Every time it is called, it yields a value. Generators may be finite or infinite; a finite generator returns an EOF object to indicate that it is exhausted. For example, read-char is a generator that generates characters from the current input port. Generators provide lightweight laziness.

6.16.1Generator constructors

The following procedures creates a generator. Except null-generator, all procedures have prefix 'g'. Arguments named generator indicates a generator.

Returns a generator which always returns EOF object.

Function circular-generator obj obj* ...
Returns a generator which repeats the given objs.

Function giota :optional (count +inf.0) (start 0) (step 1)
Returns a generator which returns count number of numbers. The returning numbers start with start and increased by step.

(generator->list (giota 5))
=> (0 1 2 3 4)
(generator->list (giota 5 10))
=> (10 11 12 13 14)
(generator->list (giota 5 10 2))
=> (10 12 14 16 18)

If count is not given, then the generator is inifinte.

Function grange :optional (start 0) (end +inf.0) (step 1)
Returns a generator which returns numbers in range of start and end. The returning numbers are increased by step.

Function gunfold stop? mapper successor seed :optional (tail-gen #f)
A generator constructor similar to unfold.

(generator->list (gunfold
                      (lambda (s) (> s 5))
                      (lambda (s) (* s 2))
                      (lambda (s) (+ s 1))
                      0))
=> (0 2 4 6 8 10)

Function list->generator list
Function vector->generator vector
Function string->generator string
Function bytevector->generator bytevector
Generator constructors. The returning generator returns the items taken from given argument from the beginning of the given sequence to the end. Except reverse-vector->generator which return end to beginning.

Generator constructors. The returning generator returns the items read from the given port. The port->char-generator uses get-char to read the port. The port->byte-generator uses get-u8.

Generic constructor of generators. By default, the following methods are defined and dispatched above generator constrocturs.

<list>, <vector>, <string>, <bytevector> and <port>.

If the given argument is type of <vector>, then vector->generator is used. If the given argument is type of <port>, then it checks if it's binary or textual and dispatches apropriate procedure.

6.16.2Generator operations

Function gcons* object ... generator
Returns a generator which adds objects in front of generator.

Function gappend generator ...
Returns a generator which yields values from the first generator and when it's exhausted continues to next.

Function gcombine proc seed generator generators ...
Returns a generator for mapping with state. It yields a sequence of sub-folds over proc.

The proc argument is a procedure which takes as many arguments as the input generators plus one. It is called as (proc v1 v2 ... seed), where v1, v2,... are the values yielded from the input generators, and seed is the current seed value. It must return two values, the yielding value and the next seed.

Function gfilter pred generator
Function gremove pred generator
Return generators which yield the items from the source generator, except those on which pred returns false or true respectively.

Function gtake generator k :optional padding
Function gdrop generator k
Return generators which take or drop k items from generator, respectively. Returning generators won't raise errors when it's exhausted before reaching k.

Optional argument padding for gtake is passed, then the value is filled until the procedure reaches k.

These procedures are analogues of SRFI-1 take and drop.

Function gtake-while generator pred
Function gdrop-while generator pred
Return generators which take or drop until procedure pred returns false value respectively.

These procedures are analogues of SRFI-1 take-while and drop-while.

Function gdelete item generator :optional (= equal?)
Returns a generator which returns items generator returns, except items which are the same as item in sense of =.

Function gdelete-neighbor-dups generator :optional (= equal?)
Returns a generator which returns items generator returns, except items which are the same as the proceeding item in sense of =.

Function gselect value-generator index-generator
Returns a generator which returns the items generated by value-generator of specified by the indice generated by index-generator. The indice must be non negative integer and increased strictly. Otherwise an error is raised.

(generator->list (gindex (list->generator '(a b c d e f))
                 (list->generator '(0 2 4))))
=> (a c e)

Function gselect value-generator truth-generator
Returns a generator which returns the items generated by value-generator that correspond to the items generated by truth-generator. If truth-generator returns true value, then the current value of value-generator is returned. Otherwise not.

(generator->list (gselect (list->generator '(a b c d e f))
                          (list->generator '(#t #f #f #t #t #f))))
=> (a d e)

Function gconcatenate generator
generator must be an generator generates generators.

Returns a generator which returns the items generated by the generators generated by given generator. It is similar to the following:

(apply gappend (generator->list generator))
The difference is that this procedure can handle infinite generator.

Function gflatten generator
generator must be a generator which returns lists as its items.

Returns a generator which flatten the items generated by given generator.

(generator->list (gflatten (list->generator (list '(1 2 3 4)
                                                  '(a b c d)
                                                  '(A B C D)))))
=> (1 2 3 4 a b c d A B C D)

If the generator returns non list item, then it is ignored.

(generator->list (gflatten (list->generator (list 'ignored
                                                  '(a b c d)
                                                  'ignored
                                                  '(A B C D)))))
=> (a b c d A B C D)
This behaviour is an error behaviour so it might be changed in future. So users should not depend on this.

Function gmerge compare generator1 generator2 ...
compare must be a procedure which accepts 2 arguments and returns boolean value. The procedure should compare the given 2 arguments and return true value if the first argument is smaller than the second argument.

Returns a generator which returns the ordered items determined by compare procedure. If the gmerge procedure is called only one argument, then it simply returns a generator (if generator1 isn't a generator then it is coerced).

(generator->list (gmerge < (list->generator '(1 4 5)) (list->generator '(0 2 3))))
=> (0 1 2 3 4 5)

Function gmap proc generator1 generator2 ...
Returns a generator which returns the items returned by proc.

The proc is called with the items returned by generator1 and generator2 if it's given.

The gmap procedure accepts uneven length of generators however one of the generator must be finite length, otherwise it won't be exhausted.

It is an analogy of map.

Function gfilter-map proc generator1 generator2 ...
Returns a generator which returns the items returnd by proc.

This procedure is similar with gmap. The difference is that the returning item is filtered if the returning value of proc is #f.

It is an analogy of filter-map.

Function generate proc
Returns a coroutine generator which return the item returned by proc.

The given argument proc must accept one argument, yield which is a procedure accepts variable arguments. The proc procedure can return values via yield procedure.

(define g
  (make-coroutine-generator
    (lambda (yield) 
      (let loop ((i 0))
        (when (< i 3) 
          (yield i) 
          (loop (+ i 1)))))))

(generator->list g)
=> (0 1 2)

Macro glet* (bindings ...) body1 body2 ...
glet* is a macro which is similar to let*. The difference is that glet* check if the bindings are EOF object or not and if it detects EOF object, then it returns EOF object immediately.

bindings must be one of the following forms:

  • (var gen-expr)
  • ( gen-expr )
If the first form is used, then the gen-expr is bound to var. Otherwise the glet* just check if the value is EOF or not.

(define g (list->generator '(1 2 3)))

(list 
  (glet* ((a (g))) a)
  (glet* ((a (g))) (define b 2) (+ a b))
  (glet* ((a (g)) (b (g))) (+ a b)))
=> (1 2 #<eof>)

Macro glet1 var expr body1 body2 ...
Convenient macro for only one binding of glet*. This is defined like the following:
(define-syntax glet1
  (syntax-rules ()
    ((_ var expr body body1 ...)
     (glet* ((var expr)) body body1 ...))))

Macro do-generator (var gen-expr) body ...
Iterates generator of then given gen-expr.

7Utility libraries

7.1(archive) - Generic archive interface

Library archive
This library provides generic interface to access archive libraries. Sagittarius supports tar and zip.

Following code describes a typical use of the library;

(import (rnrs) (archive))

;; extract file "bar.txt" from "foo.zip"
(call-with-input-archive-file 'zip "foo.zip"
  (lambda (zip-in)
    (do-entry (e zip-in)
      (when (string=? (archive-entry-name e) "bar.txt")
        (call-with-output-file "bar.txt"
          (lambda (out) (extract-entry e out))
           :transcoder #f)))))

;; archive "bar.txt" into foo.tar
(call-with-output-archive-file 'tar "foo.tar"
  (lambda (tar-out)
    (append-entry! tar-out (create-entry tar-out "bar.txt"))))

Following sections use type as a supported archive type. More precisely, if it's a supported archive type then there must be a library named (archive type).

7.1.1Archive input

Function make-input-archive type input-port
type must be a symbol and supported archive type. input-port must be a binary input port.

Creates an archive input which represents the specified type of archive.

Method next-entry! archive-input
Retrieves next entry of the given archive input. If there is no entry, then it returns #f.

Macro do-entry (entry archive-input) body ...
Macro do-entry (entry archive-input result) body ...
Convenient macro. Iterates the given archive-input's entries.

The macro is expanded like this;

(do ((entry (next-entry! archive-input) (next-entry! archive-input)))
    ((not entry) result)
  body ...)

If the first form is used, then result is #t.

Method extract-entry entry output-port
Extract the given archive entry entry to binary output port output-port.

Function extract-all-entries archive-input :key (destinator archive-entry-name) (overwrite #f)
Convenient function. Extracts all entries in the given archive-input to the file specified by destinator.

The keyword argument destinator must be a procedure which accepts one argument, archive entry, and return a string represents the file/directory path.

The keyword argument overwrite is #t, then it overwrites the file. If it is #f and there is a file, then it raises an error.

Method finish! archive-input
Finalize the given archive input.

Function call-with-input-archive archive-input proc
archive-input must be an archive input. proc must be a procedure which accepts one argument.

Call the proc with archive input and returns the result of the proc.

The archive-input is finalized by finish!.

Function call-with-input-archive-port type input-port proc
Creates an archive input with type and input-port, then call call-with-input-archive.

Function call-with-input-archive-file type file proc
Open file binary input port with given file and call call-with-input-archive-port.

7.1.2Archive output

Function make-output-archive type output-port
type must be a symbol. output-port must be a output port.

Creates an archive output which represents the specified type of archive.

Method create-entry archive-output file
Creates an archive entry from the given file.

For implementing user defined archive;

This method is defined like following on the interface library:

(define-method create-entry ((out <archive-output>) file)
  (create-entry out file file))
So as long as it doesn't have to be distinguished, users don't have to implement this method.

Method create-entry archive-output entry-name file
Creates an archive entry from the given file. The entry's name is entry-name. This is useful when users want to append entry with different name from file name.

Method append-entry! archive-output entry
Appends the given entry to archive-output.

Method finish! archive-output
Finalize the given archive output.

Function call-with-output-archive archive-output proc
archive-output must be an archive output. proc must be a procedure which accepts one argument.

Call the proc with archive input and returns the result of the proc.

The archive-output is finalized by finish!.

Function call-with-output-archive-port type output-port proc
Creates an archive output with type and output-port, then call call-with-output-archive.

Function call-with-output-archive-file type file proc
Open file binary output port with given file and call call-with-output-archive-port.

7.1.3Entry accessor

Returns the name of entry.

Returns the type of entry. It is either file or directory.

7.1.4Implementing archive implementation library

To support other archive such as RAR, then you need to create a implementation library.

The library defines all abstract class and method for the generic archive access.

To support foo archive, then the library name must be code{(archive foo)} and it must import (archive interface). So the library code should look like this;

(library (archive foo)
  (export) ;; no export procedure is needed
  (import (rnrs)
          (close user)
          (archive interface)
          ;; so on
          ...)
  ;; class and method definitions
  ...
)

For archiving, the implementation needs to implement following methods and extends following classes;

make-archive-input, next-entry, extract-entry
<archive-input> <archive-entry>

For extracting, the implementation needs to implement following methods and extends following classes;

make-archive-output, create-entry, append-entry!, finish!
<archive-output> <archive-entry>

NOTE: <archive-entry> may be shared between archiving and extracting.

Abstract class of the archive input. This class has the following slot;

source
Source of the archive. For compatibility of other archive, this should be a binary input port.

Abstract class of the archive output. This class has the following slot;

sink
Destination of the archive. For compatibility of other archive, this should be a binary output port.

Abstract class of the archive entry. This class has the following slots;

name
Entry name.
type
Entry type. For compatibility of other archive, this must be file or directory.

Method make-archive-input type (source <port>)
Method make-archive-output type (sink <port>)
Creates an archive input or output. type specifies the archive type. It is recommended to use eql specializer to specify.

Method finish! (in <archive-input>)
The finish! method for archive input has a default implementation and it does nothing.

Users can specialize the method for own archive input.

The other methods must be implemented as it's described in above section.

7.2(asn.1) - Abstract Syntas Notation One library

This section describes (asn.1) library. The library supports DER and BER formats. We do not describe DER or BER format here.

Library (asn.1)
Top most library of asn.1 procedure collection libraries. There are multiple of related libraries, however we do not mention those because it might be changed in future. So do not use the child libraries directly, use this.

7.2.1High level user APIs

Function encode obj :key (encoder der-encode)
obj must be asn.1-object which described below sections.

If you specify keyword argument encoder, it must be generic function which accepts an object and a binary output port respectively.

Encodes given obj to bytevector. If obj contains BER object, the procedure encodes it to BER. This might be changed in future to configure which format this should encode.

If you want to encode to other format such as CER or XER, then you need to implement an encoder. This procedure does not check given arguments type, just pass obj to encoder with binary output port.

in must be binary input port.

Reads asn.1-object from given port. The port must be DER or BER encoded stream otherwise it raises &assertion

7.2.2Middle level user APIs

This section is incompleted.

Generic make-der-application-specific <boolean> <integer> <bytevector>
Generic make-der-application-specific <integer> <bytevector>
Generic make-der-application-specific <boolean> <integer> <der-encodable>
Generic make-der-application-specific <integer> <der-encodable>
Creates a DER application specific object.

Generic make-der-bit-string <bytevector> <integer>
Generic make-der-bit-string <bytevector>
Creates a DER bit string object.

Generic make-der-bmp-string <bytevector>
Generic make-der-bmp-string <string>
Creates a DER bmp string object.

Generic make-der-octet-string <bytevector>
Generic make-der-octet-string <der-encodable>
Creates a DER octet string object.

Generic make-der-general-string <bytevector>
Creates a DER general string object.

Generic make-der-ia5-string <string>
Generic make-der-ia5-string <string> <boolean>
Generic make-der-ia5-string <bytevector>
Creates a DER IA5 string object.

Generic make-der-numeric-string <string> <boolean>
Generic make-der-numeric-string <bytevector>
Creates a DER numeric string object.

Generic make-der-printable-string <string> <boolean>
Generic make-der-printable-string <bytevector>
Creates a DER printable string object.

Generic make-der-t61-string <string>
Generic make-der-t61-string <bytevector>
Creates a DER T61 string object.

Generic make-der-universal-string <bytevector>
Creates a DER universal string object.

Generic make-der-utf8-string <string>
Generic make-der-utf8-string <bytevector>
Creates a DER UTF8 string object.

Generic make-der-visible-string <bytevector>
Creates a DER visible string object.

Generic make-der-boolean <boolean>
Generic make-der-boolean <bytevector>
Creates a DER boolean object.

Generic make-der-enumerated <bytevector>
Generic make-der-enumerated <integer>
Creates a DER enumerated object.

Generic make-der-integer <integer>
Generic make-der-integer <bytevector>
Creates a DER integer object.

Generic make-der-object-identifier <bytevector>
Creates a DER OID object.

Generic make-der-sequence <der-encodable>
Creates a DER sequence object.

If the third form is used, os must be list of <der-encodable>.

Generic make-der-set <der-encodable>
Generic make-der-set o ...
Creates a DER set object.

If the third form is used, os must be list of <der-encodable>.

Creates a DER null object.

Generic make-der-generalized-time <bytevector>
Creates a DER generalized time object.

Generic make-der-utc-time <string>
Generic make-der-utc-time <bytevector>
Generic make-der-utc-time <date>
Creates a DER UTC time object.

Generic make-der-tagged-object <boolean> <integer> <der-encodable>
Generic make-der-tagged-object <integer> <der-encodable>
Generic make-der-tagged-object <integer>
Creates a DER tagged object.

Generic make-der-external <der-object-identifier> <der-integer> <asn.1-object> <der-tagged-object>
Generic make-der-external <der-object-identifier> <der-integer> <asn.1-object> <integer> <der-object>
Creates a DER external object.

Creates a BER constructed object.

Generic make-ber-application-specific <integer> l ...
Creates a BER application specific object.

Generic make-ber-tagged-object <boolean> <integer> <der-encodable>
Creates a BER tagged object.

Creates a BER sequence object.

ls must be list of <der-encodable>.

Generic make-ber-set l ...
Creates a BER set object.

ls must be list of <der-encodable>.

Creates a BER null object.

7.2.3Low level User APIs

This section is incompleted. Here must desribe classes defined in (asn.1) library.

7.3(binary data) - Binary data read/write

This library provides yet another binary data structure read/write. The difference between (binary pack) and this is the level of abstraction. This library provides higher abstraction layer of the way how to handle binary data.

Macro define-simple-datum-define name reader writer
Macro define-composite-data-define name reader writer
Defines a macro named name to read binary data by generic method reader and write binary data by writer.

To use defining macros effectively, both forms' reader and writer should be the same name.

The first form defines a macro which takes 5 required arguments and optional keyword arguments. Let's say the name is define-simple, the reader is simple-read and the write is simple-write, Then the definition of defined macro would be like this;

Macro define-simple name parents slots read-proc write-proc :key (parent-metaclass <class>)
Defines name class whose parent classes are parents and slots are slots.

read-proc must be a procedure which takes one argument, a input port and return number of slots values.

write-proc must be a procedure which takes number of slots plus 1 arguments. The first one is an output port and the rest are the value of the slots of the defined class' instance.

The keyword argument parent-metaclass is a parent class of the metaclass of this class.

The slots form must be a list of slot definitions which must be followings;

  • name
  • (name)
  • (name default)
The first and second form define a slot which name is name and its initial value is #f. The third form defines a slot which name is name and its initial is default.

Note that current implemenation does not handle parent classes slots. This is only for seamless operations with other CLOS class.

The second form defines a macro which takes 3 required arguments and optional keyword arguments. Let's say the name is define-composite, the reader is simple-read and the write is simple-write, Then the definition of defined macro would be like this;

Macro define-simple name parents slots :key (parent-metaclass <class>)
Defines a composite data class named name whose parent classes are parents and slots are slots.

It is similar form with define-class however slots must be a list of one of the followings.

  • (name type)
  • (name type default)
  • (name (type count))
  • (name (type count) default)
name must be a symbol which represents the slot name.

type can be class name or eqv? comparable datum. e.g. keyword.

default can be any object.

count must be a non negative exact integer.

The first form is equivalent with the following form; (name type #f). And the third form is equivalent with the following form; (name (type count) #f).

The first 2 forms defines a datum slot which the datum is read by reader passing type and written by writer.

The rest forms defines an array data represented by a vector.

If the type is not defined by neither of the definition forms, then it is users responsibility to define a method which handles the type.

Following is the simple example to show how to use the macros above.

(import (clos user) (binary data))

;; use the same name of reader and writer
(define-simple-datum-define   define-simple    sample-read sample-write)
(define-composite-data-define define-composite sample-read sample-write)

(define-simple <simple> ()
  (a b (c 0))
  (lambda (in) (values (get-u8 in) (get-u8 in) (get-u8 in)))
  (lambda (out a b c) (put-u8 out a) (put-u8 out b) (put-u8 out c)))

(define-composite <composite> ()
  ((d :byte 1)
   (e (:byte 4) #vu8(1 2 3 4))
   (f <simple>)))

;; :byte reader and writer
(define-method sample-read ((o (eql :byte)) in array-size?)
  (if array-size?
      (get-bytevector-n in array-size?)
      (get-u8 in)))

(define-method sample-write ((type (eql :byte)) o out array-size?)
  (if array-size?
     (put-bytevector out o)
     (put-u8 out o)))

How to use the defined data structure.

;; read as a <composite> object
;; "deeeeabc" in ascii
(define bv #vu8(#x64 #x65 #x65 #x65 #x65 #x61 #x62 #x63))
(call-with-port (open-bytevector-input-port bv)
  (lambda (in)
    (let ((s (sample-read <composite> in)))
      (slot-ref s 'd) ;; => #\d
      (slot-ref s 'f) ;; => <simple>
      )))

;; write <composite> object
(call-with-bytevector-output-port
  (lambda (out)
    (let* ((s (make <simple> :a 10 :b 20))
           (c (make <composite> :f s)))
      ;; this can be written like this as well (sample-write o out)
      (sample-write <composite> c out))))
;; => #vu8(1 1 2 3 4 10 20 0)

7.4(binary io) - Binary I/O utilities

Binary I/O utility. In real world you sometimes want to treat binary port like textual port (e.g. get-line for binary port). This library exports those convenient procedures

7.4.1Binary I/O

Function get-line in :key eol (transcoder #f)
in must be binary input port.

Reads a bytevector from in until it hits the eol data. eol can be multiple length such as #vu8(#x0d #x0a). Default value is #vu8(#x0a)

If keyword argument transcoder is given, then returning value will be converted to string.

Function put-u16 out v endian
Function put-s16 out v endian
Function put-u32 out v endian
Function put-s32 out v endian
Re-exported procedure from (sagittarius) for convenience. See Sagittarius extensions.

Function put-u64 out v endian
Function put-s64 out v endian
Function put-f32 out v endian
Function put-f64 out v endian
out must be binary output port. endian must be a value returned from endianness macro.

Write v to out as unsigned/signed 16/32/64 bit integer or 32/64 bit floating number.

Function get-u16 in endian
Function get-s16 in endian
Function get-u32 in endian
Function get-s32 in endian
Re-exported procedure from (sagittarius) for convenience. See Sagittarius extensions.

Function get-u64 in endian
Function get-s64 in endian
Function get-f32 in endian
Function get-f64 in endian
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/64 bit integer or 32/64 bit floating number.

7.4.2Chunk buffered port

Default binary input port requires bytevector however if users want to handle bigger data then it would not be suitable. Chunk buffered port is a buffered port which buffer is chunks of bytevector so that it doesn't allocate huge memory.

Function ->chunked-binary-input-port ->chunks :key chunk-size
Creates chunk buffered port.

->chunks must be a procedure which takes one argument, chunk-size. And must return a list of bytevectors which size is chunk-size except the last element.

The keyword argument chunk-size is specified then it must be a positive integer. By default +default-chunk-size+ is used.

Default chunk size of chunk buffered port.

Function input-port->chunked-binary-input-port iport :key chunk-size threshold
Creates chunk buffered port from given iport.

iport must be a binary input port.

The keyword argument threshold is specified, it must be a positive integer, then the procedure only reads the number of threshold bytes from iport.

7.5(binary pack) - Packing binary data

This library provides an interface for packing and unpacking (writing and reading) binary data with template. The functionality is inspired by Industria's (weinholt struct pack) library.

Macro pack template args ...
template must be a string.

Construct a bytevector with given args according to the given template. Template characters are described below.

Macro pack! template bv offset args ...
template must be a string.

bv must be a bytevector.

offset must a non-negative exact integer.

Converts given args and put it into bv starting from offset. The conversion is done according to the template string.

The template characters are extensible so following description can only cover predefined characters.

x: padding; c: s8; C: u8; s: s16; S: u16; l: s32; L: u32; q: s64; Q: u64; f: ieee-single; d: ieee-double; ! or >: big-endian; <: little-endian; =: native-endian; u: disable natural alignment; a: enable natural alignment. Whitespace is ignored.

(pack "!c" 128)
=> #vu8(128)
(pack "s" 100)
=> #vu8(100 0)
(pack "!s" 100)
=> #vu8(0 100)
(pack "!d" 3.14)
=> #vu8(64 9 30 184 81 235 133 31)

Fields are by default aligned to their natural alignment and NUL bytes are inserted as necessary to have a field's index to be aligned to its size.

(pack "!xd" 3.14)
=> #vu8(0 0 0 0 0 0 0 0 64 9 30 184 81 235 133 31)
(pack "!uxd" 3.14)
=> #vu8(0 64 9 30 184 81 235 133 31)

Digits in front of the syntax characters means repetition. And #\* means indefinite length repetition.

(pack "3c" 1 2 3)
=> #vu8(1 2 3)
(pack "*c" 1 2 3 4)
=> #vu8(1 2 3 4)

When the macro detects the given template is string, then it tries to expand as much as possible. So it might raises the different condition even if the template strings are the same.

(pack "3c" 1 2 3 4)
=> &syntax
(pack (car '("3c")) 1 2 3 4)
=> &error

Macro unpack template bv
Macro unpack template bv offset
template must be a string.

Unpack the given bytevector according to the given template and returns the values. The template syntax are the same as pack!.

If the second form is used, then unpacking is done from the given offset.

(unpack "!SS" #vu8(0 1 0 2))
=> 1 2
(unpack "!SS" #vu8(0 1 0 2 0 3) 1)
=> 2 3
(unpack "!uSS" #vu8(0 1 0 2 0 3) 1)
=> 256 512

Macro get-unpack port template
template must be a string.

Utility unpacking macro for binary port.

Macro format-size template
Macro format-size template args ...
template must be a string.

Calculate the size of the result bytevector. If the second form is used, then macro can calculate even if the template contains indefinite length syntax #\*, otherwise #f is returned.

(format-size "!xd")
=> 16
(format-size "!uxd")
=> 9
(format-size "*c")
=> #f
(format-size "*c" 1 2 3 4)
=> 4

Macro define-**-packer (char arg) (pack expr1 ...) (unpack expr2 ...)
char must character.

pack and unpack are syntactic keywords.

Defines packing extension to given char. This macro can not overwrite the predefined characters. ** can be followings;

s8, u8, s16, u16, s32, u32, s64, u64, f32, and f64.

;; defining char to u8 converter
(define-u8-packer (#\A v)
  (pack (char->integer v))
  (unpack (integer->char v)))
(pack "AA" #\a #\b)       ;; => #vu8(97 98)
(unpack "AA" #vu8(97 98)) ;; => #\a #\b

7.6(util buffer) - Buffer utilities

This library provides buffer utitlities. Currently, it only provides pre-allocated buffer and its procedures.

7.6.1Pre-allocated buffer

Parent type of pre-allocated buffer. This library doesn't expose the record constructor for this type.

This type contains buffer and size fields.

Returns #t if given obj is a pre-allocated buffer. Otherwise #f.

Returns value of buffer field of given buffer.

The type of buffer field is implementation specific.

Returns value of size field of given buffer.

The returning value shall represents how much buffer of the given buffer is consumed.

Sets 0 to the size field of given buffer.

7.6.2Conditions

Buffer overflow condition. This is raised when an operation tries to put data exceed the buffer size.

This condition have data field which contains overflowing data.

Returns #t if given obj is &pre-allocated-buffer-overflow condition, otherwise #f.
Retrieves data field value of condition.

The condition must be a &pre-allocated-buffer-overflow condition.

7.6.3Binary pre-allocated buffer

Binary pre-allocated buffer can be used when users don't want to allocate bytevector number of times. This buffer can be used like a bytevector.

Creates pre-allocated buffer with given bytevector bv.

The returning value is a subtype of <pre-allocated-buffer>.

Returns #t if given obj is binary pre-allocated buffer, otherwise #f.

7.6.3.1Operations

Function binary-pre-allocated-buffer-put-u16! binary-buffer u16 endianness
Function binary-pre-allocated-buffer-put-u32! binary-buffer u32 endianness
Function binary-pre-allocated-buffer-put-u64! binary-buffer u64 endianness
Function binary-pre-allocated-buffer-put-s16! binary-buffer s16 endianness
Function binary-pre-allocated-buffer-put-s32! binary-buffer s32 endianness
Function binary-pre-allocated-buffer-put-s64! binary-buffer s64 endianness
Function binary-pre-allocated-buffer-put-f32! binary-buffer f32 endianness
Function binary-pre-allocated-buffer-put-f64! binary-buffer f64 endianness
Appending given integer or flonum to binary-buffer. Setting given values uses the following procedures, respectively:

bytevector-u8-set! bytevector-u16-set! bytevector-u32-set! bytevector-u64-set! bytevector-s8-set! bytevector-s16-set! bytevector-s32-set! bytevector-s64-set! bytevector-ieee-single-set! bytevector-ieee-double-set!

The endianness is passed to the above procedures if required.

This procedure also updates the size field of binary-buffer.

Function binary-pre-allocated-buffer-put-bytevector! binary-buffer bv :optional start count
Appending given bytevector bv to binary-buffer.

Optional arguments start and count specifies from where of bv and how much bytes need to be put. By default, start is 0 and count is (- (bytevector-length bv) start).

This procedure also updates the size field of binary-buffer.

Function binary-pre-allocated-buffer-set-u8! binary-buffer index u8
Function binary-pre-allocated-buffer-set-u16! binary-buffer index u16 endianness
Function binary-pre-allocated-buffer-set-u32! binary-buffer index u32 endianness
Function binary-pre-allocated-buffer-set-u64! binary-buffer index u64 endianness
Function binary-pre-allocated-buffer-set-s8! binary-buffer index s8
Function binary-pre-allocated-buffer-set-s16! binary-buffer index s16 endianness
Function binary-pre-allocated-buffer-set-s32! binary-buffer index s32 endianness
Function binary-pre-allocated-buffer-set-s64! binary-buffer index s64 endianness
Function binary-pre-allocated-buffer-set-f32! binary-buffer index f32 endianness
Function binary-pre-allocated-buffer-set-f64! binary-buffer index f64 endianness
Setting given integer/flonum to binary-buffer. These procedures are anology of the following procedures, respectively:

bytevector-u8-set! bytevector-s8-set! bytevector-u16-set! bytevector-u32-set! bytevector-u64-set! bytevector-s16-set! bytevector-s32-set! bytevector-s64-set! bytevector-ieee-single-set! bytevector-ieee-double-set!

The endianness is passed to the above procedures if required.

This procedure updates the size field of binary-buffer if sum of given index and number of bytes set in the buffer exceeds the size of the buffer.

Function binary-pre-allocated-buffer-set-bytevector! binary-buffer index bv :optional start count
Sets the given bv to binary-buffer at position of index.

Optional arguments start and count specifies from where of bv and how much bytes need to be put. By default, start is 0 and count is (- (bytevector-length bv) start).

This procedure updates the size field of binary-buffer if sum of given index and number of bytes set in the buffer exceeds the size of the buffer.

All above operations may raises an &pre-allocated-buffer-overflow, when it tries to exceed the pre-allocated buffer.

Function binary-pre-allocated-buffer-can-store? binary-buffer count :optional position
Returns #t if binary-buffer can store count bytes.

If optional argument position is given, then the procedure check from the position.

Function binary-pre-allocated-buffer-swap! binary-buffer new-buf new-size
Swaps the buffer of binary-buffer with new-buf and new-size.

Function binary-pre-allocated-buffer-get-bytevector-n! binary-buffer input-port n :optional position
Reads n bytes from given input-port and store it to binary-buffer.

If optional argument position is given, then the procedure stores from the position.

Function crop-binary-buffer binary-buffer
Returns newly allocated bytevector which contains range of 0 to size field value of buffer field.

Converts the given binary-buffer to binary output port.

If port operations try to exceed the pre-allocated buffer, then it raises &pre-allocated-buffer-overflow.

7.7(util bytevector) - Bytevector utility library

This library provides bytevector utilities which are not provided as builtin procedures such as bytevector->integer.

All procedures take bytevector as its arguments.

Function bytevector-xor bv1 bv2 ...
Function bytevector-xor! out bv1 bv2 ...
Function bytevector-ior bv1 bv2 ...
Function bytevector-ior! out bv1 bv2 ...
Function bytevector-and bv1 bv2 ...
Function bytevector-and! out bv1 bv2 ...
Compute exclusive or, logical or and logical and for each given bytevectors, respectively.

The procedures without ! freshly allocate a new bytevector as it's return value. If the given bytevectors are not the same sized, then the smallest size will be allocated.

The procedures with ! takes first argument as the storage of the result and return it.

Function bytevector-slices bv k :key (padding #f)
Slices the given bytevector bv into k size and returns a list of bytevectors.

The keyword argument padding is given and it must be a procedure accept one argument, then it will be called when the last chunk of bytevector is not size of k. The procedure should return padded bytevector and it doesn't check the returned value nor it's size so it is caller's responsibility to make sure the returned value is a bytevector and the size is k.

(bytevector-slices #vu8(1 2 3 4 5 6) 3)
=> (#vu8(1 2 3) #vu8(4 5 6))
(bytevector-slices #vu8(1 2 3 4) 3)
=> (#vu8(1 2 3) #vu8(4))
;; the given bytevector bv is #vu8(4)
(bytevector-slices #vu8(1 2 3 4) 3 :padding (lambda (bv) #vu8(4 5 6)))
=> (#vu8(1 2 3) #vu8(4 5 6))
;; this is valid as well so that bytevector-slices doesn't check the 
;; return value
(bytevector-slices #vu8(1 2 3 4) 3 :padding (lambda (bv) #f))
=> (#vu8(1 2 3) #f)

Function bytevector-split-at* bv k :key (padding #f)
w
Splits bytevector into 2 bytevectors and returns 2 values of bytevectors.

The first returned bytevector size will be k and its content is given bytevector's value starting from 0 to k - 1. The second returned value is the rest of values of bv.

If size of the given bytevector bv is less than k then the second value of returned bytevector will be empty bytevector.

The keyword argument padding is given and it must be a procedure accept one argument, then it will be called when given bytevector's size is less than k and first returned value will the result of padding.

(bytevector-split-at* #vu8(1 2 3 4 5) 3)
=> #vu8(1 2 3) and #vu8(4 5)
(bytevector-split-at* #vu8(1 2) 3 :padding (lambda (bv) #vu8(1 2 3)))
=> #vu8(1 2 3) and #vu8()
(bytevector-split-at* #vu8(1 2) 3 :padding (lambda (bv) #f))
=> #f and #vu8()

Function ->odd-parity bv :optional (start 0) (end (bytevector-length bv))
Function ->odd-parity! bv :optional (start 0) (end (bytevector-length bv))
Compute odd parity of the given bytevector bv and return the result of bytevector.

If the second procedure is used, then bv will be modified.

Function bytevector<? bv1 bv2 rest ...
Function bytevector>? bv1 bv2 rest ...
Function bytevector<=? bv1 bv2 rest ...
Function bytevector>=? bv1 bv2 rest ...
Comparing given bytevectors.

The comparison is done by comparing the elements of bytevectors from index 0. The comparison procedures are <, >, <= and >=, respectively.

Function bytevector->hex-string bv :key (upper? #t)
Converts given bytevector bv to hex string.

The keyword argument upper? is specified with true value, then the procedures converts to upper case hex values, otherwise lower case.

Converts given hex string string to bytevector.

Converts given bytevector to string without transcoder.

The conversion is the same as the following code:

(list->string (map integer->char (bytevector->u8-list bv)))
This procedure is implemented in a memory efficient way.

Function bytevector-reverse! bv :optional (start 0) (end (bytevector-length bv))
Function bytevector-reverse bv :optional (start 0) (end (bytevector-length bv))
Reverse the given bytevector bv.

Optional arguments start and end controls from and until where the procedure reverses the bytevector. end is exclusive.

The bytevector-reverse! reverses destructively.

7.7.1SRFI-13 convension APIs

7.7.1.1U8 sets

U8 set is a list of integers which range is in between 0 <= n <= 255. This is useful to handle bytevectors as if they are ASCII strings.

Function u8? o
Returns #t if given o is an integer in range of 0 <= o <= 255, otherwise #f.

Function u8-set? o
Returns #t if given o is a list and its all elements satisfy u8?. Otherwise #f.

Function u8-set-contains? u8-set u8
u8-set must satisfy u8-set?. u8 should satisfy u8. The procedure doesn't check if arguments satify this.

Returns #t if given u8-set contains u8.

Function string->u8-set string
Converts given string to list of integers. Given string should only contains in range of ASCII characters but the procedure doesn't check. Thus the procedure may return a list doesn't satify u8-set?. It is users' responsibility to pass ASCII string.

Function char-set->u8-set cset
Converts given char-set cset to u8 set. This procedure returns a list that satify u8-set? by dropping outside of ASCII characters.

7.7.1.2Bytevectors as ASCII strings

Function bytevector-fold kons knil bv :optional start end
Function bytevector-fold-right kons knil bv :optional start end
Iterate given bv from start until end. kons is called by each element with result of the kons. The inital value is knil.

This is analogy of fold-left and fold-right.

Function bytevector-take bv n
Subtract bytevector bv until index n (exclusive).

The bytevector-take takes from left and the bytevector-take-right takes from right.

Function bytevector-drop bv n
Drops given bv until index n (exclusive).

The bytevector-drop drops from left and the bytevector-drop-right drops from right.

Function bytevector-trim bv :optional criterion start end
Function bytevector-trim-right bv :optional criterion start end
Function bytevector-trim-both bv :optional criterion start end
Trims given bytevector bv from left, right and both, respectively.

The optional argument criterion specifies how to trim. By default, it uses whitespaces. " \r\f\v\n\t".

The optional arguments start and end specify from and until where the procedure trims. The default value is 0 for start and the length of given bytevector for end.

Function bytevector-pad bv n :optional (u8 0) start end
Function bytevector-pad-right bv n :optional (u8 0) start end
Pads given bytevector bv with n elements of u8. The bytevector-pad pads left side of given bv. The bytevector-pad-right pads right side of given bv.

The optional arguments start and end specify from and until where the procedure pads. The default value is 0 for start and the length of given bytevector for end.

Function bytevector-prefix-length bv1 bv2 :optional start1 end1 start2 end2
Function bytevector-suffix-length bv1 bv2 :optional start1 end1 start2 end2
Return the length of the longest common prefix/suffix of the two bytevectors.

The optional start/end indices restrict the comparison to the indicated sub bytevectors of bv1 and bv2.

Function bytevector-prefix? bv1 bv2 :optional start1 end1 start2 end2
Function bytevector-suffix? bv1 bv2 :optional start1 end1 start2 end2
Returns #t if bv1 is a prefix/suffix of bv2. Otherwise #f.

The optional start/end indices restrict the comparison to the indicated sub bytevectors of bv1 and bv2.

Function bytevector-index bv criterion :optional start end
Function bytevector-index-right bv criterion :optional start end
Searches through the given bytevector bv from the left (right), returning the index of the first occurrence of an element which satisfies the criterion.

criterion can be a u8 value, a u8 set or a procedure.

If the procedure doesn't find any element satisfies criterion, then returns #f.

Function bytevector-skip bv criterion :optional start end
Function bytevector-skip-right bv criterion :optional start end
Search through the given bytevector bv from the left (right), returning the index of the first occurrence of an element which does not satisfy the criterion.

criterion can be a u8 value, a u8 set or a procedure.

If the procedure doesn't find any element which does not satisfy criterion, then returns #f.

Function bytevector-contains bv1 bv2 :optional start1 end1 start2 end2
Returns index of bv1 where bv2 is found. If bv1 doesn't contain bv2 then returns #f.

The optional start/end indices restrict the comparison to the indicated sub bytevectors of bv1 and bv2.

Function bytevector-replace bv1 bv2 start1 end2 :optional start2 end2
Returns
(bytevector-append (bytevector-copy s1 0 start1)
                   (bytevector-copy s2 start2 end2)
                   (bytevector-copy s1 end1 (string-length s1)))

Function bytevector-tokenize bv :optional token-set start end
Split the given bytevector bv into a list of sub bytevectors, where each sub bytevector is a maximal non-empty contigunous sequence of elements from the u8 set token-set.

Optional argument token-set must be a u8 set. By default, it's a list of bytes of ASCII graphical characters.

The optional start/end indices restrict the comparison to the indicated sub bytevectors of bv.

Function bytevector-filter criterion bv :optional start end
Function bytevector-delete criterion bv :optional start end
Filter the bytevector bv, retaining only those elements that satisfy / do not satisfy the criterion argument.

criterion can be a u8 value, a u8 set or a procedure.

The optional start/end indices restrict the comparison to the indicated sub bytevectors of bv.

7.8(util concurrent) - Concurrency utilities

This library provides high level concurrency APIs.

Using low level thread and mutex sometimes causes dead lock or incomprehensible code. This library provides frameworks of common use cases. This library is built on top of SRFI-18.

7.8.1Future

A sub library of (util concurrent). This library provides future related APIs.

A future is an object that has a task which is a thunk and will be executed in future. In this implementation, future is an interface and its execution is depending on the sub class. The default implementation this library provides uses a thread per future. If users don't have to manage number of threads, then using this is sufficient.

(import (rnrs) (util concurrent))

;; creates 5 futures
(define futures
  (map (lambda (i) (future (* i i))) '(1 2 3 4 5)))

;; wait and retrieve the results
(map future-get futures)
=> (1 4 9 16 25)

Record <future>
The interface of all futures.

Function future? obj
Returns #t if given obj is a future object, otherwise #f.

Macro future expr ...
Macro future (class record)expr ...
Creates a future which executes expr. The type of the returning future is record.

The first form is equivalent with the following: (future (class <simple-future>) expr ...)

Function future-get future
Retrieves the result of the given future.

This procedure waits if the execution of the future isn't finished yet.

Function future-cancel future
Cancels the execution of future.

This procedure may or may not cancel the execution depending on the implementation of future. The <simple-future> provides by this library won't disturb the execution. Thus calling this procedure doesn't do anything but changing the future's state.

NOTE: once this procedure is called, then calling future-get with future raises a &future-terminated.

(import (rnrs) (util concurrent))

(define f (future (display "cancelled") (newline)))
(future-cancel f)
(future-get f)
=> &future-terminated

The above example may or may not print "cancelled".

Function future-done? future
Returns #t if given execution of future is finished, otherwise #f.

Function future-cancelled? future
Returns #t if given execution of future is terminated by future-cancel, otherwise #f.

Function future-state future
Returns current state of the given future.

The returning state is depending on the implementation of future. Only 2 states are defined in this library, done and terminated.

done is set when future-get is called.

terminated is set when future-cancel is called.

Condition Type &future-terminated
This type describes when a future is terminated but users try to retrieve its result.

Returns #t if given obj is object of &future-terminated.

Function terminated-future condition
condition must be a &future-terminated condition.

Retrieve terminated future from condition.

7.8.1.1Simple future

Simple future is a future implementation which executes the task on a thread immediately.

Default <future> implementation of this library.

Function simple-future? obj
Returns #t if given obj is a simple future, otherwise #f.

Creates a simple future which executes thunk.

7.8.2Executor

A sub library of (util concurrent). This library provides executor related APIs.

A executor is an object that executes submitted futures. The idea is taken from java.util.concurrent package. The library provides 2 types of executors, thread pool executor and fork join executor. The first one uses thread pool, described below section, and the latter one just creates a thread per task. The following is an example how to use the executors:

(import (rnrs) (util concurrent))

;; creates executor which uses 5 threads and push all tasks
(define executor 
  (make-thread-pool-executor 5 push-future-handler))

;; creates 10 futures
(define futures 
  (map (lambda (i) 
         (future (class <executor-future>)
           (* i i)))
       '(1 2 3 4 5 6 7 8 9 10)))

;; execute futures
(for-each (lambda (future) (execute-future! executor future)) futures)

;; wait/retrieve the results
(map future-get futures)
=> (1 4 9 16 25 36 49 64 81 100)

The thread pool executor with push-future-handler waits until the previous taskes are finished.

7.8.2.1Generic Executor APIs

Executor provided by this library is an extensible. So the most commonly used procedures are generic.

The interface of executor.

This record only has one field, state.

Function executor? obj
Returns #t if given obj is an executor, otherwise #f.

Function executor-state executor
Returns state field of the executor.

The behaviour of the folowing procedures depend on its implementation.

Function executor-available? executor
Returns #t if the given executor is available, otherwise #f.

Function execute-future! executor future
Executes given future on executor.

Function shutdown-executor! executor
Shutdowns the given executor.

This procedure may or may not affect the managed futures on the executor.

Function executor-submit! executor thunk
Converts thunk to a future and execute it on given executor, then returns the future. This procedure is defined as follows:

(define (executor-submit! e thunk)
  (let ((f (make-executor-future thunk)))
    (execute-future! e f)
    f))

7.8.2.2Thread pool executor

Thread pool executor uses (util concurrent thread-pool) as its underlying thread managing. So once the threads are created then the thread holds its environment until the executor is shutdown. In other words, if a task changes the dynamic environment, then the next task uses the changed dynamic environment. The following example describes how dynamic environments works on this executor:

(import (rnrs) (util concurrent) (srfi :39))

(define *one* (make-parameter 1))

(define executor (make-thread-pool-executor 1))

(let ((f1 (make-executor-future (lambda () (*one* 2) 1)))
      (f2 (make-executor-future (lambda () (*one*)))))
  (execute-future! executor f1)
  (future-get f1)
  (execute-future! executor f2)
  (future-get f2))
=> 2

NOTE: parameter objects are thread safe in general, thus if a thread is created per future, then the parameter *one* is initialised with the initial value 1 during thread creation.

Record type of thread pool executor. This record type inherits <executor>.

Returns #t if given obj is a thread pool executor, otherwise #f.

Function make-thread-pool-executor max-thread :optional reject-handler
Creates a thread pool executor with thread count max-thread.

If optional argument reject-handler is specified, then the specified handler is used. Otherwise, abort-rejected-handler is used.

Function thread-pool-executor-pool-size thread-pool-executor
Returns number of futures currently executing on the given thread pool executor.

This number would be greater than the thread count if push-future-handler is specified during the executor creation.

Function thread-pool-executor-max-pool-size thread-pool-executor
Returns number of thread count of the given thread pool executor.

Function thread-pool-executor-available? thread-pool-executor
Return #t if the number of executing future is less than the number of thread count.

NOTE: this procedure may return #f even tasks can be pushed to the executor if push-future-handler is specified.

Function thread-pool-executor-execute-future! thread-pool-executor future
Executes the given future on thread-pool-executor.

Function thread-pool-executor-shutdown! thread-pool-executor
Shutdown the given thread-pool-executor.

Builtin reject handlers.

Reject handler is a procedure called when thread pool executor is not available to decide how the executor should treat the given future.

Reject the future and raises &rejected-execution-error.

This is the default handler.

Terminates the oldest future.

When this handler is called, the thread which target future is running is also terminated. Thus the dynamic environment is also reset.

Function wait-finishing-handler wait-retry
Creats a reject handler which waits until one of the thread is available.

The wait-retry is a number of retry count. If none of future task is finished by this counter, then abort-rejected-handler is called.

Pushes the task to the least used thread.

A condition describes when a future is rejected by an executor.

Returns #t if given obj is &rejected-execution-error object. Otherwise #f.

Function rejected-future condition
Function rejected-executor condition
condition must be a &rejected-execution-error object.

Retrieves the rejected future and executor, respectively.

7.8.2.3Fork join executor

Fork join executor is an executor which simply creats a thread per future. It's almost the same as <simple-future>.

Record type of fork join executor. This record type inherits <executor>.

Returns #t if given obj is a fork join executor, otherwise #f.

Creates a fork join executor.

Function fork-join-executor-available? fork-join-executor
Returns #t.

Function fork-join-executor-execute-future! fork-join-executor future
Executes the given future on fork-join-executor.

NOTE: the executor doesn't manage anything so the future is actually not related to the executor.

Function fork-join-executor-shutdown! fork-join-executor
Sets executor's state shutdown.

7.8.2.4Executor future

An executor future is an future object which can be used on executor.

Record type of <executor-future>. This type inherits <future>.

Returns #t if the given obj is an executor future, otherwise #f.

Creates an executor future object.

7.8.3Thread pool

A sub library of (util concurrent). This library provides thread pool APIs.

Creating a thread is not cheap on Sagittarius. If users want to reuse threads, then this library can be used.

(import (rnrs) (util concurrent))

;; pooling 5 thread
(define thread-pool (make-thread-pool 5))

(for-each (lambda (i) (thread-pool-push-task! thread-pool (lambda () (* i i))))
	  '(1 2 3 4 5 6 7 8 9 10))

;; waits until all tasks are done
(thread-pool-wait-all! thread-pool)

;; release thread-pool
(thread-pool-release! thread-pool)

Record type of thread pool.

Function thread-pool? obj
Returns #t if given obj is a thread-pool, otherwise #f.

Function make-thread-pool thread-count :optional error-handler
Creates a thread pool with thread-count of threads.

If the optional argument error-handler is given, it must be a procedure which accept one argument, then the procedure is called when the pushed task raised an error.

Function thread-pool-size thread-pool
Returns number of threads on the given thread-pool.

Function thread-pool-push-task! thread-pool thunk
Push the given thunk to least used thread-pool's thread. And returns the id of the pushed thread. This id can be used to retrive the actual thread calling thread-pool-thread procedure.

Function thread-pool-wait-all! thread-pool
Waits all the tasks pushed into the given thread-pool.

The return value of the tasks are discarded.

Function thread-pool-release! thread-pool :optional how
Joins all the thread on the given thread-pool.

If optional argument how is specified terminate, then the procedure terminates the thread instead of joining.

NOTE: terminating a thread is very dangerous operation, so don't use casually.

Function thread-pool-thread thread-pool id
Retrieves the pooled thread associated with given id from given thread-pool.

It signals an error if the given id is not a thread id.

Function thread-pool-thread-id thread-pool thread
Retrieves the pooled thread id associated with given thread from given thread-pool. The procedure takes O(n) where n is number of threads managed by the thread-pool. It might be better to use (thread-pool-current-thread-id) procedure to retrieve thread id from managed threads.

It signals an error if the given thread is not a managed thread.

NOTE: if the thread is terminated, then the procedure also signals an error.

Retrieves thread id of current thread. If the current thread is not a managed thread, then #f is returned.

Function thread-pool-thread-terminate! thread-pool id
Terminates the pooled thread associated with given id and recreate a new thread into thread-pool.

NTOE: this is a dangerous operation. Don't use it casually.

Returns #t if the given id of thread in the thread-pool is running. Otherwise #f.

7.8.4Shared queues

A sub library of (util concurrent). This library provides shared queue APIs.

A shared queue is a queue whose operations are done atomically.

(import (rnrs) (util concurrent) (srfi :18))

(define shared-queue (make-shared-queue))

(define thread 
  (thread-start!
    (make-thread
      (lambda ()
        ;; waits until the queue has an element
        (let ((value (shared-queue-get! shared-queue)))
          (* value value))))))

(shared-queue-put! share-queue 5)

(thread-join! thread)
=> 25

Record type of shared queue.

Function shared-queue? obj
Returns #t if given obj is shared queue, otherwise #f.

Function make-shared-queue :optional (max-length -1)
Creates a shared queue.

If optional argument max-length is 0, then the queue can be used as synchronised queue. If the value is positive number, then the queue can only have specified number of elements. If it overflows, then it waits until the number of elements is less than max-length.

Function shared-queue-empty? shared-queue
Returns #t if the number of elements inside of shared-queue is 0. Otherwise #f.

Function shared-queue-size shared-queue
Returns the number of elements inside of shared-queue.

Function shared-queue-max-length shared-queue
Returns max length of shared-queue.

Function shared-queue-overflows? shared-queue count
Returns #t if putting count of element into shared-queue overflows. Otherwise #f.

Function shared-queue-get! shared-queue :optional (timeout #f) (timeout-val #f)
Retrieves the first element from shared-queue.

If the queue is empty and optional argument timeout is #f, then this procedure waits until the queue gets something.

If the optional argument timeout is specified, then the procedure only waits specified amount of time. timeout can be either integer or time object defined in SRFI-19. If the queue didn't get any object within the timeout, then timeout-val is returned.

Function shared-queue-put! shared-queue obj :optional (timeout #f) (timeout-val #f)
Puts obj into shared-queue and returns obj.

If the queue has max-length and overflows, then it wait until it's available.

If the optional argument timeout is specified, then the procedure only waits specified amount of time. timeout can be either integer or time object defined in SRFI-19. If the queue didn't get any object within the timeout, then timeout-val is returned.

Function shared-queue-remove! shared-queue obj :optional (= equal?)
Removes the given obj from the shared-queue. The procedure returns #t if obj is removed, otherwise #f.

Optional argument =, must be a comparison procedure, specifies how to compare the element of the shared-queue and given obj. Default value is equal?.

Function shared-queue-clear! shared-queue
Clears all element inside of shared-queue.

Function shared-queue-find shared-queue pred
Finds an elements which satisfies pred. This operations locks the given shared-queue.

Function shared-queue-locked? shared-queue :optional (wait? #f)
Returns #t if the given shared-queue is locked by other thread, otherwise #f.

If the optional argument wait? is given, then the procedure waits until the queue is available and returns #f.

7.9(crypto) - Cryptographic library

This documentation does not describe cryptography itself. For example, it does not describe what initial vector is and how long it must be. So users must know about cryptography's this library supports.

This library uses libtomcrypt's functionalities. The library is public domain. Thank you for the great library.

Note: the libtomcrypt is a huge cryptographic library and I am not so good with cryptographics, so the (crypto) library is not totally tested. Just the functionalities which I usually use are tested. If you find a bug or wrong documentation, pleas report it.

Library (crypto)
This library is the top most library, it exports all the other libraries procedures. Users must import only this and not to use the others.

(crypto) library supports both symmetric cryptography and public/private key mechanism. For public/private key, it only supports RSA for now.

Function crypto-object? obj
Returns #t if obj is crypto-object.

crypto-object can be either cipher or key.

7.9.1Cipher operations

Function make-cipher type key mode :key (mode-parameter #f) :allow-other-keys :rest options
Creates a cipher object.

type must be known cryptographic algorithm. Currently, (crypto) library exports the algorithm below.

The symmetric key algorithms.

Constant Blowfish
Constant X-Tea
Constant RC2
Constant RC5-32/12/b
Constant RC6-32/20/b
Constant SAFER+
Constant SAFER-K64
Constant SAFER-SK64
Constant SAFER-K128
Constant SAFER-SK128
Constant AES
Constant Twofish
Constant DES
Constant DES3
Constant DESede
Constant CAST5
Constant CAST-128
Constant Noekeon
Constant Skipjack
Constant Khazad
Constant SEED
Constant KASUMI
Constant Camellia

The public key algorithm

Constant DSA
Constant ECDSA
Constant RSA

key must be a key object which will be created by key generate procedures described below.

mode specifies the symmetric cipher's encryption and description mode. If the cipher type is public key cipher, it will be ignored. Some modes require initial vector iv. The possible mods are below.

Constant MODE_ECB
Constant MODE_CBC
Constant MODE_CFB
Constant MODE_OFB
Constant MODE_CTR
Constant MODE_GCM

The keyword argument mode-parameter is specified, it must be a mode parameter object, then the object will be parsed properly by the cipher.

Function cipher-keysize cipher test
Returns given cipher type's recommended keysize.

cipher must cipher object created by cipher procedure.

test must be fixnum.

If test is too small for the cipher, it will raise an error.

Note: this procedure is for helper. It is designed to use check keysize you want to use.

Function cipher? obj
Returns #t if the obj is cipher object.

Function cipher-encrypt cipher pt
cipher must be a cipher object.

pt must be a bytevector.

encrypt encrypts given plain text pt according to the given cipher.

Function cipher-encrypt/tag cipher pt :key tag-size
Similar with cipher-encrypt. The difference is that this procedure returns 2 values, encrypted pt and calculated tag if the given cipher supports authentication.

If the keyword argument tag-size is specified and must be an integer, then the returning tag has the specified size. If the cipher supports less size than the specified size, then the remaining tag contains unspecified value. To retrieve the maximum length of tag, use cipher-max-tag-size.

Function cipher-decrypt cipher ct
cipher must be a cipher object.

ct must be a bytevector.

decrypt decrypts given encrypted text ct according to the given cipher.

Function cipher-decrypt/tag cipher ct :key tag-size
Similar with cipher-decrypt. The difference is that this procedure returns 2 values, decrypted ct and calculated tag if the given cipher supports authentication.

If the keyword argument tag-size is specified and must be an integer, then the returning tag has the specified size. If the cipher supports less size than the specified size, then the remaining tag contains unspecified value. To retrieve the maximum length of tag, use cipher-max-tag-size.

Function cipher-decrypt/verify cipher ct tag
Similar with cipher-decrypt. The difference is that this procedure validates the calculated tag. If the given tag and calculated tag are not the same, then &decrypt is raised.

NOTE: if the tag is *not* calculated by the cipher, then this procedure always raises an error.

Function cipher-max-tag-size cipher
Returns the maximum length of tag size.

If the given cipher does not support authentication tag, then returning value is 0.

Function cipher-update-aad! cipher aad
Updates the additional authentication data.

Function cipher-tag! cipher dst
dst must be a bytevector.

Retrieves the authentication tag from given cipher.

NOTE: this procedure must be called after either cipher-encrypt or cipher-decrypt. Otherwise the filled value is unspecified.

Function cipher-tag cipher :key size
Retrieves the authentication tag from given cipher.

If the keyword argument size is specified, then the returning bytevector has the size length, otherwise maximum tag length.

NOTE: this procedure must be called after either cipher-encrypt or cipher-decrypt. Otherwise the filled value is unspecified.

Function cipher-signature public-cipher data :optional opt
public-cipher must be a cipher object created with public/private key algorithm.

data must be a bytevector.

Signs given data. This procedure is just a wrapper for the real implementations. Currently Sagittarius supports only RSA sign.

opt can specify the signer behaviour. Default supported RSA cipher can accept keyword argument encode.

encode specifies the encoder. The default encoder is pkcs1-emsa-pss-encode. And the rest keyword arguments will be passed to encoder. Supported encoders are described below.

Function cipher-verify public-cipher M S :optional opt
public-cipher must be a cipher object created with public/private key algorithm.

M and S must be bytevectors.

M is master message which will be compared with encoded message.

S is signed message.

The verity procedure verifies two messages.

opt can specify the verifier behaviour. Default supported RSA cipher can accept keyword argument verify.

verify specifies the verifier. The defaule verifier is pkcs1-emsa-pss-verify. And the rest keyword arguments will be passed to verifier. Supported verifiers are described below.

7.9.2Mode parameters

Mode parameters are pareters which can be used by specified mode. For example, iv-parameter is a parameter contains an IV.

Returns #t if the given obj is a mode parameter, otherwise #f.

Function make-composite-parameter parameters ...
Creates a composite mode parameter.

A composite parameter can hold multiple parameters.

Record Type <iv-paramater>
Record type for initial vector (IV) parameter.

iv must be a bytevector or #f.

Creates an IV mode parameter.

IV is required by some modes. e.g. MODE_CBC.

Record Type <ctr-paramater>
Record type for counter mode parameter.

This parameter is a subclass of <iv-parameter>.

Function make-ctr-paramater iv :key (rounds 0) (mode CTR_COUNTER_BIG_ENDIAN)
Creates a counter mode parameter. This is used by MODE_CTR.

iv is passed to parent constructor.

The followings are description of keyword parameters.

rounds specify how many times the cipher rounds the key.

ctr-mode specifies counter mode. The possible mode is blow.

Constant