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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With