按原样重新编译 CL 系统 运行
Recompiling a CL system as it is running
我是运行一个普通的lisp项目,每5秒获取一次市场数据。我对代码做了一些调整,想在生产环境中更新它。事件循环真的很标准:
(loop
(fetch-data)
(sleep 5))
由于 loop
的阻塞特性,我无法使用 REPL。
我的问题:我可以动态更新 运行 代码吗?
我知道我可以用 (asdf:compile-system :system-name)
重新编译项目
我也知道我可以redefine classes at runtime。 (并不是说我在我的实现中使用 类)
但是现在我不能使用 REPL,我必须以某种方式将环境加载到另一个 REPL 中。有没有办法做到这一点? (我正在使用 SBCL)
在我看来,最简洁的方法就是实现异步数据获取。
Because of the blocking nature of the loop I don't have the REPL at my disposal.
有很多解决方法:
- 自己开始循环 thread。
- 或者在你的 Lisp
中连接类似 SLIME to a running SWANK 的东西
- 或者您的循环可以定期检查代码更新
我也不会编译程序内部的代码,除非您知道代码确实可以编译或者您可以处理编译错误。编译和加载通常也比加载慢。
请注意,将代码加载到 运行ning 程序中并未标准化。使用 SBCL,您不仅可以拥有线程,而且线程可能 运行 并发。有一些更改可能不是线程安全的,或者会导致 运行ning 程序出现问题。因此,您需要计划好要进行的更改。
有一点可以简化更改代码:在循环休眠时加载更新,如果可以在 5 秒内加载更新 window。
一些程序可能需要更多的架构,比如在更新这些部分时关闭部分程序的能力。
不确定这是否适用于您的情况,但我已经非常成功地使用 swank::handle-request 在循环中调用 运行 交互式应用程序进行 REPLing:
(defun handle-swank-requests ()
(let ((connection (or swank::*emacs-connection*
(swank::default-connection))))
(when connection
(swank::handle-requests connection t))))
(defun main-cycle ()
(loop
(restart-case
(progn
(handle-swank-requests)
(fetch-data)
(sleep 5))
(continue () :report "Continue" (print "Continued after error from SWANK")))))
restart-case 构造允许在出现错误时不中断循环,并在错误得到修复后继续循环。
我不确定这种方法是否可靠,AFAIK swank 默认使用线程处理请求,因此可能存在一些同步问题,因此可能不适用于生产用途,用于开发/调试。
据我所知CEPL uses something similar, may be more sophisticated and robust version. Also nice CEPL demo video.
我是运行一个普通的lisp项目,每5秒获取一次市场数据。我对代码做了一些调整,想在生产环境中更新它。事件循环真的很标准:
(loop
(fetch-data)
(sleep 5))
由于 loop
的阻塞特性,我无法使用 REPL。
我的问题:我可以动态更新 运行 代码吗?
我知道我可以用 (asdf:compile-system :system-name)
我也知道我可以redefine classes at runtime。 (并不是说我在我的实现中使用 类)
但是现在我不能使用 REPL,我必须以某种方式将环境加载到另一个 REPL 中。有没有办法做到这一点? (我正在使用 SBCL)
在我看来,最简洁的方法就是实现异步数据获取。
Because of the blocking nature of the loop I don't have the REPL at my disposal.
有很多解决方法:
- 自己开始循环 thread。
- 或者在你的 Lisp 中连接类似 SLIME to a running SWANK 的东西
- 或者您的循环可以定期检查代码更新
我也不会编译程序内部的代码,除非您知道代码确实可以编译或者您可以处理编译错误。编译和加载通常也比加载慢。
请注意,将代码加载到 运行ning 程序中并未标准化。使用 SBCL,您不仅可以拥有线程,而且线程可能 运行 并发。有一些更改可能不是线程安全的,或者会导致 运行ning 程序出现问题。因此,您需要计划好要进行的更改。
有一点可以简化更改代码:在循环休眠时加载更新,如果可以在 5 秒内加载更新 window。
一些程序可能需要更多的架构,比如在更新这些部分时关闭部分程序的能力。
不确定这是否适用于您的情况,但我已经非常成功地使用 swank::handle-request 在循环中调用 运行 交互式应用程序进行 REPLing:
(defun handle-swank-requests ()
(let ((connection (or swank::*emacs-connection*
(swank::default-connection))))
(when connection
(swank::handle-requests connection t))))
(defun main-cycle ()
(loop
(restart-case
(progn
(handle-swank-requests)
(fetch-data)
(sleep 5))
(continue () :report "Continue" (print "Continued after error from SWANK")))))
restart-case 构造允许在出现错误时不中断循环,并在错误得到修复后继续循环。
我不确定这种方法是否可靠,AFAIK swank 默认使用线程处理请求,因此可能存在一些同步问题,因此可能不适用于生产用途,用于开发/调试。
据我所知CEPL uses something similar, may be more sophisticated and robust version. Also nice CEPL demo video.