2012-08-23

パッケージに対する雑感

よく他の言語で、コードを読みにくくするので、特定の名前空間を丸ごと取り込む(OCamlのopen MとかHaskellのimport MとかC++のusing Nとか)のは要注意って言われるけど、Common Lispの場合どれだけuse-packageしても、

(symbol-package 'x)

ホームパッケージを確認できるから、気軽にシンボルインポートできる。これは、識別子(シンボル)がファーストクラスオブジェクトなことによる大きな利点だと思う。運用で回避したり(名前空間を取り込む代わりに、短い別名を付けてアクセスすることが多い)、ツールで補助する必要があまりない。

また、名前空間(パッケージ)自体もファーストクラスなオブジェクトなので、どういうシンボルが含まれるかとか、他から取り込んでいるシンボルはどれかとか、そういうことをコードの字面から読み取る情報としてではなく、計算可能なデータとして扱うことができる。これも大きなアドバンテージじゃないだろうか。Lispの動的、対話的に開発する文化が良く出ている機能だとも思う。

対して、少し扱いづらいと感じる部分もある。例えば、OCamlにはlocal modulelocal openという機能があって、

(* ListモジュールにLという別名を付ける *)
let module L = List in L.iter print_string [ "a"; "b"; "c" ]

(* 部分的にListモジュールをopenする *)
let open List in iter print_string [ "a"; "b"; "c" ]

のようなことができるけど、こういう粒度の細かい名前空間の切り替えは、リーダーとパッケージの仕様の都合上、ANSI Common Lispの範囲ではできないと思う。(リーダーマクロを使えば実現できそう)

ちなみに、部分的にuse-packageするのとは少し違うけど、Allegro CLSBCL(1.0.55以降)には、

ppcre::(split ":" "a:b:c")

のように、指定したパッケージをカレントパッケージにして式を評価する構文がある。ただし、式の中ではパッケージが切り替わっているので、

cl-user::(let ((x 0)) cl::(print x))    ; cl::(...)の中のxの参照はcl:xの参照と解釈される

こういうことはできない。

他にも、シンボルが衝突するなどの理由でパッケージをuse-packageしたくない、でもこの長いパッケージ名を毎回明示するのは厳しい、という場合、

(let ((nicknames (package-nicknames :too-long-package-name)))
  (rename-package :too-long-package-name
                  :too-long-package-name
                  (cons :short-name nicknames)))

なんて感じで、新しい別名を付けたりすると思う。書いているコードがアプリケーションなら特に問題はないんだけど、それがライブラリだったとき困る。ライブラリをロードするたびに特定のパッケージに別名を付けてしまうのは、いかにも行儀が悪い気がするし、その別名が他のパッケージ名と衝突なんてした暁には、ライブラリの利用者に対処してもらうことになって色々悲しい。

(defparameter *old-nicknames* (package-nicknames :too-long-package-name))

(rename-package :too-long-package-name
                :too-long-package-name
                (cons :short-name *old-nicknames*))

...

(rename-package :too-long-package-name
                :too-long-package-name
                *old-nicknames*)

のようにすることはできるけど、これを毎回書くのもどうなんだという気もする。この辺りの事情を改善するためのものがFrancois-Rene Rideauのpackage-renamingだと思うんだけど、READMEを読む限りでは、少しトリッキーな感じで他の人には勧めにくい。

とまあ、物足りなく感じる部分もあるけど、Common Lispのパッケージがとても柔軟で強力な仕組みなのは間違いないと思う。特に、対話的に開発する場合には威力を発揮する。……と、他の言語を使っていて改めて実感した次第。

0 件のコメント: