From: Bruno H. <br...@cl...> - 2005-01-25 11:07:20
|
Hi Sam, Just proofreading the modifications of the last weeks. The access to copier, boa constructor and predicate names is well done. Thanks also for introducing the symbolic constants for *defstruct-description-...-location*. I should have done this earlier. Still I will make one change: instead of overloading the accessors class-direct-slots, class-instance-size, I will separate these into different functions structure-direct-slots, structure-instance-size, structure-kconstructors, structure-copier etc. The reason is 1. that the MOP API and your new API are neither a subset nor a superset - the MOP covers all kinds of classes but not LIST/VECTOR structures, and the structure API doesn't cover all kinds of metaclasses -, and 2. that the MOP API is based on a class object, whereas the structure API is based on a symbol. Thus the structure API is better viewed as a layer partially on top of the MOP API, in block diagram: +--------------+ | Structure | | API | +--------------+ | | MOP | | | API | | | | | +--------------+-------+ Therefore it seems better to me to keep these APIs separate. 3. The user might be surprised if by calling (clos:class-direct-slots xyz), where xyz does not name a class, he gets a result not related to classes. Bruno |
From: Sam S. <sd...@gn...> - 2005-01-25 15:03:55
|
Hi Bruno, > * Bruno Haible <oe...@py...t> [2005-01-25 12:01:06 +0100]: > > The access to copier, boa constructor and predicate names is well > done. thanks. > Thanks also for introducing the symbolic constants for > *defstruct-description-...-location*. I should have done this earlier. indeed. I actually wondered why you didn't do that right away and searched for some misty* reason :-) > Still I will make one change: instead of overloading the accessors > class-direct-slots, class-instance-size, I will separate these into > different functions structure-direct-slots, structure-instance-size, > structure-kconstructors, structure-copier etc. this violates the general principle "few functions which operate on many types". > The reason is 1. that the MOP API and your new API are neither a > subset nor a superset - the MOP covers all kinds of classes but not > LIST/VECTOR structures, and the structure API doesn't cover all kinds > of metaclasses -, and I see no reason in principle for CLOS classes not to have kconstructors and copiers. > 2. that the MOP API is based on a class object, > whereas the structure API is based on a symbol. that's what generic functions are for. > Thus the structure API is better viewed as a layer partially on top of > the MOP API, in block diagram: > > +--------------+ > | Structure | > | API | > +--------------+ | > | MOP | | > | API | | > | | | > +--------------+-------+ > > Therefore it seems better to me to keep these APIs separate. whatever they have in common should be kept common. you are just forcing your users (CLOCC/PORT/mop.lisp &c) to write (without-package-lock ("CLOS") (defmethod class-direct-slots ((s symbol)) ...)) this is just not nice to your users. > 3. The user might be surprised if by calling > (clos:class-direct-slots xyz), > where xyz does not name a class, he gets a result not related to classes. if xyz names a struct, it cannot name a class anyway, so the choice here is between an error and a useful behavior. I would always take some useful behavior over an error. with my approach: to get the behavior you want, the user can write (or (find-class 'xyz) (clos:class-direct-slots xyz)) with your approach: to get the behavior I want, the user has to write a much more complicated (and less portable!) kludge above. [*] german and english "mist"s are both appropriate here :-) -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.honestreporting.com> A year spent in artificial intelligence is enough to make one believe in God. |
From: Bruno H. <br...@cl...> - 2005-01-25 17:06:39
|
Hi Sam, > the general principle "few functions which operate on many types". This is the good principle if - the various types fit into a common scheme, - the functions have the same kind of input and the same kind of output. In this case, the two types are neither sub- nor supertype, and the inputs are not the same objects (classes in one case, symbols in the other). Also the common portion of the API is just two functions: -direct-slots and -instance-size. The non-overlap is bigger than the overlap in the diagram. > > The reason is 1. that the MOP API and your new API are neither a > > subset nor a superset - the MOP covers all kinds of classes but not > > LIST/VECTOR structures, and the structure API doesn't cover all kinds > > of metaclasses -, and > > I see no reason in principle for CLOS classes not to have kconstructors > and copiers. kconstructors yes. copiers no: the notion of copying an object by copying slots does not work for complex objects; there you need the INITIALIZE-INSTANCE and MAKE-LOAD-FORM generics. > you are just forcing your users (CLOCC/PORT/mop.lisp &c) > to write > > (without-package-lock ("CLOS") > (defmethod class-direct-slots ((s symbol)) > ...)) > > this is just not nice to your users. No I'm not forcing users to do this. The MOP, not clisp, specifies the class-* methods to take a class object, not a symbol. Actually I'd say the programmer who wants to go from a symbol to a direct-slots list directly has not understood what a class is about. The class is the essential entity here. The symbol is just its name. > > 3. The user might be surprised if by calling > > (clos:class-direct-slots xyz), > > where xyz does not name a class, he gets a result not related to classes. > > if xyz names a struct, it cannot name a class anyway, so the choice here > is between an error and a useful behavior. > I would always take some useful behavior over an error. For interactive functions, this may be a good approach. For APIs, it's a sin to add "useful behaviour" to some functions and not to others: For APIs, orthogonality is more important. > with my approach: > to get the behavior you want, > the user can write > (or (find-class 'xyz) > (clos:class-direct-slots xyz)) > > with your approach: > to get the behavior I want, > the user has to write a much more complicated > (and less portable!) > kludge above. No, with my approach there will be two functions: class-direct-slots, taking a class object, and structure-direct-slots, taking a symbol. The user calls either (class-direct-slots (find-class name)) or (structure-direct-slots name) depending on what he wants. Bruno |
From: Sam S. <sd...@gn...> - 2005-01-25 18:05:14
|
> * Bruno Haible <oe...@py...t> [2005-01-25 18:00:35 +0100]: > >> with my approach: >> to get the behavior you want, >> the user can write >> (or (find-class 'xyz) >> (clos:class-direct-slots xyz)) >> >> with your approach: >> to get the behavior I want, >> the user has to write a much more complicated >> (and less portable!) >> kludge above. > > No, with my approach there will be two functions: class-direct-slots, > taking a class object, and structure-direct-slots, taking a symbol. > > The user calls either > (class-direct-slots (find-class name)) > or > (structure-direct-slots name) > > depending on what he wants. what if he does not know whether NAME is implemented with a DEFCLASS or a DEFSTRUCT? you want him to write (let ((c (find-class name))) (if c (class-direct-slots c) (structure-direct-slots name))) or (let ((c (class-of object))) (if (class-p c) (class-direct-slots c) (structure-direct-slots (class-name c)))) yuk. -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.honestreporting.com> Any connection between your reality and mine is purely coincidental. |
From: Bruno H. <br...@cl...> - 2005-01-25 19:30:51
|
Sam wrote: > > The user calls either > > (class-direct-slots (find-class name)) > > or > > (structure-direct-slots name) > > > > depending on what he wants. > > what if he does not know whether NAME is implemented with a DEFCLASS or > a DEFSTRUCT? > you want him to write > > (let ((c (find-class name))) > (if c > (class-direct-slots c) > (structure-direct-slots name))) This is a hypothetical use case. Doesn't occur in practice. (Where would the 'name' come from?) > or > > (let ((c (class-of object))) > (if (class-p c) > (class-direct-slots c) > (structure-direct-slots (class-name c)))) Yes. The second branch can never be taken. For a good reason: There's no way to use the structure-* API when all you have is an object. If an object is given and it might be a list or a vector, you cannot determine which structure it comes from. (Is #(FOO 3 BAR #\X BAZ) a FOO, a BAR, or a BAZ?) Therefore when all you have is an object, you can only rely on the class-* API. In other cases you can only use the structure-* API. But never both. Bruno |
From: Sam S. <sd...@gn...> - 2005-01-25 23:39:58
|
> * Bruno Haible <oe...@py...t> [2005-01-25 20:24:47 +0100]: > >> (let ((c (find-class name))) >> (if c >> (class-direct-slots c) >> (structure-direct-slots name))) > > This is a hypothetical use case. Doesn't occur in practice. (Where > would the 'name' come from?) I save my objects in text files, writing type and slot names and values. Sometimes I use DEFCLASS and sometimes DEFSTRUCT. I don't want to have to regenerate all my data if I decide to convert my structs to classes. >> (let ((c (class-of object))) >> (if (class-p c) >> (class-direct-slots c) >> (structure-direct-slots (class-name c)))) > > Yes. The second branch can never be taken. For a good reason: There's > no way to use the structure-* API when all you have is an object. If > an object is given and it might be a list or a vector, you cannot > determine which structure it comes from. (Is #(FOO 3 BAR #\X BAZ) a > FOO, a BAR, or a BAZ?) Therefore when all you have is an object, you > can only rely on the class-* API. will this work: (defstruct foo a b c) (class-direct-slots (find-class 'foo)) -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.honestreporting.com> Your mouse pad is incompatible with MS Windows - your HD will be reformatted. |
From: Bruno H. <br...@cl...> - 2005-01-28 13:56:51
|
Sam wrote: > >> (let ((c (find-class name))) > >> (if c > >> (class-direct-slots c) > >> (structure-direct-slots name))) > > > > This is a hypothetical use case. Doesn't occur in practice. (Where > > would the 'name' come from?) > > I save my objects in text files, writing type and slot names and values. > Sometimes I use DEFCLASS and sometimes DEFSTRUCT. > I don't want to have to regenerate all my data if I decide to convert my > structs to classes. OK, then you will have to use the (find-class name nil) test. Still, this rare usecase IMO is not worth generating confusion between classes, class names and structure type names. Clarity of concepts is important. > will this work: > (defstruct foo a b c) > (class-direct-slots (find-class 'foo)) Sure. After (defstruct foo a b c) either of these will work: (class-direct-slots (find-class 'foo)) (class-slots (find-class 'foo)) (structure-slots 'foo). Bruno |
From: Sam S. <sd...@gn...> - 2005-01-30 02:02:14
|
full/lisp.exe -B . -M full/lispinit.mem -norc -q -i dirkey/dirkey1 -i bindings/w in32/win32 -i rawsock/sock -i berkeley-db/dbi -i zlib/zlib -i pcre/pcre -i postg resql/postgresql -x (saveinitmem "full/lispinit.mem") ;; Loading file /cygdrive/d/gnu/clisp/current/build-O/dirkey/dirkey1.fas ... ;; Loaded file /cygdrive/d/gnu/clisp/current/build-O/dirkey/dirkey1.fas ;; Loading file /cygdrive/d/gnu/clisp/current/build-O/bindings/win32/win32.fas . .. ;; Loaded file /cygdrive/d/gnu/clisp/current/build-O/bindings/win32/win32.fas ;; Loading file /cygdrive/d/gnu/clisp/current/build-O/rawsock/sock.fas ... ;; Loaded file /cygdrive/d/gnu/clisp/current/build-O/rawsock/sock.fas ;; Loading file /cygdrive/d/gnu/clisp/current/build-O/berkeley-db/dbi.fas ... ;; Loaded file /cygdrive/d/gnu/clisp/current/build-O/berkeley-db/dbi.fas ;; Loading file /cygdrive/d/gnu/clisp/current/build-O/zlib/zlib.fas ... ;; Loaded file /cygdrive/d/gnu/clisp/current/build-O/zlib/zlib.fas ;; Loading file /cygdrive/d/gnu/clisp/current/build-O/pcre/pcre.fas ... ;; Loaded file /cygdrive/d/gnu/clisp/current/build-O/pcre/pcre.fas ;; Loading file /cygdrive/d/gnu/clisp/current/build-O/postgresql/postgresql.fas ... *** - no-applicable-method: When calling #<standard-generic-function CLOS:SLOT-D EFINITION-READERS> with arguments (#<CLOS::STRUCTURE-EFFECTIVE-SLOT-DEFINITION r esult #x102A26A9>), no method is applicable. make: *** [full] Error 1 -- Sam Steingold (http://www.podval.org/~sds) running w2k <http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/> <http://www.mideasttruth.com/> <http://www.honestreporting.com> We are born naked, wet, and hungry. Then things get worse. |