Racket REPL over TCP

9 scheme eval racket read-eval-print-loop

我用Racket(以前的PLT Scheme)构建了一个相当复杂的应用程序,并希望添加一个REPL用于调试目的.我试图通过TCP流访问它:

(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))))))))))))
Run Code Online (Sandbox Code Playgroud)

(Try name result-if-exception form) 是一个提供基本异常处理的宏,(log ...)和(display-and-log ...)执行它们的声音.

现在,如果我访问REPL,我甚至无法评估常量,因为我不断收到错误compile: unbound identifier (and no #%app syntax transformer is bound) at: #%top-interaction.如何使这个REPL工作?如何define在启动REPL服务器之前访问值d?

Eli*_*lay 3

您正在使用read-eval-print-loop,它本质上与使用相同eval,因此会遇到同样类型的问题。有关详细说明,请参阅相关指南部分。最好完整阅读该内容,但您正在寻找的答案要么是“命名空间”部分描述的内容,要么是“命名空间和模块”部分 - 第一个是您是否想要顶级类型的命名空间,并且第二个是如果您想要一个与代码所在的实际文件相对应的命名空间。(第一个通常更好 - 例如,如果您使用第二个,那么它repl-server本身可供 REPL 用户使用,这使其成为一个有问题的功能...)

它看起来是这样的:

...
(thread (lambda ()
          (parameterize ([current-namespace (make-base-namespace)])
            ...same code...)))
...
Run Code Online (Sandbox Code Playgroud)

对于第二个,定义一个锚并使用namespace-anchor->namespace该页面上的最后一个示例所示。

[顺便说一句,另请参阅这个run-server东西,它有点旧,但仍然有用。]