2016-12-15 59 views
1

我正在運行一個通用的lisp項目,每5秒鐘獲取一次市場數據。我對代碼做了一些調整,並希望在生產環境中對其進行更新。事件循環是非常標準:重新編譯正在運行的CL系統

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

因爲loop的阻擋性質的我沒有REPL在我手上。

我的問題:我可以動態更新運行代碼嗎?

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

我也知道,我可以redefine classes at runtime重新編譯該項目。 (不是說我在實現中使用類)

但是現在我不能使用REPL,我必須以某種方式在另一個REPL中加載環境。有沒有辦法做到這一點? (我正在使用SBCL)

在我看來,最簡潔的方法是隻實現異步數據提取。

+0

你在哪個平臺上運行?你能用Control + C中斷並重新編譯嗎? – jkiiski

+0

我正在使用SBCL。我知道我可以打斷,但這樣我的數據就會有差距。 – tsikov

+0

你在自己的線程中運行循環嗎? – coredump

回答

3

由於循環的阻塞性質,我沒有REPL可供使用。

有辦法圍繞它:

我也不會和編譯代碼裏面的程序,除非你知道這些代碼實際上編譯你可以處理編譯錯誤。編譯和加載通常也比加載更慢。

請注意,將代碼加載到正在運行的程序中並不標準化。使用SBCL,您不僅可以擁有線程,而且線程可以同時運行。有些更改可能不是線程安全的,或者是在正在運行的程序中導致問題。因此你需要計劃你想要做什麼樣的改變。

簡化更改代碼的一件事:在循環睡眠期間加載更新,如果在5秒窗口內可能的話。

某些程序可能需要更多架構,例如在更新這些部件時關閉部分程序的功能。

+0

謝謝。你能舉一個例子說明正在運行的程序如何檢查自己的更新。可以是非常高級的代碼示例。 – tsikov

+1

@tsikov:primitive:只是檢查某個目錄中是否存在fasl文件,如果是,請加載它,然後移開它... –

1

不知道這是怎麼回事你的情況的工作,但我已經非常成功地使用了斯旺克::處理請求的循環中調用與正在運行的交互式應用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-案例結構允許不會打破錯誤循環,並在錯誤得到修復後繼續執行。

我不確定這種方法是否具有防彈性,AFAIK swank默認使用線程來處理請求,所以可能會有一些同步問題,因此可能不會用於開發/調試的生產用途。

AFAIK CEPL使用類似的東西,可能會更復雜和健壯的版本。也不錯CEPL demo video