概要
- Common Lisp の package について
- 解説したリンクを集めた
- package について説明を試みた
- package について疑問に思ったことをまとめた
参照リンク集
- #9LISP How to use ASDF - What the FUCK is the prerequisite of LOL?
- 日本語記事、Let Over Lambda のソースが読み込めなくて四苦八苦されている記事
- しかしそれ以上にPackage とASDFについての丁寧な記事
- ■ Common lisp の package と require でライブラリを使ったプログラムを書く方法。
- package についての操作について簡潔にまとめられている記事
- Packages, systems, modules, libraries - WTF?
- (英語)Package について初心者に説明するための記事
packageについて四苦八苦したあと読むと疑問が氷解する - cl-ppcre の作者 Edi Weitz による記事
- Package や Module, Library について海外メーリングリスト c.l.l (Common Lisp Language) には
この手の疑問に迷った初心者が同じような質問を毎週のように投げていると嘆いている
- (英語)Package について初心者に説明するための記事
- ファイヤープロジェクト シンボルとパッケージ
- xyzzy lisp / Common Lisp 入門 の パッケージの説明
- package についての解説記事, 使い方と関数・マクロについて解説あり
- Practical Common Lisp, Chapter 21
- Common Lisp HyperSpec, Chapter 11
- (英語)package の定義や実用記事
- Common Lisp Quick Reference
- (英語)packageもそうだが、ANSI Common Lisp 標準関数一覧を提供してくれるリファレンス、必携
CommonLispでの Packageとは?
- Lispの関数名も変数名も シンボル として扱われることを納得しておく必要がある
- 関数名、変数名、スペシャル関数名、マクロ名 etc
- シンボルが 所属 する シンボルの管理単位
- 一部の例外を除く(!)すべてのシンボルは パッケージに属している
- 例外1:gensym で生成されたシンボルは どのパッケージにも属さない
- 例外2:キーワード - キーワード(
keyword
)という 特別なパッケージに属している
- Common Lisp の第一級オブジェクトである(後述)
- CommonLisp が標準で持っている関数やマクロや変数(シンボル)は
cl, common-lisp
という名前空間に属している - REPLで実行して一時的に作られた and/or
特にパッケージを明示せず定義されたシンボルは
cl-user, common-lisp-user
という名前空間に属している
- REPL のデフォルトの package である
シンボルは第一級オブジェクトである、とは?
なんでも定義・変更できる(?) 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 でライブラリの「処理の中身とシンボル定義」を読み込む必要があります。
- 読み込んだ後から使えるようになります
- 自分でパッケージを扱いだすと、もう少し複雑な「シンボルがない」状況に直面すると思います
- 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にあるシンボルを
パッケージ名省略して使います、という宣言になる
まとめ。他の言語がむしろ、一つの文に複数の機能を備えていると言えるのでは。
- 名前空間の定義
- (名前空間に属する機能の)プログラムやデータの一括読み込み機構
- 関数名、変数名、クラス名について、名前空間の明示的な省略
ひとこと
- Common Lisp における package に調べだしたところ、
それがなんであるかについてはイメージを持てたのだが、
いざ説明を書こうとして説明が難しすぎてさじ投げた
- 伝わる書き方というのが結局見えなくなった
- 特に、他言語の例については、ある程度理解が進むとむしろ説明が難しい
- 何がわかっていなかったかわからなくなる
- 他言語の例は自分が知っている言語をさらしているだけのような気がする
- 投げたさじを拾ってわかっていることだけまとめておいておくことにした
- 伝わるように書くことをあきらめた
- Quick Reference に載っている関数を一通り試したのだが、
一部の関数が思ったように動いてくれない。使い方を勘違いしているのだろう。
Written with StackEdit.