我可以在Lisp中保存源文件吗?

时间:2011-09-14 23:48:34

标签: lisp common-lisp clisp land-of-lisp

我是初学程序员,正在阅读“Lisp之乡”一书。

我一直在用REPL输入书中的例子。是否可以将我当前的程序保存为.lisp文件,以便我可以加载它并在以后继续处理它?我知道我可以在文本编辑器中创建.lisp文件并加载它们,但我很乐意在全屏模式下使用REPL来完成这些示例。

2 个答案:

答案 0 :(得分:20)

简短回答

没有。在REPL中输入函数后,源表单就会消失,您只需要解释或编译的表单。你可以做一些聪明的事情,但我怀疑你现在不想处理它们。

答案很长

使用Emacs和SLIME

首先,我知道您正在享受REPL,但我鼓励您查看一些支持Lisp的编辑器,例如Emacs with SLIME(http://common-lisp.net/project/slime/),它可以为您提供两全其美的优势。你输入编辑器,它键入REPL,你真的不知道你现在做的事情有什么不同。然后,您可以将您喜欢的函数复制并粘贴到“正确的”.lisp文件中。使用Emacs的另一个好处是它基于一个名为Elisp的Lisp变体,因此您可以使用Lisp对编辑器进行编程。您可以打印代码,重新格式化并将其重构为多个函数,并执行各种优秀的操作。

足够的讲道!

如果您仍然只想输入clisp并在REPL中播放,那么您仍然可以选择。

如果要记录REPL会话的输出,请查看DRIBBLE。它会将您的会话记录到一个文件中,稍后您可以对其进行编辑以提取您想要的内容。

例如,这是一个简单的会话:

ataylor:~  $ clisp
blat blah

[1]> (dribble "/Users/ataylor/jerome.lisp")
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"/Users/ataylor/jerome.lisp">
[2]> (defun add-two (a b) (+ a b))
ADD-TWO
[3]> (add-two 1 2)
3
[4]> (dribble)
#<CLOSED OUTPUT BUFFERED FILE-STREAM CHARACTER #P"/Users/ataylor/jerome.lisp">
[5]> 
Bye.

查看文件内容很简单,但速度很快。

ataylor:~  $ cat jerome.lisp 
;; Dribble of #<IO TERMINAL-STREAM> started on 2011-09-14 18:16:57.
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"/Users/ataylor/jerome.lisp">
[2]> (defun add-two (a b) (+ a b))
ADD-TWO
[3]> (add-two 1 2)
3
[4]> (dribble)
;; Dribble of #<IO TERMINAL-STREAM> finished on 2011-09-14 18:17:16.

您可以复制(defun add-two (a b) (+ a b))并将其粘贴到文件中以供日后使用。

加载该文件(我将其添加到jerome1.lisp)非常简单。

ataylor:~  $ cat jerome1.lisp 
(defun add-two (a b) (+ a b))
ataylor:~  $ clisp
blat blah

[1]> (load "/Users/ataylor/jerome1.lisp")
;; Loading file /Users/ataylor/jerome1.lisp ...
;; Loaded file /Users/ataylor/jerome1.lisp
T
[2]> (add-two 1 2)
3
[3]> 
Bye.

保存会话

您可以做的最简单的事情是将Lisp会话保存到图像中。它将保存您创建或编译的所有功能,以及大多数状态。当你在下一个会话中加载它时,它几乎就像你没有退出clisp一样。这样做的方法是依赖于实现,并且在clisp,sbcl等之间有所不同。我将向您展示您将为clisp做些什么。

这个问题是你不能打开文件并编辑它,在github上发布它,或者其他什么。我将举一个简短的例子。

ataylor:~  $ clisp
blat blah

[1]> (defun add-two (a b) (+ a b))
ADD-TWO
[2]> (add-two 1 2)
3
[3]> (EXT:SAVEINITMEM)
;; Wrote the memory image into lispinit.mem (3,422,616 bytes)
Bytes permanently allocated:            171,840
Bytes currently in use:               3,243,400
Bytes available until next GC:          808,130
3243400 ;
808130 ;
171840 ;
1 ;
65640 ;
7834
[4]> 
Bye.

请注意有关clisp写入内存映像的位置的消息。下次启动它时,您将使用-M标志将其返回给clisp。

ataylor:~  $ clisp -M lispinit.mem 
blat blah

[1]> (add-two 1 2)
3

答案 1 :(得分:0)

由于以下原因,我想更好地回答同一个问题:

(1)在学习某种语言时,您通常需要进行实验而不是实际编写完整的应用程序。

(2)在进行实验时,查看历史记录并查看您输入的内容以及获得的结果可能非常好。

(3)我来自bash的世界,您可以将命令历史记录转换为文本文件并将其称为&#34;脚本&#34; (虽然这只是实际bash脚本所能获得的功能的一小部分,但它仍然可以实现事后自动化,并进行一些清理。)

所以,从bash的世界来看,我只是简单的路线 - 我自动清理了stdout转储。如果您正在使用具有回滚历史记录的终端(除了虚拟终端之外的任何东西 - 并且如果您在VT中编写lisp代码并且只是奇怪的话)以交互方式与clisp一起玩,只需复制整个终端将历史记录回滚到文件,然后运行:

sed -n -e 's/^\[[0-9]\+\]> //;tstuff' -e 'b;:stuff' -e 'p;:rep' -e 's/([^()]*)//;trep' -e '/^[^(]*$/{s/.*//;h;d;};h;n;p;x;G;brep' myfile.lisphist > myfile.lisp

魔术!你有一个工作的lisp程序。 (显然你应该清理它;目的是获取你的历史记录,而不是真正将它用作程序。但它只包含你输入的lisp命令,而不是输出/结果,所以它可以可以直接用作程序文件。)

然后你可以运行clisp -repl myfile.lisp瞧!你回到了上次会议的目的地。当然,要以交互方式加载它,您应该取出最后的(quit)行。 :)

对于sed命令,它的作用是查找clisp提示符[number]>,然后打印该行(删除提示符),然后尝试平衡括号。如果成功,则会扫描下一个提示;如果括号不平衡,它会打印直到它们为止。

实际上,它可以略微简化为:

sed -n -e '/^\[[0-9]\+\]> /{s///;p;:rep' -e 's/([^()]*)//;trep' -e '/^[^(]*$/d;h;n;p;x;G;brep' -e '}' myfile.lisphist > myfile.lisp

(注意:我没有使用emacs;我一直在命令行直接使用clisp。我不知道是否有SLIME中的回滚历史记录。