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 <jan.moringen@...> 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
|