在运行时重新编译CL系统

时间:2016-12-15 09:16:48

标签: common-lisp read-eval-print-loop sbcl

我正在运行一个常见的lisp项目,每5秒获取一次市场数据。我对代码做了一些调整,并希望在生产环境中更新它。事件循环非常标准:

(loop
   (fetch-data)
   (sleep 5))

由于loop的阻塞性质,我没有掌握REPL。

我的问题:我可以动态更新正在运行的代码吗?

我知道我可以使用(asdf:compile-system :system-name)

重新编译项目

我也知道我可以redefine classes at runtime。 (不是我在我的实现中使用类)

但是现在我不能使用REPL我必须以某种方式在另一个REPL中加载环境。有没有办法做到这一点? (我正在使用SBCL)

在我看来,最干净的方法是实现异步数据提取。

2 个答案:

答案 0 :(得分:3)

  

由于循环的阻塞性质,我没有可供使用的REPL。

有各种方法:

我也不会编译程序中的代码,除非你知道代码实际编译或者你可以处理编译错误。编译和加载通常也比加载慢。

请注意,将代码加载到正在运行的程序中并不是标准化的。使用SBCL,您不仅可以拥有线程,而且线程可以同时运行。有些更改可能不是线程安全的,或者在正在运行的程序中导致问题。因此,您需要计划您想要做的更改。

简化更改代码的一件事:在循环休眠时加载更新,如果在5秒窗口内可以的话。

某些程序可能需要更多架构,例如在更新这些部件时关闭部分程序的能力。

答案 1 :(得分:1)

不确定这是否适用于您的情况,但我已经成功地使用swnk :: 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")))))

重启案例构造允许不破坏错误循环,并在错误得到修复后继续。

我不确定这种方法是否是防弹的,AFAIK swank默认使用线程进行请求处理,因此可能存在一些同步问题,因此可能不会用于生产用途,无法进行开发/调试。

AFAIK CEPL使用类似的东西,可能是更复杂和更健壮的版本。也很好CEPL demo video

相关问题