#:g1: MIT Lisp Machine: Hierarchical Packagesの紹介

Posted 2014-11-19 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の324日目です。

MIT Lisp Machine: Hierarchical Packagesとはなにか

 MIT Lisp Machine: Hierarchical Packagesは、MIT Lisp Machineのパッケージシステムです。

パッケージ情報

パッケージ名MIT Lisp Machine: Hierarchical Packages
LispマシンマニュアルLisp Machine Manual 6th ed.: Packages

試してみる

 それまでのoblistでのシンボルの管理をパッケージにまとめて大規模な開発を可能にしたのがLispマシンのパッケージかと思います。
仕組みが固定し初めたのは大体1978年位でしょうか。
Common Lispのパッケージの関数と並べると下記のようになります。

階層パッケージ

 一見してCommon Lispと比較して違うところは、階層を成しているということです。
初期状態の階層は下記の通り

                           global                     keyword
                             |                          
       /-----------------------------------          fonts
       |     |          |          |       |
     user  zwei      system      format  (etc)        cli
                        |
                /----------------------------------
                |          |     |     |    |      |
         system-internals  eh  chaos  cadr  fs  compiler

 下記のように書くことで階層分けが可能です。

(package-declare aaa global 100 nil) 
(package-declare bbb aaa 100 nil)
(package-declare ccc bbb 100 nil)

こうすると、aaaの下にbbb、bbbの下にcccが作られるので、cccのシンボルdは、aaa:bbb:ccc:dということになります。
ちなみに、Common Lispのようにエクスポートしないとpkg::symと記述しなければいけないということはありません。
シンボルの継承は、上から下に勝手に継承してきます。つまり、

(intern "X" "AAA")
(eq 'aaa:x 'aaa:bbb:ccc:x)
;=> T

みたいなことになります。
これを防ぐのがCommon Lispと同じくshadowで

(shadow "X" 'aaa:bbb:ccc)

(eq 'aaa:x 'aaa:bbb:ccc:x) ;=> NIL

とできます。しかし、

(eq 'aaa:z 'aaa:bbb:ccc:z)
;=> T

でも

(eq 'aaa:bbb:ccc:q 'aaa:q)
;=> NIL

だったりして、評価順が関係してきてややこしいです。

keywordパッケージはuser

 パッケージシステムができた当初(というかCommon Lisp登場まで)はkeywordパッケージというものはなく、:fooと書けば、user:fooのことでした。
更に、自己評価オブジェクトでもなかったのでクォートを付ける必要がありました。
昔のコードで ':foo と書いてあることがあるのは、このためです。
この為、userパッケージはサブパッケージが作れない等の制限をつけていたようなのですが、Common Lispが出てくるあたりでkeywordパッケージもできたようです。

パッケージの指定は、-*- Packge: -*-で行なう

 上記の一覧では、pkg-gotoというものがありますが、基本的にパッケージの宣言は、ファイル最上部の属性リストで宣言していました。

階層パッケージの活用され具合

 Lispマシンのソースを眺める限りでは、特に階層分けを活かしたコードというのは無かったようです。
上部のパッケージから無条件でシンボルを継承してくるというのが良くなかったのか、何が悪かったのかは不明ですが、そんな為か、Common Lispをサポートする辺りになってくると、'aaa:bbb:ccc:xも'ccc:xも同じ意味になったりしていて、これだと実質パッケージ名はグローバルに唯一のものしか付けられなくなってきます。

面白い機能

 Common Lispには無い機能として、relative-names/relative-names-for-me、invisibleがあります。
relative-namesは、SBCLのlocal-nicknamesと同じで他のパッケージをパッケージローカルで別名で参照できます。
relative-names-for-meはその逆みたいですが詳細は不明です。
invisibleは、(list-all-packages)には登録されないということで、シンボルでいうuninterned symbolみたいな感じです。名前は付くもののfind-packageでは見付けられません。

まとめ

 今回は、MIT Lisp Machine: Hierarchical Packagesを紹介してみました。
不特定多数の人がバラバラに開発をしつつも統一しようとすれば、Perl/CPANのような名前の階層化が便利なのかなと思いますが、どうなのでしょう。
Common Lispの場合は、パッケージ名の衝突を回避する方法が面倒なのが厄介ですね。

comments powered by Disqus