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.
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
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.
Related
I'm on ubuntu 19.
Using emacs, slime and sbcl to practice some lisp.
Currently I have one buffer in slime mode in one window and the slime-description in the other window.
When I want to execute a line, I write it on the buffer and press C-c C-p.
But when I try to do the same for the line
(defvar *name* (read))
to set the the name var with the user input, nothing is happening.
Why ?
Also I would like to execute the whole script and not one line at a time, how do I do that ?
'Nothing is happening' because read is waiting for you to type something at the REPL. If you look at the REPL you will be confused because the form you are evaluating is not displayed, so all you see is ... nothing, but you need to type something at it. Further, it's not clear from your description what buffers you have displayed, but I suspect the REPL is not one of them, which is going to make things even worse.
I don't know how other people use SLIME, but what I do is to have at least the REPL (the thing you get after typing M-x-slime in one window, and a file I am working on in another. You can then interact with the REPL just by typing at it, and send code to the running lisp from the file with C-M-x or any of the other commands (in particular things like C-c C-k which compiles & loads the file.
However you almost never want a file you are compiling or loading to include anything which causes read to be called at compilation or load time: the results are going to be mysterious to put it mildly: the system will just stop with no prompt waiting for you to type something. It makes much more sense to do that in the REPL:
CL-USER> (defvar *name* (read))
(here is the data I am typing in)
*NAME*
Indeed, even when you go to some lengths to make calls to read non-mysterious in files being loaded, you have to go to yet further lengths to make them safe. Consider this file, toxin.lisp:
(defvar *my-thing*
(progn
(format *query-io* "~&thing? ")
(finish-output *query-io*)
(read *query-io*)))
Now:
$ lisp
[...]
(load "toxin" :verbose t)
;Loading #P"toxin"...
thing? #.(quit)
Of course there are much worse things I could have said than that to the Lisp.
I have the following code in a buffer (file ~/firsts.lsp):
(defun firsts (l)
(cond
((null l) ())
(T (cons (car (car l)) (firsts (cdr l))))))
(firsts '((A B) (C D) (E F)))
I would like to "run" this script and see the following output (or a reasonable variant thereof):
(A C E)
My buffer shows this mode:
(Lisp [COMMON-LISP-USER cmucl] adoc)
In trying to run it, I tried C-c C-k, which created a buffer slime-compilation that showed the file was "compiled" without errors, but I do not see a way to get the compiled code to execute or run the entire script through the interpreter.
Slime is installed and running (it's what coordinates the compilation). I know that I can run the forms through the repl, in a form by form manner, but I would like to run the entire script interactively.
Software Environment:
Mac OS X 10.12.3
GNU Emacs 25.1.1
Slime ChangeLog dates 2016-04-19
CMU Common Lisp 21b (21B Unicode) but same result with SBCL 1.3.14
One can imagine various ways how a Lisp source editor and a Listener (a read-eval-print-loop) work together. While SLIME is generally quite good, some of the interaction is slightly clumsy.
In this case there I use three ways to evaluate a buffer with SLIME/Emacs:
select the region, then evaluate the region using SLIME
SLIME eval buffer
save buffer, load buffer or compile-and-load buffer using SLIME
Note that if you evaluate things, results are printed in the mini buffer.
You also want to actually print something, so that you can see what happens.
Compiling things before loading/executing can help find errors. I use that often.
The actual list of key-commands for a buffer is seen on control-h m.
Side notes about interaction when evaluating a buffer
Another interaction style would be to feed each expression to a listener/repl buffer, have the results print there, until an error happens or there are no more expressions. But I don't think SLIME supports that in a direct way.
The LispWorks IDE lets you evaluate a buffer and the output (incl. the evaluation results) is displayed in a corresponding output pane.
The Clozure CL IDE lets you evaluate a buffer and the expressions are evaluated in the top most listener. Printed is the output and the last result.
I'm starting to play with CLisp, and therefore Emacs too, including the "SLIME" plugin (or whatever it's called. How is it called?)
So I've been playing with the REPL for quite some time now, and defined a lot of functions in there with (defun).
Unfortunately, none of these functions have been written in a text file, and I don't fancy retyping all that. Is there a way I could dump or otherwise save the work that has been done in the REPL to a file? (bonus points if the file is Lisp source code :) )
SLIME is an elisp program for interacting with Lisp.
There's no simple option to recover functions you've typed only into the repl into a file. function-lambda-expression can sometimes return code, but it often does not.
If the repl is still in a buffer, you could copy the whole thing into a file and then use string or regexp replacement to isolate the function definitions.
It's not too hard to avoid this problem in the future.
Most people work by writing definitions into a file, and then using a key combination to send them to Lisp, bypassing the REPL. I use the C-c C-c combination when the cursor is on a function to compile and load the expression. C-x C-e also works. Then I switch the the REPL to actually use the function.
See also the function DRIBBLE, which makes sure a log is written.
foo:~$ clisp
...
[1]> (dribble "foo.text")
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"foo.text">
[2]> (+ 3 4)
7
[3]> (defun bar (baz) (* baz baz))
BAR
[4]> (bar 10)
100
[5]> (quit)
Bye.
Let's look at the file:
foo:~$ more foo.text
;; Dribble of #<IO TERMINAL-STREAM> started on 2015-05-08 21:38:48.
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"foo.text">
[2]> (+ 3 4)
7
[3]> (defun bar (baz) (* baz baz))
BAR
[4]> (bar 10)
100
[5]> (quit)
Bye.
The last paragraph in Xach's answer is what it is all about.
When programming in Lisp, typing function definitions directly into the REPL is the wrong way to do it. The right way is to set up your text editor (emacs) so that with certain keystrokes, the expression at the cursor (the entire function definition) is sent to the REPL. Then to invoke a function, you switch to the REPL. This is what SLIME is for.
Strictly speaking, the text in your emacs buffer doesn't have to be written to a disk file, in which case it will be gone after you close the editor. But normally you save it to a file.
You can search through your REPL history for the function definitions. If you have the beginning of an expression already typed in, then SLIME will only cycle through previous entries that begin with the same thing:
CL-USER> (defun
Press M-P from there, and you'll cycle through all the defuns you've typed in.
So I just got Land of Lisp and started to do the first program.
I have a couple questions.
Is there a way to just write some code and run it through a compiler, or interpreter, and not use the REPL thing? I don't like it much. I can't seem to go back if I messed up. It just kinda says "Ha you screwed up, retype that whole function."
I would also like to know what the point of REPL is.
Non-REPL work flow
Edit your file
Compile the file using compile-file; fix errors and warnings; repeat.
Load the file using load; evaluate the form you want; repeat
Example
$ cat > f.lisp <<EOF
(defun f (x) (if (zerop x) 1 (* (f (1- x)) x)))
EOF
$ clisp -q -norc -c f.lisp
;; Compiling file /home/sds/f.lisp ...
;; Wrote file /home/sds/f.fas
0 errors, 0 warnings
$ clisp -q -norc -i f.fas -x '(f 10)'
;; Loading file f.fas ...
;; Loaded file f.fas
3628800
$
The Right Way
Use an IDE, e.g., Emacs with SLIME.
This way, you edit the code in an editor which supports auto-indent and shows you help for each standard symbol.
You compile and test the functions as soon as you write them, giving you a very short development cycle. Under the hood this is accomplished by the IDE interacting with the REPL (this answers your last question).
What is REPL?
Read-Eval-Print loop is a faster, more versatile version of the Edit-Compile-Run loop.
Instead of operating in terms of whole programs (which can be slow to compile and whose execution can be tedious to navigate to the specific location being tested), you operate in terms of a specific function you work on.
E.g., in gdb, you can execute a function with print my_func(123), but if you change my_func, you have to recompile the file and relink the whole executable, and then reload it into gdb, and then restart the process.
With Lisp-style REPL, all you need to do is re-eval the (defun my-func ...) and you can do (my-func 123) at the prompt.
there.
I'm new to eshell,and now i come to a problem that how can i script it.
i've tried
(rm ~/somefile)
and it worked.so is every command like this?how should i write conditional code and loop?and what should i customize to make the system execute my script using eshell other than others ,like bash,by default?
i'm not very good at english,and i hope you can understand what i mean.i'll also appreciate any correction to my english expression?
You can call any elisp command/function/operator from eshell; I suppose that means you can script it using elisp (See GNU Emacs Lisp Reference manual). Example:
Welcome to the Emacs shell
~ $ (defun foo (n) (if (= 0 (mod n 2)) "Even." "Odd!"))
foo
~ $ foo 2
Even.
~ $ foo 3
Odd!
~ $