eieio.el: shared-initialize: question about intended behavior

Jan Moringen <[email protected]> Sun, 01 Feb 2009 03:10:33 +0100
Newsgroups gmane.emacs.eieio
Message-ID <20165_1233454237_ZZg0m1id4iBh7.00_1233454233.3317.17.camel@localhost.localdomain>
Hi,

I wrote a class, rudel-delete, which behaves as if it had three
slots, :from, :to and :length. The slot :length is virtual in the sense
that it is entirely realized through `slot-missing'. Here is the code:

(defclass rudel-delete (rudel-operation)
  ((from :initarg :from
	 :type    (integer 0)
	 :documentation
	 "Start of the region affected by this operation.")
   (to   :initarg :to
	 :type    (integer 0)
	 :documentation
	 "End of the region affected by this operation."))
  "Delete a region.")

(defmethod slot-missing ((this rudel-delete)
			 slot-name operation &optional new-value)
  "Simulate slot :length"
  (cond
   ;; Slot :length
   ((or (eq slot-name :length)
	(eq slot-name 'length))
    (with-slots (from to) this
      (if (eq operation 'oref)
	  (- to from)
	(setq to (+ from new-value)))))
   ;; Call next method otherwise
   (t (call-next-method)))
  )

The code works for the case where the value of :length is deduced in an
object that has been initialized with :from and :to. However, when
trying to initialize an instance with :from and :length, something goes
wrong. From the resulting stacktrace and state of the half-initialized
object, the problem seems to be that `slot-missing' is called twice. The
first call correctly sets :to to the value deduced from :length
and :from. The second call to `slot-missing' has the slot symbol bound
to nil.

I looked into `initialize-instance' (in eieio.el) and probably
identified the reason for the described behavior:

       (let ((rn (eieio-initarg-to-attribute (object-class-fast obj)
 					    (car slots))))
 	(if (not rn)
-	    (slot-missing obj (car slots) 'oset (car (cdr slots))))
-	(eieio-oset obj rn (car (cdr slots))))
+	    (slot-missing obj (car slots) 'oset (car (cdr slots)))
+	  (eieio-oset obj rn (car (cdr slots)))))

The original `if' expression terminates after the call to `slot-missing'
such that `eieio-oset' is called unconditionally, even when rn is nil.
The above change makes the problem go away and makes the behavior more
logical in my opinion.

However, since I am not completely sure what the intended behavior is, I
would rather ask than breaking the very core of the object system ;)

Kind regards,
Jan Moringen


------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword