Thread: [cedet-eieio] defclass :initform behavior
Brought to you by:
zappo
From: David A. T. <tho...@gm...> - 2012-05-28 00:49:55
|
EIEIO's DEFCLASS doesn't seem to handle :INITFORM in the same manner as does Common Lisp CLOS. There does seem to have been some discussion of this back in 2010 ('Constructor -- lambda expression' (From: Frank <some.frank@gm...> - 2010-05-29 19:44)) on this list but the issue doesn't seem to have been resolved. Common Lisp specifies that the form provided to :INITFORM is evaluated only at the time a new member of the class is generated: CL-USER> (defvar x 0) X CL-USER> (setf x 0) 0 CL-USER> x 0 CL-USER> (defclass xyz () ((name :initarg :name :initform (setf x (1+ x)) :type number))) #<STANDARD-CLASS XYZ> CL-USER> x 0 CL-USER> Contrast this with EIEIO: ELISP> (defvar x 0) x ELISP> (setf x 0) 0 ELISP> x 0 ELISP> (defclass xyz () ((name :initarg :name :initform (setf x (1+ x)) :type number))) xyz ELISP> x 1 In EIEIO, DEFCLASS seems to evaluate the form passed to :INITFORM at time of DEFCLASS invocation. Is this the intended behavior? The EIEIO documents indicate, "The value passed to initform is automatically quoted." Perhaps the documentation should be clarified to be more explicit regarding whether the behavior of EIEIO is intended to diverge from that of CLOS at this point. Best wishes, Alan GNU Emacs 23.4.1 (debian emacs 23.4+1-3) |
From: Eric M. L. <eri...@gm...> - 2012-06-04 00:27:43
|
Hi David, As a general rule, I'd prefer to be more compatible with CLOS than less. As I have never used plain CL, nor CLOS, my interpretation of the online doc from when I implemented was a bit limiting. ;) In the version of EIEIO in the CEDET repository, there is a comment in initialize-instance where the default value could be evaluated. As such, I think the behavior you want (evaluation at instance creation time) is indeed true, and when I use make-instance, x is incremented. In fact, something more wrong is up, since the following also occurs if you continue your ELISP example: ELISP> x 1 ELISP> (oref-default xyz name) 2 ELISP> (oref-default xyz name) 3 ELISP> (oref-default xyz name) 4 ELISP> (oref-default xyz name) 5 That's because oref-default needs to get the value off the class, so it runs it again. In the defclass, it has a snippet that looks like this: (let ((eieio-skip-typecheck t)) ;; All type-checking has been done to our satisfaction ;; before this call. Don't waste our time in this call.. (eieio-set-defaults cache t)) (aset newc class-default-object-cache cache) The cache is a performance tweak so that new classes are just a vector copy instead of running a bunch of initialization code. As such, there is an instance being created, it's just not one you created yourself. Thus, I think the conflict between compatibility and EIEIO is on the matter of this performance tweak, which looks like it would be a challenge to expunge. If someone wanted to give it a try, that would be great! Thanks Eric On 05/27/2012 08:49 PM, David A. Thompson wrote: > EIEIO's DEFCLASS doesn't seem to handle :INITFORM in the same manner > as does Common Lisp CLOS. There does seem to have been some discussion > of this back in 2010 ('Constructor -- lambda expression' (From: Frank > <some.frank@gm...> - 2010-05-29 19:44)) on this list but the issue > doesn't seem to have been resolved. > > Common Lisp specifies that the form provided to :INITFORM is evaluated > only at the time a new member of the class is generated: > > CL-USER> (defvar x 0) > X > CL-USER> (setf x 0) > 0 > CL-USER> x > 0 > CL-USER> (defclass xyz () > ((name > :initarg :name > :initform (setf x (1+ x)) > :type number))) > #<STANDARD-CLASS XYZ> > CL-USER> x > 0 > CL-USER> > > > Contrast this with EIEIO: > > ELISP> (defvar x 0) > x > ELISP> (setf x 0) > 0 > ELISP> x > 0 > ELISP> (defclass xyz () > ((name > :initarg :name > :initform (setf x (1+ x)) > :type number))) > xyz > ELISP> x > 1 > > > In EIEIO, DEFCLASS seems to evaluate the form passed to :INITFORM at > time of DEFCLASS invocation. Is this the intended behavior? > > The EIEIO documents indicate, "The value passed to initform is > automatically quoted." Perhaps the documentation should be clarified > to be more explicit regarding whether the behavior of EIEIO is > intended to diverge from that of CLOS at this point. > > Best wishes, > > Alan > > > GNU Emacs 23.4.1 (debian emacs 23.4+1-3) > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > cedet-eieio mailing list > ced...@li... > https://lists.sourceforge.net/lists/listinfo/cedet-eieio > |
From: David A. T. <tho...@gm...> - 2012-06-09 20:41:45
|
At Sun, 03 Jun 2012 20:27:35 -0400, Eric M. Ludlam wrote: > The cache is a performance tweak so that new classes are just a vector > copy instead of running a bunch of initialization code. As such, there > is an instance being created, it's just not one you created yourself. This is really the issue. If CLOS behavior is to be emulated, DEFCLASS has no business creating an instance -- especially not in a manner which generates side-effects associated with an :INITFORM form. |
From: Eric M. L. <eri...@gm...> - 2012-06-10 15:13:45
|
On 06/09/2012 04:40 PM, David A. Thompson wrote: > At Sun, 03 Jun 2012 20:27:35 -0400, > Eric M. Ludlam wrote: >> The cache is a performance tweak so that new classes are just a vector >> copy instead of running a bunch of initialization code. As such, there >> is an instance being created, it's just not one you created yourself. > > This is really the issue. If CLOS behavior is to be emulated, DEFCLASS > has no business creating an instance -- especially not in a manner > which generates side-effects associated with an :INITFORM form. Indeed. The problem is just that two independent features went in and there was no test for this case so it slipped by. Unfortunately, that means it will be tricky to undo the problem without breaking the performance feature. For example, how do you get the default value of a slot without running the code? You can't pre-calculate the default value, because that too will run the code. When an object is saved, it only saves the slots that have changed. That means save will run the default initform too when it checks. I am not really a CLOS expert to know what it is supposed to do in these cases. Eric |