Scheme 在“鸡肉方案”中运行时更改程序代码
在csi(鸡肉方案解释器)解释程序代码时,是否可以更新程序代码?如果是,怎么做 这样我就可以以交互方式更改部分代码,并立即看到更改的效果。 例如,假设我编写了以下程序:Scheme 在“鸡肉方案”中运行时更改程序代码,scheme,interpreter,chicken-scheme,Scheme,Interpreter,Chicken Scheme,在csi(鸡肉方案解释器)解释程序代码时,是否可以更新程序代码?如果是,怎么做 这样我就可以以交互方式更改部分代码,并立即看到更改的效果。 例如,假设我编写了以下程序: (define (loop) (print "Ciao") (rest 1) (loop)) (loop) (假设(rest 1)具有暂停程序一秒钟的效果) 如果我运行这个程序,通过csi,它每秒打印字符串“Ciao”。如果我将字符串“Ciao”更改为其他内容,例如更改为“else”,并保存程序代码文件,那
(define (loop)
(print "Ciao")
(rest 1)
(loop))
(loop)
(假设(rest 1)
具有暂停程序一秒钟的效果)
如果我运行这个程序,通过csi,它每秒打印字符串“Ciao”。如果我将字符串“Ciao”更改为其他内容,例如更改为“else”,并保存程序代码文件,那么csi将继续解释旧程序代码,因此我将继续看到字符串“Ciao”。在本例中,我希望在保存修改后的代码时,字符串“Ciao”替换为“else”,csi通过查看修改后的文件而不是旧文件来继续其解释工作。
因此,我获得一些“Ciao”作为输出,后跟一些“else”:当我在源代码中将“Ciao”替换为“else”时,“else”开始出现。一般来说,答案是“不要”。您应该使用REPL的方法是,根据它评估零碎的更改,然后评估一两个函数,以确保一切按预期进行。这种方法的一部分是对程序进行结构化,以便可以轻松地对其进行分段测试,这意味着不会自动启动任何无限循环。在您询问的特定情况下,您可以改为写信
(define (do-stuff)
(print "Ciao"))
(define (main-loop)
(do-stuff)
(rest 1)
(main-loop))
(define (start) (main-loop))
现在,您可以逐步开发do stuff
,定期向您的解释器评估新版本,并调用它们以确保它们正常工作,然后在确信它正在做正确的事情后,最终调用start
您可能会从被问及有关CommonLisp的问题中获得里程数
另一方面,如果您使用的是Common Lisp和SLIME,您现在可以或多或少地执行您的建议:
(defun do-stuff ()
(format t "Ciao~%"))
(defun main-loop ()
(loop (progn (do-stuff)
(sleep 1))))
(main-loop)
启动后,将开始在SLIME REPL中的单独行上打印Ciao
。如果您将操作更改为
(defun do-stuff ()
(format t "else~%"))
然后用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中完成同样的事情,但我有理由相信这是可能的
尽管如此,您有时希望运行一个程序,其中的一部分是无限循环。一个真实的例子是在测试某种TCP服务器时。如果您处于这种情况,并且您所需的工作流程是
csi my file.scm
csi
csi my file.scm
goto 3
(define (do-stuff)
(print "Ciao"))
(define (main-loop)
(do-stuff)
(rest 1)
(main-loop))
(define (start) (main-loop))
现在,您可以逐步开发do stuff
,定期向您的解释器评估新版本,并调用它们以确保它们正常工作,然后在确信它正在做正确的事情后,最终调用start
您可能会从被问及有关CommonLisp的问题中获得里程数
另一方面,如果您使用的是Common Lisp和SLIME,您现在可以或多或少地执行您的建议:
(defun do-stuff ()
(format t "Ciao~%"))
(defun main-loop ()
(loop (progn (do-stuff)
(sleep 1))))
(main-loop)
启动后,将开始在SLIME REPL中的单独行上打印Ciao
。如果您将操作更改为
(defun do-stuff ()
(format t "else~%"))
然后用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中完成同样的事情,但我有理由相信这是可能的
尽管如此,您有时希望运行一个程序,其中的一部分是无限循环。一个真实的例子是在测试某种TCP服务器时。如果您处于这种情况,并且您所需的工作流程是
csi my file.scm
csi
csi my file.scm
goto 3
基本上,您只需要自动化步骤4到6,您需要一个外部工具来为您完成这项工作。看看or(后者没有现成的方案支持,但添加起来也不太困难)。让正在运行的程序检查其源代码是否有更改的常见方法,但您似乎有足够的Ferature可供选择:
(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))))))
现在你所要做的就是使用watchreload
而不是load
,如果文件已被修改,它将每10秒检查并重新加载一次。
如果在文件无效时保存,它将停止工作,直到您调用watch reload再次对其执行代码>操作
这可能是因为chicken程序员可能有更好的解决方案。让正在运行的程序检查其源代码是否有更改的常见方法,但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))))))
现在你所要做的就是使用watchreload
而不是load
,如果文件已被修改,它将每10秒检查并重新加载一次。
如果在文件无效时保存,它将停止工作,直到您调用watch reload再次对其执行代码>操作
可能是那只鸡