2011-05-10 75 views
8

我已經用Racket(以前稱爲PLT Scheme)構建了一個相當複雜的應用程序,並且希望爲調試目的添加REPL。我試圖讓它通過TCP流訪問:通過TCP的球拍REPL

(define repl-server 
    (thread (lambda() 
      (let ((listener (tcp-listen 8082 5 #t))) 
      (do() (#f) 
       (let-values (((in out) (tcp-accept listener))) 
       (thread (lambda() 
          (let ((port-string (get-port-string in))) 
          (Try "debug-repl" #f 
           (begin 
           (file-stream-buffer-mode out 'line) 
           (display-and-log "Password: " out) 
           (flush-output out) 
           (when (string=? (read-line in) "whatever") 
            (log "Connect to REPL: " port-string)) 
            (current-input-port in) 
            (current-output-port out) 
            (current-error-port out) 
            (read-eval-print-loop)) 
           (close-input-port in) 
           (close-output-port out)))))))))))) 

(Try name result-if-exception form)是提供基本的異常處理的宏,(日誌...)和(顯示和記錄...)?他們什麼聲音喜歡。

現在,如果我訪問REPL,我甚至不能評估常量,因爲我不斷收到錯誤compile: unbound identifier (and no #%app syntax transformer is bound) at: #%top-interaction。我怎樣才能讓這個REPL工作?在啓動REPL服務器之前,如何訪問值defined?

+4

大問題!你真的應該在球拍郵件列表http://lists.racket-lang.org/users/上提出這個問題。我可以預測以下幾點:1)有辦法做到這一點。 2)可能會很痛苦。 3)你可能想看看沙箱。 – 2011-05-10 07:23:05

+0

注意自我:下次使用'addlog'或類似的名稱作爲該功能的名稱... – lbruder 2011-05-10 07:57:50

回答

3

您使用的是read-eval-print-loop,與eval基本相同,因此存在同樣的問題。有關詳細說明,請參見relevant Guide section。最好是完全閱讀,但你要找的答案要麼是「命名空間」部分描述的內容,要麼是「命名空間和模塊」部分 - 第一個是如果你想要一個頂級的命名空間,並且第二個是如果你想要一個與代碼出現的實際文件相對應的名稱空間(第一個通常更好 - 例如,如果你使用第二個,那麼repl-server本身可用於REPL用戶,這使得它成爲一個有問題的功能...)

下面是它會是什麼樣子:

... 
(thread (lambda() 
      (parameterize ([current-namespace (make-base-namespace)]) 
      ...same code...))) 
... 

和第二個,定義一個錨和使用namespace-anchor->namespace作爲頁面所顯示的最後一個例子。

[BTW,也看到了run-server的事情,這是一個有點老了,但仍然是有用的。]

+0

完美地工作!我實際上使用了第二種情況,因爲這應該是普通用戶無法訪問的調試黑客。完全訪問正在運行的程序!我現在正在快樂地跳躍着:) – lbruder 2011-05-10 07:56:48

+1

爲了記錄,John的評論也非常相關 - 「racket/sandbox」庫也對製作健壯的repl有用。 (但是,從上述評論來看,顯然它向着你想要去的方向是不太可能的。) – 2011-05-10 08:08:51