I think I don't have a clear understanding of how slime is running lisp within Emacs.
Say I have a file with the following entries :-
(defpackage "TEST"
(:use "COMMON-LISP"))
(in-package "TEST")
*package*
Now I compile/run these three with either of say
C-c C-c
C-x C-e
and I get the output :-
#<PACKAGE "TEST">
However, if I now switch buffers to the inferior lisp buffer and type
*package*
it gives me the output as
#<PACKAGE "COMMON-LISP-USER">
What gives? Using the slime commands above clearly does something but it doesn't seem to be affecting the main REPL loop for the inferior-lisp.
Global special variables
Since global variables are using dynamic binding, one can rebind them:
CL-USER> *package*
#<The COMMON-LISP-USER package, 117/256 internal, 0/4 external>
CL-USER> (defpackage "TEST"
(:use "COMMON-LISP"))
#<The TEST package, 0/16 internal, 0/16 external>
CL-USER> (let ((*package* (find-package "TEST")))
(intern "FOO"))
So you don't need to set a global variable, you can rebind them.
So something like SLIME can rebind them and execute the code for evaluation inside the rebound variable bindings:
(let ((*package* (find-package "FOO")))
(eval (read-from-string some-string-with-code)))
Thread local global special variables
One can also create threads, such that they have their own 'thread local' global variables:
(sb-thread:make-thread (lambda (*package*)
...)
:arguments (list *package*))
Above thread function will have its own *package* variable binding.
IDE and globals
Usually one would want the IDE to use the globals in the current listener thread (each listener thread should have its own globals).
One also wants that evaluation from an editor Lisp code buffer uses the package from that buffer (typically the package defined on top or the package from the nearest IN-PACKAGE above in the code. The editor might also be able to set the package to use for the current Lisp code buffer.
Then an IDE will use something like above during evaluation: rebinding the *package* variable and/or use multiple threads with their own *package* variable binding in each thread.
IDE and multiple inferior Lisps
Typically there will be only one inferior Lisp, but it might be possible to have multiple listeners into it. Some IDEs might also support more than one inferior Lisp.
The current package in a file (or buffer actually) is determined by the first toplevel in-package form found when searching backwards from the compiled form at compilation time, e. g. when using C-c C-c to compile the toplevel form at point. I hope you can imagine the looming confusion if if were otherwise.
The current package on the REPL is set by using in-package there.
You can conveniently set the current REPL package and current directory to those of the current buffer using C-c C-~.
Related
Is it possible to expand a macro at run time in a compiled lisp executable? I would expect it to be impossible as macro expansion can only happen pre-compilation yet when i call macroexpand in compiled code i get output.
A macro is a function that's normally called automatically during compilation or evaluation, and whose return value is then compiled or evaluated in place of the original expression.
But since it's just a function, there's nothing preventing it from being called explicitly during run time as well, and that's what MACROEXPAND and MACROEXPAND-1 do.
It's roughly equivalent to:
(defun macroexpand-1 (form &optional env)
(if (and (listp form) (car form)) ;; list expression
(let ((macfun (macro-function (car form)))
(if macfun
(funcall macfun form env)
form))
form))
(Note that this definition doesn't handle symbol macros or use *MACROEXPAND-HOOK*, to keep it simple.)
It's possible to use EVAL-WHEN when defining the macro to make the macro definition only available in the compilation environment. If you do that, trying to expand at run time will fail.
In Lisp, the terms "run time" and "compile time" are situations in which a particular piece of code is being processed, not absolutes like in some static languages. If we evaluate (compile nil '(lambda ())), this is the compile function's run-time, but the lambda form's compile time: both times are happening at the same time.
The entire language is available in all situations. When you build a self-contained executable, that image contains not only support for expanding macros, but for compiling code. Your Lisp application can call compile-file to compile Lisp source to object form, and load to load the resulting object code.
The process of removing garbage, and unused functionality from a Lisp application image to make it smaller is called "tree shaking". If you don't want the compiler or macro expander in your application, find out whether/how they can be removed with your implementation's tree shaking support.
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.
64-bit Windows 7
Clozure Common Lisp Version 1.9 WindowsX8632
Emacs 24.3.1
Slime changelog date 2014-06-17
I have an example .lisp file which starts out as follows:
(ql:quickload 'qt)
(in-package "QT")
The rest of the program shows a dialog box.
When I run this from the command line, wx86cl -load helloqt.lisp it seems to work fine.
When I run this from Emacs Slime (C-x C-k) it says there is no package "QT".
However if I first evaluate the first line individually (C-x C-e) then I can compile the whole thing and it works, modulo the normal issues of trying to run a QT thread from within Slime on Windows.
How do I make it so I can compile/run the file from emacs without having to manually evaluate the first line first?
Also, why doesn't (in-package ...) change the current package in the Slime session? I have to change it manually if I want to interact with the package contents.
When you compile the file as a whole, it is first read as a whole. At that time, none of it has yet been evaluated, so the package QT is not defined yet.
You can either use eval-when to evaluate something at an earlier time, or use a system definition facility (ASDF is predominant nowadays) to load your system in the right order.
Eval-when:
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload '#:qt))
(in-package #:qt)
Note that you usually should not muck around in library packages but define your own, fresh package to hold your code:
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload '#:qt))
(defpackage #:qt-example
(:use #:qt))
(in-package #:qt-example)
;; your code here
(In case you are wondering, defpackage, defun, defclass etc. are specially designed macros that expand to a form inside such an eval-when.)
This is sometimes OK for little one-off scripts. For systems of any noteworthy size, especially as soon as they have more than one source file, use ASDF:
;;;; qt-example.asd
(in-package #:cl-user)
(asdf:defsystem #:qt-experiments
:description "Some experiments with QT."
:serial t
:components ((:file "package")
(:file "qt-example"))
:depends-on (#:qt))
;;;; package.lisp
(defpackage #:qt-example
(:use #:qt))
;;;; qt-example.lisp
(in-package #:qt-example)
ASDF comes with most open-source Common Lisp implementations. You might need to set up the ASDF registry. I like to have one or two base directories for all my local projects, so that I can just put the following into ~/.config/common-lisp/source-registry.conf:
(:source-registry
(:tree (:home "devel"))
(:tree (:home "src"))
:inherit-configuration)
Then ASDF finds all systems defined below those directories. In SLIME, you can just use ,load-system or ,open-system from the REPL with the system name to load it, resp. open all files in it, optionally loading it.
When compiling a single toplevel form (using C-c C-c) from a file, SLIME looks backward from there for an in-package form to find out what package it should assume. Conventionally, you should only have a single in-package form per file, at its top.
A commonly useful shortcut is C-c ~ in Lisp source files, which switches the REPL to the directory of the file and the effective package at point.
A little hard to find, but there is slime-repl-set-package:
(defun slime-connected-hook-switch-to-stumpwm-package ()
(slime-repl-set-package "STUMPWM"))
(add-hook #'slime-editing-mode-hook
#'slime-connected-hook-switch-to-stumpwm-package)
I'm using Emacs as my Common Lisp (SBCL, to be exact) editor, with SLIME. I set up Quicklisp as per the instructions here, and checked if it worked outside of SLIME, and everything was fine - I could grab and download code, include it, everything.
Now, I was trying to use the Compile/Load File command in Emacs for a source file with the following at the top:
(ql:quickload "priority-queue")
(defpackage :tournament
(:use :cl :priority-queue))
(in-package :tournament)
Now, once again, not in SLIME, this worked fine. However, in SLIME, I get an error of the following form:
The name "PRIORITY-QUEUE" does not designate any package.
[Condition of type SB-KERNEL:SIMPLE-PACKAGE-ERROR]
Plus a backtrace, of course. Am I missing something in particular? I installed slime using package-install from Emacs, and I have the following code in my .emacs file to set it up:
(setq inferior-lisp-program "/usr/local/bin/sbcl")
(require 'slime)
(slime-setup)
This is happening because of the separate times of compilation and loading.
When compiling, plain function calls (like ql:quickload) are not evaluated. When the compiler tries to process the defpackage form (which is not a plain function call, but a macro that has side-effects at compile-time), the function that loads "priority-queue" has not been called and the package is not available.
You won't see this if you load the file instead of compiling and loading, because load evaluates each form as it loads.
There are a few options available. The simplest is to wrap your call to ql:quickload in eval-when, e.g.
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload "priority-queue"))
I prefer to define a system for my projects, however small, so I would make a tournament.asd file that looks like this:
(asdf:defsystem #:tournament
:depends-on (#:priority-queue)
:serial t
:components ((:file "tournament.lisp")))
I'd put that in ~/quicklisp/local-projects/tournament/ (along with tournament.lisp) and use (ql:quickload "tournament") in the repl to get started and load it.
I use that latter setup so often that I wrote a Lisp program to do it for me called quickproject.
When byte-compiling several eLisp files in a batch the output from the compiler is cluttered with Warning: function `position' from cl package called at runtime warnings. I understand, although don't agree that much with the policy on cl package. But this makes spotting other, more useful warnings more difficult. So, while there's no real way to avoid the warning, is there a way to selectively shut off all warnings of a certain pattern?
EDIT: (attached an example)
create file called doodles.el
(require 'cl)
(eval-when-compile (require 'cl))
(dotimes (i 1)
(position ?\x "x"))
M-x byte-compile-file RET doodles.el
Switch to *Compile-Log* buffer:
doodles.el:1:1:Warning: cl package required at runtime
this is what you get.
You can control byte-compiler warnings with a Local variables block that sets the byte-compile-warnings variable. To turn off the CL-at-runtime warning, place this near the end of your module:
;; Local Variables:
;; byte-compile-warnings: (not cl-functions)
;; End:
The warning function position from cl package called at runtime is not there because of the policy on CL (well, it does have something to do with it, admittedly) but is pointing out an actual real problem: you use position in a file which does not (require 'cl). The file probably does (eval-when-compile (require 'cl)) which means CL is available during compilation (a.g. to expand CL macros), but will not be loaded at run time.
Often this does not result in a bug, because some other file somewhere does (require 'cl) for you, but that's just you being lucky.