このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

リクエストディスパッチの構造

イカイカン、イカイカイカン!!

形式化/抽象化をしないと、いつまでたってもハッキリしないグダグダ状態が続く。リクエストディスパッチの基本は、いちおう「集合と論理の練習問題: ツリー状の集合族 - 檜山正幸のキマイラ飼育記 」に書いた。

僕はオブジェクト指向は好きじゃないが、結果的にはオブジェクト指向っぽい話になる。「結果的」は今回のキーワードだ、as-a-result を、「結果的」を意味する形容詞に使おう。

Catyの型システムはサブタイプ/スーパータイプの宣言はないが、「結果的にサブタイプ」(as-a-result subtype、subtype as-a-result)はある。ダックタイピングと言ってもいい。リソースクラスのあいだに継承はないが、「結果的に継承」とか「結果的にサブクラス」という関係はある。この「結果的に=意図してないが」というのは非常に重要な概念だと思う。

「結果的に継承」、「結果的にサブクラス」を定式化するために、3つの集合を考える。

  1. 集合C -- クラス識別子の集合。Cの要素を単にクラスとも呼ぶ。Catyのリソースクラスに対応。
  2. 集合S -- クラスのメソッドセレクタの集合。Sの要素はメソッドそのものではなくて、メソッドを起動するための記号。Catyでは、アクションインボーカーと言っているヤツ。
  3. 集合U -- Catyでは、パス文字列全体の集合。すべてのリソースインスタンスの集合と言っても同じ。

抽象的なセッティングでは:

  1. C -- 有限集合。それ以上の制限も意味もない。空でもいいが、空だと議論する意味が無い。
  2. S -- 普通は無限集合。有限でもいい。空ではない。
  3. U -- 普通は無限集合。有限でもいい。空ではない。

構造を与えるのは、Inst:C→Pow(U) と、A:C→Pow(S) という関数。r∈C に対して、Inst(r) は |r| と略記する。クラスrのインスタンスの集合が |r| 。InstとAの条件は:

  1. r∈C に対して、 |r| は空ではない。
  2. r, s∈C に対して、 r≠s ならば、|r|⊂|s|、|s|⊂|r|、|r|∩|s|=0空集合)のどれかが成立する。
  3. r∈C に対して、A(r) は有限集合、空でもよい。

「rはsのサブクラス」と「rはsをオーバーライドする」を次のように定義する。

  • rはsのサブクラス ⇔ |r|⊂|s|
  • rはsをオーバーライドする ⇔ (|r|⊂|s| かつ A(r)∩A(s)≠0)

(i, s)∈U×S をリクエストと呼ぶ。

  • r |= (i, s) ⇔ (i∈|r| かつ s∈A(r))

次が成立する。

  • (r |= (i, s) かつ r' |= (i, s) となるリクエストが存在する) ⇔ (rはr'をオーバーライドするか、r'はrをオーバーライドする)

以上で定義した「サブクラス」「継承」「オーバーライド」は、いずれも「結果的に(as-a-result)」であって、宣言するもの(ノミナル)ではない。構造的っちゃそうだが、やはり「意図せずに」という感じが強い。