I'm trying to write a small game in (SBCL) Common Lisp, using Quickload and ASDF to define and manage dependencies. It uses CLOS, so I have a directory in project
called classes
, and in there, a file, locatable.cl
.
The defclass
form for the LOCATABLE class needs a LOCATOR parameter, so I have a line:
:initform (error "Must supply a locator parameter for this class.")
Whenever I try to load this file or quickload
the system, though, I get the error above ("Must supply a locator parameter for this class"). Since I'm trying to define a system and not creating any instances of the class, I don't understand why I'm getting this. If I comment out the error line, everything loads fine, but I was led to believe that the way I have it is a standard way of requiring an :initval
for a slot.
How do you define such a thing so you can load the file/make a system definition without actually signaling the error?
Here's the class -
(defclass locatable ()
((zone
:accessor zone
:initform nil)
(locator
:initarg :locator
:initform (error "Must supply a locator parameter for this class.")
:allocation :class
:accessor locator)))
UPDATE: I entered the form at the REPL and got the same error. For curiosity's sake, I entered it in again twice, first with :initform ""
, then with the error form. It accepted the first form, and didn't complain about the second, so this problem doesn't seem to happen on re-definition.
(defclass locatable ()
((zone
:accessor zone
:initform nil)
(locator
:initarg :locator
:initform (error "Must supply a locator parameter for this class.")
:allocation :class
:accessor locator)))
The slot locator
is shared in the class. It will be allocated somehow in the class object. The DEFCLASS
form creates this class object. Thus the slot locator
usually will be initialized when the class object is created and initialized. Way before the first instance of that class is created.
LispWorks Backtrace
CL-USER 50 : 1 > :b
Call to CLOS::CLASS-REDEFINITION-LOCK-DEBUGGER-WRAPPER
Call to INVOKE-DEBUGGER
Call to ERROR
Call to (METHOD CLOS::COMPUTE-CLASS-SLOT-CONSES (STANDARD-CLASS))
Call to (METHOD SHARED-INITIALIZE :AFTER (STANDARD-CLASS T)) ; <--
Call to CLOS::ENSURE-CLASS-USING-CLASS-INTERNAL
Call to (METHOD CLOS:ENSURE-CLASS-USING-CLASS (CLASS T))
Call to CLOS::ENSURE-CLASS-WITHOUT-LOD
Call to LET
Call to LET
Call to EVAL
Call to CAPI::CAPI-TOP-LEVEL-FUNCTION
Call to CAPI::INTERACTIVE-PANE-TOP-LOOP
Call to MP::PROCESS-SG-FUNCTION
As you see SHARED-INITIALIZE
is called on the class object, which then initializes the shared slots.
I also don't think calling error
like this should be done in user code. You might find a better way to check for missing initargs.