Thomas F. Burdick wrote:
Kenny Tilton writes:
Turns out I /do/ try to reset an ephemeral initialized to (CV <not nil>), but I only reset the cached value slot of the cell, not the slot-value per se. And the slot-value is the place the accessor looks for a value. The cache is just used for other stuff. Ah, the hazards of redundant representation.
Writing a simple KR<-->CLOS bridge was easy, but not subtly screwing up the duplicated information was kind of a headache, so I can sympathize.
Anyway, I think we are agreeing to let ephemeral + (CV <whatever>) signify that <whatever> is the value to revert to after a later ephemeral datachange for such a slot. Hmmm, let me thnk about this. I actually saw this bug and might have it in a do-list somewhere. I think it came up because I wanted a non-nil initial value for a nil-based ephemeral slot at make-instance-time.
Yep, we're in agreement. This would be very useful for ephemeral slots that take on numeric values, and for interacting well with type declarations. In SBCL, declarations = assertions (CMUCL too, but SBCL takes it more seriously), so you can do something like:
(defclass foo () ((a :accessor foo-a :type fixnum)))
and if you try to set an A slot to something other than a fixnum, you'll get a runtime error.
Good lord. Do they know CL is short for Common Lisp? Tell me they get huge runtime performance benefits from this sacrilege.
Actually, there is a problem here. Currently Cell structures land in the slot during make-instance (when I had a MOP-based implementation I shunted Cells bound for a slot over to the .cells internals slot before they ever got to the slot, by placing an around method on (setf slot-value-using-class)). Possibly I can do the same with an around meth on shared-initialize, but till then SBCL will likely not be happy with a Cell in a slot typed numeric.
Well, we'll put this in the hopper, but I propose we give higher priority to me documenting the system and getting Cello going. And I think I do want to make the resumed base value (what /do/ we call that?) of an ephemeral a distinct attribute, so as not to shadow the semantics of an instance being initialized with an ephemeral slot initialized, say, (CV 2) with baseline value zero.
Plus, you get compile-time warnings if Python's type inference shows that A could be set to a non-fixnum.
One problem with Cell-as-is on SBCL, is that the type checking only happens when you use the accessor function, not SLOT-VALUE. This is probably best considered a bug in SBCL's PCL, but it has the following unfortunate result:
- (defmodel foo () ((x :initform (cv 0) :accessor get-x :type fixnum) (10x :initform (c? (* 10 (get-x self))) :accessor get-10x :type fixnum)))
STYLE-WARNING: redefining SHARED-INITIALIZE :AFTER (FOO T) in DEFMETHOD
Hey, SBCL is creating an after method on shared-initialize?
STYLE-WARNING: redefining GET-X (FOO) in DEFMETHOD STYLE-WARNING: redefining (SETF GET-X) (T FOO) in DEFMETHOD STYLE-WARNING: redefining GET-10X (FOO) in DEFMETHOD STYLE-WARNING: redefining (SETF GET-10X) (T FOO) in DEFMETHOD
<heh-heh> I keep wondering my I do not get "get-10x defined twice in foo.lisp" et al, but I do not.
#<STANDARD-CLASS FOO>
- (setf >>foo (make-instance 'foo))
FOO
- (get-10x >>foo)
0
- (setf (get-x >>foo) most-positive-fixnum)
536870911
- (get-10x >>foo)
5368709110
- (typep * 'fixnum)
NIL
Gee, what /is/ the type?
In reverse order of simplicity, the best way to solve this would be to fix SBCL;
Have you asked the SBCL crowd whether they are set on slot-value being type-ignorant?
the second best way would be to either have Cells use :around methods, instead of redefining the primary methods, then invoke the proper next-method machinery
That scares me.in the abstract, tho I cannot point to any evil consequence, I just think one will arise in due course because it strikes me as a kluge.
-- or, have Cells propagate the type declaration to its new method definitions.
That should be easy, and sounds Deeply Correct. I am already looking at the slot definition name to get reader and writer names, may as well grab the type if any. So what's the syntax for declaring a /return/ type? And the synatx on the setf side as well.
Since we've got eager data propogation, it would be nice to get the type errors with the stack still intact. Obviously, though, this can wait for a bit (although I might make it one of my higher priorities once Cells is in CVS).
I hear a vote for early CVS. :)
Tell you what, I owe common-lisp.net a release, let me just fix the bug so a (cv 2) does get reset as advertised and the doc is accurate, then we can study this. I might want to change the syntax from :cell :ephemeral to ":cell t :ephemeral-resumes <whatever>" where by the new scheme the :cell t is unnecesary since that's the default, but anyway. Then :ephemeral-resumes is a two-fer, it gives you ephemrality as well as specifying the value to resume after a change.
Hmm, :ephemeral-resumes seems like a weird name. Maybe :ephemeral-default ? Actually, I think it would be better to stick with the :cell :ephemeral :initform ( syntax
In RMS (an ISAM) one could specify that spaces or all zeros or whatever were the NULL_VALUE for an alternate key, meaning "if this is my value for this indexed field, just leave me the hell out of that index; i cannot be found that way". This was crucial where an indexed field was populated by only one or two percent weirdo records. Without NULL-VALUE, you get a million records with the same duplicate value, and an insertion could take 30 seconds as RMS read through a vast index tree looking for the place to insert. How is:
:cell :ephemeral :c-null-value 0 :initform (cv 0)
I just feel kinda bad making them type in the initform when at this point DEFMODEL has enough info to auto-supply that (and I do frequently neglect to code in (cv nil) on ephemerals. Should we add that nicety? Do we need a warning if they say :c-null-value and they do not say :ephemeral? The parallel error went unnoticed on an RMS file with consequences you would not believe.
The nice thing about the suggested alternative
:ephemeral-resumes 0 (with :cell t by default,and of course a better name)
is that it eliminates the redundant declaration
kenny