パッケージ
Type: Variable
Package: lisp
実行中のパッケージを保持しています。
in-packageで別のパッケージに移ることができます。
使用例:
*package*
=> #<package: user>
SeeAlso: パッケージ
Type: Macro
Arguments: defpackage PACKAGE-NAME &rest OPTIONS
Package: lisp
File: package.l
新しくパッケージを作ります。
:internal-size 内部シンボルのハッシュサイズ
:external-size 外部シンボルのハッシュサイズ
:internal-size 及び :external-size の大きさは、だいたい登録するシンボル
数の1/3ぐらいの値でいいでしょう。この値が足らないからといって、新しいシ
ンボルが登録できない訳ではないので、たいして気にする必要はないでしょう。
ハッシューがチェーンされて、検索(intern時のみ)がちょっと遅くなるだけで
す。こだわる方は素数を選ぶでしょう。
使用例:
;;; henmiというパッケージを作る。
;;; lisp, editorをuseしています。
(defpackage "henmi"
(:use "lisp" "editor")
(:internal-size 200)
(:external-size 10))
互換性:
:internal-size, :external-size はcommonにはない。
SeeAlso: パッケージ
Type: Function
Arguments: delete-package PACKAGE
Package: lisp
File: builtin.l
パッケージを削除します。
使用例:
;;; test 用パッケージを作る
(defpackage "test")
=> #<package: test>
(find-package "test")
=> #<package: test>
;;; test パッケージを削除する
(delete-package "test")
=> t
(find-package "test")
=> nil
SeeAlso: make-package
Type: Macro
Arguments: do-all-symbols (VAR &optional RESULT-FORM) &body BODY
Package: lisp
File: package.l
全シンボルを列挙します。
VAR : 列挙されたシンボルを格納する変数名を指定します。
RESULT-FORM : (詳細不明)
BODY : 実行するフォームを指定します。
使用例:
;;; シンボルを列挙して変数・関数・マクロ・パッケージを出力してみる。
(do-all-symbols (sym)
(and (or (boundp sym)
(fboundp sym))
(format t "~:[ ~;V~]~:[ ~;F~]~:[ ~;M~] ~A ~S~%"
(boundp sym)
(fboundp sym)
(macro-function sym)
(package-name (symbol-package sym))
sym)))
SeeAlso: with-package-iterator
Type: Function
Arguments: export SYMBOLS &optional PACKAGE
Package: lisp
File: builtin.l
シンボルをパッケージの外部から参照できるようにします。
引数で指定された シンボル(変数や関数)はパッケージからエクスポートされ、
別のパッケージから修飾子無しで参照できるようになります。ただし、修飾子無
しで参照するには、別のパッケージからもuse-packageもしておかないといけませ
ん。
use ┌system──┐
┌─┤ │
┌lisp───┐←─┘ └─────┘ ┌user───┐
│ │←────────────┬─┤ │
└─────┘←─┐ ┌editor──┐ │ └─────┘
└─┤ │←─┘
└─────┘
上の図はどのパッケージをuse-pakcageしているかを示しています。
パッケージがuseする他のパッケージはpackage-use-listを使って確認すること
ができます。userは、lispとeditorをuse-packageしています。
si:system-rootはsystemからexportされていますが、userがsystemを
use-packageしていないので修飾子が必要です。
;;; system-rootがsystemからexportされていることを確認する。
(find-symbol "system-root" "system")
=> system:system-root
:external
このためuserからsystem-rootを使用する場合には(si:system-root)という呼び
出し方になります。
--- 原文 ---
Description: Symbols should be a symbol or a list of symbols which are
made external symbols of package. Symbols in the list that are already
external are unaffected whilst those that are internal but not inherited
become external. If a symbol in the list is inherited and thus internal,
the symbol is first imported into package, as if by import, and the becomes
external. By convention, a call to export is placed at the beginning of
a file to advertise all the symbols that are intended for use by other
programs. export returns t. package should be a package or the name or
nickname of a package.
使用例:
;;; 引数で指定された aset, file-name-sans-versions, ...は
;;; エクスポートされ、別のパッケージから参照できるようになる。
(export '(aset file-name-directory file-name-nondirectory
file-name-sans-versions))
SeeAlso: パッケージ
Type: Function
Arguments: find-package NAME
Package: lisp
File: builtin.l
パッケージを名前で検索して、そのパッケージを返します。
NAME : パッケージの名前
使用例:
;;; lispとsystemパッケージを取得してみる。
(find-package "lisp")
=> #<package: lisp>
(find-package "si")
=> #<package: system>
;;; "baz"という名のパッケージは存在しない
(find-package "baz")
=> nil
SeeAlso: パッケージ
Type: Function
Arguments: find-symbol STRING &optional PACKAGE
Package: lisp
File: builtin.l
パッケージ中にシンボルが登録されているかを調べます。
STRING : シンボルの名前
PACKAGE : パッケージの名前
戻り値は多値で返されます。
nil シンボルが見つからなかった場合はnilを返します。
nil以外 シンボルが見つかった場合はそのシンボルをそのまま返します。
使用例:
;;; find-fileとfind-file-internalというシンボルを調べてみる。
(find-symbol "find-file" "lisp")
=> nil
nil
(find-symbol "find-file" "editor")
=> find-file
:external
(find-symbol "find-file-internal" "editor")
=> editor::find-file-internal
:internal
SeeAlso: intern
Type: Function
Arguments: import SYMBOLS &optional PACKAGE
Package: lisp
File: builtin.l
シンボルのリストを指定して、その全てのシンボルをパッケージ内でパッケージ
名指定なしでアクセスできるようにします。シンボルが既にパッケージ内に存在
する場合は例外を発生します。
SeeAlso: パッケージ
Type: Macro
Arguments: in-package NAME
Package: lisp
File: package.l
どのパッケージで実行するかを変更します。変更した後に作られたシンボルは、
指定されたパッケージに登録されます。
使用例:
;;; これ以降新しく作られるシンボルは、"editor"パッケージに登録さ
;;; れるようになる。
(in-package "editor")
SeeAlso: パッケージ
Type: Function
Arguments: intern STRING &optional PACKAGE
Package: lisp
File: builtin.l
文字列からシンボルを作成します。作成したシンボルは指定されたパッケージに
internされます。make-symbolも文字列からシンボルを作り出しますが、パッケ
ージにinternされません。
STRING : 文字列
PACKAGE : 作成したシンボルを登録するパッケージ
使用例:
;;; foobarというシンボルが*package*に登録される
(intern "foobar")
=> foobar
;;; foobazというシンボルがlispパッケージに登録される。
(intern "foobaz" (find-package "lisp"))
=> foobaz
--- 原文 ---
Description: Similar to find-symbol but creates a new symbol if a match
is not found for string. The new symbol with print name string is created
and is added to package. package becomes the home package of the new
symbol, and the symbol is returned. The new symbol created is internal
unless package is the keyword package in which case the symbol is external.
The second value returned is as for find-symbol , except that nil indicates
that a new symbol was created. read uses intern to convert symbol names
into the symbols themselves.
SeeAlso: find-symbol
SeeAlso: symbol-name
SeeAlso: unintern
SeeAlso: パッケージ
Type: Function
Arguments: list-all-packages
Package: lisp
File: builtin.l
xyzzy内に存在するパッケージ一覧をリストで返します。
使用例:
(list-all-packages)
=> (#<package: win-user> #<package: winapi> #<package:
foreign> #<package: lisp> #<package: system> #<package:
keyword> #<package: user> #<package: editor>)
SeeAlso: パッケージ
Type: Function
Arguments: make-package PACKAGE-NAME &key :nicknames :use :internal-size :external-size
Package: lisp
File: builtin.l
パッケージを作成します。defpackageとの違いは?(詳細不明)
使用例:
(make-package name :external-size 0)
SeeAlso: delete-package
SeeAlso: in-package
Type: Function
Arguments: package-name PACKAGE
Package: lisp
File: builtin.l
パッケージの名称を取得します。
使用例:
(package-name (find-package "ed"))
=> "editor"
SeeAlso: find-package
Type: Function
Arguments: provide MODULE-NAME
Package: lisp
File: evalmacs.l
ある機能を持ったモジュールがロードされた事を示すためにファイルの先頭に書
いておく「おまじない」です。ここに書いたモジュール名が変数*modules*に登
録されます。
requireがモジュールのロードをする際にこの変数がチェックされてロード済だ
ったらもうロードしません。汎用的なモジュールを書く場合には使うようにしま
しょう。
互換性:
Common Lispにはあり。
muleにはなさそう。
使用例:
;;; lispmode.lより
(provide "lispmode")
SeeAlso: require
Type: Function
Arguments: require MODULE-NAME &optional PATHNAME
Package: lisp
File: evalmacs.l
指定したモジュールを読み込みます。既に読込済みであれば何もしません。
--- 原文 ---
Description: the argument module-name, which can be a string or a symbol
(in which case the print name of the symbol is used), should be the name
of some Lisp subsystem, which may or may not be already in the Lisp image.
require checks to see if it has been loaded by looking for it on the list
which is the value of *modules*. The test is case-sensitive. If the module
name is not on the *modules* list, require tries to load it into Lisp.
If pathname is present as a single pathname or a list of pathnames, require
loads those files in order. If the argument pathname is not present,
require attempts to load the file named module-name (or the print name
of module-name if it is a symbol). If the module is already present,
require returns nil. It is an error if the files cannot be loaded for any
reason. Note that module-name is typically a symbol and, since symbol
print names rarely also name files, it is recommended that pathname be
supplied.
互換性:
Common Lispにはあり。
muleにはなさそう。
使用例:
(require "foreign")
SeeAlso: provide
SeeAlso: パッケージ
Type: Function
Arguments: unexport SYMBOLS &optional PACKAGE
Package: lisp
File: builtin.l
シンボルのリストを指定して、その全てのシンボルをパッケージに登録します。
SeeAlso: export
SeeAlso: パッケージ
Type: Function
Arguments: unintern SYMBOL &optional PACKAGE
Package: lisp
File: builtin.l
パッケージにシンボルがあれば削除してtを、なければnilを返します。
SeeAlso: intern
Type: Misc
uninterned とは intern されていない状態を表します。
すなわちどのパッケージにも属していない状態です。
使用例:
;;; make-symbolでパッケージに属さないシンボルを作ってみる。
(setq a (make-symbol "foo")) => #:foo
(symbol-package a) => nil
Type: Function
Arguments: unuse-package PACKAGES-TO-UNUSE &optional PACKAGE
Package: lisp
File: builtin.l
パッケージが別のパッケージを使用しないようにします。
使用例:
;;; 使用例はcalc.lを参照
(unuse-package "lisp" *calc-package*)
=> t
Type: Function
Arguments: use-package PACKAGES-TO-USE &optional PACKAGE
Package: lisp
File: builtin.l
指定されたパッケージ(省略された場合はカレントのパッケージ)が使
用する他のパッケージを設定します。
SeeAlso: find-package
SeeAlso: defpackage
Type: Macro
Arguments: with-package-iterator (MNAME PACKAGE-LIST &rest SYMBOL-TYPE) &body BODY
Package: lisp
File: package.l
指定されたパッケージのシンボルを列挙する関数を作ってもらいます。
作られた関数を呼び出すたびにシンボルが列挙されます。
MNAME : シンボルを返す関数名を指定します。
PACKAGE-LIST : パッケージのリストを指定します。
SYMBOL-TYPE : どんなシンボルを返すかを指定するようです。
使用例:
;;; 全シンボルを列挙します。
;;; 呼ぶたびに次のシンボルを返すfooという関数を定義してもらう。
(with-package-iterator (foo (list-all-packages) :internal :external)
(loop
(multiple-value-bind (f sym type package)
(foo) ; 呼ぶと次のシンボルが返ってくる。
(unless f ; なければ終わり。
(return))
(and (or (boundp sym)
(fboundp sym))
(format t "~:[ ~;V~]~:[ ~;F~]~:[ ~;M~] ~A ~S ~S~%"
(boundp sym)
(fboundp sym)
(macro-function sym)
(package-name package)
sym
type)))))
SeeAlso: do-all-symbols
Type: Tips
| パッケージという概念に関係があるんだと思いますが、どの関数の頭に何がつくの
| かというのはどこを見ればわかるんでしょうか。
M-x apropos make-chunk RET
としたときに、
system:make-chunk
のように表示されるものはパッケージが必要なものです。ちなみに、
si は system パッケージの、c は foreign パッケージのニックネー
ムです。
----------------------------------
editor::xyzzy-mode `:'が2つ表示される場合はexportされていない
^^
editor:xyzzy-mode `:'が1つ表示される場合はexportされている
^
xyzzy-mode パッケージが表示されない場合は現在のパッケージから
直接アクセスできる
SeeAlso: パッケージの概要
Type: Tips
パッケージは簡単に言うと、いわゆる oblist とか obarray といったものが
いっぱいあって、リーダがシンボルを読んだときにどの obarray を使って
find-symbol や intern をするかを指定するものです。
さらに、一つのパッケージに 内部用と外部用の二つの obarray があり、通常
は内部用に intern されます。関数 export で、内部用から外部用に移動するこ
とができます。
内部用と外部用の違いは、パッケージを作るときに(作るときじゃなくてもい
いけど)他のパッケージを使用(use)すると宣言すると、ある名前を find-symbol
するときに、そのシンボルが指定されたパッケージに存在しない場合、そのパッ
ケージが使用しているパッケージの外部用にあるかを見にいくようになっています。
exportの仕組み:
exportしても全部のパッケージから見えるわけじゃなくて、そのパッ
ケージをuseしているパッケージから見えるようになるだけです。
(package-use-list "user")
=> (#<package: lisp> #<package: editor>)
(package-use-list "editor")
=> (#<package: lisp>)
なので、editorパッケージから見えるのは、editorのシンボルとlispのexportさ
れたシンボルだけです。
※「見える」というのはパッケージの修飾子なしで参照できるという意味合いです。
SeeAlso: パッケージの概要
Type: Tips
パッケージには外部から参照されるシンボル用の空間と、内部のシンボル用の空
間があります。シンボルは最初は内部に登録されます。exportすると外部に移動
させられます。
system lisp editor user
┌───┐ ┌───┐ ┌───┐ ┌───┐
│s-exp │ │l-exp │ │e-exp │ │u-exp │ <- 外部
├───┤ ├───┤ ├───┤ ├───┤
│s-int │ │l-int │ │e-int │ │u-int │ <- 内部
└───┘ └───┘ └───┘ └───┘
通常は user で作業をしています。 user は lisp, editor を利用すると宣言し
ています。そのため、l-exp, e-exp, u-exp, u-int に登録されたシンボルをパ
ッケージの修飾子無しで参照できるようになっています(太枠の部分です)。
system lisp editor user
┌───┐ ┏━━━┓ ┏━━━┓ ┏━━━┓
│s-exp │ ┃l-exp ┃ ┃e-exp ┃ ┃u-exp ┃ <- 外部
├───┤ ┗━━━┛ ┗━━━┛ ┠───┨
│s-int │ │l-int │ │e-int │ ┃u-int ┃ <- 内部
└───┘ └───┘ └───┘ ┗━━━┛
プログラムを書いて新しいシンボルが出てくると、u-int に登録されます。
(in-package "editor") を実行後にシンボルを書くと e-int に登録されます。
system lisp editor user
┌───┐ ┏━━━┓ ┏━━━┓ ┏━━━┓
│ │ ┃ ┃ ┃ ┃ ┃ ┃ <- 外部
│ ... │ ┃ ... ┃ ┃ ... ┃ ┃ ... ┃
├───┤ ┗━━━┛ ┗━━━┛ ┠───┨
│ │ │ │ │ bar │ ┃ foo ┃
│ ... │ │ ... │ │ ... │ ┃ ... ┃ <- 内部
└───┘ └───┘ └───┘ ┗━━━┛
このあたりまでは分かりやすいと思うのですが、難しいのは「自分(editor)を
useしているパッケージ(user)に既にあるシンボル(foo)をexportしようとしてエ
ラーがでる」というトラブルです。
u-intとe-intのそれぞれにfooというシンボルを定義している状態を考えます。
この状態自体は問題ありませんが、この状態でeditor::fooをexportしようとす
るとエラーが発生します。
system lisp editor user
┌───┐ ┏━━━┓ ┏━━━┓ ┏━━━┓
│ │ ┃ ┃ ┃ X ┃ ┃ ┃ <- 外部
│ ... │ ┃ ... ┃ ┃ .↑ ┃ ┃ ... ┃
├───┤ ┗━━━┛ ┗━│━┛ ┠───┨
│ │ │ │ │ foo │ ┃ foo ┃
│ ... │ │ ... │ │ ... │ ┃ ... ┃ <- 内部
└───┘ └───┘ └───┘ ┗━━━┛
user が参照可能な範囲からすると、u-intに既にあるシンボルと同じ名前のシン
ボルがe-expに入れられようとするため、「名前が衝突するためexportできませ
ん: editor::foo」と怒られます。
(setq foo "user")
=> "user"
(setq ed::foo "editor")
=> "editor"
(export '(ed::foo) "ed")
=> 名前が衝突するためexportできません: editor::foo
これ以外にもこんな形でも起きます。lisp::fooとeditor::fooの間の問題のよう
ですが、実はuserがlispとeditorをuseしていることが原因です。
system lisp editor user
┌───┐ ┏━━━┓ ┏━━━┓ ┏━━━┓
│ │ ┃ foo ┃ ┃ X ┃ ┃ ┃ <- 外部
│ ... │ ┃ ... ┃ ┃ .↑ ┃ ┃ ... ┃
├───┤ ┗━━━┛ ┗━│━┛ ┠───┨
│ │ │ │ │ foo │ ┃ ┃
│ ... │ │ ... │ │ ... │ ┃ ... ┃ <- 内部
└───┘ └───┘ └───┘ ┗━━━┛
SeeAlso: パッケージ