パッケージ


*package*

Type: Variable
Package: lisp
実行中のパッケージを保持しています。
in-packageで別のパッケージに移ることができます。

使用例:
  *package*
  => #<package: user>

SeeAlso: パッケージ
SeeAlso: defpackage
SeeAlso: in-package
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

defpackage

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: make-package
SeeAlso: find-package
SeeAlso: use-package
SeeAlso: delete-package
SeeAlso: in-package
SeeAlso: package-name
SeeAlso: package-nicknames
SeeAlso: パッケージ
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

delete-package

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
SeeAlso: defpackage
SeeAlso: パッケージ
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

do-all-symbols

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
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

export

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: パッケージ
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

find-package

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: パッケージ
SeeAlso: defpackage
SeeAlso: delete-package
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

find-symbol

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
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

import

Type: Function
Arguments: import SYMBOLS &optional PACKAGE
Package: lisp
File: builtin.l
シンボルのリストを指定して、その全てのシンボルをパッケージ内でパッケージ
名指定なしでアクセスできるようにします。シンボルが既にパッケージ内に存在
する場合は例外を発生します。

SeeAlso: パッケージ
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

in-package

Type: Macro
Arguments: in-package NAME
Package: lisp
File: package.l
どのパッケージで実行するかを変更します。変更した後に作られたシンボルは、
指定されたパッケージに登録されます。

使用例:
    ;;; これ以降新しく作られるシンボルは、"editor"パッケージに登録さ
    ;;; れるようになる。
    (in-package "editor")

SeeAlso: パッケージ
SeeAlso: *package*
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

intern

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: make-symbol
SeeAlso: パッケージ
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

list-all-packages

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: パッケージ
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

make-package

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: defpackage
SeeAlso: delete-package
SeeAlso: in-package
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

package-name

Type: Function
Arguments: package-name PACKAGE
Package: lisp
File: builtin.l
パッケージの名称を取得します。

使用例:
  (package-name (find-package "ed"))
  => "editor"

SeeAlso: package-nicknames
SeeAlso: find-package
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

unexport

Type: Function
Arguments: unexport SYMBOLS &optional PACKAGE
Package: lisp
File: builtin.l
シンボルのリストを指定して、その全てのシンボルをパッケージの外部から参照
できないようにします。

  ;; find-file は editor パッケージの外部シンボル
  (find-symbol "find-file" "editor")
  =>find-file
    :external

  ;; よって editor パッケージを use している user パッケージから参照できる
  (find-symbol "find-file" "user")
  =>find-file
    :inherited

  ;; 外部から参照できなくする
  (unepxport 'find-file "editor")
  =>t

  ;; 内部シンボルになった
  (find-symbol "find-file" "editor")
  =>editor::find-file
    :internal

  ;; user パッケージから参照できなくなった
  (find-symbol "find-file" "user")
  =>nil
    nil

  ;; 元に戻す
  (export 'ed::find-file "editor")
  =>t

SeeAlso: export
SeeAlso: パッケージ
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

unintern

Type: Function
Arguments: unintern SYMBOL &optional PACKAGE
Package: lisp
File: builtin.l
パッケージにシンボルがあれば削除してtを、なければnilを返します。

SeeAlso: intern
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

uninterned

Type: Misc
uninterned とは intern されていない状態を表します。
すなわちどのパッケージにも属していない状態です。

使用例:
  ;;; make-symbolでパッケージに属さないシンボルを作ってみる。
  (setq a (make-symbol "foo"))  => #:foo
  (symbol-package a)            => nil

[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

unuse-package

Type: Function
Arguments: unuse-package PACKAGES-TO-UNUSE &optional PACKAGE
Package: lisp
File: builtin.l
パッケージが別のパッケージを使用しないようにします。

使用例:
  ;;; 使用例はcalc.lを参照
  (unuse-package "lisp" *calc-package*)
  => t

SeeAlso: use-package
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

use-package

Type: Function
Arguments: use-package PACKAGES-TO-USE &optional PACKAGE
Package: lisp
File: builtin.l
指定されたパッケージ(省略された場合はカレントのパッケージ)が使
用する他のパッケージを設定します。

SeeAlso: find-package
SeeAlso: defpackage
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

with-package-iterator

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
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

どの関数の頭に何がつくのでしょうか?

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: パッケージの概要
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

パッケージ

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: パッケージの概要
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]

パッケージの概要

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: パッケージ
[ Intro | 目次 | 索引 | 目的別 | パッケージ ]