我可以在Clisp中保存源文件吗?
我是一名初级程序员,正在阅读《Lisp之地》一书 我一直在用REPL输入书中的示例。是否可以将当前程序保存为.lisp文件,以便我可以加载它并在以后继续使用?我知道我可以在文本编辑器中创建.lisp文件并将其加载,但我很喜欢在全屏模式下使用REPL来完成示例。Short answer 不可以。一旦你在REPL中输入了一个函数,源表单就消失了,你只需要解释或编译表单。你可以做一些聪明的事情,但我怀疑你现在不想处理它们 长话短说 使用Emacs和SLIME 首先,我知道您很喜欢REPL,但我鼓励您查看一些支持Lisp的编辑器,例如使用SLIME()的Emacs,它提供了两个方面的最佳功能。你在编辑器中输入,它在REPL中输入,你真的不知道与你现在做的事情有什么不同。然后,您可以将喜欢的函数复制并粘贴到一个“正确的”.lisp文件中。使用Emacs的另一个优点是,它基于称为Elisp的Lisp变体,因此您可以用Lisp编写编辑器。您可以漂亮地打印代码,重新格式化并将其重构为多个函数,还可以完成各种出色的工作 说教够了! 如果您仍然只想键入clisp并在REPL上播放,那么您仍然有选项 如果您想记录REPL会话的输出,请查看运球。它会将您的会话记录到一个文件中,您可以稍后编辑该文件以提取所需内容 例如,这是一个简单的会话:我可以在Clisp中保存源文件吗?,lisp,common-lisp,clisp,land-of-lisp,Lisp,Common Lisp,Clisp,Land Of Lisp,我是一名初级程序员,正在阅读《Lisp之地》一书 我一直在用REPL输入书中的示例。是否可以将当前程序保存为.lisp文件,以便我可以加载它并在以后继续使用?我知道我可以在文本编辑器中创建.lisp文件并将其加载,但我很喜欢在全屏模式下使用REPL来完成示例。Short answer 不可以。一旦你在REPL中输入了一个函数,源表单就消失了,你只需要解释或编译表单。你可以做一些聪明的事情,但我怀疑你现在不想处理它们 长话短说 使用Emacs和SLIME 首先,我知道您很喜欢REPL,但我鼓励您查
ataylor:~ $ clisp
ataylor:~ $ clisp
废话
[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.
[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.
[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.
[1]> (add-two 1 2)
3
废话
[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.
[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.
[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.
[1]> (add-two 1 2)
3
保存会话
最简单的方法是将Lisp会话保存到图像中。它将保存您创建或编译的所有函数以及大多数状态。当您在下一个会话中加载它时,它几乎就像您没有退出clisp一样。实现这一点的方法取决于实现,并且在clisp、sbcl等之间有所不同。我将向您展示如何处理clisp
这样做的问题是,您无法打开文件并对其进行编辑、将其发布到github或其他任何地方。我将举一个简单的例子
废话
[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.
[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.
[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.
[1]> (add-two 1 2)
3
请注意,关于clisp写入内存映像的位置的消息。下次启动时,您将使用-M
标志将其返回给clisp
ataylor:~ $ clisp -M lispinit.mem
废话
[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.
[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.
[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.
[1]> (add-two 1 2)
3
出于以下原因,我希望对同一问题有一个更好的答案: (1) 在学习一门语言时,通常您更希望进行实验,而不是实际编写完整的应用程序 (2) 在进行实验时,查看您的历史记录并查看您输入的内容和得到的结果是非常好的 (3) 我来自
bash
的世界,在那里你可以将你的命令历史记录转储到一个文本文件中,并称之为“脚本”(虽然这只是你通过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
和瞧!你又回到了上节课的状态。当然,要以交互方式加载它,您应该取出最后一行
对于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中是否有滚动历史。非常感谢您的详细解释!没问题!我喜欢尽可能鼓励Lisper.:-)我想知道您是否可以通过管道将一个进程作为其stdin发送到clisp,该进程将在读取stdin时记录stdin,并只是回显它。然后,为了在理论上重新加载它,只需让初始管道程序在开始读取真正的标准数据之前打印出日志。。。有点像黑客,不确定会不会奏效,但理论上。。。