Lisp是homoiconic,意思是代码可以被视为数据。哪些实现允许我在运行时这样做?以下是我的意思,在伪代码中的一个例子:
(defun (my-func)
(display "foo ")
(display "bar ")
(display "baz "))
(defun (main-loop)
(my-func)
(swap (first my-func) (second my-func))
(main-loop))
那应该反复输出“foo bar baz bar foo baz”。
答案 0 :(得分:2)
这可能不是最优雅的方法,但是在共同的Lisp中你可以做这样的事情:
> (setq f '(defun foo () (princ "foo ") (princ "bar ") (princ "baz ")))
(DEFUN FOO NIL (PRINC "foo ") (PRINC "bar ") (PRINC "baz "))
> (eval f)
FOO
> (foo)
foo bar baz
NIL
> (defun frot ()
; Call foo (stored in f)
(funcall (eval f))
; Swap the 1st and 2nd statements in foo
(setf tmp (cadddr f))
(setf (cadddr f) (cadr (cdddr f)))
(setf (cadr (cdddr f)) tmp)))
FROT
> (frot)
foo bar baz
(PRINC "foo ")
> (frot)
bar foo baz
(PRINC "bar ")
> (frot)
foo bar baz
(PRINC "foo ")
这会在f
中存储一个Lisp函数,而不是在 in situ 中执行它,但它确实说明了一个事实,即一个Lisp程序本身就是一个Lisp数据结构而不是可以动态操作的执行。
答案 1 :(得分:2)
其他答案很好地涵盖了这个问题。
从实际层面来看,如果您使用Common Lisp和Slime并希望能够从Emacs将代码编译到正在运行的程序中,则需要告知Swank从循环内部进行更新。
将以下内容添加到您的代码中,然后在循环中添加(update-swank)。
(defmacro continuable (&body body)
`(restart-case
(progn ,@body)
(continue () :report "Just Continue")))
(defun update-swank ()
"Called from within the main loop, this keep the lisp repl working"
(continuable
(let ((connection (or swank::*emacs-connection*
(swank::default-connection))))
(when connection
(swank::handle-requests connection t)))))
这是使用您可以使用编辑器as in this video 重新编译的事实的一种方法(抱歉插入我自己的视频)。
另一种方式(再次使用Slime)是告诉它使用不同的线程进行通信。我更喜欢前一种方法,因为当跨线程使用时,opengl非常不稳定。
[更多详情] 上面代码中的可持续宏捕获任何错误,并为您提供忽略它并继续的选项。我发现这真的很有用,而且我经常在repl中犯错,我不想从错误中“中止”,因为这会中止我的主循环。
答案 2 :(得分:1)
如果您正在修改代码,那么您就可以了解代码的结构。由于您知道代码的结构,因此可以参数化该结构
(define (foo-er foo bar baz)
(lambda ()
(display foo)
(display bar)
(display baz)))
然后你可以通过显式传递你的参数来进行交换:
(define (main-loop)
(let looping ((foo "foo ") (bar "bar ") (baz "baz "))
((foo-er foo bar baz))
(looping bar foo baz)))
> (main-loop)
foo bar baz bar foo baz foo bar baz ...
CommonLisp版本类似。
如果你需要保持my-func
:
(define my-func #f)
(define (main-loop)
(let looping ((foo "foo ") (bar "bar ") (baz "baz "))
(set! my-func (foo-er foo bar baz)
(my-func)
(looping bar foo baz)))