help-gnu-emacs
[Top][All Lists]
Advanced

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

Re: EIEIO built in methods -- question


From: Pascal J. Bourguignon
Subject: Re: EIEIO built in methods -- question
Date: Sun, 09 Jun 2013 22:47:10 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Eric Abrahamsen <eric@ericabrahamsen.net> writes:

> Specifically: Override the initialization method for a class that
> inherits from eieio-persistent, to make sure that it's impossible to
> create two instances of the class that have the same :file slot. I've
> already realized constructor is the wrong method, so probably
> initialize-instance.

Ok, initialize-instance won't do it, because make-instance doesn't
return the result of initialize-instance, and it doesn't because the
default constructor method doesn't.

In CL, make-instance is a generic function so it would be a simple
matter of overriding make-instance.

In eieio, they've made make-instance a normal function and defered to
the generic function constructor, so indeed I think you will have to
define a method on your class for contructor.

Now, the default method for constructor takes an instance of the class
eieio-default-superclass.

It would be easy if eieio was made correct, but it seems that have some
deficiencies in the meta class domain:


(class-of (make-instance 'c)) --> c                   ; in eieio
(class-of (make-instance 'c)) --> #<standard-class c> ; in CLOS

; in eieio:
(class-of (class-of (make-instance 'c))) 
Lisp error: (wrong-type-argument eieio-object-p c)

; in clos:
(class-of (class-of (make-instance 'c))) 
#<standard-class standard-class>  ; moral equivalent to eieio-default-superclass


and foremost, it lacks EQL specializers!

in CLOS, you could write:

(defmethod constructor ((class (eql (find-class 'persistent-thing))))
   …)


but not so in eieio.  For a start, eieio classes are not instances:

(class-of (find-class 'c))
Lisp error: (wrong-type-argument eieio-object-p [defclass c nil nil [0
value 0] (value) (#2=#:unbound) (nil) [t] (nil) (nil) ((default)) (nil)
(nil) ((:value . value)) nil nil #1=[] nil nil nil nil nil #1# [object c
default-cache-object #2#] (:custom-groups (default))])


And finally, eieio defclass documentation says:

    Options in CLOS not supported in EIEIO:

      :metaclass - Class to use in place of `standard-class'

so we cannot even define persistent-thing as having a different
metaclass onto which we could define a specific constructor method.



This indeed leaves us in a bad situation.

You could either patch eieio, or wrap around it. 
I would advise you the later.  If I started patching eieio, I would
rewrite it entirely to make it a correct CLOS implementation…


So instead of using make-instance to get your persistent-things, use
your own function that will test for singletons:


(defvar *file-things-map* (make-hash-table :test (function equal)))

(defun make-persistent-thing (&rest arguments)
  (let ((file (getf :file slots)))
    (assert file)
    (or (gethash file *file-things-map*)
        (setf (gethash file *file-things-map*) 
              (apply (function make-instance) 'persistent-thing arguments)))))




> Generally: If OO programming in (e)lisp is anything like OO programming
> in other languages, overloading initialization, deletion, and
> representation methods is *not* something to throw up our hands and wail
> about, it's a perfectly normal part of programming. See my specific
> example above.

Obviously, eieio failed to do that on the class level.

(class-of instance) not being objects is a big FAIL.


> Unless I'm wrong about that, I'm offering to add a section to the manual
> detailing the right way to overload the basic methods on
> eieio-default-superclass, as a learning exercise for myself, if someone
> will agree to look at what I write, help me understand the issues
> correctly, and make sure what I write is accurate. That's all.


But let's not critisize eieio authors.  AFAIK, they've just applied
usual Agile directives, implementing an object system only to fulfill a
very definite and limited goal, that of implementing cedet.  Their
product manager never had a budget to schedule a sprint about
implementing CLOS in emacs lisp.  The customer only wanted cedet, not
CLOS (and if he wanted CLOS, he would know where to find it).


Too bad your needs don't match exactly those of cedet.  Time to scratch
your itch yourself ;-)
-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.
You can take the lisper out of the lisp job, but you can't take the lisp out
of the lisper (; -- antifuchs


reply via email to

[Prev in Thread] Current Thread [Next in Thread]