Scheme 在“鸡肉方案”中运行时更改程序代码

Scheme 在“鸡肉方案”中运行时更改程序代码,scheme,interpreter,chicken-scheme,Scheme,Interpreter,Chicken Scheme,在csi(鸡肉方案解释器)解释程序代码时,是否可以更新程序代码?如果是,怎么做 这样我就可以以交互方式更改部分代码,并立即看到更改的效果。 例如,假设我编写了以下程序: (define (loop) (print "Ciao") (rest 1) (loop)) (loop) (假设(rest 1)具有暂停程序一秒钟的效果) 如果我运行这个程序,通过csi,它每秒打印字符串“Ciao”。如果我将字符串“Ciao”更改为其他内容,例如更改为“else”,并保存程序代码文件,那

在csi(鸡肉方案解释器)解释程序代码时,是否可以更新程序代码?如果是,怎么做

这样我就可以以交互方式更改部分代码,并立即看到更改的效果。 例如,假设我编写了以下程序:

(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
  • 基本上,您只需要自动化步骤4到6,您需要一个外部工具来为您完成这项工作。看看or(后者没有现成的方案支持,但添加起来并不太困难)。

    一般来说,答案是“不要”。您应该使用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

  • 基本上,您只需要自动化步骤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操作

    可能是那只鸡