Reputation: 17849
I would like to know, what is the common approach to common-lisp interactive development in emacs (i use sly, but i think the slime instructions should be the same)
say i have this file:
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload :closer-mop))
(in-package :cl-user)
(defpackage :shapes
(:use :closer-common-lisp-user)
(:export #:rectangle))
(in-package :shapes)
(defclass rectangle ()
((height :initform 0.0 :initarg :height)
(width :initform 0.0 :initarg :width)))
which is quite simple. Evaluating it experssion by expression seems to be ok, while loading the whole file (C-c C-l) gives me the following error:
The variable SHAPES:RECTANGLE is unbound.
[Condition of type UNBOUND-VARIABLE]
stripping it down to
(in-package :cl-user)
(defpackage #:shapes
(:use #:cl-user)
(:export #:rectangle))
(in-package #:shapes)
(defclass rectangle ()
((height :initform 0.0 :initarg :height)
(width :initform 0.0 :initarg :width)))
doesn't make any change.
compile-and-load (C-c C-k) doesn't work either, leaving me with:
; in: DEFCLASS RECTANGLE
; (SHAPES::DEFCLASS SHAPES:RECTANGLE NIL
; ((SHAPES::HEIGHT :INITFORM 0.0 :INITARG :HEIGHT)
; (SHAPES::WIDTH :INITFORM 0.0 :INITARG :WIDTH)))
;
; caught COMMON-LISP:STYLE-WARNING:
; undefined function: SHAPES::DEFCLASS
i see that defclass
can't be properly resolved to from cl-user:defclass
, but can't see the way to fix it.
I wonder what am i missing? And what is the common flow for developing interactively in emacs?
Upvotes: 3
Views: 396
Reputation:
The underlying problem here is that you are confusing two ways that packages can be used in CL. A package generally serves one, or both, of two purposes:
There is no formal distinction between these types of packages, but there very often is an informal distinction. Packages which are of the second type above are often called *-USER
with the canonical example being the CL-USER
package. They often (but not always) serve as places for scratch work.
So what you are doing is defining a package whose use list is such a user package. You can see that this is not going to work by simply looking at the external symbols of this package. From your second example:
> (do-external-symbols (s (find-package "CL-USER"))
(print s))
nil
In other words, CL-USER
exports no symbols at all. This means that your SHAPES
package will initially not have access to any symbols at all, and in particular none of the CL symbols will be present.
Well, the language defines a canonical 'type 1' package, which is CL
: the whole purpose of this package is to export the symbols which define the Common Lisp language, and only those symbols. So the definition of the SHAPES
packages in your second example should be
(defpackage #:shapes
(:use #:cl)
(:export #:rectangle))
(Note that SHAPES
is a type 1 package: it is providing some functionality in the form of SHAPES:RECTANGLE
, and presumably is therefore intended to be used by other packages.)
Closer to MOP provides two packages which mirror the standard CL
and CL-USER
packages:
CLOSER-COMMON-LISP
is like CL
except that various symbols are replaced by ones defined by Closer to MOP, and there may be additional MOP symbols;CLOSER-COMMON-LISP-USER
is like CL-USER
: it's a package intended general use, which users CLOSER-COMMON-LISP
but which does not export any symbol at all.Upvotes: 6