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

10.2 R7RS small language


10.2.1 R7RSライブラリ形式

R7RSのライブラリはdefine-libraryフォームで定義されます。

R7RSの観点ではdefine-libraryフォーム自体はSchemeコードではありません。 それ自身はScheme世界の外にあります。define-libraryフォームが、 R7RS Schemeの境界となるのです。その内側はR7RSの世界であり、 その外側に関してR7RSは関知しません。例えば、R7RSの仕様の範囲内では、 define-libraryフォーム自体をマクロで生成する、ということはできません。

Gaucheでは、R7RSの世界をGaucheの世界の中に作っています。 define-library自体はGauche世界で解釈されます。実際、 define-libraryはGaucheのマクロとして実装されています。 けれどもR7RSのコードを書く際には、define-libraryがどう実装されているかは 気にする必要はありません。また、define-libraryの外側には 何も書かないようにしてください。

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

[R7RS] library-nameという名前を持つライブラリを定義します。 library-nameはシンボルもしくは10進整数のリストです。

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

ライブラリ宣言library-declは、エクスポート宣言、 インポート宣言、beginに囲まれたSchemeコード、 インクルードフォーム、あるいはcond-expandフォームです。

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

export宣言はGaucheのexportフォームと同じです。 モジュールの使用参照。

import宣言はR7RSのimportフォームで、 3つのimport形式で説明しています。

includeinclude-ciフォームはGaucheのそれと同じです。 インクルード参照。Gaucheはインクルードされるコードの中身については 感知せず、単にその中身をbeginで囲んで元のフォームと 置き換えるだけです。けれどもR7RSでは、これらのフォームが読み込むファイルには Schemeコードのみが許されます(例えばdefine-libraryフォームや 他のライブラリ宣言フォームはだめです)。

include-library-declarations宣言はinclude宣言と 同じように動作しますが、読み込まれるファイルの中身はSchemeコードではなく ライブラリ宣言として解釈されます。

cond-expand宣言もGaucheのそれと同じです。 機能条件式参照。 但し、define-libraryの直下で使われた場合は、 展開結果もライブラリ宣言になっている必要があります。


10.2.2 scheme.base - R7RS基本ライブラリ

Module: scheme.base

R7RSの(scheme base)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は(import (scheme base))とすることで 使えます。

Gaucheの組み込み束縛と共通なもの

以下の構文の手続きはGaucheの組み込みのものと同じです。

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

次の2つの識別子は、schemeモジュールにあるものがエクスポートされます。 これらはgaucheモジュールの束縛とは異なることに注意してください。 Gaucheの拡張引数(:key:optional等)は認識されません。

define lambda

バイトベクタユーティリティ

R7RSのバイトベクタはGaucheのu8vectorと同じです。

以下の手続きはgauche.uvectorのものと同じです。 (バイトベクタ互換性参照)。

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

以下の手続きはgauche.vportのものと同じです。 (gauche.vport - 仮想ポート参照)。

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

そして以下の手続きはgauche.unicodeのものと同じです。 (Unicode transfer encodings参照)。

utf8->string       string->utf8

制御機能

手続きwith-exception-handlerはGauche組み込みのものと同じです。 下位レベルの例外処理機構で説明してあります。

Function: raise obj
Function: raise-continuable obj

[R7RS base] {scheme.base} Gaucheのraiseは、obj<serious-condition>でなければ、 例外ハンドラから戻って来ることを許しています。 継続可能な例外報告と継続不可能な例外報告を手続きで区別するのは、 例外ハンドラが渡されたコンディションを再び投げる場合に問題となります (元のコンディションがraiseで投げられたのかraise-continuableで 投げられたのか知る術がない!)。 しかしR7RSではそのモデルを採用したため、何とか合わせようとしています。

R7RS版のraiseはGaucheのraiseのラッパーで、 Gaucheのraiseから戻って来たらエラーを投げるようにしています。

R7RSのraise-continuableは今のところGaucheのraiseの 別名になっています。<serious-condition>を渡さなければ、 戻ってくることが可能です。R7RS準拠でないのは、 <serious-condition>かそのサブクラスのオブジェクト(例えば<error>)を raise-continuableに渡した場合ですが、 <error>を投げて戻って来ることを期待するというのはちょっとおかしいですよね。

Function: error-object? exc

[R7RS base] {scheme.base} (condition-has-type? exc <error>))として定義されています。

Function: error-object-message exc

[R7RS base] {scheme.base} exc<message-condition>であれば message-prefixの内容を、持っていなければ空文字列を返します。

Function: error-object-irritants exc

[R7RS base] {scheme.base} exc<message-condition>であれば message-argsの内容を、持っていなければ空文字列を返します。

Function: read-error? exc

[R7RS base] {scheme.base} (condition-has-type? e <read-error>))として定義されています。

Function: file-error? exc

[R7RS base] {scheme.base} 今のところ、Gaucheは独立した<file-error>コンディションを持っていませんが、 ファイルエラーのほとんどは<system-error>として投げられます。 この手続きは<system-error>のエラーコードを調べ、ファイルに起因するエラー の場合に#tを返すようにしています。

入出力

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

[R7RS base] {scheme.base} Gaucheのポートはどちらも扱えるので、これらの手続きはport?と等価です。

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

[R7RS base] {scheme.base} iport/oportがそれぞれ入力/出力ポートであり、かつクローズされていなければ #tを返します。

Function: flush-output-port :optional oport

[R7RS base] {scheme.base} flushの別名です (低レベル出力参照)。

Function: features

[R7RS base] {scheme.base} サポートされているfeature-identifierのリストを返します。 feature-identifierについては、cond-expandを参照してください (機能条件式参照)。


10.2.3 scheme.case-lambda - R7RS case-lambda

Module: scheme.case-lambda

R7RSの(scheme case-lambda)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme case-lambda))とすることで使えます。

このモジュールからエクスポートされるのはcase-lambdaだけで、 Gauche組み込みのcase-lambdaそのものです。 詳しくは手続きを作るを参照してください。


10.2.4 scheme.char - R7RS文字ライブラリ

Module: scheme.char

R7RSの(scheme char)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme char))とすることで使えます。

以下の手続きはGaucheの組み込みのものと同じです。文字参照。

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?

以下の手続きはgauche.unicodeで提供されているものと同じです (フルセットの大文字小文字変換参照)。Unicodeで定義されている フルセットの大文字小文字変換を使います(例えばドイツ語のエスツェットが考慮されます)。

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

[R7RS char] {scheme.char} cNdカテゴリの文字、つまり十進数の数字を表す文字であれば、 その文字が表す値を返します。それ以外の場合は#fを返します。

(digit-value #\3) ⇒ 3

(digit-value #\z) ⇒ #f

Unicodeには20種類以上の数字が定義されています。

(digit-value #\x11068) ⇒ 2

Gauche組み込みのdigit->integerはより汎用的なインタフェースを 持っています(文字参照)。

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

10.2.5 scheme.complex - R7RS複素数

Module: scheme.complex

R7RSの(scheme complex)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme complex))とすることで使えます。

このモジュールは以下の束縛を提供します。 全てGaucheの組み込みです(数値の変換参照)。

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

10.2.6 scheme.cxr - R7RS cxrアクセサ

Module: scheme.cxr

R7RSの(scheme complex)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme complex))とすることで使えます。

このモジュールは以下の束縛を提供します。 全てGaucheの組み込みです(リストへのアクセスと変更参照)。

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

R7RSの(scheme eval)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme eval))とすることで使えます。

このモジュールはevalをエクスポートします。これはGauche組み込みのevalと 同じです(eval と repl参照)。

Function: environment import-list …

[R7RS eval] {scheme.eval} これはR7RSでevalに渡せる環境指定子を作る手段です。Gaucheでは、 環境指定子は単なるモジュールオブジェクトです。

引数はr7rs#importが取るものと同じです。 この手続きはまず空の環境(=無名のモジュールです。 詳しくはモジュールイントロスペクションmake-module参照)を作り、 それからimport-listに指定される束縛をインポートします。

以下の例は、scheme.base及びGauche組み込みのselect-moduleを インポートした環境を作ります。

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

10.2.8 scheme.file - R7RSファイルライブラリ

Module: scheme.file

R7RSの(scheme file)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme file))とすることで使えます。

次に挙げる束縛はGaucheの組み込みと同じです (ファイルポート及びファイルの状態参照)。

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

以下の束縛はfile.utilで提供されるものと同じです (ファイル操作参照)。

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

[R7RS file] {scheme.file} Gaucheでは、ポートは同時にテキストポートでもバイナリポートでもあるので、 これらのR7RS手続きは単に open-input-fileopen-output-fileの別名になっています。 ファイルポート参照。


10.2.9 scheme.inexact - R7RS非正確数

Module: scheme.inexact

R7RSの(scheme inexact)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme inexact))とすることで使えます。

このモジュールは以下の束縛を提供します。全てGaucheの組み込みです (数値の演算及び数値に関する述語参照)。

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

10.2.10 scheme.lazy - R7RS遅延評価

Module: scheme.lazy

R7RSの(scheme inexact)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme inexact))とすることで使えます。

以下の束縛は、Gauche組み込みです (Delayとforceとlazy参照)。

delay force promise?
Special Form: delay-force promise

[R7RS lazy] {scheme.lazy} これはGauche組み込みのlazyと同じです。 使い方についてはDelayとforceとlazyの議論を参照してください。

Function: make-promise obj

[R7RS lazy] {scheme.lazy} objがプロミスならそのまま返されます。そうでなければ、 forceされた時にobjが返されるようなプロミスが返されます。 これは手続きなので、objmake-promiseを呼び出す前に 評価されてしまいます。従って遅延評価には使えませんが、 確実にプロミスを得たい場合に使えます。

forceがプロミスのみを取るような実装ではこの手続きは重要です。 ポータブルなコードは、forceに渡すものがプロミスであることを 確実にしたい場所でこの手続きを使うようにしてください。

Gaucheのforceはプロミスでない値も取れるので、 Gauche専用のコードを書いている時はこの手続きは不要です。

註: Gaucheの組み込みのmake-promiseはSRFI-226で定義された動作で、 このmake-promiseとは若干違います。 (Delayとforceとlazy参照)。


10.2.11 scheme.load - R7RS load

Module: scheme.load

R7RSの(scheme load)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme load))とすることで使えます。

Function: load file :optional env

[R7RS load] {scheme.load} R7RSのloadは省略可能引数として環境を取ります。 Gaucheのloadでは環境はキーワード引数で受け取られることに注意してください。 Schemeファイルのロード参照。

また、Gaucheでは環境は単にモジュールで良いのですが、 ポータブルなコードではR7RSのenvironment手続きを使って 環境を作る必要があります。scheme.eval - R7RS eval参照。


10.2.12 scheme.process-context - R7RSプロセスコンテキスト

Module: scheme.process-context

R7RSの(scheme process-context)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、エクスポートされた束縛は (import (scheme process-context))とすることで使えます。

次の束縛はGauche組み込みのものと同じです (コマンドライン引数、およびプログラムの終了参照):

command-line exit

次の束縛はSRFI-98のものと同じです (srfi.98 - 環境変数へのアクセス参照):

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

[R7RS process-context] {scheme.process-context} クリーンアップ手続きを飛ばしてプログラムを直ちに終了させます (dynamic-windによって設定されたafterサンクは実行されません)。 内部的には、_exit(2)システムコールを直接呼んでいます。

省略可能引数はプロセスの終了コードを指定します。 R7RSでは具体的な終了コードの値は示されておらず、ただ#tが「成功」を、 #fが「失敗」を意味するとされています。Gaucheでは#tを終了コード0に、 #fを終了コード1に対応させています。ポータブルなコードでは真偽値のみを渡してください。 これ以外のcodeの意味については、exitのエントリを参照してください。 (プログラムの終了)。


10.2.13 scheme.read - R7RS read

Module: scheme.read

R7RS (scheme read)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、 (import (scheme read))とすることでこれらの名前が使えるようになります。

このモジュールからエクスポートされるのはreadのみで、 これはGaucheでは組み込みになっています。データの読み込み参照。


10.2.14 scheme.repl - R7RS repl

Module: scheme.repl

R7RS (scheme repl)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、 (import (scheme repl))とすることでこれらの名前が使えるようになります。

このモジュールからエクスポートされるのはinteraction-environmentのみで、 これはGaucheでは組み込みになっています。eval と repl参照。


10.2.15 scheme.time - R7RS time

Module: scheme.time

R7RS (scheme time)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、 (import (scheme time))とすることでこれらの名前が使えるようになります。

Function: current-second

[R7RS time] {scheme.time} 国際原子時(TAI)の1970年1月1日0時から現在までの経過秒数を実数で返します。 (これは、Unix Epochの8秒前、国際標準時(UTC)で1969年12月31日23:59:52に相当します)。 この起点以来、閏秒がしばしば挿入されてきて、2017年現在、UTCはTAIより37秒遅れています。 すなわち、この手続きが返す秒数は、sys-timesys-gettimeofdayが 返すUnix timeより29秒大きい値です。

R7RSがTAIを採用したのは、それが狭義単調増加であり、二つの時刻の差をとるのに 適しているからです。sys-timesys-gettimeofdayは UTCの日付と時間に基づいているので、二つの時刻が閏秒を挟んでいた場合、 差は経過秒数を表しません。 (Unix Timeの正確な定義については、 IEEE Std 1003.1, 2013年版の4.15節、いわゆるSingle Unix Specification 4を参照)。

ただ、次にいつ閏秒が来るかはわからないので、現在の実装では単純に Unix Timeから固定オフセットを引いています。

この差異があることは頭の隅に留めておいてください。 でないと、current-secondの戻り値を sys-strftimeなどUTC時刻のフォーマッタに渡したり、 Unix Timeで表されたタイムスタンプと比較した時にびっくりするかもしれません。 TAIとUTCはSRFI-19で変換できます (日付)。

Function: current-jiffy

[R7RS time] {scheme.time} 過去のどこかの時点を基準とする、実経過時間を正確な整数で返します。 基準時点はプロセスの起動ごとに変わるかもしれません。 1単位は1秒のjiffies-per-second分の1です。

「現在のjiffy値」の絶対値に意味はありません。差を取って経過時間を測るのに使います。

Function: jiffies-per-second

[R7RS time] {scheme.time} current-jiffyが返す時間単位が、1秒あたりいくつあるかを示す定数を返します。 現在のGaucheの実装では、64ビットアークテクチャで10^9 (ナノ秒単位)、 32ビットアーキテクチャで10^4 (100マイクロ秒単位)です。

32ビットアーキテクチャでの分解能がかなり粗いですが、 jiffy値がbignumにオーバーフローするのを防ぐ方を優先しました。 bignumになるとアロケーションが頻繁に起きるのでベンチマークに干渉してしまいます。 現在の数値では、32ビットアーキテクチャだとプロセス開始後53,867杪でbignumになります。 64ビットアーキテクチャではナノ秒単位で測ってもbignumになることを 現実的に心配する必要はありません。

32ビットアーキテクチャでより精度の高いベンチマークを取りたい場合は、 sys-clock-gettime-monotonicsys-gettimeofdayを使ってください。


10.2.16 scheme.write - R7RS write

Module: scheme.write

R7RS (scheme write)ライブラリの束縛をエクスポートします。 R7RSプログラムからは、 (import (scheme write))とすることでこれらの名前が使えるようになります。

このモジュールからは以下の束縛がエクスポートされます。 いずれもGauche組み込みです (オブジェクトの出力参照)。

display write write-shared write-simple

10.2.17 scheme.r5rs - R5RS互換性

Module: scheme.r5rs

このモジュールは、R7RSプログラム内でR5RS環境を実現します。 次に挙げる束縛がエクスポートされます。 ここでのlambdascheme#lambdaで、 Gaucheの拡張機能 (:optionalなど) は認識されないことに注意してください。 拡張された引数リストについては手続きを作る参照。

* + - / < <= = > >= 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