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

然后在 Emacs 中,您可以M-x slime-connect,并按照提示进行操作。

如果您出于某种原因不想这样做,您的实现可能会提供一些特定的东西。

于 2012-01-16T00:54:41.123 回答
5

您需要加载新的函数定义。然后新功能将立即可用;代码将调用新加载的函数。

可以通过多种方式加载新的函数定义:

  • (load (compile-file "file.lisp"))file.lisp函数的源代码在哪里
  • (load "file.fasl")file.fasl编译的源代码在哪里
  • (eval (defun ...))

当然,也有例外和并发症:

  • 这不会取代已经运行的先前函数的调用;例如,无法以这种方式更改无限事件循环 - 它必须支持某种停止和调用新函数。但是,这种长时间运行的函数很少见。它可以通过使用递归而不是循环来解决(但并非所有编译器都进行尾调用优化)。
  • 如果您在某处抓取了指向函数的指针(例如,函数的名称(function FOO)在哪里FOO),它将保留其旧值。为避免这种情况,请使用符号而不是函数指针(可以使用符号funcall)。
  • 函数的代码是垃圾回收的对象。您应该注意不要留下对旧版本函数的引用。此外,如果某些功能变得不需要,您不应该忘记fmakunbound它们的符号。
  • 如果函数在编译时使用,所有受影响的代码也应该重新加载
  • 如果您有高级别的优化(默认情况下不是),编译器可能已将该函数内联到其他函数中。CLHS 区分重新定义函数成为“未定义行为”的情况。

但在实践中,代码重载在大多数 Common Lisp 实现中运行良好。

于 2012-01-17T18:55:49.213 回答