For Development HEAD DRAFTSearch (procedure/syntax/module):

10.2 R7RS small language


10.2.1 R7RS library form

R7RS libraries are defined by define-library form.

In R7RS view, define-library form itself does not belong to a Scheme code—it exists outside of the Scheme world. It defines the boundary of R7RS Scheme; inside define-library there is R7RS world, but outside, it’s not a business of R7RS. For example, you can’t generate define-library by a macro, within R7RS specification.

In Gauche, we implement R7RS world inside Gauche world; define-library itself is interpreted in the Gauche world. In fact, define-library is a Gauche macro. However, if you’re writing portable R7RS code, you should forget how define-library is implemented, and do not put anything outside of define-library form.

Macro: define-library library-name library-decl …

[R7RS] Defines a library library-name, which is a list of symbols or base-10 integer:

<library-name> : (<identifier-or-base-10-integer>
                  <identifier-or-base-10-integer> ...)

Library declarations library-decl can be export declarations, import declarations, begin-list of Scheme code, include forms, or cond-expand forms.

<library-decl> : (export <export-spec> ...)
               | <import declaration>
               | (begin <command-or-definition> ...)
               | (include <string> <string2> ...)
               | (include-ci <string> <string2> ...)
               | (include-library-declarations
                        <string> <string2> ...)
               | (cond-expand <cond-expand-clause>
                              <cond-expand-clause2> ...)
               | (cond-expand <cond-expand-clause>
                              <cond-expand-clause2> ...
                              (else <library-decl> ...))

The export declaration is the same Gauche’s export form; see Using modules.

The import declaration is R7RS’s import form, described in Three import forms.

The include and include-ci declarations are the same as Gauche’s; see Inclusions. Note that Gauche allows any code to be included—the content of the named file is simply wrapped with begin and substituted with these forms—but in R7RS definition, what you include must contain only Scheme code (not one of the library declarations or define-library form).

The include-library-declarations declaration works like include, but the content of the read file is interpreted as library declarations instead of Scheme code.

The cond-expand declaration is also the same as Gauche’s; see Feature conditional. When used directly below define-library, it must expands to one of the library declarations.


10.2.2 scheme.base - R7RS base library

Module: scheme.base

Exports bindings of R7RS (scheme base) library. From R7RS programs, those bindings are available by (import (scheme base)).

Bindings common to Gauche’s built-ins

The following syntaxes and procedures are the same as Gauche’s builtins:

Primitive expression types
quote if include include-ci
Derived expression types
cond case and or when unless cond-expand let let* letrec letrec*
let-values let*-values begin do make-parameter parameterize
guard quasiquote unquote unquote-splicing case-lambda
Macros
let-syntax letrec-syntax syntax-rules syntax-error define-syntax
Variable definitions
define-values
Record type definitions
define-record-type
Equivalence predicates
eqv? eq? equal?
Numbers
number? complex? real? rational? integer? exact? exact-integer?
= < > <= >= zero? positive? negative? odd? even? max min + * - / abs
floor/ floor-quotient floor-remainder
truncate/ truncate-quotient truncate-remainder
quotient modulo remainder gcd lcm numerator denominator
floor ceiling truncate round rationalize square exact-integer-sqrt
expt inexact exact number->string string->number
Booleans
not boolean? boolean=?
Pairs and lists
pair? cons car cdr set-car! set-cdr! caar cadr cdar cddr null? list?
make-list list length append reverse list-tail list-ref list-set!
memq memv member assq assv assoc list-copy
Symbols
symbol? symbol=? symbol->string string->symbol
Characters
char? char=? char<? char>? char<=? char>=? char->integer integer->char
Strings
string? make-string string string-length string-ref string-set!
string=? string<? string>? string<=? string>=? substring string-append
string->list list->string string-copy string-copy! string-fill!
string-map string-for-each
Vectors
vector? make-vector vector vector-length vector-ref vector-set!
vector->list list->vector vector->string string->vector
vector-copy vector-copy! vector-append vector-fill!
Control features
procedure? apply map call-with-current-continuation call/cc
values call-with-values dynamic-wind
Exception
error
Environments and evaluation
scheme-report-environment null-environment
Input and output
input-port? output-port? port? current-input-port current-output-port
current-error-port close-port close-input-port close-output-port
open-input-string open-output-string get-output-string
read-char peek-char read-u8 peek-u8
read-line eof-object? eof-object char-ready? u8-ready?
newline write-char write-u8

The following two identifiers are the ones bound in the scheme module, which differ from the ones bound in the gauche module. Notably, these don’t recognize Gauche’s extended lambda arguments (:key, :optional, etc.).

define lambda

Bytevector utilities

R7RS’s bytevectors are the same as Gauche’s u8vectors.

The following procedures are the same as gauche.uvector’s (see Bytevector compatibility).

bytevector         bytevector?       make-bytevector
bytevector-length  bytevector-u8-ref bytevector-u8-set!
bytevector-copy    bytevector-copy!  bytevector-append
read-bytevector    read-bytevector!  write-bytevector

The following procedures are the same as gauche.vport’s (see gauche.vport - Virtual ports).

open-input-bytevector open-output-bytevector get-output-bytevector

And the following procedures are the same as gauche.unicode’s (see Unicode transfer encodings).

utf8->string       string->utf8

Control features

The procedure with-exception-handler is the same as Gauche’s built-in. See Low-level exception handling mechanism, for the explanation.

Function: raise obj
Function: raise-continuable obj

[R7RS base] {scheme.base} Gauche’s raise may return if obj isn’t a <serious-condition>. Distinguishing continuable and noncontinuable exception throw by the procedure has an issue when your exception handler wants to reraise the condition (you don’t know if the original condition is raised by raise or raise-continuable!). Yet R7RS adopted that model, so we compel.

R7RS raise is a wrapper of Gauche’s raise, which throws an error if Gauche’s raise returns.

R7RS raise-continuable is currently just an alias of Gauche’s raise—as long as you don’t pass <serious-condition>, it may return. It is not exactly R7RS conformant—it won’t return if you pass <serious-condition> or object of one of its subclasses (e.g. <error>), but it’s weired to expect returning from raising <error>, isn’t it?

Function: error-object? exc

[R7RS base] {scheme.base} Defined as (condition-has-type? exc <error>))

Function: error-object-message exc

[R7RS base] {scheme.base} If exc is a <message-condition>, returns its message-prefix slot; otherwise, returns an empty string.

Function: error-object-irritants exc

[R7RS base] {scheme.base} If exc is a <message-condition>, returns its message-args slot; otherwise, returns an empty string.

Function: read-error? exc

[R7RS base] {scheme.base} Defined as (condition-has-type? e <read-error>)).

Function: file-error? exc

[R7RS base] {scheme.base} At this moment, Gauche doesn’t have distinct <file-error> condition, but most file errors are thrown as one of <system-error>s. This procedure checks error code of <system-error> and returns #t if the error is likely to be related to the filesystem.

Input and output

Function: textual-port? port
Function: binary-port? port

[R7RS base] {scheme.base} Gauche’s port can handle both, so these are equivalent to port?.

Function: input-port-open? iport
Function: output-port-open? oport

[R7RS base] {scheme.base} Checks whether iport/oport is an input/output port and it is not closed.

Function: flush-output-port :optional oport

[R7RS base] {scheme.base} An alias to flush (see Low-level output).

Function: features

[R7RS base] {scheme.base} Returns a list of symbols of supported feature identifiers, recognized by cond-expand (see Feature conditional).


10.2.3 scheme.case-lambda - R7RS case-lambda

Module: scheme.case-lambda

Exports bindings of R7RS (scheme case-lambda) library. From R7RS programs, those bindings are available by (import (scheme case-lambda)).

The only binding exported from this module is case-lambda, and it is the same as Gauche’s built-in case-lambda; see Making procedures for the details.


10.2.4 scheme.char - R7RS char library

Module: scheme.char

Exports bindings of R7RS (scheme char) library. From R7RS programs, those bindings are available by (import (scheme char)).

The following procedures are the same as Gauche’s builtin procedures; see Characters.

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?

The following procedures are the same as the ones provided in gauche.unicode module (see Full string case conversion). They use full case folding by Unicode standard (e.g. taking into account of German eszett).

string-ci<=? string-ci<?  string-ci=? string-ci>=?  string-ci>?
string-downcase string-foldcase string-upcase
Function: digit-value c

[R7RS char] {scheme.char} If c is a character with Nd general category—that is, if it represents a decimal digit—this procedure returns the value the character represents. Otherwise it returns #f.

(digit-value #\3) ⇒ 3

(digit-value #\z) ⇒ #f

Note that Unicode defines about two dozen sets of digit characters.

(digit-value #\x11068) ⇒ 2

Gauche’s built-in procedure digit->integer has more general interface (see Characters).

(digit-value c) ≡ (digit->integer c 10 #t)

10.2.5 scheme.complex - R7RS complex numbers

Module: scheme.complex

Exports bindings of R7RS (scheme complex) library. From R7RS programs, those bindings are available by (import (scheme complex)).

This module provides the following bindings, all of which are Gauche built-in (see Numerical conversions).

angle imag-part magnitude make-polar make-rectangular real-part

10.2.6 scheme.cxr - R7RS cxr accessors

Module: scheme.cxr

Exports bindings of R7RS (scheme cxr) library. From R7RS programs, those bindings are available by (import (scheme cxr)).

This module provides the following bindings, all of which are Gauche built-in (see List accessors and modifiers).

caaar caadr cadar caddr cdaar cdadr cddar cdddr caaaar caaadr caadar
caaddr cadaar cadadr caddar cadddr cdaaar cdaadr cdadar cdaddr cddaar
cddadr cdddar cddddr

10.2.7 scheme.eval - R7RS eval

Module: scheme.eval

Exports bindings of R7RS (scheme eval) library. From R7RS programs, those bindings are available by (import (scheme eval)).

This module exports eval, which is the same as Gauche’s built-in (see Eval and repl).

Function: environment import-list …

[R7RS eval] {scheme.eval} This is R7RS way to create an environment specifier suitable to pass to eval. In Gauche, an environment specifier is just a module object.

The argument is the same as what r7rs#import takes. This procedure creates an empty environment (as a fresh anonymous module; see make-module in Module introspection, for the details), then imports the bindings as specified by import-lists.

The following example creates an environment that includes scheme.base bindings plus select-module syntax from Gauche.

(environment
 '(scheme base)
 '(only (gauche base) select-module))
 ⇒ #<module #f>  ; an anonymous module

10.2.8 scheme.file - R7RS file library

Module: scheme.file

Exports bindings of R7RS (scheme file) library. From R7RS programs, those bindings are available by (import (scheme file)).

The following bindings provided in this module are Gauche built-in (see File ports, and File stats).

call-with-input-file call-with-output-file
file-exists?
open-input-file open-output-file
with-input-from-file with-output-to-file

The following binding is the same as one in file.util (see File operations).

delete-file
Function: open-binary-input-file filename
Function: open-binary-output-file filename

[R7RS file] {scheme.file} In Gauche, ports are both textual and binary at the same time, so these R7RS procedures are just aliases of open-input-file and open-output-file, respectively. See File ports.


10.2.9 scheme.inexact - R7RS inexact numbers

Module: scheme.inexact

Exports bindings of R7RS (scheme inexact) library. From R7RS programs, those bindings are available by (import (scheme inexact)).

This module provides the following bindings, all of which are Gauche built-in (see Arithmetics, and Numerical predicates).

acos asin atan cos exp finite? infinite? log nan? sin sqrt tan

10.2.10 scheme.lazy - R7RS lazy evaluation

Module: scheme.lazy

Exports bindings of R7RS (scheme lazy) library. From R7RS programs, those bindings are available by (import (scheme lazy)).

The following bindings this module provides are Gauche built-ins (see Delay, force and lazy).

delay force promise?
Special Form: delay-force promise

[R7RS lazy] {scheme.lazy} This is the same as Gauche’s built-in lazy. see Delay, force and lazy for the discussion about when this form should be used.

Function: make-promise obj

[R7RS lazy] {scheme.lazy} If obj is a promise, it is returned as is. Otherwise, A promise, which yields obj when forced, is returned. Because this is a procedure, expression passed as obj is eagerly evaluated, so this doesn’t have effect on lazy evaluation, but can be used to ensure you have a promise.

This procedure is important on implementations where force only takes a promise, and portable code should use this procedure to yield a value that can be passed to force.

If you write Gauche-specific code, however, force can take non-promise values, so you don’t need this.

Note: Gauche has built-in make-promise, which behaves as defined in SRFI-226 and slightly different from this one (see Delay, force and lazy).


10.2.11 scheme.load - R7RS load

Module: scheme.load

Exports bindings of R7RS (scheme load) library. From R7RS programs, those bindings are available by (import (scheme load)).

Function: load file :optional env

[R7RS load] {scheme.load} R7RS load takes environment as an optional argument, while Gauche load takes it as a keyword argument (among other keyword arguments). See Loading Scheme file.

In Gauche, env is just a module. In portable code, you can create a module with desired bindings with R7RS environment procedure; see scheme.eval - R7RS eval.


10.2.12 scheme.process-context - R7RS process context

Module: scheme.process-context

Exports bindings of R7RS (scheme process-context) library. From R7RS programs, those bindings are available by (import (scheme process-context)).

The following bindings are the same as Gauche built-ins (see Command-line arguments, and Program termination):

command-line exit

The following bindings are the same as SRFI-98 (see srfi.98 - Accessing environment variables):

get-environment-variable get-environment-variables
Function: emergency-exit :optional (obj #t)

[R7RS process-context] {scheme.process-context} Terminate the program without running any clean-up procedures (after thunks of dynamic-wind). I/O buffers won’t be flushed. Internally, it calls the _exit(2) system call directly.

The optional argument is used for the process exit code. R7RS does not specify the meaning of exit code except that #t indicates success and #f indicates failure. Portable code should only use these values. Gauche maps #t to exit code 0 and #f to exit code 1. For other values, see the entry of exit (see Program termination).


10.2.13 scheme.read - R7RS read

Module: scheme.read

Exports bindings of R7RS (scheme read) library. From R7RS programs, those bindings are available by (import (scheme read)).

The only binding exported from this module is read, which is the same as Gauche’s built-in. See Reading data.


10.2.14 scheme.repl - R7RS repl

Module: scheme.repl

Exports bindings of R7RS (scheme repl) library. From R7RS programs, those bindings are available by (import (scheme repl)).

The only binding exported from this module is interaction-environment, which is the same as Gauche’s built-in. See Eval and repl.


10.2.15 scheme.time - R7RS time

Module: scheme.time

Exports bindings of R7RS (scheme time) library. From R7RS programs, those bindings are available by (import (scheme time)).

Function: current-second

[R7RS time] {scheme.time} Returns a real number represents the number of seconds since the midnight of Jan. 1, 1970 TAI (which is 23:59:52, Dec 31, 1969 UTC, that is, -8 seconds before Unix Epoch.) Number of leap seconds were inserted since then, and as of 2017, UTC is 37 seconds behind TAI. That means the number returned is 29 seconds larger than the unix time, which is returned from sys-time or sys-gettimeofday.

The reason that R7RS adopts TAI is that it is monotonic and suitable to take difference of two timepoints. The unix time returned by sys-time and sys-gettimeofday are defined in terms of UTC date and time, so if the interval spans across leap seconds, it won’t reflect the actual number of seconds in the interval. (The precise definition is given in section 4.15 of IEEE Std 1003.1, 2013 Edition, a.k.a Single Unix Specification 4.)

However, since we don’t know yet when the next leap second happen, the current implementation just uses a fixed amount of offset from the unix time.

Just be aware the difference, or you’ll be surprised if you pass the return value of current-second to the UTC time formatter such as sys-strftime, or compare it with the file timestamps which uses the unix time. You can convert between TAI and UTC using SRFI-19 (see Date).

Function: current-jiffy

[R7RS time] {scheme.time} Returns an exact integer measuring a real (wallclock) time elapsed since some point in the past, which does not change while a process is running. The time unit is a jiffies-per-second-th second.

The absolute value of current jiffies doesn’t matter, but the difference can be used to measure the time interval.

Function: jiffies-per-second

[R7RS time] {scheme.time} Returns a constant to tell how many time units used in current-jiffy consists of a second. In the current Gauche implementation, this is 10^9 on 64bit architectures (that is, nanosecond resolution) and 10^4 on 32bit architectures (100 microseconds resolution).

The resolution for 32bit architectures is unfortunately rather coarse, but if we make it finer the current jiffy value easily becomes bignums, taking time to allocate and operate, beating the purpose of benchmarking. With the current choice, we have 53,867 seconds since process start before we spill into bignum on 32bit architecture. On 64bit architectures we have enough bits not to worry about bignums, with nanosecond resolution.

If you want to do more finer benchmarks on 32bit machines, you need to roll your own with sys-clock-gettime-monotonic or sys-gettimeofday.


10.2.16 scheme.write - R7RS write

Module: scheme.write

Exports bindings of R7RS (scheme write) library. From R7RS programs, those bindings are available by (import (scheme write)).

This module provides the following bindings, all of which are Gauche built-in (see Object output).

display write write-shared write-simple

10.2.17 scheme.r5rs - R5RS compatibility

Module: scheme.r5rs

This module is to provide R5RS environment in R7RS programs. The following bindings are exported. Note that lambda is scheme#lambda, without the support of extended formals (:optional etc.) See Making procedures, for the details of extended formals.

* + - / < <= = > >= abs acos and angle append apply asin assoc assq
assv atan begin boolean? caaaar caaadr caaar caadar caaddr caadr
caar cadaar cadadr cadar caddar cadddr caddr cadr
call-with-current-continuation call-with-input-file
call-with-output-file call-with-values car case cdaaar cdaadr cdaar
cdadar cdaddr cdadr cdar cddaar cddadr cddar cdddar cddddr cdddr cddr
cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<?
char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case?
char-numeric? char-ready? char-upcase char-upper-case? char-whitespace?
char<=? char<? char=? char>=? char>? char? close-input-port
close-output-port complex? cond cons cos current-input-port
current-output-port define define-syntax delay denominator display
do dynamic-wind eof-object? eq? equal? eqv? eval even? exact->inexact
exact? exp expt floor for-each force gcd if imag-part inexact->exact
inexact? input-port? integer->char integer? interaction-environment
lambda lcm length let let* let-syntax letrec letrec-syntax list
list->string list->vector list-ref list-tail list? load log magnitude
make-polar make-rectangular make-string make-vector map max member
memq memv min modulo negative? newline not null-environment null?
number->string number? numerator odd? open-input-file open-output-file
or output-port? pair? peek-char positive? procedure? quasiquote quote
quotient rational? rationalize read read-char real-part real? remainder
reverse round scheme-report-environment set! set-car! set-cdr! sin
sqrt string string->list string->number string->symbol string-append
string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>?
string-copy string-fill! string-length string-ref string-set!
string<=? string<? string=? string>=? string>? string? substring
symbol->string symbol? tan truncate values vector vector->list
vector-fill! vector-length vector-ref vector-set! vector?
with-input-from-file with-output-to-file write write-char zero?


For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT