14. SRFIs

Scheme Request For Implementation (SRFI) process grew out of the Scheme Workshop held in Baltimore, MD, on September 26, 1998, where the attendees considered a number of proposals for standardized feature sets for inclusion in Scheme implementations. Many of the proposals received overwhelming support in a series of straw votes. Along with this there was concern that the next Revised Report would not be produced for several years and this would prevent the timely implementation of standardized approaches to several important problems and needs in the Scheme community.

Only the implemented SRFIs are (briefly) presented here. For further information on each SRFI, please look at the official SRFI site.

14.1. Supported SRFIs

STklos supports 104 finalized SRFIS. Some of these SRFIS are embedded and some are external.

An embedded SRFI can be directly used without any particular action, whereas an external needs to be loaded before use.

The following SRFIS are implemented:

- SRFI-0 — Feature-based conditional expansion construct
- SRFI-1 — List Library
- SRFI-2 — AND-LET*: an AND with local bindings, a guarded LET* special form
- SRFI-4 — Homogeneous numeric vector datatypes
- SRFI-5 — A compatible let form with signatures and rest arguments
- SRFI-6 — Basic String Ports
- SRFI-7 — Feature-based program configuration language
- SRFI-8 — Receive: Binding to multiple values
- SRFI-9 — Defining Record Types
- SRFI-10 — Sharp Comma External Form
- SRFI-11 — Syntax for receiving multiple values
- SRFI-13 — String Library
- SRFI-14 — Character-Set Library
- SRFI-15 — Syntax for dynamic scoping (withdrawn)
- SRFI-16 — Syntax for procedures of variable arity
- SRFI-17 — Generalized set!
- SRFI-18 — Multithreading support
- SRFI-22 — Running Scheme Scripts on Unix
- SRFI-23 — Error reporting mechanism
- SRFI-25 — Multi-dimensional Arrays
- SRFI-26 — Notation for Specializing Parameters without Currying
- SRFI-27 — Source of random bits
- SRFI-28 — Basic Format Strings
- SRFI-29 — Localization
- SRFI-30 — Nested Multi-line Comments
- SRFI-31 — A special form for recursive evaluation
- SRFI-34 — Exception Handling for Programs
- SRFI-35 — Conditions
- SRFI-36 — I/O Conditions
- SRFI-37 — args-fold: a program argument processor
- SRFI-38 — External representation of shared structures
- SRFI-39 — Parameters objects
- SRFI-41 — Streams
- SRFI-45 — Primitives for Expressing Iterative Lazy Algorithms
- SRFI-48 — Intermediate Format Strings
- SRFI-51 — Handling rest list
- SRFI-54 — Formatting
- SRFI-55 — Require-extension
- SRFI-59 — Vicinity
- SRFI-60 — Integers as bits
- SRFI-61 — A more general COND clause
- SRFI-62 — S-expression comments
- SRFI-64 — A Scheme API for test suites
- SRFI-66 — Octet Vectors
- SRFI-69 — Basic Hash Tables
- SRFI-70 — Numbers
- SRFI-74 — Octet-Addressed Binary Blocks
- SRFI-87 — ⇒ in case clauses
- SRFI-88 — Keyword Objects
- SRFI-89 — Optional Positional and Named Parameters
- SRFI-94 — Type-Restricted Numerical Functions
- SRFI-96 — SLIB Prerequisites
- SRFI-98 — Interface to access environment variables
- SRFI-100 — define-lambda-object
- SRFI-111 — Boxes
- SRFI-112 — Environment Inquiry
- SRFI-113 — Sets and Bags
- SRFI-117 — Queues based on lists
- SRFI-118 — Simple adjustable-size strings
- SRFI-127 — Lazy Sequences
- SRFI-128 — Comparators (reduced)
- SRFI-129 — Titlecase procedures
- SRFI-130 — Cursor-based string library
- SRFI-132 — Sort Libraries
- SRFI-133 — Vector Library (R7RS-compatible)
- SRFI-134 — Immutable Deques
- SRFI-135 — Immutable Texts
- SRFI-137 — Minimal Unique Types
- SRFI-138 — Compiling Scheme programs to executables
- SRFI-141 — Integer Division
- SRFI-143 — Fixnums
- SRFI-144 — Flonums
- SRFI-145 — Assumptions
- SRFI-151 — Bitwise Operations
- SRFI-154 — First-class dynamic extents
- SRFI-156 — Syntactic combiners for binary predicates
- SRFI-158 — Generators and Accumulators
- SRFI-161 — Unifiable Boxes
- SRFI-169 — Underscores in numbers
- SRFI-170 — POSIX API
- SRFI-171 — Transducers
- SRFI-173 — Hooks
- SRFI-174 — POSIX Timespecs
- SRFI-175 — ASCII character library
- SRFI-176 — Version flag
- SRFI-180 — JSON
- SRFI-185 — Linear adjustable-length strings
- SRFI-189 — Maybe and Either: optional container types
- SRFI-190 — Coroutines Generators
- SRFI-192 — Port Positioning
- SRFI-193 — Command line
- SRFI-195 — Multiple-value boxes
- SRFI-196 — Range Objects
- SRFI-207 — String-notated bytevectors
- SRFI-208 — NaN procedures
- SRFI-214 — Flexvectors
- SRFI-215 — Central Log Exchange
- SRFI-216 — SICP Prerequisites (Portable)
- SRFI-217 — Integer Sets
- SRFI-219 — Define higher-order lambda
- SRFI-223 — Generalized binary search procedures
- SRFI-224 — Integer Mappings
- SRFI-229 — Tagged Procedures
- SRFI-230 — Atomic Operations

14.2. Using a SRFI

Using a particular SRFI can be done with the special form cond-expand defined in SRFI-0 which is fully supported by STklos. This form accepts features identifiers which are of the form srfi-n where n represents the number of the SRFI supported by the implementation (for instance srfi-1 or srfi-30).

For instance, to use srfi-n, you can use

(cond-expand
 (srfi-n))

This forms does nothing if srfi-n is an embedded SRFI and ensures that all the files needed by this SRFI will be properly loaded if it is an external SRFI.

STklos also offers the primitive require-feature which ensures (eventually) the loading of files needed to use a given SRFI. This primitive accepts several forms to ensure that the SRFI can be used. For instance, to use SRFI-1 (List Library), the following forms are possible:

(require-feature 'srfi-1)
(require-feature "srfi-1")
(require-feature 1)
(require-feature 'lists)   ;; Since this feature name is an alias for SRFI-1

The list of the aliases defined for the supported SRFIs is given in Table 2.

14.2.1. Embedded SRFIs

As said before, an embedded SRFI can be used directly without loading a support file. (Note that using require-feature works too and permits to ignore if the SRFI is embedded).

List of embedded SRFIs: srfi-0 srfi-6 srfi-8 srfi-10 srfi-11 srfi-15 srfi-16 srfi-18 srfi-22 srfi-23 srfi-28 srfi-30 srfi-31 srfi-34 srfi-38 srfi-39 srfi-45 srfi-55 srfi-62 srfi-70 srfi-87 srfi-88 srfi-98 srfi-111 srfi-112 srfi-118 srfi-138 srfi-143 srfi-145 srfi-169 srfi-176 srfi-192 srfi-193 srfi-195 srfi-208 srfi-219

14.2.2. External SRFIs

An external SRFI needs to load at least one external file. This can be done with require or require-feature. As with embedded SRFIS, using require-feature permits to ignore if the SRFI is external.

List of external SRFIs: srfi-1 srfi-2 srfi-4 srfi-5 srfi-7 srfi-9 srfi-13 srfi-14 srfi-17 srfi-25 srfi-26 srfi-27 srfi-29 srfi-35 srfi-36 srfi-37 srfi-41 srfi-48 srfi-51 srfi-54 srfi-59 srfi-60 srfi-61 srfi-64 srfi-66 srfi-69 srfi-74 srfi-89 srfi-94 srfi-96 srfi-100 srfi-113 srfi-117 srfi-127 srfi-128 srfi-129 srfi-130 srfi-132 srfi-133 srfi-134 srfi-135 srfi-137 srfi-141 srfi-144 srfi-151 srfi-154 srfi-156 srfi-158 srfi-161 srfi-170 srfi-171 srfi-173 srfi-174 srfi-175 srfi-180 srfi-185 srfi-189 srfi-190 srfi-196 srfi-207 srfi-214 srfi-215 srfi-216 srfi-217 srfi-223 srfi-224 srfi-229 srfi-230

14.2.3. SRFI features

For some SRFIs, STklos accepts that uses them with a name. This names are given Table 2.

Table 2. Feature identifiers
symbol require SRFI(s)

lists

srfi-1

and-let*

srfi-2

hvectors

srfi-4

program

srfi-7

records

srfi-9

case-lambda

srfi-16

error

srfi-23

random

srfi-27

args-fold

srfi-37

parameters

srfi-39

streams

srfi-41

rest-list

srfi-51

formatting

srfi-54

testing

srfi-64

hash-tables

srfi-69

boxes

srfi-111

sets-bags

srfi-113

queues-as-lists

srfi-117

adjustable-strings

srfi-118

lazy-sequences

srfi-127

comparators-reduced

srfi-128

titlecase

srfi-129

sort

srfi-132

vector

srfi-133

immutable-deques

srfi-134

immutable-texts

srfi-135

integer-division

srfi-141

bitwise-ops

srfi-151

posix

srfi-170

transducers

srfi-171

hooks

srfi-173

posix-timespecs

srfi-174

ascii

srfi-175

JSON

srfi-180

maybe-either

srfi-189

conditions

srfi-35 srfi-36

generators

srfi-158 srfi-190

14.3. Misc. Information

Previous section described the general way to use the SRFIS implemented in STklos. This section concentrates on information not given above.

srfi-0 — Feature-based conditional expansion construct

SRFI-0 defines the cond-expand special form. It is fully supported by STklos. STklos defines several features identifiers which are of the form srfi-n where n represents the number of the SRFI supported by the implementation (for instance srfi-1 or srfi-30).

STklos cond-expand accepts also some feature identifiers which are the same that the ones defined in Table 2, such as case_lambda or generators.

Furthermore, the feature identifier stklos and STklos are defined for applications which need to know on which Scheme implementation they are running on.

srfi-10 — Sharp Comma External Form

SRFI-10 is fully supported. This SRFI extends the STklos reader with the #, notation which is fully described in this document (see primitive define-reader-ctor).

srfi-16 — Syntax for procedures of variable arity

SRFI-16 is fully supported. Note that case-lambda is now defined in R7RS.

srfi-17 — Generalized set!

SRFI-17 is fully supported. See the documentation of procedures set! and setter. However, requiring explicitly srfi-17 permits to define the setters for the (numerous) cXXXXr list procedures.

srfi-22 — Running Scheme Scripts on Unix

SRFI-22 describes basic prerequisites for running Scheme programs as Unix scripts in a uniform way. Specifically, it describes:

  • the syntax of Unix scripts written in Scheme,

  • a uniform convention for calling the Scheme script interpreter, and

  • a method for accessing the Unix command line arguments from within the Scheme script.

SRFI-22 (Running Scheme Scripts on Unix) recommends to invoke the Scheme script interpreter from the script via a /usr/bin/env trampoline, like this:

#!/usr/bin/env <executable>

where <executable> can recover several specified names. STklos uses only the name stklos-script for <executable>.

Here is an example of the classical echo command (without option) in Scheme:

#!/usr/bin/env stklos-script

(define (main arguments)
  (for-each (lambda (x) (display x) (display #\space))
            (cdr arguments))
  (newline)
  0)

srfi-23 — Error reporting mechanism

SRFI-23 is fully supported. Note that the STklos error is more general than the one defined in SRFI-23.

srfi-25 — Multi-dimensional Arrays

STklos implements the arrays of SRFI-25. All the forms defined in the SRFI are implemented in STklos, but some other functions, not present in the SRFI, are documented here.

STklos procedure

(shape? obj)

Checks if obj is an array shape. SRFI-25 dictates that a shape is an ordinary array, with rank two and shape (0 r 0 2), where r is the rank of the array that the shape describes. So, any array of shape (0 r 0 2 is a shape, for any non-negative integer r.

STklos procedure

(shared-array? array)

Will return #t when the array has its data shared with other arrays, and #f otherwise.

STklos procedure

(shape-for-each shape proc [index-object])

This procedure will apply proc to all valid sequences of indices in shape, in row-major order.

If index-object is not provided, then proc must accept as many arguments as the number of dimensions that the shape describes.

(shape-for-each (shape 1 3 10 12)
                (lambda (x y)
                  (format #t "[~a ~a]~%" x y)))
        |- [1 10]
           [1 11]
           [2 10]
           [2 11]

If index-object is provided, it is used as a place to store the indices, so proc must accept either a vector or an array (this is to avoid pushing and popping too many values when calling proc). index-object, when present, must be aither a vector or array.

(let ((vec (make-vector 2 #f)))
  (shape-for-each (shape 1 3 10 12)
                  (lambda (o)
                    (format #t "[~a ~a]~%"
                    (vector-ref o 0)
                    (vector-ref o 1)))
                  vec))
        |- [1 10]
           [1 11]
           [2 10]
           [2 11]

(let ((arr (make-array (shape 0 2))))
  (shape-for-each (shape 1 3 10 12)
                  (lambda (o)
                    (format #t "[~a ~a]~%"
                    (array-ref o 0)
                    (array-ref o 1)))
                  arr))
         |- [1 10]
            [1 11]
            [2 10]
            [2 11]

STklos procedure

(share-nths a d n)

Share-nths takes every n`th slice along dimension `d into a shared array. This preserves the origin.

(define a (array (shape 0 4 0 4)
                 -1 -2 -3 -4
                 -5 -6 -7 -8
                 -9 -10 -11 -12
                 -13 -14 -15 -16))

(share-nths a 0 2)
 => #,(<array> (0 2 0 4) -1  -2  -3  -4
                         -9 -10 -11 -12)

(share-nths a 1 2)
 => #,(<array> (0 4 0 2) -1  -3  -5  -7
                         -9 -11 -13 -15)

STklos procedure

(share-column arr k)

Shares whatever the second index is about. The result has one dimension less.

(define a (array (shape 0 2 0 2 0 2) -1 -2 -3 -4 -5 -6 -7 -8))

(share-column a 1) => #,(<array> (0 2 0 2) -3 -4 -7 -8)
(share-column a 0) => #,(<array> (0 2 0 2) -1 -2 -5 -6)

STklos procedure

(share-row arr k)

Shares whatever the first index is about. The result has one dimension less.

(define a (array (shape 0 2 0 2 0 2) -1 -2 -3 -4 -5 -6 -7 -8))

(share-row a 0) => #,(<array> (0 2 0 2) -1 -2 -3 -4)
(share-row a 1) => #,(<array> (0 2 0 2) -5 -6 -7 -8)

STklos procedure

(share-array/origin arr k …​)
(share-array/origin arr index)

change the origin of arr to k …​, with index a vector or zero-based one-dimensional array that contains k …​

(define a (array (shape 0 2 0 2 ) -1 -2 -3 -4))

(share-array/origin  a 1 1) => #,(<array> (1 3 1 3) -1 -2 -3 -4)

STklos procedure

(array-copy+share array)

Returns a copy of array. If array does not have its own internal data, but was built using share-array, then the new array will be similar — it will be a copy of array, sharing the elements in the same way.

STklos procedure

(array-size array)

Returns the number of elements in array.

STklos procedure

(array-shape array)

Returns the shape of array.

STklos procedure

(array→list array)

Returns a list that contains a copy of the elements of array, in row-major order. This is not recursive, and will not flatten the array.

STklos procedure

(array→vector array)

Returns a vector that contains a copy of the elements of array, in row-major order. The new vector does not share elements with the original array (it is a fresh copy). This is not recursive, and will not flatten the array.

STklos procedure

(array-length array dim)

Returns the length of dimension dim in array array.

STklos procedure

(array-map [shape] proc arr0 arr1 …​)

This procedure is similar to map for lists: it will run proc on an element of each of the arr0, arr1, …​ arguments, storing the result in the equivalent position of a newly created array.

The shapes of the arrays must be the same.

The procedure will create a new array with shape shape (or arr0's shape, if shape was not specified).

STklos procedure

(array-map! array [shape] proc arr0 arr1 …​)

For each valid index idx, applies proc to the corresponding position in arr0, arr1, …​ and then sets the same place in array to the result.

If shape is specified, it should specify a subarray of array, and only that section will be mapped.

STklos procedure

(array-append dim arr1 arr2 …​)

Appends arrays arr1, arr2, …​ along the specified dimension dim. The arrays must have equally many dimensions and all other dimensions equally long.

(define a (array (shape 0 2 0 3) 11 22 33 44 55 66))
(define b (array (shape 0 3 0 3) -11 -22 -33 -44 -55 -66 -77 -88 -99))
(define c (array (shape 0 1 0 3) 'a 'b 'c))

(array-append 0 a b c) =>  #,(<array> (0 6 0 3)
                                      11  22  33
                                      44  55  66
                                     -11 -22 -33
                                     -44 -55 -66
                                     -77 -88 -99
                                       a   b   c)

STklos procedure

(array-share-count array)

Returns the number of arrays that were built sharing array's elements through (share-array array shape proc), and that were not yet garbage collected. Note that it may take a long time for an object to be garbage collected automatically. It is possible to force a garbage collection pass by calling (gc), but even that does not guarantee that a specific object will be collected.

STklos procedure

(array-copy array)

Returns a copy of array. The new copy will have no data shared with any other array, even if the argument array did.

STklos procedure

(array-for-each-index arr proc [index-object])

Will loop through all valid indices of array, applying proc to those indices.

If index-object is not provided, then proc must accept as many arguments as the number of dimensions that the shape describes.

If index-object is provided, it is used as a place to store the indices, so proc must accept a vector or an array (this is to avoid pushing and popping too many values when calling proc). index-object, when present, must be aither a vector or array.

See the documentation of shape-for-each for more information on index-object.

STklos procedure

(tabulate-array shape proc)
(tabulate-array shape proc idx)

Returns a new array of shape shape, populated according to proc. Each valid index in shape is passed to proc, and the result is place in the according array position.

idx is an object that may be used to store the indices, and it may be either a vector or an array. If it is not present, or if it is #f, then an index vector will be created internally.

STklos procedure

(array-retabulate! arr shp proc [index-object])

Sets the elements of arr in shape to the value of proc at that index, using index-object if provided. This is similar to tabulate-array!, except that the array is given by the user.

(define arr (array (shape 0 2 0 2) 'a 'b 'c 'd))
(array-retabulate! arr (shape 0 2 0 2) (lambda (x y) (+ 1 x y)))
arr => #,(<array> (0 2 0 2) 1 2 2 3)

STklos procedure

(transpose arr k …​)

Shares arr with permuted dimensions. Each dimension from 0 inclusive to rank exclusive must appear once in k …​

This is a generalized transpose. It can permute the dimensions any which way. The permutation is provided by a permutation matrix: a square matrix of zeros and ones, with exactly one one in each row and column, or a permutation of the rows of an identity matrix; the size of the matrix must match the number of dimensions of the array.

The default permutation is [ 0 1 , 1 0 ] of course, but any permutation array can be specified, and the shape array of the original array is then multiplied with it, and index column vectors of the new array with its inverse, from left, to permute the rows appropriately.

(transpose (array (shape 0 4 0 4)
                  -1  -2   -3  -4
                  -5  -6   -7  -8
                  -9  -10 -11 -12
                  -13 -14 -15 -16))
 => #,(<array> (0 4 0 4)
              -1 -5  -9 -13
              -2 -6 -10 -14
              -3 -7 -11 -15
              -4 -8 -12 -16)

(transpose (array (shape 0 3 0 3 0 2)
                  -1 -2
                  -3 -4
                  -5 -6

                  -7 -8
                  -9 -10
                  -11 -12

                  -13 -14
                  -15 -16
                  -17 -18))
 => #,(<array> (0 2 0 3 0 3)
               -1  -7 -13
               -3  -9 -15
               -5 -11 -17

               -2  -8 -14
               -4 -10 -16
               -6 -12 -18)

srfi-27 — Source of random bits

SRFI-27 is fully supported. Using primitives random-integer or random-real automatically load this SRFI.

srfi-28 — Basic Format Strings

SRFI-28 is fully supported. Note that STklos format is more general than the one defined this SRFI.

srfi-35 — Conditions

SRFI-35 is fully supported. See Section 7.3 for the predefined conditions and when it is required to load this file.

srfi-36 — I/O Conditions

SRFI-36 is fully supported. See Section 7.3 Conditions) for the predefined conditions and when it is required to load this file.

srfi-55 — Require-extension

SRFI-55 is fully supported. Furthermore, STklos also accepts the symbols defined in Table 2 in a require-extension clause.

srfi-69 — Basic Hash Tables

SRFI-69 is fully supported. Note that the default comparison function in STklos is eq? whereas it is equal? for the SRFI. Furthermore the hash functions defined in the SRFI are not defined by default in STklos. To have a fully compliant SRFI-69 behaviour, you need use a require-feature in your code.

srfi-88 — Keyword Objects

SRFI-88 is fully supported. The only difference between the keywords defined in the SRFI document and the STklos keywords is on the zero-length keyword: For STklos, : is equivalent to the keyword #:||, whereas the SRFI considers that : is not a keyword but a symbol.

To obtain the symbol : in STklos, you must use |:|.

srfi-138 — Compiling Scheme programs to executables

SRFI-138 is fully supported. The stklos-compile program conforms to SRFI 138, accepting all the required command line options.

The -D x flag of stklos-compile will define a feature named x for use with cond-expand in the compiled code only. It will not include x in the features list of the runtime.

srfi-145 — Assumptions

SRFI-145 is fully supported. See the assume special form.

srfi-169 — Underscores in numbers

SRFI-169 is fully supported. See parameter accept-srfi-169-numbers to eventually forbid the usage of underscores in numbers.


1. Documentation about hygienic macros has been stolen in the SLIB manual
1. In fact define-module on a given name defines a new module only the first time it is invoked on this name. By this way, interactively reloading a module does not define a new entity, and the other modules which use it are not altered.
2. This transcript uses the default toplevel loop which displays the name of the current module in the evaluator prompt.
1. Under Unix, you can simply connect to a listening socket with the telnet of netcat command. For the given example, this can be achieved with netcat localhost 12345
2. Port 13, if open, can used for testing: making a connection to it permits to know the distant system’s idea of the time of day.
1. This section is an adaptation of Jeff Dalton’s (J.Dalton@ed.ac.uk) "Brief introduction to CLOS" which can be found at http://www.aiai.ed.ac.uk/~jeff/clos-guide.html