概要
- Common Lisp の package について
- 解説したリンクを集めた
- package について説明を試みた
- package について疑問に思ったことをまとめた
参照リンク集
CommonLispでの Packageとは?
- Lispの関数名も変数名も シンボル として扱われることを納得しておく必要がある
- 関数名、変数名、スペシャル関数名、マクロ名 etc
- シンボルが 所属 する シンボルの管理単位
- 一部の例外を除く(!)すべてのシンボルは パッケージに属している
- 例外1:gensym で生成されたシンボルは どのパッケージにも属さない
- 例外2:キーワード - キーワード(
keyword
)という 特別なパッケージに属している
- Common Lisp の第一級オブジェクトである(後述)
- CommonLisp が標準で持っている関数やマクロや変数(シンボル)は
cl, common-lisp
という名前空間に属している
- REPLで実行して一時的に作られた and/or
特にパッケージを明示せず定義されたシンボルは
cl-user, common-lisp-user
という名前空間に属している
シンボルは第一級オブジェクトである、とは?
なんでも定義・変更できる(?) Common Lisp の例にもれず、package も各種操作を受け付けるということ
- パッケージ(という値)の定義、削除
- パッケージの名前の定義、削除、変更、ニックネームの定義
- やっぱりパッケージを表すシンボル なんだろうか。調べきっていない
- パッケージの中身=シンボル、の追加、削除
- パッケージの外側に公開(export)するシンボルの決定
- 他パッケージに属するシンボルを自パッケージに包含する
- 自他パッケージに属するシンボルを「隠す」「上書きする」
- shadowing? ここがまだよくわかっていない、あるいは困るまで調べない
- 関数のオーバーライドと呼ばれる機構に近いらしい
- 現在のパッケージ を切り替える
- 各種調査用関数
パッケージのシンボルに対するアクセス方法 … コロン(:) の意味
package-name:symbol-name
で export されているシンボルにアクセス
- packageが読み込み済みである必要がある
ppcre:scan
ql:quickload
asdf:load-system
など
- あるライブラリが提供している関数を使うときはこの方法を使う
package-name::symbol-name
で パッケージ内の任意のシンボルにアクセス
- exportされていなくてもアクセス可能
- private, friend, protected 、、、なんてものは存在しない、完全ノーガード
- shadowingしたらどうなるんだろう?
- この手段を使うのは冷静に考えて邪道
コロン(:) を使う特別なシンボル…キーワード について
:keyword
のように、コロン(:)から始まるシンボルをキーワードという
- キーワードは 評価するとシンボル自身を返す
* :test
:test
- キーワードは、
keyword
パッケージに属する
Common Lisp のソースを読んでいて浮かぶ疑問
- defpackage ? in-package ? なにこれ?
- defpackage のところに、パッケージ名が書かれています。
- :export という項目があれば、それが公開されている 関数、変数の一覧です
- in-package はそのあとに定義したシンボルをパッケージに所属させるための
定型文ですので、自分でライブラリを書くのでなければ気にしなくてよいです
- ライブラリの関数なんかは
ライブラリ名 + : + 関数名
、で呼べるんだね?
- だいたいそうです。
cl-ppcre:scan
とか asdf:load-system
とか。
- ライブラリ名とパッケージ名が違う可能性があるので注意してください
- ニックネームが提供されていることがかなり多いです。
cl-ppcre
は ppcre
でもOK。
- (あるはずの関数・変数について)そんなものないって怒られるんですけど
- asdf, quicklisp でライブラリの「処理の中身とシンボル定義」を読み込む必要があります。
- 自分でパッケージを扱いだすと、もう少し複雑な「シンボルがない」状況に直面すると思います
- defsystem, defgeneric, defmethod, def** ってちがうの?
- defsystem はわりと関係あるんですが、、、わかってません。ひとまず ASDF に関連してます
- defgeneric, defmethod は CLOS ですね。まだよくわかってません。
- だいたい「
**
を定義するマクロ」だと思って間違いありません。
他言語から流れてきた人間として思う疑問
- namespace, using (C++, C#, Java) とは違うの?
- namespace はかなり package に近い、クラスや関数の所属先を決めている
- 違いは CommonLisp では シンボルは、定義された瞬間のpackageに属する こと
- in-package で定義される 現在のパッケージ に属する
- シンボルをパッケージに所属させることを intern というが
任意のパッケージを指定できる
- using の代わりに、defpackage の :use や use-package関数を使う
- require(ruby), import(python) とは違うの?
- common lisp にも require はある、、、いろいろまずくて誰も使ってないけど
- ライブラリをひとまとまりで読み込む標準の機能はない
- それは quicklisp や asdf が手助けしてくれる
- 個別ファイルであれば load を使うことで可能
- using の時に書いた defpackage の、、、などが、そのpackageにあるシンボルを
パッケージ名省略して使います、という宣言になる
まとめ。他の言語がむしろ、一つの文に複数の機能を備えていると言えるのでは。
- 名前空間の定義
- (名前空間に属する機能の)プログラムやデータの一括読み込み機構
- 関数名、変数名、クラス名について、名前空間の明示的な省略
そしてLisperはおもむろにマクロを定義するのであろう。
ひとこと
- Common Lisp における package に調べだしたところ、
それがなんであるかについてはイメージを持てたのだが、
いざ説明を書こうとして説明が難しすぎてさじ投げた
- 伝わる書き方というのが結局見えなくなった
- 特に、他言語の例については、ある程度理解が進むとむしろ説明が難しい
- 何がわかっていなかったかわからなくなる
- 他言語の例は自分が知っている言語をさらしているだけのような気がする
- 投げたさじを拾ってわかっていることだけまとめておいておくことにした
- Quick Reference に載っている関数を一通り試したのだが、
一部の関数が思ったように動いてくれない。使い方を勘違いしているのだろう。
Written with StackEdit.
英語なんですが http://www.flownet.com/ron/ の The Idiot's Guide to Common Lisp Packages (pdf) なんてのもあります。色々と動作例を示して、一番後ろに Final Thoughts があります。
返信削除>nfunato さん
返信削除コメントありがとうございます!
さっそくPDF確認してみました、Final Thoughtを先に確認してみたのですが
「パッケージは文字列をどうやってシンボルに変換するかをコントロールしている。他は何もしていない。」とは、、、!Zenめいており奥深さを感じます、、、。改めて読み直して試してみます!
ぜひまたご教授いただければと思います。ありがとうございます!
Common Lispにおけるpackageは、いわゆる名前空間の機能(例えば、複数のプログラマが一つの名前を別の用途に用いてしまっても、プログラム全体を書き換えずにそれらを一つのシステムの中で用いたりできるようにする)を提供するために導入されているわけですが、
削除その実現手法としては、packageは名前(ここでは文字列)からシンボルへのマッピングを提供するようになって(http://www.lispworks.com/documentation/HyperSpec/Body/11_aa.htm)います。
これが、Final Thoughts冒頭段落の第3文(Packages control ..., nothing else.)に書いてあることです。(第4文は、CLの他の知識に関連することなので、最初は無視してよいです)
ここで、他の多くの言語と違うところは、package自体が第一級のLisp Objectになっていることです。つまり、実行時に(例えばREPLから対話的に)操作できます。もっとも、真剣な計算をしている最中に操作することは意図されておらず、プログラム環境の操作手段の一部として提供されているものと思います。
あとは、Common Lisp のsymbolは、(少なくとも概念的には)、name, value, function, package, property-list の5つのスロットを持つ構造体である、ということを理解すればよいかと思います。
おっと、最後のsymbolの構造についてはここにあります:
削除http://www.lispworks.com/documentation/lw70/CLHS/Body/t_symbol.htm
コメントありがとうございます!
返信削除まずちゃんと定義があって文書にあり、そして自分は見つけられていないということに少々愕然とするところではあります。若干またかやってしまったか、、、とも思います、、、お教えいただいてありがとうございます!
ちょっと私的に時間が取れず現在確認中の状態になっております。お教えいただいた内容と、少し確認した内容とで、概念としては理解が進んだようにように思います。記事のアップデートはまたしばらく先になりそうですが、、、。
反応が遅くて恐縮ですが、ぜひまたご教授いただければ幸いです!コメントありがとうございます!