6

SBCL の #'save-lisp-and-die を使用して、非常にうまく機能するサーバー アプリケーション App1 を作成するとします。ここで、App1 を停止せずに、関数 #'func1 を新しいバージョンに置き換えたいと考えています。Common Lisp でそれを行うにはどうすればよいでしょうか?

どんな提案でも大歓迎です!

4

2 に答える 2

10

私は個人的に、SWANK (SLIME のサーバー部分) が実行されていることを確認します。これにより、Emacs+SLIME を使用していつでもイメージに接続し、必要なものを再定義できます。

(ql:quickload "swank")
(swank:start-server :port 1234) ;; listen for SLIME connections on port 1234

M-x slime-connect次に、Emacs で、プロンプトに従うことができます。

なんらかの理由でこれを行いたくない場合は、実装によって特定のものが提供される場合があります。

于 2012-01-16T00:54:41.123 に答える
5

新しい関数定義をロードする必要があります。その後、新しい機能がすぐに利用できるようになります。コードは新しくロードされた関数を呼び出します。

新しい関数定義は、さまざまな方法でロードできます。

  • (load (compile-file "file.lisp"))file.lisp関数のソースコードはどこですか
  • (load "file.fasl")file.faslコンパイルされたソースコードはどこにありますか
  • (eval (defun ...))

もちろん、例外と複雑さがあります:

  • これは、以前の関数のすでに実行されている呼び出しを置き換えるものではありません。たとえば、無限のイベントループは、この方法で変更することはできません。ある種の停止と新しい関数の呼び出しをサポートする必要があります。ただし、このような長時間実行される関数はまれです。ループの代わりに再帰を使用することで回避できます(ただし、すべてのコンパイラが末尾呼び出しの最適化を行うわけではありません)。
  • 関数へのポインタをどこかで取得した場合(たとえば、関数の名前は(function FOO)whereでFOO)、古い値が保持されます。これを回避するには、関数ポインタの代わりにシンボルを使用します(シンボルは可能ですfuncall)。
  • 関数のコードはガベージコレクションの対象です。古いバージョンの関数への参照を残さないように注意する必要があります。また、一部の機能が不要になった場合は、fmakunboundその記号を忘れないでください。
  • 関数がコンパイル時に使用された場合は、影響を受けるすべてのコードも再ロードする必要があります
  • 高レベルの最適化(デフォルトではない)があった場合、コンパイラーが関数を他の関数にインライン化した可能性があります。CLHSは、関数の再定義が「未定義動作」になる場合を区別します。

しかし実際には、コードのリロードはほとんどのCommonLisp実装でうまく機能します。

于 2012-01-17T18:55:49.213 に答える