This is gauche-refj.info, produced by makeinfo version 4.8 from
gauche-refj.texi.

INFO-DIR-SECTION The Algorithmic Language Scheme
START-INFO-DIR-ENTRY
* Gauche Reference (ja): (gauche-refj.info).  An R5RS Scheme implementation.
END-INFO-DIR-ENTRY


File: gauche-refj.info,  Node: Top,  Next: はじめに,  Prev: (dir),  Up: (dir)

   本書は、R5RS準拠のScheme処理系、Gaucheのリファレンスマニュアルです。
Gaucheのバージョン0.8.5に対応します。

* Menu:

* はじめに::
* 主要な概念::
* Gaucheでのプログラミング::
* 基本的な構文::
* マクロ::
* 組み込みライブラリ::
* オブジェクトシステム::
* ライブラリモジュール - 概要::
* ライブラリモジュール - Gauche拡張モジュール::
* ライブラリモジュール - SRFI::
* ライブラリモジュール - ユーティリティ::
* 参考文献::
* CとSchemeの関数の対応::
* Index - 手続きと構文索引::
* Index - モジュール索引::
* Index - クラス索引::
* Index - 変数索引::


File: gauche-refj.info,  Node: はじめに,  Next: 主要な概念,  Prev: Top,  Up: Top

1 はじめに
**********

本書はGauche Scheme systemに関する、プログラマーのためのガイドと
リファレンスです。なるべくGaucheの実装を正確に記述することを
目的として、時には背景となる設計上の選択も含めて説明しています。

   したがって、既にSchemeを知っていてGaucheの全機能を活用して
プログラムを書きたいという読者を対象にしています。
Schemeに触れるのが初めての読者は、何らかのチュートリアルを併用すると
良いでしょう。私もいずれチュートリアルめいたものを書くつもりです。

   このマニュアルでは、GaucheのScheme言語としての面のみを扱います。
GaucheはC言語から呼べる汎用リスト処理ライブラリとしての側面も持っていますが、
それは別ドキュメントで解説する予定です。Gaucheを組み込み言語として使いたい、
もしくはGaucheをC言語で拡張したいという読者はそのドキュメントが必要となります。

Scheme言語としての側面に関しては、なるべくこのマニュアル一冊でリファレンスとしての
用が足りるように記述しました。標準に定められている関数でも、こちらのマニュアルだけで
使うのに必要な事項を知ることができます。但し、このマニュアルは標準文書の替わりには
なりません。記述を短くするために理論的な背景などは省略してあります。
オリジナルのドキュメントへのポインタを参考文献の項に上げておきましたので、
必要に応じて参照して下さい。

   もしあなたがこのマニュアルをオフラインで読んでいるなら、
時々下記のURLをチェックしてみて下さい。更新があるかもしれません。
     `http://www.shiro.dreamhost.com/scheme/gauche/'.

   なお、本マニュアルの日本語版製作には、 佐藤 誠 氏、山下 伸夫
氏の協力を頂きました。

* Menu:

* Gaucheの概要::
* 表記について::


File: gauche-refj.info,  Node: Gaucheの概要,  Next: 表記について,  Prev: はじめに,  Up: はじめに

1.1 Gaucheの概要
================

GaucheはScheme言語に基づくスクリプトインタプリタです。
Scheme言語の標準である、"Revised^5 Report on the Algorithmic Language
Scheme" (*Note [R5RS]: r5rs.)に準拠しています。また、SRFI
(`http://srfi.schemers.org') に規定されている数多くのライブラリを
サポートしています。

   Gaucheは、プログラマやシステム管理者がこなす日常の雑事を
効率よくSchemeで書けるようにすることを目的として設計されています。

   世の中には多くのSchemeの実装がありますが、
それぞれの実装には長所と短所があります。
Gaucheが長所とするべく重点を置いているのは次のようなポイントです。

立ち上りが速いこと
     Gaucheが想定している用途のひとつは、プロダクション環境でちょろっと
     10行スクリプトをでっちあげて、それが非常に頻繁に呼ばれるようなケースです。
     CGIスクリプトなどもそうです。
     Gaucheでは、言語のコアとスクリプトとして良く使いそうな機能に絞って
     実行ファイルにコンパイルインし、使う分野が特定される機能は必要に応じて
     読み込むようにしています。

マルチバイト文字列
     文字列が1バイトキャラクタのみを扱っていれば良かった時代は過ぎ去りました。
     現代のプログラミングシステムは、様々なエンコーディングによるマルチバイト文字／文字列を
     自然に扱える必要があります。
     Gaucheは内部的に文字列を全て、コンパイル時に選択したエンコーディングの
     マルチバイト文字列として扱います。後から付け足したライブラリレベルでの
     マルチバイト文字列のサポートよりも、一貫性がありロバストな文字列操作が可能になっています。
     詳しくは*Note マルチバイト文字列::を参照してください。

モジュラー開発
     Gaucheは名前空間を分離する単純なモジュールシステムを備えており、
     名前の衝突を心配せずに複数の開発者が並行して作業をすることができます。

統合されたオブジェクトシステム
     CLOSライクなメタオブジェクトプロトコルを備えた強力なオブジェクトシステム
     が組み込んであります。STklosやGuileのオブジェクトシステムとかなり互換性があります。

システムインタフェース
     Schemeは計算機の詳細の多くを抽象化しますが、プログラムを書いていると、
     それらの高レベル層をバイパスして地下室に降りて作業しなければならないような時が
     あります。GaucheはPOSIX.1システムコールのほとんどを組み込みでサポートします。
     また、ネットワーキングモジュールなど他のシステム関連モジュールは通常、
     高レベルの抽象的なインタフェースと低レベルのシステムコールに近いインタフェースを
     両方提供します。

強化された入出力
     本物のアプリケーションはI/O無しでは成り立ちません。
     SchemeはI/Oをポートとして簡潔に抽象化していますが、
     標準のSchemeには最低限の操作しか定義されていません。
     Gaucheはポートオブジェクトを入出力のための統合された抽象化オブジェクトと考え、
     それを通して下位のI/Oシステム層にアクセスするユーティリティ関数を提供しています。
     *Note 入出力::を参照して下さい。

   一方、Gaucheは所詮インタプリタですから、高速に大量の計算をこなしたり
巨大なデータセットを扱ったりするのは苦手です。

但し、そのような場合でも、Gaucheを各コンポーネントをつなぐ「糊」言語として
使うことは可能です。例えば性能の要求の厳しい部分はネイティブコードにコンパイルする言語で
書いておき、セットアップにGaucheを使うといった方法があります。


File: gauche-refj.info,  Node: 表記について,  Prev: Gaucheの概要,  Up: はじめに

1.2 表記について
================

このマニュアルでは、各項目は次のようなフォーマットで表記されています。

 -- カテゴリ: foo arg1 arg2
     [spec] fooの説明

   カテゴリ は項目fooの種別を示します。 次のようなカテゴリがあります。

Function                      Scheme手続き
Special Form                  特殊形式 (R5RSでは「構文」)
Macro                         マクロ
Module                        モジュール
Class                         クラス
Generic Function              ジェネリックファンクション
Method                        メソッド
Reader Syntax                 リーダによって解釈される構文要素

手続き、特殊形式、マクロに関しては、エントリの後に引数の仕様が示されます。
引数リストの中には次のような表記が現れることがあります。

ARG ...
     ゼロ個以上の可変個の引数。

&OPTIONAL X Y Z
&OPTIONAL (X X-DEFAULT) (Y Y-DEFAULT) Z
     省略可能な引数の表記。この例では3つまでの省略可能な引数が取られることを示します。
     2番目の形式では省略された場合の既定値も示しています。
     この表記はCommonLispのスタイルにならっていますが、Gauche自身がラムダリストに
     `&optional'のような表記を受け付けるわけではないことに注意してください。
     マニュアルの表記を簡潔にするためにこのような表現を用いているだけです。

&KEYWORD X Y Z
&KEYWORD (X X-DEFAULT) (Y Y-DEFAULT) Z
     キーワード引数の表記。この例ではX、Y、Zの3つのキーワード引数を
     取ることが示されます。2番目の形式では省略された場合の既定値も示されます。
     この表記はCommonLispのスタイルにならっていますが、Gauche自身がラムダリストに
     `&keyword'のような表記を受け付けるわけではないことに注意してください。
     マニュアルの表記を簡潔にするためにこのような表現を用いているだけです。

&REST ARGS
     残りの引数全てがリストになってARGSに束縛されることを示します。
     この表記はCommonLispのスタイルにならっていますが、Gauche自身がラムダリストに
     `&rest'のような表記を受け付けるわけではないことに注意してください。
     マニュアルの表記を簡潔にするためにこのような表現を用いているだけです。

   説明が項目の行に続きます。もし項目が特定の標準に準拠している場合は、
もととなった標準が次のような形式で示されます。

[R5RS]
[R5RS+]
     この項目はR5RSに定義されるように動作します。"[R5RS+]"とマークされている場合は
     R5RSの仕様に上位互換な形で追加の機能が実装されていることを示します。

[SRFI-N]
[SRFI-N+]
     この項目はSRFI-Nに定義されるように動作します。"[SRFI-N+]"とマークされている場合は
     SRFI-Nの仕様に上位互換な形で追加の機能が実装されていることを示します。

[POSIX]
     この項目はPOSIXのAPIを反映していることを示します。


File: gauche-refj.info,  Node: 主要な概念,  Next: Gaucheでのプログラミング,  Prev: はじめに,  Up: Top

2 主要な概念
************

本章では、Gauche動作の背景となるいくつかの概念を説明します。
Gaucheの動作を正確に理解する助けになると思います。

* Menu:

* 標準への準拠::
* マルチバイト文字列::
* マルチバイトスクリプト::
* 大文字小文字の区別::
* 統合されたオブジェクトシステム::
* モジュールシステム::
* コンパイル::


File: gauche-refj.info,  Node: 標準への準拠,  Next: マルチバイト文字列,  Prev: 主要な概念,  Up: 主要な概念

2.1 標準への準拠
================

Gaucheは、以下に挙げる点を除き、オプショナルな構文や手続きも含め
"Revised^5 Report of Algorithmic Language Scheme" に準拠しています。

   * デフォルトで、Gaucheはシンボルの名前の大文字小文字を区別します。
     コマンドラインオプションによって、大文字小文字を区別しないモードに
     切替えることができます(*Note 大文字小文字の区別::参照)。

   * ある条件下で作られた継続は限られたエクステントを持ちます
     (具体的には、Cのコードからコールバックとして呼ばれるSchemeコード内で作られる継続
     がこれにあたります)。詳しくは*Note 継続::を参照して下さい。

   * Numeric towerは整数、実数、複素数をサポートしていますが、
     有理数はサポートしていません。リーダーは有理数の構文を認識しますが、
     読む込むと不正確な実数になります。数字のフォーマットのうち、
     リーダは、精度に影響を与えない桁を'`#''で表す表記を認識します。

   * 手続き`rationalize'、`transcript-on'、及び`transcript-off'
     はサポートされていません。

   Gaucheはまた、以下のSRFIをサポートしています。

SRFI-0, 機能ベースの条件展開
     オートロードされるマクロとしてサポートされます。*Note
     機能条件式::参照。

SRFI-1, リストライブラリ
     モジュール`srfi-1'でサポートされます。*Note List library::参照。
     SRFI-1の手続きのうちいくつかは組み込みになっています。

SRFI-2, AND-LET*: 局所束縛をともなう AND、ガード付 LET* 特殊フォーム
     モジュール`srfi-2'でサポートされます。*Note And-let*::参照。

SRFI-4, 一様型の数値ベクタ
     モジュール`gauche.uvector'が、
     `srfi-4'の手続きのスーパーセットを提供します。
     同モジュールにはSRFI-4の手続きに加え、
     算術演算やジェネリックなインタフェースが定義されています。*Note
     ユニフォームベクタ::参照。

SRFI-5, シグネチャとrest引数に互換性のあるlet形式
     モジュール`srfi-5'でサポートされます。 *Note
     シグネチャとrest引数に互換性のあるlet形式::参照。

SRFI-6, 基本文字列ポート
     SRFI-6の手続きは組み込みになっています。*Note 文字列ポート::参照。

SRFI-7, 機能ベースプログラム設定言語
     オートロードされるマクロとしてサポートされています。 *Note
     機能ベースプログラム設定言語::参照。

SRFI-8, receive: 多値束縛
     構文`receive'は組み込みになっています。*Note 変数束縛::参照。

SRFI-9, レコード型の定義
     モジュール`srfi-9'でサポートされます。*Note レコード型::参照。

SRFI-10, Sharp-comma外部フォーム
     組み込みです。*Note 読み込み時コンストラクタ::参照。

SRFI-11, 多値を受け取るための構文
     モジュール`srfi-11'でサポートされます。*Note Let-values::参照。

SRFI-13, 文字列ライブラリ
     モジュール`srfi-13'でサポートされます。*Note
     文字列ライブラリ::参照。
     (SRFI-13の手続きのいくつかは組み込みになっています)。

SRFI-14, 文字集合のライブラリ
     文字集合と基本的なSRFI-14手続きは組み込みになっています。 *Note
     文字集合::参照。SRFI-14の完全なサポートはモジュール`srfi-14'
     で提供されています。*Note 文字集合ライブラリ::参照。

SRFI-16, 可変長引数手続き構文 (case-lambda)
     組み込みです。*Note 手続きを作る::参照。

SRFI-17, 一般化された set!
     組み込みです。*Note 代入::参照。

SRFI-18, マルチスレッドのサポート
     いくつかのSRFI-18の機能は組み込みであり、、残りのAPIは
     `gauche.threads'モジュールで提供されます。*Note スレッド::参照。

SRFI-19, 時間データの型と手続き
     時間のデータ型はGauche組み込みです(*Note 時間::参照)。
     SRFI-19の完全なサポートはモジュール`srfi-19'で提供されています。
     *Note 時間のデータ型と手続き::参照。

SRFI-22, UNIX 上の Scheme スクリプトの実行
     サポートされています。*Note Schemeスクリプトを書く::参照。

SRFI-23, エラー報告機構
     組み込みです。*Note 例外の通知::参照。

SRFI-25, 多次元配列のプリミティブ
     モジュール`gauche.array'が、SRFI-25のスーパーセットと
     なっています。*Note 配列::参照。

SRFI-26, カリー化をともなわないパラメータの特殊化記法
     オートロードされるマクロとして定義されています。*Note
     手続きを作る::参照。

SRFI-27, ランダムビットのソース
     モジュール`srfi-27'でサポートされます。*Note
     ランダムビットのソース::参照。

SRFI-28, 基本フォーマット文字列
     Gauche組み込みの`format'がSRFI-28のもののスーパーセットに
     なっています。*Note 出力::参照。

SRFI-29, 地域化
     モジュール`srfi-29'でサポートされます。 *Note 地域化::参照。

SRFI-30, ネストした複数行コメント
     ネイティブのリーダでサポートされています。*Note 字句構造::参照。

SRFI-31, 再帰評価用の特殊フォーム rec
     オートロードされるマクロとして定義されています。*Note
     変数束縛::参照。

SRFI-34, プログラムの例外処理
     組み込みです。*Note 例外::参照。
     (但し、Gaucheは`raise'に関してはsrfi-18のセマンティクスを文字通り
     実装していて、それはsrfi-34と若干異なります。将来はsrfi-34に合わせるかもしれません。)

SRFI-35, コンディション
     組み込みです。*Note コンディション::参照。

SRFI-36, I/O コンディション
     部分的にサポートされています.  *Note コンディション::参照。

SRFI-37, args-fold: プログラム引数処理
     モジュール`srfi-37'でサポートされます。 *Note args-fold
     プログラム引数処理::参照。

SRFI-38, 共有されるデータの外部表現
     組み込みです。*Note データの読み込み::と*Note 出力::参照。

SRFI-39, パラメータオブジェクト
     モジュール`gauche.parameter'でサポートされます。 *Note
     パラメータ::参照。

SRFI-42, 几帳面な内包表記
     モジュール`srfi-42'でサポートされます。 *Note Eager
     comprehensions::参照。

SRFI-55, require-extension
     オートロードマクロとしてサポートされます。 *Note Requiring
     extensions::参照。



File: gauche-refj.info,  Node: マルチバイト文字列,  Next: マルチバイトスクリプト,  Prev: 標準への準拠,  Up: 主要な概念

2.2 マルチバイト文字列
======================

伝統的に、文字列は単なるバイトの配列として長く扱われてきました。
一文字が複数バイトを占めるようになっても、
文字列は単純な文字の配列であると考えられがちです。
しかしGaucheにおいては、そうではありません。

   Gaucheは内部的に_マルチバイト文字列_をサポートします。
すなわち、文字列中の文字が占めるバイト数は一定していません。
Schemeの文字列プリミティブのセマンティクスは保たれているので、
詳細を気にしないでもプログラムは書けますが、
下にあげるいくつかの点を知っておいたほうが良いでしょう。

   文字列オブジェクトは型タグと文字列本体へのポインタを保持しています。
文字列本体は「copy-on-write」方式で管理されます。すなわち、`substring'
や正規表現を使って部分文字列を切り出したり、あるいは単に文字列をコピーした場合、
文字列オブジェクトそのものは別につくられますが、文字列本体は共有されます。
文字列が破壊的に変更される場合にのみ、文字列本体がコピーされます。

   したがって、`make-string'である大きさの文字列をあらかじめアロケート
しておき、`string-set!'で順に埋めて行くようなアルゴリズムは
Gaucheでは非常に効率が悪くなります。そのようなアルゴリズムは使わない方が良いでしょう。
(そのようなアルゴリズムはマルチバイト文字列とも相性が良くありません)。
文字列を順に埋めて行く場合は_string ports_を使うのが 効率の良い方法です
(*Note 文字列ポート::参照)。

   `string-scan' (*Note 文字列を扱うその他の手続き::参照) や正規表現
(*Note 正規表現::参照) など文字列を検索するプリミティブは、
インデックスを介さずに一致した文字列を直接返すことができます。

Gaucheのコンパイル時に、文字の_内部エンコーディング_を選択することができます。
実行時に手続き`gauche-character-encoding'によってどの内部エンコーディング
でコンパイルされたかを知ることが出来ます。
今のところ、以下のエンコーディングがサポートされています。

`euc-jp'
     ASCII、JIS X 0201カナ、JIS X 0212及びJIS X
     0213:2000文字集合のEUC-JP エンコーディング

`sjis'
     JIS X 0201カナ及びJIS X
     0213:2000文字集合のShift-JISエンコーディング。
     ソースコードの互換性のため、文字コード0から0x7fの範囲はJIS X 0201
     roman ではなくASCIIにマップされます。

`utf-8'
     UnicodeのUTF-8エンコーディング。

`none'
     8ビット固定長の文字エンコーディング。文字コード0から0x7fの範囲はASCIIと
     みなします。文字列をどのエンコーディングとして解釈するかはアプリケーション次第です。

   他の文字エンコーディングからの変換は特別なポートを使って行われます。
*Note 文字コード変換:: を参照して下さい。

   ソースプログラムのエンコーディングを指定する方法については
次の章で説明します。


File: gauche-refj.info,  Node: マルチバイトスクリプト,  Next: 大文字小文字の区別,  Prev: マルチバイト文字列,  Up: 主要な概念

2.3 マルチバイトスクリプト
==========================

リテラル文字列や文字以外にも、コメント、シンボル名、
リテラル正規表現など様々な箇所で、`us-ascii'以外の文字を
使うことができます。

   いまのところ、Gaucheは`us-ascii'以外の文字を全て、シンボルを
構成する文字として扱います。但し、Unicodeは十数個の「空白」文字を定義
しており、将来はそれらの文字がプログラム上も空白として扱われるように
なるでしょう。従って現在のところはそれらの文字の使用は
(文字列、正規表現、文字以外の箇所では)避けておくのが良いでしょう。

デフォルトでは、GaucheはSchemeプログラムをGaucheの内部文字エンコーディングで
書かれているものとして扱います。これは、自分で書いたスクリプトを自分の
環境で走らせるだけなら十分ですが、別の文字エンコーディングを使うように
コンパイルされた環境でスクリプトを走らせたい場合に問題となります。

   そこで、Gaucheは、次のようなコメントがプログラムソースコードの
2行目までに現れた場合、ソースコードの残りの部分が`<encoding-name>'で
指定されるエンコーディングで書かれているものとして、必要ならば
適切なエンコーディング変換を行います。
     ;; coding: <encoding-name>

   より正確には、1行目または2行目のコメントで、
正規表現`#/coding[:=]\s*([\w.-]+)/'にマッチするものがあった場合に、
最初の部分マッチがエンコーディング名として認識されます。
複数のマッチがあった場合は最初のものが有効になります。
このメカニズムを利用するためには、最初の2行以内にus-ascii以外の文字を
含めないようにして下さい。

   例えば次の例では、Gaucheはスクリプトがeuc-jpで書かれているものと
認識します。coding指定の周囲の"`-*-'"は、Emacsが
バッファのエンコーディングを適切に設定するのに使われます。

     #!/usr/bin/gosh
     ;; -*- coding: euc-jp -*-

     ... script written in euc-jp ...

   内部では、この特殊なコメントの処理は特別なポートによって
行われています。詳細は*Note コーディング認識ポート::を参照して下さい。
また、この処理を行わないようにする方法については *Note
Schemeファイルのロード::を参照して下さい。


File: gauche-refj.info,  Node: 大文字小文字の区別,  Next: 統合されたオブジェクトシステム,  Prev: マルチバイトスクリプト,  Up: 主要な概念

2.4 大文字小文字の区別
======================

Lisp系の言語は歴史的にシンボルの大文字小文字を区別していませんでした。
Schemeもその流れを汲んでおり、R5RSでもシンボルは読み込まれる時に大文字小文字の
区別をしないと定義されています。(但し、R5RSの範囲内でも内部的なシンボル名は
大文字小文字の区別がなされます。ここで問題としているのは読み込み時の動作です)。

しかし現在では、プログラミングが一つの言語で完結することは滅多にありません。
他の言語とインタフェースを取る場合、Scheme側でも大文字小文字を区別するように
しておいた方が便利です。

そこでGaucheでは、シンボルの読み込みと書き出しに2つのモードを用意しました。
_デフォルトのモードでは、Gaucheのリーダとライタはシンボルの大文字小文字を区別します_。
このふるまいは厳密にはR5RSに準拠しません。

     ; In case-sensitive mode (default)
     (eq? 'a 'A) => #f  ; #t in R5RS
     (symbol->string 'ABC) => "ABC"
     (symbol->string 'abc) => "abc"
     (display (string->symbol "ABC")) => writes ABC
     (display (string->symbol "abc")) => writes abc

   `gosh'インタプリタの起動時に`-fcase-fold'コマンドライン引数を
与えると、Gaucheは大文字小文字を区別しないモードで動作します (*Note
Gaucheを起動する::参照)。
このモードでは、リーダはシンボルの読み込みの際に大文字を小文字に変換します。
大文字を含んでいるシンボルに関しては、`|'
文字でエスケープされて書き出されます (*Note シンボル::参照)。

     ; In case-insensitive mode (with -fcase-fold option)
     (eq? 'a 'A) => #t
     (symbol->string 'ABC) => "abc"
     (symbol->string 'abc) => "abc"
     (display (string->symbol "ABC")) => writes |ABC|
     (display (string->symbol "abc")) => writes abc

今のところ、インタプリタの中から両方のモードを切り替えることはできません。
将来のバージョンではその方法が提供されるでしょう。


File: gauche-refj.info,  Node: 統合されたオブジェクトシステム,  Next: モジュールシステム,  Prev: 大文字小文字の区別,  Up: 主要な概念

2.5 統合されたオブジェクトシステム
==================================

GaucheはCLOSに類似した、STklosスタイルのオブジェクトシステムを持っています。
あなたが何らかのオブジェクト指向(OO)言語を使ったことがあれば、
基本的な使い方は簡単にわかるでしょう。
     ;; x, y座標を持つpointクラスを定義
     (define-class point ()
       ((x :init-value 0)
        (y :init-value 0))
       )

     (define-method move ((p point) dx dy)
       (inc! (slot-ref p 'x) dx)
       (inc! (slot-ref p 'y) dy))

     (define-method write-object ((p point) port)
       (format port "[point ~a ~a]"
               (slot-ref p 'x)
               (slot-ref p 'y)))

しかし、主流のオブジェクト指向言語に慣れてはいるがCLOSスタイルのオブジェクトシステムに
慣れていないプログラマは、Gaucheのオブジェクトシステムの詳細を見てゆくと
奇妙に感じることがあるのではないかと思います。
ここではGaucheのオブジェクトシステムの代表的な性質を簡単に述べておきます。
詳しくは*Note オブジェクトシステム::の章を参照して下さい。

_全てはオブジェクトである (それが気になる人には)_
     このような主張は他のOO言語でも見たことがあるでしょう。
     Gaucheもその例にもれず、実行時にクラスを得たりメソッドを呼び出したりといった
     操作が任意のオブジェクトに対して出来るという意味で、全てはオブジェクトです。
     また組込みクラスを含めたどんなクラスに対しても新しいメソッドを定義することができます。

     しかし、CLOS系のパラダイムでは、全てがオブジェクトかどうかという議論はあまり
     問題ではありません。というのは次のような性質があるからです。

_メソッドは全ての引数によってディスパッチされる_
     C++、Objective
     C、Python、RubyなどのOO言語では、メソッドは特定のクラスに
     所属しています。Gaucheではメソッドはクラスに従属しません。

     例えば、数値だけを要素に持つベクタークラス`<num-vector>'と
     行列クラス`<num-matrix>'を定義したとします。
     プログラマは、以下のようなあらゆる場合についてメソッド`product'を
     別々に定義することができます。

            (product <num-vector> <num-matrix>)
            (product <num-matrix> <num-vector>)
            (product <num-vector> <num-vector>)
            (product <num-matrix> <num-matrix>)
            (product <number>     <num-vector>)
            (product <number>     <num-matrix>)
            (product <number>     <number>)

     これらの各メソッドは、`<num-vector>'クラスや`<num-matrix>'
     クラスに所属するわけではありません。

     メソッドがクラスに所有されているわけではないので、既に存在するクラスに対していつでも
     独自のメソッドを定義することができます(但し、いくつかの組込みクラスの既定のメソッドには
     変更できないものがあります)。上の例で既にこれは示されています。プログラマは
     メソッド`product'を組込みクラス`<number>'に対して定義することが
     できます。これが、全てはオブジェクトであるかどうかはCLOSスタイルのオブジェクトシステム
     では問題にならないと言った理由です。

_クラスはインスタンスでもある_
     デフォルトでは、クラスは`<class>'というクラスのインスタンスであり、
     ジェネリック関数は`<generic>'というクラスのインスタンスです。
     しかし、`<class>'を継承したクラスを定義することにより、
     オブジェクトの初期化がどのように行われるかとか、スロットがどのように
     アクセスされるかといった動作をカスタマイズすることができます。
     また、`<generic>'を継承したクラスを定義することにより、
     適用可能なメソッドがどのように選択されて、どのような順序で適用されるか
     といったことがカスタマイズ可能です。このメカニズムは_メタオブジェクトプロトコル_
     と呼ばれています。メタオブジェクトプロトコルは、言語をその言語そのもので拡張する方法と
     言えるでしょう。

     例として、ディストリビューションに含まれる`lib/gauche/singleton.scm'や
     `lib/gauche/validator'等があります。`lib/gauche/object.scm'を
     読めば、クラス自身がGaucheでどのように定義されているかがわかります。
     メタオブジェクトプロトコルの更に詳しいことについては、 *Note
     [MOP]: mop.が参考になります。

_クラスは名前空間を作らない_
     メインストリームのOO言語ではクラスが名前空間を作ることがよくあります。
     CLOSスタイルのオブジェクトシステムはそうではありません。
     Gaucheでは、名前空間はオブジェクトシステムとは直交する、
     モジュールシステムによって管理されます。



File: gauche-refj.info,  Node: モジュールシステム,  Next: コンパイル,  Prev: 統合されたオブジェクトシステム,  Up: 主要な概念

2.6 モジュールシステム
======================

Gaucheは大きなソフトウェアをモジュール化して開発するための、
単純なモジュールシステムを備えています。

   高レベルのインタフェースを使うのはユーザにとっては非常に簡単です。
モジュール`foo'が提供する機能を使いたければ、 プログラム中で`(use
foo)'と表記するだけです。
このフォームはマクロで、コンパイル時に解釈されます。
通常は、`foo'の機能を実装したファイルをロードし、
その外部APIを呼び出したモジュール中にインポートします。

   `use'メカニズムは、名前空間の分離とファイルローディングという
二つの独立な低レベルのメカニズムの上に実装されています。
これらの低レベルメカニズムはそれぞれ別々に使うこともできます。

   `use'メカニズムは非遷移的です。すなわち、
モジュールBがモジュールAを'use'し、さらにモジュールCがモジュールBを
'use'している場合、モジュールCからはモジュールA内の束縛は見えません。
BとAはIS-A関係ではないためです。
例えばモジュールAが低レベルの操作を実装し、
モジュールBがその上に高レベルの抽象的なインタフェースを実装しているとしましょう。
モジュールCがモジュールBを'use'しているということは、
CはBの提供する抽象レイヤに興味があるということです。
もしCがさらに低レベルの層にもアクセスしたいならば、CはAを明示的に'use'しなければ
なりません。

   しかし、別の形の関係が必要な場合もあります。例えば既存のモジュールAに
ちょっと新しいインタフェースを付け加えたモジュールBをAの拡張として
提供したいという場合です。この時、BとAはIS-A関係であり、Bを'use'
しているモジュールからA内の束縛も見えるのが自然です。
Gaucheでは、これをモジュールの継承と呼び、
`extend'フォームにより実現しています。

   以下のセクションでモジュールの機能について詳しく説明しています。
   * *Note Gaucheのモジュールを書く:: ではモジュールの書き方について
     説明します。

   * *Note モジュール::
     ではモジュールを定義したり使うための特殊形式とマクロ、
     およびモジュールの内部を調べるための組込み手続きについて説明します。


File: gauche-refj.info,  Node: コンパイル,  Prev: モジュールシステム,  Up: 主要な概念

2.7 コンパイル
==============

Gaucheは、Schemeフォームをひとつづつ読み込んでは評価するという意味では
インタプリタです。しかし内部では、Gaucheはひとつひとつのフォームを中間形式に
コンパイルして仮想マシンで実行しています。

   組み込みの構文とマクロはコンパイル時に認識されて展開されます。
よく使われる組み込み関数は、コンパイル時にグローバルな束縛が置き換わっていない場合に、
インライン展開されます。

プログラマは通常、コンパイラの動作を気にする必要はほとんどありませんが、
いくつかの点に注意する必要があります。

_loadは実行時に評価される_
     `load'はGaucheでは一般の関数なので、実行時に評価されます。
     ロードされるファイル中でマクロを定義している場合、そのマクロは
     その`load'の呼び出しを含むトップレベルフォームが評価された後で
     有効になります。例えば、`foo.scm'がマクロ`foo'を定義しているとして、
     次のような用法を考えてみてください。
          ;; in "foo.scm"
          (define-syntax foo
            (syntax-rules () (_ arg) (quote arg)))

          ;; in your program
          (begin (load "foo") (foo (1 2 3)))
            => error, bad procedure: `1'

          (load "foo")
          (foo (1 2 3)) => '(1 2 3)
     `begin'で`load'と`foo'の呼び出しを囲んだ場合、
     コンパイラはまず`begin'全体をコンパイルします。その時点でマクロ
     `foo'は定義されていませんから、これは評価時にエラーになります。
     一方、後者では`load'が評価されてから`foo'がコンパイルされるので、
     問題は起きません。

     このような混乱を避けるために、別のプログラムファイルを読み込む必要がある時は
     `require'か`use'を使うことを勧めます。これらは構文であり、
     コンパイラに認識されます。

_require はコンパイル時に評価される_
     上記の裏返しですが、`require'と`use'はコンパイル時に
     解釈されます。したがって、`if'などの条件文のボディにこれらのフォームを
     置いておいても、指定されたファイルは条件にかかわらず読み込まれてしまいます。
     どうしてももし条件によって読み込むかどうかを変えたい場合は、`load'を使うか、
     条件判断自体をマクロで行うようにしてください。


File: gauche-refj.info,  Node: Gaucheでのプログラミング,  Next: 基本的な構文,  Prev: 主要な概念,  Up: Top

3 Gaucheでのプログラミング
**************************

* Menu:

* Gaucheを起動する::
* インタラクティブな開発::
* Schemeスクリプトを書く::
* デバッグ::
* プロファイリングとチューニング::
* Gaucheのモジュールを書く::
* 拡張パッケージの使用::


File: gauche-refj.info,  Node: Gaucheを起動する,  Next: インタラクティブな開発,  Prev: Gaucheでのプログラミング,  Up: Gaucheでのプログラミング

3.1 Gaucheを起動する
====================

Gaucheは独立したSchemeインタプリタとしても、組み込みのSchemeライブラリとしても
使うことができます。Gaucheのディストリビューションには、`gosh'という
インタプリタが附属しています。

 -- Program: gosh [options] [scheme-file arg ...]
     Gaucheのインタプリタです。  SCHEME-FILEが与えられなければ、
     `gosh'はインタラクティブに動作します。すなわち、標準入力からScheme式を読み込み、
     それを評価して結果をプリントするという動作を、EOFを読むか明示的に終了させられるまで
     続けます。

     もしSCHEME-FILEが与えられておらず、しかし入力が端末でない場合、
     `gosh'はread-eval-printループに入りますが、入力待ちの際にプロンプトを
     表示しません。これはScheme式をパイプでGOSHに処理させる場合に便利です。
     `-b'または`-i'オプションでこの動作を強制的にonまたはoffできます。

     SCHEME-FILEが与えられた場合、`gosh'はそれをSchemeプログラムとして
     ロードし、終了します。この動作に関しては*Note
     Schemeスクリプトを書く::を参照して 下さい。

コマンドラインオプション
------------------------

以下のコマンドラインオプションが`gosh'に認識されます。 `-'
で始まらない最初のコマンドライン引数がスクリプトファイルと認識されます。
スクリプトファイル名が `-'
で始まっている可能性がある場合は、ダミーオプション ``--''
をスクリプトファイル名の前に置いて下さい。

 -- Command Option: -I path
     PATHをロードパスのリストの最初に加えます。このオプションは複数指定できます。

 -- Command Option: -A path
     PATHをロードパスのリストの末尾に加えます。このオプションは複数指定できます。

 -- Command Option: -q
     `gosh'が起動時にシステムの初期化ファイルを読まないようにします。

 -- Command Option: -V
     `gosh'のバージョンを表示して終了します。

 -- Command Option: -u module
     起動後、インタラクティブなread-eval-printループに入る前、もしくはSCHEME-FILE
     をロードする前にMODULEを"use"します。つまりそのモジュールがロードされ
     インポートされます。(`use'の詳細については*Note
     モジュールの定義と選択::を参照して下さい)。
     このオプションは複数回指定できます。

 -- Command Option: -l file
     起動後、インタラクティブなread-eval-printループに入る前、もしくはSCHEME-FILE
     をロードする前にFILEをロードします(ロードの詳細については*Note
     Schemeファイルのロード::
     を参照して下さい)。このオプションは複数回指定できます。

 -- Command Option: -e scheme-expression
     起動後、インタラクティブなread-eval-printループに入る前、もしくはSCHEME-FILE
     をロードする前にSCHEME-EXPRESSIONを評価します。評価は
     INTERACTION-ENVIRONMENT中で行われます(*Note eval と repl::参照)。
     このオプションは複数回指定できます。

 -- Command Option: -E scheme-expression
     オプション-eとほぼ同じですが、SCHEME-EXPRESSIONは
     それが括弧で囲まれているかのように読まれます。
     このオプションは複数回指定できます。例：
          % gosh -umath.const -E"print (sin (* pi/180 15))" -Eexit
          0.25881904510252074

 -- Command Option: -b
     バッチ。入力が端末であっても、read-eval-printループがプロンプトを出さないようにします。

 -- Command Option: -i
     インタラクティブ。入力が端末で無くても、read-eval-printループが
     プロンプトを出すようにします。

 -- Command Option: -f compiler-option
     このオプションはコンパイラとランタイムの動作に影響を与えます。
     今のところ、次のオプションのみがCOMPILER-OPTIONとして有効です。
    no-inline
          Schemeの基本関数のインライン展開を行いません。

    no-source-info
          デバッグのためのソースファイル情報を保持しません。メモリの使用量は小さくなります。

    load-verbose
          ファイルがロードされる時にそれを報告します。

    case-fold
          R5RSに示される通り、シンボルの大文字小文字を区別しません。
          (デフォルトではこれらは区別されます)。 *Note
          大文字小文字の区別:: を参照して下さい。

    test
          "`../src'" と "`../lib'" を、初期化ファイルを読む前に
          ロードパスに加えます。これは、作成された`gosh'をインストールせずに
          ソースツリーの中で実行してみるのに便利です。

 -- Command Option: -p profiler-option
     プロファイラを有効にします。現在のところ、PROFILER-OPTIONとして
     "`time'" のみがサポートされています。 詳しくは*Note
     プロファイラを使う::を参照して下さい。

 -- Command Option: `--'
     このオプションに出会うと、`gosh'はオプションの解析を止めて、その次の引数を
     無条件にSCHEME-FILEであると見倣します。SCHEME-FILEがマイナス記号で
     始まっている場合に必要です。

   オプション-I, -A, -l, -u, -e 及び -E
は、それらがコマンドライン引数として
出現した順に処理されます。例えば、-Iにより追加されるロードパスは
それ以降の-lや-uオプションに影響を与えますが、それ以前のものには影響を
与えません。

環境変数
--------

以下の環境変数を認識します。

 -- Environment variable: GAUCHE_LOAD_PATH
     この環境変数によって、追加するロードパスを指定できます。 パスは
     '`:'' で区切ります。
     この変数によって指定されたパスはシステムのデフォルトのロードパスの前に
     連結されます。

 -- Environment variable: GAUCHE_DYNLOAD_PATH
     この変数によって、動的にロードするオブジェクト用の追加ロードパスを
     指定できます。パスは '`:'' で区切ります。
     この変数によって指定されたパスはシステムのデフォルトのロードパスの前に
     連結されます。


File: gauche-refj.info,  Node: インタラクティブな開発,  Next: Schemeスクリプトを書く,  Prev: Gaucheを起動する,  Up: Gaucheでのプログラミング

3.2 インタラクティブな開発
==========================

スクリプトファイルが与えられなかった場合、
`gosh'はインタラクティブなread-eval-printループに入ります。

インタプリタを終了するには、EOF文字(Unix端末では通常Control-D)をタイプするか、
`(exit)'を評価します。

   インタラクティブセッションでは、`gosh'は
`gauche.interactive'モジュールをロードします (*Note
インタラクティブセッション::参照)。
このモジュールはまた、ユーザーのホームディレクトリに`.gaucherc'という
ファイルがあればをれをロードします。
インタラクティブデバッグに便利な設定をそこに書いておくことができます。
(Gauche release 0.7.3から、`.gaucherc'はgoshがスクリプトモードで
起動された時は読まれなくなりました)。

   `gosh'をEmacs内部で走らせることをお勧めします。
EmacsはSchemeサブプロセスを操作するための豊富な機能を持っています。
次の行を`.emacs'に加えておくと、<M-x run-scheme> で
Emacsのバッファ内で`gosh'が走ります。
     (setq scheme-program-name "gosh")

対話環境でマルチバイト文字を使う場合は、端末の文字エンコーディングを`gosh'の
内部エンコーディングと合わせるようにして下さい。

   今のところ、`gosh'は行編集やコマンドヒストリなどの便利な機能を
備えていません。将来はこのへんも充実してゆくでしょう。


File: gauche-refj.info,  Node: Schemeスクリプトを書く,  Next: デバッグ,  Prev: インタラクティブな開発,  Up: Gaucheでのプログラミング

3.3 Schemeスクリプトを書く
==========================

`gosh'のコマンドラインにSchemeプログラムのファイル名が渡された場合、
`gosh'はそれ以降のコマンドライン引数のリストをグローバル変数`*argv*'に束縛し、
Schemeプログラムをロードします。もしSCHEME-FILEの最初の行が"`#!'"で始まって
いたら、その行は無視されます。これにより、Unix系のシステムで実行可能なSchemeスクリプト
を書くことが出来ます。

   典型的なGaucheスクリプトの最初の行は次のようなものです。
     #!/usr/local/bin/gosh
       または,
     #!/usr/bin/env gosh
       または,
     #!/bin/sh
     :; exec gosh -- $0 "$@"
後の2つは「シェルトランポリン」テクニックを用いて、`gosh'がPATHにあるディレクトリの
どこかにあれば起動できるようにしています。3番目の方法は、
`gosh'にいくつかコマンドラインオプションを渡したい時に便利です。

   ファイルが正常にロードされたら、`gosh'は userモジュールに ``main''
という手続きが定義されているかどうか調べ、
定義されていればそれを呼びます。`main'には、スクリプトへの引数のリストが
唯一の引数として渡されます。リストの最初の要素はスクリプトファイル名です。

`main'が整数の値を返したら、`gosh'はその値を終了ステータスとして終了します。
`main'が整数以外の値を返した場合は`gosh'は終了ステータス70
(`EX_SOFTWARE')で終了します。このふるまいはSRFI-22と互換です。

   `main'が定義されていなければ`gosh'はロード後にそのままステータス0で
終了します。

シェルスクリプトやPerlスクリプトと同じように、スクリプトのボディに直接
実行される式を書くこともできますが、なるべく ``main'' を使った方法を
使うことをお薦めします。そうすると、スクリプトをインタプリタにインタラクティブに
ロードしてデバッグすることもできます。

 -- Variable: *argv*
     Schemeスクリプト以降のコマンドライン引数のリストは、スクリプトのロードの前に
     この変数に束縛されます。`gosh'がインタラクティブモードで起動された場合は
     この変数は`()'となります。

     この変数はSTkと互換性がありますが、他のScheme実装は違った方法を使ってコマンドライン
     引数を得ます。ポータブルなスクリプトを書くには、`main'手続きを使う方法を
     お薦めします。

 -- Variable: *program-name*
     この変数はスクリプトファイル名に束縛されます。インタラクティブモードでは
     この変数は`gosh'自身の名前を持っています。

     この変数はSTkと互換性がありますが、他の実装は違った方法を使います。

いくつか簡単な例を示します。最初の例はUnixの`cat(1)'コマンドを模するものです。
エラー処理やコマンドラインオプションの処理は行っていません。

     #!/usr/bin/env gosh

     (define (main args)   ;entry point
       (if (null? (cdr args))
           (copy-port (current-input-port) (current-output-port))
           (for-each (lambda (file)
                       (call-with-input-file file
                         (lambda (in)
                           (copy-port in (current-output-port)))))
                     (cdr args)))
       0)

   次のスクリプトは簡単なgrepコマンドです。

     #!/usr/bin/env gosh

     (define (usage)
       (format (current-error-port)
               "Usage: ~a regexp file ...\n" *program-name*)
       (exit 2))

     (define (grep rx port)
       (with-input-from-port port
         (lambda ()
           (port-for-each
            (lambda (line)
              (when (rxmatch rx line)
                (format #t "~a:~a: ~a\n"
                        (port-name port)
                        (- (port-current-line port) 1)
                        line)))
            read-line))))

     (define (main args)
       (if (null? (cdr args))
           (usage)
           (let ((rx (string->regexp (cadr args))))
             (if (null? (cddr args))
                 (grep rx (current-input-port))
                 (for-each (lambda (f)
                             (call-with-input-file f
                               (lambda (p) (grep rx p))))
                           (cddr args)))))
       0)

   コマンドライン引数を処理するモジュールがあります。 *Note
コマンドライン引数の解析::を参照してください。


File: gauche-refj.info,  Node: デバッグ,  Next: プロファイリングとチューニング,  Prev: Schemeスクリプトを書く,  Up: Gaucheでのプログラミング

3.4 デバッグ
============

Gaucheにはまだデバッグをサポートする機能があまり実装されていません。
デバッギングのインタフェースに関して良いアイディアがあればお寄せください。

今のところ、作者は必要な時は古典的な「プリントスタブ」方式を使っています。
そのためのリーダーマクロ `#?=EXPR' が定義されています。 これは
`(debug-print EXPR)' のように読まれ、 マクロ `debug-print'
はEXPRを評価してその値を返しますが、
評価前と評価後にメッセージを出力します。

     gosh> #?=(+ 2 3)
     #?="(stdin)":1:(+ 2 3)
     #?-    5
     5
     gosh> #?=(begin (print "foo") (values 'a 'b 'c))
     #?="(stdin)":2:(begin (print "foo") (values 'a 'b 'c))
     foo
     #?-    a
     #?+    b
     #?+    c
     a
     b
     c
     gosh> (define (fact n)
             (if (zero? n)
                 1
                 (* n #?=(fact (- n 1)))))
     fact
     gosh> (fact 5)
     #?="(stdin)":6:(fact (- n 1))
     #?="(stdin)":6:(fact (- n 1))
     #?="(stdin)":6:(fact (- n 1))
     #?="(stdin)":6:(fact (- n 1))
     #?="(stdin)":6:(fact (- n 1))
     #?-    1
     #?-    1
     #?-    2
     #?-    6
     #?-    24
     120

   また、木村栄伸さんがGauche用のtrace/untraceマクロを書いてくれました：
`http://homepage.mac.com/skimu/ggc/'.


File: gauche-refj.info,  Node: プロファイリングとチューニング,  Next: Gaucheのモジュールを書く,  Prev: デバッグ,  Up: Gaucheでのプログラミング

3.5 プロファイリングとチューニング
==================================

自分のスクリプトのスピードが十分に出ないというときには、
性能を改善するポイントとして考えられる点がいくつかあります。

どんなときでも、実行時間を食いつぶしているコード部分を見つけるというの
を先ず最初にやるのがよいでしょう。Gauche にはこの作業を補助する基本的
なツールが2つあります。組込のサンプリングプロファイラ(これについては次
の節で説明します)を使えば各手続きでどれほどの時間がかかり、その手続き
が何回呼ばれたかを表示できます。`gauche.time' モジュール (*Note
時間の計測::) ではコードの中の特定の部分の実行にかかる時間を
測定するためのAPIが提供されています。

   最適化というのは特殊化ということでもあります。もっともよく使われる
実行のパターンを探して、そこを効率よく実行する専用のパスを設けることで
す。Gauche 自身も例外ではありません。したがって、Gaucheが効率よく実行
できるパターンがいくつかありますし、また一方では効率よく実行できないパ
ターンもあります。次の節では、*Note パフォーマンスに関するヒント:: では
Gauche が効
率良く実行できるパターンにコードをあわせるチョットしたコツを教えましょう。

* Menu:

* プロファイラを使う::
* パフォーマンスに関するヒント::


File: gauche-refj.info,  Node: プロファイラを使う,  Next: パフォーマンスに関するヒント,  Prev: プロファイリングとチューニング,  Up: プロファイリングとチューニング

3.5.1 プロファイラを使う
------------------------

0.8.4 から Gauche は組込みのプロファイラを備えています。これは
現時点ではまだ実験的なもので、Linux
上でしかテストしていません。すべてのプ
ラットフォームで利用できるわけではありませんし、シングルスレッドの
アプリケーションでしか動きません。

   非対話環境でこのプロファイラを使うには、gosh のコマンドラインオプショ
ンとして `-ptime'を指定してください。

     % gosh -ptime your-script.scm

   `your-script.scm' の実行完了後、Gauche
は各関数についてその呼び出し回数
および消費時間を示した表を印字します。この表は総消費時間の順でソートさ
れています。

     Profiler statistics (total 1457 samples, 14.57 seconds)
                                                         num    time/    total
     Name                                                calls  call(ms) samples
     ---------------------------------------------------+------+-------+-----------
     combinations*                                       237351  0.0142   337( 23%)
     (lset-difference #f)                               1281837  0.0020   256( 17%)
     (make-anchor make-anchor)                          3950793  0.0005   198( 13%)
     member                                             4627246  0.0004   190( 13%)
     filter                                              273238  0.0030    81(  5%)
     every                                              1315131  0.0004    59(  4%)
     (lset-difference #f #f)                            1281837  0.0004    54(  3%)
     (make-entry make-entry)                             730916  0.0005    40(  2%)
     (clear? #f)                                         730884  0.0005    33(  2%)
     (initialize #f)                                     599292  0.0005    32(  2%)
     fold                                                237307  0.0013    30(  2%)
     acons                                               806406  0.0004    29(  1%)
     clear?                                               33294  0.0084    28(  1%)
     (combinations* #f)                                  805504  0.0002    15(  1%)
     (make-exit make-exit)                               730884  0.0002    15(  1%)
     lset-difference                                     237318  0.0006    15(  1%)
     reverse!                                            475900  0.0001     6(  0%)
     (fold <top> <top> <list>)                           237323  0.0003     6(  0%)
     procedure?                                          238723  0.0002     4(  0%)
     pair?                                               237307  0.0001     3(  0%)
      :
      :

時間プロファイラは統計的標本化をおこなっていることに注意してください。
プロファイラは10ミリ秒ごとにプロセスに割込んで、その時点で実行されてい
る関数を記録します。ナノ秒オーダの関数呼出しごとの個別の実行時間に比べる
と、このサンプリングレートはかなり粗いものです。しかしながら、プロ
グラムの実行時間が長ければ、各関数ごとの標本分布は関数ごとの消費時間を
ほぼ反映しているだろうと期待できます。

   数字はあくまで近似にすぎないこと
を心にとめておいてください。ひとつの関数あたりの標本数はプログラムが扱
うデータが違えば、すぐに変化してしまうことがあります。
また、今のところGCにかかる時間はGCがトリガされた関数の実行時間に
算入されてしまっていることに注意して下さい。これによって、あまり
重要でない関数がリストの上位に浮かびあがってくることがあります。
一般的なパターンを知るには、プログラムをいろいろなデータで走らせて
みると良いでしょう。

   一方、関数呼び出し回数のカウントは正確なものです。これは Gauche は
実際の呼出しごとにカウントしているからです。

   Schemeでは基本的にすべての関数は無名なので、プロファイル結果の'name'
フィールドはヒントにすぎません。トップレベルで束縛されている関数につい
ては通常それが最初に束縛されたグローバル変数名が印字されます。内部関数
については関数の入れ子構造を反映して名前のリストが印字されます。
メソッドは、名前と特定化子のリストとして印字されます。

   プロファイラはそれ自身にオーバヘッドがあります。通常は、処理時間が
20-30% 増加します。プロファイラを選択的にオンにしたい場合や、
停止しないサーバプログラムを走らせていて、そのサーバを停止することなく、
統計を取りたいような場合には、プログラムからプロファイラ APIを呼ぶこと
ができます。詳細については *Note プロファイラAPI:: を参照してください。


File: gauche-refj.info,  Node: パフォーマンスに関するヒント,  Prev: プロファイラを使う,  Up: プロファイリングとチューニング

3.5.2 パフォーマンスに関するヒント
----------------------------------

Don't guess, just benchmark.  It is the first rule of performance
tuning.  Especially for the higher-level languages like Scheme, what
impacts on performance greatly depends on the implementation.  Certain
operations that are very cheap on an impelementation may be costly on
others.  Gauche has such implementation-specific characteristics, and
to know some of them would help to see what to look out in the
benchmark results.

   "80% of execution time is spent in 20% of the code" is another old
saying.  Don't obscure your code by "potential" optimization that has
little impact on the actual execution.  We describe some tips below,
but it doesn't mean you need to watch them all the time.  It is better
to keep most of the code clean and easy to understand, and only do
tricks on the innermost loop.

   *Ports*: To satisfy the specification of SRFI-18 (Threading), every
call to I/O primitives of Gauche locks the port.  This overhead may be
visible if the application does a lot of I/O with smaller units (e.g.
every bytes).   The primitives that deals with larger unit, such as
`read' and `read-block', are less problematic, since they just lock the
port once per call and do all the low-level I/O without the lock
overhead.

   If you find out the locking is indeed a bottleneck, there are couple
of things you can consider: (1) Try using the larger-unit primitives,
instead of calling the smaller-unit ones.  (2) Use `with-port-locking'
(see *Note ポートとスレッド::) to lock the port in larger context.

   *Strings*: Because of the multibyte strings, two operations are
particularly heavy in Gauche: string mutation and indexed string access.
It is a design choice; we encourage the programming style that avoids
those operations.  When you sequentially access the string, string
ports (see *Note 文字列ポート::) provides a cleaner and more efficient
way.  When you search and retrieve a substring, there are various
higher-level primitives are provided (see *Note
文字列を扱うその他の手続き::, *Note 正規表現::, and *Note
文字列ライブラリ::, for example).  If you're using strings to represent
an octet stream, use uniform vectors (see *Note ユニフォームベクタ::)
instead.

   *Deep recursion*: Gauche's VM uses a stack for efficient local frame
allocation.  If recursion goes very deep (depending on the code, but
usually several hundreds to a thousand), the stack overflows and Gauche
moves the content of the stack into the heap.  This incurs some
overhead.  If you observe a performance degradation beyond a certain
amount of data, check out this possibility.

   *Generic functions*: Because of its dynamic nature, generic function
calls are slower than procedure calls.  Not only because of the runtime
dispatch overhead, but also because Gauche's compile-time optimizer
can't do much optimization for generic function calls.  You don't need
to avoid generic functions because of performance reasons in general,
but if you do find single function call consuming a large part of
execution time and it is calling a generic function in its inner
loop--then it may be worth to modify it.

   *Redefining builtin functions*: Gauche inlines some builtin
functions if they are not redefined.  Although sometimes it is useful
to redefine basic functions, you may want to limit the effect.  For
example, put redefined functions in a separate module and use the
module in the code that absolutely needs those functions replaced.

   *Closure creation*: When you create a closure, its closing
environment is copied to the heap.  This overhead is small, but it
still may be visible when a closure is created within an innermost loop
that is called millions of times.   If you suspect this is a problem,
try disassemble the function.   Gauche's compiler uses some basic
technique of closure analysis to avoid creating closures for typical
cases, in which case you see the local function's bodies are inlined.
If you see a `CLOSURE' instruction, though, it means a closure is
created.

   This list isn't complete, and may change when Gauche's implementation
is improved, so don't take this as a fixed features.  We'll adjust it
occasionally.


File: gauche-refj.info,  Node: Gaucheのモジュールを書く,  Next: 拡張パッケージの使用,  Prev: プロファイリングとチューニング,  Up: Gaucheでのプログラミング

3.6 Gaucheのモジュールを書く
============================

Gaucheのライブラリはモジュール毎に整理されています。Gaucheはどんな形式でも、
有効なScheme式が書かれてさえいればロードすることができますが、
Gaucheのライブラリは一定の形式を保って書かれています。
Gauche用にまとまったSchemeコードを書いたら、それをモジュール形式にしておくと
再利用がしやすくなるでしょう。

   通常ひとつのファイルで
ひとつのモジュールを定義しますが、モジュールを複数のファイルに分けることもできます。
まずひとつのファイルでモジュールを定義する方法を説明します。
Gaucheのライブラリで使われているテンプレートは次のような形式です。

     ;; モジュールのインタフェースの定義
     (define-module foo
       (use xxx)
       (use yyy)
       (export foo1 foo2 foo3)
       )
     ;; モジュール本体
     (select-module foo)

     ... module body ...

     ;; `require' に対応するprovide
     (provide "foo")

   このファイルは"foo.scm"という名で、`*load-path*'にあるディレクトリの
いずれかに置かれなければなりません。

   まず、`define-module'フォームがモジュール`foo'を作成します。
`define-module'フォーム内で、このモジュールが依存している他のモジュール
を ``use''
マクロを使ってロードし、このモジュールがエクスポートするシンボルを
``export'' 構文を使って指定します。(これらの構文の詳細は*Note
モジュールの定義と選択::を 参照して下さい)。

   これらの`use'フォームや`export'フォームは必ずしも`define-module'
フォームの先頭に置く必要はありませんが、このようにファイルの最初の方に固めておくことで、
`foo'が依存しているモジュール群や`foo'が提供するシンボル等が
一覧しやすくなります。

   次の、``select-module'' フォームにより、それ以降のScheme式が
モジュール`foo'の中で評価されます。モジュールの内容を全て`define-module'の中に
書いてしまうことも出来ますが、最後の括弧を閉じ忘れやすいことや、エディタのインデントが
狂うことなどから、あまりお薦めしません。

`select-module'フォームの後には、モジュールの内容であるScheme式を自由に書けます。
それらはモジュール`foo'の中で評価されます。モジュール内で定義するトップレベルの
束縛のうち、明示的に`export'で指定されたシンボルのみが、このモジュールをインポートする他の
モジュールから見えます。

   最後の`provide'は一種の定型句です。`use'がrequire-provideメカニズムを
利用しているために必要です。

   これで、他のプログラムは ``(use foo)''
とするだけでこのモジュールの機能が
利用可能になります。もしモジュールをサイト全体で利用できるようにしたければ、`gosh'内で
     (gauche-site-library-directory)
   を評価して得られるディレクトリに`foo.scm'を置いて下さい。

モジュールの名前空間のトップに新たなモジュールを追加するのに気が引ける場合は、
モジュールを階層的に構成することもできます。Gaucheのモジュールの多くは既に階層的に
構成されています。具体的なモジュール例は*Note ライブラリモジュール -
概要::を参照して下さい。 例えば、`text.tr'モジュールは "`text/tr.scm'"
ファイルに
実装されています。パス名の区切り文字`/'がモジュール名ではピリオドになることに
注意して下さい。


File: gauche-refj.info,  Node: 拡張パッケージの使用,  Prev: Gaucheのモジュールを書く,  Up: Gaucheでのプログラミング

3.7 拡張パッケージの使用
========================

パッケージの構築とインストール
------------------------------

Gauche にはまとまったライブラリが付属していますが、 Gauche
をプロダクション環境で利用するのにはとても十分とはいえません。
利用可能な追加ライブラリもいくつもあります。こうしたライブラリを
_拡張パッケージ_、あるいは単にパッケージといいます。それぞれの
パッケージは追加機能を提供するひとつあるいはそれ以上のモジュールを
提供します。ほとんどのパッケージは別のCのライブラリへのバインディングを
提供しています。たとえば、グラフィックスライブラリとかデータベース
クライアントなどです。もし、パッケージがいくぶんでもCのコードを含む
場合は、利用するマシン上で、既にインストールされている Gauche システムを
使って、そのコードをコンパイルする必要があります。

   通常、パッケージは圧縮 tarball の形式になっています。標準的には、
「gzの解凍 + tarの展開 + configure + make + make
install」とやればよいように
なっています。パッケージのドキュメントを読めば、必要に応じて、
`configure' スクリプトに与えるコマンドラインオプションで
ライブラリを調整できるようになっています。

   Gauche 0.8 より、`gauche-package' というユーティリティスクリプトが
インストールされるようになっています。これはパッケージの構築と
インストールを自動化します。

   `Package-1.0.tar.gz' というパッケージをダウンロードしてきた
としましょう。もし、このパッケージが慣例に従っていれば、やることは

     $ gauche-package install Package-1.0.tar.gz

   とタイプするだけです。
これで、gzip圧縮ファイルの解凍、tarアーカイブファイルの展開、
`Package-1.0' サブディレクトリへの移動、configure スクリプトの
実行、make、make install が行われます。デフォルトでは、
`gauche-package' はカレントディレクトリに tarball を展開します。
これをカスタマイズファイル(後述)で変更することができます。

   ファイルをインストールするのに特別な権限が必要な場合には、
`--install-as' というオプションを使うと、`make install' 部分が、`sudo'
を使って実行されます。

     $ gauche-package install --install-as=root Package-1.0.tar.gz

   上手くいかない場合には、`gauche-package build Package-1.0.tar.gz'
とやってパッケージの構築だけすることもできます。この場合、手で
`Package-1.0' ディレクトリに移動して、`make install' を 実行します。

   設定オプションを `-C' あるいは `--configure-options'
というコマンドライン引数で与えられます。たとえば、

     $ gauche-package install -C "--prefix=/usr/local" Package-1.0.tar.gz

   もしパッケージがこの新しい記述ファイルを採用しているなら、
以前に指定した設定オプションを記憶していて、そのパッケージを
再度インストールするときには、自動的にそれを再利用します。
(パッケージ開発者の方は、Gauche のソースツリーにある、
`examples/spigot/README' ファイルをチェックアウトすれば、 どのように
Gauche のパッケージマネージメントシステムがやっているかを 見られます。)

   tarball がローカルディレクトリにない場合でも、ダウンロードしてくる
URL を知っているなら、その URL を直接 `gauche-package' に与える
ことができます。`gauche-package' は `http' および `ftp'
を理解し、`wget' か `ncftpget' のどちらかを使って、その tarball
をダウンロードし、configure および make を実行します。

     $ gauche-package install http://www.example.com/download/Package-1.0.tar.gz

`gauche-package' のカスタマイズ
-------------------------------

`gauche-package' プログラムは `~/.gauche-package' があれば、
それを読みます。このファイルにはパラメータの連想リストが含まれて
いなければなりません。こんな感じです。

     (
      (build-dir . "/home/shiro/tmp")
      (gzip      . "/usr/local/bin/gzip")
      (bzip2     . "/usr/local/bin/bzip2")
      (tar       . "/usr/local/bin/gtar")
     )

   以下は、認識されるパラメータのリストです。
設定ファイルにプログラムが与えられていなければ、`gauche-package' は
`PATH' を探します。

`build-dir'
     tarball が展開されるディレクトリ。もし、URL が与えられれば、
     ダウンロードされたファイルはこのディレクトリに置かれます。

`bzip2'
     `bzip2' プログラムへのパス

`cat'
     `cat' プログラムへのパス

`make'
     `make' プログラムへのパス

`ncftpget'
     `ncftpget' プログラムへのパス

`rm'
     `rm' プログラムへのパス

`sudo'
     `sudo' プログラムへのパス

`tar'
     `tar' プログラムへのパス

`wget'
     `wget' プログラムへのパス


File: gauche-refj.info,  Node: 基本的な構文,  Next: マクロ,  Prev: Gaucheでのプログラミング,  Up: Top

4 基本的な構文
**************

* Menu:

* 字句構造::
* リテラル::
* 手続きを作る::
* 代入::
* 条件式::
* 変数束縛::
* 順次実行::
* 繰り返し::
* 準クオート::
* 定義::
* モジュール::


File: gauche-refj.info,  Node: 字句構造,  Next: リテラル,  Prev: 基本的な構文,  Up: 基本的な構文

4.1 字句構造
============

GaucheはR5RS Schemeのパーザをいくつかの点で拡張しています。

_ネスト可能なブロックコメント (SRFI-30)_
     '`#|'' と '`|#'' で囲まれたテキストはコメントになります。
     ネスト可能です。

_数値リテラル_
     不正確な実数の整数部または小数部のいずれかが0の場合、それを省略することが
     できます。例：`30.', `.25', `-.4'。
     数値のリーダーは、パディングの'`#''を認識します。 有理数表記
     (例：`1/3') は認識されますが、読み込み時に不正確な実数へと
     変換されます。 複素数表記は直交座標形 (例：`1+0.3i') でも極座標形
     (例：3.0@1.57) でも 認識されます。

_シンボル名_
     シンボル名はデフォルトで大文字小文字を区別します (*Note
     大文字小文字の区別::参照)。 数字や'`+'', '`-''
     で始まるシンボル名も、
     トークンが有効な数値リテラルを構成しない限り許されます。
     また、他の変な文字も '|'
     でシンボルを囲むことによってシンボル名に含めることが できます
     (例：'`|this is a symbol|'')。 *Note シンボル::も参照して下さい。

_文字コードによる文字リテラル_
     文字リテラルを文字コードにより表記することができます。
     Gauche内部コードを使う `#\xNN' と、 Unicodeを使う
     `#\uNN'という表記があります。 *Note 文字::を参照して下さい。

_拡張された#構文_
     '`#'' で始まる特殊構文がたくさん定義されています。
     下の表を参照して下さい。

   以下の表はシャープ構文のリストです。

`#!'               [SRFI-22]
                   ファイルの先頭でインタプリタを指定します。
                      Scheme のローダはこの行を無視します。
`#"', `##', `#$',  未使用。
`#%', `#&', `#''   
`#('               [R5RS] ベクタを先導します。
`#)'               未使用。
`#*'               二重引用符がこれに続くときは、不完全な文字列を表します。*Note
                   文字列::参照。
`#+'               未使用。
`#,'               [SRFI-10] リーダ構築子構文を先導します。
`#-', `#.'         未使用。
`#/'               リテラルの正規表現を先導します。*Note
                   正規表現::参照。
`#0' ... `#9'      [SRFI-38] 共有サブストラクチャの定義と参照。
`#:', `#;'         未使用。
`#<'               読み取り不可能オブジェクトを先導します。
`#=', `#>'         未使用。
`#?'               デバッグマクロを先導します。*Note
                   デバッグ::参照。
`#@'               未使用。
`#a'               未使用。
`#b'               [R5RS] 2進数接頭辞。
`#c'               未使用。
`#d'               [R5RS] 10進数接頭辞。
`#e'               [R5RS] 正確数接頭辞。
`#f'               [R5RS] 真理値の偽、あるいは       SRFI-4
                   のユニフォームベクタを先導します。*Note
                   ユニフォームベクタ::参照
`#g', `#h'         未使用。
`#i'               [R5RS] 不正確数接頭辞。
`#j', `#k', `#l',  未使用。
`#m', `#n'         
`#o'               [R5RS] 8進数接頭辞。
`#p', `#q', `#r'   未使用。
`#s'               [SRFI-4] SRFI-4
                   のユニフォームベクタを先導します。*Note
                   ユニフォームベクタ::参照。
`#t'               [R5RS] 真理値の真。
`#u'               [SRFI-4] SRFI-4
                   のユニフォームベクタを先導します。*Note
                   ユニフォームベクタ::参照。
`#v', `#w'         未使用。
`#x'               [R5RS] 16進数接頭辞
`#y', `#z'         未使用。
`#['               リテラルの文字集合を先導します。*Note
                   文字集合::参照
`#\'               [R5RS] リテラルの文字を先導します。*Note
                   文字::参照。
`#]', `#^', `#_'   未使用。
`#`'               補間された文字列を先導します。*Note
                   文字列の補間::参照。
`#{'               未使用。
`#|'               [SRFI-30]
                   ブロックコメントを先導します。コメントは対応する
                   '`|#'' で終ります。
`#}', `#~'         未使用。


File: gauche-refj.info,  Node: リテラル,  Next: 手続きを作る,  Prev: 字句構造,  Up: 基本的な構文

4.2 リテラル
============

 -- Special Form: quote datum
     [R5RS] DATUMそれ自身を返します。
          (quote x) => x
          (quote (1 2 3)) => (1 2 3)

 -- Reader Syntax: `'DATUM'
     [R5RS] `(quote datum)'の略記です。
          'x => x
          '(1 2 3) => (1 2 3)

_注:_ R5RSは、リテラル式の値を変更するのはエラーであるとしています。
しかしGaucheはペアとベクタについてはそれが定数であるかどうかをチェックしておらず、
`set-car!'や`vector-set!'等の破壊的手続きによってそれらの値を
変更できてしまいます。そうした場合の動作は不定です。
文字列に関しては定数かどうかのチェックを行っており、定数文字列を変更しようとすると
エラーが報告されます。


File: gauche-refj.info,  Node: 手続きを作る,  Next: 代入,  Prev: リテラル,  Up: 基本的な構文

4.3 手続きを作る
================

 -- Special Form: lambda formals body ...
     [R5RS]
     この式は評価されると手続きを生成します。この式が評価された時点の環境が手続き中に保持されます。
     手続きが呼ばれると、記憶された環境に引数の束縛を追加した環境中でBODY
     が順に評価され、 最後の式の値が返されます。

     FORMALS は以下のいずれかの形でなければなりません。
        * `(VARIABLE ...)' : 手続きは決まった数の引数を取ります。
          実引数がそれぞれ対応するVARIABLEに束縛されます。

        * `VARIABLE' : 手続きは不定個の引数を取ります。
          実引数は新しいリストに集められて、そのリストがVARIBLEに束縛されます。

        * `(VARIABLE_0 ... VARIABLE_N-1. VARIABLE_N)' :
          手続きは少なくともN個の引数を取ります。N個までの実引数は対応するVARIABLE
          に束縛されます。N個を越えた実引数は新しいリストに集められて
          VARIABLE_Nに束縛されます。

          (lambda (a b) (+ a b))
            => 二つの引数を加算する手続き

          ((lambda (a b) (+ a b)) 1 2)
            => 3

_注:_ いくつかのSchemeの実装ではFORMALSの構文を拡張して、
CommonLispのように省略可能引数やキーワード引数などの表記を可能にしているものが
あります。Gaucheには今のところそのような拡張はありません。

 -- Macro: cut expr-or-slot expr-or-slot2 ...
 -- Macro: cute expr-or-slot expr-or-slot2 ...
     [SRFI-26] 手続きを簡潔に書ける便利なマクロです。
     いわゆる部分適用を実現するために使えます。

     各EXPR-OR-SLOTは式またはシンボル`<>'でなければなりません。
     最後のEXPR-OR-SLOTはシンボル`<...>'であっても構いません。
     `cut'は、そのフォーム中にある`<>'と同じ数の引数を取る
     `lambda'フォームに展開されます。そのフォームのボディには次の式が置かれます。
            (EXPR-OR-SLOT EXPR-OR-SLOT2 ...)
     但し、各`<>'は対応する仮引数に置き換えられます。
     もしシンボル`<...>'が与えられていた場合、展開された`lambda'フォームは
     可変長引数を取る手続きとなり、作成される手続きに与えられたすべての引数が
     EXPR-OR-SLOTを呼び出すのに使われます(下の4番目の例を参照のこと)。

          (cut cons (+ a 1) <>)  == (lambda (x2) (cons (+ a 1) x2))
          (cut list 1 <> 3 <> 5) == (lambda (x2 x4) (list 1 x2 3 x4 5))
          (cut list)             == (lambda () (list))
          (cut list 1 <> 3 <...>)
             == (lambda (x2 . xs) (apply list 1 x2 3 xs))
          (cut <> a b)           == (lambda (f) (f a b))

          ;; Usage
          (map (cut * 2 <>) '(1 2 3 4))
          (for-each (cut write <> port) exprs)

     `cute'は`cut'とほぼ同じですが、`expr-or-slot'に与えられた
     フォームが手続きを作る前に評価される点が異なります。

          (cute cons (+ a 1) <>)
             == (let ((xa (+ a 1))) (lambda (x2) (cons xa x2)))

     Gaucheはまた、部分適用を行う`pa$'という組み込み手続きを持っています
     (*Note コンビネータ::参照)。

 -- Macro: case-lambda clause ...
     [SRFI-16] それぞれの CLAUSE は (FORMALS EXPR ...) という形式
     でなければなりません。ここで、FORMALS は `lambda' の仮引数
     リストです。

     この式は、評価されると可変数の引数をとり、`lambda' 式から結果として
     できる手続き同じレキシカルスコープをもつ手続きになります。この手続きが
     いくつかの引数とともに呼ばれると、FORMALS と一致する引数に対応する
     最初の CLAUSE が選択されます。この引数の一致というのは、 `lambda'
     式の FORMALS に対応するものとして指定されるものです。 `formals'
     の変数は実引数に束縛され、 EXPR ... がその 環境内で評価されます。

     実際の引数がどの CLAUSE の FORMALS にも一致しなければエラーです。


File: gauche-refj.info,  Node: 代入,  Next: 条件式,  Prev: 手続きを作る,  Up: 基本的な構文

4.4 代入
========

 -- Special Form: set! symbol expression
 -- Special Form: set! (proc arg ...) expression
     [R5RS][SRFI-17]
     まずEXPRESSIONが評価されます。最初の形式では、SYMBOLへの束縛が
     EXPRESSIONの結果を指すように変更されます。
     もしSYMBOLがローカルに束縛されていない場合は、グローバルな変数SYMBOLが
     存在していなければなりません。そうでなければエラーが報告されます。

     2番目の形式はSRFI-17に定義されている「一般化されたset!」です。
     これは構文的な装飾であり、実際は以下のように解釈されます。
          ((setter PROC) ARG ... EXPRESSION)
     CommonLispの`setf'とは、setter手続きに渡される引数の順序が異なることに注意して下さい。

     例：

          (define x 3)
          (set! x (list 1 2))  => undefined
          x                    => (1 2)

          (set! (car x) 5)     => undefined
          x                    => (5 2)

 -- Macro: set!-values (var ...) expr
     複数の変数を同時に更新します。EXPRは与えられた変数と同じ
     数だけの値を生成しなけばなりません。各値が対応するVARに
     セットされます。
          (define a 0)
          (define b 1)
          (set!-values (a b) (values 3 4)) => undefined
          a => 3
          b => 4
          (set!-values (a b) (values b a)) => undefined
          a => 4
          b => 3

 -- Function: setter proc
     [SRFI-17] 手続きPROCのsetter手続きを返します。
     PROCがsetter手続きを持たない場合の動作は不定です。

     ある関数Fのsetter手続きGとは、もし`(g a b ... v)'のように
     呼ばれた場合、次の`(f a b
     ...)'がVを返すようになる手続きのことです。

     ある手続きにsetter手続きを関連付けるには、`setter'自身のsetter手続きを使うことが
     できます。
          (set! (setter F) G)

     特定の手続きにsetter手続きを「ロック」することができます。システム既定のsetter手続き、
     例えば`car'に対する`set-car!'等はロックされていて、上記のような方法で
     変更することは出来ません。ユーザ定義手続きにsetter手続きをロックするには下記の
     `getter-with-setter'を使います。

     PROCが手続きでない場合は、`object-apply'ジェネリックファンクションの
     setterが返されます。これにより、適用可能オブジェクトが一般化された`set!'
     でもうまく動作します。詳しくは*Note
     適用可能なオブジェクト::を参照して下さい。

 -- Function: has-setter? proc
     PROCがsetter手続きを持っている場合は`#t'を返します。

 -- Function: getter-with-setter get set
     [SRFI-17] 2つの手続き、GETとSETを取り、新しい手続きを返します。
     新しい手続きはGETと同じ動作をし、そのsetter手続きはSETにロックされて
     います。

     この手続きは、SRFI-17によれば、setter手続きのインライン展開を可能にするための
     ものですが、Gaucheではまだそのような最適化は実装されていません。

Gaucheでは、一般化された`set!'と同じセマンティクスを持ついくつかのマクロが定義
されています。これらはSET!を使った形に展開されます。

 -- Macro: push! place item
     ITEMとPLACEの値をコンスし、その結果を再びPLACEにセットします。
     PLACEは`set!'と同様に、 変数か(PROC ARG
     ...)という形式でなければなりません。このマクロの戻り値は
     未定義です。

          (define x (list 2))
          (push! x 3) => undefined
          x => (3 2)

          (push! (cdr x) 4) => undefined
          x => (3 4 2)

     PLACEがリストの場合、だいたいこんなふうに展開されます。

          (push! (foo x y) item)
           ==
           (let ((tfoo foo)
                 (tx x)
                 (ty y))
             ((setter tfoo) tx ty (cons item (tfoo tx ty))))

     註：Common Lispの`push'マクロは引数を逆の順番で取ります。
     `push!'は他の副作用を持つ形式との互換性を考えてこの順番としました。
     Perlの`push'関数は`push!'マクロと同じ引数順ですが、
     ITEMはシーケンスの末尾に追加されます (Perlの`unshift'の方が
     `push!'の動作に近いです)。
     Perlのpushオペレータの動作が必要ならQueueが使えます (*Note
     キュー::参照)。

 -- Macro: pop! place
     PLACEの値を取り出し、その`cdr'をPLACEにセットします。
     元の値の`car'を返します。

          (define x (list 1 2 3))
          (pop! x) => 1
          x => (2 3)

          (define x (vector (list 1 2 3)))
          x => #((1 2 3))
          (pop! (vector-ref x 0)) => 1
          x => #((2 3))

     註：この動作はCommon Lispの`pop'と同じです。
     Perlの`pop'はシーケンスの末尾から値を取ります。
     Perlなら`shift'が`pop!'の動作に近いです。

 -- Macro: inc! place &optional delta
 -- Macro: dec! place &optional delta
     PLACEの値を評価します。それは数値にならなければなりません。
     その値にDELTAが加算(`inc!')もしくは減算(`dec!')され、
     結果がPLACEに格納されます。DELTAの既定値は1です。

     Common Lispの`incf'と`decf'に当たります。

 -- Macro: update! place proc
     `push!'等のマクロの一般化された形式です。
     PROCは一つの引数を取り、一つの値を返す手続きでなければなりません。
     PLACEの値がPROCに渡され、PROCの結果がPLACEに格納されます。
          (define a (cons 2 3))
          (update! (car a) (lambda (v) (* v 3))) => undefined
          a => (6 . 3)

          (update! (cdr a) (cut - <> 3))
          a => (6 . 0)


File: gauche-refj.info,  Node: 条件式,  Next: 変数束縛,  Prev: 代入,  Up: 基本的な構文

4.5 条件式
==========

 -- Special Form: if test consequent alternative
 -- Special Form: if test consequent
     [R5RS]
     まず`test'を評価し、それが真の値を返したらCONSEQUENTを評価します。
     そうでなければALTERNATIVEを評価します。もしALTERNATIVEが与えられて
     いなければ未定義の値を返します。

          (if (number? 3) 'yes 'no) => yes
          (if (number? #f) 'yes 'no) => no

          (let ((x '(1 . 2)))
            (if (pair? x)
                (values (car x) (cdr x))
                (values #f #f)))
            => 1 and 2

 -- Special Form: cond clause1 clause2 ...
     [R5RS] 各`clause'節は次のいずれかの形式でなければなりません。
          (TEST EXPR ...)
          (TEST => EXPR)
          (else EXPR EXPR2 ...)
     最後の形式は最後の節のみに許されます。

     最初の節から順にTESTが評価され、それが真の値を返すまで次の節のTESTが
     評価されます。TESTが真の値を返したら、それが最初の形式であれば
     その節のEXPRが順に評価され、最後の評価値が戻り値となります。
     それが2番目の形式であれば、EXPRがまず評価されます。
     EXPRは引数をひとつ取る手続きを返さねばなりません。
     続いて、TESTの結果がその手続きに渡され、その手続きの戻り値が`cond'形式の
     評価値となります。
     もし全てのテストが偽の値を返し、最後の節が3番目の形式(else節)でなければ、未定義の値が返されます。

     最後の節が`else'節で、他の全てのテストが失敗した場合、`else'節のEXPR
     が順に評価され、その最後の値が`cond'形式の値となります。

          (cond ((> 3 2) 'greater)
                ((< 3 2) 'less)) => greater
          (cond ((> 3 3) 'greater)
                ((< 3 3) 'less)
                (else 'equal)) => equal
          (cond ((assv 'b '((a 1) (b 2))) => cadr)
                (else #f)) => 2

 -- Special Form: case key clause1 clause2 ...
     [R5RS] KEYは任意の式です。CLAUSEは以下の形式でなければなりません。
          ((DATUM ...) EXPR EXPR2 ...)
     ここで、各DATUMはSchemeオブジェクトの外部表現であり、全てのDATUMは
     異なっていなければなりません。最後のCLAUSEには次の形式を持つelse節が許されます。
          (else EXPR EXPR2 ...)

     まずKEYが評価され、その結果がそれぞれのDATUMと比較されます。
     KEYの値と`eqv?'(*Note 等価::参照)を使って一致するDATUM
     が見つかれば、対応するEXPRが順に評価され、その最後の値が`case'の
     値となります。もし一致するDATUMが見つからない場合、else節が与えられていれば
     そのEXPRが順に評価され、最後の値が返されます。else節がなければ`case'節
     の値は未定義です。
          (case (* 2 3)
            ((2 3 5 7) 'prime)
            ((1 4 6 8 9) 'composite)) => composite
          (case (car '(c d))
            ((a) 'a)
            ((b) 'b)) => undefined
          (case (car '(c d))
            ((a e i o u) 'vowel)
            ((w y) 'semivowel)
            (else 'consonant)) => consonant

 -- Special Form: and test ...
     [R5RS]
     TEST式が順に評価されます。最初に偽の値を返したところで評価が止まり、
     偽の値が返されます。残りの式は評価されません。
     もし全ての式が真の値を返した場合は、最後の式の値が返されます。
     式が与えれない場合は`#t'が返されます。

          (and (= 2 2) (> 2 1)) => #t
          (and (= 2 2) (< 2 1)) => #f
          (and 1 2 'c '(f g))   => (f g)
          (and)                 => #t

 -- Special Form: or test ...
     [R5RS]
     TEST式が順に評価されます。最初に真の値を返したところで評価が止まり、
     その値が返されます。残りの式は評価されません。
     もし全ての式が偽の値を返した場合は、偽の値が返されます。
     式が与えれない場合は`#f'が返されます。

          (or (= 2 2) (> 2 1)) => #t
          (or (= 2 2) (< 2 1)) => #t
          (or #f #f #f)        => #f
          (or (memq 'b '(a b c))
              (/ 3 0)) => (b c)

 -- Special Form: when test body ...
 -- Special Form: unless test body ...
     まずTESTが評価されます。それが真の値(`unless'の場合は偽の値)を返した場合、
     引続きBODYが順に評価され、最後のBODYの評価値が返されます。
     そうでなければ、未定義の値が返されます。


File: gauche-refj.info,  Node: 変数束縛,  Next: 順次実行,  Prev: 条件式,  Up: 基本的な構文

4.6 変数束縛
============

 -- Special Form: let ((var expr) ...) body ...
 -- Special Form: let* ((var expr) ...) body ...
 -- Special Form: letrec ((var expr) ...) body ...
     [R5RS] 各変数VARがEXPRの値に束縛されているローカルな環境を作成し、
     その中でBODY ...を評価します。VARはシンボルでなければ
     ならず、重複があってはなりません。BODY ...の最後の式の値が
     このフォームの値となります。

     これらの3つのフォームの違いは、EXPRが評価される時点のスコープにあります。
     `let'はEXPRをLETフォームに入る前の環境において評価します。
     `let*'はEXPRを順に、それ以前のVARが束縛された環境において評価して
     ゆきます。LETRECは全てのVARが仮想的に不定の値に束縛された環境において
     各EXPRを評価します。LETRECは相互再帰的なローカル関数を定義する場合に
     必要です。
          (define x 'top-x)

          (let  ((x 3) (y x)) (cons x y)) => (3 . top-x)
          (let* ((x 3) (y x)) (cons x y)) => (3 . 3)

          (let ((cons (lambda (a b) (+ a b)))
                (list (lambda (a b) (cons a (cons b 0)))))
            (list 1 2))  => (1 2 . 0)

          (letrec ((cons (lambda (a b) (+ a b)))
                   (list (lambda (a b) (cons a (cons b 0)))))
            (list 1 2))  => 3

 -- Macro: let1 var expr body ...
     変数が一つしか無い場合の便利なマクロです。次のように展開されます。

          (let ((VAR EXPR)) BODY ...)

 -- Macro: fluid-let ((var val) ...) body ...
     動的スコープの変数をエミュレートするマクロです。
     VARは`fluid-let'フォームを含むスコープで定義されている
     変数でなければなりません。VALは式です。
     `fluid-let'はまずVALを評価し、
     VALをVARに動的スコープで束縛してBODY ... を評価します。

     マルチスレッド環境下では、VARの値の変化は全てのスレッドから見えます。
     このフォームは主として他の処理系のコードを移植する際の利便性のために
     追加されました。スレッドローカルな動的状態を実現するには、
     パラメータオブジェクト(*Note パラメータ::参照)を 使って下さい。
          (define x 0)

          (define (print-x) (print x))

          (fluid-let ((x 1))
            (print-x))  => ;; prints 1

 -- Special Form: receive formals expression body ...
     [SRFI-8] この構文により、多値を受け取ることができます。
     FORMALSはシンボルのリストです。不完全なリストであっても構いません。
     EXPRESSIONが評価され、返された値がlambda形式の引数の束縛と
     同じようにしてFORMALS内の変数と束縛され、その環境下でBODY ...が
     評価されます。

          (define (divrem n m)
            (values (quotient n m) (remainder n m)))

          (receive (q r) (divrem 13 4) (list q r))
            => (3 1)

          (receive all (divrem 13 4) all)
            => (3 1)

          (receive (q . rest) (divrem 13 4) (list q rest)
            => (3 (1))

     なお、*Note 多値::の`call-with-values'は
     `receive'と等価な手続き的インタフェースです。
     多値を複数のトップレベル変数に束縛するには、`define-values' (*Note
     定義::参照) が使えます。 また、SRFI-11 (*Note Let-values::)
     の`let-values'と
     `let*-values'は`let'のような形式で多値を扱うことができます。

 -- Macro: rec var expr
 -- Macro: rec (name . vars) expr ...
     [SRFI-31] 再帰的な参照のある式の評価を行うマクロです。

     最初の形式は、VARがEXPRの結果に束縛される状態でEXPRを 評価します。
     2番目の形式は以下の形式と等価です。
          (rec NAME (lambda VARS EXPR ...))

     例：

          ;; constant infinite stream
          (rec s (cons 1 (delay s)))

          ;; factorial function
          (rec (f n)
            (if (zero? n)
                1
                (* n (f (- n 1)))))


File: gauche-refj.info,  Node: 順次実行,  Next: 繰り返し,  Prev: 変数束縛,  Up: 基本的な構文

4.7 順次実行
============

 -- Special Form: begin form ...
     [R5RS] FORMを順に評価し、最後の値を返します。

     `Begin'は`let'のような「ブロック」を作成するわけではありません。
     すなわち、一般的にはFORM ...の先頭に「内部のdefine (internal
     define)」を 置くことはできません。意味的には、`begin'はまるでFORM
     ...が
     `begin'を囲むコンテクスト中に展開されているかのように振舞います。
     例えば、トップレベルに次のような式があった場合、それは2つのトップレベルのdefineと
     同等です。

          (begin (define x 1) (define y 2))

     よりトリッキーな例:

          (let ()
            (begin
              (define x 2)
              (begin
                (define y 3)
              ))
            (+ x y))

            ==

          (let ()
            (define x 2)
            (define y 3)
            (+ x y))

 -- Macro: begin0 exp0 exp1 ...
     EXP0, EXP1, ... を評価し、EXP0の結果を返します。
     この名前はMzSchemeから取られました。これはCommonLispで
     `prog1'と呼ばれているものです。

     `begin'と違って、これは「ブロック」を構成します。
     `begin0'フォームは次のように展開されるからです。

          (receive tmp EXP0
            EXP1 ...
            (apply values tmp))


File: gauche-refj.info,  Node: 繰り返し,  Next: 準クオート,  Prev: 順次実行,  Up: 基本的な構文

4.8 繰り返し
============

 -- Special Form: do ((variable init [step]) ...) (test expr ...) body
          ...
     [R5RS]

 -- Special Form: let name bindings body ...
     [R5RS]

 -- Macro: dotimes (variable limit [result]) body ...
 -- Macro: dolist (variable lexpr [result]) body ...
     Common Lispからの輸入です。それぞれ以下のように展開されます。
          (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))


File: gauche-refj.info,  Node: 準クオート,  Next: 定義,  Prev: 繰り返し,  Up: 基本的な構文

4.9 準クオート(Quasiquote)
==========================

 -- Special Form: quasiquote template
     [R5RS]


File: gauche-refj.info,  Node: 定義,  Next: モジュール,  Prev: 準クオート,  Up: 基本的な構文

4.10 定義
=========

 -- Special Form: define variable expression
 -- Special Form: define (variable . formals) body ...
     [R5RS] この形式はトップレベル (ローカルな束縛が無い状態)
     とローカルスコープがある状態とで 別の意味を持ちます。

     トップレベルでは、この形式は変数VARIABLEに対するグローバルな束縛を定義します。
     最初の形式では、EXPRESSIONが評価され、その結果が変数VARIABLEの値となります。
          (define x (+ 1 2))
          x => 3
          (define y (lambda (a) (* a 2)))
          (y 8) => 16

     2番目の形式は手続きを定義するための構文的な修飾で、以下の形式と同じです。
          (define (NAME . ARGS) BODY ...)
            == (define NAME (lambda ARGS BODY ...))

     このフォームがローカルスコープの中に現われた場合、ローカル変数の束縛となります。

     `begin'は新しいスコープを作らないことに注意してください(*Note
     順次実行::参照)。
     `begin'の中に現われる`define'は、あたかも`begin'とそれを囲む
     括弧が無いかのように振舞います。すなわち、以下の2つの形式は等価です。
          (let ((x 0))
            (begin
              (define (foo y) (+ x y)))
            (foo 3))
           ==
          (let ((x 0))
            (define (foo y) (+ x y))
            (foo 3))

 -- Macro: define-values (var ...) expr
     まずEXPRが評価されます。それは与えられたVARと同数の値を
     返さなければなりません。続いて各値がVARに順に束縛されます。 *Note
     Let-values::も参照してください。
          (define-values (lo hi) (min&max 3 -1 15 2))

          lo => -1
          hi => 15

 -- Special Form: define-constant variable expression
 -- Special Form: define-constant (variable . formals) body ...
     `define'と同じように動作しますが、
     コンパイラはVARIABLEの値が今後変更されないものとして
     最適化されたコードを生成します。

     VARIABLEの値を`set!'で変更しようとするとエラーとなります。
     VARIABLEを再定義することは許されますが、警告が表示されます。

 -- Special Form: define-in-module module variable expression
 -- Special Form: define-in-module module (variable . formals) body ...
     この形式はVARIABLEのグローバルな束縛をMODULE中に作成します。
     MODULEはモジュール名を表すシンボルか、モジュールオブジェクトで
     なければなりません。MODULEがシンボルの場合、その名前を持つ
     モジュールが既に存在している必要があります。

     EXPRESSIONは現在のモジュール中で評価されます。

     2番目の形式は次の形式の構文的修飾です。
          (define-in-module module variable (lambda formals body ...))

   註:
シンボルが現在のモジュール中で定義されているか(グローバルな束縛を持つか)
を調べるには、`symbol-bound?'が使えます (*Note
モジュールイントロスペクション::参照)。


File: gauche-refj.info,  Node: モジュール,  Prev: 定義,  Up: 基本的な構文

4.11 モジュール
===============

この章では、GaucheのモジュールのセマンティクスとAPIを述べます。
Gaucheで使われているモジュールの書法については*Note
Gaucheのモジュールを書く::も 併せて参照して下さい。

* Menu:

* モジュールのセマンティクス::
* モジュールとライブラリ::
* モジュールの定義と選択::
* モジュールの使用::
* モジュールの継承::
* モジュールイントロスペクション::
* 組み込みモジュール::


File: gauche-refj.info,  Node: モジュールのセマンティクス,  Next: モジュールとライブラリ,  Prev: モジュール,  Up: モジュール

4.11.1 モジュールのセマンティクス
---------------------------------

モジュールは、シンボルを束縛へとマップするオブジェクトで、
グローバル変数の解決に影響を与えます。

   CommonLispのパッケージは名前からシンボルへのマッピングを行いますが、
Gaucheでは同じ名前を持つシンボルは常に`eq?'です。しかし、
Gaucheのシンボルは「値」のスロットを持っていません。
モジュールによってシンボルに対応する束縛が見付けられ、値はそこに
格納されています。
モジュールが違えば同じシンボルは別々の束縛へとマップされ、違う値を
返します。

     ;; 二つのモジュールAとBを作成し、グローバル変数'x'をその中で定義
     (define-module A (define x 3))
     (define-module B (define x 4))

     ;;  #<symbol 'x'> ---[module A]--> #<binding that has 3>
     (with-module A x) => 3

     ;;  #<symbol 'x'> ---[module B]--> #<binding that has 4>
     (with-module B x) => 4

   モジュールは、自身が持つ一部または全ての束縛を他のモジュールからも
使えるように_export_することができます。あるモジュールXが他の
モジュールYを_import_すると、
モジュールYでexportされている束縛が元のモジュールXから見えるようになります。
モジュールはいくつでも他のモジュールをimportすることができます。

     (define-module A
       (export pi)
       (define pi 3.1416))

     (define-module B
       (export e)
       (define e 2.71828))

     (define-module C
       (import A B))

     (select-module C)
     (* pi e) => 8.539748448

   また、モジュールは継承することもできます。
既存のモジュールを継承したモジュールに新しい束縛を足してexportすることにより、
既存のモジュールを拡張することができます。新しいモジュールの内部からは、
継承元のモジュールの束縛が(exportされていないものも含め)全て見えます。
(新しく作られるモジュールはデフォルトで`gauche'モジュールを継承しています。
新しいモジュールから`gauche'の組込み手続き等が使えるのはそのためです)。
外からは、新しいモジュールには元のモジュールの全てのexportされた束縛と
新たに追加されexportされた束縛が見えます。

     ;; Module A defines and exports deg->rad.
     ;; A binding of pi is not exported.
     (define-module A
       (export deg->rad)
       (define pi 3.1416)   ;; not exported
       (define (deg->rad deg) (* deg (/ pi 180))))

     ;; Module Aprime defines and exports rad->deg.
     ;; The binding of pi is visible from inside Aprime.
     (define-module Aprime
       (extend A)
       (export rad->deg)
       (define (rad->deg rad) (* rad (/ 180 pi))))

     ;; Module C imports Aprime.
     (define-module C
       (import Aprime)
       ;; Here, both deg->rad and rad->deg are visible,
       ;; but pi is not visible.
       )

   コンパイル中のどの時点でも、「カレントモジュール」が一意に決定され、
グローバル変数の束縛はそのカレントモジュールを起点に探されます。
その変数の束縛が見付かれば、変数参照の式はその束縛へアクセスするコードとして
コンパイルされます。もしコンパイラが束縛を見付けられなかった場合、
変数参照の式はカレントモジュールでマークされ、束縛の解決はランタイムへと
先送りされます。すなわち、ランタイムにその変数が使われる時点で
再びマークされていたモジュールから束縛の探索が行われます
(ランタイムでのカレントモジュールからでは無いことに注意)。
束縛が見付かれば、束縛へアクセスするコードがコンパイルされたコード列に
挿入されます。見付からなければ'undefined variable'エラーが報告されます。

   グローバル変数に対して適切な束縛がひとたび発見されれば、
その束縛へのアクセスはコンパイルされたコードに埋め込まれ、
その変数の束縛の探索は二度と行われません。

   `define'や`define-syntax'等の定義を行う特殊形式は
カレントモジュールに束縛を挿入します。これは、importしたり継承したりしている
モジュールの同名の束縛をシャドウします。

   グローバル変数の束縛の解決は次の手順で行われます。
まずカレントモジュールが探されます。次に、importしているモジュールが
importされた逆の順番に並べられ、それぞれについてその
モジュールおよびそのモジュールの先祖(継承されているモジュール)が順に探されます。
importは遷移的ではありません；importされたモジュールがimportしているモジュール…
というふうに再帰的に辿ることはしません。
最後に、カレントモジュールの先祖が順に探されます。

この順序は、複数のモジュールで同じ名前が定義され、あなたのモジュールが
その両方をインポートしている場合に重要になります。
その名前があなたのモジュールで
定義されていないとして、もしモジュール`A'がまずimportされ、
次に`B'がimportされている場合、あなたのコードは`B'の
束縛を見ることになります。

   `A'をimportして`B'をimportした後に再び`A'をimport
した場合、後のimportの方が効力を持ちます。すなわち、`A'の束縛が
見えることになります。


File: gauche-refj.info,  Node: モジュールとライブラリ,  Next: モジュールの定義と選択,  Prev: モジュールのセマンティクス,  Up: モジュール

4.11.2 モジュールとライブラリ
-----------------------------

モジュールは実行時データ構造です。実行時に任意の名前のモジュールを
手続き的に作成することができます。

しかしほとんどのライブラリは、固有の名前空間を生成します。これにより、
どの束縛を、ライブラリ使用者に見せるかを制御できます。

   通常ライブラリは1つ以上のSchemeソースファイル形式で提供されます。
したがって、ファイル名をモジュール名に対応づける(またはその逆の)
規約にしておけば便利です。そうすれば、たとえば、ライブラリーファイルを
ロードしたり、`use' マクロを使ってモジュールを一動作で、
インポートしたりできます。

   当分の間、Gauche
はこの対応づけのための単純なルールを使用します。すなわち、
モジュール名は、例えば `gauche.mop.validator' のように ``.''
(ピリオド)記号で階層的に区切って構成されます。このようなモジュールが
要求されても、現在の実行時環境に存在しない場合には、Gauche は
ピリオド記号をディレクトリ区切りに変換して `gauche/mop/validator'
のようにモジュール名からパス名に変換します。その後、
`gauche/mop/validator.scm' をロードパスから探します。

   これが単にデフォルトの振る舞いであることに注意してください。
理論上、1つのSchemeソース・ファイルは多数のモジュールを含むことがあります。
あるいは、1つのモジュール実装は多数のファイルにまたがることもありえます。
将来、特別なケースのために、この対応付けをカスタマイズするフックを
用意するかもしれません。したがって、モジュールおよびライブラリーファイルを
扱うルーチンを書く場合には、上記のデフォルトルールを盲目的に適用しないで
ください。Gaucheは `module-name->path' と `path->module-name' という
2つの対応づけ手続き(詳細に関しては、*Note
モジュールイントロスペクション::参照) を用意しています。


File: gauche-refj.info,  Node: モジュールの定義と選択,  Next: モジュールの使用,  Prev: モジュールとライブラリ,  Up: モジュール

4.11.3 モジュールの定義と選択
-----------------------------

 -- Special Form: define-module name body ...
     NAMEはシンボルでなければなりません。
     名前NAMEを持つモジュールが存在しなければまず作成します。
     それから、BODY ... をモジュールNAME中で評価します。

 -- Special Form: select-module name
     名前NAMEを持つモジュールをカレントモジュールとします。
     その名前を持つモジュールが無ければエラーとなります。

     `select-module'がSchemeファイルの中で用いられた場合、
     その効果はそのファイルの終了までに限られます。`select-module'を中で呼んでいる
     ファイルをloadやrequireしても、呼んだ側のカレントモジュールは影響を受けません。

 -- Special Form: with-module name body ...
     名前NAMEを持つモジュールをカレントモジュールとした状態でBODY ...
     を順に評価し、最後の結果を返します。該当するモジュールが存在しなければエラーとなります。

 -- Special Form: current-module
     コンパイル時点でのカレントモジュールに評価されます。
     これは手続きではなく特殊形式です。
     Gaucheではモジュールはコンパイル時に静的に決定されます。
          (define-module foo
            (export get-current-module)
            (define (get-current-module) (module-name (current-module))))

          (define-module bar
            (import foo)
            (get-current-module)) => foo ; not bar


File: gauche-refj.info,  Node: モジュールの使用,  Next: モジュールの継承,  Prev: モジュールの定義と選択,  Up: モジュール

4.11.4 モジュールの使用
-----------------------

 -- Special Form: export symbol ...
     カレントモジュールの中で、シンボルSYMBOLに対応する束縛をexportします。
     exportされた束縛は、カレントモジュールをimportしたモジュール中で見えるようになります。

 -- Special Form: export-all
     カレントモジュール中の全ての束縛をexportします。

 -- Special Form: import module-name ...
     名前MODULE-NAMEを持つモジュールがexportしている束縛を
     カレントモジュール中で使えるようにします。該当するモジュールが既に定義されて
     いなければなりません。

     モジュールのimportは遷移的でないことに注意してください。
     `module-name'で指定されるモジュール内でimportしているモジュールは、
     カレントモジュールにはimportされません。
     これはモジュールのモジュラリティを保つために必要です；
     例えば、ライブラリモジュールは内部で使用するためにいくつも他のモジュールを
     importするかもしれませんが、それがそのライブラリモジュールを使用するモジュールの
     名前空間に影響することはないわけです。

 -- Macro: use name
     モジュールのインポートとオンデマンドのファイルのロードを合わせて行う、
     便利なマクロです。基本的に、`(use foo)' は以下のふたつのフォームと
     等価です。
          (require "foo")
          (import foo)
     すなわち、まず名前"`foo'"を持つライブラリファイルが(まだロードされて
     いなければ)ロードされ、その中で定義されているモジュール`foo'をカレントモジュールに
     インポートします。

     ファイルのロードとモジュールとは直交する概念ですが、
     現実にはモジュール毎にファイルを分割するのが便利です。
     必ずしもそうする必要は無く、`require' と `import' を別々に
     使っても構いません。が、Gaucheに附属してくるライブラリはすべて、
     `use' マクロで使えるように書かれています。

     もしモジュールが一つのファイルに収めるには大きすぎる場合、一つのメインファイルと
     いくつかのサブファイルに分けることも出来ます。メインファイルの中でモジュールを
     定義し、サブファイルをまとめてロードするか、オートロードを設定します。

     実際は、与えられたモジュール名からファイルのパス名を得るのに
     手続き`module-name->path'が使われます。デフォルトの変換規則は、
     モジュール名NAME中のピリオド``.''を``/''に置換
     するというものです。例えば`(use foo.bar.baz)'は
          (require "foo/bar/baz")
          (import foo.bar.baz)
     となります。これはあまりScheme風ではありませんが、便利ではあります。
     将来、このマッピングルールをカスタマイズする機構が導入されるかもしれません。


File: gauche-refj.info,  Node: モジュールの継承,  Next: モジュールイントロスペクション,  Prev: モジュールの使用,  Up: モジュール

4.11.5 モジュールの継承
-----------------------

export-importメカニズムは、次のような場合をうまく処理できません。

   *
     既存のモジュールとほぼ同等の機能を持つが、若干定義を足したり変更したり
     したモジュールを作りたい。

   * 相互に関連するいくつものモジュールを作成した。
     ユーザがこれらのモジュールを使う時に毎回いくつも 'use'
     を並べないで済むように 一つにまとめたい。

   このような場合にモジュールの継承が使えます。

 -- Macro: extend module-name ...
     カレントモジュールが、MODULE-NAME ...に挙げられたモジュールを
     継承するようにします。それまでの継承の情報は捨てられ、MODULE-NAME
     ...  から計算される継承情報が有効になります。

     新たに作られるモジュールはデフォルトで`gauche'モジュールを継承しています。
     例えばそのモジュールに`(extend scheme)'というフォームを入れた場合、
     その時点でそのモジュールは`scheme'モジュール(R5RSで定義された束縛
     のみを含む)を直接継承するようになります。したがって、そのフォームの後で
     'import' やその他`gauche'特有の束縛はそのモジュール内では
     使えなくなります。

     MODULE-NAMEに挙げられたモジュールがまだ存在しなかった場合、
     `extend'は`use'と同じメカニズムを使ってファイルをロードすることを
     試みます。

     モジュールは複数のモジュールを継承することができます。
     丁度、クラスが複数のクラスを継承できるのと同じようにです。
     多重継承の場合、次のようにしてモジュール間の優先順位が決められます。

     各モジュールは_module precedence list_というモジュールのリストを
     持っています。そこにリストされた順に束縛が探されます。
     モジュールが複数のモジュールを多重継承した場合、継承される各モジュールの
     module precedence listを、次に挙げる制約を満たすようにマージ
     したものが新たなmodule precedence listとなります： (1) あるmodule
     precedence listでモジュールAがモジュールBより前に現れていたら、
     結果のmodule precedence listでもAはBより前に現れる： (2)
     モジュールAがモジュールBより`extend'フォームで前に現れていたら、
     結果のmodule precedence listでもAはBより前に現れる。
     この条件を満たすようなmodule precedence
     listが構成できない場合はエラーとなります。

   例えばあなたがライブラリを3つのモジュール、
`mylib.base'、`mylib.util'、`mylib.system'に分けて
書いたとしましょう。次のように書けば、これらのモジュールを
一つの`mylib'モジュールに見せることができます。

     (define-module mylib
       (extend mylib.system mylib.util mylib.base))

   このライブラリモジュールのユーザは `(use mylib)' とするだけで
全てのサブモジュールのexportされた束縛を利用することができるようになります。


File: gauche-refj.info,  Node: モジュールイントロスペクション,  Next: 組み込みモジュール,  Prev: モジュールの継承,  Up: モジュール

4.11.6 モジュールイントロスペクション
-------------------------------------

この節では、実行時にモジュールを操作する手続きをリストします。
これらの手続きにより、例えばモジュールの内部を調べたり、手続き的に
新しいモジュールを作成したり、特定のモジュールやライブラリの存在を
調べたりすることができます。ただし、モジュールは第一にコンパイル時の
構造であることを忘れないでください。実行時にモジュールをいじくるのは、
十分にモジュールの構造を理解した上で行ってください。

 -- Builtin Class: <module>
     モジュールクラスです。

 -- Function: module? obj
     OBJがモジュールなら真の値を返します。

 -- Function: find-module name
     名前がシンボルNAMEであるようなモジュールを返します。
     その名前をもつモジュールが存在しなければ、`#f'を返します。

 -- Function: make-module name &keyword if-exists
     シンボルの名前NAMEを持つモジュールを作成して返します。
     その名前を持つモジュールが既に存在していた場合、その動作は
     IF-EXISTSキーワード引数で指定されます。
     IF-EXISTS引数が`:error'である場合（デフォルト）、
     エラーが報告されます。それが`#f'である場合は単に`#f'が返されます。

     モジュールを実行時に動的に生成することは、通常のスクリプトでは
     あまり必要とはされません。既に書かれたプログラムの解釈においては、
     モジュールは名前で指定されている必要があるからです。
     構文`define-module'、`import'、`extend'、`with-module'
     等はモジュールそのものではなくモジュール名を取ります。
     これは、モジュールが本質的にコンパイル時の構造であるためです。
     しかし、動的に作られるモジュールが有用な場合もあります--プログラムそのものが、
     動的に作られる場合です。`eval'にモジュールを渡して、
     そのような動的に作られたプログラムがそのモジュールの中で
     コンパイルされ評価されるようにできます。

     また、NAMEに`#f'を渡すことで無名のモジュールを作ることもできます。
     無名のモジュールは`find-module'で探すことはできませんし、
     他のモジュールから`import'することも`extend'されることも
     できません（`import'や`extend'はモジュール名を必要とするからです）。
     無名のモジュールは、一時的に隔離された名前空間を動的に作りたい時に
     便利です。例えばネットワークで接続されたプログラムから送られた式を
     その中で評価して、コネクションが終了したら名前空間ごと捨ててしまうという
     ような場合です。無名のモジュールはシステムの内部辞書に登録されないので、
     モジュールへの参照が無くなればガベージコレクトされます。

 -- Function: all-modules
     現在存在する全ての名前付きモジュールのリストを返します。
     無名のモジュールは含まれません。

 -- Function: module-name module
 -- Function: module-imports module
 -- Function: module-exports module
 -- Function: module-table module
     モジュールオブジェクトのアクセスメソッドです。
     MODULEの名前(シンボル)、MODULEがインポートしているモジュールのリスト、
     エクスポートしているシンボルのリスト、そして
     シンボルから束縛へのマップを行うハッシュテーブルを返します。

     もしMODULEが全てのシンボルをエクスポートしている場合は、`module-exports'
     は`#t'を返します。

     モジュールオブジェクト以外が渡された場合はエラーになります。

 -- Function: module-parents module
 -- Function: module-precedence-list module
     モジュールの継承に関する情報を返します。
     `module-parents'はMODULEが直接継承しているモジュールのリストを
     返します。`module-precedence-list'はMODULEのmodule precedence list
     (*Note モジュールの継承::参照) を返します。

 -- Function: symbol-bound? symbol &optional module
     SYMBOLのグローバルなバインディングがMODULEから
     可視であれば、真を返します。MODULEが省略された場合は、
     現在のモジュールが使われます。

 -- Function: module-name->path symbol
     モジュール名SYMBOLを、パス名の一部へと変換します。

 -- Function: path->module-name string
     `module-name->path'の逆関数です。

特定のライブラリやモジュールがシステムにインストールされて使える状態にあるか
調べたりする場合は、*Note ライブラリの操作::を参照して下さい。


File: gauche-refj.info,  Node: 組み込みモジュール,  Prev: モジュールイントロスペクション,  Up: モジュール

4.11.7 組み込みモジュール
-------------------------

Gauche起動時にいくつかのモジュールがあらかじめ定義されています。

 -- Builtin Module: null
     このモジュールはR5RSで述べられている"null
     environment"に相当します。
     R5RSの構文要素への束縛だけを含んだモジュールです。

 -- Builtin Module: scheme
     このモジュールは`null'モジュール内の束縛全てに加えて、
     R5RSで定義されている全ての手続きの束縛を含みます。

   `select-module'によって一度`null'や`scheme'モジュールに
入ると、そこから他のモジュールに移ることはできなくなることに注意してください。
これらのモジュールからは、あらゆるモジュール操作構文が不可視だからです。

 -- Builtin Module: gauche
     このモジュールは`scheme'モジュール内の全ての束縛に加え、
     Gaucheの組込み手続きや構文が含まれています。

 -- Builtin Module: user
     このモジュールはユーザコードがコンパイルされる既定のモジュールです。
     `gauche'モジュール内の全ての束縛がインポートされています。


File: gauche-refj.info,  Node: マクロ,  Next: 組み込みライブラリ,  Prev: 基本的な構文,  Up: Top

5 マクロ
********

Gaucheでは、R5RSに定義される「健全な(hygienic)」マクロと
伝統的なマクロの両方が使えます。

Lisp系言語のマクロは、他の言語に見られるマクロ(例えばCプリプロセッサマクロ)とは
大きく異なります。Lispのマクロは元の言語の構文を拡張する手段なのです。
例えば、Gaucheの構文を若干変えることで他のScheme実装用に書かれたSchemeプログラムを
走らせたり、あるいは自分の問題解決に適した「ミニ言語」をデザインすることさえできます。

* Menu:

* 健全なマクロ::
* 伝統的なマクロ::
* マクロの展開::
* マクロユーティリティ::


File: gauche-refj.info,  Node: 健全なマクロ,  Next: 伝統的なマクロ,  Prev: マクロ,  Up: マクロ

5.1 健全なマクロ
================

R5RSの健全なマクロは特別なパターン言語に基づいていて、
また「変数捕捉」が起こらないことが保証されています。
「変数捕捉」とは、マクロが新しい変数束縛を導入した時に、その束縛が
マクロに渡されたフォーム中の変数名と衝突して、その変数名の本来の束縛を隠して
しまうことを言います。

 -- Special Form: define-syntax name transformer-spec
     [R5RS]

 -- Special Form: let-syntax ((name transformer-spec) ...) body
 -- Special Form: letrec-syntax ((name transformer-spec) ...) body
     [R5RS]

 -- Special Form: syntax-rules literals clause1 clause2 ...
     [R5RS]


File: gauche-refj.info,  Node: 伝統的なマクロ,  Next: マクロの展開,  Prev: 健全なマクロ,  Up: マクロ

5.2 伝統的なマクロ
==================

 -- Special Form: define-macro name procedure
 -- Special Form: define-macro (name formals) body ...
     変換子が PROCEDURE である大域マクロ NAME を定義します。
     2番目のフォームは、以下のフォームの簡易記法です。
          (define-macro name (lambda formals body ...))

     コンパイラが `(name ARG ...)' というフォームを見つけると、 ARG ...
     を引数として PROCEDURE を呼び出します。 PROCEDURE
     が戻ると、コンパイラは元のフォームの場所に返されたフォームを
     挿入し、再度それをコンパイルします。


File: gauche-refj.info,  Node: マクロの展開,  Next: マクロユーティリティ,  Prev: 伝統的なマクロ,  Up: マクロ

5.3 マクロの展開
================

 -- Function: macroexpand form
 -- Function: macroexpand-1 form
     FORM がリストで、その最初の要素が大域的にマクロに束縛された
     変数であるならば、`macroexpand-1'はそのマクロ変換子を実行し、
     展開されたフォームを返します。そうでなければ、FORM をそのまま
     返します。

     `macroexpand' は、FORM が展開できなくなるまで `macroexpand-1'
     を繰り返します。

     これらの手続きは、大域的に定義されたマクロを展開するために使うことが
     できます。

 -- Special Form: %macroexpand form
 -- Special Form: %macroexpand-1 form


File: gauche-refj.info,  Node: マクロユーティリティ,  Prev: マクロの展開,  Up: マクロ

5.4 マクロユーティリティ
========================

 -- Macro: syntax-error msg arg ...
 -- Macro: syntax-errorf fmt arg ...
     これらは`error'と`errorf' (*Note 例外の通知::参照) と
     ほぼ同じですが、実行時ではなくマクロ展開時(すなわち、コンパイル時)に
     エラーを通知するところが異なります。

     これらの手続きは、マクロの誤った使い方を、
     マクロ展開ルーチンの出す複雑なエラーではなく、
     分かりやすい方法でユーザーに通知するのに使えます。 そのため、ARG
     ...はまず下に述べる`unwrap-syntax'に渡されて
     内部の構文的束縛情報を取り除いた後でこれらの手続きに渡されます。

          (define-syntax my-macro
            (syntax-rules ()
              ((_ a b)   (foo2 a b))
              ((_ a b c) (foo3 a b c))
              ((_ . ?)
               (syntax-error "malformed my-macro" (my-macro . ?)))))

          (my-macro 1 2 3 4)
            => error: "malformed my-macro: (mymacro 1 2 3 4)"


 -- Function: unwrap-syntax form
     FORMの内部的な構文情報を取り除きます。
     健全なマクロの実装のために、マクロ拡張ルーチンはマクロ内のシンボルを
     識別子(identifier)に置き換えます。識別子はそれが現れる構文的環境を
     捕捉します。それはコンパイラに取っては必要な情報ですが、
     エラーメッセージに現れるとユーザーを混乱させるもとにもなります。
     そこで、この手続きではFORM中の識別子をもとのシンボルに
     置換しなおします。


File: gauche-refj.info,  Node: 組み込みライブラリ,  Next: オブジェクトシステム,  Prev: マクロ,  Up: Top

6 組み込みライブラリ
********************

* Menu:

* 等価::
* 数値::
* 論理値::
* ペアとリスト::
* シンボル::
* キーワード::
* Identifier::
* 文字::
* 文字集合::
* 文字列::
* 正規表現::
* ベクター::
* ハッシュテーブル::
* Weak ポインタ::
* 制御::
* 例外::
* eval と repl::
* 入出力::
* プログラムのロード::
* 比較とソート::
* システムインタフェース::
* 開発補助API::


File: gauche-refj.info,  Node: 等価,  Next: 数値,  Prev: 組み込みライブラリ,  Up: 組み込みライブラリ

6.1 等価
========

Schemeには等価性を判定する汎用的な述語が3つあります。
また、これらの他に、いくつかの型はその型同士で使える比較手続きを持っています。

 -- Function: eq? obj1 obj2
     [R5RS] 最も高速で、細かい区別ができる述語です。
     OBJ1とOBJ2がアロケートされる同じ型のオブジェクトで、
     かつ両者がメモリ上の全く同じ場所を占めるオブジェクトを指している場合に
     `#t'を返します。また、OBJ1とOBJ2がともに `#f',
     `#t'あるいは`()'である場合も`#t'を返します。
     ポインタ比較と考えても良いでしょう。
     OBJ1とOBJ2がともに文字、あるいは数値であった場合の振るまいは
     Schemeの標準では定められていません。

          (eq? #t #t)               => #t
          (eq? #t #f)               => #f
          (eq? 'a 'a)               => #t
          (eq? 'a 'b)               => #f
          (eq? (list 'a) (list 'a)) => #f
          (let ((x (list 'a)))
            (eq? x x))              => #t

 -- Function: eqv? obj1 obj2
     [R5RS]
     OBJ1とOBJ2がともに正確な数値、もしくはともに不正確な数値である場合、
     `(= OBJ1 OBJ2)'が真であれば`#t'が、偽であれば`#f'が 返されます。
     OBJ1とOBJ2がともに文字である場合、 `(char=? OBJ1
     OBJ2)'が真であれば`#t'が、偽であれば`#f'が 返されます。
     それ以外の場合は、Gaucheでは`eqv?'は`eq?'と同じです。

          (eqv? #\a #\a)             => #t
          (eqv? #\a #\b)             => #f
          (eqv? 1.0 1.0)             => #t
          (eqv? 1 1)                 => #t
          (eqv? 1 1.0)               => #f
          (eqv? (list 'a) (list 'a)) => #f
          (let ((x (list 'a)))
            (eqv? x x))              => #t

 -- Function: equal? obj1 obj2
     [R5RS+] OBJ1とOBJ2がリストやベクタなどの複合型である場合、
     `equal?'は再帰的に対応する要素同士を`equal?'で比較してゆきます。
     そうでなければ、`equal?'は`eqv?'と同じようにふるまいます。

     もし`obj1'とOBJ2が論理値、数値、文字、ペア、文字列、
     ベクタのいずれでもなく、かつ両者のクラスが等しい場合、`equal?'は
     ジェネリックファンクション`object-equal?'を呼びます。
     `object-equal?'にメソッドを定義することにより、
     ユーザ定義のデータ型に対する`equal?'の振るまいを拡張することができます。

          (equal? (list 1 2) (list 1 2)) => #t
          (equal? "abc" "abc")           => #t
          (equal? 100 100)               => #t
          (equal? 100 100.0)             => #f


 -- Generic Function: object-equal? obj1 obj2
     `equal?'が未知のオブジェクトに対して呼ばれた場合、
     このジェネリックファンクションが呼ばれます。自分で定義したクラスに対して
     このメソッドを定義することにより、`equal?'で等価判定が行えるように
     なります。メソッドは、OBJ1とOBJ2が等価ならば`#t'を、
     そうでなければ`#f'を返さねばなりません。
     オブジェクトの各要素に対して再帰的に等価判定を行いたい場合は、
     `object-equal?'を直接呼ぶのではなく、`equal?'を各要素に対して
     呼ぶようにして下さい。

          (define-class <foo> ()
            ((x :init-keyword :x)
             (y :init-keyword :y)))

          (define-method object-equal? ((a <foo>) (b <foo>))
            (and (equal? (slot-ref a 'x) (slot-ref b 'x))
                 (equal? (slot-ref a 'y) (slot-ref b 'y))))

          (equal? (make <foo> :x 1 :y (list 'a 'b))
                  (make <foo> :x 1 :y (list 'a 'b)))
            => #t

          (equal? (make <foo> :x 1 :y (make <foo> :x 3 :y 4))
                  (make <foo> :x 1 :y (make <foo> :x 3 :y 4)))
            => #t

しばしば、ふたつの複合型オブジェクトに関して、両者がトポロジー的に等しいこと、
すなわち一方が共有する部分構造を持っている場合にもう一方も同じように部分構造を
共有しているかどうかを調べたいことがあります。`equal?'はその目的には
使えません。モジュール`util.isomorph'の提供する`isomorphic?'が
その目的に使えます。(*Note 同型判定::参照)。


File: gauche-refj.info,  Node: 数値,  Next: 論理値,  Prev: 等価,  Up: 組み込みライブラリ

6.2 数値
========

Gaucheは次のタイプの数値をサポートしています。
多倍長の正確な整数
     メモリの許す限りの精度が扱えます。

浮動少数点の不正確な実数
     実装に使われるC言語の`double'型で表現されます。通常IEEE
     64bit浮動少数点数です。

浮動少数点の不正確な複素数
     実部と虚部はそれぞれ浮動少数点の不正確な実数で表現されます。

* Menu:

* 数値クラス::
* 数値に関する述語::
* 数値の比較::
* 数値の演算::
* 数値の変換::
* ビット演算::


File: gauche-refj.info,  Node: 数値クラス,  Next: 数値に関する述語,  Prev: 数値,  Up: 数値

6.2.1 数値クラス
----------------

 -- Builtin Class: <number>
 -- Builtin Class: <complex>
 -- Builtin Class: <real>
 -- Builtin Class: <integer>
     数値オブジェクトのクラス階層を構成します。`<complex>'は
     `<number>'を継承し、`<real>'は`<complex>'を継承し、
     `<integer>'は`<real>'を継承します。

     これらのクラスはR5RSで定義されている数値の階層とは必ずしも対応しません。
     特に、`<integer>'クラスのインスタンスはR5RSでいうexact
     integerのみになります。
          (integer? 1)        => #t
          (is-a? 1 <integer>) => #t
          (is-a? 1 <real>)    => #t

          (integer? 1.0)        => #t
          (is-a? 1.0 <integer>) => #f
          (is-a? 1.0 <real>)    => #t

          (class-of (expt 2 100)) => #<class <integer>>
          (class-of (sqrt -3)) => #<class <complex>>


File: gauche-refj.info,  Node: 数値に関する述語,  Next: 数値の比較,  Prev: 数値クラス,  Up: 数値

6.2.2 数値に関する述語
----------------------

 -- Function: number? obj
 -- Function: complex? obj
 -- Function: real? obj
 -- Function: rational? obj
 -- Function: integer? obj
     [R5RS]
     OBJがそれぞれ数、複素数、実数、有理数、整数ならば`#t'を返します。
     Gaucheでは、数の集合は複素数の集合と同一であり、有理数の集合は実数の集合と同一
     (浮動小数点数が有限精度のであるため)です。

          (complex? 3+4i)   => #t
          (complex? 3)      => #t
          (real? 3)         => #t
          (real? -2.5+0.0i) => #t
          (real? #e1e10)    => #t
          (integer? 3+0i)   => #t
          (integer? 3.0)    => #t

 -- Function: exact? obj
 -- Function: inexact? obj
     [R5RS] OBJがそれぞれ正確な数、不正確な数ならば`#t'を返します。

          (exact? 1)       => #t
          (exact? 1.0)     => #f
          (inexact? 1)     => #f
          (inexact? 1.0)   => #t

          (exact? (modulo 5 3)) => #t
          (inexact? (modulo 5 3.0)) => #f

 -- Function: zero? z
     [R5RS] 数値Zがゼロに等しければ`#t'を返します。

          (zero? 1)        => #f
          (zero? 0)        => #t
          (zero? 0.0)      => #t
          (zero? 0.0+0.0i) => #t

 -- Function: positive? x
 -- Function: negative? x
     [R5RS] 実数Xがそれぞれ正または負なら`#t'を返します。
     非実数を渡すとエラーになります。

 -- Function: odd? n
 -- Function: even? n
     [R5RS] 整数Nがそれぞれ奇数または偶数なら`#t'を返します。
     非整数を渡すとエラーになります。

          (odd? 3)     => #t
          (even? 3)    => #f
          (odd? 3.0)   => #t

 -- Function: fixnum? n
 -- Function: bignum? n
     Nが正確な整数で、かつ内部的にそれぞれFIXNUMもしくはBIGNUM
     で表現されているときに`#t'を返します。
     通常のSchemeプログラムは整数の内部表現を気にする必要はありません。
     これらの手続きは、ある種の最適化を行う低レベル手続きのために用意されています。


File: gauche-refj.info,  Node: 数値の比較,  Next: 数値の演算,  Prev: 数値に関する述語,  Up: 数値

6.2.3 数値の比較
----------------

 -- Function: `=' z1 z2 z3 ...
     [R5RS] 与えられた全ての数値Zが等しければ`#t'を返します。

          (= 2 2)          => #t
          (= 2 3)          => #f
          (= 2 2.0)        => #t
          (= 2 2.0 2.0+0i) => #t

 -- Function: `<' x1 x2 x3 ...
 -- Function: `<=' x1 x2 x3 ...
 -- Function: `>' x1 x2 x3 ...
 -- Function: `>=' x1 x2 x3 ...
     [R5RS]
     与えられた全ての実数Xがそれぞれ単調増加、単調非減少、単調減少、単調非増加している
     場合に`#t'を返します。

 -- Function: max x1 x2 ...
 -- Function: min x1 x2 ...
     [R5RS] 与えられた実数のうち、それぞれ最大と最小のものを返します。

 -- Function: min&max x1 x2 ...
     与えられた実数から、最大値と最小値の二つの値を返します。


File: gauche-refj.info,  Node: 数値の演算,  Next: 数値の変換,  Prev: 数値の比較,  Up: 数値

6.2.4 数値の演算
----------------

 -- Function: `+' z ...
 -- Function: `*' z ...
     [R5RS]
     与えられた数の和と積をそれぞれ返します。引数が与えられない場合、
     `(+)' は 0、 `(*)' は 1 となります。

 -- Function: `-' z1 z2 ...
 -- Function: `/' z1 z2 ...
     [R5RS]
     一つだけ数値が与えられた場合、それぞれnegationと逆数を返します。

     2つ以上の数値が与えられた場合、それぞれ次の結果を返します。
          Z1 - Z2 - Z3 ...
          Z1 / Z2 / Z3 ...

          (- 3)       => -3
          (- -3.0)    => 3.0
          (- 5+2i)    => -5.0-2.0i
          (/ 3)       => 0.333333333333333
          (/ 5+2i)    => 0.172413793103448-0.0689655172413793i

          (- 5 2 1)     => 2
          (- 5 2.0 1)   => 2.0
          (- 5+3i -i)   => 5.0+2.0i
          (/ 6+2i 2)    => 3.0+1.0i

 -- Function: abs z
     [R5RS+] 実数のZに対しては、その絶対値を返します。
     複素数のZに対しては、そのmagnitudeを返します。
     複素数を扱うのはGaucheの拡張です。
          (abs -1)   => 1
          (abs -1.0) => 1.0
          (abs 1+i)  => 1.4142135623731

 -- Function: quotient n1 n2
 -- Function: remainder n1 n2
 -- Function: modulo n1 n2
     [R5RS] 整数N1を整数N2で割った商(quotient)および余り(remainder,
     modulo) を返します。
     N1とN2の両方が正確な数値の時のみ、戻り値は正確な数値になります。

     `remainder'と`modulo'
     はどちらかの引数が負の時に異なる値を返します。 Remainder R と商 Q
     とは次の関係があります。
            N1 = Q * N2 + R
     ここで商について `abs(Q) = floor(abs(N1)/abs(N2))'
     ですから、Rの符号は常にN1と同じになります。

     一方、moduloはN2が正の時はN1の符号に関わらず期待したように動作します
     (例: `(modulo -1 N2) == N2 - 1')。
     N2が負の場合は次の式によって正の場合にマップできます。
            modulo(N1, N2) = -modulo(-N1, -N2)
     したがって、moduloの結果の符号は常にN2の符号と同じになります。
          (remainder 10 3)    => 1
          (modulo 10 3)       => 1

          (remainder -10 3)   => -1
          (modulo -10 3)      => 2

          (remainder 10 -3)   => 1
          (modulo 10 -3)      => -2

          (remainder -10 -3)  => -1
          (modulo -10 -3)     => -1

 -- Function: quotient&remainder n1 n2
     整数N1を整数N2で割った商(quotient)および余り(remainder)
     を同時に計算し、2つの値として返します。

 -- Function: gcd n ...
 -- Function: lcm n ...
     [R5RS] 与えられた整数の、最大公約数と最小公倍数をそれぞれ返します。

 -- Function: numerator q
 -- Function: denominator q
     [R5RS]
     有理数Qの分子と分母をそれぞれ返します。Gaucheでは今のところ有理数を完全には
     サポートしていないため、これらの手続きは実際には整数にしか使えません。すなわち、
     整数Qに対して`numerator'は常にQを返し、`denominator'
     は常に1を返します。

 -- Function: floor x
 -- Function: ceiling x
 -- Function: truncate x
 -- Function: round x
     [R5RS]
     引数Xは実数でなければなりません。`floor'と`ceiling'はそれぞれ
     Xを越えない最大の整数と、Xを下回らない最小の整数を返します。
     TRUNCATEはXの小数部をゼロの方向に向かって切捨てた整数を返します。
     ROUNDはXに最も近い(四捨五入した)整数を返します。Xの
     小数部が0.5ぴったりだった場合はROUNDは最も近い偶数を返します。

 -- Function: clamp x &optional min max
           MIN if X `<' MIN
           X   if MIN `<=' X `<=' MAX
           MAX if MAX `<' X
     を返します。もしMINまたはMAXが省略されるか`#f'が与えられたら、
     それぞれ -∞ もしくは +∞ と解釈されます。
     与えられた全ての数値が正確な整数の場合に限り正確な整数を返します。
          (clamp 3.1 0.0 1.0) => 1.0
          (clamp 0.5 0.0 1.0) => 0.5
          (clamp -0.3 0.0 1.0) => 0.0
          (clamp -5 0)        => 0
          (clamp 3724 #f 256) => 256

 -- Function: exp z
 -- Function: log z
 -- Function: sin z
 -- Function: cos z
 -- Function: tan z
 -- Function: asin z
 -- Function: acos z
 -- Function: atan z
     [R5RS] 超越関数です。複素数も扱えます。

 -- Function: atan x y
     [R5RS] 実数XとYに対して`atan(Y/X)'を返します。

 -- Function: sinh z
 -- Function: cosh z
 -- Function: tanh z
 -- Function: asinh z
 -- Function: acosh z
 -- Function: atanh z
     双曲線関数です。複素数も扱えます。

 -- Function: sqrt z
     [R5RS] 複素数Zの平方根のひとつを返します。枝刈りの定義はCommon
     Lispと同じです。 実数に対しては正の平方根を返します。

 -- Function: expt z1 z2
     [R5RS] 複素数Z1, Z2に対して、 Z1^Z2 (Z1のZ2乗)を返します。


File: gauche-refj.info,  Node: 数値の変換,  Next: ビット演算,  Prev: 数値の演算,  Up: 数値

6.2.5 数値の変換
----------------

 -- Function: make-rectangular x1 x2
 -- Function: make-polar x1 x2
     [R5RS] 二つの実数X1とX2から複素数を作ります。 `make-rectangular'
     は X1 + iX2 を返します。 `make-polar' は X1e^(iX2) を返します。

 -- Function: real-part z
 -- Function: imag-part z
 -- Function: magnitude z
 -- Function: angle z
     [R5RS] 複素数Zを取り、実数を返します。
     `real-part'と`imag-part'はZの実数部と虚数部をそれぞれ返し、
     `magnitude'と`angle'はZの絶対値と偏角をそれぞれ返します。

 -- Function: decode-float x
     与えられた浮動小数点数(不正確な実数)Xに対して、
     3つの正確な整数からなるベクタ `#(M, E, SIGN)' を返します。ここで、
            X = (* SIGN M (expt 2.0 E))
            SIGN は 1, 0 または -1.
     です。このAPIはChezSchemeから取られました。
          (decode-float 3.1415926)
           => #(7074237631354954 -51 1)
          (* 7074237631354954 (expt 2.0 -51))
           => 3.1415926

 -- Function: fmod x y
 -- Function: modf x
 -- Function: frexp x
 -- Function: ldexp x n
     [POSIX]
     これらの手続きは、浮動少数点数を分解したり合成するのに使えます。
     `fmod'は実数Xを実数Yで割った余りを返します。すなわち、
     X/Yを0に近いほうの整数に丸めた値をNとするとき、 X-N*Yを返します。
     `modf'はXの少数部と整数部を返します。
     `frexp'は実数Xを、仮数部と指数部に分解して返します。すなわち、 X =
     FRACTION * 2^EXPONENT かつ 0 <= FRACTION <= 0.5
     であるところのFRACTIONとEXPONENTを返します。
     `ldexp'は`frexp'の逆関数で、X * 2^N を返します。
          (fmod 32.1 10.0)  => 2.1
          (fmod 1.5 1.4)    => 0.1
          (modf 12.5)       => 0.5 and 12.0
          (frexp 3.14)      => 0.785 and 2
          (ldexp 0.785 2)   => 3.14

 -- Function: exact->inexact z
 -- Function: inexact->exact z
     [R5RS] 正確な数を不正確な数に変換、またその逆を行う手続きです。

     Gaucheは一般的な有理数をサポートしないため、`inexact->exact'の結果は
     常に整数となります。整数でない数を渡した場合は小数点以下が丸められます。但しこれは
     実装依存の振舞いなので、ポータブルなプログラムで不正確な実数を正確な整数に丸めたい
     時には`inexact->exact'の前に明示的に`round'を使うべきでしょう。

     不正確な数を`exact->inexact'に渡したり、または正確な数を
     `inexact->exact'に渡した場合、Gaucheでは今のところエラーにならず
     引数がそのまま返されます。これも実装依存の振舞いなのでなるべく避けるようにして下さい。

 -- Function: number->string z &optional radix use-upper?
 -- Function: string->number string &optional radix
     [R5RS+]
     これらの手続きは数値とそれをRADIX進数で表現する文字列とを変換します。
     RADIXは2から36の間でなければなりません。省略された場合は10進数とみなされます。

     `number->string'は数値Zを取り文字列を返します。
     Zが正確な整数以外の場合、RADIXは10でなければなりません。
     10より大きいRADIXに関しては、小文字のアルファベットが桁として使われます。
     但し、省略可能な引数USE-UPPER?に真の値が与えられた場合は大文字のアルファベットが
     使われます。USE-UPPER?引数はGaucheの拡張です。

     `string->number'は文字列STRINGを取り数値を返します。
     不正確な数値は10進数表記しか認識されません。与えられた文字列が数値を構成しない
     場合は`#f'が返されます。

 -- Generic Function: x->number obj
 -- Generic Function: x->integer obj
     数値への強制型変換手続きです。
     OBJをそれぞれ数値もしくは正確な整数と解釈して返します。
     数値と文字列に対してのメソッドは定義されています
     (文字列はSTRING->NUMBERを使って変換されます。
     数値として解釈できない文字列に関しては0が返されます)。
     その他のOBJについては単に0が返されます。
     `x->integer'は、OBJが数値として表現できるけれど正確な整数では
     ない場合、`round'と`inexact->exact'によって正確な整数に変換します。

     他のクラスはこのメソッドを定義することにより、独自の変換関数を提供することができます。


File: gauche-refj.info,  Node: ビット演算,  Prev: 数値の変換,  Up: 数値

6.2.6 ビット演算
----------------

これらの手続きは整数を半無限のビットベクタとして扱います。
正の整数の場合、数値の左側に無限に0が続いていると見倣されます。
負の整数の場合、数値は2の補数で表現され、左側に無限に1が続いていると見倣されます。

   APIはSLIBの"logical"モジュールに合わせてあります。

 -- Function: ash n count
     整数Nを左に整数COUNTビットだけシフトします。
     COUNTが負であれば、-COUNTだけNを右にシフトします。

          ; Note: 6  == [...00110], and
          ;       -6 == [...11010]
          (ash 6 2)   => 24  ;[...0011000]
          (ash 6 -2)  => 1   ;[...0000001]
          (ash -6 2)  => -24 ;[...1101000]
          (ash -6 -2) => -2  ;[...1111110]

 -- Function: logand n1 n2 ...
 -- Function: logior n1 n2 ...
 -- Function: logxor n1 n2 ...
     2つ以上の整数N1, N2 ...の、それぞれ論理和、論理積、
     排他的論理積を返します。

 -- Function: lognot n
     整数Nのビット否定を返します。

 -- Function: logtest n1 n2 ...
     == `(not (zero? (logand N1 N2 ...)))'

 -- Function: logbit? index n
     整数NのINDEX目のビットが1ならば`#t'を、0ならば`#f'を 返します。

 -- Function: bit-field n start end
     整数NのSTARTビット目(含む)からENDビット目(含まない)までを
     取り出した数値を返します。START < END でなければなりません。

 -- Function: copy-bit index n bit
     BITが真の値なら、整数NのINDEXビット目をセットした数値を 返します。
     BITが偽の値なら、整数NのINDEXビット目をリセットした数値を
     返します。

 -- Function: copy-bit-field n start end from

 -- Function: logcount n

 -- Function: integer-length n


File: gauche-refj.info,  Node: 論理値,  Next: ペアとリスト,  Prev: 数値,  Up: 組み込みライブラリ

6.3 論理値
==========

 -- Builtin Class: <boolean>
     論理値のクラスです。`#t'と`#f'のみがこのクラスのインスタンスです。

 -- Function: not obj
     [R5RS] OBJが`#f'の時のみ`#t'を返し、それ以外の場合は`#f'を
     返します。

 -- Function: boolean? obj
     [R5RS] OBJが論理値である場合に`#t'を返します。


File: gauche-refj.info,  Node: ペアとリスト,  Next: シンボル,  Prev: 論理値,  Up: 組み込みライブラリ

6.4 ペアとリスト
================

ペアとリストはSchemeにおける最も基本的なデータ構造のひとつです。
Gaucheのコアは全ての標準のリスト手続きと、多くのScheme実装に見られる
便利な手続きのいくつかを提供します。それらで足りない場合は
さらに多くの手続きが*Note List library::、 *Note
その他のリストライブラリ::、 *Note 組み合わせ::
といったモジュールで提供されています。
また、リストに限らないジェネリックなシーケンス/コレクションの操作が
*Note コレクションフレームワーク::と *Note
シーケンスフレームワーク::で提供されています。

* Menu:

* pairクラスとnullクラス::
* リストに関する述語::
* リストの作成::
* リストへのアクセスと変更::
* 他のリスト手続き::


File: gauche-refj.info,  Node: pairクラスとnullクラス,  Next: リストに関する述語,  Prev: ペアとリスト,  Up: ペアとリスト

6.4.1 pairクラスとnullクラス
----------------------------

 -- Builtin Class: <list>
     リストを表す抽象クラスで、クラス`<null>'とクラス`<pair>'の親クラスです。
     クラス`<sequence>'を継承します。

     循環リストやドットリストも`<list>'クラスのインスタンスですが、
     `list?'は偽の値を返すことに注意して下さい。
          (use srfi-1)
          (list? (circular-list 1 2)) => #f
          (is-a? (circular-list 1 2) <list>) => #t

 -- Builtin Class: <null>
     空リストのクラスです。`()'がこのクラスの唯一のインスタンスです。

 -- Builtin Class: <pair>
     ペアのクラスです。


File: gauche-refj.info,  Node: リストに関する述語,  Next: リストの作成,  Prev: pairクラスとnullクラス,  Up: ペアとリスト

6.4.2 リストの述語
------------------

 -- Function: pair? obj
     [R5RS] OBJがペアなら`#t'を、そうでなければ`#f'を返します。

 -- Function: null? obj
     [R5RS] OBJが空リストなら`#t'を、そうでなければ`#f'を返します。

 -- Function: list? obj
     [R5RS] OBJが正しいリストなら`#t'を、そうでなければ`#f'を返します。
     この手続きはOBJがドットリストや循環リストなら#Fを返します。

     SRFI-1(*Note SRFI-1 リストの述語::)には更に、
     `proper-list?'、`circular-list?'、`dotted-list?'
     といった手続きが定義されています。


File: gauche-refj.info,  Node: リストの作成,  Next: リストへのアクセスと変更,  Prev: リストに関する述語,  Up: ペアとリスト

6.4.3 リストの構築子
--------------------

 -- Function: cons obj1 obj2
     [R5RS] OBJ1とOBJ2のペアを作成します。
          (cons 'a 'b) => (a . b)

 -- Function: acons obj1 obj2 obj3
     `(cons (cons OBJ1 OBJ2) OBJ3)' を返します。
     連想リストの先頭に新しいエントリを加えるのに便利です。
          (acons 'a 'b '((c . d))) => ((a . b) (c . d))

 -- Function: make-list len &optional fill
     [SRFI-1]
     長さLENの正規のリストを返します。引数FILLが与えられていれば、各要素は
     FILLになります。そうでなければ各要素の値は不定です。
          (make-list 5 #t) => (#t #t #t #t #t)

 -- Function: list obj ...
     [R5RS] 要素がOBJ ...であるリストを作成します。
          (list 1 2 3) => (1 2 3)
          (list) => ()

 -- Function: list* obj1 obj2 ...
     `list'とほぼ同じですが、最後の引数が作成されるリストの最後のペアのcdrになります。
     SRFI-1ではこの手続きが`cons*'という名で定義されています。
          (list* 1 2 3) => (1 2 . 3)
          (list* 1) => 1

 -- Function: list-copy list
     [SRFI-1] LISTの浅いコピーを行います。
     LISTが循環リストの場合、この手続きは停止しません。


File: gauche-refj.info,  Node: リストへのアクセスと変更,  Next: 他のリスト手続き,  Prev: リストの作成,  Up: ペアとリスト

6.4.4 リストへのアクセスと変更
------------------------------

 -- Function: car pair
 -- Function: cdr pair
     [R5RS] それぞれPAIRのcarとcdrを返します。

 -- Function: set-car! pair obj
 -- Function: set-cdr! pair obj
     [R5RS] PAIRのcarもしくはcdrをOBJで置き換えます。

     注： `(setter car)' == `set-car!' であり、 `(setter cdr)' ==
     `set-cdr!' です。

 -- Function: caar pair
 -- Function: cadr pair
     ...

 -- Function: cdddar pair
 -- Function: cddddr pair
     [R5RS] `caar' == `(car (car x))', `cadr' == `(car (cdr x))', 等々。

     対応するsetterも定義されています。
          (let ((x (list 1 2 3 4 5)))
            (set! (caddr x) -1)
            x)
            => (1 2 -1 4 5)

 -- Function: length list
     [R5RS] 正規のリストLISTの長さを返します。
     LISTがドットリストならばエラーが起きます。
     LISTが循環リストの場合、この関数は無限ループします。

     循環リストも取り扱う場合は、SRFI-1の`length+'を使って下さい (*Note
     種々のリスト処理ルーチン::参照)。

 -- Function: list-tail list k
     [R5RS] LISTのK番目のcdrを返します。LISTは
     正規のリストでもドットリストでも循環リストでも構いません。

 -- Function: list-ref list k &optional fallback
     [R5RS+] LISTのK番目の要素を返します。LISTは
     正規のリストでもドットリストでも循環リストでも構いません。

     もしKがリストの長さを超えていたり、負数であった場合は通常はエラーが起こります。
     しかし、オプショナルな引数FALLBACKが与えられていた場合は、エラーは起きず
     FALLBACKが返されます。これはGaucheの拡張です。

 -- Function: last-pair list
     [SRFI-1] LISTの最後のペアを返します。LISTは
     正規のリストかドットリストです。


File: gauche-refj.info,  Node: 他のリスト手続き,  Prev: リストへのアクセスと変更,  Up: ペアとリスト

6.4.5 他のリスト手続き
----------------------

 -- Function: append list ...
     [R5RS]
     渡されたリストの要素を繋げたリストを返します。最後の引数の部分以外は新しいセルがアロケート
     されて使われます。最後の引数は正規のリストである必要がありません。その場合、結果は正規でない
     リストとなります。

 -- Function: append! list ...
     [SRFI-1]
     渡されたリストの要素を繋げたリストを返します。最後の引数以外のリストのセルは、結果を
     作成するために再利用されるかもしれません。
     最後の引数は正規のリストである必要はありません。

 -- Function: reverse list
     [R5RS] LISTの各要素を逆順に持つリストを新しく作成して返します。

 -- Function: reverse! list
     [SRFI-1]
     LISTの各要素を逆順に持つリストを返します。結果を作成するために、
     LISTのセルは再利用されるかもしれません。

 -- Function: memq obj list
 -- Function: memv obj list
 -- Function: member obj list
     [R5RS] LISTからOBJを探します。もしLISTのN番目の要素が
     OBJと同一ならば、`(list-tail LIST N)'を返します。
     `memq'は同一性の判定に`eq?'を、`memv'は`eqv?'を、
     `member'は`equal?'を使います。
     OBJがLIST中に見つからなければ`#f'が返されます。

     SRFI-1 (*Note List library::) を使うと、`member'は
     オプショナルな同一性判定手続きを取るように拡張されます。
          (memq 'a '(a b c))          => (a b c)
          (memq 'b '(a b c))          =>  (b c)
          (memq 'a '(b c d))          => #f
          (memq (list 'a) '(b (a) c)) => #f
          (memv 101 '(100 101 102))   => (101 102)

 -- Function: assq obj list
 -- Function: assv obj list
 -- Function: assoc obj list
     [R5RS] LISTの各要素はペアでなければなりません。
     これらの手続きは、LISTの要素であるペアのうち、そのcarが
     OBJと一致するペアを左から探して行きます。もし見付かればそのペアが、
     見付からなければ`#f'が返されます。
     `assq'は比較関数に`eq?'を、`assv'はEQV?を、
     `assoc'はEQUAL?をそれぞれ用います。

     SRFI-1 (*Note List library::) を使うと、`assoc'は
     オプショナルな同一性判定手続きを取るように拡張されます。


File: gauche-refj.info,  Node: シンボル,  Next: キーワード,  Prev: ペアとリスト,  Up: 組み込みライブラリ

6.5 シンボル
============

 -- Builtin Class: <symbol>
     シンボルを表すクラスです。

     Gaucheでは、全てのシンボルはintern、すなわち内部のテーブルに登録されています。
     そのため、同じ外部表記を持つシンボルは常に`eq?'です。

 -- Reader Syntax: `|name|'
     R5RSのシンボルの定義では許されていない文字を使った妙な名前のシンボルを表記するのに
     使う構文です。インタプリタが大文字小文字を区別しないモードで走っている場合は、
     大文字を含むシンボルを表記するときにも使えます (*Note
     大文字小文字の区別::参照)。

     この表記はCommonLispから取られました。いくつかのSchemeでも同様の表記を採用しています。

 -- Function: symbol? obj
     [R5RS] OBJがシンボルなら`#t'を返します。
          (symbol? 'abc)     => #t
          (symbol? 0)        => #f
          (symbol? 'i)       => #t
          (symbol? '-i)      => #f
          (symbol? '|-i|)    => #t

 -- Function: symbol->string symbol
     [R5RS]
     SYMBOLの名前を文字列で返します。返される文字列は変更不可です。

          (symbol->string 'foo) => foo

 -- Function: string->symbol string
     [R5RS] 文字列STRINGを名前に持つシンボルを返します。

          (string->symbol "a") => a
          (string->symbol "A") => A
          (string->symbol "weird symbol name") => |weird symbol name|

 -- Function: gensym &optional prefix


File: gauche-refj.info,  Node: キーワード,  Next: Identifier,  Prev: シンボル,  Up: 組み込みライブラリ

6.6 キーワード
==============

 -- Builtin Class: <keyword>
     キーワードは特別なシンボルの一種で、自動的にクォートされます。
     名前で渡す引数(キーワード引数)や、キーワード-値のリストで広く使われて
     います。 CommonLisp
     とは異なり、キーワードとシンボルは明確に区別される型です。

     キーワード引数の処理については、`let-keywords*' マクロ (*Note
     省略可能引数のパージング::) を参照して下さい。

 -- Reader syntax: `:NAME'
     名前が NAME であるキーワードとして読み込まれます。 (先行する ':'
     は、キーワードの名前の一部ではないことに注意してください。)

 -- Function: keyword? obj
     OBJ がキーワードであれば、`#t' を返します。

 -- Function: make-keyword name
     名前が NAME であるキーワードを返します。

 -- Function: keyword->string keyword
     キーワード KEYWORD の名前を返します。

 -- Function: get-keyword key kv-list &optional fallback
     キー-値のリストから値を取り出すのに便利な手続きです。
     キー-値のリスト KV-LIST は偶数個の要素を持たなければなりません。
     1つ目、3つ目、5つ目、... の要素はキーとして扱われ、
     2つ目、4つ目、6つ目、... の要素は、その前の要素をキーとした値と
     なります。

     この手続きは、キーの集合から KEY を探して、それが見つかれば、
     対応する値を返します。
     2つ以上のキーにマッチしたら、最左のものとなります。
     マッチするキーがない場合、FALLBACK が与えられていればそれを
     返し、さもなければエラーを通知します。

     KV-LIST が正しい偶数個の要素を持つリストでない場合は、エラーに
     なります。

     キーワード-値リストの `キーワード' と、KEY 引数は、実際には
     キーワードである必要はありません。いかなる Scheme オブジェクトで
     あっても良いです。キーの比較は、`eq?' によって行われます。

     この手続きは、STk から導入されました。

          (get-keyword :y '(:x 1 :y 2 :z 3))
            => 2
          (get-keyword 'z '(x 1 y 2 z 3))
            => 3

          (get-keyword :t '(:x 1 :y 2 :z 3))
            => #<error>
          (get-keyword :t '(:x 1 :y 2 :z 3) #f)
            => #f

 -- Macro: get-keyword* key kv-list &optional fallback
     `get-keyword' と同様ですが、KV-LIST が KEY を 含まない場合にのみ
     FALLBACK が評価されることだけが違います。

 -- Function: delete-keyword key kv-list
 -- Function: delete-keyword! key kv-list
     KV-LIST から KEY に `eq?' であるキーをもつキーと値を 削除します。

     `delete-keyword' は KV-LIST を変更しません。しかし、
     返されたリストは共通の末尾部分を共有します。

     `delete-keyword!' は新しくアロケートされることはありません。
     そして、破壊的に KV-LIST を変更する_可能性があります_。
     最初のキーがマッチした場合元のリストは変更されないこともありえますが、
     返り値のリストを使わなければいけません。

     KEY にマッチするキーがない場合 KV-LIST が返ります。

          (delete-keyword :y '(:x 1 :y 2 :z 3 :y 4))
           => (:x 1 :z 3)



File: gauche-refj.info,  Node: Identifier,  Next: 文字,  Prev: キーワード,  Up: 組み込みライブラリ

6.7 Identifier
==============

 -- Builtin Class: <identifier>

 -- Function: identifier? obj

 -- Function: identifier->symbol identiifer


File: gauche-refj.info,  Node: 文字,  Next: 文字集合,  Prev: Identifier,  Up: 組み込みライブラリ

6.8 文字
========

 -- Builtin Class: <char>

 -- Reader Syntax: `#\charname'
     [R5RS] リテラルの文字オブジェクトを表現します。

     リーダーは`#\'に出会うと、まず次の文字を読み込みます。それが文字
     `()[]{}" \|;#' のいずれかならば、その文字自身となります。
     そうでなければ、単語を構成しない文字に出会うまで文字が続けて読み込まれます。
     もし一文字しか読まれなければ、その文字自身となります。そうでなければ
     その単語が文字の名前として解釈されます。
     それが有効な文字の名前でなければエラーとなります。

     以下の文字の名前が認識されます。これらの文字の名前は大文字小文字を区別しません。
    `space'
          スペース (ASCII #x20)

    `newline, nl, lf'
          改行文字 (ASCII #x0a)

    `return, cr'
          復帰文字 (ASCII #x0d)

    `tab, ht'
          水平タブ (ASCII #x09)

    `page'
          フォームフィード、改ページ (ASCII #x0c)

    `escape, esc'
          エスケープ (ASCII #x1b)

    `delete, del'
          デリート (ASCII #x7f)

    `null'
          NUL文字 (ASCII #x00)

    `xN'
          N が16進表記の整数であるとき、内部エンコーディングが整数N
          であるような文字。この表記はASCII文字の範囲の外では、内部エンコーディングが異なる
          処理系間で互換性が無いことに注意して下さい。

    `uN'
          Nが4桁または8桁の16進数整数であるとき、UCSコードNであるような文字。
          Gaucheの内部エンコーディングがUTF-8以外でコンパイルされている場合には、
          リーダーは`gauche.charconv'モジュールを使ってUnicodeを内部エンコーディングへと
          変換します。Unicodeの該当する文字が内部エンコーディングで定義されていない場合、
          代替文字に置換されるか、エラーとなります。

          #\newline => #\newline ; 改行文字
          #\x0a     => #\newline ; 改行文字
          #\x41     => #\A       ; ASCII文字 'A'
          #\u0041   => #\A       ; ASCII文字 'A', UCSコード
          #\u3042   => #\あ      ; 平仮名「あ」, UCSコード
          #\u0002a6b2 => ; JISX0213 2-94-86 UCS4コード

     プログラムテキストがGaucheの内部エンコーディングと同じエンコーディングで
     書かれていれば、マルチバイト文字を直接表記することもできます。
          #\あ => ; 文字「あ」

 -- Function: char? obj
     [R5RS] OBJが文字なら`#t'を、そうでなければ`#f'を返します。

 -- Function: char`='? char1 char2
 -- Function: char`<'? char1 char2
 -- Function: char`<='? char1 char2
 -- Function: char`>'? char1 char2
 -- Function: char`>='? char1 char2
     [R5RS]
     文字を比較します。比較は内部の文字エンコーディングで行われます。

 -- Function: char-ci`='? char1 char2
 -- Function: char-ci`<'? char1 char2
 -- Function: char-ci`<='? char1 char2
 -- Function: char-ci`>'? char1 char2
 -- Function: char-ci`>='? char1 char2
     [R5RS] 文字を、大文字小文字を区別せずに比較します。
     現在のバージョンではASCII文字の範囲外における大文字小文字の扱いが
     きちんと定義されていないことに注意して下さい。

 -- Function: char-alphabetic? char
 -- Function: char-numeric? char
 -- Function: char-whitespace? char
 -- Function: char-upper-case? char
 -- Function: char-lower-case? char
     [R5RS] 文字CHARがそれぞれ英字(`[A-Za-z]')、数字(`[0-9]')、
     空白文字、大文字および小文字の時に真の値を返します。
     今のところ、これらの手続きはASCII文字のみで動作します。
     それ以外の文字に対しては`#f'が返されます。

 -- Function: char->integer char
 -- Function: integer->char n
     [R5RS] `char->integer'は文字CHARの内部エンコーディングに対応する
     整数値を返します。`integer->char'は数値Nと内部エンコーディングが
     同じ文字を返します。有効な文字CHARに対して以下の式は常に真となります。
          (eq? char (integer->char (char->integer char)))

     対応する内部エンコーディングを持つ文字が無い数値を`integer->char'に渡した
     場合の結果は不定です。

 -- Function: char->ucs char
 -- Function: ucs->char n
     それぞれ、文字CHARをUCSコードポイントを表す整数へ変換し、
     またUCSコードポイントを表す整数Nを文字へと変換する手続きです。

     Gaucheの内部文字エンコーディングがUTF-8でコンパイルされている場合は、
     これらの手続きはそれぞれ`char->integer'および`integer->char'
     と等価です。

     Gaucheの内部文字エンコーディングがUTF-8でない場合、
     これらの手続きは`gauche.charconv'モジュールを使って
     内部文字コードとUCSとの変換を行います (*Note
     文字コード変換::参照)。
     CHARが対応するUCSコードを持っていない場合、`char->ucs'は`#f'を
     返します。UCSコード`n'に対応する文字が内部エンコーディングで定義されていない
     場合、変換ルーチンが代替文字を提供していればそれを、そうでなければ`#f'
     が返されます。

 -- Function: char-upcase char
 -- Function: char-downcase char
     [R5RS]
     CHARの大文字と小文字をそれぞれ返します。CHARに大文字小文字の区別が
     無ければCHARがそのまま返されます。

     現在のバージョンではASCII文字の範囲外における大文字小文字の扱いが
     きちんと定義されていないことに注意して下さい。

 -- Function: digit->integer char &optional (radix 10)
     文字CHARが RADIX進数の数字を構成するのに有効な文字であれば、
     対応する整数が、そうでなければ`#f'が返されます。
          (digit->integer #\4) => 4
          (digit->integer #\e 16) => 14
          (digit->integer #\9 8) => #f
     Common
     Lispには同様の手続きが`digit-char-p'というやや曖昧な名で定義されています。

 -- Function: integer->digit integer &optional (radix 10)
     `digit->integer'の逆です。整数INTEGERを RADIX進数 ひと桁で
     表現するのに使われる文字を返します。INTEGERがひと桁で表現できない数値の場合は
     `#f'が返されます。
          (integer->digit 13 16) => #\d
          (integer->digit 10) => #f
     Common Lispの`digit-char'に当たります。

 -- Function: gauche-character-encoding
     コンパイル時に選択された内部文字エンコーディングを表すシンボルを返します。
     返される値は以下のいずれかです。
    `euc-jp'
          EUC-JP

    `utf-8'
          UTF-8

    `sjis'
          Shift JIS

    `none'
          マルチバイトキャラクタをサポートしない(8ビット固定長文字)。

 -- Function: supported-character-encodings
     ネイティブなマルチバイトエンコーディングスキームでサポートされている
     文字エンコーディングスキームの名前を表す文字列のリストを返します。


File: gauche-refj.info,  Node: 文字集合,  Next: 文字列,  Prev: 文字,  Up: 組み込みライブラリ

6.9 文字集合
============

 -- Builtin Class: <char-set>
     文字の集合を取り扱う、文字集合(キャラクタセット)のクラスです。
     Gaucheは文字集合オブジェクトのサポートと、
     ある文字がその集合に属するかどうかを調べる手続きを言語組み込みで持っています。

     文字集合に関する他の操作、例えば集合演算などは、SRFI-14モジュール
     (*Note 文字集合ライブラリ::参照) で提供されています。

 -- Reader Syntax: `#[char-set-spec]'
     この構文で、リテラル文字集合を記述することができます。
     char-set-specには集合に含める文字を列挙します。
     次の特殊なシーケンスを含めることができます。
    `X-Y'
          文字Xと文字`y'の間の文字全て。XとYも含みます。
          XはYよりも内部文字コードで比較して小さくなければなりません。

    `^'
          カレットがchar-set-specの最初に来た場合、以降に示される文字集合の
          補集合がこの文字集合となります。

    `\xNN'
          内部文字コードNN(16進数表記)の文字。

    `\uNNNN'
          UnicodeのUCS-2でNNNN(16進数表記4桁)の文字。

    `\UNNNNNNNN'
          UnicodeのUCS-4でNNNNNNNN(16進数表記8桁)の文字。

    `\s'
          空白文字。

    `\S'
          空白でない文字。(`\s'の補集合)

    `\d'
          10進数の数字

    `\D'
          `\d'の補集合

    `\w'
          単語を構成する文字の集合(アルファベット、数字、アンダースコア)

    `\W'
          `\W'の補集合

    `\\'
          バックスラッシュ文字

    `\-'
          マイナス文字

    `\^'
          カレット文字

    `[:alnum:] ...'
          POSIX流文字集合表記。以下の文字集合名が認識されます: `alnum',
          `alpha', `blank', `cntrl', `digit', `graph', `lower',
          `print', `punct', `space', `upper', `xdigit'。

          #[aeiou]     ; 母音文字'a', 'e', 'i', 'o', 'u'の集合
          #[a-zA-Z]    ; アルファベット
          #[[:alpha:]] ; アルファベット (POSIX表記)
          #[\x0d\x0a]  ; 改行とリターン
          #[\\\-]      ; バックスラッシュとマイナス文字
          #[]          ; 空の文字集合
          #[ぁ-ん]     ; 平仮名の集合

 -- Function: char-set? obj
     [SRFI-14] OBJが文字集合であれば真の値を返します。

 -- Function: char-set-contains? char-set char
     [SRFI-14]
     文字集合CHAR-SETが文字CHARを含んでいれば真の値を返します。
          (char-set-contains? #[a-z] #\y) => #t
          (char-set-contains? #[a-z] #\3) => #f

          (char-set-contains? #[^ABC] #\A) => #f
          (char-set-contains? #[^ABC] #\D) => #t

          (char-set-contains? #[あ-お] #\う) => #t
          (char-set-contains? #[あ-お] #\ぷ) => #f

 -- Function: char-set char ...
     [SRFI-14] 文字CHAR ... からなる文字集合を作成して返します。
          (char-set #\a #\b #\c)   => #[a-c]
          (char-set #\あ #\い #\う) => #[あいう]

 -- Function: char-set-copy char-set
     [SRFI-14] CHAR-SETのコピーを作って返します。


File: gauche-refj.info,  Node: 文字列,  Next: 正規表現,  Prev: 文字集合,  Up: 組み込みライブラリ

6.10 文字列
===========

 -- Builtin Class: <string>
     文字列のクラスです。Gaucheでは、文字列は文字のシーケンスともバイトのシーケンスとも
     みなすことができます。

   R5RSに定義されている文字列操作は非常に限られています。
Gaucheでは追加の組込み手続きのほか、
SRFI-13に定義されている豊富な文字列ライブラリを備えています。
SRFI-13については*Note 文字列ライブラリ::を参照してください。

* Menu:

* 文字列の表記::
* 文字列に関する述語::
* 文字列の作成::
* 文字列の補間::
* 文字列のアクセスと変更::
* 文字列の比較::
* 文字列を扱うその他の手続き::
* 文字列ポインタ::
* 不完全文字列::


File: gauche-refj.info,  Node: 文字列の表記,  Next: 文字列に関する述語,  Prev: 文字列,  Up: 文字列

6.10.1 文字列の表記
-------------------

 -- Reader syntax: `"'...`"'
     [R5RS+] リテラル文字列です。ダブルクオートの中では、
     以下のエスケープシーケンスが認識されます。

    `\"'
          [R5RS] ダブルクオート文字

    `\\'
          [R5RS] バックスラッシュ文字

    `\n'
          改行文字 (ASCII 0x0a)

    `\r'
          復帰文字 (ASCII 0x0d)

    `\f'
          フォームフィード (ASCII 0x0c)

    `\t'
          タブ文字 (ASCII 0x09)

    `\0'
          NUL文字 (ASCII 0x00)

    `\xNN'
          2桁の16進数NNで指定されるバイト。
          このバイトは内部エンコーディングによって解釈されます。

    `\uNNNN'
          4桁の16進数NNNNによって示されるUCS2コードを持つ文字。

    `\UNNNNNNNN'
          8桁の16進数NNNNNNNNによって示されるUCS4コードを持つ文字。

     GaucheがUTF-8以外の内部エンコーディングでコンパイルされていた場合、
     リーダーは`gauche.charconv'モジュールを使って
     エスケープシーケンス`\uNNNN'と`\UNNNNNNNN'の解釈を行います。

 -- Reader syntax: `#*"'...`"'
     不完全な文字列のリテラル表記です。完全な文字列と同様のエスケープシーケンスが
     使えます。

     註：以前は、不完全な文字列のリテラル表記には`#"..."'という構文が使われていました。
     Gauche 0.6.3から構文は`#*"..."'に変更されました。
     将来は、文字列の補間機能が`#"..."'構文を使うようになります。

     '`#*'' という構文はCommon
     Lispでビットベクタの表記に使われています。
     不完全な文字列は実際はバイトベクタであることから、類似点を認めてこの構文を
     採用しました。(もし将来必要になってビットベクタが実装されたとしても、
     この構文と共存できます)。


File: gauche-refj.info,  Node: 文字列に関する述語,  Next: 文字列の作成,  Prev: 文字列の表記,  Up: 文字列

6.10.2 文字列に関する述語
-------------------------

 -- Function: string? obj
     [R5RS] OBJが文字列なら`#t'を、そうでなければ`#f'を返します。

 -- Function: string-immutable? obj
     OBJが変更不可な文字列なら`#t'を、そうでなければ`#f'を返します。

 -- Function: string-incomplete? obj
     OBJが不完全文字列なら`#t'を、そうでなければ`#f'を返します。


File: gauche-refj.info,  Node: 文字列の作成,  Next: 文字列の補間,  Prev: 文字列に関する述語,  Up: 文字列

6.10.3 文字列の構築子
---------------------

 -- Function: make-string k &optional char
     [R5RS] 長さKの文字列を作成して返します。
     CHARが与えられればそれで内容を満たします。CHARが与えられなければ
     空白文字で満たされます。常に完全な文字列が返されます。

          (make-string 5 #\x) => "xxxxx"
          (make-string 5 #\ふ) => "ふふふふふ"

     `make-string'で必要な長さの文字列をアロケートして、`string-set!'
     で順番に埋めて行くアルゴリズムは、Gaucheでは_極めて_非効率であることに
     注意してください。そのようなアルゴリズムは、文字列の内部表現とアロケーションメカニズムに
     関して不必要な仮定を置いており、Gaucheはその仮定とは合致しません。
     文字列の順次作成に適しているのは文字列ポートです (*Note
     文字列ポート::参照)。それが使えない場合、
     文字のリストを作成し、`list->string'で変換する方がまだ`make-string'と
     `string-set!'を使うより良いでしょう。

 -- Function: make-byte-string k &optional byte
     大きさKの不完全な文字列を作成して返します。
     BYTEが与えられた場合は、その下位1バイトで文字列の各バイトを初期化します。
     BYTEは正確な整数でなければなりません。

 -- Function: string char ...
     [R5RS] 文字CHAR ... から構成された文字列を返します。

 -- Generic Function: x->string obj
     文字列への強制型変換手続きです。 OBJの文字列表現を返します。
     デフォルトのメソッドでは、文字列はそのまま返され、数値は`number->string'で、
     シンボルは`symbol->string'で変換され、その他のオブジェクトは`display'表現
     が使われます。

     他のクラスはこのメソッドを定義することにより、独自の変換関数を提供することができます。


File: gauche-refj.info,  Node: 文字列の補間,  Next: 文字列のアクセスと変更,  Prev: 文字列の作成,  Up: 文字列

6.10.4 文字列の補間
-------------------

「文字列の補間(string interpolation)」という用語は、
PerlやPythonなど様々なスクリプト言語で、文字列リテラル内に式を埋め込んでおき
実行時に式を評価した値をそのリテラル内に埋め込む機能を指します。

Schemeはそのような機能を定義していませんが、Gaucheではリーダーマクロを使って
文字列の補間を実装しました。

 -- Reader syntax: `#`'STRING-LITERAL
     文字列に評価されます。STRING-LITERAL内に、`,EXPR'
     というシーケンス(ここでEXPRは有効なScheme式の外部表現)が
     現われたら、EXPRが評価されてその結果がもとの位置に埋め込まれます。
     結果の文字列化には`x->string'が使われます(*Note
     文字列の作成::参照)。

     コンマと続く式とは、空白文字等を入れずに隣接していなければなりません。
     そうでない場合は置換されません。

     二つの連続するコンマは一つのリテラルのコンマ文字に置き換えられます。
     これによって、コンマと非空白文字の連続をSTRING-LITERALに入れることができます。

     それ以外のSTRING-LITERAL内の文字シーケンスはそのままコピーされます。

     EXPRに単独の変数を使う場合で、それに続く文字列と変数名を区切りたい
     場合は、`|'文字を使ったシンボルエスケープ構文が使えます。下の例の最後の
     2つを見て下さい。

          #`"This is Gauche, version ,(gauche-version)."
           => "This is Gauche, version 0.8.5."

          #`"Date: ,(sys-strftime \"%Y/%m/%d\" (sys-localtime (sys-time)))"
           => "Date: 2002/02/18"

          (let ((a "AAA")
                (b "BBB"))
           #`"xxx ,a ,b zzz")
           => "xxx AAA BBB zzz"

          #`"123,,456,,789"
           => "123,456,789"

          (let ((n 5)) #`"R,|n|RS")
           => "R5RS"

          (let ((x "bar")) #`"foo,|x|.")
           => "foobar"

     実は、リーダーはこの構文をマクロ呼び出しへと変換し、それが最終的には
     `string-append'への呼び出しへと変換されます。
          #`"This is Gauche, version ,(gauche-version)."
           ==
          (string-append "This is Gauche, version "
                         (x->string (gauche-version))
                         ".")

   _この構文を採用した理由:_ 他のスクリプト言語では、``$expr'' や
'`#{...}'' が良く使われています。 準クオート (*Note 準クオート::参照)
との類似性からこの構文を採用しました。
変数名の区切りを明確にするのに`|'を使う必要があるのは少々奇妙ですが、
慣れたSchemeプログラマならコンマ構文を読むのは他の言語から借りた構文よりも
楽だと思います。

Schemeは他のスクリプト言語より一般的により多くの文字を変数名に使うことが出来ることに注意して下さい。
結果として、変数の値を文字列に挿入する際、ほとんどの場合において変数名を`|'で区切る
必要があるでしょう。例えば、Perlでは `"$year/$month/$day
$hour:$minutes:$seconds"' と書けたものが、Gaucheでは
`#`",|year|/,|month|/,day ,|hour|:,|minutes|:,seconds"'
と書かねばなりません。
混乱を避けるためには、この構文内では常に直接の変数参照は`|'で区切るようにしておくのが良いかもしれません。


File: gauche-refj.info,  Node: 文字列のアクセスと変更,  Next: 文字列の比較,  Prev: 文字列の補間,  Up: 文字列

6.10.5 文字列のアクセスと変更
-----------------------------

 -- Function: string-length string
     [R5RS] 文字列STRINGの長さ(文字数)を返します。
     STRINGは不完全な文字列であっても構いません。

 -- Function: string-size string
     文字列STRINGの大きさを返します。文字列の大きさは、
     STRINGが占めるメモリ上のバイト数で、これは文字列の内部エンコーディングに
     依存します。同じ文字列であっても内部エンコーディングが違えば違う大きさになる場合も
     あります。

     不完全な文字列では、文字列の長さと大きさは常に一致します。

 -- Function: string-ref cstring k &optional fallback
     [R5RS+] 完全な文字列CSTRINGのK番目の文字を返します。
     不完全な文字列を渡すのはエラーです。

     Kが負数であったりCSTRINGの長さと同じかそれ以上であった場合には
     エラーが報告されます。但し、引数FALLBACKが与えられている場合にはエラーを
     報告せずFALLBACKが返されます。これはGaucheの拡張です。

 -- Function: string-byte-ref string k
     (多分、不完全な)文字列STRINGのK番目のバイトを返します。
     戻り値は、0から255の範囲の整数です。Kは0以上、 `(string-size
     STRING)'より小でなければなりません。

 -- Function: string-set! string k char
     [R5RS] STRINGのK番目の文字をCHARで置き換えます。
     Kは0以上、`(string-length STRING)'より小でなければ
     なりません。戻り値は未定義です。

     STRINGが不完全文字列の場合、CHARの下位8ビットの整数値は、
     STRINGのK番目のバイトをセットするために使われます。

     パフォーマンス上の考慮点について、`make-string'の説明を参照して下さい。

 -- Function: string-byte-set! string k byte
     STRINGのK番目のバイトを整数BYTEで置き換えます。
     BYTEは0から255の範囲(255を含む)でなければなりません。
     Kは0以上、`(string-size STRING)'より小である必要があります。
     STRINGが完全文字列の場合、この操作により不完全文字列になります。
     戻り値は未定義です。


File: gauche-refj.info,  Node: 文字列の比較,  Next: 文字列を扱うその他の手続き,  Prev: 文字列のアクセスと変更,  Up: 文字列

6.10.6 文字列の比較
-------------------

 -- Function: string=? string1 string2
 -- Function: string-ci`='? string1 string2
     [R5RS]

 -- Function: string`<'? string1 string2
 -- Function: string`<='? string1 string2
 -- Function: string`>'? string1 string2
 -- Function: string`>='? string1 string2
 -- Function: string-ci`<'? string1 string2
 -- Function: string-ci`<='? string1 string2
 -- Function: string-ci`>'? string1 string2
 -- Function: string-ci`>='? string1 string2
     [R5RS]


File: gauche-refj.info,  Node: 文字列を扱うその他の手続き,  Next: 文字列ポインタ,  Prev: 文字列の比較,  Up: 文字列

6.10.7 文字列を扱うその他の手続き
---------------------------------

 -- Function: substring string start end
     [R5RS]

 -- Function: string-append string ...
     [R5RS]

 -- Function: string->list string &optional start end
 -- Function: list->string list
     [R5RS+][SRFI-13]

 -- Function: string-copy string &optional start end
     [R5RS+][SRFI-13]

 -- Function: string-fill! string char &optional start end
     [R5RS+][SRFI-13] STRING を CHAR で埋めます。 オプションの START と
     END は、影響を受ける領域を 制限します。
          (string-fill! "orange" #\X)
            => "XXXXXX"
          (string-fill! "orange" #\X 2 4)
            => "orXXge"

 -- Function: string-join strs &optional delim grammer
     [SRFI-13] リスト STRS 中にある文字列を、文字列 DELIM を'糊'
     として連結します。

     引数 GRAMMER は、文字列がどのように連結されるかを指定する
     シンボルで、以下のうちの一つです。
    `infix'
          それぞれの文字列の間に DELIM を使います。このモードが
          デフォルトです。STRS が空文字列かヌル文字列を含むリスト
          である場合は、曖昧に(適当に)動作します。
               (string-join '("apple" "mango" "banana") ", ")
                 => "apple, mango, banana"
               (string-join '() ":")
                 => ""
               (string-join '("") ":")
                 => ""

    `strict-infix'
          `infix' のように動作しますが、STRS には空リストは
          許されません。したがって、曖昧さはありません。

    `prefix'
          DELIM をそれぞれの文字列の前に補います。
               (string-join '("usr" "local" "bin") "/" 'prefix)
                 => "/usr/local/bin"
               (string-join '() "/" 'prefix)
                 => ""
               (string-join '("") "/" 'prefix)
                 => "/"

    `suffix'
          DELIM をそれぞれの文字列の後ろに補います。
               (string-join '("a" "b" "c") "&" 'suffix)
                 => "a&b&c&"
               (string-join '() "&" 'suffix)
                 => ""
               (string-join '("") "&" 'suffix)
                 => "&"


 -- Function: string-scan string item &optional return
     STRING にある ITEM (文字列あるいは文字)を探します。 引数 RETURN
     は、STRING 中に ITEM が見つかった
     場合にどの値が返されるかを指定します。それは以下のシンボルのうちの
     一つでなければなりません。

    `index'
          ITEM が見つかった場合はSTRING 内でのインデックス、
          そうでなければ `#f'
          を返します。これがデフォルトの振る舞いです。
               (string-scan "abracadabra" "ada") => 5
               (string-scan "abracadabra" #\c) => 4
               (string-scan "abracadabra" "aba") => #f

    `before'
          ITEM よりも前にある STRING の部分文字列、あるいは ITEM
          が見つからなければ `#f' を返します。
               (string-scan "abracadabra" "ada" 'before) => "abrac"
               (string-scan "abracadabra" #\c 'before) => "abra"

    `after'
          ITEM より後ろにある STRING の部分文字列、あるいは ITEM
          が見つからなければ `#f' を返します。
               (string-scan "abracadabra" "ada" 'after) => "bra"
               (string-scan "abracadabra" #\c 'after) => "adabra"

    `before*'
          ITEM の前にある STRING の部分文字列と後ろにある STRING
          の部分文字列を返します。ITEM が見つからない場合は、 `(values
          #f #f)' を返します。
               (string-scan "abracadabra" "ada" 'before*)
                 => "abrac" and "adabra"
               (string-scan "abracadabra" #\c 'before*)
                 => "abra" and "cadabra"

    `after*'
          STRING のうち、ITEM の終端までの部分文字列とその残りを
          返します。ITEM が見つからなかった場合は、`(values #f #f)'
          を返します。
               (string-scan "abracadabra" "ada" 'after*)
                 => "abracada" and "bra"
               (string-scan "abracadabra" #\c 'after*)
                 => "abrac" and "adabra"

    `both'
          STRING のうち、ITEM の前と ITEM の後ろの
          部分文字列を返します。ITEM が見つからない場合、 `(values #f
          #f)' を返します。
               (string-scan "abracadabra" "ada" 'both)
                 => "abrac" and "bra"
               (string-scan "abracadabra" #\c 'both)
                 => "abra" and "adabra"

 -- Function: string-split string splitter
     STRING を SPLITTER で分割し、文字列のリストを返します。 SPLITTER
     には、文字、文字セット、文字列、正規表現、手続きが 使えます。

     SPLITTER が文字の場合、その文字がデリミタとして使われます。

     SPLITTER が文字セットの場合は、その文字セットに含まれる文字の
     連続がデリミタとして使われます。

     SPLITTER に手続きが与えられた場合、STRING にある各文字に
     対してその手続きが呼ばれ、SPLITTER が真の値を返すような連続した
     文字群がデリミタとして使われます。

          (string-split "/aa/bb//cc" #\/)    => ("" "aa" "bb" "" "cc")
          (string-split "/aa/bb//cc" "/")    => ("" "aa" "bb" "" "cc")
          (string-split "/aa/bb//cc" "//")   => ("/aa/bb" "cc")
          (string-split "/aa/bb//cc" #[/])   => ("" "aa" "bb" "cc")
          (string-split "/aa/bb//cc" #/\/+/) => ("" "aa" "bb" "cc")
          (string-split "/aa/bb//cc" #[\w])  => ("/" "/" "//" "")
          (string-split "/aa/bb//cc" char-alphabetic?) => ("/" "/" "//" "")

          ;; some boundary cases
          (string-split "abc" #\/) => ("abc")
          (string-split ""    #\/) => ("")

     `string-tokenize' (*Note 他の文字列操作::) も参照して下さい。


File: gauche-refj.info,  Node: 文字列ポインタ,  Next: 不完全文字列,  Prev: 文字列を扱うその他の手続き,  Up: 文字列

6.10.8 文字列ポインタ
---------------------

 -- Builtin Class: <string-pointer>
     文字列ポインタは、文字列をシーケンシャルに(前向き、または後向きに)
     効果的なアクセスをするためのオブジェクトです。

     このプリミティブに基づき、高レベルな文字列イテレータとアクセッサが
     構成されています。詳細は、*Note
     文字列ライブラリ::を参照して下さい。
     ポータビリティのため、これらの文字列ポインタオブジェクトの代わりに
     SRFI-13の関数を使うことを強く推奨します。

 -- Function: make-string-pointer str &optional (index 0)
     文字列STRのINDEX番目の文字を指す文字列ポインタを生成します。

 -- Function: string-pointer-copy sp
     文字列ポインタをコピーします。結果となる文字列ポインタはSPと同じ
     文字列を共有しますが、ポインタとしては区別されます。

 -- Function: string-pointer? obj
     OBJが文字列ポインタであれば`#t'を返します。

 -- Function: string-pointer-next! sp
 -- Function: string-pointer-prev! sp

 -- Function: string-pointer-set! sp index

 -- Function: string-pointer-substring sp &keyword (after #f)

 -- Function: string-pointer-index sp
 -- Function: string-pointer-byte-index sp


File: gauche-refj.info,  Node: 不完全文字列,  Prev: 文字列ポインタ,  Up: 文字列

6.10.9 不完全文字列
-------------------

 -- Function: string-complete->incomplete str

 -- Function: string-incomplete->complete str


File: gauche-refj.info,  Node: 正規表現,  Next: ベクター,  Prev: 文字列,  Up: 組み込みライブラリ

6.11 正規表現
=============

GaucheはPOSIXの拡張正規表現にほぼ上位互換な正規表現エンジンを
組込みで持っています。また、Perl 5の正規表現からいくつかの
拡張機能を採り入れています。

 -- Builtin Class: <regexp>
     正規表現オブジェクトのクラスです。`string->regexp'を使って実行時に
     作成できます。また、Gaucheはリテラルの正規表現を表す構文を持っており、
     ロード時に作成することもできます。

     Gaucheの正規表現エンジンはマルチバイト文字列に対応しています。

 -- Builtin Class: <regmatch>
     正規表現マッチオブジェクトのクラスです。正規表現エンジン`rxmatch'は、
     一致した場合にこのオブジェクトを返します。部分一致の情報を含めた
     全てのマッチに関する情報がこのオブジェクトに含まれています。

     一致した部分文字列やそのインデックスのリストではなく
     マッチオブジェクトを返すことの利点は効率です。
     regmatchオブジェクトはマッチの内部状態を保持しており、
     要求された時にはじめて該当する部分文字列やインデックスを計算します。
     これは特にマルチバイト文字列に有効です。マルチバイト文字列
     へのインデックスアクセスは遅いからです。

 -- Reader Syntax: `#/regexp-spec/'
 -- Reader Syntax: `#/regexp-spec/i'
     リテラルの正規表現オブジェクトを表記します。読まれた際に`<regexp>'の
     インスタンスとなります。

     末尾に文字`i'が与えられた場合は、マッチ時に大文字小文字を区別しない
     正規表現オブジェクトとなります。(現在のバージョンでは、大文字小文字の
     同一視はASCII文字のみに対して行われます。それ以外の文字は通常の方法でマッチします)。

     `string->regexp'に対してこの構文を使う利点は、
     正規表現のコンパイルが一度しか行われない点です。この構文は、
     内部ループの中でも、正規表現のコンパイルのオーバヘッドを気にせずに
     使うことができます。動的に正規表現を作成したい場合のみ`string->regexp'を
     使って下さい。

   Gaucheの組み込み正規表現構文はPOSIX拡張正規表現に準じたものに、
Perlの拡張の一部を採り入れたものです。

   ここに示す構文は表面的な構文にすぎないことに注意して下さい。
Gaucheの正規表現コンパイラは抽象構文木を扱うようになっており、
将来はSREのような別の構文もサポートされる予定です。

`re*'
     reの0回以上の繰り返しにマッチします。

`re+'
     reの1回以上の繰り返しにマッチします。

`re?'
     reの0回または1回の出現にマッチします。

`re{n}'
`re{n,}'
`re{n,m}'
     回数に範囲のある繰り返しです。
     `re{n}'はreのn回の繰り返しにマッチします。
     `re{n,}'はreのn回以上の繰り返しにマッチします。
     `re{n,m}'はreのn回以上、m回以下の 繰り返しにマッチします。但しN <=
     Mとします。

`re*?'
`re+?'
`re??'
`re{n,}?'
`re{n,m}?'
     上記の繰り返し構造とほぼ同じですが、これらの構文は「non-greedy」または
     「lazy」と呼ばれるマッチ戦略を用います。すなわち、まずreがマッチする
     最小の回数を試し、それが失敗したら順に繰り返しの回数を増やしてゆきます。
     次の例を比べてみてください：
          (rxmatch-substring (#/<.*>/ "<tag1><tag2><tag3>") 0)
            => "<tag1><tag2><tag3>"

          (rxmatch-substring (#/<.*?>/ "<tag1><tag2><tag3>") 0)
            => "<tag1>"

`(re...)'
     捕捉とクラスタリング。括弧でくくられた正規表現の列がグループとして
     扱われ、またそれにマッチした文字列はサブマッチとして保存されます。

`(?:re...)'
     捕捉無しクラスタリング。`re ...'はグループとして
     扱われますが、サブマッチとして保存されません。

`(?i:re...)'
`(?-i:re...)'
     大文字小文字の区別の制御。
     `(?i:re...)'はre...が大文字小文字にかかわらず
     マッチするようにします。 `(?-i:re...)'はその逆です。

     Perlの正規表現では'?'と':'の間に他のいくつかのフラグを使うことが
     できますが、Gaucheでは今のところこのフラグのみをサポートしています。

`pattern1|pattern2|...'
     パターンのいずれかにマッチします。

`.'
     任意の1文字にマッチします。改行文字にもマッチします。

`[char-set-spec]'
     char-set-specで指定される文字セット内の文字にマッチします。
     char-set-specについては*Note 文字集合::を参照して下さい。

`\s, \d, \w'
     それぞれ空白文字(`#[[:space:]]')、 数字(`#[[:digit:]]')、
     単語を構成する文字(`#[[:alpha:][:digit:]_]')にマッチします。

     文字セット内でも、その外でも使えます。

`\S, \D, \W'
     それぞれ`\s'、`\d'、`\w'で指定される文字セットの補集合の
     文字にマッチします。

`^, $'
     それぞれ、パターンの最初または最後に指定された場合、
     文字列の最初か最後にマッチします。

`\b, \B'
     `\b'は単語の境界の空文字列にマッチします。 `\B'はその逆です。

`(?=pattern)'
`(?!pattern)'
     Positive/negative lookahead assertion.  Match succeeds if pattern
     matches (or does not match) the input string from the current
     position, but this doesn't move the current position itself, so
     that the following regular expression is applied again from the
     current position.

     For example, the following expression matches strings that might
     be a phone number, except the numbers in Japan (i.e. ones that
     begin with "81").
          \+(?!81)\d{9,}


 -- Function: string->regexp string &keyword case-fold
     文字列STRINGを正規表現とみなして、`<regexp>'のインスタンスを
     作成して返します。

     キーワード引数CASE-FOLDに真の値が与えられた場合、作成される正規表現は
     大文字小文字を区別しないものとなります。
     (大文字小文字を区別しない正規表現に関しては上の説明を参照して下さい)。

 -- Function: regexp? OBJ
     OBJが正規表現オブジェクトなら真の値を返します。

 -- Function: regexp->string REGEXP
     正規表現REGEXPを記述する元になった文字列を返します。
     返される文字列は変更不可な文字列です。

 -- Function: rxmatch regexp string
     正規表現オブジェクトREGEXPに一致するものを文字列STRINGから
     探します。一致が見付かった場合は`<regmatch>'オブジェクトを返し、
     見付からなかった場合は`#f'を返します。

     他のScheme処理系ではこれは
     `match'、`regexp-search'、`string-match'など
     様々な名で呼ばれています。

 -- Generic application: REGEXP STRING
     正規表現オブジェクトは直接文字列に対して適用することもできます。
     これは`(rxmatch REGEXP STRING)'と同じ動作をしますが、
     表記が短くて済みます。この機能は*Note 適用可能なオブジェクト::
     で述べているメカニズムを 使って実装されています。

 -- Function: rxmatch-start match &optional (i 0)
 -- Function: rxmatch-end match &optional (i 0)
 -- Function: rxmatch-substring match &optional (i 0)
     `rxmatch'が返すマッチオブジェクトMATCHから情報を取り出します。
     Iが省略されるか0の場合、これらの手続きはそれぞれ一致した
     文字列の開始インデックス、終了インデックス、および一致した部分文字列を
     返します。Iに正の整数が与えられた場合は、I番目のサブマッチ
     に関する情報を返します。Iにそれ以外の値を与えるのはエラーです。

     簡便のために、MATCHに`#f'を渡すことも許されています。
     その場合、これらの手続きは`#f'を返します。

     これらの手続きはScshで`match:start'、`match:end'、
     `match:substring'と呼ばれているものと等価です。

 -- Function: rxmatch-num-matches match
     MATCHの持つマッチの数を返します。この数には
     「マッチ全体」も含まれるので、`<regmatch>'オブジェクトに対しては
     常に正の整数が返ることになります。また、値を持たないマッチもカウントされます
     (下の例を参照)。

     簡便のために、MATCHに`#f'を渡すこともできます。
     その場合は0が返ります。

          (rxmatch-num-matches (rxmatch #/abc/ "abc"))
            => 1

          (rxmatch-num-matches (rxmatch #/(a(.))|(b(.))/ "ba"))
            => 5

          (rxmatch-num-matches #f)
            => 0


 -- Function: rxmatch-after match &optional (i 0)
 -- Function: rxmatch-before match &optional (i 0)
     マッチオブジェクトMATCHの前および後の文字列を返します。
     正の整数がIに与えられた場合はi番目のサブマッチの前および後の
     文字列を返します。
          (define match (rxmatch #/(\d+)\.(\d+)/ "pi=3.14..."))

          (rxmatch-after match) => "..."
          (rxmatch-after match 1) => ".14..."

          (rxmatch-before match) => "pi="
          (rxmatch-before match 2) => "pi=3."

 -- Generic application: REGMATCH &optional INDEX
 -- Generic application: REGMATCH `'before' &optional INDEX
 -- Generic application: REGMATCH `'after' &optional INDEX
     マッチオブジェクトは直接整数のインデックスもしくはシンボル`before'または
     `after'に対して適用することができます。
     それぞれ`(rxmatch-substring REGMATCH INDEX)'、 `(rxmatch-before
     REGMATCH)'、および `(rxmatch-after REGMATCH)'と同じ動作をしますが、
     表記が短くて済みます。 この機能は*Note 適用可能なオブジェクト::
     で述べているメカニズムを使って実装されています。

          (define match (#/(\d+)\.(\d+)/ "pi=3.14..."))

          (match)           => "3.14"
          (match 1)         => "3"
          (match 2)         => "14"

          (match 'after)    => "..."
          (match 'after 1)  => ".14..."

          (match 'before)   => "pi="
          (match 'before 2) => "pi=3."

   また、*Note 正規表現ユーティリティ::には、正規表現検索に便利な
マクロや手続きが定義されています。参照して下さい。


File: gauche-refj.info,  Node: ベクター,  Next: ハッシュテーブル,  Prev: 正規表現,  Up: 組み込みライブラリ

6.12 ベクター
=============

 -- Builtin Class: <vector>
     ベクタはSchemeオブジェクトの単純な一次元配列です。
     インデックスを用いて定数時間でその要素にアクセスできます。
     一度作成されたベクタはその大きさを変えることはできません。

     `<vector>'クラスはまた`<sequence>'クラスを継承し、
     `map'や`fold'など様々な総称関数を使うことができます。 *Note
     コレクションフレームワーク:: と *Note シーケンスフレームワーク::
     を参照して下さい。

     数値しか要素に持たないベクタを使う場合、SRFI-4の
     単一型ベクタも使えるかもしれません (*Note 単一型のベクタ::参照)。

 -- Function: vector? obj
     [R5RS] OBJがベクタなら`#t'を、そうでなければ#Fを返します。

 -- Function: make-vector k &optional fill
     [R5RS] 長さKのベクタを作成して返します。
     省略可能な引数FILLが与えられていれば、ベクタの各要素はその値で
     初期化されます。そうでなければベクタの各要素の値は不定です。

 -- Function: vector obj ...
     [R5RS] 要素がOBJ ...であるようなベクタを作成して返します。

 -- Function: vector-length vector
     [R5RS] ベクタVECTORの長さを返します。

     `gauche.collection'モジュールをロードしていれば、
     メソッド`size-of'も同じ目的で使えます。

 -- Function: vector-ref vector k &optional fallback
     [R5RS+] ベクタVECTORのK番目の要素を返します。

     `vector-ref'はKが負の値であったりベクタの長さより
     大きかったりした場合はエラーを通知します。但し、省略可能な引数FALLBACK
     が与えられている場合はその値が返されます。これはGaucheの拡張です。

     `gauche.sequence'モジュールをロードしていれば、
     メソッド`ref'も同じ目的で使えます。

 -- Function: vector-set! vector k obj
     [R5RS] ベクタVECTORのK番目の要素をOBJに変更します。
     Kが負数であったりベクタの長さより大きい場合はエラーとなります。

     `gauche.sequence'モジュールをロードしていれば、
     メソッド`ref'のsetterメソッドも使えます。

 -- Function: vector->list vector &optional start end
 -- Function: list->vector list
     [R5RS+] ベクタをリストに変換したり、その逆を行う手続きです。

     VECTOR->LISTに省略可能な引数STARTとENDを与えることにより、
     値を取り出す範囲を制限することができます。

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

     `gauche.collection'モジュールをロードしていれば、 `(coerce-to
     <list> VECTOR)' と `(coerce-to <vector> LIST)'
     も同じ目的で使えます。

 -- Function: vector-fill! vector fill &optional start end
     [R5RS+] ベクタVECTORの全ての要素をFILLに変更します。

     省略可能な引数STARTとENDが与えられた場合、
     START番目の要素からEND-1番目の要素までのみに
     FILLを格納します。STARTとENDの既定値は
     それぞれ0とVECTORの大きさです。 START, END引数はGaucheの拡張です。

 -- Function: vector-copy vector &optional start end fill
     [SRFI-43] ベクタVECTORをコピーします。引数STARTとENDを与えることで
     コピーされる範囲を制限することができます。
     STARTとENDで指定される範囲が元のVECTORの範囲を越えた
     場合は、その部分がFILLで埋められます。

          (vector-copy '#(1 2 3 4 5))     => #(1 2 3 4 5)
          (vector-copy '#(1 2 3 4 5) 2 4) => #(3 4)
          (vector-copy '#(1 2 3 4 5) 3 7 #f) => #(4 5 #f #f)


File: gauche-refj.info,  Node: ハッシュテーブル,  Next: Weak ポインタ,  Prev: ベクター,  Up: 組み込みライブラリ

6.13 ハッシュテーブル
=====================

 -- Builtin Class: <hash-table>
     ハッシュテーブルのクラスです。

 -- Function: make-hash-table &optional type
     ハッシュテーブルを作成します。シンボルTYPEはテーブルのタイプを指定します。
     現在、以下のようなタイプがサポートされています。
     (TYPEが省略された場合は`eq?'とみなされます。)
    `eq?'
          キーの比較に`eq?'を使います。

    `eqv?'
          キーの比較に`eqv?'を使います。

    `equal?'
          キーの比較に`equal?'を使います。

    `string=?'
          キーの比較に`string=?'を使います。キーは文字列でなければなりません。

     `eq?'、`eqv?'、`string=?'タイプのハッシュテーブルでは、
     システム組み込みのハッシュ関数が使われます。Schemeからは、
     それらのハッシュ関数はそれぞれ`eq-hash'、`eqv-hash'、
     そしてSRFI-13の`string-hash'として呼ぶことができます。
     これらの関数はユーザ定義型に対応するように拡張することはできません。
     一方、`equal?'タイプのハッシュテーブルは
     下に述べる`hash'関数を使います。後者では、ユーザ定義型に対するハッシュ関数を
     独自に定義することができます。


 -- Function: hash obj
     OBJ のハッシュ値を返します。`equal?'-タイプのハッシュテーブルで
     利用するハッシュ関数です。この関数が返すハッシュ値は正確な非負整数で、
     以下の二つの性質があります。
        * A および B の型について、`hash' が定義されているとき、
          あらゆるオブジェクト A および  B に対して、 `(equal? A B)'
          であれば `(= (hash A) (hash B))'。

        * `hash'
          は(そのデータのアドレスというような)実行時の計算機の状態とは
          独立しています。それゆえ、その値をファイルに格納し、別のプロセスで読み込んで
          利用しても、ハッシュ値の正当性を失うことがないので、安全です。
     OBJ が、数値、真理値、文字、シンボル、キーワード、文字列、リスト、
     ベクタのいずれかならば、そのハッシュ値を求めるのには内部ハッシュ関数を
     使います。 OBJ が、それ以外であれば、 `hash' は総称関数
     `object-hash' を呼んで、そのハッシュ値を計算します。

 -- Generic Function: object-hash obj
     この総称関数に対するメソッドを定義することにより、ユーザ定義された
     型のオブジェクトはハッシュ値を持つことができ、`equal?'型のハッシュ
     テーブルで利用することができるようになります。

     メソッドは正確な非負整数を返さなければなりません。また、`hash' と
     同じ制約に従わなければなりません。

     メソッドが OBJ の要素のハッシュ値を必要とする場合には、
     それらに対しては、`object-hash' ではなく、`hash' を
     呼ばなければなりません。プリミティブなオブジェクトのハッシュ計算は
     `hash' が行うからです。

          (define-class <myclass> () (x y))

          ;; user-defined equality function
          (define-method object-equal? ((a <myclass>) (b <myclass>))
            (and (equal? (ref a 'x) (ref b 'x))
                 (eq?    (ref a 'y) (ref b 'y))))

          ;; user-defined hash function
          (define-method object-hash ((a <myclass>))
            (hash (list (ref a 'x) (ref a 'y))))

 -- Function: eq-hash obj
 -- Function: eqv-hash obj
     この2つは `eq?'-タイプおよび `eqv?'-タイプのハッシュテーブル
     用のハッシュ関数で、2^_n_-1 以下の非負の整数を返します。ここで、
     _n_ は 32 以上のシステム依存の値です。返り値のハッシュ値は、
     システムおよびプロセスに依存する値です。動作しているプロセスの境界を
     超えてもちまわることはできません。

     注意: `eq-hash' をつかって、数をハッシュしてはいけません。
     2つの数はたとえその値が等しくても `eq?' であることは保証されて
     いません。したがって、`eq?'-タイプのハッシュテーブルで、
     数のキーとしての使用はサポートされていません。

 -- Function: hash-table? obj
     OBJがハッシュテーブルであれば`#t'を返します。

 -- Function: hash-table-type ht
     ハッシュテーブルHTのタイプに応じて、シンボル
     `eq?'、`eqv?'、`equal?'、`string=?'のいずれかを 返します。

 -- Function: hash-table-num-entries ht
     ハッシュテーブルHT中の要素の個数を返します。

 -- Function: hash-table type key&value ...
     与えられたキーと値の列からタイプがTYPEであるハッシュテーブルを構築して
     返します。TYPEの意味は`make-hash-table'と同じです。
     各KEY&VALUEはペアでなければならず、そのcarがキー、cdrが値として使われます。

          (hash-table 'eq? '(a . 1) '(b . 2))
            ==
            (let ((h (make-hash-table 'eq?)))
               (hash-table-put! h 'a 1)
               (hash-table-put! h 'b 2)
               h)

 -- Function: hash-table-get ht key &optional default
     キーKEYをハッシュテーブルHTから探します。見つかればキーに対応する
     値を返します。キーが見つからなかった場合、DEFAULTが与えられていればそれを
     返し、そうでなければエラーを報告します。

 -- Function: hash-table-put! ht key value
     キーKEYと対応する値VALUEをハッシュテーブルHTに挿入します。

 -- Method: ref (ht <hash-table>) key &optional default
 -- Method: (setter ref) (ht <hash-table>) key value
     `hash-table-get'と`hash-table-put!'のメソッド版です。

 -- Function: hash-table-exists? ht key
     ハッシュテーブルHTにキーKEYを持つエントリがあれば`#t'を返します。

 -- Function: hash-table-delete! ht key
     ハッシュテーブル`ht'からキーKEYを持つエントリを削除します。
     KEYを持つエントリが実際に存在して削除された場合は`#t'を、
     エントリが存在しなかった場合は`#f'を返します。
     この手続きはSTkで`hash-table-remove!'と呼ばれているものです
     (STkのは戻り値が定義されていませんが)。GaucheではSRFI-1,
     SRFI-13やその他の ライブラリとの一貫性のために `delete'
     を採用しました。

 -- Function: hash-table-push! ht key value
     ハッシュテーブルHT中の、キーKEYに対応する値にVALUEをコンスし、
     それをKEYに対する新たな値とします。もしKEYに対応する値がまだ無ければ、
     新たなエントリが作成され、`(list VALUE)'がその値となります。

     この手続きは次のコードと同じ動作をしますが、キーの探索が一度しか行われないためより高速です。
          (hash-table-put! ht key
              (cons value (hash-table-get ht key '())))

 -- Function: hash-table-pop! ht key &optional default
     ハッシュテーブルHT中のキーKEYに対応する値が存在し、かつペアで
     あった場合に、そのエントリーを元の値のcdrで置き換え、元の値のcarを返します。
     KEYに対応する値が存在しないかペアではなかった場合、テーブルは変更されず、
     DEFAULTが与えられていればそれが返され、与えられていなければエラーが報告されます。

     値が置き換えれる場合でもキーの探索は一度しか行われないため効率が良いです。

 -- Function: hash-table-update! ht key proc &optional default
     `hash-table-push!'等のより一般的なバージョンです。
     ハッシュテーブルの探索が一度しか行われないことを除いては、
     基本的に次のように動作します。
          (let ((tmp (proc (hash-table-get HT KEY))))
            (hash-table-put! HT KEY tmp)
            tmp)
     KEYに対応するエントリがHTに無かった場合、動作は
     DEFAULTが与えられているかどうかで異なります。
     DEFAULTが与えられている場合は、それがKEYに対応する値として
     テーブルHTに追加されます (PROCは呼ばれません)。
     DEFAULTが与えられていなければ、エラーが報告されます。

     例えば、ハッシュテーブルを使ってオブジェクトの個数を数えているとしましょう。
     次の1行で、オブジェクトITEMが既に出現したかどうかを気にせずに
     その個数をインクリメントできます。

          (hash-table-update! ht item (cut + 1 <>) 0))


 -- Function: hash-table-for-each ht proc
 -- Function: hash-table-map ht proc
     ハッシュテーブルHT内の全てのエントリについて、各エントリのキーと値を
     2つの引数として手続きPROCを呼びます。

 -- Function: hash-table-fold ht kons knil
     ハッシュテーブルHT内の全てのエントリについてPROCを呼びます。
     PROCには3つの引数が渡されます。
     各エントリのキーと値、および一つ前のPROCの返り値です。
     最初のPROCの呼び出しの時には、第3引数にKNILが渡されます。
     最後のPROCの返り値が`hash-table-fold'の返り値となります。

 -- Function: hash-table-keys ht
 -- Function: hash-table-values ht
     それぞれ、ハッシュテーブルHT内の全てのキーまたは値をリストにして返します。

   *Note その他のリストライブラリ::も参照して下さい。
`hash-table->alist'と`alist->hash-table'が定義されています。


File: gauche-refj.info,  Node: Weak ポインタ,  Next: 制御,  Prev: ハッシュテーブル,  Up: 組み込みライブラリ

6.14 Weak ポインタ
==================

Weak
ポインタとは、それが参照しているオブジェクトがガベージコレクトされることを
許すようなポインタです。 Gaucheは_weak ベクタ_オブジェクトによってweak
ポインタの機能を提供します。 Weak
ベクタは通常のベクタに似ていますが、要素のオブジェクトがweak
ベクタ以外から
参照されていない場合、オブジェクトはガベージコレクトされ、weak
ベクタの該当するエントリは `#f'で置き換えられます。
     gosh> (define v (make-weak-vector 1))
     v
     gosh> (weak-vector-ref v 0)
     #f
     gosh> (weak-vector-set! v 0 (cons 1 1))
     #<undef>
     gosh> (weak-vector-ref v 0)
     (1 . 1)
     gosh> (gc)
     #<undef>
     gosh> (gc)
     #<undef>
     gosh> (weak-vector-ref v 0)
     #f

 -- Builtin Class: <weak-vector>
     Weak
     ベクタのクラスです。`<sequence>'と`<collection>'を継承しているので、
     `gauche.collection' (*Note コレクションフレームワーク::参照) と
     `gauche.sequence' (*Note シーケンスフレームワーク::参照)
     も使えます。
          (coerce-to <weak-vector> '(1 2 3 4))
            => a weak vector with four elements

 -- Function: make-weak-vector size
     大きさSIZEのweak ベクタを作成して返します。

 -- Function: weak-vector-length wvec
     weak ベクタ WVECの大きさを返します。

 -- Function: weak-vector-ref wvec k &optioal fallback
     weak ベクタ WVECのK番目の要素を返します。

     `weak-vector-ref'はKが負の値であったりベクタの長さより
     大きかったりした場合はエラーを通知します。但し、省略可能な引数FALLBACK
     が与えられている場合はその値が返されます。

     `gauche.sequence'モジュールをロードしていれば、
     メソッド`ref'も同じ目的で使えます。

 -- Function: weak-vector-set! wvec k obj
     weak ベクタ WVECのK番目の要素をOBJに変更します。
     Kが負数であったりベクタの長さより大きい場合はエラーとなります。


File: gauche-refj.info,  Node: 制御,  Next: 例外,  Prev: Weak ポインタ,  Up: 組み込みライブラリ

6.15 制御
=========

* Menu:

* 手続き::
* 適用可能なオブジェクト::
* 継続::
* 多値::
* 遅延評価::


File: gauche-refj.info,  Node: 手続き,  Next: 適用可能なオブジェクト,  Prev: 制御,  Up: 制御

6.15.1 手続き
-------------

 -- Builtin Class: <procedure>

 -- Function: procedure? obj
     [R5RS] OBJが手続きなら`#t'を、そうでなければ`#f'を返します。

 -- Function: apply proc arg1 ... args
     [R5RS] `(ARG1 ... . ARGS)'を引数として手続きPROCを呼びます。
     最後の引数ARGSは正規のリストでなければなりません。 PROCが返す
     値をそのまま返します。
          (apply list 'a 'b '(c d e)) => (a b c d e)

          (apply + 1 2 '(3 4 5))      => 15

* Menu:

* マッピング::
* コンビネータ::
* 省略可能引数のパージング::
* 手続きのアリティ::


File: gauche-refj.info,  Node: マッピング,  Next: コンビネータ,  Prev: 手続き,  Up: 手続き

6.15.1.1 マッピング
...................

 -- Function: map proc list1 list2 ...
     [R5RS+]
     与えられたリストの各要素に対してPROCを適用し、その結果をリストにして
     返します。R5RSではPROCの適用順序が定められていませんが、Gaucheでは
     常にPROCはリスト内の順番で呼ばれます。
     複数のリストが与えられた場合、最も短いリストが終了した時点でPROCの適用を
     打ち切ります。

          (map car '((a b) (c d) (e f))) => (a c e)

          (map cons '(a b c) '(d e f))
            => ((a . d) (b . e) (c . f))

     `gauche.collection'モジュール(*Note
     コレクションフレームワーク::参照)
     を使うと、`map'がリスト以外のコレクション型に対しても動作するようになります。

 -- Function: for-each proc list1 list2 ...
     [R5RS] 手続きPROCをリストの各エレメントに対して順に適用します。
     PROCの結果は捨てられます。`for-each'の戻り値は定義されていません。
     複数のリストが与えられた場合、一番短いリストが終了した時点で`for-each'は終了します。

     `gauche.collection'モジュール(*Note
     コレクションフレームワーク::参照)
     を使うと、`for-each'がリスト以外のコレクション型に対しても動作するようになります。


File: gauche-refj.info,  Node: コンビネータ,  Next: 省略可能引数のパージング,  Prev: マッピング,  Up: 手続き

6.15.1.2 コンビネータ
.....................

Gaucheには、combinatory
programmingに使えるいくつかの基本手続きがあります。

 -- Function: pa$ proc arg ...
     部分適用。手続きを返します。その手続きが引数M ...を伴って
     呼ばれた場合、それは`(proc arg ... m ...)'と等価になります。

          (define add3 (pa$ + 3))
          (add3 4) => 7

          (map (pa$ * 2) '(1 2 3)) => (2 4 6)

     SRFI-26で定義されているマクロ`cut'と`cute'も似たような抽象化の
     方法を提供しますが、`pa$'より多少柔軟性が高く、その分やや冗長です。
     *Note 手続きを作る::を参照して下さい。

 -- Function: apply$ proc
 -- Function: map$ proc
 -- Function: for-each$ proc
     `apply', `map'と`for-each'の部分適用版です。

          (define map2* (map$ (pa$ * 2)))
          (map2* '(1 2 3)) => (2 4 6)


   他にも`fold$'、`filter$'、`member$'等
いくつかの部分適用版の手続きが定義されています。 *Note List
library::を参照してください。

 -- Function: compose f ...
     複数の手続きを結合します。引数は全て手続きでなければなりません。
     2つの引数が渡された時、`(compose f g)'は次の式と等価です。
          (lambda args (call-with-values (lambda () (apply g args)) f))

     2つ以上の引数が渡された場合は、次のように結合されます。
          (compose f g h ...) == (compose (compose f g) h ...)

     いくつか例を示します。

          (define not-zero? (compose not zero?))
          (not-zero? 3) => #t
          (not-zero? 0) => #f

          (define dot-product (compose (apply$ +) (map$ *)))
          (dot-product '(1 2 3) '(4 5 6)) => 32

     境界のケース：ひとつだけ引数が渡された場合は、その引数がそのまま返されます。
     引数が全く渡されなかった場合は手続きVALUESが返されます。

 -- Function: any-pred pred ...
     与えられた引数をそれぞれ述語PREDに適用する手続きを返します。
     いずれかのPREDが`#f'でない値を返す場合、その値を返します。
     全てのPREDが`#f'を返す場合、`#f'を返します。

          (define string-or-symbol? (any-pred string? symbol?))
          (string-or-symbol? "abc") => #t
          (string-or-symbol? 'abc)  => #t
          (string-or-symbol? 3)     => #f

          (define <> (any-pred < >))
          (<> 3 4) => #t
          (<> 3 3) => #f

          ((any-pred (cut memq <> '(a b c))
                     (cut memq <> '(1 2 3)))
           'b)  => '(b c)

 -- Function: every-pred pred ...
     与えられた引数をそれぞれ述語PREDに適用する手続きを返します。
     全てのPREDが`#f'でない値を返す場合、戻り値は最後の
     PREDの戻り値になります。いずれかのPREDが`#f'を
     返す場合、`every-pred'はそれ以降のPREDを呼び出さずに
     `#f'を返します。

          ((every-pred odd? positive?) 3)  => #t
          ((every-pred odd? positive?) 4)  => #f
          ((every-pred odd? positive?) -3) => #f

          (define safe-length (every-pred list? length))
          (safe-length '(a b c))  => 3
          (safe-length "aaa")     => #f


File: gauche-refj.info,  Node: 省略可能引数のパージング,  Next: 手続きのアリティ,  Prev: コンビネータ,  Up: 手続き

6.15.1.3 省略可能引数のパージング
.................................

Schemeでオプショナル引数やキーワード引数を使うためには、
可変引数をリストとして取り自分で分解しなければなりません。
以下のマクロがヘルパーとして使えます。

 -- Macro: let-optionals* restargs (var-spec ...) body ...
 -- Macro: let-optionals* restargs (var-spec ... . restvar) body ...
     与えられた値のリストRESTARGSを、VAR-SPECにしたがって
     変数に束縛し、BODYを評価します。

     VAR-SPECはシンボルか、そのcarがシンボルである2要素のリストの
     いずれかです。シンボルは束縛された変数名です。
     RESTARGSにある値は、順番にシンボルに束縛されます。
     RESTARGSにVAR-SPECに示される数の値がない場合は、
     残りのSYMBOLは以下に従ってデフォルト値が束縛されます。
     VAR-SPECが単なるシンボルなら、デフォルト値は未定義です。
     VAR-SPECがリストなら、デフォルト値はリストの2番目の要素を
     評価した結果です。後者の場合、2番目の要素は十分な引数がない場合にのみ
     評価されます。
     束縛はVAR-SPECの順番にしたがって行われるので、2番目の要素は
     以前のVAR-SPECのバインディングを参照するかも知れません。

     2番目のフォームでは、RESTVARはシンボルでなければならず、
     VAR-SPECに束縛された後、RESTARGSに残っている値のリストに
     束縛されます。

     RESTARGがVAR-SPECよりも多い値を持っていてもエラーでは
     ありません。最初のフォームでは、余分な値は単に無視されます。

          (define (proc x . args)
            (let-optionals* args ((a 'a)
                                  (b 'b)
                                  (c 'c))
              (list x a b c)))

          (proc 0)         => (0 a b c)
          (proc 0 1)       => (0 1 b c)
          (proc 0 1 2)     => (0 1 2 c)
          (proc 0 1 2 3)   => (0 1 2 3)

          (define (proc2 . args)
            (let-optionals* args ((a 'a) . b)
              (list a b)))

          (proc2)          => (a ())
          (proc2 0)        => (0 ())
          (proc2 0 1)      => (0 (1))
          (proc2 0 1 2)    => (0 (1 2))

          (define (proc3 . args)
            (let-optionals* args ((a 0)
                                  (b (+ a 1))
                                  (c (+ b 1)))
              (list a b c)))

          (proc3)          => (0 1 2)
          (proc3 8)        => (8 9 10)
          (proc3 8 2)      => (8 2 3)
          (proc3 8 2 -1)   => (8 2 -1)

 -- Macro: get-optional restargs default
     これはLET-OPTIONALS*の短いバージョンで、オプショナル引数が
     1つしかないときに使います。オプショナル引数のリストとしてRESTARGSが
     与えらると、このマクロはオプショナル引数が与えられていればその値を返し、
     そうでなければDEFAULTの結果を返します。DEFAULTはRESTARGSが
     空リストでなければ評価されません。

          (define (proc x . maybe-opt)
            (let ((option (get-optional maybe-opt #f)))
              (list x option)))

          (proc 0)         => (0 #f)
          (proc 0 1)       => (0 1)

 -- Macro: let-keywords* restarg (var-spec ...) body ...
     このマクロはキーワード引数のためのものです。VAR-SPECは
     以下のフォームのうちのいずれかです。

    `(SYMBOL EXPR)'
          RESTARGがSYMBOLと同じ名前を持つキーワードを含んでいる場合、
          SYMBOLを対応する値に束縛します。そのようなキーワードがRESTARGに
          ない場合は、SYMBOLをEXPRの結果に束縛します。

    `(SYMBOL KEYWORD EXPR)'
          RESTARGがキーワードKEYWORDを含む場合、
          SYMBOLを対応する値に束縛します。そのようなキーワードがRESTARGに
          ない場合、SYMBOLをEXPRの結果に束縛します。

     デフォルト値EXPRは、RESTARGにキーワードが与えられてなかった
     場合にのみ評価されます。束縛はVAR-SPECでの順番に行われるので、
     EXPRは以前のVAR-SPECにより束縛された変数を参照できます。

     VAR-SPECにリストされていないキーワードがRESTARGに現れた場合、
     それは単に無視されます。

          (define (proc x . options)
            (let-keywords* options ((a 'a)
                                    (b :beta 'b)
                                    (c 'c))
              (list x a b c)))

          (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) => (0 a 1 3)


File: gauche-refj.info,  Node: 手続きのアリティ,  Prev: 省略可能引数のパージング,  Up: 手続き

6.15.1.4 手続きのアリティ
.........................

手続きのアリティを問い合わせるインターフェースです。 APIは、MzScheme
(PLT Scheme)を参考にしました。

 -- Function: arity PROC
     手続きPROCを与え、整数、_arity-at-least_オブジェクト、
     整数と_arity-at-least_オブジェクトからなるリストのいずれかを
     返します。

     整数の戻り値は、PROCが正確にその数の引数を取ることを表します。
     _arity-at-least_は、PROCが最低でも 引数`(arity-at-least-value
     _arity-at-least_)'を取ることを
     表します。リストは、異なるアリティを持つ複数の手続きがあることを
     表します。

     Gaucheではいつでも、既存の手続きやジェネリック関数にメソッドを追加
     できるので、`arity'が返す値はその手続きの現在の状態を示すに
     過ぎません。その手続きやジェネリック関数に新しいメソッドが追加
     されると、それも変更されます。

          (arity cons) => 2
          (arity list) => #<arity-at-least 0>
          (arity make) => (#<arity-at-least 1>)

 -- Function: arity-at-least? OBJ
     OBJがarity-at-leastオブジェクトなら、真を返します。

 -- Function: arity-at-least-value ARITY-AT-LEAST
     arity-at-leastオブジェクトが表す必須引数の数を返します。

 -- Function: procedure-arity-includes? PROC K
     手続きPROCが引数Kを取れる場合、`#t'を返します。
     そうでなければ`#f'を返します。


File: gauche-refj.info,  Node: 適用可能なオブジェクト,  Next: 継続,  Prev: 手続き,  Up: 制御

6.15.2 適用可能なオブジェクト
-----------------------------

Gaucheでは、特別な組み込みの機構によって任意のオブジェクトを
「適用可能」にすることができます。

 -- Generic Function: object-apply OBJECT ARG ...
     手続きでもジェネリックファンクションでもないオブジェクトが何らかの引数に
     適用されたとき、そのオブジェクトと引数がジェネリックファンクション`object-apply'
     に渡されます。

     この機能は、具体的な例を挙げた方が説明し易いでしょう。

   例えば、次のような式を評価しようとしたとします。

     ("abcde" 2)

オペレータは文字列に評価されますから、手続きでもジェネリックファンクションでも
ありません。そこで、Gaucheはこの式を、あたかも次のような式が与えられた
かのように解釈します。

     (object-apply "abcde" 2)

   デフォルトでは、`<string>'と`<integer>'を引数とする
`object-apply'のメソッドは定義されていないので、
この式はエラーになります。しかし、次のようなメソッドを定義すると：

     (define-method object-apply ((s <string>) (i <integer>))
       (string-ref s i))

   最初の式はまるで文字列が整数に適用されたかのように動作します。

     ("abcde" 2) => #\c

   このメカニズムは手続きが許されるほとんどの箇所で使うことができます。

     (apply "abcde" '(1))   => (#\b)
     (map "abcde" '(3 2 1)) => (#\d #\c #\b)

   Gauche組み込みオブジェクトのうち、`<regexp>'オブジェクトと
`<regmatch>'オブジェクトに対しては`object-apply'メソッドが定義されて
います。*Note 正規表現::を参照して下さい。

 -- Generic Function: (setter object-apply) OBJECT ARG ... VALUE
     適用可能オブジェクトを適用するフォームが`set!'フォームの第一ポジションに
     現れた場合、そのフォームは下に示すように展開され、このメソッドが呼ばれます。
          (set! (OBJECT ARG ...) VALUE)
           => ((setter object-apply) OBJECT ARG ... VALUE)


File: gauche-refj.info,  Node: 継続,  Next: 多値,  Prev: 適用可能なオブジェクト,  Up: 制御

6.15.3 継続
-----------

 -- Function: call-with-current-continuation proc
 -- Function: call/cc proc
     [R5RS] 現在の継続を手続き (継続手続き)
     にパッケージ化して、それを引数として
     PROCを呼び出します。PROCが戻ったら、その返り値が`call/cc'の
     値となります。作成された継続手続きがどこかで0個または複数個の引数を伴って呼ばれたら、
     あたかも`call/cc'から戻ったかのように実行が継続されます。その場合、
     `call/cc'は、継続手続きに与えられた引数を複数の値として返します。

     ファーストクラスの継続はSchemeの最も特徴的な機能のひとつですが、それを
     十分に説明するにはこの本の余白は狭すぎます。適切なドキュメントを参照してください。

     Gaucheはわずかの例外を除いて、完全な継続をサポートしています。つまり継続は通常
     無制限のエクステントを持ちます。しかし、継続がCコードからの「コールバック」
     --SchemeがCで書かれたコードを呼び出し、それが再びSchemeコードを呼び出した場合--
     で作られたら、その継続のエクステントはコールバックが呼び出したCコードに戻るまでと
     なります。エクステントの切れた継続を呼ぼうとするとGaucheはエラーを報告します。
     これは根本的な制限であり、おそらく解決されないでしょう。

     なお、コールバックコードから有効な継続を呼ぶことは常に可能です。また、
     高階関数を使う`map'や`for-each'、`apply'といった手続きは
     Cからのコールバックを使っておらず、この制限の影響を受けません。

     おそらく、そのようなコールバック内で無制限のエクステントを持つ継続を作る必要というのは
     あまり無いでしょう。Gauche組み込みの機能では、以下のようなコードがCからのコールバックで
     呼び出されます。さらに、外部のCライブラリを使った場合、例えばGUIツールキットからの
     コールバックなどはこの制限を受けるでしょう。
        * `write'、`display'、`format'から呼び出される
          `write-object'メソッド (*Note 出力::参照)。

        * バッファードポートから呼び出されるfillerとflusher手続き。
          (*Note 仮想ポート::参照)。


 -- Macro: let/cc var body ...
     このマクロは次のように展開されます : `(call/cc (lambda (VAR) BODY
     ...))'.  APIはPLT Schemeから取りました。

 -- Function: dynamic-wind before thunk after
     [R5RS] BEFORE、THUNKおよびAFTER は引数を取らない手続きです。
     `dynamic-wind'はまずBEFOREを呼び出し、続いてTHUNKを呼び出し、
     続いてAFTERを呼び出します。そしてTHUNKが返した値を返します。

     もし`dynamic-wind'のダイナミックスコープの外で捕捉された継続が
     THUNKの中で呼ばれることにより制御がTHUNKから飛び出した場合、
     (THUNKの中でエラーが起こった場合などが考えられます)、
     AFTERが呼ばれます。

     もし、THUNKの中で捕捉された継続がDYNAMIC-WINDのダイナミックスコープの
     外で呼ばれることにより制御がTHUNKの中へ飛び込んだ場合、
     BEFOREが呼ばれます。
          (letrec ((paths '())
                   (c #f)
                   (add (lambda (s) (push! paths s))))
            (dynamic-wind
             (lambda () (add 'connect))
             (lambda ()
               (add (call/cc (lambda (c0) (set! c c0) 'talk1))))
             (lambda () (add 'disconnect)))
            (if (< (length paths) 4)
                (c 'talk2)
                (reverse paths)))
           => (connect talk1 disconnect connect talk2 disconnect)


File: gauche-refj.info,  Node: 多値,  Next: 遅延評価,  Prev: 継続,  Up: 制御

6.15.4 多値
-----------

 -- Function: values obj ...
     [R5RS] OBJ ... を多値として返します。 呼び出し側は、組み込み構文の
     `receive' (*Note 変数束縛::参照)か、
     下に説明するR5RSの手続き`call-with-values'を使って多値を受け取ることが
     できます。 *Note Let-values::も参照してください。
          (values 1 2) => 1 and 2

 -- Function: call-with-values producer consumer
     [R5RS] 手続きPRODUCERを引数無しで呼びます。そして、それが返した値
     を引数としてCONSUMERを呼びます。CONSUMERが返す値を 返します。
          (call-with-values (lambda () (values 1 2)) cons)
            => (1 . 2)

 -- Macro: values-ref mv-expr k
     MV-EXPRが返す多値のK-番目の値を返します。概念としては、
     以下のコードと同じです。
          (call-with-values (lambda () mv-expr) (lambda r (list-ref r k)))
     このマクロは k がゼロであるような典型的な場合にはより単純な形へと
     展開されます。

     Common Lisp の `nth-value'
     に似ていますが、引数の順が逆になっています。 Scheme の他の`*-ref'
     手続きと合わせるためです。


File: gauche-refj.info,  Node: 遅延評価,  Prev: 多値,  Up: 制御

6.15.5 遅延評価
---------------

構文`delay'および手続き`force'は共に_遅延評価_のセマンティクスを
実装するのに使います。

 -- Special Form: delay expression
     [R5RS] EXPRESSIONの評価を内包した_プロミス_オブジェクトを返します。
     EXPRESSIONの評価はその値が`force'によって、明示的に要求される
     まで遅延されます。

 -- Function: force promise
     [R5RS] もし、PROMISEがプロミスでなければ、それをそのまま返します。

     そうではない場合で、もしPROMISEの値がまだ計算されていない場合には、
     `force'はPROMISEが内包している式を評価し、その結果を返します。

     いったん、PROMISEの値が計算されると、その値はメモ化され、あとで
     再び`force'されても、再計算がおこなわれることはありません。

 -- Function: promise? obj
     OBJが`delay'で生成されたプロミスオブジェクトである場合で、
     その場合に限り、`#t'を返します。

以下は、フィボナッチ数を計算するのに単純な遅延ストリームを用いた例です。

     (define (lcar lis)   ;; lazy car
       (car (force lis)))

     (define (lcdr lis)   ;; lazy cdr
       (cdr (force lis)))

     (define (ltake lis n)  ;; lazy take
       (if (<= n 0) '() (cons (lcar lis) (ltake (lcdr lis) (- n 1)))))

     (define (lmap proc l1 l2)  ;; lazy map
       (if (null? l1)
         '()
         (cons (proc (lcar l1) (lcar l2))
               (delay (lmap proc (lcdr l1) (lcdr l2))))))

     ;; lazy list of fibonacci numbers
     (define fibs (list* 1 1 (delay (lmap + fibs (cdr fibs)))))

     ;; take a look
     (ltake fibs 20)
       => (1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
           987 1597 2584 4181 6765)


File: gauche-refj.info,  Node: 例外,  Next: eval と repl,  Prev: 制御,  Up: 組み込みライブラリ

6.16 例外
=========

Gaucheの例外システムは次の3つのコンポーネントから構成されています。
(1)例外状況が発生したことを通知する方法、
(2)例外状況をどのように処理するかを指定する方法、
(3)例外状況を知らせたコードとそれを処理するコードがやりとりするための
標準オブジェクト(_コンディション_)。

   普通これらの3つのコンポーネントは一緒に使われます。
そこで、最初に例を用いて典型的な使い方について説明し、
そのあとでそれぞれの機能について詳しく解説します。

   用語について: いくつかの言語では_例外(exception)_というと、
例外的状況に遭遇したコードとそのハンドラがやりとりをするために用られる
オブジェクトのことを指します。Gaucheではそのようなオブジェクトのことを言うときには、
SRFI-35にならって_コンディション(condition)_を使います。
_例外_というのは、状況であり、_コンディション_はそれを記述する
実行時のオブジェクトです。

* Menu:

* 例外処理の概要::
* 例外の通知::
* 例外の処理::
* コンディション::


File: gauche-refj.info,  Node: 例外処理の概要,  Next: 例外の通知,  Prev: 例外,  Up: 例外

6.16.1 例外処理の概要
---------------------

特定のエラーを捕まえる
......................

最もよくある例外処理のひとつは、組み込みあるいは
ライブラリの手続きから発生した特定のエラーを捕捉するというものです。
`guard'マクロがこのような目的の場合に使えます。
コードは以下のような感じになるでしょう。

     (guard (exc
             ((condition-has-type? exc <read-error>) (format #t "read error!")
                                                     'read-error)
             (else 'other-error))
       (read-from-string "(abc")))

   `guard'節の cadr 部は `(VARIABLE CLAUSE ...)' という
形式です。この例では、変数は `exc'で、2つの節があります。 それぞれの
CLAUSE は `cond' と似た形式になります。

   `guard' の cddr 部は本体で、式のリストです。この例では、式は
`(read-from-string "(abc")' のひとつだけです。

   `guard' はその本体部を実行するところから始めます。
`read-from-string' は構文エラーに出くわすと、`<read-error>'型の
エラーを発生させます。`guard'フォームがこのエラーを捕捉し、
そのコンディションオブジェクトを変数EXCに束縛し、EXCの後の
節を、`cond'と同じようにチェックします。この場合、投げられた
コンディションは `<read-error>'なので、最初の節のテストを満し、
その節の残りの部分が実行されます。すなわち、`"read error!"' が
印字され、シンボル `read-error' が返ります。

他の言語を使い慣れていれば、同じパターンであることがわかると思います。
`guard' フォームの cddr 部は、C++やJavaの TRY 節、あるいは、 Common
Lisp の `handler-case' の cadr 部に似ています。 また、`guard'
フォームの cdadr 部は、`catch' 節あるいは、 `handler-case' の cddr
部に似ています。

   テスト式においては、投げられたコンディションのタイプをチェックする
のが普通です。`condition-has-type?' という関数が SRFI-35
で定義されていますが、これはちょっと冗長です。Gauche の
コンディションクラスは述語のようも使えるようになっており、上の
式は以下のように書くこともができます。

     (guard (exc
             ((<read-error> exc) 'read-error)
             (else 'other-error))
       (read-from-string "(abc")))

   _注意事項:_ 一般的には、投げられたコンディションが特定の
タイプであるかをチェックするのに`is-a?'は使えません。
コンディションが合成されたものである可能性があるからです。
合成されたコンディションについての 詳細は *Note コンディション::
を参照してください。

   もし、CLAUSE のどのテストも満されず、かつ `else' 節があたえられて
いなければ、その例外は `guard' から「抜け」ます。すなわち、`guard'
の外側のレベルあるいはトップレベルで処理されることになります。たとえば、
以下の `guard' フォームでは、`<read-error>' と `<system-error>'
としか処理できず、もし、本体が他のタイプのコンディション
を投げてきたら、その外側のレベルで処理しなければなりません。

     (guard (exc
             ((<read-error> exc) (handle-read-error))
             ((<system-error> exc) (handle-system-error))
             )
       body ...)

   `guard'および他の低レベルの例外処理の構成についての詳細は *Note
例外の処理:: を参照してください。

自分のコードから例外を通知する
..............................

例外を通知する一般的な方法は `raise'手続きを使うことです。

     (raise CONDITION)

   CONDITIONにはどんなオブジェクトでも渡すことができます。
それをどのように解釈するかはひとえに例外ハンドラにかかってます。
もし、コンディションとして整数があがってくるというのが判っていれば、
`guard' で以下のように捕捉することができます。

     (guard (exc
             ((integer? exc) 'raised))
       (raise 3))

   とはいうものの、`<condition>' あるいはそのサブクラスのインスタンスを
使うのが好ましいというのが通例です。`condition' マクロはコンディション
オブジェクトを作成するのに使えます。以下の例は、いくつかのスロット値をもち
それらを発生させるコンディションの作りかたを示したものです。

     ;; create and raise an error condition
     (raise (condition
             (<error> (message "An error occurred."))))

     ;; create and raise a system error condition
     (raise (condition
             (<system-error> (message "A system error occurred.")
                             (errno 4))))

   `condition' マクロおよび、どのようなコンディションクラスが用意
されているかの詳細については *Note コンディション:: を参照してください。

   もっとも、一般的なコンディションのタイプはエラーコンディション
ですから、`error' および `errorf' という便利な手続きが
用意されています。これらはメッセージ付きのエラーコンディションを
生成し、それを発生させます。

     ;; `error' concatenates the arguments into a message.
     (unless (integer? obj)
       (error "Integer expected, but got:" obj))

     ;; `errorf' uses format to create a message.
     (unless (equal? x y)
       (errorf "~s and ~s don't match" x y))

   _注意事項:_ いくつかの言語での例外を投げる機構、たとえば、
Cl++やJavaの `throw' はその継続を破棄します。これとは違い Schemeの
`raise' はその呼び出し元へ戻ることができます。もし、 `raise'
で元へもどらないで欲しいのなら、簡便な方法としては、
常にエラーコンディションの一つをわたるようにするというのがあります。
そうすると Gauche では `raise' は戻らないことを保証します。
`raise'の詳細については、*Note 例外の通知::を参照してください。

独自のコンディションを定義する
..............................

独自のコンディションクラスを定義することが可能で、そうすることで、
アプリケーション固有の情報を例外が発生した点からハンドラへ渡すことが
できます。

   Gauche のフレームワーク(SRFI-35)に適合させるためには、新しく定義する
コンディションクラスは組み込みの `<condition>' クラスあるいは
その子孫を継承し、また、メタクラス `<condition-meta>'
のインスタンスであることが望まれます。

   可搬性を増すと同時に上の慣例を確実にするための方法のひとつは、
`define-condition-type'マクロを使うことです。これは、
`SRFI-35'で定義されています。

     (define-condition-type <myapp-error> <error>
       myapp-error?
       (debug-info myapp-error-debug-info)
       (reason myapp-error-reason))

   これは、(Gauche内のクラス)`<myapp-err>'を定義するもので、
このクラスには`myapp-error?'という述語とアクセサのあるスロット
があります。こうすれば、以下のようなコードで新しいコンディション
型が使えます。

     (guard (exc
              ((myapp-error? exc)
               (let ((debug-info (myapp-error-debug-info exc))
                     (reason (myapp-error-reason exc)))
                 ... handle myapp-error ...)))
       ...
       ...
       (if (something-went-wrong)
         (raise (condition
                  (<myapp-error> (debug-info "during processing xxx")
                                 (reason "something went wrong")))))
       ...
       ...
       )

   Gauche
のオブジェクトシステムでコンディション型がどのように実装されているかは
`define-condition-type'マクロの解説を参照してください。


File: gauche-refj.info,  Node: 例外の通知,  Next: 例外の処理,  Prev: 例外処理の概要,  Up: 例外

6.16.2 例外の通知
-----------------

エラーの通知
............

最も良くある例外ケースはエラーです。標準的なエラー条件を通知するために、
ふたつの簡単な関数が用意されています。
標準的なエラー以外の条件を通知するには、
下で説明する`raise'手続きを使って下さい。

 -- Function: error string arg ...
     [SRFI-23] エラーを通知します。内部的には、このアクションは次の
     2つのステップで実現されます。
       1. 前にSTRING、後にARGが続くメッセージとともに、
          エラーコンディションが生成されます。

       2.
          エラーコンディションが投げられます。現在アクティブな例外ハンドラがあれば、
          それにより処理されます。

     アクティブなエラーハンドラがない場合、デフォルトのエラーハンドラが
     使われます。それはエラーメッセージといくらかのデバッグ情報を現在の
     エラーポートに出力します。Gaucheがインタラクティブに動作しているときは、
     制御がトップレベルに移ります。Gaucheがスクリプトを実行しているときは、
     終了ステータス`EX_SOFTWARE'とともに終了します。

 -- Function: errorf fmt-string arg ...
     エラーに似ていますが、エラーメッセージは`format'によりフォーマット
     されます。すなわち、以下と等価です。
          (define (errorf fmt . args)
            (error (apply format #f fmt args)))

一般的な条件の通知
..................

 -- Function: raise condition
     [SRFI-18] これは、例外事態を通知する基本となるメカニズムです。

     この手続きは現在の例外ハンドラを呼び出します。引数CONDITIONは
     例外の性質を表現するのに使われ、例外ハンドラに渡されます。
     Gaucheの組み込み手続きやライブラリ手続きは常に、`<condition>'クラス
     もしくはそのサブクラスのインスタンスをCONDITIONとして用いますが、
     ユーザは任意のオブジェクトを`raise'に渡すこともできます。
     渡されたCONDITIONの解釈は例外ハンドラに任されます。

     _注意事項:_
     いくつかの主流の言語では、例外を「投げる」と制御はそこに
     戻りません。Gaucheでは`raise'から戻って来れるように
     セットアップすることが可能です。詳細は*Note 例外の処理::を
     参照してください。

     `raise'から戻って来ることが無いようにしたい場合は、
     `<serious-condition>'やそのサブクラスのインスタンスをCONDITION
     として`raise'に渡すのが確実です。
     組み込みコンディションのクラス階層については*Note
     コンディション::を参照して下さい。


File: gauche-refj.info,  Node: 例外の処理,  Next: コンディション,  Prev: 例外の通知,  Up: 例外

6.16.3 例外の処理
-----------------

上位レベルの例外処理機構
........................

 -- Macro: guard (var clause ...) body ...
     [SRFI-34] これはGaucheでのエラー処理の高水準フォームです。
     これは後述の`with-error-handler'関数の上に作り上げられています。

     VAR はシンボルで CLAUSE は `cond' 節と同じ形式です。
     つまり、各節は以下の形式のどれかひとつです。
       1. `(TEST EXPR ...)'

       2. `(TEST => PROC)'

     最後のCLAUSEは`(else EXPR ...)'という形式も許されます。

     このフォームは通常の場合には BODY ... を評価し最後の BODY
     の式の値を返します。本体の式を評価している最中に例外が
     発生した場合、発生した例外を変数 VAR に束縛し、その後 各節の TEST
     式を評価します。もし、TEST 式のひとつが
     真値を返したとき、その節が上述の最初の形式であれば、対応する EXPR
     が評価されます。あるいは、節が二番目の形式であれば、
     手続きPROCにTESTの結果が渡されます。

     指定された節の TEST および EXPR が評価されるとき、
     `guard'を呼び出した時点での例外ハンドラが設定されます。つまり、
     CLAUSE 内部で再び例外が発生した場合、その例外は、_外側の_
     例外ハンドラまたは `guard' フォームで処理されます。

     もし、どの TEST も真値を返さず、最後の `clause' が `else'
     節であれば、それに結びつけられた EXPR が評価されます。 もし、どの
     TEST も真値を返さず、`else' 節がなければ、再び
     例外が発生し、外側の例外ハンドラで処理されます。

     例外が `clause' のどれかで処理された時には、`guard' は
     それを処理した節の最後の EXPR の値を返します。

 -- Function: with-error-handler handler thunk
     HANDLERをアクティブなエラーハンドラにし、THUNKを実行します。
     THUNKが正常に戻ったら、その結果が返されます。
     THUNKの実行中にエラーが通知されたら、エラーを表す例外オブジェクトを
     1引数とするHANDLERが、`with-error-handler'の継続とともに呼ばれます。
     すなわち、`with-error-handler'は、HANDLERが返す値を返します。

     HANDLERがエラーを通知したら、それは`with-error-handler'が
     呼ばれたときにインストールされていたハンドラにより処理されます。

     HANDLERが実行される場合の動的な環境は、エラーが起きたときのそれと
     同じです。THUNK内で`dynamic-wind'が使われていたら、
     そのAFTERメソッドはHANDLERが戻った後、かつ`with-error-handler'が
     戻る前に呼ばれます。

     `with-error-handler'の振舞いは、低レベルなメカニズムを使って
     以下のようなSchemeコードで
     表すことができます。実際の関数は、より軽量なメカニズム ("one-shot
     continuation", *Note [1CC]: onecont.に似ています)
     を使って仮想マシンに組み込まれていることに注意して下さい。

          ;; with-error-handlerの概念的な実装
          (define (with-error-handler handler thunk)
            (call/cc
              (lambda (cont)
                (let* ((prev-handler (current-exception-handler))
                  (with-exception-handler
                    (lambda (exn)
                      (if (error? exn)
                          (with-exception-handler
                            (lambda (err) (prev-handler err))
                            (lambda () (call-with-values (handler exn) cont)))
                          (prev-handler exn)))
                    thunk))))))

下位レベルの例外処理機構
........................

このレイヤはSRFI-18互換のシンプルな例外メカニズムを提供します。
`with-error-handler'のような高次元の構造の振る舞いを、
`with-exception-handler'を使って上書きすることができます。

   これは諸刃の剣であることに注意して下さい。あなたは独自の例外処理
セマンティクスを構築する自由がありますが、Gaucheシステムは何か
間違いがあっても救ってくれません。システムの高次元のセマンティクスを
カスタマイズしたいか、他のSRFI-18準拠のコードを移植している場合にのみ、
これらのプリミティブを使って下さい。

 -- Function: current-exception-handler
     [SRFI-18] 現在の例外ハンドラを返します。

 -- Function: with-exception-handler handler thunk
     [SRFI-18] HANDLERは1引数を取る手続きです。この手続きは、HANDLERを
     現在の例外ハンドラにセットし、THUNKを呼び出します。

   一般的に、エラーのような継続不可能な例外をこの低レベルなメカニズムで
扱いたい場合は、明示的にそのハンドラから制御を移さなければなりません
(前述の`with-error-handler'の説明を参照して下さい)。
`raise'は、ハンドラが継続不可能な例外を返したことを検知し、
デフォルトのエラーハンドラメカニズムを使ってエラーを報告しますが、
それは単に安全ネットにしか過ぎません。

   HANDLERは`raise'の動的な環境と同じ環境で呼ばれることにも
注意して下さい。したがって、HANDLER内部で例外を発生させると、
再度HANDLERによって捕捉されます。その例外処理を"外側"の例外
ハンドラへ伝播させるのはプログラマの責任です。

   これらの手続きの振る舞いは、次の概念的なSchemeコードによって
説明されるでしょう。

     ;; 低レベルな例外メカニズムの概念的な実装
     ;; %xhは例外ハンドラのリスト

     (define (current-exception-handler) (car %xh))

     (define (raise exn)
       (receive r ((car %xh) exn)
         (when (uncontinuable-exception? exn)
           (set! %xh (cdr %xh))
           (raise (make-error "returned from uncontinuable exception")))
         (apply values r)))

     (define (with-exception-handler handler thunk)
       (let ((prev %xh))
         (dynamic-wind
           (lambda () (set! %xh (cons handler %xh)))
           thunk
           (lambda () (set! %xh prev)))))


File: gauche-refj.info,  Node: コンディション,  Prev: 例外の処理,  Up: 例外

6.16.4 コンディション
---------------------

組み込みコンディションクラス
............................

現在のところGaucheには以下の組み込みコンディションクラスの階層があります。
これは、おおよそのところ SRFI-35 および SRFI-36 のコンディションの階層を
反映したものですが、Gauche風のクラス名になっています。対応する SRFI の
コンディションタイプがあるものについては、SRFI でのクラス名も使えます。

       <condition>
         +- <compound-condition>
         +- <serious-condition>
         |    +- <serious-compound-condition> ; also inherits <compound-condition>
         +- <message-condition>
              +- <error>                      ; also inherits <serious-condition>
                   +- <system-error>
                   +- <read-error>
                   +- <io-error>
                        +- <port-error>
                             +- <io-read-error>
                             +- <io-write-error>
                             +- <io-closed-error>
                             +- <io-unit-error>

いくつかのコンディションが同時に発生することがあることに注意してください。
たとえば、ファイルの読み込がデバイスの欠陥により失敗した場合は、
`<system-error>' _および_ `<io-read-error>' の両方からなる
エラーとなるでしょう。 このような場合、_合成したコンディション
(compound condition)_ が発生します。
したがって、たとえば、`<io-read-error>' が投げられたかどうかをチェック
するのに、単に `(is-a? obj <io-read-error>)' を使えばよいというわけ
にはいきません。 後述の「コンディション API」の節を参照してください。

 -- Metaclass: <condition-meta>
     すべてのコンディションクラスはこのクラスのインスタンスです。
     このクラスは `object-apply' を定義していますので、
     コンディションクラスは述語として使うことができます。たとえば、

          (<error> obj) == (condition-has-type? obj <error>)

 -- Class: <condition>
 -- Condition Type: &condition
     [SRFI-35] コンディションの階層のルートクラスです。

 -- Class: <compound-condition>
     合成コンディションを表現します。合成コンディションは
     `make-compound-condition' を用いて1つ以上のコンディションから
     生成することができます。このクラスを直接使ってはいけません。

     合成コンディションは`condition-has-type?' に対して、
     元のコンディションのどれかが、与えられたタイプなら、`#t'
     を返します。

 -- Class: <serious-condition>
 -- Condition Type: &serious
     [SRFI-35]
     このクラスのコンディションは無視して先を続けることはできない深刻な
     状況のためにあります。特に、このタイプのコンディションを `raise'
     したら、それは元には絶対に戻らないと考えて問題ありません。

 -- Class: <serious-compound-condition>
     深刻なコンディションを含む合成コンディションを表現するための
     内部クラスです。`<compound-condition>' および
     `<serious-condition>' の両方を継承しています。
     `make-compound-condition' は深刻なコンディションを含む複数の
     コンディションを渡されると、このクラスを使います。このクラスを
     直接使ってはいけません。

 -- Class: <message-condition>
 -- Condition Type: &message
     [SRFI-35]
     このクラスはメッセージ付のコンディションを表現し、スロットを一つ
     もっています。

      -- Instance Variable of <message-condition>: message
          メッセージ


 -- Class: <error>
 -- Condition Type: &error
     [SRFI-35] エラーを表します。`<serious-condition>' および
     `<message-condition>' を継承しています。したがって、 `message'
     スロットを持っています。

     注意事項: SRFI-35 の`&error'コンディションは `&serious'
     のみを継承し、`&message' は継承していません。したがって、
     このエラーコンディションにメッセージを付与するためには、
     合成コンディションを使わなければなりません。Gauche は
     主として過去のバージョンとの互換性を確保するために、
     ここで多重継承を用いています。
     可搬性のあるコードを掛くには、以下のようにメッセージコンディション
     付きのエラーコンディションを使うべきです。

          (condition
            (&message (message "Error message"))
            (&error))

 -- Class: <system-error>
     `<error>' のサブクラス。
     システムコールがエラーを返したとき、この型の例外が投げられます。
     `message' スロットには通常エラーの(`strerror(3)'のような)説明が
     含まれています。それ以外に、このクラスにはもうひとつ次のような
     インスタンススロットがあります。

      -- Instance Variable of <system-error>: errno
          システムのエラー番号の整数値を持ちます。

     このクラスには対応する SRFI のコンディションタイプがありませんが、
     OSの生のエラーコードを取得するのに重要です。いくつかのケースで
     このタイプのコンディションは他の、たとえば `<io-read-error>'
     のようなコンディションと合成されます。

 -- Class: <read-error>
 -- Condition Type: &read-error
     [SRFI-36] `<error>'
     のサブクラス。リーダがS式を読み込み中に、字句エラー
     または構文エラーを検出したとき、この型の例外が投げられます。

      -- Instance Variable of <read-error>: port
          リーダがS式を読みこんでいたポート。 (註: SRFI-36 の
          `&read-error' はこのスロットを定義していません。
          ポータブルなプログラムを書く場合はこのスロットを使わないで下さい)。

      -- Instance Variable of <read-error>: line
          リーダがこのエラーを発生させたときの入力行カウント(1がベース)。
          リーダが行カウントを保持しないポートから読み込むときには、-1
          となる。

      -- Instance Variable of <read-error>: column
      -- Instance Variable of <read-error>: position
      -- Instance Variable of <read-error>: span
          これらのスロットは、SRFI-36 の `&read-error'
          で定義されています。 今のところ、これらのスロットは常に `#f'
          を保持するようになっています。


 -- Class: <io-error>
 -- Condition Type: &io-error
     [SRFI-36] I/O エラーのベースとなるクラス。`<error>'
     を継承しています。

 -- Class: <port-error>
 -- Condition Type: &io-port-error
     [SRFI-36] ポート関連の I/O エラー。`<io-error>' を継承しています。

      -- Instance Variable of <port-error>: port
          エラーを起したポートを保持。

 -- Class: <io-read-error>
 -- Condition Type: &io-read-error
     [SRFI-36] ポートから読み込み中の I/O エラー。`<port-error>'
     を継承しています。

 -- Class: <io-write-error>
 -- Condition Type: &io-write-error
     [SRFI-36] ポートへの書き出し中の I/O エラー。`<port-error>'
     を継承しています。

 -- Class: <io-closd-error>
 -- Condition Type: &io-closed-error
     [SRFI-36]
     クローズされたポートで読み込み/書き出しをしようしたときの I/O
     エラー。 `<port-error>' を継承しています。

 -- Class: <io-unit-error>
     対象となるポートでサポートされていない単位での読み/書き要求
     (たとえば、キャラクタ専用ポートでのバイナリ I/O 要求)の際の I/O
     エラー。 `<port-error>' を継承しています。

コンディションAPI
.................

 -- Macro: define-condition-type name supertype predicate field-spec ...
     [SRFI-35+]
     新しいコンディションタイプを定義します。Gaucheでは、コンディションタイプは
     クラスであり、そのメタクラスは `<condition-meta>' です。

     NAME が新しいタイプの名前になり、この名前の変数が作成された
     コンディションタイプに束縛されます。SUPERTYPE はこのコンディション
     タイプのスーパータイプ(直接のスーパークラス)の名前です。コンディション
     タイプは `<condition>' を継承するか、その子孫を継承しなければ
     なりません。(この形式では、多重継承を指定することはできません。
     一般的にいって、コンディションタイプの階層の中では多重継承は避ける
     べきです。そのかわりに、合成コンディションを使えます。合成コンディションは
     多重継承を使いません。)

     変数 PREDICATE はこのコンディションタイプ用の述語手続きに
     束縛されます。

     各 `field-spec' は `(field-name accessor-name)' の形式で
     このコンディションは、フィールド名は FIELD-NAME で決まります。
     変数 ACCESSOR-NAME はそのフィールドにアクセスする手続きに
     束縛されます。Gauche では、それぞれのフィールドは生成された
     クラスのスロットとなります。

     Gaucheはsrfi-35を拡張して、PREDICATEやACCESSOR-NAMEを
     定義する必要が無い場合はその位置に`#f'を指定できるようにしています。
     ACCESSOR-NAMEが必要無い場合はそれを省略することもできます。

 -- Function: condition-type? obj
     [SRFI-35] OBJがコンディションタイプである場合で、その場合にかぎり、
     `#t' を返します。Gauche では `(is-a? obj <condition-meta>)'
     と同じです。

 -- Function: make-condition-type name parent field-names
     [SRFI-35] 新しいコンディションタイプを生成する手続き版です。

 -- Function: make-condition type field-name value ...
     [SRFI-35] コンディションタイプ TYPE のコンディションを生成し、
     `field-name' および `value' のペアで指定されたように
     フィールドを初期化します。

 -- Function: condition? obj
     [SRFI-35] OBJ がコンディションである場合で、その場合にかぎり、
     `#t' を返します。Gauche では `(is-a? obj <condition>)' と
     同じです。

 -- Function: condition-has-type? obj type
     [SRFI-35] OBJ がコンディションタイプ TYPE に属している場合で、その
     場合にかぎり、`#t' を返します。合成コンディションがあるので、
     これは、`is-a?' と同じではありません

 -- Function: condition-ref condition field-name
     [SRFI-35] CONDITION のフィールド FIELD-NAME の値を検索します。
     CONDITION が合成コンディションであれば、元のコンディションの
     フィールドにアクセスできます。もし、複数の元のコンディションが、
     FIELD-NAME を持つ場合には、最初に `make-compound-condition'
     に渡されたものが優先されます。

     コンディションのフィールドにアクセスするには、SLOT-REF および REF
     の両方あるいはどちらかを使えます。合成コンディションでは、
     `slot-missing' メソッドが定義されますので、SLOT-REF は
     あたかも、合成コンディションが元になったコンディションの全てのスロットを
     もつかのように振舞います。しかしながら、`condition-ref' を
     使う方が可搬性が増します。

 -- Function: make-compound-condition condition0 condition1 ...
     [SRFI-35] CONDITION0 CONDITION1 ...
     のすべてを持つ合成コンディション
     を返します。返されたコンディションのフィールドは、与えられたコンディション
     のすべてのフィールドの和集合になります。同じ名前のフィールドを持つ
     コンディションがある場合には最初に与えられものが優先されます。
     返されたコンディションは元になったコンディションのすべてのタイプの
     コンディションタイプをもつことになります。
     (これは多重継承ではありません。上の `<compound-condition>' を参照)

 -- Function: extract-condition condition condition-type
     [SRFI-35] CONDITION はコンディションで、CONDITION-TYPEタイプで
     なければなりません。この手続きは CONDITION-TYPE のコンディション
     を返し、CONDITION からとりだされた値のフィールドを持ちます。

 -- Macro: condition type-field-binding ...
     [SRFI-35] コンディションを生成するのに便利なマクロ。
     合成されたコンディションも生成できます。 TYPE-FIELD-BINDING は、
     `(CONDITION-TYPE (FIELD-NAME VALUE-EXPR) ...)'
     という形式になります。

          (condition
            (type0 (field00 value00) ...)
            (type1 (field10 value10) ...)
            ...)
           ==
          (make-compound-condition
            (make-condition type0 'field00 value00 ...)
            (make-condition type1 'field10 value10 ...)
            ...)


File: gauche-refj.info,  Node: eval と repl,  Next: 入出力,  Prev: 例外,  Up: 組み込みライブラリ

6.17 eval と repl
=================

 -- Function: eval expr env
     [R5RS] EXPRを評価します。ENVは下に述べる手続きにより
     返される値でなければなりません。現時点では、それは単なる
     `<module>'オブジェクトですが、Gaucheが将来、ファースト
     クラスの環境オブジェクトを採用する可能性はあります。

 -- Function: null-environment version
 -- Function: scheme-report-environment version
 -- Function: interaction-environment
     [R5RS] `eval'の第2引数として使われる環境識別子を返します。
     現時点では、環境識別子は単にモジュールです。 `(null-environment
     5)'は、R5RSで規定されている単なる構文的な
     束縛を含む`null'モジュールを返します。 `(scheme-report-environment
     5)'は、R5RSで規定されている
     構文的な束縛と手続きの束縛を含む`scheme'モジュールを返します。
     `(interaction-environment)'は、全てのGaucheのビルトインと
     ユーザ定義の全てを含んだ`user'モジュールを返します。
     将来、Gaucheがファーストクラスの環境オブジェクトを採用する可能性が
     あるので、環境識別子が単なるモジュールであることを当てにしないで
     下さい。

     引数VERSIONに5以外の値を渡すとエラーが通知されます。


 -- Function: read-eval-print-loop &optional reader evaluator printer
          prompter
     `gosh'のデフォルトのread-eval-printループをアプリケーションに
     エクスポートします。それぞれの引数は、Gaucheのデフォルトの手続きを使うことを
     示す`#f'であっても良いですし、以下の条件を満たす手続きであっても構いません。

    _reader_
          引数を取らない手続きです。式を読み込んでそれを返すことを期待されます。

    _evaluator_
          式と環境識別子を2引数として取る手続きです。式を評価して、0個以上の値を
          返すことを期待されます。

    _printer_
          0個以上の引数を取る手続きです。それらの値を出力することを期待されます。
          この手続きの戻り値は無視されます。

    _prompter_
          引数を取らない手続きです。プロンプトを出力することを期待されます。
          この手続きの戻り値は無視されます。

     これらの手続きが与えられると、`read-eval-print-loop'は以下のように
     動作します。

       1. PROMPTERを呼んでプロンプトを出力します。

       2.
          READERを呼んで式を読み込みます。EOFが返されたら、ループを終了し
          `read-eval-print-loop'から戻ります。

       3. EVALUATORを呼んで式を評価します。

       4. PRINTERを呼んで結果を出力し、その後、1から繰り返します。

     これらの手続きのうちの1つからエラーが通知されると、そのエラーは
     デフォルトのエスケープハンドラにより捕捉・報告され、その後、
     ループが1から再開します。

     これらの手続きの内部で継続を捕捉し、後で再起動することは
     許されています。


File: gauche-refj.info,  Node: 入出力,  Next: プログラムのロード,  Prev: eval と repl,  Up: 組み込みライブラリ

6.18 入出力
===========

* Menu:

* ポート::
* ポートとスレッド::
* ポート共通の操作::
* ファイルポート::
* 文字列ポート::
* コーディング認識ポート::
* 入力::
* 出力::


File: gauche-refj.info,  Node: ポート,  Next: ポートとスレッド,  Prev: 入出力,  Up: 入出力

6.18.1 ポート
-------------

 -- Builtin Class: <port>
     Portは、Schemeにおいて抽象化された入出力のインタフェースを提供します。
     Gaucheはportにいくつかの拡張を行い、いろいろなアプリケーションに対応できるようにしました。

     標準のSchemeでは、portはキャラクタを一文字づつ読み込む(一文字先読み可)、
     もしくは書き出すだけのもので、他の入出力ルーチンはその上に構築されています。

     Gaucheではさらに次のような操作がportに対して可能になっています。

    バイナリI/O
          キャラクタ毎でなく、オクテット毎のI/Oが可能です(Gaucheではマルチバイト文字を
          扱うので、この２つが異なることに注意して下さい)。大抵のポートでは
          キャラクタI/OとバイナリI/Oを混ぜて使うことができます。

          最も基本的なバイナリI/Oプリミティブは`read-byte'と`write-byte'です。
          また、より高機能な`pack'や`unpack'といった手続きが *Note
          バイナリデータのパック:: で提供されています。

    ブロックI/O
          ポートから指定した数のバイト列を読んだり、ポートへ書いたりできます。
          ポートがブロックI/Oを行うデバイスに接続されている場合、ある程度大きなブロック毎に
          読み書きすると効率の良いデータ転送ができます。

    変換
          ポートはまた、データストリームを変換するのにも使えます。例えば`gauche.charconv'
          モジュールでは、文字コード間の変換を行うポートを提供しています
          (詳しくは*Note 文字コード変換::を参照)。

    追加機能
          また、特殊な機能を実現するポートもあります。
          コーディング認識ポート(*Note コーディング認識ポート::参照)は
          ファイル中の特殊なコメントを認識して、そのファイルがどの文字エンコーディング
          で書かれているかを検出します。 仮想ポート(*Note
          仮想ポート::参照)はSchemeでふるまいをプログラムできる
          ポートを提供します。



File: gauche-refj.info,  Node: ポートとスレッド,  Next: ポート共通の操作,  Prev: ポート,  Up: 入出力

6.18.2 ポートとスレッド
-----------------------

GaucheがスレッドサポートをONにしてコンパイルされている場合、
組み込みのポート操作関数はポートをロックして、
複数のスレッドからの同一のポートへのアクセスがポートの内部状態を壊さないように
しています。 (SRFI-18によって要求されている動作です)。
ここで「組み込みのポート操作関数」はGaucheにより提供される、
ポートを引数に取り何らかのI/O動作や問い合わせを行う手続きで、
`read'/`write'、`read-char'/`write-char'、 `port->string'等を含みます。
但し、`call-with-*'や`with-*'系関数は、
与えられた手続きを呼ぶ際にはポートをロックしません。
その手続きが別のスレッドにポートを渡すかもしれず、Gaucheにはそれを知ることが
できないからです。

このことはつまり、マルチスレッド環境でポートへのアクセス競合にそれほど
気を使わなくても良いということですが、同時にポートアクセスの度に
いくぶんかのオーバヘッドがあることを意味します。I/Oを多く行うプログラムで、
しかもその粒度が細かい場合(文字ごととかバイトごととか)、このオーバヘッドが
問題になるかもしれません。
その場合、次の手続きを使って処理中にポートを明示的にロックすることができます。

 -- Function: with-port-locking port thunk
     PORTをロックし、THUNKを実行します。
     ロックはTHUNKのダイナミックエクステントの期間有効です。

     PORTがロックされている期間での組み込みのポートアクセス関数の
     呼び出しは排他制御をバイパスするため、性能向上が見込まれます。

     ロックの有効期間はTHUNKのダイナミックエクステントなので、
     THUNK内から`with-port-locking'の外で捕捉された
     継続を呼んだ場合、ロックは解放されます。その後、THUNK内で
     捕捉された継続が呼ばれた場合、再びロックが獲得されます。

     `with-port-locking'はネスト可能です。ロックは最も外側の
     `with-port-locking'の期間中有効となります。


File: gauche-refj.info,  Node: ポート共通の操作,  Next: ファイルポート,  Prev: ポートとスレッド,  Up: 入出力

6.18.3 ポート共通の操作
-----------------------

 -- Function: port? obj
 -- Function: input-port? obj
 -- Function: output-port? obj
     [R5RS] OBJ
     がそれぞれポート、入力ポート、出力ポートなら真を返します。
     `port?'はR5RSの"Standard Procedures"の項には
     載っていませんが、"Disjointness of Types"の項に挙げられています。

 -- Function: port-closed? port
     OBJがポートであり、既に閉じられていた場合に真を返します。
     一度閉じたポートは再び開くことはできません。

 -- Function: current-input-port
 -- Function: current-output-port
     [R5RS] 現在の入力ポートと出力ポートをそれぞれ返します。

 -- Function: current-error-port
     現在のエラーポートを返します。

 -- Function: standard-input-port
 -- Function: standard-output-port
 -- Function: standard-error-port
     プログラム開始時点の入力、出力、エラーポートをそれぞれ返します。

 -- Function: with-input-from-port port thunk
 -- Function: with-output-to-port port thunk
 -- Function: with-error-to-port port thunk
     それぞれ入力、出力、エラーポートはPORTにセットした状態でTHUNKを呼び出します。

 -- Function: close-input-port port
 -- Function: close-output-port port
     [R5RS] それぞれ、入力ポートと出力ポートを閉じます。

 -- Function: port-type port
     PORTのタイプを、シンボル`file'、`string'、`proc'の
     いずれかで返します。

 -- Function: port-name port
     PORTの名前を返します。ポートがファイルに関連付けられている場合は、ポートの名前は
     ファイル名です。そうでない場合、ポートを説明する文字列が返されます。

 -- Function: port-buffering port
 -- Function: (setter port-buffering) port buffering-mode
     ファイルポート(`(port-type PORT)'が`file'を返すもの)
     に対して、そのバッファリングモードを読みだし、もしくは変更します。
     入力ポートではバッファリングモードは `:full'、
     `:modest'、`:none'のいずれかです。 出力ポートでは `:full'、
     `:line'、`:none'のいずれかです。
     バッファリングモードの詳細な説明は、*Note ファイルポート::
     を参照してください。

     `port-buffering'がファイルポート以外のポートに対して呼ばれた場合は
     `#f'を返します。`port-buffering'のsetterが
     ファイルポート以外のポートに対して呼ばれた場合はエラーとなります。

 -- Function: port-current-line port
     PORTの現在の行番号を返します。行番号は、ファイルに関連付けられたポートで
     かつシーケンシャルなキャラクタI/Oを行っている場合のみ有効です。それ以外の場合は
     -1を返します。

 -- Function: port-file-number port
     PORTがファイルに関連付けられている場合、そのファイルディスクリプタ番号を
     返します。それ以外の場合は`#f'を返します。

 -- Function: port-seek port offset &optional whence
     PORTがランダムアクセス可能なポートの場合、
     この手続きはPORTのread/writeポインタをOFFSETとWHENCEの値によって
     設定し、新たなread/writeポインタの値(データの先頭からのバイトオフセット)を
     返します。PORTがランダムアクセス可能でない場合は`#f'が返されます。
     現在のバージョンでは、ファイルポートおよび入力文字列ポートがランダムアクセス可能です。
     出力文字列ポートは現在のポインタの値を問い合わせる動作だけが可能です。

     ポートのポインタはバイト数で表現され、文字数とは異なることに注意して下さい。

     PORTが出力ファイルポートの場合は、データの終端を超えた位置までseek
     することが可能です。その場合の動作はPOSIXのlseek(2)に準じます。
     入力ファイルポートや入力文字列ポートではデータの終端以降にseekすることはできません。

     WHENCE引数は、OFFSETの基準を指定する小さな整数です。
     以下の定数が定義されています。

    `SEEK_SET'
          OFFSETはデータ先頭からのバイト数を指定します。
          WHENCEが省略された場合のデフォルトの動作です。

    `SEEK_CUR'
          OFFSETは現在のread/writeポインタからの相対バイト数を指定します。
          OFFSETが0であれば、ポインタを動かさずに現在のポート位置を知ることができます。

    `SEEK_END'
          OFFSETはデータの終端からの相対バイト数を指定します。

 -- Function: port-tell port
     PORTの現在のread/writeポインタの値をバイト数で返します。
     PORTがランダムアクセス可能でない場合は`#f'が返されます。
     これは以下の呼び出しと等価です。
          (port-seek PORT 0 SEEK_CUR)

   _名前に関するメモ_: `port-seek'は他の処理系で
`seek'、`file-position'、`input-port-position'/
`output-port-position'等と呼ばれています。
`port-tell'は`tell'、`ftell'、`set-file-position!'等と
呼ばれています。いくつかの処理系は`port-position'という手続きを
持っていますが、`port-seek'とは別の機能を実現しています。
`file-position'はCommonLisp由来の名前ですが、
fileポート以外のものも扱うため採用しませんでした。
また、`seek'と`tell'はPOSIXの名前由来であり、
Gaucheの名前付け規則を使って`sys-seek'と`sys-tell'としても
よさそうですが、portの操作はシステムコールレベルよりも抽象度が高いため
これも採用しませんでした。結局、新しい名前を採用することにしました。

 -- Function: copy-port src dst &keyword (unit 0)
     SRCからEOFまでデータを読みだし、DSTへ書き出します。

     キーワード引数UNITは0以上の整数か、シンボル`byte'もしくは`char'
     でなければなりません。これはデータをコピーする単位を指定します。
     整数ならば、その大きさ(0の場合はシステム規定の大きさ)のバッファが確保され、
     ブロックI/Oを使って転送が行われます。通常のファイルをコピーする場合などはこれが
     速いでしょう。もしUNITがシンボル`byte'であれば、バイト毎
     に読みだし／書き込みが行われます。UNITがシンボル`char'であれば、
     キャラクタ毎に読みだし／書き込みが行われます。


File: gauche-refj.info,  Node: ファイルポート,  Next: 文字列ポート,  Prev: ポート共通の操作,  Up: 入出力

6.18.4 ファイルポート
---------------------

 -- Function: open-input-file filename &keyword if-does-not-exist
          buffering element-type
 -- Function: open-output-file filename &keyword if-does-not-exist
          if-exists buffering element-type
     [R5RS+] ファイルFILENAMEを入力または出力用にオープンし、
     入力ポートまたは出力ポートを作成して返します。

     キーワード引数により、例外的な場合の動作を細かく指定できます。

    `:if-exists'
          このキーワード引数は`open-output-file'のみに指定でき、
          FILENAMEが既に存在した場合の動作を指定します。次の値のいずれかを与えることができます。
         `:supersede'
               既存のファイルが長さ0に縮められます。これが既定の動作です。

         `:append'
               既存のファイルにこれから書き出す内容が追加されます。

         `:overwrite'
               既存のファイルにこれから書き出す内容が上書きされます。
               書き出されるデータが既存のファイルのデータよりも短い場合、
               残りの部分はそのまま残されます。

         `:error'
               エラーが報告されます。

         `#f'
               何もせず、`#f'を返します。

    `:if-does-not-exist'
          このキーワード引数はFILENAMEが存在しない場合の動作を指定します。
         `:error'
               エラーを報告します。これが`open-input-file'の既定の動作です。

         `:create'
               ファイルが作成されます。これが`open-output-file'の既定の動作です。
               ファイルの存在のチェックと作成はアトミックに行われます。
               このオプションに加え、IF-EXISTSオプションに`:error'か`#f'を
               指定することで、排他的にファイルを作成することができます。
               `open-input-file'に対してはこの値を指定することはできません。

         `#f'
               何もせず、`#f'を返します。

    `:buffering'
          この引数はバッファリングモードを指定します。以下の値が設定できます。
          ポートのバッファリングモードは手続き`port-buffering' (*Note
          ポート共通の操作::参照)によって 読みだし/変更可能です。
         `:full'
               出来る限りデータをバッファリングします。これがデフォルトのモードです。

         `:none'
               バッファリングを行いません。出力ポートにデータが書き出されるか、
               入力ポートからデータが読み込まれる度に、下位にあるシステムコールが呼ばれます。
               プロセスの標準エラーポートはこのモードでオープンされています。

         `:line'
               このモードは出力ポートにのみ有効です。書き出されたデータはバッファに
               貯められますが、改行文字が書かれたらフラッシュされます。
               このモードは対話的な出力ポートなどに便利です。
               プロセスの標準出力ポートはこのモードでオープンされています。
               (これは、Cのstdioライブラリの「ラインバッファリング」とちょっと違うことに
               注意してください。stdioでは同じファイルディスクリプタから入力が行われる時も
               バッファはフラッシュされますが、Gaucheではそうはなりません)。

         `:modest'
               このモードは入力ポートにのみ有効です。ほとんど`:full'バッファリングモードと
               同じですが、`read-block'はポートに要求されたデータより少ないデータしか
               無かった場合、要求された量がたまるまで待つのではなく、今あるデータだけを
               返します。このモードはポートがパイプやネットワークに接続されている場合に
               便利です。

    `:element-type'
          この引数はファイルのタイプを指定します。
         `:character'
               ファイルはキャラクタモード(テキストモード)でオープンされます。

         `:binary'
               ファイルはバイナリモードでオープンされます。
          _現在のバージョンでは、この引数は無視され、全てのファイルはバイナリモードで
          オープンされます。いずれにせよUnixプラットフォームでは違いはありません。_

     IF-EXISTSとIF-DOES-NOT-EXISTフラグの組合せにより、
     色々な動作を実現できます。
          (open-output-file "foo" :if-exists :error)
           => ;"foo"を排他的にオープンするかエラーを報告する

          (open-output-file "foo" :if-exists #f)
           => ;"foo"を排他的にオープンするか#fを返す

          (open-output-file "foo" :if-exists :append
                                  :if-does-not-exist :error)
           => ;"foo"が既に存在する場合に限り、それを追加モードでオープン

     ファイルをオープンせずにその存在をチェックするには、
     `sys-access'か`file-exists?'を使って下さい (*Note
     ファイルの状態::参照)。

     註：`gauche.charconv'モジュールはこれらの手続きを、
     ENCODINGキーワード引数を取るように拡張して、
     異なる文字エンコーディングでのファイルの読み書きを可能にします。
     *Note 文字コード変換::参照。

     移植性に関する註：Schemeシステムによっては、FILENAMEのところに
     シェルコマンドを指定して、サブプロセスの標準入出力と通信できるようにするものが
     あります。他のスクリプティング言語(例：Perl)にも同様の機能があります。
     Gaucheでは、`open-input-file'と`open-output-file'は
     あくまでファイル (OSがファイルとして扱うもの)
     のみに対して使えます。
     サブプロセスと通信するためには、「プロセスポート」という機能が提供されています。
     *Note Process ports::を参照して下さい。

 -- Function: call-with-input-file string proc &keyword
          if-does-not-exist buffering element-type
 -- Function: call-with-output-file string proc &keyword
          if-does-not-exist if-exists buffering element-type
     [R5RS] STRINGで示されるファイルを入力または出力用にオープンし、
     作成されたポートを引数として手続きPROCを呼び出します。
     PROCが正常終了するか、PROC内で捕捉されないエラーが起きた場合に
     ファイルはクローズされます。

     キーワード引数は`if-exists'、`buffering', `element-type'、
     `if-does-not-exist'は
     `open-input-file'及び`open-output-file'のものと同じ意味を持ちます。
     IF-EXISTSやIF-DOES-NOT-EXISTに`#f'を指定した場合、
     ファイルがオープンされなかった場合はPROCにポートではなく`#f'が渡される
     ことに注意して下さい。

     PROCが返す値を返します。

 -- Function: with-input-from-file string thunk &keyword
          if-does-not-exist buffering element-type
 -- Function: with-output-to-file string thunk &keyword
          if-does-not-exist if-exists buffering element-type
     [R5RS]
     STRINGで示されるファイルを入力または出力用にオープンし、オープンされた
     ポートを現在の入力または出力ポートに設定して、THUNKを呼び出します。
     THUNKが戻るか、THUNK内で捕捉されないエラーが生じた際にファイルは閉じられます。

     THUNKが返す値を返します。

     キーワード引数は
     `open-input-file'及び`open-output-file'のものと同じ意味を持ちます。
     但しIF-EXISTSやIF-DOES-NOT-EXISTに`#f'が指定され、
     ファイルがオープンできなかった場合は、THUNKは呼ばれずに
     直ちに`#f'が返されます。

   _ポートを閉じるセマンティクスについて:_
R5RSは`call-with-input-file'等の説明において、次のように述べています。
「_procが戻って来なかった場合、今後ポートが読み書きに一切使われないことが
証明できない限りは、ポートは自動的には閉じられない_」。

Gaucheの実装は若干この条件には反しています。捕捉されないエラーがPROCから
発せられたというだけでは、そのポートが今後一切使われないかどうかはわかりません。
しかし実際には、そのようなエラーが発せられた後でポートに対して意味のある操作をするのは
非現実的です。ポートがどのような状態にあるかわからないわけですから。
現実的なプログラムでは、ポートに対して意味のある操作をしつづけたいのなら、
PROCの中で明示的にエラーをハンドルすべきでしょう。

   `call-with-input-file'の外で捕捉された継続をPROC内で呼んだ場合には
ポートは閉じられないことに注意して下さい。後でPROCへと制御が戻ってくるかも
しれないからです (コルーチン等)。また、 低レベルの例外メカニズム(*Note
例外の処理::
参照)を利用した場合、エラー時にポートを閉じるのはプログラマの責任になります。

 -- Function: open-input-fd-port fd &keyword buffering name owner?
 -- Function: open-output-fd-port fd &keyword buffering name owner?
     与えられたファイルディスクリプタにアクセスする入力または出力ポートを
     作成して返します。BUFFERING は`open-input-file' の項で
     説明されたポートのバッファリングモードを指定します。デフォルトは`:full'です。
     NAMEは`port-name'によって返されるポートの名前を指定します。 OWNER?
     は、このポートを閉じた時にFDもクローズすべきかどうかを
     指定するブーリアン値です。


File: gauche-refj.info,  Node: 文字列ポート,  Next: コーディング認識ポート,  Prev: ファイルポート,  Up: 入出力

6.18.5 文字列ポート
-------------------

文字列ポートは、メモリ上のデータと関連付けられたポートです。

 -- Function: open-input-string string
     [SRFI-6] STRINGを内容とする入力文字列ポートを作って返します。
     文字列に逐次的にアクセスする場合、インデックスをインクリメントしながら
     `string-ref'を呼び出すより効率の良い方法です。
          (define p (open-input-string "文字 列"))
          (read p) => 文字
          (read-char p) => #\space
          (read-char p) => #\列
          (read-char p) => #<eof>
          (read-char p) => #<eof>

 -- Function: get-remaining-input-string port
     PORTは入力文字列ポートでなければなりません。
     入力ポートに残っている文字列を返します。
     PORTの内部ポインタは動かされないので、PORTに対するreadは
     影響を受けません。PORTが既にEOFに達していた場合は、空文字列が返されます。

          (define p (open-input-string "abc\ndef")
          (read-line p)                  => "abc"
          (get-remaining-input-string p) => "def"
          (read-char p)                  => #\d
          (read-line p)                  => "ef"
          (get-remaining-input-string p) => ""

 -- Function: open-output-string
     [SRFI-6]
     出力文字列ポートを作成して返します。このポートに書き出された文字列は
     内部のバッファにたくわえられ、`get-output-string' で取り出すことが
     できます。
     これは、順番に文字列を構成する方法として、あらかじめ文字列をアロケートして
     `string-set!'で埋めて行くよりもずっと効率の良い方法です。

 -- Function: get-output-string port
     [SRFI-6]
     出力文字列ポート`port'を取り、それまでそのポートに蓄積された
     文字列を返します。バイトデータがそのポートに書き出されていた場合、
     この手続きはまず内部バッファをスキャンし、結果が完全な文字列で表現できるかどうかを
     調べます。もし表現できなければ、不完全な文字列が返されます。

     これはPORTの操作には影響をあたえません。`get-ouptut-string'を
     呼んだ後でも、PORTに内容を蓄積しつづけることができます。

 -- Function: call-with-input-string string proc
 -- Function: call-with-output-string proc
 -- Function: with-input-from-string string thunk
 -- Function: with-output-to-string thunk
     これらのユーティリティ関数は次に定義されるような動作をします。
     インタフェースはファイルポートを扱う類似の関数と揃えてあります。
          (define (call-with-output-string proc)
            (let ((out (open-output-string)))
              (proc out)
              (get-output-string out)))

          (define (call-with-input-string str proc)
            (let ((in (open-input-string str)))
              (proc in)))

          (define (with-output-to-string thunk)
            (let ((out (open-output-string)))
              (with-output-to-port out thunk)
              (get-output-string out)))

          (define (with-input-from-string str thunk)
            (with-input-from-port (open-input-string str) thunk))

 -- Function: call-with-string-io str proc
 -- Function: with-string-io str thunk
          (define (call-with-string-io str proc)
            (let ((out (open-output-string))
                  (in  (open-input-string str)))
              (proc in out)
              (get-output-string out)))

          (define (with-string-io str thunk)
            (with-output-to-string
              (lambda ()
                (with-input-from-string str
                  thunk))))

 -- Function: write-to-string obj &optional writer
 -- Function: read-from-string string &optional start end
     文字列ポートを使う定型句をユーティリティ関数にしました。
          (write-to-string obj writer)
            ==
            (with-output-to-string (lambda () (writer obj)))

          (read-from-string string)
            ==
            (with-input-from-string string read)
     WRITERの既定値は`write'です。START, ENDは
     省略されればそれぞれ0と文字列の長さになります。

     移植性への註：Common
     Lispに同名の関数があります。必須引数の動作は同じですが、
     省略可能な引数は異なります。
     STkには`read-from-string'がありますが、省略可能な引数は取りません。


File: gauche-refj.info,  Node: コーディング認識ポート,  Next: 入力,  Prev: 文字列ポート,  Up: 入出力

6.18.6 コーディング認識ポート
-----------------------------

コーディング認識ポートは特殊な手続的入力ポートで、`load'が
プログラムソースコードを読む際に使われています。このポートは `;; -*-
coding: utf-8 -*-'のような、プログラムソースの
文字エンコーディングを指定する特殊なコメントを認識し、適切な
文字エンコーディング変換を行います。
特殊なコメントでソースの文字エンコーディングを指定することについては、
*Note マルチバイトスクリプト::を参照して下さい。

 -- Function: open-coding-aware-port iport
     入力ポートを引数としてとりコーディング認識入力ポートを返します。
     基本的には IPORT からの入力データをリーダにわたしているだけです。
     しかし、IPORT からの入力データの最初の2行以内に、特別な呪文コメント
     が現れた場合、コーディング認識ポートは、その後に読み込まれるデータについて
     必要な文字エンコーディング変換を行います。

     引数として渡されたポート、IPORT は生成されたコーディング認識
     ポートによって所有されます。つまり、コーディング認識ポートがクローズ
     されると、IPORT もクローズされます。IPORT から読み込まれた
     内容はコーディング認識ポート内でバッファリングさます、したがって、
     別のコードで IPORT から読み出しを行うべきではありません。

     デフォルトでは、Gauche の `load' はプログラムソースを読むのに
     コーディング認識ポートを使います。したがって、文字エンコーディングを
     示す特別な呪文コメントは、Gauche
     のソースプログラムでは有効になります (*Note
     Schemeファイルのロード::参照)。ただし、この機構自身は `load' とは
     独立しており、このポートを別の目的で利用できます。特にコーディングの
     呪文コメントがある Scheme
     のソースプログラムを処理する関数を書くときに 便利です。


File: gauche-refj.info,  Node: 入力,  Next: 出力,  Prev: コーディング認識ポート,  Up: 入出力

6.18.7 入力
-----------

入力に関する手続きで、省略可能な引数IPORTは入力ポートでなければなりません。
省略された場合が現在の入力ポートが使われます。

* Menu:

* データの読み込み::
* 読み込み時コンストラクタ::
* 入力ユーティリティ手続き::


File: gauche-refj.info,  Node: データの読み込み,  Next: 読み込み時コンストラクタ,  Prev: 入力,  Up: 入力

6.18.7.1 データの読み込み
.........................

 -- Function: read &optional iport
     [R5RS] IPORTからS式をひとつ読み込んで返します。
     GaucheはR5RSに定義されている構文要素に加え、*Note 字句構造::に
     定義されている拡張構文要素を認識します。

     IPORTが既にEOFに達していた場合は、EOFオブジェクトが返されます。

     この手続きはS式を構成する最後の文字までを読み、その後の文字はポートに
     残します。これは、S式に続く空白文字も読み込むCommonLispの`read'の
     振る舞いとは異なります。

 -- Function: read-with-shared-structure &optional iport
 -- Function: read/ss &optional iport
     [SRFI-38] これらの手続きは，SRFI-38
     で定義されていて，共有構造を表す記法 (`#n=',
     `#n#')を認識できます．Gauche の組み込み `read' は この SRFI-38
     の記法を認識します．それゆえ，これらの手続きは，`read'
     と同じで，SRFI-38 との互換性のために用意されています．

 -- Function: read-char &optional iport
     [R5RS] IPORTから1文字読み込んで返します。
     IPORTが既にEOFに達していた場合はeofオブジェクトを返します。
     IPORTにあるバイトストリームが正しい文字を構成しない場合、
     ふるまいは未定義です。(将来はポート側に、不正な文字に対する対応を決める
     オプションを設ける予定です)。

 -- Function: peek-char &optional iport
     [R5RS]
     IPORTから1文字読み込んで返します。文字はそのままIPORTに留まります。
     IPORTが既にEOFに達していた場合はeofオブジェクトを返します。
     IPORTにあるバイトストリームが正しい文字を構成しない場合、
     ふるまいは未定義です。(将来はポート側に、不正な文字に対する対応を決める
     オプションを設ける予定です)。

 -- Function: read-byte &optional iport
     入力ポートIPORTから1バイト読み込み、0から255までの整数値として返します。
     IPORTが既にEOFに達していた場合はeofオブジェクトを返します。

 -- Function: peek-byte &optional iport
     入力ポートIPORTの先頭の1バイトを見て、それを0から255までの整数値として返します。
     IPORTが既にEOFに達していた場合はeofオブジェクトを返します。

 -- Function: read-line &optional iport allow-byte-string?
     入力ポートから、行末もしくはEOFまで読み込んで文字列として返します。
     よく使われる行末 (LF only, CRLF, and CR only) を認識します。
     戻り値にはこれらの行末文字は含まれません。
     IPORTが既にEOFに達していた場合はeofオブジェクトを返します。

     IPORTから、内部文字エンコーディングでは文字を構成し得ないバイトシーケンスが
     読まれた場合、デフォルトでは`read-line'はエラーを通知します。
     しかし、省略可能な引数ALLOW-BYTE-STRING?に真の値が与えられた場合は、
     `read-line'はエラーを通知せず、かわりにバイト文字列
     (不完全な文字列) を
     返します。この動作は、特に文字エンコーディングが不明なソースから読み込む際に
     便利です。例えばXMLドキュメントを読み込む際、最初の行のcharsetパラメータを
     チェックしてから適切な文字エンコーディング変換ポートを使うといった用途などです。

 -- Function: read-block nbytes &optional iport
     NBYTESバイトのデータをIPORTから読み込み、
     不完全な文字列として返します。IPORTに十分なデータが無い場合、
     返される文字列はNBYTESより短いかもしれません。
     NBYTESが0の場合は、常に空文字列が返されます。

     IPORTが既にEOFに達していた場合はEOFオブジェクトが返されます。

     IPORTがファイルポートだった場合、`read-block'は
     ポートのバッファリングモードによってふるまいが異なります
     (バッファリングモードの詳細については*Note
     ファイルポート::を参照して下さい)。
        * バッファリングモードが`:full'の場合、`read-block'は
          EOFを読まない限り、NBYTESのデータが読まれるまで待ちます。

        * バッファリングモードが`:modest'か`:none'である場合、
          `read-block'はEOFが読まれなくても、すぐに読めるデータがNBYTESよりも
          少ない場合はそのデータだけを返します。

     `read-block'は呼ばれるたびに新たな文字列をアロケートします。
     アロケーションを避け、あらかじめ用意された固定長のバッファにデータを読み込みたい
     場合は、`gauche.uvector'モジュールの`read-block!' を使って下さい
     (*Note ユニフォームベクタのブロック入出力::参照)。
     `Read-block!'はuniform vectorをバッファとして用います。

     データブロックをポートに書き出すには、データが文字列で表現されている
     場合は単純に`display'が使えます。データがuniform
     vectorで表現されている
     場合は`gauche.uvector'モジュールの`write-block'が 使えます (*Note
     ユニフォームベクタのブロック入出力::参照)。

 -- Function: eof-object? obj
     [R5RS] OBJがEOFオブジェクトなら`#t'を返します。

 -- Function: char-ready? port
     [R5RS] PORTから文字が読み出せる状態ならば`#t'を返します。

     今のところ、この手続きはPORTから少なくとも1バイト読み出せる状態なら`#t'
     を返します。そのバイトがマルチバイト文字を構成する場合、`char-ready?'を返した
     ポートから文字全てを読み込もうとすると、ブロックする可能性があります。
     (通常の使用状況ではそのようなことは起きないでしょうが、理論的には起こり得ます。
     慎重を期したい場合は`read-block'でバイトシーケンスとして読み込んだ後、
     入力文字列ポート等を使って文字毎に読むようにして下さい。)


File: gauche-refj.info,  Node: 読み込み時コンストラクタ,  Next: 入力ユーティリティ手続き,  Prev: データの読み込み,  Up: 入力

6.18.7.2 読み込み時コンストラクタ
.................................

SRFI-10で定義されている読み込み時コンストラクタは、ユーザ定義の構造の
外部表現を作るための簡単な方法を提供します。

 -- Reader Syntax: `#,(TAG ARG ...)'
     [SRFI-10] GaucheはTAG
     (シンボル)を_コンストラクタ手続き_に関連付ける
     グローバルなテーブルを管理しています。

     リーダーがこの構文に出会ったとき、ARG ...を読み込み、
     TAGに関連付けられた読み込みコンストラクタを探し、 ARG
     ...を引数としてそのコンストラクタを呼び出し、
     その構文を読み込んだ結果としてそのコンストラクタが返した値を挿入します。

     この構文はリーダー内部で処理されることに注意して下さい。評価器は
     ARGを見ず、リーダーが返したオブジェクトしか見ません。

 -- Function: define-reader-ctor TAG PROCEDURE
     [SRFI-10] 読み込みコンストラクタPROCEDUREをTAGに関連付けます。

     例:
          (define-reader-ctor 'pi (lambda () (* (atan 1) 4)))

          #,(pi) => 3.141592653589793

          '(#,(pi)) => (3.141592653589793)

          (define-reader-ctor 'hash
            (lambda (type . pairs)
              (let ((tab (make-hash-table type)))
                (for-each (lambda (pair)
                            (hash-table-put! tab (car pair) (cdr pair)))
                          pairs)
                tab)))

          (define table
           #,(hash eq? (foo . bar) (duh . dah) (bum . bom)))

          table => #<hash-table eq? 0x80f9398>
          (hash-table-get table 'duh) => dah

     `write-object'メソッド(*Note 出力::参照)と組み合わせて、
     読み戻ることが可能なフォームで書かれたユーザ定義のクラスを
     作ることが簡単になります。

          (define-class <point> ()
            ((x :init-value 0 :init-keyword :x)
             (y :init-value 0 :init-keyword :y)))

          (define-method write-object ((p <point>) out)
            (format out "#,(<point> ~s ~s)" (ref p 'x) (ref p 'y)))

          (define-reader-ctor '<point>
            (lambda (x y) (make <point> :x x :y y)))


   _注意:_ `define-reader-ctor'の効果の範囲はSRFI-10には
規定されておらず、SRFI-10をサポートする実装においても互換性の問題を
起こすことがあるかもしれません。
(実際に、`define-reader-ctor'の存在そのものが実装の選択に
任されています。)

   Gaucheでは、現時点においては、`define-reader-ctor'はそのフォームが
コンパイルされ評価された時点で効力を持ちます。
Gaucheはトップレベルのフォームを順番にコンパイル・評価するので、
`define-reader-ctor'で指定されたTAGは、その指定の直後から 使えます。
しかし、`define-reader-ctor'の呼び出しとTAGの使用が
`begin'フォームで囲まれている場合は、`begin'フォーム全体は
評価される前に一度にコンパイルされるため、うまく動作しません。

   他の実装では、`define-reader-ctor'の呼び出しが効力を持つようにする
前にファイル全体を読み込むことを要求するかも知れません。
その場合は、`define-reader-ctor'と定義されたTAGの使用を
同じファイルに置く事は実質的に不可能です。
可能ならば、`define-reader-ctor'の呼び出しと、TAGの使用は
異なるファイルに分離されることが望まれます。

   現在の`define-reader-ctor'に関するもう1つの問題は、それが
Gaucheシステムのグローバルテーブルを変更してしまうことで、それゆえに
モジュール性が良くありません。
複数人によって書かれたコードは同じタグを使っているかも知れず、
期待されない結果を引き起こすかも知れません。
作者にはまだ明確なアイデアがありませんが、将来のバージョンでは、
GaucheにはTAGのスコープをカプセル化する方法が導入されるかも しれません。


File: gauche-refj.info,  Node: 入力ユーティリティ手続き,  Prev: 読み込み時コンストラクタ,  Up: 入力

6.18.7.3 入力ユーティリティ手続き
.................................

 -- Function: port->string port
 -- Function: port->list reader port
 -- Function: port->string-list port
 -- Function: port->sexp-list port
     便利な入力手続きです。APIはScshとSTkから取りました。

     `port->string'はPORTをEOFまで読み込み、
     読んだものを文字列として返します。

     `port->list'は手続きREADERをPORTに繰り返し適用し、
     結果をリストに蓄積します。READERがEOFを返したら
     蓄積されたリストを返します。

     `(port->string-list port)' == `(port->list read-line port)'
     であり、 `(port->sexp-list port)' == `(port->list read port)'
     です。

 -- Function: port-fold fn knil reader
 -- Function: port-fold-right fn knil reader
 -- Function: port-for-each fn reader
 -- Function: port-map fn reader
     READERによって読まれる入力に対する便利な繰り返し手続きです。
     基本的に、READERが引数無しでEOFを返すまで繰り返し呼ばれ、
     それが返した値に対してFNが呼ばれます。
     READERはいずれEOFを返す手続きなら、入力ポートと関係している必要はありません。

     READERが要素 {X0, X1, ..., Xn} を返したとすると、 `port-fold'
     は次の値を返します。
          (fn Xn (fn Xn-1 ... (fn X0 knil)))
     一方、PORT-FOLD-RIGHTは次の値を返します。
          (fn X0 (fn X1 ... (fn Xn knil)))
     すなわち、`(port-fold cons '() read)'は全ての入力の逆リストを
     返し、`(port-fold-right cons '() read)'は `(port->list read
     port)'と同じものを返します。

     `port-for-each'と`port-map'はFNを読まれた要素に
     次々と適用します。前者は`fn'の結果を捨てますが、後者は`fn'の
     結果をリストにして返します。


File: gauche-refj.info,  Node: 出力,  Prev: 入力,  Up: 入出力

6.18.8 出力
-----------

以下の手続きで、省略可能な引数PORTは出力ポートでなければなりません。
省略された場合が現在の出力ポートが使われます。

 -- Function: write obj &optional port
 -- Function: display obj &optional port
     [R5RS]
     オブジェクトOBJの表示可能な表現を生成し、出力ポートに書き出します。
     `write'は可能な限り、OBJの標準的な外部表現を使い、
     生成された出力が`read'で再び読み込めるようにします。
     DISPLAYはより人間にとって可読性の高い出力を生成します。

     `write'や`display'が表示中にユーザ定義クラスのオブジェクトに
     出会った場合は、ジェネリックファンクション`write-object'を呼び出します。

     OBJが循環する構造を持っていた場合、これらの手続きは停止しないかも
     しれません。`write/ss'を参照して下さい。

 -- Function: write-with-shared-structure obj &optional port
 -- Function: write/ss obj &optional port
 -- Function: write* obj &optional port
     [SRFI-38]
     `write'と同じような出力を生成しますが、これらの手続きはさらに
     共有される部分構造や循環構造を認識し、`#n=', `#n#'構文を使って
     それらを表現します。

          (write/ss
            (let ((x (list 'a)))
              (list x x)))
           => ;; writes (#0=(a) #0#)

          (write/ss
            (let ((x (list 'a)))
              (set-cdr! x x)
              x))
           => ;; writes #0=(a . #0#)

     `read'手続きもこの構文を認識するので、読み込めば
     もとの構造と同型の構造が得られます。

     3つの手続きは等価です。
     Gaucheは、STklosから取った`write*'という名前を長く使ってきましたが、
     srfi-38によって`write-with-shared-structure'と`write/ss'が
     定義されました。今後は後者の名前を使った方がポータブルでしょう。

     註: ユーザ定義の`write-object'メソッドはこれらの手続きに対して
     透過的に動作します。

 -- Function: print expr ...
     EXPR ... を`display'を使って現在の出力ポートに表示し、
     最後に改行を書き出します。

 -- Method: write-object (obj <object>) port
     このメソッドをつかって，オブジェクトをどのように印字するかをカスタマイズ
     できます．

 -- Function: newline &optional port
     [R5RS] PORTに改行文字を書き出します。

 -- Function: flush &optional port
 -- Function: flush-all-ports
     それぞれ、PORT、および全てのポートにバッファされているデータを
     全て書き出します。

     手続き"flush"はScheme実装によって様々な名前で呼ばれています：
     `force-output' (Scsh, SCM)、 `flush-output'
     (Gambit)、`flush-output-port' (Bigloo) 等。
     `flush'の名前はSTkとSTklosから取りました。

 -- Function: write-char char &optional port
     [R5RS] 文字CHARをポートに出力します。

 -- Function: write-byte byte &optional port
     出力ポートに1バイトのデータBYTEを書き出します。
     BYTEは0から255の間の正確な整数でなければなりません。

 -- Function: format port string arg ...
 -- Function: format string arg ...
     [SRFI-28+] STRING の指示に従い、ARG ...をフォーマットします。
     この手続きはCommonLispの`format'のサブセットに、Gauche独自の拡張を
     加えたものです。また、これはSRFI-28 "Basic format strings"
     のスーパーセットに なっています (*Note [SRFI-28]: srfi-28.)。

     PORTは出力先を指定します。それが出力ポートであれば、フォーマットされた
     結果はそのポートに書き出されます。PORTが`#t'であれば、結果は
     現在の出力ポートに書き出されます。PORTが`#f'であれば、結果は
     文字列として`format'から返されます。
     PORTは省略することもできます。その場合は、`port'に`#f'
     を指定したのと同じ動作をします(SRFI-28の`format')。

     STRINGはフォーマット指示子を含んだ文字列です。
     フォーマット指示子はチルダ``~''から始まり、特定の文字で終了する文字の並びで、
     それぞれのフォーマット指示子が対応するARGを取りフォーマットします。
     STRING内のフォーマット指示子以外の文字列はそのまま出力されます。

          (format #f "the answer is ~s" 42)
            => "the answer is 42"

     フォーマット指示子は一つ以上のコンマで区切られたパラメータを取ることもできます。
     パラメータは整数か文字です。文字の場合、クオート文字に続けてその文字を置きます。
     パラメータが省略された場合は既定値が使われます。パラメータの意味はフォーマット指示子毎に
     異なります。

     さらに、フォーマット指示子は2種類のフラグ、``@'' と ``:'' を
     取ることができます。これらの組合せでフォーマットの動作が変わります。フラグは
     (もしあれば)パラメータの後、指示子の文字の直前に置かれなければなりません。

     パラメータの位置に文字 ``v'' か ``V'' を置くこともできます。
     その場合、パラメータの値が引数リストから取られます。対応する引数は整数か
     文字、または`#f'でなければなりません。`#f'の場合はそのパラメータが
     省略されたのと同じになります。

     いくつかの例です。

    `~10,2s'
          パラメータ10と2を伴う、フォーマット指示子`~s'。

    `~12,,,'*A'
          第1パラメータに数値12、第4パラメータに文字``*''を取るフォーマット指示子`~a'。
          第2と第3のパラメータは省略されています。

    `~10@d'
          フォーマット指示子`~d'。パラメータ10と``@''フラグがついています。

    `~v,vx'
          フォーマット指示子`~x'。第1パラメータと第2パラメータは引数リストから取られます。

     以下にサポートされているフォーマット指示子を示します。フォーマット指示子の文字自体は
     大文字であっても小文字であっても構いません。特に断りのない限り両者は同じ動作をします。

    ~MINCOL,COLINC,MINPAD,PADCHAR,MAXCOLA
          ASCII出力。対応する引数が`display'を使ってフォーマットされます。
          整数がMINCOLに与えられた場合、それは出力される最小の文字数を指定します。
          引数のフォーマット結果がMINCOLより短ければ、空白が右に追加されます(つまり、
          左詰めになります)。

          COLINC、MINPAD、そしてPADCHARは更に細かいパディング方法を
          指定します。PADCHARに文字が与えられた場合、それが空白文字の代わりにパディング文字と
          して使われます。MINPADに0以上の整数が与えられた場合、少なくともその数だけの
          パディング文字が追加されます。COLINCが指定された場合、
          追加されるパディング文字の数がCOLINCの倍数に調整されます。

          アトマーク ``@''
          フラグが与えられた場合、結果は右詰めになります。

          MAXCOLパラメータは与えられていれば書かれる文字数の上限を指定します。
          フォーマット後の文字列の長さがMAXCOLを超えた場合、MAXCOL文字だけが
          書かれます。コロン ``:'' フラグが同時に与えられていれば、
          MAXCOL - 4 文字が書かれた後、文字列"` ...'"が書かれます。

               (format #f "|~a|" "oops")
                 => "|oops|"
               (format #f "|~10a|" "oops")
                 => "|oops      |"
               (format #f "|~10@a|" "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式出力。対応する引数が`write'を使ってフォーマットされます。
          パラメータの意味は`~A'指示子と同じです。

               (format #f "|~s|" "oops")
                 => "|\"oops\"|"
               (format #f "|~10s|" "oops")
                 => "|\"oops\"    |"
               (format #f "|~10@s|" "oops")
                 => "|    \"oops\"|"
               (format #f "|~10,,,'*@s|" "oops")
                 => "|****\"oops\"|"
               (format #f "|~10,,,'★s|" "oops")
                 => "|\"oops\"★★★★|"

    ~MINCOL,PADCHAR,COMMACHAR,INTERVALD
          10進出力。対応する引数が10進数表記でフォーマットされます。もし引数が数値でなければ、
          全てのパラメータは(``v''パラメータの処理後に)無視され、
          引数は`~A'でフォーマットされます。

          もしMINCOLに整数が与えられたら、それが最小の文字数を指定します。
          結果の文字数がそれより少なければ、文字PADCHARが左に追加されます(右詰めになります)。
          PADCHARが省略された場合は空白文字が使われます。

               (format #f "|~d|" 12345)
                 => "|12345|"
               (format #f "|~10d|" 12345)
                 => "|     12345|"
               (format #f "|~10,'0d|" 12345)
                 => "|0000012345|"

          アトマーク ``@'' フラグが与えられた場合、正の引数に対して
          ``+'' が 先頭につけられます。

          コロンフラグ ``:''
          が与えられた場合、結果の文字はINTERVAL文字毎に
          まとめられ、間に文字COMMACHARが挿入されます。デフォルトでは3文字毎にコンマが
          挿入されます。

               (format #f "|~:d|" 12345)
                 => "|12,345|"
               (format #f "|~,,'_,4:d|" -12345678)
                 => "|-1234_5678|"

    ~MINCOL,PADCHAR,COMMACHAR,INTERVALB
          2進出力。対応する引数が2進数の整数としてフォーマットされます。
          パラメータの意味は`~D'と同じです。

    ~MINCOL,PADCHAR,COMMACHAR,INTERVALO
          8進出力。対応する引数が8進数の整数としてフォーマットされます。
          パラメータの意味は`~D'と同じです。

    ~MINCOL,PADCHAR,COMMACHAR,INTERVALX

    ~MINCOL,PADCHAR,COMMACHAR,INTERVALx
          16進出力。対応する引数が16進数の整数としてフォーマットされます。
          フォーマット指示文字に ``X'' が与えられた場合は ``ABCDEF''
          が桁文字として 使われ、 ``x'' が与えられた場合は ``abcdef''
          が桁文字として使われます。 パラメータの意味は`~D'と同じです。

               (format #f "~8,'0x" 259847592)
                 => "0f7cf5a8"
               (format #f "~8,'0X" 259847592)
                 => "0F7CF5A8"

    ~COUNT*
          引数のカウンタをCOUNTだけ後方にずらします。つまり、COUNT個の引数が
          無視されることになります。COUNTのデフォルト値は1です。
          コロンフラグが与えられた場合は引数カウンタを前方に動かします。
          例えば`~:*'は次のディレクティブが直前に使った引数を再び使うようにします。
          アトマークフラグが与えられた場合は、COUNTが引数の絶対位置を示します。
          0が最初の引数です。



File: gauche-refj.info,  Node: プログラムのロード,  Next: 比較とソート,  Prev: 入出力,  Up: 組み込みライブラリ

6.19 プログラムのロード
=======================

* Menu:

* Schemeファイルのロード::
* ダイナミックライブラリのロード::
* requireとprovide::
* Autoload::
* ライブラリの操作::


File: gauche-refj.info,  Node: Schemeファイルのロード,  Next: ダイナミックライブラリのロード,  Prev: プログラムのロード,  Up: プログラムのロード

6.19.1 Schemeファイルのロード
-----------------------------

 -- Function: load file &keyword paths (error-if-not-found #t)
          environment ignore-coding
     [R5RS+]
     FILEをロードします。すなわち、FILEに書かれたScheme式を順次読み込んで
     評価します。FILEの拡張子 ("`.scm'") は省略できます。

     FILEが "/", "./" または "../" で始まっていない場合は、
     システムファイルサーチパス (変数`*load-path*' に格納されています)
     の中から該当ファイルが探されます。あるいは、キーワード引数PATHSにディレクトリ名の
     リストを渡すことによりサーチパスを指定することもできます。

     ロードに成功した場合は`#t'が返されます。
     指定ファイルがみつからない場合はエラーとなりますが、もしキーワード引数
     `error-if-not-found'に`#f'が与えられていれば単に`load'から
     `#f'が返されます。

     デフォルトでは、`load'はコーディング認識ポート(*Note
     コーディング認識ポート::参照)を
     使ってソースファイルを読み込むので、ファイル先頭の"`coding:'"
     コメントによる 文字エンコーディング指定が有効になります。
     (codingコメントについては*Note マルチバイトスクリプト::を参照)。
     但し、キーワード引数IGNORE-CODINGに真の値が渡された場合、
     `load'はcoding-aware portを作成せず、直接ファイルポートから
     ソースを読み込みます。

     キーワード引数ENVIRONMENTにモジュールが渡された場合は、
     あたかもそのモジュールがファイルの先頭でselectされたかのように
     `load'されます。

     カレントモジュールは保存されます。つまり、FILE中で`select-module'によって
     カレントモジュールを変更しても、`load'が終わったら`load'を読んだ時点の
     モジュールに戻ります。

     ライブラリファイルをロードする場合は、``use'' (*Note
     モジュールの定義と選択::参照) を 使うか、下に説明する``require''
     を使う方が良いでしょう。 `load'と`require'の違いについては*Note
     コンパイル::を参照してください。

 -- Variable: *load-path*
     `load'と`require'がファイルを探すディレクトリのリストを保持しています。

     もしサーチパスにディレクトリを追加したい場合は、この変数を直接変更せずに、下に説明する
     `add-load-path'を用いて下さい。

 -- Special Form: add-load-path path &optional (afterp #f)
     パスPATHをライブラリロードパスのリストに加えます。
     AFTERPに真の値が与えられていればPATHは既存のリストの末尾に
     追加されます。そうでなければPATHは既存のリストの先頭に追加されます。

     ロードパスを変更したい場合、`*load-path*'を直接替えずにこのフォームを
     使って下さい。このフォームはコンパイル時に解釈されるのに対し、`*load-path*'を
     書き換えるコードは実行時に解釈されます。"`use'" や "`require'" は
     コンパイル時のロードパスを使うので、`*load-path*'への変更は反映されないかもしれません。

     更に、`add-load-path'はPATHの下にアーキテクチャ依存のディレクトリが
     ないかどうかを探し、あればそれを内部の共有ライブラリサーチパスに追加します。
     例えばあなたが自分のSchemeモジュールを`/home/yours/lib'に入れていて、
     それが共有ライブラリを必要としていたとします。手続き`gauche-architecture'
     (*Note 環境の問い合わせ::参照)が返す値をARCHとして、
     共有ライブラリを`/home/yours/lib/ARCH/'に置いておくと、
     共有ライブラリはそこからロードされます。この方法を取ると、複数のプラットフォーム用に
     別々にコンパイルされた共有ライブラリを管理することができます。

 -- Function: load-from-port port
     入力ポートPORTから、EOFを読むまで繰り返しScheme式を読み込み評価します。

     PORTにコーディング認識ポートを渡さない限り、"`coding:'"コメント
     による文字コード変換は行われないことに注意して下さい。

 -- Function: current-load-port
 -- Function: current-load-history
 -- Function: current-load-next
     これらの手続きによって、現在のロードのコンテクストを知ることができます。
     ロードされているファイルの中でこれらの手続きを呼ぶと、次のような値が返されます。
    `current-load-port'
          現在のファイルがロードされている入力ポート。

    `current-load-history'
          入力ポートと行番号のペアのリストで、ロードのネスティングを示したもの。
          例えばあなたが`foo.scm'をロードし、そのファイルの7行目で
          `bar.scm'がロードされ、そのファイルの18行目で`baz.scm'が
          ロードされたとします。`current-load-history'を`baz.scm'中で
          呼ぶと、それは次のような値を返します。
               ((#<port "foo.scm"> . 7) (#<port "bar.scm"> . 18))

    `current-load-next'
          現在のファイルがロードされた時点での、ファイルサーチパスの残りを返します。
          例えば `*load-path*' が `("." "../lib" "/home/gauche/lib"
          "/share/gauche/lib")'で、
          あなたが`foo.scm'をロードしたところ、それが`../lib/'中に見つかったと
          しましょう。このとき、`foo.scm'中で`current-load-next'を呼べば
               ("/home/gauche/lib" "/share/gauche/lib")
          が返されます。

     `load'されていない状態で呼ばれた時は、これらの手続きはそれぞれ`#f'、
     `()'、`()'を返します。


File: gauche-refj.info,  Node: ダイナミックライブラリのロード,  Next: requireとprovide,  Prev: Schemeファイルのロード,  Up: プログラムのロード

6.19.2 ダイナミックライブラリのロード
-------------------------------------

 -- Function: dynamic-load file &keyword init-function export-symbols
     ダイナミックローダブルライブラリ(共有ライブラリ)FILEをロードしてリンクします。
     FILEにはサフィックス(".so" 等) を含めないで下さい。システムによって
     サフィックスは異なるため、`dynamic-load'がそれを追加します。

     キーワード引数INIT-FUNCTIONは共有ライブラリ中の初期化関数の名前を
     指定します。デフォルトでは、サフィックスを除くファイル名が "foo"
     の場合、 初期化関数名は "Scm_Init_foo" となります。

     キーワード引数EXPORT-SYMBOLSは、ロードされるライブラリ中の外部シンボルを
     プロセスのシンボルテーブルに追加すべきかどうかを指定します。(註：ここでの「シンボル」
     とはCの関数名や変数名のことで、Schemeのシンボルのことではありません)。
     デフォルトでは共有ライブラリの外部シンボルはプロセスのシンボルテーブルに追加されず、
     それぞれの共有ライブラリは他の共有ライブラリのシンボルを見ることができません。
     EXPORT-SYMBOLSに真の値を渡すと、フラグ`RTLD_GLOBAL'が
     `dlopen()'に渡されて、その共有ライブラリ中のシンボルがこれからロードされる
     共有ライブラリからも見えるようになります。

     通常、共有ライブラリはSchemeモジュール中でロードされるので、モジュールユーザが
     直接この手続きを呼ぶ必要はほとんどないでしょう。

     一度ロードされた共有ライブラリをアンロードすることはできません。


File: gauche-refj.info,  Node: requireとprovide,  Next: Autoload,  Prev: ダイナミックライブラリのロード,  Up: プログラムのロード

6.19.3 requireとprovide
-----------------------

 -- Special Form: require feature
     FEATUREがまだロードされていなければロードします。FEATUREは文字列で
     なければなりません。それがそのまま(サフィックスを除く)ファイル名としてロードパスから
     探されます。`require'の解釈はコンパイル時に行われます。
     ロードされたファイルはその中でFEATUREをprovideしなければなりません。
     そうでないと警告が出されます。

     SLIBモジュールをロードすると、`require'が拡張されます。詳しくは*Note
     SLIBインタフェース::を 参照して下さい。

 -- Function: provide feature
     FEATUREをシステムのprovideされたフィーチャーリストに加えます。
     以降、FEATUREが`require'されてもファイルはふたたびロードされません。
     通常この手続きは、requireされるファイルの末尾で呼ばれます。ファイルの末尾で呼ぶのが良いのは、
     もしファイルのロード中にエラーが発生した場合、そのエラーを修正した上でふたたび`require'
     でロードできるからです。

 -- Function: provided? feature
     FEATUREが既にprovideされていれば`#t'を返します。


File: gauche-refj.info,  Node: Autoload,  Next: ライブラリの操作,  Prev: requireとprovide,  Up: プログラムのロード

6.19.4 Autoload
---------------

 -- Macro: autoload file/module item ...
     ITEM ... がオートロードされるように設定します。すなわち、
     次にITEMが参照された時、それが実際に評価される前にFILE/MODULEがロード
     されるようにします。これによって、必要とされる時までFILE/MODULEのロードを遅らせる
     ことができます。

     引数FILE/MODULEには、文字列かシンボルを指定できます。文字列の場合は
     そのファイルがロードされます。シンボルの場合、その名のモジュールが(`use'と
     同じルールで)ロードされ、ITEMがFILE/MODULEから
     オートロードを呼び出したモジュールへとインポートされます。
     (モジュールの`use'の詳細については*Note
     モジュールの定義と選択::を参照して下さい)。

     ITEMは変数名(シンボル)か、`(:macro SYMBOL)'というフォーム
     でなければなりません。変数名の場合は、その変数が評価されようとした時に
     指定のファイル／モジュールがロードされます。後者のフォームの場合は、
     `(SYMBOL arg ...)' というフォームがコンパイルされようとした
     時に指定のファイル／モジュールがロードされます。後者はマクロのオートロードになります。

     SYMBOLはFILE/MODULEの中で定義されなければなりません。
     そうでなければロード時にエラーが報告されます。

     手続きのオートロードの例を示します。
          (autoload "foo" foo0 foo1)
          (autoload "bar" bar0 bar1)

          (define (foobar x)
            (if (list? x)
                (map bar0 x)
                (foo0)))

          (foobar '(1 2)) ; この時点で "bar" がロードされる

          (foobar #f)     ; この時点で "foo" がロードされる

     マクロのオートロードを設定した場合、指定のファイルまたはモジュールは、
     そのマクロを使っているフォームが実行されるされないにかかわらず、
     コンパイラがそのフォームを見た時点でロードされることに注意してください。


File: gauche-refj.info,  Node: ライブラリの操作,  Prev: Autoload,  Up: プログラムのロード

6.19.5 ライブラリの操作
-----------------------

ある特定のライブラリおよび/あるいはモジュールがシステムにインストールされ
ているかどうかをチェックするための手続きがいくつかあります。

   以下の説明の中では、PATTERNはシンボルまたは文字列です。シンボル
である場合にはモジュール名(たとえば、`foo.bar')を指定します。
文字列である場合にはライブラリの部分パス(たとえば、`"foo/bar"')を
指定します。これはライブラリサーチパス以下で検索されます。

 -- Function: library-fold pattern proc seed &keyword paths strict?
          allow-duplicates?
     ライブラリ/モジュールファイルに対する基本イテレータ。この手続きは
     PATTERN にマッチする Scheme のプログラムファイルを検索します。
     検索は PATHS (デフォルトは標準のファイルロードパス、
     `*load-path*')にリストされたディレクトリ以下でおこなわれます。
     マッチしたファイル毎に、PROC が、そのマッチしたモジュール名あるいは
     ライブラリ名、そのプログラムファイルのフルパス、状態値、の3つの引数を
     ともなって呼びだされます。SEEDは、初期状態値として使われ、 PROC
     が返す値は次の PROC の呼出し時に状態値として使われます。 最後の
     PROC から返された値は `library-fold' の値として返ります。

     PATTERN がシンボルでかつ、キーワード引数 STRICT? が `#t'
     (デフォルト値)であれば、この手続きは
     あたえられたモジュール名のパターンにマッチするようにみえるファイル名に
     たいして `library-has-module?' を適用して、
     本当にそのモジュールを実装しているファイルを見付けます。
     大量のモジュールにマッチさせようとすると、時間がかる可能性があります。
     `#f' を STRICT? に渡すことで、余分なチェックを回避できます。
     PATTERN が文字列だった場合、照合はファイル名に対してのみ行われ、
     STRICT?は無視されます。

     デフォルトでは、PATH 中の PATTERN にマッチする同じ名前をもつ
     2つ以上のファイルがあるばあい、PATH に最初に出現したものだけが
     採用されます。そのライブラリに対して、`require' あるいは `use'
     を用いたをつかった場合に得られるのはこのファイルです。
     すべてのマッチしたファイルについて反復したければ、ALLOW-DUPLICATES?
     キーワード引数に `#t' を渡します。
          (library-fold 'srfi-1 acons '())
           => ((srfi-1 . "../lib/srfi-1.scm"))

          (library-fold "srfi-1" acons '())
           => (("srfi-1" . "../lib/srfi-1.scm"))

          ;; `acons' が呼ばれるのとは逆順のリストが
          ;; 返ることに注意してください
          (library-fold 'srfi-1 acons '() :allow-duplicates? #t)
           => ((srfi-1 . "/usr/share/gauche/0.7.1/lib/srfi-1.scm")
             (srfi-1 . "../lib/srfi-1.scm"))

          ;; 以下の場合は、モジュール名ではマッチしませんが、
          ;; ファイル名ではマッチします
          (library-fold 'srfi-19.* acons '())
           => ()

          (library-fold "srfi-19/*" acons '())
           => (("srfi-19/read-tai" . "../lib/srfi-19/read-tai.scm")
             ("srfi-19/format" . "../lib/srfi-19/format.scm"))

          ;; 利用可能な dbm の実装を見付けます
          (library-fold 'dbm.* acons '())
           => ((dbm.cdb . "/usr/share/gauche/0.7.4.2/lib/dbm/cdb.scm")
             (dbm.gdbm . "../lib/dbm/gdbm.scm")
             (dbm.ndbm . "../lib/dbm/ndbm.scm")
             (dbm.odbm . "../lib/dbm/odbm.scm"))

 -- Function: library-map pattern proc &keyword paths allow-duplicates?
          strict?
 -- Function: library-for-each pattern proc &keyword paths
          allow-duplicates? strict?
     マッチしたライブラリ/モジュール上のイテレータの `map'版および
     `for-each'版。照合操作とキーワード引数の詳細については上述の
     `library-fold'を参照してください。

     PROCは、マッチしたモジュール/ファイル名と、そのファイルの
     フルパスの 2 つの引数をうけとります。`library-for-each' は
     結果を捨てます。

          (library-map 'srfi-4 list :allow-duplicates? #t)
           => ((srfi-4 "../lib/srfi-4.scm")
                      (srfi-4 "/usr/share/gauche/0.7.1/lib/srfi-4.scm"))

          (library-map 'dbm.* (lambda (m p) m))
           => (dbm.odbm dbm.ndbm dbm.gdbm dbm.cdb)

 -- Function: library-exists? mod/path &keyword paths force-search?
          strict?
     MOD/PATH で指定されたライブラリあるいはモジュールを検索し、
     もしあれば、真値を返します。キーワード引数 PATHS および STRICT? は
     `library-fold' のそれと同じ意味です。

     上述のイテレータ手続きとはちがい、この手続きは呼び出しの過程で
     最初に既にロードされているライブラリおよびモジュールをチェックします。
     もしそのときに MOD/PATH を見つけたら、真値を返し、ファイル
     システムを見にいくことはありません。キーワード引数 FORCE-SEARCH?
     に `#t' を渡せば、すでにロードされいるライブラリおよびモジュール
     のチェックはスキップされます。

 -- Function: library-has-module? path module
     PATH で指定したファイルが存在し、かつ、`module' で名指しされた
     モジュールが実装されている場合でその場合に限り、`#t' を返します。
     PATH は実際のファイル名でなければなりません。

          (library-has-module? "./test/foo/bar.scm" 'foo.bar)
           => #t ;; if ./test/foo/bar.scm implements module foo.bar.

     この手続きは典型的なソースコードの配置を仮定して、与えられたファイルが
     そのモジュールを実装しているかどうかを決定します。すなわち、
     まずそのコードのフォームを読み、与えられたモジュールを定義している
     `define-module' フォームかどうかを見ます。


File: gauche-refj.info,  Node: 比較とソート,  Next: システムインタフェース,  Prev: プログラムのロード,  Up: 組み込みライブラリ

6.20 比較とソート
=================

 -- Function: compare obj1 obj2

 -- Generic Function: object-compare obj1 obj2

 -- Function: sort seq &optional cmpfn
 -- Function: sort! seq &optional cmpfn
     シーケンスSEQ(リストかベクタ)の要素を昇順にソートし、
     ソートされたシーケンスを返します。
     `sort!'は、オリジナルのシーケンスを破壊的に再利用します。
     ソート順は`cmpfn'で指定されます。`cmpfn'はSEQのふたつの要素を
     引数に取り、最初の要素が厳密に2番目の要素より先行するものの場合は
     `#t'を返す手続きです。

          (sort '(("Chopin" "Frederic")
                  ("Liszt" "Franz")
                  ("Alkan" "Charles-Valentin"))
                (lambda (x y) (string<? (car x) (car y))))
            => (("Alkan" "Charles-Valentin")
                       ("Chopin" "Frederic")
                       ("Liszt" "Franz"))

     いくつかのビルトインオブジェクトは自然な比較順を持っており、
     CMPFNが省略された場合にはそれが使われます。

     現在の実装では、CMPFNが省略された場合は
     クィックソートとヒープソートを使い、
     CMPFNが与えられた場合はマージソートを使っています。
     これは将来変更されるかもしれません。

 -- Function: stable-sort seq cmpfn
 -- Function: stable-sort! seq cmpfn
     安定ソートアルゴリズム(現時点ではマージソート)を使って、並び SEQ
     (リストまたはベクタ)をソートします。ソート順は `cmpfn'
     で指定します。 `cmpfn' は LIST
     のふたつの要素を引数として取る関数で、
     厳密に、最初の引数が第二の引数の前にくるものである場合に `#t'
     を返します。`sort'/`sort!' と違い、CMPFN を省略することは
     できません。


File: gauche-refj.info,  Node: システムインタフェース,  Next: 開発補助API,  Prev: 比較とソート,  Up: 組み込みライブラリ

6.21 システムインタフェース
===========================

GaucheはPOSIX.1の多くの関数と、さまざまなUnixで共通して使われているシステム関数へのインタフェースを
組込み手続きとして提供しています。

   多くのScheme実装はいろいろな形で何らかのシステムインタフェースを提供
しています。名前だけが違うもの(例：`delete-file'、`remove-file'
、`unlink') もあれば、新しいSchemeオブジェクトを導入して
抽象化を行っているものもあります。Gaucheでは、既存のAPIのどれかを
そのまま真似るのではなく、2つのレイヤを提供することにしました。
この章で述べられる低レベルレイヤは、OSのインタフェースに似せたものを実装します。
その上に、既存のシステムと互換性のある高レベルのインタフェースが実装されます。

   `sys-'NAMEという名前を持つ手続きは、多くの場合、
システムコールNAMEに対応しています。
可能な限り、インタフェースが似るようにしました。

   なお、Gaucheはシステムコールがシグナルによって割り込まれた場合、
システムコールをリスタートします。詳しくは*Note
シグナル::を参照して下さい。

   Cによるシステムプログラミングに慣れている方は、 *Note
CとSchemeの関数の対応::も参考にして下さい。
Cの標準ライブラリとGaucheの手続きとの対応が示してあります。

* Menu:

* プログラムの終了::
* 環境の問い合わせ::
* ファイルシステム::
* Unixのグループとユーザ::
* ロケール::
* シグナル::
* システムへの問い合わせ::
* 時間::
* Unixのプロセス管理::
* I/Oの多重化::
* その他のシステムコール::


File: gauche-refj.info,  Node: プログラムの終了,  Next: 環境の問い合わせ,  Prev: システムインタフェース,  Up: システムインタフェース

6.21.1 プログラムの終了
-----------------------

 -- Function: exit &optional (code 0)
     [POSIX] 現在のプロセスを終了し、CODEを終了コードにします。
     CODEはゼロもしくは正の正確な整数でなければなりません。
     この手続きはまずアクティブなダイナミックハンドラのAFTER手続きを全て呼び出し
     (*Note 継続::)、続いてオープンされている出力ポートのバッファを
     フラッシュし、最後に`exit(2)'を呼び出します。

 -- Function: sys-exit &optional (code 0)
     [POSIX] 現在のプロセスを終了し、CODEを終了コードにします。
     CODEはゼロもしくは正の正確な整数でなければなりません。
     この手続きは`_exit(2)'を直接コールします。
     クリーンアップは一切行われません。
     フラッシュされてないファイルバッファの内容は捨てられます。

 -- Function: sys-abort
     [POSIX]
     POSIXのabort()を呼びます。通常、現在のプロセスは終了され、コアダンプされます。
     クリーンアップは一切行われません。


File: gauche-refj.info,  Node: 環境の問い合わせ,  Next: ファイルシステム,  Prev: プログラムの終了,  Up: システムインタフェース

6.21.2 環境の問い合わせ
-----------------------

 -- Function: sys-getenv name
     [POSIX]
     環境変数NAMEの値を文字列で返します。もしNAMEが定義されていなければ、
     `#f'が返ります。

 -- Function: sys-putenv name value
     プロセスの環境変数NAMEに値VALUEをセットします。システムが
     putenv(3)をサポートしていない場合はエラーが通知されます。

 -- Function: gauche-version
 -- Function: gauche-architecture
 -- Function: gauche-library-directory
 -- Function: gauche-architecture-directory
 -- Function: gauche-site-library-directory
 -- Function: gauche-site-architecture-directory
     これらの手続きはGaucheインタプリタの情報を文字列で返します。


File: gauche-refj.info,  Node: ファイルシステム,  Next: Unixのグループとユーザ,  Prev: 環境の問い合わせ,  Up: システムインタフェース

6.21.3 ファイルシステム
-----------------------

ファイルシステムに関するシステムコール群です。
ここで述べる手続きの上に、より高レベルなAPIがモジュール`file.util'として
実装されています。*Note
ファイルシステムユーティリティ::を参照して下さい。

* Menu:

* ディレクトリ::
* ディレクトリ操作::
* パス名::
* ファイルの状態::
* 他のファイル操作::


File: gauche-refj.info,  Node: ディレクトリ,  Next: ディレクトリ操作,  Prev: ファイルシステム,  Up: ファイルシステム

6.21.3.1 ディレクトリ
.....................

高レベルAPIに関しては*Note
ディレクトリユーティリティ::も参照して下さい。

 -- Function: sys-readdir path
     PATHは存在するディレクトリを示すパス名でなければなりません。
     この手続きはディレクトリの全エントリを文字列のリストとして返します。
     リストはソートされません。PATHが存在しなかったり、ディレクトリでなかった場合は
     エラーとなります。

 -- Function: sys-glob pattern
     glob(3)関数へのインタフェースです。PATTERNはsh(1)で使われるパターンです:
     ``?''は任意の一文字にマッチし、``*''は0以上の任意の文字にマッチし、
     ``[abc]''は文字``a'', ``b'', ``c'' のいずれにも
     マッチします。マッチするパス名が無ければ空のリストが返されます。

     glob()をサポートしていないシステムでは、エラーが通知されます。

     註：glob()の実装にセキュリティ上の問題のあるシステムがあることが知られています。
     Gaucheではいずれ、自前のglob()実装を持つ予定です。

   パスがディレクトリかどうかチェックする方法は、*Note
ファイルの状態::を参照してください。


File: gauche-refj.info,  Node: ディレクトリ操作,  Next: パス名,  Prev: ディレクトリ,  Up: ファイルシステム

6.21.3.2 ディレクトリ操作
.........................

 -- Function: sys-remove filenmae
     [POSIX] FILENAMEがファイルであればそれを消去します。
     システムによってはFILENAMEが空のディレクトリであっても動作しますが、
     移植性を気にする場合はその動作に依存しない方が良いでしょう。

 -- Function: sys-rename old new
     [POSIX] ファイルOLDをNEWにリネームします。新しい名前は
     古い名前と異なるディレクトリにあってもかまいませんが、両者は同じデバイス上に
     なければなりません。

 -- Function: sys-tmpnam
     [POSIX]
     ユニークなファイル名を作成して返します。この関数はPOSIXに含まれていますが、
     セキュリティ上の問題が指摘されており、使わない方が良いとされています。
     可能なら下にあげる`sys-mkstemp'を使って下さい。

 -- Function: sys-mkstemp template
     ユニークな名前を持つファイルを作成してオープンし、オープンされたポートとファイル名の
     二つの値を返します。ファイルは排他的に作成されるため、レースコンディションは起こりません。
     TMPNAMEはファイル名のプレフィックスに使われます。Unixのmkstempと違って、
     パディングキャラクタをつける必要はありません。ファイルは書き込み用としてオープンされ、
     パーミッションは600にセットされます。

 -- Function: sys-link existing new
     [POSIX]
     既存のファイルEXISTINGに対し、NEWという名のハードリンクを作成します。

 -- Function: sys-unlink pathname
     [POSIX] PATHNAMEで示されるファイルを消去します。
     PATHNAMEはディレクトリであってはなりません。
     もし消去に成功したら`#t'が、PATHNAMEが存在しなければ`#f'が返されます。
     他の場合はエラーが通知されます。

 -- Function: sys-symlink existing new
     EXISTINGを指すNEWという名のシンボリックを作成します。
     シンボリックリンクをサポートしないシステムでは、この手続きは定義されません。

 -- Function: sys-readlink path
     PATHで示されるファイルがシンボリックリンクならば、それが指すパスを返します。
     もしPATHが存在しなかったり、シンボリックリンクでなければ、エラーが通知されます。
     シンボリックリンクをサポートしないシステムでは、この手続きは定義されません。

 -- Function: sys-mkdir pathname mode
     [POSIX] ディレクトリPATHNAMEをモードMODEで作成します。
     (MODEはさらにumaskでマスクされることに注意して下さい；下の`sys-umask'
     参照)。
     PATHNAMEの親ディレクトリは存在して、プロセスが書き込めるようになっていなければ
     なりません。中間のディレクトリも一度に作成するには、
     `file.util'の`make-directory*'が使えます (*Note
     ディレクトリユーティリティ::)。

 -- Function: sys-rmdir pathname
     [POSIX]
     ディレクトリPATHNAMEを消去します。ディレクトリは空でなければなりません。
     ディレクトリの内容も一緒に消去するには、`file.util'の`remove-directory*'
     が使えます(*Note ディレクトリユーティリティ::)。

 -- Function: sys-umask mode
     [POSIX] umaskをMODEにセットします。変更される前のumaskを返します。
     umaskについては`man umask'を参照してください。


File: gauche-refj.info,  Node: パス名,  Next: ファイルの状態,  Prev: ディレクトリ操作,  Up: ファイルシステム

6.21.3.3 パス名
...............

高レベルのAPIに関しては*Note
パスネームユーティリティ::も参照して下さい。

 -- Function: sys-normalize-pathname pathname &keyword absolute expand
          canonicalize
     与えられたキーワード引数によってPATHNAMEを以下のように変換します。
     キーワード引数は同時に複数指定できます。
    `absolute'
          このキーワード引数に真の値が与えられて、PATHNAMEが絶対パスでない場合、
          PATHNAMEの前にプロセスのワーキングディレクトリを足して絶対パスにします。

    `expand'
          このキーワード引数に真の値が与えられて、PATHNAMEが``~''
          で始まっていた   場合、以下のように展開されます。
             *
               PATHNAMEが"`~'"のみであるか、または"`~/'"で始まっている
               場合、文字"`~'"が現在のプロセスのユーザのホームディレクトリに置き換えられます。

             *
               上記以外の場合、``~''以降、``/''かPATHNAMEの終端までの文字列
               がユーザ名とみなされ、そのユーザのホームディレクトリに置換されます。もし該当するユーザが
                  いなければエラーとなります。

    `canonicalize'
          パス名から "`.'" や "`..'" を除き、単純化します。
          この操作は実際のファイルシステムを参照せずに行われます。元のパス名がディレクトリへの
          シンボリックリンクを含んでいた場合、単純化されたパス名は正しくないかもしれません。

 -- Function: sys-basename pathname
 -- Function: sys-dirname pathname
     `sys-basename'は与えられたパスのベース名、すなわち最後のコンポーネントを返します。
     `sys-dirname'は与えられたパスのディレクトリ名、すなわち最後のコンポーネント以外の
     コンポーネントを返します。PATHNAMEの末尾が``/''である場合、その文字は
     無視されます。
          (sys-basename "foo/bar/bar.z") => "bar.z"
          (sys-basename "coo.scm") => "coo.scm"
          (sys-basename "x/y/") => "y"
          (sys-dirname "foo/bar/bar.z") => "foo/bar"
          (sys-dirname "coo.scm") => "."
          (sys-dirname "x/y/") => "x"
     この手続きはPATHNAMEが存在するかどうかはチェックしません。

     特殊なケース：
          (sys-basename "") => ""
          (sys-dirname "") => "."

          (sys-basename "/") => ""
          (sys-dirname "/") => "/"
     註：このふるまいはPerlの`basename'および`dirname'と同様です。
     システムによっては、コマンドの`basename'は`"/"'に対して`"/"'を、
     `"."'に対して`"."'を返すものがあります。

 -- Function: sys-realpath pathname
     `sys-realpath'は"`.'", "`..'"およびシンボリックリン
     クを含まないPATHNAMEの絶対パスを返します。システムがrealpath(3)
     をサポートしていない場合はエラーが通知されます。


File: gauche-refj.info,  Node: ファイルの状態,  Next: 他のファイル操作,  Prev: パス名,  Up: ファイルシステム

6.21.3.4 ファイルの状態
.......................

高レベルのAPIに関しては*Note
ファイル属性ユーティリティ::も参照して下さい。

 -- Function: file-exists? path
 -- Function: file-is-regular? path
 -- Function: file-is-directory? path
     それぞれ、PATHが存在するか、存在してそれがレギュラーファイルであるか、
     存在してそれがディレクトリであれば`#t'を返します。

     これらの手続きは便利であり、STkとの互換性もあるので定義されていますが、
     実体は下に説明されている低レベル手続きの上に作成されています。

 -- Builtin Class: <sys-stat>
     ファイルシステム内のエントリの属性を表す、`struct stat'のラッパー
     オブジェクトです。以下に示す読みだし専用のスロットを持ちます。

      -- Instance Variable of <sys-stat>: type
          ファイルのタイプを示すシンボルです。
          `regular'         a regular file
          `directory'       a directory
          `character'       a character device
          `block'           a block device
          `fifo'            a fifo
          `symlink'         a symbolic link
          `socket'          a socket
          以上のどれにも当てはまらない場合は`#f'が返されます。

          注：いくつかのオペレーティングシステムでは`socket'ファイルタイプを
          `fifo'と区別せず、どちらに対しても`fifo'を返します。
          ポータブルなプログラムを書くときは注意して下さい。

      -- Instance Variable of <sys-stat>: perm
          パーミッションビットマスク。"mode"スロットの下位9ビットと同じですが、
          便利なので独立したスロットとして提供されます。

      -- Instance Variable of <sys-stat>: mode
      -- Instance Variable of <sys-stat>: ino
      -- Instance Variable of <sys-stat>: dev
      -- Instance Variable of <sys-stat>: rdev
      -- Instance Variable of <sys-stat>: nlink
      -- Instance Variable of <sys-stat>: uid
      -- Instance Variable of <sys-stat>: gid
      -- Instance Variable of <sys-stat>: size
          `struct stat'の該当するフィールドの値。正確な整数です。

      -- Instance Variable of <sys-stat>: atime
      -- Instance Variable of <sys-stat>: mtime
      -- Instance Variable of <sys-stat>: ctime
          `struct stat'の該当するフィールドの値を、Unix
          Epochからの秒数で。

 -- Function: sys-stat path
 -- Function: sys-fstat port-or-fd
     [POSIX] 与えられたパス名PATH、またはポートかファイルディスクリプタ
     PORT-OR-FDで示されるファイルの情報を`<sys-stat>'オブジェクトで
     返します。

     `sys-stat'は、PATHがシンボリックリンクであった場合は
     リンクの指す先のファイルに関する情報を返します。

     `sys-fstat'は、PORT-OR-FDがファイルに関係ないポートであった
     場合は`#f'を返します。

 -- Function: sys-lstat path
     `sys-stat'と同じですが、PATHがシンボリックリンクであった
     場合はリンクそのものの情報を返します。

     gosh> (describe (sys-stat "gauche.h"))
     #<<sys-stat> 0x815af70> is an instance of class <sys-stat>
     slots:
       type      : regular
       perm      : 420
       mode      : 33188
       ino       : 845140
       dev       : 774
       rdev      : 0
       nlink     : 1
       uid       : 400
       gid       : 100
       size      : 79549
       atime     : 1020155914
       mtime     : 1020152005
       ctime     : 1020152005

 -- Function: sys-stat->mode stat
 -- Function: sys-stat->ino stat
 -- Function: sys-stat->dev stat
 -- Function: sys-stat->rdev stat
 -- Function: sys-stat->nlink stat
 -- Function: sys-stat->size stat
 -- Function: sys-stat->uid stat
 -- Function: sys-stat->gid stat
 -- Function: sys-stat->atime stat
 -- Function: sys-stat->mtime stat
 -- Function: sys-stat->ctime stat
 -- Function: sys-stat->file-type stat
     *Deprecated*.
     `<sys-stat>'オブジェクトの情報にアクセスするには`slot-ref'を
     使って下さい。

 -- Function: sys-access pathname amode
     [POSIX] PATHNAMEへのアクセスが
     MODEに示されるモードで許可されているかどうかを示す真偽値を返します。
     この手続きは、suid/sgidプログラムで使われるとエラーとなります(下記註参照)。
     MODEは以下に示す定数のコンビネーション(logical or)です。
    `R_OK'
          PATHNAMEをカレントユーザが読み出し可能かどうか

    `W_OK'
          PATHNAMEへカレントユーザが書き込み可能かどうか

    `X_OK'
          PATHNAMEをカレントユーザが実行可能かどうか(PATHNAMEが
          ディレクトリの場合はサーチ可能かどうか)

    `F_OK'
          PATHNAMEのパーミッションフラグにかかわらず、PATHNAMEが
          存在するかどうか
          (但しPATHNAMEがあるディレクトリの読みだし許可は必要)。

     _註:_ access(2)は、suid/sgidプログラム中で
     実ユーザの権限を確かめるために使われた場合、セキュリティホールと
     なります。

 -- Function: sys-chmod path mode
     ファイルPATHのパーミッションビットをMODEに変更します。
     MODEは小さな正の正確な整数で、POSIXスタイルのパーミッションビットマスク
     でなければなりません。

 -- Function: sys-chown path owner-id group-id
     ファイルPATHのオーナーとグループをOWNER-IDとGRUOP-ID
     で示されるものに変更します。OWNER-IDとGRUOP-IDは正確な整数で
     なければなりません。どちらかに-1が渡された場合は、対応する情報は変更されません。

 -- Function: sys-utime path &optional atime mtime
     ファイルのアクセスタイムと変更タイムをATIMEとMTIMEが示す
     値にセットします。ATIMEとMTIMEが省略された場合は現在の時刻が
     使われます。 *Note ファイル操作::の`touch-file'も参照して下さい。


File: gauche-refj.info,  Node: 他のファイル操作,  Prev: ファイルの状態,  Up: ファイルシステム

6.21.3.5 他のファイル操作
.........................

 -- Function: sys-chdir dir
     [POSIX] `chdir(2)'へのインタフェースです。
     `current-direoctry'(*Note
     ディレクトリユーティリティ::)も参照して下さい。

 -- Function: sys-pipe &keyword (buffering :line)
     [POSIX] パイプを作り、ポートを2つ返します。
     最初に返されるポートは入力ポートで、2番目に返されるポートは出力ポートです。
     出力ポートへ書き出したデータは、入力ポートから読み込めます。

     BUFFERINGは`:full'、`:line'、`:none'のいずれかで、
     パイプ上に開かれたポートのバッファリングモードを指定します。
     バッファリングモードの詳細については、*Note
     ファイルポート::を参照して下さい。
     通常のケースでは、デフォルトのモードで間に合うでしょう。

          (receive (in out) (sys-pipe)
            (display "abc\n" out)
            (flush out)
            (read-line in)) => "abc"

     注意: 戻り値はバージョン0.3.15から変更されています。それまでは、
     `sys-pipe'は2つのポートのリストを返します。

 -- Function: sys-mkfifo path mode
     [POSIX] 名前がPATHでモードがMODEのFIFO(名前付きパイプ)を
     作ります。MODEはファイルのモードを表す正の正確整数でなければ
     なりません。

 -- Function: sys-isatty port-or-fd
     [POSIX] PORT-OR-FDはポートか整数のファイルディスクリプタです。
     ポートがコンソールに接続されていれば`#t'を、そうでなければ`#f'を
     返します。

 -- Function: sys-ttyname port-or-fd
     [POSIX] PORT-OR-FDはポートか整数のファイルディスクリプタです。
     ポートに接続された端末の名前か、ポートが端末に接続されていなければ
     `#f'を返します。


File: gauche-refj.info,  Node: Unixのグループとユーザ,  Next: ロケール,  Prev: ファイルシステム,  Up: システムインタフェース

6.21.4 Unixのグループとユーザ
-----------------------------

Unix groups
...........

 -- Builtin Class: <sys-group>
     Unixのグループの情報です。以下のスロットを持ちます。

      -- Instance Variable of <sys-group>: name
          グループ名。

      -- Instance Variable of <sys-group>: gid
          グループID

      -- Instance Variable of <sys-group>: passwd
          グループパスワード。

      -- Instance Variable of <sys-group>: mem
          このグループに属するユーザ名のリスト。


 -- Function: sys-getgrgid gid
 -- Function: sys-getgrnam name
     [POSIX]
     グループIDGIDもしくはグループ名NAMEで示されるグループの情報を
     `<sys-group>'で返します。該当するグループが存在しない場合は
     `#f'が返されます。

 -- Function: sys-gid->group-name gid
 -- Function: sys-group-name->gid name
     グループIDとグループ名を相互変換する便利な手続きです。

Unix users
..........

 -- Builtin Class: <sys-passwd>
     Unixのユーザの情報です。以下のスロットを持ちます。

      -- Instance Variable of <sys-passwd>: name
          ユーザ名。

      -- Instance Variable of <sys-passwd>: uid
          ユーザID

      -- Instance Variable of <sys-passwd>: gid
          ユーザのプライマリグループID。

      -- Instance Variable of <sys-passwd>: passwd
          ユーザの(暗号化された)パスワード。システムがシャドウパスワードファイルを
          使っている場合は、 "x" のような無意味な文字列が入っています。

      -- Instance Variable of <sys-passwd>: gecos
          Gecosフィールド。

      -- Instance Variable of <sys-passwd>: dir
          ユーザのホームディレクトリ。

      -- Instance Variable of <sys-passwd>: shell
          ユーザのログインシェル。

      -- Instance Variable of <sys-passwd>: class
          ユーザのクラス。(特定のシステムでのみ有効)。


 -- Function: sys-getpwuid uid
 -- Function: sys-getpwnam name
     [POSIX] ユーザIDUIDもしくはユーザ名NAMEで示されるユーザの情報を
     `<sys-passwd>'で返します。該当するユーザが存在しない場合は
     `#f'が返されます。

 -- Function: sys-uid->user-name uid
 -- Function: sys-user-name->uid
     ユーザIDとユーザ名を相互変換する便利な手続きです。

Password encryption
...................

 -- Function: sys-crypt key salt
     これは、`crypt(3)'へのインターフェースです。KEYとSALTは
     文字列でなければならず、暗号化された文字列が返されます。
     `crypt(3)'が利用できないシステムでこの関数を呼ぶとエラーが通知されます。


File: gauche-refj.info,  Node: ロケール,  Next: シグナル,  Prev: Unixのグループとユーザ,  Up: システムインタフェース

6.21.5 ロケール
---------------

 -- Function: sys-setlocale category locale
     [POSIX] カテゴリーCATEGORYのロケールをLOCALEにセットします。
     CATEGORYは整数でなければなりません；以下の変数がCATEGORYの
     ために定義されています。LOCALEはロケールを表す文字列です。
     成功した場合は新しいロケール名を、ロケールが変更できなかった場合は`#f'を
     返します。

 -- Variable: LC_ALL
 -- Variable: LC_COLLATE
 -- Variable: LC_CTYPE
 -- Variable: LC_MONETARY
 -- Variable: LC_NUMERIC
 -- Variable: LC_TIME
     `sys-setlocale'のCATEGORYに渡せる数値を定義しています。

 -- Function: sys-localeconv
     [POSIX]
     現在のロケールで数値をフォーマットする際に必要な様々な情報をassoc
     listに して返します。

例を示します。あなたのシステム設定によっては異なる結果になるかもしれません。
     (sys-localeconv)
      =>
        ((decimal_point . ".") (thousands_sep . "")
         (grouping . "") (int_curr_symbol . "")
         (currency_symbol . "") (mon_decimal_point . "")
         (mon_thousands_sep . "") (mon_grouping . "")
         (positive_sign . "") (negative_sign . "")
         (int_frac_digits . 127) (frac_digits . 127)
         (p_cs_precedes . #t) (p_sep_by_space . #t)
         (n_cs_precedes . #t) (n_sep_by_space . #t)
         (p_sign_posn . 127) (n_sign_posn . 127))

     (sys-setlocale LC_ALL "fr_FR")
      => "fr_FR"

     (sys-localeconv)
      =>
       ((decimal_point . ",") (thousands_sep . "")
        (grouping . "") (int_curr_symbol . "FRF ")
        (currency_symbol . "F") (mon_decimal_point . ",")
        (mon_thousands_sep . " ") (mon_grouping . "\x03\x03")
        (positive_sign . "") (negative_sign . "-")
        (int_frac_digits . 2) (frac_digits . 2)
        (p_cs_precedes . #f) (p_sep_by_space . #t)
        (n_cs_precedes . #f) (n_sep_by_space . #t)
        (p_sign_posn . 1) (n_sign_posn . 1))


File: gauche-refj.info,  Node: シグナル,  Next: システムへの問い合わせ,  Prev: ロケール,  Up: システムインタフェース

6.21.6 シグナル
---------------

Gaucheでは、OSのシグナルを自分自身や他のプロセスに送ったり、
送られたシグナルを処理することができます。

   マルチスレッド環境では、全てのスレッドがシグナルハンドラを共有し、
各スレッドが独自のシグナルマスクを持ちます。 詳しくは*Note
シグナルとスレッド::を参照して下さい。

   システムコールがシグナルによって割り込まれ、
プログラマがシグナルハンドラをセットしており、そのハンドラが別コンテキストに
制御を移さずに戻った場合、そのシステムコールはハンドラからの復帰後に
リスタートされます。

* Menu:

* シグナルとシグナルセット::
* シグナルの送出::
* シグナルの処理::
* シグナルのマスクと待機::
* シグナルとスレッド::


File: gauche-refj.info,  Node: シグナルとシグナルセット,  Next: シグナルの送出,  Prev: シグナル,  Up: シグナル

6.21.6.1 シグナルとシグナルセット
.................................

シグナルはオペレーティングシステムで定義された小さな整数値で表現されます。
システムのシグナル番号に束縛された変数が定義されています。
システムのシグナル番号はアーキテクチャによって異なるので、
なるべく変数を利用するようにして下さい。

 -- Variable: SIGABRT
 -- Variable: SIGALRM
 -- Variable: SIGCHLD
 -- Variable: SIGCONT
 -- Variable: SIGFPE
 -- Variable: SIGHUP
 -- Variable: SIGILL
 -- Variable: SIGINT
 -- Variable: SIGKILL
 -- Variable: SIGPIPE
 -- Variable: SIGQUIT
 -- Variable: SIGSEGV
 -- Variable: SIGSTOP
 -- Variable: SIGTERM
 -- Variable: SIGTSTP
 -- Variable: SIGTTIN
 -- Variable: SIGTTOU
 -- Variable: SIGUSR1
 -- Variable: SIGUSR2
     これらの変数はPOSIXで定義された対応するシグナルの番号に束縛されています。

 -- Variable: SIGTRAP
 -- Variable: SIGIOT
 -- Variable: SIGBUS
 -- Variable: SIGSTKFLT
 -- Variable: SIGURG
 -- Variable: SIGXCPU
 -- Variable: SIGXFSZ
 -- Variable: SIGVTALRM
 -- Variable: SIGPROF
 -- Variable: SIGWINCH
 -- Variable: SIGPOLL
 -- Variable: SIGIO
 -- Variable: SIGPWR
     これらの変数はシステム依存のシグナル番号に束縛されています。
     全てのシステムで全てのシグナルがサポートされているわけではありません。

   それぞれのシグナル番号の他に、`<sys-sigset>'オブジェクトを使って
シグナルの集合を扱うことができます。シグナルの集合はシグナルマスクを操作したり、
ひとつのシグナルハンドラを多数のシグナルに同時に設定したりする際に使えます。

 -- Class: <sys-sigset>
     シグナルの集合を表します。空のシグナルの集合は次の式で作成できます：
          (make <sys-sigset>)

 -- Function: sys-sigset-add! sigset signal ...
 -- Function: sys-sigset-delete! sigset signal ...
     SIGSETは`<sys-sigset>'オブジェクトでなければなりません。
     これらの手続きはSIGSETに指定されたシグナルを追加、
     もしくはSIGSETから指定されたシグナルを削除します。
     変更されたSIGSETが返されます。

 -- Function: sys-sigset-fill! sigset
 -- Function: sys-sigset-empty! sigset
     システムで定義された全てのシグナルをSIGSETにセット、
     もしくはSIGSETを空にします。

 -- Function: sys-signal-name signal
     シグナルの名前を返します。


File: gauche-refj.info,  Node: シグナルの送出,  Next: シグナルの処理,  Prev: シグナルとシグナルセット,  Up: シグナル

6.21.6.2 シグナルの送出
.......................

シグナルを送るには、`sys-kill'を使うことができます。
これはシステムの`kill(2)'のように動作します。

 -- Function: sys-kill pid sig
     [POSIX] シグナルSIGを指定されたプロセス(群)に送ります。
     SIGは正確な正整数でなければなりません。PIDは正確な整数でなければ
     ならず、次のルールで対象となるプロセスを指定します。
        * PIDが正ならば、それがそのまま対象となるプロセスIDです。

        *
          PIDがゼロならば、シグナルは現在のプロセスのプロセスグループ内の全ての
          プロセスに送られます。

        *
          PIDが-1より小さければ、シグナルはプロセスグループIDが-PIDである
          全てのプロセスに送られます。

   POSIXのRAISE()に対応するScheme関数はありませんが、 `(sys-kill
(sys-getpid) SIG)' で同じことができます。


File: gauche-refj.info,  Node: シグナルの処理,  Next: シグナルのマスクと待機,  Prev: シグナルの送出,  Up: シグナル

6.21.6.3 シグナルの処理
.......................

Schemeでシグナルを処理する手続きを登録できます。
(マルチスレッド環境では、シグナルハンドラの設定は全てのスレッドで共有されます。
*Note シグナルとスレッド::を参照して下さい)。

シグナルがSchemeプロセスに送られると、それはVM中のキューに入れられます。
VMは「安全なポイント」に達した時にキューを検査し、シグナルが届いていれば
それを順に処理します。
(このメカニズムのため、`SIGILL'のようなシグナルはSchemeレベルでは
処理できません。そのシグナルをキューに入れた後でプロセスが意味のある処理を続行できない
からです)。

   `gosh'インタプリタを使っている場合、デフォルトでのシグナルの処理は
次のように設定されています。

`SIGABRT, SIGILL, SIGKILL, SIGCONT, SIGSTOP, SIGSEGV, SIGBUS'
     Schemeでは処理できません。`gosh'ではこれらのシグナルを受けると
     システムのデフォルトの動作をします。

`SIGCHLD, SIGTSTP, SIGTTIN, SIGTTOU, SIGWINCH'
     `gosh'は初期状態ではこれらのシグナルのハンドラを設定せず、
     システムのデフォルトの振るまいに任せます。Schemeプログラムは必要ならば
           これらのシグナルのハンドラを設定できます。

`SIGHUP, SIGQUIT, SIGTERM'
     `gosh'はこれらのシグナルに対して、終了コード0でアプリケーションを
          終了するシグナルハンドラをセットします。

`SIGPWR, SIGXCPU, SIGUSR1, SIGUSR2'
     Linuxプラットフォームでスレッドを使用している場合は、
     これらのシグナルはシステムで使用されるため、Schemeからは使用できません。
     他のシステムではこれらのシグナルは下記の「他のシグナル」と同じ動作と
           なります。

`他のシグナル'
     `gosh'はデフォルトのシグナルハンドラを設定します。
     デフォルトのシグナルハンドラは "unhandled signal"
     エラーを通知します。
     Schemeプログラムはシグナル毎に独自のハンドラを設定することが可能です。

`gosh'でなく、他のアプリケーションに埋め込まれたGaucheを使っている場合、
Schemeレベルでのシグナルの使用をアプリケーションが制限している場合があります。

   Schemeからシグナルハンドラを設定するには以下の手続きを使って下さい。

 -- Function: set-signal-handler! signals handler
     SIGNALSはシグナル番号か`<sys-sigset>'オブジェクト、
     HANDLERは`#t'、`#f'、一つの引数を取る手続きのいずれか
     でなければなりません。
     HANDLERが手続きの場合、プロセスが指定されたシグナル(のうちのいずれか)を
     受けた時に、そのシグナル番号を引数としてHANDLERが呼ばれます。
     HANDLERの中でできる操作にはほとんど制限がありません。
     HANDLERからエラーを投げたり、他の場所で補足された継続を呼ぶことも
     できます。但し、HANDLER内で補足した継続はHANDLERから
     戻った時点で無効になります。

     HANDLERが`#t'の場合、指定されたシグナルにはオペレーティングシステムの
     デフォルトの振るまいが設定されます。
     HANDLERが`#f'の場合、指定されたシグナルは無視されます。

     マルチスレッドプログラムでは、
     シグナルハンドラの設定はスレッド間で共有されることに注意して下さい。
     ハンドラはシグナルを受けたスレッドで実行されます。 詳しくは*Note
     シグナルとスレッド::を参照して下さい。

 -- Function: get-signal-handler signum
     シグナルSIGNUMに設定されたハンドラを返します。

 -- Function: get-signal-handlers
     現在の全てのシグナルハンドラの設定を連想リストにして返します。
     返されるリストの各要素のcarには`<sys-sigset>'オブジェクトが、
     cdrにはそれらのシグナルに対応するハンドラ(手続きもしくはブール値)がセットされて
     います。

 -- Macro: with-signal-handlers (handler-clause ...) thunk
     THUNKの実行中だけシグナルハンドラを一時的に設定する便利なマクロです
     (このマクロは便利ですが下に述べるような多少危険な性質もあるので、
     注意して使って下さい)。

     HANDLER-CLAUSEは以下のいずれかの形式です
    `(SIGNALS EXPR ...)'
          SIGNALSは、評価された時に単独のシグナル番号、シグナル番号のリスト、
          あるいは`<sys-sigset>'オブジェクトを生成する式でなければなりません。
          SIGNALSに含まれるシグナルを受け取った時に、EXPR ...を
          評価するようなハンドラを設定します。

    `(SIGNALS => HANDLER)'
          SIGNALSは上と同じです。SIGNALSに含まれるシグナルに
          対して、処理HANDLERを設定します。

          HANDLERは`#t'、`#f'、一つの引数を取る手続きのいずれか
          でなければなりません。
          HANDLERが手続きの場合、プロセスが指定されたシグナル(のうちのいずれか)を
          受けた時に、そのシグナル番号を引数としてHANDLERが呼ばれます。
          HANDLERが`#t'の場合、指定されたシグナルにはオペレーティングシステムの
          デフォルトの振るまいが設定されます。
          HANDLERが`#f'の場合、指定されたシグナルは無視されます。

     THUNKから制御が抜けた時に、`with-signal-handlers'が呼ばれた時点での
     シグナルハンドラが再設定されます。

     _注意：_ このフォームで一つ以上のシグナルハンドラを設定する場合、
     それらは順にシステムに設定されます。全てのハンドラの設定が終る前に
     シグナルが届いた場合、シグナルハンドラの設定や再設定が不完全なままになる
     かもしれません。また、シグナルハンドラはグローバルな設定であり、
     「スレッドローカル」なハンドラを設定することはできませんが、
     `with-signal-handlers'の形式はそれを誤解させるかもしれません。


File: gauche-refj.info,  Node: シグナルのマスクと待機,  Next: シグナルとスレッド,  Prev: シグナルの処理,  Up: シグナル

6.21.6.4 シグナルのマスクと待機
...............................

Schemeプログラムで、送出がブロックされるシグナルの集合であるシグナルマスク
をセットできます。プロセスで完全にブロックされるシグナルが送出されると、
そのシグナルは"保留"となります。保留されたシグナルは、指定されたシグナルを
ブロックしないようにシグナルマスクが変更されると送出されるかもしれません。
(しかし、保留されたシグナルがキューに入れられるかどうかはオペレーティング
システムに依存します。)

マルチスレッドの環境では、スレッド毎に独自のシグナルマスクを持ちます。

 -- Function: sys-sigmask how mask
     現在のスレッドのシグナルマスクを変更し、以前のシグナルマスクを返します。
     MASKは`<sys-sigset>'オブジェクトでなければなりません。
     引数HOWは以下の整数定数のうちの1つでなければなりません。
    `SIG_SETMASK'
          MASKをそのスレッドのシグナルマスクとしてセットします。

    `SIG_BLOCK'
          そのスレッドのシグナルマスクにMASKにあるシグナルを追加します。

    `SIG_UNBLOCK'
          そのスレッドのシグナルマスクからMASKにあるシグナルを削除します。

 -- Function: sys-sigsuspend mask
     アトミックに、スレッドのシグナルマスクをMASKにセットし、
     呼び出しているスレッドを一時停止します。ブロックされておらずシグナル
     ハンドラがインストールされているシグナルが送出されると、関連
     付けられたハンドラが呼ばれ、`sys-sigsuspend'は戻ります。


File: gauche-refj.info,  Node: シグナルとスレッド,  Prev: シグナルのマスクと待機,  Up: シグナル

6.21.6.5 シグナルとスレッド
...........................

シグナルのセマンティクスはマルチスレッド環境では少々複雑に見えます。
しかし、いくつかのルールを覚えてしまえば、とても理解しやすいものでも
あります。さらにGaucheでは、プログラマの簡単に使えるようにデフォルトの
振る舞いをセットアップしています。

   細かいことは知りたくないという場合は、
次の1つのことだけを覚えておいて下さい。
*デフォルトでは*、シグナルはメインスレッドで処理されます。
しかし、メインスレッドがmutexや条件変数で一時停止している場合は、
シグナルは全く処理されないので注意が必要です。

   詳細に興味がある場合は、ここにルールがあります。
   * シグナルハンドラのセッティングは、全てのスレッドで共有されます。

   * シグナルマスクはスレッド固有です。

   * プロセスが非同期のシグナルを受け取ったら(他のプロセスからシグナルが
     送出されたと考えて下さい)、そのシグナルをブロックしていないスレッドの
     うちから任意の1つのスレッドが選ばれます。

   * シグナルハンドラは選択されたスレッドにおいて実行されます。
     しかし、選択されたスレッドがmutexのロックの獲得や条件変数を待っている
     場合は、シグナルの処理はそのスレッドが再開するまで遅延されます。
     シグナルの送出自体はスレッドを再開しません。

   これらのルールにはいくつかの暗黙の了解があります。

   特定のシグナルをブロックしないスレッドが1つ以上ある場合、
どのスレッドがそのシグナルを受け取るかを知る術はありません。
そのような状況は、GaucheにおいてはCプログラムよりもさらに不便です。
なぜなら、受信側のスレッドがmutexや条件変数で待機している場合、
シグナル処理は無期限に遅延されうるからです。
したがって、それぞれのシグナルについて、それを受け取ることのできるスレッドが
常にただの1つしかないようにすることを推奨します。

   Gaucheでは、`make-thread'(*Note スレッド手続き::参照)
で作られた全てのスレッドは、デフォルトで全てのシグナル(予約済みを除く)
をブロックします。これは、全てのシグナルがメインスレッドへ
送られるということです。

   もう1つの戦略は、シグナル処理のみを行うスレッドを作る方法です。
そうするためには、メインスレッドでシグナルをブロックして、
シグナル処理専用スレッドを作り、そのスレッドで全てのシグナルを
受け付けることにします。そのようなスレッドは`sys-pause'
で単にループしていれば良いでしょう。

     (thread-start!
       (make-thread
         (lambda ()
           (sys-sigmask SIG_SETMASK (make <sys-sigset>)) ;;empty mask
           (let loop () (sys-pause) (loop)))))

   複雑なアプリケーションでは、正確にスレッド毎のシグナル処理を
制御したいかもしれません。それは、いつでも、指定されたスレッドのみが
望むシグナルをブロックしないようにすれば、可能です。


File: gauche-refj.info,  Node: システムへの問い合わせ,  Next: 時間,  Prev: シグナル,  Up: システムインタフェース

6.21.7 システムへの問い合わせ
-----------------------------

 -- Function: sys-uname
     [POSIX] 次の5要素のリストを返します。 `(SYSNAME NODENAME RELEASE
     VERSION MACHINE)'。

 -- Function: sys-gethostname
     ホスト名を返します。システムでgethostname()が使えない場合、
     `sys-uname'が返すリストの2番目の要素が使われます。

 -- Function: sys-getdomainname
     ドメイン名を返します。システムでgetdomainname()が使えない場合、
     `"localdomain"'が返されます。

 -- Function: sys-getcwd
     [POSIX] 現在の作業ディレクトリを文字列で返します。
     システムから現在の作業ディレクトリが得られない場合は、エラーが通知されます。
     `sys-chdir'(*Note 他のファイル操作::参照)、`current-directory'
     (*Note ディレクトリユーティリティ::参照)も参照して下さい。

 -- Function: sys-getgid
 -- Function: sys-getegid
     [POSIX]
     現在のプロセスの実グループIDと実効グループIDをそれぞれ整数で返します。

 -- Function: sys-setgid gid
     [POSIX] 現在のプロセスの実効グループIDをセットします。

 -- Function: sys-getuid
 -- Function: sys-geteuid
     [POSIX]
     現在のプロセスの実ユーザIDと実効ユーザIDをそれぞれ整数で返します。

 -- Function: sys-setuid uid
     [POSIX] 現在のプロセスの実効ユーザIDをセットします。

 -- Function: sys-getgroups
     [POSIX] 補助的なグループのIDの整数のリストを返します。

 -- Function: sys-getlogin
     [POSIX]
     現在のプロセスの制御端末にログインしているユーザの名前を文字列で
     返します。システムがその情報を決定できない場合、`#f'が返されます。

 -- Function: sys-getpgrp
     [POSIX] 現在のプロセスのプロセスグループIDを返します。

 -- Function: sys-getpgid pid
     PIDで指定されたプロセスのプロセスグループIDを返します。
     PIDが0の場合、現在のプロセスが使われます。

     `getpgid()'はPOSIXではないことに注意して下さい。
     システムにGETPGID()がない場合、PIDが0ならば
     SYS-GETPGIDがまだ動作しますが(それは単に`sys-getpgrp'を呼びます)
     、PIDが0でない場合はエラーが通知されます。

 -- Function: sys-setpgid pid pgid
     [POSIX] プロセスPIDのプロセスグループIDをPGIDにセットします。
     PIDが0ならば、現在のプロセスのプロセスIDが使われます。
     PGIDが0ならば、`pid'で指定されたプロセスのプロセスIDが 使われます。
     (したがって、`sys-getpgid(0, 0)'は、現在のプロセスのプロセス
     グループIDを現在のプロセスIDにセットします。)

 -- Function: sys-setsid
     [POSIX] 呼んでいるプロセスがプロセスグループリーダでなければ、
     新しいセッションを作ります。

 -- Function: sys-getpid
 -- Function: sys-getppid
     [POSIX] 現在のプロセスIDと親プロセスのIDをそれぞれ返します。

 -- Function: sys-times
     [POSIX]

 -- Function: sys-ctermid
     [POSIX] プロセスの制御端末の名前を返します。
     これは単に```/dev/tty'''かもしれません。`sys-ttyname'も参照して下さい。


File: gauche-refj.info,  Node: 時間,  Next: Unixのプロセス管理,  Prev: システムへの問い合わせ,  Up: システムインタフェース

6.21.8 時間
-----------

Gaucheでは時間は2種類の表現を持ちます。ひとつはPOSIX APIとコンパチブルな
表現で、もう一つはSRFI-18、SRFI-19、SRFI-21とコンパチブルな表現です。
多くの手続きはどちらの表現も理解しますが、そうでない場合は
適用可能な表現を'POSIX time'または'SRFI time'と表記します。

   POSIX timeは実数で、Unix Epoch(Jan 1, 1970, 0:00:00GMT)からの秒数で
表現されます。POSIXの`time(2)'に対応する`sys-time'手続きは
この表現を返します。

   SRFI互換の時間は`<time>'クラスのインスタンスとして表現され、
秒、およびナノ秒のスロットを持ちます。
また、時間の種別(UTC、TAI、期間、プロセス時間、他)も保持しています。
`Current-time'はこの表現を返します。

POSIX time
..........

 -- Function: sys-time
     [POSIX] 現在の時間を POSIX 時間(エポック(00:00:00 UTC, January 1,
     1970)
     からの秒数)で返します。マシンのアーキテクチャによっては、不正確数で
     あるかもしれません。

 -- Function: sys-gettimeofday
     2つの値を返します。1970/1/1 0:00:00 UTC を基準として、
     1つ目の値は秒数、2つ目の値は端数をマイクロ秒で表したものです。
     システムが `gettimeofday' 呼び出しをサポートしていない場合、
     この手続きは `time()' を呼び出し、その場合はマイクロ秒の
     部分はいつも 0 です。

 -- Builtin Class: <sys-tm>
     カレンダーである、`struct tm'
     を表します。以下のスロットを持ちます。

      -- Instance Variable of <sys-tm>: sec
          秒。0-61。

      -- Instance Variable of <sys-tm>: min
          分。0-59。

      -- Instance Variable of <sys-tm>: hour
          時。0-23。

      -- Instance Variable of <sys-tm>: mday
          月の日。1 から数える。1-31。

      -- Instance Variable of <sys-tm>: mon
          月。0 から数える。0-11。

      -- Instance Variable of <sys-tm>: year
          1900年からの年数。例えば、102 なら 2002年。

      -- Instance Variable of <sys-tm>: wday
          曜日。日曜は 0 .. 土曜は 6。

      -- Instance Variable of <sys-tm>: yday
          1年の中での日数。1月1日は 0 .. 12月31日は 364 か 365。

      -- Instance Variable of <sys-tm>: isdst
          夏時間が有効であるかどうかを指定するフラグ。有効なら正の数、無効なら
          0、 分からなければ負の数。

 -- Function: sys-gmtime time
 -- Function: sys-localtime time
     [POSIX] TIME を `<sys-tm>' オブジェクトに変換します。
     標準時での表現かローカルタイムゾーンでの表現かで使い分けます。
     TIME は POSIX 時間か SRFI 時間です。

 -- Function: sys-ctime time
     [POSIX] TIME を POSIX の ctime() を使って文字列表現に変換します。
     TIME は POSIX 時間か SRFI 時間です。

 -- Function: sys-difftime time1 time0
     [POSIX] 2つの時間の差を、秒の実数で返します。TIME0 とTIME1 は
     POSIX 時間か SRFI 時間です。

 -- Function: sys-asctime tm
     [POSIX] `<sys-tm>' オブジェクトである TM を文字列表現に変換します。

 -- Function: sys-strftime format tm
     [POSIX] `<sys-tm>' オブジェクトである TM を、フォーマット文字列
     FORMAT に従って文字列表現に変換します。

 -- Function: sys-mktime tm
     [POSIX] ローカルタイムとして表現された `<sys-tm>'
     オブジェクトである TM を POSIX
     時間(エポックからの秒数)に変換します。

 -- Function: sys-tm->alist tm
     (Deprecated function)

SRFI time
.........

 -- Builtin Class: <time>
     ある時刻を表す`<time>'オブジェクトです。

      -- Instance Variable of <time>: type
          timeの型を表します。デフォルトは`time-utc'で、Unixエポックからの
          秒数を表します。SRFI-19(*Note 時間のデータ型と手続き::参照)
          ではさらに型が追加されています。

      -- Instance Variable of <time>: second
          timeの秒の部分です。

      -- Instance Variable of <time>: nanosecond
          timeのナノ秒の部分です。

 -- Function: current-time
     [SRFI-18][SRFI-21]
     現在の時間を`time-utc'で表す`<time>'オブジェクトを返します。 *Note
     時間のデータ型と手続き::では、`current-time'が再定義され、
     timeの型を指定するオプショナル引数を受け付けるようにされています。

 -- Function: time? obj
     [SRFI-18][SRFI-19][SRFI-21]
     OBJがtimeオブジェクトなら`#t'を返します。

 -- Function: time->seconds time
 -- Function: seconds->time seconds
     [SRFI-18][SRFI-21] timeオブジェクトと秒数(POSIX時間)を変換します。
     `time->seconds'の引数TIMEは、`<time>'オブジェクトで
     なければなりません。


File: gauche-refj.info,  Node: Unixのプロセス管理,  Next: I/Oの多重化,  Prev: 時間,  Up: システムインタフェース

6.21.9 Unixのプロセス管理
-------------------------

以下の手続きは、システムコールに対する直接的なインタフェースを提供します。
*Note 高レベルプロセスインタフェース::も合わせて参照して下さい。
より高レベルの便利な手続きが定義されています。

Fork and exec
.............

 -- Function: sys-system command
     [POSIX] サブプロセスでCOMMANDを実行します。COMMANDは通常、
     `sh'へ渡されるので、シェルのメタキャラクタは解釈されます。

     この関数は、`system()'が返した整数値を返します。
     POSIXは`system()'が何を返すかを定義していないので、
     戻り値をポータブルな方法で解釈することができません。

 -- Function: sys-fork
     [POSIX]
     現在のプロセスをフォークします。子プロセスにいるならば0が返り、
     親プロセスにいるならば子プロセスのプロセスIDが返ります。
     全ての開かれているファイルディスクリプタは、親プロセスと子プロセスで
     共有されます。詳細は、システムの`fork(2)'を参照して下さい。

     子プロセスが`sys-exec'を呼ぶ代わりにSchemeコードを実行して
     終了する場合は、`exit'ではなく`sys-exit'を呼ぶ必要があります。
     通常のexitの呼び出しはファイルバッファのフラッシュを試み、
     OSによっては親のファイルバッファを混乱させるでしょう。

     `sys-fork'は複数のスレッドが走っている時には安全ではないことに
     注意してください。`fork(2)'システムコールはプロセスのメモリイメージを
     複製しますが、それには他のスレッドでロックされているmutexも含まれます。
     もし`sys-fork'の瞬間に他のスレッドが何かをロックしていたとすれば、
     子プロセスでもその資源はロックされたままになりますが、
     その時子プロセスはもはやその資源をアンロックするスレッドを持っていません。
     (これは内部で使っているmutexにも起こり得るため、Schemeレベルでmutexを
     全く使っていないとしても防ぐことはできません)。

     やりたいことが、マルチスレッドアプリケーションで別プログラムをspawnする
     ことであるなら、下に説明する`sys-fork-and-exec'を使ってください。
     どうしても別プロセスでSchemeコードを走らせたいのなら、よくある方法は、
     アプリケーションの起動後すぐにマネージャプロセスとなる子プロセスをfork
     しておき、新たなプロセスが欲しくなったらそのマネージャプロセスに
     forkを依頼するという方法です。

 -- Function: sys-exec command args &optional iomap
     [POSIX+] COMMANDを引数のリストであるARGSを伴って実行します。
     現在のプロセスイメージはCOMMANDに置き換えられるので、
     この関数は戻りません。

     ARGSの全ての要素は文字列でなければなりません。
     ARGSの最初の要素は、`argv[0]'、すなわちプログラム名として
     使われます。

     オプショナル引数のIOMAPは、与えられた場合は、開かれている
     ファイルディスクリプタがどのように扱われるかを指定します。
     この引数は以下のフォーマットでなければなりません。
          ((to-fd . from-port-or-fd) ...)
     to-fdは整数でなければならず、from-port-or-fdは整数のファイル
     ディスクリプタかポートでなければなりません。
     リストのそれぞれの要素は、現在のプロセスのfrom-port-or-fdの
     ファイルディスクリプタを、実行されているプロセスのファイルディスクリプタ
     to-fdにマップさせます。

     IOMAPが与えられると、iomapリストで指定されていないいかなるファイル
     ディスクリプタも`exec()'の前に閉じられます。さもなければ、現在のプロセスの
     全てのファイルディスクリプタは開かれたままになります。

          (sys-exec "ls" '("ls" "-l")) => ;; ls is executed.

          (let ((out (open-output-file "ls.out")))
            (sys-exec "ls" '("ls" "-l") `((2 . 1) (1 . ,out)))
             =>
            ;; ls is executed, with its stderr redirected
            ;; to the current process's stdout, and its
            ;; stdout redirected to the file "ls.out".

     エラーに遭遇すると、たいていの場合エラー条件を投げます。
     一旦ファイルディスクリプタの順番が変えられると、合理的な方法でエラーを処理する
     ことは実行不可能です(標準エラーがまだ有効かどうかさえ知る術がありません)。
     したがって、Gaucheはエラー時には単に終了するだけです。

 -- Function: sys-fork-and-exec command args &optional iomap
     `sys-exec'と同じですが、ファイルディスクリプタを変更して
     `execvp(2)'を実行する直前に、`fork(2)'を実行します。
     子プロセスのプロセスidを返します。

     他のスレッドが走っている環境下で別プログラムをspawnしたい場合は、
     `sys-fork'と`sys-exec'を別々に使うのではなく、
     この手続きを使ってください。
     この手続き中では、`fork(2)'と`execvp(2)'の間で
     メモリアロケーションもロックの獲得も行われないため、
     マルチスレッド環境で実行しても安全になっています。

Wait
....

 -- Function: sys-wait
     [POSIX]
     システムの`wait(2)'を呼びます。プロセスは、子プロセスの1つが
     終了するまでその実行を一時停止します。2つの正確整数、1つ目は子プロセスのID、
     2つ目はステータスコードを返します。ステータスコードは以下の関数によって
     解釈できます。

 -- Function: sys-waitpid pid &keyword nohang untraced
     [POSIX] これは、waitの拡張バージョンである、`waitpid(3)'への
     インターフェースです。

     PIDは、待っている子プロセスを指定する正確整数です。正の整数ならば、
     特定の子プロセスを待っています。0ならば、このプロセスグループのいずれかの
     メンバを待っています。-1ならば、いずれかの子プロセスを待っています。
     -1よりも小さければ、プロセスグループIDがPIDの絶対値と等しいいずれかの
     子プロセスを待っています。

     キーワード引数NOHANGに真値が指定されていなければ、
     呼んでいるプロセスは、それらの子プロセスのうちの1つが終了するまで一時停止します。

     キーワード引数UNTRACEDに真値が指定されていれば、
     停止した子プロセスのステータスも返ります。

     戻り値は2つの正確整数で、1つ目は子プロセスのID、2つ目はステータスコードです。
     NOHANGが真で子プロセスのステータスが利用できない場合は、1つ目の値は0です。

 -- Function: sys-wait-exited? status
 -- Function: sys-wait-exit-status status
     [POSIX] 引数は`sys-wait'か`sys-waitpid'の2番目の値として返される
     終了ステータスです。子プロセスが正常終了したら、`sys-wait-exited?'は
     `#t'を返します。`sys-wait-exit-status'は、子プロセスが
     `exit(2)'に渡した終了コードか、`main()'の戻り値を返します。

 -- Function: sys-wait-signaled? status
 -- Function: sys-wait-termsig status
     [POSIX]
     引数は、`sys-wait'か`sys-waitpid'の2つ目の戻り値である終了ステータスです。
     子プロセスが捕捉されないシグナルで終了した場合は、`sys-wait-signaled?'は
     `#t'を返します。
     `sys-wait-termsig'は、子プロセスを終了したシグナルの番号を返します。

 -- Function: sys-wait-stopped? status
 -- Function: sys-wait-stopsig status
     [POSIX]
     引数は、`sys-waitpid'の2つ目の戻り値である終了ステータスです。
     子プロセスが停止されれば、`sys-wait-stopped?'は`#t'を
     返します。このステータスは、`sys-waitpid'がUNTRACED引数に
     真値を持っている場合にのみ捕捉されます。`sys-wait-stopsig'は
     子プロセスを停止させたシグナルの番号を返します。


File: gauche-refj.info,  Node: I/Oの多重化,  Next: その他のシステムコール,  Prev: Unixのプロセス管理,  Up: システムインタフェース

6.21.10 I/Oの多重化
-------------------

`select(2)'へのインターフェース関数です。
これらのプリミティブの上に構築された高次元のインターフェースが
提供されています。*Note 簡単なディスパッチャ::を 参照して下さい。

 -- Builtin Class: <sys-fdset>
     ファイルディスクリプタの集合である`fd_set'を表します。
     makeメソッドによって、空のファイルディスクリプタの集合を作れます。
          (make <sys-fdset>)

 -- Function: sys-fdset-ref fdset port-or-fd
 -- Function: sys-fdset-set! fdset port-or-fd flag
     FDSETの特定のファイルディスクリプタビットを取得・セットできます。
     PORT-OR-FDは関連付けられたファイルディスクリプタを持っていないポートで、
     `sys-fdset-ref'は`#f'を返し、`sys-fdset-set!'はFDSETを
     変更しません。FLAGは真偽値でなければなりません。

     下記のように、`sys-fdset-ref'のジェネリックなセッタが使えます。
          (set! (sys-fdset-ref fdset port-or-fd) flag)
            == (sys-fdset-set! fdset port-or-fd flag)

 -- Function: sys-fdset-max-fd fdset
     FDSETにある最大のファイルディスクリプタ番号を返します。

 -- Function: sys-select readfds writefds exceptfds &optional timeout
 -- Function: sys-select! readfds writefds exceptfds &optional timeout
     ステータスを変更するためにファイルディスクリプタの集合を待ちます。
     READFDS、WRITEFDS、EXCEPTFDSは、注目するファイル
     ディスクリプタの集合を表す`<fdset>'オブジェクトです。
     READFDSにあるファイルディスクリプタは、文字を読み込む準備が
     出来たかどうかを検査するために監視されています。
     WRITEFDSにあるファイルディスクリプタはそこへ書き込むことができる
     ようになったか監視されています。EXCEPTFDSにあるファイルディスクリプタは
     例外のために監視されています。条件を監視する必要がない場合は、これらの引数の
     1つ以上に`#f'を渡すことができます。

     TIMEOUTは`sys-select'が条件の変更を待つ最大の時間を指定します。
     それは、マイクロミリ秒を表す実数か、1つ目が秒数で2つ目がマイクロ秒である
     2つの整数からなるリストです。`#f'を渡すと、`sys-select'は
     永久に待ちます。

     `sys-select'は4つの値を返します。1つ目の値は、ステータスの変更を
     検知したディスクリプタの数です。timeoutが経過したら0になるでしょう。
     2、3、4番目の値は、それぞれ読み込み、書き出し、例外のステータスを変更
     するディスクリプタの集合を含む`<fdset>'オブジェクトです。
     READFDS、WRITEFDS、EXCEPTFDSのうちの1つ以上に`#f'を
     渡すと、対応する戻り値は`#f'になります。

     `sys-select!'の仲間は、それが渡された引数`<fdset>'を変更することを
     除けば、`sys-select'と同じように動作します。
     `sys-select'は、新しい`<fdset>'オブジェクトを作り、その
     引数を変更しません。


File: gauche-refj.info,  Node: その他のシステムコール,  Prev: I/Oの多重化,  Up: システムインタフェース

6.21.11 その他のシステムコール
------------------------------

 -- Function: sys-pause
     [POSIX]
     シグナルキャッチ関数の実行かプロセスの終了を指示するシグナルを
     受け取るまでプロセスを一時停止します。この関数は、シグナルキャッチ関数が
     戻ったときにのみ戻ります。戻り値は未定義です。

     Schemeレベルでは、`pause()'を呼ぶだけでは上記のセマンティクスを
     満足しません。内部的にこの手続きは現在のシグナルマスクを伴って、
     `sigsuspend()'を呼びます。

 -- Function: sys-alarm seconds
     [POSIX] SIGALRMシグナルがSECONDS秒後に送出されるように準備します。
     以前のアラームクロックのセッティングはキャンセルされます。
     SECONDSに0を渡すと、新しいアラームをスケジューリングしません。
     以前にスケジューリングされていたアラームが送出されるまでの残り時間を
     秒数で返します(アラームがアクティブでない場合は0を返します)。

 -- Function: sys-sleep seconds
     [POSIX]
     指定された秒数が経過するまで、あるいはプロセスがシグナルを受け取るまで
     スレッドを一時停止します。一時停止している場合は0を返し、
     シグナルによって一時停止が解除されている場合は、解除されてからの秒数を返します。

     POSIX実装間でポータブルにするためには、SECONDSを65536より小さく保って
     下さい。

 -- Function: sys-nanosleep nanoseconds
     [POSIX]
     指定されたナノ秒が経過するか、シグナルを受け取るまでプロセスを一時停止します。
     引数NANOSECONDSは`<time>'オブジェクト(*Note 時間::参照)か
     実数です。NANOSECONDSが経過したら`#f'を返し、
     `sys-nanosleep'がシグナルによって割り込まれると残りの時間を表す
     `<time>'オブジェクトを返します。

          ;wait for 0.5 sec
          (sys-nanosleep 500000000)

          ;wait for 1.3 sec
          (sys-nanosleep (make <time> :second 1 :nanosecond 300000000)

 -- Function: sys-random
 -- Function: sys-srandom seed
     擬似的な乱数ジェネレータです。
     `sys-random'は0からRAND_MAX(それ自体を含む)までの間で乱数を
     返します。これは`random(3)'への直接的なインターフェースです。
     システムに`random(3)'がない場合、`lrand48(3)'が使われます。

     `sys-srandom'は乱数ジェネレータの種をセットします。
     システムによって、`srandom(3)'か`srand48(3)'を使います。

     これらの関数の意図は、乱数ジェネレータ(RNG; random number
     generator)の
     品質や速度を気にしないアプリケーションに、完成された便利なRNGを提供することです。
     本格的な統計分析には、`math.mt-random'モジュールのMersenne Twister
     RNGを 使って下さい(*Note Mersenne Twister乱数発生器::参照)。

 -- Variable: RAND_MAX
     `sys-random'が返す正の整数に束縛されます。


File: gauche-refj.info,  Node: 開発補助API,  Prev: システムインタフェース,  Up: 組み込みライブラリ

6.22 開発補助API
================

Gauche
には開発者がプログラムを解析するための基本的な組込みAPIがあります。

* Menu:

* デバッグ補助::
* プロファイラAPI::


File: gauche-refj.info,  Node: デバッグ補助,  Next: プロファイラAPI,  Prev: 開発補助API,  Up: 開発補助API

6.22.1 デバッグ補助
-------------------

 -- Macro: debug-print expr
     このマクロはEXPRをそのフォームのまま印字してから、その式を評価し、
     評価の結果を印字し、その値を返します。

     特殊リーダー構文 `#?=EXPR' は `(debug-print EXPR)' に展開されます。
     詳細については *Note デバッグ:: を参照してください。

 -- Function: disasm closure
     コンパイル済のCLOSUREの本体部分をディスアセンブルして印字します。
     これはコンパイラのバグをなんとかしようという場合か、限界まで
     チューンしようとしないかぎりは役には立たないでしょう。

     このディスアセンブラの出力結果を読む場合には、コンパイルされたコードに
     はデッドコードが含まれている可能性があることを心してください。デッドコー
     ドはジャンプ最適化によって生成されるのですが、コンパイラはこれをわざわ
     ざ除去することはしていません。


File: gauche-refj.info,  Node: プロファイラAPI,  Prev: デバッグ補助,  Up: 開発補助API

6.22.2 プロファイラAPI
----------------------

ここに挙げている関数は、Gauche の組込みプロファイラを制御するためのも
のです。プロファイラの説明については *Note プロファイラを使う::
を参照してく ださい。

注意：現時点ではプロファイラはマルチスレッドプログラムでは正しく動作し
ません。

 -- Function: profiler-start
     標本化プロファイラを始動します。プロファイラが既に始動しいる場合
     には何もしません。

 -- Function: profiler-stop
     標本化プロファイラを停止し、標本データを内部データ構
     造に保存します。既に標本データが保存されていた場合には、新
     しく収集された標本データがその後に追加されます。もしプロファイラが動いてい
     なかった場合には何もしません。

 -- Function: profiler-reset
     もしプロファイラが動いていればそれを停止し、保存されていた標本データ
     を破棄します。


 -- Function: profiler-show &keyword sort-by max-rows
     格納されている標本データを表示します。

     キーワード引数 SORT-BY は指定する場合は、`time'、 `count' または
     `time-per-call' のどれかひとつです。
     これで結果の整列順を指定します。デフォルトでは `time'です。

     キーワード引数 MAX-ROWS では結果を表示する最大行数を指定します。
     この値が `#f' であればすべてのデータが表示されます。


File: gauche-refj.info,  Node: オブジェクトシステム,  Next: ライブラリモジュール - 概要,  Prev: 組み込みライブラリ,  Up: Top

7 オブジェクトシステム
**********************

Gaucheのオブジェクトシステムのデザインは、TinyCLOSから
派生したSTklosから大きな影響を受けています。
多重継承、マルチメソッド、メタオブジェクトプトロコルを
サポートしています。

   型システムは、オブジェクトシステムに統合されています。
つまり、文字列は`<string>'クラスのインスタンスである、などです。

* Menu:

* オブジェクトシステムの紹介::
* 一般的な問い合わせ::
* クラス::
* インスタンス::
* ジェネリックファンクションとメソッド::
* メタオブジェクトプロトコル::


File: gauche-refj.info,  Node: オブジェクトシステムの紹介,  Next: 一般的な問い合わせ,  Prev: オブジェクトシステム,  Up: オブジェクトシステム

7.1 オブジェクトシステムの紹介
==============================

この節では Gauche のオブジェクトシステムの基本的構造について手短かに
説明します。Gauche のオブジェクトシステムは CLOS (Common-Listp Object
System) に強く影響されています。CLOS やそれにかかわりのある
TinyCLOS、STklos、 あるいは Guile
のオブジェクトシステムの経験がある方は、この節を飛ばして、
次の節にいってもよいでしょう。

   CLOS 風のオブジェクトシステムでは 3
つの概念が中心的な役割をはたします。
_クラス_、_ジェネリック関数_、それに_メソッド_です。

   _クラス_はオブジェクトの構造を指定します。また、データ型も定義します
(厳密にいうと、データ型とはちがうものですが、難しいところは今は
おいておきましょう)。

   たとえば、2 次元空間の点は x 座標と y
座標で表現できます。点のクラスは `define-class'
マクロを使って定義できます。もっとも手短かには、
次のように定義できます。

     (define-class <2d-point> () (x y))

   (この節の例の定義コードは Gauche ソース配布物のなかの
`examples/oointro.scm' にあります。)

   シンボル `<2d-point>' はクラスの名前です。グローバル変数
`<2d-point>'はクラスオブジェクトに束縛されています。クラス名を `<' と
`>' で囲むのは慣習にすぎません。`define-class'
には任意のシンボルを渡すことができます。

   `define-class'の第二引数は、直接のスーパークラスのリストです。
これでこのクラスの継承を指定します。これについては後で説明します。

   `define-class'の第三引数は_スロット_のリストです。
スロットはなにかを格納しておく場所で、通常は各オブジェクトに対して、値を格納できます。
これは、他のオジェクト指向言語では、フィールドとかインスタンス変数などと
呼ばれているものに似たものです。しかし、スロットは単なる各オブジェクト毎の
格納スペース以上の使い方ができます。

   さて、2
次元の点のクラスを定義しましたので、点のインスタンスを生成できます。
クラスをジェネリック関数 `make' に渡してインスタンスを生成します。
(ジェネリック関数がどんなものであるかは気にしないで下さい。今はある特殊な
タイプの関数とだけ考えておいてください。)

     (define a-point (make <2d-point>))

     a-point  => #<<2d-point> 0x8117570>

   対話モードで `gosh' を使っているなら、ジェネリック関数 `describe' を
使って、インスタンスの内部を点検できます。
便利なので、省略形として`d'という名前も定義されています。
(詳細については、*Note インタラクティブセッション::参照)

     gosh> (d a-point)
     #<<2d-point> 0x8117570> is an instance of class <2d-point>
     slots:
       x         : #<unbound>
       y         : #<unbound>

   スロットの値にアクセスあるいは値を変更するためには、それぞれ、
`slot-ref' および `slot-set!' が使えます。これらの名前は STklos
からとりました。

     (slot-ref a-point 'x)  ;; a-point のスロット x にアクセス
       => error, since slot 'x doesn't have a value yet

     (slot-set! a-point 'x 10.0)  ;; a-point のスロット x を 10.0 に設定

     (slot-ref a-point 'x)
       => 10.0

   Gauche では、より短かい名前 `ref' も使えます。これを使えば srfi-17
の一般化された `set!' の構文が使えます。
     (ref a-point 'x) => 10.0

     (set! (ref a-point 'y) 20.0)

     (ref a-point 'y) => 20.0

   スロットの値が設定されていることを見てみましょう。
     gosh> (d a-point)
     #<<2d-point> 0x8117570> is an instance of class <2d-point>
     slots:
       x         : 10.0
       y         : 20.0

   実際には、スロットにデフォルト値を設定できたり、インスタンス生成時に
スロットに値を設定できると便利なことが多いです。このような情報は、
_スロットオプション_で指定できます。`<2d-point>'の定義を
次のように変更してみましょう。

     (define-class <2d-point> ()
       ((x :init-value 0.0 :init-keyword :x :accessor x-of)
        (y :init-value 0.0 :init-keyword :y :accessor y-of)))

   各スロットの指定は、前の例では一つのシンボルでしたが、こんどはリスト
であることに注意してください。 こんどは、リストの car
部分がスロット名の指定で、cdr 部分にいろいろな情報が
はいります。`:init-value' のうしろの値はそのスロットのデフォルト値を
定義しています。`:init-keyword'のうしろのキーワードは、生成時にスロットを
初期化するために `make'
に渡すことのできるキーワード引数を定義しています。 キーワード
`:accessor' のうしろの名前は、スロットへのアクセス/変更の
ために使えるジェネリック関数に束縛されます。これは
`slot-ref'/`slot-set!' のかわりに使います。

   ちょっとした対話セッションをみてみましょう。新しい `<2d-point>'
クラスの
インスタンスをつくります。スロットがデフォルト値で初期化されているのがわかり
ますね。
     gosh> (define a-point (make <2d-point>))
     a-point
     gosh> (d a-point)
     #<<2d-point> 0x8148680> is an instance of class <2d-point>
     slots:
       x         : 0.0
       y         : 0.0

こんどは、キーワード引数で初期値を与えて、別のインスタンスを作ります。
     gosh> (define b-point (make <2d-point> :x 50.0 :y -10.0))
     b-point
     gosh> (d b-point)
     #<<2d-point> 0x8155b80> is an instance of class <2d-point>
     slots:
       x         : 50.0
       y         : -10.0

   アクセサは `slot-ref'/`slot-set!' より短かくなって便利に
なりましたね。
     gosh> (x-of a-point)
     0.0
     gosh> (x-of b-point)
     50.0
     gosh> (set! (y-of a-point) 3.33)
     #<undef>
     gosh> (y-of a-point)
     3.33

   利用可能な全スロットオプションのリストは*Note
クラスの定義::にあります。
ちょっと見ると、これらのスロットオプションの宣言は冗長に見えるかもしれません。
システム側で初期化キーワードやアクセス名を自動的に定義する静的な仕組を
用意することもできたかもしれません。 しかしながら、CLOS
風のシステムでは柔軟性の方をより重視します。
メタオブジェクトプロトコルと呼ばれる機構をもちいて、これらの
スロットオプションがどのように解釈されるかをカスタマイズすることができます。
また、自分用のスロットオプションを追加することもできます。 詳しくは
*Note メタオブジェクトプロトコル:: を見てください。

   また、似たような流儀で `<2d-vector>' クラスを定義できます。

     (define-class <2d-vector> ()
       ((x :init-value 0.0 :init-keyword :x :accessor x-of)
        (y :init-value 0.0 :init-keyword :y :accessor y-of)))

   そうです。同じアクセサ名を `x-of' のように使うことができます。
これは事実上、多重定義されます。

主流のオブジェクト指向言語に慣れた方は、そろそろ、メソッドはどこにあるのだと
思い始めているかもしれません。いよいよメソッドの登場です。以下のフォームは、3
つの引数 PT、DY、DY をとり、 しかもPT は `<2d-point>'
のインスタンスであるような メソッド `move-by!' を定義するものです。

     (define-method move-by! ((pt <2d-point>) dx dy)
       (inc! (x-of pt) dx)
       (inc! (y-of pt) dy))

   `define-method' マクロの第二引数は_メソッド特定化子リスト_を
指定しています。これは、第一引数が `<2d-point>' のインスタンスで
なければならないことを示し、第二、第三引数は任意の型でよいことを
示しています。メソッド呼び出しの構文は通常関数の呼び出しと同じです。

     gosh> (move-by! b-point 1.4 2.5)
     #<undef>
     gosh> (d b-point)
     #<<2d-point> 0x8155b80> is an instance of class <2d-point>
     slots:
       x         : 51.4
       y         : -7.5

別の特定化子によりこのメソッドを多重定義することが可能です。以下のように
ベクタを使って点を動かすこともできます。
     (define-method move-by! ((pt <2d-point>) (delta <2d-vector>))
       (move-by! pt (x-of delta) (y-of delta)))

   特定化はユーザ定義のクラスにだけ限定されているわけではありません。
Gauche の組み込み型を使ってメソッドを特定化することもできます。

     (define-method move-by! ((pt <2d-point>) (c <complex>))
       (move-by! pt (real-part c) (imag-part c)))

   以下はセッション例です。
     gosh> (define d-vector (make <2d-vector> :x -9.0 :y 7.25))
     d-vector
     gosh> (move-by! b-point d-vector)
     #<undef>
     gosh> (d b-point)
     #<<2d-point> 0x8155b80> is an instance of class <2d-point>
     slots:
       x         : 42.4
       y         : -0.25
     gosh> (move-by! b-point 3+2i)
     #<undef>
     gosh> (d b-point)
     #<<2d-point> 0x8155b80> is an instance of class <2d-point>
     slots:
       x         : 45.4
       y         : -2.25

   メソッドがその主レシーバ `<2d-point>' によってのみディスパッチされる
のではなく、その他の引数によってもディスパッチされているのがわかると思います。
実は、第一引数は残りの引数に比べて何ら特別ではありません。 CLOS
風のシステムではメソッドは特定のクラスに属するものではないのです。

   ではメソッドとはいったいなんでしょう。`move-by!' を点検してみると
それが `<generic>' のインスタンスであり、ジェネリック関数であると
わかります。(`describe' は可読性のために `methods' スロットの
値の印字を途中で切っていることに注意してください。)

     gosh> move-by!
     #<generic move-by! (3)>
     gosh> (d move-by!)
     #<generic move-by! (3)> is an instance of class <generic>
     slots:
       name      : move-by!
       methods   : (#<method (move-by! <2d-point> <complex>)> #<method (move-
     gosh> (ref move-by! 'methods)
     (#<method (move-by! <2d-point> <complex>)>
      #<method (move-by! <2d-point> <2d-vector>)>
      #<method (move-by! <2d-point> <top> <top>)>)

   ジェネリック関数は特別なタイプの関数だと言いましたが、Gauche
ではこれは
適用可能オブジェクトとして認識されます。それは、適用されるとその引数に
対応して適切なメソッドを選択して、その選択されたメソッドを呼び出すという動作を
行います。

   実際 `define-method' マクロがやっていることは、(1)もし与えられた
名前のジェネリック関数がまだ存在していなければ、これを生成し、(2)与えられた
特定化子と本体とでメソッドオブジェクトを生成し、(3)ジェネリック関数に
そのメソッドオブジェクトを追加する、ということです。

   アクセサも同様にジェネリック関数で、`define-class'
マクロが暗黙のうちに 生成します。

     gosh> (d x-of)
     #<generic x-of (2)> is an instance of class <generic>
     slots:
       name      : x-of
       methods   : (#<method (x-of <2d-vector>)> #<method (x-of <2d-point>)>)

   主流の動的オジェクト指向言語では、クラスには多くの役割があります。
クラスは構造と型を定義し、スロットとメソッドの名前空間を生成し、
メソッドのディスパッチに責任をもちます。Gaucheでは、名前空間は
モジュールによって管理し、メソッドのディスパッチはジェネリック関数で
あつかいます。

オブジェクトの印字表現は、デフォルトでは、あまりユーザにやさしくありません。
Gauche の `write' および `display' 関数は、どのように印字して
よいかわからないインスタンスにであうと、ジェネリック関数 `write-object'
を呼びます。定義したクラスのインスタンスをどのように印字するかを
カスタマイズするために、そのクラスに特定したメソッドを定義することができます。

     (define-method write-object ((pt <2d-point>) port)
       (format port "[[~a, ~a]]" (x-of pt) (y-of pt)))

     (define-method write-object ((vec <2d-vector>) port)
       (format port "<<~a, ~a>>" (x-of vec) (y-of vec)))

   で、どうなったかというと、
     gosh> a-point
     [[0.0, 3.33]]
     gosh> d-vector
     <<-9.0, 7.25>>

   srfi-10
のフォーマットを満すように印字表現をカスタマイズし、読み込み時
構築子を定義すれば、自分の定義したクラスのインスタンスを、組み込み
オブジェクトと同様に書き出し、読み戻しできます。詳しくは *Note
読み込み時コンストラクタ:: を見てください。

   いくつかの組み込み関数はユーザ定義オブジェクトに対して同様の方法で
機能拡張できます。たとえば、`object-equal?' を特定化すれば、 `equal?'
を使ってインスタンスの比較ができます。

     (define-method object-equal? ((a <2d-point>) (b <2d-point>))
       (and (equal? (x-of a) (x-of b))
            (equal? (y-of a) (y-of b))))

     (equal? (make <2d-point> :x 1 :y 2) (make <2d-point> :x 1 :y 2))
       => #t

     (equal? (make <2d-point> :x 1 :y 2) (make <2d-point> :x 2 :y 1))
       => #f

     (equal? (make <2d-point> :x 1 :y 2) 'a)
       => #f

     (equal? (list (make <2d-point> :x 1 :y 2)
                   (make <2d-point> :x 3 :y 4))
             (list (make <2d-point> :x 1 :y 2)
                   (make <2d-point> :x 3 :y 4)))
       => #t

   もっとおもしろい例を見てみましょう。描画可能な `<shape>' というクラス
を考えます。
基本クラスとして、色や線の太さといった共通属性をスロットに持たせます。

     (define-class <shape> ()
       ((color     :init-value '(0 0 0) :init-keyword :color)
        (thickness :init-value 2 init-keyword :thickness)))

   インスタンスを生成する際、`make' はジェネリック関数 `initialize'
を呼びます。この関数は init-keyword や init-value
を処理するようなスロットの 面倒を見ます。この `initialize'
メソッドを特定化することによって、初期化
の振舞いをカスタマイズすることができます。`initialize' メソッドは二つの
引数とともに呼ばれます。ひとつは新しく生成されたインスタンス、もうひとつは
`make' にわたされた引数のリストです。

   `initialize' メソッドを `<shape>' クラス用に定義し、生成された shape
が自動的にグローバルなリストに登録されるようにしましょう。
システムのもつ `initialize' の振舞いを完全に置き換えたくはないという
ことに注意してください。init-keyword
は相変わらず扱う必要があるからです。

     (define *shapes* '())  ;; グローバルな shape のリスト

     (define-method initialize ((self <shape>) initargs)
       (next-method)  ;; このシステムがスロットの初期化処理をするようにする
       (push! *shapes* self)) ;; 自分自身をグローバルなリストに登録する

   仕掛けは、特別なメソッド `next-method' にあります。これは
メソッド本体の中でしか使えません。同じジェネリック関数の
_特定化の度合がより低いメソッド_を呼びます。これは、典型的には
スーパークラスの同じメソッドを呼ぶということを意味します。
ほとんどのオジェクト指向言語には、スーパークラスのメソッドを呼ぶという
概念があります。多重引数ディスパッチと多重継承のために `next-method'
は少し複雑にはなっていますが、基本的なアイディアは同じです。

   さて、では `<shape>' のスーパークラスはなんでしょう。実は、 すべての
Scheme で定義されたクラスは `<object>' というクラスを
継承します。スロットのめんどうを見ているのは、`<object>' の
初期化メソッドなのです。自分で定義した `initialize' メソッド中で
`next-method' を呼びだしたあとでは、すべてのスロットが
正しくイニシャライズされたとみなせます。というわけで、自分で定義した
`initialize' のなかで通常、最初にすべきことは `next-method'
を呼ぶことです。

   上のコードを点検してみましょう。`(make <shape> args ...)' を呼ぶと、
システムは `<shape>' のインスタンスのためのメモリを確保し、
`initialize' ジェネリック関数を、そのインスタンスと `args ...'
で呼びます。これは、いま自分で定義した `initialize' にディスパッチ
されます。その中で `next-method' よび、それがこんどは `<object>'
クラスの `initialize' メソッドをよびます。これでこのインスタンスは
init-value と init-keyword で初期化されます。`next-method' からもどった
あと、新しい `<shape>' インスタンスをグローバルの shape リストに
`*shapes*' に登録します。

   この `<shape>' クラスは shape
の抽象的概念を表現しているにすぎません。
では、いくつかの具体的な描画可能な shape を `<shape>' の
_サブクラス化_によって定義しましょう。

     (define-class <point-shape> (<shape>)
       ((point  :init-form (make <2d-point>) :init-keyword :point)))

     (define-class <polyline-shape> (<shape>)
       ((points :init-value '() :init-keyword :points)
        (closed :init-value #f  :init-keyword :closed)))

   `define-class' の第二引数に注目してください。これは `<point-shape>'
および `<polyline-shape>' が `<shape>'
クラスのスロットを継承していることを示しています。そして `<shape>'
クラスが受け入れるものはすべて、それらのサブクラスでも受け入れらること
も示しています。

   `<point-shape>' には `point' というスロットがひとつ追加
されています。このスロットはこの節の最初で定義した、`<2d-point>' の
インスタンスを持ちます。`<polyline-shape>' クラスは点のリスト、
フラグを格納します。フラグは多角形のラインが終点と始点つないでいるか
どうかを指定します。

   継承はとりあつかいに注意が必要な強力な機構です。うっかりするとすぐに
追跡不能なコードができあがります。(Paul Graham は『百年の言語』という
記事のなかで、「オブジェクト指向プログラミングはスパゲッティコードを
書くための持続的な方法を提供してくれる。」と言っているように。)
経験則からいうとサブタイプが必要なときにサブクラスを作るのがよいようです。
スロットの継承は付随するなにかではありますが、サブクラス化のための
主要な理由にしてはいけません。`<point-shape>' クラスでやったように
サブストラクチャを「インクルード」することは常にできるのです。

   `<point-shape>' クラスに新しいスロットオプションがあらわれました。
`:init-form' というスロットオプションは、init-keyword が `make'
に与えられなかったときのそのスロットのデフォルト値を指定します。
しかし、クラス定義時に評価される `:init-value' の値とはちがって、 この
`:init-form' をともなう値はシステムが実際のその値を必要とした
ときに評価されます。したがって、`<point-shape>' のインスタンス
では、`<point-shape>' インスタンスが `:point' キーワード引数を
わたされずに生成されたときにのみ、デフォルトの `<2d-point>'
インスタンスが生成されます。

   shape は別のデバイスに別の方法で描画され得ます。いまのところは、
PostScript 出力だけを考慮しましょう。`draw' メソッドに多相性を持たせる
ために、PostScript 出力デバイス `<ps-device>' を定義します。

     (define-class <ps-device> () ())

   こうすると、`<shape>' および `<ps-device>' の両方に特定化した `draw'
メソッドを書くことができます。

     (define-method draw ((self <shape>) (device <ps-device>))
       (format #t "gsave\n")
       (draw-path self device)
       (apply format #t "~a ~a ~a setrgbcolor\n" (ref self 'color))
       (format #t "~a setlinewidth\n" (ref self 'thickness))
       (format #t "stroke\n")
       (format #t "grestore\n"))

   このコードでは DEVICE 引数はメソッド本体内では使われていません。
メソッドディスパッチのためのみに使われます。いずれ別の出力デバイス
を必要になったら、そのデバイスに特定化した `draw' メソッドを
追加することができます。

   上の `draw' メソッドは共通の仕事をしますが、実際の描画は
それぞれのサブクラス用に特定化された方法で行わなければなりません。

     (define-method draw-path ((self <point-shape>) (device <ps-device>))
       (apply format #t "newpath ~a ~a 1 0 360 arc closepath\n"
              (point->list (ref self 'point))))

     (define-method draw-path ((self <polyline-shape>) (device <ps-device>))
       (let ((pts (ref self 'points)))
         (when (>= (length pts) 2)
           (format #t "newpath\n")
           (apply format #t "~a ~a moveto\n" (point->list (car pts)))
           (for-each (lambda (pt)
                       (apply format #t "~a ~a lineto\n" (point->list pt)))
                     (cdr pts))
           (when (ref self 'closed)
             (apply format #t "~a ~a lineto\n" (point->list (car pts))))
           (format #t "closepath\n"))))

     ;; utility method
     (define-method point->list ((pt <2d-point>))
       (list (x-of pt) (y-of pt)))

   最後にもう少しだけ、ハックしましょう。`draw' メソッドを shape
のリストに対しても動作するようにします。こうすれば、
同一ページ内で複数の shape をひつまとめで描画できます。

     (define-method draw ((shapes <list>) (device <ps-device>))
       (format #t "%%\n")
       (for-each (cut draw <> device) shapes)
       (format #t "showpage\n"))

   これで簡単な図を書けるようになります。

     (use srfi-1)      ;; for iota
     (use math.const)  ;; for constant pi

     (define (shape-sample)

       ;; creates 5 corner points of pentagon
       (define (make-corners scale)
         (map (lambda (i)
                (let ((pt (make <2d-point>)))
                  (move-by! pt (make-polar scale (* i 2/5 pi)))
                  (move-by! pt 200 200)
                  pt))
              (iota 5)))

       (set! *shapes* '())  ;; clear the shape list
       (let* ((corners (make-corners 100)))
         ;; a pentagon in green
         (make <polyline-shape>
           :color '(0 1 0) :closed #t
           :points corners)
         ;; a star-shape in red
         (make <polyline-shape>
           :color '(1 0 0) :closed #t
           :points (list (list-ref corners 0)
                         (list-ref corners 2)
                         (list-ref corners 4)
                         (list-ref corners 1)
                         (list-ref corners 3)))
         ;; put dots in each corner of the star
         (for-each (cut make <point-shape> :point <>)
                   (make-corners 90))
         ;; draw the shapes
         (draw *shapes* (make <ps-device>)))
       )

   関数 `shape-sample' は現在の出力ポートに簡単な PostScript
の描画コード
を書き出します。これを以下のような式でファイルに出力し、GhostScriptなどの
PostScriptビューワで結果を見てください。

     (with-output-to-file "oointro.ps" shape-sampe)


File: gauche-refj.info,  Node: 一般的な問い合わせ,  Next: クラス,  Prev: オブジェクトシステムの紹介,  Up: オブジェクトシステム

7.2 一般的な問い合わせ
======================

 -- Function: class-of obj
     OBJのクラスを返します。

          (class-of 3)         => #<class <integer>>
          (class-of "foo")     => #<class <string>>
          (class-of <integer>) => #<class <class>>

 -- Function: is-a? obj class
     OBJがCLASSのインスタンスであるか、CLASSのサブクラスの
     インスタンスである場合に、真を返します。

          (is-a? 3 <integer>)   => #t
          (is-a? 3 <real>)      => #t
          (is-a? 5+3i <real>)   => #f
          (is-a? :foo <symbol>) => #f

OBJのクラスが再定義されてしまうと、これらの手続きは、最初に
OBJのクラスを新しいクラスに変更します。したがって、`class-of' は
いつも新しいクラスを返します。この振舞いは stklos 0.55 とは異ります。
stklos 0.55 では `class-of'は、OBJが更新されていなければ、
旧いクラスを返します。もし、旧いクラスが必要なばあいは、以下の
`current-class-of' を使うべきです。クラス再定義のセマンティクスの
詳細については *Note クラスの再定義:: を見てください。

 -- Function: current-class-of obj
     OBJ のクラスメタオブジェクトを返します。OBJ のクラスが
     再定義されてしまった場合でも、OBJ がその変更に合せて更新されて
     いない場合には、この手続きは OBJ の元のクラスを返します。
     この手続きは、OBJ を更新しません。

     この手続きはめったに必要にはなりません。必要になるのは
     `change-class' メソッド内で、OBJ
     の更新のトリガーを引きたくないような場合
     (無限ループを起す可能性がある場合)です。


File: gauche-refj.info,  Node: クラス,  Next: インスタンス,  Prev: 一般的な問い合わせ,  Up: オブジェクトシステム

7.3 クラス
==========

この節では、Gauche におけるクラスについて詳しく説明します。

* Menu:

* クラスの定義::
* 継承::
* クラスオブジェクト::
* スロット定義オブジェクト::
* クラスの再定義::
* クラスの定義例::


File: gauche-refj.info,  Node: クラスの定義,  Next: 継承,  Prev: クラス,  Up: クラス

7.3.1 クラスの定義
------------------

クラスを定義するには、`define-class' マクロを使います。

 -- Macro: define-class name supers (slot-spec ...) option ...
     引数によって指定されたクラスオブジェクトを作成し、それを NAME に
     グローバルに束縛します。このマクロはトップレベルでのみ使うことができます。

     SUPERS はそのクラスが継承する直接のスーパークラスのリストです。
     多重継承も使えます。継承の詳細については*Note 継承::
     を参照して下さい。

     SLOT-SPEC は「スロット」の仕様で、他の言語ではよく
     「フィールド」や「インスタンス変数」と呼ばれるものです (SLOT-SPEC
     を使って「クラス変数」を指定することもできます)。 SLOT-SPEC
     の最も単純なフォームはシンボルそのもので、その名前が
     スロットであるものです。あるいは、最初の要素がシンボルで残りの要素が
     キーワードと値が交互に来るリストを渡すこともできます。

     このリストフォームは、スロットの名前を定義するだけでなく、そのスロットの
     振る舞いも定義します。スロットの定義については以下で説明します。

     最後に、OPTION ... は、クラスオブジェクトがどのように
     作られるかを指定する、キーワードと値が交互に来るリストです。

     このマクロでは1つのキーワード引数、`:metaclass' により、
     メタクラス(他のクラスをインスタンス化するクラス)を指定できます。
     他のオプションはクラスオブジェクトを作成するために、`make'
     メソッドに渡されます。メタクラスの使用方法については、 *Note
     クラスのインスタンシエーション::を参照。

   スロットの指定はリストで、以下のようなフォームであるべきです。

     (SLOT-NAME :option1 value1 :option2 value2 ...)

   各キーワード(`option1' など) は _slot option_ を与えます。
デフォルトでは、以下のスロットオプションが認識されます。
メタクラスを定義することで、デフォルト以外のスロットオプションを
追加できます。

`:allocation'
     このスロットのアロケーションタイプを指定します。これは、このスロットが
     どのように値を格納するかを指定します。以下のようなキーワード値が
     標準クラスによって認識されます。プログラマは、自分用のメタクラスを定義し、
     これら以外のアロケーションタイプを認識するように、このクラスを拡張すること
     ができます。

    `:instance'
          スロットは各インスタンス毎にアロケートされます。したがって、おのおのの
          インスタンスは別々の値をもてます。これは、いわゆる「インスタンス
          変数」の振舞いを実現します。`:allocation' スロットオプションが
          省略された場合、これがデフォルトとなります。

    `:class'
          スロットはクラスオブジェクト自身にアロケートされます。したがって、おのおのの
          インスタンスはこのスロットの同じ値を共有します。これは、いわゆる
          「クラス変数」の振舞いを実現します。このスロットの値は、すべてのサブクラス
          でも共有されます。(ただし、サブクラスの定義がこのスロットをシャドウする
          場合には、そのかぎりではありません。)

    `:each-subclass'
          `class'
          アロケーションと似ていますが、スロットはクラス毎にアロケート
          されます。すなわち、このスロットは、このクラスのすべてのインスタンスで
          共有されますが、サブクラスのインスタンスには共有されません。

    `:virtual'
          このタイプのスロット用には格納領域はアロケートされません。このスロット
          にアクセスすると以下で説明する `:slot-ref' および `:slot-set!'
          オプションで与えられた手続きが呼ばれます。いいかえれば、手続きスロットを
          作成できるということです。スロットアロケーションが virtual
          と指定されて いる場合、少なくとも `:slot-ref'
          オプションが同時に
          指定されていなければなりません。さもなければ、`define-class'
          は エラーを発生させます。

    `:builtin'
          このアロケーションタイプは組み込みクラスの中だけに現れます。
          Scheme 定義のクラスでこのタイプを指定することはできません。

`:init-keyword'
     このスロットオプションに与えられたキーワード値は、インスタンスが生成
     される際に `make' メソッドに初期値をわたすために使えます。

`:init-value'
     生成時にキーワード引数で初期化されてないスロットの場合、これによって
     スロットの初期値を与えます。その値は `define-class' が評価される
     ときに、評価されます。

`:init-form'
     `init-value' と似ていますが、与えられた値は thunk で包まれていて、
     その値が必要とされた時に毎回評価されます。`init-value' と
     `init-form' との両方が与えられた時には `init-form' が無視されます。
     実際には、`:init-form EXPR' は `define-class' マクロの
     `:init-thunk (lambda () EXPR)' に変換されます。

`:initform'
     `init-form' と同義です。STk
     との互換性のためにあります。新しくコードを
     書く場合には使うべきではありません。

`:init-thunk'
     thunk
     を与えます。もし、当該スロットが生成時にキーワード引数によって
     初期化されていなければ、その thunk
     を評価して当該スロットの初期値とします。 `:init-form' に `value'
     を与えることと、`:init-thunk' に `(lambda () value)'
     を与えることは同じことです。

`:getter'
     シンボルをとり、getter
     メソッドを生成し、同じ名前のジェネリック関数に 束縛します。getter
     メソッドは当該クラスのインスタンスを引数とし、当該
     スロットの値を返します。

`:setter'
     シンボルをとり、setter
     メソッドを生成し、同じ名前のジェネリック関数に 束縛します。setter
     メソッドは当該クラスのインスタンスと値をひとつ引数
     として、そのインスタンスの当該スロットの値をその値にセットします。

`:accessor'
     シンボルをとり、2 つのメソッド(getter メソッドと setter メソッド)を
     生成します。getter メソッドは与えられた名前のジェネリック関数に
     束縛され、setter メソッドは、与えられた名前のジェネリック
     関数のsetterとして追加されます(setter については *Note 代入::
     を参照して下さい)。

`:slot-ref'
     評価すると引数(インスタンス)を一つとる手続きとなる値を指定します。
     このスロットオプションは当該スロットのアロケーションが `virtual'
     である場合、必ず指定されていなければなりません。プログラムが
     `slot-ref'やgetter メソッドを使って
     当該スロットの値を得ようとすると、
     このオプションに指定された手続きが呼ばれ、その結果が
     当該スロットの値として返されます。手続きは undef 値を返し
     (`undefined'の戻り値)、スロットが値をもっていないことを示す
     ことができます。もしスロットのアロケーションが `virtual' で
     なければ、このスロットオプションは無視されます。

`:slot-set!'
     評価すると二つの引数(インスタンスと値)をとる手続きとなる値を指定します。
     プログラムが`slot-set!' あるいは setter メソッドを使って
     当該スロットに値をセットしようとするときに、
     指定した手続きがインスタンスとセットすべき値を引数として
     呼ばれます。スロットアロケーションが
     `virtual'でなければ、このスロットオプションは無視されます。
     このスロットオプションの無いvirtualスロットはリードオンリースロットとなります。

`:slot-bound?'
     評価すると引数(インスタンス)を一つとる手続きとなる値を指定します。
     このスロットオプションは当該スロットのアロケーションが `virtual'
     である場合しか意味を持ちません。
     プログラムが当該スロットが値を持っているかどうかを決定しようとしたときに、
     この手続きを呼ばれます。手続きは、スロットが値をもつなら、真の値を、
     そうでなければ`#f' を返します。仮想スロットに対して、このスロット
     オプションが省略されると、システムは代りに `slot-ref' に与えられ
     た手続きを呼び、それが、`#<undef>' を返すかどうか見ます。


File: gauche-refj.info,  Node: 継承,  Next: クラスオブジェクト,  Prev: クラスの定義,  Up: クラス

7.3.2 継承
----------

継承にはふたつの役割があります。第一に、スロットを追加することで
既存のクラスを_拡張_できます。第二には、既存のクラス
関連するメソッドを_特定化_して、元々のメソッドよりもすこし
特定化した仕事をやらせるようにできます。

   いくつかの用語を定義しておきましょう。クラス `<T>' がクラス
`<S>'を継承しているとき、`<T>' を `<S>' の _サブクラス_といい、`<S>' を
`<T>' の _スーパークラス_といいます。この関係は推移的です。すなわち、
`<T>' のサブクラスは、やはり `<S>' のサブクラスであり、 `<S>'
のスーパークラスは、やはり `<T>' のスーパークラスです。 特に、`<T>' が
`<S>' を直接継承している場合、すなわち、 `<S>' が `<T>'
を定義する際のスーパークラスリストに 現われている場合には `<S>' を
`<T>' の _直接スーパークラス_といい、`<T>' を `<S>' の
_直接サブクラス_といいます。

クラスを定義したとき、そのクラスとそのスーパークラスは、サブクラスから
スーパークラスという順序になり、クラスのリストがその順で生成されます。
このリストのことを_クラス順位リスト_、あるいは CPL といいます。
すべてのクラスはそれぞれ自身の CPL を持っています。 クラスの CPL
は常に自分自身からはじまり、`<top>' で終ります。

   手続き `class-precedence-list' を用いてクラスの CPL を問い合わせ
ることができます。

     gosh> (class-precedence-list <boolean>)
     (#<class <boolean>> #<class <top>>)
     gosh> (class-precedence-list <string>)
     (#<class <string>> #<class <sequence>> #<class <collection>> #<class <top>>)

   見るとわかるように、すべてのクラスは `<top>' という名前のクラスを
継承しています。組み込みクラスには、いくつかの抽象クラスを CPL 中で
自分自身と `<top>' の間に連ねているものもあります。上の例では
`<string>' クラスは `<sequence>' と `<collection>' を
継承しています。これは、文字列がシーケンスとしても、コレクションとして
も振舞うことができるということです。

     gosh> (is-a? "abc" <string>)
     #t
     gosh> (is-a? "abc" <sequence>)
     #t
     gosh> (is-a? "abc" <collection>)
     #t

   Schemeで定義したクラスの継承についてはどうでしょう。
単一継承なら、CPL は直截的です。そのクラスのスーパークラス、
スーパークラスのスーパークラス、
スーパークラスのスーパークラスのスーパークラス、... と `<top>'
に到達するまで、たどっていけます。例を見てください。

     gosh> (define-class <a> () ())
     <a>
     gosh> (define-class <b> (<a>) ())
     <b>
     gosh> (class-precedence-list <b>)
     (#<class <b>> #<class <a>> #<class <object>> #<class <top>>)

   Scheme定義のクラスは常に `<object>' を継承します。
システムが自動的に挿入します。

多重継承が使われる場合には話はすこし複雑になります。複数のスーパークラスの
複数の CPL をひとつの CPL にマージしなければなりません。このことを
_線形化_といい、いくつかの線形化戦略が知られています。Gauche では
デフォルトで _C3 線形化_と呼ばれているアルゴリズムを使います。
このアルゴリズムは局所的な順位、単調性、拡張順位グラフと整合性のとれた
ものです。ここでは詳細に立ち入りませんが、一般的なルールとして、 CPL
中のスーパークラスの順序は、つねにそのクラスの直接スーパークラスの
順序、それぞれのスーパークラスの CPL の順序、および、各スーパークラス
の直接スーパークラスの順序、などと整合性をもちます。正確な説明について
は*Note [Dylan]: dylan.を参照してください。

   もしクラスが、整合性を満した CPL を構築できないようなやり方で
複数のスーパークラスを継承すると、エラーになります。以下は多重継承の
単純な例です。

     (define-class <grid-layout> () ())

     (define-class <horizontal-grid> (<grid-layout>) ())

     (define-class <vertical-grid> (<grid-layout>) ())

     (define-class <hv-grid> (<horizontal-grid> <vertical-grid>) ())

     (map class-name (class-precedence-list <hv-grid>))
      => (<hv-grid> <horizontal-grid> <vertical-grid>
          <grid-layout> <object> <top>)

   `<hv-grid>' の直接スーパークラス(`<horizontal-grid>'と
`<vertical-grid>')の順序が保存されていることに注意してください。

   以下は、すこしひねくれた例です。

     (define-class <pane> () ())

     (define-class <scrolling-mixin> () ())

     (define-class <scrollable-pane> (<pane> <scrolling-mixin>) ())

     (define-class <editing-mixin> () ())

     (define-class <editable-pane> (<pane> <editing-mixin>) ())

     (define-class <editable-scrollable-pane>
        (<scrollable-pane> <editable-pane>) ())

     (map class-name (class-precedence-list <editable-scrollable-pane>))
      => (<editable-scrollable-pane> <scrollable-pane>
          <editable-pane> <pane> <scrolling-mixin> <editing-mixin>
          <object> <top>)

いったんクラス順位が決まると、定義されたクラスのスロットが以下の手順で
計算されます。スロットの定義が CPL 中のスーパークラスからサブクラスへの
順で集められます。サブクラスにスーパークラスと同じ名前のスロット定義が
あった場合には、サブクラスのそのスロット定義が採用され、スーパークラス
の方の定義は捨てられます。あるクラス `<S>' がスロット `a'、 `b'、および
`c' を定義しており、あるクラス `<T>' が スロット `c'、`d'、および `e'
を定義し、さらに、 あるクラス `<U>' がスロット `b' および `e'
を定義していると しよう。`<U>' の CPL が `(<U> <T> <S> <object> <top>)'
と なっている場合、`<U>' のスロットが下の図のように計算されます。
すなわち、`<U>' は 5つのスロットは 5 つのスロットをもち、 `b' および
`e' の定義は `<U>' のものを、`c' および `d' の定義は `<T>'
由来のものを、そして、`a' の定義は `<S>' 由来のものとなります。

        CPL         | スロットの定義
                    |  () はシャドウされたスロットを表す
      --------------+-------------------
        <top>       |
        <object>    |
        <S>         | a  (b) (c)
        <T>         |         c   d  (e)
        <U>         |     b           e
      --------------+--------------------
      <U>のスロット | a   b   c   d   e

   `class-slots' 関数を使ってクラスオブジェクトのスロット定義の
リストを得ることができます。

   上述の振舞いはデフォルトの振舞いにすぎないことに注意してください。
CPL の計算方法あるいはスロット定義の継承方法は、メタクラスを
定義することでカスタマイズ可能です。たとえば、同じスロット名の
スロットオプションはどれかが他のものをシャドウしますが、これを
マージすることができるようにメタクラスを書くことができます。
あるいは、サブクラスがスーパークラスのスロットをシャドウするのを
禁止するようにメタクラスを書くことができます。


File: gauche-refj.info,  Node: クラスオブジェクト,  Next: スロット定義オブジェクト,  Prev: 継承,  Up: クラス

7.3.3 クラスオブジェクト
------------------------

クラスとは何か。Gauche ではクラスはオブジェクトをインスタンス化して
ある特定の機能を実装するようなオブジェクトにすぎません。
そうなので、スロットの値を見るだけで、クラス内部を覗けます。
このように内部を覗くのに便利な手続きがいくつか用意されています。
これらの手続きがリストを返す場合、それはクラスに所属するもので、
変更してはいけないということに注意してください。

 -- Function: class-name class
     CLASS の名前を返します。

          (class-name <string>) => <string>

 -- Function: class-precedence-list class
     CLASS のクラス順位リストを返します。

          (class-precedence-list <string>)
            => (#<class <string>>
                #<class <sequence>>
                #<class <collection>>
                #<class <top>>)

 -- Function: class-direct-supers class
     CLASS の直接スーパークラスのリストを返します。
     直接スーパークラスは CLASS が直接継承しているクラスです。

          (class-direct-supers <string>)
            => (#<class <sequence>>)

 -- Function: class-direct-subclasses class
     CLASS の直接サブクラスのリストを返します。 直接サブクラスは CLASS
     を直接継承しているクラスです。 `<T>' が `<S>'
     の直接サブクラスであれば、 `<S>' は `<T>'
     の直接スーパークラスです。

 -- Function: class-slots class
     CLASS の _スロット定義_ のリストを返します。スロット定義は
     リストで、その car 部はスロット名、cdr
     部はスロットオプションを指定する
     キーワード値のリストです。スロット定義内部を覗いてスロットのもつ性格を
     知ることができます。詳しくは *Note スロット定義オブジェクト:: を
     参照してください。

     与えられたクラスのスロット名のリストを得るための標準的な方法は、
     `(map slot-definition-name (class-slots class))' です。

 -- Function: class-slot-definition class slot-name
     クラス CLASS 中の SLOT-NAME で指定されたスロットの
     スロット定義を返します。CLASS が指定した名前のスロットを
     持たなければ `#f' が返ります。

 -- Function: class-direct-slots class
     当該クラスで直接定義されている(つまりスーパークラスから継承された
     ものではない)スロット定義のリストを返します。この情報は、クラスの
     初期化の際にスロットの継承を処理するために利用されます。

 -- Function: class-direct-methods class
     CLASSを特定化子中にもつメソッドのリストを返します。

 -- Function: class-slot-accessor class slot-name
     CLASS で SLOT-NAME で指定したスロットの
     スロットアクセサオブジェクトを返します。
     スロットアクセサオブジェクトは内部オブジェクトで与えられたスロットへの
     アクセス方法、変更方法、初期化の方法という情報をカプセル化しています。

     メタオブジェクトプロトコルを使って特別なスロットを定義するのでなければ、
     通常スロットアクセサオブジェクトを扱う必要はありません。


File: gauche-refj.info,  Node: スロット定義オブジェクト,  Next: クラスの再定義,  Prev: クラスオブジェクト,  Up: クラス

7.3.4 スロット定義オブジェクト
------------------------------

`class-slots' が返すスロットの定義オブジェクト `class-direct-slots'
および `class-slot-definition' はスロットに関する情報を保持しています。
現時点では Gauche
はスロット定義を表現するのにリストを使っています。これは STklos や
TinyCLOS と同じです。しかし、Gauche が将来にわたって、この構造を
保持するかどうかは保証のかぎりではありません。スロット定義オブジェクトの
情報を得るには以下のそれ専用のアクセサメソッドを使うべきです。

 -- Function: slot-definition-name slot-def
     スロット定義オブジェクト SLOT-DEF で与えられたスロットの名前を
     返します。

 -- Function: slot-definition-options slot-def
     SLOT-DEF のスロットオプションのキーワード値リストを返します。

 -- Function: slot-definition-allocation slot-def
     SLOT-DEF の `:allocation' オプションの値を返します。

 -- Function: slot-definition-getter slot-def
 -- Function: slot-defininion-setter slot-def
 -- Function: slot-definition-accessor slot-def
     それぞれ、SLOT-DEF の `:getter'、`:setter' および `:accessor'
     スロットオプションの値を返します。

 -- Function: slot-definition-option slot-def option &optional default
     SLOT-DEF のスロットオプション OPTION の値を返します。
     そのようなオプションがない場合には、DEFAULT が与えられていれば
     それを返し、さもなければ、エラーシグナルがあがります。


File: gauche-refj.info,  Node: クラスの再定義,  Next: クラスの定義例,  Prev: スロット定義オブジェクト,  Up: クラス

7.3.5 クラスの再定義
--------------------

`define-class' を使うとき、指定したクラス名がすでにあるクラスに束縛
されている場合、これは元々のクラスの_再定義_と看倣されます。

   クラスの再定義は以下の操作を意味します。
   * 新しいクラスオブジェクトは新しい定義にもとづいて生成され、
     `define-class' に与えられた変数に束縛されます。

   * 元々のクラスに対して定義されたメソッド(すなわち、特定化子の中に
     元々のクラスを持つメソッド)は新しいクラス上で定義されたように
     変更されます。

   * 元々のクラスの直接スーパークラスの直接サブクラスリンクは、
     新しいクラスを指すように変更されます。

   * 元々のクラスのすべてのサブクラスはそのクラスの変更を反映するように
     再帰的に再定義されます。各クラスはその初期化引数を覚えており、
     再定義されたサブクラスは元々のサブクラスと同じ初期化引数を受けとります。

   * 元々のクラスには_再定義_マークが付きます。

元々のクラスと新しいクラスは別のオブジェクトであることに注意してください。
元々のクラスオブジェクトは元々どのモジュールでどの変数に束縛されていたかを
覚えており、この束縛を新しいクラスに置き換えます。どこかで、元々のクラスへ
の直接参照を持っていれば、その参照は元々クラスへの参照のままです。この点
については特に注意してください。`class-redefinition' メソッドを
定義することによりクラス再定義の振舞いをカスタマイズできます。 詳しくは
*Note メタオブジェクトプロトコル::を参照してください。

   元々のクラスのインスタンスが存在している場合、それらのインスタンスは
以下のようなメソッドでアクセスあるいは変更しようとしたときに自動的に
更新されます。`class-of'、`is-a?'、`slot-ref'、
`slot-set!'、`ref'、getterメソッド、setterメソッド。

インスタンスの更新とは、インスタンスのクラスを(旧いクラスから新しいクラスへ)
変更するということです。デフォルトでは、元々のクラスと新しいクラスで
共通のスロットの値はそのまま引き継がれます。新しいクラスで追加された
スロットは新しいクラスでのそのスロットの仕様にしたがって初期化されます。
元々のクラスから削除されたスロットの値は破棄されます。この振舞いは、
`change-class' メソッドを書くことでカスタマイズできます。詳しくは *Note
クラスの変更:: を参照してください。

スレッド安全性について
......................

クラス再定義処理はローカルな処理ではなく、多くの副作用を行います。
複数のスレッドが同時にクラス再定義プロトコルを走らせた場合の
安全性を保証するのは困難です。そこでGauche
では、一度にひとつのスレッドしか
クラス再定義プロトコルに入らないように、プロセスレベルのロックを使用します。

   スレッドが、別のスレッドが再定義プロトコルにいる最中にクラスを
再定義しようとした場合、たとえ、別々のクラスを再定義しようとしている
場合でも、そのスレッドはブロックされます。このようにするのは、
再定義がそのすべてのサブクラス、そのクラスとそのサブクラスに
関わるすべてのメソッドおよびジェネリック関数に影響するからで、
ふたつのクラスが完全に独立であるかどうかを決定するのは、自明では
ないからです。

   スレッドが他のスレッドが再定義しようとしているクラスのインスタンスに
アクセスしようとした場合にも、このスレッドは再定義が完了するまで、
ブロックされます。

   インスタンス更新プロトコルは直列化されません。ふたつのスレッドが
再定義されたクラスのインスタンスにアクセスしようとすると、両方の
スレッドが更新プロトコルを起動します。これは好ましくない競合状態を
生じる可能性があります。このような場合がおきないようにするのは
アプリケーションの責任です。インスタンスへのアクセスはどのみち
システムが直列化するわけではないので、これは自然なことです。
インスタンス内に mutex を持たせる場合は特に注意が必要です。
インスタンス中のmutexにアクセスするだけでインスタンス更新プロトコルを
起動することになる可能性があるからです。

互換性に関して
..............

クラス再定義プロトコルは CLOS風の Scheme システムとは微妙に違います。
Gauche のものは STklos のものによく似ていますが、STklos 0.56 は再定義
サブクラスの束縛を置き換えず、初期化引数を覚えたりはしないので、
再定義されたサブクラスは、元々のサブクラスが持っていた情報のなにがしかを
失ってしまう可能性があるという点にちがいがあります。Guile のオブジェクト
システムはクラス再定義プロトコルの最後で、元々のクラスのアイデンティティと
再定義されたクラスをアイデンティティを入れ替えてしまします。それゆえ、
元々のクラスへの参照は、再定義されたクラスへの参照となります。筆者が
知るかぎり、クラス再定義は、STklos 0.56 においても、Guile 1.6.4
においても スレッド安全ではありません。


File: gauche-refj.info,  Node: クラスの定義例,  Prev: クラスの再定義,  Up: クラス

7.3.6 クラスの定義例
--------------------

いくつかの例をみましょう。グラフィカルツールキットを定義しているところ
だということにしましょう。`<window>' はスクリーン上の矩形領域で、
幅と高さを持ちます。これを階層構造に構成することが可能です。すなわち、
ある window は別の window 中に置くことができ、親 window へのポインタを
もっているものとします。window の位置は、親ウィンドウの位置からの
相対座標、x と y で指定します。スクリーン全体を覆う「ルート」window
を作り、これがデフォルトの親 window にもなります。ここまでで、次のように
なります。

     ;; The first version
     (define-class <window> ()
       (;; Pointer to the parent window.
        (parent      :init-keyword :parent :init-form *root-window*)
        ;; Sizes of the window
        (width       :init-keyword :width  :init-value 1)
        (height      :init-keyword :height :init-value 1)
        ;; Position of the window relative to the parent.
        (x           :init-keyword :x :init-value 0)
        (y           :init-keyword :y :init-value 0)
        ))

     (define *screen-width* 1280)
     (define *screen-height* 1024)

     (define *root-window*
       (make <window> :parent #f :width *screen-width* :height *screen-height*))

   `:init-value' および `:init-form' の使い方に注意してください。
`<window>' クラスが定義されたとき、`*root-window*' はまだ束縛
されていませんので、ここでは `:init-value' は使えません。

     gosh> *root-window*
     #<<window> 0x80db1d0>
     gosh> (define window-a (make <window> :width 100 :height 100))
     window-a
     gosh> (d window-a)
     #<<window> 0x80db1b0> is an instance of class <window>
     slots:
       parent    : #<<window> 0x80db1d0>
       width     : 100
       height    : 100
       x         : 0
       y         : 0
     gosh> (define window-b
             (make <window> :parent window-a :width 50 :height 20 :x 10 :y 5))
     window-b
     gosh> (d window-b)
     #<<window> 0x80db140> is an instance of class <window>
     slots:
       parent    : #<<window> 0x80db1b0>
       width     : 50
       height    : 20
       x         : 10
       y         : 5

   筆者と同じ感覚の持ち主なら、`*root-window*' のようなグローバル
変数をツールキットのユーザに見せたいとは思わないでしょう。これを
カプセル化するひとつの方法は、ルート window へのポインタをクラス変数に
保持させることです。`<window>' の定義に以下のようなスロットオプションを
追加すると `<window>' クラスの `root-window' スロットは同じ
格納領域を参照するようになります。

     (define-class <window> ()
       (...
        ...
        (root-window :allocation :class)
        ...))

   `<window>' のインスタンスに対して、`slot-ref' および `slot-set!'
を、また、`<window>' クラスそのものに対しては、 `class-slot-ref' や
`class-slot-set!' を使って `root-window'
スロットの値を取得したり、セットしたりできます。

   ツールキットのユーザは window
の相対座標のかわりに絶対座標(ルートウィンドウ
中の座標)が欲しいと思うことがあるでしょう。以下のようにして、絶対座標を
返す仮想スロットを提供することができます。

     (define-class <window> ()
       (...
        ...
        (root-x :allocation :virtual
                :slot-ref  (lambda (o)
                             (if (ref o 'parent)
                                 (+ (ref (ref o 'parent) 'root-x)
                                    (ref o 'x))
                                 (ref o 'x)))
                :slot-set! (lambda (o v)
                             (set! (ref o 'x)
                                   (if (ref o 'parent)
                                       (- v (ref (ref o 'parent) 'root-x))
                                       v)))
                 )
         ...))

メソッドあるいは仮想スロット経由のこのようなインタフェースを供給することは
いくぶんか趣味の問題です。仮想スロットは実装の変更を隠すことができるという
利点があります。つまり、`root-x' を実スロットに保持するように変更し、
`x' をあとで仮想スロットに変更するということを `<window>'を
使うコードをだめにすることなくおこなえます。オブジェクト指向の主流の言語
では、通常このような「実装変更の隠蔽」はインスタンス変数を隠し、メソッドを
公開するということでおこなわれています。Gauche やその他の CLOS
風システムでは
スロットは常にユーザから見えており状況はすこし違うのです。


File: gauche-refj.info,  Node: インスタンス,  Next: ジェネリックファンクションとメソッド,  Prev: クラス,  Up: オブジェクトシステム

7.4 インスタンス
================

この節では、インスタンスの生成のしかたと使い方について説明します。

* Menu:

* インスタンスの作成::
* インスタンスへのアクセス::
* クラスの変更::


File: gauche-refj.info,  Node: インスタンスの作成,  Next: インスタンスへのアクセス,  Prev: インスタンス,  Up: インスタンス

7.4.1 インスタンスの作成
------------------------

クラスオブジェクトをつかうと、ジェネリック関数 `make' でその
クラスのインスタンスを生成できます。標準の `<class>' に対して
特定化されたメソッドは以下のとおり定義されています。

 -- Generic Function: make
 -- Method: make (class <class>) arg ...
     CLASS のインスタンスを生成し、それを返します。ARG ... は
     典型的な場合には、そのインスタンスを初期化するためのキーワード値のリストです。

   概念としては、デフォルトの `make' メソッドは以下のように定義されて
います。

     (define-method make ((class <class>) . initargs)
       (let ((obj (allocate-instance class initargs)))
         (initialize obj initargs)
         obj))

   すなわち、最初、`class' のインスタンス用にメモリをアロケートし、
それから、INITIALIZE メソッドを用いてそれを初期化します。

 -- Generic Function: allocate-instance
 -- Method: allocate-instance (class <class>) initargs
     CLASSの新規にアロケートされた、初期化されていないインスタンスを返します。

 -- Generic Function: initialize
 -- Method: initialize (obj <object>) initargs
     `<object>'
     に対するデフォルトの初期化メソッドは以下のように働きます。

        * そのクラスの初期化可能なスロットのそれぞれに対して、
             * もし (そのスロットが :init-keyword
               スロットオプションを持ち、「かつ」 そのキーワードが
               INITARGS 中にある)
               そのときは、対応する値がそのスロットを初期化するのに使われます。

             * そうではないとき、もし、そのスロットが、:init-value
               スロットオプションを
               持てば、そのオプションに与えられた値がそのスロットを初期化するのに使われます。

             * そうでもないとき、もし、そのスロットが、:init-thunk
               スロットオプションを 持てば、その thunk
               が呼ばれその返り値が、そのスロットを初期化するのに
               使われます。

             * さらにどれでもなければ、そのスロットは未束縛のままです。

     デフォルトのスロットアロケーションクラスのなかで、インスタンスアロケート
     スロットだけが初期化可能で、上の流れで処理されます。クラスアロケート
     スロット(すなわち、スロットアロケーションが `:class' あるいは
     `:each-subclass' のどちらかの場合)は、`:init-value' あるいは
     `:init-form'
     スロットオプションが与えられていれば、クラスオブジェクト
     生成時に初期化されます。仮想スロットが、初期化されることはありません。

     ユーザ定義アロケーションクラスは、初期化可能にも不可能にも設定することが
     できます。詳しくは *Note メタオブジェクトプロトコル::
     を参照してください。

     INITIALIZE メソッドを特定化する場合には `next-method' が
     確実に呼ばれるようにして、新しく生成されたインスタンスのすべての
     スロットにアクセスする前にデフォルトの流れで、そのスロットが正しく
     初期化されるようにしてください。

   定義したクラスに対応する `initialize' メソッドを特定化して
インスタンスの初期化の方法をカスタマイズするというのが、典型的な
やりかたです。

   `allocate-instance' メソッドを特定化するというのは一般的な方法では
ありません。しかしながら、`make' がどのように働くかを知っているなら、
`make' そのものを特定化して、なんらかの状況(たとえば、アロケート
前のインスタンスを使うというような状況)でインスタンスのアロケーションを
回避できます。


File: gauche-refj.info,  Node: インスタンスへのアクセス,  Next: クラスの変更,  Prev: インスタンスの作成,  Up: インスタンス

7.4.2 インスタンスへのアクセス
------------------------------

標準アクセサ
............

 -- Function: slot-ref obj slot
     オブジェクトOBJECTのスロットSLOTの値を返します。

     指定したスロットが値に束縛されていない場合、ジェネリック関数
     `slot-unbound'が3つの引数、OBJのクラス、OBJ、SLOT
     を伴って呼び出されます。`slot-unbound'のデフォルトの振る舞いは、
     エラーの通知です。

     オブジェクトが指定されたスロットを持っていない場合は、ジェネリック関数
     `slot-missing'が3つの引数、OBJのクラス、OBJ、SLOTを
     伴って呼び出されます。`slot-missing'のデフォルトの振る舞いは、
     エラーの通知です。

 -- Function: slot-set! obj slot value
     オブジェクトOBJECTのスロットSLOTの値を、VALUEに セットします。

     オブジェクトが指定したスロットを持っていない場合は、ジェネリック関数
     `slot-missing'が4つの引数、OBJのクラス、OBJ、
     SLOT、VALUEを伴って呼び出されます。

 -- Function: slot-bound? obj slot
     オブジェクトOBJのスロットSLOTが束縛されていれば真を、
     そうでなければ偽を返します。

     オブジェクトが指定したスロットを持っていない場合は、ジェネリック関数
     `slot-missing'が3つの引数、OBJのクラス、OBJ、
     SLOTを伴って呼び出されます。

 -- Function: slot-exists? obj slot
     OBJがSLOTを持っていれば真を返します。

 -- Function: slot-push! obj slot value
     この関数は、一般的なイディオムの実装です。
     これは以下のようなコードで定義できます(が、将来のバージョンでは
     最適化されるでしょう)。
          (define (slot-push! obj slot value)
            (slot-set! obj slot (cons value (slot-ref obj slot))))

 -- Method: ref (obj <object>) (slot <symbol>)
 -- Method: (setter ref) (obj <object>) (slot <symbol>) value
     これらのメソッドはそれぞれ、単に `slot-ref' および `slot-set!'
     を呼ぶだけです。直接 `slot-ref' や `slot-set!' を呼ぶよりも
     効率はすこしよくないですが、プログラムコードはコンパクトになります。

フォールバックメソッド
......................

 -- Generic Function: slot-unbound
 -- Method: slot-unbound (class <class>) obj slot
     このジェネリック関数は束縛されていないスロットの値を取り出そうとしたときに
     呼び出されます。このジェネリック関数の返り値は値を得ようとした呼出しもとに
     返されます。

     デフォルトのメソッドは単にエラーのシグナルをあげるだけです。

 -- Generic Function: slot-missing
 -- Method: slot-missing (class <class>) obj slot &optional value
     このジェネリック関数は存在しないスロットの値を取り出そうとしたとき、あるいは
     設定しようとしたときに呼びだされます。このジェネリック関数の返り値は、
     値を得ようとした呼出しもとに返されます。

     デフォルトのメソッドは単にエラーのシグナルをあげるだけです。

特殊アクセサ
............

 -- Function: class-slot-ref class slot-name
 -- Function: class-slot-set! class slot-name obj
 -- Function: class-slot-bound? class slot-name obj
     スロットの`:allocation'オプションが`:class'もしくは
     `:each-subclass'である場合、これらの手続きを使って、
     インスタンス無しでそれらのスロットの値を取得/設定できます。

 -- Method: slot-ref-using-class (class <class>) (obj <object>)
          slot-name
 -- Method: slot-set-using-class! (class <class>) (obj <object>)
          slot-name value
 -- Method: slot-bound-using-class? (class <class>) (obj <object>)
          slot-name
     `slot-ref'、`slot-set!'、`slot-bound?' のジェネリック
     関数版です。CLASS は OBJECT のクラスでなければなりません。

     これらの関数は、ジェネリックであることに加えて、 `obj'
     のクラスが再定義されてもクラスの再定義を起動しない
     (そのような場合、CLASSは OBJECT の元々のクラスで
     なければならない)という点で手続き版とは違います。

     覚書: CLOS とはちがい、`slot-ref' などは、その中でジェネリック
     関数版を呼ぶことはありません。それゆえ、`slot-ref-using-class' を
     特定化することによって、`slot-ref'
     をカスタマイズすることはできません。
     つまり、これらのジェネリック関数の主たる目的は `change-class'
     メソッドの内部で使われることです。とくに、`slot-ref' などは
     クラス再定義を再度起動する(詳細については *Note クラスの変更:: を
     参照)ので、OBJ の再定義中には使えません。


File: gauche-refj.info,  Node: クラスの変更,  Prev: インスタンスへのアクセス,  Up: インスタンス

7.4.3 クラスの変更
------------------

クラス変更プロトコル
....................

CLOS-系のオブジェクトシステムのユニークな機能は既存のインスタンスの
クラスを変更できるということです。新旧二つのクラスに関連性がある必要は
ありません。おのぞみなら、ミシンを雨がさに変更することもできます。

 -- Generic Function: change-class
 -- Method: change-class (obj <object>) (new-class <class>)
     オブジェクト OBJ のクラスを NEW-CLASS に変更します。
     デフォルトのメソッドは単に `change-object-class'
     手続きを呼ぶだけです。

 -- Function: change-object-class obj orig-class new-class
     オブジェクト OBJ のクラスを ORIG-CLASS から NEW-CLASS
     に変更します。これはジェネリック関数ではありません。
     オブジェクトのクラスを変更するにはちょっとした秘密の内部的操作が必要で、
     この手続きはそれを隠蔽しています。

     クラスを変更する正確なステップは以下のようになっています。

       1. NEW-CLASS の新しいインスタンスが `allocate-instance' によって
          アロケートされる。

       2. NEW-CLASSの各スロットに対して、
            1. もし、そのスロットが OLD-CLASS に存在し、OBJ
               で束縛されていれば、 その値は OBJ
               から取り出され、新しいインスタンスにセットされる。
               (そのスロットは_持ち越され_ます。)

            2. そうでなければ、新しいインスタンスのスロットは、*Note
               インスタンスの作成:: に
               あるように、標準のスロット初期化プロトコルによって初期化されます。

       3. 最後に、新しいインスタンスの内容が OBJ
          に_移植_されます。すなわち、 OBJ
          がアイデンティティを変えることなく NEW-CLASS のインスタンス
          となります。

     `initilize' メソッドは OBJ に対して呼ばれているわけではないことに
     注意してください。おのぞみなら、独自の `change-class' メソッドを
     定義して`intialize'を呼ぶようにすることができます。

     `change-object-class' は OBJ を返します。

ユーザは大抵の場合、`change-object-class'を直接呼ぶ必要は無いでしょう。
そのかわり、特定化した `change-class' を定義するべきです。
たとえば、旧いクラスのスロット `x' を 新しいクラスのスロット `y'
へ持ち越すことは、 こんな風に書けば可能です。

     (define-method change-class ((obj <old-class>) <new-class>)
       (let ((old-val (slot-ref obj 'x)))
         (next-method)               ;; calls default change-class
         (slot-set! obj 'y old-val)  ;; here, obj's class is already <new-class>.
         obj))

インスタンス更新のカスタマイズ
..............................

再定義されたクラスのインスタンスが更新される場合は、それもクラス変更として
扱われます。オブジェクトは通常のスロットアクセサ/モディファイア
経由でアクセスされるときに、そのクラスが再定義されたかどうかを
チェックされます。そいて再定義が行われていれば、
再定義されたクラスをNEW-CLASSとして `change-class'が呼ばれます。
すなわち、インスタンスの更新はオブジェクトの
クラスを元々のものから再定義されたものへ変更することと看倣されます。

   `change-class' を特定化することで、インスタンスを再定義された
クラス用に更新する方法をカスタマイズできます。しかし、クラス再定義 用の
`change-class' を書くには特別な注意が必要です。

まず、再定義はクラスオブジェクトのグローバルな束縛を変更してしまいます。
それゆえ、クラス再定義がおこる前の旧いクラスへの参照を保持しておく
必要があり、`change-class' メソッドの特定化をするには、この旧い
クラスを使う必要があります。

     ;; save old <myclass>
     (define <old-myclass> <myclass>)

     ;; redefine <myclass>
     (define-class <myclass> ()
       ...)

     ;; define customized change-class method
     (define-method change-class ((obj <old-myclass>) <myclass>)
       ...
       (next-method)
       ...)

   次に、上の `change-class' メソッドは、`slot-ref'、`slot-set!'、
`class-of' などを経由して、暗黙のうちに起動される得ることに
注意してください。もし、`change-class' 内で、OBJ に対して 再度
`slot-ref' のような手続き使うと、インスタンス更新プロトコルが
再帰的に起動され、無限ループをひきおこすことになります。インスタンス
更新を起動しないようなメソッドしか使えません。すなわち、
`slot-ref-using-class'、`slot-set-using-class!'、
`slot-bound-using-class?'、`current-class-of' しか使えません。

   仮想スロットのように、手続きによって計算される値をもつスロットを
持ち越したいのであれば、`slot-ref' その他が、そのスロットの値を
計算している最中に、暗黙裏に OBJ に対して呼ばれることがありえます。
実際のところは、`change-object-class' はこのような再帰を検出する
保護機構をもっています。もし、このようなことが起これば、
`change-object-class' はそのスロットの値を取り出すのを諦め、
新しいインスタンスのスロットを旧いスロットが未束縛であるとして、
初期化します。

   インスタンス更新をカスタマイズするのは非常に強力ですがたいへん
トリッキーな仕事です。Gauche のソース tar ball 中のテストプログラム
には自明ではないいくつかのケースが含まれています。`test/object.scm'
見てみてください。


File: gauche-refj.info,  Node: ジェネリックファンクションとメソッド,  Next: メタオブジェクトプロトコル,  Prev: インスタンス,  Up: オブジェクトシステム

7.5 ジェネリックファンクションとメソッド
========================================

メソッドの定義
--------------

 -- Macro: define-generic name &keyword class
     ジェネリック関数を生成し、NAME に束縛します。

     通常は、これを使う必要はありません。もし、まだ存在していなければ、
     `define-method'
     マクロが暗黙裏にジェネリック関数を生成してくれるからです。

     キーワード引数`class'に、`<generic>'のサブクラスを渡すことで、
     作られるジェネリック関数をデフォルトの`<generic>'クラスのインスタンスでは
     なく指定のクラスのインスタンスにすることができます。`<generic>'の
     サブクラスを定義してメソッド適用をカスタマイズする場合に便利です。

 -- Macro: define-method name specs body
     NAME という名前のメソッドを定義します。すでにグローバルに NAME
     に束縛されているジェネリック関数オブジェクトが存在していれば、生成された
     メソッドはそのジェネリック関数に追加されます。NAME が未束縛であるか
     またはジェネリック関数以外に束縛されているなら、新しいジェネリック関数が
     生成され、NAME に束縛されて、新しいメソッドがそれに追加されます。

     SPECS はこのメソッドに対応する引数とその型を指定します。これは
     lambda
     形式の引数リストに似ていますが、それぞれの引数の型を指定できる
     ところが違います。

          specs : ( arg ... )
                | ( arg ... . symbol )
                | symbol

          arg   : ( symbol class )
                | symbol

     class は引数が所属すべきクラスを指定します。`arg' が単に
     シンボルであれば、`(arg <top>)' と同じです。rest 引数の
     型を指定することはできません。それは常にリストに束縛されるからです。

     引数リストのクラスのリストは_メソッド特定化子リスト_といい、
     これを基に、ジェネリック関数は適切なメソッドを選択します。SPECS と
     それに対応する特定化子リストの例をあげておきます。

          specs:        ((self <myclass>) (index <integer>) value)
          specializers: (<myclas> <integer> <top>)

          specs:        ((self <myclass>) obj . options)
          specializers: (<myclas> <top> . <top>)

          specs:        (obj (attr <string>))
          specializers: (<top> <string>)

          specs:        args
          specializers: <top>

     その特定化子リストがジェネリック関数の中のメソッドの一つに一致するような
     NAME 上のメソッドを定義すると、既存のメソッドは新しく定義された
     メソッドに置き換えられます。

ジェネリック関数の適用
----------------------

ジェネリック関数は適用されると、まず、与えられた引数に適合する
特定化子リストを持つメソッドを選択します。たとえば、ジェネリック関数
`foo' が 3つのメソッドを持っており、それらの特定化子リストが
それぞれ、`(<string> <top>)'、`(<string> <string>)'、 `(<top> <top>)'
であるとします。`foo' が `(foo "abc" 3)' の
ように適用されたとき、最初と 3番目のメソッドが選択されます。

選択されたメソッドは、もっとも_特定化された_ものから、もっとも一般的なものへ
の順でソートされます。これは以下のように計算されます。

   * `(A1 A2 ...)' という特定化子リストをもつメソッド `a' と `(B1 B2
     ...)' という特定化子リストをもつメソッド `b' とが あるとします。

   * `An' と `Bn' とが異る最小の N を見つけます。N 番目の
     引数のクラスをとり、そのクラスの順位リストをチェックします。もし、
     その CPL の中で、`An' が `Bn' より先にくれば、method `a' は
     メソッド `b' より特定化されているということにし、さもなければ、
     `b' が `a' がより特定化されているということにします。

   * もし、`a' および `b' のすべての特定化子が、一方は rest 引数
     をもち、もう一方はもたないという以外同じであれば、rest 引数をもつ
     メソッドのほうがそうでないものより特定化されているとします。

   メソッドがソートされたら、最初のメソッドの本体が実引数で呼ばれます。

   メソッド本体内部では、特別なローカル変数 `next-method'が暗黙裏に
束縛されます。

 -- Next method: next-method
 -- Next method: next-method args ...
     この変数は、メソッド本体内部で、ソートされたメソッドリストで次のメソッド
     をカプセル化した特別なオブジェクトに束縛されます。

     引数なしで呼ぶと、次のメソッドがこのメソッドよばれたときとと同じ引数で
     起動されます。ARGS ... を明示的にわたすと、次のメソッドがその
     渡された引数で起動されます。

     `next-method' がもっとも特定化されていないメソッドで呼ばれた場合、
     すなわち、「次のメソッド」がない場合、エラーシグナルがあがります。


File: gauche-refj.info,  Node: メタオブジェクトプロトコル,  Prev: ジェネリックファンクションとメソッド,  Up: オブジェクトシステム

7.6 メタオブジェクトプロトコル
==============================

CLOS 風のオブジェクトシステムでは、オブジェクトシステムがそれ自身の上に
構築されます。すなわち、クラス構造のようなもの、クラスをどのように
生成するか、インスタンスをどのように生成し初期化するか、メソッドをどのように
ディスパッチし呼び出すか、これらはすべてオブジェクトシステムによって、
定義されます。たとえば、クラスはジェネリックな構造と標準的クラスの
振舞いを定義する `<class>' クラスのインスタンスです。`<class>'
のサブクラス化すると、デフォルトのものとは違う振舞いをする、独自の
クラス集合をつくることができます。これは結局、独自のオブジェクトシステムを
つくることになります。

   _メタオブジェクトプロトコル_は、どのようにオブジェクトシステムを
構築するかに関連する API
群の定義です。ブロック構築のクラス、オブジェクト
システムを操作するあいだに呼ばれるジェネリック関数の名前と順序などです。
これらのクラスをサブクラス化し、これらのメソッドを特定化することは、
オブジェクトシステムの振舞いをカスタマイズすることを意味します。

* Menu:

* クラスのインスタンシエーション::
* スロットアクセスのカスタマイズ::
* メソッドのインスタンシエーション::
* メソッド適用のカスタマイズ::


File: gauche-refj.info,  Node: クラスのインスタンシエーション,  Next: スロットアクセスのカスタマイズ,  Prev: メタオブジェクトプロトコル,  Up: メタオブジェクトプロトコル

7.6.1 クラスのインスタンシエーション
------------------------------------

すべてのクラスはある特殊なクラスのグループのインスタンスになっています。
他のクラスのクラスになれるようなクラスのことを _メタクラス_ と呼びます。
Gauche では `<class>' クラスおよびそのサブクラスのみがメタクラスに
なれます。

`define-class' の展開
.....................

`define-class' マクロは基本的には `<class>' (あるいは指定された
メタクラス)のインスタンスを生成するコードのラッパーで、それを与えられた
名前に束縛します。以下のような `define-class' 形式を前提とします。

     (define-class NAME (SUPERS)
       SLOT-SPECS
       OPTIONS ...)

   これを次のように展開します。 (``gauche-config
--syslibdir`/gauche/object.scm' の `define-class'
マクロの定義をみれば展開形式を見ることができます。)
     (define NAME
       (let ((tmp1 (make METACLASS
                      :name 'NAME :supers (list SUPERS)
                      :slots (map PROCESS-SLOT-DEFINITIONS
                                  SLOT-SPECS)
                      :defined-modules (list (current-module))
                      OPTIONS ...)))
         ... CHECK CLASS REDEFINITION ...
         ... REGISTERING ACCESSOR METHODS ...
         tmp1))

   生成されるクラスのクラス、つまり、METACLASS は以下のルールで
決定されます。

  1. もし、`:metaclass' オプションが `define-class' マクロに
     与えられていれば、その値を使います。その値は、`<class>' クラスか
     あるいはその子孫でなければなりません。

  2. さもなければ、クラス順位リスト中のクラスのメタクラスが試されます。
        * もし、すべてのメタクラスが `<class>' であるなら、生成される
          クラスのメタクラスも `<class>' になります。

        * もし、すべてのメタクラスが `<class>' かあるいは別のメタクラス
          `A' のどちらかであれば、生成されるクラスのメタクラスは、`A' に
          なります。

        * もしメタクラスの集合が `<class>' 以外の 2つ以上のメタクラス
          (`A', `B', `C' ...)を含む場合、生成されるクラスの
          メタクラスはこれらのメタクラス `A', `B', `C' ... すべてを
          継承したメタクラスになります。

   クラスの名前、スーパークラス、スロットの定義は初期化引数として
ジェネリック関数 `make' に引き渡され、それ以外の引数は `define-class'
に引き渡されます。初期化引数 `define-modules' は
どのモジュールでそのクラスが定義されたかを覚えておくために引き渡されます。
これはこのクラスの再定義のとき用です。

   スロットの仕様 SLOT-SPECS は内部メソッド PROCESS-SLOT-DEFINITIONS
(これは直接呼び出すことはできません)で処理され、スロット定義になります。
厳密には、`:init-form' スロットオプションは、`:init-thunk' オプション
になり、`:getter'、`:setter'、`:accessor' のスロットオプションは
引用されます。

   クラス(METACLASS のインスタンス)が生成された後、NAME のグローバル
な束縛がチェックされます。それが、クラスに束縛されていれば、クラスの再定義
プロトコルが起動されます(*Note クラスの再定義:: 参照)。

   その後、SLOT-SPECS 中で、`:getter'、`:setter'、 `:accessor'
スロットオプションに与えられたメソッドが集められ、対応する
ジェネリック関数に登録されます。

クラス構造
..........

 -- Class: <class>
     すべてのメタクラスのベースクラスである `<class>' は以下のような
     スロットを持っています。これらのスロットは内部的な管理のためにあるので
     クラスが初期化された後に、これらの値を変更すべきではないということに
     注意してください。クラスの情報を得るには、これらのスロットに直接
     アクセスするのではなく、*Note クラスオブジェクト::
     にある手続きを使うことをおすすめ します。

      -- Instance Variable of <class>: name
          クラスの名前、`define-class' マクロに与えられたシンボルです。
          `class-name' はこの値を返します。

      -- Instance Variable of <class>: cpl
          クラス順位リストです。`class-precedence-list'
          はこの値を返します。

      -- Instance Variable of <class>: direct-supers
          直接スーパークラスのリストです。 `class-direct-supers'
          はこの値を返します。

      -- Instance Variable of <class>: accessors
          スロットアクセサの連想リストです。これは各スロットがどのようにアクセスされる
          べきかをカプセル化しています。

      -- Instance Variable of <class>: slots
          スロット定義のリストです。`class-slots' はこの値を返します。
          スロット定義についての詳細は、*Note
          スロット定義オブジェクト:: を参照してください。

      -- Instance Variable of <class>: direct-slots
          このクラスの定義で直接指定された(つまり継承したものではない)スロット定義の
          リストです。`class-direct-slots' はこの値を返します。

      -- Instance Variable of <class>: num-instance-slots
          インスタンスにアロケートされるスロットの数です。

      -- Instance Variable of <class>: direct-subclasses
          このクラスを直接継承しているクラスのリストです。
          `class-direct-subclasses' はこの値を返します。

      -- Instance Variable of <class>: direct-methods
          このクラスを特定化子リスト中にもつメソッドのリストです。
          `class-direct-methods' はこの値を返します。

      -- Instance Variable of <class>: initargs
          このクラスが生成されるときの初期化引数リストです。この情報は
          再定義されたクラスを初期化するのに使います(*Note
          クラスの再定義:: 参照)。

      -- Instance Variable of <class>: defined-modules
          このクラスがグローバル束縛をもつモジュールのリストです。

      -- Instance Variable of <class>: redefined
          このクラスが再定義された場合、このスロットは新しいクラスへの参照を含みます。
          そうでない場合にはこのスロットは `#f' をもっています。

      -- Instance Variable of <class>: category
          このスロットの値は、このクラスがどのように生成されたかを示しています。
          Scheme 定義のクラスは、`scheme'
          というシンボルを持っています。それ以外の
          値は内部的に使用するだけです。

`<class>' 用の make メソッド
............................

 -- Method: make (class <class>) &rest initargs


File: gauche-refj.info,  Node: スロットアクセスのカスタマイズ,  Next: メソッドのインスタンシエーション,  Prev: クラスのインスタンシエーション,  Up: メタオブジェクトプロトコル

7.6.2 スロットアクセスのカスタマイズ
------------------------------------

 -- Generic Function: compute-slots

 -- Generic Function: compute-get-n-set

 -- Function: slot-ref-using-accessor obj slot-accessor
 -- Function: slot-set-using-accessor obj slot-accessor value


File: gauche-refj.info,  Node: メソッドのインスタンシエーション,  Next: メソッド適用のカスタマイズ,  Prev: スロットアクセスのカスタマイズ,  Up: メタオブジェクトプロトコル

7.6.3 メソッドのインスタンシエーション
--------------------------------------

 -- Method: make (class <method>) &rest initargs


File: gauche-refj.info,  Node: メソッド適用のカスタマイズ,  Prev: メソッドのインスタンシエーション,  Up: メタオブジェクトプロトコル

7.6.4 メソッド適用のカスタマイズ
--------------------------------

 -- Generic Function: apply-generic gf args

 -- Generic Function: sort-applicable-methods gf methods args

 -- Generic Function: method-more-specific? method1 method2 classes

 -- Generic Function: apply-methods gf methods args

 -- Generic Function: apply-method gf method build-next args


File: gauche-refj.info,  Node: ライブラリモジュール - 概要,  Next: ライブラリモジュール - Gauche拡張モジュール,  Prev: オブジェクトシステム,  Up: Top

8 ライブラリモジュール - 概要
*****************************

続くいくつかの章で、Gaucheのディストリビューションに含まれる
ライブラリモジュールを解説します。
これらのモジュールを使うにあたっては、特に断りのない限り、
モジュールをロードしてimportすることが必要です
(通常は`use'マクロが使えます。*Note モジュールの使用::参照)。

   いくつかのモジュールは「オートロードされる」と表記されています。
この場合は、そのモジュールを使うにあたってあらかじめモジュールをロードしたり
`use'しておく必要はありません。そのモジュールの束縛が使われた時点で、
モジュールが自動的にロードされインポートされます。オートロードの
詳細については*Note Autoload::を参照してください。

   *Note ライブラリモジュール - Gauche拡張モジュール::では、
`gauche.*'モジュールを解説します。
これらのモジュールはGaucheのコアの機能ですが、使用頻度が少ないために
モジュールとして分離されたものです。
(一部のモジュールはそれほど重要ではありませんが、
歴史的な理由からこのカテゴリに含まれています)。
このカテゴリに含まれるモジュールには、システムAPI (`gauche.fcntl'、
`gauche.termios'等)、ネットワーキング(`gauche.net')、 スレッドAPI
(`gauche.threads')、
それからGaucheの低レベルのコアAPIの上に実装された高レベルなルーチン
(`gauche.process'、`gauche.regexp'等) があります。

   *Note ライブラリモジュール -
SRFI::では、SRFIの機能を提供するモジュールを
解説します。一部のSRFIはGaucheのコアに組み込まれており、
この章には挙げられていないことに注意して下さい。
サポートされている全てのSRFIのリストは*Note 標準への準拠::にあります。

   *Note ライブラリモジュール - ユーティリティ::
ではその他のさまざまなユーティリティ
関数を提供するモジュールを解説します。dbmスタイルのデータベース
インタフェース、ファイルシステムユーティリティ、ネットワークプロトコルユーティリティ
等があります。

   実行時にプログラムが特定のモジュールやライブラリの存在を検査できる
手続きがいくつか提供されています。 詳しくは*Note
ライブラリの操作::を参照して下さい。

   下の表は、モジュールの名前付けの分類を示します。
外部モジュール、及び将来予定されているモジュールも含みます。

`data.*'
     汎用的なデータ構造。(予定)

`dbm.*'
     DBMインタフェース

`gauche.*'
     Gauche本体の一部として考えられている機能。

`gl.*'
     OpenGLバインディングと関連するライブラリ (外部パッケージ)。

`gtk.*'
     GTk+バインディングと関連するライブラリ (外部パッケージ)。

`file.*'
     ファイルとディレクトリの操作。

`lang.*'
     言語に関するライブラリ(人工的なものも自然言語関連も)。(予定)

`math.*'
     数学。

`compat.*'
     他の実装とのコンパチビリティに関するライブラリ。 (予定)

`rfc.*'
     RFCで定義されているデータフォーマットやネットワークプロトコルの実装。

`srfi-*'
     SRFIの実装

`text.*'
     テキストデータを扱うライブラリ

`util.*'
     汎用的なアルゴリズムの実装。

`www.*'
     WWWで主として使われるプロトコルやデータフォーマットの実装。


File: gauche-refj.info,  Node: ライブラリモジュール - Gauche拡張モジュール,  Next: ライブラリモジュール - SRFI,  Prev: ライブラリモジュール - 概要,  Up: Top

9 ライブラリモジュール - Gauche拡張モジュール
*********************************************

* Menu:

* 配列::
* 文字コード変換::
* コレクションフレームワーク::
* コンフィグレーション情報::
* 低レベルファイル操作::
* フック::
* インタラクティブセッション::
* リスナー::
* ユーザレベルのロギング::
* シングルトン::
* Validator付きスロット::
* ネットワーキング::
* パラメータ::
* コマンドライン引数の解析::
* 高レベルプロセスインタフェース::
* 正規表現ユーティリティ::
* モジュールの再ロード::
* 簡単なディスパッチャ::
* シーケンスフレームワーク::
* Syslog::
* Termios::
* 単体テスト::
* スレッド::
* 時間の計測::
* ユニフォームベクタ::
* バージョン番号の比較::
* 仮想ポート::


File: gauche-refj.info,  Node: 配列,  Next: 文字コード変換,  Prev: ライブラリモジュール - Gauche拡張モジュール,  Up: ライブラリモジュール - Gauche拡張モジュール

9.1 `gauche.array' - 配列
=========================

 -- Module: gauche.array
     このモジュールは多次元配列のデータタイプとそれに関する操作を提供します。
     プリミティブなAPIはSRFI-25で定義されているものに従います。
     任意のSchemeオブジェクトを保持できるSRFI-25の汎用配列の他に、
     均一な数値ベクタ(*Note ユニフォームベクタ::参照)を使って
     数値要素を効率良く保持する配列型も提供されます。
     また、SRFI-10を使った配列の外部表現も実装されます。

     N次元の配列の各エレメントは`N'個の整数のインデックス `[ I_0 I_1
     ... I_N-1 ]'でアクセスされます。
     配列は、各次元のインデックスの下限S_Kおよび上限E_Kを決める
     SHAPEを持っています。ここで、S_K <= E_Kであり、
     K次元目のインデックスI_Kは S_K <= I_K < E_K を満たすものとします。
     (S_K == E_K であるような配列も作れますが、
     その配列にはデータをストアすることはできません。
     また、0次元の配列は作れます。それは一つだけデータを保持できます)。
     Shapeはそれ自体が [ D x 2 ] の配列です。
     ここでDはそのshapeが表現する配列の次元数です。

     配列のプリミティブに対しインデックスを渡すにはいくつか方法があります。
     各インデックスをばらばらの引数として渡すこともできますし、
     ベクタや1次元の配列にパックして渡すこともできます。
     後者においてインデックスがパックされたベクタや配列を「インデックスオブジェクト」
     と呼ぶことがあります。Gaucheでは、配列の要素に次々とアクセスするような処理では
     ベクタをインデックスオブジェクトとして使うと若干効率が良いでしょう。

     配列は`equal?'手続きで比較することが出来ます。
     二つの配列のshapeが等しく、また対応する各要素が`equal?'の意味で
     等しい場合に二つの配列は`equal?'であると見なされます。

     内部的には、配列は1次元のインデックスでアクセスされるバッキングストレージと、
     多次元のインデックスをバッキングストレージへのインデックスにマップする手続きとから
     構成されています。

 -- Class: <array-base>
     配列に関する汎用操作を実装している、抽象ベースクラスです。
     実際に配列のインスタンスを作るには、以下のいずれかの具体クラスを使って下さい。

 -- Class: <array>
 -- Class: <u8array>
 -- Class: <s8array>
 -- Class: <u16array>
 -- Class: <s16array>
 -- Class: <u32array>
 -- Class: <s32array>
 -- Class: <u64array>
 -- Class: <s64array>
 -- Class: <f32array>
 -- Class: <f64array>
     具体配列クラスです。`<array>'クラスはsrfi-25互換の配列、
     すなわち、任意のSchemeオブジェクトを格納できる配列を実装します。
     `<u8array>'から`<f64array>'までは、
     それぞれ`<u8vector>'から`<f64vector>'をバッキングストレージとして
     用いる配列を実装し、制限された範囲の整数もしくは不正確な実数のみを
     効率良く格納することができます。

 -- Reader syntax: `#,(<array> SHAPE OBJ ...)'
     配列はこの形式で書き出されます。
     (配列が例えば`<u8array>'であるなら、`<array>'の部分は`<u8array>'
     となります。) SHAPEは偶数個の整数のリストで、
     2N番目の整数がN次元目のインデックスの下限を、2N+1番目の
     整数がN次元目のインデックスの上限(+1)を表します。
     その後に、配列の要素がrow-majorの順で書き出されます。

     この構文が読み込まれると、もとの配列と`equal?'である配列が作成されます。

          ; 次のような配列：
          ;   8 3 4
          ;   1 5 9
          ;   6 7 2
          #,(<array> (0 3 0 3) 8 3 4 1 5 9 6 7 2)

          ; 4x4の単位行列
          #,(<array> (0 4 0 4) 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1)

 -- Function: array? obj
     [SRFI-25] OBJが配列であれば#Tが、そうでなければ#Fが返されます。
     `(is-a? obj <array-base>)'と等価です。

 -- Function: make-array shape &optional init
     [SRFI-25] ShapeがSHAPEである配列を作成します。 SHAPEは [ D x 2 ]
     の配列で、 0 <= K < D なる各Kに対して要素 [ K 0 ] は 要素[ K 1
     ]以下でなければなりません。
     INITが与えられた場合は、配列の各要素がINITで初期化されます。
     INITが与えられなかった場合の配列の要素の初期値は不定です。

          (make-array (shape 0 2 0 2 0 2) 5)
           => #,(<array> (0 2 0 2 0 2) 5 5 5 5 5 5 5 5)

 -- Function: make-u8array shape &optional init
 -- Function: make-s8array shape &optional init
     ...

 -- Function: make-f32array shape &optional init
 -- Function: make-f64array shape &optional init
     `make-array'と似ていますが、均一な数値配列を返します。

 -- Function: shape bound ...
     [SRFI-25]
     偶数個の正確な整数を引数に取り、配列のshapeとして使える2次元の配列を返します。

          (shape 0 2 1 3 3 5)
           => #,(<array> (0 3 0 2) 0 2 1 3 3 5)

          (shape)
           => #,(<array> (0 0 0 2))

 -- Function: array shape init ...
     [SRFI-25] ShapeがSHAPEであるような配列を作成し、 その要素をINIT
     ...で初期化します。

          (array (shape 0 2 1 3) 'a 'b 'c 'd)
           => #,(<array> (0 2 1 3) a b c d)

 -- Function: array-rank array
     [SRFI-25] 配列ARRAYの次元数を返します。

          (array-rank (make-array (shape 0 2 0 2 0 2))) => 3
          (array-rank (make-array (shape))) => 0

 -- Function: array-shape array
     配列ARRAYのshapeを表す配列を返します。

 -- Function: array-start array dim
 -- Function: array-end array dim
 -- Function: array-length array dim
     [SRFI-25+] `array-start'は配列ARRAYのDIM番目の次元の
     インデックスの下限を返します。
     `array-end'は上限+1を、そして`array-start'は両者の差を返します。
     `array-start'と`array-end'はSRFI-25で定義されています。

          (define a (make-array (shape 1 5 0 2)))

          (array-start a 0)  => 1
          (array-end a 0)    => 5
          (array-length a 0) => 4
          (array-start a 1)  => 0
          (array-end a 1)    => 2
          (array-length a 1) => 2

 -- Function: array-size array
     配列ARRAYの全要素数を返します。

          (array-size (make-array (shape 5 9 1 3))) => 8
          (array-size (make-array (shape))) => 1
          (array-size (make-array (shape 0 0 0 2))) => 0

 -- Function: array-ref array k ...
 -- Function: array-ref array index
     [SRFI-25] 配列ARRAYの要素を取り出します。最初の形式では、
     要素は整数のインデックスK ...で指定されます。
     2番目の形式では、要素はベクタまたは1次元配列のインデックスオブジェクトINDEX
     で指定されます。

 -- Function: array-set! array k ... value
 -- Function: array-set! array index value
     [SRFI-25] 配列ARRAYの要素にVALUEをセットします。 最初の形式では、
     要素は整数のインデックスK ...で指定されます。
     2番目の形式では、要素はベクタまたは1次元配列のインデックスオブジェクトINDEX
     で指定されます。

 -- Function: share-array array shape proc
     [SRFI-25]
     ShapeがSHAPEであり、与えられた配列ARRAYとバッキングストレージを
     共有する新しい配列を作成して返します。
     PROCは、新しい配列へのインデックスを古い配列へのインデックスへ
     マップする手続きです。新しい配列の次元数をN、古い配列の次元数をMと
     した時、PROCはN個の引数を取りM個の値を返す手続きでなければ
     なりません。さらに、各マッピングはaffineマッピング、すなわち、
     出力は入力の線形合成(プラス定数)でなければなりません。
     (`share-array'はPROCがaffineマッピングであるという事実に基づいた
     最適化を行います。新しい配列にアクセスする度にPROCが呼ばれるというわけでは
     ありません)。

 -- Function: array-for-each-index array proc &optional index

 -- Function: shape-for-each shape proc &optional index

 -- Function: tabulate-array shape proc &optional index

 -- Function: array-retabulate! array shape proc &optional index
 -- Function: array-retabulate! array proc &optional index

 -- Function: array-map! array shape proc array0 array1 ...
 -- Function: array-map! array proc array0 array1 ...

 -- Function: array-map shape proc array0 array1 ...
 -- Function: array-map proc array0 array1 ...

 -- Function: array->vector array
 -- Function: array->list array

 -- Function: array-concatenate a b &optional dimension

 -- Function: array-transpose array &optional dim1 dim2

 -- Function: array-rotate-90 array &optional dim1 dim2

 -- Function: array-flip array &optional dimension
 -- Function: array-flip! array &optional dimension

 -- Function: identity-array dimension &optional class

 -- Function: array-inverse array

 -- Function: determinant array
 -- Function: determinant! array

 -- Function: array-mul a b

 -- Function: array-expt array pow

 -- Function: array-div-left a b
 -- Function: array-div-right a b

 -- Function: array-add-elements array array-or-scalar ...
 -- Function: array-add-elements! array array-or-scalar ...

 -- Function: array-sub-elements array array-or-scalar ...
 -- Function: array-sub-elements! array array-or-scalar ...
 -- Function: array-mul-elements array array-or-scalar ...
 -- Function: array-mul-elements! array array-or-scalar ...
 -- Function: array-div-elements array array-or-scalar ...
 -- Function: array-div-elements! array array-or-scalar ...


File: gauche-refj.info,  Node: 文字コード変換,  Next: コレクションフレームワーク,  Prev: 配列,  Up: ライブラリモジュール - Gauche拡張モジュール

9.2 `gauche.charconv' - 文字コード変換
======================================

 -- Module: gauche.charconv
     与えられたデータストリームの文字エンコーディングを変換するための手続き群を提供する
     モジュールです。また、このモジュールは`open-input-file'や
     `call-with-output-file'等のファイルストリームを作成する手続きを
     置き換え、`:encoding' キーワード引数を認識するようにします。

     リリース0.5.6より、Gaucheは日本語の主要エンコーディング
     (ISO2022JP, ISO2022JP-3, EUC-JP (EUC-JISX0213), Shift_JIS
     (Shift_JISX0213), UTF-8 (Unicode
     3.2))間の変換を自前で持つようになりました。
     上記以外のコードとの変換は`iconv(3)'を利用します。
     サポートされるコーディングシステムに関する詳細は *Note
     サポートされる文字エンコーディング::を参照して下さい。

* Menu:

* サポートされる文字エンコーディング::
* 文字エンコーディングの自動判定::
* 変換ポート::
* 拡張されたポート手続き::


File: gauche-refj.info,  Node: サポートされる文字エンコーディング,  Next: 文字エンコーディングの自動判定,  Prev: 文字コード変換,  Up: 文字コード変換

9.2.1 サポートされる文字エンコーディング
----------------------------------------

CESの名前は文字列またはシンボルで指定します。大文字小文字の違いは無視されます。
同じCESにいくつかの別名がついていることがあります。

   CES名 "none" は特殊です。Gaucheのネイティブエンコーディングが`none'の
場合、Gaucheは文字列を単なるバイト列として扱い、そのエンコーディングの解釈は
アプリケーションに任されます。したがって、CES "none" への変換、および
"none" からの変換は「何もしない」変換として扱われます。

特定の変換がシステムでサポートされているかどうかは次の手続きで調べることができます。

 -- Function: ces-conversion-supported? from-ces to-ces
     CES FROM-CESからTO-CESへの変換がサポートされていれば`#t'を、
     そうでなければ`#f'を返します。

     システムがFROM-CESからTO-CESへの変換を部分的にしか
     サポートしていない場合でもこの手続きは`#t'を返すことに注意して下さい。
     そのような場合、実際の変換作業はFROM-CESにあってTO-CESにない
     コードを置換文字に置き換える等で情報を失うかもしれません
     (例えば、UnicodeからEUC-JPへの変換はサポートされていますが、
     UnicodeにはEUC-JPにない文字も含まれています)。

     FROM-CESかTO-CESが "none" ならばこの手続きは常に`#t'を
     返します。なぜならそのような変換は常に成功するからです(何も変換しないわけですが)。

          ;; 内部エンコーディングからEUC-JPに変換できるか?
          (ces-conversion-supported? (gauche-character-encoding) "euc-jp")

   また、CESを扱う二つの便利な手続きが用意されています。

 -- Function: ces-equivalent? ces-a ces-b &optional unknown-value
     CES CES-AとCES-Bがシステムの知る限りで等価だった場合に
     `#t'を、等価でない場合に`#f'を返します。
     システムがその等価性を判断出来ない場合はUNKNOWN-VALUEに与えられた
     値を返します。そのデフォルトは`#f'です。

     CES名 "none"
     はワイルドカードのように動作します。それはどんなCESとも
     等価と見倣されます。(従って、`ces-equivalent?'
     は遷移的ではありません。
     この手続きは、二つのCESを知った時に相互の変換が
     必要かどうかを判断するためのものです)。

          (ces-equivalent? 'eucjp "EUC-JP")            => #t
          (ces-equivalent? 'shift_jis "EUC-JP")        => #f
          (ces-equivalent? "NoSuchEncoding" 'utf-8 '?) => ?

 -- Function: ces-upper-compatible? ces-a ces-b &optional unknown-value
     CES CES-Bでエンコードされた文字列が、システムの知る限りで
     変換無しにCES-Aでエンコードされたものと見倣せる場合に`#t'を
     返します。見倣せない場合は#Fを返します。
     システムが判断できない場合はUNKNOWN-VALUEに与えられた
     値を返します。そのデフォルトは`#f'です。

     `ces-equivalent?'と同様に、CES名 "none" はワイルドカードとして
     働きます。CES-A か CES-B が "none" であれば、
     常に`#t'が返されます。

          (ces-upper-compatible? "eucjp" "ASCII")             => #t
          (ces-upper-compatible? "eucjp" "utf-8")             => #f
          (ces-upper-compatible? "utf-8" "NoSuchEncoding" '?) => ?

   日本語の文字セットJIS X 0201及びJIS X 0213のエンコーディング
(EUC_JP、Shift JIS、UTF-8及びISO2022-JP) 間の変換に関しては、
Gaucheが内部に変換アルゴリズムを持っています (詳細は下の注記を参照)。
それ以外のCESに関しては、リンクされていればGaucheは`iconv(3)'を用いて
変換を行います。

   出力CESへマップ不可能な入力文字に出会った場合、Gaucheの変換ルーチンは
その文字が入力CESでマルチバイトである場合はgeta mark '〓' (U+3013) に、
入力CESでシングルバイトである場合は '?' に置換します。
iconvによる変換でマップ不可能な文字に出会った場合の処理はiconvの実装に
依存します(例えばglibcではエラーとなります)。

   変換ルーチンが、入力CESとして不正な入力文字列に出会った場合は
エラーが報告されます。

   *Gaucheの内部変換アルゴリズムの詳細:* EUC_JP、Shift
JIS、及びISO2022JP間の変換は可能な限り計算で行います。
文字が未定義のコードポイントも計算式に従って変換されます。
Unicode(UTF-8)とEUC_JP間の変換はテーブルルックアップによって行われます。
UnicodeとShift JISまたはISO2022JP間の変換は、入力CESを一度EUC_JPに
変換し、それを出力CESに変換することによって行います。
入力と出力のCESがGaucheの内部アルゴリズムがサポートする範囲で等しかった場合、
Gaucheの変換ルーチンはエンコーディングの正当性はチェックせず、
単に入力を出力にコピーします。

`EUC_JP, EUCJP, EUCJ, EUC_JISX0213'
     ASCII, JIS X 0201カナ、JIS X 0212、及びJIS X
     0213文字セットをカバーします。 JIS X 0212は、単にJIS X
     0213と重ならないコードを使っているためにサポート
     されていますが、他のCESへの変換は行われないので注意して下さい。
     なるべくJIS X 0213の使用をおすすめします。

`SHIFT_JIS, SHIFTJIS, SJIS'
     Shift_JISX0213をカバーします。但し、0x5cと0x7eに関しては JIS X
     0201 Roman (YEN SIGNとOVERLINE) ではなく ASCII (REVERSE
     SOLIDUSとTILDE) にマップされます。

`UTF-8, UTF8'
     Unicode 3.2です。JIS X 0213中の文字のいくつかはExtension B
     (U+20000〜) にマップされます。JIS X
     0213中の他の文字のいくつかは2つのUnicode文字 (base character +
     combining character)にマップされます。

`ISO2022JP, CSISO2022JP, ISO2022JP-1, ISO2022JP-2, ISO2022JP-3'
     これらのエンコーディングは、CSISO2022JPがISO2022JPのエイリアスであることを除き
     異なるエスケープシーケンスを使いますが、Gaucheの中では同じルーチンで処理されます。
     これらのエンコーディングのいずれかが入力CESに指定された場合、
     Gaucheは全てのバリエーションのエスケープシーケンスを認識します。
     但し、ISO2022JP-2に定義された日本語以外の言語のエスケープシーケンスに関しては、
     Gaucheはエスケープシーケンスの認識だけを行い、
     文字は'?'あるいは'〓' に置換します。

     出力に関してはGaucheは出来る限りISO2022JPでエンコードし、 JIS X
     0212文字に出会ったらISO2022JP-1のエスケープシーケンスを、 JIS X
     0213の第2面の文字に出会ったらISO2022JP-3のエスケープシーケンスを
     用います。したがって、文字列がJIS X
     0208の範囲だけで構成されていた場合は
     出力はISO2022JP互換となります。 厳密には、JIS X
     0213では包摂基準の変更により、 「JIS X
     0208と同じコードポイントを用いるがJIS X
     0208のエスケープシーケンスを
     使ってはいけない文字」というのが定義されています。
     Gaucheでは互換性のため、これらの文字もJIS X
     0208のエスケープシーケンスを 用いてエンコードします
     (これは、Emacs-Muleにおけるiso2022jp-3-compatible
     モードと同じ方針です)。


File: gauche-refj.info,  Node: 文字エンコーディングの自動判定,  Next: 変換ポート,  Prev: サポートされる文字エンコーディング,  Up: 文字コード変換

9.2.2 文字エンコーディングの自動判定
------------------------------------

しばしば、入力のCESが未知であり、可能性のあるいくつかの候補から入力のCESを
推測しなければならない場合があります。推測するアルゴリズムはいくつも考えられるので、
それぞれに名前がついています。今のところ、一つのアルゴリズムしか実装されていません。
`"*JP"'
     日本語のテキストのCESを、ISO2022-JP(-1,2,3), EUCJP, SHIFT_JIS
     または UTF-8の いずれかであるとして推測する。

このアルゴリズム名は、いくつかの変換関数においてCES名の代わりに使うことができます。

 -- Function: ces-guess-from-string string scheme
     文字列STRINGのCESを、CES推測アルゴリズムSCHEME ("*JP"など)
     を使って推測し、結果のCES名を返します。もしどのCESにも該当しないデータが
     含まれていれば`#f'が返されます。複数のCESが可能である場合、
     ネイティブエンコーディングが含まれていればそれを、
     そうでなければ可能なCESからどれかひとつが選んで返されます。


File: gauche-refj.info,  Node: 変換ポート,  Next: 拡張されたポート手続き,  Prev: 文字エンコーディングの自動判定,  Up: 文字コード変換

9.2.3 変換ポート
----------------

 -- Function: open-input-conversion-port source from-code &keyword
          to-code buffer-size owner?
     文字が符号化方法FROM-CODEで符号化されているデータを読み出せる
     入力ポートSOURCEを取り、符号化方法TO-CODEで符号化されたデータを
     読み出せるポートを作成して返します。

     TO-CODEが省略された場合はネイティブのCESと見なされます。

     BUFFER-SIZEは変換のための内部バッファのサイズを指定します。
     省略時のサイズは1Kバイト程で、通常の使用には問題ないサイズです。

     入力のCESが不明な場合、`"*JP"'などのCES推測アルゴリズム名をFROM-CODE
     として指定することができます。変換ポートは最高でバッファサイズまでのデータを先読みし、
     CESを推測しようとします。そのアルゴリズムで推測されるどのCESにも該当しないデータが
     検出された場合はエラーが報告されます。もし複数のCESが可能であるようなデータであった
     場合は、Gaucheのネイティブエンコーディングが可能なCESに含まれていればそれが選ばれ、
     そうでなければいずれかのCESが適当に選ばれます。従って、バッファサイズが小さすぎると
     誤った判定をする可能性が高くなります。大抵のテキストドキュメントに対して、
     既定のバッファサイズは十分ですが、大きなテキストのほとんどがASCII文字で最後だけ
     マルチバイト文字が現われるようなテキストでは誤判定の可能性があります。
     最悪の場合でも結果を保証するには、テキスト全体が格納できるバッファサイズを指定すると
     良いでしょう。

     通常、`open-input-conversion-port'は変換が全て終了した後でもSOURCE
     はオープンしたままにします。キーワード引数OWNER?に真の値を指定すると、
     EOFが読まれた後でSOURCEはクローズされます。

     例を示しましょう。以下のコードは未知のCES(但しEUC-JP, SJIS,
     ISO2022-JP, UTF8の
     いずれかであることは分かっている)で書かれたテキストファイル`unknown.txt'を
     読みだし、文字エンコーディングをEUC-JPに変換して`eucjp.txt'に書き出します。
          (call-with-output-file "eucjp.txt"
            (lambda (out)
              (copy-port (open-input-conversion-port
                           (open-input-file "unknown.txt")
                           "*jp"             ;guess code
                           :to-code "eucjp"
                           :owner? #t)       ;close unknown.txt afterwards
                         out)))

 -- Function: open-output-conversion-port sink to-code &keyword
          from-code buffer-size owner?
     文字のエンコーディングをFROM-CODEから`to-code'に変換して
     出力ポートSINKに書き出すような出力変換ポートを作成して返します。
     TO-CODEが省略された場合はネイティブのCESと見なされます。
     FROM-CODEにもTO-CODEにも、CES推測アルゴリズム名を
     使用することはできません。

     BUFFER-SIZEは内部で変換に使われるバッファサイズを指定します。
     出力変換ポートに書き出された文字は、`flush'を使って明示的に
     フラッシュするか出力変換ポートが閉じられるまで、バッファ内に残っている可能性があります。

     通常、出力変換ポートがクローズされてもSINKはクローズされません。
     OWNER?に真の値を与えれば、出力変換ポートのクローズ時にSINKを
     クローズするようにできます。

 -- Function: ces-convert string from-code &optional to-code
     FROM-CODEでエンコーディングされた文字列STRINGを
     TO-CODEでエンコーディングされた文字列に変換します。
     TO-CODEがネイティブエンコーディングで無い場合、返される文字列は
     バイト文字列(不完全な文字列)であるかもしれません。

     FROM-CODEにはCES推測アルゴリズム名("*JP"など)を与えることができます。
     TO-CODEが省略された場合はネイティブエンコーディングと見なされます。

 -- Function: call-with-input-conversion iport proc &keyword encoding
          conversion-buffer-size
 -- Function: call-with-output-conversion oport proc &keyword encoding
          conversion-buffer-size
     この2つの手続きを使うと、元のポートのエンコーディングとは異る一時的な
     エンコーディングをもつ文字I/Oを行うことが可能です。

     `call-with-input-conversion' は、文字エンコードENCODING を
     もつ入力ポート IPORT をとり、PROCを一つの引数、すなわち、
     変換入力ポートとともに呼びだします。このポートから、PROC は文字を
     Gauche の内部エンコーディングで読み込むことができます。いったん、
     PROCが呼ばれたら、EOFまでのすべての文字を読み込まなくてはなりません。
     後述の注意を参照してください。

     `call-with-output-conversion' は、文字エンコーディング ENCODING
     を期待する出力ポート OPORT をとり、PROCを一つの引数、すなわち、
     一時的な変換出力ポートとともに呼びだします。このポートへ、PROCは
     Gauche の内部エンコーディングをもつ文字を書き込むことができます。
     PROC が戻るか、エラーで抜けると、この一時的な変換出力ポートは
     フラッシュされて、クローズされます。`call-with-output-conversion'
     の呼出し側は、その後、元のエンコーディングのポートOPORTを使い
     続けること可能です。

     どちらの手続きも PROC が返す値を返します。ENCODING
     のデフォルト値は Gauche
     の内部エンコーディングです。この2つの手続きは
     必要がなければ、変換ポートを作成しません。もし
     CONVERSION-BUFFER-SIZE が与えられていれば、変換ポートがオープン
     されるときに、BUFFER-SIZE 引数として使われます。

     PROC がアクティブであるあいだは、IPORT/OPORT を直接
     使うべきではありません。文字のエンコーディングはステートフルなプロセスで
     変換ポート(から/へ)の入出力を混在させると元にあるポートの状態がおかしく
     なってしまいます。

     _注意:_ `call-with-input-conversion' については、 PROC が EOF
     を読むまでは、IPORT を再度利用することはできません。
     これは、変換ポートがバッファを必要とし、PROC がもどったときに
     IPORTへのバッファ付き入力をアンドゥする方法がないからです。

 -- Function: with-input-conversion iport thunk &keyword encoding
          conversion-buffer-size
 -- Function: with-output-conversion oport thunk &keyword encoding
          conversion-buffer-size
     `call-with-*-conversion' と似ていますが、この2つの手続きは、 THUNK
     を引数なしで呼びます、また、変換ポートはそれぞれ標準入力、標準
     出力のポートにセットされます。 キーワード引数の意味は
     `call-with-*-conversion' と同じです。

 -- Function: wrap-with-input-conversion port from-code &keyword
          to-code owner? buffer-size
 -- Function: wrap-with-output-conversion port to-code &keyword
          from-code owner? buffer-size
     不要な変換ポートを作らないようにする便利な手続きです。
     各手続きはそれぞれ`open-input-conversion-port'と
     `open-output-conversion-port'のように動作します。
     但し、指定されたCES間の変換が必要でないとシステムが知っている場合は、
     変換ポートは作られず、PORTがそのまま返されます。

     変換ポートが作られた場合、PORTは常に変換ポートに所有されます
     (`:owner #t'となる)。ポートを閉じる場合はPORTではなく
     常に`wrap-with-*-conversion'が返したポートを閉じるようにして下さい。
     元のPORTが先に閉じられた場合、変換中の結果が書き出されない可能性があります。
     (変換によっては、ポートが閉じられる時点で終了シーケンスを書き出すものがあるので、
     単にポートを`flush'するだけでは不十分です)。

     `:buffer-size' 引数はそのまま 変換ポート作成手続きに渡されます。


File: gauche-refj.info,  Node: 拡張されたポート手続き,  Prev: 変換ポート,  Up: 文字コード変換

9.2.4 拡張されたポート手続き
----------------------------

 -- Function: open-input-file filename &keyword encoding
          conversion-buffer-size ...
 -- Function: call-with-input-file filename proc &keyword encoding
          conversion-buffer-size ...
 -- Function: with-input-from-file filename thunk &keyword encoding
          conversion-buffer-size ...
 -- Function: open-output-file filename &keyword encoding
          conversion-buffer-size ...
 -- Function: call-with-output-file filename proc &keyword encoding
          conversion-buffer-size ...
 -- Function: with-output-to-file filename thunk &keyword encoding
          conversion-buffer-size ...
     これらのGauche組み込みの手続きは、ENCODINGとCONVERSION-BUFFER-SIZE
     という二つの追加のキーワード引数を取るように拡張されます。
     (これらの手続きの元の動作については*Note
     ファイルポート::を参照して下さい)。

     FILENAMEの文字エンコーディング名をENCODINGに渡すと、
     ファイルを読む際にENCODINGからGaucheの内部エンコーディングへの変換が
     行われます。入力の場合はENCODINGにCES推測アルゴリズム名を渡すこともできます。

     CONVERSION-BUFFER-SIZEは`open-input-conversion-port'
     におけるBUFFER-SIZEと同じ意味を持ちます。


File: gauche-refj.info,  Node: コレクションフレームワーク,  Next: コンフィグレーション情報,  Prev: 文字コード変換,  Up: ライブラリモジュール - Gauche拡張モジュール

9.3 `gauche.collection' - コレクションフレームワーク
====================================================

 -- Module: gauche.collection
     このモジュールは、様々なコレクションに対して繰り返し処理を行う総称関数を提供します。
     Schemeの規格は`map'や`for-each'などの繰り返し手続きを定義しており、
     またSRFI-1(*Note List
     library::参照)は更に数多くの繰り返し手続きを提供しますが、
     それらはリストに対してしか動作しません。

     このモジュールはオブジェクトシステムのメソッドディスパッチを利用して、
     これらの手続きをベクタやハッシュテーブルのような一般のコレクションタイプに対しても
     効率良く動作するように拡張します。また、ユーザ定義のクラスにこれらの操作を実装するための
     簡単な方法も提供します。今のところ、次のような総称関数が提供されています。

    マッピング
          `fold', `fold2', `fold3', `map', `map-to', `map-accumf,
          '`for-each'

    選択と探索
          `find', `filter', `filter-to', `remove', `remove-to',
          `partition', `partition-to' `group-collection'

    変換
          `coerce-to'

    その他
          `size-of', `lazy-size-of'

    基礎的なイテレータ構築メソッド
          `call-with-iterator', `call-with-builder', `with-iterator',
          `with-builder', `call-with-iterators'.

     これらの操作は、_コレクション_とそのサブクラスである
     _シーケンス_に対して動作します。コレクションは、その要素を全て
     訪れる方法が用意されているようなオブジェクトの集合です。
     シーケンスは、要素間に全順序関係が定義されておりインデックスで要素を取り出すことが
     できるようなコレクションです。

     次にあげるGaucheの組み込みオブジェクトはシーケンスあるいはコレクションとして動作します。
    `<list>'
          シーケンス

    `<vector>'
          シーケンス

    `<string>'
          文字のシーケンス

    `<hash-table>'
          コレクション。各要素はキーと値のペア。

    `<s8vector>, <u8vector>, ... <f64vector>'
          シーケンス。メソッドは`srfi-4'モジュール内で定義されます。
          *Note 単一型のベクタ::参照。

     *Note
     シーケンスフレームワーク::も参照してください。シーケンス特有のメソッドが
     追加されます。

     オブジェクトの集合を返すようなメソッド、すなわち
     `map'、`filter'、`remove'および`partition'は、
     リストを返します。対応する"-to"がつくメソッド
     (`map-to'、`filter-to'、`remove-to'、`partition-to')
     はコレクションクラスも引数に取り、そのクラスのコレクションを返します。

* Menu:

* コレクションに対するマッピング::
* コレクションからの選択と探索::
* コレクションに対する様々な操作::
* 基礎的なイテレータ構築メソッド::
* コレクションの実装::


File: gauche-refj.info,  Node: コレクションに対するマッピング,  Next: コレクションからの選択と探索,  Prev: コレクションフレームワーク,  Up: コレクションフレームワーク

9.3.1 コレクションに対するマッピング
------------------------------------

これらのジェネリックファンクションは標準のマッピング手続きを拡張します。
要素だけでなくそのインデックスも必要な場合は*Note
シーケンス上のマップ::を 参照して下さい。

 -- Generic function: fold proc knil coll coll2 ...
     SRFI-1で定義されるFOLD (*Note
     リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map)::参照)
     の自然な拡張です。

     コレクションCOLLの各要素EIに対して、手続きPROCが (PROC EI RI-1)
     のように呼ばれます。ここで、 RI-1 は I > 0 に対しては
     (I-1)番目のPROCの呼び出しの
     結果であり、R0はKNILです。最後のPROCの戻り値を返します。
          (fold + 0 '#(1 2 3 4)) => 10
          (fold cons '() "abc")  => (#\c #\b #\a)

     COLLがシーケンスでもある場合、要素はシーケンスの順にPROCに渡されます。
     そうでなければ繰り返しの順序は未定義です。

     複数のコレクションを`fold'に渡すこともできます
     (但し、その全てがシーケンスで
     なければあまり意味のある操作では無いでしょう)。
     K番目のコレクションのI番目の要素をE(K, I)とするとき、
     PROCは以下のように呼ばれます。
          (PROC E(0,I) E(1,I) ... E(K-1,I) RI-1)

     異なる型のコレクションを混ぜて扱うことができます。

          (fold acons '() "abc" '#(1 2 3))
            => ((#\c 3) (#\b 2) (#\a 1))

          ;; 二つのベクタの内積を計算
          (fold (lambda (a b r) (+ (* a b) r)) 0
                '#(3 5 7) '#(2 4 6))
            => 68

     複数のコレクションが与えられた場合、`fold'は少なくともひとつのコレクションが
     終了した時点で終了します。

 -- Generic function: fold2 proc knil1 knil2 coll coll2 ...
 -- Generic function: fold3 proc knil1 knil2 knil3 coll coll2 ...
     `fold'と似ていますが、1つではなくそれぞれ2, 3個の状態値を
     持ち回ります。状態値はKNILNによって初期化されます。
     手続きPROCはコレクションCOLLNの各要素値と状態値を
     引数として取り、`fold2'の場合は2個、`fold3'の場合は3個の
     値を返さねばなりません。返された値が次の繰り返しでの状態値として
     使われます。最後に返された値が`fold2', `fold3'の戻り値と なります。

          (fold2 (lambda (elt a b) (values (min elt a) (max elt b)))
                 256 0 '#u8(33 12 142 1 74 98 12 5 99))
           => 1 and 142  ;; find minimum and maximum values

     下の`map-accum'も参照。

 -- Generic function: map proc coll coll2 ...
     組み込み手続き`map' (*Note 手続き::参照) を拡張します。
     コレクションCOLLの各要素に手続きPROCを適用し、その結果をリストにして
     返します。

     COLLがシーケンスでもある場合、要素はシーケンスの順にPROCに渡されます。
     そうでなければ繰り返しの順序は未定義です。

     複数のコレクションが与えられた場合、PROCは各コレクションからの要素を引数として
     呼び出されます。`map'はひとつでもコレクションの最後に到達したら終了します。
     複数のコレクションを渡すのは、コレクションの全てがシーケンスでないとあまり意味がないでしょう。

          (map (lambda (x) (* x 2)) '#(1 2 3))
            => #(2 4 6)

          (map char-upcase "abc")
            => (#\A #\B #\C)

          (map + '#(1 2 3) '#(4 5 6))
            => (5 7 9)

     `map'は常にリストを返します。別のコレクション型で結果を得たい場合は、
     次に示す`map-to'を使って下さい。何故`(map char-upcase "abc")'が
     `"ABC"'を返さないのか疑問なら、この最後にあるディスカッションを参照してください。

 -- Generic function: map-to class proc coll coll2 ...
     `map'と同じように動作しますが、結果はクラスCLASSのインスタンスとして返されます。
     CLASSはコレクションクラスでなければなりません。
     また、ビルダーインタフェースを持っている必要があります (*Note
     基礎的なイテレータ構築メソッド::参照).

          (map-to <vector> + '#(1 2 3) '#(4 5 6))
            => #(5 7 9)

          (map-to <string> char-upcase "def")
            => "DEF"

          (map-to <vector> char=? "bed" "pet")
            => #(#f #t #f)

 -- Generic function: map-accum proc seed coll1 coll2 ...
     状態値を持ち回りながらPROCのコレクションの各要素への呼び出しを集めます。
     PROCは次のように呼ばれます。
          (PROC ELT1 ELT2 ... SEED)
     ここでELT1 ELT2 ...は COLL1 COLL2 ...の各要素です。
     PROCは2つの値を返さねばなりません。最初の値が`map'のように
     リストへと集められます。2つ目の値は次のPROCの呼び出しのSEED
     として使われます。

     いずれかのコレクションの要素を使い切った時点で、`map-accum'は
     2つの値を返します。最初の値はPROCの最初の戻り値をリストにしたもの、
     2番目の値はPROCの最後の呼び出しの2番目の戻り値です。

     もし与えられたコレクションがシーケンスであった場合は、
     PROCはシーケンスの順序通りに適用されます。

     この手続きはHaskellの`mapAccumL'と似ています。但し、
     `proc'の引数と戻り値の順が逆転していることに注意して下さい。

 -- Generic function: for-each proc coll coll2 ...
     組み込み手続き`for-each' (*Note 手続き::参照) を拡張します。
     コレクションCOLLの各要素に手続きPROCを適用します。
     PROCの結果は捨てられます。`for-each'の結果は未定義です。

     COLLがシーケンスでもある場合、要素はシーケンスの順にPROCに渡されます。
     そうでなければ繰り返しの順序は未定義です。

     複数のコレクションが与えられた場合、PROCは各コレクションからの要素を引数として
     呼び出されます。`for-each'はひとつでもコレクションの最後に到達したら終了します。
     複数のコレクションを渡すのは、コレクションの全てがシーケンスでないとあまり意味がないでしょう。

 -- Generic Function: fold$ proc
 -- Generic Function: fold$ proc knil
 -- Generic Function: map$ proc
 -- Generic Function: for-each$ proc
     `fold'、`map'、`for-each'の部分評価版です。

   _Discussion:_  `map'がリスト以外に対して適用されたとき、どういう
コレクション型を返すべきでしょう。 `(map * '#(1 2) '#(3 4))'
がベクタを返し、 `(map char-upcase "abc")'
が文字列を返すようにするほうが「自然」でしょうか。

   そのようなインタフェースは単純な場合には動作するように思えますが、
一般的な拡張は困難です。文字列とベクタが同時に渡されたらどうします?
更に、コレクションクラスによっては繰り返しインタフェースは持っていても
ビルダーインタフェースを持っていない場合があり、結果をそのコレクションクラスとして
返せない場合もあります
(データベースレコードのコレクションに対してマップする、
といった用法を考えてみて下さい)。また、Schemeプログラマは`map'が
リストを返すという事実に慣れ親しんでおり、既存のコードもMAPの戻り値を
リストを受け取る手続きに渡すことがよく行われています。

そこで、結果の型を明示的に指定する`map-to'という別のメソッドを定義しました。
結果の型を渡すのは、CommonLispの`map'関数にならっていますが、
Gaucheではクラスメタオブジェクトを渡すようにしたため、メソッドディスパッチを使って
拡張することが容易です。"-to"
のつくメソッドは結果のコレクションのクラスを
取るというインタフェースはコレクションフレームワーク中で統一的に使われています。


File: gauche-refj.info,  Node: コレクションからの選択と探索,  Next: コレクションに対する様々な操作,  Prev: コレクションに対するマッピング,  Up: コレクションフレームワーク

9.3.2 コレクションからの選択と探索
----------------------------------

 -- Generic function: find pred coll
     PREDをコレクションCOLLの要素に適用してゆきます。PREDが
     真の値を返したらそこで打ち切り、その要素を返します。PREDが真の値を返す
     要素が無かった場合は`#f'を返します。

     COLLがシーケンスでもある場合、要素はシーケンスの順にPROCに渡されます。
     そうでなければ繰り返しの順序は未定義です。

          (find char-upper-case? "abcDe") => #\D
          (find even? '#(1 3 4 6)) => 4
          (find even? '(1 3 5 7))  => #F

 -- Generic function: filter pred coll
     コレクションCOLL中の要素のうち、述語手続きPREDが真の値を返したものの
     リストを返します。コレクションがシーケンスであれば、結果の要素の順序は元のシーケンスの
     順序と同じになります。

          (filter char-upper-case? "Hello, World")
            => (#\H #\W)
          (filter even? '#(1 2 3 4)) => (2 4)

 -- Generic function: filter-to class pred coll
     `filter'と同じですが、結果のコレクションがCLASSのインスタンスで
     返されます。

          (filter-to <vector> even? '#(1 2 3 4)) => #(2 4)
          (filter-to <string> char-upper-case? "Hello, World")
            => "HW"

 -- Generic function: remove pred coll
     コレクションCOLL中の要素のうち、述語手続きPREDが偽の値を返したものの
     リストを返します。コレクションがシーケンスであれば、結果の要素の順序は元のシーケンスの
     順序と同じになります。

          (remove char-upper-case? "Hello, World")
            => (#\e #\l #\l #\o #\, #\space #\o #\r #\l #\d)
          (remove even? '#(1 2 3 4)) => (1 3)

 -- Generic function: remove-to class pred coll
     `remove'と同じですが、結果のコレクションがCLASSのインスタンスで
     返されます。

          (remove-to <vector> even? '#(1 2 3 4)) => #(1 3)
          (remove-to <string> char-upper-case? "Hello, World")
            => "ello, orld"

 -- Generic function: partition pred coll
     `filter'と`remove'を同時に行います。
     二つのリストを返します。最初のリストはコレクションCOLLの要素のうち
     述語手続きPREDが真の値を返したものから構成され、二つ目のリストは
     そうでない要素から構成されます。

          (partition char-upper-case? "PuPu")
            => (#\P #\P) and (#\u #\u)
          (partition even? '#(1 2 3 4))
            => (2 4) and (1 3)

 -- Generic function: partition-to class pred coll
     `partition'と同じですが、結果がクラスCLASSのコレクションとして
     返されます。

          (partition-to <string> char-upper-case? "PuPu")
            => "PP" and "uu"
          (partition-to <vector> even? '#(1 2 3 4))
            => #(2 4) and #(1 3)

 -- Generic function: group-collection coll &keyword key test
     `partition'を汎化したものです。COLL内の要素を同じキーを
     持つ値同士でグループ化し、リストのリストにして返します。
     キーの値は要素に手続きKEYを適用することで得られます。KEYの
     デフォルト値は`identity'です。COLLの各要素に対して、
     KEYは正確に一回だけ呼ばれます。
     キーの等価性判定には手続きTESTが使われます。デフォルト値は`eqv?'です。

     COLLがシーケンスである場合、結果の各グループに含まれる要素の順は
     もとのシーケンス内での順と同じになります。

          (group-collection '(1 2 3 2 3 1 2 1 2 3 2 3))
            => ((1 1 1) (2 2 2 2 2) (3 3 3 3))

          (group-collection '(1 2 3 2 3 1 2 1 2 3 2 3) :key odd?)
            => ((1 3 3 1 1 3 3) (2 2 2 2 2))

          (group-collection '(("a" 2) ("b" 5) ("c" 1) ("b" 3) ("a" 6))
            :key car :test string=?)
            => ((("a" 2) ("a" 6)) (("b" 5) ("b" 3)) (("c" 1)))

     `gauche.sequence'の`group-sequence'も参照して下さい (*Note
     シーケンスに対する選択と探索::)。
     隣り合う要素同士でグループ化するものです。


File: gauche-refj.info,  Node: コレクションに対する様々な操作,  Next: 基礎的なイテレータ構築メソッド,  Prev: コレクションからの選択と探索,  Up: コレクションフレームワーク

9.3.3 コレクションに対する様々な操作
------------------------------------

 -- Generic function: size-of coll
     コレクションの要素数を返します。
     デフォルトのメソッドは、コレクション中の要素をすべて数え上げるものですが、
     あまり効率は良くないでしょう。また、無限個の要素を持つコレクションでは
     帰ってきません。多くのコレクションクラスはより効率の良い方法でこのメソッドを定義しています。

 -- Generic function: lazy-size-of coll
     コレクションの要素数か、もしくはそれを計算するプロミスを返します。
     このメソッドの目的は、要素数の計算が高価な場合にそれを避けることにあります。
     しばしば、呼び出し側では最適化のための参考値として要素数が欲しい場合があり、
     そういった場合は要素数を計算するために時間を費すのは望ましくありません。
     このメソッドを代わりに呼び出して、結果がプロミスであればそれを使わない、
     という選択ができます。

 -- Generic function: coerce-to class coll
     コレクションCOLLを、クラスCLASSのインスタンスである
     別のコレクションへと変換します。COLLがシーケンスであり、
     CLASSがシーケンスクラスであれば、元のシーケンスの順序は保存されます。

          (coerce-to <vector> '(1 2 3 4))
            => #(1 2 3 4)

          (coerce-to <string> '#(#\a #\b #\c))
            => "abc"


File: gauche-refj.info,  Node: 基礎的なイテレータ構築メソッド,  Next: コレクションの実装,  Prev: コレクションに対する様々な操作,  Up: コレクションフレームワーク

9.3.4 基礎的なイテレータ構築メソッド
------------------------------------

ここに挙げるメソッドは、他のコレクションメソッドの基礎となるものです。
メソッドのインタフェースは一般のコードで使われることよりも、
効率良く他の繰り返しメソッドを記述するのに便利なように設計されています。
何故このインタフェースを基礎のメソッドとして選んだかについてはこの章の最後に説明します。

 -- Generic function: call-with-iterator collection proc &keyword start
     基礎となるイテレータ構築メソッドです。このメソッドはコレクションCOLLECTION
     から繰り返しのための二つの手続きを作成し、それらを引数として手続きPROCを
     呼びます。作られる最初の手続きは終了判定手続きで、引数無しで呼び出され、繰り返しが
     終了していれば`#t'を、まだ要素が残っていれば`#f'を返します。
     作られる二番目の手続きはインクリメント手続きで、呼ばれる度に現在の要素を返し、
     内部のポインタを次の要素へと進めます。終了判定手続きが`#t'を返した後に
     インクリメント手続きを呼んだ場合の動作は未定義です。

     コレクションがシーケンスでもある場合、インクリメント手続きはシーケンスの順番に要素を取り出します。
     キーワード引数STARTが与えられていればイテレーションの範囲は
     START番目の要素から最後の要素までとなります。シーケンスでないコレクションに
     対してはSTART引数は意味を持ちません。

     CALL-WITH-ITERATORのメソッド実装は、イテレータのエクステントを
     そのメソッドのダイナミックスコープ内に限ることを許されます。例えば、
     メソッドはPROCを呼ぶ前に何らかのリソースを確保し(データベースへのコネクションなど)、
     PROCから戻った後でそれを解放するということができます。

     このメソッドは PROC が返した値をそのまま返します。

          (call-with-iterator '(1 2 3 4 5)
            (lambda (end? next)
              (do ((odd-nums 0))
                  ((end?) odd-nums)
                (when (odd? (next)) (inc! odd-nums)))))
           => 3

     下に示す`with-iterator'マクロも参照してください。

 -- Macro: with-iterator (collection end? next args ...) body ...
     `call-with-iterator'を簡潔に呼び出すマクロです。
          (with-iterator (coll end? next args ...) body ...)
           ==
          (call-with-iterator coll
            (lambda (end? next) body ...)
             args ...)

 -- Function: call-with-iterators collections proc
     N-aryのイテレータメソッドを書くのに便利な手続きです。
     この手続きはコレクションのリストCOLLECTIONSの各コレクションに対して
     `call-with-iterator'を呼び、二つのリストを作ります。最初のリストには
     終了判定手続きが順に集められており、二つ目のリストにはインクリメント手続きが
     順に集められています。そして、これらのリストを引数としてPROCを呼び出します。
     PROCが返した値を返します。

 -- Generic function: call-with-builder collection-class proc &keyword
          size
     基礎的なビルダー構築メソッドです。ビルダーはコレクションをインクリメンタルに
     作成する方法です。コレクションクラスによってはこの手続きを提供しないものもあります。

     COLLECTION-CLASSは作成されるコレクションのクラスです。
     このメソッドは、追加手続きと結果手続きの二つの手続きを作成し、それらを
     引数としてPROCを呼びます。追加手続きは一つ引数を取り、それを作成中の
     コレクションに追加します。結果手続きは引数を取らず、作成されたコレクションを返します。
     結果手続きが呼ばれた後で追加手続きを呼んだ場合の動作は未定義です。

     作られるコレクションのサイズが分かっている場合、キーワード引数SIZEを与える
     ことができます。コレクションクラスによってはその情報を使って効率的にコレクションを
     作成することができます。その情報を単に無視するコレクションクラスもあります。
     SIZE個より多くの要素が追加されたり、SIZE個の要素が追加される前に
     結果手続きが呼ばれたりした場合の動作は未定義です。

     コレクションクラスがシーケンスクラスであった場合、追加手続きは要素を
     シーケンスの順に追加してゆきます。

     コレクションクラスによっては、コレクションオブジェクトの初期化のために
     他のキーワード引数を取るかもしれません。

     このメソッドはPROCが返す値を返します。

          (call-with-builder <list>
            (lambda (add! get)
              (add! 'a) (add! 'b) (add! 'c) (get)))
           => (a b c)

          (call-with-builder <vector>
            (lambda (add! get)
              (add! 'a) (add! 'b) (add! 'c) (get)))
           => #(a b c)

     下に示す`with-builder'マクロも参照してください。

 -- Macro: with-builder (collection add! get args ...) body ...
     `call-with-builder'を簡潔に呼び出すマクロです。
          (with-builder (coll add! get args ...) body ...)
           ==
          (call-with-builder coll
            (lambda (add! get) body ...)
            args ...)

   _Discussion_:
他のイテレータメソッドは全てこのcall-with-iteratorとcall-with-builderの上に構築可能です。
最低限これらのメソッドを定義すれば、そのクラスはコレクションとして振舞うことができます。
もちろん最適化のために他のイテレータメソッドを定義しても構いませんが。

   どの操作を基礎的なメソッドとするかには議論の余地があります。
Gaucheでは、作者がよく見るパターンで最も効率が良くなるように考えて現在のスタイルを
選びました。以下に、他の基礎的なメソッドの可能性を検討します。

`fold'
     `fold'を最も基礎的なメソッドとして、他のイテレータメソッドをその上に
     構築することも可能です。繰り返しの状態はスタックに置かれるので効率良く走ります。
     `fold'を基礎とした繰り返し関数を最適化する方法は良く知られています。
     しかし、`fold'を元にしてジェネレータスタイルのインタフェースを
     作成するのは複雑です。また、複数のコレクションに対しての繰り返しを書くのも
     面倒です。

CPS
     繰り返しの中身の手続きに対し、繰り返しを続けるための継続手続きを渡す方法です。
     繰り返しを続けたくなければ、手続きは継続を呼ばすにそのまま戻ります。
     Oleg Kiselyovの記事(*Note OLEG2: oleg2.)に指摘されているような、
     リソース管理の問題があります。

Iterator object
     C++のイテレータやCommon
     Lispのジェネレータのようなオブジェクトを使う方法です。
     ループを書くのは容易ですが、終了判定や要素取り出しの度にメソッドディスパッチが
     起こってしまいます。

Series
     Common
     Lispのシリーズはコンパイラがシリーズの使われかたを追跡できれば
     非常に効率の良いコードに変換できます。Gaucheのコンパイラはそこまでのデータフロー解析を
     行っていません。また、それをやったとしても、コレクションクラスを拡張するための方法が
     Gaucheのオブジェクトシステムとはうまく調和しません。

Macros
     効率を気にするなら、イテレータをマクロで書いてしまう方法もあります
     (例えばScheme48の`iterator'マクロなど)。
     効率は良いのですが、拡張するにはマクロを書くことが必要となり、
     Gaucheのオブジェクトシステムとうまく調和しません。

現在の実装はイテレータオブジェクトアプローチに近いですが、イテレータオブジェクトを
作る代わりにクロージャを使うことで内部のループでのメソッドディスパッチを
避けています。また、現在のインタフェースはリソース管理の問題を解決しています。


File: gauche-refj.info,  Node: コレクションの実装,  Prev: 基礎的なイテレータ構築メソッド,  Up: コレクションフレームワーク

9.3.5 コレクションの実装
------------------------

コレクションクラスの実装に最低限要求されるものには、以下のものがあります。
   * 抽象クラス`<collection>'を継承している。

   * メソッド`call-with-iterator'が実装されている。

   これにより、`map'、`for-each'、`find'、`filter'などの
イテレータメソッドが動作するようになります。

   建設的なメソッド(例えば、コレクションを作るための`map-to'など)を
作るためには、メソッド`call-with-builder'も実装しなければなりません。
メソッド`call-with-builder'は、クラスによりディスパッチされるクラスメソッドの
一種で、インスタンスによりディスパッチされる通常のメソッドとは異なります。
Gaucheでは、これはメタクラスを使うことによって実装できます。
最小限のコードは次のようになります。

     (define-class <your-collection-meta> (<class>) ())

     (define-class <your-collection> (<collection>)
      (...) ;; slots
      :metaclass <your-collection-meta>)

     (define-method call-with-iterator
         ((coll <your-collection>) proc . options)
       ...
       )

     (define-method call-with-builder
          ((coll <your-collection-meta>) proc . options)
       ...
       )

パフォーマンスの最適化のために、他のジェネリック関数をオーバロードすることも
できます。


File: gauche-refj.info,  Node: コンフィグレーション情報,  Next: 低レベルファイル操作,  Prev: コレクションフレームワーク,  Up: ライブラリモジュール - Gauche拡張モジュール

9.4 `gauche.config' - コンフィグレーション情報
==============================================

 -- Module: gauche.config
     このモジュールは、`gauche-config' プログラム経由で設定パラメータを
     取得するシンプルなラッパーを提供します。

     `gauche-config' プログラムは、Gauche の設定時に与えられた
     様々なパラメータを記録するためのシンプルなシェルスクリプトです。

 -- Function: gauche-config option
     `gauche-config' をオプション OPTION とともに呼び出すと、
     パラメータの値の文字列が返ります。gauche-config
     が理解できないオプションを 渡すとエラーになります。

     有効なオプションについては、`gauche-config' のマニュアルページを
     見るか、シェルで `gauche-config' を引数なしで実行して下さい。
          (gauche-config "--cc")
            => "gcc"
          (gauche-config "-L")
            => "-L/usr/lib/gauche/0.6.5/i686-pc-linux-gnu"
          (gauche-config "-l")
            => "-ldl -lcrypt -lm -lpthread"


File: gauche-refj.info,  Node: 低レベルファイル操作,  Next: フック,  Prev: コンフィグレーション情報,  Up: ライブラリモジュール - Gauche拡張モジュール

9.5 `gauche.fcntl' - 低レベルファイル操作
=========================================

 -- Module: gauche.fcntl
     アドバイザリ・ファイルロックを含む、
     `fcntl(2)'へのインタフェースを提供します。

 -- Function: sys-fcntl port-or-fd operation &optional arg
     PORT-OR-FD で指定されたファイルに対して特定の操作をおこないます。
     ファイル指定は、ポートオブジェクトもしくはシステムのファイルディスクリプタ
     である整数でなくてはなりません。それがポートである場合には、すでにオープン
     されたファイルを結びついていなければなりません。 (`port-type' が
     `file' を返すようなポートということです。 *Note
     ポート共通の操作::参照。)

     操作は整数 OPERATION で指定します。
     いくつかの変数が定義されいて、OPERATION に使用できます。

    `F_GETFD'
          PORT-OR-FD
          のファイルディスクリプタに結びついているフラグを返します。
          オプション引数のARGは使われません。返り値は整数で、その定義はシステム
          によります。ただし、`FD_CLOEXEC'だけは例外で、これは`exec'で
          クローズされたことを示しています。
          詳しくはあなたのシステムの`fcntl(2)'のマニュアルエントリを
          参照してください。

    `F_SETFD'
          PORT-OR-FDのファイルディスクリプタのフラグを与えられたARGに
          します。たとえば、`FL_CLOEXEC'フラグを設定する、互換性のある方法では
          次のようにします。
               (sys-fcntl port F_SETFD
                         (logior FD_CLOEXEC
                                 (sys-fcntl port F_GETFD)))

    `F_GETFL'
          PORT-OR-FDによって指定されたオープンしたファイルに結びついている
          フラグを返します。このフラグには以下のような情報が含まれています。

             * ファイルのアクセスモード。`O_ACCMODE' でマスクしたとき、
               これは、`O_RDONLY'、`O_WRONLY'、`O_RDWR'のうちどれかひとつです。

             * ファイルの作成オプション。`O_CREAT'、`O_EXCL'のどちらか、または両方。
               `O_TRUNC'.

             * `O_APPEND'でマスクしたとき、追記が許されているかどうか。

             * `O_NONBLOCK'でマスクしたとき、I/O
               が非ブロックモードかブロックモードか。

             * `O_NOCTTY'でマスクしたとき、端末制御を切離しているかどうか。

          システムが、そのシステム特有のフラグを定義していることがあります。

    `F_SETFL'
          PORT-OR-FDで指定したオープンされたファイルのフラグを設定します。
          上に列挙されたフラグのうち、`O_NONBLOCK' と `O_APPEND' だけが
          変更可能です。

          `F_GETFD'/`F_SETFD'
          はファイルディスクリプタそのものに結びついた
          フラグについてであり、一方、`F_GETFL'/`F_SETFL'
          はオープンされた
          ファイルそのものに結びついているフラグについての操作であることに注意して
          ください。この違いは、2つ以上のファイルディスクリプタが同じオープンされた
          ファイルを指しているような場合にあらわれます。

    `F_DUPFD'
          PORT-OR-FDで参照しているのと同じファイルを指す新しいファイル
          ディスクリプタを生成します。
          ARGで整数を与えなければなりません。この数は割り当てられる
          ファイルディスクリプタの最小値を指定します。

    `F_GETLK'
          3つめの引数を与えなければなりません。これは、以下に述べる`<sys-flock>'
          オブジェクトのインスタンスでなければなりません。ARGで指定された
          ロック情報を検索し、それにしかるべく変更します。

    `F_SETLK'
    `F_SETLKW'
          3つめの引数を与えなければなりません。これは、以下に述べる`<sys-flock>'
          オブジェクトのインスタンスでなければなりません。ARGにしたがって、
          アドバイザリロックを設定します。ロックの取得に成功すれば、`#t'が
          返ります。もし、別のプロセスがロックをもっていて要求したものと衝突した
          場合には `F_SETLK' のときは `#f' を返します。一方、`F_SETLKW'
          のときはロックが利用可能になるまで待ちます。

    `F_GETOWN'
          当該ファイルディスクリプタ上のイベント用シグナル、SIGIO
          および SIGURG を
          受けとることになるプロセスのプロセスIDあるいはプロセスグループを返します。
          プロセスグループは負の値で表示されます。このフラグはシステムにこのような
          機能がある場合にのみ利用可能です(BSD や Linux
          にはこの機能があります)。

    `F_SETOWN'
          当該ファイルディスクリプタ上のイベント用シグナル、SIGIO
          および SIGURG を
          受けとることになるプロセスのプロセスIDあるいはプロセスグループを設定します。
          プロセスグループは負の値で表示されます。このフラグはシステムにこのような
          機能がある場合にのみ利用可能です(BSD や Linux
          にはこの機能があります)。 詳細については、お使いのシステムの
          fcntl(2) のマニュアルページをチェック してください。


     これ以外の値を OPERATION で指定しようとするとエラーになります。

 -- Builtin Class: <sys-flock>
     POSIX
     のアドバイザリレコードロックを表わす構造体です。アドバイザリレコードロック
     というのは、適切なロックをもたないプロセスが対象ファイルを操作しても
     システムは関知しない、ということです。すべてのプロセスが、共有される可能性
     のあるファイルを操作する前にロックを`fcntl'を使って検査することが
     期待されています。

      -- Instance Variable of <sys-flock>: type
          ロックのタイプを表す整数です。利用可能な値として以下の変数があらかじめ
          定義されています。

         `F_RDLCK'
               読み込みのロック

         `F_WRLCK'
               書き込みのロック

         `F_UNLCK'
               `F_SETLK'によるロックを除去するか、あるいはレコードが`F_GETLK'
               でロックされていないことを示す。

      -- Instance Variable of <sys-flock>: whence
          `start'の計測が開始される位置を示す。

      -- Instance Variable of <sys-flock>: start
          ロックされる領域の開始位置オフセット

      -- Instance Variable of <sys-flock>: len
          ロックされるバイト数。ゼロは「EOFまで」という意味。

      -- Instance Variable of <sys-flock>: pid
          当該のロックをもっている整数のプロセスID。`F_GETLK'でのみ使用。


File: gauche-refj.info,  Node: フック,  Next: インタラクティブセッション,  Prev: 低レベルファイル操作,  Up: ライブラリモジュール - Gauche拡張モジュール

9.6 `gauche.hook' - フック
==========================

 -- Module: gauche.hook
     フックオブジェクトを提供します。これは、特定のタイミングで
     呼び出されるクロージャのリストを管理するものです。

     フックのAPIはGuileのそれと上方互換で、下記のように拡張されています。
        * Gaucheのオブジェクトシステムをベースにしています。
          ほとんどのAPIはメソッドなので、フックの機能を拡張することが
          できます。

        *
          フックオブジェクトはそれ自身適用可能です。`run-hook'を使う必要は
          ありません。

        *
          フックから手続きを削除するメソッドは、SRFI-1やその他との一貫性の
          ために`delete-hook!'と呼ばれます。
          Guileとの互換性のために、`remove-hook!'が`delete-hook!'の
          エイリアスとして定義されています。

 -- Class: <hook>
     フックのクラスで、一度に呼び出される手続きのリストを保持しています。

     `<hook>'クラスには`object-apply'メソッドが定義されているので、
     あたかもそれが手続きであるかのようにフックオブジェクトを"適用"できます。
     フックオブジェクトを適用すると、登録されている全ての手続きが呼び出されます。

 -- Function: make-hook &optional (arity 0)
     与えられたアリティ(正の整数でなければなりません)とともに新しい
     フックオブジェクトを作成します。

 -- Function: hook? obj
     OBJがフックオブジェクトであれば、真を返します。

 -- Function: hook-empty? hook
     HOOKの手続きリストが空なら、真を返します。

 -- Method: add-hook! (hook <hook>) proc &optional (append? #f)
     手続きPROCをHOOKに追加します。
     APPEND?が与えられ真であれば、PROCはリストの最後に
     追加されます。そうでなければ、PROCはリストの最初に追加 されます。
     PROCは、`make-hook'時に与えられたアリティとともに
     呼ばれなければなりません。

 -- Method: delete-hook! (hook <hook>) proc
 -- Method: remove-hook! (hook <hook>) proc
     HOOKの手続きリストからPROCを削除します。
     Guileとの互換性のためだけに、`remove-hook!'が`delete-hook!'の
     エイリアスとなっています。

 -- Method: reset-hook! (hook <hook>)
     HOOKの手続きリストを空にします。

 -- Method: hook->list (hook <hook>)
     HOOKの手続きリストのコピーを返します。

 -- Method: run-hook (hook <hook>) arg ...
     HOOKの手続きを、ARG ...を引数として順番に呼び出します。
     引数の数は、`make-hook'時に与えられたアリティにマッチしなければ
     なりません。


File: gauche-refj.info,  Node: インタラクティブセッション,  Next: リスナー,  Prev: フック,  Up: ライブラリモジュール - Gauche拡張モジュール

9.7 `gauche.interactive' - インタラクティブセッション
=====================================================

 -- Module: gauche.interactive
     インタラクティブセッションで便利なユーティリティ手続きを提供します。

     `gosh'をインタラクティブモードで起動した場合、
     このモジュールは自動的にロードされます。

     また、このモジュールは`gauche.reload' (*Note
     モジュールの再ロード::参照)で定義される
     手続きに対してautoloadを設定し、それらの手続きが
     インタラクティブな開発時にデフォルトで使えるようにします。

 -- Macro: apropos pattern &optional module
     名前がPATTERNにマッチするような定義された変数のリストを表示します。
     MODULEにモジュールオブジェクトまたはモジュール名を与えた場合は、
     そのモジュール内で定義されている変数のみが表示されます。MODULEが
     省略された場合は、カレントモジュールから「見える」変数が全て表示されます。

     PATTERNはシンボルか正規表現オブジェクトでなければなりません。
     シンボルの場合、そのシンボル名を部分文字列として名前に含むような変数が
     リストされます。正規表現オブジェクトの場合は、その正規表現にマッチする
     名前を持つ変数がリストされます。

     いくつか例を示します。
          ;; "string"を名前に含む変数を表示
          (apropos 'string)

          ;; srfi-14モジュールの中のみを検索
          (apropos 'char 'srfi-14)

 -- Generic Function: describe obj
 -- Generic Function: d obj
     SchemeオブジェクトOBJの詳細情報を表示します。
     既定メソッドはOBJのクラスを表示し、さらにOBJがスロットを
     持っていればその名前と内容をリストします。
     このメソッドをスペシャライズすることによりクラス毎に表示をカスタマイズできます。

 -- Function: info symbol
     Gaucheのinfoドキュメント中から、
     SYMBOLで指定される手続きか構文要素の定義を含んでいるページを表示します。
     infoドキュメントは、もし環境変数`INFOPATH'が定義されていればそこに
     示されるディレクトリ中から探され、そうでなければ`gosh'のライブラリディレクトリ
     から推測されるディレクトリ中から探されます。infoドキュメントが見付からなかったり、
     見付かってもSYMBOLがIndexページ中に無かった場合はエラーとなります。
     つまり、この手続きはinfoファイルがインストールされていないと動作しません。

     現在の出力ポートが端末である場合、infoドキュメントの該当ページは
     ページングプログラムを用いて表示されます。環境変数`PAGER'が指定されていれば
     それを用い、そうでなければコマンドサーチパスから`less'及び`more'を
     この順で探します。いずれも見付からなかった場合や、出力ポートが端末では
     ない場合には、単にページがそのまま出力されます。

     この手続きのセッション中での最初の呼び出しは、infoファイルをパーズするために
     多少時間がかかります。


File: gauche-refj.info,  Node: リスナー,  Next: ユーザレベルのロギング,  Prev: インタラクティブセッション,  Up: ライブラリモジュール - Gauche拡張モジュール

9.8 `gauche.listener' - リスナー
================================

 -- Module: gauche.listener
     このモジュールは、
     複数のread-eval-printループ(repl)を並行して動作させるのに便利な機能を提供します。

     複数のreplを実現する自明な方法は、セッション毎にスレッドを生成して
     各スレッド上で`read-eval-print-loop' (*Note eval と repl::参照)を
     呼ぶことですが、シングルスレッドでの実装が好ましい場合もあります。
     例えばアプリケーションがMT-safeでないライブラリに大きく依存していたり、
     既にアプリケーションがselectやpollをベースにしたディスパッチメカニズムを
     持っているような場合です。

     シングルスレッドのselectionベースのアプリケーションでreplを実装するには、
     通常、listenしているポートにデータが到着した時に呼ばれるハンドラを登録します。
     ハンドラはポートからデータを読み、内部バッファに追加します。
     そして内部バッファをスキャンし、データが完全な式を構成した場合は
     それをS式として読みだし、評価して結果をポートに流します。
     このモジュールの`<listener>'クラスはこのハンドラのメカニズムを提供するので、
     アプリケーション側はそれを自分のディスパッチメカニズムに登録するだけで済みます。

     註：場合によっては、出力もバッファリングする必要があるかもしれませんが、
     現在はそれは実装されていません。

 -- Class: <listener>
     Replセッションの状態を維持するオブジェクトです。
     オブジェクトのふるまいをカスタマイズするためにいくつもの外部スロットがあります。
     これらのスロットの値は、スロットの名前と同名のキーワード引数を用いて
     オブジェクトの構築時に指定することもできますし、オブジェクト構築後に
     `slot-set!'で設定することもできますが、`listener-read-handler'
     を呼ぶ前に確定していなければなりません。

      -- Instance Variable of <listener>: input-port
          リスナーが入力を受けとる入力ポートを指定します。デフォルト値は、
          オブジェクトが構築された時のカレント入力ポートです。

      -- Instance Variable of <listener>: output-port
          リスナーが出力をおこなう出力ポートを指定します。デフォルト値は、
          オブジェクトが構築された時のカレント出力ポートです。

      -- Instance Variable of <listener>: error-port
          リスナーのエラーメッセージを出力するポートを指定します。デフォルト値は、
          オブジェクトが構築された時のカレントエラー出力ポートです。

      -- Instance Variable of <listener>: reader
          引数を取らない手続きです。呼び出し時のカレント入力ポートからScheme式を
          読み込まなければなりません。デフォルト値はシステムの`read'手続きです。

      -- Instance Variable of <listener>: evaluator
          Scheme式と環境指定子のふたつの引数をとる手続きです。
          式を与えられた環境で評価し、0個以上の値を返さなければなりません。
          デフォルト値はシステムの`eval'手続きです。

      -- Instance Variable of <listener>: printer
          0以上の引数をとり、カレント出力ポートに印字する手続きです。
          デフォルト値は、各値を`write'で印字したのち、改行する手続きです。

      -- Instance Variable of <listener>: prompter
          引数をとらない手続きです。カレント出力ポートにプロンプトを
          印字しなければなりません。リスナーは、この手続きが面倒を見なくてよいように、
          出力をフラッシュします。 デフォルトの手続きは `"listener> "'
          を印字します。

      -- Instance Variable of <listener>: environment
          式を評価する環境指定子です。デフォルト値は`(interaction-environment)'が
          返す値です。

      -- Instance Variable of <listener>: finalizer
          `input-port'からEOFが読み込まれたときに呼び出されるサンクです。
          このような手続きが必要ない場合は`#f'にしておいて構いません。
          デフォルトの値は`#f'です。

      -- Instance Variable of <listener>: error-handler
          エラー例外をひとつ引数としてとる手続きです。read-eval-printの最中に
          エラーが発生すると、エラーシグナルが発生すのと同じ動的環境で、
          呼び出されます。
          デフォルト値はエラー例外を`report-error'を使って印字する手続きです。

 -- Method: listener-read-handler (listener <listener>)
     リスナーの`input-port'から読み込んだデータが正しい時に
     呼ばれるサンクを返します。

     返されたサンク(readハンドラ)は、以下のように実行されます。
     この手続きは最初のプロンプトを印字_しない_ことに
     注意してください。これについては後述の`listener-show-prompt'を
     参照してください。
       1. `input-port'にあるデータを読み、これをリスナーの内部バッファに
          連結する。

       2. バッファをスキャンして、それが完結したS式であるかを確かめ、
          完結していなければ、リターンする。

       3. バッファからそのS式を読み込み、そのバッファからは
          そのデータを除去する。

       4. そのS式を評価して、結果を`output-port'へ印字する。
          `output-port'.

       5.
          プロンプタ手続きを使って、プロンプトを`output-port'に印字したのち、
          `output-port'をフラッシュする。

       6. 2から繰り返す。

 -- Method: listener-show-prompt (listener <listener>)
     リスナーの出力ポートにプロンプトを表示します。表示にはリスナーの
     プロンプタ手続きを使います。通常この手続きは最初のプロンプトを
     印字するために使います。たとえば、クライアントがリスナーソケットに
     接続してきたときです。

 -- Function: complete-sexp? str
     もし、STRが完結したＳ式を含んでいれば`#t'を返します。
     このユーティリティ手続きは、他の目的にも有用なので、
     他の手続きといっしょにエクスポートしてあります。

     この手続きは構文のチェックをするだけで、(不正な文字名を含んだり、
     登録されていないSRFI-10のタグを含むなど)誤りのある式を判別するわけでは
     ないことに注意してください。この手続きは入力が'`#<''文字の
     シーケンスを含むと、エラーを発生させます。

   以下のコード断片は、サーバソケットをオープンし、クライアントが
接続してきたときにSchemeの対話的セッションをオープンするというものです。
(註: このコードはdemo用のコードです。決して、外のネットワークから
アクセス可能なマシン上で走らせてはいけません！)

     (use gauche.net)
     (use gauche.selector)
     (use gauche.listener)

     (define (scheme-server port)
       (let ((selector (make <selector>))
             (server   (make-server-socket 'inet port :reuse-addr? #t))
             (cid      0))

         (define (accept-handler sock flag)
           (let* ((client (socket-accept server))
                  (id     cid)
                  (input  (socket-input-port client :buffering :none))
                  (output (socket-output-port client))
                  (finalize (lambda ()
                              (selector-delete! selector input #f #f)
                              (socket-close client)
                              (format #t "client #~a disconnected\n" id)))
                  (listener (make <listener>
                              :input-port input
                              :output-port output
                              :error-port output
                              :prompter (lambda () (format #t "client[~a]> " id))
                              :finalizer finalize))
                  (handler (listener-read-handler listener))
                  )
             (format #t "client #~a from ~a\n" cid (socket-address client))
             (inc! cid)
             (listener-show-prompt listener)
             (selector-add! selector input (lambda _ (handler)) '(r))))

         (selector-add! selector
                        (socket-fd server)
                        accept-handler
                        '(r))
         (format #t "scheme server started on port ~s\n" port)
         (do () (#f) (selector-select selector))))


File: gauche-refj.info,  Node: ユーザレベルのロギング,  Next: シングルトン,  Prev: リスナー,  Up: ライブラリモジュール - Gauche拡張モジュール

9.9 `gauche.logger' - ユーザレベルのロギング
============================================

 -- Module: gauche.logger
     プログラムからログを書き出す簡単なインタフェースを提供します。
     情報は指定されたファイルへ書き出されるか、もしくは`syslog(3)'を
     使ってシステムログへと送られます。 ファイルに書き出される場合は、
     syslogに似たプレフィクスが各メッセージの前に追加されます。
     プレフィクスはカスタマイズすることもできます。
     また、ログファイルの排他制御も行われます (下の`lock-policy'の説明を
     参照して下さい)。

 -- Class: <log-drain>
     ログメッセージの行き先を表現するオブジェクトです。
     デフォルトのログの行き先として、グローバルな`<log-drain>'のインスタンスが
     ひとつ作られます。
     ログをいくつかにわけて出力する場合などは`make'メソッドを使って
     いくつでも`<log-drain>'のインスタンスを作ることができます。

      -- Instance Variable of <log-drain>: path
          ログファイルのパス名か、`#t'、`#f'、あるいはシンボル`syslog'
          の値を取ります。このスロットが`#t'の場合、ログメッセージは現在のエラーポートに
          書き出されます。`#f'の場合は`log-format'は
          ログを書き出すかわりにフォーマットされたログメッセージを文字列として返します。
          シンボル`syslog'の場合はメッセージがシステムログへと送られます。

          このスロットの初期値は`#f'です。

      -- Instance Variable of <log-drain>: prefix
          各メッセージの前に追加されるプレフィクス文字列を指定します。
          メッセージが複数行に渡る場合、プレフィクスは各行の頭に追加されます。
          またこのスロットには手続きをセットすることもできます。
          その場合、プレフィクス文字列が必要とされる度にその手続きが`<log-drain>'
          を引数として呼び出され、戻り値の文字列がプレフィクスとして使われます。

          `path'スロットの値がシンボル`syslog'の場合は、
          このスロットの値は無視されます。システムのログ機構が適切なプレフィクスを付けるからです。

          prefixスロットの値が文字列の場合、以下に挙げる文字シーケンスは特別な意味を持ち、
          `log-format'によって置換されます。

         `~T'
               現在の時刻を"Mmm DD hh:mm:ss"という形式で表したもの。
               ここで"Mmm" は英語の月名の省略形、"DD" は日、"hh"、"mm"、
               "ss" は時間(24時間制)、分、秒です。
               このフォーマットはシステムログと同じです。

         `~Y'
               4桁で表した現在の西暦。

         `~P'
               プログラム名。初期値は`*program-name*'の値のbasenameが使われます
               (*Note Schemeスクリプトを書く::参照)。
               下に述べる`program-name'スロットの値を変えれば
               ここに現れる文字列を変えることができます。

         `~$'
               このプログラムのプロセスID。

         `~U'
               このプロセスの実行ユーザ名。

         `~H'
               このプロセスが走っているホスト名。

          このスロットの初期値は"`~T ~P[~$]: '"です。例えば "this is a
          log message.\nline 2\nline 3"というメッセージが
          与えられると、次のようなログが書き出されます。

               Sep  1 17:30:23 myprogram[441]: this is a log message
               Sep  1 17:30:23 myprogram[441]: line 2
               Sep  1 17:30:23 myprogram[441]: line 3


      -- Instance Variable of <log-drain>: program-name
          プレフィクス文字列の`~P'が置換されるプログラム名を指定します。

      -- Instance Variable of <log-drain>: lock-policy
          ログファイルのロックの方法を指定します。
          このスロットの値がシンボル`fcntl'だった場合は、
          fcntl()によるファイルロックが使われます (*Note
          低レベルファイル操作::参照)。
          このスロットの値がシンボル`file'だった場合は、
          ログファイルのパス名に ".lock"
          を追加したロックファイルを作成することによる
          排他制御が行われます。この場合、ログを行うプロセスはログファイルの
          置かれるディレクトリに書き込み権限が必要です。
          また、プロセスがログファイル書き込み中に強制的に終了させられた場合、
          ロックファイルが残ってしまう恐れがあります。
          `Log-format'はロックファイルが十分に古い場合(現在は10分をリミットとしています)
          ロックファイルを自動的に削除します。
          このスロットの値が`#f'だった場合は、排他制御は行われません。

          デフォルトの値は`fcntl'です。但しMacOSXではfcntlスタイルのロックが
          サポートされていないため、`file'がデフォルト値となります。

          ログの行き先がファイルでない場合は排他制御は行われません。

      -- Instance Variable of <log-drain>: syslog-option
      -- Instance Variable of <log-drain>: syslog-facility
      -- Instance Variable of <log-drain>: syslog-priority
          これらのスロットの値は、ログの行き先がシステムログの場合にのみ使われます。
          これらの値に関する説明は*Note Syslog::を参照して下さい。
          デフォルトの値はそれぞれ`LOG_PID'、`LOG_USER'、`LOG_INFO'です。

 -- Function: log-open path &keyword prefix program-name
     デフォルトのログの行き先をPATHに指定します。
     PATHは文字列かboolean値あるいはシンボル`syslog'で、
     上の`path'スロットで述べたものと
     おなじ意味を持ちます。またプレフィクスとプログラム名をキーワード引数で
     指定することもできます。

     名前に"open"とありますが、この手続きは指定されたファイルをオープンしません。
     ファイルは`log-format'が呼ばれるたびにオープンされクローズされます。

 -- Method: log-format (format <string>) arg ...
 -- Method: log-format (drain <log-drain>) (format <string>) arg ...
     ログメッセージを`format'手続きでフォーマットし(*Note 出力::参照)、
     指定された行き先に書き出します。最初の形式ではデフォルトの行き先が使われます。

     ファイルはこの手続きが呼ばれるたびにオープンされクローズされます。
     したがって、ログファイルに書き出すプログラムが走っている最中でも
     ログファイルをmoveすることができます。
     また、`log-format'は`sys-fcntl' (*Note 低レベルファイル操作::参照)
     を使ってファイルロックを獲得します。

     `log-open'が呼ばれる前に`log-format'が最初の形式で呼ばれた場合、
     `log-format'は何もしません。したがって、`log-format'をデバッグに
     活用し、必要なくなったら`log-open'だけをコメントアウトする、というような
     使用法も可能です。


File: gauche-refj.info,  Node: シングルトン,  Next: Validator付きスロット,  Prev: ユーザレベルのロギング,  Up: ライブラリモジュール - Gauche拡張モジュール

9.10 `gauche.mop.singleton' - シングルトン
==========================================

 -- Module: gauche.mop.singleton
     シングルトンクラスを定義するためのメタクラスを提供します。

 -- Class: <singleton-meta>
     シングルトンクラスを生成します。シングルトンクラスはそのインスタンスが
     ただ一つしかないことを保証するクラスです。 `make' の
     最初の呼び出しで、唯一のインスタンスを生成し、その後の呼出しでは
     最初に生成したものと同一のインスタンスを返します。
          (define-class single () () :metaclass <singleton-meta>)

          (define a (make single))
          (define b (make single))

          (eq? a b) => #t

     インスタンスのスロットは最初の `make' の呼び出し時に
     初期化されます。`make'への初期引数は最初の呼び出しのときに
     だけ効果があり、それ以降の呼び出しでは無視されます。

 -- Method: instance-of (class <singleton-meta>) &rest initargs
     このメソッドは渡された引数とともに `make' を呼んでいるだけです。
     シングルトンを扱うプログラム中ではこちらの方が分りやすいでしょう。

 -- Class: <singleton-mixin>
     `<singleton-meta>'のインスタンスです。`<singleton-meta>' を
     `define-class' の `:metaclass' 引数として指定せずに、
     このクラスを継承することで、定義しようとするクラスにシングルトンの
     性質を与えることができます。


File: gauche-refj.info,  Node: Validator付きスロット,  Next: ネットワーキング,  Prev: シングルトン,  Up: ライブラリモジュール - Gauche拡張モジュール

9.11 `gauche.mop.validator' - Validator付きスロット
===================================================

 -- Module: gauche.mop.validator
     `:validator'スロットオプションを追加するメタクラスを提供するモジュールです。

 -- Class: <validator-meta>
     このメタクラスは、スロットに対して値がセットされようとする時にその値の正当性を
     検査する手続きを指定する機能を提供します。例えば、あるスロットに常に文字列のみが
     セットされているようにしたい場合、そのスロットに、`slot-ref'経由であれ
     アクセサメソッド経由であれ値がセットされようとした時に指定の手続きが呼ばれるように
     し、その手続きの中で、値が文字列でなかったらエラーとするか、強制的に値を
     文字列に変換してしまうことができます。その手続きが返した値が実際にスロットに
     セットされます。

     検査手続きは`:validator'スロットオプションによってスロット毎に指定できます。
     手続きは、インスタンスとセットされようとしている値の二つを引数に取ります。
     その手続きが返した値が実際にスロットにセットされる値となります。
     下の例を参照して下さい。

          (define-class <v> ()
            ((a :accessor a-of
                :validator (lambda (obj value) (x->string value)))
             (b :accessor b-of
                :validator (lambda (obj value)
                             (if (integer? value)
                                 value
                                 (error "integer required for slot b")))))
            :metaclass <validator-meta>)

          (define v (make <v>))
          (slot-set! v 'a 'foo)
          (slot-ref v 'a) => "foo"

          (set! (a-of v) 1234)
          (a-of v) => "1234"

          (slot-set! v 'b 55)
          (slot-ref v 'b) => 55

          (slot-set! v 'b 3.4) => error
          (set! (b-of v) 3.4)  => error

     `:validator' が指定されたスロットにも、`:init-value'等を
     使って既定の初期値を指定しておくことができます。その場合、インスタンスの初期化ルーチンは、
     init-keywordによる初期値指定が無ければ既定の初期値を引数としてvalidator手続きを
     呼び出します。

          (define-class <v> ()
            ((a :initform 'foo :init-keyword :a
                :validator (lambda (obj value) (x->string value)))))

          (slot-ref (make <v>) 'a)        => "foo"
          (slot-ref (make <v> :a 555) 'a) => "555"

     仮想スロットに似ていますが、validatorを持つスロットはインスタンス内に実際に
     値を格納している点が異なります。

     このモジュールはまた、スロットのアクセスをメタオブジェクトプロトコルを使って
     カスタマイズする例でもあります。この機能は20行ほどのコードで実現されています。


File: gauche-refj.info,  Node: ネットワーキング,  Next: パラメータ,  Prev: Validator付きスロット,  Up: ライブラリモジュール - Gauche拡張モジュール

9.12 `gauche.net' - ネットワーキング
====================================

 -- Module: gauche.net
     BSDソケットに基づいたネットワーキングに必要な手続きを提供するモジュールです。

     2つのレベルのAPIが定義されています。低レベルの手続きは`bind(2)'のような
     BSDソケットインタフェースに近いインタフェースを提供し、高レベルの手続きは
     典型的なコネクション指向のクライアントサーバアプリケーションに便利な
     インタフェースを提供します。

     また、ホストネームやプロトコルに関する情報にアクセスするAPIも定義されます。

* Menu:

* ソケットアドレス::
* 高レベルネットワーク手続き::
* 低レベルソケットインタフェース::
* Netdbインタフェース::


File: gauche-refj.info,  Node: ソケットアドレス,  Next: 高レベルネットワーク手続き,  Prev: ネットワーキング,  Up: ネットワーキング

9.12.1 ソケットアドレス
-----------------------

 -- Builtin Class: <sockaddr>
     ソケットアドレスの抽象ベースクラスです。
     ソケットアドレスファミリはこのクラスのサブクラスとして実装されます。

     ソケットアドレスはビルトインクラスですが、`make'メソッドで
     特定のソケットアドレスファミリのインスタンスを作成することができます。

 -- Generic Function: sockaddr-family addr
     ソケットアドレスADDRのファミリを表すシンボルを返します。

 -- Generic Function: sockaddr-name addr
     ソケットアドレスADDRの名前を表す文字列を返します。

 -- Builtin Class: <sockaddr-in>
     AF_INETファミリのソケットアドレスです。このクラスのインスタンスを
     作成するには、次のようにして`make'メソッドを呼びます。
          (make <sockaddr-in> :host HOST :port PORT)
     HOSTは文字列か、 `:any'、`:broadcast'、`:none'、`:loopback'の
     いずれかのキーワードでなければなりません。
     文字列の場合、それはホスト名かIPアドレスのドット表記です。
     Gaucheは`gethostbyname(3)'を使って実際のIPアドレスを得ます。
     この値がキーワード`:any'か`:broadcast'なら、それぞれ
     `INADDR_ANY'か`INADDR_BROADCAST'がアドレスとして使われます。
     キーワード`:loopback'はIPv4のループバックアドレス"127.0.0.1"を表します。

     PORTはポート番号を示す正の整数です。
     2つ以上のプロトコルスタックを持つようなマシン上で複数のソケットアドレスを
     生成するには、後述の `make-sockaddrs' も参照してください。

 -- Method: sockaddr-family (addr <sockaddr-in>)
     シンボル`inet'を返します。

 -- Method: sockaddr-name (addr <sockaddr-in>)
     文字列"A.B.C.D:PORT"を返します。
     コロンの前はIPアドレスのドット表記で、PORTはポート番号です。

 -- Method: sockaddr-addr (addr <sockaddr-in>)
     IPアドレスを整数で返します。

 -- Method: sockaddr-port (addr <sockaddr-in>)
     ポート番号を整数で返します。

 -- Builtin Class: <sockaddr-un>
     AF_UNIXファミリのソケットアドレスです。このクラスのインスタンスを作成するには、
     `make'メソッドを次のように呼んで下さい。
          (make <sockaddr-un> :path PATH)
     PATHはソケットのパス名を表す文字列です。

 -- Method: sockaddr-family (addr <sockaddr-un>)
     シンボル`unix'を返します。

 -- Method: sockaddr-name (addr <sockaddr-un>)
     ソケットアドレスのパス名を返します。

 -- Builtin Class: <sockaddr-in6>
     AF_INET6ファミリのソケットアドレスです。
     このクラスはgaucheが-enable-ipv6つきでconfigureされている場合に使えます。
     コンストラクタとスロットは`<sockaddr-in>'と同じです。
     2つ以上のプロトコルスタックを持つようなマシン上で複数のソケットアドレスを
     生成するには、後述の `make-sockaddrs' も参照してください。

 -- Function: make-sockaddrs host port &optional proto
     これは上位レベルのユーティリティ手続きで、プロトコル PROTO の
     `HOST:PORT' を指す、可能なすべてのドメインソケット
     アドレスを生成します。特に、指定したホストが IPv4 および IPv6
     の両方の
     アドレスを持ち、稼働中のシステムがその両方をサポートしている場合、IPv4
     と IPv6 の両方のソケットアドレスが返ります。もし、HOST が複数の IP
     アドレスをもつ場合、ソケットアドレスはそれぞれのIPアドレス毎に生成
     されます。自分のネットワークアプリケーションを異るネットワークスタックの
     設定の間でこれまでよりはるかにポータブルなものにすることができます。

     HOST に `#f' を渡すと、ローカルな(サーバ)アドレスが生成されます。
     PORT 引数に整数のかわりに、サービス名(たとえば、`"http"')を
     わたすこともできます。PROTO の値は、`tcp' あるいは `udp'
     のどちらかのシンボルになります。デフォルトでは、`tcp' です。

     この手続きは常にソケットアドレスのリストを返します。もし、HOST の
     検索に失敗した場合には、空リストが返ります。


File: gauche-refj.info,  Node: 高レベルネットワーク手続き,  Next: 低レベルソケットインタフェース,  Prev: ソケットアドレス,  Up: ネットワーキング

9.12.2 高レベルネットワーク手続き
---------------------------------

 -- Builtin Class: <socket>
     コミュニケーション終端であるソケットを表すクラスです。

     コネクション型のソケットに対しては、2つのポート(入力用と出力用)を使って
     コミュニケーションチャネルにアクセスすることができます。
     `socket-input-port'と`socket-output-port'がこれらのポートを
     それぞれ返します。

   以下の2つの手続きはコネクション型のソケットを作成する
便利な手続きです。これらは典型的な場合に対する簡単な方法を提供しますが、
細かい制御はできません。動作のより細かい制御が必要な場合は低レベルAPIを
見て下さい。

 -- Function: make-client-socket &optional address-spec ...
     引数ADDRESS-SPEC ... によって指定されるアドレスと通信する
     クライアントソケットを作成して返します。

    `(make-client-socket 'unix PATH)'
          PATHで待っているUnixドメインのサーバーソケットに接続します。

    `(make-client-socket 'inet HOST PORT)'
          ホストHOSTのポートPORTで待っているInetドメインのサーバーソケットに
          TCPを使って接続します。HOSTはIPアドレスのドット表記でもホスト名でも
          構いません。Gaucheが-enable-ipv6でコンパイルされていれば、IPv6形式のアドレス
          表記も受け付けます。
          PORTはポート番号を指定する正確な整数か、文字列のサービス名
          (`"http"'等)でなければなりません。

          Gaucheが-enable-ipv6でコンパイルされており、ホスト名が渡されて、
          そのホストがIPv6とIPv4の両方のアドレスを持っていた場合は、
          最初にIPv6での接続が試みられ、それが失敗した場合にIPv4での接続が試みられます。

    `(make-client-socket HOST PORT)'
          上と同じです。この形式はSTkとの互換性のために提供されています。

    `(make-client-socket SOCKADDR)'
          `<sockaddr>'のインスタンスが渡された場合には、それに対応する
          ソケットがオープンされ、そのアドレスへと接続されます。

     ソケットを作成できなかったり、指定されたアドレスに接続できなかった場合は
     エラーが報告されます。

          (make-client-socket 'inet "www.w3.com" 80)
            => ;a socket connected to www.w3.com, port 80
          (make-client-socket "127.0.0.1" 23)
            => ;a socket connected to localhost, port 23
          (make-client-socket 'unix "/tmp/.sock"
            => ;a socket connected to a unix domain socket "/tmp/.sock"

 -- Function: make-server-socket &optional address-spec ...
     ADDRESS-SPECにて接続を待つサーバソケットを作成して返します。

    `(make-server-socket 'unix PATH)'
          パス名PATHを持つUnixドメインソケットが作成されます。

    `(make-server-socket 'inet PORT [:reuse-addr? FLAG] [:sock-init PROC])'
          ポートPORTにて接続を待つInetドメインのTCPソケットが作成されます。
          PORTは非負の整数か、文字列のサービス名(`"http"'等)でなければなりません。
          PORTが0の場合はシステムが適当なポート番号を割り当てます。
          キーワード引数REUSE-ADDR?に真の値が与えられた場合は、
          ソケットに`SO_REUSEADDR'オプションがセットされます。
          このオプションをセットすると、他のプロセスがそのポートを使わなくなったら直ちに
          このプロセスがそのポートを使うことができます。

          キーワード引数`sock-init'が与えられた場合、それは
          2つ引数を取る手続きでなければなりません。その手続きは
          ソケットが作られた直後に、ソケットとアドレスを引数にして呼び出されます。
          特殊なソケットオプションを設定したいような場合に使えます。

    `(make-server-socket PORT [:reuse-addr? FLAG] [:sock-init PROC])'
          これは、PORTが整数でなければならないことを除けば、
          上の形式と同じ動作をします。STkの`make-server-socket'との
          互換性のために提供されています。

    `(make-server-socket SOCKADDR [:reuse-addr? FLAG][:sock-init PROC])'
          この形式は、listenするソケットアドレスを`<sockaddr>'のインスタンスで
          明示的に指定します。

          (make-server-socket 'inet 8080)
            => #<socket (listen "0.0.0.0:8080")>
          (make-server-socket 8080)
            => #<socket (listen "0.0.0.0:8080")>
          (make-server-socket 'inet 0)
            => #<socket (listen "0.0.0.0:35628")>
          (make-server-socket 'unix "/tmp/.sock")
            => #<socket (listen "/tmp/.sock")>

 -- Function: make-server-sockets host port &keyword reuse-addr?
          sock-init
     HOST のすべての利用可能なネットワークインタフェース上の PORT
     をリッスンする1つ以上のソケットを生成します。 PORT
     に対しては数字のポート番号と同様に、サービス名を
     指定できます。たとえば、"`http'" です。この手続きは
     オープンされ、バインドされ、リッスンされたソケットのリストを
     返します。

     この手続きは、ホストが複数のプロトコルスタック(IPv4とIPv6など)を
     持つ場合に特に便利です。このような場合、両方のプロトコルで
     リッスンするようなサーバを `make-server-sockets' をつかって、
     スタートすることができます。

     キーワード引数の意味は`make-server-socket'のそれと同じです。

返されたソケットオブジェクトに対して、以下のようなアクセサを適用することができます。

 -- Function: socket-address socket
     ソケットSOCKETのアドレスを返します。
     ソケットにアドレスがまだバインドされていない場合は`#f'が返ります。

 -- Function: socket-input-port socket &keyword (buffering `:modest')
 -- Function: socket-output-port socket &keyword (buffering `:line')
     SOCKETからデータを読みだす入力ポート、または
     SOCKETにデータを書き出す出力ポートを返します。

     キーワード引数BUFFERINGはポートのバッファリングモードを
     指定します。バッファリングモードの説明は*Note
     ファイルポート::を見て下さい。

 -- Function: socket-close socket
     ソケットSOCKETをクローズします。SOCKETの入出力ポートも
     クローズされます。

     注意: リリース 0.7.2
     より、この手続きは接続をシャットダウンしないように
     なりました。その理由は、SOCKET が fork した別プロセスから参照され
     ている可能性があり、既存の接続を妨害することなくクローズしたい場合がある
     からです。`socket-shutdown'
     を呼べば接続を明示的にシャットダウンできます。

 -- Function: call-with-client-socket socket proc
     SOCKETは接続されたクライアントソケットでなければなりません。
     PROCがソケットから読み出す入力ポートと、
     ソケットに書き出す出力ポートを引数として呼ばれます。
     PROCが正常終了するか、エラーを投げた場合にソケットは閉じられます。

これは高レベルソケット手続きを使った、非常に単純なhttpクライアントです。

     #!/usr/bin/env gosh
     (use gauche.regexp)
     (use gauche.net)

     (define (usage)
       (display "Usage: swget url\n" (current-error-port))
       (exit 1))

     ;; Returns three values: host, port, and path.
     (define (parse-url url)
       (rxmatch-let (rxmatch #/^http:\/\/([-A-Za-z\d.]+)(:(\d+))?(\/.*)?/ url)
           (#f host #f port path)
         (values host port path)))

     (define (get url)
       (receive (host port path) (parse-url url)
         (call-with-client-socket
             (make-client-socket 'inet host (string->number (or port "80")))
           (lambda (in out)
             (format out "GET ~a HTTP/1.0\r\n" path)
             (format out "host: ~a\r\n\r\n" host)
             (flush out)
             (copy-port in (current-output-port))))))

     (define (main args)
       (if (= (length args) 2)
           (get (cadr args))
           (usage))
       0)


File: gauche-refj.info,  Node: 低レベルソケットインタフェース,  Next: Netdbインタフェース,  Prev: 高レベルネットワーク手続き,  Up: ネットワーキング

9.12.3 低レベルソケットインタフェース
-------------------------------------

ここにある関数群はシステムコールと類似した API を提供します。 ソケット
API プログラミングに慣れていれば、ソケットをより細かく
制御できるので、役に立つでしょう。

 -- Function: make-socket domain type &optional protocol
     パラメータで指定したソケットを返します。

 -- Variable: PF_UNIX
 -- Variable: PF_INET
     これらの変数はそれぞれ、`PF_UNIX'、`PF_INET' に束縛されています。

 -- Variable: AF_UNIX
 -- Variable: AF_INET
     これらの変数はそれぞれ、`AF_UNIX'、`AF_INET' に束縛されています。

 -- Variable: SOCK_STREAM
 -- Variable: SOCK_DGRAM
 -- Variable: SOCK_RAW
     これらの変数はそれぞれ、`SOCK_STREAM'、`SOCK_DGRAM'、 `SOCK_RAW'
     に束縛されています。

 -- Function: socket-fd socket
     ソケットのもつ整数のシステムファイルディスクリプタを返します。

 -- Function: socket-status socket
     SOCKET の内部状態を、以下のシンボルのどれかで返します。
     none                生成直後
     bound               `socket-bind'
                         によって、あるアドレスに束縛されている
     listening           `socket-listen' によって、接続をリッスンしている
     connected           `socket-connect' あるいは `socket-accept'
                         によって接続されている
     shutdown            `socket-shutdown' によってシャットダウンされた
     closed              `socket-close' によってクローズされた

 -- Function: socket-bind socket address
     SOCKET をローカルネットワークアドレス ADDRESS に束縛します。
     通常は、特定のアドレスをこのサーバのポートに結びつけるのに用います。
     もし、束縛が失敗したら(多くの場合、そのアドレスが既に使用されている)、
     エラーシグナルが発生します。

     INET ドメインアドレスの場合には port=0 とした ADDRESS を
     渡せます。システムがポート番号を割当て、SOCKET の `address'
     スロットに実際のアドレスをセットします。

 -- Function: socket-listen socket backlog
     SOCKET をリッスンします。ソケットは既になんらかのアドレスに
     束縛されていなければなりません。BACKLOG はキューに入れる
     接続要求の最大数を指定します。

 -- Function: socket-accept socket
     SOCKETに来た接続要求をアクセプトします。リモートエンティティへ
     接続している新しいソケットを返します。元の SOCKET は引き続き
     次の接続要求を待ちます。接続要求がないとき、これの呼出しは要求が
     一つ来るまで待ちます。

     接続要求をペンディングしているかどうかをチェックするのに
     `sys-select'が使えます。

 -- Function: socket-connect socket address
     SOCKET をリモートアドレス ADDRESS に接続します。
     これは、クライアントソケットをリモートエンティティに接続するための
     方法です。

 -- Function: socket-shutdown socket how
     SOCKET の接続をシャットダウンします。HOW が0なら、 SOCKET
     の受信チャネルが不許可となります。HOW が1なら、 SOCKET
     の送信チャネルが不許可となります。HOW が2なら、 SOCKET
     の送受信チャネルの両方が不許可となります。
     接続していないソケットに対して、この手続きを呼ぶとエラーになります。

     ソケットの送信チャネルをシャットダウンすると、リモート側の受信チャネル
     に EOF があらわれます。これは、リモート側が何かを送り返す前に EOF
     を受けとることを期待している場合、便利です。

 -- Function: socket-getsockname socket
     SOCKETのローカル側アドレスを表す`<sockaddr>'インスタンスを返します。

 -- Function: socket-getpeername socket
     SOCKETの通信相手のアドレスを表す`<sockaddr>'インスタンスを返します。

 -- Function: socket-send socket msg &optional flags
 -- Function: socket-sendto socket msg to-address &optional flags.
     それぞれ、`send(2)' および `sendto(2)' へのインタフェース。 MSG
     の内容(文字列)を SOCKET を通じて送出します。 `socket-send'
     を使うときには、SOCKET は既に接続されて
     いなければなりません。他方、`socket-setdto' は未接続の
     ソケットに対して使用でき、送出先アドレスは `<sockaddr>'
     のインスタンス TO-ADDRESS で指定します。

     オプション引数 FLAGS は整数定数 `MSG_*' のビット毎のORで
     指定できます。詳しくはシステムの man ページ `send(2)' および
     `sendto(2)' を見て下さい。

 -- Function: socket-recv socket bytes &optional flags
 -- Function: socket-recvfrom socket bytes &optional flags
     それぞれ、`recv(2)' および `recvfrom(2)' へのインタフェース。
     ソケット SOCKET から BYTES バイトまでのメッセージを受信します。
     `socket-recv' は接続済みのソケットを使わなければなりませんが、
     他方、`socket-recvfrom' は未接続のソケットを使えます。

     `socket-recv'
     は(不完全なものである可能性もある)文字列として受信した
     メッセージを返します。`socket-recvfrom'
     は値を2つ返し、一つは受信した
     メッセージ、もうひとつは送信者のソケットアドレスです。

     オプション引数 FLAGS は整数定数 `MSG_*' のビット毎のORで
     指定できます。詳しくはシステムの man ページ `recv(2)' および
     `recvfrom(2)' を見て下さい。

 -- Variable: MSG_CTRUNC
 -- Variable: MSG_DONTROUTE
 -- Variable: MSG_EOR
 -- Variable: MSG_OOB
 -- Variable: MSG_PEEK
 -- Variable: MSG_TRUNC
 -- Variable: MSG_WAITALL
     `socket-send'、`socket-sendto'、`socket-recv' および
     `socket-recvfrom' の FLAG として使う定義済み整数定数。
     これらの定数のいくつかは、基盤のＯＳが提供していなければ未定義に
     なっています。

   以下に解説する getsockopt/setsockopt インタフェースを使えば、
ソケットやプロトコルをさらに制御することができます。

 -- Function: socket-setsockopt socket level option value
 -- Function: socket-getsockopt socket level option rsize
     これらは、setsockopt() および getsockopt() を呼ぶための
     インタフェースです。このインタフェースが少々ぎこちないのは、
     低レベルの呼び出しすべてにアクセスできるようにしているためです。

     SOCKET および OPTION は、処理する対象の
     プロトコルスタックのレベルおよびオプションを指定する
     正確な整数です。以下にリストアップしたシステム定数に束縛された
     変数があります。

     ソケットオプションを設定するには、VALUE に正確な整数を渡す方法と
     文字列を渡す方法があります。それが、整数なら、その値は、C の `int'
     として setsockopt (2) に渡されます。文字列なら、バイト列が
     そのまま渡されます。どの型の値が要求されるかは、オプションに依存します。
     Gauche 側では渡された値が setsockopt (2)
     で期待された型であるかどうかは
     知ることができません。正しい値が渡されるかどうかはプログラマの責任です。

     ソケットオプションを知るには、結果として期待する最大の長さを RSIZE
     を使って教える必要があります。Gauche
     側は返されるそれぞれのオプションの 合計を知らないからです。
     `socket-getsockopt' はオプションの値をバイト列として返します。
     オプションの値が整数だと、わかっているなら RSIZE に0を渡すこと
     ができます。その場合 `socket-getsockopt'
     は正確な整数として値を返します。

     関数名に関する註: これらの関数の名前を socket-{set|get}opt あるいは
     socket-{set|get}-option にしようかとも思いましたが、結局、命名の
     一貫性をとることにしました。それで、"sock" が重複しています。


   以下のような定義済みの変数が用意されています。
すべてのプラットフォームで利用できるわけではないものも含まれている
ことに注意してください。 これらの値の正確な使用は、お使いのシステムの
man ページ `socket(7)'、 `tcp(7)' あるいは `ip(7)' を参照してください。

   "level" 引数

 -- Variable: SOL_SOCKET
 -- Variable: SOL_TCP
 -- Variable: SOL_IP
     これらの変数は、それぞれ、`SOL_SOCKET'、`SOL_TCP' および `SOL_IP'
     に束縛されています。

   "option" 引数

 -- Variable: SO_KEEPALIVE
     整数が期待されています。0でなければ、コネクション指向ソケットに
     キープアライブ(keep-alive)メッセージを送ることができます。

 -- Variable: SO_OOBINLINE
     整数が期待されています。0でなければ、帯域外データは直接
     受信データストリームに乗ります。さもなければ、帯域外データは、受信中に
     MSG_OOBフラグが設定されてたときにのみ渡されます。

 -- Variable: SO_REUSEADDR
     整数が期待されています。0ではない場合、`socket-bind'は、
     ローカル・アドレスが、アクティブソケットにリッスンされていない
     場合にかぎり、そのアドレスを再利用することを許可されます。


 -- Variable: SO_TYPE
     ソケットの型(`sock_stream'など)を整数として取得します。
     `socket-getsockopt'でのみ使用可能です。

 -- Variable: SO_BROADCAST
     整数が期待されています。0でなければ、データグラムソケットは
     ブロードキャストパケットを送受信することを許されます。

 -- Variable: SO_PRIORITY
     整数が期待されています。このソケットで送信されるすべてのパケットに
     ついてプロトコル定義の優先順位を指定します。

 -- Variable: SO_ERROR
     保留状態のソケットエラー(整数値)を取得し、それをクリアします。
     `socket-getsockopt'でのみ使用可能です。


File: gauche-refj.info,  Node: Netdbインタフェース,  Prev: 低レベルソケットインタフェース,  Up: ネットワーキング

9.12.4 Netdbインタフェース
--------------------------

 -- Builtin Class: <sys-hostent>
     このクラスはネットワークホストのオブジェクト用で、 C の `struct
     hostent' に対応しています。以下のスロットは読み込み専用です。

      -- Instance Variable of <sys-hostent>: name
          ホストの正式名(文字列)

      -- Instance Variable of <sys-hostent>: aliases
          ホストの別名リスト(文字列のリスト)

      -- Instance Variable of <sys-hostent>: addresses
          アドレスのリスト(文字列のリスト)。現時点では IPv4
          のアドレスのみサポート
          しています。それぞれのアドレスは、ドットつき十進記法で表記されています。

 -- Function: sys-gethostbyname name
     NAMEという名まえのホストを探し、見つかれば、`<sys-hostent>'
     オブジェクトを返します。見つからなければ、`#f' を返します。
          (let ((host (sys-gethostbyname "www.w3c.org")))
            (list (slot-ref host 'name)
                  (slot-ref host 'aliases)
                  (slot-ref host 'addresses)))
            => ("www.w3.org" ("www.w3c.org") ("18.29.1.34" "18.29.1.35"))

 -- Function: sys-gethostbyaddr addr proto
     PROTOというプロトコルの、ADDRというアドレスを持つホストを
     探します。ADDRはアドレスの自然な文字列表現で、IPv4 については、
     ドットつき十進記法です。PROTOはプロトコル番号で、現時点では
     `AF_INET'のみサポートされています。ホストが見つかれば、
     `<sys-hostent>'オブジェクトを返します。 見つからなければ、`#f'
     を返します。
          (let ((host (sys-gethostbyaddr "127.0.0.1" AF_INET)))
            (list (slot-ref host 'name)
                  (slot-ref host 'aliases)
                  (slot-ref host 'addresses))
            => ("localhost" ("localhost.localdomain") ("127.0.0.1"))

 -- Builtin Class: <sys-servent>
     ネットワークサービスデータベースのエントリです。 C の `struct
     servent'に対応しています。 以下のスロットは読み込み専用です。

      -- Instance Variable of <sys-servent>: name
          サービスの正式名(文字列)

      -- Instance Variable of <sys-servent>: aliases
          サービスの別名リスト(文字列のリスト)

      -- Instance Variable of <sys-servent>: port
          サービスに割り当てられたポート番号(正確な整数)

      -- Instance Variable of <sys-servent>: proto
          このサービス用のプロトコル名(文字列)

 -- Function: sys-getservbyname name proto
     ネットワークサービスデータベースをサービス名 NAME および
     プロトコル PROTO で検索します。NAME および PROTO
     は文字列でなければなりません。サービスが見つかれば、`<sys-servent>'
     のインスタンスが返します。見つからなければ、`#f' を返します。
          (let ((serv (sys-getservbyname "http" "tcp")))
            (list (slot-ref serv 'name)
                  (slot-ref serv 'aliases)
                  (slot-ref serv 'port)
                  (slot-ref serv 'proto)))
            => ("http" () 80 "tcp")

 -- Function: sys-getservbyport port proto
     ネットワークサービスデータベースをサービス名 PORT および
     プロトコル PROTO で検索します。PORT は正確な整数でなければ
     なりません。また、PROTO は文字列でなければなりません。
     サービスが見つかれば、`<sys-servent>'
     のインスタンスが返します。見つからなければ、`#f' を返します。
          (let ((serv (sys-getservbyport 6000 "tcp")))
            (list (slot-ref serv 'name)
                  (slot-ref serv 'aliases)
                  (slot-ref serv 'port)
                  (slot-ref serv 'proto)))
            => ("x-server" () 6000 "tcp")

 -- Builtin Class: <sys-protoent>
     プロトコルデータベースのエントリです。C の `struct protoent'に
     対応しています。以下のスロットは読み込み専用です。

      -- Instance Variable of <sys-servent>: name
          プロトコルの正式名(文字列)

      -- Instance Variable of <sys-servent>: aliases
          プロトコルの別名のリスト(文字列のリスト)

      -- Instance Variable of <sys-servent>: proto
          プロトコル番号(正確な整数)

 -- Function: sys-getprotobyname name
     名前 NAME でネットワークプロトコルデータベースを検索します。 名前
     NAME は文字列でなければなりません。
     プロトコルが見つかれば、`<sys-protoent>'
     のインスタンスを返します。見つからなければ、`#f' を返します。
          (let ((proto (sys-getprotobyname "icmp")))
            (list (slot-ref proto 'name)
                  (slot-ref proto 'aliases)
                  (slot-ref proto 'proto)))
            => ("icmp" ("ICMP") 1)

 -- Function: sys-getprotobynumber number
     プロトコル番号 NUMBER でネットワークプロトコルデータベースを検索
     する。プロトコル番号 NUMBER は正確な整数でなければなりません。
     プロトコルが見つかれば、`<sys-protoent>'
     のインスタンスを返します。見つからなければ、`#f' を返します。
          (let ((proto (sys-getprotobynumber 17)))
            (list (slot-ref proto 'name)
                  (slot-ref proto 'aliases)
                  (slot-ref proto 'proto)))
            => ("udp" ("UDP") 17)

 -- Builtin Class: <sys-addrinfo>
     アドレス情報を保持する新しいインタフェースです。C の `struct
     addrinfo' に対応しています。これは gauche が -enable-ipv6
     オプションで設定され、
     ビルドされた場合にのみ利用可能です。以下のスロットが提供されます。

      -- Instance Variable of <sys-addrinfo>: flags

      -- Instance Variable of <sys-addrinfo>: family

      -- Instance Variable of <sys-addrinfo>: socktype

      -- Instance Variable of <sys-addrinfo>: protocol

      -- Instance Variable of <sys-addrinfo>: addrlen

      -- Instance Variable of <sys-addrinfo>: addr

 -- Function: sys-getaddrinfo nodename servname hints
     与えられた NODENAME、SERVNAME および HINTS から `<sys-addrinfo>'
     のインスタンスを返します。 これは gauche が -enable-ipv6
     オプションで設定され、 ビルドされた場合にのみ利用可能です。


File: gauche-refj.info,  Node: パラメータ,  Next: コマンドライン引数の解析,  Prev: ネットワーキング,  Up: ライブラリモジュール - Gauche拡張モジュール

9.13 `gauche.parameter' - パラメータ
====================================

 -- Module: gauche.parameter
     「パラメータ」は基本的にゼロもしくは一個の引数を取る状態を持つ手続きとみなせます。
     引数が与えられなかった場合、それは内部に保持した値を返します。
     一つの引数が与えられた場合、その値が新たなパラメータ内部の値となり、
     変更前の値が返されます。 パラメータは状態を保持する手段として、
     単なるグローバル変数に比べていくつかの利点を持っています。

     パラメータの値はスレッド毎に保持されるので、
     パラメータをスレッドローカルな格納領域として利用することができます。
     新たに作られたスレッドは、その作成元のスレッドのパラメータのコピーを
     受け取ります。

     パラメータに値がセットされるときに、指定の「フィルタ手続き」を呼んで
     値を検査することができます。これにより、パラメータの値が常に正当なもので
     あることを保証できます。

     マクロ`parameterize'により、特定のダイナミックスコープの中だけ
     パラメータの値を変えることができます。これは、実質的にダイナミックスコープを
     持つ変数を置き換えることができます。

     また、パラメータの値が変更されたときに呼ばれるコールバック手続きを
     登録しておくこともできます。これによって実質的に、いわゆる
     「traceされた変数」を置き換えることができます。

     パラメータオブジェクトの基本的な機能はSRFI-39で定義されています。
     この機能はまた、ChezScheme、Chicken、MzSchemeなどいくつかのScheme処理系に
     見られます。GaucheのパラメータはSRFI-39の上位互換になっています。

 -- Class: <parameter>
     パラメータのクラスです。`object-apply'メソッドが定義されているので、
     パラメータオブジェクトは普通の手続きと同様に使うことが出来ます。

 -- Function: make-parameter value &optional filter
     [SRFI-39] 初期値がVALUEであるパラメータを作成します。
     もし省略可能な引数FILTERが与えられた場合、
     それは一つの引数を取る手続きでなければなりません。
     パラメータの値が変更されようとした時、FILTERは与えられた値を
     引数として呼ばれ、FILTERが返した値がパラメータの新しい値と
     なります。FILTERはエラーを報告したりパラメータの値を変えずに置くことも
     可能です。

 -- Macro: parameterize ((param value) ...) body ...
     [SRFI-39] BODY ...を評価します。 但し、BODY ...
     の実行中のみ、パラメータPARAMの値を
     VALUEに変更します。最後BODYの返した値を返します。

   例：
     (define a (make-parameter 1))
     (a) => 1
     (a 2) => 1
     (a) => 2
     (parameterize ((a 3))
       (a)) => 3
     (a) => 2

 -- Method: parameter-observer-add! (p <parameter>) proc &optional when
          where
     PROCをパラメータPの"オブザーバ"手続きに追加します。
     オブザーバ手続きは、(1)パラメータに新しい値がセットされる直前、
     あるいは(2)パラメータに新しい値がセットされた直後、に呼ばれます。
     (1)の場合、コールバックが呼ばれる前にフィルタ手続きがすでに適用
     されています。どちらの場合も、オブザーバ手続きは、古い値と新しい
     値の2引数を伴って呼ばれます。オブザーバ手続きの戻り値は無視されます。

     オプショナル引数WHENは、シンボル`before'か`after'の
     いずれかでなければならず、値が変更された前と後のどちらでPROCが
     呼ばれるかを指定します。省略されると、`after'を指定したものと
     されます。

     オプショナル引数WHEREは、シンボル`append'か`prepend'の
     いずれかでなければならず、PROCが既存のオブザーバ手続きのリストの
     前に追加されるか後に追加されるかを指定します。省略されると、`append'
     を指定したものとされます。

     _注意_: パラメータの値自身がスレッドローカルであっても、
     オブザーバのリストは全てのスレッドで共有されます。

 -- Method: parameter-observer-delete! (p <parameter>) proc &optional
          when
     パラメータPのオブザーバ手続きのリストからPROCを削除します。
     PROCがリストになければ、何も起こりません。
     WHEN引数にシンボル`before'か`after'を与えて、
     PROCをどちらのリストから削除するかを指定することができます。
     WHEN引数が省略されると、PROCは両方のリストから削除されます。

 -- Method: parameter-pre-observers (p <parameter>)
 -- Method: parameter-post-observers (p <parameter>)
     "before"か"after"オブザーバをそれぞれキープするフックオブジェクト
     (*Note フック::参照)を返します。

     _注意_: パラメータの値自身がスレッドローカルであっても、
     オブザーバのリストは全てのスレッドで共有されます。


File: gauche-refj.info,  Node: コマンドライン引数の解析,  Next: 高レベルプロセスインタフェース,  Prev: パラメータ,  Up: ライブラリモジュール - Gauche拡張モジュール

9.14 `gauche.parseopt' - コマンドライン引数の解析
=================================================

 -- Module: gauche.parseopt
     このモジュールでは、コマンドラインオプションをパースするための便利な方法を定義
     しています。インタフェースは Perl
     にヒントを受けたもので、複数のオプション引数を
     伴う長い形式のオプションを便利に扱うことができます。

     実際、Gauche
     でコマンドラインオプションをパースするにはいくつかの選択肢が
     あります。SRFI-37 (*Note args-fold プログラム引数処理::参照)では、
     POSIX/GNU
     互換の引数構文をパースするための関数的なインタフェースを提供しています。
     SLIB は、`getopt' 互換のユーティリティを持っています。
     要求される機能はアプリケーションごとに異なるので、
     あなたの要求にフィットするものを選んで下さい。

 -- Macro: parse-options args (option-clause ...)
     ARGS は、コマンドライン引数のリストを含む式です。
     このマクロは、コマンドラインオプション(``-''
     で始まる引数)をスキャンし、 OPTION-CLAUSE
     の指定に従って処理し、残りの引数を返します。

     C における典型的な `getopt' や `getopt_long' の実装とは異なり、
     `parse-options' は与えられたコマンドライン引数の順番を変えません。
     オプションでない引数(ハイフンで始まらない引数)に遭遇した時点でパースを
     中止します。

     パーサは、ハイフン2つのみの引数 ``--''
     に遭遇すると、引数パーシングを 中止して``--''
     の後の引数のリストを返します。

     それぞれの OPTION-CLAUSE は、OPTION-SPEC とそのアクションのペアで
     構成されます。

     OPTION-SPEC
     は、オプションの名前とそのオプションがどのように引数を取るか
     を指定する文字列です。オプションの名前には、アルファベット文字、数字、
     アンダースコア、プラス記号、ハイフンが許されますが、ハイフンは最初の文字としては
     使えません。すなわち、有効なオプションの名前は、`#/[\w+][-\w+]*/'
     という 正規表現にマッチするものです。

     オプションが引数を取る場合、名前の後ろに等号文字と引数の型を表現する文字を
     付けることで指定できます。オプションは一つ以上の引数を取ることができます。
     以下の文字がオプションの引数の型を表現するものとして認識されます。

    `s'
          文字列。

    `n'
          数値。

    `f'
          実数 (flonum)。

    `i'
          正確な整数。

    `e'
          S式。

    `y'
          シンボル (引数は`string->symbol'により変換される)。

     OPTION-SPECの例を見てみましょう：

    `"NAME"'
          引数を取らないオプションの NAME を指定します。

    `"NAME=s"'
          オプション NAME
          は引数を一つ取り、それは文字列として渡されます。

    `"NAME=i"'
          オプション NAME
          は引数を一つ取り、それは正確整数として渡されます。

    `"NAME=ss"'
          オプション NAME は引数を二つ取り、両方とも文字列です。

    `"NAME=iii"'
          オプション NAME は3つの整数の引数を取ります。

    `"NAME=sf"'
          オプション NAME は2つの引数を取ります。一つ目は文字列で、
          二つ目は数値です。

     オプションにいくつかの別名がある場合は、"|"
     でつなげて書いておくことができます。
     例えば`"h|help"'というOPTION-SPECは "h"にも"help"にもマッチします。

     コマンドラインでは、オプションは一つか二つのハイフンに続いて与えられます。
     オプションの引数は、オプションそのものと等号記号でつながれていても構いません。
     例えば、以下の全てのコマンドライン引数は、オプションの仕様、`"prefix=s"'
     に マッチします。
          -prefix /home/shiro
          -prefix=/home/shiro
          --prefix /home/shiro
          --prefix=/home/shiro

     与えられたコマンドラインオプションが OPTION-SPEC
     の一つにマッチすると、
     関連付けられたアクションが評価されます。アクションは以下のフォームの一つです。

    `BIND-SPEC BODY ...'
          BIND-SPEC
          は、ラムダリストのような変数の正しいリストかドット対リストです。
          オプションの引数は BIND-SPEC に束縛され、BODY ...
          が評価されます。

    `=> PROC'
          コマンドラインオプションが OPTION-SPEC にマッチすると、 PROC
          がオプションの引数のリストとともに呼び出されます。

     Examples:
          (parse-options '("-file" "foo")
            (("file=s" (file)
               (format #t "file is ~s\n" file))))
           => ;"`file is "foo"'" is printed

          (parse-options '("-scale" "1.5" "2.2")
            (("scale=ff" (xscale yscale)
               (format #t "scale is ~sx~s\n" xscale yscale))))
           => ;"`scale is 1.5x2.2'" is printed

          (parse-options '("-scale" "1.5" "2.2")
            (("scale=ff" scales
               (format #t "scale is ~s\n" scales))))
           => ;"`scale is (1.5 2.2)'" is printed

          (define (scales x y)
            (format #t "scale is ~sx~s\n" x y))

          (parse-options '("-scale" "1.5" "2.2")
            (("scale=ff" => scales)))
           => ;"`scale is 1.5x2.2'" is printed

     シンボル `else' が OPTION-SPEC の位置にある場合、その節は、
     与えられたコマンドラインオプションにマッチする他のオプション節が
     ない場合に選択されます。その節には3つの"引数"が関連付けられます。
     それらは、マッチしなかったオプション、引数の残り、オプションパーサを
     表す手続きです。

          (parse-options args
            (("file=s" => process-file)
             (else (option . _)  (error "unrecognized option:" option))))

     他の節とは異なり、else 節はそれ以上繰り返しをせずに
     `parse-options' の呼び出し元へ戻ります。
     繰り返しを続けるためには、else 節の三つ目の引数を残りの引数を
     伴って呼び出さなければなりません。これは、あなた独自のサブパーサを
     実装するのに使うことができるでしょう。以下の例では、認識されない
     オプションを単にスキップし、警告を表示し、パーシングを続けます。

          (parse-options args
            (("file=s" => process-file)
             (else (option args continue)
               (format #t "warning: ignoring unrecognized option: ~a" option)
               (continue args))))


 -- Macro: let-args args (bind-spec ... [. rest]) body ...
     このマクロは`parse-options'のラッパーで、
     より通常のScheme構文に近い形式を提供します。
     例えば、簡単なスクリプトが次のように書けるでしょう。

          (define (main args)
            (let-args (cdr args)
                ((quiet   "q|quiet" #t)
                 (verbose "v|verbose" #f)
                 (outfile "o|outfile=s")
                 (help    "h|help" => (cut show-help (car args)))
                )
              ....))

          (define (show-help progname)
            ...)

     BIND-SPECは次のいずれかの形式でなければなりません。

          1. (VAR OPTION-SPEC)
          2. (VAR OPTION-SPEC DEFAULT)
          3. (VAR OPTION-SPEC => CALLBACK)
          4. (VAR OPTION-SPEC DEFAULT => CALLBACK)

          5. (else FORMALS FORM ...)

     コマンドライン引数のリストがARGSに渡されると、それが
     OPTION-SPECに基づいてパーズされます。該当するオプションが見付かれば、
     変数VARが次に述べる値に束縛されます：
          (a) BIND-SPECの形式が上の1. または2. の場合：
            (a1) OPTION-SPECが引数を要求しない場合は、`#t'。
            (a2) OPTION-SPECがひとつの引数を要求する場合は、その引数の値。
            (a3) OPTION-SPECがそれ以上の引数を要求する場合は、引数の値のリスト。
          (b) BIND-SPECの形式が上の3. または4. の場合、CALLBACKを
            引数の値を伴って呼び出し、その戻り値。

     特別な場合として、VARを`#f'とすることもできます。
     その場合、値は無視されます。
     CALLBACKでの副作用だけに関心がある場合に使えるでしょう。

     対応するオプションがARGSに与えられなかった場合、
     VARはDEFAULTが与えられていればその値に、
     そうでなければ`#f'に束縛されます。

     最後のBIND-SPECは5.の形式であっても良く、
     その場合は`parse-options'の`else'節と同様に処理されます。

     束縛リストは、最後の`car'にシンボルを持つ不完全なリストであっても良く、
     その場合はコマンドライン引数の残りのリストがその変数にと束縛されます。

     DEFAULT、CALLBACK、`else'節のフォーム等は
     VARの束縛の外側のスコープで評価されることに注意して下さい。

     全ての束縛が終了した後、BODY ... が評価されます。
     BODYは内部defineで始まっていても構いません。

 -- Macro: make-option-parser (option-clause ...)
     これは低レベルのインタフェースです。OPTION-CLAUSE は、
     `parse-options'
     と同じです。このマクロは、コマンドラインオプションを
     後でパースするために使うことができる手続きを返します。

     返される手続きは、一つの必須の引数と一つのオプション引数を取ります。
     必須の引数は、与えられたコマンドライン引数としての文字列のリストです。
     オプションの引数は、三つ以上の引数を取る手続きで、それが与えられると
     手続きはそれが `else'
     オプション節のボディであるかのように使われます。


File: gauche-refj.info,  Node: 高レベルプロセスインタフェース,  Next: 正規表現ユーティリティ,  Prev: コマンドライン引数の解析,  Up: ライブラリモジュール - Gauche拡張モジュール

9.15 `gauche.process' - 高レベルプロセスインタフェース
======================================================

 -- Module: gauche.process
     このモジュールは、`sys-fork' や `sys-exec' などの低レベルな
     システムコールの上に実装された、Unix プロセス制御の高レベル API
     を提供します。 インターフェースは、STk
     のプロセスライブラリとほとんどの点で互換性があります。
     また、このモジュールは、サブプロセスに情報を送ったり、サブプロセスから
     情報を受け取ったりするのに便利な「プロセスポート」を提供します。

* Menu:

* Process object::
* Process ports::


File: gauche-refj.info,  Node: Process object,  Next: Process ports,  Prev: 高レベルプロセスインタフェース,  Up: 高レベルプロセスインタフェース

9.15.1 Process object
---------------------

 -- Class: <process>
     子プロセスの状態を保持するためのオブジェクト。以下で説明される
     `run-process' 手続きにより、プロセスを作ることができます。
     次章で説明するプロセスポートもプロセスオブジェクトを用いています。

     `<process>'クラスは、`run-process'や`open-input-process'
     といった高レベルAPIで作られた子プロセスの状態を管理しています。
     それらの子プロセスの終了ステータスをとるには、
     `process-wait'や`process-wait-any'といった
     高レベルAPIを利用してください。これらの手続きはシステムコール以外の情報管理も
     行います。`sys-wait'や`sys-waitpid'といった低レベルAPIで
     直接子プロセスの終了ステータスを取ると、`<process>'クラスの
     内部状態に矛盾が生じます。


 -- Function: run-process command arg ...
     サブプロセスで、ARG を引数として COMMAND を実行し、 `<process>'
     オブジェクトを返します。COMMAND は、
     コマンドサーチパスから探されます。

     コマンドライン引数 ARG は、下に示す、
     子プロセスを特別に扱うためのキーワード引数を含むことができます。

     それらのキーワード引数を除いては、COMMANDとARGは
     `x->string'を用いて文字列に変換されます。
    `:input FILE'
    `:output FILE'
    `:error FILE'
          これらの引数は、サブプロセスの標準入出力を制御します。 FILE
          は文字列かキーワード `:pipe' です。
          文字列の場合は、プロセスの標準入力、標準出力、標準エラーはそのファイルに
          なります。`:pipe'
          の場合は、プロセスの対応する標準入出力はパイプに
          結び付けられ、そのパイプのもう一方はプロセスの呼び出し側で利用できます。

    `:wait FLAG'
          FLAG が真の場合、`run-process'
          はサブプロセスが終了するまで待ちます。
          そうでなければ、サブプロセスは非同期に実行され、`run-process'
          は すぐに返ります。これがデフォルトの振る舞いになります。
          サブプロセスが非同期に実行している場合、その終了ステータスを回収するために
          適切なタイミングで `process-wait'
          を呼ぶことは、呼び出し側の責任であることに 注意してください。

    `:fork FLAG'
          FLAG が真の場合、`run-process' はサブプロセスを実行するために
          フォークします。これはデフォルトの振る舞いです。FLAG
          が偽の場合、 `run-process' は直接 `sys-exec'
          を呼ぶので、それは返りません。

 -- Function: process? obj
     == `(is-a? OBJ <process>)'

 -- Method: process-pid (process <process>)
     サブプロセス PROCESS のプロセスIDを返します。

 -- Method: process-command (process <process>)
     サブプロセス PROCESS 内で起動されたコマンドを返します。

 -- Method: process-input (process <process>)
 -- Method: process-output (process <process>)
 -- Method: process-error (process <process>)
     プロセスの標準入力、標準出力、標準エラーがパイプに接続されている場合は、
     パイプのもう一方の終端を返します。例えば、`process-input' は、
     PROCESS の標準入力へデータを送ることができる出力ポートを返します。
     `process-output' は PROCESS の標準出力からデータを読み込むことの
     できる入力ポートを返します。そして、`process-error' は、`process'
     の標準エラーからデータを読み込むことのできる入力ポートを返します。
     対応する入出力がパイプに接続されていない場合、手続きは `#f'
     を返します。

          (let* ((process (run-process "date" :output :pipe))
                 (line (read-line (process-output process))))
            (process-wait process)
            line)
           => "Fri Jun 22 22:22:22 HST 2001"

 -- Function: process-alive? process
     PROCESS が生きている場合は真を返します。`process-wait' によって
     明示的にチェックされない限り、Gauche
     はサブプロセスのステータスを知ることが
     できないことに注意してください。

 -- Function: process-list
     アクティブなプロセスのリストを返します。プロセスは、その終了ステータスが
     `process-wait' によって明示的に回収されない場合は、アクティブなまま
     残ります。
     ひとたび終了ステータスが回収され、プロセスの状態がインアクティブに
     変更されると、そのプロセスは`process-list'が返すリストからは除かれます。

 -- Function: process-wait process &optional nohang
     サブプロセス PROCESS の終了ステータスを取得し、PROCESS
     のstatusスロットに値を格納します。statusスロットの値は
     `process-exit-status'で得ることができます。

     デフォルトでは、この手続きはPROCESS
     が終了するまで実行を一時停止します。
     しかし、NOHANGに真の値が与えられた場合は、PROCESSが終了して
     いない場合にも直ちに返ります。

     この呼び出しによってPROCESSの終了ステータスが実際に取得された場合は
     `#t'を、そうでなければ`#f'を返します。

 -- Function: process-wait-any &optional nohang
     `run-process'で作られたサブプロセスのどれかの終了ステータスを取得します。
     終了ステータスが取得できたプロセスのプロセスオブジェクトを返します。

     真の値がNOHANGに与えられた場合は、どの子プロセスも終了していない場合は
     直ちに`#f'を返します。そうでなければ、この手続きはいずれかの子プロセスが
     終了するまで待ちます。

     子プロセスが存在しない場合は、この手続きは直ちに`#f'を返します。

 -- Function: process-exit-status process
     `process-wait'によって取得されたPROCESSの終了ステータスを
     返します。PROCESSに対して`process-wait'を呼ぶ前にこの手続きを
     呼んだ場合の結果は未定義です。

 -- Function: process-send-signal process signal
     サブプロセス PROCESS にシグナル SIGNAL を送ります。 SIGNAL
     は正確整数のシグナルナンバーでなければなりません。
     シグナルの定義済み変数については、*Note
     シグナル::を参照して下さい。

 -- Function: process-kill process
 -- Function: process-stop process
 -- Function: process-continue process
     それぞれ、PROCESS に、SIGKILL、SIGSTOP、SIGCONT を送ります。


File: gauche-refj.info,  Node: Process ports,  Prev: Process object,  Up: 高レベルプロセスインタフェース

9.15.2 Process ports
--------------------

 -- Function: open-input-process-port command &keyword output error
          encoding conversion-buffer-size
     COMMAND を子プロセスで非同期に実行します。
     走らせた子プロセスの標準出力につながれた入力ポートと、
     プロセスオブジェクトの二つの値を返します。

     COMMANDは文字列かリストです。
     文字列の場合、それは`/bin/sh'に渡されます。
     環境変数の置換やグロブパターン、リダイレクトなどのシェルの機能が
     文字列中で使えます。

     COMMANDがリストの場合は、各要素が`x->string'で文字列に
     変換された後に、`sys-exec'を使って直接コマンドを起動します
     (リストの`car'がコマンドのパス名と`argv[0]'の両方に使われます)。
     シェルの介入を避けたい場合はこの形式を使うと良いでしょう。

     デフォルトでは、子プロセスの標準出力は`/dev/null'にリダイレクトされ、
     標準エラー出力は呼び出したプロセスと共有されます。
     OUTPUTとERRORキーワード引数にパス名を与えることで、
     これらの出力をリダイレクトすることができます。

     また、プロセスの出力の文字エンコーディングを指定するために
     ENCODINGキーワード引数を与えることもできます。
     それがGaucheの内部エンコーディングと異なっていた場合、
     `open-input-process-port'は文字コード変換ポートを挿入します。
     ENCODINGが与えられた場合、CONVERSION-BUFFER-SIZEキーワード引数で
     変換バッファの大きさを指定することも可能です。文字コード変換の詳細については
     *Note 文字コード変換::を参照して下さい。
          (receive (port process) (open-input-process-port "ls -l Makefile")
            (begin0 (read-line port)
                    (process-wait process)))
           => "-rw-r--r--   1 shiro    users        1013 Jun 22 21:09 Makefile"

          (receive (port process) (open-input-process-port '(ls -l "Makefile"))
            (begin0 (read-line port)
                    (process-wait process)))
           => "-rw-r--r--   1 shiro    users        1013 Jun 22 21:09 Makefile"

          (open-input-process-port "command 2>&1")
           => ;the port reads both stdout and stderr

          (open-input-process-port "command 2>&1 1>/dev/null")
           => ;the port reads stderr
     サブプロセスの終了ステータスは自動的に回収されません。
     `process-wait' を呼ぶことは呼び出し側の責任であり、これを怠ると
     サブプロセスはゾンビプロセスになります。それが面倒であれば、以下の
     手続きを使うことができます。

 -- Function: call-with-input-process command proc &keyword output
          error encoding conversion-buffer-size
     子プロセスでCOMMAND を実行し、その標準出力と入力ポートを
     パイプで繋ぎ、そのポートを引数として PROC を呼び出します。 PROC
     が返るとその終了ステータスを回収し、PROC が返した
     結果を返します。PROC がエラーを通知しても、クリーンアップは
     行われます。

     COMMANDおよびキーワード引数の意味は`open-input-process-port'と
     同じです。
          (call-with-input-process "ls -l *"
            (lambda (p) (read-line p)))

 -- Function: with-input-from-process command thunk &keyword output
          error encoding conversion-buffer-size
     子プロセスで COMMAND を実行し、コマンドの標準出力に
     接続された現在の入力ポートとともに THUNK を呼び出します。
     THUNKが終了するかエラーを投げた後に、コマンドの終了ステータスが
     回収されます。

     COMMANDおよびキーワード引数の意味は`open-input-process-port'と
     同じです。
          (with-input-from-process "ls -l *" read-line)

 -- Function: open-output-process-port command &keyword input error
          encoding conversion-buffer-size
     子プロセスで `command' を非同期に実行します。
     子プロセスの標準入力に接続された出力ポートと、
     プロセスオブジェクトの二つの値を返します。

     デフォルトでは、子プロセスの標準入力は`/dev/null'にリダイレクトされ、
     標準エラー出力は呼び出したプロセスと共有されます。
     INPUTとERRORキーワード引数にパス名を与えることで、
     これらの出力をリダイレクトすることができます。

     COMMAND引数、およびENCODINGとCONVERSION-BUFFER-SIZEの
     意味は、`open-input-process-port'と同じです。

     サブプロセスの終了ステータスは自動的には回収されません。
     適切なタイミングで、サブプロセスに対して `process-wait' を呼ぶ
     必要があります。

 -- Function: call-with-output-process command proc &keyword input
          error encoding conversion-buffer-size
     `command' を子プロセスで実行し、コマンドの標準入力に
     接続された出力ポートとともに PROC を呼び出します。
     コマンドの終了ステータスは、PROC が返るかエラーを通知した
     後に回収されます。

     キーワード引数の意味はOPEN-INPUT-PROCESS-PORTと同じです。
          (call-with-output-process "/usr/sbin/sendmail"
            (lambda (out) (display mail-body out)))

 -- Function: with-output-to-process command thunk &keyword input error
          encoding conversion-buffer-size
     コマンドの標準入力に接続された出力ポートが、THUNK の実行中は
     現在の出力ポートにセットされることを除いて、`call-with-output-process'
     と同じです。

 -- Function: call-with-process-io command proc &keyword error encoding
          conversion-buffer-size
     COMMAND をサブプロセスで実行し、PROC を2つの引数と
     ともに呼び出します。最初の引数は入力ポートで、コマンドの標準出力に
     接続されたものです。2番目の引数は出力ポートでコマンドの標準入力に
     接続されたものです。コマンドからのエラー出力は、ERRORキーワード
     引数でパス名が指定されない限り、呼び出したプロセスのエラー出力が共有されます。

     コマンドの終了ステータスは、PROCが戻るかエラーを投げた場合に
     回収されます。

 -- Function: process-output->string command
 -- Function: process-output->string-list command
     COMMAND を実行し、その(標準出力への)出力を回収して返します。
     `process-output->string' は COMMAND からの全ての出力を連結し
     1つの文字列とします。その際、空白文字からなるシーケンスは1つの空白に
     置換されます。このアクションは、シェルスクリプトにおける「コマンド置換」
     に似たものです。 `process-output->string-list' は COMMAND
     からの出力を行ごとに
     回収し、それらをリストにしたものを返します。改行文字は削除されます。

     内部的には、COMMAND は `call-with-input-process' により
     実行されます。
          (process-output->string "uname -smp")
            => "Linux i686 unknown"

          (process-output->string "ls")
            => "a.out foo.c foo.c~ foo.o"

          (process-output->string-list "ls")
            => ("a.out" "foo.c" "foo.c~" "foo.o")



File: gauche-refj.info,  Node: 正規表現ユーティリティ,  Next: モジュールの再ロード,  Prev: 高レベルプロセスインタフェース,  Up: ライブラリモジュール - Gauche拡張モジュール

9.16 `gauche.regexp' - 正規表現ユーティリティ
=============================================

 -- Module: gauche.regexp
     このモジュールは正規表現のマッチに関連する便利なマクロとユーティリティ関数を
     定義します。組み込みの正規表現機能については*Note 正規表現::を
     参照して下さい。また、リリース0.4.11以降、このモジュールは`gosh'を
     使う場合はオートロードされるようになっているので、 `(use
     gauche.regexp)'とする必要はありません。

     いくつかのマクロのインタフェースはscshの
     `if-match'、`let-match'、`match-cond'
     を参考にしました。但し名前に関してはscshのものは正規表現以外の
     マッチライブラリと混乱しやすいため
     (例：Biglooのパターンマッチライブラリ
     には`match-case'があります)、正規表現であることを明示する
     名前に変えてあります。

   以下のマクロにおいて、MATCH-EXPRはマッチオブジェクトか
`#f'を生成する式でなければなりません。通常それは
`rxmatch'を呼ぶ式になりますが、それだけに限られるわけではありません。

 -- Macro: rxmatch-let match-expr (var ...) form ...
     MATCH-EXPRを評価し、それがマッチオブジェクトを返したら、
     マッチした文字列をVAR ...に束縛し、FORMを評価します。
     最初のVARはマッチした文字列全体に束縛され、
     以降の変数はサブマッチ文字列に束縛されます。実際のサブマッチ文字列が
     与えられた変数より少なかった場合は、余った変数は`#f'に束縛されます。

     特定のマッチ文字列を受け取る必要が無いときは、その場所の
     変数の変わりに`#f'を置いておくこともできます。

          (rxmatch-let (rxmatch #/(\d+):(\d+):(\d+)/
                                "Jan  1 23:59:58, 2001")
             (time hh mm ss)
            (list time hh mm ss))
           => ("23:59:58" "23" "59" "58")

          (rxmatch-let (rxmatch #/(\d+):(\d+):(\d+)/
                                "Jan  1 23:59:58, 2001")
             (#f hh mm)
            (list hh mm))
           => ("23" "59")

     このマクロはscshの`let-match'に相当します。

 -- Macro: rxmatch-if match-expr (var ...) then-form else-form
     MATCH-EXPRを評価し、それがマッチオブジェクトを返したら
     マッチした文字列を変数VAR ...に束縛してTHEN-FORMを
     評価します。マッチオブジェクトが返されなければ束縛は行われず、
     ELSE-FORMが評価されます。変数VARをマッチ文字列に
     束縛するルールは`rxmatch-let'と同じです。

          (rxmatch-if (rxmatch #/(\d+:\d+)/ "Jan 1 11:22:33")
              (time)
            (format #f "time is ~a" time)
            "unknown time")
           => "time is 11:22"

          (rxmatch-if (rxmatch #/(\d+:\d+)/ "Jan 1 11-22-33")
              (time)
            (format #f "time is ~a" time)
            "unknown time")
           => "unknown time"

     このマクロはscshの`if-match'に相当します。

 -- Macro: rxmatch-cond clause ...
     CLAUSEの条件を順に評価してゆき、条件を満たすものが現れたら
     そのCLAUSEの残りのフォームを評価し、最後のフォームの値を
     `rxmatch-cond'の値とします。CLAUSEは以下のいずれかの
     形式でなければなりません。

    `(MATCH-EXPR (VAR ...) FORM ...)'
          MATCH-EXPRを評価し、それがマッチオブジェクトを返した場合は
          マッチ文字列を変数VAR ...に束縛した上で FORM ...を評価します。

    `(test EXPR FORM ...)'
          EXPRを評価し、それが真の値を返した場合はFORM ...を評価します。

    `(test EXPR => PROC)'
          EXPRを評価し、それが真の値を返した場合は
          それを唯一の引数として手続きPROCを呼びます。

    `(else FORM ...)'
          このCLAUSEは、もし与えられたとすれば最後のCLAUSEでなければ
          なりません。全てのCLAUSEが失敗した場合に、FORM ...が
          評価されます。

     `else' CLAUSEが与えられず、かつ全てのCLAUSEが
     失敗した場合の戻り値は未定義です。

          ;; 何通りかの日付のフォーマットをパーズする
          (define (parse-date str)
            (rxmatch-cond
              ((rxmatch #/^(\d\d?)\/(\d\d?)\/(\d\d\d\d)$/ str)
                  (#f mm dd yyyy)
                (map string->number (list yyyy mm dd)))
              ((rxmatch #/^(\d\d\d\d)\/(\d\d?)\/(\d\d?)$/ str)
                  (#f yyyy mm dd)
                (map string->number (list yyyy mm dd)))
              ((rxmatch #/^\d+\/\d+\/\d+$/ str)
                  (#f)
               (error "ambiguous: ~s" str))
              (else (error "bogus: ~s" str))))

          (parse-date "2001/2/3") => (2001 2 3)
          (parse-date "12/25/1999") => (1999 12 25)

     このマクロはscshの`match-cond'に相当します。

 -- Macro: rxmatch-case string-expr clause ...
     STRING-EXPRがまず評価され、続いてCLAUSEが順に検査されます。
     CLAUSEは以下のいずれかの形式でなければなりません。

    `(RE (VAR ...) FORM ...)'
          REはリテラル正規表現オブジェクトでなければなりません (*Note
          正規表現::参照)。STRING-EXPRの結果が文字列であり
          REにマッチした場合は、マッチ文字列が変数VAR ...に
          束縛され、FORMが評価されます。最後のFORMの値が`rxmatch-case'
          の値となります。

          STRING-EXPRの結果の文字列がREにマッチしないか、
          STRING-EXPRの結果が文字列以外であった場合は次のCLAUSEへと
          処理が進みます。

    `(test PROC FORM ...)'
          手続きPROCがSTRING-EXPRの結果を引数として呼ばれます。
          それが真の値を返した場合はFORMが順に評価され、最後のFORMの
          値が`rxmatch-case'の値として返されます。

          PROCが`#f'を返した場合は次のCLAUSEへと 処理が進みます。

    `(test PROC => PROC2)'
          手続きPROCがSTRING-EXPRの結果を引数として呼ばれます。
          それが真の値を返した場合は、その値を引数としてPROC2が呼ばれ、
          その返り値が`rxmatch-case'の値として返されます。

          PROCが`#f'を返した場合は次のCLAUSEへと 処理が進みます。

    `(else FORM ...)'
          このフォームは、与えられる場合は最後のCLAUSEでなければなりません。
          他の全てのCLAUSEが失敗した場合に、FORMが順に評価され、最後のFORMの
          値が`rxmatch-case'の値として返されます。

     `else' CLAUSEが与えられず、かつ全てのCLAUSEが
     失敗した場合の戻り値は未定義です。

     上の`parse-date'の例は`rxmatch-case'を使うとより単純になります。
          (define (parse-date2 str)
            (rxmatch-case str
              (test (lambda (s) (not (string? s))) #f)
              (#/^(\d\d?)\/(\d\d?)\/(\d\d\d\d)$/ (#f mm dd yyyy)
               (map string->number (list yyyy mm dd)))
              (#/^(\d\d\d\d)\/(\d\d?)\/(\d\d?)$/ (#f yyyy mm dd)
               (map string->number (list yyyy mm dd)))
              (#/^\d+\/\d+\/\d+$/                (#f)
               (error "ambiguous: ~s" str))
              (else (error "bogus: ~s" str))))

 -- Function: regexp-replace regexp string substitution
 -- Function: regexp-replace-all regexp string substitution
     STRING中で`regexp'にマッチした部分をSUBSTITUTIONで
     置き換えます。`regexp-replace'は最初にマッチした部分のみを置き換え、
     `regexp-replace-all'は全てのマッチを置き換えます。

     SUBSTITUTIONは文字列か手続きです。
     文字列の場合、バックスラッシュに続く数値を使ってサブマッチ文字列を参照できます。
     `\0'はマッチ文字列全体を参照します。文字列リテラルにバックスラッシュを
     埋め込む場合は二つのバックスラッシュが必要であることに注意して下さい。
     バックスラッシュそのものをSUBSTITUTION中で使いたい場合は
     二つのバックスラッシュを重ねます;
     文字列リテラルの場合は4つのバックスラッシュが 必要になります。

          (regexp-replace #/def|DEF/ "abcdefghi" "...")
            => "abc...ghi"
          (regexp-replace #/def|DEF/ "abcdefghi" "|\\0|")
            => "abc|def|ghi"
          (regexp-replace #/def|DEF/ "abcdefghi" "|\\\\0|")
            => "abc|\\0|ghi"
          (regexp-replace #/c(.*)g/ "abcdefghi" "|\\1|")
            => "ab|def|hi"

     SUBSTITUTIONが手続きである場合、STRING中の各マッチについて、
     マッチオブジェクトを引数としてその手続きが呼ばれます。その手続きが返す
     値を`display'で表現したものが置換文字列として使われます。

          (regexp-replace #/c(.*)g/ "abcdefghi"
                          (lambda (m)
                            (list->string
                             (reverse
                              (string->list (rxmatch-substring m 1))))))
           => "abfedhi"

     註: `regexp-replace-all' は文字列でマッチした部分の後ろの部分に
     ついて再帰的に自分自身を適用します。従って、REGEXPが
     文字列先頭のアサーション (`^') を含んでいても、それはSTRINGの
     先頭だけにマッチするとは限りません。

 -- Function: regexp-quote string
     STRING中で、正規表現において特別な意味を持つ文字を全てエスケープした
     文字列を返します。
          (regexp-quote "[2002/10/12] touched foo.h and *.c")
           => "\\[2002/10/12\\] touched foo\\.h and \\*\\.c"


File: gauche-refj.info,  Node: モジュールの再ロード,  Next: 簡単なディスパッチャ,  Prev: 正規表現ユーティリティ,  Up: ライブラリモジュール - Gauche拡張モジュール

9.17 `gauche.reload' - モジュールの再ロード
===========================================

 -- Module: gauche.reload
     開発のサイクルのなかで、モジュールを再ロードしなければならないことは
     頻繁におこります。このモジュールはそれを支援するものです。

     プログラムのいくつかの部分のセマンティクスはモジュールのロードの順に
     依存します。それで、任意のモジュールを再ロードすることはプログラムの
     ふるまいを予期せぬものに変えてしまう可能性があります。このモジュールは
     自分がなにをしようとしているか判っている開発者向けのものです。

     *再定義ルール*: モジュールを再ロードすると、デフォルトでは、その
     モジュール内のすべての束縛はリセットされます。
     しかしながら、場合によってこれは望ましいことではありません。たとえば、
     再構築するのに時間のかかるオブジェクトの大きなリストをもつような場合です。
     再ロード手続きにどの束縛を保存するかを決めるためのルールを指定することが
     できます。

     このルールは以下の構文で記述します。
            <module-rules> : (<module-rule> ...)
            <module-rule>  : (<module-pattern> <rule> ...)
            <module-pattern> : a symbol module name, or a symbol containing glob pattern
            <rule>         : procedure | symbol | regexp
                           | (and <rule> ...)
                           | (or  <rule> ...)
                           | (not <rule>)

     `<module-rules>' はモジュールごとのルールをきめるグローバルルール
     です。`<module-pattern>' はモジュール名シンボルまたは(`mylib.*'
     のような)グロブパターンを含むシンボルのどちらかです。`<rule>' が
     手続きであれば、述語として使われ、この述語を満す値の束縛は再定義から
     保護されます。`<rule>' がシンボルであれば、それと同じ名前の
     変数の束縛は保護されます。`<rule>' が正規表現の場合、この正規表現に
     マッチする名前の変数は保護されます。

     再定義からの保護機構は、場当たり的なもので、セマンティクスとしても
     不透明なものであることに注意してください。利便のためだけのものです。
     正確な振舞いをしれたければ、コードを見てください。

 -- Function: reload module-name &optional rule ...
     指定されたモジュールを再ロードします。オプションで RULE ...
     をつかって再定義ルールを指定することができます。
     ここで、それぞれの RULE は上の `<rule>' で定義されたものです。

 -- Function: reload-modified-modules &optional module-rules
     前回ロードしたときより変更のあったモジュールを再ロードします。
     オプション引数 MODULE-RULES が与えられていれば、再ロードした
     モジュールに適用する再定義ルールを決定するために使います。
     MODULE-RULESが省略された場合、現在のルールが適用されます。
     デフォルトの現在のルールは空です。現在のルールは
     `module-reload-rules'をつかって設定できます。


 -- Function: module-reload-rules &optional module-rules
     これは一種の「パラメータ」(*Note パラメータ::参照)で、
     `reload-modified-modules'に対応するデフォルトのモジュールルールを
     保持しています。引数なしで呼ばれたときには、現在のモジュールルールを
     返します。MODULE-RULESとともに呼ばれたきにはその引数を
     現在のモジュールルールにします。

 -- Function: reload-verbose &optional flag
     これは再ロード手続きのメッセージ出力レベルを制御するパラメータです。
     引数なしで呼ばれると現在の出力レベルフラグを返します。FLAGと
     ともに呼ばれると現在の出力レベルをこれに設定します。


File: gauche-refj.info,  Node: 簡単なディスパッチャ,  Next: シーケンスフレームワーク,  Prev: モジュールの再ロード,  Up: ライブラリモジュール - Gauche拡張モジュール

9.18 `gauche.selector' - 簡単なディスパッチャ
=============================================

 -- Module: gauche.selector
     このモジュールは、`sys-select' (*Note I/Oの多重化::参照)に基づき、
     登録されたハンドラにI/Oイベントをディスパッチするためのシンプルな
     インタフェースを提供します。

 -- Class: <selector>
     ディスパッチャのインスタンスで、ハンドラを携えてI/Oポートを監視します。
     `make'メソッドで新しいインスタンスを作れます。

 -- Method: selector-add! (self <selector>) port-or-fd proc flags
     セレクタにハンドラPROCを追加します。PROCは、PORT-OR-FD
     (ポートオブジェクトかシステムのファイルディスクリプタを表す整数)が
     FLAGSで指定された条件に合致した場合に呼ばれます。
     FLAGSは、以下のシンボルの1つ以上のリストでなければなりません。
    `r'
          PORT-OR-FDが読み取り可能になった時点でPROCが呼ばれます。

    `w'
          PORT-OR-FDが書き込み可能になった時点でPROCが呼ばれます。

    `x'
          PORT-OR-FDで例外的な状況が発生した場合にPROCが呼ばれます。

     PROCは、2引数で呼ばれます。1つ目はPORT-OR-FDそのもので、
     2つ目は条件を表すシンボル、`r'、`w'あるいは`x'です。

     同じ条件の下ですでにPORT-OR-FDにハンドラが関連付けられていた場合は、
     以前のハンドラがPROCで置き換えられます。

 -- Method: selector-delete! (self <selector>) port-or-fd proc flags
     PORT-OR-FD、PROC、FLAGSにマッチするハンドラエントリを
     削除します。引数のいずれかが`#f'である場合は、それが何でも良いことを
     意味します。例えば、
          (selector-delete! selector the-port #f #f)
     THE-PORTに関連付けられた全てのハンドラを削除します。
          (selector-delete! selector #f #f '(w))
     書き込み可能になるのを待っている全てのハンドラを削除します。

 -- Method: selector-select (self <selector>) &optional (timeout #f)
     ディスパッチャのボディです。SELFに登録された条件を待ち、条件が合致すると
     それに関連付けられたハンドラを呼びます。
     TIMEOUT引数が省略されるか偽の場合、このメソッドは永久に待ちます。
     タイムアウトの値を与える場合は、マイクロ秒を表す実数か、秒とマイクロ秒を
     表す2つの整数のリストを与えます。

     戻り値は、ハンドラが呼ばれた回数です。0(ゼロ)は、セレクタがタイムアウト
     したことを意味します。

     ハンドラの中でSELFを変更することは安全です。その変更は、次回の
     `selector-select'の呼び出し以降に反映されます。

   echoサーバのシンプルな例を示します。

     (use gauche.net)
     (use gauche.selector)

     (define (echo-server port)
       (let ((selector (make <selector>))
             (server   (make-server-socket 'inet port :reuse-addr? #t)))

         (define (accept-handler sock flag)
           (let* ((client (socket-accept server))
                  (output (socket-output-port client)))
             (selector-add! selector
                            (socket-input-port client :buffered? #f)
                            (lambda (input flag)
                              (echo client input output))
                            '(r))))

         (define (echo client input output)
           (let ((str (read-block 4096 input)))
             (if (eof-object? str)
                 (begin (selector-delete! selector input #f #f)
                        (socket-close client))
                 (begin (display str output)
                        (flush output)))))

         (selector-add! selector
                        (socket-fd server)
                        accept-handler
                        '(r))
         (do () (#f) (selector-select selector))))


File: gauche-refj.info,  Node: シーケンスフレームワーク,  Next: Syslog,  Prev: 簡単なディスパッチャ,  Up: ライブラリモジュール - Gauche拡張モジュール

9.19 `gauche.sequence' - シーケンスフレームワーク
=================================================

 -- Module: gauche.sequence
     _シーケンス_に関するジェネリックな操作を提供するモジュールです。
     シーケンスとは、コレクションのうち0から始まる整数インデックスで
     アクセスできるものです。

     このモジュールは`gauche.collection'を継承しています (*Note
     コレクションフレームワーク::参照)。
     コレクションに使えるジェネリックな操作は全てシーケンスに対しても適用可能です。

     Gauche組み込みクラスのうち、リスト、ベクター、そして文字列は
     シーケンスであり、このモジュールでメソッドが定義されます。
     また`gauche.uvector'のユニフォームベクタ等、
     いくつかの拡張データタイプはシーケンスとなっています。

* Menu:

* 基本的なシーケンスのアクセサ::
* シーケンスのスライス::
* シーケンス上のマップ::
* シーケンスに対する選択と探索::
* シーケンスを実装する::


File: gauche-refj.info,  Node: 基本的なシーケンスのアクセサ,  Next: シーケンスのスライス,  Prev: シーケンスフレームワーク,  Up: シーケンスフレームワーク

9.19.1 基本的なシーケンスのアクセサ
-----------------------------------

 -- Method: ref (seq <sequence>) index &optional fallback
     シーケンスSEQのINDEX番目の要素を返します。
     このメソッドによって、全てのシーケンスが統一的にアクセスできます。

     INDEXが負値だったりシーケンスのサイズ以上だった場合は、
     FALLBACKが与えられていればそれが返され、
     そうでなければエラーとなります。

          (ref '(a b c) 1)  => b
          (ref '#(a b c) 1) => b
          (ref "abc" 1)     => #\b

 -- Method: (setter ref) (seq <sequence>) index value
     統一的なシーケンスの変更メソッドです。
     シーケンスSEQのINDEX番目の要素にVALUEをセットします。

          (let ((x (list 'a 'b 'c)))
            (set! (ref x 1) 'z)
            x) => (a z c)

          (let ((x (vector 'a 'b 'c)))
            (set! (ref x 1) 'z)
            x) => #(a z c)

          (let ((x (string #\a #\b #\c)))
            (set! (ref x 1) #\z)
            x) => "azc"

 -- Method: referencer (seq <sequence>)

 -- Method: modifier (seq <sequence>)


File: gauche-refj.info,  Node: シーケンスのスライス,  Next: シーケンス上のマップ,  Prev: 基本的なシーケンスのアクセサ,  Up: シーケンスフレームワーク

9.19.2 シーケンスのスライス
---------------------------

 -- Method: subseq (seq <sequence>) &optional start end
     シーケンスSEQの、START番目の要素からEND番目の要素の直前
     までの部分シーケンスを返します。ENDが省略された場合はシーケンスの
     最後までが取られます。返されるシーケンスの型はSEQと同じになります。

          (subseq '(a b c d e) 1 4)   => (b c d)
          (subseq '#(a b c d e) 1 4)  => #(b c d)
          (subseq "abcde" 1 4)        => "bcd"

          (subseq '(a b c d e) 3)     => (d e)

 -- Method: (setter subseq) (seq <sequence>) start end value-seq
 -- Method: (setter subseq) (seq <sequence>) start value-seq
     VALUE-SEQの各要素を、シーケンスSEQのSTART番目から
     END番目の直前まで順にセットします。
     VALUE-SEQはどんなシーケンスでも構いませんが、 (END - START)
     よりは長くなくてはなりません。

     2番目の形式では、ENDがVALUE-SEQの長さから算出されます。

          (define s (vector 'a 'b 'c 'd 'e))
          (set! (subseq s 1 4) '(4 5 6))
          s => #(a 4 5 6 e)
          (set! (subseq s 0)   "ab")
          s => #(#\a #\b 5 6 e)


File: gauche-refj.info,  Node: シーケンス上のマップ,  Next: シーケンスに対する選択と探索,  Prev: シーケンスのスライス,  Up: シーケンスフレームワーク

9.19.3 シーケンス上のマップ
---------------------------

シーケンスはまたコレクションでもあるので、シーケンスについて
`fold'、`map'、`for-each'や他のジェネリック関数を
拡張することができます。しかし、時にはイテレーション中に要素そのものと
そのインデックスを知りたいことでしょう。そのためのジェネリック関数が
いくつかあります。

 -- Method: fold-with-index kons knil (seq <sequence>) ...
     ジェネリックな`fold'と似ていますが、KONSにはSEQの
     インデックス内から、第1引数としてSEQの要素と増加する値が渡る
     点が異なります。

          (fold-with-index acons '() '(a b c))
            => ((2 . c) (1 . b) (0 . a))

 -- Method: map-with-index proc (seq <sequence>) ...
 -- Method: map-to-with-index class proc (seq <sequence>) ...
 -- Method: for-each-with-index proc (seq <sequence>) ...
     `map'、`map-to'、`for-each'と似ていますが、PROCが
     第1引数としてインデックスを受け取る点が違います。

          (map-with-index list '(a b c d) '(e f g h))
            => ((0 a e) (1 b f) (2 c g) (3 d h))

          (map-to-with-index <vector> cons '(a b c d))
            => #((0 . a) (1 . b) (2 . c) (3 . d))

 -- Method: find-with-index pred (seq <sequence>)
     `find'のように、SEQの中でPREDを満足する最初の要素を
     探しますが、2つの値、要素のインデックスと要素自身を返します。
     PREDを満足する要素がなかったら、2つの`#f'が返ります。

          (find-with-index char-upper-case? "abraCadabra")
            => 4 and #\C

          (find-with-index char-numeric? "abraCadabra")
            => #f and #f

 -- Method: find-index pred (seq <sequence>)
     `find'に似ていますが、SEQの中でPREDを満足する最初の、
     要素自身ではなくインデックスを返す点が異なります。
     SEQの中にPREDを満足する要素がなかったら、`#f'が返ります。

          (find-index char-upper-case? "abraCadabra")
            => 4

          (find-index char-numeric? "abraCadabra")
            => #f

     SRFI-1 (*Note リストの探索::参照)の`list-index'も見て下さい。


File: gauche-refj.info,  Node: シーケンスに対する選択と探索,  Next: シーケンスを実装する,  Prev: シーケンス上のマップ,  Up: シーケンスフレームワーク

9.19.4 シーケンスに対する選択と探索
-----------------------------------

コレクションに対する選択と探索はシーケンスにも使えます。 *Note
コレクションからの選択と探索::を参照して下さい。

 -- Generic function: group-sequence seq &keyword key test
     シーケンスSEQの連続する要素で、同じキー値を持つもの同士を
     グループ化します。
     キーの値は要素に手続きKEYを適用することで得られます。KEYの
     デフォルト値は`identity'です。SEDQの各要素に対して、
     KEYは正確に一回だけ呼ばれます。
     キーの等価性判定には手続きTESTが使われます。デフォルト値は`eqv?'です。

          (group-sequence '(1 1 1 2 3 4 4 2 2 3 1 1 3))
            => ((1 1 1) (2) (3) (4 4) (2 2) (3) (1 1) (3))

          (group-sequence '(1 1 1 2 3 4 4 2 2 3 1 1 3)
                          :key (cut modulo <> 2)))
            => ((1 1 1) (2) (3) (4 4 2 2) (3 1 1 3))

          (group-sequence '#("a" "a" "b" "b" "c" "d" "d")
                          :test string=?)
            => (("a" "a") ("b" "b") ("c") ("d" "d"))

          (group-sequence "aabbcdd"
                          :test char=?)
            => ((#\a #\a) (#\b #\b) (#\c) (#\d #\d))

     このメソッドはHaskellの`group'と似ています。
     隣り合っていない要素もグループ化したい場合は、 `group-collection'
     (*Note コレクションからの選択と探索::参照)を使って下さい。



File: gauche-refj.info,  Node: シーケンスを実装する,  Prev: シーケンスに対する選択と探索,  Up: シーケンスフレームワーク

9.19.5 シーケンスを実装する
---------------------------


File: gauche-refj.info,  Node: Syslog,  Next: Termios,  Prev: シーケンスフレームワーク,  Up: ライブラリモジュール - Gauche拡張モジュール

9.20 `gauche.syslog' - Syslog
=============================

 -- Module: gauche.syslog
     このモジュールは syslog(3)
     のシステムロガーのインタフェースを提供します。

     一般的なアプリケーションについては、`gauche.logger' モジュールの
     ほうが使いやすいでしょう(*Note ユーザレベルのロギング::参照)。
     このモジュールは syslog の API
     に直接アクセスする必要のある人向きです。

     手続き群は基盤になっているシステムで syslog
     がサポートされている場合に のみ定義されます。

 -- Function: sys-openlog ident option facility
     [POSIX]
     システムロガーへのコネクションをオープンします。文字列の引数 IDENT
     はログの接頭辞に使われます。通常はプログラムを名前にします。OPTION
     は整数のフラグで、ログの振舞いを制御します。FACILITY はプログラムの
     タイプを指定する整数です。

     OPTIONのフラグは以下の整数定数の1つまたは複数を `logior' で
     合成することができます： `LOG_CONS'、`LOG_NDELAY'、`LOG_NOWAIT'、
     `LOG_ODELAY'、`LOG_PERROR' および `LOG_PID' です
     (これらの定数のいくつかは基盤となるシステムがサポートしていなければ
     定義されません)。

     FACILITY 引数は以下の整数定数のどれかひとつです。
     `LOG_AUTH'、`LOG_AUTHPRIV'、`LOG_CRON',
     `LOG_DAEMON'、`LOG_FTP'、`LOG_KERN'、`LOG_LOCAL0'、 から
     `LOG_LOCAL7'、`LOG_LPR'、`LOG_MAIL'、`LOG_NEWS',
     `LOG_SYSLOG'、`LOG_USER'、`LOG_UUCP' までです。
     (これらの定数のいくつかは基盤となるシステムがサポートしていなければ
     定義されません)。

     これらの定数の詳しい説明については、システムの openlog(3) の
     マニュアル・ページを見てください。

 -- Function: sys-syslog priority message
     [POSIX] 文字列 MESSAGE をログに記録します。syslog(3)
     とは違って、この手続きは
     フォーマットを行いません。フォーマットされた文字列を生成するなら
     `format' (*Note 出力::参照)が使えます。あるいは、より高水準の
     ルーチン `log-format' (*Note ユーザレベルのロギング::参照)
     を使うこともできます。

     整数の引数 PRIORITY は上述の FACILITY 定数のどれかひとつ
     と、以下のLEVEL定数と`logior'して、合成することができます：
     `LOG_EMERG'、`LOG_ALERT'、`LOG_CRIT'、`LOG_ERR'、
     `LOG_WARNING'、`LOG_NOTICE'、`LOG_INFO'、`LOG_DEBUG'


 -- Function: sys-closelog
     [POSIX] ロギングシステムとのコネクションをクローズします。

 -- Function: sys-setlogmask mask
     [POSIX] どの
     `sys-syslog'への呼び出しを記録できるかを決める、プロセスのログ
     優先度マスクを設定します。
     優先度マスクMASKは`sys-syslog'のLEVEL引数に
     対応するビットマスクを`logior'することで作成できます。
     レベルに対応するビットマスクは下の`sys-logmask'から
     取得することができます。

 -- Function: sys-logmask level
     [POSIX] ログレベル LEVEL から `sys-setlogmask' に対する
     ビットマスク整数を返します。


File: gauche-refj.info,  Node: Termios,  Next: 単体テスト,  Prev: Syslog,  Up: ライブラリモジュール - Gauche拡張モジュール

9.21 `gauche.termios' - Termios
===============================

 -- Module: gauche.termios
     このモジュールは端末の属性を制御する POSIX termios インタフェースを
     定義しています。さらに、このモジュールでは、システムが提供している場合には
     擬似 tty のインタフェースも提供しています。

 -- Builtin Class: <sys-termios>
     POSIX termios(7) の構造体です。

      -- Instance Variable of <sys-termios>: iflag

      -- Instance Variable of <sys-termios>: oflag

      -- Instance Variable of <sys-termios>: cflag

      -- Instance Variable of <sys-termios>: lflag

      -- Instance Variable of <sys-termios>: cc

     `iflag'、`oflag'、`cflag'、`lflag'の各スロットは、
     対応するビットマスクを非負の整数で表現した値を保持しています。

     また、`cc'スロットは`struct termios'の`c_cc'配列の
     _コピー_を返します。
     `c_cc'配列の値を変えたい場合は、変更したu8vectorを明示的に
     `cc'スロットに`set!'して下さい。


   このセクションを通じて、引数 PORT-OR-FD はポートオブジェクトか
システムのファイルディスクリプタを表現する小さい整数かのどちらかです。
PORTがシステム端末に結びついていないければ、エラーになります。
(`sys-isatty?'を使えばPORTが端末と結びついているか
どうかチェックできます。 *Note 他のファイル操作::参照)

 -- Function: sys-tcgetattr port-or-fd
     PORT-OR-FD と結びついている `<sys-termios>'オブジェクトの
     端末パラメータを返します。

 -- Function: sys-tcsetattr port-or-fd when termios
     PORT-OR-FDと結びついている端末のパラメータを TERMIOS に設定します。
     TERMIOS は `<sys-termios>' のインスタンスでなければなりません。

     整数の引数WHENはいつ変更を有効にするかを指定します。
     この引数用に3つの変数があらかじめ定義されています。
    `TCSANOW'
          変更を直ちに反映します。

    `TCSADRAIN'
          変更を、すべてのペンディングになっている出力がフラッシュされた後に反映します。

    `TCSAFLUSH'
          変更を、すべてのペンディングになっている出力がフラッシュされ、かつ、
          すべてのペンディングになっている入力が破棄されたあとに反映します。

 -- Function: sys-tcsendbreak port-or-fd duration
     ゼロストリームを指定した時間、PORT-OR-FDと結びついている端末に
     送出します。。時間の単位はシステム依存です。詳しくは、おつかいの
     システムのマニュアルページ tcsendbreak(3)を参照してください。

 -- Function: sys-tcdrain port-or-fd
     PORT-OR-FDへのすべての出力が送出されるまで待ちます。

 -- Function: sys-tcflush port-or-fd queue
     PORT-OR-FDのバッファ内のデータを破棄します。QUEUEには以下の値の
     どれかを指定します。
    `TCIFLUSH'
          受信データしたが読み込んではいないデータを破棄します。

    `TCOFLUSH'
          書き出したが送出していないデータを破棄します。

    `TCIOFLUSH'
          `TCIFLUSH' と `TCOFLUSH' の両方の動作をします。

 -- Function: sys-tcflow port-or-fd action
     PORT-OR-FDのデータフローをACTIONで制御します。ACTIONは
     以下の値のうちどれかです。
    `TCOOFF'
          出力の送出をサスペンドします。

    `TCOON'
          出力の送出を再開します。

    `TCIOFF'
          端末デバイスがシステムへの送出を止めるよう STOP
          文字を送出する。

    `TCION'
          端末デバイスがシステムへの送出を再開するよう START
          文字を送出する。

 -- Function: sys-tcgetpgrp port-or-fd
     PORT-OR-FDの結びついている端末のプロセスのグループIDを返します。

 -- Function: sys-tcsetpgrp port-or-fd pgrp
     PORT-OR-FDの結びついている端末のプロセスのグループIDをPGRPに
     設定します。

 -- Function: sys-cfgetispeed termios
 -- Function: sys-cfsetispeed termios speed
 -- Function: sys-cfgetospeed termios
 -- Function: sys-cfsetospeed termios speed
     TERMIOS内の入出力スピード(ボーレート)を取得/設定します。スピードは
     以下の定義ずみの数値で表現されてます：
     `B0'、`B50'、`B75'、`B110'、`B134'、
     `B150'、`B200'、`B300'、`B600'、`B1200'、
     `B1800'、`B2400'、`B4800'、`B9600'、 `B19200'、`B38400'。

     もっと速いボーレート、たとえば、`B57600'、 `B115200' あるいは
     `B230400' をサポートしている
     システムもあります。`symbol-bound?'をつかえば、これらの
     オプションが定義されているかどうかをチェックできます。`B0'
     はコネクションを終了するのに使われます。

 -- Function: sys-openpty &optional term
     擬似 tty のペア、マスターとスレーブをオープンし、2つの
     ファイルディスクリプタの整数を返します。オプション引数 TERM
     が渡される場合は、`<sys-termios>'オブジェクトでなければなりません。
     これは、pty パラメータを設定します。

     `open-input-fd-port'と`open-output-fd-port'の両方またはどちらか
     を返されたファイルディスクリプタに対するポートを生成するために使うことが
     できます(*Note ファイルポート::参照)。擬似端末の名前を得るには
     `sys-ttyname' を使います(*Note 他のファイル操作::参照)。

     この関数はシステムが `openpty(3)' をサポートしている場合にのみ利用
     可能です。

 -- Function: sys-forkpty &optional term
     擬似 ttyのペア、マスターとスレーブをオープンし、スレーブ sty を
     ログイン端末になるよう設定し、fork(2) します。

     二つの整数、最初の値は親プロセスに対しては子の pid の値で、0ならば
     子プロセスです。ふたつ目の値はマスター pty
     のファイルディスクリプタの 値です。

     オプション引数
     TERMが渡される場合は、それは`<sys-termios>'オブジェクト
     でなければなりません。これはスレーブ pty のパラメータを設定します。

     この関数はシステムが `forkpty(3)' をサポートしている場合にのみ利用
     可能です。

以下の例は、ユーザからのパスワードをエコーなしで取得する方法を示しています。

     (use gauche.termios)

     (define (get-password prompt)
       (let* ((port (current-input-port))
              (attr (sys-tcgetattr port))
              (lflag (slot-ref attr 'lflag)))
         ;; Show prompt
         (display prompt)
         (flush)
         ;; Turn off echo during reading.
         (dynamic-wind
          (lambda ()
            (slot-set! attr 'lflag (logand lflag (lognot ECHO)))
            (sys-tcsetattr port TCSAFLUSH attr))
          (lambda ()
            (read-line port))
          (lambda ()
            (slot-set! attr 'lflag lflag)
            (sys-tcsetattr port TCSANOW attr)))))


File: gauche-refj.info,  Node: 単体テスト,  Next: スレッド,  Prev: Termios,  Up: ライブラリモジュール - Gauche拡張モジュール

9.22 `gauche.test' - 単体テスト
===============================

 -- Module: gauche.test
     テストスクリプトを書くための手続きを提供します。
     テストスクリプトは次のような形になります。
          (use gauche.test)
          (test-start "my feature")
          (load "my-feature")  ; テストすべきプログラムをロード
          (import my-feature)  ; モジュールを定義している場合はインポート

          (test-module 'my-feature) ; モジュールの一貫性チェック

          (test-section "feature group 1")
          (test "feature 1-1" EXPECT (lambda () TEST-BODY))
          (test "feature 1-2" EXPECT (lambda () TEST-BODY))
           ...

          (test-section "feature group 2")
          (define test-data ...)
          (test "feature 2-1" EXPECT (lambda () TEST-BODY))
          (test "feature 2-2" *test-error* (lambda () TEST-THAT-SIGNALS-ERROR))
           ...

          (test-end)

     このテストスクリプトは、バッチ処理でもインタラクティブセッションからでも
     実行できます。インタラクティブセッションの場合はこのテストスクリプトを
     ただロードすれば、各テストの結果とサマリーが報告されます。
     バッチテストの場合は、標準出力を別のファイルにリダイレクトしておくと良いでしょう。
     標準出力が端末でない場合、テスト手続きは詳しい結果をstdoutに出力し、簡単な
     メッセージを標準エラー出力に書き出します。

     モジュールやプログラムを書いたら、Makefileに"test"ターゲットを作ることを
     お薦めします。ルールはこんな感じになるでしょう：

          test :
                  gosh my-feature-test.scm > test.log


 -- Function: test name expected thunk &optional compare
     THUNKを呼び、その結果をEXPECTEDと比較します。
     比較手続きには、引数COMPAREが与えられていればそれを用い、
     そうでなければ`equal?'
     を用います。NAMEはログに残すためのテストの名前です。

     THUNK内で捕捉されないエラーが発生した場合、それは捕捉され、
     特別なエラーオブジェクトに置き換えられます。グローバル変数`*test-error*'
     がエラーオブジェクトに束縛されており、エラーが期待される状況もテストすることが
     できます。

     手続きCOMPAREは次のように呼び出されます。
          (COMPARE EXPECTED RESULT-OF-THUNK)
     この手続きは、渡された結果が期待する値と合致する場合に`#t'を、
     そうでなければ`#t'を返さなければなりません。
     特別な比較手続きのひとつの用法は、不正確な数値を、多少の誤差を許して
     比較するような場合です。

          (test "test 1" (/ 3.141592653589 4)
                (lambda () (atan 1))
                (lambda (expected result)
                  (< (abs (- expected result)) 1.0e-10)))

 -- Variable: *test-error*
     特別なエラーオブジェクトに束縛されています。
     テストのthunkがエラーを起こすことが期待されている状況で、
     エラーオブジェクトをEXPECTED引数に渡すことができます。

          (test "test if car signals an error" *test-error*
                (lambda () (car 5)))

 -- Variable: *test-report-error*
     この変数が真であれば、`test'ルーチンはエラーを捕捉した際に
     スタックトレースをカレントエラーポートに出力します。
     期待しない状況でtest-errorオブジェクトが返された際に、そのエラーが
     どこで起こったかを知るのに役立つでしょう。

     この変数は`gauche.test'モジュールが読み込まれた時点で
     環境変数`GAUCHE_TEST_REPORT_ERROR'の値により初期化されます。
     例えば、テストスクリプト中の予期せぬエラーを調べるのに、
     次のようにすることができるでしょう
     (環境変数がセットされていれば、値は関係ありません)。

          env GAUCHE_TEST_REPORT_ERROR=1 gosh mytest.scm

 -- Macro: test* name expected expr &optional compare
     EXPRをlambdaでくるんでくれる便利なマクロです。

          (test* name expected expr)
            == (test name expected (lambda () expr))

 -- Function: test-module module
     MODULEはモジュール名のシンボルかモジュールでなければなりません。
     この手続きはモジュールMODULEに関していくつかの経験的な一貫性チェックを
     行います：(1)
     autoloadに設定されたシンボルがちゃんとロードできるか、 (2)
     exportにリストされたシンボルがモジュール内で定義されているか。
     この手続きは完璧ではないものの、
     ケアレスミスによる名前の綴り間違いを発見することができます。

 -- Function: test-start module-name
     テストの状態を初期化して、ヘッダをログに書き出します。テストを呼ぶ前に呼んで下さい。
     MODULE-NAMEはログのために使われる文字列です。

 -- Function: test-section section-name
     一群のテストの開始をマークします。単にログに使われるだけです。

 -- Function: test-end
     失敗したテストのリストを報告します。


File: gauche-refj.info,  Node: スレッド,  Next: 時間の計測,  Prev: 単体テスト,  Up: ライブラリモジュール - Gauche拡張モジュール

9.23 `gauche.threads' - スレッド
================================

Gaucheでは、コンパイル時に有効にしていれば、POSIXスレッド(pthreads)の
上に構築されるスレッドを使うことができます。

 -- Module: gauche.threads
     スレッドを扱うAPIを提供します。コンパイル時にスレッドのサポートを
     指定したか否かに関わらず、このモジュールを'usr'することができます。
     スレッドがサポートされていない場合は、多くのスレッド関連の手続きは
     単に"not supported"エラーを通知するだけです。

動作中のGaucheプログラムの中でスレッドが有効かどうかをチェックするためには、
次の手続きを使います。

 -- Function: gauche-thread-type
     サポートされているスレッドのタイプを表すシンボルを返します。
     現在のバージョンでは、POSIXスレッドの上に構築されるスレッドが
     有効な場合は`pthread'を返し、スレッドが有効でない場合は
     `none'を返します。

   SchemeレベルのスレッドAPIはSRFI-18、"マルチスレッドサポート" (*Note
[SRFI-18]: srfi-18.)を満たし、Gaucheのオブジェクトの
インターフェースでラップされます。

* Menu:

* スレッドプログラミングTips::
* スレッド手続き::
* 同期プリミティブ::
* スレッド例外::


File: gauche-refj.info,  Node: スレッドプログラミングTips,  Next: スレッド手続き,  Prev: スレッド,  Up: スレッド

9.23.1 スレッドプログラミングTips
---------------------------------

スレッドのAPIは外見上シンプルでポータブルに見えますが、
その機能の潜在的な力を活用するためには、スレッドがどのように
実装されているかを知る必要があります。
いくつかの言語では言語組み込みの機能としてスレッドをサポートし、
プログラマによるスレッドの利用を推奨しています。
しかし、多くの場合、実現したいアルゴリズムをスレッドを使わずに
実装する方法があります。
スレッドを使うことの利点と欠点を、そのスレッドがシステムによってどのように
実現されているかを考慮した上で比較する必要があります。

   Gaucheでは、スレッドを使う一番の目的は、他の方法で表現することが
難しい、プリエンプティブなスケジューリングを_必要_とする
プログラムを書くことです。プリエンプティブなスレッドは、
例えば、中断できないブロッキングI/Oを行うモジュールを
使わなければならないときや、実行時間の分からない計算に
割り込みを行いたいときなどに必要となります。

   それぞれのGaucheのスレッドには、個別の仮想マシンが割り当てられ、
専用のPOSIXスレッドにより実行されます。したがって、コンテキスト
スイッチのオーバヘッドは、ネイティブスレッドとほとんど変わりません。
しかし、スレッドの生成は、例えばcall/ccによる軽量スレッドよりは
ずっとコストのかかる処理です。
このように、Gaucheのプリエンプティブなスレッドは、
きめ細かい計算のために幾千ものスレッドを生成したいアプリケーション
向けでは_ありません_。

   推奨される使用方法は、いわゆる"スレッドプール"と呼ばれる
テクニックです。つまり、スレッドの集合を作って長時間それを
保持し、必要になったときにジョブをそこへディスパッチする
というものです。

   プリエンプティブなスレッドには他にも難しい点があり (*Note
[FairThreads]: fairthreads.参照)、
しばしばネイティブなプリエンプティブスレッドよりも
より良くフィットする代替策があります。

   * 単に同時実行が必要なだけなら、`call/cc'による協調スレッド
     テクニックが使えるでしょう。call/ccベースのスレッドの生成は、
     ネイティブスレッドを生成するよりも高速です。

   * ブロッキングI/Oを扱う必要があり、全てのコードが手元にある場合は、
     古き良き`select'ベースのディスパッチ(*Note 簡単なディスパッチャ::に
     例があります)を使うほうが簡単なことがあります。

   *
     サブシステムにおけるリソースの消費をコントロールする必要がある場合で、
     サブシステムがメインシステムとほとんど独立に動作する場合は、
     スレッドの代わりにUnixプロセスが使えることでしょう。
     時代に逆行するように聞こえますが、Unixプロセスはサブシステムと
     メインシステムの間に高度な"防御壁"を提供します。
     (例えば、サブシステムがセグメンテーション違反を起こしても、
     メインシステムは実行しつづけられます。)


もちろん、これらのテクニックはネイティブスレッドとは相互排他ではありません。
例えば、"スレッドプール"テクニックと一緒にディスパッチャを使うこともできます。
それらの機能を実現するために、ネイティブスレッドが唯一の方法ではないということを
心に留め置いて下さい。


File: gauche-refj.info,  Node: スレッド手続き,  Next: 同期プリミティブ,  Prev: スレッドプログラミングTips,  Up: スレッド

9.23.2 スレッド手続き
---------------------

 -- Builtin Class: <thread>
     スレッドを表すクラスです。それぞれのスレッドは、POSIXスレッドにより
     評価される関連付けられた手続きを持ちます。手続きが正常に戻ると、
     その結果は内部的な"結果"スロットに格納され、`thread-join!'により
     取得することができます。例外が投げられるか
     `thread-terminate!'により終了されるかで、手続きが異常終了すると、
     例外条件が内部的な"結果としての例外"スロットに格納され、
     その例外条件は終了したスレッドに対して`thread-join!'を
     呼ぶスレッドへと渡されます。

     それぞれのスレッドは独自の動的環境と動的なハンドラスタックを持っています。
     あるスレッドが生成されると、その動的な環境は生成者の動的な環境によって
     初期化されます。そのスレッドの動的なハンドラスタックは初期においては空です。

     複数のスレッドで共有されるリソースへのアクセスは、同期化プリミティブにより
     明示的に保護されなければなりません。*Note 同期プリミティブ::参照。

     ポートへのアクセスはGaucheによりシリアライズされます。
     複数のスレッドが1つのポートへの書き込みを試みた場合、それらの出力は
     混じることもありますが、失われる出力はなく、そのポートのステータスは
     一貫性が保たれます。複数のスレッドが1つのポートからの読み込みを試みた
     場合、1つの読み込みプリミティブ(例えば、`read'や`read-char'、
     `read-line'など)がアトミックに実行されます。

     シグナルハンドラは全てのスレッドで共有されますが、それぞれのスレッドは
     独自のシグナルマスクを持ちます。詳細は、*Note
     シグナルとスレッド::を参照。

     スレッドオブジェクトは以下の外部スロットを持ちます。

      -- Instance Variable of <thread>: name
          スレッドに関連付けられる名前。
          これは単にアプリケーションにとっての便宜を図るためのものです。
          原始となるスレッドは"`root'"という名前を持ちます。

      -- Instance Variable of <thread>: specific
          アプリケーションが使うスレッドローカルなスロット。

 -- Function: current-thread
     [SRFI-18]、[SRFI-21] 現在のスレッドを返します。

 -- Function: thread? obj
     [SRFI-18]、[SRFI-21]
     OBJがスレッドなら`#t'、そうでなければ`#f'を返します。

 -- Function: make-thread thunk &optional name
     [SRFI-18]、[SRFI-21]
     新しいスレッドを生成して返します。そのスレッドを実行するためには、
     `thread-start!'を呼ぶ必要があります。

     オプション引数NAMEを与えることで、そのスレッドに名前を与えることができます。

     内部的に、この手続きは単にSchemeスレッドオブジェクトを割り当て初期化している
     だけです。POSIXスレッドは`thread-start!'が呼ばれるまで生成されません。

 -- Function: thread-name thread
     [SRFI-18]、[SRFI-21] THREADのスロットNAMEの値を返します。

 -- Function: thread-specific thread
 -- Function: thread-specific-set! thread value
     [SRFI-18]、[SRFI-21]
     THREADのし呈したスレッドの値を取得/設定します。

 -- Function: thread-start! thread
     [SRFI-18]、[SRFI-21]
     THREADを開始します。THREADがすでに開始されていればエラーになります。
     THREADを返します。

 -- Function: thread-yield!
     [SRFI-18]、[SRFI-21]
     呼び出しているスレッドの実行を中断し、他に待機中の実行可能なスレッドがあれば、
     CPUにそれを処理させます。

 -- Function: thread-sleep! timeout
     [SRFI-18]、[SRFI-21]
     呼び出しているスレッドをTIMEOUTに指定した時間だけ中断します。
     TIMEOUTは絶対的な時間を表す`<time>'オブジェクト(*Note
     時間::参照)か、
     この手続きが呼ばれた時刻からの相対的な秒数を表す実数でなければなりません。

     指定された時間が経過すると、`thread-sleep!'は未定義値を返します。

     TIMEOUTが過去の時間を指していたら、`thread-sleep!'はすぐに戻ります。

 -- Function: thread-terminate! thread
     [SRFI-18]、[SRFI-21] 指定されたスレッドTHREADを終了します。
     THREADは終了され、`<terminated-thread-exception>'のインスタンスが
     THREADの結果例外のフィールドに格納されます。

     THREADが呼び出しているスレッドと同じ場合、この手続きは戻りません。
     そうでなければ、この手続きは未定義値を返します。

     THREADには(`dynamic-wind'での'after'手続きのような)クリーンアップ手続きを
     呼ぶチャンスがないので、この手続きは注意して使って下さい。
     THREADがクリティカルセクションにあるならば、一貫性のない状態を残すことに
     なります。
     しかし、あるスレッドが一旦終了すると、そのスレッドが保持していたmutexは
     'abandoned'(放棄された)状態になり、そのようなmutexをロックしようとするスレッドは
     'abandoned mutex
     exception'を投げるので、その状況を知ることができます。 *Note
     同期プリミティブ::参照。

 -- Function: thread-join! thread &optional timeout timeout-val
     [SRFI-18]、[SRFI-21]
     THREADの終了、あるいはTIMEOUTが与えられていればtimeoutが
     それに達するのを待ちます。

     TIMEOUTは絶対的な時間を表す`<time>'オブジェクト(*Note
     時間::参照)か、
     この手続きが呼ばれた時刻からの相対的な時間を秒数で表した実数でなければなりません。
     タイムアウトが指定されていない(デフォルト)は`#f'です。

     THREADが正常に終了したら、`thread-join!'はTHREADの
     結果フィールとに格納されている値を返します。
     THREADが異常終了したら、`thread-join!'はTHREADの結果例外
     フィールドに格納されている例外を投げます。

     タイムアウトに達すると、TIMEOUT-VALが与えられていればTHREAD-JOIN!を返し、
     与えられていなければ`<join-timeout-exception>'を投げます。


File: gauche-refj.info,  Node: 同期プリミティブ,  Next: スレッド例外,  Prev: スレッド手続き,  Up: スレッド

9.23.3 同期プリミティブ
-----------------------

 -- Builtin Class: <mutex>
     同期のための基本的デバイスです。次の4つの状態のいずれかを持ちます:
     locked/owned、locked/not-owned、unlocked/abandoned、unlocked/not-abandoned。
     Mutexは、それがunlocked(ロックされていない状態)であるときのみ、
     (`mutex-lock!'により)ロックされます。 所有されている(owned)
     mutexは、そのmutexを所有しているスレッドを記憶しています。
     通常、所有者となるスレッドはmutexをロックしたスレッドですが、
     ロックしたのとは別のスレッドがmutexを所有するようにすることもできます。
     ロックは`mutex-unlock!'によるか、所有するスレッドが終了すると解放されます。
     前者の場合、mutexはunlocked/not-abandoned(ロックされておらず、放棄されていない状態)
     になります。
     後者の場合、mutexはunlocked/abandoned(ロックされておらず、放棄された状態)になります。

     Mutexは、以下の外部スロットを持ちます。

      -- Instance Variable of <mutex>: name
          Mutexの名前。

      -- Instance Variable of <mutex>: state
          Mutexの状態。これは読み取りのみ可能なスロットです。
          下記の`mutex-state'の説明を参照して下さい。

      -- Instance Variable of <mutex>: specific
          アプリケーションが任意のデータを保持することのできるスロットです。
          例えば、アプリケーションはこの固有フィールドで'再帰的な'
          mutexを 実装することができます。

 -- Function: mutex? obj
     [SRFI-18]、[SRFI-21]
     OBJがmutexであれば`#t'、そうでなければ`#f'を返します。

 -- Function: make-mutex &optional name
     [SRFI-18]、[SRFI-21] 新しいmutexオブジェクトを生成して返します。
     生成時には、mutexの状態は、unlocked/not-abandoned(ロックされておらず、
     放棄されていない状態)です。オプションで、このmutexに名前を付けることができます。

 -- Function: mutex-name mutex
     [SRFI-18]、[SRFI-21] Mutexの名前を返します。

 -- Function: mutex-specific mutex
 -- Function: mutex-specific-set! mutex value
     [SRFI-18]、[SRFI-21] Mutexの固有の値を取得/セットできます。

 -- Function: mutex-state mutex
     [SRFI-18]、[SRFI-21]
     MUTEXの状態を返します。状態は以下のうちの1つです。

    あるスレッド
          Mutexはlocked/owned(ロックされ所有されている)で、所有者は返されたスレッド。

    シンボル `not-owned'
          Mutexはlocked/not-owned(ロックされているが所有されていない)。

    シンボル `abandoned'
          Mutexはunlocked/abandoned(ロックされておらず、放棄されている)。

    シンボル `not-abandoned'
          Mutexはunlocked/not-abandoned(ロックされておらず、放棄されていない)。

 -- Function: mutex-lock! mutex &optional timeout thread
     [SRFI-18]、[SRFI-21]
     MUTEXをロックします。MUTEXがunlocked/not-abandoned(
     ロックされておらず放棄されていない状態)なら、
     この手続きはその状態を排他的なlocked(ロックされた状態)に変更します。
     デフォルトでは、MUTEXはlocked/owned(ロックされ、所有された状態)になり、
     所有者は呼び出したスレッドです。
     他の所有しているスレッドを、引数THREADを与えることもできます。
     引数THREADに`#f'が与えられると、mutexはlocked/not-owned
     (ロックされ所有されていない状態)になります。

     MUTEXがunlocked/abandoned(ロックされておらず放棄された状態)ならば、それはつまり、
     他の何らかのスレッドがそのロックを解放せずに終了した場合、
     この手続きはMUTEXの状態を変更した後に、'abandoned mutex exception'
     (*Note スレッド例外::参照)を通知します。

     MUTEXがlocked(ロックされた状態)で、TIMEOUTが省略されるか`#f'ならば、
     この手続きはMUTEXのロックが解放されるまでブロックします。
     TIMEOUTが指定されている場合は、ロックが獲得できなかったケースでは
     指定された時間に達した時に`mutex-lock!'は戻ります。
     TIMEOUTには、絶対的な時間(`<time>'オブジェクト、*Note
     時間::参照)か、 相対的な時間を(実数で)指定できます。

     MUTEXのロックが成功すると`mutex-lock!'は`#t'を返し、
     タイムアウトに達すると`#f'が返ります。

     MUTEXそれ自身は'再帰的なロック'の機能は実装していません。
     つまり、MUTEXをロックしたスレッドが再度MUTEXをロックしようと
     すると、そのスレッドはブロックします。しかし、このmutexに
     基づいて再帰的なロックをセマンティクスを実装することは難しくありません。
     次の例は、SRFI-18のドキュメントから引用したものです。

          (define (mutex-lock-recursively! mutex)
            (if (eq? (mutex-state mutex) (current-thread))
                (let ((n (mutex-specific mutex)))
                  (mutex-specific-set! mutex (+ n 1)))
                (begin
                  (mutex-lock! mutex)
                  (mutex-specific-set! mutex 0))))

          (define (mutex-unlock-recursively! mutex)
            (let ((n (mutex-specific mutex)))
              (if (= n 0)
                  (mutex-unlock! mutex)
                  (mutex-specific-set! mutex (- n 1)))))

 -- Function: mutex-unlock! mutex &optional condition-variable timeout
     [SRFI-18]、[SRFI-21]
     MUTEXをアンロックします。MUTEXの状態は、unlocked/not-abandoned
     (ロックされておらず、放棄されていない状態)となります。
     呼び出しているスレッドにより所有されていないmutexをアンロックすることは
     許されています。

     オプショナル引数のCONDITIONAL-VARIABLEが与えられている場合、
     `mutex-unlock!'は"条件変数待機"の動作も行います(例えば、POSIXスレッドの
     `pthread_cond_wait')。 現在のスレッドはMUTEXをアンロックし、
     CONDITION-VARIABLEの待ち状態に入る動作をアトミックに行います。
     スレッドは、他のスレッドがCONDITION-VARIABLEにシグナルを通知するか
     (下記の`condition-variable-signal!'と`condition-variable-broadcast!'を
     見て下さい)、
     TIMEOUTが与えられていてそれに達すると、ブロックが解除されます。
     引数TIMEOUTは、絶対的な時間を表す`<time>'オブジェクト(*Note
     時間::参照)、
     相対的な時間を秒数で表す実数、タイムアウトしないことを表す`#f'のいずれかです。
     ブロックが解除された時に、必ずしも条件が満たされているとは限らないので、
     次に挙げる例(SRFI-18のドキュメントより引用)のように、
     呼び出したスレッドはMUTEXのロックを再獲得して条件を検査するべきです。

          (let loop ()
            (mutex-lock! m)
            (if (condition-is-true?)
                (begin
                  (do-something-when-condition-is-true)
                  (mutex-unlock! m))
                (begin
                  (mutex-unlock! m cv)
                  (loop))))

 -- Function: with-locking-mutex mutex thunk
     MUTEXをロックしてTHUNKを呼びます。次のように実装されています。
          (define (with-locking-mutex mutex thunk)
            (dynamic-wind
             (lambda () (mutex-lock! mutex))
             thunk
             (lambda () (mutex-unlock! mutex))))

 -- Builtin Class: <condition-variable>
     条件変数は、ある条件が真になるのを待っているスレッドの集合を保持します。
     あるスレッドがその条件を変更する時、`condition-variable-signal!'あるいは
     `condition-variable-broadcast!'が呼ばれ、それは1つ以上の待機中の
     スレッドのブロックを解除するため、それらのスレッドは条件が満足するかどうか
     検査できます。

     条件変数オブジェクトは以下のスロットを持ちます。

      -- Instance Variable of <mutex>: name
          条件変数の名前。

      -- Instance Variable of <mutex>: specific
          アプリケーションが任意のデータを保持できるスロット。

     SRFI-18は、pthreadの`pthread_cond_wait'に相当する手続きを
     持たないことに注意してください。条件変数を待つのは、
     `mutex-unlock!'の省略可能引数に条件変数を渡し、
     その後mutexを再び`mutex-lock!'で得ることで行います。
     この設計は柔軟性のためです。詳しくはSRFI-18を参照して下さい。

     このような、pthreadで条件変数を使う定石は：
          while (some_condition != TRUE) {
            pthread_cond_wait(condition_variable, mutex);
          }
     SRFI-18では次のようなコードになります。
          (let loop ()
            (unless some-condition
              (mutex-unlock! mutex condition-variable)
              (mutex-lock! mutex)
              (loop)))

 -- Function: condition-variable? obj
     [SRFI-18]、[SRFI-21]
     OBJが条件変数なら`#t'、そうでなければ`#f'を返します。

 -- Function: make-condition-variable &optional name
     [SRFI-18]、[SRFI-21]
     新しい条件変数を返します。オプショナル引数NAMEで
     その名前を与えることができます。

 -- Function: condition-variable-name cv
     [SRFI-18]、[SRFI-21] 条件変数の名前を返します。

 -- Function: condition-variable-specific cv
 -- Function: condition-variable-specific-set! cv value
     [SRFI-18]、[SRFI-21] 条件変数の固有の値を取得/セットします。

 -- Function: condition-variable-signal! cv
     [SRFI-18]、[SRFI-21]
     CVで待機しているスレッドがある場合は、それらのうちの1つがスケジューラに
     より選択され、実行可能にされます。

 -- Function: condition-variable-broadcast! cv
     [SRFI-18]、[SRFI-21]
     CVで待機している全てのスレッドのブロックを解除します。


File: gauche-refj.info,  Node: スレッド例外,  Prev: 同期プリミティブ,  Up: スレッド

9.23.4 スレッド例外
-------------------

例外のいくつかのタイプは、スレッド関連の手続きから投げられます。
これらの例外は、Gaucheの例外メカニズム(*Note 例外::参照)により
扱われます。

 -- Builtin Class: <thread-exception>
     スレッド関連の例外の基底クラスです。`<exception>'クラスを継承しています。
     スロットを1つ持っています。

      -- Instance Variable of <thread-exception>: thread
          この例外を投げたスレッド。

 -- Builtin Class: <join-timeout-exception>
     待機していたスレッドが戻る前にタイムアウトに達した時に`thread-join!'によって
     投げられる例外。`<thread-exception>'を継承しています。

 -- Builtin Class: <abandoned-mutex-exception>
     ロックされるMUTEXが、unlocked/abandoned(ロックされておらず、放棄された状態)
     であるときに`mutex-lock!'により投げられる例外。
     `<thread-exception>'を継承しています。スロットを1つ持ちます。

      -- Instance Variable of <abandoned-mutex-exception>: mutex
          この例外の原因となったmutex。

 -- Builtin Class: <terminated-thread-exception>
     待機していたスレッドが(`thread-terminate!'により)異常終了した
     場合に(`thread-join!'により)投げられる例外。
     `<thread-exception>'を継承し、スロットを1つ持ちます。

      -- Instance Variable of <terminated-thread-exception>: terminator
          この例外の原因となったスレッドを終了したスレッド。

 -- Builtin Class: <uncaught-exception>
     待機していたスレッドが捕捉されない例外により終了された場合に
     `thread-join!'により投げられる例外。
     `<thread-exception>'を継承し、スロットを1つ持ちます。

      -- Instance Variable of <uncaught-exception>: reason
          そのスレッドの終了の原因となった例外。

 -- Function: join-timeout-exception? obj
 -- Function: abandoned-mutex-exception? obj
 -- Function: terminated-thread-exception? obj
 -- Function: uncaught-exception? obj
     [SRFI-18]、[SRFI-21]
     これらの手続きは、OBJが特定のタイプの例外かどうかを検査します。
     SRFI-18との互換性のために提供されています。

 -- Function: uncaught-exception-reason exc
     [SRFI-18]、[SRFI-21]
     `<uncaught-exception>'オブジェクトの`reason'スロットの値を
     返します。 SRFI-18との互換性のために提供されています。


File: gauche-refj.info,  Node: 時間の計測,  Next: ユニフォームベクタ,  Prev: スレッド,  Up: ライブラリモジュール - Gauche拡張モジュール

9.24 `gauche.time' - 時間の計測
===============================

 -- Module: gauche.time
     Schemeコードの実行時間を測る2つの単純な方法を提供します。
     インタラクティブな使用に便利な`time'マクロ及び、
     プログラム中に埋め込んで使える`<time-counter>'オブジェクトです。

 -- Macro: time expr expr2 ...
     式EXPR EXPR2 ... を順に評価し、最後の式の結果を返します。
     結果が返される前に、全ての式の評価にかかった実(経過)時間および
     ユーザースペース、カーネルスペースで費されたCPU時間がカレントエラーポートに
     報告されます。

     現在の実装は、経過時間に対しては`sys-gettimeofday' (*Note
     時間::参照)を、CPU時間に対しては`sys-times' (*Note
     システムへの問い合わせ::参照)を用いています。従って、
     それぞれの数値の分解能はこれらの手続きが用いているシステムコールに依存します。
     CPU時間は10ms単位で、経過時間はそれより細かいことが多いです。
     但しgettimeofday(2)コールをサポートしていないOSでは経過時間が最悪の場合
     秒単位になります。

          gosh> (time (length (sort (call-with-input-file "/usr/share/dict/words" port->string-list))))
          ;(time (length (sort (call-with-input-file "/usr/share/dict/words" port- ...
          ; real   0.357
          ; user   0.350
          ; sys    0.000
          45427

 -- Class: <time-counter>
     時間カウンタの抽象クラスです。時間カウンタは
     時間の経過と共にその値が増加してゆく一種のタイマーです。
     何度でもカウントを止めたり開始したりできます。
     カウンタの値はカウントが止まっている時に読み出すことができます。
     複数の時間カウンタを使えば、
     例えばループ中の二つの部分について費される時間を別々に計測することもできます。

     具体的なサブクラスが、どの時間をカウントするかを決定します。
     時間カウンタを使うには、下に挙げるサブクラスのいずれかを
     インスタンシエイトしなければなりません。

 -- Class: <real-time-counter>
 -- Class: <user-time-counter>
 -- Class: <system-time-counter>
 -- Class: <process-time-counter>
     それぞれ、実経過時間、ユーザースペースCPU時間、カーネルスペースCPU時間、
     総CPU時間 (ユーザー+カーネル)を計測する時間カウンタのクラスです。

 -- Method: time-counter-start! (counter <time-counter>)
 -- Method: time-counter-stop! (counter <time-counter>)
     時間カウンタCOUNTERを開始/停止します。カウンタが走っている間の時間が、
     カウンタが停止した時点でカウンタの値に加算されます。

     開始/停止の対はネストすることができます。その場合は、一番外側の対のみが
     有効です。
     つまり、既に走っているカウンタに対し`time-counter-start!'を呼んでも
     何も起こりませんが、一度余分に`time-counter-stop!'を呼ばないと
     カウンタは止まりません。
     これは、内部に既に開始/停止の対を含んでいるかもしれない大きなコードブロックの
     全体の時間を計測したいというような場合に便利です。

     既に停止しているカウンタに対して`time-counter-stop!'を呼んでも
     何も起こりません。

 -- Method: time-counter-reset! (counter <time-counter>)
     カウンタCOUNTERの値をリセットします。既にCOUNTERが走っている
     場合は、リセットの前にカウンタは停止させられます。

 -- Method: time-counter-value (counter <time-counter>)
     カウンタCOUNTERの現在の値(秒数)を実数で返します。
     分解能はそれぞれのカウンタが用いているシステムコールに依存します。

 -- Macro: with-time-counter counter expr ...
     式EXPR ...が評価される間だけCOUNTERを走らせる、
     便利なマクロです。最後の式の結果を返します。このマクロは次のように
     定義されます。
          (define-syntax with-time-counter
            (syntax-rules ()
              ((_ counter . exprs)
               (dynamic-wind
                (lambda () (time-counter-start! counter))
                (lambda () . exprs)
                (lambda () (time-counter-stop! counter))))
              ))

   下の例では、ループ内でのprocess-Aとprocess-Bにて費された
概略の時間をそれぞれ計測します。

     (let ((ta (make <real-time-counter>))
           (tb (make <real-time-counter>)))
       (dotimes (i 100000)
         (with-time-counter ta
           (process-A))
         (with-time-counter tb
           (process-B)))
       (format #t "Time spent in process-A: ~s\n" (time-counter-value ta))
       (format #t "Time spent in process-B: ~s\n" (time-counter-value tb))
       )


File: gauche-refj.info,  Node: ユニフォームベクタ,  Next: バージョン番号の比較,  Prev: 時間の計測,  Up: ライブラリモジュール - Gauche拡張モジュール

9.25 `gauche.uvector' - ユニフォームベクタ
==========================================

 -- Module: gauche.uvector
     SRFI-4(*Note SRFI-4: srfi-4.)に定義されている、
     要素が同一の数値型であるようなベクタを提供します。

     Gaucheの実装は、SRFI-4の仕様を次のように拡張しています。
        * いくつかの手続きはSRFI-4に無い省略可能な引数を取ります。
          `TAGvector->list'は省略可能なstartとendのインデックスを取り、
          `TAGvector-ref'は省略可能なデフォルト値を取ります。

        * 追加の手続き： コピー(`TAGvector-copy', `TAGvector-copy!')、
          変換 (`TAGvector->vector', `vector->TAGvector')、
          及び各種算術演算(`TAGvector-add'等)。

        * コレクションフレームワーク (*Note
          コレクションフレームワーク::参照)と シーケンスフレームワーク
          (*Note シーケンスフレームワーク::参照)の実装。 例えば `map',
          `for-each', `ref', `subseq'等の
          メソッドがSRFI-4ベクタに対して使えます。

     通常のベクタではなくSRFI-4ベクタを使うことにより得られる利点がいくつかあります。
     まず、SRFI-4ベクタは通常のベクタよりもコンパクトです。
     いくつかのオペレーション(特に、Gaucheの拡張仕様であるベクタ上の数値演算)では、
     型検査と型変換を個々の要素に対して行わなくても良いため、
     極めて効率の良い演算が可能です。さらに、
     数値の配列を扱う外部のライブラリとのインタフェースが容易です。
     例えば、GaucheのOpenGLバインディングではSRFI-4ベクタを多用しています。
以下の10タイプのベクタが定義されます。
_s8vector_
     要素が -2^7 から 2^7-1 の間の正確な整数であるベクタ

_u8vector_
     要素が 0 から 2^8-1 の間の正確な整数であるベクタ

_s16vector_
     要素が -2^15 から 2^15-1 の間の正確な整数であるベクタ

_u16vector_
     要素が 0 から 2^16-1 の間の正確な整数であるベクタ

_s32vector_
     要素が -2^31 から 2^31-1 の間の正確な整数であるベクタ

_u32vector_
     要素が 0 から 2^32-1 の間の正確な整数であるベクタ

_s64vector_
     要素が -2^63 から 2^63-1 の間の正確な整数であるベクタ

_u64vector_
     要素が 0 から 2^64-1 の間の正確な整数であるベクタ

_f32vector_
     要素が、GaucheをコンパイルしたCコンパイラの`float'で表現し得るような
     不正確な実数(通常IEEE単精度浮動少数点数)であるベクタ

_f64vector_
     要素が、GaucheをコンパイルしたCコンパイラの`double'で表現し得るような
     不正確な実数(通常IEEE倍精度浮動少数点数)であるベクタ

ベクタの型が許す範囲外の値を格納しようとした場合、通常はエラーとなります。
いくつかの手続きは省略可能な引数CLAMPによって、
そのような場合に別のふるまいを指定することができます。
CLAMPには以下のいずれかの値を与えることが出来ます。
`#f'
     デフォルト (エラーを通知)

`high'
     高い方の値をクランプ、すなわち、格納しようとする値が許される値の最大値より大きかった
     場合は、可能な最大値を代わりに格納します。

`low'
     低い方の値をクランプ、すなわち、格納しようとする値が許される値の最小値より大きかった
     場合は、可能な最小値を代わりに格納します。

`both'
     高いほうと低いほうの両方の値をクランプします。

     (list->u8vector '(-1))         => error
     (list->u8vector '(-1) 'low)    => #u8(0)
     (list->u8vector '(-1) 'high)   => error
     (list->u8vector '(3000) 'high) => #u8(255)
     (list->u8vector '(-100 20 300) 'both) => #u8(0 20 255)

   以下の記述では、`TAG'は `s8', `u8', `s16', `u16', `s32', `u32',
`s64', `u64', `f32', `f64'
のいずれにも置き換えて読むことができるものとします。

* Menu:

* ユニフォームベクタの基本操作::
* ユニフォームベクタの変換::
* ユニフォームベクタの数値演算::
* ユニフォームベクタのブロック入出力::


File: gauche-refj.info,  Node: ユニフォームベクタの基本操作,  Next: ユニフォームベクタの変換,  Prev: ユニフォームベクタ,  Up: ユニフォームベクタ

9.25.1 ユニフォームベクタの基本操作
-----------------------------------

 -- Builtin Class: <TAGvector>
     TAGvectorのクラス。`<sequence>'を継承します。

 -- Reader Syntax: `#TAG(N ...)'
     リテラルの単一型のベクタを記述します。
          #s8(3 -2 4)
          #u32(4154 88357 2 323)
          #f32(3.14 0.554525 -3.342)

 -- Function: TAGvector? OBJ
     [SRFI-4] OBJがTAGvectorなら`#t'を、そうでなければ`#f'を返します。

 -- Function: TAGvector X ...
     [SRFI-4] 数値X ... を要素に持つTAGvectorを作成して返します。
     正確な整数のベクタに対しては、数値は正確な整数でなければならず、
     また有効な範囲内の値でなければなりません。
          (s8vector 1 2 3) => #s8(1 2 3)

 -- Function: make-TAGvector LEN &OPTIONAL FILL
     [SRFI-4] 長さLENのTAGvectorを作成して返します。各要素はFILLで
     初期化されます。正確な整数のベクタに対しては、FILLは正確な整数でなければならず、
     また有効な範囲内の値でなければなりません。
     FILLが省略された場合、各要素の初期値は不定です。
          (make-u8vector 4 0) => #u8(0 0 0 0)

 -- Function: TAGvector-length VEC
     [SRFI-4] TAGvector VECの長さを返します。

     モジュール`gauche.collection'をインポートしていれば、
     VECの長さを知るのに、総称関数`size-of'を使うこともできます (*Note
     コレクションフレームワーク::参照)。
          (s16vector-length '#s16(111 222 333)) => 3

          (use gauche.collection)
          (size-of '#s16(111 222 333)) => 3

 -- Function: TAGvector-ref VEC K &optional FALLBACK
     [SRFI-4+] TAGvector VECのK番目の要素を返します。

     Kが有効な範囲外であった場合、通常はエラーが通知されますが、
     省略可能な引数FALLBACKが与えられている場合はそれが返されます。

     モジュール`gauche.collection'をインポートしていれば、
     総称関数`ref'を使うこともできます。

          (u16vector-ref '#u16(111 222 333) 1) => 222

          (use gauche.collection)
          (ref '#u16(111 222 333) 1) => 222

 -- Function: TAGvector-set! VEC K N &optional CLAMP
     [SRFI-4+] TAGvector VECのK番目の要素に数値Nをセットします。
     省略可能な引数CLAMPが、Nが正しい範囲外の数であった場合の動作を指定します。
     デフォルトではエラーが通知されます。

     モジュール`gauche.collection'をインポートしていれば、
     総称関数`ref'のsetter手続きを使うこともできます。
          (let ((v (s32vector -439 852 8933)))
            (s32vector-set! v 1 4)
            v)
           => #s32vector(-439 4 8933)

          (use gauche.collection)
          (let ((v (s32vector -439 852 8933)))
            (set! (ref v 1) 4)
            v)
           => #s32vector(-439 4 8933)

 -- Function: TAGvector-copy VEC &optional START END
     ベクタVECをコピーします。
     省略可能な引数STARTとENDが与えられた場合、
     それらは取り出される要素の範囲を制限します。

          (u8vector-copy '#u8(1 2 3 4))     => #u8(1 2 3 4)
          (u8vector-copy '#u8(1 2 3 4) 2)   => #u8(3 4)
          (u8vector-copy '#u8(1 2 3 4) 1 3) => #u8(2 3)

 -- Function: TAGvector-copy! TARGET TSTART SOURCE &optional SSTART SEND
     TARGET および SOURCE はともに TAGvector でなければ
     なりません。さらに、TARGET は変更可能でなければなりません。
     この手続きは、STARTの要素を、インデックスSSTARTから(これを含み)
     SEND までを、TARGET へインデックス TSTARTからコピーします。
     SSTARTおよびTSTARTは省略可能で、その場合には、それぞれ、 0 および
     SOURCEの長さが仮定されます。

          (let ((target (u8vector 0 1 2 3 4 5 6)))
            (u8vector-copy! target 2 '#u8(10 11 12 13 14) 1 4)
            target)
           => #u8(0 1 11 12 13 6)

     もし、コピー元のベクタの SSTART と SEND の間にある要素の
     数がコピー先のベクタのTSTART以降の部分よりも大きければ、超過分の
     ベクタはだまって捨てられます。

     _注意事項:_ この手続きは以前はユニフォームベクタ TARGET および
     SOURCE のみを引数としてとり、SOURCE の内容を TARGET へ
     コピーするためだけに使われました。両方のベクタは同じ型で、同じ長さでなけ
     ればなりませんでした。この API は `string-copy!' (SRFI-13) および
     `vector-copy!' (SRFI-43)にあわせて現在の形式に改訂されています。
     旧来のインタフェースもバックワードコンパチビリティのためにサポートされて
     いますが、これは廃止予定で、将来のリリースではサポートされなくなります。

   コレクションやシーケンスフレームワークを使うと、さらに様々な操作を
行うことができます。

     (use gauche.collection)
     (use gauche.sequence)

     (fold + 0 '#s32(1 2 3 4)) => 10

     (map-to <f32vector> * '#f32(3.2 1.1 4.3) '#f32(-4.3 2.2 9.4))
       => #f32(-13.760001 2.420000 40.420002)

     (subseq #u32(1 4 3 4 5) 2 4) => #u32(3 4)


File: gauche-refj.info,  Node: ユニフォームベクタの変換,  Next: ユニフォームベクタの数値演算,  Prev: ユニフォームベクタの基本操作,  Up: ユニフォームベクタ

9.25.2 ユニフォームベクタの変換
-------------------------------

 -- Function: TAGvector->list VEC &optional START END
     [SRFI-4+] TAGvector VECをリストに変換します。
     省略可能な引数STARTとENDが与えられた場合、
     それらは取り出される要素の範囲を制限します。

     モジュール`gauche.collection'をインポートしていれば、
     総称関数`coerce-to'を使うこともできます。
          (u32vector->list '#u32(9 2 5)) => (9 2 5)

          (use gauche.collection)
          (coerce-to <list> '#u32(9 2 5)) => (9 2 5)

 -- Function: TAGvector->vector VEC &optional START END
     TAGvector VECをベクタに変換します。
     省略可能な引数STARTとENDが与えられた場合、
     それらは取り出される要素の範囲を制限します。

     モジュール`gauche.collection'をインポートしていれば、
     総称関数`coerce-to'を使うこともできます。
          (f32vector->vector '#f32(9.3 2.2 5.5))   => #(9.3 2.2 5.5)
          (f32vector->vector '#f32(9.3 2.2 5.5) 2) => #(5.5)

          (use gauche.collection)
          (coerce-to <vector> '#f32(9.3 2.2 5.5)) => #(9.3 2.2 5.5)

 -- Function: list->TAGvector LIST &optional CLAMP
     [SRFI-4+] リストLISTをTAGvectorに変換します。
     省略可能な引数CLAMPが、リスト内の要素が正しい範囲外の数であった場合の
     動作を指定します。

     モジュール`gauche.collection'をインポートしていれば、
     総称関数`coerce-to'を使うこともできます。
          (list->s64vector '(9 2 5)) => #s64(9 2 5)

          (use gauche.collection)
          (coerce-to <s64vector> '(9 2 5)) => #s64(9 2 5)

 -- Function: vector->TAGvector VEC &optional START END CLAMP
     ベクタVECをTAGvectorに変換します。
     省略可能な引数STARTとENDが与えられた場合、
     それらは取り出される要素の範囲を制限します。
     省略可能な引数CLAMPが、ベクタ内の要素が正しい範囲外の数であった場合の
     動作を指定します。

     モジュール`gauche.collection'をインポートしていれば、
     総称関数`coerce-to'を使うこともできます。
          (vector->f64vector '#(3.1 5.4 3.2)) => #f64(3.1 5.4 3.2)

          (use gauche.collection)
          (coerce-to <f64vector> '#(3.1 5.4 3.2)) => #f64(3.1 5.4 3.2)

 -- Function: string->s8vector string &optional start end
 -- Function: string->u8vector string &optional start end
     与えられた文字列の内部表現のバイト列と同じバイト列を持つs8vectorもしくは
     u8vectorを返します。省略可能な範囲引数START、ENDは、
     変換される文字列中の文字位置を指定します。

     これらの手続きは、文字を構成するバイト列をランダムにアクセスしたい場合などに
     有用です。

          (string->u8vector "abc") => #u8(97 98 99)

          ;; 内部コードがEUCの場合
          (string->u8vector "いろは") => #u8(164 164 164 237 164 207)

 -- Function: string->s8vector! target tstart string &optional start end
 -- Function: string->u8vector! target tstart string &optional start end
     TARGET は、それぞれ s8vector あるいは u8vector
     でなければなりません。 TARGET は、変更可能でなければなりません。
     STRING の生バイト表現を TARGET へインデックス TSTART
     からコピーします。

     TARGET を返します。

          (let ((target (make-u8vector 10 0)))
            (string->u8vector! target 3 "abcde"))
           => #u8(0 0 0 97 98 99 100 101 0 0)


 -- Function: s8vector->string vec &optional start end
 -- Function: u8vector->string vec &optional start end
     与えられたs8vectorもしくはu8vector
     VECのバイト列と同じ内部バイト列を
     持つ文字列を作成して返します。省略可能な範囲引数START、ENDは、
     VEC中の変換されるべき範囲をバイト位置で指定します。

     VEC中のバイト列が文字列の内部表現として不正な値を持っていた場合は、
     不完全な文字列が返されます。

 -- Function: string->s32vector string &optional start end
 -- Function: string->u32vector string &optional start end
     与えられた文字列STRINGの各文字の内部コードを値として持つ
     s32vectorもしくはu32vectorを返します。
     省略可能な範囲引数START、ENDは、
     変換される文字列中の文字位置を指定します。

     これらの手続きは、文字列中の文字をランダムにアクセスする場合に便利です。

 -- Function: s32vector->string vec &optional start end
 -- Function: u32vector->string vec &optional start end
     STARTとENDを考えなければ、
     これらの手続きは次のコードのような動作をします：
          (lambda (vec) (map-to <string> integer->char vec)))
     省略可能な範囲引数START、ENDは、
     VEC中の変換されるべき範囲を指定します。

 -- Function: uvector-alias uvector-class vec &optional start end
     この手続きは、クラスがUVECTOR-CLASSであり、
     ユニフォームベクタVECのメモリ領域を共有するような
     新しいユニフォームベクタを作成して返します。
     省略可能な引数STARTとENDが与えられた場合は
     VECの内容のうちそれらのインデックスで指定される範囲のみが使われます。
     メモリ領域が共有されているので、VECに加える変更は
     新しいベクタから見えますし、その逆も可能です。

     クラスUVECTOR-CLASSはユニフォームベクタのクラスでなければなりませんが、
     VECのクラスと一致している必要はありません。
     そのような場合は、新しいベクタはVECと同じメモリ領域の値を
     異なる値と解釈するかもしれません。
     例えば、次のコードはGaucheが走っているマシンが
     リトルエンディアンであるかビッグエンディアンであるかを判定します。

          (let ((u8v (uvector-alias <u8vector> #u32(1))))
            (if (zero? (u8vector-ref u8v 0))
                'big-endian
                'little-endian))

     UVECTOR-CLASSがs8vectorかu8vector以外の場合、
     新しいベクタが指す領域は、そのベクタの要素のアラインメントの要請に
     したがっていなければなりません。
     ユニフォームベクタの開始点は常に全てのユニフォームベクタのアラインメント要請を
     満たします。したがって、例えばu8vectorからu32vectorを作成する場合、
     STARTおよびENDは4の倍数でなければなりません
     (あるいは、START/ENDが省略された場合、VECの長さが
     4の倍数でなければなりません)。
     与えられたパラメータでアラインメントの要請が満たせない場合はエラーが通知されます。


File: gauche-refj.info,  Node: ユニフォームベクタの数値演算,  Next: ユニフォームベクタのブロック入出力,  Prev: ユニフォームベクタの変換,  Up: ユニフォームベクタ

9.25.3 ユニフォームベクタの数値演算
-----------------------------------

 -- Function: TAGvector-add VEC VAL &optional CLAMP
 -- Function: TAGvector-add! VEC VAL &optional CLAMP
 -- Function: TAGvector-sub VEC VAL &optional CLAMP
 -- Function: TAGvector-sub! VEC VAL &optional CLAMP
 -- Function: TAGvector-mul VEC VAL &optional CLAMP
 -- Function: TAGvector-mul! VEC VAL &optional CLAMP
     要素毎の計算手続きです。VECはTAGvectorでなければなりません。
     また、VALはVECと同じ長さのTAGvectorかベクタかリスト、
     あるいは数値(整数ベクタに対しては正確な整数、実数ベクタに対しては実数)
     でなければなりません。

     VALがTAGvectorの場合、
     VECと対応する要素毎に加算、減算、乗算が行われ、
     結果がTAGvectorとして返されます。
     破壊的なバージョン(名前に`!'がついているもの)では、VECが
     結果を格納するために再利用されます。
     演算の結果がTAGvectorの要素の値域外になった場合の動作は
     省略可能な引数CLAMPによって指定されます。
     (f32vectorとf64vectorでは、値域外になった要素にはinfinityが格納され、
     CLAMPの値は無視されます)。

     VALが数値である場合、VECの各要素とその数値の間で演算が行われます。

          (s8vector-add '#s8(1 2 3 4) '#s8(5 6 7 8)) => #s8(6 8 10 12)
          (u8vector-sub '#u8(1 2 3 4) '#u8(2 2 2 2)) => error
          (u8vector-sub '#u8(1 2 3 4) '#u8(2 2 2 2) 'both) => #u8(0 0 1 2)

          (f32vector-mul '#f32(3.0 2.0 1.0) 1.5) => #f32(4.5 3.0 1.5)

 -- Function: TAGvector-div VEC VAL
 -- Function: TAGvector-div! VEC VAL
     要素毎の除算です。これらはf32vectorとf64vectorのみに対して定義されます。
     VALはVECと同じ大きさのTAGvectorかベクタかリスト、
     あるいは実数でなければなりません。

          (f32vector-div '#f32(1.0 2.0 3.0) 2.0) => #f32(0.5 1.0 1.5)

 -- Function: TAGvector-and VEC VAL
 -- Function: TAGvector-and! VEC VAL
 -- Function: TAGvector-ior VEC VAL
 -- Function: TAGvector-ior! VEC VAL
 -- Function: TAGvector-xor VEC VAL
 -- Function: TAGvector-xor! VEC VAL
     要素毎の論理(ビット)演算です。
     これらの手続きは整数ベクタに対してのみ定義されています。
     VALはVECと同じ大きさのTAGvectorかベクタかリスト、
     あるいは正確な整数でなければなりません。VECの各要素と、対応するVALの要素
     (VALが非スカラー値の場合)もしくはVAL自身
     (VALが整数の場合)とのビット毎のand, inclusive orまたはexclusive or
     が計算され、結果がTAGvectorで返されます。
     破壊的なバージョン(名前に`!'がついているもの)では、VECが
     結果を格納するために再利用されます。

 -- Function: TAGvector-dot VEC0 VEC1
     ふたつのTAGvectorの内積を計算します。
     VEC0とVEC1の長さは等しくなければなりません。

 -- Function: TAGvector-range-check VEC MIN MAX
     VECはTAGvectorでなければなりません。
     MINとMAXはそれぞれ、VECと同じ長さのTAGvector、
     ベクタ、リストのいずれかか、実数もしくは`#f'でなければなりません。

     VECの各要素に対して、この手続きはそれが対応するMINVALとMAXVAL
     の間にあるかどうかを検査します。MINVALとMAXVALも範囲に含みます。
     ここで、MINVALとMAXVALは、MIN/MAXが非スカラー値
     であればVECの要素に対応するそれぞれの要素、
     MIN/MAXが数値であればその数値そのものです。
     MINが`#f'の場合、最小値はマイナス無限大と考えられます。
     MAXが`#f'の場合、最大値はプラス無限大と考えられます。

     VECの全ての要素が範囲内であった場合は#Fが返されます。
     そうでなければ、範囲を外れた要素のうちもっとも左のもののVEC内での
     インデックスが返されます。

          (u8vector-range-check '#u8(3 1 0 2) 0 3)  => #f
          (u8vector-range-check '#u8(3 1 0 2) 1 3)  => 2

          (u8vector-range-check '#u8(4 32 64 98) 0 '#u8(10 40 70 90))
            => 3

          ;; Range check in a program
          (cond
           ((u8vector-range-check u8v 1 31)
            => (lambda (i)
                (errorf "~sth vector element is out of range: ~s"
                        i (u8vector-ref u8v i))))
           (else (do-something u8v)))

 -- Function: TAGvector-clamp VEC MIN MAX
 -- Function: TAGvector-clamp! VEC MIN MAX
     VECはTAGvectorでなければなりません。
     MINとMAXはそれぞれ、VECと同じ長さのTAGvector、
     ベクタ、リストのいずれかか、実数もしくは`#f'でなければなりません。

     TAGvector-range-checkと同じように、この手続きはVECの各要素が
     MINおよびMAXで指定される最小値と最大値の間にあるかどうかを
     検査します。要素が最小値より小さかった場合はそれが最小値に置き換えられます。
     要素が最大値より大きかった場合はそれが最大値に置き換えられます。

     TAGvector-clampはVECのコピーを作ってそれに対して
     クランプ操作を行います。TAGvector-clamp!はVECを直接
     変更します。どちらもクランプ操作が行われた後のTAGvectorを返します。

          (s8vector-clamp '#s8(8 14 -3 -22 0) -10 10) => #s8(8 10 -3 -10 0)


File: gauche-refj.info,  Node: ユニフォームベクタのブロック入出力,  Prev: ユニフォームベクタの数値演算,  Up: ユニフォームベクタ

9.25.4 ユニフォームベクタのブロック入出力
-----------------------------------------

ユニフォームベクタは、メモリの固まりを抽象化しているものと考えることも
できます。それなら、それをバイナリI/Oに使えないでしょうか。もちろんできます。

 -- Function: read-block! vec &optional iport start end
     与えられた入力ポートIPORTからデータの固まりを読みだし、それを
     ユニフォームベクタVECに格納します。
     どんな種類のユニフォームベクタでも与えることができます。
     省略可能な引数STARTとENDが与えられた場合は、
     それらがVEC中でデータが格納されるべき領域のインデックスの範囲を
     示します。その範囲外のVECの値は変更されません。
     START、ENDが与えられなかった場合はVEC全体が使われます。
     IPORTが省略された場合はカレント入力ポートが使われます。

     要求された領域を埋め終る前に入力がEOFに達した場合は、ベクタの残りの部分は
     変更されません。

     `read-block!'が呼ばれた時既にIPORTがEOFに達していた場合は
     EOFが、そうでなければ読まれた要素の数 (バイト数ではありません)
     が返されます。

     IPORTがバッファードポートであり、そのバッファリングモードが
     `modest' か `none' であった場合、`read-block!'はIPORTが
     EOFに達していなくても、VECを埋める前に戻ることがあります
     (バッファリングモードについては*Note
     ファイルポート::)を参照して下さい。
     パイプやネットワークに接続されたポートはデフォルトでそのように振舞います。
     もし、十分なデータが到着することがわかっており、VECを確実に埋めたい場合は
     ポートのバッファリングモードを`full'に変更して下さい。

     データはバイトストリームとして読まれるので、
     s8vectorとu8vector以外のユニフォームベクタを与えた場合は
     結果がプラットフォームのエンディアンに影響を受けることに注意して下さい。
     例えば入力が`#x01, #x02, #x03, #x04'というバイトシーケンスだったと
     します。これをu32vectorに読み込んだ場合、最初の要素は
     ビッグエンディアンアーキテクチャでは`#x01020304'になりますが、
     リトルエンディアンアーキテクチャでは`#x04030201'となるでしょう。

 -- Function: write-block vec &optional oport start end
     ユニフォームベクタVECの内容を「そのまま」OPORTに書き出します。
     OPORTが省略された場合はカレント出力ポートが使われます。
     省略可能な引数STARTとENDが与えられた場合は、
     それらのインデックスの範囲が示すVECの内容のみが出力されます。
     この手続きの返す値は未定義です。

     `s8vector'と`u8vector'以外のユニフォームベクタを与えた場合、
     `read-block!'と同じようにエンディアンの影響を受けることに注意して
     下さい。u32vector中の数値`#x01020304'は、
     プラットフォームによってバイトシーケンス`#x01, #x02, #x03, #x04'と
     なるかもしれませんし、`#x04, #x03, #x02,
     #x01'となるかもしれません。


File: gauche-refj.info,  Node: バージョン番号の比較,  Next: 仮想ポート,  Prev: ユニフォームベクタ,  Up: ライブラリモジュール - Gauche拡張モジュール

9.26 `gauche.version' - バージョン番号の比較
============================================

 -- Module: gauche.version
     このモジュールは、バージョン番号(リリース番号)を比較する便利な手続きを提供します。
     ここでのバージョン番号とはソフトウェアのリリースにつけられる
     "`0.5.1'"、"`3.2-3'"、"`8.2pl1'"といった文字列で、
     通常これらの番号間には順序関係が定義できます。 例えば "1.2.3" は
     "1.2" より新しいが "2.1" より古い、といった具合です。
     以下のようにこれらの文字列の順序を比較することができるようになります。

          (version<? "2.2.3" "2.2.11")     => #t
          (version<? "2.3.1" "2.3")        => #f
          (version<? "2.3.1-1" "2.3.1-10") => #t
          (version<? "13a" "5b")           => #f

     バージョン番号の付け方には特に標準というものはありませんが、
     よく使われている方法を採用しました。全ての場合に使えるとはいきませんが、
     大抵の場合はカバーできるのではないかと思います。

     厳密に言えば、分岐などの場合があるのでバージョン番号間の関係は半順序関係にしかなりません。
     このモジュールでは単純な定義を使って、全順序関係があるものとして扱います。

     まず、ここでのバージョン番号は以下の構文に従うものとします。
           <version> : <principal-release>
                     | <version> <post-subrelease>
                     | <version> <pre-subrelease>
           <principal-release> : <relnum>
           <post-subrelease>   : [.-] <relnum>
           <pre-subrelease>    : _ <relnum>
           <relnum>            : [0-9A-Za-z]+

     通常`<relnum>'は数字部分と、それに続く省略可能な拡張部分とからなります。
     例えば "`23a'" は数字部分23と拡張部分"`a'"からなります。
     もし`<relnum>'が数字で始まらない場合、その数字部分は-1であると考えることにします。

     `<relnum>'の順序関係を次のように定義します。
       1. relnum Aとrelnum
          Bが異なる数字部分を持っている場合、拡張部分を無視して
          数字部分を数値として比較します。例："`3b'" < "`4a'"。

       2. relnum Aとrelnum
          Bの数字部分が等しい場合、拡張部分を辞書順に比較します。
          例："`4c'" < "`4d'"、"`5'" < "`5a'"。

     `<relnum>'間の順序が定義できたところで、バージョン番号の順序を次のように定義します。
       1. 各々のバージョン番号を分解して `<principal-release>'
          とそれに続く
          サブリリース部品のリストに入れる。このリストの各要素のことを「リリース部品」
          と呼びます。

       2.
          もし両方のリストの最初のリリース部品が同じなら、それを両方のリストから
          取り除きます。これをリストの先頭が異るまでくりかえします。

       3. そうすると次のような場合に分られます。
            1. 両方のリストが空： バージョンは同じ。

            2. 一方のリスト (A) が空で、他方のリスト (B)
               の先頭がポストサブリリース： A が B より前のバージョン。

            3. 一方のリスト (A) が空で、他方のリスト (B)
               の先頭がプリサブリリース： B が A より前のバージョン

            4. リスト A の先頭がポストサブリリースで、リスト B
               の先頭がプリサブリリース： B が A より前のバージョン

            5.
               両方のリストとも先頭がポストサブリリースであるかプリサブリリース：
               relnum を比較する。

     以下はいくつかの例です。
          "1" < "1.0" < "1.1" < "1.1.1" < "1.1.2" < "1.2" < "1.11"
          "1.2.3" < "1.2.3-1" < "1.2.4"
          "1.2.3" < "1.2.3a" < "1.2.3b"
          "1.2_rc0" < "1.2_rc1" < "1.2" < "1.2-pl1" < "1.2-pl2"
          "1.1-patch112" < "1.2_alpha"

     `<pre-subrelease>' があるのは、「リリース候補」あるいは
     「プリリリース」のバージョンをつかえるようにするためです。

 -- Function: version=? ver1 ver2
 -- Function: version<? ver1 ver2
 -- Function: version<=? ver1 ver2
 -- Function: version>? ver1 ver2
 -- Function: version>=? ver1 ver2
     ふたつのバージョン番号文字列 VER1 と VER2 の順序関係によって
     真偽値を返します。もし引数が、バージョン番号を定義するのに不正な文字列を
     含んでいたばあい、エラーが上ります。

 -- Function: version-compare ver1 ver2
     ふたつのバージョン番号文字列 VER1 と VER2 を比較し、 VER1 のほうが
     VER2 より前、VER1 と VER2 は同じ、 VER1 が VER2
     の後、の3つの場合によって、それぞれ、 -1、0、1 を返します。

 -- Function: relnum-compare rel1 rel2
     これは `version-compare'の下位レベルの手続きです。
     ふたつのリリース番号 (relnum) REL1 と REL2 を比較し、 REL1 が REL2
     より前、REL1 と REL2 が同じ、 REL1 が REL2
     より後、の3つの場合によって、それぞれ、 -1、0、1 を返します。


File: gauche-refj.info,  Node: 仮想ポート,  Prev: バージョン番号の比較,  Up: ライブラリモジュール - Gauche拡張モジュール

9.27 `gauche.vport' - 仮想ポート
================================

 -- Module: gauche.vport
     _仮想ポート_あるいは手続き的ポートとは、その振舞いを Scheme
     でプログラム可能なポートです。

     このモジュールは 2 種類の仮想ポートを提供します。ひとつは、
     完全仮想ポートで、すべての I/O 操作でユーザが提供する手続きが
     呼出されるものです。もうひとつは、仮想バッファポートで、 I/O
     操作は内部バッファ上で行われ、ユーザが提供する手続きは
     バッファを一杯にするかフラッシュする必要がある場合にのみ
     呼出されます。

     このモジュールはさらに、ユニフォームベクタにより
     バックアップされる仮想バッファポートも提供します。
     これは仮想ポートの使用例でもあります。

完全仮想ポート
..............

このタイプの仮想ポートは、`<virtual-input-port>' クラス および
`<virtual-output-port>' クラスで実現されています。
適切なスロットに手続きをセットすることでポートの振舞いをカスタマイズ
可能です。

 -- Class: <virtual-input-port>
     このクラスのインスタンスは入力ポートとして使えます。
     このポートの振舞いはインスタンスのスロットに設定された値に依存します。

     まともな入力ポートとして動かすためには、少くとも、`getb' スロット
     あるいは `getc' スロットのどちらか一方は設定しなければなりません。
     さもなければ、このポートはすべての入力要求に対して EOF を返します。

      -- Instance Variable of <virtual-input-port>: getb
          設定されているのなら、その値は、引数を取らない手続きでなければなりません。
          バイナリ入力の要求のたびに、この手続きが呼ばれます。

          この手続きは、0 から 255
          までの正確な整数を返すか、`#f'あるいは EOF
          オブジェクトを返さなければなりません。整数を返す場合には、
          それがこのポートから読みとられる値となります。それ以外の値を返す
          場合は、このポートは EOF を返します。

          このポートが文字入力を要求され、かつ、`getc'
          手続きを持たない場合、
          このポートはこの手続きを呼び(複数回の可能性もある)文字全体を構築します。

      -- Instance Variable of <virtual-input-port>: getc
          設定されているのなら、その値は、引数を取らない手続きでなければなりません。
          文字入力の要求のたびに、この手続きが呼ばれます。

          この手続きは文字を返すか、または`#f'あるいはEOFオブジェクトを返さなければ
          なりません。文字を返した場合には、それがこのポートから読みとられる値と
          なります。それ以外の値を返す場合は、このポートは EOF
          を返します。

          このポートがバイナリ入力を要求され、かつ、`getb'
          手続きを持たない場合、
          このポートはこの手続きを呼び、文字をバイト列に変換し、それをこのポートから
          読みだされる値として使います。

      -- Instance Variable of <virtual-input-port>: gets
          設定されているなら、その値は、正の正確な整数の引数をひとつだけとる手続き
          でなければなりません。ブロックバイナリ入力、たとえば、
          `read-block'などが要求された場合に、呼出されます。

          そしてそれは文字列、 不完全文字列、 `#f'、 EOF オブジェクトを
          返さなくてはなりません.
          文字列を返す場合は上記正の正確な整数によって
          指定された大きさを越えてはなりません。空文字列、 `#f'、EOF を
          返した場合はポートの終端にたどり着いたものとみなされます。
          (注意:
          文字列大きさは文字数でなく文字列が占めるバイト数で指定されます。)

          この手続きは効率のためにあります。もし、この手続きが用意されて
          いなければ、このポートは、データブロックを準備するのに
          `getb'を
          繰り返し呼びます。場合によっては、ブロック入力を用意するほうが
          はるかに効率的です。(たとえば、メモリチャンクのブロックからの読みだし
          を行なうような場合です。)

          こうした利点を必要としないのなら、このスロットは未設定のままにして
          おいてもかまいません。

      -- Instance Variable of <virtual-input-port>: ready
          設定されているなら、その値は、真偽値をひとつだけとる手続きでなければ
          なりません。この手続きは、このポートに対して、`char-ready?'
          あるいは `byte-ready?'
          が呼ばれたときに呼出されます。設定した手続き
          が返す値が、これらの手続きの結果になります。

          `char-ready?' が呼ばれたのなら、真偽値引数は `#t' です。
          `byte-ready?' が呼ばれたのなら、真偽値引数は `#f' になります。

          未設定なら、`char-ready?' および `byte-ready?' は
          このポートに対して常に、`#t' を返します。

      -- Instance Variable of <virtual-input-port>: close
          設定されているのなら、その値は引数を取らない手続きでなければなりません。
          その手続きはこのポートがクローズされるときに呼びだされ、返り値は
          捨てられます。このポートをクローズするときになんらかのアクションが
          必要でないのなら、未設定にしておけます。

          この手続きはファイナライザから呼ばれることもあり得ます。したがって、
          この手続きは慎重に書く必要があります。後述のファイナライズに
          関する注意を参照してください。

      -- Instance Variable of <virtual-input-port>: seek
          設定されているのなら、その値は、オフセット引数とそれがどこからかを示す引数
          の
          2つの引数をとる手続きでなければなりません。これらの引数の意味は、
          `port-seek' (*Note ポート共通の操作:: 参照) のそれと同じです。
          この手続きは、次の読み出しが新しい位置から始められるように
          内部のリードポインタを調整しなければなりません。そして
          更新されたポインタ(ポート先頭からのバイトオフセット)
          を返さなければなりません。

          未設定なら、このポートに対する `port-seek' および `port-tell'
          の呼び出しは `#f' になります。

          この手続きは単に現在の位置を問合せるために、 `offset' として
          0 を、`whence' として `SEEK_CUR' を与えて
          呼び出すこともあることに注意してください。リードポインタの位置は知って
          いるが、動かすことができないという場合にも、この手続きを提供することが
          できます。上のような問合せには、現在位置を返し、そうでない場合には、
          `#f' を返します。


 -- Class: <virtual-output-port>
     このクラスのインスタンスは出力ポートとして使えます。
     このポートの振舞いはインスタンスのスロットに設定された値に依存します。

     まともな出力ポートとして動かすためには、少くとも、`putb' スロット
     あるいは `putc' スロットのどちらか一方は設定しなければなりません。

      -- Instance Variable of <virtual-output-port>: putb
          設定されているなら、その値は、バイト値(0 から
          255までの正確な整数)を
          ひとつだけ引数としてとる手続きでなければなりません。バイナリ出力
          の要求のたびに、この手続きが呼ばれます。この手続きの返り値は無視
          されます。

          このスロットが未設定の場合、バイナリ出力を要求されると、このポートは
          `<io-unit-error>' エラーを発生させることがあります。

      -- Instance Variable of <virtual-output-port>: putc
          設定されているなら、それは文字をひとつ引数にとる手続きでなければなりません。
          文字出力の要求があるたびにこの手続きがよばれます。この手続きの返り値は
          無視されます。

          このスロットが未設定であっても、`putb'
          スロットが設定されていれば、
          この仮想ポートは文字をバイト列に展開してから、`putb'
          を呼びだします。

      -- Instance Variable of <virtual-output-port>: puts
          設定されていれば、その値は、文字列(不完全なものである可能性もある)を
          ひとつ引数としてとる手続きでなければなりません。この手続きの返り値は
          無視されます。

          これは、効率のためにあります。このスロットが未設定であれば、この
          仮想ポートは、データのかたまりを出力するために、`putb'
          あるいは `putc' を繰り返し呼びます。もし、ひとかたまりの
          出力を効率的に実行可能なコードであれば、この手続きを提供できます。

      -- Instance Variable of <virtual-output-port>: flush
          設定されていれば、その値は引数をとらない手続きでなければなりません。
          ポートのフラッシュを要求されたときに呼ばれます(たとえば、`flush'
          がこのポートに対して呼ばれたとき、あるいは、このポートがクローズ
          されるとき)。

          この手続きは、ポートが何らかのバッファリングをおこなうか、なんらかの
          状態を持つような場合に便利です。ポートが状態をともなう操作を行わない
          のなら、これは未設定にしておけます。

          この手続きはファイナライザから呼ばれることがあります。したがって、
          特別な注意が必要です。後述のファイナライザに関する注意を
          参照してください。


      -- Instance Variable of <virtual-output-port>: close
          `<virtual-input-port>' の `close' スロットと同様です。

      -- Instance Variable of <virtual-output-port>: seek
          `<virtual-input-port>' の `seek' スロットと同様です。


仮想バッファポート
..................

このタイプの仮想ポートは `<buffered-input-port>' クラス および
`<buffered-output-port>' クラスで実現されています。
適切なスロットに手続きを設定するこでポートの振舞いをカスタマイズ
することができます。

   これらのポートは、内部バッファを持っており、そのバッファを満たすか
フラッシュするかの必要があるときにのみ、Scheme の手続きが呼ばれます。
通常、I/O毎に Scheme の手続きを呼ぶよりも遥かに効率がいいものです。
実際の内部バッファリング機構は、GaucheのファイルI/Oポートと同じです。

   これらのポートはバッファとして `u8vector' を使います。詳細は、 *Note
ユニフォームベクタ:: を参照してください。

 -- Class: <buffered-input-port>
     このクラスのインスタンスは、入力ポートとして振舞います。
     これは以下のようなインスタンススロットを持ちます。
     意味のある入力ポートとして使うには少くとも、`fill' スロットを
     設定しなければなりません。

      -- Instance Variable of <buffered-input-port>: fill
          設定されているなら、`u8vector'
          の引数を一つとる手続きでなければ
          なりません。そのベクタの最初からデータを満たさなければなりません。
          要求されたものよりデータの残りが少ない場合には、
          ベクタ全体を満たす必要はありません。しかしながら、
          データが残っている場合には少くとも1バイトは満たさなければなりません。
          もしデータがまだ利用可能になっていなければ、なにがしかのデータが利用可能に
          なるまで待たなければなりません。

          この手続きは実際に満されたバイト数を返さなければなりません。ポートが
          EOFに達したことを示すために、0 または
          EOFオブジェクトを返すこともできます。

      -- Instance Variable of <buffered-input-port>: ready
          設定されているなら、引数をとらない手続きでなければなりません。
          この手続きは、なにがしかの読み込み用データが利用可能になっていれば
          真の値を返し、そうでなければ、`#f'を返します。完全仮想ポートとはちがい、
          バイナリI/Oと文字I/Oを区別する必要はありません。

          このスロットが未定義の場合、このポートは常にデータが利用可能になっている
          とみなされます。

      -- Instance Variable of <buffered-input-port>: close
          設定されていれば、引数をとらない手続きでなければなりません。この手続きは
          仮想バッファポートがクローズされるときに呼出されます。ポートがクローズ
          されるときに、なにがしかのクリーンアップを行うのでなければ、設定する必要
          はありません。

          この手続きは、ファイナライザから呼ばれる可能性がありますので、特別な
          注意が必要です。後述のファイナライズに関する注意書きを参照してください。

      -- Instance Variable of <buffered-input-port>: filenum
          設定されているなら、このポートの使っているファイルディスクリプタ番号(正確な非負整数)
          を返す手続きでなければなりません。この手続きは
          `port-file-number'
          をこのポートに対して呼出したときに呼ばれます。

          そのようなファイルディスクリプタが存在していなければ、 `#f'
          を返すことができます。
          あるいは、このスロットを未設定にしておくこともできます。

      -- Instance Variable of <buffered-input-port>: seek
          設定されているなら、オフセット引数とどこからかを示す引数の2つをとる
          手続きでなければなりません。これは、前述の
          `<virtual-input-port>'のseek 手続きと同じように動作します。

          この手続きはファイナライザから呼ばれる可能性があり、特別な注意が
          必要です。後述のファイナライズに関する注意を参照してください。


 -- Class: <buffered-output-port>
     このクラスのインスタンスは出力ポートして振舞います。これは、以下のような
     インスタンススロットを持ちます。少くとも `flush' は設定しなければ
     なりません。

      -- Instance Variable of <buffered-output-port>: flush
          設定されているなら、`u8vector'のバッファとフラグという2つの
          引数をとる手続きでなければなりません。手続きはバッファ内のデータを
          どこかへ出力しなければならず、実際に出力したバイト数を返します。

          フラグが偽なら、この手続きはバッファ全体よりも少い(ただし、最低でも
          1バイト)の出力を行ってもかまいません。もしフラグが真ならば、この手続きは、
          バッファの内容をすべて出力しなければなりません。

      -- Instance Variable of <buffered-output-port>: close
          `<buffered-input-port>' の `close' スロットと同様です。

      -- Instance Variable of <buffered-output-port>: filenum
          `<buffered-input-port>' の `filenum' スロットと同様です。

      -- Instance Variable of <buffered-output-port>: seek
          `<buffered-input-port>' の `seek' スロットと同様です。


ユニフォームベクタポート
........................

以下の 2つの手続きは、ユニフォームベクタでバックアップされた、
バッファ入/出力ポートを返します。読み込み元のベクタあるいは
書き出し相手のベクタはどのようなユニフォームベクタであってもかまいませんが、
実際の入出力時には`u8vector' にaliasされます (*Note
ユニフォームベクタの変換:: の `uvector-alias' 参照)。

   `pack'/`unpack'(*Note バイナリデータのパック::参照) と一緒に使うと
バイナリのデータ構造をパースしたり、構築したりするのに便利です。
また、仮想ポートの使い方の例でもあります。実装法に興味があれば、
ソースツリーの `gauche/vport.scm'(あるいは `ext/vport/vport.scm')
を読んでください。

 -- Function: open-input-uvector uvector
     与えられたユニフォームベクタ UVECTORの最初からその内容を読む
     入力ポートを返します。読み込み動作が、UVECTORの終端に到達したら
     EOFが返されます。シーク操作も実装されています。

 -- Function: open-output-uvector uvector
     与えられた uvector
     をポートへのデータ出力で満たす出力ポートを返します。
     UVECTORが満杯になれば、それ以上のデータは黙って廃棄されます。
     シーク操作も実装されています。

ファイナライズに関する注意
..........................

クローズされていない仮想ポートがガベージ・コレクションされると、
クローズ手続きが呼ばれます(仮想バッファポートの場合は、
フラッシュ手続きがクローズ手続きの前に呼ばれます)。これは、
そのポートのファイナライザによって行われます。これはガベージ・コレクション
処理の一部ですから(Scheme 手続きそのものはガーベッジ・コレクタの
メインパートの外側で呼ばれているのですが、それでも)特別な注意が必要です。

   * 仮想ポートが参照しているオブジェクトが既にファイナライズされて
     しまっているということがあり得ます。たとえば、仮想ポート X
     は、_流し込み用_のポート Y への唯一の参照を保持しており、それに
     出力するものとします。Xの `flush' 手続きは、その出力を
     Yへ送ります。もし`flush' 手続きがファイナライザから
     呼ばれた場合、Y のファイナライザが既に 呼ばれていて、Y
     がクローズしてしまっていることがあるのです。 従って X の `flush'
     手続きは、Y が既にクローズして
     いるかどうかをチェックする必要があります。

   * いつ、どのスレッドでファイナライザが走るかを知ることはできません。
     それゆえ、仮想ポートの `close' あるいは `flush' などの
     手続きが、グローバルなリソースをロックしたり、アクセスしたりする
     必要のある場合には、デッドロックやアクセスの衝突を回避するために
     特に注意する必要があります。

     単一スレッドのプログラムにおいても、ファイナライザは、Schemeの
     プログラムのいたるところで走る可能性があります。したがって、実質的に
     それは別のスレッドで走っていると考えておくべきです。


File: gauche-refj.info,  Node: ライブラリモジュール - SRFI,  Next: ライブラリモジュール - ユーティリティ,  Prev: ライブラリモジュール - Gauche拡張モジュール,  Up: Top

10 ライブラリモジュール - SRFI
******************************

この章ではSRFIの機能を提供するモジュールをリストします。
一部のSRFIはGaucheのコアに組み込まれており、
この章には挙げられていないことに注意して下さい。
サポートされている全てのSRFIのリストは*Note 標準への準拠::にあります。

* Menu:

* 機能条件式::
* List library::
* And-let*::
* 単一型のベクタ::
* シグネチャとrest引数に互換性のあるlet形式::
* 機能ベースプログラム設定言語::
* レコード型::
* Let-values::
* 文字列ライブラリ::
* 文字集合ライブラリ::
* 時間のデータ型と手続き::
* ランダムビットのソース::
* 地域化::
* args-fold プログラム引数処理::
* Eager comprehensions::
* Requiring extensions::


File: gauche-refj.info,  Node: 機能条件式,  Next: List library,  Prev: ライブラリモジュール - SRFI,  Up: ライブラリモジュール - SRFI

10.1 `srfi-0' - 機能条件式
==========================

 -- Module: srfi-0
     このモジュールは SRFI-0 の `cond-expand' マクロ形式を提供します。
     現在、このモジュールは `cond-expand' を使用したときに、自動的に
     ロードされますので、明示的に `(use srfi-0)'
     を書く必要はありません。 ポータブルなプログラムにするには、'use'
     形式を使わない方が良いでしょう。

 -- Macro: cond-expand (feature-requirement command-or-definition ...)
          ...
     [SRFI-0] Gauche が FEATURE-REQUIREMENT
     をサポートしていれば、このマクロは COMMAND-OR-DEFINITION ...
     を展開します。 異るScheme
     の実装による機能の差異を吸収するのに使えると言えるでしょう。

     FEATURE-REQUIREMNT は以下のような構文でなければなりません。
          FEATURE-REQUIREMENT
            : FEATURE-IDENTIFIER
            | (and FEATURE-REQUIREMENT ...)
            | (or  FEATURE-REQUIREMENT ...)
            | (not FEATURE-REQUIREMENT)

     FEATURE-IDENTIFIER は機能を示すシンボルです。ある機能が Gauche で
     サポートされているなら、それは、FEATURE-REQUIREMENT を満たします。
     より複雑な条件を構成するために、FEATURE-REQUIREMENT
     のブール代数による 組み合わせを用いることが出来ます。

     このマクロは FEATURE-REQUIREMENT を順にテストし、そのひとつが
     満たされたら、対応する COMMAND-OR-DEFINITION ... に展開されます。

     最後の節は、FEATURE-REQUIREMENT ではなく、`else' で始めることも
     できます。これ以前に満たされた条件がない場合には、このマクロは
     else 節の COMMAND-OR-DEFINITION に展開されます。もし、else
     節がなく、 満たされる条件節がひとつもなければ、エラーが発生します。

     現時点の Gauche では、サポートされている SRFI の機能は、srfi 名
     (たとえば、`srfi-1')で識別されます(サポートされている SRFI に
     ついては *Note 標準への準拠:: を参照してください)。 また、シンボル
     `gauche' も FEATURE-IDENTIFIER として認識されます。

     srfi-13
     (文字列ライブラリ)を必要とするプログラムを書いているとしましょう。
     Gauche では、標準的には、以下のようにします。

          (use srfi-13)

          ;; ... あなたのプログラム ...

     しかし、この 'use' マクロは Gauche 専用で、他の Scheme の実装では
     動作しません。代りに以下のように書くことができます。

          (cond-expand
            (srfi-13
              ;; ... あなたのプログラム ...
            ))

     その実装が `srfi-13' をサポートしていれば、この形式は「あなたの
     プログラム」に展開されます。Gauche では、この場合に 内部で`(use
     srfi-13)'を呼び出します。

     上記のフォームは実装がsrfi-13をサポートしていなければエラーとなります。
     そのような実装の上でもプログラムを走らせたい時は、
     代替となるライブラリ定義を提供すると良いでしょう。

          (cond-expand
           (srfi-13
             ;; ... あなたのプログラム ...
           )
           (else
             (load "my-srfi-13-implementation")
             ;; ... あなたのプログラム ...
           ))


File: gauche-refj.info,  Node: List library,  Next: And-let*,  Prev: 機能条件式,  Up: ライブラリモジュール - SRFI

10.2 `srfi-1' - List library
============================

 -- Module: srfi-1
     SRFI-1 は、リスト操作ライブラリの豊富なコレクションです (*Note
     [SRFI-1]: srfi-1.)。 このライブラリを使うには、`(use srfi-1)'
     として下さい。 Olin
     Shivers氏のリファレンス実装に基づいて実装されています。
     必要に応じてオートロードされるいくつかのサブファイルに分割して
     あります。

* Menu:

* SRFI-1 リスト構築子::
* SRFI-1 リストの述語::
* SRFI-1 リスト選択子::
* 種々のリスト処理ルーチン::
* リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map)::
* リストのフィルタおよび分割::
* リストの探索::
* リストの削除::
* 連想リスト::
* 集合としてのリスト::


File: gauche-refj.info,  Node: SRFI-1 リスト構築子,  Next: SRFI-1 リストの述語,  Prev: List library,  Up: List library

10.2.1 リストの構築子
---------------------

 -- Function: xcons cd ca
     [SRFI-1] `(cons ca cd)' と同等です。高階手続きへ渡すのに便利です。

 -- Function: cons* elt1 elt2 ...
     [SRFI-1] `list' と似ていますが、最後の引数が構築されたリストの
     末尾になります。Gauche の組み込み手続き `list*' と同意です。
          (cons* 1 2 3 4) => (1 2 3 . 4)
          (cons* 1) => 1

 -- Function: list-tabulate n init-proc
     [SRFI-1] N個の要素をもつリストを構築し、それぞれの要素を
     `(INIT-PROC i)' で生成します。
          (list-tabulate 4 values) => (0 1 2 3)

 -- Function: circular-list elt1 elt2 ...
     [SRFI-1] 指定した要素をもつ循環リストを構築します。
          (circular-list 'z 'q) => (z q z q z q ...)

 -- Function: iota count &optional (start 0) (step 1)
     [SRFI-1] STARTから始まり、STEPずつ増加する、 COUNT
     個の要素からなる数値のリストを返します。
          (iota 5) => (0 1 2 3 4)
          (iota 5 0 -0.1) => (0 -0.1 -0.2 -0.3 -0.4)


File: gauche-refj.info,  Node: SRFI-1 リストの述語,  Next: SRFI-1 リスト選択子,  Prev: SRFI-1 リスト構築子,  Up: List library

10.2.2 リストの述語
-------------------

 -- Function: proper-list? x
     [SRFI-1] X が真性リストであれば `#t' を返します。

 -- Function: circular-list? x
     [SRFI-1] X が循環リストであれば `#t' を返します。

 -- Function: dotted-list? x
     [SRFI-1] X が有限の大きさで、空リストで終端していないリストなら
     `#t' を返します。これには、ペアではなく、空リストもない値(たとえば
     シンボルや数値)のような長さ0のドットリストと考えられるものを含みます。

 -- Function: null-list? list
     [SRFI-1] LIST が空リスト `()' なら `#t' を返します。
     それ以外のときは #F を返します。

 -- Function: not-pair? x
     [SRFI-1] `(lambda (x) (not (pair? x)))'と同じです。

     SRFI-1
     では、「真性リストおよびドットリストの両方で、すべての有限リストを
     扱う手続き用の終端条件として便利なように用意した」とあります。

 -- Function: list= elt= list ...
     [SRFI-1] ELT= を用いて、n番目の要素をそれぞれ比較することで、
     与えられたリストの同値性を決定します。

     `list=' を真性リスト以外に適用するとエラーになります。

     同値性判定の手続きは `eq?' と整合性がなければなりません。すなわち
          (eq? x y) => (elt= x y).


File: gauche-refj.info,  Node: SRFI-1 リスト選択子,  Next: 種々のリスト処理ルーチン,  Prev: SRFI-1 リストの述語,  Up: List library

10.2.3 リスト選択子
-------------------

 -- Function: first pair
 -- Function: second pair
 -- Function: third pair
 -- Function: fourth pair
 -- Function: fifth pair
 -- Function: sixth pair
 -- Function: seventh pair
 -- Function: eighth pair
 -- Function: ninth pair
 -- Function: tenth pair
     [SRFI-1] リスト(非真性でも可)のn番目の要素を返します。

 -- Function: car+cdr pair
     [SRFI-1] `(car pair)' および `(cdr pair)' の二つの値を返します。

 -- Function: take x i
 -- Function: drop x i
     [SRFI-1] `take' はリスト X の最初のi個の要素を返します。 `drop'
     はリスト X の最初のi個の要素を除いたリストを返します。
          (take '(a b c d e)  2) => (a b)
          (drop '(a b c d e)  2) => (c d e)
     X はあらゆる値をとりえます。
          (take '(1 2 3 . d) 2) => (1 2)
          (drop '(1 2 3 . d) 2) => (3 . d)
          (drop '(1 2 3 . d) 3) => d
     `drop' は X に I 回 cdr 操作をおこなうのと全く
     同じです。返される値は、X と共通の末尾を共有します。一方、 take
     は、引数のリストが長さ0でないリストなら必ず新しいリストの
     領域を確保します。

     I がリスト X の終端を超えたらエラーが発生します。
     より寛容なバージョンの `take' と `drop' については、 *Note
     その他のリストライブラリ:: を参照してください。

     あらゆる並びからの部分並びを抽出する汎用的な方法に関しては、 *Note
     シーケンスのスライス:: にある `subseq' を参照してください。

 -- Function: take-right flist i
 -- Function: drop-right flist i
     [SRFI-1] `take-right' は FLIST の最後の I個の要素
     からなるリストを返します。 `drop-right' は FLIST の最後の
     I個の要素を 除いたリスト返します。
          (take-right '(a b c d e) 2) => (d e)
          (drop-right '(a b c d e) 2) => (a b c)
     FLIST は有限リストであればOKです。
          (take-right '(1 2 3 . d) 2) => (2 3 . d)
          (drop-right '(1 2 3 . d) 2) => (1)
          (take-right '(1 2 3 . d) 0) => d
          (drop-right '(1 2 3 . d) 0) => (1 2 3)
     `take-right' の返す値はいつでも FIRST の共通の末尾を共有します。
     `drop-right' は、引数が長さが0でないリストなら、必ず新しいリストの
     領域を確保します。

     I がリスト FLIST の長さより大きければエラーが発生します。
     より寛容なバージョンの `take-right' と `drop-right' については、
     *Note その他のリストライブラリ:: を参照してください。

 -- Function: take! x i
 -- Function: drop-right! x i
     [SRFI-1] TAKE および DROP-RIGHT の
     その場で更新されるバージョンです。これらの 手続きは X
     を破壊的に変更するかもしれません。

     X が循環リストなら、`take!' は期待されるものより短いリストを返す
     可能性があります。

 -- Function: split-at x i
 -- Function: split-at! x i
     [SRFI-1] `split-at' はリスト X をインデックス I の
     位置で分割し、最初の I 個の要素からなるリストと、残りの末尾とを
     返します。
          (split-at '(a b c d e) 2) => (a b) (c d e)
     `split-at!' はその場で更新されるバージョンです。 これは X
     を破壊的に更新するかもしれません。

 -- Function: last pair
     [SRFI-1] 空ではない有限リスト PAIR の最後の要素を返します。
     これは、`(car (last-pair pair))' と同等です。

     註: `last-pair' は Gauche の組み込み手続きです。


File: gauche-refj.info,  Node: 種々のリスト処理ルーチン,  Next: リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map),  Prev: SRFI-1 リスト選択子,  Up: List library

10.2.4 種々のリスト処理ルーチン
-------------------------------

 -- Function: length+ x
     EN [SRFI-1] If X is a proper list, returns its length.  Otherwise,
     returns `#f'.  [SRFI-1] X
     が真性リストなら、その長さを返します。さもなければ、 `#f'
     を返します。

 -- Function: concatenate list-of-lists
 -- Function: concatenate! list-of-lists!
     [SRFI-1] それぞれ、`(apply append LIST-OF-LISTS)' および `(apply
     append! LIST-OF-LISTS)' と同等です。

 -- Function: append-reverse rev-head tail
 -- Function: append-reverse! rev-head tail
     [SRFI-1] `append-reverse' は `(append (reverse rev-head) tail)' を
     返します。`append-reverse!' はその場で更新されるバージョンです。

 -- Function: zip clist1 clist2 ...
     [SRFI-1] `(map list clist1 clist2 ...)' と同等です。 N
     本のリストが `zip' に渡された場合には、そのなかで一番短いものと
     同じ長さのリストを返します。返されたリストは、要素が N
     要素のリストで、
     そのそれぞれが、引数として渡ってリストの対応する要素になっています。
          (zip '(one two three)
               '(1 2 3)
               '(odd even odd even odd even odd even))
               => ((one 1 odd) (two 2 even) (three 3 odd))

          (zip '(1 2 3)) => ((1) (2) (3))
     引数のリストのうち、少くともひとつは有限のリストでなければなりません。
          (zip '(3 1 4 1) (circular-list #f #t))
               => ((3 #f) (1 #t) (4 #f) (1 #t))

 -- Function: unzip1 list
 -- Function: unzip2 list
 -- Function: unzip3 list
 -- Function: unzip4 list
 -- Function: unzip5 list
     [SRFI-1] `unzip1' はリストのリストを引数としてとります。それぞれの
     リストは少くとも一つの要素を含むものでなくてはなりません。結果として
     それぞれのリストの最初の要素のリストを返します。 `unzip2'
     はリストのリストを引数としてとります。それぞれのリストは
     少くとも二つの要素を含むものでなくてはなりません。結果として二つの値を
     返します。最初の要素のリストと二番目の要素のリストです。`unzip3' は
     3番目までの要素について同様です。以下も同様です。
          (unzip2 '((1 one) (2 two) (3 three))) =>
             (1 2 3) and
             (one two three)

 -- Function: count pred clist1 clist2 ...
     [SRFI-1] N をゼロから与えられたリストのうち最も短いリストの
     長さまでとして、PRED 手続きを与えられたリストの N 番目の要素に
     それぞれ適用します。 PRED が真を返した数が返ります。
          (count even? '(3 1 4 1 5 9 2 5 6)) => 3
          (count < '(1 2 4 8) '(2 4 6 8 10 12 14 16)) => 3
     引数で与えられるリストの少くともひとつは有限でなければなりません。
          (count < '(3 1 4 1) (circular-list 1 10)) => 2

 -- Function: count$ pred
     `count' の部分適用バージョンです。
          ((count$ pred) arg ...) === (count pred arg ...)


File: gauche-refj.info,  Node: リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map),  Next: リストのフィルタおよび分割,  Prev: 種々のリスト処理ルーチン,  Up: List library

10.2.5 リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map)
------------------------------------------------------------------

 -- Function: fold kons knil clist1 clist2 ...
     [SRFI-1] 基本リスト反復演算子です。単一のリスト CLIST1 = (E1 E2
     ... EN) を与えられたときには、以下を返します。
          (KONS EN ... (KONS E2 (KONS E1 KNIL)) ... )

     N 本のリストが与えられた場合には、KONS 関数は N+1 個の引数
     をとる関数でなければなりません。それぞれのリストから要素をひとつずつと、
     初期値 KNIL である「種」あるいは畳み込み状態とよばれものです。
     この畳み込み演算は、もっとも短いリストの要素がなくなったところで終了します。
     与えられるリストの少くともひとつは有限でなければなりません。

     例:
          (fold + 0 '(3 1 4 1 5 9)) => 23 ;sum up the elements
          (fold cons '() '(a b c d e)) => (e d c b a) ;reverse
          (fold cons* '() '(a b c) '(1 2 3 4 5))
              => (c 3 b 2 a 1) ;n-ary case

 -- Function: fold-right kons knil clist1 clist2 ...
     [SRFI-1] 基本リスト再帰演算子です。単一のリスト CLIST1 = (E1 E2
     ... EN) を与えられたときには、以下を返します。
          (KONS E1 (KONS E2 ... (KONS EN KNIL)))

     N 本のリストが与えられた場合には、KONS 関数は N+1 個の引数
     をとる関数でなければなりません。それぞれのリストから要素をひとつずつと、
     初期値 KNIL である「種」あるいは畳み込み状態とよばれものです。
     この畳み込み演算は、もっとも短いリストの要素がなくなったところで終了します。
     与えられるリストの少くともひとつは有限でなければなりません。

     例:
          (fold-right cons '() '(a b c d e))
             => (a b c d e) ;copy list
          (fold-right cons* '() '(a b c) '(1 2 3 4 5))
             => (a 1 b 2 c 3) ;n-ary case

 -- Function: pair-fold kons knil clist1 clist2 ...
 -- Function: pair-fold-right kons knil clist1 clist2 ...
     [SRFI-1] `fold' および `fold-right' と同様ですが、KONS 手続き
     は与えられた CLIST の `car' ではなく、`cdr' をとります。

 -- Function: reduce f ridentity list
 -- Function: reduce-right f ridentity list
     [SRFI-1] `fold' および `fold-right' の変形バージョンです。 F
     は二項演算子でなければなりません。 また、RIDENTITY は F
     の入力として許される あらゆる値 X
     について以下を満していなければなりません。
           (f x ridentity) == x

     これらの関数は実質的に `fold' や `fold-right' と同じことを
     行いますが、RIDENTITYには上記の性質があるため、
     FはRIDENTITYには適用されません。
     RIDENTITYが使われるのはLISTが空の場合だけです。

 -- Function: unfold p f g seed &optional tail-gen
     [SRFI-1] 基本リスト再帰構築子です。
     以下のように再帰的に定義されています。

          (unfold p f g seed tail-gen) ==
             (if (p seed)
                 (tail-gen seed)
                 (cons (f seed)
                       (unfold p f g (g seed))))
     ここでは、P は終了位置の判定、G は現在の「種」から次の「種」
     を生成するのに用い、F はそれぞれの「種」をリストの要素に変換する
     のに用いられます。

 -- Function: unfold-right p f g seed &optional tail
     [SRFI-1] 基本リスト反復構築子です。
     以下のように再帰的に定義されています。

          (unfold-right p f g seed tail) ==
            (let lp ((seed seed) (lis tail))
              (if (p seed)
                  lis
                  (lp (g seed) (cons (f seed) lis))))

 -- Function: append-map f clist1 clist2 ...
 -- Function: append-map! f clist1 clist2 ...
     [SRFI-1] 以下と同等です。

            (apply append (map F CLIST1 CLIST2 ...))
            (apply append! (map F CLIST1 CLIST2 ...))
     引数のリストのうち少くともひとつは有限でなければなりません。

 -- Function: map! f clist1 clist2 ...
     [SRFI-1] 手続き F は CLIST1 の各要素と CLIST2 の対応する要素
     に適用され、結果なひとつのリストに集められます。CLIST1 のセルは
     結果のリストを構築するのに再利用されます。

 -- Function: map-in-order f clist1 clist2 ...
     [SRFI-1] `map' の変形バージョンですが、F の適用順序が、引数として
     与えられたリストの要素の左から右への順であることを保証します。
     Gauche では `map' の実装はこの順になっているので、`map' と
     同意です。

 -- Function: pair-for-each f clist1 clist2 ...
     `for-each' と似ていますが、手続き F は各リスト CLIST の `cdr'
     に適用されます。

 -- Function: filter-map f clist1 clist2 ...
     `map' と似ていますが、真になる場合の値のみが保存されます。
     引数として与えられるリストの少くともひとつは有限でなければなりません。
          (filter-map (lambda (x) (and (number? x) (* x x)))
                      '(a 1 b 3 c 7))
            => (1 9 49)

 -- Function: fold$ kons &optional knil
 -- Function: fold-right$ kons &optional knil
 -- Function: reduce$ f &optional ridentity
 -- Function: reduce-right$ f &optional ridentity
     それぞれ、`fold'、`fold-right'、`reduce'、 `reduce-right'
     の部分適用バージョンです。


File: gauche-refj.info,  Node: リストのフィルタおよび分割,  Next: リストの探索,  Prev: リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map),  Up: List library

10.2.6 リストのフィルタおよび分割
---------------------------------

 -- Function: filter pred list
 -- Function: filter! pred list
     [SRFI-1] 手続き PRED が LIST の各要素に適用され、 PRED
     が真を返す要素のリストが返されます。
          (filter odd? '(3 1 4 5 9 2 6)) => (3 1 5 9)
     `filter!' はその場で更新されるバージョンです。結果を生成するために
     LIST を破壊的に変更するかもしれません。

 -- Function: remove pred list
 -- Function: remove! pred list
     [SRFI-1] 手続き PRED が LIST の各要素に適用され、 PRED
     が偽を返す要素のリストが返されます。
          (remove odd? '(3 1 4 5 9 2 6)) => (4 2 6)
     `remove!' はその場で更新されるバージョンです。結果を生成するために
     LIST を破壊的に更新するかもしれません。

 -- Function: partition pred list
 -- Function: partition! pred list
     [SRFI-1] `filter' と `remove' は同時に、すなわち2つのリストを
     返しますが、一つ目は PRED により LIST の要素をフィルタリング
     した結果で、二つ目は PRED により LIST の要素を削除した結果 です。
          (partition odd? '(3 1 4 5 9 2 6))
            => (3 1 5 9) (4 2 6)
     `partition!'
     はその場で更新されるバージョンです。結果を生成するために LIST
     を破壊的に更新するかもしれません。

 -- Function: filter$ pred
 -- Function: remove$ pred
 -- Function: partition$ pred
     `filter'、`remove'、`partition'の部分的に適用するバージョンです。


File: gauche-refj.info,  Node: リストの探索,  Next: リストの削除,  Prev: リストのフィルタおよび分割,  Up: List library

10.2.7 リストの探索
-------------------

 -- Function: find pred clist
     [SRFI-1] CLIST の各要素に対して左から右に PRED を適用し、 PRED
     が真を返す最初の要素を返します。

 -- Function: find-tail pred clist
     [SRFI-1] CLIST の各要素に対して左から右に PRED を適用し、PRED が
     真を返す場合、その car がその要素であるペアを返します。

 -- Function: take-while pred clist
 -- Function: take-while! pred list
     [SRFI-1] CLIST の最初から、PRED
     を満足する限りの最長部分要素を返します。

 -- Function: drop-while pred clist
     [SRFI-1] CLIST の最初から、PRED
     を満足する限りの最長部分要素を削除し、 残りを返します。

 -- Function: span pred clist
 -- Function: span! pred list
 -- Function: break pred clist
 -- Function: break! pred list
     [SRFI-1] `span' は `(values (take-while pred clist) (drop-while
     pred clist))' と等価です。`break' は PRED の意味を反転します。

 -- Function: any pred clist1 clist2 ...
     [SRFI-1] CLIST の各要素に PRED を適用し、PREDが偽でない
     値を返したら直ちにその値を返します。
     PREDが偽でない値を返す前にリストの要素を使いきってしまったら
     `#f'が返ります。

 -- Function: every pred clist1 clist2 ...
     [SRFI-1] CLIST の各要素に PRED を順に適用し、PREDが
     偽を返した場合、直ちに偽を返します。全てのPREDの適用が
     偽でない値を返した場合は、最後に返された値が返されます。

 -- Function: list-index pred clist1 clist2 ...
     [SRFI-1] PRED を満足する最も左の要素のインデックスを返します。

 -- Function: member$ item
 -- Function: find$ pred
 -- Function: find-tail$ pred
 -- Function: any$ pred
 -- Function: every$ pred
     `member'、`find'、`find-tail'、`any'、`every'の部分的適用
     バージョンです。


File: gauche-refj.info,  Node: リストの削除,  Next: 連想リスト,  Prev: リストの探索,  Up: List library

10.2.8 リストの削除
-------------------

 -- Function: delete x list &optional elt=
 -- Function: delete! x list &optional elt=
     [SRFI-1] 以下と同等です。
            (remove (lambda (y) (elt= x y)) list)
            (remove! (lambda (y) (elt= x y)) list)
     比較手続き ELT= はデフォルトでは `equal?' です。

 -- Function: delete$ x
     `delete' の部分適用バージョンです。

 -- Function: delete-duplicates list &optional elt=
 -- Function: delete-duplicates! list &optional elt=
     [SRFI-1] LIST から重複した要素を取り除きます。LIST 中に等しい要素が
     複数ある場合、一番左がわにある最初のものだけが残ります。これらの
     生き残った要素間の順番は最初のリストの順番が保存されます。
     比較手続き ELT= のデフォルト値は、`equal?' です。


File: gauche-refj.info,  Node: 連想リスト,  Next: 集合としてのリスト,  Prev: リストの削除,  Up: List library

10.2.9 連想リスト
-----------------

 -- Function: alist-cons key datum alist
     [SRFI-1] `(cons (cons KEY DATUM) ALIST)' を返します。
     これは、Gauche の組み込み手続き `acon' の別名です。

 -- Function: alist-copy alist
     [SRFI-1] ALIST の新しい複製を返します。ALIST の背骨の部分、
     およびキーと値を指す各セルは複製されます。
          (define a (list (cons 'a 'b) (cons 'c 'd)))
          a => ((a . b) (c . d))

          (definea b (alist-copy a))
          b => ((a . b) (c . d))

          (set-cdr! (car a) 'z)
          a => ((a . z) (c . d))
          b => ((a . b) (c . d))

 -- Function: alist-delete key alist &optional =
 -- Function: alist-delete! key alist &optional =
     [SRFI-1] ALIST から KEYと同じキーをもつすべてのセルを削除します。
     比較は = で行います。これのデフォルト値は `eqv?' です。

     その場で更新を行うバージョン `alist-delete!' は元の ALIST
     を変更してしまうことがあります。

 -- Function: assoc$ item
     `assoc' の部分適用バージョンです。


File: gauche-refj.info,  Node: 集合としてのリスト,  Prev: 連想リスト,  Up: List library

10.2.10 集合としてのリスト
--------------------------

これらの手続きはリストを集合としてあつかいます。すなわち、どのような
要素があるかは重要ですが、その順序は重要ではありません。

   この範疇にあるすべての手続きは、比較手続き ELT= を最初の引数として
とります。この比較手続きは与えられた二つの集合の要素が等しいかどうかを
判定します。

   集合の要素の組み合せについては *Note 組み合わせ::
も参照してください。

 -- Function: lset<= elt= list1 ...
     [SRFI-1] LIST1 のすべての要素が LIST2 (以降の集合)に含まれている
     ときに限り `#t' を返します。リストが与えられなかった場合
     および一つだけしか与えられなかった場合には、`#t' を返します。

 -- Function: lset= elt= list1 list2 ...
     [SRFI-1] LIST1 のすべての要素が LIST2 に含まれており、かつ、 LIST2
     のすべての要素が LIST1 に含まれていれば、`#t' を返します。

          (lset= eq? '(b e a) '(a e b) '(e e b a)) => #t

 -- Function: lset-adjoin elt= list elt ...
     [SRFI-1] ELT ... を集合 LIST にまだなければ、追加します。
     (順序はとくに決っていません。)

          (lset-adjoin eq? '(a b c) 'a 'e) => '(e a b c)

 -- Function: lset-union elt= list1 ...
     [SRFI-1] LIST1 ... の和集合を返します。

 -- Function: lset-intersection elt= list1 list2 ...
     [SRFI-1] すべての LIST に含まれる要素の集合を返します。

 -- Function: lset-difference elt= list1 list2 ...
     [SRFI-1] LIST1 には含まれていて、LIST2
     には含まれていない要素の集合を 返します。引数が n
     個与えれらた場合には、差分をとる二項演算が 畳み込まれます。

 -- Function: lset-xor elt= list1 ...
     [SRFI-1] 与えられた集合の排他的論理和を返します。すなわち、LIST1
     および LIST2 のどちらか一方にのみ属する要素からなる集合を返します。
     引数が n 個の場合には、xor の二項演算が畳み込まれます。

 -- Function: lset-diff+intersection elt= list1 list2 ...
     [SRFI-1] 与えられた集合の差集合と積集合のふたつの集合を返します。

 -- Function: lset-union! elt= list ...
 -- Function: lset-intersection! elt= list1 list2 ...
 -- Function: lset-difference! elt= list1 list2 ...
 -- Function: lset-xor! elt= list1 ...
 -- Function: lset-diff+intersection! elt= list1 list2 ...
     [SRFI-1] それぞれ対応する手続きのその場で更新するバージョンです。
     最初の引数のリストのセルが結果を構築するのに再利用されるかもしれません。


File: gauche-refj.info,  Node: And-let*,  Next: 単一型のベクタ,  Prev: List library,  Up: ライブラリモジュール - SRFI

10.3 `srfi-2' - And-let*
========================

 -- Module: srfi-2
     SRFI-2の`and-let*'マクロを提供します。

 -- Macro: and-let* (binding ...) body ...
     [SRFI-2] 簡単に言うと、このフォームは`let*'のように動作しますが、
     BINDINGS中の式が`#f'に評価されたらそこで評価を打ち切り
     `#f'を返します。

     各BINDINGは以下のいずれかの形式でなければなりません。
    (VARIABLE EXPRESSION)
          EXPRESSIONが評価されます。それが真の値を返したら、その値がVARIABLE
          に束縛され、次のBINDINGへと進みます。もうBINDINGが無ければ
          BODY ...が評価されます。もしEXPRESSIONが`#f'を返したら、
          評価を打ち切り、`and-let*'から`#f'を返します。

    (EXPRESSION)
          この形式ではVARIABLEが省略されています。EXPRESSIONが評価され、
          その結果は評価を続行するか打ち切るかを判断するためにのみ使われます。

     いくつか例を挙げます。次のコードは連想リストALISTからKEYを
     探し、見つかったらその値を返します。
          (and-let* ((entry (assoc key alist))) (cdr entry))

     もしARGが正確な整数の文字列表現だった場合はNUMを返し、そうでなければ
     0を返します：
          (or (and-let* ((num (string->number arg))
                         ((exact? num))
                         ((integer? num)))
                num)
              0)

     以下のコードはとあるサーバーのポート番号をいくつかの可能性
     (環境変数、設定ファイル…)の中から探す仮想的なコードです。
          (or (and-let* ((val (sys-getenv "SERVER_PORT")))
                (string->number val))
              (and-let* ((portfile (expand-path "~/.server_port"))
                         ((file-exists? portfile))
                         (val (call-with-input-string portfile port->string)))
                (string->number val))
              8080) ; default



File: gauche-refj.info,  Node: 単一型のベクタ,  Next: シグネチャとrest引数に互換性のあるlet形式,  Prev: And-let*,  Up: ライブラリモジュール - SRFI

10.4 `srfi-4' - 単一型のベクタ
==============================

 -- Module: srfi-4
     SRFI-4は、`gauche.uvector'モジュールとして実装されています。 *Note
     ユニフォームベクタ::参照。
     このモジュールは後方互換性のために単に`gauche.uvector'を継承しています。


File: gauche-refj.info,  Node: シグネチャとrest引数に互換性のあるlet形式,  Next: 機能ベースプログラム設定言語,  Prev: 単一型のベクタ,  Up: ライブラリモジュール - SRFI

10.5 `srfi-5' - シグネチャとrest引数に互換性のあるlet形式
=========================================================

 -- Module: srfi-5
     このモジュールは SRFI-5 の拡張 `let' 構文を提供します。

 -- Macro: let ((var val) ... [. (rest val ...)]) body ...
 -- Macro: let name ((var val) ... [. (rest val ...)]) body ...
 -- Macro: let (name (var val) ... [. (rest val ...)]) body ...
     [SRFI-5] `let' 構文は 2通りの拡張がされています。

        * 拡張 `let' 構文は、NAME 束縛リスト中で(名前付き let 構文用の)
          識別子を許します(上の3つめの構文)。

        * 拡張 `let' 構文は、`lambda' 構文の rest パラメータと同様の
          働きをする rest パラメータ束縛を許します。

     この拡張に関する理論的根拠については SRFI-5
     のドキュメントを参照してください。


File: gauche-refj.info,  Node: 機能ベースプログラム設定言語,  Next: レコード型,  Prev: シグネチャとrest引数に互換性のあるlet形式,  Up: ライブラリモジュール - SRFI

10.6 `srfi-7' - 機能ベースプログラム設定言語
============================================

 -- Module: srfi-7
     このモジュールは、SRFI-7 で定義されている
     プログラム設定メタ言語(`program' フォーム)を提供します。

     Gauche は srfi-7 モジュールを autoload しますので、`(use srfi-7)'
     と 明示的に書く必要はありません。

     `program' フォームは Scheme
     の式である必要がないことに注意してください。 SRFI-7 では、この
     `program'フォームを処理して Scheme プログラムを
     生成してから、それを別の方法で実行するような実装を許しています。

     Gauche `program' フォームをマクロとして実装しています。それゆえ、
     そのフォームを直接、評価することができます。とはいえ、`program'
     フォームと他のフォームを一つのファイル中で混在させたり、`program'
     フォームの返り値を期待するのは、よいことではありません。

     `program'フォームの典型的な使い方は、`program' フォームのみを
     含む単一のファイルを用意することです。(`program'フォーム中で
     `files' 節(後述)を用いて他のファイルをロードするとが可能です。)
     このようなプログラムファイルを Gauche で実行するには、単にそれを
     ロードするだけです。

 -- Configuration Language: program program-clause program-clause2 ...
     [SRFI-7] これは Scheme
     プログラムを構成する設定言語で、機能の利用可能性に基づいて います。

     Scheme のプログラムは、この `program'フォームから構築されます。
     Gauche は構築された Scheme のプログラムをそのまま実行します。

     各 PROGRAM-CLAUSE は以下の "Program Clause" のどれか一つである
     必要があります。

 -- Program Clause: requires feature-id feature-id2 ...
     [SRFI-7] FEATURE-ID は `srfi-0' のものと同じです (*Note
     機能条件式::)。 あとに続くコードが FEATURE-ID
     を必要とすることを教えます。

     Gauche ではサポートされていない feature-id が与えられた場合には、
     エラーシグナルが発生します。

 -- Program Clause: files filename ...
     [SRFI-7] プログラムに FILENAMEの内容を挿入します。Gauche では
     単に、現在のモジュール中への FILENAME のロードをひきおこします。

 -- Program Clause: code scheme-expression ...
     [SRFI-7] SCHEME-EXPRESSION がプログラムに挿入されます。

 -- Program Clause: feature-cond clause clause2 ...
     [SRFI-7] CLAUSE は以下のようなフォームです。
          (REQUIREMENT PROGRAM-CLAUSE PROGRAM-CLAUSE2 ...)

     ここでは、REQUIREMENT
     は以下のもののどれかひとつでなければなりません。
        * FEATURE-ID

        * `(and REQUIREMENT ...)'

        * `(or REQUIREMENT ...)'

        * `(not REQUIREMENT)'

     最後の CLAUSE の REQUIREMENT は `else' になるでしょう。

     Gauche はそれぞれの REQUIREMENT をひとつずつチェックし、 満された
     REQUIREMENT が見つかると、そのCLAUSE中の PROGRAM-CLAUSE
     をプログラムに挿入します。


File: gauche-refj.info,  Node: レコード型,  Next: Let-values,  Prev: 機能ベースプログラム設定言語,  Up: ライブラリモジュール - SRFI

10.7 `srfi-9' - レコード型
==========================

 -- Module: srfi-9
     このモジュールはレコード型を使うマクロを含んでいます。レコード型は
     Gauche のオブジェクトシステム上で実装されています。

     SRFI-9
     のレコード型はオブジェクトシステムほどには強力ではありませんが、
     ポータブルなプログラムを書くときには役に立ちます。

     ちなみに、レコード型に対するSCMコンパチブルな
     手続き的APIを提供する*Note
     SLIB-互換のレコード型::モジュールもあります。

 -- Macro: define-record-type name (constructor init-tag ...) predicate
          (field accessor [modifier]) ...
     レコード型を作成し、それを NAME に束縛します。Gauche では、
     レコード型は `<record>' のサブクラスです。

     CONSTRUCTOR はそのレコード型のインスタンスを作成する手続きに
     束縛されており、INIT-TAG ... として多くの引数をとります。
     それぞれの INIT-TAG はフィールド名に対応しており、作成された
     レコード型のインスタンスのフィールドはそれぞれの  INIT-TAG
     にしたがって、初期化されます。INIT-TAG には全てのフィールドが
     ある必要なはく、初期化されないフィールドは、未束縛のままになります。

     PREDICATE は、一つの引数をとり、もしその引数が、定義された
     レコード型のインスタンスであれば、`#t' を返し、さもなければ、 `#f'
     を返すような手続きに束縛されます。

     そのあとは、フィールドの仕様です。レコードはフィールド FIELD ...
     をもち、それぞれのフィールドはメソッド ACCESSOR
     によってアクセス可能です。そのフィールドに対して MODIFIER
     が与えられていれば、それは、そのフィールドの
     値をセットするメソッドに束縛されます。

     例:
          (define-record-type pare
            (kons x y) pare?
            (x kar set-kar!)
            (y kdr))
           => #<class pare>

          (pare? (kons 2 3)) => #t
          (pare? (cons 2 3)) => #f

          (kar (kons 2 3)) => 2
          (kdr (kons 2 3)) => 3

          (let ((x (kons 2 3)))
            (set-kar! x -1)
            (kar x)) => -1

     概念的には、上の例は以下の形式のならびに展開されます。
          (define-class pare (<record>) (x y))
          (define (kons x y)
            (let ((obj (make pare)))
              (slot-set! obj 'x x)
              (slot-set! obj 'y y)
              obj))
          (define (pare? obj) (is-a? obj pare))
          (define-method kar ((obj pare))
            (slot-ref obj 'x))
          (define-method set-kar! ((obj pare) value)
            (slot-set! obj 'x value))
          (define-method kdr ((obj pare))
            (slot-ref obj 'y))



File: gauche-refj.info,  Node: Let-values,  Next: 文字列ライブラリ,  Prev: レコード型,  Up: ライブラリモジュール - SRFI

10.8 `srfi-11' - Let-values
===========================

 -- Module: srfi-11
     二つのマクロ、`let-values' と `let*-values' を定義しています。
     これらは、多値とともに利用すると便利です。(*Note [SRFI-11]:
     srfi-11.)


 -- Macro: let-values ((vars expr) ...) body ...
     [SRFI-11] VARS は変数のリストです。EXPR
     は評価され、最初の返り値は、 VARS
     の最初の変数に束縛されます。二番目の返り値は、VARS の
     二番目の変数に束縛され、以下同様です。そのあと、BODY
     が評価されます。 EXPR のスコープは `let' と同様に、`let-values' の
     外側になります。

          (let-values (((a b) (values 1 2))
                       ((c d) (values 3 4)))
            (list a b c d)) => (1 2 3 4)

          (let ((a 1) (b 2) (c 3) (d 4))
            (let-values (((a b) (values c d))
                         ((c d) (values a b)))
              (list a b c d))) => (3 4 1 2)

     VARS lambda パラメータと同様に、ドット付リストでも、
     単一のシンボルでもかまいません。

          (let-values (((x . y) (values 1 2 3 4)))
            y) => (2 3 4)

          (let-values ((x (values 1 2 3 4)))
            x) => (1 2 3 4)

     EXPR によって返された値の数と VARS が期待する数とが一致しない
     場合にはエラーになります。

 -- Macro: let*-values ((vars expr) ...) body ...
     [SRFI-11] `let-values'と同じですが、各 EXPR のスコープが先行する
     VARS を含みます。

          (let ((a 1) (b 2) (c 3) (d 4))
            (let*-values (((a b) (values c d))
                          ((c d) (values a b)))
              (list a b c d))) => (3 4 3 4)


File: gauche-refj.info,  Node: 文字列ライブラリ,  Next: 文字集合ライブラリ,  Prev: Let-values,  Up: ライブラリモジュール - SRFI

10.9 `srfi-13' - 文字列ライブラリ
=================================

 -- Module: srfi-13
     文字列に関連する関数の大きなセットを定義しています。
     Gaucheでは、それらの関数はいくつかのファイルに分割されており、
     `(use srfi-13)'というフォームは単にそれらのファイルの
     オートロードのセットアップをするだけです。
     したがって、スクリプトのスタートアップを遅くするようなことは
     ありません。 詳細な仕様とデザインに関する議論については、SRFI-13
     (*Note [SRFI-13]: srfi-13.)  を参照して下さい。
     このマニュアルは、関数のAPIのリファレンスとして提供されます。
     いくつかのSRFI-13の関数は、Gaucheのビルトインになっており、
     ここにはリストされていないものもあります。 注意:
     SRFI-13のドキュメントは、これらの関数を実装するモジュールの
     名前を"string-lib"と"string-lib-internals"とすることを推奨しています。
     Gaucheでは、一貫性のために"srfi-13"と名付けています。

* Menu:

* 一般規約::
* 文字列についての述語::
* 文字列の構築子::
* 文字列の選択::
* 文字列の色々な比較::
* 文字列のプリフィックスとサフィックス::
* 文字列の探索::
* 文字列のケース(大文字小文字)マッピング::
* 文字列の反転と追加::
* 文字列のマッピング::
* 文字列のローテーション::
* 他の文字列操作::
* 文字列のフィルタリング::
* 低レベルな文字列に関する手続き::


File: gauche-refj.info,  Node: 一般規約,  Next: 文字列についての述語,  Prev: 文字列ライブラリ,  Up: 文字列ライブラリ

10.9.1 一般規約
---------------

文字列ライブラリのAPIにはいくつか共通するものがありますが、
それぞれの関数の説明において繰り返しません。

_引数の仕様_
     以下の引数名はその型を暗に表しています。
    S, S1, S2
          これらの引数は文字列でなければなりません。

    CHAR/CHAR-SET/PRED
          この引数は、文字、文字セットオブジェクト、あるいは1つの文字を引数に取り
          真偽値を返す述語のいずれかです。"文字にCHAR/CHAR-SET/PREDを適用する"
          の意味はそれぞれ、CHAR/CHAR-SET/PREDが文字ならば与えられた文字と比較される、
          CHAR/CHAR-SET/PREDが文字セットならばその文字セットに与えられた文字が
          含まれるかを検査する、CHAR/CHAR-SET/PREDが述語ならばそれを与えられた
          文字に適用する、となります。"ある文字がCHAR/CHAR-SET/PREDを満足する"
          とは、その文字への前述のような適用が真値を返すという意味になります。

    START, END
          SRFI-13の関数の多くは、その操作が実行される対象入力文字列の
          範囲を限定する開始インデックスと終了インデックスをオプショナルな
          引数として取ります。開始(START番目)の文字は含まれ、
          終了(END番目)の文字は含まれません。 これらが指定されるとき、0
          <= START <= END <= LENGTH OF THE STRINGが
          満たされなければなりません。STARTとENDのデフォルト値は、
          それぞれ0と文字列の長さです。

_`shared'バージョン_
     いくつかの関数は、その名前に"/shared"が付きます。
     SRFI-13では、それらの関数はより良いパフォーマンスのために
     入力文字列の一部を共有しても良いと定義しています。
     Gaucheは、共有文字列という概念を持っていませんし、
     それらの関数は単に共有でないバージョンの変名に過ぎません。
     しかし、Gaucheは_内部的には_文字列の保存場所を共有しているので、
     一般的には部分文字列をコピーするオーバヘッドについて心配する
     必要はありません。

_`right'バージョン_
     ほとんどの関数は、入力文字列を左から右へと扱います。
     いくつかの関数は、その名前に"-right"が付き、右から左へと
     扱うものがあります。



File: gauche-refj.info,  Node: 文字列についての述語,  Next: 文字列の構築子,  Prev: 一般規約,  Up: 文字列ライブラリ

10.9.2 文字列についての述語
---------------------------

 -- Function: string-null? s
     [SRFI-13] Sが空文字列、`""'なら、`#t'を返します。

 -- Function: string-every char/char-set/pred s &optional start end
     [SRFI-13] Sに含まれる全ての文字がCHAR/CHAR-SET/PREDを
     満足するかを検査します。満足するならば、`string-every'は
     最後に適用されたCHAR/CHAR-SET/PREDが返した値を戻り値とします。
     どの適用も`#f'を返した場合は、`string-every'はすぐに
     `#f'を返します。

 -- Function: string-any char/char-set/pred s &optional start end
     [SRFI-13] Sに含まれるいずれかの文字がCHAR/CHAR-SET/PRED
     を満足するかを検査します。いずれかの文字が満足するならば、
     `string-any'はその適用が返した値を戻り値とします。
     どの文字もCHAR/CHAR-SET/PREDを満たさなければ、`#f'が返ります。


File: gauche-refj.info,  Node: 文字列の構築子,  Next: 文字列の選択,  Prev: 文字列についての述語,  Up: 文字列ライブラリ

10.9.3 文字列の構築子
---------------------

 -- Function: string-tabulate proc len
     [SRFI-13] PROCは整数を1つ引数として取り文字を返す手続きで
     なければなりません。`string-tabulate'は、そのI番目の 文字が`(proc
     i)'で計算されるような文字列を返します。
          (string-tabulate
            (lambda (i) (integer->char (+ i #x30))) 10)
           => "0123456789"


 -- Function: reverse-list->string char-list
     [SRFI-13] == `(list->string (reverse char-list))'.


File: gauche-refj.info,  Node: 文字列の選択,  Next: 文字列の色々な比較,  Prev: 文字列の構築子,  Up: 文字列ライブラリ

10.9.4 文字列の選択
-------------------

 -- Function: substring/shared s start &optional end
     [SRFI-13] Gaucheでは、引数ENDがオプショナルであることを除いて、
     `substring'と同じです。
          (substring/shared "abcde" 2) => "cde"

 -- Function: string-copy! target tstart s &optional start end
     [SRFI-13] 文字列Sを、文字列TARGETのTSTART番目以降へコピーします。
     オプションの引数STARTとENDは、Sの範囲を制限します。
     コピーされた文字列がTARGETの終端を越えたらエラーが通知されます。
          (define s (string-copy "abcde"))
          (string-copy! s 2 "ZZ")
          s => "abZZe"

 -- Function: string-take s nchars
 -- Function: string-drop s nchars
 -- Function: string-take-right s nchars
 -- Function: string-drop-right s nchars
     [SRFI-13]
     `string-take'は、Sの最初のNCHARS文字からなる文字列を返します。
     `string-drop'は、Sから最初のNCHARS文字からなる文字列を
     除いた残りを返します。`*-right'バージョンは、文字列の最後から数えます。
     返される文字列はいつもSのコピーであり、どの文字も削除されないことが
     保証されています。
          (string-take "abcde" 2) => "ab"
          (string-drop "abcde" 2) => "cde"

          (string-take-right "abcde" 2) => "de"
          (string-drop-right "abcde" 2) => "abc"

 -- Function: string-pad s len &optional char start end
 -- Function: string-pad-right s len &optional char start end
     [SRFI-13] 文字列SがLENより短い場合は、CHARがそれぞれ左か
     右にパディングされた長さLENの文字列を返します。
     SがLENよりも長い場合は、LEN文字が右端か左端から
     取り除かれます。CHARのデフォルト値は`#\space'です。
     STARTとENDが与えられると、Sの部分文字列がソース
     文字列として使われます。

          (string-pad "abc" 10)    => "       abc"
          (string-pad "abcdefg" 3) => "efg"

          (string-pad-right "abc" 10) => "abc       "

          (string-pad "abcdefg" 10 #\+ 2 5)
            => "+++++++cde"

 -- Function: string-trim s &optional char/char-set/pred start end
 -- Function: string-trim-right s &optional char/char-set/pred start end
 -- Function: string-trim-both s &optional char/char-set/pred start end
     [SRFI-13] SからCHAR/CHAR-SET/PREDにマッチする文字を削除します。
     `String-trim'はSの左から文字を削除し、
     `string-trim-right'は右から、`string-trim-both'は
     両端から削除します。
     CHAR/CHAR-SET/PREDのデフォルト値は`#[\s]'、つまり空白文字の
     文字セットです。STARTとENDが与えられると、Sの部分文字列が
     ソース文字列として使われます。

          (string-trim "   abc  ")       => "abc  "
          (string-trim-right "   abc  ") => "   abc"
          (string-trim-both "   abc  ")  => "abc"


File: gauche-refj.info,  Node: 文字列の色々な比較,  Next: 文字列のプリフィックスとサフィックス,  Prev: 文字列の選択,  Up: 文字列ライブラリ

10.9.5 文字列の色々な比較
-------------------------

 -- Function: string-compare s1 s2 proc< proc= proc> &optional start1
          end1 start2 end2
 -- Function: string-compare-ci s1 s2 proc< proc= proc> &optional
          start1 end1 start2 end2
     [SRFI-13]

 -- Function: string= s1 s2 &optional start1 end1 start2 end2
 -- Function: string`<>' s1 s2 &optional start1 end1 start2 end2
 -- Function: string`<' s1 s2 &optional start1 end1 start2 end2
 -- Function: string`<=' s1 s2 &optional start1 end1 start2 end2
 -- Function: string`>' s1 s2 &optional start1 end1 start2 end2
 -- Function: string`>=' s1 s2 &optional start1 end1 start2 end2
     [SRFI-13]

 -- Function: string-ci`=' s1 s2 &optional start1 end1 start2 end2
 -- Function: string-ci`<>' s1 s2 &optional start1 end1 start2 end2
 -- Function: string-ci`<' s1 s2 &optional start1 end1 start2 end2
 -- Function: string-ci`<=' s1 s2 &optional start1 end1 start2 end2
 -- Function: string-ci`>' s1 s2 &optional start1 end1 start2 end2
 -- Function: string-ci`>=' s1 s2 &optional start1 end1 start2 end2
     [SRFI-13]

 -- Function: string-hash s &optional bound start end
 -- Function: string-hash-ci s &optional bound start end
     [SRFI-13]


File: gauche-refj.info,  Node: 文字列のプリフィックスとサフィックス,  Next: 文字列の探索,  Prev: 文字列の色々な比較,  Up: 文字列ライブラリ

10.9.6 文字列のプリフィックスとサフィックス
-------------------------------------------

 -- Function: string-prefix-length s1 s2 &optional start1 end1 start2
          end2
 -- Function: string-suffix-length s1 s2 &optional start1 end1 start2
          end2
 -- Function: string-prefix-length-ci s1 s2 &optional start1 end1
          start2 end2
 -- Function: string-suffix-length-ci s1 s2 &optional start1 end1
          start2 end2
     [SRFI-13]

 -- Function: string-prefix? s1 s2 &optional start1 end1 start2 end2
 -- Function: string-suffix? s1 s2 &optional start1 end1 start2 end2
 -- Function: string-prefix-ci? s1 s2 &optional start1 end1 start2 end2
 -- Function: string-suffix-ci? s1 s2 &optional start1 end1 start2 end2
     [SRFI-13]


File: gauche-refj.info,  Node: 文字列の探索,  Next: 文字列のケース(大文字小文字)マッピング,  Prev: 文字列のプリフィックスとサフィックス,  Up: 文字列ライブラリ

10.9.7 文字列の探索
-------------------

 -- Function: string-index s char/char-set/pred &optional start end
 -- Function: string-index-right s char/char-set/pred &optional start
          end
     [SRFI-13] 文字列Sの中で、CHAR/CHAR-SET/PREDにマッチする
     最初の要素を探し、そのインデックスを返します。
     Sの中にCHAR/CHAR-SET/PREDが見つからない場合は、`#f'を
     返します。オプションのSTARTとENDは、Sの中で検索対象と
     なる範囲を制限します。
          (string-index "Aloha oe" #\a) => 4
          (string-index "Aloha oe" #[Aa]) => 0
          (string-index "Aloha oe" #[\s]) => 5
          (string-index "Aloha oe" char-lower-case?) => 1
          (string-index "Aloha oe" #\o 3) => 6

     ポータビリティよりも速度を重視する場合は、Gaucheのビルトイン手続き
     `string-scan'(*Note 文字列を扱うその他の手続き::)を参照して下さい。

 -- Function: string-skip s char/char-set/pred &optional start end
 -- Function: string-skip-right s char/char-set/pred &optional start end
     [SRFI-13] CHAR/CHAR-SET/PREDにマッチしない最初の要素を探し、
     そのインデックスを返します。そのような要素が見つからない場合、`#f'を
     返します。オプションのSTARTとENDは、Sの中で検索対象と
     なる範囲を制限します。

 -- Function: string-count s char/char-set/pred &optional start end
     [SRFI-13] Sの中で、CHAR/CHAR-SET/PREDにマッチする要素の数を
     カウントします。オプションのSTARTとENDは、Sの中で検索対象と
     なる範囲を制限します。

 -- Function: string-contains s1 s2 &optional start1 end1 start2 end2
 -- Function: string-contains-ci s1 s2 &optional start1 end1 start2 end2
     [SRFI-13] S1の中で、文字列S2を探します。見つかった場合は、
     S1でマッチした文字列が始まるインデックスを返します。そうでなければ、
     `#f'を返します。 オプションのSTART1、END1、START2、END2は、
     S1とS2の範囲を制限します。

     ポータビリティよりも速度を重視する場合は、Gaucheのビルトイン手続き
     `string-scan'(*Note 文字列を扱うその他の手続き::)を参照して下さい。


File: gauche-refj.info,  Node: 文字列のケース(大文字小文字)マッピング,  Next: 文字列の反転と追加,  Prev: 文字列の探索,  Up: 文字列ライブラリ

10.9.8 文字列のケース(大文字小文字)マッピング
---------------------------------------------

 -- Function: string-titlecase s &optional start end
 -- Function: string-titlecase! s &optional start end
     [SRFI-13]

 -- Function: string-upcase s &optional start end
 -- Function: string-upcase! s &optional start end
     [SRFI-13]

 -- Function: string-downcase s &optional start end
 -- Function: string-downcase! s &optional start end
     [SRFI-13]


File: gauche-refj.info,  Node: 文字列の反転と追加,  Next: 文字列のマッピング,  Prev: 文字列のケース(大文字小文字)マッピング,  Up: 文字列ライブラリ

10.9.9 文字列の反転と追加
-------------------------

 -- Function: string-reverse s &optional start end
 -- Function: string-reverse! s &optional start end
     [SRFI-13] Sの文字の位置を逆順にした文字列を返します。
     `string-reverse!'はSそのものを変更します。
          (string-reverse "mahalo") => "olaham"
          (string-reverse "mahalo" 3) => "ola"
          (string-reverse "mahalo" 1 4) => "aha"

          (let ((s (string-copy "mahalo")))
            (string-reverse! s 1 5)
            s)
            => "mlahao"

 -- Function: string-concatenate string-list
     [SRFI-13] 文字列のリストを連結します。
          (string-concatenate '("humuhumu" "nukunuku" "apua" "`a"))
            => "humuhumunukunukuapua`a"

 -- Function: string-concatenate/shared string-list
 -- Function: string-append/shared s ...
     [SRFI-13] `string-concatenate'と`string-append'の"共有"
     バージョンです。Gaucheでは、これらは単に別名です。

 -- Function: string-concatenate-reverse string-list
 -- Function: string-concatenate-reverse/shared string-list
     [SRFI-13] STRING-LISTを連結する前に逆順にします。
     Gaucheでは、"共有"バージョンは全く同じ動作をします。


File: gauche-refj.info,  Node: 文字列のマッピング,  Next: 文字列のローテーション,  Prev: 文字列の反転と追加,  Up: 文字列ライブラリ

10.9.10 文字列のマッピング
--------------------------

 -- Function: string-map proc s &optional start end
 -- Function: string-map! proc s &optional start end
     [SRFI-13] `string-map'は、Sの全ての文字に対してPROCを
     適用し、その結果を文字列に集めそれを返します。
     一方、`string-map!'はSそのものを変更します。
          (string-map char-upcase "wikiwiki") => "WIKIWIKI"
          (string-map char-upcase "wikiwiki" 4) => "WIKI"

          (let ((s (string-copy "wikiwiki")))
            (string-map! char-upcase s 4)
            s)
            => "wikiWIKI"

 -- Function: string-fold kons knil s &optional start end
 -- Function: string-fold-right kons knil s &optional start end
     [SRFI-13]

 -- Function: string-unfold p f g seed &optional base make-final
     [SRFI-13]

 -- Function: string-unfold-right p f g seed &optional base make-final
     [SRFI-13]

 -- Function: string-for-each proc s &optional start end
     [SRFI-13]

 -- Function: string-for-each-index proc s &optional start end
     [SRFI-13]


File: gauche-refj.info,  Node: 文字列のローテーション,  Next: 他の文字列操作,  Prev: 文字列のマッピング,  Up: 文字列ライブラリ

10.9.11 文字列のローテーション
------------------------------

 -- Function: xsubstring s from &optional to start end
     [SRFI-13]

 -- Function: string-xcopy! target tstart s sfrom &optional sto start
          end
     [SRFI-13]


File: gauche-refj.info,  Node: 他の文字列操作,  Next: 文字列のフィルタリング,  Prev: 文字列のローテーション,  Up: 文字列ライブラリ

10.9.12 他の文字列操作
----------------------

 -- Function: string-replace s1 s2 start1 end2 &optional start2 end2
     [SRFI-13]

 -- Function: string-tokenize s &optional token-set start end
     [SRFI-13] 文字列 S を、TOKEN-SET で指定される文字セットで
     構成される、空でない最大限連続した文字のシーケンスのそれぞれを
     要素とするリストを返します。 TOKEN-SET のデフォルト値は
     `char-set:graphic' (*Note 定義済みの文字セット::参照)。

     同様の機能を提供する、しかし異なる基準を持つ、Gauche
     の組み込み手続き `string-split' (*Note
     文字列を扱うその他の手続き:: 参照) も見て下さい。


File: gauche-refj.info,  Node: 文字列のフィルタリング,  Next: 低レベルな文字列に関する手続き,  Prev: 他の文字列操作,  Up: 文字列ライブラリ

10.9.13 文字列のフィルタリング
------------------------------

 -- Function: string-filter s char/char-set/pred &optional start end
 -- Function: string-delete s char/char-set/pred &optional start end
     [SRFI-13]


File: gauche-refj.info,  Node: 低レベルな文字列に関する手続き,  Prev: 文字列のフィルタリング,  Up: 文字列ライブラリ

10.9.14 低レベルな文字列に関する手続き
--------------------------------------

 -- Function: string-parse-start+end proc s args
 -- Function: string-parse-final-start+end proc s args
     [SRFI-13]

 -- Macro: let-string-start+end (start end [rest]) proc-exp s-exp
          args-exp body ...
     [SRFI-13]

 -- Function: check-substring-spec proc s start end
 -- Function: substring-spec-ok? s start end
     [SRFI-13]

 -- Function: make-kmp-restart-vector s &optional c= start end
     [SRFI-13]

 -- Function: kmp-step pat rv c i c= p-start
     [SRFI-13]

 -- Function: string-kmp-partial-search pat rv s i &optional c= p-start
          s-start s-end
     [SRFI-13]


File: gauche-refj.info,  Node: 文字集合ライブラリ,  Next: 時間のデータ型と手続き,  Prev: 文字列ライブラリ,  Up: ライブラリモジュール - SRFI

10.10 `srfi-14' - 文字集合ライブラリ
====================================

 -- Module: srfi-14
     SRFI-14で定義された文字セットライブラリを実装します (*Note
     SRFI-14: srfi-14.)。
     基本的な文字セットの操作はGauche組み込みになっています(*Note
     文字集合::参照)。
     このモジュールでは多くのユーティリティ手続きが追加されます。

* Menu:

* 文字セットの構築子::
* 文字セットの比較::
* 文字セットのイテレーション::
* 文字セットへの問い合わせ::
* 文字セットに適用できる代数的関数::
* 定義済みの文字セット::


File: gauche-refj.info,  Node: 文字セットの構築子,  Next: 文字セットの比較,  Prev: 文字集合ライブラリ,  Up: 文字集合ライブラリ

10.10.1 文字セットの構築子
--------------------------

 -- Function: list->char-set char-list &optional base-cs
 -- Function: list->char-set! char-list base-cs
     [SRFI-14]
     与えられた文字のリストCHAR-LISTから文字セットを構築して返します。
     文字セットBASE-CSが与えられていた場合、返される文字セットは
     その文字セットにCHAR-LIST中の文字を追加したものとなります。
     `list->char-set!'は、結果を格納するためにBASE-CSを
     変更するかもしれません。

 -- Function: string->char-set s &optional base-cs
 -- Function: string->char-set! s base-cs
     [SRFI-14] 追加する文字をリストでなく文字列Sで与えることを除けば
     `list->char-set'、`list->char-set!'と同じです。

 -- Function: char-set-filter pred char-set &optional base-cs
 -- Function: char-set-filter! pred char-set base-cs
     [SRFI-14] CHAR-SET内の文字のうち、`(PRED C)' が真の値を
     返すようなCからなる文字セットを作成して返します。
     文字セットBASE-CSが与えられた場合は、その内容が結果に追加されます。
     `char-set-filter!'は、結果を格納するためにBASE-CSを変更するかも
     しれません。

 -- Function: ucs-range->char-set lower upper &optional error? base-cs
 -- Function: ucs-range->char-set! lower upper error? base-cs
     [SRFI-14]

 -- Function: integer-range->char-set lower upper &optional error?
          base-cs
 -- Function: integer-range->char-set! lower upper error? base-cs

 -- Function: ->char-set x
     [SRFI-14]


File: gauche-refj.info,  Node: 文字セットの比較,  Next: 文字セットのイテレーション,  Prev: 文字セットの構築子,  Up: 文字集合ライブラリ

10.10.2 文字セットの比較
------------------------

 -- Function: char-set= char-set1 ...
     [SRFI-14]

 -- Function: char-set`<=' char-set1 ...
     [SRFI-14]

 -- Function: char-set-hash char-set &optional bound
     [SRFI-14]


File: gauche-refj.info,  Node: 文字セットのイテレーション,  Next: 文字セットへの問い合わせ,  Prev: 文字セットの比較,  Up: 文字集合ライブラリ

10.10.3 文字セットのイテレーション
----------------------------------

 -- Function: char-set-cursor char-set
     [SRFI-14]

 -- Function: char-set-ref char-set cursor
     [SRFI-14]

 -- Function: char-set-cursor-next char-set cursor
     [SRFI-14]

 -- Function: end-of-char-set? ccursor
     [SRFI-14]

 -- Function: char-set-fold kons knil char-set
     [SRFI-14]

 -- Function: char-set-unfold pred fun gen seed &optional base-char-set
 -- Function: char-set-unfold! pred fun gen seed base-char-set
     [SRFI-14]

 -- Function: char-set-for-each proc char-set
     [SRFI-14]

 -- Function: char-set-map proc char-set
     [SRFI-14]


File: gauche-refj.info,  Node: 文字セットへの問い合わせ,  Next: 文字セットに適用できる代数的関数,  Prev: 文字セットのイテレーション,  Up: 文字集合ライブラリ

10.10.4 文字セットへの問い合わせ
--------------------------------

 -- Function: char-set-size char-set
     [SRFI-14]

 -- Function: char-set-count pred char-set
     [SRFI-14]

 -- Function: char-set->list char-set
     [SRFI-14]

 -- Function: char-set->string char-set
     [SRFI-14]

 -- Function: char-set-every pred char-set
     [SRFI-14]

 -- Function: char-set-any pred char-set
     [SRFI-14]


File: gauche-refj.info,  Node: 文字セットに適用できる代数的関数,  Next: 定義済みの文字セット,  Prev: 文字セットへの問い合わせ,  Up: 文字集合ライブラリ

10.10.5 文字セットに適用できる代数的関数
----------------------------------------

 -- Function: char-set-adjoin char-set char1 ...
 -- Function: char-set-adjoin! char-set char1 ...
     [SRFI-14] Returns a character set that adds CHAR1 ... to CHAR-SET.

 -- Function: char-set-delete char-set char1 ...
 -- Function: char-set-delete! char-set char1 ...
     [SRFI-14]

 -- Function: char-set-complement char-set
 -- Function: char-set-complement! char-set
     [SRFI-14]

 -- Function: char-set-union char-set ...
 -- Function: char-set-union! char-set1 char-set2 ...
     [SRFI-14]

 -- Function: char-set-intersection char-set ...
 -- Function: char-set-intersection! char-set1 char-set2 ...
     [SRFI-14]

 -- Function: char-set-difference char-set1 char-set2 ...
 -- Function: char-set-difference! char-set1 char-set2 ...
     [SRFI-14]

 -- Function: char-set-xor char-set ...
 -- Function: char-set-xor! char-set1 char-set2 ...
     [SRFI-14]

 -- Function: char-set-diff+intersection char-set1 char-set2 ...
 -- Function: char-set-diff+intersection! char-set1 char-set2 char-set3
          ...
     [SRFI-14]


File: gauche-refj.info,  Node: 定義済みの文字セット,  Prev: 文字セットに適用できる代数的関数,  Up: 文字集合ライブラリ

10.10.6 定義済みの文字セット
----------------------------

 -- Variable: char-set:letter
     [SRFI-14]

 -- Variable: char-set:blank
     [SRFI-14]

 -- Variable: char-set:iso-control
     [SRFI-14]

 -- Variable: char-set:digit
 -- Variable: char-set:hex-digit
     [SRFI-14]

 -- Variable: char-set:graphic
     [SRFI-14]

 -- Variable: char-set:lower-case
 -- Variable: char-set:upper-case
 -- Variable: char-set:title-case
     [SRFI-14]

 -- Variable: char-set:printing
     [SRFI-14]

 -- Variable: char-set:punctuation
     [SRFI-14]

 -- Variable: char-set:whitespace
     [SRFI-14]

 -- Variable: char-set:symbol
     [SRFI-14]

 -- Variable: char-set:ascii
     [SRFI-14]

 -- Variable: char-set:empty
     [SRFI-14]

 -- Variable: char-set:full
     [SRFI-14]


File: gauche-refj.info,  Node: 時間のデータ型と手続き,  Next: ランダムビットのソース,  Prev: 文字集合ライブラリ,  Up: ライブラリモジュール - SRFI

10.11 `srfi-19' - 時間のデータ型と手続き
========================================

このSRFIは、時間と日付に関する様々な表現と、それらの間の変換メソッドを提供します。

   Gaucheでは、timeオブジェクトは`<time>'クラスとして組み込みで
サポートされています(*Note 時間::参照)。dateオブジェクトは以下で説明する
`<date>'クラスとしてサポートされます。

* Menu:

* 時間のタイプ::
* 時間に関する問い合わせ::
* 時間に関する手続き::
* 日付::
* 日付の読み書き::


File: gauche-refj.info,  Node: 時間のタイプ,  Next: 時間に関する問い合わせ,  Prev: 時間のデータ型と手続き,  Up: 時間のデータ型と手続き

10.11.1 時間のタイプ
--------------------

時間のタイプはシンボルで表現されます。
このモジュールでは以下の定数が自分の名前に束縛された形で提供されています。

 -- Constant: time-utc
     [SRFI-19] UTC
     timeです。Gaucheの組み込みの`current-time'は常にこのタイプの時間を
     返します (*Note 時間::参照)。

 -- Constant: time-tai
     [SRFI-19] International Atomic
     Time。この時間は閏秒を計算に入れており、
     UTCより若干大きな値を取ります。

 -- Constant: time-monotonic
     [SRFI-19]
     実装依存の、単調増加する時間。Gaucheの実装ではこれは`time-tai'と同じです。

 -- Constant: time-duration
     [SRFI-19] 二つの絶対的な時点の間の期間。

 -- Constant: time-process
     [SRFI-19] 現在のプロセスのCPU時間。 Gaucheは、POSIX
     time(3)コールが返すユーザ時間とシステム時間の合計からこの値を
     計算します。

 -- Constant: time-thread
     [SRFI-19] 現在のスレッドのCPU時間。
     現在の実装ではこれは`time-process'と同じです。


File: gauche-refj.info,  Node: 時間に関する問い合わせ,  Next: 時間に関する手続き,  Prev: 時間のタイプ,  Up: 時間のデータ型と手続き

10.11.2 時間に関する問い合わせ
------------------------------

 -- Function: current-time &optional time-type
     [SRFI-19] Gauche組み込みの`current-time' (*Note
     時間::参照)を拡張して、
     必要な時間のタイプを省略可能な引数TIME-TYPEで指定できるようにしています。
     可能なTIME-TYPEの値は*Note 時間のタイプ::で説明されているものです。

 -- Function: current-date &optional tz-offset
     [SRFI-19]
     現在の日付を`<date>'クラスのインスタンスとして返します(*Note
     日付::参照)。
     TZ-OFFSETが与えられた場合、それがUTCからのオフセットを表す秒数として
     使われます。TZ-OFFSETが与えられなかった場合はローカルタイムゾーンで
     表現された日付が返されます。

 -- Function: current-julian-day
     [SRFI-19] 現在のユリウス日(Julian day)を返します。Julian dayは
     -4714-11-24T12:00:00Z (November 24, -4714 at noon, UTC)
     からの日数を 実数で表現したものです。

 -- Function: current-modified-julian-day
     [SRFI-19] 現在の改訂ユリウス日(Modified julian
     day)を返します。Modified julian dayは 1858-11-17T00:00:00Z
     (November 17, 1858 at midnight, UTC)
     からの日数を実数で表現したものです。

 -- Function: time-resolution
     [SRFI-19]


File: gauche-refj.info,  Node: 時間に関する手続き,  Next: 日付,  Prev: 時間に関する問い合わせ,  Up: 時間のデータ型と手続き

10.11.3 時間に関する手続き
--------------------------

 -- Function: make-time type nanoseconds seconds
     [SRFI-19]
     与えられた初期値を持つ`<time>'クラスのインスタンスを返します。
     `(make <time> :type type :second seconds :nanosecond nanoseconds)'
     と等価です。

     (この関数は0.6.8より前のリリースでは間違って定義されていました。
     SECONDSとNANOSECONDSの引数が逆になっていたのです。
     `make-time'を使っているコードは注意して下さい)。

 -- Function: time-type time
 -- Function: time-second time
 -- Function: time-nanosecond time
 -- Function: set-time-type! time type
 -- Function: set-time-second! time second
 -- Function: set-time-nanosecond! time nanosecond
     [SRFI-19] `<time>'オブジェクトのスロットのアクセサです。

 -- Function: copy-time time
     [SRFI-19]
     与えられたTIMEと同じ内容の新しい`<time>'オブジェクトを返します。

 -- Function: time=? time0 time1
 -- Function: time<? time0 time1
 -- Function: time<=? time0 time1
 -- Function: time>? time0 time1
 -- Function: time>=? time0 time1
     [SRFI-19]
     二つの時間を比較します。時間のタイプは一致していなければなりません。

 -- Function: time-difference time0 time1
 -- Function: time-difference! time0 time1
     [SRFI-19]
     二つの時間の差を`time-duration'タイプの時間として返します。
     二つの時間のタイプは一致していなければなりません。
     `Time-difference!'は結果を格納するためにTIME0を変更します。

 -- Function: add-duration time0 time-duration
 -- Function: add-duration! time0 time-duration
 -- Function: subtract-duration time0 time-duration
 -- Function: subtract-duration! time0 time-duration
     [SRFI-19] TIME-DURATIONをTIME0に加算、またはTIME0から減算します。
     返される時間のタイプはTIME0と同じです。TIME-DURATIONのタイプは
     `time-duration'でなければなりません。
     `add-duration!'と`subtract-duration!'は結果を格納するのに
     TIME0を再利用します。


File: gauche-refj.info,  Node: 日付,  Next: 日付の読み書き,  Prev: 時間に関する手続き,  Up: 時間のデータ型と手続き

10.11.4 日付
------------

 -- Class: <date>
     日付を表現します。

      -- Instance Variable of nanosecond:
          日付のナノ秒部分、0 から 999,999,999 までの整数です。

      -- Instance Variable of second:
          日付の秒部分、0 から 60 までの整数です。(60 は閏秒)

      -- Instance Variable of minute:
          日付の分部分、0 から 59 までの整数です。

      -- Instance Variable of hour:
          日付の時部分、0 から 23 までの整数です。

      -- Instance Variable of day:
          日付の日部分、0 から 31
          日までの整数です。実際の上限は年と月によって決定
          されます。(註: 1 は朔日(ついたち)、0
          は仕様では認められていますが、 なぜなのかはわかりません。)

      -- Instance Variable of month:
          日付の月部分、1 から 12 までの整数です。1 は一月、2
          は二月、以下同様です。 (註: これは POSIX の `<sys-tm>'
          の命名法とは異ります。)

      -- Instance Variable of year:
          日付の年部分です。

      -- Instance Variable of zone-offset:
          このタイムゾーンが GMT より何秒東にあるかを示す整数です。

 -- Function: make-date nanosecond second minute hour day month year
          zone-offset
     [SRFI-19] 与えられた値から `<date>' オブジェクトを作成します。 註:
     この手続きは与えられた値が正しい範囲であるかどうかをチェックしません。

 -- Function: date? obj
     [SRFI-19] OBJ が `<date>'
     オブジェクトである場合にかぎり真を返します。

 -- Function: date-nanosecond date
 -- Function: date-second date
 -- Function: date-minute date
 -- Function: date-hour date
 -- Function: date-day date
 -- Function: date-month date
 -- Function: date-year date
 -- Function: date-zone-offset date
     [SRFI-19] アクセサです。

 -- Function: date-year-day date
 -- Function: date-week-day date
 -- Function: date-week-number date day-of-week-starting-week
     [SRFI-19] それぞれ、一年の何日目(一月一日が 1)か、何曜日(日曜日が
     0、月曜日が 1
     など)か、一年のうち何週目(一年の最初の週が一週間に満たない場合はその
     週は無視)かを計算します。

 -- Function: date->julian-day date
 -- Function: date->modified-julian-day date
 -- Function: date->time-monotonic date
 -- Function: date->time-tai date
 -- Function: date->time-utc date
     [SRFI-19] 日付から様々な様式の日付/時間に変換します。

 -- Function: julian-day->date jd &optional tz-offset
 -- Function: julian-day->time-monotonic jd
 -- Function: julian-day->time-tai jd
 -- Function: julian-day->time-utc jd
     [SRFI-19] ユリウス日からから様々な様式の日付/時間に変換します。

 -- Function: modified-julian-day->date jd &optional tz-offset
 -- Function: modified-julian-day->time-monotonic jd
 -- Function: modified-julian-day->time-tai jd
 -- Function: modified-julian-day->time-utc jd
     [SRFI-19] 改訂ユリウス日から様々な様式の日付/時間に変換します。

 -- Function: time-monotonic->date time &optional tz-offset
 -- Function: time-monotonic->julian-day time
 -- Function: time-monotonic->modified-julian-day time
 -- Function: time-monotonic->time-tai time
 -- Function: time-monotonic->time-tai! time
 -- Function: time-monotonic->time-utc time
 -- Function: time-monotonic->time-utc! time
     [SRFI-19] time-monotonic形式から様々な様式の日付/時間に変換します。

 -- Function: time-tai->date time &optional tz-offset
 -- Function: time-tai->julian-day time
 -- Function: time-tai->modified-julian-day time
 -- Function: time-tai->time-monotonic time
 -- Function: time-tai->time-monotonic! time
 -- Function: time-tai->time-utc time
 -- Function: time-tai->time-utc! time
     [SRFI-19] time-tai形式から様々な様式の日付/時間に変換します。

 -- Function: time-utc->date time &optional tz-offset
 -- Function: time-utc->julian-day time
 -- Function: time-utc->modified-julian-day time
 -- Function: time-utc->time-monotonic time
 -- Function: time-utc->time-monotonic! time
 -- Function: time-utc->time-tai time
 -- Function: time-utc->time-tai! time
     [SRFI-19] UTC 形式から様々な様式の日付/時間に変換します。


File: gauche-refj.info,  Node: 日付の読み書き,  Prev: 日付,  Up: 時間のデータ型と手続き

10.11.5 日付の読み書き
----------------------

 -- Function: date->string date &optional format-string
     [SRFI-19]

 -- Function: string->date string template-string
     [SRFI-19]


File: gauche-refj.info,  Node: ランダムビットのソース,  Next: 地域化,  Prev: 時間のデータ型と手続き,  Up: ライブラリモジュール - SRFI

10.12 `srfi-27' - ランダムビットのソース
========================================

 -- Module: srfi-27
     このモジュールはメルセンヌツイスタアルゴリズム (*Note Mersenne
     Twister乱数発生器:: 参照)
     を基礎に用いたSRFI-27疑似乱数発生器インタフェースを提供します。

 -- Function: random-integer n
     [SRFI-27] デフォルトの乱数発生源を用いて、0 から N-1
     までの正確な整数の乱数を
     返します。この手続きの乱数のシードを設定するには
     `default-random-source' に対して `random-source-randomize!'
     あるいは、 `random-source-pseudo-randomize!' を用います。

 -- Function: random-real
     [SRFI-27] デフォルトの乱数発生源を用いて、0 より大きく、1
     未満の実数乱数を返します。 この手続きの乱数のシードを設定するには
     `default-random-source' に対して `random-source-randomize!'
     あるいは、 or `random-source-pseudo-randomize!' を用います。

 -- Variable: default-random-source
     [SRFI-27] `random-integer'
     が利用するデフォルトの乱数発生源を保持しています。

 -- Function: make-random-source
     [SRFI-27] 乱数の発生源を生成し返します。 現在の Gauche
     の実装では、これは `<mersenne-twister>' のオブジェクトです。
     将来の実装では変更される可能性があります。

 -- Function: random-source? obj
     [SRFI-27] OBJ が乱数発生源オブジェクトであれば、`#t' を返します。

 -- Function: random-source-state-ref s
 -- Function: random-source-state-set! s state
     [SRFI-27] 乱数発生源 S
     の状態の「スナップショット」を獲得あるいは設定します。 STATE
     は背後にある発生器に依存する内容をもつ不透明なオブジェクトです。

 -- Function: random-source-randomize! s
     [SRFI-27] 乱数発生源 S
     の状態を完全にランダムな状態にしようとします。
     現在の実装では乱数のシードを設定するのに、現在の時刻とプロセス ID
     を 使います。

 -- Function: random-source-pseudo-randomize! s i j
     [SRFI-27] 乱数発生源 S の状態を発生源とは独立した (I, J) 番の
     初期状態に設定します。I および J は非負の整数です。
     この手続きは乱数発生源 S を二つの非負整数でインデックス付した、
     大規模の独立の乱数発生源として再利用するときに利用できます。
     この手続きは、完全な決定性があることに注意してください。

 -- Function: random-source-make-integers s
     [SRFI-27] 呼出しのたびに乱数発生源 S より、 0 から N-1 までの整数の
     乱数を返す、一つの整数 N を引数としてとる手続きを、返します。

 -- Function: random-source-make-reals s &optional unit
     [SRFI-27] 呼出しのたびに乱数発生源 S から 0 より大きく 1
     未満の実数乱数を 返す、無引数の手続きを返します。


File: gauche-refj.info,  Node: 地域化,  Next: args-fold プログラム引数処理,  Prev: ランダムビットのソース,  Up: ライブラリモジュール - SRFI

10.13 `srfi-29' - 地域化
========================

 -- Module: srfi-29
     このモジュールは SRFI-29
     で定義されたメッセージの地域化機構を実装したものです。

     実際には、このモジュールは2つのサブモジュール、`srfi-29.bundle'
     および `srfi-29.format' で構成されています。`srfi-29'モジュールは
     このふたつのモジュールを拡張しています。このようにしているのは、
     SRFI-29 での `format' 手続きの定義が Gauche ネイティヴの(すなわち
     Common Lisp の) `format' とでは `~@*' 指令の扱い
     において互換性がないからです。

     そんなわけで、SRFI-29 の `format' を含む `srfi-29.format' と
     それ以外(「バンドル」API)を含む `srfi-29.bundle' に分離しました。
     プログラムを SRFI-29
     と完全に互換性のあるものにしたければ、`srfi-29'
     モジュールを使って下さい。こうすると Gauche ネイティヴの `format'
     が上書きされます。SRFI-29 の「バンドル」API を使いたいだけで、
     Gauche の `format' をそのままにしておきたいなら、`srfi-29.bundle'
     を使って下さい。

     地域化機能は `text.gettext' モジュールによっても提供され (*Note
     地域化メッセージ::)、Gauche でメッセージの地域化をするのなら
     `text.gettext' を使うのが好ましい方法です。`srfi-29' モジュールは
     主として SRFI-29
     の機能を使っているコードをポーティングするためにあります。

バンドル指定子
--------------

_バンドル指定子_はシンボルを要素とする任意のリストです。しかし
典型的には以下のようなフォームになります。
     `(PACKAGE LANGUAGE COUNTRY DETAILS ...)'
   ここで、PACKAGE はソフトウェアパッケージを指定し、 LANGUAGE および
COUNTRY は言語と国コードを指定、そして、 DETAILS
はエンコーディングのようなそのほかの情報を指定します。

デフォルトのバンドル指定子の値は以下のようなパラメータで取得可能です。

 -- Parameter: current-language
 -- Parameter: current-country
 -- Parameter: current-locale-details
     [SRFI-29] `current-language' および `current-country' パラメータは
     ISO 639-1 の言語コードと ISO 3166-1 の国コードをそれぞれシンボルで
     保持しています。`current-locale-details' はエンコーディングのような
     補助的な地域情報のリストを保持しています。

     これらのパラメータは、環境変数 `LANG' が `lang_country.encoding'
     フォーマットの形式で設定されていれば、初期化されます。たとえば、
     `LANG' が `ja_JP.eucJP' に設定されていれば、それらの
     パラメータはそれぞれ `ja'、`jp'、`(eucjp)' に設定されます。 `LANG'
     が `C' であるかあるいは定義されていなければ、
     デフォルト値は、それぞれ `en'、`us'、`()' です。

バンドル準備
------------

 -- Function: declare-bundle! bundle-specifier association-list
     [SRFI-29]
     テンプレートキー(シンボル)と特定ロケールのメッセージ(文字列)の連想リストを
     BUNDLE-SPECIFIER をキーとして、バンドルデータベースに入れます。

   Gauche
は現在のところメモリ上のバンドルデータベースのみサポートしています。
つまり、地域化されてメッセージを探しあてるには、そのアプリケーション内で
`declare-bundle!' を呼ぶ必要があるということです。

 -- Function: save-bundle! bundle-specifier
 -- Function: load-bundle! bundle-specifier
     [SRFI-29] Gauche
     は今のところ永続バンドルデータベースをサポートしていないので、
     これらの手続きはなにもせず `#f' を返します (これはいまのところ
     srfi-29 の振舞いと適合しています)。

地域化されたメッセージの検索
----------------------------

 -- Function: localized-template package-name message-template-name
     [SRFI-29] 地域化されたメッセージを検索します。当該メッセージは
     PACKAGE-NAME パッケージの中で、MESSAGE-TEMPLATE-NAME
     シンボルと関連つけられています。

拡張された format 手続き
------------------------

 -- Function: format format-string args
     [SRFI-29] SRFI-29 は SRFI-28 の `format' 手続きの仕様(これは `~a'、
     `~s'、`~%' および `~~' 指令をサポートしている)を
     引数再配置をサポートするために拡張しています。

     `~N@*' 指令は N-番目のオプション引数から値を引き出す次の
     指令の契機となります。参照された値が消費されることはありません。また、
     参照された値がその後につづく指令の処理に影響を与えることはありません。

     SRFI-28 の仕様は Gauche ネイティヴの `format' (*Note 出力::) と
     互換性がありますが、この SRFI-29 の拡張には互換性がありません。
     具体的には、Gauche ネイティヴの `format' の `~N@*' 指定は
     引数ポインタを N-番目のオプション引数を指すように変更します。
     それゆえ、そのあとに続くすべての引数に影響をあたえます。

     この非互換性があるために、この関数は、分離したモジュール
     `srfi-29.format' で定義されています。`srfi-29.bundle' と
     `srfi-29.format' を拡張する `srfi-29' を使うと、`format' 手続きは
     SRFI-29 の `format' でそのモジュール内で上書きされます。 Gauche
     ネイティヴの `format' を使いたければ、`srfi-29.bundle'
     だけを使うようにしてください。


File: gauche-refj.info,  Node: args-fold プログラム引数処理,  Next: Eager comprehensions,  Prev: 地域化,  Up: ライブラリモジュール - SRFI

10.14 `srfi-37' - args-fold プログラム引数処理
==============================================

 -- Module: srfi-37
     このモジュールは、`args-fold' を実装しています。 これは、SRFI-37
     (*Note [SRFI-37]: srfi-37.) で定義されている
     コマンドライン引数の処理をするもうひとつの手続きです。

     `gauche.parseopt' (*Note コマンドライン引数の解析:: 参照)
     とは違って、`args-fold' は関数的なインタフェースです。すなわち、
     利用者側の状態は、パーザの引数を通じて明示的に渡され、値が返ります。
     また、ロングオプションを含む、POSIX および GNU の getopt
     のガイドラインに 準拠しています。

 -- Function: args-fold args options unrecognized-proc operand-proc
          &rest seeds
     与えられたオプション仕様 OPTIONS および、ふたつの手続き
     UNRECOGNIZED-PROC と OPERAND-PROC とにしたがって、プログラム 引数
     ARGS を左から右へ処理ます。

     OPTIONS はオプションオブジェクトのリストで以下のようなものです。
     各オプションオブジェクトはオプションの名前、そのオプションが引数を
     とるかどうかを指定するフラグ、そのオプションを処理する手続き
     (今後これを _オプション手続き_とよびます)を保持しています。

     `args-fold' は単一文字のオプション(ショートオプション)と
     ロングオプションの両方を認識します。ショートオプションは単一の
     ハイフンで始まって(たとえば、`-a')いなければなりません。一方、
     ロングオプションは二つのハイフンで始まって(たとえば、`--help')
     いなければなりません。ショートオプションは連結することが可能で、
     たとえば、`-abc' あるいは `-a -b -c' と書くことができます。
     ショートオプション、ロングオプションはともに、必須引数あるいはオプショナル
     引数を取ることができます。ショートオプションの必須引数は当該オプション
     あとに空白なしあるいは空白をいれて指定することができます。たとえば、
     `-afoo' あるいは `-a foo' が可能です。ロングオプションの
     引数は'`=''文字あるいは空白をはさみます。たとえば、 `--long=foo'
     または `--long foo' です。

     `args-fold' はオプションの引数ではなく、ハイフンで始まっていない
     コマンドライン引数を_オペランド_としてとりあつかいます。
     `args-fold' はオペランドとオプションが交互に出現するのを許します。
     しかし、'`--'' に出逢うと、のこりは、ハイフンで始まっていようと
     なかろうと、オペランドとして扱われます。

     与えられたオプションが OPTIONS 内のオプションオブジェクトのひとつ
     にマッチすれば、オプション手続きが以下のように呼出されます。

          (OPTION-PROC OPTION NAME ARG SEED ...)

     ここで、OPTION はマッチしたオプションオブジェクトで、NAME
     は実際にオプションを指定するのに使われた文字列、ARG
     はそのオプション の引数(あるいは存在しなければ、`#f')、そして SEED
     ... は 利用者側の状態情報です。OPTION-PROC は SEED と同じ数だけ
     値を返さなければなりません。

     `args-fold' がオペランドを見つけたら、OPERAND-PROC が
     以下のように呼出されます。

          (OPERAND-PROC OPERAND SEED ...)

     OPTION-PROC は SEED と同じ数だけ 値を返さなければなりません。

     呼出し側の状態は明示的にシード引数で渡され、戻されます。初期のシード値は
     `args-fold' に与えた SEED にです。この値は、オプション手続き
     UNRECOGNIZED-PROC と OPERAND-PROC によって戻され、
     次にこれらのオプション手続きの呼出し時にシード引数として使われます。
     これらの手続きの最後の呼出しから返されたこの値は `args-fold'
     によって 返されます。

 -- Function: option names require-arg? optional-arg? processor
     渡されたプロパティでオプションオブジェクトを作成します。

     NAME
     は文字と(あるいは)文字列のリストです。文字はショートオプションに
     使い、文字列はロングオプションに使います。

     ふたつのフラグ REQUIRE-ARG? と OPTIONAL-ARG? はオプションが
     必須引数をとるか、あるいは、オプショナル引数をとるかを示します。

     PROCESSOR はそのオプションの処理をする手続きです。

     オプションの引数が '`='' つきで渡された場合には、 たとえ
     REQUIRE-ARG?、OPTIONAL-ARG? がともに `#f'
     であっても、そのオプションの引数はオプション処理手続きに渡されることに
     注意してください。オプション手続きにその引数を処理させようとします。

     ショートオプションに対するオプショナルなオプションの引数は、オプションに
     つづいてスペースなしで指定されたときにだけ認識されることにも
     注意してください。たとえば、ショートオプション `d' がオプショナル
     引数をもつことになっているとき、'`-dfoo'' は '`-d'' が引数 '`foo''
     をもつと解釈されますが、'`-d foo'' は引数なしの '`-d''
     とオペランド '`foo'' と解釈されてしまいます。もし、 '`-d''
     が必須引数をもつと設定されているなら、両方ともに '`-dfoo'' は
     '`-d'' が引数 '`foo'' をもつと解釈されます。

 -- Function: option? obj
     OBJ がオプションオブジェクトなら `#t' を返し、
     そうでなければ、`#f' を返します。

 -- Function: option-names option
 -- Function: option-required-arg? option
 -- Function: option-optional-arg? option
 -- Function: option-processor
     オプションオブジェクト OPTION のプロパティを返します。

   簡単な例:

     (use srfi-37)

     (define options
      (list (option '(#\d "debug") #f #t
                    (lambda (option name arg debug batch paths files)
                      (values (or arg "2") batch paths files)))
            (option '(#\b "batch") #f #f
                    (lambda (option name arg debug batch paths files)
                      (values debug #t paths files)))
            (option '(#\I "include") #t #f
                    (lambda (option name arg debug batch paths files)
                      (values debug batch (cons arg paths) files)))))

     (define (main args)
       (receive (debug-level batch-mode include-paths files)
         (args-fold (cdr args)
                    options
                    (lambda (option name arg . seeds)         ; unrecognized
                      (error "Unrecognized option:" name))
                    (lambda (operand debug batch paths files) ; operand
                      (values debug batch paths (cons operand files)))
                    0      ; default value of debug level
                    #f     ; default value of batch mode
                    '()    ; initial value of include paths
                    '()    ; initial value of files
                    )
          (print "debug level = " debug-level)
          (print "batch mode = " batch-mode)
          (print "include paths = " (reverse include-paths))
          (print "files = " (reverse files))
          0))


File: gauche-refj.info,  Node: Eager comprehensions,  Next: Requiring extensions,  Prev: args-fold プログラム引数処理,  Up: ライブラリモジュール - SRFI

10.15 `srfi-42' - Eager comprehensions
======================================

 -- Module: srfi-42
     This module provides a generic comprehension mechanism, which some
     other languages (e.g. Haskell and Python) provides as a built-in
     mechanism.  It provides rich set of operators so it can be used as
     not only a list generator but a generic loop construct (actually,
     some may say it is as powerful/evil as Common Lisp's _loop_ macro).

     It is also runs eagerly, that is, if it generates a list, it
     creates the entire list when evaluated, instead of generate the
     elements _on demand_.  Thus it can't represent an infinite
     sequence, which Haskell's comprehension naturally can.  In Scheme,
     you can use streams built on top of delayed evaluation for such
     purpose.

Eager comprehension examples
----------------------------

Let's begin with some examples.

   Generate a list of squares for the first five integers:
     (list-ec (: i 5) (* i i)) => (0 1 4 9 16)

   Generate set of pair of numbers `(x y)', where `x' is between 2
(inclusive) and 5 (exclusive), and `y' is between 1 (inclusive) and x
(exclusive).
     (list-ec (: x 2 5) (: y 1 x) (list x y))
       => ((2 1) (3 1) (3 2) (4 1) (4 2) (4 3))

   The above two examples can be written in Haskell as the followings:
     [ i*i   | i <- [0..4] ]
     [ (x,y) | x <- [2..4], y <- [1..x-1] ]
   Note the differences: (1) In Haskell, the body expression to yield
the elements comes first, followed by qualifiers (selectors).  In
srfi-42, the body expression comes last.  (2) In srfi-42, range
operator's lower bound is inclusive but its upper bound is exclusive.

   List a set of numbers `(a b c d)', where `a^3+b^3 = c^3+d^3':
     (define (taxi-number n)
       (list-ec (: a 1 n)
                (: b (+ a 1) n)
                (: c (+ a 1) b)
                (: d (+ c 1) b)
                (if (= (+ (expt a 3) (expt b 3))
                       (+ (expt c 3) (expt d 3))))
                (list a b c d)))

   You can generate not only a list, but other sequences:
     (vector-ec (: i 5) i) => #(0 1 2 3 4)
     (string-ec (: i 5) (integer->char (+ i 65))) => "ABCDE"

   Or apply folding operations:
     (sum-ec (: i 1 10) i)
       => 450    ;; sum of integers from 1 below 100.
     (product-ec (: i 1 10) i)
       => 362880 ;; ... and product of them.

Comprehension macros
--------------------

Each comprehension takes the following form.
     (COMPREHENSION-MACRO QUALIFIER ... BODY)

   Evaluates BODY repeatedly as specified by QUALIFIERs.  Depending on
the type of comprehension, the results of BODY may be either collected
to create an aggregate (list, vector, string, ...), folded by some
operator (sum, product, min, max, ...), or simply discarded.

   A few comprehensions takes extra values before QUALIFIERS or after
BODIES.

 -- Macro: do-ec qualifier ... body
     [SRFI-42]

 -- Macro: list-ec qualifier ... body
     [SRFI-42]

 -- Macro: append-ec qualifier ... body
     [SRFI-42]

 -- Macro: string-ec qualifier ... body
 -- Macro: string-append-ec qualifier ... body
     [SRFI-42]

 -- Macro: vector-ec qualifier ... body
     [SRFI-42]

 -- Macro: vector-of-length-ec qualifier ... body
     [SRFI-42]

 -- Macro: sum-ec qualifier ... body
 -- Macro: product-ec qualifier ... body
 -- Macro: min-ec qualifier ... body
 -- Macro: max-ec qualifier ... body
     [SRFI-42]

 -- Macro: any?-ec qualifier ... test
 -- Macro: every?-ec qualifier ... test
     [SRFI-42]

 -- Macro: first-ec default qualifier ... body
 -- Macro: last-ec default qualifier ... body
     [SRFI-42]

 -- Macro: fold-ec x0 qualifier ... expr f2
 -- Macro: fold3-ec x0 qualifier ... expr f1 f2
     [SRFI-42]

Qualifiers
----------

Control qualifiers
..................

 -- EC Qualifier: if test

 -- EC Qualifier: not test
 -- EC Qualifier: and test
 -- EC Qualifier: or test

 -- EC Qualifier: begin test

 -- EC Qualifier: nested test

Generational qualifiers
.......................

 -- EC Qualifier: : vars arg1 args ...

 -- EC Qualifier: :list vars arg1 args ...
 -- EC Qualifier: :vector vars arg1 args ...
 -- EC Qualifier: :string vars arg1 args ...

 -- EC Qualifier: :integers vars

 -- EC Qualifier: :range vars stop
 -- EC Qualifier: :range vars start stop
 -- EC Qualifier: :range vars start stop step

 -- EC Qualifier: :real-range vars stop
 -- EC Qualifier: :real-range vars start stop
 -- EC Qualifier: :real-range vars start stop step

 -- EC Qualifier: :char-range vars min max

 -- EC Qualifier: :port vars port
 -- EC Qualifier: :port vars port read-proc

 -- EC Qualifier: :dispatched vars dispatch arg1 args ...

 -- EC Qualifier: :do (lb ...) ne1? (ls ...)
 -- EC Qualifier: :do (let (ob ...) oc ...) (lb ...) ne1? (let (ib ...)
          ic ...) ne2? (ls ...)

 -- EC Qualifier: :let vars expr

 -- EC Qualifier: :parallel generator ...

 -- EC Qualifier: :while generator expr

 -- EC Qualifier: :until generator expr


File: gauche-refj.info,  Node: Requiring extensions,  Prev: Eager comprehensions,  Up: ライブラリモジュール - SRFI

10.16 `srfi-55' - Requiring extensions
======================================

 -- Module: srfi-55
     This module defines `require-extension' macro, a yet another way
     to write portable scripts.  See *Note 機能条件式:: and *Note
     機能ベースプログラム設定言語:: for other means of ensuring
     specific features.

     This module is autoloaded when you use `require-extension', so you
     don't need explicitly say `(use srfi-55)'; for portable scripts,
     you shouldn't.

 -- Macro: require-extension clause ...
     Make extension(s) specified by CLAUSEs available in the rest of
     the program.

     A CLAUSE takes the following form:
          (EXTENSION-ID EXTENSION-ARG ...)

     Currently, only `srfi' is supported as EXTENSION-ID, and its
     arguments are SRFI numbers.

     For example, the following form:
          (require-extension (srfi 1 13 14))

     Roughly correspons to Gauche's `use' forms:
          (use srfi-1)
          (use srfi-13)
          (use srfi-14)


File: gauche-refj.info,  Node: ライブラリモジュール - ユーティリティ,  Next: 参考文献,  Prev: ライブラリモジュール - SRFI,  Up: Top

11 ライブラリモジュール - ユーティリティ
****************************************

* Menu:

* バイナリデータのパック::  (binary.pack)
* 汎用DBMインタフェース::  (dbm)
* ファイルシステムdbm::  (dbm.fsdbm)
* GDBMインタフェース::  (dbm.gdbm)
* NDBMインタフェース::  (dbm.ndbm)
* オリジナルのDBMインタフェース::  (dbm.odbm)
* ファイルのフィルタ::  (file.filter)
* ファイルシステムユーティリティ::  (file.util)
* 定数::  (math.const)
* Mersenne Twister乱数発生器::  (math.mt-random)
* RFC822メッセージ形式::  (rfc.822)
* Base64エンコーディング::  (rfc.base64)
* HTTPクッキー::  (rfc.cookie)
* HMAC鍵付きハッシング::  (rfc.hmac)
* HTTP::  (rfc.http)
* MD5メッセージダイジェスト::  (rfc.md5)
* MIMEメッセージ処理::  (rfc.mime)
* Quoted-printableエンコーディング::  (rfc.quoted-printable)
* SHA1メッセージダイジェスト::  (rfc.sha1)
* URIの解析と作成::  (rfc.uri)
* SLIBインタフェース::  (slib)
* 関数的なXMLパーザ::  (sxml.ssax)
* SXMLクエリ言語::  (sxml.sxpath)
* SXML構造を操作する::  (sxml.tools)
* CSVテーブル::  (text.csv)
* テキストストリームの相違点を計算する::  (text.diff)
* 地域化メッセージ::  (text.gettext)
* シンプルなHTMLドキュメントの構築::  (text.html-lite)
* 入力ストリームのパージング::  (text.parse)
* 文字変換::  (text.tr)
* 怠惰なテキスト構築::  (text.tree)
* 組み合わせ::  (util.combinations)
* メッセージダイジェストフレームワーク::  (util.digest)
* 同型判定::  (util.isomorph)
* 最長共通サブシーケンス::  (util.lcs)
* その他のリストライブラリ::  (util.list)
* パターンマッチング::  (util.match)
* キュー::  (util.queue)
* SLIB-互換のレコード型::  (util.record)
* トポロジカルソート::  (util.toposort)
* CGIユーティリティ::  (www.cgi)
* CGIのテスト::  (www.cgi-test)


File: gauche-refj.info,  Node: バイナリデータのパック,  Next: 汎用DBMインタフェース,  Prev: ライブラリモジュール - ユーティリティ,  Up: ライブラリモジュール - ユーティリティ

11.1 `binary.pack' - バイナリデータのパック
===========================================

 -- Module: binary.pack
     このモジュールは、バイナリデータをテンプレートを使って
     パック/アンパック(読み書き)するためのインタフェースを提供します。
     この機能は、その多くをPerlのpack/unpack関数から着想し、他の言語での
     同じような機能と比較しながら、しかし、データベースライクな処理に
     便利なように、より一般的でより効率が良くなるように実装しました。
     これを受けて、最も大きな相違点は、全てのパック可能な値はアンパック
     可能で(逆も同様)、パック/アンパックのデフォルトの振る舞いはポートI/Oを
     使うので、巨大なファイルを読みながらそこからアンパックすることが
     できます。また、テンプレートはディスパッチクロージャとして格納でき、
     パック、アンパック、あるいは値のスキップさえも、テンプレートを
     パーズし直すことなく行えます。


 -- Function: pack template list &keyword :output :to-string?
     LISTにある値を、文字列TEMPLATEで指定されたフォーマットに
     したがって、現在の出力ポートに書き出します。テンプレート文字列は、
     1文字のコードの連続で、オプションで(デフォルトが1である)カウント用の数字
     が続きます。

     フォーマット文字は一般的に、カウントを文字のバイト数と解釈する
     文字列型と、カウントを繰り返し指示子と解釈するオブジェクト型に
     分けられます。カウントは文字`*'で指定され、文字列型では
     文字列の全体の長さを、オブジェクト型では残りの全ての値を使うことを
     意味します。

     カウントは大括弧に囲まれたテンプレートとしても指定でき、その場合
     カウントはその大括弧を囲んでいるテンプレートのバイト数を意味します。
     例えば、`x[L]'はlongをスキップします。

     特別なフォーマット文字`/'は、パックされたデータが、値に続く
     動的なカウント分を含むという構造を表すために使われます。
     テンプレートは、`<count-item>/<value-item>'のように書かれ、
     ここでは`<count-item>'は数値のカウントと解釈されるいかなる
     テンプレート文字、`<value-item>'はこのカウントを使ういかなる
     他のテンプレート文字です。
     `<value-item'>の後に通常のカウントが与えられても、無視されます。

     フォーマット文字`@'は、カウントとともに使われ、テンプレートの
     最初からの絶対位置までパディングします。

     サブテンプレートは、括弧の中にグループ化されます。<>が使われると、
     ネストされたリストに再帰的に適用されるグループ化オペレータとしても
     振舞います。

     文字列型:

    `a'
          任意の不完全文字列。NULLでパディングされます。

    `A'
          テキスト文字列。空白スペースでパディングされます。

    `Z'
          NULL終端(ASCIZ)文字列。NULLでパディングされます。

    `b'
          ビット文字列(それぞれのバイトにおけるビットオーダーは昇順)。

    `B'
          ビット文字列(それぞれのバイトにおけるビットオーダーは降順)。

    `h'
          16進文字列(低いニブルが先)。

    `H'
          16進文字列(高いニブルが先)。

     オブジェクト型:

    `c'
          1つのchar。

    `C'
          符号なしchar。シングルバイトのみ。

    `s'
          符号付きshort(16ビット)。

    `S'
          符号なしshort(16ビット)。

    `i'
          符号付き整数(>= 32ビット)。

    `I'
          符号なし整数(>= 32ビット)。

    `l'
          符号付きlong(32ビット)。

    `L'
          符号なしlong(32ビット)。

    `n'
          ネットワークオーダー(ビッグエンディアン)での符号なしshort(16ビット)。

    `N'
          ネットワークオーダー(ビッグエンディアン)での符号なしlong(32ビット)。

    `v'
          VAXオーダー(リトルエンディアン)での符号なしshort(16ビット)。

    `V'
          VAXオーダー(リトルエンディアン)での符号なしlong(32ビット)。

    `q'
          符号付きquad(64ビット)。

    `Q'
          符号なしquad(64ビット)。

    `f'
          負の単精度float。

    `d'
          負の倍精度float。

    `w'
          BER圧縮された整数。ベース128における符号なし整数で、最も大きな桁が
          最初で、高いビットが最後の(一番小さな)バイト以外にセットされる。
          したがって、どのような大きさの整数もエンコードできるが、
          エンコーディングは効率的で、小さな整数は通常のchar/short/int
          エンコーディングの場合よりも占有する空間が少ない。

    `x'
          NULLバイト。

    `o'
          S式。`read'と`write'で扱われる。


     オプションのキーワード:OUTPUTが与えられると、
     現在の出力ポートの代わりにそのポートが使われます。
     :TO-STRING?が与えられそれが真である場合は、
     パックは蓄積され、その出力は文字列として返ります。

          (pack "CCCC" '(65 66 67 68) :to-string? #t)
           => "ABCD"

          (pack "C/a*" '("hello") :to-string? #t)
           => "\x05hello"

 -- Function: unpack template &keyword :input :from-string
     packの逆を行うもので、unpackは現在の入力ポートから、値が文字列の
     templateでパックされているものとして読み込み、その値をリストとして
     返します。unpackはpackと同じフォーマット文字列を受け付けます。
     また、いかなるリストXとフォーマット文字列FMTにおいても、
     次のようなトートロジーが維持されます。

          (equal? x (unpack fmt :from-string (pack fmt x :to-string? #t)))

     ただ一つの例外は、テンプレートが`*'を含み、`o'テンプレートが
     使われている場合です。これは、Schemeの数値リテラルは確実に区切られる
     ことができないからです(`pack'の将来のバージョンでは、
     新しいread構文を登録することによってこれは回避されるでしょう)。

     オプションのキーワード:INPUTが与えられると、現在の入力ポートの
     代わりにそのポートが使われます。:FROM-STRINGが与えられると、
     packはその文字列を入力とします。

          (unpack "CCCC" :from-string "ABCD")
           => '(65 66 67 68)

          (unpack "C/a*" :from-string "\x05hello")
           => '("hello")

     _註:_ 現在のバージョンには、`unpack'のテンプレートの
     `@'が想定したように動かないというバグがあります。
     将来のバージョンでfixされます。

 -- Function: unpack-skip template &keyword :input
     unpack-skipは、値を返さないことを除いてunpackと同じです。
     いくつかのケースでは、特に固定サイズのテンプレートを使うときには、
     単に値を読み飛ばしたいときにより効率的です。

 -- Function: make-packer template
     低レベルなインタフェースです。この関数は、pack、unpackやキャッシュ
     された同じテンプレートを読み飛ばす時に使われるディスパッチクロージャを
     返します。ディスパッチクロージャは、以下のようにシンボルメソッドを
     受け付けます。

    `'pack list'
          listにあるアイテムを、現在の出力ポートへpackします。

    `'unpack'
          現在の入力ポートからアイテムをunpackします。

    `'skip'
          現在の入力ポートからのアイテムをスキップします。

    `'packer'
          キャッシュされた'packクロージャを返します。

    `'unpacker'
          キャッシュされた'unpackクロージャを返します。

    `'skipper'
          キャッシュされた'skipクロージャを返します。

    `'length'
          テンプレートの知られている固定された長さを返します。

    `'variable-length?'
          テンプレートが可変長の要素を持っている場合に#tを返します。


File: gauche-refj.info,  Node: 汎用DBMインタフェース,  Next: ファイルシステムdbm,  Prev: バイナリデータのパック,  Up: ライブラリモジュール - ユーティリティ

11.2 `dbm' - 汎用DBMインタフェース
==================================

 -- Module: dbm
     DBM系のライブラリはキーでインデックスされた値をファイルに格納する簡単な方法を
     提供します。一種の永続的な連想記憶と言えるでしょう。

     このモジュールが定義する抽象クラス`<dbm>'は、DBM系ライブラリへの
     統一されたインタフェースを提供します。`dbm'モジュールだけをインポートすれば、
     既にオープンされたデータベースを操作することができます。

     データベースをオープンしたり作成したりするには、dbmインタフェースを実装した
     モジュールが必要になります。今のところGaucheでは以下の実装が使えます。
     それぞれのモジュールは、dbmインタフェース共通の手続きの他に、
     直接実装を操作できる低レベルの手続きも提供します。
     システムによっては以下のインタフェースの全てが実装されているわけではないことに
     注意してください。Gaucheではシステムが提供する実装のみを定義します。

    `dbm.fsdbm'
          ファイルシステムdbm (*Note ファイルシステムdbm::参照).

    `dbm.gdbm'
          GDBMライブラリ (*Note GDBMインタフェース::参照).

    `dbm.ndbm'
          NDBMライブラリ (*Note NDBMインタフェース::参照).

    `dbm.odbm'
          DBMライブラリ  (*Note オリジナルのDBMインタフェース::参照).

以下にdbmデータベースの使用例を示します。

     (use dbm)         ; dbm abstract interface
     (use dbm.gdbm)    ; dbm concrete interface

     ; open the database
     (define *db* (dbm-open <gdbm> :path "mydb" :rw-mode :write))

     ; put the value to the database
     (dbm-put! *db* "key1" "value1")

     ; get the value from the database
     (define val (dbm-get *db* "key1"))

     ; iterate over the database
     (dbm-for-each *db* (lambda (key val) (foo key val)))

     ; close the database
     (dbm-close *db*)

* Menu:

* DBMデータベースのオープンとクローズ::
* DBMデータベースのアクセス::
* DBMデータベース上の繰り返し処理::
* DBMデータベースインスタンスの管理::


File: gauche-refj.info,  Node: DBMデータベースのオープンとクローズ,  Next: DBMデータベースのアクセス,  Prev: 汎用DBMインタフェース,  Up: 汎用DBMインタフェース

11.2.1 DBMデータベースのオープンとクローズ
------------------------------------------

 -- Class: <dbm>
     DBM系のデータベースのための抽象クラスです。データベースへの共通のオペレーションを
     定義します。以下のインスタンススロットを持ちます。これらのスロットの値は
     `dbm-open'によってデータベースがオープンされる前にセットされて
     いなければなりません。

     具体クラスは、データベースの操作をより細かく行うための追加のスロット(例えばロックを
     行うかどうか)を持つかもしれません。

      -- Instance Variable of <dbm>: path
          データベースファイルのパス名。dbmの実装によっては、このパスにサフィックスが追加されます。

      -- Instance Variable of <dbm>: rw-mode
          読み書きのモードを指定します。以下の値のいずれかを取ります。
         `:read'
               データベースは`dbm-open'によって読みだし専用モードでオープンされます。
               オープンされる時点でデータベースは存在していなければなりません。

         `:write'
               データベースは`dbm-open'によって読み書き可能なモードでオープンされます。
               データベースが存在しなければ、`dbm-open'は新しいデータベースを作成します。

         `:create'
               `dbm-open'によって新しいデータベースが作成され、読み書き可能なモードでオープンされます。
               既にデータベースが存在していた場合、その内容はクリアされます。

      -- Instance Variable of <dbm>: file-mode
          データベースが作成されるときのファイルパーミッションを指定します。
          デフォルトは`#o664'です。

      -- Instance Variable of <dbm>: key-convert
      -- Instance Variable of <dbm>: value-convert
          デフォルトでは、dbmデータベースはキーにも値にも文字列しか使うことはできません。
          これらのスロットによって、それ以外のSchemeオブジェクトを取り扱う方法を指定することが
          できます。以下の値のいずれかが可能です。
         `#f'
               デフォルトの値です。キーあるいは値は変換されません。それらは文字列でなければなりません。

         `#t'
               キーあるいは値は`write'を使って文字列に変換されデータベースに格納されます。
               そして`read'を使って文字列からSchemeオブジェクトへと変換されます。
               後で`read'で読みこめるようなキーあるいは値のみを扱うことができます。
               (但し、dbmライブラリは書き込み時にそれが後で読み込めるかどうかのチェックは行いません)。
               キーの比較は文字列に変換された後で行われるので、同じ値となるキーは同じ文字列表現を
               持つ必要があります。

         二つの手続きのリスト
               どちらの手続きも一つの引数を取ります。最初の手続きはSchemeオブジェクトを受け取り、
               文字列を返します。キーあるいは値をデータベースに格納する時に呼ばれます。
               二つ目の手続きは文字列を受け取りSchemeオブジェクトを返します。データベースから
               キーあるいは値を取り出す時に呼ばれます。
               キーの比較は文字列に変換された後で行われるので、同じ値となるキーは同じ文字列に
               変換される必要があります。

 -- Metaclass: <dbm-meta>
     <DBM>クラス及びそのサブクラスのメタクラスです。

 -- Method: dbm-open (dbm <dbm>)
     DBMデータベースをオープンします。DBMは、`<dbm>'クラスを継承した
     具体クラスのインスタンスでなければなりません。また、そのスロットには適切な値が
     セットされている必要があります。オープンに成功したらDBM自身が返されます。
     失敗した場合はエラーが報告されます。

 -- Method: dbm-open (dbm-class <dbm-meta>) options ...
     DBMインスタンスを作成してオープンするための便利なメソッドです。
     次のように定義されます。
          (define-method dbm-open ((class <class>) . initargs)
            (dbm-open (apply make class initargs)))

   データベースファイルはガベージコレクトされる際にクローズされますが、
変更を正しくデータベースに反映するには、明示的にクローズした方が良いでしょう。

 -- Method: dbm-close (dbm `<dbm>')
     データベースDBMをクローズします。データベースがクローズされると、
     それ以降のアクセスオペレーションはエラーとなります。

 -- Method: dbm-closed? (dbm `<dbm>')
     データベースDBMが既にクローズされていたら`#t'を返します。


File: gauche-refj.info,  Node: DBMデータベースのアクセス,  Next: DBMデータベース上の繰り返し処理,  Prev: DBMデータベースのオープンとクローズ,  Up: 汎用DBMインタフェース

11.2.2 DBMデータベースのアクセス
--------------------------------

データベースがオープンされたら、以下のアクセスメソッドが使えます。

 -- Method: dbm-put! (dbm `<dbm>') key value
     値VALUEをキーKEYと関連付けて保存します。

 -- Method: dbm-get (dbm `<dbm>') key &optional default
     キーKEYに関連付けられた値を返します。もし値が存在しなければ、DEFAULTが
     与えられていればそれを返し、そうでなければエラーを報告します。

 -- Method: dbm-exists? (dbm `<dbm>') key
     キーKEYに関連付けられた値が存在すれば`#t'を返します。

 -- Method: dbm-delete! (dbm `<dbm>') key
     キーKEYに関連付けられた値を消去します。値が存在しない場合は何もしません。


File: gauche-refj.info,  Node: DBMデータベース上の繰り返し処理,  Next: DBMデータベースインスタンスの管理,  Prev: DBMデータベースのアクセス,  Up: 汎用DBMインタフェース

11.2.3 DBMデータベース上の繰り返し処理
--------------------------------------

全データベースを渡り歩く処理のために、以下のメソッドが用意されています。

 -- Method: dbm-fold (dbm `<dbm>') procedure knil
     基本的な繰り返し処理です。データベース内の各キー／値のペアに関して、手続き
     PROCEDUREが `(PROCEDURE KEY VALUE R)',
     のように呼ばれます。ここでRは、最初のPROCEDUREの呼び出しの時にはKNIL
     が、以降の呼び出しの時にはその直前のPROCEDUREが返した値が渡されます。
     最後のPROCEDUREの戻り値が`dbm-fold'の戻り値となります。
     データベース中にデータがひとつもなければKNILがそのまま返されます。

     次の例は、データベース中の整数の値を全て加算します。
          (dbm-fold dbm (lambda (k v r) (if (integer? v) (+ v r) r)) 0)

 -- Method: dbm-for-each (dbm `<dbm>') procedure
     データベース内の各キー／値のペアに関して、手続きPROCEDUREを呼び出します。
     PROCEDUREにはキーと値が渡されます。PROCEDUREの戻り値は捨てられます。

 -- Method: dbm-map (dbm `<dbm>') procedure
     データベース内の各キー／値のペアに関して、手続きPROCEDUREを呼び出します。
     PROCEDUREにはキーと値が渡されます。PROCEDUREの戻り値はリストに
     集められて`dbm-map'の戻り値となります。


File: gauche-refj.info,  Node: DBMデータベースインスタンスの管理,  Prev: DBMデータベース上の繰り返し処理,  Up: 汎用DBMインタフェース

11.2.4 DBMデータベースインスタンスの管理
----------------------------------------

各DBM実装は、データベースを格納するのに独自の方法を使います。
レガシーなDBMは、PATHスロットの値にそれぞれ`.dir'と
`.pag'を付けた名前の2つのファイルを使います。
`fsdbm'はPATHの下にディレクトリを作ります。
DBMデータベースが他のデータベースサーバによってバック
アップされる場合は、PATHはそのサーバで単なるキーと
して使われるでしょう。

   以下のメソッドは、そのようなバリエーションを隠し、
データベースそれ自体を管理する簡易な方法を提供します。
最初の引数に、具体的なDBMデータベースを実装している
クラスを渡す必要があります。

 -- Generic Function: dbm-db-exists? class name
     NAMEで指定されたCLASS暮らすのデータベースが
     存在する場合は`#t'を返します。

          ;; Returns #t if testdb.dir and testdb.pag exist
          (dbm-db-exists? <odbm> "testdb")

 -- Generic Function: dbm-db-remove class name
     NAMEで指定されるCLASSクラスのデータベース 全体を削除します。

 -- Generic Function: dbm-db-copy class from to
     FROMで指定されたCLASSクラスのデータベースを TOへコピーします。

          (dbm-db-copy <gdbm> "testdb.dbm" "backup.dbm")

 -- Generic Function: dbm-db-move class from to
     FROMで指定されたCLASSクラスのデータベースを
     TOへ移動、あるいはリネームします。


File: gauche-refj.info,  Node: ファイルシステムdbm,  Next: GDBMインタフェース,  Prev: 汎用DBMインタフェース,  Up: ライブラリモジュール - ユーティリティ

11.3 `dbm.fsdbm' - ファイルシステムdbm
======================================

 -- Module: dbm.fsdbm
     Implements fsdbm.  Extends `dbm'.

 -- Class: <fsdbm>
     `fsdbm'は、直接ファイルシステムを扱うDBM実装です。
     基本的には、ファイル名をキー、ファイルの内容を値として使います。
     他のDBM実装とは違い、これは他の特別なライブラリに依存しません
     (純粋にSchemeのみにより実装されています)。
     したがって、他のDBM実装が使えないときでも、いつでも使うことが
     できます。

     明らかに、たくさんのエントリを持っていたり、エントリの追加や
     削除が頻繁に起こるようなデータベースには向いていません。
     エントリの数が相対的に小さく、キーが小さいのに値が大きいような
     場合に向いています。

     `<fsdbm>'のインスタンスに与えられるデータベース名は、
     データを格納するディレクトリの名前として使われます。

     データのファイルは、`fsdbm'インスタンスのPATHの
     サブディレクトリに格納され、キーによりハッシュされます。
     キーに英数字でない文字がある場合はエンコードされます。
     例えば、'`:''は、`_3a'にエンコードされます。
     キーがファイル名としては長すぎる場合は、いくつかに
     分割され、その最後の文字列片以外はディレクトリ名として
     使われます。長いキー名は問題を引き起こすかも知れないことに
     注意して下さい。例えば、いくつかの古い'tar'コマンドは、256文字
     を越える長いパス名を扱えません(それぞれのパスコンポーネント
     ではなく、パス名全体でです)。

   fsdbmは、全てのDBMプロトコルを実装しています (*Note
汎用DBMインタフェース::参照)。 fsdbm特有の手続きというものはありません。


File: gauche-refj.info,  Node: GDBMインタフェース,  Next: NDBMインタフェース,  Prev: ファイルシステムdbm,  Up: ライブラリモジュール - ユーティリティ

11.4 `dbm.gdbm' - GDBMインタフェース
====================================

 -- Module: dbm.gdbm
     Provides interface to the gdbm library.  Extends `dbm'.

 -- Class: <gdbm>
     `<dbm>' を継承します。GDBM ライブラリのための実装を提供します。
     このモジュールは、すでにあなたのシステムにすでに GDBM
     がある場合にのみ インストールされます(バージョン 1.8.0
     が推奨されますが、いくつかの制限が あるだけで古い 1.7.x
     でも動作します)。

      -- Instance Variable of <gdbm>: sync

      -- Instance Variable of <gdbm>: nolock

      -- Instance Variable of <gdbm>: bsize

   統合された DBM インターフェース (*Note 汎用DBMインタフェース::) の
他に、このモジュールでは GDBM API への直接のアクセスを提供する以下の
低レベルな手続きを提供しています。これらの API の詳細については GDBM の
マニュアルを見て下さい。

 -- Function: gdbm-open path &optional size rwmode fmode error-callback
      -- Variable: GDBM_READER

      -- Variable: GDBM_WRITER

      -- Variable: GDBM_WRCREAT

      -- Variable: GDBM_NEWDB

      -- Variable: GDBM_FAST

      -- Variable: GDBM_SYNC

      -- Variable: GDBM_NOLOCK

 -- Function: gdbm-close gdbm-object

 -- Function: gdbm-closed? gdbm-object

 -- Function: gdbm-store key value &optional flag
      -- Variable: GDBM_INSERT

      -- Variable: GDBM_REPLACE


 -- Function: gdbm-fetch gdbm-object key

 -- Function: gdbm-delete gdbm-object key

 -- Function: gdbm-firstkey gdbm-object

 -- Function: gdbm-nextkey gdbm-object key

 -- Function: gdbm-reorganize gdbm-object

 -- Function: gdbm-sync gdbm-object

 -- Function: gdbm-exists gdbm-object key

 -- Function: gdbm-strerror errno

 -- Function: gdbm-setopt gdbm-object option value
      -- Variable: GDBM_CACHESIZE

      -- Variable: GDBM_FASTMODE

      -- Variable: GDBM_SYNCMODE

      -- Variable: GDBM_CENTFREE

      -- Variable: GDBM_COALESCEBLKS

 -- Function: gdbm-version

 -- Function: gdbm-errno


File: gauche-refj.info,  Node: NDBMインタフェース,  Next: オリジナルのDBMインタフェース,  Prev: GDBMインタフェース,  Up: ライブラリモジュール - ユーティリティ

11.5 `dbm.ndbm' - NDBMインタフェース
====================================

 -- Module: dbm.ndbm
     Provides interface to the 'new' dbm library, a.k.a. ndbm.  Extends
     `dbm'.

 -- Class: <ndbm>
     `<dbm>' を継承します。NDBM ライブラリのための実装を提供します。
     このモジュールはあなたのシステムにすでに NDBM がある場合にのみ
     インストールされます。

   統合された DBM インターフェース (*Note 汎用DBMインタフェース::) の
他に、このモジュールでは NDBM API への直接のアクセスを提供する以下の
低レベルな手続きを提供しています。これらの API の詳細については NDBM の
マニュアルを見て下さい。

 -- Function: ndbm-open path flags mode

 -- Function: ndbm-close ndbm-object

 -- Function: ndbm-closed? ndbm-object

 -- Function: ndbm-store ndbm-object key content &optional flag

 -- Function: ndbm-fetch ndbm-object key

 -- Function: ndbm-delete ndbm-object key

 -- Function: ndbm-firstkey ndbm-object

 -- Function: ndbm-nextkey ndbm-object

 -- Function: ndbm-error ndbm-object

 -- Function: ndbm-clear-error ndbm-object


File: gauche-refj.info,  Node: オリジナルのDBMインタフェース,  Next: ファイルのフィルタ,  Prev: NDBMインタフェース,  Up: ライブラリモジュール - ユーティリティ

11.6 `dbm.odbm' - オリジナルのDBMインタフェース
===============================================

 -- Module: dbm.odbm
     Provides interface to the legacy dbm library.  Extends `dbm'.

 -- Class: <odbm>
     `<dbm>' を継承しています。レガシーな DBM ライブラリのための実装を
     提供します。このモジュールは、あなたのシステムにすでに DBM
     がある場合にのみ インストールされます。

     レガシー DBM
     の最大の制限は、データベースを一時に一つしか開けないことです。
     複数の `<odbm>'
     のインスタンスを作ることができますが、一時に一つしか
     開くことが出来ず、一つ以上開こうとするとエラーになります。

   統合された DBM インターフェース (*Note 汎用DBMインタフェース::) の
他に、このモジュールでは DBM API への直接のアクセスを提供する以下の
低レベルな手続きを提供しています。これらの API の詳細については DBM の
マニュアルを見て下さい。

 -- Function: odbm-init path

 -- Function: odbm-close

 -- Function: odbm-store key value

 -- Function: odbm-fetch key

 -- Function: odbm-delete key

 -- Function: odbm-firstkey

 -- Function: odbm-nextkey key


File: gauche-refj.info,  Node: ファイルのフィルタ,  Next: ファイルシステムユーティリティ,  Prev: オリジナルのDBMインタフェース,  Up: ライブラリモジュール - ユーティリティ

11.7 `file.filter' - ファイルのフィルタ
=======================================

 -- Module: file.filter
     このモジュールは、フィルター型のコマンド、
     すなわち入力を読み込み、処理をして結果を書き出すような場合に
     共通するパターンに使えるユーティリティ手続きを提供します。
     共通するパターンとは：

        *
          入力は指定されたファイルかポートで、デフォルトはカレント入力ポート。

        *
          出力は指定されたファイルかポートで、デフォルトはカレント出力ポート。

        * 出力は一時ファイルに書き出すこともできて、
          その場合は処理が終了した時点で指定されたファイルにリネーム。

        * 処理途中でエラーが起こった場合に出力ファイルを削除

 -- Function: file-filter proc &keyword input output temporary-file
          keep-output?
     二つの引数、入力ポートと出力ポートを引数としてPROCを呼び出し、
     その結果を返します。
     入力ポートと出力ポートはキーワード引数により決定されます。

    `input'
          この引数は入力ポートかファイル名を示す文字列でなければなりません。
          入力ポートの場合、それはそのままPROCに渡されます。
          文字列が渡された場合は、そのファイル名を持つファイルを入力用にオープンし、
          そのポートがPROCに渡され、またこのポートはPROCが戻った時に閉じられます。
          この引数が省略された場合は、現在の入力ポートが渡されます。

    `output'
          この引数は入力ポートかファイル名を示す文字列でなければなりません。
          出力ポートの場合、それはそのままPROCに渡されます。
          文字列が渡された場合は、そのファイル名を持つファイルを出力用にオープンし、
          そのポートがPROCに渡されます (但し、TEMPORARY-FILE
          引数が渡された時はそれに指定されるファイルが一時ファイルとしてオープンされます)。
          オープンされたポートはPROCが戻った時に閉じられます。
          この引数が省略された場合は、現在の出力ポートが渡されます。

    `temporary-file'
          文字列でファイル名が渡された場合、処理の間の出力先としてOUTPUTに指定された
          ファイルのかわりにそのファイルがオープンされます。
          PROCにはその一時ファイルへの出力ポートが渡されます。
          PROCが正常に返って来た時点で、一時ファイルはOUTPUTに指定された
          ファイルへとリネームされます。

          もし一時ファイル名が`"/"'、`"./"'、`"../"'以外の
          文字で始まっていた場合は、OUTPUTに与えられたファイル名のディレクトリが
          一時ファイルの前に追加されます。さらに、ユニークなサフィックスが一時ファイルの後に
          追加されます(一時ファイルは`sys-mkstemp'を使ってオープンされます)。

          この引数は、OUTPUTにファイル名が与えられなかった場合は無視されます。

    `keep-output?'
          真の値が与えられた場合、PROCがエラーになった場合でも出力ファイルを削除しません。
          デフォルトでは、出力ファイル(もしくはTEMPORARY-FILEが与えられた場合は
          そのファイル)はエラーの場合には削除されます。


File: gauche-refj.info,  Node: ファイルシステムユーティリティ,  Next: 定数,  Prev: ファイルのフィルタ,  Up: ライブラリモジュール - ユーティリティ

11.8 `file.util' - ファイルシステムユーティリティ
=================================================

 -- Module: file.util
     ファイルやディレクトリを扱う便利な手続き群を提供します。
     これらの手続きは*Note
     ファイルシステム::で述べられたプリミティブなシステム手続きの上に
     構築されています。

     このモジュール内の多くの手続きはFOLLOW-LINK?というキーワード引数を取ります。
     これは手続きがシンボリックリンクに出会ったときの動作を指定します。FOLLOW-LINK?が
     真であれば、手続きはリンクの指す先のファイルに作用します。これがデフォルトの振舞いです。
     FOLLOW-LINK?に`#f'が渡された場合は手続きはリンクそのものに作用します。

   名前つけ規則に関する注記：ファイルやディレクトリを
作成するのに`"create"'という語を使う処理系と`"make"'を
使う処理系があります。ファイルやディレクトリを削除するのにも`"remove"'と
`"delete"'の流派があります。どちらも同じくらい広く使われているようなので、
Gaucheでは_両方の_名前を提供することにしました。

* Menu:

* ディレクトリユーティリティ::
* パスネームユーティリティ::
* ファイル属性ユーティリティ::
* ファイル操作::


File: gauche-refj.info,  Node: ディレクトリユーティリティ,  Next: パスネームユーティリティ,  Prev: ファイルシステムユーティリティ,  Up: ファイルシステムユーティリティ

11.8.1 ディレクトリユーティリティ
---------------------------------

 -- Function: current-directory &optional new-directory
     引数無しで呼ばれた場合、カレントディレクトリを返します。
     文字列NEW-DIRECTORYが与えられた場合はプロセスのカレントディレクトリを
     NEW-DIRECTORYに変更します。変更が出来なかった場合はエラーとなります。

     この関数はChezSchemeやMzSchemeなどいくつかのScheme処理系に見られます。

 -- Function: home-directory &optional user
     名前または整数のユーザidで与えられたユーザUSERのホームディレクトリを
     返します。USERが省略された場合はカレントユーザが使われます。
     与えられたユーザが見付けられないか、ホームディレクトリを決定できなかった場合は
     `#f'が返されます。

 -- Function: temporary-directory
     一時ファイルを作るのに適したディレクトリ名を返します。
     現在のところ、この手続きは常に`/tmp'を返しますが、
     将来はプラットフォームやシステム特有の設定を反映しするように
     なるかもしれません。

 -- Function: directory-list path &keyword children? add-path? filter
          filter-add-path?
     ディレクトリPATH中のエントリのリストを返します。
     リストは文字列順にソートされます。

     デフォルトではエントリのベースネーム(パスの最後のコンポーネント)のみが
     返されますが、キーワード引数ADD-PATH?に真の値が与えられた時は
     PATHが各エントリの前に追加されます。
     CHILDREN?に真の値が与えられた時は、カレントディレクトリと親ディレクトリが
     リストから除かれます。

     FILTER引数は、もし与えられれば、一つの引数を取る
     手続きでなければなりません。ディレクトリ中の各エントリを引数としてその手続きが呼ばれ、
     真を返したエントリのみが結果に含まれます。
     FILTERに与えられるエントリはデフォルトではベース名のみですが、
     引数FILTER-ADD-PATH?が真ならばPATHが前に追加された名前となります。

     PATHがディレクトリでない場合はエラーが報告されます。

          (directory-list "test")
           => ("." ".." "test.scm" "test.scm~")

          (directory-list "test" :add-path? #t)
           => ("test/." "test/.." "test/test.scm" "test/test.scm~")

          (directory-list "test" :children? #t)
           => ("test.scm" "test.scm~")

          (directory-list "test" :children? #t :add-path? #t
             :filter (lambda (e) (not (string-suffix? "~" e))))
           => ("test/test.scm")

 -- Function: directory-list2 path &keyword children? add-path? filter
          follow-link?
     `directory-list'に似ていますが、ふたつの値を返します。最初の値は
     PATH内にあるサブディレクトリのリストで、次の値はそれ以外のエントリのリストです。
     キーワード引数CHILDREN?、`add-path?'、FILTERは
     `directory-list'と同じ意味をもちます。

     偽の値をFOLLOW-LINK?に与えると、PATH内のシンボリックリンクを
     辿りません；すなわち、PATH内にディレクトリへのシンボリックリンクがあった場合、
     デフォルト、もしくはFOLLOW-LINK?に真の値が与えられた場合は
     それは最初のリスト(サブディレクトリ)に入りますが、FOLLOW-LINK?
     に偽の値が与えられた場合は後者のリスト(その他のエントリ)に入ります。

 -- Function: directory-fold path proc knil &keyword lister follow-link?
     ディレクトリ探索の最も基本的な手続きです。基本的な動作は以下に示すような再帰的なものです。

        * PATHがディレクトリでない場合は`(PROC PATH KNIL)' を
          評価し、結果を返します。

        * PATHがディレクトリであった場合、まず (LISTER PATH KNIL)
          を評価します。
          手続きLISTERはパス名のリストを返さなければなりません。
          続いて、`directory-fold'が各パス名に対して再帰的に呼ばれます。
          各呼び出しの結果が次の再帰呼び出しのKNILの値に使われます。

     デフォルトのLISTERは`directory-list'を次のように呼び出すものです。
          (lambda (path knil)
            (directory-list path :add-path? #t :children? #t)))))

     LISTERはPATH自身への参照 (`"."') やその親ディレクトリへの参照を
     返してはなりません。また、LISTERの戻り値は現在のディレクトリからアクセス可能な
     パス名でなければなりません。例えばPATHが`"/usr/lib/foo"'であり、
     そのディレクトリが`"libfoo.a"'と`"libfoo.so"'を含んでいた場合、
     LISTERは`'("/usr/lib/foo/libfoo.a" "/usr/lib/foo/libfoo.so")'
     のようなリストを返す必要があります。

     キーワード引数FOLLOW-LINK?はディレクトリを指しているシンボリックリンクに対して
     LISTERを呼ぶかどうかを決定します。FOLLOW-LINK?が真(デフォルト値)である
     場合はそのようなシンボリックリンクに対してもLISTERが呼ばれます。
     一方、FOLLOW-LINK?が偽であればシンボリックリンクに対してはPROCが呼ばれます。

     次の例は、与えられたpath以下からemacsのバックアップファイル
     ("~"で終る名を持つファイル) のリストを返します。
          (use srfi-13) ;; for string-suffix?
          (directory-fold path
                          (lambda (entry result)
                            (if (string-suffix? "~" entry)
                                (cons entry result)
                                result))
                          '())


 -- Function: make-directory* name &optional perm
 -- Function: create-directory* name &optional perm
     ディレクトリNAMEを作成します。NAMEに至るパスが存在しない
     場合は必要なディレクトリが作成されます (Unixの`mkdir -p'コマンドと
     同様です)。ディレクトリNAMEが既に存在していた場合は何もしません。
     PERMは作成されるディレクトリのパーミッションビットを指定します。

 -- Function: remove-directory* name
 -- Function: delete-directory* name
     ディレクトリNAMEとその内容を再帰的に消去します (Unixの`rm
     -r'コマンドと同様です)。シンボリックリンクは辿られません。


File: gauche-refj.info,  Node: パスネームユーティリティ,  Next: ファイル属性ユーティリティ,  Prev: ディレクトリユーティリティ,  Up: ファイルシステムユーティリティ

11.8.2 パスネームユーティリティ
-------------------------------

 -- Function: build-path base-path component ...
     パス名のコンポーネントCOMPONENTをBASE-PATHに追加します。
     COMPONENTはシンボル`up'または`same'であっても 構いません;
     Unixではそれらは`".."'または`"."'と等価です。
     このAPIはMzSchemeから採られました。

 -- Function: absolute-path? path
 -- Function: relative-path? path
     PATHがそれぞれ絶対パスまたは相対パスならば`#t'を返します。

 -- Function: expand-path path
     PATHがチルダ表記を含んでいたらそれを展開したものを返します。
     そうでなければPATHそのものを返します。この手続きはPATHが
     存在しアクセス可能であるかどうかはチェックしません。

 -- Function: resolve-path path
     PATHを`expand-path'と同様に展開し、
     続いてPATHの各コンポーネントに対してそれがシンボリックリンクであればリンク先の
     ものに置き換えてゆきます。PATHが存在しないパスを指していたり、
     シンボリックリンクの先が存在しなかったり、読み出せないディレクトリがあった場合は
     エラーとなります。

 -- Function: simplify-path path
     PATHから、親ディレクトリへの参照(`".."')と自分自身への参照(`"."')を
     出来る限り取り除きます。この手続きはファイルシステムへはアクセスしません。

 -- Function: decompose-path path
     パス名PATHのディレクトリ部、拡張子を除いたファイル名、
     そして拡張子の3つの値を返します。パス名が拡張子を持たない場合、
     最後の値は`#f'になります。パス名がディレクトリセパレータで
     終わっている場合は2番目と3番目の値が`#f'になります。
     (後置されたディレクトリセパレータに関するこの取扱いは、
     `sys-dirname'/`sys-basename'と異なることに注意して下さい。
     `sys-dirname'等は後置されたディレクトリセパレータを無視するという
     シェル等の慣習に従っています。)
          (decompose-path "/foo/bar/baz.scm")
            => "/foo/bar", "baz", "scm"
          (decompose-path "/foo/bar/baz")
            => "/foo/bar", "baz", #f

          (decompose-path "baz.scm")
            => ".", "baz", "scm"
          (decompose-path "/baz.scm")
            => "/", "baz", "scm"

          ;; Boundary cases
          (decompose-path "/foo/bar/baz.")
            => "/foo/bar", "baz", ""
          (decompose-path "/foo/bar/.baz")
            => "/foo/bar", ".baz", #f
          (decompose-path "/foo/bar.baz/")
            => "/foo/bar.baz", #f, #f

 -- Function: path-extension path
 -- Function: path-sans-extension path
     それぞれ、PATHの拡張子と、PATHから拡張子を除いたものを返します。
     PATHが拡張子を持っていない場合はそれぞれ`#f'とPATHが返されます。

          (path-extension "/foo/bar.c")       => "c"
          (path-sans-extension "/foo/bar.c")  => "/foo/bar"

          (path-extension "/foo/bar")         => #f
          (path-sans-extension "/foo/bar")    => "/foo/bar"

 -- Function: path-swap-extension path newext
     PATHの拡張子がNEWEXTに置換されたものが返されます。`path'が
     拡張子を持たない場合は、PATHに "." とNEWEXTが追加されます。

     NEWEXTが`#f'の場合は、PATHの拡張子が除かれたものが
     返されます。すなわち、

          (path-swap-extension "/foo/bar.c" "o")  => "/foo/bar.o"
          (path-swap-extension "/foo/bar.c" #f)   => "/foo/bar"

 -- Function: find-file-in-paths name &keyword paths pred
     名前NAMEを持ち、述語PREDを満たすファイルをパス名のリストPATHS
     から探します。見つかった場合はファイルの絶対パス名を、見つからなかった場合は
     `#f'を返します。

     NAMEが絶対パス名で与えられた場合はそれが存在するかどうかと
     PREDを満たすかどうかのみがチェックされます。

     PATHSのデフォルト値は環境変数`PATH'から取られます。また、
     PREDのデフォルト値は`file-is-executable?' (*Note
     ファイル属性ユーティリティ::参照)です。すなわち、デフォルトでは
     この手続きはコマンドサーチパスから実行可能ファイルを探すのに使えます。

          (find-file-in-paths "ls")
            => "/bin/ls"

          ;; アプリケーション"myapp"のユーザプレファレンスファイルを探す例
          (find-file-in-paths "userpref"
            :paths `(,(expand-path "~/.myapp")
                     "/usr/local/share/myapp"
                     "/usr/share/myapp")
            :pred  file-is-readable?)


File: gauche-refj.info,  Node: ファイル属性ユーティリティ,  Next: ファイル操作,  Prev: パスネームユーティリティ,  Up: ファイルシステムユーティリティ

11.8.3 ファイル属性ユーティリティ
---------------------------------

 -- Function: file-type path &keyword follow-link?
 -- Function: file-perm path &keyword follow-link?
 -- Function: file-mode path &keyword follow-link?
 -- Function: file-ino path &keyword follow-link?
 -- Function: file-dev path &keyword follow-link?
 -- Function: file-rdev path &keyword follow-link?
 -- Function: file-nlink path &keyword follow-link?
 -- Function: file-uid path &keyword follow-link?
 -- Function: file-gid path &keyword follow-link?
 -- Function: file-size path &keyword follow-link?
 -- Function: file-atime path &keyword follow-link?
 -- Function: file-mtime path &keyword follow-link?
 -- Function: file-ctime path &keyword follow-link?
     これらの手続きはPATHで示されるファイルやディレクトリのアトリビュートを
     返します。アトリビュート名は`<sys-stat>'のスロット名に対応しています。
     *Note ファイルの状態::を参照して下さい。PATHで示されるファイルが
     存在しなければ`#f'が返されます。

     PATHがシンボリックリンクだった場合、オプショナルな引数
     FOLLOW-LINK? に偽の値が与えられていない限り、これらの手続きは
     リンクの指す先のファイルに関する情報を返します。

     MzSchemeとChickenには`file-size'があります。
     Chickenには`file-modification-time'があり、これは`file-mtime'と
     同じです。

 -- Function: file-is-readable? path
 -- Function: file-is-writable? path
 -- Function: file-is-executable? path
     PATHが存在して、現在の実効ユーザがそれぞれ読み取り/書き込み/実行可能なら`#t'を
     返します。 このAPIはSTkから取られました。

 -- Function: file-is-symlink? path
     PATHが存在して、それがシンボリックリンクなら`#t'を返します。
     (参照：*Note ファイルの状態::の`file-is-regular?',
     `file-is-directory?').

 -- Function: file-eq? path1 path2
 -- Function: file-eqv? path1 path2
 -- Function: file-equal? path1 path2
     PATH1とPATH2で示されるファイルを比較します。
     `file-eq?'と`file-eqv?'はPATH1とPATH2が
     全く同一のファイルを参照しているかどうか、すなわち、同じデバイス上にあり同じ
     inode番号を持つかどうかをチェックします。二つの手続きの違いは、
     `path1'やPATH2の最後のコンポーネントがシンボリックリンクで
     あった場合に、FILE-EQ?はリンクそのものの比較をするが
     `file-eqv?'はリンクを辿った先のファイルの比較をする、という点です。

     `file-equal?'はPATH1とPATH2をその内容まで考慮して比較します。
     すなわち、二つのファイルが`file-eqv?'の意味で同一でなかった場合、
     `file-equal?'はファイルの内容を比較し、全てが一致した場合に`#t'を返します。

     PATH1とPATH2ともにディレクトリが与えられた場合の
     `file-equal?'の動作は未定義です。将来、ディレクトリ内容を
     スキャンするような拡張が加えられるかもしれません。

 -- Generic Function: file-mtime=? f1 f2
 -- Generic Function: file-mtime<? f1 f2
 -- Generic Function: file-mtime<=? f1 f2
 -- Generic Function: file-mtime>? f1 f2
 -- Generic Function: file-mtime>=? f1 f2
     二つのファイルの変更時間を比較します。それぞれの引数に対して、
     次のような型のオブジェクトが渡せるようなメソッドが定義されています。

        *
          文字列のパス名。そのパス名で示されるファイルから変更時間が取られます。

        * `<sys-stat>'オブジェクト (*Note ファイルの状態::)。
          stat構造体から変更時間が取られます。

        * `<time>'オブジェクト。その示す時間が変更時間と考えられます。

        * 数値。変更時間をUnix
          Epochからの秒数で表したものと見なされます。

          ;; "foo.c" より "foo.o" が新しいかどうか調べる
          (file-mtime>? "foo.c" "foo.o")

          ;; "foo.log"が過去24時間以内に更新されたかどうかを調べる
          (file-mtime>? "foo.c" (- (sys-time) 86400))

 -- Generic Function: file-ctime=? f1 f2
 -- Generic Function: file-atime=? f1 f2
     `file-mtime=?'と同じですが、ファイルの属性変更時間とアクセス時間に
     関して比較します。 `<', `<=', `>',
     `>='を使う関数も同様に定義されています。


File: gauche-refj.info,  Node: ファイル操作,  Prev: ファイル属性ユーティリティ,  Up: ファイルシステムユーティリティ

11.8.4 ファイル操作
-------------------

 -- Function: touch-file path
     PATHのタイムスタンプを現在の時刻に更新します。
     PATHが存在しなかった場合はそのファイルを作成します。 *Note
     ファイルの状態::の`sys-utime'も参照して下さい。

 -- Function: copy-file src dst &keyword if-exists backup-suffix safe
          keep-timestamp
     ファイルSRCをDSTへコピーします。コピー元ファイルSRCは
     存在していなければなりません。コピー先ファイルDSTが存在していた場合の
     ふるまいはキーワード引数IF-EXISTSによって以下のように指定されます。

    `:error'
          (デフォルト) DSTが存在していたらエラーを通知する。

    `:supersede'
          DSTを`src'のコピーで置き換える。

    `:backup'
          DSTの名前を変えてキープする。

    `#f'
          DSTが存在していたらコピーをせず`#f'を返す。

     `copy-file'はコピーが完了したら`#t'を返します。

     IF-EXISTSが`:backup'である場合、 DSTがリネームされる名前は
     DSTにキーワード引数BACKUP-SUFFIXで指定されるサフィックスを
     付けたものとなります。デフォルト値は`".orig"'です。

     デフォルトでは`copy-file'は直接DSTにコピーを行いますが、
     キーワード引数SAFEに真の値が与えられた場合は、DSTと同じディレクトリ
     内の一時ファイルにまずコピーし、それが完了した時点でDSTへとリネームします。
     コピーが何らかの理由で中断された場合、ファイルシステムはコピー前の状態へと
     「ロールバック」されます。

     キーワード引数KEEP-TIMESTAMPに真の値が与えられた場合は、
     `copy-file'はコピー後にコピー先のファイルのタイムスタンプを
     コピー元のタイムスタンプに合わせます。

 -- Function: move-file src dst &keyword if-exists backup-suffix
     ファイルSRCをDSTへ移動します。移動元ファイルSRCは
     存在していなければなりません。移動先ファイルDSTが存在した場合の
     ふるまいはキーワード引数IF-EXISTSによって以下のように指定されます。
    `:error'
          (デフォルト) DSTが存在していたらエラーを通知する。

    `:supersede'
          DSTを`src'で置き換える。

    `:backup'
          DSTの名前を変えてキープする。

    `#f'
          DSTが存在していたら移動をせず`#f'を返す。

     `move-file'は移動が完了したら`#t'を返します。

     IF-EXISTSが`:backup'である場合、DSTがリネームされる
     名前はDSTにキーワード引数BACKUP-SUFFIXで指定されるサフィックスを
     付けたものとなります。デフォルト値は`".orig"'です。

     ファイルSRCとDSTは別のファイルシステム上にあっても構いません。
     その場合、`move-file'はまずSRCをDSTと同じディレクトリの
     一時ファイルにコピーし、それをDSTにリネームし、それから
     SRCを消去します。

 -- Function: file->string filename options ...
 -- Function: file->list reader filename options ...
 -- Function: file->string-list filename options ...
 -- Function: file->sexp-list filename options ...
     ファイル FILENAME から読み込むための便利手続き。
     これらの手続きは、まず、指定された名前のファイルをオープンし、その
     オープンしたファイルに対してそれぞれ `port->string'、
     `port->list'、`port->string-list' および `port->sexp-list'
     を呼びます(*Note
     入力ユーティリティ手続き::参照)。すべての内容が読み込まれる
     かまたは読み込み中にエラーシグナルがあがれば、ファイルはクローズされます。

     すべてのオプション引数 OPTIONS ... はそのまま
     `call-with-input-file' に渡されます。


File: gauche-refj.info,  Node: 定数,  Next: Mersenne Twister乱数発生器,  Prev: ファイルシステムユーティリティ,  Up: ライブラリモジュール - ユーティリティ

11.9 `math.const' - 定数
========================

 -- Module: math.const
     いくつかの一般的に用いられる数学定数を定義しています。

 -- Constant: pi
 -- Constant: pi/2
 -- Constant: pi/4
 -- Constant: pi/180
 -- Constant: 1/pi
 -- Constant: 180/pi
     それぞれ、π、π/2、π/4、π/180、1/π、180/πです。

 -- Constant: e
     e.


File: gauche-refj.info,  Node: Mersenne Twister乱数発生器,  Next: RFC822メッセージ形式,  Prev: 定数,  Up: ライブラリモジュール - ユーティリティ

11.10 `math.mt-random' - Mersenne Twister乱数発生器
===================================================

 -- Module: math.mt-random
     Makoto MatsumotoとTakuji Nishimuraにより開発された、 "Mersenne
     Twister"アルゴリズムに基づく、
     仮想的な乱数発生器(RNG)を提供します。
     高速で、2^19937-1という極めて長大な周期を持ちます。
     アルゴリズムの詳細については、*Note MT: MT.を参照して下さい。

 -- Class: <mersenne-twister>
     Mersenne Twister RNGの状態をカプセル化するクラスです。
     このクラスのそれぞれのインスタンスは独自の状態を持ち、
     個別のシードで初期化されていれば、それぞれがランダムビットの
     独立したソースになり得ます。

     ランダムシードの値は初期化引数`:seed'により初期化時に与えるか、
     以下で説明する`mt-random-set-seed!'を使います。

          (define m (make <mersenne-twister> :seed (sys-time)))

          (mt-random-real m) => 0.10284287848537865
          (mt-random-real m) => 0.463227748348805
          (mt-random-real m) => 0.8628500643709712
          ...

 -- Function: mt-random-set-seed! mt seed
     Mersenne Twister RNG MTにランダムシードの値SEEDをセットします。
     SEEDは任意の正の正確整数か、任意長のu32vector (*Note
     単一型のベクタ::参照)が使えます。
     整数の場合は、初期化のために低位の32ビットが使われます。
     u32vectorの場合は、初期化のために624までの要素が使われます。

 -- Function: mt-random-get-state mt
 -- Function: mt-random-set-state! mt state
     Mersenne Twister RNG MTを取り出して再インストールします。
     状態は、625要素のu32vectorで表現されます。
     状態はどこにでも保存することができ、仮想的なランダムシーケンスの
     生成を続行するために、`<mersenne-twister>'のインスタンスとして
     リストアできます。

 -- Function: mt-random-real mt
 -- Function: mt-random-real0 mt
     0.0と1.0の間のランダムな実数を返します。 1.0は範囲に含まれません。
     `mt-random-real'は、0.0も範囲に含みませんが、
     `mt-random-real0'は含みます。
     0.0を含まないのは、SRFI-27ドラフトに依拠しています。

 -- Function: mt-random-integer mt range
     0からRANGE-1までの正の正確整数をランダムに返します。
     RANGEはいかなる正の正確整数でも構いません。

 -- Function: mt-random-fill-u32vector! mt u32vector
 -- Function: mt-random-fill-f32vector! mt f32vector
 -- Function: mt-random-fill-f64vector! mt f64vector
     与えられたユニフォームベクタをランダムな数値で埋めます。
     `mt-random-fill-u32vector!'では、要素は0と2^32-1の間の
     正の正確整数で埋められます。
     `mt-random-fill-f32vector!'と`mt-random-fill-f64vector!'
     では、0.0と1.0(含まれない)の間の不正確実数で埋められます。


File: gauche-refj.info,  Node: RFC822メッセージ形式,  Next: Base64エンコーディング,  Prev: Mersenne Twister乱数発生器,  Up: ライブラリモジュール - ユーティリティ

11.11 `rfc.822' - RFC822メッセージ形式
======================================

 -- Module: rfc.822
     電子メールを交換する際に使用されるテキストのフォーマット、"インターネット・
     メッセージ・フォーマット" をパーズ/生成する手続きを定義しています。
     最新の仕様は、RFC2822 (*Note [RFC2822]: rfc2822.) にあります。
     このフォーマットは最初 RFC 822
     で定義されたため、未だに"RFC822形式"と
     呼ばれています。それがこのモジュール名の由来です。
     以下では、このフォーマットを"RFC822形式"と呼んでいます。

     このモジュールを使うためには、`(use rfc.822)' として下さい。

Parsing a message header
------------------------

 -- Function: rfc822-header->list iport &keyword strict? reader
     入力ポート IPORT から、メッセージ・ヘッダの終わりに達するまで、
     RFC822 形式のメッセージを読み込みます。
     ヘッダ・フィールドは以下のフォーマットのリストに展開、分離されます。
          ((name body) ...)
     NAME ... はフィールド名で、BODY ... は対応するフィールドの
     ボディ、ともに文字列です。
     フィールド名は小文字に変換されます。フィールドのボディは、たたまれている
     行が連結され CRLF が削除される以外は変更されません。
     フィールドの順番は保存されます。

     デフォルトでは、パーザの動作は寛容です。ヘッダをパーズ中に EOF に
     出会うとそれをメッセージの終端とみなします。継続(畳み込み)行でもなく、
     新しいヘッダフィールドの始端でもない行は無視します。このふるまいは
     キーワード引数 STRICT? に真の値を渡すことで変更することができます。
     真を渡すと、このような不正な形式のヘッダに対してエラーを発生させるように
     なります。

     キーワード引数 READER は IPORT から一行読み込む手続きを
     とります。デフォルトは `read-line' です。ほとんどの場合これで
     十分のはずです。

 -- Function: rfc822-header-ref header-list field-name &optional default
     `rfc822-header->list' が返すパーズ済みのヘッダリストから
     特定のフィールドを得るためのユーティリティ手続きです。

     FIELD-NAME は小文字の文字列でフィールド名を指定します。
     与えられた名前をもつフィールドが HEADER-LIST 中にあれば、
     その値を文字列で返します。そうでない場合、もし DEFAULT が
     与えられていればそれが返り、与えられていなければ `#f'
     が返されます。

基本的なフィールドパーザ
------------------------

RFC2822メッセージの「構造化」されたヘッダフィールドをパーズするために、
いくつかの手続きが提供されています。これらの手続きはヘッダフィールドの
本体部を処理します。たとえば、ヘッダフィールドが、 "`To: Wandering
Schemer <schemer@example.com>'" であれば、これらの 手続きは "`Wandering
Schemer <schemer@example.com>'" をパーズします。

ほとんどの手続きは入力ポートを引数にとります。通常は最初に、ヘッダフィールド
全部を `rfc822-header->list' でパーズし、ヘッダの本体を
`rfc822-header-ref' で取得してから、その本体用に入力文字列ポートを
オープンして、それをこれらの手続きを用いてパーズします。

   このように複雑になっているのは、フィールドのタイプによって別々の
トークン化スキームが必要になるからです。RFC2822 では多くの場合
トークン間にコメントがあらわれことを許しているので、初心な正規表現では
うまくいきません。RFC2822 のコメントはネスト可能で、正規表現では表現
しきれないからです。
そういうわけで、このレイヤの手続きは、いろいろな構文に対応できるよう
十分な柔軟性があるように設計されています。標準的なタイプのヘッダについては
高水準のパーザも提供されています。後述の「特定フィールド用パーザ」を
参照してください。

 -- Function: rfc822-next-token iport &optional tokenizer-specs
     基本的なトークナイザです。まず、もしあれば、白空白および/または
     コメント (`CFWS') を IPORT から読み飛ばします。それから、
     TOKENIZER-SPECS にしたがってトークンをひとつ読み込みます。
     トークンを読み込む前に、IPORT が EOF に到達したら、EOF が
     返されます。

     TOKENIZER-SPECS はトークナイザ仕様のリストです。
     トークナイザ仕様は、文字集合または文字集合と手続きのペアのどちらかです。

     `CFWS' を読み飛ばしたあと、この手続きは IPORT の先頭の一文字
     を見て、TOKENIZER-SPECS のひとつひとつに対してチェックします。
     その文字が含まれている文字集合がみつかれば、トークンを次のようにして
     引き出します。トークナイザ仕様が文字集合だけの場合、その文字集合に
     属している文字の並びがトークンを構成します。トークナイザ仕様が文字集合と
     手続きのペアだったら、その手続きを IPORT とともに呼びだし、
     トークンを読み込みます。

     もし、先頭も文字がどの文字集合ともマッチしなければ、そも文字が
     IPORT から取り出され、それが返されます。

     デフォルトの TOKENIZER-SPECS は以下のようになっています。
          (list (cons #["] rfc822-quoted-string)
                (cons *rfc822-atext-chars* rfc822-dot-atom))
     ここで `rfc822-quoted-string' および `rfc822-dot-atom' は
     後述するトークナイザ手続きで、`*rfc822-atext-chars*' は RFC2822 で
     規定された `atext' の文字集合に束縛されています。
     つまり、`rfc822-next-token' はデフォルトでは RFC2822 で規定された
     `quoted-string' あるいは `dot-atom' のトークンを引き出します。

     TOKENIZER-SPECS をつかって、ヘッダフィールドのパーズ方法を
     カスタマイズすることができます。たとえば、(1)
     英字で構成された単語、または (2)
     クウォート文字列、のトークンを取り出したいときには、
     `rfc822-next-token' をこんなふうに呼べます。

          (rfc822-next-token iport
             `(#[[:alpha:]] (#["] . ,rfc822-quoted-string)))

 -- Function: rfc822-field->tokens field &optional tokenizer-specs
     これは便利関数です。フィールド本体 FIELD に対応する入力文字列ポート
     を生成し、それに対して、`rfc822-next-token'
     を全入力を消費するまで、
     繰り返しよび、トークンのリストを返します。TOKENIZER-SPECS は、
     `rfc822-next-token' に渡されます。

 -- Function: rfc822-skip-cfws iport
     IPORT から、すべてのコメントおよび/または白空白文字を消費し、
     白空白でもコメントでもない、先頭の文字を返します。返された文字は、
     IPORTに残ります。

 -- Constant: *rfc822-atext-chars*
     `atom' を構成する有効な文字集合に束縛されています。

 -- Constant: *rfc822-standard-tokenizers*
     デフォルトの TOKENIZER-SPECS に束縛されています。

 -- Function: rfc822-atom iport
 -- Function: rfc822-dot-atom iport
 -- Function: rfc822-quoted-string iport
     それぞれ、`atom'、`dot-atom' および `quoted-string' に
     対応するトークナイザです。`quoted-string' 中の二重引用符および
     エスケープのためのバックスラッシュは `rfc822-quoted-string' に
     よって取り除かれます。

特定フィールド用パーザ
----------------------

 -- Function: rfc822-parse-date string
     RFC822 形式の日付文字列を取り、8つの値を返します。
          year, month, day-of-month, hour, minutes, seconds, timezone, day-of-week.

     _timezone_ は UT(グリニッジ標準時)からの分単位のオフセットです。
     _day-of-week_ は日曜日から数えた曜日で、情報が不足している場合は
     #f です。 _month_は1から12までの整数です。
     文字列がパーズ不可能ならば、全ての要素が #f になります。

 -- Function: rfc822-date->date string
     RFC822形式の日付フォーマットをパーズし、SRFI-19 の `<date>'
     オブジェクト (*Note 日付:: 参照) を返します。STRING
     がパーズできないときは かわりに `#f' を返します。


File: gauche-refj.info,  Node: Base64エンコーディング,  Next: HTTPクッキー,  Prev: RFC822メッセージ形式,  Up: ライブラリモジュール - ユーティリティ

11.12 `rfc.base64' - Base64エンコーディング
===========================================

 -- Module: rfc.base64
     このモジュールでは、RFC 2045 (*Note [RFC2045]: rfc2045.) で
     定義されている Base64
     フォーマットへエンコード/デコードするいくつかの
     手続きを定義しています。

 -- Function: base64-encode
     現在の入力ポートからバイト・ストリームを読み込み、それを Base64
     フォーマットに
     エンコードし、現在の出力ポートに文字ストリームとして書き出します。
     現在の入力ポートから EOF を読み込むと変換を終了します。

 -- Function: base64-encode-string string
     STRING の内容を Base64 でエンコードされたフォーマットに変換します。
     入力となる文字列は、完全文字列でも不完全文字列でも良いです。
     常にバイト・シーケンスとして扱われます。

 -- Function: base64-decode
     現在の入力ポートから文字ストリームを読み込み、それを Base64
     フォーマットとして
     デコードし、現在の出力ポートにバイトストリームとして書き出します。
     変換は EOF か、終端文字 (`=') を読み込むと終了します。 Base64
     でエンコードされた文字として適当でない文字は沈黙のまま無視されます。

 -- Function: base64-decode-string string
     Base64 でエンコードされた文字列 STRING
     をデコードして文字列を返します。 変換は STRING
     の終わりか、終端文字 (`=') で終了します。 Base64
     でエンコードされた文字として適当でない文字は沈黙のまま無視されます。


File: gauche-refj.info,  Node: HTTPクッキー,  Next: HMAC鍵付きハッシング,  Prev: Base64エンコーディング,  Up: ライブラリモジュール - ユーティリティ

11.13 `rfc.cookie' - HTTPクッキー
=================================

 -- Module: rfc.cookie
     RFC 2965 (*Note RFC2965: rfc2965.)
     で定義されている「クッキー」情報を
     パースしたり構築したりするための手続きを定義しています。

 -- Function: parse-cookie-string string &optional version
     リクエスト・ヘッダの Cookie の値のクッキー文字列 STRING を
     パースします。通常、CGI プログラムでは、同じ情報は環境変数
     HTTP_COOKIE を通して利用できます。

     リクエスト・ヘッダ Cookie2 を通してクッキーのバージョンが分かる
     場合は、VERSION へ整数のバージョンとして渡されなければなりません。
     そうでなければ、`parse-cookie' は STRING からバージョンを
     取り出します。

     結果は以下のフォーマットを持ちます。
          ((<name> <value> [:path <path>] [:domain <domain>] [:port <port>])
           ...)
     <NAME> は属性名で、<VALUE> は対応する値です。
     属性が値を持たない場合、<VALUE> は `#f' になります。 (属性が NULL
     値を持つ場合は、`""' となることに注意。)
     属性がパスやドメイン、ポート番号のオプションを持つ場合は、
     キーワード-値のペアの形式で与えられます。

 -- Function: construct-cookie-string specs &optional version
     与えられたクッキーの仕様のリストから、`Set-cookie2' か
     `Set-cookie' ヘッダに適切なクッキー文字列を作ります。

     オプションの VERSION 引数は、クッキー・プロトコルのバージョンを
     指定するものです。0 は古い Netscape スタイルのフォーマットで、1 は
     RFC2965 スタイルのフォーマットです。省略された場合、1
     が指定されたものと されます。

     クッキーの仕様は以下のフォーマットを持ちます。
          (<name> <value> [:comment <comment>] [:comment-url <url>]
                          [:discard <bool>] [:domain <domain>]
                          [:max-age <age>] [:path <path>]
                          [:port <port-list>] [:secure <bool>]
                          [:version <version>] [:expires <date>])

    `<name>'
          文字列。クッキーの名前。

    `<value>'
          クッキーの値。文字列か、値が必要なければ `#f' 。

    `<comment> <url> <domain> <path> <port-list>'
          文字列。

    `<bool>'
          真偽値。

    `<age> <version>'
          整数。

    `<date>'
          整数(エポックからの秒数)か、Netscape
          のクッキー仕様に従うフォーマットされた 日付文字列。

     属性値は適切にクォートされます。指定された属性が VERSION に不適切な
     場合は無視されます。古いスタイルと新しいスタイルの両方のクッキー文字列を
     作るために同じ仕様を渡すことができます。

     戻り値はそれぞれのクッキー文字列のリストです。(`Set-cookie' を使う)
     古いスタイルのプロトコルでは、それぞれを独立したヘッダとして送らなければ
     なりません。(`Set-cookie2' ヘッダを使う)新しいプロトコルでは、
     それらをカンマで繋ぎ、一度に送ることができます。詳細は RFC2965
     を見て下さい。

     いくつかの例を示します。
          (construct-cookie-string
             `(("name" "foo" :domain "foo.com" :path "/"
                             :expires ,(+ (sys-time) 86400) :max-age 86400)))
           => ("name=foo;Domain=foo.com;Path=/;Max-age=86400")

          (construct-cookie-string
             `(("name" "foo" :domain "foo.com" :path "/"
                             :expires ,(+ (sys-time) 86400) :max-age 86400))
             0)
           =>
           ("name=foo;Domain=foo.com;Path=/;Expires=Sun, 09-Sep-2001 01:46:40 GMT")


File: gauche-refj.info,  Node: HMAC鍵付きハッシング,  Next: HTTP,  Prev: HTTPクッキー,  Up: ライブラリモジュール - ユーティリティ

11.14 `rfc.hmac' - HMAC鍵付きハッシング
=======================================

 -- Module: rfc.hmac
     このモジュールは、RFC 2104で定義されている、メッセージ認証のための
     鍵付きハッシングのHMACアルゴリズムを実装しています。

     シンプルなバッチ処理での鍵付きハッシングでは、高レベルなAPIである
     `hmac-digest'と`hmac-digest-string'が使えます。
     あるいは、`<hmac>'オブジェクトを作成して、入力となるデータで
     その状態を更新することもできます。

 -- Class: <hmac>
     HMACアルゴリズムの状態情報を保持します。
     鍵とハッシングアルゴリズムは、キーワード引数`:key'と`:hasher'を
     それぞれ使って、生成時に与えます。 `<md5>' (*Note
     MD5メッセージダイジェスト::参照)や `<sha1>' (*Note
     SHA1メッセージダイジェスト::参照)などのような
     ダイジェストインタフェース(*Note
     メッセージダイジェストフレームワーク::参照)を
     実装するいかなるクラスオブジェクトを渡すこともできます。

     例:
          (make <hmac> :key (make-byte-string 16 #x0b) :hasher <md5>)

 -- Method: hmac-update! (hmac <hmac>) data
     (不完全かもしれない)文字列で表現されるDATAにより、
     HMACの内部状態を更新します。

 -- Method: hmac-final! (hmac <hmac>)
     HMACの内部状態を終了させ、不完全文字列でハッシュされた文字列を
     返します。
     "hexified"(16進化)された結果を得るために、`digest-hexify' (*Note
     メッセージダイジェストフレームワーク::参照)を使うことが できます。
     一旦終了されると、HMACに対しては`hmac-update!'や
     `hmac-final!'を呼ぶことはできません。

 -- Method: hmac-digest &keyword key hasher
     `<hmac>'オブジェクトを作り、現在の入力ポートからの
     データストリームをハッシュし、不完全文字列でそのハッシュされた
     結果を返します。

 -- Method: hmac-digest-string string &keyword key hasher
     `<hmac>'オブジェクトを作り、STRINGにあるデータをハッシュし、
     不完全文字列でそのハッシュされた結果を返します。


File: gauche-refj.info,  Node: HTTP,  Next: MD5メッセージダイジェスト,  Prev: HMAC鍵付きハッシング,  Up: ライブラリモジュール - ユーティリティ

11.15 `rfc.http' - HTTP
=======================

 -- Module: rfc.http
     このモジュールは、RFC2616 "Hypertext Transfer Protocol - HTTP/1.1"
     で定義されているHTTP/1.1に対する簡単なクライアントAPIを提供します。
     (*Note [RFC2616]: rfc2616.).

     現在のAPIは、プロトコルの一部のみ実装されています。
     GET、HEAD、POSTリクエストのみがサポートされており、
     HTTP/1.0のサーバーとはうまく通信できません。
     また、HTTP/1.1の先進的機能、例えば永続的接続などはサポートしていません。
     これらの機能は、将来のバージョンで追加されるでしょう。

 -- Function: http-get server request-uri &keyword sink flusher
          no-redirect ...
 -- Function: http-head server request-uri &keyword no-redirect ...
 -- Function: http-post server request-uri body &keyword sink flusher
          no-redirect ...
     SERVERに、それぞれHTTPのGET、HEAD、POSTリクエストを送り、
     サーバの応答を返します。

     サーバが "3xx"
     のリダイレクトを指示する応答を返した場合、これらの手続きは
     デフォルトで、応答のメッセージヘッダの "location"
     で返されるURIに従うよう
     試みます。リダイレクションを抑制するには、下の"キーワード引数"を参照してください。

     *必須の引数:* SERVER引数では、文字列でHTTPサーバ名を指定します。
     サーバ名は、オプションでコロンに続いてポート番号を付加できます。
     Examples: `"w3c.org"', `"mycompany.com:8080"'.

     REQUEST-URI引数は、RFC2616で規定されているリクエストURIで、通常これは
     HTTP URLのパス部分です。

     `http-post'は、サーバへポストされる文字列、BODYを第3引数として
     取ります。ボディは"そのまま"送られるので、呼び出し側は必要なエスケープや
     エンコーディングを行う必要があります。

     あるURLのコンテンツを取得する最もシンプルなフォームは次のようになるでしょう。
          (http-get "www.shiro.dreamhost.com" "/scheme/index.html")

     プロクシを通してのアクセスは、SERVERにプロクシ・サーバを指定し、
     REQUEST-URIに完全なURIを渡すことで行えますが、まだテストされていません。

     *戻り値:* 全ての手続きは3つの値を返します。

     1つ目は、RFC2616で定義されているステータスコードの文字列値(例えば、成功時の
     200、"Not found"の404など)です。

     2つ目は、パーズされたヘッダのリストで、リストの要素は`(HEADER-NAME
     VALUE ...)'です。HEADER-NAMEはヘッダの文字列名(例えば、
     "content-type"や"location"など)で、VALUEは対応する値の文字列値です。
     ヘッダ名は小文字に変換されます。値は、RFC2822で定義されている無指定行区切
     (ソフト・ライン・ブレイク)が除かれる以外はそのままです。
     サーバが同じ名前のヘッダを1つ以上返した場合は、
     1つのリストに統合されます。それ以外では、2つ目の戻り値に
     おけるヘッダのリストの順番は、サーバの応答での順番と同じです。

     3つ目の戻り値は、サーバの応答におけるメッセージボディです。
     デフォルトでは、文字列で表現されたメッセージボディそのものです。
     サーバの応答がボディを持たない場合、3つ目の戻り値は`#f'です。
     キーワード引数によって、メッセージボディがどのように扱われるかを制御できます。
     例えば、中間的な文字列を作らずに、返されたメッセージボディを直接ファイルに
     格納することが出来ます。詳細は以下で説明しています。

     *キーワード引数:*
     デフォルトで、これらの手続きはリクエストメッセージに`"Host"'ヘッダ・フィールドを
     追加するだけです。他のヘッダ・フィールドを追加するためにキーワード引数を
     与えることができます。
          (http-get "foo.bar.com" "/index.html"
            :accept-language "ja"
            :user-agent "My Scheme Program/1.0")

     以下のキーワード引数は手続きによって解釈され、リクエストヘッダには現れません。

    NO-REDIRECT
          真の値が与えられた場合、リダイレクションには従わなくなります。すなわち、
          手続きは"3xx"のメッセージをそのまま返します。

    SINK, FLUSHER
          これらのキーワード引数によりメッセージ・ボディがどのように扱われるかを
          カスタマイズできます。SINKには出力ポートを、FLUSHERには2引数を
          取る手続きを渡さなければなりません。

          手続きがメッセージ・ボディを受信し始めると、SINKへ受け取った
          データ片をフィードします。手続きがメッセージ・ボディを受信し終わると、
          FLUSHERに与えられた手続きが、SINKと(手続きからの2つ目の
          戻り値と同じフォーマットの)メッセージ・ヘッダ・フィールドのリストとともに
          呼び出されます。FLUSHERの戻り値が、手続きからの3つ目の戻り値と
          なります。

          したがって、SINKのデフォルト値は、新しく開かれた文字列ポートで、
          FLUSHERのデフォルト値は`(lambda (sink headers)
          (get-output-string sink))' とも言えます。

          以下のサンプルは、(とても大きい可能性のある)文字列バッファを作らずに、
          メッセージ・ボディを直接ファイルに保存します。
               (call-with-output-file "page.html"
                 (lambda (out)
                   (http-get "www.schemers.org" "/"
                      :sink out :flusher (lambda _ #t))))




File: gauche-refj.info,  Node: MD5メッセージダイジェスト,  Next: MIMEメッセージ処理,  Prev: HTTP,  Up: ライブラリモジュール - ユーティリティ

11.16 `rfc.md5' - MD5メッセージダイジェスト
===========================================

 -- Module: rfc.md5
     このモジュールは、RFC 1321(*Note [RFC1321]: rfc1321.参照)で
     定義されている、MD5メッセージダイジェストアルゴリズムを実装しています。
     このモジュールは、util.digest (*Note
     メッセージダイジェストフレームワーク::参照) を拡張しています。

 -- Class: <md5>
     このクラスのインスタンスは、MD5ダイジェストアルゴリズムの内部状態を
     保持しています。

     このクラスは、`util.digest'フレームワークのインターフェースである、
     `digest-update!'、`digest-final!'、`digest'、
     `digest-string'を実装しています。
     これらのメソッドの詳細な説明は、*Note
     メッセージダイジェストフレームワーク:: を参照して下さい。

ダイジェスタフレームワークに加えて、このモジュールはショートカット手続きを
提供します。

 -- Function: md5-digest
     現在の入力ポートからEOFまで読み込み、そのダイジェストを不完全文字列で
     返します。

 -- Function: md5-digest-string string
     STRINGにあるデータをダイジェストし、その結果を不完全文字列で
     返します。


File: gauche-refj.info,  Node: MIMEメッセージ処理,  Next: Quoted-printableエンコーディング,  Prev: MD5メッセージダイジェスト,  Up: ライブラリモジュール - ユーティリティ

11.17 `rfc.mime' - MIMEメッセージ処理
=====================================

 -- Module: rfc.mime
     RFC2045からRFC2049で定義されている、
     多目的インターネットメール拡張(Multipurpose Internet Mail
     Extensions; MIME) メッセージを扱う便利な手続きです。

     このモジュールは、`rfc.822'モジュールと一緒に使うことを
     想定しています(*Note RFC822メッセージ形式::参照)。

Utilities for header fields
---------------------------

MIME特有のヘッダフィールドをパーズする便利な手続き。

 -- Function: mime-parse-version field
     FIELDがそのMIMEバージョンのヘッダフィールドとして有効であれば、
     そのメジャーバージョン番号とマイナーバージョン番号をリストにして
     返します。そうでなければ、`#f'を返します。
     FIELDには`#f'を渡せるので、`rfc822-header-ref'の
     戻り値を直接渡すこともできます。`rfc822-header->list'により
     返されるパーズ済みヘッダのリストを渡すことで、以下のように
     MIMEのバージョンを得ることができます。(現在は、`(1 0)'です。)
          (mime-parse-version (rfc822-header-ref headers "mime-version"))

     注意: FIELDはトークンの間にコメントを含むかもしれないので、
     `#/\d+\.\d+/'のような単純な正規表現では実現できません。

 -- Function: mime-parse-content-type field
     "content-type"ヘッダフィールドをパーズし、次のようなリストを
     返します。
          (type subtype (attribute . value) ...)
     ここで、typeとsubtypeはそれぞれ、MIMEメディアタイプと
     サブタイプを文字列で表したものになります。

          (mime-parse-content-type "text/html; charset=iso-2022-jp")
           => ("text" "html" ("charset" . "iso-2022-jp"))

     FIELDが有効なcontent-typeフィールドでない場合は、 `#f'が返ります。

 -- Function: mime-decode-word word
     RFC2047でエンコードされたWORDをデコードします。
     WORDがRFC2047でエンコードされたものでない場合は、そのまま
     返されます。

          (mime-decode-word "=?iso-8859-1?q?this=20is=20some=20text?=")
           => "this is some text"

Streaming parser
----------------

メッセージ全体が読み込まれる前にメッセージボディをどのように
扱うかをコントロールできるように、ストリームパーザが用意されて います。

 -- Function: mime-parse-message port headers handler
     基本的なストリームパーザです。PORTは、メッセージを読み込む
     入力ポートです。HEADERSは`rfc822-header->list'により
     パーズされたヘッダのリストです。つまり、この手続きは、
     PORTから読み込まれたメッセージのヘッダ部分がパーズされた
     後に使われることを想定しています。
          (let* ((headers (rfc822-header->list port)))
            (if (mime-parse-version (rfc822-header-ref headers "mime-version"))
               ;; parse MIME message
               (mime-parse-message port headers handler)
               ;; retrieve a non-MIME body
               ...))

     `mime-parse-message'はHEADERSを解析し、
     メッセージボディのそれぞれについて、2引数をもって
     HANDLERを呼び出します。

          (handler PART-INFO XPORT)

     PART-INFOは、以下で説明するような、メッセージのこのパートの
     情報をカプセル化した`<mime-part>'ストラクチャです。

     XPORTは入力ポートで、最初はメッセージボディの先頭を指しています。
     ハンドラはこのポートからメッセージボディを読み込むことが出来ます。
     XPORTはMIMEバウンダリを認識し、パートの最後に到達したら
     EOFを返します。 (元のPORTから直接読み込まないようにして下さい。
     そうしてしまうと、VPORTの内部状態がおかしくなります)。

     HANDLERは、パートをメモリに読み込んだり、ディスクに保存したり、
     あるいはそのパートを無視したりできます。ただ、何をするにせよ、
     VPORTがEOFを返すまでデータを読まなければなりません。

     HANDLERの戻り値は、PART-INFOの`content'スロットに セットされます。

     メッセージが、ネストしたマルチパートメッセージを含んでいる場合は、
     HANDLERは深さ優先でそれぞれの"葉"のパートに対して呼ばれます。
     HANDLERは、PART-INFOストラクチャを調べることで、
     そのネストのレベルを知ることができます。

     メッセージはマルチパートである必要はありません。メッセージが MIME
     `mesasge'タイプである場合は、HANDLERは囲まれたメッセージの
     ボディに対して呼ばれます。メッセージが、`text'や`application'
     などの他のメディアタイプの場合は、HANDLERは単にメッセージボディに
     対して呼ばれます。

 -- Class: <mime-part>
     MIMEパートのメタ情報を含むストラクチャです。
     これは、そのパートのヘッダが読み込まれた時点で構築され、
     そのパートのボディを読み込むハンドラに渡されます。

     以下のスロットを持ちます。

      -- Instance Variable of <mime-part>: type
          MIMEメディアタイプの文字列。そのパートの`content-type'ヘッダが
          省略された場合は、適切なデフォルト値がセットされます。

      -- Instance Variable of <mime-part>: subtype
          MIMEメディアのサブタイプの文字列。そのパートの`content-type'
          ヘッダが省略された場合は、適切なデフォルト値がセットされます。

      -- Instance Variable of <mime-part>: parameters
          `content-type'ヘッダフィールドに渡されるパラメータの連想リスト。

      -- Instance Variable of <mime-part>: transfer-encoding
          `content-transfer-encoding'ヘッダフィールドの値。
          このヘッダフィールドが省略された場合は、適切なデフォルト値が
          セットされます。

      -- Instance Variable of <mime-part>: headers
          `rfc822-header->list'によりパーズされた、ヘッダフィールドのリスト。

      -- Instance Variable of <mime-part>: parent
          それがマルチパートメッセージあるいはカプセル化されたメッセージの
          パートである場合は、それを含んでいるパートの`<mime-part>'
          ストラクチャを指します。そうでなければ`#f'を返します。

      -- Instance Variable of <mime-part>: index
          同じ親を持つパートの中でのそのパートのシーケンス番号。

      -- Instance Variable of <mime-part>: content
          そのパートのメディアタイプがmultipart/*あるいはmessage/*で
          ある場合は、このスロットにはそれに含まれるパートのリストが
          入っています。そうでなければ、HANDLERの戻り値が
          格納されています。

 -- Function: mime-retrieve-body part-info xport outp
     メッセージボディを取得するための手続きです。
     `mime-parse-message'へ渡される、HANDLERの
     ビルディングブロックとなることを意図しています。

     PART-INFOは、`<mime-part>'のオブジェクトです。
     XPORTはハンドラに渡された入力ポートで、
     そこからMIMEパートが読みこまれるものです。

     この手続きは、XPORTからEOFに達するまで読み込み、
     PART-INFOの`transfer-encoding'も見て、
     ボディを適切にデコードします。つまり、base64やquoted-printable
     のエンコーディングは適切に処理されます。結果が出力ポートOUTPへと
     出力されます。

     この手続きは文字セットの変換は扱いません。
     必要であれば、呼び出し側がOUTPとしてCES変換ポートを
     使う必要があります(*Note 文字コード変換::参照)。


   典型的なケースのために、いくつかの便利な手続きが`mime-retrieve-body'
の上に定義されています。

 -- Function: mime-body->string part-info xport
 -- Function: mime-body->file part-info xport filename
     MIMEメッセージのボディを読み込み、転送(transfer)エンコーディングを
     デコードし、それぞれ文字列として返すか、ファイルへ書き出します。

   MIMEメッセージパーザの最もシンプルな使い方は次のように なります。

     (let ((headers (rfc822-header->list port)))
       (mime-parse-message port headers
                           (cut mime-body->string <> <>)))

   これは、メッセージの全てをメモリに読み込み、
一番上層の`<mime-part>'オブジェクトを返します。
("葉"である`<mime-part>'オブジェクトの`content'フィールドは、
そのパートのボディを文字列として保持しています。)
内容の転送エンコーディング(content transfer encoding)は認識され処理
されますが、文字セットの変換は行われません。

   メッセージボディを直接ファイルに書き出したり、MIMEメディアタイプや
他のヘッダ情報に基づいていくつかのボディをスキップしたいかもしれません。
その場合は、ロジックをハンドラのクロージャに入れることができます。
それが、このモジュールが、オールインワンの手続きではなく、
ビルディングブロックを提供している理由です。


File: gauche-refj.info,  Node: Quoted-printableエンコーディング,  Next: SHA1メッセージダイジェスト,  Prev: MIMEメッセージ処理,  Up: ライブラリモジュール - ユーティリティ

11.18 `rfc.quoted-printable' - Quoted-printableエンコーディング
===============================================================

 -- Module: rfc.quoted-printable
     このモジュールでは、RFC 2045 (*Note [RFC2045]: rfc2045.参照)の
     セクション6.7で定義されている、Quoted-printableフォーマットにエンコード/から
     デコードするためのいくつかの関数を定義しています。

 -- Function: quoted-printable-encode
     現在の入力ポートからバイトストリームを読み込み、それをQuoted-printable
     フォーマットにエンコードし、現在の出力ポートへ結果の文字ストリームを
     書き出します。この変換は、現在の入力ポートからEOFを読み出すと終了します。

 -- Function: quoted-printable-encode-string string
     STRINGの内容をQuoted-printableエンコードされたフォーマットに
     変換します。入力の文字列は、完全文字列でも不完全文字列でも構いません。
     常にバイトシーケンスとして処理されます。

 -- Function: quoted-printable-decode
     現在の入力ポートから文字ストリームを読み込み、それをQuoted-printable
     フォーマットからデコードし、結果のバイトストリームを現在の出力ポートへ
     書き出します。 この変換は、EOFを読み出すと終了します。
     不正なシーケンス('='の後に16進文字が続かない、など)に出会うと、それらを
     リテラルのまま出力へコピーします。

 -- Function: quoted-printable-decode-string string
     Quoted-printableエンコードされた文字列STRINGをデコードし、
     その結果を文字列で返します。


File: gauche-refj.info,  Node: SHA1メッセージダイジェスト,  Next: URIの解析と作成,  Prev: Quoted-printableエンコーディング,  Up: ライブラリモジュール - ユーティリティ

11.19 `rfc.sha1' - SHA1メッセージダイジェスト
=============================================

 -- Module: rfc.sha1
     このモジュールは、RFC 3174 (*Note [RFC3174]: rfc3174.参照)で
     定義されている、US Secure Hash Algorithm 1 (SHA1)を実装しています。
     このモジュールは、util.digest (*Note
     メッセージダイジェストフレームワーク::参照) を拡張しています。

 -- Class: <sha1>
     このクラスのインスタンスは、SHA1ダイジェストアルゴリズムの内部状態を
     保持しています。

     このクラスは、`util.digest'フレームワークのインターフェース、
     `digest-update!'、`digest-final!'、`digest'、
     `digest-string'を実装しています。
     これらのメソッドの詳細な説明は、*Note
     メッセージダイジェストフレームワーク::を 参照して下さい。

   ダイジェスタフレームワークに加えて、このモジュールはショートカット
手続きを提供します。

 -- Function: sha1-digest
     現在の入力ポートからデータをEOFまで読み込み、そのダイジェストを
     不完全文字列で返します。

 -- Function: sha1-digest-string string
     STRINGのデータをダイジェストし、その結果を不完全文字列で 返します。


File: gauche-refj.info,  Node: URIの解析と作成,  Next: SLIBインタフェース,  Prev: SHA1メッセージダイジェスト,  Up: ライブラリモジュール - ユーティリティ

11.20 `rfc.uri' - URIの解析と作成
=================================

 -- Module: rfc.uri
     RFC 2396 (*Note [RFC2396]: rfc2396.)で定義されている Uniform
     Resource Identifiers をパーズする関数を提供します。

 -- Function: uri-parse uri
 -- Function: uri-scheme&specific uri
 -- Function: uri-decompose-hierarchical specific
 -- Function: uri-decompose-authority authority
     URIの一般的なパーザです。これらの関数はURIエンコーディングを
     デコードしません。URIスキームによってどの部分をデコードすべきかが
     異なるからです。パージングを行った後に、後述の`uri-decode'等を
     使ってデコードを行ってください。

     `uri-parse'は最も手軽な手続きで、uriを以下に示す部分に
     分割し、多値で返します。
     もし該当する部分がuriに無かった場合は、その部分には`#f'が返ります。
        * URIスキームを文字列で。 (例：
          `"mailto:foo@example.com"'の`"mailto"')。

        * authorityパートのuser-infoを文字列で。 (例：
          `ftp://anonymous@ftp.example.com/pub/foo'の`"anonymous"')。

        * authorityパートのhostnameを文字列で。 (例：
          `ftp://anonymous@ftp.example.com/pub/foo'の
          `"ftp.example.com"')。

        * authorityパートのport番号を整数で。 (例：
          `http://www.example.com:8080/'の`8080')。

        * pathパート。 (例：
          `http://www.example.com/index.html'の`"/index.html"')。

        * queryパート。 (例：
          `http://www.example.com/search?key=xyz&lang=en'の
          `"key=xyz&lang=en"')。

        * fragmentパート。 (例：
          `http://www.example.com/document.html#section4'の
          `"section4"')。

     以下の手続きはより詳細に、段階をふんでuriを分割してゆくものです。

     `uri-scheme&specific' は URI URI を引数に取り、
     スキーム部分と、そのスキーム特有の部分を表す2つの値を返します。
     URI がスキーム部分を持たない場合、#F を返します。
          (uri-scheme&specific "mailto:sclaus@north.pole")
            => "mailto" and "sclaus@north.pole"
          (uri-scheme&specific "/icons/new.gif")
            => #f and "/icons/new.gif"

     URI が階層的な記法を用いている場合、すなわち、
     "`//AUTHORITY/PATH?QUERY#FRAGMENT'"
     のような場合、スキーム特有の部分を `uri-decompose-hierarchical'
     に渡すと、AUTHORITY、PATH、QUERY、FRAGMENT の4つの値が返ります。
          (uri-decompose-hierarchical "//www.foo.com/about/company.html")
            => "www.foo.com", "/about/company.html", #f and #f
          (uri-decompose-hierarchical "//zzz.org/search?key=%3fhelp")
            => "zzz.org", "/search", "key=%3fhelp" and #f
          (uri-decompose-hierarchical "//jjj.jp/index.html#whatsnew")
            => "jjj.jp", "/index.html", #f and "whatsnew"
          (uri-decompose-hierarchical "my@address")
            => #f, #f, #f and #f

     さらに、階層的 URI の AUTHORITY の部分を `uri-decompose-authority'
     に渡すと、USERINFO、 HOST、PORT が返ります。
          (uri-decompose-authority "yyy.jp:8080")
            => #f, "yyy.jp" and "8080"
          (uri-decompose-authority "mylogin@yyy.jp")
            => "mylogin", "yyy.jp" and #f

 -- Function: uri-compose &keyword scheme userinfo host port authority
          path path* query fragment specific
     与えられたコンポーネントから URI を構成します。 妥当な URI
     を作成するためのコンポーネントの組み合わせはたくさんあります。
     以下のダイアグラムは、考え得る組み合わせの方法を示しています。

                  /-----------------specific-------------------\
                  |                                            |
           scheme-+------authority-----+-+-------path*---------+-
                  |                    | |                     |
                  \-userinfo-host-port-/ \-path-query-fragment-/

     キーワード引数に `#f' が与えられた場合、それはキーワード引数が
     指定されないことと等価です。これは URI をパーズした結果を渡す場合に
     特に有用です。

     コンポーネントに適切でない文字が含まれている場合は、 `url-compose'
     に渡す前に正しくエスケープされなければなりません。

     いくつかの例を示します。
          (uri-compose :scheme "http" :host "foo.com" :port 80
                       :path "/index.html" :fragment "top")
            => "http://foo.com:80/index.html#top"

          (uri-compose :scheme "http" :host "foo.net"
                       :path* "/cgi-bin/query.cgi?keyword=foo")
            => "http://foo.net/cgi-bin/query.cgi?keyword=foo"

          (uri-compose :scheme "mailto" :specific "a@foo.org")
            => "mailto:a@foo.org"

          (receive (authority path query fragment)
             (uri-decompose-hierarchical "//foo.jp/index.html#whatsnew")
           (uri-compose :authority authority :path path
                        :query query :fragment fragment))
            => "//foo.jp/index.html#whatsnew"

 -- Function: uri-decode &keyword :cgi-decode
 -- Function: uri-decode-string string &keyword :cgi-decode
     URI エンコーディング、すなわち、`%'でエスケープされた URI 文字列を
     デコードします。`uri-decode' は現在の入力ポートから入力を受け取り、
     デコードした結果を現在の出力ポートに書き出します。
     `uri-decode-string' は STRING を入力とし、デコードした
     文字列を返します。

     CGI-DECODE が真の場合は、`+' がスペース文字に置換されます。

 -- Function: uri-encode &keyword :noescape
 -- Function: uri-encode-string string &keyword :noescape
     安全でない文字を、`%'によるエスケープでエンコードします。
     `uri-encode' は現在の入力ポートから入力を受け取り、
     結果を現在の出力ポートに書き出します。 `uri-encode-string' は
     STRING を入力とし、エンコードした 文字列を返します。

     デフォルトでは、RFC2396 で"非予約文字"として規定されていない文字は
     エスケープされます。NOESCAPE 引数に異なる文字セットを渡すことで、
     それらがエンコードされるのを抑止することができます。

     マルチバイト文字は、Gauche のネイティブなマルチバイト表現の
     オクテット・ストリームとしてエンコードされます。


File: gauche-refj.info,  Node: SLIBインタフェース,  Next: 関数的なXMLパーザ,  Prev: URIの解析と作成,  Up: ライブラリモジュール - ユーティリティ

11.21 `slib' - SLIBインタフェース
=================================

 -- Module: slib
     このモジュールはAubrey Jaffer氏のSLIBへのインタフェースです。
     SLIBがインストールされている場合、`(use slib)' とすれば
     SLIBの機能が使えるようになります。
     SLIBそのものはGaucheのディストリビューションには含まれていません。
     あなたのシステムにまだインストールされていない場合は
     `http://www-swiss.ai.mit.edu/~jaffer/SLIB.html'から入手することができます。

     このモジュールは`require'を再定義し、Gaucheオリジナルの`require'を
     シャドウします。`require'にシンボルが渡された場合はSLIBの`require'
     のように動作します。`require'に文字列が渡された場合はGaucheの`require'
     のように動作します。`provide'と`provided?'についても同様です。

     `require'でロードされる、SLIBで導入されるすべての定義は、
     `slib'モジュール内で行われます。

     (use slib)         ; load and set up slib
     (require 'getopt)  ; load SLIB's getopt module
     (require "foo")    ; load Gauche's foo module


File: gauche-refj.info,  Node: 関数的なXMLパーザ,  Next: SXMLクエリ言語,  Prev: SLIBインタフェース,  Up: ライブラリモジュール - ユーティリティ

11.22 `sxml.ssax' - 関数的なXMLパーザ
=====================================

 -- Module: sxml.ssax
     `sxml.*'モジュールは、XML構造のS式表現に基づく Oleg
     KiselyovのSXMLフレームワーク(*Note SSAX: ssax.参照)の適合です。

     SSAXは、SXMLフレームワークのパーザ部分です。以下は、
     SSAXのウェブページからの引用です。

          SSAXは関数的なXMLパージングフレームワークで、DOM/SXMLパーザ、SAXパーザ、
          字句解析・構文解析手続きのサポートライブラリから構成されます。
          パッケージ内の手続きは、XML文書の様々な部分をトークナイズ、あるいは
          パーズするために独立して使うことができます。
          このフレームワークは、XML名前空間、文字、内部および外部解析済み実体、
          属性値の正規化、処理命令とCDATAセクションをサポートしています。
          パッケージは、ある程度の妥当性検査を行うSXMLパーザ:
          SAXパーザの
          インスタンスであるDOMモードのパーザ(SSAXと呼ばれます)を含んでいます。

     現在のバージョンは、SXMLツールセットの最新の'公式な'リリース(4.9)よりも
     新しい、SSAXのCVSバージョンをベースにしており、パッケージSXML-gauche-0.9は、
     SXML-4.9をベースにしています。
     SXMLのリリース4.9以降では、重要な変更があります。
     現在のAPIでは、大文字の接頭辞`SSAX:'の代わりに小文字の`ssax:'を
     使います。Gaucheはデフォルトで文字の大小を区別するために、この違いは
     問題となります。
     後方互換性のためにエイリアスされた名前が定義されていますが、
     大文字の接頭辞付きの名前の使用は推奨されません。

マニュアルのこのパートの内容はSSAXのソースコードから抽出されたもので、
単にそのコメントをTexinfoのフォーマットに変換しただけです。
オリジナルのテキストは、Oleg Kiselyovによるものです。
変換により生じた誤字・誤植やフォーマットエラーの責任は、 Shiro
Kawaiにあります。

このマニュアルのエントリは、低レベルの構造から高レベルのユーティリティへと
"ボトムアップ"の方法で並べられています。
もし、あなたが単にXMLドキュメントをパーズしたりSXMLを得たいだけならば、
*Note SSAXの高レベルのパーザ - XMLからSXMLへ::の`ssax:xml->sxml'を
チェックして下さい。

* Menu:

* SSAXデータタイプ::
* SSAXの低レベルパージングコード::
* SSAXの高レベルのパーザとスキャナ::
* SSAXの高レベルのパーザ - XMLからSXMLへ::


File: gauche-refj.info,  Node: SSAXデータタイプ,  Next: SSAXの低レベルパージングコード,  Prev: 関数的なXMLパーザ,  Up: 関数的なXMLパーザ

11.22.1 SSAXデータタイプ
------------------------

_TAG-KIND_
     シンボル'`START'、'`END'、'`PI'、'`DECL'、'`COMMENT'、
     '`CDSECT'は、マークアップトークンを識別するものです。

_UNRES-NAME_
     XML文書で、マークアップトークン: 開始タグ、`PI'ターゲット、属性名に
     与えられる名前(XML勧告では`GI'と呼ばれます)です。
     `GI'が`NCName'である場合、UNRES-NAMEはこの`NCName'が
     Schemeのシンボルに変換されたものになります。
     `GI'が`QName'ならば、UNRES-NAMEは、シンボルのペア、 (PREFIX .
     LOCALPART)となります。

_RES-NAME_
     展開された名前、つまりUNRES-NAMEの解決されたバージョンです。
     名前空間URIが空でない場合の要素や属性名では、RES-NAMEはシンボルのペア、
     (URI-SYMB . LOCALPART)です。そうでない場合は、1つのシンボルです。

_ELEM-CONTENT-MODEL_
     以下のシンボルのうちの1つです。
     `ANY'                何でもよく、ENDタグがあるもの。
     `EMPTY-TAG'          内容がなく、ENDタグのないもの。
     `EMPTY'              内容がなく、次のトークンがENDタグであるもの。
     `PCDATA'             文字データのみで、子要素がないもの。
     `MIXED'              
     `ELEM-CONTENT'       

_URI-SYMB_
     名前空間を表すシンボル、あるいはURIを表すためにユーザが選んだ他のシンボルです。
     前者の場合、URI-SYMBは不正なURI文字が`%'でクォートされた
     文字列をシンボルに変換したものです。

_NAMESPACES_
     効力を持つ名前空間を表すリストです。リストの要素は、以下のフォームのうちの1つです。

    `(PREFIX URI-SYMB . URI-SYMB)'
          あるいは、

    `(PREFIX USER-PREFIX . URI-SYMB)'
          USER-PREFIXは、そのURIを表現するためにユーザにより選ばれたシンボル。

    `(#f USER-PREFIX . URI-SYMB)'
          ユーザが選んだプリフィックスとURI-SYMBOLの指定。

    `(*DEFAULT* USER-PREFIX . URI-SYMB)'
          デフォルト名前空間の宣言。

    `(*DEFAULT* #f . #f)'
          デフォルト名前空間を宣言しない。この記法は、それ以前の宣言を上書き
          することを表す。

     NAMESPACESのリストは、同じPREFIXについていくつかの要素を含むかも
     しれません。リストの先頭に近いものが効力を持ちます。

_ATTLIST_
     ペア(NAME . VALUE)の順序付きのコレクションで、NAMEは
     RES-NAMEかUNRES-NAMEです。このコレクションはADTです。

_STR-HANDLER_
     3引数の手続き `(STRING1 STRING2 SEED)'で、 新しいSEEDを返します。
     この手続きは、文字データSTRING2が後に続く、文字データSTRING1を
     扱うものです。STRING2は、"\n"や""のような短い文字列です。

_ENTITIES_
     ペア (NAMED-ENTITY-NAME . NAMED-ENTITY-BODY)の連想リストで、
     NAMED-ENTITY-NAMEはその実体が宣言されたシンボル、
     NAMED-ENTITY-BODYは文字列か、(外部実体の場合は)
     (そこから実体が読み込める)入力ポートを返す手続きです。
     NAMED-ENTITY-BODYはまた、`#f'かも知れません。
     これは、NAMED-ENTITY-NAMEがその時点で展開されていることを
     示します。
     このNAMED-ENTITY-NAMEへの参照は、WFC非再帰違反としてエラーに
     なります。

_XML-TOKEN_
     KINDとTOKENという2つのスロットを持つレコードです。
     このレコードは、XML勧告によれば、「開始タグ、終了タグ、空要素タグ、
     実体参照、文字参照、コメント、CDATAセクションの区切り、
     文書型宣言、処理命令の形を取る」マークアップを表します。
    KIND
          TAG-KIND。

    HEAD
          UNRES-NAME。'`COMMENT'と'`CDSECT'というkindのXMLトークンでは、
          そのheadは`#f'になります。

     例を示します。
          <P>  => kind='START, head='P
          </P> => kind='END, head='P
          <BR/> => kind='EMPTY-EL, head='BR
          <!DOCTYPE OMF ...> => kind='DECL, head='DOCTYPE
          <?xml version="1.0"?> => kind='PI, head='xml
          &my-ent; => kind = 'ENTITY-REF, head='my-ent
     文字参照は、対応する文字へと透過的に解決されるので、XMLトークンとしては
     表現されません。

_XML-DECL_
     ELEMS、ENTITIES、NOTATIONSという3つのスロットを持つレコードです。

     このレコードは、XML文書のデータタイプを表現します。それは、
     宣言された要素とその属性のリスト、宣言された記法、
     解析済み一般実体の置換文字列やロードされる手続きのリストなどです。
     通常、xml-declレコードは、それを作るには他にたくさんの方法
     (例えばファイルからロードするなど)があるにも関わらず、DTDかXML
     Schemaから 作られます。

     ELEMS: decl-elemか`#f'の(連想)リスト。後者は、パーザに、
     要素と属性の妥当性検査を行わないように指示します。

     DECL-ELEM: 1つの要素の宣言: `(ELEM-NAME ELEM-CONTENT DECL-ATTRS)';
     ELEM-NAMEはその要素のUNRES-NAME。
     ELEM-CONTENTはELEM-CONTENT-MODEL。
     DECL-ATTRSはATTLISTか、`(ATTR-NAME . VALUE)'の 連想リスト。
     この要素は、要素のパージングを扱うユーザ手続きを宣言できます。
     (例えば、カスタムな妥当性検査を行ったり、タグに出会うたびに
     IDのハッシュを構築するなど。)

     DECL-ATTR: ATTLISTの要素で、1つの属性 `(ATTR-NAME CONTENT-TYPE
     USE-TYPE DEFAULT-VALUE)' の宣言:
     ATTR-NAMEはその宣言された属性のUNRES-NAME、
     CONTENT-TYPEはシンボル`CDATA'、NMTOKEN、NMTOKENS、
     あるいは列挙されたタイプの文字列のリスト。
     USE-TYPEはシンボル`REQUIRED'、`IMPLIED'、`FIXED'。
     default-valueは、デフォルト値としての文字列か、与えられなければ`#f'。

 -- Function: make-empty-attlist
 -- Function: attlist-add attlist name-value
 -- Function: attlist-null?
 -- Function: attlist-remoev-top attlist
 -- Function: attlist->alist attlist
 -- Function: attlist-fold
     名前-値の属性リストを扱うユーティリティ手続きです。

 -- Function: make-xml-token kind head
 -- Function: xml-token? token
     XML-TOKENレコードのコンストラクタと述語です。

 -- Macro: xml-token-kind token
 -- Macro: xml-token-head token
     XML-TOKENレコードのアクセッサマクロです。


File: gauche-refj.info,  Node: SSAXの低レベルパージングコード,  Next: SSAXの高レベルのパーザとスキャナ,  Prev: SSAXデータタイプ,  Up: 関数的なXMLパーザ

11.22.2 SSAXの低レベルパージングコード
--------------------------------------

これらは、プリミティブな字句解析ユニット(名前、空白、タグ)や、
より一般的な断片を扱います。
これらのパーザのほとんどは、適切なコンテキストで呼ばれなければなりません。
例えば、`ssax:complete-start-tag'は、開始タグが検知されその`GI'が
読み込まれたときにのみ呼ばれなければなりません。

 -- Function: ssax:skip-S port
     次のように定義されるS(空白)をスキップします。
           [3] S ::= (#x20 | #x9 | #xD | #xA)
     この手続きは、PORTのスキャン中に遭遇した最初の空白ではない文字を
     返します。この文字は、入力ストリームに残されます。

 -- Function: ssax:ncname-starting-char? a-char
     `NCName'がa-charで始まるかどうかを検査します。

 -- Function: ssax:read-NCName port
     PORTで現在の位置から始まる`NCName'を読み込み、それをシンボルとして
     返します。

 -- Function: ssax:read-QName port
     (名前空間)完全修飾名、`QName'をPORTの現在の位置から読み込みます。

     REC-xml-namesは、
           [6] QName ::= (Prefix ':')? LocalPart
           [7] Prefix ::= NCName
           [8] LocalPart ::= NCName

     戻り値は、UNRES-NAMEです。

 -- Variable: ssax:Prefix-XML
     定義済みのXML名前空間の接頭辞、つまり、'`xml'です。

 -- Function: ssax:read-markup-token port
     この手続きは、マークアップトークンのパージングを開始します。
     ストリームの現在の位置は、`#\<'でなければなりません。
     この手続きは、見ているマークアップトークンがどの種類のものか見当を
     つけるに十分な程度、入力ストリームをスキャンします。
     この手続きは、そのトークンを表現するxml-token構造を返します。
     通常、その時点のマークアップの読み込みは完了していないことに注意して下さい。
     特に、開始タグトークンの属性はスキャンされていません。

     特定の値が返されたときの戻り値とPORTでの位置を詳細に説明します。
    `PI-token'
          `PI'ターゲットのみが読み込まれました。
          処理命令の読み込みを完了してそれを無視するためには、`ssax:skip-pi'を呼びます。
          (`PI'の内容が、属性-値のペアの場合は、)`ssax:read-attributes'も
          便利です。

    `END-token'
          終了タグが完全に読み込まれました。
          現在の位置は、終了の`#\>'文字の直後です。

    `COMMENT'
          コメントが完全に読み込まれスキップされました。
          現在の位置は、コメントが終了する"`-->'"の直後です。

    `CDSECT'
          現在の位置は、"`<!CDATA['"の直後です。
          残りを読むためには、`ssax:read-cdata-body'を使います。

    `DECL'
          この宣言マークアップを識別するキーワード("`<!'"に続くもの)を
          読み込んだところです。現在の位置は、(通常は空白文字である)
          そのキーワードの直後です。

    `START-token'
          この開始タグのキーワード(`GI')を読み込んだところです。
          属性はまだスキャンされていません。
          また、このタグが空の要素を持つかどうかも分かりません。
          このトークンのパージングを終了するためには、
          `ssax:complete-start-tag'を使います。

 -- Function: ssax:skip-pi port
     現在の位置は、`PI'の内側です。 `PI'の残りをスキップします。

 -- Function: ssax:read-pi-body-as-string port
     現在の位置は、`PITarget'を読み込んだ直後です。
     `PI'のボディを読み込んで、それを文字列として返します。
     ポートでは、`PI'を終了する'`?>''の直後の文字を指します。
           [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'

 -- Function: ssax:skip-internal-dtd port
     ポートでの現在の位置は、内部DTDサブセットの内側です
     (例えば、内部DTDサブセットの始まりである`#\[ 'を読み込んだところ)。
     このDTDを終了する、組み合わせとなる"`]>'"までをスキップします。

 -- Function: ssax:read-cdata-body port str-handler seed
     この手続きは、`CDATA'セクションを開始する文字列、"`<![CDATA['"を
     読み込んだ後に呼ばれなければなりません。
     現在の位置は、`CDATA'のボディの最初の位置です。
     この手続きは、`CDATA'のボディの_データ_を読み込み、それらを
     STR-HANDLER(文字データのコンシューマ)へ渡します。

     str-handlerは、`string1' STRING2 SEEDを取る手続き STR-HANDLERです。
     STR-HANDLERの最初の引数STRING1は、改行を含みません。
     2番目の引数STRING2は、改行を含むことがよくあります。
     STR-HANDLERの最初の呼び出しでは、seedは`ssax:read-cdata-body'の
     第3引数として渡されるものです。
     この最初の呼び出しの結果は、文字データのコンシューマの引数seedとして渡され、
     以降同じように続きます。
     STR-HANDLERの最後の呼び出しの結果は、`ssax:read-cdata-body'
     から返されるものです。 基本的な'`fold''イテレータに似ています。

     `CDATA'セクションでは、以下の3つだけの例外を除いて、全ての文字は
     その表面上の値を持ちます。
        * `CR'、`LF'、`CRLF'は行区切りとして扱われ、STR-HANDLERへは
          1つの`#\newline'として渡されます。

        * 組み合わせとなる"`]]>'"は、`CDATA'セクションの終わりであると
          されます。

        * `&gt;'は、`#\>'文字の埋め込みとして扱われます。
          `&lt;'と`&amp;'は特別なものとして認識されない(よって展開されない)ことに
          注意が必要です!

 -- Function: ssax:read-char-ref port
           [66]  CharRef ::=  '&#' [0-9]+ ';'
                            | '&#x' [0-9a-fA-F]+ ';'
     この手続きは、文字参照を表す"`&#'"を読み込んだ後に呼ばれなければ
     なりません。
     この手続きは、この参照を読み込んで対応する文字を返します。
     PORTでの現在の位置は、文字参照の終わりとなる"`;'"の後と なります。
     `WFC: XML-Spec.html#wf-Legalchar'も参照のこと。

     XML勧告のセクション"4.1 文字と実体参照"によると、

          "[定義: 文字参照は、ISO/IEC
          10646文字セットにある特定の文字を参照する。
          例えば、利用できる入力デバイスからは直接アクセスできないものなど。]"
     したがって、入力ストリームの現在の文字エンコーディングに_関係なく_、
     文字コードを文字に変換するために関数`ucscode->char'を使います。

 -- Function: ssax:handle-parsed-entity port name entities
          content-handler str-handler seed
     解析済み実体参照を展開し処理します。
        * PORT - ポート

        * NAME - 展開する解析済み実体の名前。シンボル。

        * ENTITIES - ENTITIESを参照。

        * CONTENT-HANDLER - PORT ENTITIES SEEDを取る手続きで、
          SEEDを返す。

        * STR-HANDLER -
          STR-HANDLER。対象となる実体が宣言済み実体となった
          場合に呼ばれる。
     戻り値は、CONTENT-HANDLERかSTR-HANDLERから返された値です。

     こちらも参照のこと。
            WFC: XML-Spec.html#wf-entdeclared
            WFC: XML-Spec.html#norecursion

 -- Function: ssax:read-attributes port entities
     この手続きは、`Attribute*'を読み込みパーズします。
           [41] Attribute ::= Name Eq AttValue
           [10] AttValue ::=  '"' ([^<&"] | Reference)* '"'
                           | "'" ([^<&'] | Reference)* "'"
           [25] Eq ::= S? '=' S?
     この手続きは、NAME(UNRES-NAME)とVALUE(文字列)のペアである
     ATTLISTを返します。
     PORTでの現在の文字は、NCNameの開始文字ではなく、空白ではない文字です。

     'AttValue'を読み込むときには、以下のルールに留意して下さい。
     "属性の値がアプリケーションに渡されるか妥当性が検査される前に、
     XMLプロセッサはそれを以下のように正規化しなければならない:
        * 文字参照は、属性値に参照された文字を追加することで処理される。

        * 実体参照は、その実体のテキストの置換を再帰的に行うことにより
          処理される。[ENTITIES参照] [名前付きのエンティティ、amp lt gt
          quot aposは定義済みと想定される]

        * 空白文字(`#x20'、`#xD'、`#xA'、`#x9')は、
          外部解析済み実体か内部解析済み実体のリテラルの実体の値の一部である
          "`#xD#xA'"のシーケンスにただ1つの`#x20'が追加されることを
          除いて、正規化された値に`#x20'を追加することで処理される。

        *
          他の文字は、正規化された値をそれらに追加することにより処理される"

     こちらも参照のこと。
           WFC: XML-Spec.html#CleanAttrVals
           WFC: XML-Spec.html#uniqattspec

 -- Function: ssax:resolve-name port unres-name namespaces
          apply-default-ns?
     与えられた適切なNAMESPACESの宣言を用いて、UNRES-NAMEを
     RES-NAMEに変換する。
     最後の引数APPLY-DEFAULT-NS?は、デフォルト名前空間の適用を行うか
     どうかを決めます(例えば、属性名には適用しないなど)。

     `REC-xml-names/#nsc-NSDeclared'によれば、接頭辞"xml"は
     名前空間名"`http://www.w3.org/XML/1998/namespace'"に定義済みで束縛されていると
     されます。

     この手続きは、名前空間の制約をテストします:
     `http://www.w3.org/TR/REC-xml-names/#nsc-NSDeclared'。

 -- Function: ssax:uri-string->symbol uri-str
     URI-STRを適切なシンボルに変換します。

 -- Function: ssax:complete-start-tag tag port elems entities namespaces
     この手続きは、開始タグのマークアップのパージングを完了するためのものです。
     この手続きは、開始タグトークンが読み込まれた後に呼ばれなければなりません。
     TAGはUNRES-NAMEです。 ELEMSは`xml-decl::elems'のインスタンスで、
     手続きに、要素とそれらの属性の妥当性検査を_行わない_ように
     指示するために、`#f'を指定することができます。

     この手続きはいくつかの値を返します。
    ELEM-GI
          RES-NAME。

    ATTRIBUTES
          要素の属性。`(RES-NAME . STRING)'というペアのATTLIST。
          このリストは、`xmlns'属性を_含みません_。

    NAMESPACES
          パージング中の開始タグに含まれる名前空間(再)宣言により修正された後の
          名前空間の入力リスト。

     終了時のPORTでの現在の位置は、開始タグのマークアップを終了する
     `#\>'の後になります。

     こちらも参照のこと。
           VC: XML-Spec.html#enum
           VC: XML-Spec.html#RequiredAttr
           VC: XML-Spec.html#FixedAttr
           VC: XML-Spec.html#ValueType
           WFC: XML-Spec.html#uniqattspec (after namespaces prefixes are resolved)
           VC: XML-Spec.html#elementvalid
           WFC: REC-xml-names/#dt-NSName

     XML勧告では明示されていませんが、XMLNSとXMLNS:属性は、
     (そのデフォルト値を指定するために宣言されることが出来ますが)
     宣言される必要がないことに注意して下さい。

 -- Function: ssax:read-external-id port
     この手続きは、`ExternalID'をパーズします。
           [75] ExternalID ::= 'SYSTEM' S SystemLiteral
                           | 'PUBLIC' S PubidLiteral S SystemLiteral
           [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
           [12] PubidLiteral ::=  '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
           [13] PubidChar ::=  #x20 | #xD | #xA | [a-zA-Z0-9]
                          | [-'()+,./:=?;!*#@$_%]
     この手続きは、`ExternalID'が期待されるところで呼ばれます。
     つまり、現在の文字は、それぞれ`SYSTEM'か`PUBLIC'トークンを開始する
     `#\S'か`#\P'でなければなりません。
     この手続きは、`SystemLiteral'を文字列として返します。
     `PubidLiteral'は、存在したとしても無視されます。


File: gauche-refj.info,  Node: SSAXの高レベルのパーザとスキャナ,  Next: SSAXの高レベルのパーザ - XMLからSXMLへ,  Prev: SSAXの低レベルパージングコード,  Up: 関数的なXMLパーザ

11.22.3 SSAXの高レベルのパーザとスキャナ
----------------------------------------

これらは、全体的な実体(ドキュメント)あるいはその高レベルな断片
(プロローグ、ルート要素など)をパーズします。

 -- Function: ssax:scan-Misc port
     そのコンテキストでの`Misc'をスキャンします。
          [1]  document ::=  prolog element Misc*
          [22] prolog ::= XMLDecl? Misc* (doctypedec l Misc*)?
          [27] Misc ::= Comment | PI |  S
     以下の関数は、プロローグかエピローグのコンテキストで呼ばれます。
     これらのコンテキストでは、空白文字は完全に無視されます。
     `ssax:scan-Misc'からの戻り値は、`PI'トークンか`DECL'トークン、
     `START'トークン、EOFのいずれかです。
     コメントは無視され報告されません。

 -- Function: ssax:read-char-data port expect-eof? str-handler seed
     この手続きは、XML文書かXML要素の文字内容を読むためのものです。
           [43] content ::=
                  (element | CharData | Reference | CDSect | PI
                   | Comment)*
     具体的には、この手続きは`CharData'を読み込み、`CDSect'と
     文字実体を展開し、コメントをスキップします。
     この手続きは、名前付き参照、EOF、`PI'あるいは開始/終了タグの開始地点で
     停止します。

    PORT
          読み込むポート。

    EXPECT-EOF?
          EOFがノーマルかどうか、つまり、文字データがEOFで終わるかどうかを
          表す真偽値。解析済み実体を処理している間はEOFはノーマル。

    STR-HANDLER
          STR-HANDLER。

    SEED
          STR-HANDLERの最初の呼び出し時に渡される引数。

     この手続きは2つの結果、SEEDとTOKENを返します。

     SEEDはSTR-HANDLERの最後の呼び出しの結果、あるいは
     STR-HANDLERが一度も呼ばれなかった場合はオリジナルのseedです。

     TOKENはEOFオブジェクト(これはEXPECT-EOF?が`#t'の場合のみ)か、
        * STARTタグかENDタグを表すxml-token。
          開始トークンの場合は、呼び出し側が読み込みを完了する必要がある。

        * `PI'の開始を表すxml-token。
          この`PI'の残りを読み込むかスキップするかはアプリケーションに
          任される。

        * 名前付き実体参照を表すxml-token。

     `CDATA'セクションと文字参照はインラインで展開され返されません。
     コメントは無視されます。

     XML勧告が要求するように、文字データ中の全ての空白文字は保存されなければなりません。
     しかし、`CR'文字(`#xD')は、`LF'文字(`#A')の前に現れるか
     `#xA'文字で置き換えられた場合は、無視されなければなりません。
     XML勧告のセクション2.10と2.11を参照して下さい。
     また、正規のXML勧告も参照して下さい。

 -- Function: ssax:assert-token token kind gi error-cont
     TOKENが、予想されたKINDのもので、予想されたGIを
     持つことを確認します。GI引数は、実際には2つのシンボル、
     名前空間URIかその接頭辞と、そのローカル名のペアでしょう。
     アサーションが失敗したら、ERROR-CONTに3つの引数、TOKEN KIND GI
     を渡されて評価されます。 ERROR-CONTの結果が返されます。


File: gauche-refj.info,  Node: SSAXの高レベルのパーザ - XMLからSXMLへ,  Prev: SSAXの高レベルのパーザとスキャナ,  Up: 関数的なXMLパーザ

11.22.4 SSAXの高レベルのパーザ - XMLからSXMLへ
----------------------------------------------

これらのパーザは、SSAXパーザをインスタンス化するための構文的フォームのセットです。
ユーザは、完全な妥当性検査、妥当性検査なし、特定の妥当性検査を行うために
このパーザをインスタンス化できます。
ユーザは、どの`PI'について通知されたいかを指定します。
ユーザは、解析済み文字と要素のデータで何をしたいかを知らせます。
後者のハンドラは、パージングがSAXやDOMモデルに従うかを決定します。

 -- Macro: ssax:make-pi-parser my-pi-handlers
     1つの処理命令(`PI')をパーズして処理するパーザを作ります。

     MY-PI-HANDLERS: (PI-TAG . PI-HANDLER)のペアの連想リスト。
     PI-TAGはNCNAMEのシンボル、`PI'ターゲット。 PI-HANDLERはPORT PI-TAG
     SEEDを引数とする手続きで、
     PORTでは`PI'ターゲットの後の最初のシンボルを指しています。
     ハンドラは、`PI'を終了する組み合わせとなる'`?>''を含む、
     `PI'の残りを読み込みます。ハンドラは新しいseedを返します。
     PI-TAGの1つは、シンボル`*DEFAULT*'でしょう。
     これに対応するハンドラは、他のハンドラが扱わない`PI'を処理します。
     `*DEFAULT*' PI-TAGが指定されていない場合は、
     `ssax:make-pi-parser'は、`PI'のボディをスキップするパーザを
     作ります。

     `ssax:make-pi-parser'が返すのは、PORT PI-TAG SEEDを
     取る手続きで、ユーザ指定のハンドラに従い現在の`PI'をパーズします。

 -- Macro: ssax:make-elem-parser my-new-level-seed my-finish-element
          my-char-data-handler my-pi-handlers
     その文字内容や子要素をも含む１つの要素をパーズし処理するパーザを作ります。
     このパーザは通常、ドキュメントのルート要素の適用されます。

    MY-NEW-LEVEL-SEED
          ELEM-GI ATTRIBUTES NAMESPACES EXPECTED-CONTENT SEED
          を引数に取る手続きで、ELEM-GIは処理されようとしている要素のRES-NAMEです。
          この手続きは、要素の内容を処理するハンドラに渡されるseedを生成します。

    MY-FINISH-ELEMENT
          ELEM-GI ATTRIBUTES NAMESPACES PARENT-SEED SEED
          を引数に取る手続きです。この手続きは、ELEM-GIのパージングが完了した時に
          呼ばれます。 SEEDは、最後に呼ばれたパーザからの(あるいは、
          要素が空要素であった場合は、MY-NEW-LEVEL-SEEDからの)結果です。
          PARENT-SEEDは、MY-NEW-LEVEL-SEEDへ渡されたのと同じseedです。
          この手続きは、パーザの結果となるseedを生成するためのものです。

    MY-CHAR-DATA-HANDLER
          STR-HANDLER。

    MY-PI-HANDLERS
          `ssax:make-pi-handler'を参照して下さい。

     生成されたパーザは: START-TAG-HEAD PORT ELEMS ENTITIES NAMESPACES
     PRESERVE-WS? SEED
     を引数に取る手続きです。
     この手続きは、開始タグのトークンが読み込まれた後に呼ばれなければなりません。
     START-TAG-HEADは要素の開始タグのUNRES-NAMEです。
     ELEMSは`xml-decl::elems'のインスタンスです。
     `ssax:complete-start-tag::preserve-ws?'も参照して下さい。

     こちらも参照のこと。
           VC: XML-Spec.html#elementvalid
           WFC: XML-Spec.html#GIMatch

 -- Macro: ssax:make-parser user-handler-tag user-handler-proc ...
     XMLパージングフレームワークのインスタンスである、XMLパーザを作ります。
     これは、提供されるユーザハンドラによって、SAX、DOM、あるいは特化された
     パーザになります。

     USER-HANDLER-TAGはシンボルで、タグに続く手続き的な式を識別します。
     以下にタグと対応する手続きのシグネチャを示します。
     全てのタグが指定される必要はありません。
     いくつかが省略されると、合理的なデフォルトのものが適用されます。

    `tag: DOCTYPE'
          ハンドラ手続きの引数: PORT DOCNAME SYSTEMID INTERNAL-SUBSET?
          SEED

          INTERNAL-SUBSET?が`#t'なら、ポートでの現在の位置は内部DTDサブセットの
          開始となる`#\['を読んだ直後です。
          手続きから戻る前に、このサブセットの残りの読み込みを完了しなければなりません
          (あるいは、それを読むことに興味がなければ、skip-internal-subsetを呼ばなければなりません)。
          終了時のポートでの位置は、DOCTYPE宣言全体のあとの最初のシンボルでなければなりません。

          ハンドラ手続きは4つの値:
          ELEMS ENTITIES NAMESPACES SEED
          を生成しなければなりません。
          ELEMSについては、`xml-decl::elems'を参照して下さい。
          妥当性検査をオフにするためには、`#f'になるでしょう。
          NAMESPACESは、通常、選択されたURI-SYMBに対してUSER-PREFIXを含む
          でしょう。
          デフォルトのハンドラ手続きは、内部サブセットがあってもそれをスキップし、
          `(values #f '() '() seed)'を返します。

    `tag: UNDECL-ROOT'
          ハンドラ手続きの引数: ELEM-GI SEED
          ELEM-GIはルート要素のUNRES-NAMEです。
          この手続きは、パージング中のXML文書が`DOCTYPE'宣言を_含まない_時に
          呼ばれます。
          ハンドラ手続きは、上ではDOCTYPEハンドラですが、4つの値:
          ELEMS ENTITIES NAMESPACES SEED
          を生成しなければなりません。
          デフォルトのハンドラ手続きは、`(values #f '() '()
          seed)'を返します。

    `tag: DECL-ROOT'
          ハンドラ手続きの引数: ELEM-GI SEED
          ELEM-GIは、ルート要素のUNRES-NAMEです。
          この手続きは、パージング中のXML文書が`DOCTYPE'宣言を含む場合に呼ばれます。
          このハンドラ手続きは、新しい`seed'を生成しなければなりません
          (そして、ハンドラが望めば、ルート要素の名前がDOCTYPEにマッチするかを
          検証します)。
          デフォルトのハンドラ手続きは、それ自身を返す手続きです。

    `tag: NEW-LEVEL-SEED'
          ハンドラ手続きの引数:
          `ssax:make-elem-parser'とMY-NEW-LEVEL-SEEDを参照して下さい。

    `tag: FINISH-ELEMENT'
          ハンドラ手続きの引数:
          `ssax:make-elem-parser'とMY-FINISH-ELEMENTを参照して下さい。

    `tag: CHAR-DATA-HANDLER'
          ハンドラ手続きの引数:
          `ssax:make-elem-parser'とMY-CHAR-DATA-HANDLERを参照して下さい。

    `tag: PI'
          ハンドラ手続きの引数: `ssax:make-pi-parser'を参照して下さい。
          デフォルトの値は、`'()'です。

     生成されるパーザは、
     PORT SEEDを取る手続き、
     です。

     この手続きは、ドキュメントのプロローグをパーズして、
     その残りを処理するために(ssax:make-elem-parserで作られた)パーザへ
     引き継いで終了します。

           [1]  document ::=  prolog element Misc*
           [22] prolog ::= XMLDecl? Misc* (doctypedec | Misc*)?
           [27] Misc ::= Comment | PI |  S

           [28] doctypedecl ::=  '<!DOCTYPE' S Name (S ExternalID)? S?
                                  ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
           [29] markupdecl ::= elementdecl | AttlistDecl
                                | EntityDecl
                                | NotationDecl | PI
                                | Comment

   いくつかの便利なユーティリティ手続きがあります。

 -- Function: ssax:reverse-collect-str fragments
     FRAGMENTS(そのいくつかはテキスト文字列)のリストを渡すと、
     そのリストを逆順にして隣り合ったテキスト文字列を連結します。

 -- Function: ssax:reverse-collect-str-drop-ws fragments
     fragments(そのいくつかはテキスト文字列)のリストを渡すと、
     そのリストを逆順にして隣り合ったテキスト文字列を連結します。
     "重要でない"空白文字、つまり、最初や最後、要素の間にある空白文字を
     削除します。文字データに含まれる空白文字には影響を与えません。
     この手続きは、パーズされたSXMLにある"重要でない"空白文字を
     "知的に"削除するために使います。空白文字に関して、厳密に
     XML勧告に準拠したい場合は、代わりに手続き
     `ssax:reverse-collect-str'を使って下さい。

 -- Function: ssax:xml->sxml port namespace-prefix-assig
     これは、上のSSAXパーザのインスタンスで、PORTから読み込まれる
     XMLドキュメントのSXML表現を返します。
     NAMESPACE-PREGIX-ASSIGは、`(USER-PREFIX . URI-STRING)'
     のリストで、特定のURI-STRINGで識別されるある名前空間を
     USER-PREFIXに割り当てます。これは空リストでも構いません。
     この手続きは、SXMLツリーを返します。
     ポートでの位置は、ルート要素の後の最初の文字を指します。


File: gauche-refj.info,  Node: SXMLクエリ言語,  Next: SXML構造を操作する,  Prev: 関数的なXMLパーザ,  Up: ライブラリモジュール - ユーティリティ

11.23 `sxml.sxpath' - SXMLクエリ言語
====================================

 -- Module: sxml.sxpath
     SXPathは、XML Information set
     (Infoset)のインスタンスのS式フォームである
     SXMLのためのクエリ言語です。

     これは最初にOleg Kiselyovによって書かれ、Dmitry LizorkinとKirill
     Lisovsky によって改良されました。 このモジュールにはまた、Dmitry
     LizorkinとKirill LisovskyによりSXPathのために
     書かれたたくさんの手続きが盛り込まれています。

     現在のバージョンは、sxpathlib.scm v3.915、sxpath.scm
     v1.1、sxpath-ext.scm v1.911を ベースにしています。

このマニュアルは、そのほとんどがオリジナルのソースファイルのコメントより
導出されています。

   このモジュールは3つのレイヤから構成されます。
  1.
     SXMLツリーへのアクセスやその変換の手段を提供する基本的なコンバータや
     アプリケータ(適用子)。

  2.
     省略形のSXPathを取り、与えられたノードセットから指定されたパスを満足する
     ノードセットを選択するScheme関数を返す、高レベルなクエリ言語コンパイラ。

  3. W3CのXPathコア関数ライブラリのSXML版を実装する拡張ライブラリ。

* Menu:

* SXPathの基本的なコンバータとアプリケータ::
* SXPathクエリ言語::
* SXPathの拡張::


File: gauche-refj.info,  Node: SXPathの基本的なコンバータとアプリケータ,  Next: SXPathクエリ言語,  Prev: SXMLクエリ言語,  Up: SXMLクエリ言語

11.23.1 SXPathの基本的なコンバータとアプリケータ
------------------------------------------------

コンバータは、以下を満たす関数です。
       type Converter = Node|Nodeset -> Nodeset
   コンバータは、述語としての役割を担うこともあります。
その場合、コンバータが、ノードやノードセットに適用され、空ではないノードセットを
返す場合、述語としてのコンバータは満足したものとみなされます。
このファイルを通して、nilノードセットは失敗を表す`#f'と等価です。

 -- Function: nodeset? x
     与えられたオブジェクトがノードセットならば、`#t'を返します。

 -- Function: as-nodeset x
     Xがノードセットならば、それをそのまま返し、そうでなければそれを
     リストでラップして返します。

 -- Function: sxml:element? obj
     OBJがSXMLの要素であれば#Tを返し、そうでなければ#Fを 返す述語です。

 -- Function: ntype-names?? crit
     関数`ntype-names??'は、判定基準として受け付け可能なノード名のリストを取り、
     関数を返します。この関数は、ノードに適用された際、そのノード名が判定基準リストに
     含まれていれば`#t'を、含まれていなければ`#f'を返す関数です。
           ntype-names?? :: ListOfNames -> Node -> Boolean

 -- Function: ntype?? crit
     関数`ntype??'は、型に関する判定基準を取り、関数を返します。
     この関数は、ノードに適用された際、そのノードがそのテストを満足するかを
     返します。
            ntype?? :: Crit -> Node -> Boolean

     判定基準CRITは、以下のシンボルのうちの1つです。
    `id'
          そのノードが正しい名前(id)を持っているかをテストします。

    `@'
          そのノードがATTRIBUTES-LISTであるかをテストします。

    `*'
          そのノードがELEMENTであるかをテストします。

    `*text*'
          そのノードがテキストノードであるかをテストします。

    `*data*'
          そのノードがデータノード(テキスト、数値、真偽値などで、ペアではない)であるか
          をテストします。

    `*PI*'
          そのノードが`PI'ノードであるかをテストします。

    `*COMMENT*'
          そのノードが`COMMENT'ノードであるかをテストします。

    `*ENTITY*'
          そのノードが`ENTITY'ノードであるかをテストします。

    `*any*'
          どんなタイプのノードに対しても`#t'を返します。

 -- Function: ntype-namespace-id?? ns-id
     この関数は、名前空間IDを取り、述語`Node -> Boolean'を
     返します。この述語はまさにその名前空間IDを持つノードに対しては
     `#t'を返します。NS-IDは文字列です。 `(ntype-namespace-id??
     #f)'は、完全修飾されていない名前を
     持つノードに対して`#t'を返します。

 -- Function: sxml:invert pred
     この関数は、述語を取り、それを反対にして返します。
     与えられた述語が`#f'や'`()'を返す場合、反対にされたものは
     与えられたノード(`#t')を返します。

 -- Function: node-eq? other
 -- Function: node-equal? other
     等価な述語としてのコンパータにカリー化します。すなわち、
            ((node-eq? a) b)    == (eq? a b)
            ((node-equal? a) b) == (equal? a b)

 -- Function: node-pos n
           node-pos:: N -> Nodeset -> Nodeset, or
           node-pos:: N -> Converter

     ノードセットのN番目の要素を選択し、1つの要素を持つノードセットを返します。
     N番目の要素が存在しなければ、空のノードセットを返します。
     `((node-pos 1)
     Nodeset)'は、ノードセットの先頭ノードがあればそれを選択します。
     `((node-pos 2) Nodeset)'は、2番目のノードがあればそれを選択します。
     Nは負の数でも構いません。その場合、ノードはリストの末尾から数えられます。
     `((node-pos -1)
     Nodeset)'は、空ではないノードセットの最後のノードを選択します。
     `((node-pos -2)
     Nodeset)'は、最後から2番目のノードがあればそれを選択します。

 -- Function: sxml:filter pred?
           filter:: Converter -> Converter

     フィルタリングを行う、フィルタアプリケータです。
     引数のコンバータは、`#f'あるいはnilとなることが失敗を意味する述語と
     みなされます。

 -- Function: take-until pred?
           take-until:: Converter -> Converter, or
           take-until:: Pred -> Node|Nodeset -> Nodeset

     述語としてのコンバータとノードセットが与えられると、
     ノードセットの各要素に述語を適用し、
     述語が#Fあるいはnil以外を返すと、
     (その述語が失敗した)その時点までに処理された要素を返します。
     `take-until'は、上のフィルタのバリエーションの1つです。
     `take-until'は、その述語を満足する最初の要素(それ自体は含まない)まで、
     順序付けられた入力のセットの要素をパスします。 `((take-until (not
     pred)) nset)'により返されるノードセットは、 `((filter pred)
     nset)'により返されるノードセットのサブセット - 具体的には接頭辞
     -になります。

 -- Function: take-after pred?
          take-after:: Converter -> Converter, or
          take-after:: Pred -> Node|Nodeset -> Nodeset

     述語としてのコンバータとノードセットを与えると、
     述語をノードセットの各要素に適用し、 述語が`#f'かnil以外を返すと、
     まだ述語が適用されていない要素を返します。
     つまり、述語を満足する最初の要素の後に続く要素を返します。
     `take-after'と`take-until'を一緒に使うと、
     入力のノードセットを3つのパート:
     述語を満足する最初の要素、その要素の前の部分、その要素の後の部分に
     分けます。

 -- Function: map-union proc lst
     procをlstの各要素に適用し、結果のリストを返します。
     procがノードセットを返す場合、それを結果につなぎ合わせます。

     別の観点から見ると、`map-union'はConverter->Converter関数で、
     結合を行いたいコンテキストでの引数としてのコンバータに 位置します。

 -- Function: node-reverse node-or-nodeset
          node-reverse :: Converter, or
          node-reverse:: Node|Nodeset -> Nodeset

     ノードセットでのノードの順番を逆順にします。
     この基本的なコンバータは、逆順のドキュメントオーダーを実装するために
     必要です。(XPath勧告を参照して下さい。)

 -- Function: node-trace title
           node-trace:: String -> Converter

     `(node-trace title)'は、それ自身を返すコンバータです。
     また、自身が適用されるノードやノードセットを、'title'という
     プリフィックスを付けてプリントします。
     このコンバータは、デバッグの際にとても便利です。

   コンバータの組み合わせに続くものは、コンバータを一変させる、
あるいはコンバータのシーケンスを1つの強力なコンバータにつなぎ合わせる
高階関数です。そのゴールは、XPathのロケーションパスに対応する
コンバータとなることです。

   別の観点から見ると、コンバータは、コンバータ群の適用の固定され
名前の付いた_パターン_とみなせます。
以下に挙げるのは、XPathのロケーションパスの仕様を実装する
そのようなパターンの完全なセットです。
結局のところ、これら全てのコンビネータはいくつかの基本的なブロック、
通常の関数的なコンポジション、map-unionとfilterアプリケータ、
ノードセットユニオンなどから構築することができます

 -- Function: select-kids test-pred?
          select-kids:: Pred -> Node -> Nodeset
     ノードを与えると、述語(実際はコンバータ)を満足するその子要素の
     (順序付けられた)サブセットを返します。

          select-kids:: Pred -> Nodeset -> Nodeset
     上と同じですが、ノードセットの全てのノードの子要素から選択します。

 -- Function: node-self pred
           node-self:: Pred -> Node -> Nodeset, or
           node-self:: Converter -> Converter

     select-kidsに似ていますが、自身をその子要素に適用するのでは
     なく、ノードそれ自身に適用します。
     結果のノードセットは、1つのコンポーネントを含むか、
     空(ノードが述語を満足しない場合)になります。

 -- Function: node-join . selectors
           node-join:: [LocPath] -> Node|Nodeset -> Nodeset, or
           node-join:: [Converter] -> Converter

     上のタイトルコメントで説明されるようなロケーションステップ
     あるいはロケーションパスのシーケンスをつなぎ合わせます。

 -- Function: node-reduce . converters
           node-reduce:: [LocPath] -> Node|Nodeset -> Nodeset, or
           node-reduce:: [Converter] -> Converter

     コンバータの通常の関数的なコンポジションです。
     見方を変えると、`((apply node-reduce converters) nodeset)'は
     `(foldl apply nodeset converters)'と等価です。
     すなわち、コンバータのリストをノードセットをseedとして畳み込みや分解
     を行うようなものです。

 -- Function: node-or . converters
           node-or:: [Converter] -> Converter

     このコンビネータは、全てのコンバータを与えられたノードに適用し、
     それらの結果のユニオンを作ります。
     このコンビネータは、XPathのロケーションパスでの'`|''オペレーション
     であるユニオンに対応します。

 -- Function: node-closure test-pred?
           node-closure:: Converter -> Converter

     述語としてのコンバータを満足するノードの全ての_子孫_を選択します。
     このコンビネータは`select-kids'に似ていますが、孫要素やその
     子要素達にも適用を行います。
     このコンビネータは、XPathの軸である"`descendant::'"を実装します。
     概念的には、このコンビネータは以下のように表現することができます。
           (define (node-closure f)
                (node-or
                  (select-kids f)
          	 (node-reduce (select-kids (ntype?? '*)) (node-closure f))))

     この定義は、字面の通り、フィックスポイントのような何かで、
     永久に実行し続けます。しかし、いつかは`(select-kids (ntype?? '*))'
     が空のノードセットを返すことは明白です。その時点では、以降の
     イテレーションはその結果に影響を及ぼさず停止されることができます。


File: gauche-refj.info,  Node: SXPathクエリ言語,  Next: SXPathの拡張,  Prev: SXPathの基本的なコンバータとアプリケータ,  Up: SXMLクエリ言語

11.23.2 SXPathクエリ言語
------------------------

 -- Function: sxpath abbrpath . ns-binding
     Evaluates an abbreviated SXPath

           sxpath:: AbbrPath -> Converter, or
           sxpath:: AbbrPath -> Node|Nodeset -> Nodeset

     ABBRPATHはリストです。これは、以下の書き換えルールに従って
     完全なSXPathに変換されます。
           (sxpath '()) -> (node-join)
           (sxpath '(path-component ...)) ->
                          (node-join (sxpath1 path-component) (sxpath '(...)))
           (sxpath1 '//) -> (node-or
                               (node-self (ntype?? '*any*))
                               (node-closure (ntype?? '*any*)))
           (sxpath1 '(equal? x)) -> (select-kids (node-equal? x))
           (sxpath1 '(eq? x))    -> (select-kids (node-eq? x))
           (sxpath1 '(or@ ...))  -> (select-kids (ntype-names??
                                                    (cdr '(or@ ...))))
           (sxpath1 '(not@ ...)) -> (select-kids (sxml:invert
                                                   (ntype-names??
                                                    (cdr '(not@ ...)))))
           (sxpath1 '(ns-id:* x)) -> (select-kids
                                                (ntype-namespace-id?? x))
           (sxpath1 ?symbol)     -> (select-kids (ntype?? ?symbol))
           (sxpath1 ?string)     -> (txpath ?string)
           (sxpath1 procedure)   -> procedure
           (sxpath1 '(?symbol ...)) -> (sxpath1 '((?symbol) ...))
           (sxpath1 '(path reducer ...)) ->
                          (node-reduce (sxpath path) (sxpathr reducer) ...)
           (sxpathr number)      -> (node-pos number)
           (sxpathr path-filter) -> (filter (sxpath path-filter))

`sxpath'には、いくつかのラッパ関数があります。

 -- Function: if-sxpath path
     `sxpath'は、常にリストを返し、それはSchemeでは`#t'となります。
     `if-sxpath'は、空リストの代わりに`#f'を返します。

 -- Function: if-car-sxpath path
     もし存在すれば、最初に見つかったノードを返します。
     そうでなければ、`#f'を返します。

 -- Function: car-sxpath path
     もし存在すれば、最初に見つかったノードを返します。
     そうでなければ、空リストを返します。

 -- Function: sxml:id-alist node . lpaths
     与えられたノードについて、`(ID_VALUE . ELEMENT)'の
     ペアのリストをインデックスとして構築します。
     LPATHSは、タイプIDの属性のロケーションパスです。


File: gauche-refj.info,  Node: SXPathの拡張,  Prev: SXPathクエリ言語,  Up: SXMLクエリ言語

11.23.3 SXPathの拡張
--------------------

W3CのXPathコア関数ライブラリのSXML版です。

 -- Function: sxml:string object
     XPathの`string'関数(XPath勧告のセクション4.2)に対応するものです。
     与えられたオブジェクトを文字列に変換します。 注意:
       1.
          ノードセットを変換する時は、ドキュメントオーダーは保持されません。

       2. NUMBER->STRING関数は、その結果をXPath勧告の仕様とは少し違った
          フォームで返します。

 -- Function: sxml:boolean object
     XPathの`boolean'関数(XPath勧告のセクション4.3)に対応するものです。
     引数を真偽値に変換します。

 -- Function: sxml:number obj
     XPathの`number'関数(XPath勧告のセクション4.4)に対応するものです。
     引数を数値に変換します。 注意:
       1. 引数は(まだ?)オプションではありません。

       2. `string->number'の変換は、IEEE 754の四捨五入ではありません。

       3. NaNは、0として表現されます。

 -- Function: sxml:string-value node
     XPath勧告のセクション5.1 - 5.7にしたがって、与えられたノードの
     文字列値を返します。

 -- Function: sxml:node? node
     XPathの仕様2.3にしたがい、このテストはいかなるXPathノードに
     対しても真を返します。
     SXMLの補助的なリストや属性のリストは除外されます。

 -- Function: sxml:attr-list obj
     与えられたSXMLノードの属性のリストを返します。
     与えられたノードが要素ではないか、属性のリストを持っていない場合は、
     空リストが返されます。

 -- Function: sxml:id id-index
     SXML要素を、そのユニークなIDによって選択します(XPath勧告 4.1)。
     OBJECTを引数に取るコンバータを返します。
     このOBJECTは、ノードセットか、'`string''関数により
     文字列に変換できるデータタイプです。

     ID-INDEXは、`( (id-value . element) (id-value . element) ...
     )'です。

     このインデックスは、要素をそのユニークなIDによって選択するために使われます。

   XPathオブジェクトの比較子:

 -- Function: sxml:equality-cmp bool-op number-op string-op
     XPathの等値比較: `='、`!='のためのヘルパです。
     BOOL-OP、NUMBER-OP、'STRING-OPはそれぞれ、
     真偽値、数値、文字列のペアのための比較子です。

 -- Function: sxml:equal? a b
 -- Function: sxml:not-equal? a b
     XPathの等値比較: `='、`!='に対応するもので、
     デフォルトの等値テストを使います。

 -- Function: sxml:relational-cmp op
     2つのXPathオブジェクトの関係比較( `<'、`>'、`<='、`>=' )
     を作ります。 `op'は、比較を行う手続き: `<'、`>'、`<='、`>='です。

   XPathの軸。 結果のノードセットにおける順序は維持されます。

 -- Function: sxml:attribute test-pred?
     属性の軸です。

 -- Function: sxml:child test-pred?
     子要素の軸です。
     この関数は、'`select-kids''に似ていますが、処理命令やコメント、
     実体ノードについては、空の子リストを返します。

 -- Function: sxml:parent test-pred?
     親の軸です。

     述語を与えると、`RootNode -> Converter'関数を返します。
     この関数は、rootnodeに適用されると、`node -> parent'と なります。

     このようなコンバータは、` ((sxml:parent test-pred) rootnode) '
     を使って構築され、それが適用されたノードの親を帰します。
     ノードセットに適用された場合、そのノードセットにあるノードの
     親のリストを返します。
     rootnodeはSXMLツリー全体のルートノードである必要はありません。
     興味の対象となるブランチ(枝)のルートノードでも構いません。
     `parent::'軸は、どんなSXMLノードにも使えます。

 -- Function: sxml:ancestor test-pred?
     祖先の軸です。

 -- Function: sxml:ancestor-or-self test-pred?
     祖先と自分の軸です。

 -- Function: sxml:descendant test-pred?
     子孫の軸です。

 -- Function: sxml:descendant-or-self test-pred?
     子孫と自分の軸です。

 -- Function: sxml:following test-pred?
     後続するものの軸です。

 -- Function: sxml:following-sibling test-pred?
     後続する兄弟の軸です。

 -- Function: sxml:namespace test-pred?
     名前空間の軸です。

 -- Function: sxml:preceding test-pred?
     先行するものの軸です。

 -- Function: sxml:preceding-sibling test-pred?
     先行する兄弟の軸です。

   ポピュラーなショートカット:

 -- Function: sxml:child-nodes nodeset
          ((sxml:child sxml:node?) nodeset)

 -- Function: sxml:child-elements nodeset
          ((select-kids sxml:element?) nodeset)


File: gauche-refj.info,  Node: SXML構造を操作する,  Next: CSVテーブル,  Prev: SXMLクエリ言語,  Up: ライブラリモジュール - ユーティリティ

11.24 `sxml.tools' - SXML構造を操作する
=======================================

 -- Module: sxml.tools
     現在のバージョンは、sxml-toolsのCVSのリビジョン3.13から導出されています。

     マニュアルのエントリは主に、オリジナルのソースコードから導出されています。

* Menu:

* SXMLの述語::
* SXMLへのアクセッサ::
* SXMLのモディファイヤ::
* SXPathの補助的ユーティリティ::
* SXMLからマークアップへの変換::


File: gauche-refj.info,  Node: SXMLの述語,  Next: SXMLへのアクセッサ,  Prev: SXML構造を操作する,  Up: SXML構造を操作する

11.24.1 SXMLの述語
------------------

 -- Function: sxml:empty-element? obj
     与えられた要素OBJが空なら#Tを返す述語です。
     空要素は、ネストした要素、テキストノード、`PI'、コメントや実体を
     持ちませんが、属性や名前空間IDは持つかもしれません。
     それは、XMLの`empty-element'のSXML版です。

 -- Function: sxml:shallow-normalized? obj
     与えられたOBJが浅く正規化されたSXML要素であれば`#t'を返します。
     要素それ自体は正規化されていなければなりませんが、ネストした要素は
     テストされません。

 -- Function: sxml:normalized? obj
     与えられたOBJが正規化されたSXML要素であれば`#t'を返します。
     要素それ自体とその全てのネストした要素が正規化されていなければなりません。

 -- Function: sxml:shallow-minimized? obj
     与えられたOBJが浅く最小化されたSXML要素であれば`#t'を返します。
     要素それ自体は最小化されていなければなりませんが、そのネストした要素は
     テストされません。

 -- Function: sxml:minimized? obj
     与えられたOBJが最小化されたSXML要素であれば`#t'が返されます。
     要素それ自体とその全てのネストした要素が最小化されていなければなりません。


File: gauche-refj.info,  Node: SXMLへのアクセッサ,  Next: SXMLのモディファイヤ,  Prev: SXMLの述語,  Up: SXML構造を操作する

11.24.2 SXMLへのアクセッサ
--------------------------

 -- Function: sxml:name obj
     与えられたSXMLノードの名前を返します。
     これは単に`car'のエイリアスに過ぎませんが、カプセル化のために導入されています。

 -- Function: sxml:element-name obj
     `sxml:name'の、与えられたOBJがSXML要素ではない場合は`#f'を返す
     バージョンです。OBJがSXML要素であれば、その名前を返します。

 -- Function: sxml:node-name obj
     `sxml:name'の、与えられたOBJがSXMLノードでない場合は`#f'を返す、
     安全なバージョンです。OBJがSXMLノードであれば、その名前を返します。

 -- Function: sxml:ncname obj
     与えられたobjの完全修飾名(Namespaces in XML production
     [6])のローカルパート、
     つまりその完全修飾名を"`:'"で分割した後ろの部分を返します。
     与えられたノードの名前が`NCName'(Namespaces in XML production
     [4])であれば、 それをそのまま返します。
     SXMLの名前はシンボルですが、この関数は文字列を返すことに注意して下さい。

 -- Function: sxml:name->ns-id sxml-name
     与えられた名前の名前空間ID部分を返します。与えられた名前がLocalNameの
     場合は#Fを返します。

 -- Function: sxml:content obj
     与えられたSXML要素かノードセット(テキストノードと要素ノードのみ)の内容を、
     ドキュメントオーダーにしたがった文字列のリストとネストした要素として
     返します。このリストは、OBJが空要素や空リストの場合は空です。

 -- Function: sxml:content-raw obj
     正規化されたSXML要素の全ての内容を、ATTR-LISTとAUX-LISTを除いて
     返します。 したがってそれは、`PI'、`COMMENT'、`ENTITY'
     ノードとともに、`sxml:content'によって返される`TEXT'や`ELEMENT'も含みます。
     戻り値は、ドキュメントオーダーにしたがったノードのリストか、
     OBJが空要素や空リストの場合は空リストになります。
     この関数は、`sxml:content'よりも高速です。

   SXMLの通常のフォームでは、1つの要素は次のようなリストで表現されます。
       (NAME ATTR-LIST AUX-LIST CONTENT ...)
   ATTR-LISTは`@'で始まるリストで、AUX-LISTは`@@'で 始まるリストです。

   最小化されたフォームでは、AUX-LISTは空であれば省略できます。
ATTR-LISTは、それが空で_かつ_AUX-LISTがなければ省略できます。

   以下の手続きは、ATTR-LISTとAUX-LISTを抽出するものです。

 -- Function: sxml:attr-list-node obj
     与えられたOBJのATTR-LISTを返します。
     ATTR-LISTが存在しなければ`#f'を返します。

 -- Function: sxml:attr-as-list obj
     ATTR-LISTをリストにラップして返します。
     ATTR-LISTが存在せずAUN-LISTがある場合は'`((@))'を返します。
     両方とも存在しない場合には'`()'を返します。

 -- Function: sxml:aux-list-node obj
     与えられたOBJのAUX-LISTを返します。
     ATTR-LISTが存在しなければ`#f'を返します。

 -- Function: sxml:aux-as-list obj
     AUX-LISTをリストにラップして返します。
     AUX-LISTが存在しなければ'`()'を返します。

 -- Function: sxml:attr-list-u obj
     与えられた要素かノードセットの属性のリストを返します。 `((sxpath
     '(@ *)) OBJ)'と類似です。
     属性のリストがない場合は空リストが返されます。

 -- Function: sxml:aux-list obj
     与えられた要素かノードセットの補助ノードのリストを返します。
     `((sxpath '(@@ *)) OBJ)'と類似です。
     補助ノードのリストがない場合は空リストが返されます。

 -- Function: sxml:aux-list-u obj
     与えられた要素かノードセットの補助ノードのリストを返します。
     `((sxpath '(@@ *)) OBJ)'と類似です。
     補助ノードのリストがない場合は空リストが返されます。

     `-u'が付くものは、正規化されていないSXMLノードに対しても
     使えるということを示しています。('u'は'universal'の意味です。)

 -- Function: sxml:aux-node obj aux-name
     与えられたSXML要素OBJでAUX-NAMEという名前の付いている最初の
     補助ノードを返します。そのようなノードがない場合は`#f'を返します。
     注意: 複数のノードがあっても_最初に_見つかったノードのみを
     返します。したがって、ユニークな名前を持っているノード群に対して
     使われることを意図しています。

 -- Function: sxml:aux-nodes obj aux-name
     与えられたSXML要素OBJでAUX-NAMEとうい名前の付いている補助ノードの
     リストを返します。そのようなノードがなければ'`()'を返します。

 -- Function: sxml:attr obj attr-name
     与えられたSXML要素OBJのATTR-NAMEという属性へのアクセッサです。
     戻り値は、その属性が存在すればその属性の値、与えられた要素に
     そのような属性がなければ#Fです。

 -- Function: sxml:num-attr obj attr-name
     与えられたSXML要素OBJのATTR-NAMEという数値の属性への
     アクセッサです。
     戻り値は、その属性が存在してその値が`string->number'により数値へ
     変換できる場合はその属性を数値としてその属性の値、
     与えられた要素にそのような属性がないかその値が数値へ変換できない場合は
     `#f'です。

 -- Function: sxml:attr-u obj attr-name
     与えられたSXML要素OBJのATTR-NAMEという名前の属性への
     アクセッサです。OBJは、(通常はSXML要素の内容である)
     属性リストやノードセットでも構いません。

     戻り値は、その属性が存在すればその属性の値、与えられた要素に
     そのような属性がない場合は`#f'です。

     `-u'が付くものは、正規化されていないSXMLノードに対しても
     使えるということを示しています。('u'は'universal'の意味です。)

 -- Function: sxml:ns-list obj
     与えられた要素の名前空間のリストを返します。 `((sxpath '(@@
     *NAMESPACES* *)) OBJ)'と類似です。
     名前空間のリストがない場合は空リストが返されます。

 -- Function: sxml:ns-id->nodes obj namespace-id
     SXML要素OBJで、与えられたNAMESPACE-IDに対応する名前空間の
     連想リストのリストを返します。 `((sxpath '(@@ *NAMESPACES*
     namespace-id)) OBJ)'と類似です。
     与えられたNAMESPACE-IDに対応する名前空間の連想リストがない場合は
     空リストが返されます。

 -- Function: sxml:ns-id->uri obj namespace-id
     与えられたNAMESPACE-IDに対応するURIを返します。
     与えられたNAMESPACE-IDに対応する名前空間の連想リストがない場合は
     `#f'を返します。

 -- Function: sxml:ns-uri->id obj uri
     与えられた名前空間URIに対応する名前空間IDを返します。

 -- Function: sxml:ns-id ns-assoc
     与えられた名前空間連想リストに対応する名前空間IDを返します。

 -- Function: sxml:ns-uri ns-assoc
     与えられた名前空間連想リストに対応するURIを返します。

 -- Function: sxml:ns-prefix ns-assoc
     与えられた名前空間連想リストに対応する名前空間接頭辞を返します。
     与えられた名前空間IDの(XML文書における)オリジナルの接頭辞は、
     それが名前空間IDと異なる場合は、名前空間連想リストの3番目の要素として
     格納されなければなりません。
     名前空間連想リストでオリジナルの接頭辞が省略されている場合は、
     代わりに名前空間IDが使われます。


File: gauche-refj.info,  Node: SXMLのモディファイヤ,  Next: SXPathの補助的ユーティリティ,  Prev: SXMLへのアクセッサ,  Up: SXML構造を操作する

11.24.3 SXMLのモディファイヤ
----------------------------

正規化されたSXMLデータのコンストラクタやミューテータです。
これらの関数は、正規化されたSXMLデータに最適化されています。
任意の正規化されていないSXMLデータには適用できません。

   ほとんどの関数には2つのバージョンがあります。
  1. 与えられた要素のその場での更新のために副作用が意図された関数。
     これらの名前はエクスクラメーションマークで終わっています。
     このバージョンの戻り値は、特に断りのない限り未定義です。
     例としては、`sxml:change-content!'が挙げられます。

  2. 変更された要素を返す、副作用のない純粋な関数。
     例としては、`sxml:change-content'が挙げられます。

 -- Function: sxml:change-content obj new-content
 -- Function: sxml:change-content! obj new-content
     与えられたSXML要素の内容を、NEW-CONTENTに変更します。
     NEW-CONTENTが空リストの場合は、OBJは空要素に変更されます。
     結果のSXML要素は正規化されています。

 -- Function: sxml:change-attrlist obj new-attrlist
 -- Function: sxml:change-attrlist! obj new-attrlist
     結果のSXML要素は正規化されています。
     NEW-ATTRLISTが空の場合は、OBJのcadrは`(@)'になります。

 -- Function: sxml:change-name obj new-name
 -- Function: sxml:change-name! obj new-name
     SXML要素の名前を破壊的に変更します。

 -- Function: sxml:add-attr obj attr
     属性ATTRが追加されたSXML要素OBJを返します。
     与えられた名前の属性がすでに存在する場合は`#f'を返します。
     ATTRは`(ATTR-NAME ATTR-VALUE)'です。
     `sxml:add-attr!'に対応する純粋関数的な関数です。

 -- Function: sxml:add-attr! obj attr
     要素OBJに属性ATTRを追加します。
     与えられた名前の属性がすでに存在する場合は`#f'を返します。
     結果のSXMLノードは正規化されています。
     `sxml:add-attr'に対応するその場で更新する関数です。

 -- Function: sxml:change-attr obj attr
     属性ATTRの値が変更されたSXML要素OBJを返します。
     与えられた名前の属性がない場合は`#f'を返します。 ATTRは`(ATTR-NAME
     ATTR-VALUE)'です。

 -- Function: sxml:change-attr! obj attr
     要素OBJの属性の値を変更します。 ATTRは`(ATTR-NAME
     ATTR-VALUE)'です。 そのような属性がない場合は`#f'を返します。

 -- Function: sxml:set-attr obj attr
 -- Function: sxml:set-attr! obj attr
     要素OBJの属性ATTRをセットします。
     そのような属性がない場合は新しい属性として追加されます。

 -- Function: sxml:add-aux obj aux-node
     補助ノードAUX-NODEが追加されたSXML要素OBJを返します。

 -- Function: sxml:add-aux! obj aux-node
     要素OBJに補助ノードAUX-NODEを追加します。

 -- Function: sxml:squeeze obj
 -- Function: sxml:squeeze! obj
     与えられたSXML要素OBJとその子孫について、空のリストである属性
     および補助リストを排除します(最小化)。
     最小化され、正規化されたSXML要素が返されます。

 -- Function: sxml:clean obj
     与えられたSXML要素OBJとその子孫について、空リストである属性と、
     全ての補助リストを削除します。
     最小化され、正規化されたSXML要素が返されます。


File: gauche-refj.info,  Node: SXPathの補助的ユーティリティ,  Next: SXMLからマークアップへの変換,  Prev: SXMLのモディファイヤ,  Up: SXML構造を操作する

11.24.4 SXPathの補助的ユーティリティ
------------------------------------

これらは、SXPathの機能を拡張する便利なユーティリティです。

 -- Function: sxml:add-parents obj . top-ptr
     SXMLノードセットに'親へのポインタ'を追加したものを返します。
     親へのポインタは、`(*PARENT* THUNK)'というフォームを持つ
     補助ノードです。THUNKは親要素を返します。

 -- Function: sxml:node-parent rootnode
     高速な'node-parent'関数を返します。
     すなわち、SXML要素を1引数として取り、補助リストで
     `*PARENT*'ポインタを使ってその親ノードを返す関数を返します。
     '`*TOP-PTR*'はルートノードへのポインタとして使われます。
     ルートノードに対して適用されると空リストを返します。

 -- Function: sxml:lookup id index
     要素をそのIDを使って探します。


File: gauche-refj.info,  Node: SXMLからマークアップへの変換,  Prev: SXPathの補助的ユーティリティ,  Up: SXML構造を操作する

11.24.5 SXMLからマークアップへの変換
------------------------------------

SXMLからXMLやHTMLなどのマークアップされたテキストを生成する手続き。

 -- Function: sxml:clean-feed . fragments
     'fragments'をフィルタします。
     fragmentsは、文字列、文字、数値、手続き、`#f'、他のフラグメントの
     リストです。 この関数はツリーを深さ優先でトラバースし、
     文字列、文字、実行された手続きのリストを返し、
     `#f'と'`()'を無視します。

     全ての意味のあるフラグメントは文字列で、 この関数の結果に(APPLY
     STRING-APPEND ... )を 適用すると、そのstring-valueを返します。

     これは、Oleg Kiselyovの`SRV:send-reply'の変種であるとみなすことが
     できるでしょう。
     `SRV:send-reply'はフラグメントを印字(display)しますが、
     この関数は意味のあるフラグメントのリストを返し、ごみをふるい落とします。

 -- Function: sxml:attr->xml attr
     属性のXMLマークアップを作ります。

 -- Function: sxml:string->xml string
     与えられた文字列中の全ての`<'、`>'、`&'、```'、
     `''を対応する文字実体参照に置き換えた、文字列あるいは
     文字列のリストを返します。 `sxml:string->html'も参照して下さい。

 -- Function: sxml:sxml->xml tree
     SXML->XML変換に特化され最適化されたバージョンのノードディスパッチです。

 -- Function: sxml:attr->html attr
     属性のHTMLマークアップを作ります。

 -- Function: sxml:string->html string
     与えられた文字列で、それがエンコーディングを必要とする文字、
     <、>、&、"を含まないことをチェックします。 *Note
     シンプルなHTMLドキュメントの構築::の
     `html-escape-string'も参照して下さい。

 -- Function: sxml:non-terminated-html-tag? tag
     この述語は、"終了タグのない"HTML 4.0のタグに対して`#t'を 返します。

 -- Function: sxml:sxml->html tree
     SXML->HTML変換に対して特化され最適化されたバージョンのノードディスパッチ
     です。


File: gauche-refj.info,  Node: CSVテーブル,  Next: テキストストリームの相違点を計算する,  Prev: SXML構造を操作する,  Up: ライブラリモジュール - ユーティリティ

11.25 `text.csv' - CSVテーブル
==============================

 -- Module: text.csv
     CSV (カンマ区切りの値)
     の表をパーズ/生成するための手続きを提供します。
     実際には、区切り文字はカンマに制限されず、カスタマイズできます。

     CSV
     形式は、「正式な」仕様が無さそうなのにも関わらず、プレーン・テキストで
     表形式のデータを交換するために広く使われています。

     CSV の表は、改行で区切られた RECORD の連続で構成されます。
     それぞれのレコードは、区切り文字(デフォルトではカンマ)で区切られた
     複数の FIELD を含みます。フィールドは、クォートされている
     (二重引用符で囲まれている)場合は、カンマや改行を含むことができます。
     クォートされたフィールドに二重引用符を含めるには、2つの連続する
     二重引用符を使います。通常、フィールドの前後の空白は無視されます。


   現時点では、以下の2つの低レベルな手続きが提供されています。
フィールドにラベル付けをしたり、自動的に変換するなどの
より高レベルな機能の提供を計画しています。

 -- Function: make-csv-reader separator &optional (quote-char #\")
     入力ポートを唯一の引数として取る手続きを返します。
     手続きが呼ばれると、ポートからレコードを1つ読み込み、フィールドの
     リストを返します。入力ポートが EOF に達すると、EOF を返します。

 -- Function: make-csv-writer separator &optional newline (quote-char
          #\")
     出力ポートとフィールドのリストの2つの引数を取る手続きを返します。
     手続きが呼ばれると、SEPARATOR で区切られたフィールドを
     正しくエスケープして出力ポートに出力します。レコードの区切り文字列を
     NEWLINE で指定することもできます。例えば、ファイルが Windows の
     プログラムでも読めるように、`"\r\n"' を渡すことができます。


File: gauche-refj.info,  Node: テキストストリームの相違点を計算する,  Next: 地域化メッセージ,  Prev: CSVテーブル,  Up: ライブラリモジュール - ユーティリティ

11.26 `text.diff' - テキストストリームの相違点を計算する
========================================================

 -- Module: text.diff
     このモジュールでは、`util.lcs' (*Note
     最長共通サブシーケンス::参照)を
     使って、2つのテキストストリーム、あるいは2つの文字列の相違点を計算します。

 -- Function: diff src-a src-b &keyword reader eq-fn
     テキストソースSRC-AとSRC-Bから"編集リスト"を生成します。

     それぞれのテキストソース、SRC-AとSRC-Bは入力ポートか文字列です。
     もし文字列であれば、それは内部的に文字列ポートに変換されます。
     そして、2つのソースからのテキストストリームは、それらに対してREADERを繰り返し
     呼ぶことによってシーケンスに変換されます。デフォルトのREADERはREAD-LINEで、
     2つのシーケンスは編集リストを計算するために`lcs-edit-list'に渡されます。
     `lcs-edit-list'には、等値を検査する関数EQ-FNも渡されます。

     編集リストとは、`src-a'から`src-b'へテキストシーケンスを
     変更するためのコマンドのセットです。編集リストの詳細な説明は、
     `lcs-edit-list'を参照してください。

          (diff "a\nb\nc\nd\n" "b\ne\nd\nf\n")
          =>
            (((- 0 "a"))
             ((- 2 "c") (+ 1 "e"))
             ((+ 3 "f")))

 -- Function: diff-report src-a src-b &keyword reader eq-fn writer
     2つのテキストソースのdiffをとって、その結果をきれいに表示するための
     簡易手続きです。この手続きは、2つのテキストソースの相違点を計算する
     ために`lcs-fold'を呼び出します。SRC-A、SRC-B、
     READER、EQ-FNの意味は、`diff'の場合と同じです。

     WRITERは2つの引数、テキスト要素とタイプ(シンボル`+'、
     シンボル`-'、あるいは`#f'のいずれか)を取る手続きです。
     テキスト要素がSRC-Aにしかない場合は、WRITERがそのテキスト要素と
     `-'とともに呼ばれます。テキスト要素がSRC-Bにしかない場合は、
     WRITERはそのテキスト要素と`+'とともに呼ばれます。
     テキスト要素が両方のソースにある場合は、WRITERはそのテキスト要素と
     `#f'とともに呼ばれます。WRITERのデフォルトの手続きは、
     渡されたテキスト要素を現在の出力ポートにユニファイドdiffのようなフォーマットで
     出力します。
          (diff-report "a\nb\nc\nd\n" "b\ne\nd\nf\n")
     displays:
          - a
            b
          - c
          + e
            d
          + f


File: gauche-refj.info,  Node: 地域化メッセージ,  Next: シンプルなHTMLドキュメントの構築,  Prev: テキストストリームの相違点を計算する,  Up: ライブラリモジュール - ユーティリティ

11.27 `text.gettext' - 地域化メッセージ
=======================================

 -- Module: text.gettext
     このモジュールは地域化メッセージを扱うユーティリティを提供します。
     API は GNU の gettext と互換性があり、メッセージは `*.po' および
     `*.mo' ファイルから読み込まれます。それゆえ、GNU の gettext
     toolchain
     をつかって地域化メッセージを準備することができます。しかし、このコードは
     Alex Shinn によってスクラッチから書き起こされたものであり、GNU の
     gettext ライブラリには依存していません。

     この実装は GNU の gettext API を以下のように拡張したものです。
        *
          複数のメッセージファイルから、カスケードされた方法で読み込むことができます。
          これにより、アプリケーションはメッセージファイルの部分を共有できます。

        * 複数のロケール/ドメインを同時に扱えます。

     SRFI-29 (*Note 地域化::参照) はこれとは別のメッセージの地域化
     機構を提供しています。ポータブルなプログラムでは、SRFI-29
     の方がよいこと もありますが、一般には、Gauche
     スクリプトでは、`text.gettext' の
     方を推奨します。それは、既存のメッセージファイルとの互換性と柔軟性の
     ためです。

gettext-互換の API
------------------

 -- Function: textdomain domain-name &optional locale dirs cdir cached?
          lookup-cached?
     アプリケーション用に、デフォルトのドメインとそのほかのパラメータを
     設定します。この設定は、以降の `gettext' の呼出しに影響を与えます。

     DOMAIN は文字列または文字列のリストで、ドメイン(`.mo' あるいは
     `.po' ファイル名)を C の gettext と同じように指定します。 `#f' を
     DOMAIN-NAME として渡すと、デフォルトのドメインアクセサ
     手続きが得られます。また、複数のドメインを DOMAIN-NAMEにあたえる
     ことができあす。
          (textdomain '("myapp" "gimp"))  ; search 1st myapp, then gimp
          (gettext "/File/Close")         ; "Close" from gimp unless overridden

     LOCALE は文字列または文字列のリストで、標準的なUnixのフォーマット
     `LANG[_REGION][.ENCODING]' です。フォールバックを指定するロケール
     のリストを渡すこともできます。

          (textdomain "myapp" '("ru" "uk"))  ; search 1st Russian then Ukranian,
          (gettext "Hello, World!")          ; which are somewhat similar

     DIRS は実際のメッセージカタログを含む `LOCALE/CDIR/'
     ディレクトリのサーチパスです。これは常にシステムのデフォルト(たとえば、
     `"/usr/share/locale"')に追加されます。そして、コロンで区切られた
     `GETTEXT_PATH' 環境変数を継承します。

     CDIR はカテゴリーディレクトリで、既定値を `LC_CATEGORY'
     環境変数または、適当なシステム既定値(たとえば `LC_MESSAGES')に
     設定します。一般にはこれを指定する必要はありません。

     CACHED? は個別のメッセージをキャッシュするかを意味し、デフォルトは
     `#t' です。

     LOOKUP-CACHED?
     は、これらのパラメータで生成されるディスパッチをキャッシュするかどうか
     を意味し、デフォルトは `#t' です。

     `textdomain' はこれらのパラメータを内部の `make-gettext' に
     渡し、その結果を、`gettext' で使われるグローバルなディスパッチに
     束縛します。これらのクロージャを複数の別々のドメインやロケールを一度に
     扱うのに便利なように、手で構築することができます。(これらは
     サーバ環境で便利です。) 後述の `make-gettext' を参照してください。

     `textdomain' はそのドメインの情報をもつ _アクセサ手続き_を
     返します。詳細については、後述の `make-gettext'
     を参照してください。

 -- Function: gettext msg-id
     MSG-ID の翻訳されたメッセージを返します。もし、翻訳された
     メッセージがなければ、MSG-ID それ自身を返します。

 -- Function: ngettext msg-id &optional msg-id2 num
     GETTEXTと似ていますが、複数形を処理するのに使うことが
     できます。単数形のメッセージを MSG-ID へ、複数形のメッセージを
     `msg-id2' に渡します。NUM 引数は、複数形を決定
     するのに使われます。もし、メッセージカタログが見つからなければ、
     NUM が 1 のときは、MSG-ID が返り、そうでなければ、 MSG-ID2
     が返ります。

 -- Function: bindtextdomain domain dirs
     ドメイン DOMAIN のサーチパスを DIRS に設定します。
     単一のディレクトリ名であったり、ディレクトリのリストであったりします。

 -- Function: dgettext domain msg-id
 -- Function: dcgettext domain msg-id locale
     DOMAIN 中の MSG-ID の翻訳されたメッセージを返します。 `dcgettext'
     は LOCALE も引数としてとります。

低水準の柔軟な API
------------------

以下の手続きはより柔軟性のあるインタフェースで、この上で、gettext-互換の
API が書かれています。

 -- Function: make-gettext &optional domain locale dirs gettext-cached?
          lookup-cached?
     _アクセサ手続き_ を生成して返します。返された手続きは、
     地域化されたメッセージを検索するメソッドをカプセル化しています。

     引数の意味は上述の `textdomain' と同じです。 実際は、`textdomain'
     は `make-gettext' を呼び、その後、
     それは、結果をこのグローバルパラメータに束縛します。`make-gettext'
     を直接呼んで、自分自身で、アクセサ手続きを管理することもできます。

          (define my-gettext (make-gettex "myapp"))
          (define (_ (my-gettext 'getter)))
          (_ "Hello, World!")


File: gauche-refj.info,  Node: シンプルなHTMLドキュメントの構築,  Next: 入力ストリームのパージング,  Prev: 地域化メッセージ,  Up: ライブラリモジュール - ユーティリティ

11.28 `text.html-lite' - シンプルなHTMLドキュメントの構築
=========================================================

 -- Module: text.html-lite
     HTML ドキュメントを簡単に構築するための手続きを提供します。
     例えば、以下のコードは HTML のテーブルを構築します。
          (html:table
            (html:tr (html:th "Item No") (html:th "Quantity"))
            (html:tr (html:td 1) (html:td 120))
            (html:tr (html:td 2) (html:td 30))
            (html:tr (html:td 3) (html:td 215)))
     詳細については、以下の `html:ELEMENT' の説明を見てください。

     このモジュールでは生成されたHTMLドキュメントに関して、
     例えばアトリビュートに有効な値が入っているか、要素の内容はDTDを満たしているか、
     等のチェックをほとんど行いません。また、HTMLをパーズする関数も提供されません。
     それが「lite」の名の由来です。

 -- Function: html-escape
 -- Function: html-escape-string string
     HTML に含まれる"安全でない"文字をエスケープします。 `html-escape'
     は、現在の入力ポートから文字列を読み込み、
     結果を現在の出力ポートへ書き出します。`html-escape-string' は
     STRING を入力とし、文字列を返します。

 -- Function: html-doctype &keyword type
     HTML ドキュメントの文書型宣言を返します。 TYPE
     は、以下のいずれかを指定します (デフォルトは`:html-4.01-strict'
     です)。
    `:html-4.01-strict, :html-4.01, :strict'
          HTML 4.01 Strict DTD

    `:html-4.01-transitional, :transitional'
          HTML 4.01 Transitional DTD

    `:html-4.01-frameset, :frameset'
          HTML 4.01 Frameset DTD

    `:xhtml-1.0-strict, :xhtml-1.0'
          XHTML 1.0 Strict DTD

    `:xhtml-1.0-transitional'
          XHTML 1.0 Transitional DTD

    `:xhtml-1.0-frameset'
          XHTML 1.0 Frameset DTD

    `:xhtml-1.1'
          XHTML 1.1 DTD

 -- Function: html:ELEMENT ARGS ...
     ELEMENT の HTML 要素を構築します。現時点では以下の要素が
     サポートされています。 (HTML 4.01 DTD
     `http://www.w3.org/TR/html4/sgml/dtd.html'
     に定義されている要素です)。
          a        abbr       acronym    address     area      b
          base     bdo        big        blockquote  body      br
          button   caption    cite       code        col       colgroup
          dd       del        dfn        div         dl        dt
          em       fieldset   form       frame       frameset
          h1       h2         h3         h4          h5        h6
          head     hr         html       i           iframe    img
          input    ins        kbd        label       legend    li
          link     map        meta       nofrmaes    noscript  object
          ol       optgroup   option     p           param     pre
          q        samp       script     select      small     span
          strong   style      sub        sup         table     tbody
          td       textarea   tfoot      th          thead     title
          tr       tt         ul         var

     これらの手続きは、テキスト・セグメントのツリーを返すので、
     `write-tree' でポートに書き出したり、`tree->string' で
     文字列に変換したりできます (*Note 怠惰なテキスト構築::参照)。

     要素のアトリビュートは要素の内容に先立つキーワード-値の表記で指定することができます。
          (tree->string (html:a :href "http://foo/bar" "foobar"))
            =>
            "<a href=\"http://foo/bar\">foobar</a>\n"

          (tree->string
            (html:table :width "100%" :cellpading 0 "content here"))
            =>
            "<table width=\"100%\" cellpadding=\"0\">content here</table>\n"

     属性に与える真偽値は特別な意味を持ちます。 `#t'
     が与えられると、属性は値なしでレンダリングされます。 `#f'
     が与えられると、属性それ自体がレンダリングされません。
          (tree->string (html:table :border #t))
            => "<table border></table>\n"

          (tree->string (html:table :border #f))
            => "<table></table>\n"

     属性の値における特別な文字は、手続きによってエスケープされますが、
     要素の内容にある特別な文字はエスケープされません。それをエスケープ
     するのは呼び出し側の責任です。

     内容を持たない HTML
     要素に内容を与えると手続きはエラーを通知します。
     手続きは、与えられた属性が妥当であるか、与えられた内容がその要素に
     とって妥当であるかのチェックはしません。


File: gauche-refj.info,  Node: 入力ストリームのパージング,  Next: 文字変換,  Prev: シンプルなHTMLドキュメントの構築,  Up: ライブラリモジュール - ユーティリティ

11.29 `text.parse' - 入力ストリームのパージング
===============================================

 -- Module: text.parse
     入力ポートに対して単純な解析を行うユーティリティのコレクションです。
     API は Oleg Kiselyov 氏の入力解析ライブラリ (*Note OLEG1: oleg1.)
     に 触発され、互換性を持つものです。氏のライブラリは、他のたくさんの
     ライブラリで使われています。特に、Scheme
     のみで書かれたパーサ/ジェネレータ である SSAX (*Note SSAX: ssax.)
     が挙げられます。

     このモジュールは、氏の `input-parse.scm' や `look-for-str.scm'
     の代わりに使うことができます。

     Gauche
     で効果的になるように手続きを再実装しました。特に、`string-set!'
     の使用は完全に取り除きました。インターフェースを少し拡張したので、
     文字セットや述語、文字のリストにも使うことができます。

     これらの手続きは、与えられた入力ポートに対してシーケンシャルに動作します。
     それは、ポートから必要なだけ読み、余分な文字をバッファリングしないということです。

 -- Function: find-string-from-port? str in-port &optional max-no-chars
     入力ポート IN-PORT から、文字列 STR を探します。 オプショナル引数
     MAX-NO-CHARS は、ポートから読み込まれる最大文字数を
     制限します。省略されると、検索する範囲は EOF までとなります。

     STR が見つかると、手続きはすでに読み込んだ文字の数を返します。
     IN-PORT の次回の読み込みは、STR の次の文字を返します。 STR
     が見つからない場合、`#f' が返ります。

     注意: この手続きはその名前に「`?'」がつきますが、Scheme
     の慣習に反し、 真偽値ではない値を返すことがあります。

 -- Function: peek-next-char &optional port
     現在の文字を破棄し、PORT
     から次の文字を読みます。一文字先読みするのに 便利です。PORT
     が省略されると、現在の入力ポートが使われます。

   以下の手続きでは、CHAR-LIST は次のどれかを意味します。
   * 文字セット。

   * 文字、文字セット、シンボル `*eof*' の任意の組み合わせのリスト。
   [That denotes a set of characters.] シンボル `*eof*' が含まれる場合、
EOF の条件もまた含まれます。`*eof*' が含まれない場合、EOF の条件は
エラーとして扱われます。

 -- Function: assert-curr-char char-list string &optional port
     PORT から文字を読みます。その文字が CHAR-LIST に含まれている場合は
     その文字を返します。そうでなければ、STRING を含むメッセージとともに
     エラーを通知します。

 -- Function: skip-until char-list/number &optional port
     CHAR-LIST/NUMBER は、文字のリストか数です。
     数の場合、たくさんの文字を読んで、`#f' を返します。
     入力が十分に長くない場合は、エラーが通知されます。
     CHAR-LIST/NUMBER が文字のリストの場合、その文字リストに属する文字に
     出会うまで PORT を読み込み、その文字を返します。 PORT
     が省略された場合、現在の入力ポートが使われます。

 -- Function: skip-while char-list &optional port
     CHAR-LIST に属しない文字に出会うまで、PORT を読み込みます。
     文字はストリームに残されます。EOF に達したら EOF が返されます。
     PORT が省略された場合、現在の入力ポートが使われます。

     この例では、入力から空白スペースをスキップしています。ポートからの次の
     読み込みは、最初の空白スペースでない文字を返します。
          (skip-while #[\s] port)

 -- Function: next-token prefix-char-list break-char-list &optional
          comment port
     PREFIX-CHAR-LIST に含まれる文字はいくつでもスキップします。
     そして、BREAK-CHAR-LIST に含まれる文字に出会うまで、文字を
     蓄積します。蓄積された文字群は文字列として返されます。 中断文字は
     PORT に残されます。

     手続きが EOF に達し、`*eof*' が BREAK-CHAR-LIST に含まれていない
     場合、COMMENT が含まれたメッセージとともにエラーが通知されます。

 -- Function: next-token-of char-list/pred &optional port
     読み込んだ文字が CHAR-LIST/PRED にある限り蓄積し、文字列として
     返します。CHAR-LIST/PRED
     に含まれない最初の文字はポートに残されます。

     CHAR-LIST/PRED は文字のリストか文字を取る述語です。述語の場合、
     それぞれの文字がその述語に渡され、真の値が返る場合はその文字は
     CHAR-LIST/PRED に属するとみなされます。

 -- Function: read-string n &optional port
     N 文字まで読み込み、文字列として蓄積しそれを返します。
     入力ストリームに含まれる文字のほうが少ない場合、有効な文字を可能な限り
     含む文字列が返ります。


File: gauche-refj.info,  Node: 文字変換,  Next: 怠惰なテキスト構築,  Prev: 入力ストリームのパージング,  Up: ライブラリモジュール - ユーティリティ

11.30 `text.tr' - 文字変換
==========================

 -- Module: text.tr
     このモジュールは、入力ストリームから指定の文字を置き換えて出力する、
     文字変換(transliterate)機能を提供します。
     Unixの`tr(1)'コマンドで実装され、`sed'や`perl'にも
     採り入れられている機能です。

     Gaucheの`tr'はマルチバイト文字／文字列を正しく扱います。

 -- Function: tr from-list to-list &keyword :complement :delete
          :squeeze :table-size :input :output
     INPUTから文字を読み込み、その文字がFROM-LIST内にあれば
     対応するTO-LIST内の文字に置き換えて、OUTPUTへと書き出します。
     FROM-LISTに無い文字はそのままOUTPUTへと渡されます。

     INPUTとOUTPUTの既定値はそれぞれ現在の入力ポートと 出力ポートです。

     FROM-LISTとTO-LISTは文字列でなければなりません。
     その中には次のような表記を使うことができます。それ以外の文字はそのまま使われます。

    `x-y'
          文字`x'から文字`y'までの文字の昇順の並びと解釈されます。
          `x'と`y'は含まれます。文字の並びはGaucheの内部文字エンコーディングに
          よって決定されるので、一般には`x'と`y'は同じキャラクタクラスの中に
          止めておいた方が安全でしょう。`x'は`y'より小さくなければなりません。

    `x*n'
          文字`x'の`n'個の並び。`n'は10進数で表記された数値です。
          これはTO-LISTでのみ有効で、FROM-LISTで使うとエラーになります。
          `n'が省略されるか0の場合、`x'はTO-LISTの長さがFROM-LIST
          の長さに達するまで繰り返されます(その場合、TO-LISTの残りは無視されます)。

    ``\'x'
          文字`x'それ自身。特殊文字そのものを埋め込みたい場合に使います。
          文字列のリーダも`\'を解釈するので、`\\'と書かねばならないことに注意
          して下さい。

          グラフィカルでない文字のための構文はありません。文字列リーダの構文を使って
          そのような文字を文字列に含めることができます。

     いくつか例を挙げます。
          ;; 大文字と小文字を交換します
          (tr "A-Za-z" "a-zA-Z")

          ;; ひらがなとかたかなを交換します
          (tr "ぁ-んァ-ン" "ァ-ンぁ-ん")

          ;; 7ビットのノングラフィカルな文字を`?'に変換します
          (tr "\x00-\x19\x7f" "?*")

     TO-LISTがFROM-LISTより短い場合、動作はキーワード引数DELETEに
     依存します。もし真の値がDELETEに与えられれば、FROM-LISTに現われて
     TO-LISTに対応するものがない文字は入力から取り除かれます。そうでなければ
     そのような文字はそのまま出力されます。

     真の値がCOMPLEMENTに与えられた場合、FROM-LISTの文字の
     補集合がFROM-LISTとして使われます。この文字集合は極めて大きくなる
     可能性があることに注意してください。従って、一般にこのオプションは
     TO-LISTに`*'を使ってそれらの文字を一文字にマッピングするか、
     `delete'オプションと併用するかしないとあまり意味がありません。

     真の値がSQUEEZEに与えられた場合、同じ文字への置換が2つ以上並ぶ場合に
     2つめ以降の文字が削除されます。TO-LISTが空の場合は、FROM-LIST
     に含まれる文字で同一文字が並んだ場合に2つめ以降の文字が削除されます。

     内部的に、`tr'はキャラクタのマッピングのためにテーブルを使用します。
     但し、Gaucheでは極めて大きな文字セットを扱うため、テーブルはキャラクタコードの
     小さい文字のみに対して使われます(デフォルトではコード255以下の文字)。
     もし、より大きな文字を頻繁に変換することが分かっていて、メモリを余分に使っても
     速度を上げたい場合は、このテーブルの大きさをTABLE-SIZEキーワード引数で
     指定することができます。例えばEUC-JPコードで大量の平仮名と片仮名を変換する場合は、
     TABLE-SIZEを42483以上にすると、全ての変換がテーブルルックアップで
     行われます。

     `tr'が変換テーブルを計算するのにいくらかオーバーヘッドがあることに
     注意して下さい。内側のループで`tr'を繰り返し呼ぶような場合は
     下に示す`build-transliterator'を使った方が良いでしょう。

 -- Function: string-tr string from-list to-list &keyword :complement
          :delete :squeeze :table-size
     入力をSTRINGから取って変換結果を文字列で返す以外は`tr'と同じです。

 -- Function: build-transliterator from-list to-list &keyword
          :complement :delete :squeeze :table-size :input :output
     実際の変換動作をする手続きを作成して返します。内部データのセットアップを済ませるため、
     同じ文字変換セットに対して`tr'を繰り返し呼ぶような場合は、この手続きを用いることで
     初期化のオーバヘッドを軽減することができます。

     註記：INPUTやOUTPUTキーワード引数が省略された場合、
     作成される変換手続きは、それが使用された時点でのカレント入出力ポート
     を参照します。

          (with-input-from-file "huge-file.txt"
            (lambda ()
              (let loop ((line (read-line)))
                (unless (eof-object? line) (tr "A-Za-z" "a-zA-Z")))))

          ;; 以下の方が効率良く動作します...

          (with-input-from-file "huge-file.txt"
            (lambda ()
              (let ((ptr (build-transliterator "A-Za-z" "a-zA-Z")))
                (let loop ((line (read-line)))
                  (unless (eof-object? line) (ptr))))))



File: gauche-refj.info,  Node: 怠惰なテキスト構築,  Next: 組み合わせ,  Prev: 文字変換,  Up: ライブラリモジュール - ユーティリティ

11.31 `text.tree' - 怠惰なテキスト構築
======================================

 -- Module: text.tree
     テキストを生成する場合によく使われるシンプルな手続きを定義します。

     プログラムでテキストを生成する場合、テキストの断片をつなぎ合わせて行く操作が
     非常に多く現われます。しかし単純に`string-append'を繰り返し
     呼んでしまうと、中間結果の文字列を保持するためだけにメモリアロケーションが多発しますし、
     途中でエラーが発生した場合にその中間結果は結局捨てられてしまうかもしれません
     (例えば、CGIスクリプト中でHTMLドキュメントを構築してゆくような場合を考えてみて下さい)。

     よく知られた効率の良い方法は、テキストの断片をつなぎ合わせるのを本当に必要に
     なるまで遅らせることです。Schemeではそれは非常に簡単です。単に断片をコンス
     していって木構造を作り、最後にそれをトラバースしてテキストを作成するのです。
     場合によっては、トラバースしながらテキストを出力すれば事足りてしまうので、
     中間結果のバッファを持つ必要さえありません。 (Hans
     Boehmのガベージコレクションライブラリに附属している "cord"
     ライブラリ
     はこのテクニックを実装したもので、エディタ等のアプリケーションで非常に効率良く
     動作することが知られています)。

     木構造をトラバースする手続きなどほんの2〜3行で書けてしまいますが、
     「一度、そして一度だけ」の精神の下に、このモジュールを提供します。
     インタフェースが統一されてたほうが便利ですしね。

 -- Generic Function: write-tree tree &optional out
     TREEをテキストの木構造とみなして、出力ポートOUTに出力します。
     OUTが省略された場合は現在の出力ポートが使われます。

     下に示す2つのメソッドが定義されています。より複雑な動作をさせたい場合は、
     単純なリストの替わりにノードとなるクラスを定義して、それにメソッドを定義するようにすれば
     動作をカスタマイズできます。

 -- Method: write-tree ((tree <list>) out)
 -- Method: write-tree ((tree <top>) out)
     `write-tree'の既定の動作です。TREEがリストなら、その要素それぞれに
     ついて`write-tree'を呼び出します。それ以外のオブジェクトに関しては
     `display'を呼んで出力します。

 -- Function: tree->string tree
     出力文字列ポートを作成して`write-tree'を呼び、生成された文字列を返します。


File: gauche-refj.info,  Node: 組み合わせ,  Next: メッセージダイジェストフレームワーク,  Prev: 怠惰なテキスト構築,  Up: ライブラリモジュール - ユーティリティ

11.32 `util.combinations' - 組み合わせ
======================================

 -- Module: util.combinations
     このモジュールは、いくつかの便利なコンビネーションや順列とそれに関連する
     操作の手続きを実装しています。

     このモジュールのほとんどの手続きは2つのバージョンを持っています。
     1つはアスタリスクの付かない手続き(例えば、`permutations')で、
     与えられたセットにある全ての要素を区別して扱います。もう1つは、
     アスタリスクの付く手続き(例えば、`permutations*')で、重複を
     考慮します。アスタリスクの付く手続きは、オプショナルなEQ引数を取り
     ます。それは等値性のテストに使われ、デフォルトは`eqv?'です。

 -- Function: permutations set
 -- Function: permutations* set &optional eq
     リストSETの全ての順列のリストを返します。

          (permutations '(a b c))
            => ((a b c) (a c b) (b a c) (b c a) (c a b) (c b a))

          (permutations '(a a b))
            => ((a a b) (a b a) (a a b) (a b a) (b a a) (b a a))

          (permutations* '(a a b))
            => ((a a b) (a b a) (b a a))

     SETがある程度の要素を持っている場合、可能性のある順列の数は
     爆発的に大きくなります。注意して使って下さい。
     一度にそれぞれの順列を処理したい場合は、下記の`permutations-for-each'の
     使用を考慮して下さい。

 -- Function: permutations-for-each proc set
 -- Function: permutations*-for-each proc set &optional eq
     リストSETのそれぞれの順列に対して、PROCを呼び出します。
     戻り値は未定義値です。

 -- Function: combinations set n
 -- Function: combinations* set n &optional eq
     リストSETのN個の要素の可能性のある全ての順列のリストを 返します。

          (combinations '(a b c) 2)
            => ((a b) (a c) (b c))

          (combinations '(a a b) 2)
            => ((a a) (a b) (a b))

          (combinations* '(a a b) 2)
            => ((a a) (a b))

     SETが大きいときは、組み合わせの爆発について注意して下さい。

 -- Function: combinations-for-each proc set n
 -- Function: combinations*-for-each proc set n &optional eq
     SETのN個の要素のそれぞれの組み合わせについてPROCを
     呼び出します。戻り値は未定義値です。

 -- Function: power-set set
 -- Function: power-set* set &optional eq
     リストSETの累乗集合(全てのサブセット)を返します。

          (power-set '(a b c))
            => (() (a) (b) (c) (a b) (a c) (b c) (a b c))

          (power-set* '(a a b)
            => (() (a) (b) (a a) (a b) (a a b))

 -- Function: power-set-for-each proc set
 -- Function: power-set*-for-each proc set &optional eq
     SETのそれぞれのサブセットについてPROCを呼び出す。

 -- Function: power-set-binary set
     `power-set'のように、SETの累乗集合を返しますが、順番が異なります。
     `power-set-binary'はサブセットの空間を深さ優先でトラバースしますが、
     `power-set'は横型探索を行います。

          (power-set-binary '(a b c))
            => (() (c) (b) (b c) (a) (a c) (a b) (a b c))

 -- Function: cartesian-product list-of-sets
 -- Function: cartesian-product-right list-of-sets
     LIST-OF-SETSにあるセットのデカルト積を返します。
     `cartesian-product'は左固定順で結果を構築しますが
     (一番右の要素がまず異なる)、
     `cartesian-product-right'は右固定順で行います
     (一番左の要素がまず異なる)。

          (cartesian-product '((a b c) (0 1)))
            => ((a 0) (a 1) (b 0) (b 1) (c 0) (c 1))

          (cartesian-product-right '((a b c) (0 1)))
            => ((a 0) (b 0) (c 0) (a 1) (b 1) (c 1))


File: gauche-refj.info,  Node: メッセージダイジェストフレームワーク,  Next: 同型判定,  Prev: 組み合わせ,  Up: ライブラリモジュール - ユーティリティ

11.33 `util.digest' - メッセージダイジェストフレームワーク
==========================================================

 -- Module: util.digest
     このモジュールは、MD5 (*Note MD5メッセージダイジェスト::参照)や
     SHA1 (*Note SHA1メッセージダイジェスト::参照)などの、メッセージ
     ダイジェストアルゴリズムのためのベースクラスと一般的なインターフェースを
     提供します。

 -- Class: <message-digest-algorithm-meta>
     メッセージダイジェストアルゴリズムの実装のメタクラスです。

 -- Class: <message-digest-algorithm>
     メッセージダイジェストアルゴリズムの実装のベースクラスです。

メッセージダイジェストアルゴリズムの具体サブクラスは、以下のメソッドを
実装しなければなりません。

 -- Generic function: digest-update! algorithm data
     メッセージダイジェストアルゴリズムのインスタンスを取り、
     それを(不完全な可能性のある)文字列で表されるデータDATAで
     更新します。

 -- Generic function: digest-final! algorithm
     メッセージダイジェストアルゴリズムのインスタンスを終了させ、
     そのダイジェストの結果を不完全文字列で返します。

 -- Generic function: digest class
     ダイジェストルーチンのラッパです。メッセージダイジェストアルゴリズム
     CLASSを与え、現在の入力ポートから入力データをEOFまで読み込み、
     そのダイジェストの結果を不完全文字列で返します。

 -- Generic function: digest-string class string
     ダイジェストルーチンのラッパです。メッセージダイジェストアルゴリズム
     CLASSを与え、入力データをSTRINGから読み込み、
     そのダイジェストの結果を不完全文字列で返します。

 -- Function: digest-hexify digest-result
     ユーティリティ手続きです。ダイジェストの結果、DIGEST-RESULTを
     与えると、それを16進文字列に変換します。


File: gauche-refj.info,  Node: 同型判定,  Next: 最長共通サブシーケンス,  Prev: メッセージダイジェストフレームワーク,  Up: ライブラリモジュール - ユーティリティ

11.34 `util.isomorph' - 同型判定
================================

 -- Module: util.isomorph
     二つの構造が同型かどうかを判定する手続きを提供するモジュールです。

 -- Function: isomorphic? obj1 obj2 &optional context
     OBJ1とOBJ2が同型であれば`#t'を返します。

     省略可能な引数CONTEXTは、下で説明する`object-isomorphic?'
     の中から`isomorphic?'を再帰的に呼び出す場合に使います。

          (isomorphic? '(a b) '(a b)) => #t

          (define x (cons 0 0))
          (define y (cons 0 0))
          (isomorphic? (cons x x)
                       (cons x y))
           => #f
          (isomorphic? (cons x x)
                       (cons y y))
           => #t

 -- Generic Function: object-isomorphic? obj1 obj2 context
     このメソッドで、二つのオブジェクトの同型判定処理をカスタマイズできます。
     基本的には、オブジェクトのトラバースしたいスロットに対して`isomorphic?'を順に適用し、
     全てが成功すれば`#t'を、一つでも失敗すれば`#f'を返すようにします。
     CONTEXTはトラバースのコンテクストを保持しているオブジェクトです。そのまま
     `isomorphic?'に渡して下さい。

     デフォルトメソッドは、OBJ1とOBJ2が`equal?'の意味で等しければ
     `#t'を返します。


File: gauche-refj.info,  Node: 最長共通サブシーケンス,  Next: その他のリストライブラリ,  Prev: 同型判定,  Up: ライブラリモジュール - ユーティリティ

11.35 `util.lcs' - 最長共通サブシーケンス
=========================================

 -- Module: util.lcs
     このモジュールは、与えられた2つのシーケンスの最長共通サブシーケンスを見つける
     アルゴリズムを実装しています。アルゴリズムは、Eugene Meyersの
     O(ND)アルゴリズムに基づいています(*Note [Meyers86]: meyers86.)。

     このアルゴリズムを使うアプリケーションの1つは、2つのテキストストリームの
     相違点を計算する*Note テキストストリームの相違点を計算する::です。

 -- Function: lcs seq-a seq-b &optional eq-fn
     2つのリスト、SEQ-AとSEQ-Bの最長共通シーケンスを計算して
     返します。オプションのEQ-FNでは、比較を行う述語を指定します。
     省略されると、`equal?'が使われます。

          (lcs '(x a b y) '(p a q b))
           => (a b)

 -- Function: lcs-with-positions seq-a seq-b &optional eq-fn
     `lcs'の詳細バージョンです。引数は同じです。

     以下の構造のリストを返します。

          (LENGTH ((ELT A-POS B-POS) ...))

     LENGTHは、見つかったLCS(最長共通サブシーケンス)の長さを表す整数です。
     それに続くのは、LCSの要素のリストで、その要素を構成するそれぞれのサブリスト、
     SEQ-Aの中での要素の位置(整数)、SEQ-Bの中での要素の位置(整数)
     となります。

          (lcs-with-positions '(a) '(a))
           => (1 ((a 0 0)))

          (lcs-with-positions '(x a b y) '(p q a b))
           => (2 ((a 1 2) (b 2 3)))

          (lcs-with-positions '(x a b y) '(p a q b))
           => (2 ((a 1 1) (b 2 3)))

          (lcs-with-positions '(x y) '(p q))
           => (0 ())

 -- Function: lcs-fold a-proc b-proc both-proc seed a b &optional eq-fn
     2つのリストAとBから引き出された"編集リスト"に対する
     基本的なイテレータです。

     A-PROC、B-PROC、BOTH-PROCは全て2引数を取る手続きです。
     2番目の引数は、計算の中間の値です。最初の値は、A-PROCではAにしかない要素、
     B-PROCではBにしかない要素、BOTH-PROCではAとBの両方に
     ある要素となります。それぞれの手続きが返す値は、次に呼び出される手続きのうちの1つの
     状態を表す値として使われます。SEEDは、状態を表す値の初期値として使われます。
     `lcs-fold'が返す値は、最後の状態を表す値です。

     これらの3つの手続きは、以下の順番で呼ばれます。ここでは、シーケンスAは
     A'CA"、BはB'CB"となっているとすると、
     ここではA'、B'、A"、B"はサブシーケンスで、
     CはAとBのLCSの先頭になります。そして、A-PROCはまず
     A'のそれぞれの要素に対して呼ばれ、B-PROCがB'のそれぞれの
     要素に対して呼ばれ、BOTH-PROCがCに対して呼ばれます。
     その後、このプロセスはA"とB"を使って繰り返されます。

 -- Function: lcs-edit-list a b &optional eq-fn
     2つのリストAとBから"編集リスト"を計算します。それは、
     AをBに変更するためのコマンド(追加と削除)の最小セットです。
     この手続きは、上の`lcs-fold'の上に構築されています。
          (+|- POSITION ELEMENT)

     例を挙げます。AとBがそれぞれ以下のようなリストだとします。

          A == ("A" "B" "C" "E" "H" "J" "L" "M" "N" "P")
          B == ("B" "C" "D" "E" "F" "J" "K" "L" "M" "R" "S" "T")

     すると、`(lcs-edit-list a b equal?)'は以下のリストを返します。
          (((- 0 "A"))
           ((+ 2 "D"))
           ((- 4 "H") (+ 4 "F"))
           ((+ 6 "K"))
           ((- 8 "N") (- 9 "P") (+ 9 "R") (+ 10 "S") (+ 11 "T"))
          )
     結果は5つの片からなります。最初のものは1つのディレクティブ、`(- 0
     ``A'')'から
     なり、これはリストAの位置0にある要素```A'''が削除されることを意味します。
     2番目のものはまた1つのディレクティブ、`(+ 2 ``D'')'からなり、これは
     リストBの位置2にある要素```D'''が追加されることを意味します。
     3番目のものは、リストAの位置4にある```H'''は削除され、リストBの
     位置4にある```F'''が追加される、などとなります。

     もしあなたがPerlのAlgorithm::Diffモジュールを良く知っていれば、
     その`diff'手続きが返すものと同じ構造だということが分かるでしょう。


File: gauche-refj.info,  Node: その他のリストライブラリ,  Next: パターンマッチング,  Prev: 最長共通サブシーケンス,  Up: ライブラリモジュール - ユーティリティ

11.36 `util.list' - その他のリストライブラリ
============================================

 -- Module: util.list
     このモジュールは、srfi-1 (*Note List library::参照)にはないが、
     一般的に便利なリストユーティリティ関数を提供します。

     リストに対して用いることができる便利なジェネリック関数を定義している
     *Note コレクションフレームワーク::と*Note
     シーケンスフレームワーク::も 見て下さい。

 -- Function: take* list k &optional fill? padding
     LISTの最初のK個の要素で構成されるリストを返します。
     これは、SRFI-1の`take'に似ていますが、この手続きのほうが
     寛容です。つまり、LISTがKよりも短いとき、`take*'は
     エラーを通知しません。その代わり、デフォルトで(あるいは、オプショナル
     引数FILL?が`#f'の場合)LISTのコピーを返します。
     FILL?が真の場合、その長さをKにするために、PADDINGが
     その結果に追加されます。PADDINGのデフォルト値は`#f'です。

          (take* '(a b c d) 3)       => (a b c)
          (take* '(a b c d) 6)       => (a b c d)
          (take* '(a b c d) 6 #t)    => (a b c d #f #f)
          (take* '(a b c d) 6 #t 'z) => (a b c d z z)

     注意:
     一般的な、いかなるシーケンスからのサブシーケンスの抽出については、
     *Note シーケンスのスライス::の`subseq'を見て下さい。

 -- Function: drop* list k
     LISTの最初のK個の要素が削除されたリストを返します。
     これは、SRFI-1の`drop'に似ていますが、この手続きのほうが
     寛容です。LISTがKよりも短い場合、空リストが返されます。

          (drop* '(a b c d) 3)       => (d)
          (drop* '(a b c d) 5)       => ()

 -- Function: take-right* list k &optional fill? padding
     `take*'と同じですが、LISTの右端からカウントします。
     必要ならば、結果の左にPADDINGが追加されます。

 -- Function: drop-right* list k
     `drop*'と同じですが、LISTの右端からカウントします。

 -- Function: split-at* list k &optional fill? padding
     SRFI-1の`split-at'の寛容なバージョンです。
     `take*'とDROP*の結果を返します。

          (split-at* '(a b c d) 6 #t 'z)
            => (a b c d z z) and ()

 -- Function: slices list k &optional fill? padding
     LISTを、それぞれの長さがKであるようなサブリスト(スライス)に
     分割します。 LISTの長さがKの整数倍でない場合は、最後のスライスは
     `take*'と同じ方法で扱われます。つまり、デフォルトではKより
     短いもの、あるいはFILL?が真ならばPADDINGが追加されます。

          (slices '(a b c d e f g) 3)
            => ((a b c) (d e f) (g))
          (slices '(a b c d e f g) 3 #t 'z)
            => ((a b c) (d e f) (g z z))

 -- Function: intersperse item list
     LISTの要素の間にITEMを挿入します。
     (引数の順番は、Haskellのintersperseと同じです。)

          (intersperse '+ '(1 2 3))  => (1 + 2 + 3)
          (intersperse '+ '(1))      => (1)
          (intersperse '+ '())       => ()

 -- Macro: cond-list clause ...
     条件によりエントリを追加することによりリストを構築します。
     それぞれのCLAUSEは条件と式を持ちます。
     条件が真であれば、関連する式の結果が結果のリストの構築に使われます。
     条件が偽であれば、何も挿入されません。

     CLAUSEは、以下のフォームのうちの1つでなければなりません。
    `(TEST EXPR ...)'
          TESTが評価され、それが真ならばEXPR ...が評価され、
          戻り値が結果の一部となります。EXPRが与えられなければ、
          TESTの結果が偽でなければその結果が使われます。

    `(TEST => PROC)'
          TESTが評価され、それが真ならばPROCがその値とともに
          呼ばれ、その戻り値が結果を構築するために使われます。

          (let ((alist '((x 3) (y -1) (z 6))))
           (cond-list ((assoc 'x alist) 'have-x)
                      ((assoc 'w alist) 'have-w)
                      ((assoc 'z alist) => cadr)))
            => (have-x 6)

 -- Function: alist->hash-table alist &optional cmp
     alistに含まれるそれぞれの要素をエントリとして持つハッシュテーブルを
     作成して返します。その時、要素のcarがキーとして、要素のcdrが値として
     使われます。CMPは作成されたハッシュテーブルの比較関数を
     指定するシンボルで、現在は`eq?'、`eqv?'、`equal?'、
     `string=?'がサポートされています。

 -- Function: hash-table->alist hash-table
            (hash-table-map h cons)

 -- Function: rassoc key alist &optional eq-fn
 -- Function: rassq key alist
 -- Function: rassv key alist
     与えられるKEYがALISTのそれぞれの要素で、_car_の代わりに
     _cdr_にマッチするような逆になった連想リストです。
     両方向の連想リストと理解すると簡単です。
     `rassoc'は、そのデフォルトが`equal?'である、オプションの
     比較関数を取ります。`rassq'はEQ?、`rassv'はEQV?を 使います。

 -- Function: assoc-ref alist key &optional default eq-fn
 -- Function: assq-ref alist key &optional default
 -- Function: assv-ref alist key &optional default
     これらの手続きは、他の*-ref手続きと対照的な連想リストへの
     アクセスを提供します。これは、一般的な連想リストアクセスのパターン
     です。
          (assoc-ref alist key default eq-fn)
           ==
            (cond ((assoc key alist eq-fn) => cdr)
                  (else default))))

     DEFAULTが省略されると、`#f'が使われます。

     `assoc-ref'は、そのデフォルトが`equal?'である、オプションの
     比較関数EQ-FNを取ります。`assq-ref'は`eq?'を、
     `assv-ref'は`eqv?'をそれぞれ使います。

 -- Function: rassoc-ref alist key &optional default eq-fn
 -- Function: rassq-ref alist key &optional default
 -- Function: rassv-ref alist key &optional default
     `assoc-ref'の逆連想リストバージョンです。
          (rassoc-ref alist key default eq-fn)
           ==
            (cond ((rassoc key alist eq-fn) => car)
                  (else default))))
     オプショナル引数の意味は、`assoc-ref'と同じです。

 -- Function: assoc-set! alist key val &optional eq-fn
 -- Function: assq-set! alist key val
 -- Function: assv-set! alist key val
     `alist'に`(key . val)'のペアが追加された連想リストを返します。
     `alist'がすでにKEYをキーとする要素を持っている場合、
     その要素の_cdr_は破壊的にVALに変更されます。
     ALISTがKEYをキーとする要素を持っていない場合は、
     新しいペアが作成され、ALISTの一番前に追加されます。
     したがって、KEY-VALペアが追加されたことを保証するために
     その戻り値を使うべきです。

     `assoc-set!'は、そのデフォルトが`equal?'である、オプションの
     比較関数EQ-FNを取ります。`assq-set!'は`eq?'を、
     `assv-set!'は`eqv?'を、それぞれ使います。


File: gauche-refj.info,  Node: パターンマッチング,  Next: キュー,  Prev: その他のリストライブラリ,  Up: ライブラリモジュール - ユーティリティ

11.37 `util.match' - パターンマッチング
=======================================

 -- Module: util.match
     このモジュールは Andrew Wright
     のパターンマッチングマクロライブラリを
     ポートしたものです。このライブラリは Scheme
     界では広くつかわれており、 Chez Scheme、PLT
     Scheme、Scheme48、Chicken および SLIB を含む、様々な Scheme
     の実装にポートされています。この機能は Common Lisp の
     `destructuring-bind' に似ていますがより強力です。

     この版では、オリジナルの Wright's macro
     のマクロとの互換性が保たれて
     います。ただし、例外がふたつあって、それは、(1) BOX
     はサポートされて いません。Gauche にそれがないからです。(2)
     構造のマッチングは Gauche の
     オブジェクトシステムに統合されています。

   まず API
のリストを示し、それからパターンの完全な構文のテーブルを示し、
そして例を示します。

パターンマッチング API
----------------------

 -- Macro: match expr clause ...
     それぞれの CLAUSE は以下のうちどちらかです。
          (PAT BODY ...)
          (PAT (=> IDENTIFIER) BODY ...)

     まず、EXPR を各節の PAT に照合します。パターンの詳しい
     構文については後述します。

     PAT にマッチする部分が見つかれば、PAT 中の _パターン変数_ は、EXPR
     中の対応する要素に束縛され、その後、BODY ...
     が評価されます。`match'はBODY ...の最後の式の値を返します。

     節が 2つ目の形式である場合、IDENTIFIER は CLAUSE の失敗継続
     に束縛されます。これは引数をもたない手続きで、呼ばれると、あたかも、
     PAT の照合に失敗したかの如くマッチャーに戻り、`match' が
     残りの節について試行を続けます。それゆえ、BODY ... 内部で
     追加のテストを実行することが可能で、もし、満足いくものでなければ、
     `(IDENTIFIER)' を呼ぶことで、照合結果を拒絶することができます。
     より詳しくは、後述の例を見てください。

     どの PAT もマッチしなければ、`match' はエラーを報告します。

 -- Macro: match-lambda clause ...
     ひとつの引数をとり、それに対して CLAUSE ... を用いて、 `match'
     を実行する関数を生成します。機能としては以下の式と同等です。
          (lambda (expr) (match expr CLAUSE ...))

 -- Macro: match-lambda* clause ...
     `match-lambda' と同じですが、`match' をすべての引数のリスト
     に対して実行します。機能としては以下の式と同等です。
          (lambda expr (match expr CLAUSE ...))

 -- Macro: match-let ((pat expr) ...) body-expr ...
 -- Macro: match-let name ((pat expr) ...) body-expr ...
 -- Macro: match-let* ((pat expr) ...) body-expr ...
 -- Macro: match-letrec ((pat expr) ...) body-expr ...
     束縛部分が単なる変数ではなく、パターンを許す、一般化された `let'、
     `let*' および `letrec' です。 各 EXPR が評価され、その後、PAT
     と照合され、束縛された パターン変数が BODY-EXPR ...
     から見えるようになります。

          (match-let (
                       (((ca . cd) ...)   '((a . 0) (b . 1) (c . 2)))
                     )
            (list ca cd))
           => ((a b c) (0 1 2))

     括弧はうんざりという向きには、以下の `match-let1' をおためしあれ。

 -- Macro: match-let1 pat expr body-expr ...
     これは Gauche での拡張で、オリジナルの Wright
     のコードにはありません。 これは以下のコードと同等です。
          (match-let ((PAT EXPR)) BODY-EXPR ...)

     構文としては `match-let1' は Common Lisp の `destructuring-bind'
     に非常によく似ています。

 -- Macro: match-define pat expr
     トップレベルの `define'
     と同様ですが、変数の代りにパターンが許されます。

パターンの構文
--------------

ここにあるのはパターンの構文の要約です。説明の後にあるアスタリスク
`(*)' はオリジナルの Wright のコードにはない、Gauche の拡張で
あることを意味します。

     pat : patvar                       ;; すべて、かつ、パターン変数を束縛
         | _                            ;; すべて
         | ()                           ;; 空リスト
         | #t                           ;; #t
         | #f                           ;; #f
         | string                       ;; 文字列
         | number                       ;; 数
         | character                    ;; 文字
         | keyword                      ;; キーワード (*)
         | 'sexp                        ;; Ｓ式
         | 'symbol                      ;; シンボル(Ｓ式の特殊ケース)
         | (pat1 ... patN)              ;; n 要素のリスト
         | (pat1 ... patN . patN+1)     ;; n 以上の要素を含むリスト
         | (pat1 ... patN patN+1 ooo)   ;; n 以上の要素を含むリスト、残りの各要素は
                                        ;; patN+1 にマッチしなければならない
         | #(pat1 ... patN)             ;; n 要素のベクタ
         | #(pat1 ... patN patN+1 ooo)  ;; n 以上の要素を含むベクタ、残りの各要素は
                                        ;; patN+1 にマッチしなければならない
         | ($ class pat1 ... patN)      ;; オブジェクト (patK はスロット順でマッチ)
         | (struct class pat1 ... patN) ;; 同上 (*)
         | (@ class (slot1 pat1) ...)  ;; オブジェクト (スロット名を使う) (*)
         | (object class (slot1 pat1) ...) ;; 同上 (*)
         | (= proc pat)                 ;; procを適用し、結果を pat にマッチさせる
         | (and pat ...)                ;; すべての pat にマッチするか
         | (or pat ...)                 ;; マッチする pat があるか
         | (not pat ...)                ;; どの pat もマッチしないか
         | (? predicate pat ...)        ;; predicate が真、かつ、全 pat がマッチ
         | (set! patvar)                ;; すべて、かつ、セッタを束縛
         | (get! patvar)                ;; すべて、かつ、ゲッタを束縛
         | `qp                          ;; 擬似パターン

     patvar : a symbol except _, quote, $, struct, @, object, =, and, or,
              not, ?, set!, get!, backquote, ..., ___, ..k, __k.

     ooo : ...                          ;; ゼロまたはそれ以上
         | ___                          ;; ゼロまたはそれ以上
         | ..k                          ;; k またはそれ以上
         | __k                          ;; k またはそれ以上

   * 素のシンボルは「パターン変数」で、あらゆるものとマッチし、
     式のマッチした部分がそのシンボルに束縛されます。
     以下のシンボルは特別な意味をもち、パターン変数としては使えません。
     `_'、`quote'、`$'、`struct'、`@'、`object'、
     `='、`and'、`or'、`not'、`?'、`set!'、
     `get!'、`backquote'、`...'、`___' および `..k' と `__k'
     (ここで、_k_ は整数)。

   * シンボル `_' はあらゆるものマッチし、パターン変数は束縛しません。
     プレースホルダであることを示すのに用います。

   * 空リスト、真偽値、文字列、数、文字およびキーワードのリテラルは
     (`equal?'という意味で)同じオブジェクトとマッチします。

   * クウォートされた式は(`equal?' という意味で)同じ式とマッチします。
     クウォートされたシンボルをそれ自身とマッチさせるのに使えます。

   *
     通常リストおよびベクタは、それぞれ、パターン中の要素にマッチする要素を
     もつリストまたはベクタとマッチします。ただし、最初の要素が上であげた
     特別なシンボルではない限りです。そのような場合には特別な意味を持ちます。

     特別な場合として、ベクタあるいはリストの最後の要素のあとにシンボル
     `...' を付加することができます。この場合には、`...' シンボル
     直前のパターンが与えられた式のすべての要素を尽すまで繰り返し適用されます。
     シンボル `___' は `...' の場所で使えます。構文規則マクロによって
     パターンを生成したいときに便利です。

     リストのパターンに対しては、シンボル `..1'、`..2'、... が
     使えます。これは繰り返しの最小値を指定するものです。

   * `($ class pat1 ...)' は `class' クラスのインスタンスと
     マッチします。各パターン `pat1' ... はスロットの各値と
     `(class-slots class)' の順にマッチします。

     `(struct class pat1 ...)' は同じ意味です。オリジナルの Wright
     のコードには、`struct' はありませんが、PLT Scheme の拡張
     照合機能にはそなわっています。こちらの方がより説明的です。

     これはオリジナルの機能を構造(structure)にもマッチするように調整した
     ものです。スロットの順番が予め分るような単純なインスタンスをマッチする
     のに便利です。たとえば、SRFI-9 (*Note レコード型::参照)で作成した
     簡単なレコードは簡単に位置指定された値でマッチすることができます。

     インスタンスのクラスが継承を使っている場合、位置によるマッチを
     おこなうのは少々難しくなります。以下の `@' あるいは `object'
     パターンを使って、スロット名でマッチを行うことができます。

   * `(object class (slot1 pat1) ...)' は SLOT1 ... の値が PAT1 ...
     にマッチするような `class'
     クラスのインスタンスとマッチします。これは、 Gauche
     の拡張です。`@' は `object' と同じ場所で使えます。
     ただし、`object' の方が説明的でわかりやすいので、こちらを
     推奨します。

   * `(= proc pat)' は最初に PROC を対応する式に適用し、 その結果と PAT
     をマッチさせます。

   * `(and pat ...)'、`(or pat ...)' および `(not pat ...)'
     はパターンの真偽値演算子です。

   * `(? predicate pat ...)' は最初、述語を対応する式に適用し、
     真が返れば、各 `pat' ... をその式に適用します。

   * `(set! patvar)' はあらゆるものにマッチし、一引数の手続きを
     パターン変数 PATVAR に束縛します。その手続きが呼ばれると、
     マッチしたパターンの値を与えられた引数で置き換えます。

   * `(get! patvar)' はあらゆるものにマッチし、引数なしの手続きを
     パターン変数 PATVAR に束縛します。その手続きが呼ばれると、
     マッチしたパターンの値を返します。

   * ``qp'はquasipatternです。QPは、クオートされたパターンと同様、
     それそのものにマッチしますが、その中にアンクオートされているパターンがあると、
     その部分だけは通常のパターンとして解釈されます。
     (準クオート(quasiquote)とquasipatternを混同しないようにしてください。
     機能的に両者は似ていますが、準クオートがアンクオートされた部分木以外の
     部分の評価をoffにするのに対し、quasipatternはアンクオートされた部分木
     以外の部分のパターン構文を無効にします。下の例も参照して下さい。)

パターン例
----------

単純な構造の分解
     (match '(0 (1 2) (3 4 5))
       ((a (b c) (d e f))
        (list a b c d e f)))
      => (0 1 2 3 4 5)

   述語パターンの使用
     (match 123
       ((? string? x) (list 'string x))
       ((? number? x) (list 'number x)))
      => (number 123)

   `let' から変数と式を取り出す 反復および述語パターンの利用
     (define let-analyzer
       (match-lambda
         (('let (? symbol?)
                ((var expr) ...)
            body ...)
          (format "named let, vars=~s exprs=~s" var expr))
         (('let ((var expr) ...)
            body ...)
          (format "normal let, vars=~s exprs=~s" var expr))
         (_
          (format "malformed let"))))

     (let-analyzer '(let ((a b) (c d)) e f g))
      => "normal let, vars=(a c) exprs=(b d)"

     (let-analyzer '(let foo ((x (f a b)) (y (f c d))) e f g))
      => "named let, vars=(x y) exprs=((f a b) (f c d))"

     (let-analyzer '(let (a) b c d))
      => "malformed let"

   `=' 関数適用。パターン変数 M は正規表現の適用結果にマッチする
     (match "gauche-ref.texi"
       ((? string? (= #/(.*)\.([^.]+)$/ m))
        (format "base=~a suffix=~a" (m 1) (m 2))))
      => "base=gauche-ref suffix=texi"

   quasipatternの例です。最初の式では、パターンのうち`value'以外の
部分がクオートされたことになり、従ってシンボル`the', `answer',
`is'はパターン変数ではなくリテラルシンボルとなります。
2番目の式がそのことを示しています。入力にあるシンボル`was'は
パターンの`is'とマッチしません。もしクオートを行わないと、
全てのシンボルはパターン変数となるので、3番目の例に示すように
任意の4つの要素を持つリストとマッチしてしまいます。
     (match '(the answer is 42)
       (`(the answer is ,value) value)
       (else #f))
      => 42

     (match '(the answer was 42)
       (`(the answer is ,value) value)
       (else #f))
      => #f

     (match '(a b c d)
       ((the answer is value) value)
       (else #f))
      => d


File: gauche-refj.info,  Node: キュー,  Next: SLIB-互換のレコード型,  Prev: パターンマッチング,  Up: ライブラリモジュール - ユーティリティ

11.38 `util.queue' - キュー
===========================

 -- Module: util.queue
     キュー(FIFO)機能を提供します。この実装は安全さよりスピードに重点を置いています。
     キューは単に先頭と末尾のpairで表現され、多くのオペレーションでキューが正しいかどうかは
     チェックされません。

     SLIB (*Note
     SLIBインタフェース::参照)にはより安全なキューの実装があります。
     このAPIはSLIBの実装の上位互換です。特定の手続きや構造体の中だけで使うため、
     厳しいチェックが必要でない場合にはこのモジュールを使うのが良く、そうでない場合は
     SLIBのものが良いでしょう。要求仕様によって使い分けて下さい。

 -- Function: make-queue
     空のキューを作って返します。

 -- Function: queue? obj
     OBJがキューであれば`#t'を返します。この操作に限り、OBJが
     本当にキューの構造をしているかどうかのチェックがなされます。

 -- Function: queue-empty? queue
     OBJが空のキューであれば`#t'を返します。

 -- Function: queue-length queue
     キューの中にあるアイテムの数を返します。

 -- Function: enqueue! queue obj &optional more-objs ...
     OBJをキューQUEUEの末尾に追加します。
     一つ以上のOBJを与えることができ、その場合はそれらが順にenqueueされます。
     (註：SLIBの`enqueue!'はオプショナルな引数を取りません)。

 -- Function: queue-push! queue obj &optional more-objs ...
     OBJをキューQUEUEの先頭に追加します。
     一つ以上のOBJを与えることができ、その場合はそれらが順にpushされます。
     (註：SLIBの`queue-push!'はオプショナルな引数を取りません)。

 -- Function: enqueue-unique! queue eq-proc obj &optional more-objs ...
 -- Function: queue-push-unique! queue eq-proc obj &optional more-objs
          ...
     OBJが既にQUEUEの中に含まれている場合にはQUEUEを
     変更しないことを以外には、`enqueue!'および`queue-push!'と同じ
     動作をします。OBJが含まれているかどうかの検査は
     2引数の関数EQ-PROCで行います。

 -- Function: dequeue! queue
 -- Function: queue-pop! queue
     キューQUEUEの先頭からひとつ要素を取って返します。
     二つの手続きは全く同じ動作をします。`queue-pop!'は`queue-push!'と
     ペアで使われていることを強調したいときに使うと良いでしょう。キューが空の場合は
     エラーが報告されます。

 -- Function: dequeue-all! queue
     キューの全ての内容をリストにして返します。キューそのものは空になります。
     キューが既に空の場合は空リストが返されます。
     下の`queue->list'も参照してください。

 -- Function: queue-front queue
 -- Function: queue-rear queue
     キューQUEUEの先頭もしくは末尾の要素を返します。キューそのものは変更されません。
     キューが空の場合はエラーが報告されます。

 -- Function: list->queue list
     与えられたリストLISTの各要素をその順で持つようなキューを作成して返します。

 -- Function: queue->list queue
     キューQUEUEの内容をリストにして返します。
     `dequeue-all!'と異なり、キューそのものの内容は変化しません。

     Gaucheでは`queue->list'は新しいリストをアロケートしてキューの
     内容をコピーします (`dequeue-all!'はコピーをせずにキューの内部の
     リストをそのまま返します)。組込みで`queue->list'を持っているScheme
     実装がいくつかありますが、その中には`queue->list'がキューの
     内容をコピーすることを保証していないものがあるので、それらの処理系と
     共有するコードでは`queue->list'がリストをコピーすることを
     あてにしない方が良いでしょう。

 -- Function: find-in-queue pred queue
     キュー内の要素のうち述語PREDを満たす最初の要素を返します。
     引数の順序はSRFI-1の`find'に揃えました (*Note リストの探索::参照)。

 -- Function: remove-from-queue! pred queue
     キューから、述語PREDを満たす要素を全て取り除きます。
     要素が削除された場合は`#t'が、そうでなければ`#f'が返されます。
     引数の順序はSRFI-1の`remove'に揃えました (*Note
     リストのフィルタおよび分割::参照)。

移植性に関する註：Scheme48には、述語ではなく削除するオブジェクトそのものを取る
`delete-from-queue!'がありますが、引数の順序が逆(キューが先)になっています。
まぎらわしい衝突を避けるため、敢えて`delete-from-queue!'は
提供しませんでした。`remove-from-queue!'を使えば、Scheme48互換の方法でも、
あるいはSRFI-1と一貫性のある方法でも`delete-from-queue!'をすぐ書けるでしょう。


File: gauche-refj.info,  Node: SLIB-互換のレコード型,  Next: トポロジカルソート,  Prev: キュー,  Up: ライブラリモジュール - ユーティリティ

11.39 `util.record' - SLIB-互換のレコード型
===========================================

 -- Module: util.record
     このモジュールは、Guile と SLIB とに互換性のあるレコード型 API
     を提供します。 これは、Gauche
     のオブジェクトシステム上に構築されています。

     便利なマクロ `define-record-type' を提供する *Note レコード型:: も
     参照してください。

 -- Function: make-record-type type-name field-names
     あらしいレコード型を表わす新しいクラスを返します。 (これは SLIB
     では _レコード型記述子_とよばれているものです。) Gauche
     では、この新しいクラスは `<record>' のサブクラスです (*Note
     レコード型:: 参照)。

     TYPE-NAME はデバッグの目的で使われる文字列です。
     これは、シンボルに変換され、この新しいクラスの名前として設定されます。
     FIELD-NAMES はフィールド名のシンボルのリストです。
     各々のフィールドはこの新しいクラスののスロットとして実装されます。

   以下の手続きでは、RTD は `make-record-type' によって
生成されたクラスです。

 -- Function: record-constructor rtd &optional field-names
     与えられた RTD レコード型のインスタンスを構築する手続きを
     返します。返された手続きは FIELD-NAMES とちょうど同じ数の
     引数をとります。FIELD-NAMES のデフォルトは `'()' です。
     それぞれの引数は FIELD-NAMES の対応するフィールドの初期値を
     設定します。

 -- Function: record-predicate rtd
     一つの引数をとり、与えられた引数が RTD と同じ型であり、その場合に
     限り `#t' を返す手続きを返します。

 -- Function: record-accessor rtd field-name
     RTD 型の FIELD-NAME によって名付けられたフィールドへの
     アクセサ手続きを返します。このアクセサ手続きは、RTD
     のインスタンスを 一つとり、そのフィールドの値を返します。

 -- Function: record-modifier rtd field-name
     RTD 型の FIELD-NAME によって名付けられたフィールドへの
     モディファイア手続きを返します。このモディファイア手続きは、 RTD
     のインスタンスと値のふたつの引数をとり、その引数を
     指定されたフィールドに設定します。

     (define rtd (make-record-type "my-record" '(a b c)))

     rtd => #<class my-record>

     (define make-my-record (record-constructor rtd '(a b c)))

     (define obj (make-my-record 1 2 3))

     obj => #<my-record 0x819d9b0>

     ((record-predicate? rtd) obj)  => #t

     ((record-accessor rtd 'a) obj) => 1
     ((record-accessor rtd 'b) obj) => 2
     ((record-accessor rtd 'c) obj) => 3

     ((record-modifier rtd 'a) obj -1)

     ((record-accessor rtd 'a) obj) => -1


File: gauche-refj.info,  Node: トポロジカルソート,  Next: CGIユーティリティ,  Prev: SLIB-互換のレコード型,  Up: ライブラリモジュール - ユーティリティ

11.40 `util.toposort' - トポロジカルソート
==========================================

 -- Module: util.toposort
     トポロジカルソートのアルゴリズムを実装します。

 -- Function: topological-sort graph &optional eqproc
     GRAPHは有向非循環グラフ(DAG)を表現するリストです。
     リストの各要素は次の形をしています。
          (<node> <downstream> <downstream2> ...)
     これで、ノード`<node>'から別のノード`<downstream>'等への接続が
     あることを表現します。`<node>'はどんなオブジェクトであっても構いませんが、
     同一性の判定がEQPROCで行えなければなりません。EQPROCの既定値は
     `eqv?'です (*Note 等価::参照)。
     トポロジカルにソートされたノードのリストを返します。

     グラフに循環が検出された場合はエラーとなります。


File: gauche-refj.info,  Node: CGIユーティリティ,  Next: CGIのテスト,  Prev: トポロジカルソート,  Up: ライブラリモジュール - ユーティリティ

11.41 `www.cgi' - CGIユーティリティ
===================================

 -- Module: www.cgi
     CGIスクリプトを書くのに便利ないくつかの基本的な手続きを提供します。

     CGIスクリプトを手軽に書くにはこのモジュールの他に、 `rfc.uri'
     (*Note URIの解析と作成::)、 `text.html-lite' (*Note
     シンプルなHTMLドキュメントの構築::)、 `text.tree' (*Note
     怠惰なテキスト構築::) 等のモジュールを併せて 使うとよいでしょう。

     注：現在有効な、CGIに関する「正式な」仕様というのはどうも無いようです。
     `http://w3c.org/CGI/'あたりを参照して下さい。

メタ変数
--------

 -- Parameter: cgi-metavariables &optional metavariables
     通常、httpdはcgiプログラムに様々な情報を環境変数経由で渡します。
     `www.cgi'中の多くの手続きはその情報(メタ変数)を参照します。
     しかし、cgiに関連するプログラムを開発中に環境変数にアクセスするのは
     不便な場合もあります。
     このパラメータを使うと、メタ変数をオーバライドすることができます。

     METAVARIABLESは2要素のリストのリストです。
     内側のリストは、最初の要素が変数名を、2つめの要素がその値を、それぞれ
     文字列で与えます。

     例えば次のコードは`REQUEST_METHOD'と
     `QUERY_STRING'のメタ変数を`my-cgi-procedure'の実行期間中に
     上書きします。(`parameterize'の詳細については *Note
     パラメータ::を参照して下さい)。

          (parameterize ((cgi-metavariables '(("REQUEST_METHOD" "GET")
                                              ("QUERY_STRING" "x=foo"))))
            (my-cgi-procedure))

 -- Function: cgi-get-metavariable name
     NAMEで指定されるCGIメタ変数の値を返します。
     この関数はまずパラメータ`cgi-metavariables'を探し、
     指定されたメタ変数が見つからなければ`sys-getenv'を呼びます。

     CGIスクリプトは、なるべく`sys-getenv'を直接呼ぶのではなく
     `cgi-get-metavariable'を使うのが良いでしょう。
     スクリプトの再利用もしやすくなります。

パラメータの取得
----------------

 -- Function: cgi-parse-parameters &keyword :query-string
          :merge-cookies :part-handlers
     CGIプログラムに渡されたquery
     stringをパーズして、パラメータの連想リストにして
     返します。文字列がキーワード引数QUERY-STRINGに与えられればそれがパーズすべき
     query stringとなります。その引数が渡されなければこの手続きは
     メタ変数`REQUEST_METHOD'を参照し、その値によって標準入力もしくは
     メタ変数`QUERY_STRING'からquery stringが取られます。
     そのようなメタ変数が定義されておらず、かつ現在の入力ポートが端末である場合、
     インタラクティブにデバッグをしているものと考えて、
     この手続きはプロンプトを出してユーザにパラメータの入力を促します。

     `REQUEST_METHOD'が`POST'の場合、この手続きはenctypeとして
     `application/x-www-from-urlencoded'と`multipart/form-data'の
     両方を処理できます。後者は通常、ファイルアップロード機能を持つフォームに使われます。

     POSTデータが`multipart/form-data'で送られて来た場合、
     各パートの内容がパラメータの値となります。すなわち、アップロードされた
     ファイルはその内容がひとつの文字列として得られることになります。
     元のファイル名のようなその他の情報は捨てられます。これが望ましい動作で
     ない場合は、PART-HANDLERS引数によって動作をカスタマイズすることができます。
     詳しくは下の「ファイルアップロードの処理」で説明します。

     キーワード引数MERGE-COOKIESに真の値が与えられた場合は、
     メタ変数`HTTP_COOKIE'からクッキーの値が読まれ、解析されて
     結果に追加されます。

     パラメータは複数の値を取り得るため、結果のパラメータに対応する値は常にリストになります。
     パラメータに値が与えられていなければ、結果のパラメータに対する値には`#t'が置かれます。
     次の例を参照して下さい。
          (cgi-parse-parameters
            :query-string "foo=123&bar=%22%3f%3f%22&bar=zz&buzz")
           => (("foo" "123") ("bar "\"??\"" "zz") ("buzz" #t))

 -- Function: cgi-get-parameter name params &keyword :default :list
          :convert
     `cgi-parse-parameters'が返す、パーズされたQuery文字列PARAMSから、
     名前NAMEを持つパラメータの値を簡単に取り出すための手続きです。

     キーワード引数LISTに真の値が与えられていなければ、
     返される値はスカラー値です。パラメータNAMEに複数の値が与えられた場合でも、
     最初の値のみが返されます。LISTに真の値が与えられれば、返されるのは
     常に値のリストとなります。

     キーワード引数CONVERTに手続きを与えると、対応する値が取り出された後でその
     手続きが値を引数として呼ばれます。これによって値を文字列から必要な型へと変換することが
     できます。LISTに真の値が与えられている場合、変換手続きは各値に対して呼ばれ、
     その結果のリストがCGI-GET-PARAMETERから返されます。

     パラメータNAMEに対応する値が無ければ、DEFAULTに与えられた値がそのまま
     返されます。DEFAULTが省略された場合、LISTが偽であれば`#f'が、
     真であれば`()'が返されます。

出力の生成
----------

 -- Function: cgi-header &keyword status content-type location cookies
     HTTPリプライメッセージのヘッダを、テキストツリー形式(*Note
     怠惰なテキスト構築::参照)
     で作成して返します。最も簡単な呼び出しでは次のようになります。
          (tree->string (cgi-header))
            => "Content-type: text/html\r\n\r\n"

     キーワード引数CONTENT-TYPEによってContent typeを指定できます。
     また、COOKIESにクッキー文字列のリストを渡すことにより、
     クライアントにクッキーを設定できます。クッキー文字列を構築するには手続き
     `construct-cookie-string' (*Note HTTPクッキー::参照) が使えます。

     キーワード引数LOCATIONは、`Location'ヘッダを作成して
     クライアントを別のURIに誘導するのに使えます。また、`Status'ヘッダを
     指定するためにSTATUSキーワード引数が使えます。クライアントを
     別URIに転送するよくある方法は次のようなものです。

          (cgi-header :status "302 Moved Temporarily"
                      :location target-uri)


 -- Parameter: cgi-output-character-encoding &optional encoding
     このパラメータの値は次に説明する`cgi-main'が出力するデータの
     文字符合化法(CES)を指定します。デフォルトの値はGaucheのネイティブエンコーディング
     です。それ以外の値がセットされている場合、`cgi-main'は
     `gauche.charconv'モジュールを用いて出力のエンコーディングの変換を
     行います。 (*Note 文字コード変換::参照)。

便利な手続き
------------

 -- Function: cgi-main proc &keyword on-error merge-cookies output-proc
          part-handlers
     CGIスクリプトのための便利なラッパー手続きです。
     この手続きは、まず`cgi-parse-parameters'を呼び出してCGIスクリプトに
     渡されたパラメータを解析し、続いてその結果を引数としてPROCを呼び出します。
     キーワード引数MERGE-COOKIESは、与えられればそのまま
     `cgi-parse-parameters'に渡されます。

     手続きPROCはHTTPヘッダを含むドキュメントを
     テキストツリー構造(*Note 怠惰なテキスト構築::参照)で
     返さなければなりません。`cgi-main'はそれを`write-tree'を使って
     現在の出力ポートに書き出し、0を返します。

     もしPROC内でエラーが起こった場合、そのエラーは捕捉されて、エラーを報告する
     HTMLページが作成されて出力されます。このエラーページは、ON-ERRORキーワード引数に
     手続きを渡すことでカスタマイズできます。ON-ERRORに渡された手続きは
     エラー発生時に`<condition>'オブジェクト(*Note コンディション::参照)
     を引数として呼ばれ、HTTPヘッダを含むドキュメントをテキストツリー構造で返さねばなりません。

     `cgi-main'は最終的な結果を出力を書き出す時に
     パラメータ`cgi-output-character-encoding'を参照し、
     必要ならば出力の文字エンコーディングを変換します。

     `cgi-main'の出力のふるまいはキーワード引数OUTPUT-PROCで
     カスタマイズできます。OUTPUT-PROCが渡された場合、それは
     PROCの戻り値、あるいはエラーハンドラが作成したテキストツリー構造を
     受け取る手続きでなければなりません。その手続きはテキストツリーを
     フォーマットして現在の出力ポートに出力しなければなりません。
     必要ならば文字エンコーディングの変換もその手続き内で行います。

     キーワード引数PART-HANDLERSは、そのまま`cgi-parse-parameters'
     に渡されます。この引数によって、ファイルアップロードの際の動作をカスタマイズ
     できます。詳しくは下の「ファイルアップロードの処理」の項を参照して下さい。

     この引数で、一時ファイルを使うように指定した場合、`cgi-main'は
     PROCから抜ける際に(エラーでも正常終了でも)一時ファイルを
     消去します。この機能を他でも利用するには`cgi-add-temporary-file'の項を
     参考にして下さい。

     以下の例はCGIに渡されたパラメータ全てをテーブルにして表示します。

          #!/usr/local/bin/gosh

          (use text.html-lite)
          (use www.cgi)

          (define (main args)
            (cgi-main
              (lambda (params)
                `(,(cgi-header)
                  ,(html-doctype)
                  ,(html:html
                    (html:head (html:title "Example"))
                    (html:body
                     (html:table
                      :border 1
                      (html:tr (html:th "Name") (html:th "Value"))
                      (map (lambda (p)
                             (html:tr
                              (html:td (html-escape-string (car p)))
                              (html:td (html-escape-string (x->string (cdr p))))))
                           params))))
                 ))))

 -- Function: cgi-add-temporary-file filename
     この手続きは`cgi-main'に渡されるPROC中で呼ばれることを
     想定しています。
     この手続きは、FILENAMEを一時ファイルとして登録し、PROCが
     終了する際に消去されるようにします。cgiスクリプトがエラー終了した場合
     などでもごみを残さないようにする便利な方法です。
     この手続きを呼んだ後で、PROCがFILENAMEを消去したり
     名前を変えたりしても構いません。

 -- Parameter: cgi-temporary-files
     `cgi-add-temporary-file'で登録された一時ファイルを保持するパラメータです。

ファイルアップロードの処理
--------------------------

`cgi-parse-parameters'の項で説明したように、ファイルアップロードは
デフォルトでは透過的に扱われます。すなわち、アップロードされた
ファイルの内容がパラメータの値となります。
これは望みの動作ではないかもしれません。例えばアップロードされるファイルが
巨大であることが予想されるなら、それを全てメモリに読み込んで持ち回りたくは
ないかもしれません。`cgi-parse-parameters'や`cgi-main'の
PART-HANDLERS引数によって、ファイルアップロードの
処理をカスタマイズすることが可能です。
(この引数は、フォームデータが`multipart/form-data' enctypeで
送られた場合にのみ意味を持ちます)。

   PART-HANDLERS引数が与えられている場合、それはリストのリストで、
内部のリストは`(NAME-PATTERN ACTION)' の形式で なければなりません。
アップロードされたファイルは、そのパラメータ名がNAME-PATTERNに
マッチした場合にACTIONで指示されるように処理されます。
(ここで、パラメータ名とはsubmitされたフォームの`input'要素に与えられた
'name'属性のことです。アップロードされたファイルの名前ではありません)。

   NAME-PATTERNは文字列のリストか、正規表現か、`#t'です。
文字列のリストの場合はそれのいずれかとパラメータ名が等しければマッチと
みなされます。`#t'は全てのものにマッチします。

   `action'は次のいずれかの値でなければなりません。
`#f'
     デフォルトのアクションです。すなわち、アップロードされたファイルの内容が
     文字列として読み込まれ、パラメータの値となります。

`ignore'
     アップロードされたファイルの内容を無視します。

`file'
     アップロードされたファイルの内容は一時ファイルへと格納されます。
     パラメータの値は、一時ファイルの名前となります。

     このアクションを使う場合は、エントリを `(NAME-PATTERN file
     PREFIX)' のように書くことも
     でき、その場合はPREFIXが一時ファイルのパス名のプリフィクスとして
     使われます。例えば`("image" file "/var/mycgi/incoming/img")'
     のようにしておくと、`"image"'パラメータとしてアップロードされた
     ファイルが`/var/mycgi/incoming/img49g2Ua'のような一時ファイルに
     格納されることになります。

     アプリケーションは、この一時ファイルを(必要ならば)適切な場所に
     移動しなければなりません。`cgi-main'を用いている場合は、
     一時ファイルは`cgi-main'を抜ける際に(まだあれば)unlinkされます。

`file+name'
     `file'と同様ですが、パラメータの値が一時ファイル名と
     クライアントが送ってきたファイル名からなるリストになります。
     クライアントが送信したファイル名を利用したい場合に便利です
     (ただ、クライアントが常に正しいファイル名を送って来ると仮定しては
     いけません。例えば、アップロードされたファイルを
     チェック無しにクライアントが送ってきた名前にrenameするというような
     ことは避けてください)。

`PROCEDURE'
     この場合、アップロードされた内容を処理するために、手続きPROCEDUREが
     呼ばれます。手続きは4つの引数を伴って呼ばれます： `(procedure NAME
     FILENAME PART-INFO IPORT)'.

     NAMEはパラメータの名前、FILENAMEはオリジナルファイルの名前
     (クライアント側でのパス名)です。PART-INFOは`<mime-part>'オブジェクトで、
     このMIMEパートの情報を保持しており、そしてIPORTは内容を読むための入力ポートです。
     これらの引数の詳しい意味については*Note MIMEメッセージ処理::を
     参照して下さい。独自のPROCEDUREを書く際に、`rfc.mime'の
     `mime-retrieve-body'のような手続きが使えるかもしれません。

     PROCEDURE内で一時ファイルを作る場合は、それを
     `cgi-add-temporary-file'で登録しておけば、cgi処理中に
     エラーが起きた場合でも一時ファイルが消去されるようにすることができます。

   ファイルアップロード以外のパラメータはPART-HANDLERSの対象外である
ことに注意して下さい。それらのパラメータの値は常に文字列へと変換されます。

   簡単な例を示します。例えば次のようなフォームがあったとします。

     <form enctype="multipart/form-data" method="POST" action="mycgi.cgi">
     <input type="file" name="imagefile" />
     <input type="text" name="description" />
     <input type="hidden" name="mode" value="normal" />
     </form>

   `mycgi.cgi'内で、`cgi-parse-parameters'を
PART-HANDLERS引数なしで使った場合は、
例えば次のようなリストがパラメータパージングの結果として得られるでしょう。
(実際の値は、webクライアントがどのようにフォームを埋めたかに依存します)。

     (("imagefile" #*".....(image file content as a string)....")
      ("description" "my image")
      ("mode" "normal"))

   ここでもし、`'(("imagefile" file "/tmp/mycgi"))'をPART-HANDLERSに
渡したなら、替わりに次のような結果が得られるでしょう。
ここで、アップロードされたファイルは`/tmp/mycgi7gq0B'にセーブ
されていることになります。

     (("imagefile" "/tmp/mycgi7gq0B")
      ("description" "my image")
      ("mode" "normal"))

   上の例でシンボル`file'のかわりに`file+name'を使えば、
例えば`"imagefile"'の値として`("/tmp/mycgi7gq0B" "logo.jpg")'
のようなものが得られるでしょう。ここで`"logo.jpg"'は
アップロードされたファイルのクライアント側でのパス名です。
(注意：クライアントは任意の文字列をファイル名として送信することが
できるため、その文字列が有効なパス名であることを仮定してはなりません。)


File: gauche-refj.info,  Node: CGIのテスト,  Prev: CGIユーティリティ,  Up: ライブラリモジュール - ユーティリティ

11.42 `www.cgi-test' - CGIのテスト
==================================

 -- Module: www.cgi-test
     CGIスクリプトをテストするための便利な手続きを定義しています。
     このテストは、指定された環境変数をセットし、実際にスクリプトを
     実行し、出力を取得します。ユーザのテスト手続きは、その出力が
     期待したものであるかどうかを検査します。

 -- Function: cgi-test-enviornment-ref envvar-name
 -- Function: (setter cgi-test-enviornment-ref) envvar-name value
     モジュールにより、CGIスクリプトが実行される際の環境変数の
     デフォルト値のテーブルが保持されます。プログラマは、これらの
     手続きを使ってそのデフォルト値を取得したり設定したりできます。

     CGIスクリプトの呼び出し毎に、これらのデフォルト値を上書きしたり、
     追加の環境変数を渡したりできます。

     デフォルトでは、下記の環境変数が設定されています。
     Name                               Value
     `SERVER_SOFTWARE'                  `cgitest/1.0'
     `SERVER_NAME'                      `localhost'
     `GATEWAY_INTERFACE'                `CGI/1.1'
     `SERVER_PROTOCOL'                  `HTTP/1.1'
     `SERVER_PORT'                      `80'
     `REQUEST_METHOD'                   `GET'
     `REMOTE_HOST'                      `remote'
     `REMOTE_ADDR'                      `127.0.0.1'

 -- Function: call-with-cgi-script script proc &keyword (environment
          ()) (parameters #f)
     与えられた環境でスクリプトを実行し、そのスクリプトの標準出力のパイプに
     接続された入力ポートを1つ引数に取る PROC を呼び出します。

     引数 SCRIPT は、プログラムの名前とその引数のリストでなければ
     なりません。リストの要素はそれぞれ、文字列化されるためにまず
     `x->string'に渡されます。

     スクリプトは、変数 ENVIRONMENT で与えられる環境と、上述した
     デフォルトのテスト環境の下で実行されます。
     ENVIRONMENTは、キー(`car')がその環境変数の名前、
     `cdr'が対応する値であるような連想リストでなければなりません。
     両方ともまず `x->string' に渡されます。 ENVIRONMENT
     とデフォルトのテスト環境に同じ環境変数がある場合は、 ENVIRONMENT
     にあるものが使われます。

     さらに、引数 PARAMETERS に連想リストが渡された場合、そこから
     クエリストリングが作られスクリプトに渡されます。
     クエリストリングを渡す実際のメソッドは、環境変数 `REQUEST_METHOD'の
     値に依存します。`REQUEST_METHOD' が `GET' か `HEAD' で
     ある場合は、クエリストリングは環境変数 `QUERY_STRING'
     に置かれます。 `REQUEST_METHOD' が `POST'
     の場合は、クエリストリングは
     スクリプトの標準入力から取得されます。後者の場合、`CONTENT_TYPE'
     には `application/x-www-form-urlencoded'が、 `CONTENT_LENGTH' には
     `QUERY_STRING'の長さが、それぞれ自動的に
     セットされます。`REQUEST_METHOD' がその他の値の場合は、 PARAMETERS
     は無視されます。
     必要であれば、このメカニズムをバイパスして、環境変数
     `QUERY_STRING' を 直接セットアップすることも可能です。

 -- Function: run-cgi-script->header&body script reader &keyword
          environment parameters
     `call-with-cgi-script' の便利なラッパー手続きです。
     SCRIPT、ENVIRONMENT、PARAMETERSは、 そのまま
     `call-with-cgi-script'に渡されます。
     スクリプトの出力は、`run-cgi-script->header&body'により
     パーズされます。 最初に、RFC2822ヘッダフィールドが
     `rfc822-header->list' (*Note
     RFC822メッセージ形式::参照)によりパーズされます。
     次に、READERが、スクリプトの出力にパイプされた入力ポートと
     ともに呼ばれます。

     `run-cgi-script->header&body'は、ヘッダのリスト
     (`rfc822-header->list'によりパーズされたもの)と
     READERの戻り値の2つの値を返します。

 -- Function: run-cgi-script->sxml script &keyword environment
          parameters
     この手続きでは、`run-cgi-script->header&body'の
     READERとして、`ssax:xml->sxml' (*Note
     関数的なXMLパーザ::参照)を使います。
     整形式(Well-formed)のHTMLやXMLドキュメントを生成する
     CGIスクリプトをテストする場合に便利です。

 -- Function: run-cgi-script->string script &keyword environment
          parameters
 -- Function: run-cgi-script->string-list script &keyword environment
          parameters
     これらの手続きは、`run-cgi-script->header&body'の
     READERとして、それぞれ `port->string'、
     `port->string-list'を使います。

   例:
     (run-cgi-script->string-list "bbs.cgi"
                                  :environment '((REMOTE_ADDR . "12.34.56.78"))
                                  :parameters '((command . "view")
                                                (page . 1234)))


File: gauche-refj.info,  Node: 参考文献,  Next: CとSchemeの関数の対応,  Prev: ライブラリモジュール - ユーティリティ,  Up: Top

Appendix A 参考文献
*******************

[R5RS]
     R. Kelsey, W. Clinger, J. Rees (eds.), Revised^5 Report on the
     Algorithmic Language Scheme, Higher-Order and Symbolic
     Computation, 11(1), September, 1998 and ACM SIGPLAN Notices,
     33(9), October, 1998.
     `http://www.schemers.org/Documents/Standards/R5RS/'.

[1CC]
     Carl Bruggeman, Oscar Waddell and R. Kent Dybvig, Representing
     control in the presence of one-shot continuations, in Proceedings
     of SIGPLAN '96, pp. 99-107, 1996.

[Meyers86]
     Eugene Myers, An O(ND) Difference Algorithm and Its Variations,
     Algorithmica Vol. 1 No. 2, pp. 251-266, 1986.

[MOP]
     Gregor Kiczales, Jim Des Rivieres, Daniel Bobrow, The Art of
     Metaobject Protocol, The MIT Press.

[Dylan]
     Kim Barrett, Bob Cassels, Paul Haahr, David A. Moon, Keith
     Playford, P. Tucker Withington, A Monotonic Superclass
     Linearization for Dylan, in Proceedings of OOPSLA 96, October 1996.
     `http://www.webcom.com/~haahr/dylan/linearization-oopsla96.html'.

[FairThreads]
     F. Boussinot, Java Fair Threads,
     `http://www-sop.inria.fr/mimosa/rp/FairThreads/html/FairThreads.html'.

[RFC1321]
     R. Rivest, The MD5 Message-Digest Algorithm.
     April 1992.
     `ftp://ftp.isi.edu/in-notes/rfc1321.txt'.

[RFC2045]
     N. Freed, N. Borenstein: Multipurpose Internet Mail Extension
     (MIME) Part One: Format of Internet Message Bodies, November 1996.
     `ftp://ftp.isi.edu/in-notes/rfc2045.txt'.

[RFC2396]
     T. Berners-Lee, R. Fielding, L. Masinter, Uniform Resource
     Identifiers (URI): Generic Syntax, August 1998.
     `ftp://ftp.isi.edu/in-notes/rfc2396.txt'.

[RFC2616]
     R. Fielding et al, Hypertext Transfer Protocol - HTTP/1.1, June
     1999.
     `ftp://ftp.isi.edu/in-notes/rfc2616.txt'.

[RFC2822]
     P. Resnick (ed.), Internet Message Format, April 2001.
     `ftp://ftp.isi.edu/in-notes/rfc2822.txt'.

[RFC2965]
     D. Kristol, L. Montulli, HTTP State Management Mechanism, October
     2000.
     `ftp://ftp.isi.edu/in-notes/rfc2965.txt'.

[RFC3174]
     D. Eastlake, 3rd and P. Jones, US Secure Hash Algorithm 1 (SHA1).
     September 2001.
     `ftp://ftp.isi.edu/in-notes/rfc3174.txt'.

[SRFI-0]
     Marc Feeley, Feature-based conditional expansion construct, May
     1999.
     `http://srfi.schemers.org/srfi-0/srfi-0.html'.

[SRFI-1]
     Olin Shivers, List Library, October 1999.
     `http://srfi.schemers.org/srfi-1/srfi-1.html'.

[SRFI-2]
     Oleg Kiselyov, `AND-LET*': an `AND' with local bindings, a guarded
     `LET*' special form, March 1998.
     `http://srfi.schemers.org/srfi-2/srfi-2.html'.

[SRFI-4]
     Marc Feeley, Homogeneous numeric vector types, May 1999.
     `http://srfi.schemers.org/srfi-4/srfi-4.html'.

[SRFI-6]
     William D Clinger, Basic String Ports, July 1999.
     `http://srfi.schemers.org/srfi-6/srfi-6.html'.

[SRFI-8]
     John David Stone, receive: Binding to multiple values, August
     1999.
     `http://srfi.schemers.org/srfi-8/srfi-8.html'.

[SRFI-9]
     Richard Kelsey, Defining Record Types, September 1999.
     `http://srfi.schemers.org/srfi-9/srfi-9.html'.

[SRFI-10]
     Oleg Kiselyov, `#,' external form, January 2000.
     `http://srfi.schemers.org/srfi-10/srfi-10.html'.

[SRFI-11]
     Lars T Hansen, Syntax for receiving multiple values, March 2000.
     `http://srfi.schemers.org/srfi-11/srfi-11.html'.

[SRFI-13]
     Olin Shivers, String Libraries, December 2000.
     `http://srfi.schemers.org/srfi-13/srfi-13.html'.

[SRFI-14]
     Olin Shivers, Character-set Library, December 2000.
     `http://srfi.schemers.org/srfi-14/srfi-14.html'.

[SRFI-17]
     Per Bothner, Generalized `set!', July 2000.
     `http://srfi.schemers.org/srfi-17/srfi-17.html'.

[SRFI-18]
     Marc Feeley, Multithreading Support, April 2000.
     `http://srfi.schemers.org/srfi-18/srfi-18.html'.

[SRFI-19]
     Will Fitzgerald, Time Data Types and Procedures, August 2000.
     `http://srfi.schemers.org/srfi-19/srfi-19.html'.

[SRFI-21]
     Marc Feeley, Readl-time Multithreading Support, April 2000.
     `http://srfi.schemers.org/srfi-21/srfi-21.html'.

[SRFI-22]
     Martin Gasbichler and Michael Sperber, Running Scheme Scripts on
     Unix, January 2002.
     `http://srfi.schemers.org/srfi-22/srfi-22.html'.

[SRFI-23]
     Stephan Housen, Error reporting mechanism, April 2001.
     `http://srfi.schemers.org/srfi-23/srfi-23.html'.

[SRFI-25]
     Jussi Piitulainen, Multi-dimensional Array Primitives, June 2002.
     `http://srfi.schemers.org/srfi-25/srfi-25.html'.

[SRFI-26]
     Sebastian Egner, Notation for Specializing Parameters without
     Currying, June 2002.
     `http://srfi.schemers.org/srfi-26/srfi-26.html'.

[SRFI-27]
     Sebastian Egner, Sources of Random Bits, June 2002.
     `http://srfi.schemers.org/srfi-27/srfi-27.html'.

[SRFI-28]
     Scott G. Miller, Basic Format Strings, June 2002.
     `http://srfi.schemers.org/srfi-28/srfi-28.html'.

[SRFI-37]
     Anthony Carrico, Args-fold: a program argument processor, Jan.
     2003.
     `http://srfi.schemers.org/srfi-37/srfi-37.html'.

[SSAX]
     Oleg Kiselyov, XML and Scheme,
     `http://pobox.com/~oleg/ftp/Scheme/xml.html'.
     The SSAX distribution is also available at sourceforge:
     `http://ssax.sourceforge.net/'.

[MT]
     M. Matsumoto and T. Nishimura, "Mersenne Twister: A
     623-dimensionally equidistributed uniform pseudorandom number
     generator", ACM Trans. on Modeling and Computer Simulation Vol. 8,
     No. 1, Januray pp.3-30 1998.
     `http://www.math.keio.ac.jp/~matumoto/emt.html'

[OLEG1]
     Oleg Kiselyov, Making sense of an input stream,
     `http://pobox.com/~oleg/ftp/Scheme/parsing.html'.

[OLEG2]
     Oleg Kiselyov, General ways to traverse collections,,
     `http://pobox.com/~oleg/ftp/Scheme/enumerators-callcc.html'.  2000.


File: gauche-refj.info,  Node: CとSchemeの関数の対応,  Next: Index - 手続きと構文索引,  Prev: 参考文献,  Up: Top

Appendix B CとSchemeの関数の対応
********************************

Cに馴染んだプログラマのために、Cのオペレータとライブラリ関数から
Schemeの関数への対応表を示しておきます。

`+'
     R5RS の算術演算手続き `+'。*Note 数値の演算::参照。

`+='
     Gauche の `inc!' マクロ。*Note 代入::参照。

`-'
     R5RS の算術演算手続き `-'。*Note 数値の演算::参照。

`-='
     Gauche の `dec!' マクロ。*Note 代入::参照。

`->'
     Gauche の `slot-ref' が近いものです。*Note
     インスタンスへのアクセス::参照。

`* (二項演算子)'
     R5RS の算術演算手続き `*'。*Note 数値の演算::参照。

`* (単項演算子)'
     同等の手続きはありません。Scheme
     には明示的ポインタ表記はありません。

`*='
     同等の手続きはありません。

`/'
     R5RS の算術演算手続き `/'。*Note 数値の演算::参照。

`/='
     同等の手続きはありません。

`& (二項演算子)'
     Gauche の `logand'。*Note ビット演算::参照。

`& (単項演算子)'
     同等の手続きはありません。Scheme
     には明示的ポインタ表記はありません。

`&&'
     R5RS の構文 `and'。*Note 条件式::参照。

`&='
     同等の手続きはありません。

`|'
     Gauche の `logior'。*Note ビット演算::参照。

`||'
     R5RS の構文 `or'。*Note 条件式::参照。

`|='
     同等の手続きはありません。

`^'
     Gauche の `logxor'。*Note ビット演算::参照。

`='
     R5RS の構文 `set!'。*Note 代入::参照。

`=='
     R5RS の同等性手続き `eq?'、`eqv?' および `equal?'。 *Note
     等価::参照。

`<'
`<='
     R5RS の算術演算手続き `<' および `<='。 *Note 数値の比較::参照。C
     の演算子とちがい、Scheme のものは 推移的なものです。

`<<'
     Gauche の `ash'。*Note ビット演算::参照。

`<<='
     同等の手続きはありません。

`>'
`>='
     R5RS の算術演算手続き `<' および `<='。 *Note 数値の比較::参照。C
     の演算子とちがい、Scheme のものは 推移的なものです。

`>>'
     Gauche の `ash'。*Note ビット演算::参照。

`>>='
     同等の手続きはありません。

`%'
     R5RS の演算子 `modulo' および `remainder'。*Note 数値の演算::参照。

`%='
     同等の手続きはありません。

`[]'
     R5RS の `vector-ref' (*Note ベクター::参照)
     が近いものです。あるいは、 Gauche のジェネリック関数 `ref' (*Note
     シーケンスフレームワーク::参照)が、 任意の並び用になっています。

`.'
     Gauche の `slot-ref' がこれに近いものです。*Note
     インスタンスへのアクセス::参照。

`~'
     Gauche の `lognot'。*Note ビット演算::参照。

`~='
     同等の手続きはありません。

`!'
     R5RS の手続き `not'。*Note 論理値::参照。

`!='
     同等の手続きはありません。

`abort'
     Gauche の `sys-abort'。*Note プログラムの終了::参照。

`abs'
     R5RS の `abs'。*Note 数値の演算::参照。

`access'
     Gauche の `sys-access'。*Note ファイルの状態::参照。

`acos'
     R5RS の `acos'。*Note 数値の演算::参照。

`alarm'
     Gauche の `sys-alarm'。*Note その他のシステムコール::参照。

`asctime'
     Gauche の `sys-asctime'。*Note 時間::参照。

`asin'
     R5RS の `asin'。*Note 数値の演算::参照。

`assert'
     Gauche には同等の関数はありません。

`atan'
`atan2'
     R5RS の `atan'。*Note 数値の演算::参照。

`atexit'
     Gauche には同等の関数はありませんが、`exit' が呼ばれたとき
     アクティブな動的ハンドラの「事後」サンクが呼ばれます。 *Note
     プログラムの終了:: および *Note 継続:: 参照。

`atof'
`atoi'
`atol'
     `string->number' が使えます。*Note 数値の変換::参照。

`bsearch'
     Gauche には同等の関数はありません。

`calloc'
     Scheme ではメモリ割当は自動的に処理されます。

`ceil'
     R5RS の `ceiling'。*Note 数値の演算::参照。

`cfgetispeed'
`cfgetospeed'
`cfsetispeed'
`cfsetospeed'
     Gauche の `sys-cfgetispeed'、`sys-cfgetospeed'、
     `sys-cfsetispeed'、`sys-cfsetospeed'。*Note Termios::参照。

`chdir'
     Gauche の `sys-chdir'。*Note 他のファイル操作::参照。

`chmod'
     Gauche の `sys-chmod'。*Note ファイルの状態::参照。

`chown'
     Gauche の `sys-chown'。*Note ファイルの状態::参照。

`clearerr'
     未サポート。

`clock'
     Gauche には同等の関数はありません。`sys-times' を使って、
     CPUタイムに情報を得ることができます。

`close'
     ファイルディスクリプタを直接クローズすることはできませんが、
     `close-input-port' あるいは `close-output-port' を使うと、
     元になるファイルはクローズされます。
     いくつかのポートに関連する関数、たとえば、`call-with-output-file'
     などは、操作終了時に自動的にファイルをクローズします。
     また、それを支配しているポートがGCされたときにクローズされます。
     *Note ポート共通の操作::参照。

`closedir'
     Gauche には同等の関数はありません。`sys-readdir' を使うと
     ディレクトリの内容を一度に読むことができます。 *Note
     ディレクトリ:: 参照。

`cos'
`cosh'
     `cos' および `cosh'。*Note 数値の演算:: 参照。

`creat'
     デフォルトでは、書き込みのためにファイルをオープンしたときに、暗黙のうちに
     ファイルが作成されます。ファイル作成のより詳しい制御については
     *Note ファイルポート:: を参照してください。

`ctermid'
     Gauche の `sys-ctermid'。*Note システムへの問い合わせ:: 参照。

`ctime'
     Gauche の `sys-ctime'。*Note 時間:: 参照。

`cuserid'
     同等の関数はありません。これは新しい POSIX からは削除されています。
     別法として、`sys-getuid' といっしょに、`sys-getlogin' あるいは
     `sys-getpwuid' などの関数が使えます。

`difftime'
     Gauche の `sys-difftime'。*Note 時間:: 参照。

`div'
     R5RS の `quotient' および `remainder' を使えます。 *Note
     数値の演算:: 参照。

`dup'
`dup2'
     同等の関数はありません。子プロセス用の I/O を設定したいのであれば、
     `sys-exec' の `iomap' 引数が使えます。*Note Unixのプロセス管理::
     参照。

`execl'
`execle'
`execlp'
`execv'
`execve'
`execvp'
     Gauche の `sys-exec'。*Note Unixのプロセス管理:: 参照。
     より高水準のインタフェースについては *Note
     高レベルプロセスインタフェース:: 参照。

`exit'

`_exit'
     必要なことに応じて、`exit' あるいは `sys-exit' を使いましょう。
     *Note プログラムの終了:: 参照。

`exp'
     R5RS の `exp'。*Note 数値の演算:: 参照。

`fabs'
     R5RS の `abs'。*Note 数値の演算:: 参照。

`fclose'
     ファイルストリームを直接クローズすることはできませんが、
     `close-input-port' あるいは `close-output-port' を使うと、
     元になるファイルはクローズされます。
     いくつかのポートに関連する関数、たとえば、`call-with-output-file'
     などは、操作終了時に自動的にファイルをクローズします。
     また、それを支配しているポートがGCされたときにクローズされます。
     *Note ポート共通の操作::参照。

`fcntl'
     `gauche.fcntl' モジュールで、`sys-fcntl' として実装されています。
     *Note 低レベルファイル操作:: 参照。

`fdopen'
     Gauche の `open-input-fd-port' あるいは `open-output-fd-port'。
     *Note ファイルポート:: 参照。

`feof'
     未サポート。

`ferror'
     未サポート。

`fflush'
     Gauche の `flush'。*Note 出力:: 参照。

`fgetc'
     `read-char' あるいは `read-byte' を使いましょう。*Note 入力::
     参照。

`fgetpos'
     Gauche の `port-tell' を使いましょう。(*Note
     ポート共通の操作::参照。)

`fgets'
     `read-line' あるいは `read-block' を使いましょう。*Note 入力::
     参照。

`fileno'
     `port-file-numer'。*Note ポート共通の操作:: 参照。

`floor'
     R5RS の `floor'。*Note 数値の演算:: 参照。

`fmod'
     Gauche の `fmod'。

`fopen'
     この操作に対応するのは、R5RS の `open-input-file' あるいは
     `open-output-file' です。*Note ファイルポート:: 参照。

`fork'
     Gauche の `sys-fork'。*Note Unixのプロセス管理:: 参照。

`forkpty'
     `sys-forkpty' を使いましょう。*Note Termios:: 参照。

`fpathconf'
     未サポート。

`fprintf'
     直接はサポートされていませんが、Gauche の `format' は
     似たような機能を提供しています。*Note 出力::参照。 SLIB は
     `printf' の実装を持っています。

`fputc'
     `write-char' あるいは `write-byte'を使いましょう。*Note
     出力::参照。

`fputs'
     `display'を使いましょう。*Note 出力:: 参照。

`fread'
     直接はサポートされていません。バイトのチャンクで読みたければ、
     `read-block' を使えるでしょう。

`free'
     Scheme では必要がありません。

`freopen'
     未サポート。

`frexp'
     Gauche の `frexp'。

`fscanf'
     サポートしていません。一般的にはパーザを書かねばなりません。
     データを S式で保持しているなら、`read' が使えます。
     構文がごく単純なら、`srfi-14' (*Note 文字列ライブラリ::) の
     `string-tokenize' や、正規表現 (*Note 正規表現:: および *Note
     正規表現ユーティリティ::) が使えるでしょう。

`fseek'
     Gauche の `port-seek'(*Note ポート共通の操作::参照)を使いましょう。

`fsetpos'
     Gauche の `port-seek'(*Note ポート共通の操作::参照)を使いましょう。

`fstat'
     Gauche の `sys-stat'。*Note ファイルの状態:: 参照。

`ftell'
     Gauche の `port-tell'(*Note ポート共通の操作::参照)を使いましょう。

`fwrite'
     直接はサポートされていません。バイト列のチャンクを書き出したければ、
     単に `display' を使うだけでよいでしょう。*Note 出力::参照。

`getc'
`getchar'
     `read-char' あるいは `read-byte'を使いましょう。*Note 入力::参照。

`getcwd'
     Gauche の `sys-getcwd'。*Note システムへの問い合わせ:: 参照。

`getdomainname'
     Gauche の `sys-getdomainname'。*Note システムへの問い合わせ::
     参照。

`getegid'
     Gauche の `sys-getegid'。*Note システムへの問い合わせ:: 参照。

`getenv'
     Gauche の `sys-getenv'。*Note 環境の問い合わせ:: 参照。

`geteuid'
     Gauche の `sys-geteuid'。*Note システムへの問い合わせ:: 参照。

`gethostname'
     Gauche の `sys-gethostname'。*Note システムへの問い合わせ:: 参照。

`getgid'
     Gauche の `sys-getgid'。*Note システムへの問い合わせ:: 参照。

`getgrgid'
`getgrnam'
     Gauche の `sys-getgrgid' および `sys-getgrnam'。 *Note
     Unixのグループとユーザ:: 参照。

`getgroups'
     Gauche の `sys-getgroups'。*Note システムへの問い合わせ::参照。

`getlogin'
     Gauche の `sys-getlogin'。*Note システムへの問い合わせ::参照。

`getpgrp'
     Gauche の `sys-getpgrp'。*Note システムへの問い合わせ:: 参照。

`getpid'
`getppid'
     Gauche の `sys-getpid'。*Note システムへの問い合わせ:: 参照。

`getpwnam'
`getpwuid'
     Gauche の `sys-getpwnam' および `sys-getpwuid'。 *Note
     Unixのグループとユーザ:: 参照。

`gets'
     `read-line' または `read-block'を使いましょう。*Note 入力::参照。

`gettimeofday'
     Gauche の `sys-gettimeofday'。*Note 時間:: 参照。

`getuid'
     Gauche の `sys-getuid'。*Note システムへの問い合わせ:: 参照。

`gmtime'
     Gauche の `sys-gmtime'。*Note 時間:: 参照。

`isalnum'
     直接はサポートされていませんが、R5RS の `char-alphabetic?' および
     `char-numeric?' が使えます。*Note 文字:: 参照。また、文字集合も
     使えます。*Note 文字集合::、*Note 文字集合ライブラリ:: 参照。

`isalpha'
     R5RS の `char-alphabetic?'。*Note 文字:: 参照。また、 *Note
     文字集合:: および *Note 文字集合ライブラリ:: も参照してください。

`isatty'
     Gauche の `sys-isatty'。*Note 他のファイル操作:: 参照。

`iscntrl'
     直接はサポートされていませんが、`srfi-14' で `(char-set-contains?
     char-set:iso-control c)' が使えます。 *Note 文字集合ライブラリ::
     参照。

`isdigit'
     R5RS の `char-numeric?'。*Note 文字:: 参照。 `srfi-14'
     で、`(char-set-contains? char-set:digit c)' も 使えます。*Note
     文字集合ライブラリ:: 参照。

`isgraph'
     直接はサポートされていませんが、`srfi-14' で `(char-set-contains?
     char-set:graphic c)' が使えます。 *Note 文字集合ライブラリ:: 参照。

`islower'
     R5RS の `char-lower-case?'。*Note 文字:: 参照。 `srfi-14' で
     `(char-set-contains? char-set:lower-case c)' も使えます。*Note
     文字集合ライブラリ:: 参照。

`isprint'
     直接はサポートされていませんが、`srfi-14' で `(char-set-contains?
     char-set:printing c)' が使えます。 *Note 文字集合ライブラリ::
     参照。

`ispunct'
     直接はサポートされていませんが、`srfi-14' で `(char-set-contains?
     char-set:punctuation c)' が使えます。 *Note 文字集合ライブラリ::
     参照。

`isspace'
     R5RS の `char-whitespace?'。*Note 文字:: 参照。 `srfi-14' で
     `(char-set-contains? char-set:whitespace c)' も使えます。*Note
     文字集合ライブラリ:: 参照。

`isupper'
     R5RS の `char-upper-case?'。*Note 文字:: 参照。 `srfi-14' で
     `(char-set-contains? char-set:upper-case c)' も使えます。*Note
     文字集合ライブラリ:: 参照。

`isxdigit'
     直接はサポートされていませんが、`srfi-14' で `(char-set-contains?
     char-set:hex-digit c)' が使えます。 *Note 文字集合ライブラリ::
     参照。

`kill'
     Gauche の `sys-kill'。*Note シグナル:: 参照。

`labs'
     R5RS の `abs'。*Note 数値の演算:: 参照。

`ldexp'
     Gauche の `ldexp'。

`ldiv'
     R5RS の `quotient' および `remainder' を使いましょう。 *Note
     数値の演算::参照。

`link'
     Gauche の `sys-link'。*Note ディレクトリ操作::参照。

`localeconv'
     Gauche の `sys-localeconv'。*Note ロケール:: 参照。

`localtime'
     Gauche の `sys-localtime'。*Note 時間:: 参照。

`log'
     R5RS の `log'。*Note 数値の演算:: 参照。

`log10'
     直接はサポートされていません。 `log10(z)' == `(/ (log z) (log
     10))' です。

`longjmp'
     R5RS の `call/cc' が類似(上位)のメカニズムを提供しています。 *Note
     継続:: 参照。

`lseek'
     Gauche の `port-seek' (*Note ポート共通の操作::参照)
     を使いましょう。

`malloc'
     Scheme では必要ありません。

`mblen'
`mbstowcs'
`mbtowc'
     Gauche ではマルチバイト文字列を内部的に処理しますので、一般的には
     文字列がマルチバイトであるかどうかを気にする必要はありません。
     `string-length' は常に、サポートされているエンコーディングの
     文字列に対して、文字数を返します。文字のエンコーディング変換を
     したいのであれば、*Note 文字コード変換:: を参照してください。

`memcmp'
`memcpy'
`memmove'
`memset'
     同等の関数はありません。

`mkdir'
     Gauche の `sys-mkdir'。*Note ディレクトリ操作:: 参照。

`mkfifo'
     Gauche の `sys-mkfifo'。

`mkstemp'
     Gauche の `sys-mkstemp'。*Note ディレクトリ操作:: 参照。 tmpnam
     の代りにこちらを使いましょう。

`mktime'
     Gauche の `sys-mktime'。*Note 時間:: 参照。

`modf'
     Gauche の `modf'。

`open'
     直接はサポートされていません。この操作に対応するのな R5RS の
     `open-input-file' または `open-output-file' です。 *Note
     ファイルポート:: 参照。

`opendir'
     直接はサポートされていません。
     ディレクトリのエントリをいちどに読むには `sys-readdir'
     が使えます。*Note ディレクトリ:: 参照。

`openpty'
     `sys-openpty' を使いましょう。*Note Termios:: 参照。

`pathconf'
     サポートしません。

`pause'
     Gauche の `sys-pause'。*Note その他のシステムコール:: 参照。

`perror'
     Gauche には同等んお関数はありません。システムコールは一般的には
     error (`<system-error>')
     を投げます。これには、失敗した理由の説明が含まれて います。

`pipe'
     Gauche の `sys-pipe'。*Note 他のファイル操作:: 参照。

`pow'
     R5RS の `expt'。*Note 数値の演算:: 参照。

`printf'
     直接はサポートされていませんが、Gauche の `format' は類似の機能を
     提供しています。*Note 出力:: 参照。SLIB には `printf'
     の実装があります。

`putc'
`putchar'
     `write-char' または `write-byte' を使いましょう。*Note 出力::
     参照。

`puts'
     `display' を使いましょう。*Note 出力:: 参照。

`qsort'
     Gauche の `sort' および `sort!' はリストをソートする便利な方法を
     提供しています。*Note 比較とソート:: 参照。

`raise'
     Gauche には同等の関数はありません。Scheme の関数 `raise' (SRFI-18)
     が例外を発生させます。シグナル `SIG' を現在のプロセスに送るには
     `(sys-kill (sys-getpid) SIG)' が使えます。

`rand'
     直接はサポートされていませんが、多くのプラットフォーム上で、`sys-random'
     のような、よりよい RNG が利用可能です。*Note
     その他のシステムコール:: 参照。

`read'
     直接はサポートされていませんが、 `read-block' (*Note 入力::参照)
     あるいは `read-block!' (*Note
     ユニフォームベクタのブロック入出力::参照)が使えます。

`readdir'
     直接はサポートされていません。Gauche の `sys-readdir' は
     指定のディレクトリを一度に読みます。*Note ディレクトリ:: 参照。

`readlink'
     Gauche の `sys-readlink'。*Note ディレクトリ操作:: 参照。
     この関数はシンボリックリンクをサポートしているシステム上で利用可能です。

`realloc'
     Scheme では必要ありません。

`realpath'
     Gauche の `sys-normalize-pathname' あるいは `sys-realpath'。 *Note
     パス名::参照。

`remove'
     Gauche の `sys-remove'。*Note ディレクトリ操作::参照。

`rename'
     Gauche の `sys-rename'。*Note ディレクトリ操作::参照。

`rewind'
     未サポート。

`rewinddir'
     直接はサポートされていません。
     ディレクトリエントリを一度に読むには `sys-readdir' が使えます。
     *Note ディレクトリ::参照。

`rmdir'
     Gauche の `sys-rmdir'。*Note ディレクトリ操作::参照。

`scanf'
     サポートしていません。一般的にはパーザを書かねばなりません。
     データを S式で保持できるなら、`read' が使えます。
     構文がごく単純なら、`srfi-14' (*Note 文字列ライブラリ::) の
     `string-tokenize' や、正規表現 (*Note 正規表現:: および *Note
     正規表現ユーティリティ::) が使えるでしょう。

`select'
     Gauche の `sys-select'。*Note I/Oの多重化::参照。

`setbuf'
     必要ありません。

`setgid'
     Gauche の `sys-getgid'。

`setjmp'
     R5RS の `call/cc' が類似(上位)のメカニズムを提供しています。 *Note
     継続:: 参照。

`setlocale'
     Gauche の `sys-setlocale'。*Note ロケール::参照。

`setpgid'
     Gauche の `sys-setpgid'。*Note システムへの問い合わせ::参照。

`setsid'
     Gauche の `sys-setsid'。*Note システムへの問い合わせ::参照。

`setuid'
     Gauche の `sys-setuid'。*Note システムへの問い合わせ::参照。

`setvbuf'
     必要ありません。

`sigaction'
     シグナルハンドラを設定するには、`set-signal-handler!' が使えます。
     *Note シグナルの処理::参照。

`sigaddset'
`sigdelset'
`sigemptyset'
`sigfillset'
     Gauche の `sys-sigset-add!' および `sys-sigset-delete!'。 *Note
     シグナルとシグナルセット::参照。

`sigismember'
     未サポート。

`siglongjmp'
     R5RS の `call/cc' が類似(上位)のメカニズムを提供しています。 *Note
     継続:: 参照。

`signal'
     シグナルハンドラを設定するのには、`with-signal-handlers'
     が使えます。 *Note シグナルの処理:: 参照。

`sigpending'
     未サポート

`sigprocmask'
     シグナルマスクは内部的に処理されます。*Note シグナルの処理::参照。

`sigsetjmp'
     R5RS の `call/cc' が類似(上位)のメカニズムを提供しています。 *Note
     継続:: 参照。

`sigsuspend'
     Gauche の `sys-sigsuspend'。*Note シグナルのマスクと待機::参照。

`sin'
`sinh'
     `sin' および `sinh' を使いましょう。*Note 数値の演算::参照。

`sleep'
     Gauche の `sys-sleep'。*Note その他のシステムコール::参照。

`sprintf'
     直接はサポートされていませんが、Gauche の `format' は類似の機能を
     提供しています。*Note 出力:: 参照。SLIB には `printf'
     の実装があります。

`sqrt'
     R5RS の `sqrt'。*Note 数値の演算::参照。

`srand'
     直接はサポートされていませんが、多くのプラットフォーム上で、`sys-random'
     のような、よりよい RNG が利用可能です。*Note
     その他のシステムコール:: 参照。

`sscanf'
     サポートしていません。一般的にはパーザを書かねばなりません。
     データを S式で保持できるなら、`read' が使えます。
     構文がごく単純なら、`srfi-14' (*Note 文字列ライブラリ::) の
     `string-tokenize' や、正規表現 (*Note 正規表現:: および *Note
     正規表現ユーティリティ::) が使えるでしょう。

`stat'
     Gauche の `sys-stat'。*Note ファイルの状態::参照。

`strcasecmp'
     R5RS の `string-ci=?' および、その他の比較関数。 *Note
     文字列の比較::参照。

`strcat'
     R5RS の `string-append'。*Note 文字列を扱うその他の手続き::参照。

`strchr'
     SRFI-13 の `string-index'。  *Note 文字列の探索::参照。

`strcmp'
     R5RS の `string=?' および、その他の比較関数。 *Note
     文字列の比較::参照。

`strcoll'
     未サポート。

`strcpy'
     R5RS の `string-copy'。*Note 文字列を扱うその他の手続き::参照。

`strcspn'
     直接はサポートされていませんが、文字集合とともに、SRFI-13 の
     `string-skip' が使えます。*Note 文字列の探索::参照。

`strerror'
     サポートされません。

`strftime'
     Gauche の `sys-strftime'。*Note 時間::参照。

`strlen'
     R5RS の `string-length'。*Note 文字列のアクセスと変更::参照。

`strncat'
     直接はサポートされていませんが、`string-append' および `substring'
     が使えます。

`strncasecmp'
     SRFI-13 の `string-compare-ci' は非常に柔軟な(しかし、使うのは
     多少難しい)機能を提供しています。*Note 文字列の色々な比較::参照。
     ふたつの文字列の固定長の接頭辞が一致しているかどうかをチェックしたい
     だけなら、SRFI-13 の `string-prefix-ci?' が使えます。

`strncmp'
     SRFI-13 の `string-compare-ci' は非常に柔軟な(しかし、使うのは
     多少難しい)機能を提供しています。*Note 文字列の色々な比較::参照。
     ふたつの文字列の固定長の接頭辞が一致しているかどうかをチェックしたい
     だけなら、SRFI-13 の `string-prefix-ci?' が使えます。 *Note
     文字列のプリフィックスとサフィックス::参照。

`strncpy'
     SRFI-13 の `substring'。*Note 文字列を扱うその他の手続き::参照。

`strpbrk'
     直接はサポートされていませんが、文字集合と SRFI-13 の `string-skip'
     が使えます。*Note 文字列の探索::参照。

`strrchr'
     SRFI-13 の `string-index-right'。*Note 文字列の探索::参照。

`strspn'
     直接はサポートされていませんが、文字集合と SRFI-13 の
     `string-index' が使えます。*Note 文字列の探索::参照。

`strstr'
     SRFI-13 の `string-contains'。*Note 文字列の探索::参照。

`strtod'
     R5RS の `string->number'が使えます。*Note 数値の変換::参照。

`strtok'
     SRFI-13 の `string-tokenize'。*Note 他の文字列操作::参照。

`strtol'
`strtoul'
     R5RS の `string->number'が使えます。*Note 数値の変換::参照。

`strxfrm'
     未サポート。

`symlink'
     Gauche の `sys-symlink'。*Note ディレクトリ操作::参照。
     この関数は、シンボリックリンクをサポートしているシステム上で利用可能です。

`sysconf'
     未サポート。

`system'
     Gauche の `sys-system'。*Note Unixのプロセス管理::参照。
     一般的にはプロセスライブラリ(*Note
     高レベルプロセスインタフェース::) を使うことを推奨します。

`tan'
`tanh'
     R5RS の `tan' および Gauche の `tanh'。*Note 数値の演算::参照。

`tcdrain'

`tcflow'

`tcflush'

`tcgetattr'

`tcgetpgrp'

`tcsendbreak'

`tcsetattr'

`tcsetpgrp'
     対応する関数はそれぞれ、`sys-tcdrain'、`sys-tcflow'、
     `sys-tcflush'、`sys-tcgetattr'、`sys-tcgetpgrp'、
     `sys-tcsendbreak'、`sys-tcsetattr'、`sys-tcsetpgrp' です。 *Note
     Termios::参照。

`time'
     Gauche の `sys-time'。  *Note 時間::参照。

`times'
     Gauche の `sys-times'。*Note システムへの問い合わせ::参照。

`tmpfile'
     厳密には、サポートしません。

`tmpnam'
     Gauche の `sys-tmpnam'。この関数は POSIX
     にあるので提供されていますが、
     潜在的なセキュリティリスクがあるため、利用はおすすめできません。
     代りに `sys-mkstemp' を使いましょう。*Note ディレクトリ操作::参照。

`tolower'
`toupper'
     R5RS の `char-upcase' および `char-downcase'。*Note 文字::参照。

`ttyname'
     Gauche の `sys-ttyname'。*Note 他のファイル操作::参照。

`tzset'
     未サポート。

`umask'
     Gauche の `sys-umask'。*Note ディレクトリ操作::参照。

`uname'
     Gauche の `sys-uname'。*Note システムへの問い合わせ::参照。

`ungetc'
     直接はサポートされません。プッシュしなおす代りに、`peek-char'
     をつかって 先読みしましょう。

`unlink'
     Gauche の `sys-unlink'。*Note ディレクトリ操作::参照。

`utime'
     Gauche の `sys-utime'。*Note ファイルの状態::参照。

`va_arg'
`va_end'
`va_start'
     Scheme は可変長引数を自然に処理できますので、必要ありません。

`vfprintf'
`vprintf'
`vsprintf'
     直接はサポートされていませんが、Gauche の `format' は類似の機能を
     提供しています。*Note 出力:: 参照。SLIB には `printf'
     の実装があります。

`wait'
     Gauche の `sys-wait'。*Note Unixのプロセス管理::参照。

`waitpid'
     Gauche の `sys-waitpid'。*Note Unixのプロセス管理::参照。

`wcstombs'
`wctomb'
     Gauche
     はマルチバイト文字列を内部的に処理します。それゆえ、一般的には
     文字列がマルチバイトであるかどうかを気にする必要はありません。
     `string-length'
     は常にサポートされているエンコーディングでの文字列の
     文字数を返します。文字エンコーディングを変換したければ、 *Note
     文字コード変換::を参照してください。

`write'
     R5RS の `display' (*Note 出力::)。 あるいは `write-block' (*Note
     ユニフォームベクタのブロック入出力::参照)。


File: gauche-refj.info,  Node: Index - 手続きと構文索引,  Next: Index - モジュール索引,  Prev: CとSchemeの関数の対応,  Up: Top

Appendix C Index - 手続きと構文索引
***********************************

[index]
* Menu:

* %macroexpand:                          マクロの展開.        (line  20)
* %macroexpand-1:                        マクロの展開.        (line  21)
* (setter cgi-test-enviornment-ref):     CGIのテスト.         (line  14)
* (setter object-apply):                 適用可能なオブジェクト.
                                                              (line  47)
* (setter port-buffering):               ポート共通の操作.    (line  49)
* (setter ref) <1>:                      インスタンスへのアクセス.
                                                              (line  49)
* (setter ref) <2>:                      基本的なシーケンスのアクセサ.
                                                              (line  19)
* (setter ref):                          ハッシュテーブル.    (line 121)
* (setter subseq):                       シーケンスのスライス.
                                                              (line  19)
* *:                                     数値の演算.          (line   8)
* +:                                     数値の演算.          (line   7)
* -:                                     数値の演算.          (line  13)
* ->char-set:                            文字セットの構築子.  (line  37)
* /:                                     数値の演算.          (line  14)
* ::                                     Eager comprehensions.
                                                              (line 133)
* :char-range:                           Eager comprehensions.
                                                              (line 149)
* :dispatched:                           Eager comprehensions.
                                                              (line 154)
* :do:                                   Eager comprehensions.
                                                              (line 158)
* :integers:                             Eager comprehensions.
                                                              (line 139)
* :let:                                  Eager comprehensions.
                                                              (line 160)
* :list:                                 Eager comprehensions.
                                                              (line 135)
* :parallel:                             Eager comprehensions.
                                                              (line 162)
* :port:                                 Eager comprehensions.
                                                              (line 152)
* :range:                                Eager comprehensions.
                                                              (line 143)
* :real-range:                           Eager comprehensions.
                                                              (line 147)
* :string:                               Eager comprehensions.
                                                              (line 137)
* :until:                                Eager comprehensions.
                                                              (line 166)
* :vector:                               Eager comprehensions.
                                                              (line 136)
* :while:                                Eager comprehensions.
                                                              (line 164)
* <:                                     数値の比較.          (line  15)
* <=:                                    数値の比較.          (line  16)
* =:                                     数値の比較.          (line   7)
* >:                                     数値の比較.          (line  17)
* >=:                                    数値の比較.          (line  18)
* abandoned-mutex-exception?:            スレッド例外.        (line  47)
* abs:                                   数値の演算.          (line  33)
* absolute-path?:                        パスネームユーティリティ.
                                                              (line  13)
* acons:                                 リストの作成.        (line  11)
* acos:                                  数値の演算.          (line 118)
* acosh:                                 数値の演算.          (line 129)
* add-duration:                          時間に関する手続き.  (line  44)
* add-duration!:                         時間に関する手続き.  (line  45)
* add-hook!:                             フック.              (line  43)
* add-load-path:                         Schemeファイルのロード.
                                                              (line  51)
* alist->hash-table:                     その他のリストライブラリ.
                                                              (line  96)
* alist-cons:                            連想リスト.          (line   7)
* alist-copy:                            連想リスト.          (line  11)
* alist-delete:                          連想リスト.          (line  24)
* alist-delete!:                         連想リスト.          (line  25)
* all-modules:                           モジュールイントロスペクション.
                                                              (line  52)
* allocate-instance:                     インスタンスの作成.  (line  28)
* and <1>:                               条件式.              (line  74)
* and:                                   Eager comprehensions.
                                                              (line 123)
* and-let*:                              And-let*.            (line  10)
* angle:                                 数値の変換.          (line  15)
* any:                                   リストの探索.        (line  31)
* any$:                                  リストの探索.        (line  48)
* any-pred:                              コンビネータ.        (line  56)
* any?-ec:                               Eager comprehensions.
                                                              (line 102)
* append:                                他のリスト手続き.    (line   7)
* append!:                               他のリスト手続き.    (line  13)
* append-ec:                             Eager comprehensions.
                                                              (line  83)
* append-map:                            リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  82)
* append-map!:                           リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  83)
* append-reverse:                        種々のリスト処理ルーチン.
                                                              (line  18)
* append-reverse!:                       種々のリスト処理ルーチン.
                                                              (line  19)
* apply:                                 手続き.              (line  12)
* apply$:                                コンビネータ.        (line  23)
* apply-generic:                         メソッド適用のカスタマイズ.
                                                              (line   7)
* apply-method:                          メソッド適用のカスタマイズ.
                                                              (line  15)
* apply-methods:                         メソッド適用のカスタマイズ.
                                                              (line  13)
* apropos:                               インタラクティブセッション.
                                                              (line  18)
* args-fold:                             args-fold プログラム引数処理.
                                                              (line  19)
* arity:                                 手続きのアリティ.    (line  10)
* arity-at-least-value:                  手続きのアリティ.    (line  33)
* arity-at-least?:                       手続きのアリティ.    (line  30)
* array:                                 配列.                (line 114)
* array->list:                           配列.                (line 197)
* array->vector:                         配列.                (line 196)
* array-add-elements:                    配列.                (line 222)
* array-add-elements!:                   配列.                (line 223)
* array-concatenate:                     配列.                (line 199)
* array-div-elements:                    配列.                (line 229)
* array-div-elements!:                   配列.                (line 230)
* array-div-left:                        配列.                (line 219)
* array-div-right:                       配列.                (line 220)
* array-end:                             配列.                (line 131)
* array-expt:                            配列.                (line 217)
* array-flip:                            配列.                (line 205)
* array-flip!:                           配列.                (line 206)
* array-for-each-index:                  配列.                (line 181)
* array-inverse:                         配列.                (line 210)
* array-length:                          配列.                (line 132)
* array-map:                             配列.                (line 193)
* array-map!:                            配列.                (line 191)
* array-mul:                             配列.                (line 215)
* array-mul-elements:                    配列.                (line 227)
* array-mul-elements!:                   配列.                (line 228)
* array-rank:                            配列.                (line 121)
* array-ref:                             配列.                (line 155)
* array-retabulate!:                     配列.                (line 188)
* array-rotate-90:                       配列.                (line 203)
* array-set!:                            配列.                (line 162)
* array-shape:                           配列.                (line 127)
* array-size:                            配列.                (line 147)
* array-start:                           配列.                (line 130)
* array-sub-elements:                    配列.                (line 225)
* array-sub-elements!:                   配列.                (line 226)
* array-transpose:                       配列.                (line 201)
* array?:                                配列.                (line  82)
* as-nodeset:                            SXPathの基本的なコンバータとアプリケータ.
                                                              (line  17)
* ash:                                   ビット演算.          (line  13)
* asin:                                  数値の演算.          (line 117)
* asinh:                                 数値の演算.          (line 128)
* assert-curr-char:                      入力ストリームのパージング.
                                                              (line  51)
* assoc:                                 他のリスト手続き.    (line  46)
* assoc$:                                連想リスト.          (line  32)
* assoc-ref:                             その他のリストライブラリ.
                                                              (line 115)
* assoc-set!:                            その他のリストライブラリ.
                                                              (line 142)
* assq:                                  他のリスト手続き.    (line  44)
* assq-ref:                              その他のリストライブラリ.
                                                              (line 116)
* assq-set!:                             その他のリストライブラリ.
                                                              (line 143)
* assv:                                  他のリスト手続き.    (line  45)
* assv-ref:                              その他のリストライブラリ.
                                                              (line 117)
* assv-set!:                             その他のリストライブラリ.
                                                              (line 144)
* atan:                                  数値の演算.          (line 122)
* atanh:                                 数値の演算.          (line 130)
* attlist->alist:                        SSAXデータタイプ.    (line 135)
* attlist-add:                           SSAXデータタイプ.    (line 132)
* attlist-fold:                          SSAXデータタイプ.    (line 136)
* attlist-null?:                         SSAXデータタイプ.    (line 133)
* attlist-remoev-top:                    SSAXデータタイプ.    (line 134)
* autoload:                              Autoload.            (line   7)
* base64-decode:                         Base64エンコーディング.
                                                              (line  24)
* base64-decode-string:                  Base64エンコーディング.
                                                              (line  31)
* base64-encode:                         Base64エンコーディング.
                                                              (line  13)
* base64-encode-string:                  Base64エンコーディング.
                                                              (line  19)
* begin <1>:                             Eager comprehensions.
                                                              (line 126)
* begin:                                 順次実行.            (line   7)
* begin0:                                順次実行.            (line  37)
* bignum?:                               数値に関する述語.    (line  60)
* bindtextdomain:                        地域化メッセージ.    (line  91)
* bit-field:                             ビット演算.          (line  39)
* boolean?:                              論理値.              (line  14)
* break:                                 リストの探索.        (line  26)
* break!:                                リストの探索.        (line  27)
* build-path:                            パスネームユーティリティ.
                                                              (line   7)
* build-transliterator:                  文字変換.            (line  89)
* caaaar:                                リストへのアクセスと変更.
                                                              (line  19)
* caaadr:                                リストへのアクセスと変更.
                                                              (line  19)
* caaar:                                 リストへのアクセスと変更.
                                                              (line  19)
* caadar:                                リストへのアクセスと変更.
                                                              (line  19)
* caaddr:                                リストへのアクセスと変更.
                                                              (line  19)
* caadr:                                 リストへのアクセスと変更.
                                                              (line  19)
* caar:                                  リストへのアクセスと変更.
                                                              (line  18)
* cadaar:                                リストへのアクセスと変更.
                                                              (line  19)
* cadadr:                                リストへのアクセスと変更.
                                                              (line  19)
* cadar:                                 リストへのアクセスと変更.
                                                              (line  19)
* caddar:                                リストへのアクセスと変更.
                                                              (line  19)
* cadddr:                                リストへのアクセスと変更.
                                                              (line  19)
* caddr:                                 リストへのアクセスと変更.
                                                              (line  19)
* cadr:                                  リストへのアクセスと変更.
                                                              (line  19)
* call-with-builder:                     基礎的なイテレータ構築メソッド.
                                                              (line  59)
* call-with-cgi-script:                  CGIのテスト.         (line  34)
* call-with-client-socket:               高レベルネットワーク手続き.
                                                              (line 136)
* call-with-current-continuation:        継続.                (line   7)
* call-with-input-conversion:            変換ポート.          (line  73)
* call-with-input-file <1>:              ファイルポート.      (line 120)
* call-with-input-file:                  拡張されたポート手続き.
                                                              (line  10)
* call-with-input-process:               Process ports.       (line  56)
* call-with-input-string:                文字列ポート.        (line  51)
* call-with-iterator:                    基礎的なイテレータ構築メソッド.
                                                              (line  12)
* call-with-iterators:                   基礎的なイテレータ構築メソッド.
                                                              (line  50)
* call-with-output-conversion:           変換ポート.          (line  75)
* call-with-output-file <1>:             拡張されたポート手続き.
                                                              (line  16)
* call-with-output-file:                 ファイルポート.      (line 122)
* call-with-output-process:              Process ports.       (line  98)
* call-with-output-string:               文字列ポート.        (line  52)
* call-with-process-io:                  Process ports.       (line 115)
* call-with-string-io:                   文字列ポート.        (line  74)
* call-with-values:                      多値.                (line  14)
* call/cc:                               継続.                (line   8)
* car:                                   リストへのアクセスと変更.
                                                              (line   7)
* car+cdr:                               SRFI-1 リスト選択子. (line  19)
* car-sxpath:                            SXPathクエリ言語.    (line  49)
* cartesian-product:                     組み合わせ.          (line  83)
* cartesian-product-right:               組み合わせ.          (line  84)
* case:                                  条件式.              (line  50)
* case-lambda:                           手続きを作る.        (line  70)
* cdaaar:                                リストへのアクセスと変更.
                                                              (line  19)
* cdaadr:                                リストへのアクセスと変更.
                                                              (line  19)
* cdaar:                                 リストへのアクセスと変更.
                                                              (line  19)
* cdadar:                                リストへのアクセスと変更.
                                                              (line  19)
* cdaddr:                                リストへのアクセスと変更.
                                                              (line  19)
* cdadr:                                 リストへのアクセスと変更.
                                                              (line  19)
* cdar:                                  リストへのアクセスと変更.
                                                              (line  19)
* cddaar:                                リストへのアクセスと変更.
                                                              (line  19)
* cddadr:                                リストへのアクセスと変更.
                                                              (line  19)
* cddar:                                 リストへのアクセスと変更.
                                                              (line  19)
* cdddar:                                リストへのアクセスと変更.
                                                              (line  22)
* cddddr:                                リストへのアクセスと変更.
                                                              (line  23)
* cdddr:                                 リストへのアクセスと変更.
                                                              (line  19)
* cddr:                                  リストへのアクセスと変更.
                                                              (line  19)
* cdr:                                   リストへのアクセスと変更.
                                                              (line   8)
* ceiling:                               数値の演算.          (line  89)
* ces-conversion-supported?:             サポートされる文字エンコーディング.
                                                              (line  17)
* ces-convert:                           変換ポート.          (line  63)
* ces-equivalent?:                       サポートされる文字エンコーディング.
                                                              (line  36)
* ces-guess-from-string:                 文字エンコーディングの自動判定.
                                                              (line  16)
* ces-upper-compatible?:                 サポートされる文字エンコーディング.
                                                              (line  53)
* cgi-add-temporary-file:                CGIユーティリティ.   (line 204)
* cgi-get-metavariable:                  CGIユーティリティ.   (line  41)
* cgi-get-parameter:                     CGIユーティリティ.   (line  88)
* cgi-header:                            CGIユーティリティ.   (line 109)
* cgi-main:                              CGIユーティリティ.   (line 141)
* cgi-metavariables:                     CGIユーティリティ.   (line  21)
* cgi-output-character-encoding:         CGIユーティリティ.   (line 130)
* cgi-parse-parameters:                  CGIユーティリティ.   (line  54)
* cgi-temporary-files:                   CGIユーティリティ.   (line 213)
* cgi-test-enviornment-ref:              CGIのテスト.         (line  13)
* change-class:                          クラスの変更.        (line  15)
* change-object-class:                   クラスの変更.        (line  20)
* char:                                  文字.                (line  72)
* char->integer:                         文字.                (line  97)
* char->ucs:                             文字.                (line 107)
* char-alphabetic?:                      文字.                (line  87)
* char-ci:                               文字.                (line  80)
* char-downcase:                         文字.                (line 126)
* char-lower-case?:                      文字.                (line  91)
* char-numeric?:                         文字.                (line  88)
* char-ready?:                           データの読み込み.    (line  98)
* char-set <1>:                          文字セットの比較.    (line  10)
* char-set:                              文字集合.            (line  91)
* char-set->list:                        文字セットへの問い合わせ.
                                                              (line  13)
* char-set->string:                      文字セットへの問い合わせ.
                                                              (line  16)
* char-set-adjoin:                       文字セットに適用できる代数的関数.
                                                              (line   7)
* char-set-adjoin!:                      文字セットに適用できる代数的関数.
                                                              (line   8)
* char-set-any:                          文字セットへの問い合わせ.
                                                              (line  22)
* char-set-complement:                   文字セットに適用できる代数的関数.
                                                              (line  15)
* char-set-complement!:                  文字セットに適用できる代数的関数.
                                                              (line  16)
* char-set-contains?:                    文字集合.            (line  79)
* char-set-copy:                         文字集合.            (line  96)
* char-set-count:                        文字セットへの問い合わせ.
                                                              (line  10)
* char-set-cursor:                       文字セットのイテレーション.
                                                              (line   7)
* char-set-cursor-next:                  文字セットのイテレーション.
                                                              (line  13)
* char-set-delete:                       文字セットに適用できる代数的関数.
                                                              (line  11)
* char-set-delete!:                      文字セットに適用できる代数的関数.
                                                              (line  12)
* char-set-diff+intersection:            文字セットに適用できる代数的関数.
                                                              (line  35)
* char-set-diff+intersection!:           文字セットに適用できる代数的関数.
                                                              (line  37)
* char-set-difference:                   文字セットに適用できる代数的関数.
                                                              (line  27)
* char-set-difference!:                  文字セットに適用できる代数的関数.
                                                              (line  28)
* char-set-every:                        文字セットへの問い合わせ.
                                                              (line  19)
* char-set-filter:                       文字セットの構築子.  (line  21)
* char-set-filter!:                      文字セットの構築子.  (line  22)
* char-set-fold:                         文字セットのイテレーション.
                                                              (line  19)
* char-set-for-each:                     文字セットのイテレーション.
                                                              (line  26)
* char-set-hash:                         文字セットの比較.    (line  13)
* char-set-intersection:                 文字セットに適用できる代数的関数.
                                                              (line  23)
* char-set-intersection!:                文字セットに適用できる代数的関数.
                                                              (line  24)
* char-set-map:                          文字セットのイテレーション.
                                                              (line  29)
* char-set-ref:                          文字セットのイテレーション.
                                                              (line  10)
* char-set-size:                         文字セットへの問い合わせ.
                                                              (line   7)
* char-set-unfold:                       文字セットのイテレーション.
                                                              (line  22)
* char-set-unfold!:                      文字セットのイテレーション.
                                                              (line  23)
* char-set-union:                        文字セットに適用できる代数的関数.
                                                              (line  19)
* char-set-union!:                       文字セットに適用できる代数的関数.
                                                              (line  20)
* char-set-xor:                          文字セットに適用できる代数的関数.
                                                              (line  31)
* char-set-xor!:                         文字セットに適用できる代数的関数.
                                                              (line  32)
* char-set=:                             文字セットの比較.    (line   7)
* char-set?:                             文字集合.            (line  76)
* char-upcase:                           文字.                (line 125)
* char-upper-case?:                      文字.                (line  90)
* char-whitespace?:                      文字.                (line  89)
* char?:                                 文字.                (line  67)
* check-substring-spec:                  低レベルな文字列に関する手続き.
                                                              (line  15)
* circular-list:                         SRFI-1 リスト構築子. (line  21)
* circular-list?:                        SRFI-1 リストの述語. (line  10)
* clamp:                                 数値の演算.          (line  99)
* class-direct-methods:                  クラスオブジェクト.  (line  62)
* class-direct-slots:                    クラスオブジェクト.  (line  57)
* class-direct-subclasses:               クラスオブジェクト.  (line  35)
* class-direct-supers:                   クラスオブジェクト.  (line  28)
* class-name:                            クラスオブジェクト.  (line  14)
* class-of:                              一般的な問い合わせ.  (line   7)
* class-precedence-list:                 クラスオブジェクト.  (line  19)
* class-slot-accessor:                   クラスオブジェクト.  (line  65)
* class-slot-bound?:                     インスタンスへのアクセス.
                                                              (line  78)
* class-slot-definition:                 クラスオブジェクト.  (line  52)
* class-slot-ref:                        インスタンスへのアクセス.
                                                              (line  76)
* class-slot-set!:                       インスタンスへのアクセス.
                                                              (line  77)
* class-slots:                           クラスオブジェクト.  (line  41)
* close-input-port:                      ポート共通の操作.    (line  36)
* close-output-port:                     ポート共通の操作.    (line  37)
* code:                                  機能ベースプログラム設定言語.
                                                              (line  52)
* coerce-to:                             コレクションに対する様々な操作.
                                                              (line  21)
* combinations:                          組み合わせ.          (line  41)
* combinations*:                         組み合わせ.          (line  42)
* combinations*-for-each:                組み合わせ.          (line  57)
* combinations-for-each:                 組み合わせ.          (line  56)
* compare:                               比較とソート.        (line   7)
* complete-sexp?:                        リスナー.            (line 115)
* complex?:                              数値に関する述語.    (line   8)
* compose:                               コンビネータ.        (line  36)
* compute-get-n-set:                     スロットアクセスのカスタマイズ.
                                                              (line   9)
* compute-slots:                         スロットアクセスのカスタマイズ.
                                                              (line   7)
* concatenate:                           種々のリスト処理ルーチン.
                                                              (line  13)
* concatenate!:                          種々のリスト処理ルーチン.
                                                              (line  14)
* cond:                                  条件式.              (line  23)
* cond-expand:                           機能条件式.          (line  15)
* cond-list:                             その他のリストライブラリ.
                                                              (line  74)
* condition:                             コンディション.      (line 257)
* condition-has-type?:                   コンディション.      (line 223)
* condition-ref:                         コンディション.      (line 228)
* condition-type?:                       コンディション.      (line 205)
* condition-variable-broadcast!:         同期プリミティブ.    (line 205)
* condition-variable-name:               同期プリミティブ.    (line 193)
* condition-variable-signal!:            同期プリミティブ.    (line 200)
* condition-variable-specific:           同期プリミティブ.    (line 196)
* condition-variable-specific-set!:      同期プリミティブ.    (line 197)
* condition-variable?:                   同期プリミティブ.    (line 184)
* condition?:                            コンディション.      (line 218)
* cons:                                  リストの作成.        (line   7)
* cons*:                                 SRFI-1 リスト構築子. (line  10)
* construct-cookie-string:               HTTPクッキー.        (line  31)
* copy-bit:                              ビット演算.          (line  43)
* copy-bit-field:                        ビット演算.          (line  48)
* copy-file:                             ファイル操作.        (line  13)
* copy-port:                             ポート共通の操作.    (line 118)
* copy-time:                             時間に関する手続き.  (line  25)
* cos:                                   数値の演算.          (line 115)
* cosh:                                  数値の演算.          (line 126)
* count:                                 種々のリスト処理ルーチン.
                                                              (line  55)
* count$:                                種々のリスト処理ルーチン.
                                                              (line  64)
* create-directory*:                     ディレクトリユーティリティ.
                                                              (line 111)
* current-class-of:                      一般的な問い合わせ.  (line  31)
* current-country:                       地域化.              (line  46)
* current-date:                          時間に関する問い合わせ.
                                                              (line  13)
* current-directory:                     ディレクトリユーティリティ.
                                                              (line   7)
* current-error-port:                    ポート共通の操作.    (line  23)
* current-exception-handler:             例外の処理.          (line  91)
* current-input-port:                    ポート共通の操作.    (line  19)
* current-julian-day:                    時間に関する問い合わせ.
                                                              (line  21)
* current-language:                      地域化.              (line  45)
* current-load-history:                  Schemeファイルのロード.
                                                              (line  77)
* current-load-next:                     Schemeファイルのロード.
                                                              (line  78)
* current-load-port:                     Schemeファイルのロード.
                                                              (line  76)
* current-locale-details:                地域化.              (line  47)
* current-modified-julian-day:           時間に関する問い合わせ.
                                                              (line  26)
* current-module:                        モジュールの定義と選択.
                                                              (line  24)
* current-output-port:                   ポート共通の操作.    (line  20)
* current-thread:                        スレッド手続き.      (line  45)
* current-time <1>:                      時間.                (line 115)
* current-time:                          時間に関する問い合わせ.
                                                              (line   7)
* cut:                                   手続きを作る.        (line  35)
* cute:                                  手続きを作る.        (line  36)
* d:                                     インタラクティブセッション.
                                                              (line  37)
* date->julian-day:                      日付.                (line  66)
* date->modified-julian-day:             日付.                (line  67)
* date->string:                          日付の読み書き.      (line   7)
* date->time-monotonic:                  日付.                (line  68)
* date->time-tai:                        日付.                (line  69)
* date->time-utc:                        日付.                (line  70)
* date-day:                              日付.                (line  52)
* date-hour:                             日付.                (line  51)
* date-minute:                           日付.                (line  50)
* date-month:                            日付.                (line  53)
* date-nanosecond:                       日付.                (line  48)
* date-second:                           日付.                (line  49)
* date-week-day:                         日付.                (line  59)
* date-week-number:                      日付.                (line  60)
* date-year:                             日付.                (line  54)
* date-year-day:                         日付.                (line  58)
* date-zone-offset:                      日付.                (line  55)
* date?:                                 日付.                (line  44)
* dbm-close:                             DBMデータベースのオープンとクローズ.
                                                              (line  79)
* dbm-closed?:                           DBMデータベースのオープンとクローズ.
                                                              (line  83)
* dbm-db-copy:                           DBMデータベースインスタンスの管理.
                                                              (line  30)
* dbm-db-exists?:                        DBMデータベースインスタンスの管理.
                                                              (line  20)
* dbm-db-move:                           DBMデータベースインスタンスの管理.
                                                              (line  35)
* dbm-db-remove:                         DBMデータベースインスタンスの管理.
                                                              (line  27)
* dbm-delete!:                           DBMデータベースのアクセス.
                                                              (line  19)
* dbm-exists?:                           DBMデータベースのアクセス.
                                                              (line  16)
* dbm-fold:                              DBMデータベース上の繰り返し処理.
                                                              (line   9)
* dbm-for-each:                          DBMデータベース上の繰り返し処理.
                                                              (line  20)
* dbm-get:                               DBMデータベースのアクセス.
                                                              (line  12)
* dbm-map:                               DBMデータベース上の繰り返し処理.
                                                              (line  24)
* dbm-open:                              DBMデータベースのオープンとクローズ.
                                                              (line  70)
* dbm-put!:                              DBMデータベースのアクセス.
                                                              (line   9)
* dcgettext:                             地域化メッセージ.    (line  96)
* debug-print:                           デバッグ補助.        (line   7)
* dec!:                                  代入.                (line 126)
* declare-bundle!:                       地域化.              (line  63)
* decode-float:                          数値の変換.          (line  20)
* decompose-path:                        パスネームユーティリティ.
                                                              (line  33)
* define:                                定義.                (line   7)
* define-class:                          クラスの定義.        (line   9)
* define-condition-type:                 コンディション.      (line 178)
* define-constant:                       定義.                (line  47)
* define-generic:                        ジェネリックファンクションとメソッド.
                                                              (line  10)
* define-in-module:                      定義.                (line  56)
* define-macro:                          伝統的なマクロ.      (line   7)
* define-method:                         ジェネリックファンクションとメソッド.
                                                              (line  22)
* define-module:                         モジュールの定義と選択.
                                                              (line   7)
* define-reader-ctor:                    読み込み時コンストラクタ.
                                                              (line  23)
* define-record-type:                    レコード型.          (line  20)
* define-syntax:                         健全なマクロ.        (line  13)
* define-values:                         定義.                (line  38)
* delay:                                 遅延評価.            (line  10)
* delete:                                リストの削除.        (line   7)
* delete!:                               リストの削除.        (line   8)
* delete$:                               リストの削除.        (line  14)
* delete-directory*:                     ディレクトリユーティリティ.
                                                              (line 118)
* delete-duplicates:                     リストの削除.        (line  17)
* delete-duplicates!:                    リストの削除.        (line  18)
* delete-hook!:                          フック.              (line  50)
* delete-keyword:                        キーワード.          (line  65)
* delete-keyword!:                       キーワード.          (line  66)
* denominator:                           数値の演算.          (line  81)
* dequeue!:                              キュー.              (line  49)
* dequeue-all!:                          キュー.              (line  56)
* describe:                              インタラクティブセッション.
                                                              (line  36)
* determinant:                           配列.                (line 212)
* determinant!:                          配列.                (line 213)
* dgettext:                              地域化メッセージ.    (line  95)
* diff:                                  テキストストリームの相違点を計算する.
                                                              (line  12)
* diff-report:                           テキストストリームの相違点を計算する.
                                                              (line  32)
* digest:                                メッセージダイジェストフレームワーク.
                                                              (line  31)
* digest-final!:                         メッセージダイジェストフレームワーク.
                                                              (line  27)
* digest-hexify:                         メッセージダイジェストフレームワーク.
                                                              (line  41)
* digest-string:                         メッセージダイジェストフレームワーク.
                                                              (line  36)
* digest-update!:                        メッセージダイジェストフレームワーク.
                                                              (line  22)
* digit->integer:                        文字.                (line 134)
* directory-fold:                        ディレクトリユーティリティ.
                                                              (line  71)
* directory-list:                        ディレクトリユーティリティ.
                                                              (line  27)
* directory-list2:                       ディレクトリユーティリティ.
                                                              (line  59)
* disasm:                                デバッグ補助.        (line  14)
* display:                               出力.                (line  11)
* do:                                    繰り返し.            (line   8)
* do-ec:                                 Eager comprehensions.
                                                              (line  77)
* dolist:                                繰り返し.            (line  15)
* dotimes:                               繰り返し.            (line  14)
* dotted-list?:                          SRFI-1 リストの述語. (line  13)
* drop:                                  SRFI-1 リスト選択子. (line  23)
* drop*:                                 その他のリストライブラリ.
                                                              (line  33)
* drop-right:                            SRFI-1 リスト選択子. (line  45)
* drop-right!:                           SRFI-1 リスト選択子. (line  65)
* drop-right*:                           その他のリストライブラリ.
                                                              (line  45)
* drop-while:                            リストの探索.        (line  20)
* dynamic-load:                          ダイナミックライブラリのロード.
                                                              (line   7)
* dynamic-wind:                          継続.                (line  45)
* eighth:                                SRFI-1 リスト選択子. (line  14)
* end-of-char-set?:                      文字セットのイテレーション.
                                                              (line  16)
* enqueue!:                              キュー.              (line  31)
* enqueue-unique!:                       キュー.              (line  41)
* eof-object?:                           データの読み込み.    (line  95)
* eq-hash:                               ハッシュテーブル.    (line  77)
* eq?:                                   等価.                (line  10)
* equal?:                                等価.                (line  45)
* eqv-hash:                              ハッシュテーブル.    (line  78)
* eqv?:                                  等価.                (line  28)
* error:                                 例外の通知.          (line  15)
* errorf:                                例外の通知.          (line  31)
* eval:                                  eval と repl.        (line   7)
* even?:                                 数値に関する述語.    (line  51)
* every:                                 リストの探索.        (line  37)
* every$:                                リストの探索.        (line  49)
* every-pred:                            コンビネータ.        (line  74)
* every?-ec:                             Eager comprehensions.
                                                              (line 103)
* exact->inexact:                        数値の変換.          (line  50)
* exact?:                                数値に関する述語.    (line  25)
* exit:                                  プログラムの終了.    (line   7)
* exp:                                   数値の演算.          (line 112)
* expand-path:                           パスネームユーティリティ.
                                                              (line  17)
* export:                                モジュールの使用.    (line   7)
* export-all:                            モジュールの使用.    (line  11)
* expt:                                  数値の演算.          (line 137)
* extend:                                モジュールの継承.    (line  19)
* extract-condition:                     コンディション.      (line 252)
* f32vector:                             ユニフォームベクタの基本操作.
                                                              (line  19)
* f32vector->list:                       ユニフォームベクタの変換.
                                                              (line   7)
* f32vector->vector:                     ユニフォームベクタの変換.
                                                              (line  19)
* f32vector-add:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* f32vector-add!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* f32vector-clamp:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* f32vector-clamp!:                      ユニフォームベクタの数値演算.
                                                              (line  96)
* f32vector-copy:                        ユニフォームベクタの基本操作.
                                                              (line  75)
* f32vector-copy!:                       ユニフォームベクタの基本操作.
                                                              (line  84)
* f32vector-div:                         ユニフォームベクタの数値演算.
                                                              (line  37)
* f32vector-div!:                        ユニフォームベクタの数値演算.
                                                              (line  37)
* f32vector-dot:                         ユニフォームベクタの数値演算.
                                                              (line  60)
* f32vector-length:                      ユニフォームベクタの基本操作.
                                                              (line  32)
* f32vector-mul:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* f32vector-mul!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* f32vector-range-check:                 ユニフォームベクタの数値演算.
                                                              (line  64)
* f32vector-ref:                         ユニフォームベクタの基本操作.
                                                              (line  43)
* f32vector-set!:                        ユニフォームベクタの基本操作.
                                                              (line  57)
* f32vector-sub:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* f32vector-sub!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* f32vector?:                            ユニフォームベクタの基本操作.
                                                              (line  16)
* f64vector:                             ユニフォームベクタの基本操作.
                                                              (line  19)
* f64vector->list:                       ユニフォームベクタの変換.
                                                              (line   7)
* f64vector->vector:                     ユニフォームベクタの変換.
                                                              (line  19)
* f64vector-add:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* f64vector-add!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* f64vector-clamp:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* f64vector-clamp!:                      ユニフォームベクタの数値演算.
                                                              (line  96)
* f64vector-copy:                        ユニフォームベクタの基本操作.
                                                              (line  75)
* f64vector-copy!:                       ユニフォームベクタの基本操作.
                                                              (line  84)
* f64vector-div:                         ユニフォームベクタの数値演算.
                                                              (line  37)
* f64vector-div!:                        ユニフォームベクタの数値演算.
                                                              (line  37)
* f64vector-dot:                         ユニフォームベクタの数値演算.
                                                              (line  60)
* f64vector-length:                      ユニフォームベクタの基本操作.
                                                              (line  32)
* f64vector-mul:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* f64vector-mul!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* f64vector-range-check:                 ユニフォームベクタの数値演算.
                                                              (line  64)
* f64vector-ref:                         ユニフォームベクタの基本操作.
                                                              (line  43)
* f64vector-set!:                        ユニフォームベクタの基本操作.
                                                              (line  57)
* f64vector-sub:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* f64vector-sub!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* f64vector?:                            ユニフォームベクタの基本操作.
                                                              (line  16)
* feature-cond:                          機能ベースプログラム設定言語.
                                                              (line  55)
* fifth:                                 SRFI-1 リスト選択子. (line  11)
* file->list:                            ファイル操作.        (line  74)
* file->sexp-list:                       ファイル操作.        (line  76)
* file->string:                          ファイル操作.        (line  73)
* file->string-list:                     ファイル操作.        (line  75)
* file-atime:                            ファイル属性ユーティリティ.
                                                              (line  17)
* file-atime<=?:                         ファイル属性ユーティリティ.
                                                              (line  89)
* file-atime<?:                          ファイル属性ユーティリティ.
                                                              (line  89)
* file-atime=?:                          ファイル属性ユーティリティ.
                                                              (line  89)
* file-atime>=?:                         ファイル属性ユーティリティ.
                                                              (line  89)
* file-atime>?:                          ファイル属性ユーティリティ.
                                                              (line  89)
* file-ctime:                            ファイル属性ユーティリティ.
                                                              (line  19)
* file-ctime<=?:                         ファイル属性ユーティリティ.
                                                              (line  89)
* file-ctime<?:                          ファイル属性ユーティリティ.
                                                              (line  89)
* file-ctime=?:                          ファイル属性ユーティリティ.
                                                              (line  88)
* file-ctime>=?:                         ファイル属性ユーティリティ.
                                                              (line  89)
* file-ctime>?:                          ファイル属性ユーティリティ.
                                                              (line  89)
* file-dev:                              ファイル属性ユーティリティ.
                                                              (line  11)
* file-eq?:                              ファイル属性ユーティリティ.
                                                              (line  44)
* file-equal?:                           ファイル属性ユーティリティ.
                                                              (line  46)
* file-eqv?:                             ファイル属性ユーティリティ.
                                                              (line  45)
* file-exists?:                          ファイルの状態.      (line  10)
* file-filter:                           ファイルのフィルタ.  (line  25)
* file-gid:                              ファイル属性ユーティリティ.
                                                              (line  15)
* file-ino:                              ファイル属性ユーティリティ.
                                                              (line  10)
* file-is-directory?:                    ファイルの状態.      (line  12)
* file-is-executable?:                   ファイル属性ユーティリティ.
                                                              (line  35)
* file-is-readable?:                     ファイル属性ユーティリティ.
                                                              (line  33)
* file-is-regular?:                      ファイルの状態.      (line  11)
* file-is-symlink?:                      ファイル属性ユーティリティ.
                                                              (line  39)
* file-is-writable?:                     ファイル属性ユーティリティ.
                                                              (line  34)
* file-mode:                             ファイル属性ユーティリティ.
                                                              (line   9)
* file-mtime:                            ファイル属性ユーティリティ.
                                                              (line  18)
* file-mtime<=?:                         ファイル属性ユーティリティ.
                                                              (line  65)
* file-mtime<?:                          ファイル属性ユーティリティ.
                                                              (line  64)
* file-mtime=?:                          ファイル属性ユーティリティ.
                                                              (line  63)
* file-mtime>=?:                         ファイル属性ユーティリティ.
                                                              (line  67)
* file-mtime>?:                          ファイル属性ユーティリティ.
                                                              (line  66)
* file-nlink:                            ファイル属性ユーティリティ.
                                                              (line  13)
* file-perm:                             ファイル属性ユーティリティ.
                                                              (line   8)
* file-rdev:                             ファイル属性ユーティリティ.
                                                              (line  12)
* file-size:                             ファイル属性ユーティリティ.
                                                              (line  16)
* file-type:                             ファイル属性ユーティリティ.
                                                              (line   7)
* file-uid:                              ファイル属性ユーティリティ.
                                                              (line  14)
* files:                                 機能ベースプログラム設定言語.
                                                              (line  48)
* filter <1>:                            リストのフィルタおよび分割.
                                                              (line   7)
* filter:                                コレクションからの選択と探索.
                                                              (line  19)
* filter!:                               リストのフィルタおよび分割.
                                                              (line   8)
* filter$:                               リストのフィルタおよび分割.
                                                              (line  34)
* filter-map:                            リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line 105)
* filter-to:                             コレクションからの選択と探索.
                                                              (line  28)
* find <1>:                              コレクションからの選択と探索.
                                                              (line   7)
* find:                                  リストの探索.        (line   7)
* find$:                                 リストの探索.        (line  46)
* find-file-in-paths:                    パスネームユーティリティ.
                                                              (line  81)
* find-in-queue:                         キュー.              (line  81)
* find-index:                            シーケンス上のマップ.
                                                              (line  44)
* find-module:                           モジュールイントロスペクション.
                                                              (line  20)
* find-string-from-port?:                入力ストリームのパージング.
                                                              (line  26)
* find-tail:                             リストの探索.        (line  11)
* find-tail$:                            リストの探索.        (line  47)
* find-with-index:                       シーケンス上のマップ.
                                                              (line  33)
* first:                                 SRFI-1 リスト選択子. (line   7)
* first-ec:                              Eager comprehensions.
                                                              (line 106)
* fixnum?:                               数値に関する述語.    (line  59)
* floor:                                 数値の演算.          (line  88)
* fluid-let:                             変数束縛.            (line  39)
* flush:                                 出力.                (line  65)
* flush-all-ports:                       出力.                (line  66)
* fmod:                                  数値の変換.          (line  31)
* fold <1>:                              リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line   7)
* fold:                                  コレクションに対するマッピング.
                                                              (line  11)
* fold$ <1>:                             リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line 112)
* fold$:                                 コレクションに対するマッピング.
                                                              (line 132)
* fold-ec:                               Eager comprehensions.
                                                              (line 110)
* fold-right:                            リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  24)
* fold-right$:                           リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line 113)
* fold-with-index:                       シーケンス上のマップ.
                                                              (line  13)
* fold2:                                 コレクションに対するマッピング.
                                                              (line  46)
* fold3:                                 コレクションに対するマッピング.
                                                              (line  47)
* fold3-ec:                              Eager comprehensions.
                                                              (line 111)
* for-each <1>:                          コレクションに対するマッピング.
                                                              (line 120)
* for-each:                              マッピング.          (line  24)
* for-each$ <1>:                         コンビネータ.        (line  25)
* for-each$:                             コレクションに対するマッピング.
                                                              (line 135)
* for-each-with-index:                   シーケンス上のマップ.
                                                              (line  23)
* force:                                 遅延評価.            (line  15)
* format <1>:                            出力.                (line  83)
* format:                                地域化.              (line  91)
* fourth:                                SRFI-1 リスト選択子. (line  10)
* frexp:                                 数値の変換.          (line  33)
* gauche-architecture:                   環境の問い合わせ.    (line  17)
* gauche-architecture-directory:         環境の問い合わせ.    (line  19)
* gauche-character-encoding:             文字.                (line 151)
* gauche-config:                         コンフィグレーション情報.
                                                              (line  14)
* gauche-library-directory:              環境の問い合わせ.    (line  18)
* gauche-site-architecture-directory:    環境の問い合わせ.    (line  21)
* gauche-site-library-directory:         環境の問い合わせ.    (line  20)
* gauche-thread-type:                    スレッド.            (line  19)
* gauche-version:                        環境の問い合わせ.    (line  16)
* gcd:                                   数値の演算.          (line  76)
* gdbm-close:                            GDBMインタフェース.  (line  43)
* gdbm-closed?:                          GDBMインタフェース.  (line  45)
* gdbm-delete:                           GDBMインタフェース.  (line  55)
* gdbm-errno:                            GDBMインタフェース.  (line  82)
* gdbm-exists:                           GDBMインタフェース.  (line  65)
* gdbm-fetch:                            GDBMインタフェース.  (line  53)
* gdbm-firstkey:                         GDBMインタフェース.  (line  57)
* gdbm-nextkey:                          GDBMインタフェース.  (line  59)
* gdbm-open:                             GDBMインタフェース.  (line  28)
* gdbm-reorganize:                       GDBMインタフェース.  (line  61)
* gdbm-setopt:                           GDBMインタフェース.  (line  69)
* gdbm-store:                            GDBMインタフェース.  (line  47)
* gdbm-strerror:                         GDBMインタフェース.  (line  67)
* gdbm-sync:                             GDBMインタフェース.  (line  63)
* gdbm-version:                          GDBMインタフェース.  (line  80)
* gensym:                                シンボル.            (line  42)
* get-keyword:                           キーワード.          (line  29)
* get-keyword*:                          キーワード.          (line  61)
* get-optional:                          省略可能引数のパージング.
                                                              (line  66)
* get-output-string:                     文字列ポート.        (line  41)
* get-remaining-input-string:            文字列ポート.        (line  20)
* get-signal-handler:                    シグナルの処理.      (line  71)
* get-signal-handlers:                   シグナルの処理.      (line  74)
* getter-with-setter:                    代入.                (line  67)
* gettext:                               地域化メッセージ.    (line  79)
* group-collection:                      コレクションからの選択と探索.
                                                              (line  73)
* group-sequence:                        シーケンスに対する選択と探索.
                                                              (line  10)
* guard:                                 例外の処理.          (line  10)
* has-setter?:                           代入.                (line  64)
* hash:                                  ハッシュテーブル.    (line  36)
* hash-table:                            ハッシュテーブル.    (line 100)
* hash-table->alist:                     その他のリストライブラリ.
                                                              (line 103)
* hash-table-delete!:                    ハッシュテーブル.    (line 127)
* hash-table-exists?:                    ハッシュテーブル.    (line 124)
* hash-table-fold:                       ハッシュテーブル.    (line 178)
* hash-table-for-each:                   ハッシュテーブル.    (line 173)
* hash-table-get:                        ハッシュテーブル.    (line 112)
* hash-table-keys:                       ハッシュテーブル.    (line 185)
* hash-table-map:                        ハッシュテーブル.    (line 174)
* hash-table-num-entries:                ハッシュテーブル.    (line  97)
* hash-table-pop!:                       ハッシュテーブル.    (line 145)
* hash-table-push!:                      ハッシュテーブル.    (line 136)
* hash-table-put!:                       ハッシュテーブル.    (line 117)
* hash-table-type:                       ハッシュテーブル.    (line  93)
* hash-table-update!:                    ハッシュテーブル.    (line 153)
* hash-table-values:                     ハッシュテーブル.    (line 186)
* hash-table?:                           ハッシュテーブル.    (line  90)
* hmac-digest:                           HMAC鍵付きハッシング.
                                                              (line  41)
* hmac-digest-string:                    HMAC鍵付きハッシング.
                                                              (line  46)
* hmac-final!:                           HMAC鍵付きハッシング.
                                                              (line  33)
* hmac-update!:                          HMAC鍵付きハッシング.
                                                              (line  29)
* home-directory:                        ディレクトリユーティリティ.
                                                              (line  14)
* hook->list:                            フック.              (line  59)
* hook-empty?:                           フック.              (line  40)
* hook?:                                 フック.              (line  37)
* html-doctype:                          シンプルなHTMLドキュメントの構築.
                                                              (line  29)
* html-escape:                           シンプルなHTMLドキュメントの構築.
                                                              (line  22)
* html-escape-string:                    シンプルなHTMLドキュメントの構築.
                                                              (line  23)
* html:a:                                シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:abbr:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:acronym:                          シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:address:                          シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:area:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:b:                                シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:base:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:bdo:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:big:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:blockquote:                       シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:body:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:br:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:button:                           シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:caption:                          シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:cite:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:code:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:col:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:colgroup:                         シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:dd:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:del:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:dfn:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:div:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:dl:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:dt:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:em:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:fieldset:                         シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:form:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:frame:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:frameset:                         シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:h1:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:h2:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:h3:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:h4:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:h5:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:h6:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:head:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:hr:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:html:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:i:                                シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:iframe:                           シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:img:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:input:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:ins:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:kbd:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:label:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:legend:                           シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:li:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:link:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:map:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:meta:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:noframes:                         シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:noscript:                         シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:object:                           シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:ol:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:optgroup:                         シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:option:                           シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:p:                                シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:param:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:pre:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:q:                                シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:samp:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:script:                           シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:select:                           シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:small:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:span:                             シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:strong:                           シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:style:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:sub:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:sup:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:table:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:tbody:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:td:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:textarea:                         シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:tfoot:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:th:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:thead:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:title:                            シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:tr:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:tt:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:ul:                               シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* html:var:                              シンプルなHTMLドキュメントの構築.
                                                              (line  54)
* http-get:                              HTTP.                (line  19)
* http-head:                             HTTP.                (line  20)
* http-post:                             HTTP.                (line  22)
* identifier->symbol:                    Identifier.          (line  11)
* identifier?:                           Identifier.          (line   9)
* identity-array:                        配列.                (line 208)
* if <1>:                                Eager comprehensions.
                                                              (line 120)
* if:                                    条件式.              (line   8)
* if-car-sxpath:                         SXPathクエリ言語.    (line  45)
* if-sxpath:                             SXPathクエリ言語.    (line  41)
* imag-part:                             数値の変換.          (line  13)
* import:                                モジュールの使用.    (line  14)
* inc!:                                  代入.                (line 125)
* inexact->exact:                        数値の変換.          (line  51)
* inexact?:                              数値に関する述語.    (line  26)
* info:                                  インタラクティブセッション.
                                                              (line  43)
* initialize:                            インスタンスの作成.  (line  32)
* input-port?:                           ポート共通の操作.    (line   8)
* instance-of:                           シングルトン.        (line  26)
* integer->char:                         文字.                (line  98)
* integer->digit:                        文字.                (line 143)
* integer-length:                        ビット演算.          (line  52)
* integer-range->char-set:               文字セットの構築子.  (line  34)
* integer-range->char-set!:              文字セットの構築子.  (line  35)
* integer?:                              数値に関する述語.    (line  11)
* interaction-environment:               eval と repl.        (line  15)
* intersperse:                           その他のリストライブラリ.
                                                              (line  66)
* iota:                                  SRFI-1 リスト構築子. (line  25)
* is-a?:                                 一般的な問い合わせ.  (line  14)
* isomorphic?:                           同型判定.            (line  10)
* join-timeout-exception?:               スレッド例外.        (line  46)
* julian-day->date:                      日付.                (line  73)
* julian-day->time-monotonic:            日付.                (line  74)
* julian-day->time-tai:                  日付.                (line  75)
* julian-day->time-utc:                  日付.                (line  76)
* keyword->string:                       キーワード.          (line  26)
* keyword?:                              キーワード.          (line  20)
* kmp-step:                              低レベルな文字列に関する手続き.
                                                              (line  22)
* lambda:                                手続きを作る.        (line   7)
* last:                                  SRFI-1 リスト選択子. (line  82)
* last-ec:                               Eager comprehensions.
                                                              (line 107)
* last-pair:                             リストへのアクセスと変更.
                                                              (line  52)
* lazy-size-of:                          コレクションに対する様々な操作.
                                                              (line  13)
* lcm:                                   数値の演算.          (line  77)
* lcs:                                   最長共通サブシーケンス.
                                                              (line  15)
* lcs-edit-list:                         最長共通サブシーケンス.
                                                              (line  66)
* lcs-fold:                              最長共通サブシーケンス.
                                                              (line  47)
* lcs-with-positions:                    最長共通サブシーケンス.
                                                              (line  23)
* ldexp:                                 数値の変換.          (line  34)
* length:                                リストへのアクセスと変更.
                                                              (line  32)
* length+:                               種々のリスト処理ルーチン.
                                                              (line   7)
* let <1>:                               変数束縛.            (line   7)
* let <2>:                               繰り返し.            (line  11)
* let:                                   シグネチャとrest引数に互換性のあるlet形式.
                                                              (line  10)
* let*:                                  変数束縛.            (line   8)
* let*-values:                           Let-values.          (line  42)
* let-args:                              コマンドライン引数の解析.
                                                              (line 166)
* let-keywords*:                         省略可能引数のパージング.
                                                              (line  80)
* let-optionals*:                        省略可能引数のパージング.
                                                              (line  12)
* let-string-start+end:                  低レベルな文字列に関する手続き.
                                                              (line  12)
* let-syntax:                            健全なマクロ.        (line  16)
* let-values:                            Let-values.          (line  13)
* let/cc:                                継続.                (line  41)
* let1:                                  変数束縛.            (line  34)
* letrec:                                変数束縛.            (line   9)
* letrec-syntax:                         健全なマクロ.        (line  17)
* library-exists?:                       ライブラリの操作.    (line  91)
* library-fold:                          ライブラリの操作.    (line  16)
* library-for-each:                      ライブラリの操作.    (line  74)
* library-has-module?:                   ライブラリの操作.    (line 103)
* library-map:                           ライブラリの操作.    (line  72)
* list:                                  リストの作成.        (line  22)
* list*:                                 リストの作成.        (line  27)
* list->char-set:                        文字セットの構築子.  (line   7)
* list->char-set!:                       文字セットの構築子.  (line   8)
* list->f32vector:                       ユニフォームベクタの変換.
                                                              (line  32)
* list->f64vector:                       ユニフォームベクタの変換.
                                                              (line  32)
* list->queue:                           キュー.              (line  66)
* list->s16vector:                       ユニフォームベクタの変換.
                                                              (line  32)
* list->s32vector:                       ユニフォームベクタの変換.
                                                              (line  32)
* list->s64vector:                       ユニフォームベクタの変換.
                                                              (line  32)
* list->s8vector:                        ユニフォームベクタの変換.
                                                              (line  32)
* list->string:                          文字列を扱うその他の手続き.
                                                              (line  14)
* list->u16vector:                       ユニフォームベクタの変換.
                                                              (line  32)
* list->u32vector:                       ユニフォームベクタの変換.
                                                              (line  32)
* list->u64vector:                       ユニフォームベクタの変換.
                                                              (line  32)
* list->u8vector:                        ユニフォームベクタの変換.
                                                              (line  32)
* list->vector:                          ベクター.            (line  55)
* list-copy:                             リストの作成.        (line  33)
* list-ec:                               Eager comprehensions.
                                                              (line  80)
* list-index:                            リストの探索.        (line  42)
* list-ref:                              リストへのアクセスと変更.
                                                              (line  44)
* list-tabulate:                         SRFI-1 リスト構築子. (line  16)
* list-tail:                             リストへのアクセスと変更.
                                                              (line  40)
* list=:                                 SRFI-1 リストの述語. (line  29)
* list?:                                 リストに関する述語.  (line  13)
* listener-read-handler:                 リスナー.            (line  83)
* listener-show-prompt:                  リスナー.            (line 109)
* load:                                  Schemeファイルのロード.
                                                              (line   8)
* load-bundle!:                          地域化.              (line  74)
* load-from-port:                        Schemeファイルのロード.
                                                              (line  70)
* localized-template:                    地域化.              (line  83)
* log:                                   数値の演算.          (line 113)
* log-format:                            ユーザレベルのロギング.
                                                              (line 119)
* log-open:                              ユーザレベルのロギング.
                                                              (line 109)
* logand:                                ビット演算.          (line  24)
* logbit?:                               ビット演算.          (line  36)
* logcount:                              ビット演算.          (line  50)
* logior:                                ビット演算.          (line  25)
* lognot:                                ビット演算.          (line  30)
* logtest:                               ビット演算.          (line  33)
* logxor:                                ビット演算.          (line  26)
* lset-adjoin:                           集合としてのリスト.  (line  28)
* lset-diff+intersection:                集合としてのリスト.  (line  50)
* lset-diff+intersection!:               集合としてのリスト.  (line  57)
* lset-difference:                       集合としてのリスト.  (line  40)
* lset-difference!:                      集合としてのリスト.  (line  55)
* lset-intersection:                     集合としてのリスト.  (line  37)
* lset-intersection!:                    集合としてのリスト.  (line  54)
* lset-union:                            集合としてのリスト.  (line  34)
* lset-union!:                           集合としてのリスト.  (line  53)
* lset-xor:                              集合としてのリスト.  (line  45)
* lset-xor!:                             集合としてのリスト.  (line  56)
* lset<=:                                集合としてのリスト.  (line  17)
* lset=:                                 集合としてのリスト.  (line  22)
* macroexpand:                           マクロの展開.        (line   7)
* macroexpand-1:                         マクロの展開.        (line   8)
* magnitude:                             数値の変換.          (line  14)
* make <1>:                              クラスのインスタンシエーション.
                                                              (line 145)
* make <2>:                              インスタンスの作成.  (line  11)
* make:                                  メソッドのインスタンシエーション.
                                                              (line   7)
* make-array:                            配列.                (line  86)
* make-byte-string:                      文字列の作成.        (line  24)
* make-client-socket:                    高レベルネットワーク手続き.
                                                              (line  20)
* make-compound-condition:               コンディション.      (line 242)
* make-condition:                        コンディション.      (line 213)
* make-condition-type:                   コンディション.      (line 210)
* make-condition-variable:               同期プリミティブ.    (line 188)
* make-csv-reader:                       CSVテーブル.         (line  28)
* make-csv-writer:                       CSVテーブル.         (line  34)
* make-date:                             日付.                (line  40)
* make-directory*:                       ディレクトリユーティリティ.
                                                              (line 110)
* make-empty-attlist:                    SSAXデータタイプ.    (line 131)
* make-f32array:                         配列.                (line 100)
* make-f32vector:                        ユニフォームベクタの基本操作.
                                                              (line  25)
* make-f64array:                         配列.                (line 101)
* make-f64vector:                        ユニフォームベクタの基本操作.
                                                              (line  25)
* make-gettext:                          地域化メッセージ.    (line 107)
* make-hash-table:                       ハッシュテーブル.    (line  10)
* make-hook:                             フック.              (line  33)
* make-keyword:                          キーワード.          (line  23)
* make-kmp-restart-vector:               低レベルな文字列に関する手続き.
                                                              (line  19)
* make-list:                             リストの作成.        (line  16)
* make-module:                           モジュールイントロスペクション.
                                                              (line  24)
* make-mutex:                            同期プリミティブ.    (line  38)
* make-option-parser:                    コマンドライン引数の解析.
                                                              (line 222)
* make-packer:                           バイナリデータのパック.
                                                              (line 183)
* make-parameter:                        パラメータ.          (line  39)
* make-polar:                            数値の変換.          (line   8)
* make-queue:                            キュー.              (line  18)
* make-random-source:                    ランダムビットのソース.
                                                              (line  29)
* make-record-type:                      SLIB-互換のレコード型.
                                                              (line  15)
* make-rectangular:                      数値の変換.          (line   7)
* make-s16array:                         配列.                (line  97)
* make-s16vector:                        ユニフォームベクタの基本操作.
                                                              (line  25)
* make-s32array:                         配列.                (line  97)
* make-s32vector:                        ユニフォームベクタの基本操作.
                                                              (line  25)
* make-s64array:                         配列.                (line  97)
* make-s64vector:                        ユニフォームベクタの基本操作.
                                                              (line  25)
* make-s8array:                          配列.                (line  97)
* make-s8vector:                         ユニフォームベクタの基本操作.
                                                              (line  25)
* make-server-socket:                    高レベルネットワーク手続き.
                                                              (line  56)
* make-server-sockets:                   高レベルネットワーク手続き.
                                                              (line  95)
* make-sockaddrs:                        ソケットアドレス.    (line  68)
* make-socket:                           低レベルソケットインタフェース.
                                                              (line  11)
* make-string:                           文字列の作成.        (line   7)
* make-string-pointer:                   文字列ポインタ.      (line  17)
* make-thread:                           スレッド手続き.      (line  52)
* make-time:                             時間に関する手続き.  (line   7)
* make-u16array:                         配列.                (line  97)
* make-u16vector:                        ユニフォームベクタの基本操作.
                                                              (line  25)
* make-u32array:                         配列.                (line  97)
* make-u32vector:                        ユニフォームベクタの基本操作.
                                                              (line  25)
* make-u64array:                         配列.                (line  97)
* make-u64vector:                        ユニフォームベクタの基本操作.
                                                              (line  25)
* make-u8array:                          配列.                (line  96)
* make-u8vector:                         ユニフォームベクタの基本操作.
                                                              (line  25)
* make-vector:                           ベクター.            (line  23)
* make-weak-vector:                      Weak ポインタ.       (line  39)
* make-xml-token:                        SSAXデータタイプ.    (line 139)
* map <1>:                               マッピング.          (line   7)
* map:                                   コレクションに対するマッピング.
                                                              (line  61)
* map!:                                  リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  90)
* map$ <1>:                              コンビネータ.        (line  24)
* map$:                                  コレクションに対するマッピング.
                                                              (line 134)
* map-accum:                             コレクションに対するマッピング.
                                                              (line 101)
* map-in-order:                          リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  95)
* map-to:                                コレクションに対するマッピング.
                                                              (line  86)
* map-to-with-index:                     シーケンス上のマップ.
                                                              (line  22)
* map-union:                             SXPathの基本的なコンバータとアプリケータ.
                                                              (line 133)
* map-with-index:                        シーケンス上のマップ.
                                                              (line  21)
* match:                                 パターンマッチング.  (line  30)
* match-define:                          パターンマッチング.  (line  87)
* match-lambda:                          パターンマッチング.  (line  52)
* match-lambda*:                         パターンマッチング.  (line  57)
* match-let:                             パターンマッチング.  (line  62)
* match-let*:                            パターンマッチング.  (line  64)
* match-let1:                            パターンマッチング.  (line  79)
* match-letrec:                          パターンマッチング.  (line  65)
* max:                                   数値の比較.          (line  23)
* max-ec:                                Eager comprehensions.
                                                              (line  99)
* md5-digest:                            MD5メッセージダイジェスト.
                                                              (line  26)
* md5-digest-string:                     MD5メッセージダイジェスト.
                                                              (line  30)
* member:                                他のリスト手続き.    (line  29)
* member$:                               リストの探索.        (line  45)
* memq:                                  他のリスト手続き.    (line  27)
* memv:                                  他のリスト手続き.    (line  28)
* method-more-specific?:                 メソッド適用のカスタマイズ.
                                                              (line  11)
* mime-body->file:                       MIMEメッセージ処理.  (line 168)
* mime-body->string:                     MIMEメッセージ処理.  (line 167)
* mime-decode-word:                      MIMEメッセージ処理.  (line  45)
* mime-parse-content-type:               MIMEメッセージ処理.  (line  33)
* mime-parse-message:                    MIMEメッセージ処理.  (line  59)
* mime-parse-version:                    MIMEメッセージ処理.  (line  20)
* mime-retrieve-body:                    MIMEメッセージ処理.  (line 144)
* min:                                   数値の比較.          (line  24)
* min&max:                               数値の比較.          (line  27)
* min-ec:                                Eager comprehensions.
                                                              (line  98)
* modf:                                  数値の変換.          (line  32)
* modified-julian-day->date:             日付.                (line  79)
* modified-julian-day->time-monotonic:   日付.                (line  80)
* modified-julian-day->time-tai:         日付.                (line  81)
* modified-julian-day->time-utc:         日付.                (line  82)
* modifier:                              基本的なシーケンスのアクセサ.
                                                              (line  37)
* module-exports:                        モジュールイントロスペクション.
                                                              (line  58)
* module-imports:                        モジュールイントロスペクション.
                                                              (line  57)
* module-name:                           モジュールイントロスペクション.
                                                              (line  56)
* module-name->path:                     モジュールイントロスペクション.
                                                              (line  82)
* module-parents:                        モジュールイントロスペクション.
                                                              (line  70)
* module-precedence-list:                モジュールイントロスペクション.
                                                              (line  71)
* module-reload-rules:                   モジュールの再ロード.
                                                              (line  58)
* module-table:                          モジュールイントロスペクション.
                                                              (line  59)
* module?:                               モジュールイントロスペクション.
                                                              (line  17)
* modulo:                                数値の演算.          (line  43)
* move-file:                             ファイル操作.        (line  46)
* mt-random-fill-f32vector!:             Mersenne Twister乱数発生器.
                                                              (line  57)
* mt-random-fill-f64vector!:             Mersenne Twister乱数発生器.
                                                              (line  58)
* mt-random-fill-u32vector!:             Mersenne Twister乱数発生器.
                                                              (line  56)
* mt-random-get-state:                   Mersenne Twister乱数発生器.
                                                              (line  37)
* mt-random-integer:                     Mersenne Twister乱数発生器.
                                                              (line  52)
* mt-random-real:                        Mersenne Twister乱数発生器.
                                                              (line  45)
* mt-random-real0:                       Mersenne Twister乱数発生器.
                                                              (line  46)
* mt-random-set-seed!:                   Mersenne Twister乱数発生器.
                                                              (line  30)
* mt-random-set-state!:                  Mersenne Twister乱数発生器.
                                                              (line  38)
* mutex-lock!:                           同期プリミティブ.    (line  66)
* mutex-name:                            同期プリミティブ.    (line  43)
* mutex-specific:                        同期プリミティブ.    (line  46)
* mutex-specific-set!:                   同期プリミティブ.    (line  47)
* mutex-state:                           同期プリミティブ.    (line  50)
* mutex-unlock!:                         同期プリミティブ.    (line 112)
* mutex?:                                同期プリミティブ.    (line  34)
* ndbm-clear-error:                      NDBMインタフェース.  (line  39)
* ndbm-close:                            NDBMインタフェース.  (line  23)
* ndbm-closed?:                          NDBMインタフェース.  (line  25)
* ndbm-delete:                           NDBMインタフェース.  (line  31)
* ndbm-error:                            NDBMインタフェース.  (line  37)
* ndbm-fetch:                            NDBMインタフェース.  (line  29)
* ndbm-firstkey:                         NDBMインタフェース.  (line  33)
* ndbm-nextkey:                          NDBMインタフェース.  (line  35)
* ndbm-open:                             NDBMインタフェース.  (line  21)
* ndbm-store:                            NDBMインタフェース.  (line  27)
* negative?:                             数値に関する述語.    (line  46)
* nested:                                Eager comprehensions.
                                                              (line 128)
* newline:                               出力.                (line  62)
* next-method:                           ジェネリックファンクションとメソッド.
                                                              (line  96)
* next-token:                            入力ストリームのパージング.
                                                              (line  74)
* next-token-of:                         入力ストリームのパージング.
                                                              (line  83)
* ngettext:                              地域化メッセージ.    (line  83)
* ninth:                                 SRFI-1 リスト選択子. (line  15)
* node-closure:                          SXPathの基本的なコンバータとアプリケータ.
                                                              (line 211)
* node-eq?:                              SXPathの基本的なコンバータとアプリケータ.
                                                              (line  77)
* node-equal?:                           SXPathの基本的なコンバータとアプリケータ.
                                                              (line  78)
* node-join:                             SXPathの基本的なコンバータとアプリケータ.
                                                              (line 186)
* node-or:                               SXPathの基本的なコンバータとアプリケータ.
                                                              (line 203)
* node-pos:                              SXPathの基本的なコンバータとアプリケータ.
                                                              (line  83)
* node-reduce:                           SXPathの基本的なコンバータとアプリケータ.
                                                              (line 193)
* node-reverse:                          SXPathの基本的なコンバータとアプリケータ.
                                                              (line 140)
* node-self:                             SXPathの基本的なコンバータとアプリケータ.
                                                              (line 177)
* node-trace:                            SXPathの基本的なコンバータとアプリケータ.
                                                              (line 148)
* nodeset?:                              SXPathの基本的なコンバータとアプリケータ.
                                                              (line  14)
* not <1>:                               論理値.              (line  10)
* not:                                   Eager comprehensions.
                                                              (line 122)
* not-pair?:                             SRFI-1 リストの述語. (line  22)
* ntype-names??:                         SXPathの基本的なコンバータとアプリケータ.
                                                              (line  24)
* ntype-namespace-id??:                  SXPathの基本的なコンバータとアプリケータ.
                                                              (line  65)
* ntype??:                               SXPathの基本的なコンバータとアプリケータ.
                                                              (line  30)
* null-environment:                      eval と repl.        (line  13)
* null-list?:                            SRFI-1 リストの述語. (line  18)
* null?:                                 リストに関する述語.  (line  10)
* number->string:                        数値の変換.          (line  63)
* number?:                               数値に関する述語.    (line   7)
* numerator:                             数値の演算.          (line  80)
* object-apply:                          適用可能なオブジェクト.
                                                              (line  10)
* object-compare:                        比較とソート.        (line   9)
* object-equal?:                         等価.                (line  62)
* object-hash:                           ハッシュテーブル.    (line  53)
* object-isomorphic?:                    同型判定.            (line  27)
* odbm-close:                            オリジナルのDBMインタフェース.
                                                              (line  28)
* odbm-delete:                           オリジナルのDBMインタフェース.
                                                              (line  34)
* odbm-fetch:                            オリジナルのDBMインタフェース.
                                                              (line  32)
* odbm-firstkey:                         オリジナルのDBMインタフェース.
                                                              (line  36)
* odbm-init:                             オリジナルのDBMインタフェース.
                                                              (line  26)
* odbm-nextkey:                          オリジナルのDBMインタフェース.
                                                              (line  38)
* odbm-store:                            オリジナルのDBMインタフェース.
                                                              (line  30)
* odd?:                                  数値に関する述語.    (line  50)
* open-coding-aware-port:                コーディング認識ポート.
                                                              (line  15)
* open-input-conversion-port:            変換ポート.          (line   8)
* open-input-fd-port:                    ファイルポート.      (line 172)
* open-input-file <1>:                   拡張されたポート手続き.
                                                              (line   8)
* open-input-file:                       ファイルポート.      (line   8)
* open-input-process-port:               Process ports.       (line   8)
* open-input-string:                     文字列ポート.        (line   9)
* open-input-uvector:                    仮想ポート.          (line 304)
* open-output-conversion-port:           変換ポート.          (line  48)
* open-output-fd-port:                   ファイルポート.      (line 173)
* open-output-file <1>:                  拡張されたポート手続き.
                                                              (line  14)
* open-output-file:                      ファイルポート.      (line  10)
* open-output-process-port:              Process ports.       (line  80)
* open-output-string:                    文字列ポート.        (line  33)
* open-output-uvector:                   仮想ポート.          (line 309)
* option:                                args-fold プログラム引数処理.
                                                              (line  73)
* option-names:                          args-fold プログラム引数処理.
                                                              (line 103)
* option-optional-arg?:                  args-fold プログラム引数処理.
                                                              (line 105)
* option-processor:                      args-fold プログラム引数処理.
                                                              (line 106)
* option-required-arg?:                  args-fold プログラム引数処理.
                                                              (line 104)
* option?:                               args-fold プログラム引数処理.
                                                              (line  99)
* or <1>:                                条件式.              (line  86)
* or:                                    Eager comprehensions.
                                                              (line 124)
* output-port?:                          ポート共通の操作.    (line   9)
* pa$:                                   コンビネータ.        (line  10)
* pack:                                  バイナリデータのパック.
                                                              (line  21)
* pair-fold:                             リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  41)
* pair-fold-right:                       リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  42)
* pair-for-each:                         リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line 101)
* pair?:                                 リストに関する述語.  (line   7)
* parameter-observer-add!:               パラメータ.          (line  63)
* parameter-observer-delete!:            パラメータ.          (line  85)
* parameter-post-observers:              パラメータ.          (line  93)
* parameter-pre-observers:               パラメータ.          (line  92)
* parameterize:                          パラメータ.          (line  48)
* parse-cookie-string:                   HTTPクッキー.        (line  12)
* parse-options:                         コマンドライン引数の解析.
                                                              (line  22)
* partition <1>:                         コレクションからの選択と探索.
                                                              (line  53)
* partition:                             リストのフィルタおよび分割.
                                                              (line  23)
* partition!:                            リストのフィルタおよび分割.
                                                              (line  24)
* partition$:                            リストのフィルタおよび分割.
                                                              (line  36)
* partition-to:                          コレクションからの選択と探索.
                                                              (line  64)
* path->module-name:                     モジュールイントロスペクション.
                                                              (line  85)
* path-extension:                        パスネームユーティリティ.
                                                              (line  60)
* path-sans-extension:                   パスネームユーティリティ.
                                                              (line  61)
* path-swap-extension:                   パスネームユーティリティ.
                                                              (line  71)
* peek-byte:                             データの読み込み.    (line  45)
* peek-char:                             データの読み込み.    (line  33)
* peek-next-char:                        入力ストリームのパージング.
                                                              (line  38)
* permutations:                          組み合わせ.          (line  18)
* permutations*:                         組み合わせ.          (line  19)
* permutations*-for-each:                組み合わせ.          (line  37)
* permutations-for-each:                 組み合わせ.          (line  36)
* pop!:                                  代入.                (line 108)
* port->list:                            入力ユーティリティ手続き.
                                                              (line   8)
* port->sexp-list:                       入力ユーティリティ手続き.
                                                              (line  10)
* port->string:                          入力ユーティリティ手続き.
                                                              (line   7)
* port->string-list:                     入力ユーティリティ手続き.
                                                              (line   9)
* port-buffering:                        ポート共通の操作.    (line  48)
* port-closed?:                          ポート共通の操作.    (line  15)
* port-current-line:                     ポート共通の操作.    (line  62)
* port-file-number:                      ポート共通の操作.    (line  67)
* port-fold:                             入力ユーティリティ手続き.
                                                              (line  24)
* port-fold-right:                       入力ユーティリティ手続き.
                                                              (line  25)
* port-for-each:                         入力ユーティリティ手続き.
                                                              (line  26)
* port-map:                              入力ユーティリティ手続き.
                                                              (line  27)
* port-name:                             ポート共通の操作.    (line  44)
* port-seek:                             ポート共通の操作.    (line  71)
* port-tell:                             ポート共通の操作.    (line  99)
* port-type:                             ポート共通の操作.    (line  40)
* port?:                                 ポート共通の操作.    (line   7)
* positive?:                             数値に関する述語.    (line  45)
* power-set:                             組み合わせ.          (line  61)
* power-set*:                            組み合わせ.          (line  62)
* power-set*-for-each:                   組み合わせ.          (line  72)
* power-set-binary:                      組み合わせ.          (line  75)
* power-set-for-each:                    組み合わせ.          (line  71)
* print:                                 出力.                (line  54)
* procedure-arity-includes?:             手続きのアリティ.    (line  36)
* procedure?:                            手続き.              (line   9)
* process-alive?:                        Process object.      (line  84)
* process-command:                       Process object.      (line  63)
* process-continue:                      Process object.      (line 133)
* process-error:                         Process object.      (line  68)
* process-exit-status:                   Process object.      (line 120)
* process-input:                         Process object.      (line  66)
* process-kill:                          Process object.      (line 131)
* process-list:                          Process object.      (line  90)
* process-output:                        Process object.      (line  67)
* process-output->string:                Process ports.       (line 125)
* process-output->string-list:           Process ports.       (line 126)
* process-pid:                           Process object.      (line  60)
* process-send-signal:                   Process object.      (line 125)
* process-stop:                          Process object.      (line 132)
* process-wait:                          Process object.      (line  97)
* process-wait-any:                      Process object.      (line 110)
* process?:                              Process object.      (line  57)
* product-ec:                            Eager comprehensions.
                                                              (line  97)
* profiler-reset:                        プロファイラAPI.     (line  24)
* profiler-show:                         プロファイラAPI.     (line  29)
* profiler-start:                        プロファイラAPI.     (line  14)
* profiler-stop:                         プロファイラAPI.     (line  18)
* program:                               機能ベースプログラム設定言語.
                                                              (line  30)
* promise?:                              遅延評価.            (line  24)
* proper-list?:                          SRFI-1 リストの述語. (line   7)
* provide:                               requireとprovide.    (line  17)
* provided?:                             requireとprovide.    (line  24)
* push!:                                 代入.                (line  78)
* quasiquote:                            準クオート.          (line   7)
* queue->list:                           キュー.              (line  69)
* queue-empty?:                          キュー.              (line  25)
* queue-front:                           キュー.              (line  61)
* queue-length:                          キュー.              (line  28)
* queue-pop!:                            キュー.              (line  50)
* queue-push!:                           キュー.              (line  36)
* queue-push-unique!:                    キュー.              (line  43)
* queue-rear:                            キュー.              (line  62)
* queue?:                                キュー.              (line  21)
* quote:                                 リテラル.            (line   7)
* quoted-printable-decode:               Quoted-printableエンコーディング.
                                                              (line  22)
* quoted-printable-decode-string:        Quoted-printableエンコーディング.
                                                              (line  29)
* quoted-printable-encode:               Quoted-printableエンコーディング.
                                                              (line  12)
* quoted-printable-encode-string:        Quoted-printableエンコーディング.
                                                              (line  17)
* quotient:                              数値の演算.          (line  41)
* quotient&remainder:                    数値の演算.          (line  72)
* raise:                                 例外の通知.          (line  40)
* random-integer:                        ランダムビットのソース.
                                                              (line  12)
* random-real:                           ランダムビットのソース.
                                                              (line  19)
* random-source-make-integers:           ランダムビットのソース.
                                                              (line  56)
* random-source-make-reals:              ランダムビットのソース.
                                                              (line  60)
* random-source-pseudo-randomize!:       ランダムビットのソース.
                                                              (line  49)
* random-source-randomize!:              ランダムビットのソース.
                                                              (line  43)
* random-source-state-ref:               ランダムビットのソース.
                                                              (line  37)
* random-source-state-set!:              ランダムビットのソース.
                                                              (line  38)
* random-source?:                        ランダムビットのソース.
                                                              (line  34)
* rassoc:                                その他のリストライブラリ.
                                                              (line 106)
* rassoc-ref:                            その他のリストライブラリ.
                                                              (line 132)
* rassq:                                 その他のリストライブラリ.
                                                              (line 107)
* rassq-ref:                             その他のリストライブラリ.
                                                              (line 133)
* rassv:                                 その他のリストライブラリ.
                                                              (line 108)
* rassv-ref:                             その他のリストライブラリ.
                                                              (line 134)
* rational?:                             数値に関する述語.    (line  10)
* read:                                  データの読み込み.    (line   7)
* read-block:                            データの読み込み.    (line  64)
* read-block!:                           ユニフォームベクタのブロック入出力.
                                                              (line  10)
* read-byte:                             データの読み込み.    (line  41)
* read-char:                             データの読み込み.    (line  26)
* read-eval-print-loop:                  eval と repl.        (line  32)
* read-from-string:                      文字列ポート.        (line  89)
* read-line:                             データの読み込み.    (line  49)
* read-string:                           入力ストリームのパージング.
                                                              (line  92)
* read-with-shared-structure:            データの読み込み.    (line  18)
* read/ss:                               データの読み込み.    (line  19)
* real-part:                             数値の変換.          (line  12)
* real?:                                 数値に関する述語.    (line   9)
* rec:                                   変数束縛.            (line  84)
* receive:                               変数束縛.            (line  57)
* record-accessor:                       SLIB-互換のレコード型.
                                                              (line  40)
* record-constructor:                    SLIB-互換のレコード型.
                                                              (line  29)
* record-modifier:                       SLIB-互換のレコード型.
                                                              (line  45)
* record-predicate:                      SLIB-互換のレコード型.
                                                              (line  36)
* reduce:                                リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  46)
* reduce$:                               リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line 114)
* reduce-right:                          リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  47)
* reduce-right$:                         リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line 115)
* ref <1>:                               ハッシュテーブル.    (line 120)
* ref <2>:                               基本的なシーケンスのアクセサ.
                                                              (line   7)
* ref:                                   インスタンスへのアクセス.
                                                              (line  48)
* referencer:                            基本的なシーケンスのアクセサ.
                                                              (line  35)
* regexp->string:                        正規表現.            (line 154)
* regexp-quote:                          正規表現ユーティリティ.
                                                              (line 203)
* regexp-replace:                        正規表現ユーティリティ.
                                                              (line 164)
* regexp-replace-all:                    正規表現ユーティリティ.
                                                              (line 165)
* regexp?:                               正規表現.            (line 151)
* relative-path?:                        パスネームユーティリティ.
                                                              (line  14)
* relnum-compare:                        バージョン番号の比較.
                                                              (line  99)
* reload:                                モジュールの再ロード.
                                                              (line  44)
* reload-modified-modules:               モジュールの再ロード.
                                                              (line  49)
* reload-verbose:                        モジュールの再ロード.
                                                              (line  65)
* remainder:                             数値の演算.          (line  42)
* remove <1>:                            リストのフィルタおよび分割.
                                                              (line  15)
* remove:                                コレクションからの選択と探索.
                                                              (line  36)
* remove!:                               リストのフィルタおよび分割.
                                                              (line  16)
* remove$:                               リストのフィルタおよび分割.
                                                              (line  35)
* remove-directory*:                     ディレクトリユーティリティ.
                                                              (line 117)
* remove-from-queue!:                    キュー.              (line  85)
* remove-hook!:                          フック.              (line  51)
* remove-to:                             コレクションからの選択と探索.
                                                              (line  45)
* require:                               requireとprovide.    (line   7)
* require-extension:                     Requiring extensions.
                                                              (line  17)
* requires:                              機能ベースプログラム設定言語.
                                                              (line  40)
* reset-hook!:                           フック.              (line  56)
* resolve-path:                          パスネームユーティリティ.
                                                              (line  22)
* reverse:                               他のリスト手続き.    (line  19)
* reverse!:                              他のリスト手続き.    (line  22)
* reverse-list->string:                  文字列の構築子.      (line  16)
* rfc822-atom:                           RFC822メッセージ形式.
                                                              (line 134)
* rfc822-date->date:                     RFC822メッセージ形式.
                                                              (line 154)
* rfc822-dot-atom:                       RFC822メッセージ形式.
                                                              (line 135)
* rfc822-field->tokens:                  RFC822メッセージ形式.
                                                              (line 116)
* rfc822-header->list:                   RFC822メッセージ形式.
                                                              (line  21)
* rfc822-header-ref:                     RFC822メッセージ形式.
                                                              (line  43)
* rfc822-next-token:                     RFC822メッセージ形式.
                                                              (line  77)
* rfc822-parse-date:                     RFC822メッセージ形式.
                                                              (line 145)
* rfc822-quoted-string:                  RFC822メッセージ形式.
                                                              (line 136)
* rfc822-skip-cfws:                      RFC822メッセージ形式.
                                                              (line 123)
* round:                                 数値の演算.          (line  91)
* run-cgi-script->header&body:           CGIのテスト.         (line  66)
* run-cgi-script->string:                CGIのテスト.         (line  90)
* run-cgi-script->string-list:           CGIのテスト.         (line  92)
* run-cgi-script->sxml:                  CGIのテスト.         (line  82)
* run-hook:                              フック.              (line  62)
* run-process:                           Process object.      (line  22)
* rxmatch:                               正規表現.            (line 158)
* rxmatch-after:                         正規表現.            (line 207)
* rxmatch-before:                        正規表現.            (line 208)
* rxmatch-case:                          正規表現ユーティリティ.
                                                              (line 115)
* rxmatch-cond:                          正規表現ユーティリティ.
                                                              (line  71)
* rxmatch-end:                           正規表現.            (line 174)
* rxmatch-if:                            正規表現ユーティリティ.
                                                              (line  50)
* rxmatch-let:                           正規表現ユーティリティ.
                                                              (line  26)
* rxmatch-num-matches:                   正規表現.            (line 188)
* rxmatch-start:                         正規表現.            (line 173)
* rxmatch-substring:                     正規表現.            (line 175)
* s16vector:                             ユニフォームベクタの基本操作.
                                                              (line  19)
* s16vector->list:                       ユニフォームベクタの変換.
                                                              (line   7)
* s16vector->vector:                     ユニフォームベクタの変換.
                                                              (line  19)
* s16vector-add:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s16vector-add!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s16vector-and:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s16vector-and!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s16vector-clamp:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* s16vector-clamp!:                      ユニフォームベクタの数値演算.
                                                              (line  96)
* s16vector-copy:                        ユニフォームベクタの基本操作.
                                                              (line  75)
* s16vector-copy!:                       ユニフォームベクタの基本操作.
                                                              (line  84)
* s16vector-dot:                         ユニフォームベクタの数値演算.
                                                              (line  60)
* s16vector-ior:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s16vector-ior!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s16vector-length:                      ユニフォームベクタの基本操作.
                                                              (line  32)
* s16vector-mul:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s16vector-mul!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s16vector-range-check:                 ユニフォームベクタの数値演算.
                                                              (line  64)
* s16vector-ref:                         ユニフォームベクタの基本操作.
                                                              (line  43)
* s16vector-set!:                        ユニフォームベクタの基本操作.
                                                              (line  57)
* s16vector-sub:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s16vector-sub!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s16vector-xor:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s16vector-xor!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s16vector?:                            ユニフォームベクタの基本操作.
                                                              (line  16)
* s32vector:                             ユニフォームベクタの基本操作.
                                                              (line  19)
* s32vector->list:                       ユニフォームベクタの変換.
                                                              (line   7)
* s32vector->string:                     ユニフォームベクタの変換.
                                                              (line 105)
* s32vector->vector:                     ユニフォームベクタの変換.
                                                              (line  19)
* s32vector-add:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s32vector-add!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s32vector-and:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s32vector-and!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s32vector-clamp:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* s32vector-clamp!:                      ユニフォームベクタの数値演算.
                                                              (line  96)
* s32vector-copy:                        ユニフォームベクタの基本操作.
                                                              (line  75)
* s32vector-copy!:                       ユニフォームベクタの基本操作.
                                                              (line  84)
* s32vector-dot:                         ユニフォームベクタの数値演算.
                                                              (line  60)
* s32vector-ior:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s32vector-ior!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s32vector-length:                      ユニフォームベクタの基本操作.
                                                              (line  32)
* s32vector-mul:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s32vector-mul!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s32vector-range-check:                 ユニフォームベクタの数値演算.
                                                              (line  64)
* s32vector-ref:                         ユニフォームベクタの基本操作.
                                                              (line  43)
* s32vector-set!:                        ユニフォームベクタの基本操作.
                                                              (line  57)
* s32vector-sub:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s32vector-sub!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s32vector-xor:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s32vector-xor!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s32vector?:                            ユニフォームベクタの基本操作.
                                                              (line  16)
* s64vector:                             ユニフォームベクタの基本操作.
                                                              (line  19)
* s64vector->list:                       ユニフォームベクタの変換.
                                                              (line   7)
* s64vector->vector:                     ユニフォームベクタの変換.
                                                              (line  19)
* s64vector-add:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s64vector-add!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s64vector-and:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s64vector-and!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s64vector-clamp:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* s64vector-clamp!:                      ユニフォームベクタの数値演算.
                                                              (line  96)
* s64vector-copy:                        ユニフォームベクタの基本操作.
                                                              (line  75)
* s64vector-copy!:                       ユニフォームベクタの基本操作.
                                                              (line  84)
* s64vector-dot:                         ユニフォームベクタの数値演算.
                                                              (line  60)
* s64vector-ior:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s64vector-ior!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s64vector-length:                      ユニフォームベクタの基本操作.
                                                              (line  32)
* s64vector-mul:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s64vector-mul!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s64vector-range-check:                 ユニフォームベクタの数値演算.
                                                              (line  64)
* s64vector-ref:                         ユニフォームベクタの基本操作.
                                                              (line  43)
* s64vector-set!:                        ユニフォームベクタの基本操作.
                                                              (line  57)
* s64vector-sub:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s64vector-sub!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* s64vector-xor:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s64vector-xor!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* s64vector?:                            ユニフォームベクタの基本操作.
                                                              (line  16)
* s8vector:                              ユニフォームベクタの基本操作.
                                                              (line  19)
* s8vector->list:                        ユニフォームベクタの変換.
                                                              (line   7)
* s8vector->string:                      ユニフォームベクタの変換.
                                                              (line  86)
* s8vector->vector:                      ユニフォームベクタの変換.
                                                              (line  19)
* s8vector-add:                          ユニフォームベクタの数値演算.
                                                              (line  12)
* s8vector-add!:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s8vector-and:                          ユニフォームベクタの数値演算.
                                                              (line  49)
* s8vector-and!:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s8vector-clamp:                        ユニフォームベクタの数値演算.
                                                              (line  96)
* s8vector-clamp!:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* s8vector-copy:                         ユニフォームベクタの基本操作.
                                                              (line  75)
* s8vector-copy!:                        ユニフォームベクタの基本操作.
                                                              (line  84)
* s8vector-dot:                          ユニフォームベクタの数値演算.
                                                              (line  60)
* s8vector-ior:                          ユニフォームベクタの数値演算.
                                                              (line  49)
* s8vector-ior!:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s8vector-length:                       ユニフォームベクタの基本操作.
                                                              (line  32)
* s8vector-mul:                          ユニフォームベクタの数値演算.
                                                              (line  12)
* s8vector-mul!:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s8vector-range-check:                  ユニフォームベクタの数値演算.
                                                              (line  64)
* s8vector-ref:                          ユニフォームベクタの基本操作.
                                                              (line  43)
* s8vector-set!:                         ユニフォームベクタの基本操作.
                                                              (line  57)
* s8vector-sub:                          ユニフォームベクタの数値演算.
                                                              (line  12)
* s8vector-sub!:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* s8vector-xor:                          ユニフォームベクタの数値演算.
                                                              (line  49)
* s8vector-xor!:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* s8vector?:                             ユニフォームベクタの基本操作.
                                                              (line  16)
* save-bundle!:                          地域化.              (line  73)
* scheme-report-environment:             eval と repl.        (line  14)
* second:                                SRFI-1 リスト選択子. (line   8)
* seconds->time:                         時間.                (line 126)
* select-kids:                           SXPathの基本的なコンバータとアプリケータ.
                                                              (line 169)
* select-module:                         モジュールの定義と選択.
                                                              (line  12)
* selector-add!:                         簡単なディスパッチャ.
                                                              (line  16)
* selector-delete!:                      簡単なディスパッチャ.
                                                              (line  36)
* selector-select:                       簡単なディスパッチャ.
                                                              (line  45)
* set!:                                  代入.                (line   8)
* set!-values:                           代入.                (line  29)
* set-car!:                              リストへのアクセスと変更.
                                                              (line  11)
* set-cdr!:                              リストへのアクセスと変更.
                                                              (line  12)
* set-signal-handler!:                   シグナルの処理.      (line  51)
* set-time-nanosecond!:                  時間に関する手続き.  (line  22)
* set-time-second!:                      時間に関する手続き.  (line  21)
* set-time-type!:                        時間に関する手続き.  (line  20)
* setter:                                代入.                (line  42)
* seventh:                               SRFI-1 リスト選択子. (line  13)
* sha1-digest:                           SHA1メッセージダイジェスト.
                                                              (line  26)
* sha1-digest-string:                    SHA1メッセージダイジェスト.
                                                              (line  30)
* shape:                                 配列.                (line 104)
* shape-for-each:                        配列.                (line 183)
* share-array:                           配列.                (line 168)
* simplify-path:                         パスネームユーティリティ.
                                                              (line  29)
* sin:                                   数値の演算.          (line 114)
* sinh:                                  数値の演算.          (line 125)
* sixth:                                 SRFI-1 リスト選択子. (line  12)
* size-of:                               コレクションに対する様々な操作.
                                                              (line   7)
* skip-until:                            入力ストリームのパージング.
                                                              (line  56)
* skip-while:                            入力ストリームのパージング.
                                                              (line  64)
* slices:                                その他のリストライブラリ.
                                                              (line  55)
* slot-bound-using-class?:               インスタンスへのアクセス.
                                                              (line  88)
* slot-bound?:                           インスタンスへのアクセス.
                                                              (line  30)
* slot-defininion-setter:                スロット定義オブジェクト.
                                                              (line  26)
* slot-definition-accessor:              スロット定義オブジェクト.
                                                              (line  27)
* slot-definition-allocation:            スロット定義オブジェクト.
                                                              (line  22)
* slot-definition-getter:                スロット定義オブジェクト.
                                                              (line  25)
* slot-definition-name:                  スロット定義オブジェクト.
                                                              (line  15)
* slot-definition-option:                スロット定義オブジェクト.
                                                              (line  31)
* slot-definition-options:               スロット定義オブジェクト.
                                                              (line  19)
* slot-exists?:                          インスタンスへのアクセス.
                                                              (line  38)
* slot-missing:                          インスタンスへのアクセス.
                                                              (line  65)
* slot-push!:                            インスタンスへのアクセス.
                                                              (line  41)
* slot-ref:                              インスタンスへのアクセス.
                                                              (line  10)
* slot-ref-using-accessor:               スロットアクセスのカスタマイズ.
                                                              (line  11)
* slot-ref-using-class:                  インスタンスへのアクセス.
                                                              (line  84)
* slot-set!:                             インスタンスへのアクセス.
                                                              (line  23)
* slot-set-using-accessor:               スロットアクセスのカスタマイズ.
                                                              (line  12)
* slot-set-using-class!:                 インスタンスへのアクセス.
                                                              (line  86)
* slot-unbound:                          インスタンスへのアクセス.
                                                              (line  58)
* sockaddr-addr:                         ソケットアドレス.    (line  43)
* sockaddr-family:                       ソケットアドレス.    (line  55)
* sockaddr-name:                         ソケットアドレス.    (line  39)
* sockaddr-port:                         ソケットアドレス.    (line  46)
* socket-accept:                         低レベルソケットインタフェース.
                                                              (line  57)
* socket-address:                        高レベルネットワーク手続き.
                                                              (line 112)
* socket-bind:                           低レベルソケットインタフェース.
                                                              (line  42)
* socket-close:                          高レベルネットワーク手続き.
                                                              (line 125)
* socket-connect:                        低レベルソケットインタフェース.
                                                              (line  66)
* socket-fd:                             低レベルソケットインタフェース.
                                                              (line  28)
* socket-getpeername:                    低レベルソケットインタフェース.
                                                              (line  85)
* socket-getsockname:                    低レベルソケットインタフェース.
                                                              (line  82)
* socket-getsockopt:                     低レベルソケットインタフェース.
                                                              (line 134)
* socket-input-port:                     高レベルネットワーク手続き.
                                                              (line 116)
* socket-listen:                         低レベルソケットインタフェース.
                                                              (line  52)
* socket-output-port:                    高レベルネットワーク手続き.
                                                              (line 117)
* socket-recv:                           低レベルソケットインタフェース.
                                                              (line 101)
* socket-recvfrom:                       低レベルソケットインタフェース.
                                                              (line 102)
* socket-send:                           低レベルソケットインタフェース.
                                                              (line  88)
* socket-sendto:                         低レベルソケットインタフェース.
                                                              (line  89)
* socket-setsockopt:                     低レベルソケットインタフェース.
                                                              (line 133)
* socket-shutdown:                       低レベルソケットインタフェース.
                                                              (line  71)
* socket-status:                         低レベルソケットインタフェース.
                                                              (line  31)
* sort:                                  比較とソート.        (line  11)
* sort!:                                 比較とソート.        (line  12)
* sort-applicable-methods:               メソッド適用のカスタマイズ.
                                                              (line   9)
* span:                                  リストの探索.        (line  24)
* span!:                                 リストの探索.        (line  25)
* split-at:                              SRFI-1 リスト選択子. (line  73)
* split-at!:                             SRFI-1 リスト選択子. (line  74)
* split-at*:                             その他のリストライブラリ.
                                                              (line  48)
* sqrt:                                  数値の演算.          (line 133)
* ssax:assert-token:                     SSAXの高レベルのパーザとスキャナ.
                                                              (line  68)
* ssax:complete-start-tag:               SSAXの低レベルパージングコード.
                                                              (line 208)
* ssax:handle-parsed-entity:             SSAXの低レベルパージングコード.
                                                              (line 140)
* ssax:make-elem-parser:                 SSAXの高レベルのパーザ - XMLからSXMLへ.
                                                              (line  33)
* ssax:make-parser:                      SSAXの高レベルのパーザ - XMLからSXMLへ.
                                                              (line  68)
* ssax:make-pi-parser:                   SSAXの高レベルのパーザ - XMLからSXMLへ.
                                                              (line  14)
* ssax:ncname-starting-char?:            SSAXの低レベルパージングコード.
                                                              (line  19)
* ssax:read-attributes:                  SSAXの低レベルパージングコード.
                                                              (line 160)
* ssax:read-cdata-body:                  SSAXの低レベルパージングコード.
                                                              (line  93)
* ssax:read-char-data:                   SSAXの高レベルのパーザとスキャナ.
                                                              (line  21)
* ssax:read-char-ref:                    SSAXの低レベルパージングコード.
                                                              (line 122)
* ssax:read-external-id:                 SSAXの低レベルパージングコード.
                                                              (line 243)
* ssax:read-markup-token:                SSAXの低レベルパージングコード.
                                                              (line  39)
* ssax:read-NCName:                      SSAXの低レベルパージングコード.
                                                              (line  22)
* ssax:read-pi-body-as-string:           SSAXの低レベルパージングコード.
                                                              (line  82)
* ssax:read-QName:                       SSAXの低レベルパージングコード.
                                                              (line  26)
* ssax:resolve-name:                     SSAXの低レベルパージングコード.
                                                              (line 192)
* ssax:reverse-collect-str:              SSAXの高レベルのパーザ - XMLからSXMLへ.
                                                              (line 155)
* ssax:reverse-collect-str-drop-ws:      SSAXの高レベルのパーザ - XMLからSXMLへ.
                                                              (line 159)
* ssax:scan-Misc:                        SSAXの高レベルのパーザとスキャナ.
                                                              (line  10)
* ssax:skip-internal-dtd:                SSAXの低レベルパージングコード.
                                                              (line  88)
* ssax:skip-pi:                          SSAXの低レベルパージングコード.
                                                              (line  79)
* ssax:skip-S:                           SSAXの低レベルパージングコード.
                                                              (line  13)
* ssax:uri-string->symbol:               SSAXの低レベルパージングコード.
                                                              (line 205)
* ssax:xml->sxml:                        SSAXの高レベルのパーザ - XMLからSXMLへ.
                                                              (line 169)
* stable-sort:                           比較とソート.        (line  36)
* stable-sort!:                          比較とソート.        (line  37)
* standard-error-port:                   ポート共通の操作.    (line  28)
* standard-input-port:                   ポート共通の操作.    (line  26)
* standard-output-port:                  ポート共通の操作.    (line  27)
* string <1>:                            文字列の比較.        (line  11)
* string <2>:                            文字列の作成.        (line  29)
* string:                                文字列の色々な比較.  (line  18)
* string->char-set:                      文字セットの構築子.  (line  16)
* string->char-set!:                     文字セットの構築子.  (line  17)
* string->date:                          日付の読み書き.      (line  10)
* string->list:                          文字列を扱うその他の手続き.
                                                              (line  13)
* string->number:                        数値の変換.          (line  64)
* string->regexp:                        正規表現.            (line 143)
* string->s32vector:                     ユニフォームベクタの変換.
                                                              (line  96)
* string->s8vector:                      ユニフォームベクタの変換.
                                                              (line  58)
* string->s8vector!:                     ユニフォームベクタの変換.
                                                              (line  72)
* string->symbol:                        シンボル.            (line  35)
* string->u32vector:                     ユニフォームベクタの変換.
                                                              (line  97)
* string->u8vector:                      ユニフォームベクタの変換.
                                                              (line  59)
* string->u8vector!:                     ユニフォームベクタの変換.
                                                              (line  73)
* string-any:                            文字列についての述語.
                                                              (line  17)
* string-append:                         文字列を扱うその他の手続き.
                                                              (line  10)
* string-append-ec:                      Eager comprehensions.
                                                              (line  87)
* string-append/shared:                  文字列の反転と追加.  (line  26)
* string-byte-ref:                       文字列のアクセスと変更.
                                                              (line  27)
* string-byte-set!:                      文字列のアクセスと変更.
                                                              (line  42)
* string-ci <1>:                         文字列の比較.        (line   8)
* string-ci <2>:                         文字列の色々な比較.  (line  21)
* string-ci <3>:                         文字列の比較.        (line  18)
* string-ci <4>:                         文字列の色々な比較.  (line  23)
* string-ci <5>:                         文字列の比較.        (line  15)
* string-ci <6>:                         文字列の色々な比較.  (line  24)
* string-ci:                             文字列の比較.        (line  16)
* string-compare:                        文字列の色々な比較.  (line   8)
* string-compare-ci:                     文字列の色々な比較.  (line  10)
* string-complete->incomplete:           不完全文字列.        (line   7)
* string-concatenate:                    文字列の反転と追加.  (line  20)
* string-concatenate-reverse:            文字列の反転と追加.  (line  30)
* string-concatenate-reverse/shared:     文字列の反転と追加.  (line  31)
* string-concatenate/shared:             文字列の反転と追加.  (line  25)
* string-contains:                       文字列の探索.        (line  36)
* string-contains-ci:                    文字列の探索.        (line  37)
* string-copy:                           文字列を扱うその他の手続き.
                                                              (line  17)
* string-copy!:                          文字列の選択.        (line  12)
* string-count:                          文字列の探索.        (line  31)
* string-delete:                         文字列のフィルタリング.
                                                              (line   8)
* string-downcase:                       文字列のケース(大文字小文字)マッピング.
                                                              (line  15)
* string-downcase!:                      文字列のケース(大文字小文字)マッピング.
                                                              (line  16)
* string-drop:                           文字列の選択.        (line  21)
* string-drop-right:                     文字列の選択.        (line  23)
* string-ec:                             Eager comprehensions.
                                                              (line  86)
* string-every:                          文字列についての述語.
                                                              (line  10)
* string-fill!:                          文字列を扱うその他の手続き.
                                                              (line  20)
* string-filter:                         文字列のフィルタリング.
                                                              (line   7)
* string-fold:                           文字列のマッピング.  (line  20)
* string-fold-right:                     文字列のマッピング.  (line  21)
* string-for-each:                       文字列のマッピング.  (line  30)
* string-for-each-index:                 文字列のマッピング.  (line  33)
* string-hash:                           文字列の色々な比較.  (line  29)
* string-hash-ci:                        文字列の色々な比較.  (line  30)
* string-immutable?:                     文字列に関する述語.  (line  10)
* string-incomplete->complete:           不完全文字列.        (line   9)
* string-incomplete?:                    文字列に関する述語.  (line  13)
* string-index:                          文字列の探索.        (line   7)
* string-index-right:                    文字列の探索.        (line   9)
* string-join:                           文字列を扱うその他の手続き.
                                                              (line  28)
* string-kmp-partial-search:             低レベルな文字列に関する手続き.
                                                              (line  26)
* string-length:                         文字列のアクセスと変更.
                                                              (line   7)
* string-map:                            文字列のマッピング.  (line   7)
* string-map!:                           文字列のマッピング.  (line   8)
* string-null?:                          文字列についての述語.
                                                              (line   7)
* string-pad:                            文字列の選択.        (line  36)
* string-pad-right:                      文字列の選択.        (line  37)
* string-parse-final-start+end:          低レベルな文字列に関する手続き.
                                                              (line   8)
* string-parse-start+end:                低レベルな文字列に関する手続き.
                                                              (line   7)
* string-pointer-byte-index:             文字列ポインタ.      (line  35)
* string-pointer-copy:                   文字列ポインタ.      (line  20)
* string-pointer-index:                  文字列ポインタ.      (line  34)
* string-pointer-next!:                  文字列ポインタ.      (line  27)
* string-pointer-prev!:                  文字列ポインタ.      (line  28)
* string-pointer-set!:                   文字列ポインタ.      (line  30)
* string-pointer-substring:              文字列ポインタ.      (line  32)
* string-pointer?:                       文字列ポインタ.      (line  24)
* string-prefix-ci?:                     文字列のプリフィックスとサフィックス.
                                                              (line  19)
* string-prefix-length:                  文字列のプリフィックスとサフィックス.
                                                              (line   8)
* string-prefix-length-ci:               文字列のプリフィックスとサフィックス.
                                                              (line  12)
* string-prefix?:                        文字列のプリフィックスとサフィックス.
                                                              (line  17)
* string-ref:                            文字列のアクセスと変更.
                                                              (line  19)
* string-replace:                        他の文字列操作.      (line   7)
* string-reverse:                        文字列の反転と追加.  (line   7)
* string-reverse!:                       文字列の反転と追加.  (line   8)
* string-scan:                           文字列を扱うその他の手続き.
                                                              (line  68)
* string-set!:                           文字列のアクセスと変更.
                                                              (line  32)
* string-size:                           文字列のアクセスと変更.
                                                              (line  11)
* string-skip:                           文字列の探索.        (line  24)
* string-skip-right:                     文字列の探索.        (line  25)
* string-split:                          文字列を扱うその他の手続き.
                                                              (line 121)
* string-suffix-ci?:                     文字列のプリフィックスとサフィックス.
                                                              (line  20)
* string-suffix-length:                  文字列のプリフィックスとサフィックス.
                                                              (line  10)
* string-suffix-length-ci:               文字列のプリフィックスとサフィックス.
                                                              (line  14)
* string-suffix?:                        文字列のプリフィックスとサフィックス.
                                                              (line  18)
* string-tabulate:                       文字列の構築子.      (line   7)
* string-take:                           文字列の選択.        (line  20)
* string-take-right:                     文字列の選択.        (line  22)
* string-titlecase:                      文字列のケース(大文字小文字)マッピング.
                                                              (line   7)
* string-titlecase!:                     文字列のケース(大文字小文字)マッピング.
                                                              (line   8)
* string-tokenize:                       他の文字列操作.      (line  10)
* string-tr:                             文字変換.            (line  85)
* string-trim:                           文字列の選択.        (line  53)
* string-trim-both:                      文字列の選択.        (line  55)
* string-trim-right:                     文字列の選択.        (line  54)
* string-unfold:                         文字列のマッピング.  (line  24)
* string-unfold-right:                   文字列のマッピング.  (line  27)
* string-upcase:                         文字列のケース(大文字小文字)マッピング.
                                                              (line  11)
* string-upcase!:                        文字列のケース(大文字小文字)マッピング.
                                                              (line  12)
* string-xcopy!:                         文字列のローテーション.
                                                              (line  11)
* string=:                               文字列の色々な比較.  (line  13)
* string=?:                              文字列の比較.        (line   7)
* string?:                               文字列に関する述語.  (line   7)
* subseq:                                シーケンスのスライス.
                                                              (line   7)
* substring:                             文字列を扱うその他の手続き.
                                                              (line   7)
* substring-spec-ok?:                    低レベルな文字列に関する手続き.
                                                              (line  16)
* substring/shared:                      文字列の選択.        (line   7)
* subtract-duration:                     時間に関する手続き.  (line  46)
* subtract-duration!:                    時間に関する手続き.  (line  47)
* sum-ec:                                Eager comprehensions.
                                                              (line  96)
* supported-character-encodings:         文字.                (line 166)
* sxml:add-attr:                         SXMLのモディファイヤ.
                                                              (line  35)
* sxml:add-attr!:                        SXMLのモディファイヤ.
                                                              (line  41)
* sxml:add-aux:                          SXMLのモディファイヤ.
                                                              (line  61)
* sxml:add-aux!:                         SXMLのモディファイヤ.
                                                              (line  64)
* sxml:add-parents:                      SXPathの補助的ユーティリティ.
                                                              (line   9)
* sxml:ancestor:                         SXPathの拡張.        (line  96)
* sxml:ancestor-or-self:                 SXPathの拡張.        (line  99)
* sxml:attr:                             SXMLへのアクセッサ.  (line  99)
* sxml:attr->html:                       SXMLからマークアップへの変換.
                                                              (line  35)
* sxml:attr->xml:                        SXMLからマークアップへの変換.
                                                              (line  24)
* sxml:attr-as-list:                     SXMLへのアクセッサ.  (line  57)
* sxml:attr-list:                        SXPathの拡張.        (line  40)
* sxml:attr-list-node:                   SXMLへのアクセッサ.  (line  53)
* sxml:attr-list-u:                      SXMLへのアクセッサ.  (line  70)
* sxml:attr-u:                           SXMLへのアクセッサ.  (line 112)
* sxml:attribute:                        SXPathの拡張.        (line  74)
* sxml:aux-as-list:                      SXMLへのアクセッサ.  (line  66)
* sxml:aux-list:                         SXMLへのアクセッサ.  (line  75)
* sxml:aux-list-node:                    SXMLへのアクセッサ.  (line  62)
* sxml:aux-list-u:                       SXMLへのアクセッサ.  (line  80)
* sxml:aux-node:                         SXMLへのアクセッサ.  (line  88)
* sxml:aux-nodes:                        SXMLへのアクセッサ.  (line  95)
* sxml:boolean:                          SXPathの拡張.        (line  18)
* sxml:change-attr:                      SXMLのモディファイヤ.
                                                              (line  47)
* sxml:change-attr!:                     SXMLのモディファイヤ.
                                                              (line  52)
* sxml:change-attrlist:                  SXMLのモディファイヤ.
                                                              (line  26)
* sxml:change-attrlist!:                 SXMLのモディファイヤ.
                                                              (line  27)
* sxml:change-content:                   SXMLのモディファイヤ.
                                                              (line  20)
* sxml:change-content!:                  SXMLのモディファイヤ.
                                                              (line  21)
* sxml:change-name:                      SXMLのモディファイヤ.
                                                              (line  31)
* sxml:change-name!:                     SXMLのモディファイヤ.
                                                              (line  32)
* sxml:child:                            SXPathの拡張.        (line  77)
* sxml:child-elements:                   SXPathの拡張.        (line 128)
* sxml:child-nodes:                      SXPathの拡張.        (line 125)
* sxml:clean:                            SXMLのモディファイヤ.
                                                              (line  73)
* sxml:clean-feed:                       SXMLからマークアップへの変換.
                                                              (line   9)
* sxml:content:                          SXMLへのアクセッサ.  (line  31)
* sxml:content-raw:                      SXMLへのアクセッサ.  (line  36)
* sxml:descendant:                       SXPathの拡張.        (line 102)
* sxml:descendant-or-self:               SXPathの拡張.        (line 105)
* sxml:element-name:                     SXMLへのアクセッサ.  (line  11)
* sxml:element?:                         SXPathの基本的なコンバータとアプリケータ.
                                                              (line  21)
* sxml:empty-element?:                   SXMLの述語.          (line   7)
* sxml:equal?:                           SXPathの拡張.        (line  63)
* sxml:equality-cmp:                     SXPathの拡張.        (line  58)
* sxml:filter:                           SXPathの基本的なコンバータとアプリケータ.
                                                              (line  98)
* sxml:following:                        SXPathの拡張.        (line 108)
* sxml:following-sibling:                SXPathの拡張.        (line 111)
* sxml:id:                               SXPathの拡張.        (line  45)
* sxml:id-alist:                         SXPathクエリ言語.    (line  53)
* sxml:invert:                           SXPathの基本的なコンバータとアプリケータ.
                                                              (line  72)
* sxml:lookup:                           SXPathの補助的ユーティリティ.
                                                              (line  21)
* sxml:minimized?:                       SXMLの述語.          (line  27)
* sxml:name:                             SXMLへのアクセッサ.  (line   7)
* sxml:name->ns-id:                      SXMLへのアクセッサ.  (line  27)
* sxml:namespace:                        SXPathの拡張.        (line 114)
* sxml:ncname:                           SXMLへのアクセッサ.  (line  19)
* sxml:node-name:                        SXMLへのアクセッサ.  (line  15)
* sxml:node-parent:                      SXPathの補助的ユーティリティ.
                                                              (line  14)
* sxml:node?:                            SXPathの拡張.        (line  35)
* sxml:non-terminated-html-tag?:         SXMLからマークアップへの変換.
                                                              (line  44)
* sxml:normalized?:                      SXMLの述語.          (line  18)
* sxml:not-equal?:                       SXPathの拡張.        (line  64)
* sxml:ns-id:                            SXMLへのアクセッサ.  (line 143)
* sxml:ns-id->nodes:                     SXMLへのアクセッサ.  (line 128)
* sxml:ns-id->uri:                       SXMLへのアクセッサ.  (line 135)
* sxml:ns-list:                          SXMLへのアクセッサ.  (line 123)
* sxml:ns-prefix:                        SXMLへのアクセッサ.  (line 149)
* sxml:ns-uri:                           SXMLへのアクセッサ.  (line 146)
* sxml:ns-uri->id:                       SXMLへのアクセッサ.  (line 140)
* sxml:num-attr:                         SXMLへのアクセッサ.  (line 104)
* sxml:number:                           SXPathの拡張.        (line  22)
* sxml:parent:                           SXPathの拡張.        (line  82)
* sxml:preceding:                        SXPathの拡張.        (line 117)
* sxml:preceding-sibling:                SXPathの拡張.        (line 120)
* sxml:relational-cmp:                   SXPathの拡張.        (line  68)
* sxml:set-attr:                         SXMLのモディファイヤ.
                                                              (line  56)
* sxml:set-attr!:                        SXMLのモディファイヤ.
                                                              (line  57)
* sxml:shallow-minimized?:               SXMLの述語.          (line  22)
* sxml:shallow-normalized?:              SXMLの述語.          (line  13)
* sxml:squeeze:                          SXMLのモディファイヤ.
                                                              (line  67)
* sxml:squeeze!:                         SXMLのモディファイヤ.
                                                              (line  68)
* sxml:string:                           SXPathの拡張.        (line   9)
* sxml:string->html:                     SXMLからマークアップへの変換.
                                                              (line  38)
* sxml:string->xml:                      SXMLからマークアップへの変換.
                                                              (line  27)
* sxml:string-value:                     SXPathの拡張.        (line  31)
* sxml:sxml->html:                       SXMLからマークアップへの変換.
                                                              (line  47)
* sxml:sxml->xml:                        SXMLからマークアップへの変換.
                                                              (line  32)
* sxpath:                                SXPathクエリ言語.    (line   7)
* symbol->string:                        シンボル.            (line  29)
* symbol-bound?:                         モジュールイントロスペクション.
                                                              (line  77)
* symbol?:                               シンボル.            (line  21)
* syntax-error:                          マクロユーティリティ.
                                                              (line   7)
* syntax-errorf:                         マクロユーティリティ.
                                                              (line   8)
* syntax-rules:                          健全なマクロ.        (line  20)
* sys-abort:                             プログラムの終了.    (line  21)
* sys-access:                            ファイルの状態.      (line 107)
* sys-alarm:                             その他のシステムコール.
                                                              (line  17)
* sys-asctime:                           時間.                (line  83)
* sys-basename:                          パス名.              (line  35)
* sys-cfgetispeed:                       Termios.             (line 104)
* sys-cfgetospeed:                       Termios.             (line 106)
* sys-cfsetispeed:                       Termios.             (line 105)
* sys-cfsetospeed:                       Termios.             (line 107)
* sys-chdir:                             他のファイル操作.    (line   7)
* sys-chmod:                             ファイルの状態.      (line 131)
* sys-chown:                             ファイルの状態.      (line 136)
* sys-closelog:                          Syslog.              (line  57)
* sys-crypt:                             Unixのグループとユーザ.
                                                              (line  82)
* sys-ctermid:                           システムへの問い合わせ.
                                                              (line  79)
* sys-ctime:                             時間.                (line  75)
* sys-difftime:                          時間.                (line  79)
* sys-dirname:                           パス名.              (line  36)
* sys-exec:                              Unixのプロセス管理.  (line  50)
* sys-exit:                              プログラムの終了.    (line  14)
* sys-fcntl:                             低レベルファイル操作.
                                                              (line  11)
* sys-fdset-max-fd:                      I/Oの多重化.         (line  27)
* sys-fdset-ref:                         I/Oの多重化.         (line  16)
* sys-fdset-set!:                        I/Oの多重化.         (line  17)
* sys-fork:                              Unixのプロセス管理.  (line  22)
* sys-fork-and-exec:                     Unixのプロセス管理.  (line  87)
* sys-forkpty:                           Termios.             (line 134)
* sys-fstat:                             ファイルの状態.      (line  59)
* sys-getaddrinfo:                       Netdbインタフェース. (line 138)
* sys-getcwd:                            システムへの問い合わせ.
                                                              (line  19)
* sys-getdomainname:                     システムへの問い合わせ.
                                                              (line  15)
* sys-getegid:                           システムへの問い合わせ.
                                                              (line  26)
* sys-getenv:                            環境の問い合わせ.    (line   7)
* sys-geteuid:                           システムへの問い合わせ.
                                                              (line  34)
* sys-getgid:                            システムへの問い合わせ.
                                                              (line  25)
* sys-getgrgid:                          Unixのグループとユーザ.
                                                              (line  26)
* sys-getgrnam:                          Unixのグループとユーザ.
                                                              (line  27)
* sys-getgroups:                         システムへの問い合わせ.
                                                              (line  41)
* sys-gethostbyaddr:                     Netdbインタフェース. (line  31)
* sys-gethostbyname:                     Netdbインタフェース. (line  22)
* sys-gethostname:                       システムへの問い合わせ.
                                                              (line  11)
* sys-getlogin:                          システムへの問い合わせ.
                                                              (line  44)
* sys-getpgid:                           システムへの問い合わせ.
                                                              (line  52)
* sys-getpgrp:                           システムへの問い合わせ.
                                                              (line  49)
* sys-getpid:                            システムへの問い合わせ.
                                                              (line  72)
* sys-getppid:                           システムへの問い合わせ.
                                                              (line  73)
* sys-getprotobyname:                    Netdbインタフェース. (line  98)
* sys-getprotobynumber:                  Netdbインタフェース. (line 109)
* sys-getpwnam:                          Unixのグループとユーザ.
                                                              (line  70)
* sys-getpwuid:                          Unixのグループとユーザ.
                                                              (line  69)
* sys-getservbyname:                     Netdbインタフェース. (line  60)
* sys-getservbyport:                     Netdbインタフェース. (line  72)
* sys-gettimeofday:                      時間.                (line  30)
* sys-getuid:                            システムへの問い合わせ.
                                                              (line  33)
* sys-gid->group-name:                   Unixのグループとユーザ.
                                                              (line  33)
* sys-glob:                              ディレクトリ.        (line  16)
* sys-gmtime:                            時間.                (line  69)
* sys-group-name->gid:                   Unixのグループとユーザ.
                                                              (line  34)
* sys-isatty:                            他のファイル操作.    (line  36)
* sys-kill:                              シグナルの送出.      (line  10)
* sys-link:                              ディレクトリ操作.    (line  30)
* sys-localeconv:                        ロケール.            (line  22)
* sys-localtime:                         時間.                (line  70)
* sys-logmask:                           Syslog.              (line  69)
* sys-lstat:                             ファイルの状態.      (line  70)
* sys-mkdir:                             ディレクトリ操作.    (line  49)
* sys-mkfifo:                            他のファイル操作.    (line  31)
* sys-mkstemp:                           ディレクトリ操作.    (line  23)
* sys-mktime:                            時間.                (line  90)
* sys-nanosleep:                         その他のシステムコール.
                                                              (line  33)
* sys-normalize-pathname:                パス名.              (line  11)
* sys-openlog:                           Syslog.              (line  19)
* sys-openpty:                           Termios.             (line 120)
* sys-pause:                             その他のシステムコール.
                                                              (line   7)
* sys-pipe:                              他のファイル操作.    (line  12)
* sys-putenv:                            環境の問い合わせ.    (line  12)
* sys-random:                            その他のシステムコール.
                                                              (line  47)
* sys-readdir:                           ディレクトリ.        (line  10)
* sys-readlink:                          ディレクトリ操作.    (line  44)
* sys-realpath:                          パス名.              (line  59)
* sys-remove:                            ディレクトリ操作.    (line   7)
* sys-rename:                            ディレクトリ操作.    (line  12)
* sys-rmdir:                             ディレクトリ操作.    (line  58)
* sys-select:                            I/Oの多重化.         (line  30)
* sys-select!:                           I/Oの多重化.         (line  31)
* sys-setgid:                            システムへの問い合わせ.
                                                              (line  30)
* sys-setlocale:                         ロケール.            (line   7)
* sys-setlogmask:                        Syslog.              (line  60)
* sys-setpgid:                           システムへの問い合わせ.
                                                              (line  61)
* sys-setsid:                            システムへの問い合わせ.
                                                              (line  68)
* sys-setuid:                            システムへの問い合わせ.
                                                              (line  38)
* sys-sigmask:                           シグナルのマスクと待機.
                                                              (line  16)
* sys-signal-name:                       シグナルとシグナルセット.
                                                              (line  69)
* sys-sigset-add!:                       シグナルとシグナルセット.
                                                              (line  57)
* sys-sigset-delete!:                    シグナルとシグナルセット.
                                                              (line  58)
* sys-sigset-empty!:                     シグナルとシグナルセット.
                                                              (line  65)
* sys-sigset-fill!:                      シグナルとシグナルセット.
                                                              (line  64)
* sys-sigsuspend:                        シグナルのマスクと待機.
                                                              (line  29)
* sys-sleep:                             その他のシステムコール.
                                                              (line  24)
* sys-srandom:                           その他のシステムコール.
                                                              (line  48)
* sys-stat:                              ファイルの状態.      (line  58)
* sys-stat->atime:                       ファイルの状態.      (line  99)
* sys-stat->ctime:                       ファイルの状態.      (line 101)
* sys-stat->dev:                         ファイルの状態.      (line  93)
* sys-stat->file-type:                   ファイルの状態.      (line 102)
* sys-stat->gid:                         ファイルの状態.      (line  98)
* sys-stat->ino:                         ファイルの状態.      (line  92)
* sys-stat->mode:                        ファイルの状態.      (line  91)
* sys-stat->mtime:                       ファイルの状態.      (line 100)
* sys-stat->nlink:                       ファイルの状態.      (line  95)
* sys-stat->rdev:                        ファイルの状態.      (line  94)
* sys-stat->size:                        ファイルの状態.      (line  96)
* sys-stat->uid:                         ファイルの状態.      (line  97)
* sys-strftime:                          時間.                (line  86)
* sys-symlink:                           ディレクトリ操作.    (line  40)
* sys-syslog:                            Syslog.              (line  43)
* sys-system:                            Unixのプロセス管理.  (line  14)
* sys-tcdrain:                           Termios.             (line  65)
* sys-tcflow:                            Termios.             (line  80)
* sys-tcflush:                           Termios.             (line  68)
* sys-tcgetattr:                         Termios.             (line  40)
* sys-tcgetpgrp:                         Termios.             (line  97)
* sys-tcsendbreak:                       Termios.             (line  60)
* sys-tcsetattr:                         Termios.             (line  44)
* sys-tcsetpgrp:                         Termios.             (line 100)
* sys-time:                              時間.                (line  24)
* sys-times:                             システムへの問い合わせ.
                                                              (line  76)
* sys-tm->alist:                         時間.                (line  95)
* sys-tmpnam:                            ディレクトリ操作.    (line  17)
* sys-ttyname:                           他のファイル操作.    (line  41)
* sys-uid->user-name:                    Unixのグループとユーザ.
                                                              (line  75)
* sys-umask:                             ディレクトリ操作.    (line  64)
* sys-uname:                             システムへの問い合わせ.
                                                              (line   7)
* sys-unlink:                            ディレクトリ操作.    (line  34)
* sys-user-name->uid:                    Unixのグループとユーザ.
                                                              (line  76)
* sys-utime:                             ファイルの状態.      (line 141)
* sys-wait:                              Unixのプロセス管理.  (line 102)
* sys-wait-exit-status:                  Unixのプロセス管理.  (line 129)
* sys-wait-exited?:                      Unixのプロセス管理.  (line 128)
* sys-wait-signaled?:                    Unixのプロセス管理.  (line 135)
* sys-wait-stopped?:                     Unixのプロセス管理.  (line 143)
* sys-wait-stopsig:                      Unixのプロセス管理.  (line 144)
* sys-wait-termsig:                      Unixのプロセス管理.  (line 136)
* sys-waitpid:                           Unixのプロセス管理.  (line 109)
* tabulate-array:                        配列.                (line 185)
* take:                                  SRFI-1 リスト選択子. (line  22)
* take!:                                 SRFI-1 リスト選択子. (line  64)
* take*:                                 その他のリストライブラリ.
                                                              (line  15)
* take-after:                            SXPathの基本的なコンバータとアプリケータ.
                                                              (line 120)
* take-right:                            SRFI-1 リスト選択子. (line  44)
* take-right*:                           その他のリストライブラリ.
                                                              (line  41)
* take-until:                            SXPathの基本的なコンバータとアプリケータ.
                                                              (line 105)
* take-while:                            リストの探索.        (line  15)
* take-while!:                           リストの探索.        (line  16)
* tan:                                   数値の演算.          (line 116)
* tanh:                                  数値の演算.          (line 127)
* temporary-directory:                   ディレクトリユーティリティ.
                                                              (line  20)
* tenth:                                 SRFI-1 リスト選択子. (line  16)
* terminated-thread-exception?:          スレッド例外.        (line  48)
* test:                                  単体テスト.          (line  44)
* test*:                                 単体テスト.          (line  89)
* test-end:                              単体テスト.          (line 111)
* test-module:                           単体テスト.          (line  95)
* test-section:                          単体テスト.          (line 108)
* test-start:                            単体テスト.          (line 104)
* textdomain:                            地域化メッセージ.    (line  34)
* third:                                 SRFI-1 リスト選択子. (line   9)
* thread-join!:                          スレッド手続き.      (line 109)
* thread-name:                           スレッド手続き.      (line  62)
* thread-sleep!:                         スレッド手続き.      (line  80)
* thread-specific:                       スレッド手続き.      (line  65)
* thread-specific-set!:                  スレッド手続き.      (line  66)
* thread-start!:                         スレッド手続き.      (line  70)
* thread-terminate!:                     スレッド手続き.      (line  91)
* thread-yield!:                         スレッド手続き.      (line  75)
* thread?:                               スレッド手続き.      (line  48)
* time:                                  時間の計測.          (line  12)
* time->seconds:                         時間.                (line 125)
* time-counter-reset!:                   時間の計測.          (line  68)
* time-counter-start!:                   時間の計測.          (line  52)
* time-counter-stop!:                    時間の計測.          (line  53)
* time-counter-value:                    時間の計測.          (line  72)
* time-difference:                       時間に関する手続き.  (line  37)
* time-difference!:                      時間に関する手続き.  (line  38)
* time-monotonic->date:                  日付.                (line  85)
* time-monotonic->julian-day:            日付.                (line  86)
* time-monotonic->modified-julian-day:   日付.                (line  87)
* time-monotonic->time-tai:              日付.                (line  88)
* time-monotonic->time-tai!:             日付.                (line  89)
* time-monotonic->time-utc:              日付.                (line  90)
* time-monotonic->time-utc!:             日付.                (line  91)
* time-nanosecond:                       時間に関する手続き.  (line  19)
* time-resolution:                       時間に関する問い合わせ.
                                                              (line  32)
* time-second:                           時間に関する手続き.  (line  18)
* time-tai->date:                        日付.                (line  94)
* time-tai->julian-day:                  日付.                (line  95)
* time-tai->modified-julian-day:         日付.                (line  96)
* time-tai->time-monotonic:              日付.                (line  97)
* time-tai->time-monotonic!:             日付.                (line  98)
* time-tai->time-utc:                    日付.                (line  99)
* time-tai->time-utc!:                   日付.                (line 100)
* time-type:                             時間に関する手続き.  (line  17)
* time-utc->date:                        日付.                (line 103)
* time-utc->julian-day:                  日付.                (line 104)
* time-utc->modified-julian-day:         日付.                (line 105)
* time-utc->time-monotonic:              日付.                (line 106)
* time-utc->time-monotonic!:             日付.                (line 107)
* time-utc->time-tai:                    日付.                (line 108)
* time-utc->time-tai!:                   日付.                (line 109)
* time<=?:                               時間に関する手続き.  (line  31)
* time<?:                                時間に関する手続き.  (line  30)
* time=?:                                時間に関する手続き.  (line  29)
* time>=?:                               時間に関する手続き.  (line  33)
* time>?:                                時間に関する手続き.  (line  32)
* time?:                                 時間.                (line 121)
* topological-sort:                      トポロジカルソート.  (line  10)
* touch-file:                            ファイル操作.        (line   7)
* tr:                                    文字変換.            (line  16)
* tree->string:                          怠惰なテキスト構築.  (line  44)
* truncate:                              数値の演算.          (line  90)
* u16vector:                             ユニフォームベクタの基本操作.
                                                              (line  19)
* u16vector->list:                       ユニフォームベクタの変換.
                                                              (line   7)
* u16vector->vector:                     ユニフォームベクタの変換.
                                                              (line  19)
* u16vector-add:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u16vector-add!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u16vector-and:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u16vector-and!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u16vector-clamp:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* u16vector-clamp!:                      ユニフォームベクタの数値演算.
                                                              (line  96)
* u16vector-copy:                        ユニフォームベクタの基本操作.
                                                              (line  75)
* u16vector-copy!:                       ユニフォームベクタの基本操作.
                                                              (line  84)
* u16vector-dot:                         ユニフォームベクタの数値演算.
                                                              (line  60)
* u16vector-ior:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u16vector-ior!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u16vector-length:                      ユニフォームベクタの基本操作.
                                                              (line  32)
* u16vector-mul:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u16vector-mul!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u16vector-range-check:                 ユニフォームベクタの数値演算.
                                                              (line  64)
* u16vector-ref:                         ユニフォームベクタの基本操作.
                                                              (line  43)
* u16vector-set!:                        ユニフォームベクタの基本操作.
                                                              (line  57)
* u16vector-sub:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u16vector-sub!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u16vector-xor:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u16vector-xor!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u16vector?:                            ユニフォームベクタの基本操作.
                                                              (line  16)
* u32vector:                             ユニフォームベクタの基本操作.
                                                              (line  19)
* u32vector->list:                       ユニフォームベクタの変換.
                                                              (line   7)
* u32vector->string:                     ユニフォームベクタの変換.
                                                              (line 106)
* u32vector->vector:                     ユニフォームベクタの変換.
                                                              (line  19)
* u32vector-add:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u32vector-add!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u32vector-and:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u32vector-and!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u32vector-clamp:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* u32vector-clamp!:                      ユニフォームベクタの数値演算.
                                                              (line  96)
* u32vector-copy:                        ユニフォームベクタの基本操作.
                                                              (line  75)
* u32vector-copy!:                       ユニフォームベクタの基本操作.
                                                              (line  84)
* u32vector-dot:                         ユニフォームベクタの数値演算.
                                                              (line  60)
* u32vector-ior:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u32vector-ior!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u32vector-length:                      ユニフォームベクタの基本操作.
                                                              (line  32)
* u32vector-mul:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u32vector-mul!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u32vector-range-check:                 ユニフォームベクタの数値演算.
                                                              (line  64)
* u32vector-ref:                         ユニフォームベクタの基本操作.
                                                              (line  43)
* u32vector-set!:                        ユニフォームベクタの基本操作.
                                                              (line  57)
* u32vector-sub:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u32vector-sub!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u32vector-xor:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u32vector-xor!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u32vector?:                            ユニフォームベクタの基本操作.
                                                              (line  16)
* u64vector:                             ユニフォームベクタの基本操作.
                                                              (line  19)
* u64vector->list:                       ユニフォームベクタの変換.
                                                              (line   7)
* u64vector->vector:                     ユニフォームベクタの変換.
                                                              (line  19)
* u64vector-add:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u64vector-add!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u64vector-and:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u64vector-and!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u64vector-clamp:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* u64vector-clamp!:                      ユニフォームベクタの数値演算.
                                                              (line  96)
* u64vector-copy:                        ユニフォームベクタの基本操作.
                                                              (line  75)
* u64vector-copy!:                       ユニフォームベクタの基本操作.
                                                              (line  84)
* u64vector-dot:                         ユニフォームベクタの数値演算.
                                                              (line  60)
* u64vector-ior:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u64vector-ior!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u64vector-length:                      ユニフォームベクタの基本操作.
                                                              (line  32)
* u64vector-mul:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u64vector-mul!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u64vector-range-check:                 ユニフォームベクタの数値演算.
                                                              (line  64)
* u64vector-ref:                         ユニフォームベクタの基本操作.
                                                              (line  43)
* u64vector-set!:                        ユニフォームベクタの基本操作.
                                                              (line  57)
* u64vector-sub:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u64vector-sub!:                        ユニフォームベクタの数値演算.
                                                              (line  12)
* u64vector-xor:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u64vector-xor!:                        ユニフォームベクタの数値演算.
                                                              (line  49)
* u64vector?:                            ユニフォームベクタの基本操作.
                                                              (line  16)
* u8vector:                              ユニフォームベクタの基本操作.
                                                              (line  19)
* u8vector->list:                        ユニフォームベクタの変換.
                                                              (line   7)
* u8vector->string:                      ユニフォームベクタの変換.
                                                              (line  87)
* u8vector->vector:                      ユニフォームベクタの変換.
                                                              (line  19)
* u8vector-add:                          ユニフォームベクタの数値演算.
                                                              (line  12)
* u8vector-add!:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u8vector-and:                          ユニフォームベクタの数値演算.
                                                              (line  49)
* u8vector-and!:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u8vector-clamp:                        ユニフォームベクタの数値演算.
                                                              (line  96)
* u8vector-clamp!:                       ユニフォームベクタの数値演算.
                                                              (line  96)
* u8vector-copy:                         ユニフォームベクタの基本操作.
                                                              (line  75)
* u8vector-copy!:                        ユニフォームベクタの基本操作.
                                                              (line  84)
* u8vector-dot:                          ユニフォームベクタの数値演算.
                                                              (line  60)
* u8vector-ior:                          ユニフォームベクタの数値演算.
                                                              (line  49)
* u8vector-ior!:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u8vector-length:                       ユニフォームベクタの基本操作.
                                                              (line  32)
* u8vector-mul:                          ユニフォームベクタの数値演算.
                                                              (line  12)
* u8vector-mul!:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u8vector-range-check:                  ユニフォームベクタの数値演算.
                                                              (line  64)
* u8vector-ref:                          ユニフォームベクタの基本操作.
                                                              (line  43)
* u8vector-set!:                         ユニフォームベクタの基本操作.
                                                              (line  57)
* u8vector-sub:                          ユニフォームベクタの数値演算.
                                                              (line  12)
* u8vector-sub!:                         ユニフォームベクタの数値演算.
                                                              (line  12)
* u8vector-xor:                          ユニフォームベクタの数値演算.
                                                              (line  49)
* u8vector-xor!:                         ユニフォームベクタの数値演算.
                                                              (line  49)
* u8vector?:                             ユニフォームベクタの基本操作.
                                                              (line  16)
* ucs->char:                             文字.                (line 108)
* ucs-range->char-set:                   文字セットの構築子.  (line  29)
* ucs-range->char-set!:                  文字セットの構築子.  (line  30)
* uncaught-exception-reason:             スレッド例外.        (line  54)
* uncaught-exception?:                   スレッド例外.        (line  49)
* unfold:                                リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  59)
* unfold-right:                          リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map).
                                                              (line  72)
* unless:                                条件式.              (line 100)
* unpack:                                バイナリデータのパック.
                                                              (line 150)
* unpack-skip:                           バイナリデータのパック.
                                                              (line 178)
* unwrap-syntax:                         マクロユーティリティ.
                                                              (line  30)
* unzip1:                                種々のリスト処理ルーチン.
                                                              (line  39)
* unzip2:                                種々のリスト処理ルーチン.
                                                              (line  40)
* unzip3:                                種々のリスト処理ルーチン.
                                                              (line  41)
* unzip4:                                種々のリスト処理ルーチン.
                                                              (line  42)
* unzip5:                                種々のリスト処理ルーチン.
                                                              (line  43)
* update!:                               代入.                (line 133)
* uri-compose:                           URIの解析と作成.     (line  78)
* uri-decode:                            URIの解析と作成.     (line 114)
* uri-decode-string:                     URIの解析と作成.     (line 115)
* uri-decompose-authority:               URIの解析と作成.     (line  14)
* uri-decompose-hierarchical:            URIの解析と作成.     (line  13)
* uri-encode:                            URIの解析と作成.     (line 124)
* uri-encode-string:                     URIの解析と作成.     (line 125)
* uri-parse:                             URIの解析と作成.     (line  11)
* uri-scheme&specific:                   URIの解析と作成.     (line  12)
* use:                                   モジュールの使用.    (line  27)
* uvector-alias:                         ユニフォームベクタの変換.
                                                              (line 113)
* values:                                多値.                (line   7)
* values-ref:                            多値.                (line  20)
* vector:                                ベクター.            (line  28)
* vector->f32vector:                     ユニフォームベクタの変換.
                                                              (line  44)
* vector->f64vector:                     ユニフォームベクタの変換.
                                                              (line  44)
* vector->list:                          ベクター.            (line  54)
* vector->s16vector:                     ユニフォームベクタの変換.
                                                              (line  44)
* vector->s32vector:                     ユニフォームベクタの変換.
                                                              (line  44)
* vector->s64vector:                     ユニフォームベクタの変換.
                                                              (line  44)
* vector->s8vector:                      ユニフォームベクタの変換.
                                                              (line  44)
* vector->u16vector:                     ユニフォームベクタの変換.
                                                              (line  44)
* vector->u32vector:                     ユニフォームベクタの変換.
                                                              (line  44)
* vector->u64vector:                     ユニフォームベクタの変換.
                                                              (line  44)
* vector->u8vector:                      ユニフォームベクタの変換.
                                                              (line  44)
* vector-copy:                           ベクター.            (line  77)
* vector-ec:                             Eager comprehensions.
                                                              (line  90)
* vector-fill!:                          ベクター.            (line  69)
* vector-length:                         ベクター.            (line  31)
* vector-of-length-ec:                   Eager comprehensions.
                                                              (line  93)
* vector-ref:                            ベクター.            (line  37)
* vector-set!:                           ベクター.            (line  47)
* vector?:                               ベクター.            (line  20)
* version-compare:                       バージョン番号の比較.
                                                              (line  94)
* version<=?:                            バージョン番号の比較.
                                                              (line  87)
* version<?:                             バージョン番号の比較.
                                                              (line  86)
* version=?:                             バージョン番号の比較.
                                                              (line  85)
* version>=?:                            バージョン番号の比較.
                                                              (line  89)
* version>?:                             バージョン番号の比較.
                                                              (line  88)
* weak-vector-length:                    Weak ポインタ.       (line  42)
* weak-vector-ref:                       Weak ポインタ.       (line  45)
* weak-vector-set!:                      Weak ポインタ.       (line  55)
* when:                                  条件式.              (line  99)
* with-builder:                          基礎的なイテレータ構築メソッド.
                                                              (line  95)
* with-error-handler:                    例外の処理.          (line  43)
* with-error-to-port:                    ポート共通の操作.    (line  33)
* with-exception-handler:                例外の処理.          (line  94)
* with-input-conversion:                 変換ポート.          (line 113)
* with-input-from-file <1>:              拡張されたポート手続き.
                                                              (line  12)
* with-input-from-file:                  ファイルポート.      (line 138)
* with-input-from-port:                  ポート共通の操作.    (line  31)
* with-input-from-process:               Process ports.       (line  69)
* with-input-from-string:                文字列ポート.        (line  53)
* with-iterator:                         基礎的なイテレータ構築メソッド.
                                                              (line  42)
* with-locking-mutex:                    同期プリミティブ.    (line 144)
* with-module:                           モジュールの定義と選択.
                                                              (line  20)
* with-output-conversion:                変換ポート.          (line 115)
* with-output-to-file <1>:               拡張されたポート手続き.
                                                              (line  18)
* with-output-to-file:                   ファイルポート.      (line 140)
* with-output-to-port:                   ポート共通の操作.    (line  32)
* with-output-to-process:                Process ports.       (line 109)
* with-output-to-string:                 文字列ポート.        (line  54)
* with-port-locking:                     ポートとスレッド.    (line  26)
* with-signal-handlers:                  シグナルの処理.      (line  80)
* with-string-io:                        文字列ポート.        (line  75)
* with-time-counter:                     時間の計測.          (line  76)
* wrap-with-input-conversion:            変換ポート.          (line 122)
* wrap-with-output-conversion:           変換ポート.          (line 124)
* write:                                 出力.                (line  10)
* write*:                                出力.                (line  26)
* write-block:                           ユニフォームベクタのブロック入出力.
                                                              (line  44)
* write-byte:                            出力.                (line  78)
* write-char:                            出力.                (line  75)
* write-object:                          出力.                (line  58)
* write-to-string:                       文字列ポート.        (line  88)
* write-tree:                            怠惰なテキスト構築.  (line  39)
* write-with-shared-structure:           出力.                (line  24)
* write/ss:                              出力.                (line  25)
* x->integer:                            数値の変換.          (line  80)
* x->number:                             数値の変換.          (line  79)
* x->string:                             文字列の作成.        (line  32)
* xcons:                                 SRFI-1 リスト構築子. (line   7)
* xml-token-head:                        SSAXデータタイプ.    (line 144)
* xml-token-kind:                        SSAXデータタイプ.    (line 143)
* xml-token?:                            SSAXデータタイプ.    (line 140)
* xsubstring:                            文字列のローテーション.
                                                              (line   7)
* zero?:                                 数値に関する述語.    (line  37)
* zip:                                   種々のリスト処理ルーチン.
                                                              (line  23)


File: gauche-refj.info,  Node: Index - モジュール索引,  Next: Index - クラス索引,  Prev: Index - 手続きと構文索引,  Up: Top

Appendix D Index - モジュール索引
*********************************

[index]
* Menu:

* binary.pack:                           バイナリデータのパック.
                                                               (line  7)
* dbm:                                   汎用DBMインタフェース.
                                                               (line  7)
* dbm.fsdbm:                             ファイルシステムdbm.  (line  7)
* dbm.gdbm:                              GDBMインタフェース.   (line  7)
* dbm.ndbm:                              NDBMインタフェース.   (line  7)
* dbm.odbm:                              オリジナルのDBMインタフェース.
                                                               (line  7)
* file.filter:                           ファイルのフィルタ.   (line  7)
* file.util:                             ファイルシステムユーティリティ.
                                                               (line  7)
* gauche:                                組み込みモジュール.   (line 22)
* gauche.array:                          配列.                 (line  7)
* gauche.charconv:                       文字コード変換.       (line  7)
* gauche.collection:                     コレクションフレームワーク.
                                                               (line  7)
* gauche.config:                         コンフィグレーション情報.
                                                               (line  7)
* gauche.fcntl:                          低レベルファイル操作. (line  7)
* gauche.hook:                           フック.               (line  7)
* gauche.interactive:                    インタラクティブセッション.
                                                               (line  7)
* gauche.listener:                       リスナー.             (line  7)
* gauche.logger:                         ユーザレベルのロギング.
                                                               (line  7)
* gauche.mop.singleton:                  シングルトン.         (line  7)
* gauche.mop.validator:                  Validator付きスロット.
                                                               (line  7)
* gauche.net:                            ネットワーキング.     (line  7)
* gauche.parameter:                      パラメータ.           (line  7)
* gauche.parseopt:                       コマンドライン引数の解析.
                                                               (line  7)
* gauche.process:                        高レベルプロセスインタフェース.
                                                               (line  7)
* gauche.regexp:                         正規表現ユーティリティ.
                                                               (line  7)
* gauche.reload:                         モジュールの再ロード. (line  7)
* gauche.selector:                       簡単なディスパッチャ. (line  7)
* gauche.sequence:                       シーケンスフレームワーク.
                                                               (line  7)
* gauche.syslog:                         Syslog.               (line  7)
* gauche.termios:                        Termios.              (line  7)
* gauche.test:                           単体テスト.           (line  7)
* gauche.threads:                        スレッド.             (line 10)
* gauche.time:                           時間の計測.           (line  7)
* gauche.uvector:                        ユニフォームベクタ.   (line  7)
* gauche.version:                        バージョン番号の比較. (line  7)
* gauche.vport:                          仮想ポート.           (line  7)
* math.const:                            定数.                 (line  7)
* math.mt-random:                        Mersenne Twister乱数発生器.
                                                               (line  7)
* null:                                  組み込みモジュール.   (line  9)
* rfc.822:                               RFC822メッセージ形式. (line  7)
* rfc.base64:                            Base64エンコーディング.
                                                               (line  7)
* rfc.cookie:                            HTTPクッキー.         (line  7)
* rfc.hmac:                              HMAC鍵付きハッシング. (line  7)
* rfc.http:                              HTTP.                 (line  7)
* rfc.md5:                               MD5メッセージダイジェスト.
                                                               (line  7)
* rfc.mime:                              MIMEメッセージ処理.   (line  7)
* rfc.quoted-printable:                  Quoted-printableエンコーディング.
                                                               (line  7)
* rfc.sha1:                              SHA1メッセージダイジェスト.
                                                               (line  7)
* rfc.uri:                               URIの解析と作成.      (line  7)
* scheme:                                組み込みモジュール.   (line 14)
* slib:                                  SLIBインタフェース.   (line  7)
* srfi-0:                                機能条件式.           (line  7)
* srfi-1:                                List library.         (line  7)
* srfi-11:                               Let-values.           (line  7)
* srfi-13:                               文字列ライブラリ.     (line  7)
* srfi-14:                               文字集合ライブラリ.   (line  7)
* srfi-2:                                And-let*.             (line  7)
* srfi-27:                               ランダムビットのソース.
                                                               (line  7)
* srfi-29:                               地域化.               (line  7)
* srfi-29.bundle:                        地域化.               (line  7)
* srfi-29.format:                        地域化.               (line  7)
* srfi-37:                               args-fold プログラム引数処理.
                                                               (line  7)
* srfi-4:                                単一型のベクタ.       (line  7)
* srfi-42:                               Eager comprehensions. (line  7)
* srfi-5:                                シグネチャとrest引数に互換性のあるlet形式.
                                                               (line  7)
* srfi-55:                               Requiring extensions. (line  7)
* srfi-7:                                機能ベースプログラム設定言語.
                                                               (line  7)
* srfi-9:                                レコード型.           (line  7)
* sxml.ssax:                             関数的なXMLパーザ.    (line  7)
* sxml.sxpath:                           SXMLクエリ言語.       (line  7)
* sxml.tools:                            SXML構造を操作する.   (line  7)
* text.csv:                              CSVテーブル.          (line  7)
* text.diff:                             テキストストリームの相違点を計算する.
                                                               (line  7)
* text.gettext:                          地域化メッセージ.     (line  7)
* text.html-lite:                        シンプルなHTMLドキュメントの構築.
                                                               (line  7)
* text.parse:                            入力ストリームのパージング.
                                                               (line  7)
* text.tr:                               文字変換.             (line  7)
* text.tree:                             怠惰なテキスト構築.   (line  7)
* user:                                  組み込みモジュール.   (line 26)
* util.combinations:                     組み合わせ.           (line  7)
* util.digest:                           メッセージダイジェストフレームワーク.
                                                               (line  7)
* util.isomorph:                         同型判定.             (line  7)
* util.lcs:                              最長共通サブシーケンス.
                                                               (line  7)
* util.list:                             その他のリストライブラリ.
                                                               (line  7)
* util.match:                            パターンマッチング.   (line  7)
* util.queue:                            キュー.               (line  7)
* util.record:                           SLIB-互換のレコード型.
                                                               (line  7)
* util.toposort:                         トポロジカルソート.   (line  7)
* www.cgi:                               CGIユーティリティ.    (line  7)
* www.cgi-test:                          CGIのテスト.          (line  7)


File: gauche-refj.info,  Node: Index - クラス索引,  Next: Index - 変数索引,  Prev: Index - モジュール索引,  Up: Top

Appendix E Index - クラス索引
*****************************

For readability, the surrounding `<' and `>' are stripped off.

[index]
* Menu:

* abandoned-mutex-exception:             スレッド例外.        (line  22)
* array:                                 配列.                (line  55)
* array-base:                            配列.                (line  41)
* boolean:                               論理値.              (line   7)
* buffered-input-port:                   仮想ポート.          (line 208)
* buffered-output-port:                  仮想ポート.          (line 265)
* char:                                  文字.                (line   7)
* char-set:                              文字集合.            (line   7)
* class:                                 クラスのインスタンシエーション.
                                                              (line  80)
* complex:                               数値クラス.          (line  10)
* compound-condition:                    コンディション.      (line  50)
* condition:                             コンディション.      (line  47)
* condition-meta:                        コンディション.      (line  39)
* condition-variable:                    同期プリミティブ.    (line 152)
* date:                                  日付.                (line   7)
* dbm:                                   DBMデータベースのオープンとクローズ.
                                                              (line   7)
* dbm-meta:                              DBMデータベースのオープンとクローズ.
                                                              (line  61)
* error:                                 コンディション.      (line  85)
* f32array:                              配列.                (line  55)
* f32vector:                             ユニフォームベクタの基本操作.
                                                              (line   7)
* f64array:                              配列.                (line  55)
* f64vector:                             ユニフォームベクタの基本操作.
                                                              (line   7)
* fsdbm:                                 ファイルシステムdbm. (line  10)
* gdbm:                                  GDBMインタフェース.  (line  10)
* hash-table:                            ハッシュテーブル.    (line   7)
* hmac:                                  HMAC鍵付きハッシング.
                                                              (line  16)
* hook:                                  フック.              (line  26)
* identifier:                            Identifier.          (line   7)
* integer:                               数値クラス.          (line  10)
* io-closed-error:                       コンディション.      (line 165)
* io-error:                              コンディション.      (line 143)
* io-read-error:                         コンディション.      (line 155)
* io-unit-error:                         コンディション.      (line 170)
* io-write-error:                        コンディション.      (line 160)
* join-timeout-exception:                スレッド例外.        (line  18)
* keyword:                               キーワード.          (line   7)
* list:                                  pairクラスとnullクラス.
                                                              (line   7)
* log-drain:                             ユーザレベルのロギング.
                                                              (line  16)
* md5:                                   MD5メッセージダイジェスト.
                                                              (line  13)
* mersenne-twister:                      Mersenne Twister乱数発生器.
                                                              (line  14)
* message-condition:                     コンディション.      (line  75)
* message-digest-algorithm:              メッセージダイジェストフレームワーク.
                                                              (line  16)
* message-digest-algorithm-meta:         メッセージダイジェストフレームワーク.
                                                              (line  13)
* mime-message:                          MIMEメッセージ処理.  (line 104)
* module:                                モジュールイントロスペクション.
                                                              (line  14)
* mutex:                                 同期プリミティブ.    (line   7)
* ndbm:                                  NDBMインタフェース.  (line  11)
* null:                                  pairクラスとnullクラス.
                                                              (line  17)
* number:                                数値クラス.          (line  10)
* odbm:                                  オリジナルのDBMインタフェース.
                                                              (line  10)
* pair:                                  pairクラスとnullクラス.
                                                              (line  20)
* parameter:                             パラメータ.          (line  35)
* port:                                  ポート.              (line   7)
* port-error:                            コンディション.      (line 148)
* procedure:                             手続き.              (line   7)
* process:                               Process object.      (line   7)
* process-time-counter:                  時間の計測.          (line  48)
* read-error:                            コンディション.      (line 119)
* real:                                  数値クラス.          (line  10)
* real-time-counter:                     時間の計測.          (line  48)
* regexp:                                正規表現.            (line  11)
* regmatch:                              正規表現.            (line  18)
* s16array:                              配列.                (line  55)
* s16vector:                             ユニフォームベクタの基本操作.
                                                              (line   7)
* s32array:                              配列.                (line  55)
* s32vector:                             ユニフォームベクタの基本操作.
                                                              (line   7)
* s64array:                              配列.                (line  55)
* s64vector:                             ユニフォームベクタの基本操作.
                                                              (line   7)
* s8array:                               配列.                (line  55)
* s8vector:                              ユニフォームベクタの基本操作.
                                                              (line   7)
* selector:                              簡単なディスパッチャ.
                                                              (line  12)
* serious-compound-condition:            コンディション.      (line  66)
* serious-condition:                     コンディション.      (line  60)
* sha1:                                  SHA1メッセージダイジェスト.
                                                              (line  13)
* singleton-meta:                        シングルトン.        (line  10)
* singleton-mixin:                       シングルトン.        (line  30)
* sockaddr:                              ソケットアドレス.    (line   7)
* sockaddr-in:                           ソケットアドレス.    (line  20)
* sockaddr-in6:                          ソケットアドレス.    (line  61)
* sockaddr-un:                           ソケットアドレス.    (line  49)
* socket:                                高レベルネットワーク手続き.
                                                              (line   7)
* string:                                文字列.              (line   7)
* string-pointer:                        文字列ポインタ.      (line   7)
* symbol:                                シンボル.            (line   7)
* sys-addrinfo:                          Netdbインタフェース. (line 120)
* sys-fdset:                             I/Oの多重化.         (line  11)
* sys-flock:                             低レベルファイル操作.
                                                              (line 111)
* sys-group:                             Unixのグループとユーザ.
                                                              (line  10)
* sys-hostent:                           Netdbインタフェース. (line   7)
* sys-passwd:                            Unixのグループとユーザ.
                                                              (line  40)
* sys-protoent:                          Netdbインタフェース. (line  85)
* sys-servent:                           Netdbインタフェース. (line  44)
* sys-sigset:                            シグナルとシグナルセット.
                                                              (line  53)
* sys-stat:                              ファイルの状態.      (line  19)
* sys-termios:                           Termios.             (line  12)
* sys-tm:                                時間.                (line  37)
* system-error:                          コンディション.      (line 103)
* system-time-counter:                   時間の計測.          (line  48)
* terminated-thread-exception:           スレッド例外.        (line  30)
* thread:                                スレッド手続き.      (line   7)
* thread-exception:                      スレッド例外.        (line  11)
* time:                                  時間.                (line 103)
* time-counter:                          時間の計測.          (line  33)
* u16array:                              配列.                (line  55)
* u16vector:                             ユニフォームベクタの基本操作.
                                                              (line   7)
* u32array:                              配列.                (line  55)
* u32vector:                             ユニフォームベクタの基本操作.
                                                              (line   7)
* u64array:                              配列.                (line  55)
* u64vector:                             ユニフォームベクタの基本操作.
                                                              (line   7)
* u8array:                               配列.                (line  55)
* u8vector:                              ユニフォームベクタの基本操作.
                                                              (line   7)
* uncaught-exception:                    スレッド例外.        (line  38)
* user-time-counter:                     時間の計測.          (line  48)
* validator-meta:                        Validator付きスロット.
                                                              (line  10)
* vector:                                ベクター.            (line   7)
* virtual-input-port:                    仮想ポート.          (line  30)
* virtual-output-port:                   仮想ポート.          (line 133)
* weak-vector:                           Weak ポインタ.       (line  30)


File: gauche-refj.info,  Node: Index - 変数索引,  Prev: Index - クラス索引,  Up: Top

Appendix F Index - 変数索引
***************************

[index]
* Menu:

* :                                      日付.                (line  13)
* &condition:                            コンディション.      (line  47)
* &error:                                コンディション.      (line  85)
* &io-closed-error:                      コンディション.      (line 165)
* &io-error:                             コンディション.      (line 143)
* &io-port-error:                        コンディション.      (line 148)
* &io-read-error:                        コンディション.      (line 155)
* &io-write-error:                       コンディション.      (line 160)
* &read-error:                           コンディション.      (line 119)
* &serious:                              コンディション.      (line  60)
* *argv*:                                Schemeスクリプトを書く.
                                                              (line  41)
* *load-path*:                           Schemeファイルのロード.
                                                              (line  45)
* *program-name*:                        Schemeスクリプトを書く.
                                                              (line  50)
* *rfc822-atext-chars*:                  RFC822メッセージ形式.
                                                              (line 128)
* *rfc822-standard-tokenizers*:          RFC822メッセージ形式.
                                                              (line 131)
* *test-error*:                          単体テスト.          (line  67)
* *test-report-error*:                   単体テスト.          (line  75)
* 1/pi:                                  定数.                (line  14)
* 180/pi:                                定数.                (line  15)
* accessors:                             クラスのインスタンシエーション.
                                                              (line 100)
* addr:                                  Netdbインタフェース. (line 136)
* addresses:                             Netdbインタフェース. (line  17)
* addrlen:                               Netdbインタフェース. (line 134)
* AF_INET:                               低レベルソケットインタフェース.
                                                              (line  19)
* AF_UNIX:                               低レベルソケットインタフェース.
                                                              (line  18)
* aliases:                               Netdbインタフェース. (line  51)
* atime:                                 ファイルの状態.      (line  52)
* bsize:                                 GDBMインタフェース.  (line  21)
* category:                              クラスのインスタンシエーション.
                                                              (line 136)
* cc:                                    Termios.             (line  23)
* cflag:                                 Termios.             (line  19)
* char-set:ascii:                        定義済みの文字セット.
                                                              (line  40)
* char-set:blank:                        定義済みの文字セット.
                                                              (line  10)
* char-set:digit:                        定義済みの文字セット.
                                                              (line  16)
* char-set:empty:                        定義済みの文字セット.
                                                              (line  43)
* char-set:full:                         定義済みの文字セット.
                                                              (line  46)
* char-set:graphic:                      定義済みの文字セット.
                                                              (line  20)
* char-set:hex-digit:                    定義済みの文字セット.
                                                              (line  17)
* char-set:iso-control:                  定義済みの文字セット.
                                                              (line  13)
* char-set:letter:                       定義済みの文字セット.
                                                              (line   7)
* char-set:lower-case:                   定義済みの文字セット.
                                                              (line  23)
* char-set:printing:                     定義済みの文字セット.
                                                              (line  28)
* char-set:punctuation:                  定義済みの文字セット.
                                                              (line  31)
* char-set:symbol:                       定義済みの文字セット.
                                                              (line  37)
* char-set:title-case:                   定義済みの文字セット.
                                                              (line  25)
* char-set:upper-case:                   定義済みの文字セット.
                                                              (line  24)
* char-set:whitespace:                   定義済みの文字セット.
                                                              (line  34)
* class:                                 Unixのグループとユーザ.
                                                              (line  65)
* close:                                 仮想ポート.          (line 279)
* column:                                コンディション.      (line 134)
* content:                               MIMEメッセージ処理.  (line 138)
* cpl:                                   クラスのインスタンシエーション.
                                                              (line  92)
* ctime:                                 ファイルの状態.      (line  54)
* default-random-source:                 ランダムビットのソース.
                                                              (line  25)
* defined-modules:                       クラスのインスタンシエーション.
                                                              (line 129)
* dev:                                   ファイルの状態.      (line  44)
* dir:                                   Unixのグループとユーザ.
                                                              (line  59)
* direct-methods:                        クラスのインスタンシエーション.
                                                              (line 120)
* direct-slots:                          クラスのインスタンシエーション.
                                                              (line 109)
* direct-subclasses:                     クラスのインスタンシエーション.
                                                              (line 116)
* direct-supers:                         クラスのインスタンシエーション.
                                                              (line  96)
* e:                                     定数.                (line  18)
* environment:                           リスナー.            (line  68)
* errno:                                 コンディション.      (line 110)
* error-handler:                         リスナー.            (line  77)
* error-port:                            リスナー.            (line  45)
* evaluator:                             リスナー.            (line  53)
* F_DUPFD:                               低レベルファイル操作.
                                                              (line  71)
* F_GETFD:                               低レベルファイル操作.
                                                              (line  22)
* F_GETFL:                               低レベルファイル操作.
                                                              (line  39)
* F_GETLK:                               低レベルファイル操作.
                                                              (line  77)
* F_GETOWN:                              低レベルファイル操作.
                                                              (line  91)
* F_OK:                                  ファイルの状態.      (line 122)
* F_RDLCK:                               低レベルファイル操作.
                                                              (line 123)
* F_SETFD:                               低レベルファイル操作.
                                                              (line  31)
* F_SETFL:                               低レベルファイル操作.
                                                              (line  58)
* F_SETLK:                               低レベルファイル操作.
                                                              (line  83)
* F_SETLKW:                              低レベルファイル操作.
                                                              (line  83)
* F_SETOWN:                              低レベルファイル操作.
                                                              (line  99)
* F_UNLCK:                               低レベルファイル操作.
                                                              (line 129)
* F_WRLCK:                               低レベルファイル操作.
                                                              (line 126)
* family:                                Netdbインタフェース. (line 128)
* FD_CLOEXEC:                            低レベルファイル操作.
                                                              (line  22)
* file-mode:                             DBMデータベースのオープンとクローズ.
                                                              (line  33)
* filenum:                               仮想ポート.          (line 282)
* fill:                                  仮想ポート.          (line 214)
* finalizer:                             リスナー.            (line  72)
* flags:                                 Netdbインタフェース. (line 126)
* flush:                                 仮想ポート.          (line 170)
* GDBM_CACHESIZE:                        GDBMインタフェース.  (line  70)
* GDBM_CENTFREE:                         GDBMインタフェース.  (line  76)
* GDBM_COALESCEBLKS:                     GDBMインタフェース.  (line  78)
* GDBM_FAST:                             GDBMインタフェース.  (line  37)
* GDBM_FASTMODE:                         GDBMインタフェース.  (line  72)
* GDBM_INSERT:                           GDBMインタフェース.  (line  48)
* GDBM_NEWDB:                            GDBMインタフェース.  (line  35)
* GDBM_NOLOCK:                           GDBMインタフェース.  (line  41)
* GDBM_READER:                           GDBMインタフェース.  (line  29)
* GDBM_REPLACE:                          GDBMインタフェース.  (line  50)
* GDBM_SYNC:                             GDBMインタフェース.  (line  39)
* GDBM_SYNCMODE:                         GDBMインタフェース.  (line  74)
* GDBM_WRCREAT:                          GDBMインタフェース.  (line  33)
* GDBM_WRITER:                           GDBMインタフェース.  (line  31)
* gecos:                                 Unixのグループとユーザ.
                                                              (line  56)
* getb:                                  仮想ポート.          (line  38)
* getc:                                  仮想ポート.          (line  52)
* gets:                                  仮想ポート.          (line  66)
* gid <1>:                               Unixのグループとユーザ.
                                                              (line  16)
* gid <2>:                               ファイルの状態.      (line  48)
* gid:                                   Unixのグループとユーザ.
                                                              (line  49)
* headers:                               MIMEメッセージ処理.  (line 127)
* hour:                                  時間.                (line  47)
* iflag:                                 Termios.             (line  15)
* index:                                 MIMEメッセージ処理.  (line 135)
* initargs:                              クラスのインスタンシエーション.
                                                              (line 124)
* ino:                                   ファイルの状態.      (line  43)
* input-port:                            リスナー.            (line  37)
* isdst:                                 時間.                (line  65)
* key-convert:                           DBMデータベースのオープンとクローズ.
                                                              (line  37)
* LC_ALL:                                ロケール.            (line  14)
* LC_COLLATE:                            ロケール.            (line  15)
* LC_CTYPE:                              ロケール.            (line  16)
* LC_MONETARY:                           ロケール.            (line  17)
* LC_NUMERIC:                            ロケール.            (line  18)
* LC_TIME:                               ロケール.            (line  19)
* len:                                   低レベルファイル操作.
                                                              (line 139)
* lflag:                                 Termios.             (line  21)
* line:                                  コンディション.      (line 129)
* lock-policy:                           ユーザレベルのロギング.
                                                              (line  81)
* mday:                                  時間.                (line  50)
* mem:                                   Unixのグループとユーザ.
                                                              (line  22)
* message:                               コンディション.      (line  80)
* min:                                   時間.                (line  44)
* mode:                                  ファイルの状態.      (line  42)
* mon:                                   時間.                (line  53)
* MSG_CTRUNC:                            低レベルソケットインタフェース.
                                                              (line 118)
* MSG_DONTROUTE:                         低レベルソケットインタフェース.
                                                              (line 119)
* MSG_EOR:                               低レベルソケットインタフェース.
                                                              (line 120)
* MSG_OOB:                               低レベルソケットインタフェース.
                                                              (line 121)
* MSG_PEEK:                              低レベルソケットインタフェース.
                                                              (line 122)
* MSG_TRUNC:                             低レベルソケットインタフェース.
                                                              (line 123)
* MSG_WAITALL:                           低レベルソケットインタフェース.
                                                              (line 124)
* mtime:                                 ファイルの状態.      (line  53)
* mutex:                                 スレッド例外.        (line  27)
* name <1>:                              Unixのグループとユーザ.
                                                              (line  13)
* name <2>:                              Netdbインタフェース. (line  89)
* name <3>:                              クラスのインスタンシエーション.
                                                              (line  88)
* name <4>:                              スレッド手続き.      (line  37)
* name <5>:                              同期プリミティブ.    (line 161)
* name:                                  Unixのグループとユーザ.
                                                              (line  43)
* nanosecond:                            時間.                (line 112)
* nlink:                                 ファイルの状態.      (line  46)
* nolock:                                GDBMインタフェース.  (line  19)
* num-instance-slots:                    クラスのインスタンシエーション.
                                                              (line 113)
* O_ACCMODE:                             低レベルファイル操作.
                                                              (line  42)
* O_APPEND:                              低レベルファイル操作.
                                                              (line  48)
* O_CREAT:                               低レベルファイル操作.
                                                              (line  45)
* O_EXCL:                                低レベルファイル操作.
                                                              (line  45)
* O_NOCTTY:                              低レベルファイル操作.
                                                              (line  53)
* O_NONBLOCK:                            低レベルファイル操作.
                                                              (line  50)
* O_RDONLY:                              低レベルファイル操作.
                                                              (line  42)
* O_RDWR:                                低レベルファイル操作.
                                                              (line  42)
* O_TRUNC:                               低レベルファイル操作.
                                                              (line  45)
* O_WRONLY:                              低レベルファイル操作.
                                                              (line  42)
* oflag:                                 Termios.             (line  17)
* output-port:                           リスナー.            (line  41)
* parameters:                            MIMEメッセージ処理.  (line 119)
* parent:                                MIMEメッセージ処理.  (line 130)
* passwd:                                Unixのグループとユーザ.
                                                              (line  52)
* path <1>:                              DBMデータベースのオープンとクローズ.
                                                              (line  16)
* path:                                  ユーザレベルのロギング.
                                                              (line  23)
* perm:                                  ファイルの状態.      (line  38)
* PF_INET:                               低レベルソケットインタフェース.
                                                              (line  15)
* PF_UNIX:                               低レベルソケットインタフェース.
                                                              (line  14)
* pi:                                    定数.                (line  10)
* pi/180:                                定数.                (line  13)
* pi/2:                                  定数.                (line  11)
* pi/4:                                  定数.                (line  12)
* pid:                                   低レベルファイル操作.
                                                              (line 142)
* port <1>:                              Netdbインタフェース. (line  54)
* port:                                  コンディション.      (line 151)
* position:                              コンディション.      (line 135)
* prefix:                                ユーザレベルのロギング.
                                                              (line  32)
* printer:                               リスナー.            (line  58)
* program-name:                          ユーザレベルのロギング.
                                                              (line  78)
* prompter:                              リスナー.            (line  62)
* proto:                                 Netdbインタフェース. (line  57)
* protocol:                              Netdbインタフェース. (line 132)
* putb:                                  仮想ポート.          (line 140)
* putc:                                  仮想ポート.          (line 150)
* puts:                                  仮想ポート.          (line 160)
* R_OK:                                  ファイルの状態.      (line 112)
* RAND_MAX:                              その他のシステムコール.
                                                              (line  63)
* rdev:                                  ファイルの状態.      (line  45)
* reader:                                リスナー.            (line  49)
* ready:                                 仮想ポート.          (line  89)
* reason:                                スレッド例外.        (line  43)
* redefined:                             クラスのインスタンシエーション.
                                                              (line 132)
* rw-mode:                               DBMデータベースのオープンとクローズ.
                                                              (line  19)
* sec:                                   時間.                (line  41)
* second:                                時間.                (line 109)
* seek:                                  仮想ポート.          (line 112)
* shell:                                 Unixのグループとユーザ.
                                                              (line  62)
* SIGABRT:                               シグナルとシグナルセット.
                                                              (line  12)
* SIGALRM:                               シグナルとシグナルセット.
                                                              (line  13)
* SIGBUS:                                シグナルとシグナルセット.
                                                              (line  35)
* SIGCHLD:                               シグナルとシグナルセット.
                                                              (line  14)
* SIGCONT:                               シグナルとシグナルセット.
                                                              (line  15)
* SIGFPE:                                シグナルとシグナルセット.
                                                              (line  16)
* SIGHUP:                                シグナルとシグナルセット.
                                                              (line  17)
* SIGILL:                                シグナルとシグナルセット.
                                                              (line  18)
* SIGINT:                                シグナルとシグナルセット.
                                                              (line  19)
* SIGIO:                                 シグナルとシグナルセット.
                                                              (line  44)
* SIGIOT:                                シグナルとシグナルセット.
                                                              (line  34)
* SIGKILL:                               シグナルとシグナルセット.
                                                              (line  20)
* SIGPIPE:                               シグナルとシグナルセット.
                                                              (line  21)
* SIGPOLL:                               シグナルとシグナルセット.
                                                              (line  43)
* SIGPROF:                               シグナルとシグナルセット.
                                                              (line  41)
* SIGPWR:                                シグナルとシグナルセット.
                                                              (line  45)
* SIGQUIT:                               シグナルとシグナルセット.
                                                              (line  22)
* SIGSEGV:                               シグナルとシグナルセット.
                                                              (line  23)
* SIGSTKFLT:                             シグナルとシグナルセット.
                                                              (line  36)
* SIGSTOP:                               シグナルとシグナルセット.
                                                              (line  24)
* SIGTERM:                               シグナルとシグナルセット.
                                                              (line  25)
* SIGTRAP:                               シグナルとシグナルセット.
                                                              (line  33)
* SIGTSTP:                               シグナルとシグナルセット.
                                                              (line  26)
* SIGTTIN:                               シグナルとシグナルセット.
                                                              (line  27)
* SIGTTOU:                               シグナルとシグナルセット.
                                                              (line  28)
* SIGURG:                                シグナルとシグナルセット.
                                                              (line  37)
* SIGUSR1:                               シグナルとシグナルセット.
                                                              (line  29)
* SIGUSR2:                               シグナルとシグナルセット.
                                                              (line  30)
* SIGVTALRM:                             シグナルとシグナルセット.
                                                              (line  40)
* SIGWINCH:                              シグナルとシグナルセット.
                                                              (line  42)
* SIGXCPU:                               シグナルとシグナルセット.
                                                              (line  38)
* SIGXFSZ:                               シグナルとシグナルセット.
                                                              (line  39)
* size:                                  ファイルの状態.      (line  49)
* slots:                                 クラスのインスタンシエーション.
                                                              (line 104)
* SO_BROADCAST:                          低レベルソケットインタフェース.
                                                              (line 199)
* SO_ERROR:                              低レベルソケットインタフェース.
                                                              (line 207)
* SO_KEEPALIVE:                          低レベルソケットインタフェース.
                                                              (line 180)
* SO_OOBINLINE:                          低レベルソケットインタフェース.
                                                              (line 184)
* SO_PRIORITY:                           低レベルソケットインタフェース.
                                                              (line 203)
* SO_REUSEADDR:                          低レベルソケットインタフェース.
                                                              (line 189)
* SO_TYPE:                               低レベルソケットインタフェース.
                                                              (line 195)
* SOCK_DGRAM:                            低レベルソケットインタフェース.
                                                              (line  23)
* SOCK_RAW:                              低レベルソケットインタフェース.
                                                              (line  24)
* SOCK_STREAM:                           低レベルソケットインタフェース.
                                                              (line  22)
* socktype:                              Netdbインタフェース. (line 130)
* SOL_IP:                                低レベルソケットインタフェース.
                                                              (line 174)
* SOL_SOCKET:                            低レベルソケットインタフェース.
                                                              (line 172)
* SOL_TCP:                               低レベルソケットインタフェース.
                                                              (line 173)
* span:                                  コンディション.      (line 136)
* specific <1>:                          同期プリミティブ.    (line 164)
* specific:                              スレッド手続き.      (line  42)
* ssax:Prefix-XML:                       SSAXの低レベルパージングコード.
                                                              (line  36)
* start:                                 低レベルファイル操作.
                                                              (line 136)
* state:                                 同期プリミティブ.    (line  25)
* subtype:                               MIMEメッセージ処理.  (line 115)
* sync:                                  GDBMインタフェース.  (line  17)
* syslog-facility:                       ユーザレベルのロギング.
                                                              (line 103)
* syslog-option:                         ユーザレベルのロギング.
                                                              (line 102)
* syslog-priority:                       ユーザレベルのロギング.
                                                              (line 104)
* TCIFLUSH:                              Termios.             (line  71)
* TCIOFF:                                Termios.             (line  89)
* TCIOFLUSH:                             Termios.             (line  77)
* TCION:                                 Termios.             (line  93)
* TCOFLUSH:                              Termios.             (line  74)
* TCOOFF:                                Termios.             (line  83)
* TCOON:                                 Termios.             (line  86)
* TCSADRAIN:                             Termios.             (line  53)
* TCSAFLUSH:                             Termios.             (line  56)
* TCSANOW:                               Termios.             (line  50)
* terminator:                            スレッド例外.        (line  35)
* thread:                                スレッド例外.        (line  15)
* time-duration:                         時間のタイプ.        (line  24)
* time-monotonic:                        時間のタイプ.        (line  20)
* time-process:                          時間のタイプ.        (line  27)
* time-tai:                              時間のタイプ.        (line  15)
* time-thread:                           時間のタイプ.        (line  32)
* time-utc:                              時間のタイプ.        (line  10)
* transfer-encoding:                     MIMEメッセージ処理.  (line 122)
* type <1>:                              低レベルファイル操作.
                                                              (line 119)
* type <2>:                              時間.                (line 104)
* type <3>:                              ファイルの状態.      (line  23)
* type:                                  MIMEメッセージ処理.  (line 111)
* uid <1>:                               ファイルの状態.      (line  47)
* uid:                                   Unixのグループとユーザ.
                                                              (line  46)
* value-convert:                         DBMデータベースのオープンとクローズ.
                                                              (line  38)
* W_OK:                                  ファイルの状態.      (line 115)
* wday:                                  時間.                (line  59)
* whence:                                低レベルファイル操作.
                                                              (line 133)
* X_OK:                                  ファイルの状態.      (line 118)
* yday:                                  時間.                (line  62)
* year:                                  時間.                (line  56)



Tag Table:
Node: Top250
Node: はじめに878
Node: Gaucheの概要2469
Node: 表記について5637
Node: 主要な概念8226
Node: 標準への準拠8644
Node: マルチバイト文字列14117
Node: マルチバイトスクリプト16713
Node: 大文字小文字の区別18736
Node: 統合されたオブジェクトシステム20599
Node: モジュールシステム24871
Node: コンパイル26858
Node: Gaucheでのプログラミング28940
Node: Gaucheを起動する29291
Node: インタラクティブな開発34589
Node: Schemeスクリプトを書く35907
Node: デバッグ39905
Node: プロファイリングとチューニング41269
Node: プロファイラを使う42559
Node: パフォーマンスに関するヒント46966
Node: Gaucheのモジュールを書く51314
Node: 拡張パッケージの使用54347
Node: 基本的な構文58599
Node: 字句構造58886
Node: リテラル62658
Node: 手続きを作る63407
Node: 代入66968
Node: 条件式72035
Node: 変数束縛76054
Node: 順次実行79693
Node: 繰り返し81000
Node: 準クオート81848
Node: 定義82048
Node: モジュール84766
Node: モジュールのセマンティクス85240
Node: モジュールとライブラリ89796
Node: モジュールの定義と選択91560
Node: モジュールの使用92995
Node: モジュールの継承95550
Node: モジュールイントロスペクション98212
Node: 組み込みモジュール102227
Node: マクロ103276
Node: 健全なマクロ103895
Node: 伝統的なマクロ104588
Node: マクロの展開105241
Node: マクロユーティリティ105924
Node: 組み込みライブラリ107369
Node: 等価107845
Node: 数値111694
Node: 数値クラス112228
Node: 数値に関する述語113130
Node: 数値の比較115100
Node: 数値の演算115939
Node: 数値の変換120405
Node: ビット演算124291
Node: 論理値125918
Node: ペアとリスト126326
Node: pairクラスとnullクラス127080
Node: リストに関する述語127790
Node: リストの作成128443
Node: リストへのアクセスと変更129671
Node: 他のリスト手続き131430
Node: シンボル133556
Node: キーワード134963
Node: Identifier137888
Node: 文字138130
Node: 文字集合144297
Node: 文字列147155
Node: 文字列の表記147840
Node: 文字列に関する述語149512
Node: 文字列の作成149975
Node: 文字列の補間151663
Node: 文字列のアクセスと変更154612
Node: 文字列の比較156538
Node: 文字列を扱うその他の手続き157158
Node: 文字列ポインタ162737
Node: 不完全文字列163973
Node: 正規表現164191
Node: ベクター173041
Node: ハッシュテーブル176365
Node: Weak ポインタ184453
Node: 制御186355
Node: 手続き186554
Node: マッピング187198
Node: コンビネータ188417
Node: 省略可能引数のパージング191384
Node: 手続きのアリティ195634
Node: 適用可能なオブジェクト197018
Node: 継続198852
Node: 多値202084
Node: 遅延評価203194
Node: 例外204824
Node: 例外処理の概要205818
Node: 例外の通知212467
Node: 例外の処理214810
Node: コンディション220111
Node: eval と repl231259
Node: 入出力233948
Node: ポート234231
Node: ポートとスレッド236083
Node: ポート共通の操作237890
Node: ファイルポート243332
Node: 文字列ポート251632
Node: コーディング認識ポート255771
Node: 入力257522
Node: データの読み込み257856
Node: 読み込み時コンストラクタ262894
Node: 入力ユーティリティ手続き266399
Node: 出力268107
Node: プログラムのロード278038
Node: Schemeファイルのロード278328
Node: ダイナミックライブラリのロード283261
Node: requireとprovide284794
Node: Autoload285945
Node: ライブラリの操作287806
Node: 比較とソート293134
Node: システムインタフェース294841
Node: プログラムの終了296316
Node: 環境の問い合わせ297345
Node: ファイルシステム298133
Node: ディレクトリ298613
Node: ディレクトリ操作299744
Node: パス名302698
Node: ファイルの状態305379
Node: 他のファイル操作310777
Node: Unixのグループとユーザ312437
Node: ロケール314965
Node: シグナル316928
Node: シグナルとシグナルセット317698
Node: シグナルの送出319944
Node: シグナルの処理320856
Node: シグナルのマスクと待機325942
Node: シグナルとスレッド327400
Node: システムへの問い合わせ330019
Node: 時間332869
Node: Unixのプロセス管理337192
Node: I/Oの多重化343988
Node: その他のシステムコール346710
Node: 開発補助API349339
Node: デバッグ補助349599
Node: プロファイラAPI350520
Node: オブジェクトシステム351816
Node: オブジェクトシステムの紹介352456
Node: 一般的な問い合わせ372595
Node: クラス374172
Node: クラスの定義374498
Node: 継承381775
Node: クラスオブジェクト387977
Node: スロット定義オブジェクト390829
Node: クラスの再定義392301
Node: クラスの定義例396639
Node: インスタンス400931
Node: インスタンスの作成401247
Node: インスタンスへのアクセス404587
Node: クラスの変更408783
Node: ジェネリックファンクションとメソッド413662
Node: メタオブジェクトプロトコル418063
Node: クラスのインスタンシエーション419340
Node: スロットアクセスのカスタマイズ425370
Node: メソッドのインスタンシエーション425820
Node: メソッド適用のカスタマイズ426123
Node: ライブラリモジュール - 概要426617
Node: ライブラリモジュール - Gauche拡張モジュール429550
Node: 配列430386
Node: 文字コード変換439186
Node: サポートされる文字エンコーディング440241
Node: 文字エンコーディングの自動判定446531
Node: 変換ポート447590
Node: 拡張されたポート手続き454660
Node: コレクションフレームワーク455969
Node: コレクションに対するマッピング458708
Node: コレクションからの選択と探索465529
Node: コレクションに対する様々な操作469375
Node: 基礎的なイテレータ構築メソッド470789
Node: コレクションの実装477701
Node: コンフィグレーション情報479033
Node: 低レベルファイル操作480145
Node: フック486194
Node: インタラクティブセッション488659
Node: リスナー491424
Node: ユーザレベルのロギング499071
Node: シングルトン505325
Node: Validator付きスロット506769
Node: ネットワーキング509471
Node: ソケットアドレス510271
Node: 高レベルネットワーク手続き514005
Node: 低レベルソケットインタフェース521348
Node: Netdbインタフェース529984
Node: パラメータ535816
Node: コマンドライン引数の解析540180
Node: 高レベルプロセスインタフェース548875
Node: Process object549624
Node: Process ports555383
Node: 正規表現ユーティリティ561834
Node: モジュールの再ロード570513
Node: 簡単なディスパッチャ573971
Node: シーケンスフレームワーク577610
Node: 基本的なシーケンスのアクセサ578644
Node: シーケンスのスライス579833
Node: シーケンス上のマップ581069
Node: シーケンスに対する選択と探索583170
Node: シーケンスを実装する584637
Node: Syslog584817
Node: Termios587693
Node: 単体テスト593856
Node: スレッド598426
Node: スレッドプログラミングTips599646
Node: スレッド手続き602555
Node: 同期プリミティブ607888
Node: スレッド例外616682
Node: 時間の計測618929
Node: ユニフォームベクタ623242
Node: ユニフォームベクタの基本操作626863
Node: ユニフォームベクタの変換631545
Node: ユニフォームベクタの数値演算637544
Node: ユニフォームベクタのブロック入出力642357
Node: バージョン番号の比較645126
Node: 仮想ポート649703
Node: ライブラリモジュール - SRFI665579
Node: 機能条件式666410
Node: List library669427
Node: SRFI-1 リスト構築子670206
Node: SRFI-1 リストの述語671291
Node: SRFI-1 リスト選択子672558
Node: 種々のリスト処理ルーチン675829
Node: リストの畳み込み(fold)、解きほぐし(unfold)、および写像(map)678720
Node: リストのフィルタおよび分割683720
Node: リストの探索685262
Node: リストの削除687071
Node: 連想リスト687926
Node: 集合としてのリスト689036
Node: And-let*691397
Node: 単一型のベクタ693283
Node: シグネチャとrest引数に互換性のあるlet形式693698
Node: 機能ベースプログラム設定言語694641
Node: レコード型697524
Node: Let-values700150
Node: 文字列ライブラリ701829
Node: 一般規約703220
Node: 文字列についての述語705292
Node: 文字列の構築子706206
Node: 文字列の選択706805
Node: 文字列の色々な比較709559
Node: 文字列のプリフィックスとサフィックス710916
Node: 文字列の探索711807
Node: 文字列のケース(大文字小文字)マッピング713932
Node: 文字列の反転と追加714530
Node: 文字列のマッピング715844
Node: 文字列のローテーション717006
Node: 他の文字列操作717370
Node: 文字列のフィルタリング718110
Node: 低レベルな文字列に関する手続き718469
Node: 文字集合ライブラリ719262
Node: 文字セットの構築子719922
Node: 文字セットの比較721467
Node: 文字セットのイテレーション721836
Node: 文字セットへの問い合わせ722620
Node: 文字セットに適用できる代数的関数723185
Node: 定義済みの文字セット724458
Node: 時間のデータ型と手続き725352
Node: 時間のタイプ725950
Node: 時間に関する問い合わせ727029
Node: 時間に関する手続き728332
Node: 日付730340
Node: 日付の読み書き734422
Node: ランダムビットのソース734698
Node: 地域化737336
Node: args-fold プログラム引数処理742146
Node: Eager comprehensions748624
Node: Requiring extensions753745
Node: ライブラリモジュール - ユーティリティ754867
Node: バイナリデータのパック756685
Node: 汎用DBMインタフェース763672
Node: DBMデータベースのオープンとクローズ765715
Node: DBMデータベースのアクセス769923
Node: DBMデータベース上の繰り返し処理770747
Node: DBMデータベースインスタンスの管理772098
Node: ファイルシステムdbm773505
Node: GDBMインタフェース775189
Node: NDBMインタフェース777256
Node: オリジナルのDBMインタフェース778452
Node: ファイルのフィルタ779678
Node: ファイルシステムユーティリティ782675
Node: ディレクトリユーティリティ783895
Node: パスネームユーティリティ789506
Node: ファイル属性ユーティリティ793767
Node: ファイル操作797779
Node: 定数801113
Node: Mersenne Twister乱数発生器801605
Node: RFC822メッセージ形式804328
Node: Base64エンコーディング811504
Node: HTTPクッキー813020
Node: HMAC鍵付きハッシング816506
Node: HTTP818497
Node: MD5メッセージダイジェスト823441
Node: MIMEメッセージ処理824658
Node: Quoted-printableエンコーディング832702
Node: SHA1メッセージダイジェスト834270
Node: URIの解析と作成835515
Node: SLIBインタフェース841555
Node: 関数的なXMLパーザ842710
Node: SSAXデータタイプ845015
Node: SSAXの低レベルパージングコード850646
Node: SSAXの高レベルのパーザとスキャナ861334
Node: SSAXの高レベルのパーザ - XMLからSXMLへ864314
Node: SXMLクエリ言語872201
Node: SXPathの基本的なコンバータとアプリケータ873497
Node: SXPathクエリ言語882635
Node: SXPathの拡張885158
Node: SXML構造を操作する889346
Node: SXMLの述語889890
Node: SXMLへのアクセッサ891101
Node: SXMLのモディファイヤ897554
Node: SXPathの補助的ユーティリティ900570
Node: SXMLからマークアップへの変換901475
Node: CSVテーブル903385
Node: テキストストリームの相違点を計算する905192
Node: 地域化メッセージ907546
Node: シンプルなHTMLドキュメントの構築912726
Node: 入力ストリームのパージング917144
Node: 文字変換921452
Node: 怠惰なテキスト構築926449
Node: 組み合わせ928717
Node: メッセージダイジェストフレームワーク932268
Node: 同型判定934088
Node: 最長共通サブシーケンス935429
Node: その他のリストライブラリ939341
Node: パターンマッチング945748
Node: キュー957484
Node: SLIB-互換のレコード型961671
Node: トポロジカルソート964249
Node: CGIユーティリティ965137
Node: CGIのテスト979694
Node: 参考文献984268
Ref: r5rs984438
Ref: onecont984725
Ref: meyers86984910
Ref: mop985042
Ref: dylan985156
Ref: fairthreads985433
Ref: rfc1321985562
Ref: rfc2045985687
Ref: rfc2396985884
Ref: rfc2616986059
Ref: rfc2822986197
Ref: rfc2965986315
Ref: rfc3174986455
Ref: srfi-0986605
Ref: srfi-1986747
Ref: srfi-2986856
Ref: srfi-4987028
Ref: srfi-6987152
Ref: srfi-8987269
Ref: srfi-9987409
Ref: srfi-10987531
Ref: srfi-11987650
Ref: srfi-13987785
Ref: srfi-14987902
Ref: srfi-17988024
Ref: srfi-18988138
Ref: srfi-19988257
Ref: srfi-21988389
Ref: srfi-22988519
Ref: srfi-23988679
Ref: srfi-25988804
Ref: srfi-26988940
Ref: srfi-27989098
Ref: srfi-28989220
Ref: srfi-37989340
Ref: ssax989484
Ref: MT989677
Ref: oleg1989966
Ref: oleg2990083
Node: CとSchemeの関数の対応990224
Node: Index - 手続きと構文索引1014230
Node: Index - モジュール索引1245987
Node: Index - クラス索引1254790
Node: Index - 変数索引1265897

End Tag Table
