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

12.92 util.relation - リレーションフレームワーク

Module: util.relation

リレーションに対する共通の操作を提供します。

値の集合を S1, S2, ..., Sn とするとリレーション R はタプルの集合で、 タプルの最初の要素は S1 からの値で、2番目は S2 から、で n 番目は Sn からとなっている。いいかえれば、R は S1, ..., Sn の直積です。 (この定義とリレーションという用語は 1970年のCoddのペーパー "A Relational Model of Data for Large Shared Data Banks", in CACM 13(6) pp.377–387.によるものです。)

この定義はいろいろなデータベースセットにあてはまります。各インスタンス をタプルとみなし、各スロット値を実際の値と見ると、Gaucheのオブジェクト システムの集合はリレーションです。リストのリストもリレーションです。 CSVテーブルからの読み出しストリームはリレーションを生成します。このよ うことから、表現に依存しないリレーション上のジェネリックな操作を実装す るモジュールを用意することは有意義です。

操作という観点からいえば、以下の4つのメソッドがあれば、どのようなデー タ構造もあつかえます。タプルのコレクション(行)を取り出す relation-rows、それから、relation-column-namesrelation-accessorrelation-modifier、これらはメタ情報に アクセスする方法を提供しています。これ以外のすべてのリレーション操作は 上のプリミティブメソッドを使って組まれています。

リレーションの具体的な実装にはダックタイピングが適用できます。 すなわち、リレーションメソッドを使うのに特定のベースクラスを継承する必 要はありません。しかし、利便のためにこのモジュールには、ベースクラス <relation>が用意されています。これは、ミックスインクラスのよう な働きをします。具象クラスは典型的には<relation>および <collection>または<sequence>を継承することになるでしょう。 興味があれば、ソースツリーにあるlib/util/relation.scmに含まれる サンプル実装をチェックするとよいでしょう。

このモジュールは現時点では開発途上にあります。計画では共通メソッド上に 有用なリレーション操作関数群を構築することになっています。

基本となるクラスとメソッド

Class: <relation>

{util.relation} リレーションの抽象ベースクラス

Method: relation-column-names (r <relation>)

{util.relation} サブクラスではこのメソッドを必ず実装しなければなりません。 カラムの名前のシーケンスを返す必要があります。カラム名の型はリレーショ ンによります。equal?の意味で相互に異っているかぎり、カラム名に ついて特に制限はありません。

Method: relation-accessor (r <relation>)

{util.relation} サブクラスではこのメソッドは必ず実装しなければなりまん。2つの引数をと り、リレーションrの行とカラム名をとり、指定したカラムの値を返す 手続を返さなければなりません。

Method: relation-modifier (r <relation>)

{util.relation} サブクラスではこのメソッドは必ず実装しなければなりまん。 3つの引数、リレーションrの行、カラム名、値をとり、その値をセット する手続を返さなければなりません。

リレーションが読み込み専用の場合はこのメソッドは#fを返します。

Method: relation-rows (r <relation>)

{util.relation} サブクラスではこのメソッドは必ず実装しなければなりまん。 基盤となっている<collection>クラスまたはそのサブクラス(たとえば <sequence>)のインスタンスを返さなければなりません。

のこりのメソッドは上の4つのメソッドを使って組まれています。とはいえ、 <relation> のサブクラスでは以下のメソッドを性能を得るためにオー バーロードすることもできます。

Method: relation-column-name? (r <relation>) column

{util.relation} columnがリレーションrにおいて有効なカラム名である場合にの み真を返します。

Method: relation-column-getter (r <relation>) column
Method: relation-column-setter (r <relation>) column

{util.relation} リレーションrの行の指定したカラムにアクセスする手続を返します。 Relation-column-getterは、1つの引数、行をとる手続きを返さなけれ ばなりません。Relation-column-setterは2つの引数、行と新しくセッ トする値を取る手続きを返さなければなりません。

リレーションが読み込み専用の場合はrelation-column-setter#fを返します。

Method: relation-ref (r <relation>) row column :optional default

{util.relation} rowはリレーションrの行です。rowcolumnの値を 返します。columnが不正なカラム名である場合、defaultが与え られていればそれを返し、そうでなければ、エラーを示すシグナルがあがりま す。

Method: relation-set! (r <relation>) row column value

{util.relation} rowはリレーションrの行です。valuerowcolumnに設定します。リレーションが読み込み専用の場合には エラーを示すシグナルがあがります。

Method: relation-column-getters (r <relation>)
Method: relation-column-setters (r <relation>)

{util.relation} ゲッタとセッタの完全なリストを返します。通常はデフォルトのメソッドで十 分ですが、たとえばゲッタのリストをキャッシュしたいときもあるでしょう。

Method: relation-coercer (r <relation>)

{util.relation} 行をシーケンスに変換する手続きを返します。行がすでにシーケンスで表現さ れているリレーションであれば、行をそのまま返す手続きです。

Method: relation-insertable? (r <relation>)

{util.relation} リレーションrに新しい行を挿入可能な場合にのみ真を返します。

Method: relation-insert! (r <relation>) row

{util.relation} リレーションrに行rowを挿入します。

Method: relation-deletable? (r <relation>)

{util.relation} リレーションrから行を削除可能である場合にのみ真を返します。

Method: relation-delete! (r <relation>) row

{util.relation} リレーションrから行rowを削除します。

Method: relation-fold (r <relation>) proc seed column …

{util.relation} procを各行のカラムcolumn … の値に適用します。 seedは状態の値として渡されます。すなわち、リレーションrの 各行ごとに以下のようにprocを呼びます。


(proc v_0 v_1 ... v_i seed)

 where v_k = (relation-ref r row column_k)

呼び出しの結果があたらしいシードの値となり、最終の結果が relation-foldから返ります。

たとえば、リレーションが amount という名前のカラムをもつものと し、リレーション r 内にあるそのカラムをすべて足しあわせたいとす ると以下のように書けます。

(relation-fold r + 0 'amount)

具象クラス

Class: <simple-relation>

{util.relation}

Class: <object-set-relation>

{util.relation}



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