2

私は現在、WindowsのSBCLでlispbuilder-sdlを使用しています。

私のソースコードは次のとおりです。

(asdf:operate 'asdf:load-op :lispbuilder-sdl)
(asdf:operate 'asdf:load-op :lispbuilder-sdl-binaries)
(asdf:operate 'asdf:load-op :lispbuilder-sdl-examples)
(sdl-examples:squashed)

ファイルをコンパイルすると、次のエラーが発生します。パッケージ「SDL-EXAMPLES」が見つかりません。

(sdl-examples:squashed)をファイルから削除すると、コンパイルは正常に行われます。次に、replで(sdl-examples:squashed)と入力すると、デモゲームが正常に開始されます。

sdl-examplesパッケージがreplから検出されたのに、ファイルをコンパイルしたときに検出されなかったのはなぜですか?

4

1 に答える 1

2

そのファイルのすべてのコンパイルは、load-opのいずれかを実行する前に行われます。したがって、Lispが行をコンパイルするとき、パッケージを定義するを(sdl-examples:squashed)実行していません。load-op

が実際に実行される前sdl-examplesにリーダーがそのsquashedシンボルを見つける必要があるパッケージについて言及しないことで、これを回避できます。load-op

(funcall (symbol-function (intern (symbol-name '#:squashed)
                                  (find-package (symbol-name '#:sdl-examples)))))

アイデアは、シンボル名からパッケージを計算し、関数に名前を付けるシンボルを検索し、名前を付けた関数をフェッチすることです。ただし、この方法では、パッケージが最初に読み取られたときではなく、コードが実行されたときにのみ存在する必要があります。次に、4つのステートメントをすべてコンパイルして順番に実行し、最後のステートメントが実行されるまでに、load-opsがパッケージを作成します。


それで、ここで何が起こっているかについてもう少し情報があります:

  • 書き込み'#:some-nameとは、パッケージの一部ではないシンボルを指します。そのため、(1)パッケージが存在すると想定したり、(2)他のパッケージをその名前でいじったりすることなく、シンボリック名を参照できます。
  • 次に'(symbol-name #:some-name)、シンボルの名前を文字列として抽出します。書いてみません"some-name"か?あなたはそうすることができました、そしてそれは通常うまくいくでしょう。しかし、この方法は、「モダンモード」の大文字と小文字を区別するLispを実行する場合にはもう少し堅牢です。
  • find-package文字列名をLispのパッケージ表現にマップします。この行を実行するまでに、パッケージが存在することを忘れないでください。
  • intern指定されたパッケージに含まれる指定された名前のシンボルを返します。
  • symbol-functionシンボルに関連付けられた関数オブジェクト(ラムダ抽象化、またはより可能性が高いのはそのコンパイル済み表現)を返します。
  • そして、funcallその関数を呼び出します。ちょっと不格好ですが、残念ながら、コードをロードする呼び出しを組み合わせて、同じファイル内のそのパッケージに存在する名前を持つパッケージを作成するためのより良い方法はありません。
于 2010-08-25T13:05:39.767 に答える