[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

common errors

This thread exists in comp.lang.lisp, but I thought you folks might be
interested in the problem and the fix.

   From: hewett@cs.utexas.edu (Micheal S. Hewett)
   Newsgroups: comp.lang.lisp
   Date: 8 May 1994 13:09:58 -0500
   Organization: CS Dept, University of Texas at Austin

   Here are some problems I've seen over the years that keep recurring:

   1) defvar doesn't redefine

        Editing a file to change the value of a DEFVAR'ed variable
        and then reloading the file DOES NOT change the value of
        the variable in memory.  This one causes effects that are
        very puzzling to novice programmers.

Analogous to your defvar is the case of class allocated instance
variables on redefinition of the class which changes the variable

(defclass foo () ((bar :initform 20 :allocation :class)))
(slot-value (make-instance 'foo) 'bar)
(defclass foo () ((bar :initform 10 :allocation :class)))
(slot-value (make-instance 'foo) 'bar)

This is in MCL 2.0.  I'm not sure if the behaviour is correct, but
I patch the environment so that evaluation of such forms *does* make
the change. (by setting the instance variable in the class prototype)


here is the patch:

(In-package :ccl)
; Alan Ruttenberg
; alanr@media.mit.edu
;Evaluation of a single defclass in a fred buffer causes the class variables to 
;be redefined according to the definition. Analogous to the behaviour for defvars
;when the variable *always-eval-user-defvars* is set to t. That variable also
;controls this hack, as does the variable *single-form-dwim*. 
;dwim means "Do What I Mean".

(defvar *single-form-dwim* t)

(defun process-single-selection (form &aux message)
  (when (or *always-eval-user-defvars* *single-form-dwim*)
    (cond ((and (listp form) (eq (car form) 'defvar) (cddr form))
           (setq form `(defparameter ,@(cdr form)))
           (setq message (format nil "Value of defvar ~A being replaced..." 
                                 (second form))))
          ((and (listp form) (eq (car form) 'defclass) *single-form-dwim*
                (find-class (Second form) nil))
           (multiple-value-bind (redef-forms iv-names) 
                                (defclass-classvar-redefinitions form)
             (setq message  
                   (format nil "Class ~A class-allocated: ~A being replaced..."
                           (second form) iv-names))
             (setq form `(prog1 ,form ,@redef-forms))
  (when message (set-mini-buffer (front-window) message))

(defun defclass-classvar-redefinitions (defclass-form)
  (let* ((class (second defclass-form))
         (iv-specs (fourth defclass-form))
         (class-ivs (remove-if-not #'(lambda (spec) 
                                       (and (eq (getf (cdr spec) :allocation) :class)
                                            (member :initform spec)))
     (loop for spec in class-ivs
           with prototype = (class-prototype (find-class class))
           collecting `(setf (slot-value ,prototype ',(car spec)) 
                             ,(getf (cdr spec) :initform)))
     (mapcar 'car class-ivs))))