Can I save source files in Clisp?
Asked Answered
B

2

18

I'm a beginner programmer and am going through the book "Land of Lisp".

I have been typing in the examples from the book with the REPL. Is it possible to save my current program as a .lisp file so I can load it and continue working on it later? I know I can just create the .lisp files in a text editor and load them in, but I am enjoying using the REPL in full screen mode to do the examples.

Bogan answered 14/9, 2011 at 23:48 Comment(1)
I wonder if you could pipe a process to clisp as its stdin that would log stdin as it read and just echo it. Then in order to reload it in theory, just have that initial pipe program print out that log before starting to read the real stdin... A bit of a hack, not sure it would work, but in theory...Hapte
O
22

Short answer

No. Once you enter a function into the REPL, the source form is gone and you just have the interpreted or compiled form. You can do some clever things, but I suspect you don't want to deal with them right now.

Long answer

Use Emacs and SLIME

First, I know you are enjoying the REPL, but I would encourage you to look at some of the editors with Lisp support, such as Emacs with SLIME (http://common-lisp.net/project/slime/) that gives you the best of both worlds. You type into the editor, it types into the REPL, and you really don't know the difference from how you are doing things now. Then you can copy and paste the functions you like into a "proper" .lisp file. The other advantage of using Emacs is that it's based on a variant of Lisp called Elisp, so you can program your editor in Lisp. You can pretty print your code, reformat and refactor it into multiple functions, and do all kinds of excellent things.

Enough preaching!

If you still just want to type clisp and play at the REPL, then you still have options.

If you want to log the output of your REPL session, check out DRIBBLE. It will log your session to a file, and you can edit that later to extract what you want.

For example, this is a simple session:

ataylor:~  $ clisp

blah 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.

Viewing the contents of the file is easy, but it can get big quickly.

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.

You could copy (defun add-two (a b) (+ a b)) and paste it into a file for later.

Loading that file (I added it to jerome1.lisp) is very simple.

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

blah 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.

Saving a session

The easiest thing you can do is saving your Lisp session to an image. It will save all of the functions you've created or compiled, along with most state. When you load it at your next session, it will be almost as if you hadn't exited clisp. The way to do this is implementation dependent, and differs between clisp, sbcl, etc. I'll show you what you would do for clisp.

The problem with this is that you can't open a file and edit it, post it on github, or whatever. I'll give a brief example.

ataylor:~  $ clisp

blah 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.

Note that message about where clisp wrote the memory image. You'll give that back to clisp with the -M flag when starting it the next time.

ataylor:~  $ clisp -M lispinit.mem 

blah blah

[1]> (add-two 1 2)
3
Oblong answered 15/9, 2011 at 1:49 Comment(1)
No problem! I like to encourage Lispers wherever I can. :-)Oblong
C
1

I wanted a better answer to this same question for the following reasons:

(1) When learning a language, oftentimes you more want to experiment than to actually write a full application.

(2) When experimenting, it can be really nice to look through your history and see what you entered and what results you got.

(3) I come from the world of bash, where you can literally dump your command history into a text file and call it a "script" (though this is only a tiny fraction of the power you can get with actual bash scripting, it still serves the purpose of after-the-fact-automation, with a little cleanup.)

So, from the world of bash, I just went with the simple route—I automated a cleanup of the stdout dump. If you're using a terminal with scrollback history (anything but a virtual terminal—and if you code lisp in a VT you're just strange) to play with clisp interactively, just copy the entire terminal scrollback history to a file, then run:

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

Magic! You have a working lisp program. (Obviously you should clean it up; the purpose is to have your history, not really to use it as a program. But it will only contain the lisp commands you entered, not the output/result, so it could be used directly as the program file.)

Then you can run clisp -repl myfile.lisp and voila! You're back where you got to in the last session. Of course, to load it interactively, you should take out the final (quit) line. :)

As for that sed command, what it does is look for the clisp prompt [number]>, then print that line (removing the prompt) and then try to balance the parentheses. If it succeeds, it scans for the next prompt; if the parentheses don't balance, it prints lines until they do.

Actually, it can be simplified slightly to:

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

(Note: I don't use emacs; I've been using just clisp called directly at the command line. I don't know if there is a scrollback history within SLIME.

Chekhov answered 15/12, 2015 at 7:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.