Next: 依存関係について, Previous: オペレーション, Up: ASDFのオブジェクトモデル [Contents][Index]
component
オブジェクトが表すのは、1つのソースファイルか、複数のソースファイルのまとまりか、あるいはそれらから変換されるもの(faslなど)です。
component
の組み込みのサブクラスとして重要なのはsystem
、source-file
、module
です。system
はコンポーネント階層のトップレベルにある特別なコンポーネントであり、find-system
によって発見することができます。source-file
は1つのソースファイルに対応します。module
は中間的なコンポーネントであり、他のコンポーネント(source-file
やさらなるmodule
であっても良い)のまとまりを表します。(→ コンポーネントの組み込みのサブクラス)
システム指示子(system designator)はシステムそのものか、システムを表す文字列、シンボルです。(コンポーネント名の仕様と同じく、シンボルは小文字に変換されます。)
コンポーネント指示子(component designator)は基点となるコンポーネントに対する相対的な指示子であり、コンポーネントそのものか、文字列、シンボルか、あるいはコンポーネント指示子のリストです。
find-system
はシステム指示子を引数に取り、システムを返します。システムが見つからなかった場合、デフォルトではエラーmissing-component
を通知しますが、error-pがnil
の場合は単にnil
を返します。
システム定義ファイルを見つけてメモリ上のシステムをアップデートするために、find-system
はリスト*system-definition-search-functions*
に含まれる関数をそれぞれfuncall
します。それらの関数はシステム名を引数に取り、(システム定義ファイルの)パス名かシステムオブジェクト(system-source-directory
でパス名に変換される)を返すべきであり、返ったパス名はメモリ上に登録されるでしょう。こうして見つかったシステム定義ファイルがロードされるのは、次の条件のいずれかを満たす場合です:
.asdファイルからシステム定義がロードされる際の暗黙のカレントパッケージはasdf-user
であり、asdf-user
はasdf
、uiop
、uiop/common-lisp
をuse
しています。27
.asdファイル内で新しい変数・関数・クラスを定義するなど、単純なシステム定義にとどまらないことをする場合は、defpackage
とin-package
で別のパッケージを作り、asdf-user
とは干渉しないようにするべきです。ただ、フォームを追加する目的が、(開発・デバッグのために)cl:load
で手動で.asdファイルをロードできるようにすることなのであれば28、そうするよりもasdf:load-asd
を使うことを推奨します。なお、SLIMEを使っている場合は、slime-asdf
拡張をロードすれば、.asdファイルの編集時にasdf:load-asd
が適切に適用されるようになります。
デフォルトでは*system-definition-search-functions*
は3つの関数からなるリストです。最初の関数は、*central-registry*
の要素を評価して得られた各ディレクトリから、ファイル名がシステム名であり、拡張子が.asdであるファイルを探し、最初に見つかったパス名を返します。ただし、探索対象のシステムがそのファイル内で実際に定義されているかどうかはチェックしません。2つ目の関数は同様のことをsource-registry
で指定されたディレクトリに対して行いますが、実際にファイルシステムを探すのは1回のみであり、結果はキャッシュされます。29 3つ目の関数はpackage-inferred-system
拡張で使われます。詳細はpackage-inferred-system拡張を参照してください。
システムの探索関数の仕様からもわかるように、システムfoo
はfoo.asdという名のファイルに定義するべきであり、また、ファイルはセントラルレジストリかソースレジストリに指定されたディレクトリに置くようにするべきです。
1つのファイル内で複数のシステムを定義するのが便利なケースも良くあるでしょうが、ASDFはシステム名に基づいてシステム定義ファイルを探すことしかできません。この理由により、ASDF 3からはシステム定義を探すアルゴリズムが拡張され、ファイルfoo.asdには、システムfoo
に加えてfoo/bar
、foo/baz
、foo/quux
といった名のシステムも定義できるようになりました。/
で区切られたシステム名の最初の部分をシステムのプライマリネーム(primary name)と呼び、対応するシステムをプライマリシステム(primary system)と呼びます。ASDF 3は、名前にスラッシュを含むシステムを探すように指示されると、関数asdf:primary-system-name
によってプライマリネームを抽出し、まずはプライマリシステムを探してロードしようとします。そして、見つかった場合は、そのファイルにターゲットのシステムが定義されているかどうか、もしくはpackage-inferred-system
が定義されているかどうか調べます。30
foo.asdに、この命名ルールに従わないシステム(例えばfoo-test
など)が定義されている場合、ASDFはシステム定義の場所を自動的に見つけることができないので、事前に(asdf:find-system "foo")
を実行するなどして、明示的にプライマリシステムの定義をロードしておかなければなりません。我々はそのような命名の慣習をやめることを強く推奨しますが、今のところ、後方互換性のためにサポートされてはいます。
nameがスラッシュ/
によって区切られている場合、primary-system-name
はプライマリネーム、つまり最初の部分を返します。
一般的には、この関数を直接呼び出すべきではありません。この関数がAPIの一部としてエクスポートされているのは、独自の*system-definition-search-functions*
を使いたいプログラマのためです。
locate-system
はシステム名の指示子を引数に取り、システム定義をどこからロードすれば良いか調べようとします。
[訳者補足]
この関数そのものはシステム定義をロードすることはない――と原文には書かれています。しかし現在のバージョンでは、プライマリネームが絡んでいるケースで、例えば(asdf:locate-system :baz/test)
などとすると、baz
とbaz/test
のシステム定義がロードされることがあるようです。いずれにせよ、システム定義のロードにはfind-system
を、システムそのもののロードにはload-system
を使うべきです。
[訳者補足終わり]
この関数は6つの値を返します: foundp、found-system、pathname、
previous、previous-time、previous-primary。foundpはシステムが見つかれば(未登録であれ、登録済みであれ)真です。found-systemがnil
でない場合、システムオブジェクトです。(そのシステムは登録されているかもしれないし、されていないかもしれません。)
pathnameがnil
でない場合、システム定義ファイルのパス名であり、このパス名はfound-systemかpreviousのシステムと対応しているでしょう。previousがnil
でない場合、前回ロードされた同名のシステムオブジェクトです。(なお、ここでロードされているのはシステム定義であって、システムそのものではないことに注意しましょう。)previous-timeがnil
でない場合、previousの定義が前回ロードされた際のシステム定義ファイルのタイムスタンプです。previous-primaryがnil
でない場合、システムpreviousのプライマリシステムです。
例えば、ソースレジストリに登録されたパス/current/path/to/foo.asdにシステム定義ファイルがあるとしましょう。しかし、システムfoo
は前回は/previous/path/to/foo.asdからロードされたとします。このとき、locate-system
は次の値を返すでしょう:
t
です。
nil
です。
#p"/current/path/to/foo.asd"
です。
system
オブジェクトであり、そのsystem-source-file
スロットは#p"/previous/path/to/foo.asd"
です。
#p"/previous/path/to/foo.asd"
がロードされたときのタイムスタンプです。
baseコンポーネント(あるいは指示子)とpathを引数に取り、baseを基点としてpathで指示されるコンポーネントを見つけます。
pathがコンポーネントオブジェクトの場合は、baseに関係なく、そのままpathが返ります。
pathが文字列かシンボル(coerce-name
で文字列に変換される)の場合、baseはシステムかモジュールを指していなくてはなりません。この場合、返り値はpathの指すbaseの子コンポーネントです。
pathがcons
セルの場合、find-component
はbaseとpathのcar
から再帰的に子コンポーネントを辿り、末端のコンポーネントを返します。
baseがnil
の場合、(find-component path nil)
と同等になります。
baseが文字列かシンボル(coerce-name
で文字列に変換される)の場合、baseはfind-system
の返すシステムであるとみなされます。
baseがcons
セルの場合、baseは(find-component (car base) (cdr base))
の返すコンポーネントであるとみなされます。
• コンポーネントの共通の属性 | ||
• コンポーネントの組み込みのサブクラス | ||
• 新しいコンポーネント型を定義する |
バージョン2.27~3.0.3では、uiop
の代わりにuiop/package
のみがuse
されていました。バージョン3.1.2以前に対応したコードを書くためには、uiop
をuse
したパッケージを自ら定義するか、あるいはuiop:
というパッケージ接頭辞をいちいち付ける必要があります。
[訳注] 例えば冒頭に(cl:in-package :asdf-user)
を追加する、など。
[訳注] clear-source-registry
でキャッシュのリセットができます。
ASDF 2.26以前はプライマリネームの機能をサポートしていませんでした。従って、それらのバージョンでは、システムfoo/bar
がfoo.asdに定義されている場合は、(asdf:find-system "foo")
を実行するなどして、事前にそのファイルを明示的にロードしなければなりません。我々はASDF 2をサポートしていませんので、ASDF 3にアップグレードすることを推奨します。