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.