以可读形式打印Lisp函数

9

我正在尝试学习Lisp,并通过书籍《Practical Common Lisp》(网址:http://www.gigamonkeys.com/book/)进行学习。

是否有一种命令可以以可读的方式打印先前在REPL中定义的函数? 我已经尝试过:

(print #'function-name)

但是这样会导致输出被包含在#<>中,无法读回(如果*print-readably*设置为T,那么只会得到一个错误)。使用princprin1代替print也会得到相同的结果。
我有点惊讶,这并不容易找到。 Lisp 中的一些文章鼓励在 REPL 上进行实验,但如果您不能在输入函数后保存它们,那么您就不得不在输入之前将它们写入单独的文件中,这在某种程度上削弱了其优点。
4个回答

14

函数对象无法被读回。

1) 您可以使用DRIBBLE函数,使REPL输入保存到文件中。

2) 从编辑器评估到REPL是常见的。您不需要在REPL中键入,您可以键入编辑器文本缓冲区并从那里将表达式发送到REPL。

3) Common Lisp具有FUNCTION-LAMBDA-EXPRESSION,在某些情况下可以恢复源代码(或Lisp系统记录的源代码):

CL-USER 200 > (defun foo (a) (+ a b))
FOO

CL-USER 201 > (function-lambda-expression #'foo)
(LAMBDA (A) (DECLARE (SYSTEM::SOURCE-LEVEL #<EQ Hash Table{0} 41C00751D3>))
  (DECLARE (LAMBDA-NAME FOO))
  (+ A B))
NIL
FOO

3
好的解释!但是请注意,function-lambda-expression 需要一个函数,而不是一个符号。因此,如果可用,(function-lambda-expression #'foo) 保证可以给出 foo 的 lambda 表达式。对于某些实现来说,使用符号调用 function-lambda-expression 可能没有问题,但对于其他一些实现可能不起作用。例如,在 CMUCL 和 SBCL 中,它确实需要一个函数。 - Frank Zalkow

3
简而言之,没有。但是,相反的操作很容易——你可以很容易地将它们写入文件并使用emacs和slime发送到repl。
默认情况下,C-x e在repl中立即评估光标前的表单。
这为您提供了最佳的两种世界:文件的一致性和repl的交互性。
祝你的lisp之旅好运!

1
谢谢,我还没有下载Slime,但我会看一下的。 - OpenSauce
1
绝对需要这样做,与仅使用repl相比,它的工作效率提高了100倍。 - tobyodavies

1

我建议你使用Emacs。加载漂亮的打印功能。该包是(quote pp)。只需输入pretty printer,就能找到它。Slime也可以对函数进行漂亮的打印(如果我记得正确),但是用Emacs的包比较好。

(require 'pp)

我写了一个格式语句,用于打印匿名(或命名)函数,但代码在另一台机器上。如果你有兴趣,请告诉我,我会尝试找到它。

[...]

是的,您可以在以后的时间找到并打印在REPL中键入的函数,只需检查函数名称的命名空间。将名称空间视为哈希表。如果函数已被内部化,则应显示在命名空间中。我认为有一种方法可以说,映射哈希命名空间...

一些Lisp实现需要您设置一个变量来保留函数代码附加到函数符号; 这就像C中的调试符号。它占用空间,但使用自动生成的函数进行调试很麻烦,其中还要添加一些宏1扩展...

尝试使用命令,,...我想不起来了。已经过了一段时间。通常最大的问题是修复未命名的函数(lambda表达式)。一些实现还实现了“匿名命名函数”或类似功能。

<是否有一种命令可以以后可以读取的方式打印先前在REPL中定义的函数?

真是个好问题。是的,您可以。它可能只是write-fasl-stream或更复杂一些。


0

函数被编译,它们的源代码永远不会被存储。我建议使用Emacs + Slime,这样你可以轻松浏览你的历史记录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接