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

"Eric M. Ludlam" <[email protected]> Sun, 1 Feb 2009 08:46:08 -0500
Newsgroups gmane.emacs.eieio
Message-ID <[email protected]>
I agree with your deduction, especially since there is no test in
eieio-tests.el for this particular use of slot-missing.  It would be
great if you could check in this change.  It would be even better if
there were also a couple tests.

Thanks!
Eric

>>> Jan Moringen <[email protected]> seems to think that:
>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