在 Chicken Scheme 中 运行 更改程序代码
Change program code while running in Chicken Scheme
Chicken Scheme 解释器 csi 正在解释程序代码时是否可以更新程序代码?如果是,怎么做?
这样我就可以交互式地更改部分代码并立即看到更改的效果。
例如,假设我编写了以下程序:
(define (loop)
(print "Ciao")
(rest 1)
(loop))
(loop)
(假设 (rest 1)
具有暂停程序一秒钟的效果)。
如果我 运行 这个程序,通过 csi,它每秒打印字符串 "Ciao"。如果我把字符串"Ciao"改成别的东西,比如改成"else",然后保存程序代码文件,那么csi继续解释旧的程序代码,所以我不断看到字符串 "Ciao"。我想,在这种情况下,当我用 "else" 替换字符串 "Ciao" 保存修改后的代码时,csi 通过查看继续其解释工作修改后的文件,而不是旧文件。
这样我就得到一些 "Ciao" 和一些 "else" 作为输出:当我在源代码中用 "else" 替换 "Ciao" 时,"else" 开始出现。
一般来说,答案是"don't"。您应该使用 REPL 的方式是评估针对它的零碎更改,然后评估一两个函数以确保一切按预期进行。这种方法的一部分是构建您的程序,以便可以轻松地对其进行分段测试,这意味着不会自动启动任何无限循环。在您询问的特定情况下,您可以改写
(define (do-stuff)
(print "Ciao"))
(define (main-loop)
(do-stuff)
(rest 1)
(main-loop))
(define (start) (main-loop))
您现在可以逐步开发 do-stuff
,定期评估您的解释器的新版本并调用它们以确保它们正常工作,然后在您确信它运行正确后最终调用 start
事物。
您可能会从 this similar question 询问有关 Common Lisp 的问题中受益匪浅。
顺便说一句,如果您使用的是 Common Lisp 和 SLIME,您现在可以或多或少地执行您建议的操作:
(defun do-stuff ()
(format t "Ciao~%"))
(defun main-loop ()
(loop (progn (do-stuff)
(sleep 1))))
(main-loop)
启动它会在您的 SLIME REPL 中的不同行上开始打印 Ciao
。如果您将 do-stuff
更改为
(defun do-stuff ()
(format t "else~%"))
然后用 C-c C-c
(slime-compile-defun
的默认绑定)点击它,你会看到你的 SLIME REPL 开始打印 else
行。
CL-USER> (main-loop)
Ciao
Ciao
Ciao
; compiling (DEFUN DO-STUFF ...)else
else
else
else
else
else
; Evaluation aborted on NIL. User break.
CL-USER>
我不确定如何在 Scheme 中完成同样的事情,但我有理由相信这是可能的。
综上所述,您有时想要 运行 一个程序部分是无限的 loop
。一个真实世界的例子是在测试某种 TCP 服务器时。如果您处于这种情况,并且您想要的工作流程是
- 写入文件
- 运行
csi my-file.scm
- 编辑文件
- 杀死
csi
- 运行
csi my-file.scm
goto 3
而您基本上只想自动执行第 4 步到第 6 步,您需要一个外部工具来为您完成。看一下 entr
or hsandbox
(后者没有开箱即用的 Scheme 支持,但看起来并不难添加)。
没有通用的方法可以让 运行 程序检查其来源是否有更改,但您似乎可以在 Chicken 中使用足够的功能来推出自己的功能:
(use posix)
(use srfi-18)
(define (watch-reload! file)
(define (tsleep n)
(thread-sleep! (seconds->time (+ n (time->seconds (current-time))))))
(define (get-time)
(file-modification-time file))
(thread-start!
(lambda ()
(let loop ((filetime '()))
(let ((newtime (get-time)))
(when (not (equal? filetime newtime))
(load file))
(tsleep 10)
(loop newtime))))))
现在您所要做的就是使用 watch-reload!
而不是 load
,如果文件已被修改,它将每 10 秒检查并重新加载一次。
如果您在文件不是有效方案时保存,它将停止工作,直到您再次对其调用 watch-reload!
。
可能吃鸡程序员有更好的解决办法
Chicken Scheme 解释器 csi 正在解释程序代码时是否可以更新程序代码?如果是,怎么做?
这样我就可以交互式地更改部分代码并立即看到更改的效果。 例如,假设我编写了以下程序:
(define (loop)
(print "Ciao")
(rest 1)
(loop))
(loop)
(假设 (rest 1)
具有暂停程序一秒钟的效果)。
如果我 运行 这个程序,通过 csi,它每秒打印字符串 "Ciao"。如果我把字符串"Ciao"改成别的东西,比如改成"else",然后保存程序代码文件,那么csi继续解释旧的程序代码,所以我不断看到字符串 "Ciao"。我想,在这种情况下,当我用 "else" 替换字符串 "Ciao" 保存修改后的代码时,csi 通过查看继续其解释工作修改后的文件,而不是旧文件。 这样我就得到一些 "Ciao" 和一些 "else" 作为输出:当我在源代码中用 "else" 替换 "Ciao" 时,"else" 开始出现。
一般来说,答案是"don't"。您应该使用 REPL 的方式是评估针对它的零碎更改,然后评估一两个函数以确保一切按预期进行。这种方法的一部分是构建您的程序,以便可以轻松地对其进行分段测试,这意味着不会自动启动任何无限循环。在您询问的特定情况下,您可以改写
(define (do-stuff)
(print "Ciao"))
(define (main-loop)
(do-stuff)
(rest 1)
(main-loop))
(define (start) (main-loop))
您现在可以逐步开发 do-stuff
,定期评估您的解释器的新版本并调用它们以确保它们正常工作,然后在您确信它运行正确后最终调用 start
事物。
您可能会从 this similar question 询问有关 Common Lisp 的问题中受益匪浅。
顺便说一句,如果您使用的是 Common Lisp 和 SLIME,您现在可以或多或少地执行您建议的操作:
(defun do-stuff ()
(format t "Ciao~%"))
(defun main-loop ()
(loop (progn (do-stuff)
(sleep 1))))
(main-loop)
启动它会在您的 SLIME REPL 中的不同行上开始打印 Ciao
。如果您将 do-stuff
更改为
(defun do-stuff ()
(format t "else~%"))
然后用 C-c C-c
(slime-compile-defun
的默认绑定)点击它,你会看到你的 SLIME REPL 开始打印 else
行。
CL-USER> (main-loop)
Ciao
Ciao
Ciao
; compiling (DEFUN DO-STUFF ...)else
else
else
else
else
else
; Evaluation aborted on NIL. User break.
CL-USER>
我不确定如何在 Scheme 中完成同样的事情,但我有理由相信这是可能的。
综上所述,您有时想要 运行 一个程序部分是无限的 loop
。一个真实世界的例子是在测试某种 TCP 服务器时。如果您处于这种情况,并且您想要的工作流程是
- 写入文件
- 运行
csi my-file.scm
- 编辑文件
- 杀死
csi
- 运行
csi my-file.scm
goto 3
而您基本上只想自动执行第 4 步到第 6 步,您需要一个外部工具来为您完成。看一下 entr
or hsandbox
(后者没有开箱即用的 Scheme 支持,但看起来并不难添加)。
没有通用的方法可以让 运行 程序检查其来源是否有更改,但您似乎可以在 Chicken 中使用足够的功能来推出自己的功能:
(use posix)
(use srfi-18)
(define (watch-reload! file)
(define (tsleep n)
(thread-sleep! (seconds->time (+ n (time->seconds (current-time))))))
(define (get-time)
(file-modification-time file))
(thread-start!
(lambda ()
(let loop ((filetime '()))
(let ((newtime (get-time)))
(when (not (equal? filetime newtime))
(load file))
(tsleep 10)
(loop newtime))))))
现在您所要做的就是使用 watch-reload!
而不是 load
,如果文件已被修改,它将每 10 秒检查并重新加载一次。
如果您在文件不是有效方案时保存,它将停止工作,直到您再次对其调用 watch-reload!
。
可能吃鸡程序员有更好的解决办法