[cells-gtk-devel] Re: [cells-devel] Use of :initform c? and c-in

Kenny Tilton ktilton at nyc.rr.com
Tue Oct 4 19:42:11 UTC 2005


>I think the whole question is confused by not recognizing that the set of 
>notions (initargs, :default-initargs, :initform) address a different concern 
>than does :formula. Those three are about providing an initial 
>value,...
>

I see "The :initform slot option is used to provide a default initial 
value form to be used in the initialization of the slot 
<cid:part1.03000704.07080902 at nyc.rr.com>."

The slot is indeed being initialized by the inital value produced by a 
c-input or c-formula form.

Note by the way, that I can start off with:

     (make-instance 'box :width (c? (big-long-calculation)))

...and then decide, to hell with it, I can just go with a fixed value. 
then I just edit to produce:

     (make-instance 'box :width 42)

You do not know me, but little things like the fiercer editing required 
to switch initializations under your scheme are how I decide design issues.

> :formula  (or any declaration that "this slot is a cell-slot") is 
>about providing reader and writer functions.
>
I do not understand the above. DEFMODEL still uses :reader, :write, and 
:accessor for that.

> Once you assert that access to 
>the slot's value is provided through a cell's accessor, you have effectively 
>disconnected from the documented meaning of initargs, :default-initargs 
>and :initform.
>
Hunh? Of course a slot's value is provided by its accessors. Do you mean 
that I have broken slot-value? Well, no, slot-value still works, but I 
have made it into a backdoor, so yeah.

> You can, as far as I am concerned, disallow or ignore the use 
>of any of these on a cells slot. Perhaps you would be better off using a 
>cells-specific constructor rather than make-instance, since cells doesn't use 
>the usual semantics of the initargs.
>
That would be a reasonable way to go if confusion reins. Note that this 
is open source, and it seems to me you could roll your own DEFWHATEVER 
that thiny wrapped DEFMODEL and substituted a different syntax to get 
things defined. And you would need a new make-instance and .... hmmm, it 
could get complicated. :)

I should dig up some earlier versions of Cells. Back in the day, Cell 
slots were not even slots. A class had one slot for an assoc of names 
and cells (or literals).

> -- But, hey, if you are going to say 
>"its sooo... easy"
>
What I liked as Cells evolved over time was not so much the ease and 
naturalness (to me, anyway) of the syntax as that the syntax was just 
raw CLOS. Sleight of hand took place behind the scenes, but if you 
understand CLOS, you know the syntax of DEFMODEL (tho we disagree here). 
I know how to subclass and override (and I also get all the power of 
CLOS in doing so).

I think the big mistake of something like CLIM is introducing a new 
DEFTHIS syntax with all new rules to invent and learn.

I do understand your point that confusion arises when familiar syntax is 
used for something unrelated, btw. I just do not see the Cells usage as 
unrelated, and the contortions I anticipate of separating initilaization 
to a Cell from initialization to 42 tell me they are related.

What is unusual is that the initializing value is functional, if you 
will. C++ /I think/ has computed members. There was wholly different 
syntax, but then there was no way to vary the computation at 
instantiation time, nor a way to instantiate with a literal instead. I 
think. Last time I looked I could not even find the computed slot syntax. :)

> sure stick with it. I don't care. I'm trying to help, not 
>trying to be critical.
>
>  
>
>>Also, what do we do about:
>>
>>       (make-instance 'republican :indictments (c-formula ()
>>(years-in-office self)))
>>
>>That would override an initform or :default-initarg. How are cells
>>supplied at make-instance time in your scheme?
>>    
>>
>
>(mk-republican 'indictments (c-formula () (months-in-office self)))
>
>indictments names a slot, it might not be an initarg.
>
I think one of the Great Strengths of Cells is that it is raw CLOS 
(make-instance, initargs, initforms, default-initargs, etc etc). I 
believe you are on the verge of inventing a new object model, but doing 
so is the only thing Garnet fans regret about Garnet.

>>There are a lot of examples in the test suite with some pretty simple
>>relationships. Am I the only one who prefers examples to turgid,
>>abstract documentation trying to sound like a PhD thesis by using big
>>words and never saying what they really mean?
>>    
>>
>
>Well, I hope I am not being turgid or using big words. After seeing a couple 
>of examples, I like definitions.
>
What I find is that good technical writing (well, good writing) is quite 
rare. So unless the doc is merely defining the legal syntax, once the 
writer goes for an abstract definition, only someone who already 
understands the subject can understand the writing.

> So far I have this:
>
>A C-INPUT CELL is a cell whose value may be set through explicit procedural 
>code, using setf on the slot. Setf-ing the cell typically causes the values 
>of other cells to be recomputed. 
>
This is a good example of what I just said. Things are fine in the first 
sentence, where you define c-input according to legal operations on 
them. Well, there is a little confusion because the reader (or one like 
me) starts wondering when one would /not/ be able to SETF a slot. I 
think I always start with ruled Cells and /then/ explain c-inputs as the 
bottom turtles, if you will, in the overall application dataflow model. 
Unfortunately, this also gets us smack into an optimization issue: using 
a raw literal value instead of c-input permits a very nice optimization. 
I always gloss over that with a bit of "don't ask, it's faster". Anyway, 
in the next sentence things get tougher....

You tried for a little precision with "typically causes the values of 
other cells to be recomputed". I know what you are saying and even I 
find that alarming. I do not like the fuzziness of "typically". Right 
away I want to know when and when not. And merely saying "other cells" 
leaves me dumbfounded: Hunh? What other cells?

Hmmm, maybe this is why I do not like reading doc, or why good doc is so 
hard to write. I do not like mysteries in technical material, but that 
is what i usually find. getting back to this sentence, again, this is 
why I try to start with ruled cells. I can say there something along the 
lines "The slot value will be recomputed when and only when some other 
slot (a) mediated itself by a Cell (b) accessed during the prior 
computation (c) changes." Then when I get to c-input I can say: 
"Changing the value (via SETF) causes any ruled Cells dependent on the 
c-input Cell (meaning the c-inpuit was used in the most recent 
computation of the c-ruled) to be recomputed."

Ouch, we are defining Cells by behavior and have not mentioned 
def-c-output. Maybe we go the other way:

Start with "(defclass box () ((width :cell t...)))".

The first thing that supports is (def-c-output width ((self box) new old 
old-valid-p) (format t "~&width ~a" new))

But that only gets called once for (make-instance 'box :width 42) 
because (setf width) is illegal where a cell has bound to it a normal 
lisp object. To use SETF...

   (make-instance 'box :width (c-in 42))

Now you can call (setf width) on this instance. Why is c-in necessary? 
we get a nice optimization by forcing the user to declare when a slot is 
changeable.

And now we can setf a series of values into width and see a series of 
format outputs.

Finally, (make-instance 'box :width (c-in 42) :height (c? (golden-rule 
(width self))))

etc etc from here on. The only thing is that I am resisting the 
temptation to say too much about c-input (that it triggers propagation 
to dependent ruled cells), with the downside that the reader is 
wondering what the hell all the syntax is about until we get to ruled 
cells. But if we keep it short and sweet, they are only in suspense for 
a paragraph or two.

>
>A C-FORMULA CELL is a cell whose value is obtained through evaluation of a 
>formula.
>
>Note that the usual semantics of :initform do not apply when :initform is 
>given by c-formula. Instead of just setting the value at initialization, the 
>c-formula (an arbitrary lisp form) specifies the dynamic relationship between 
>the slot's value and other aspects of the program state. 
>
>I don't have a definition of "cell" ...
>
One thing to be wary of is that I use cells two ways. First, they are 
the structures produced by c-input or c? which mediate a slot. Second, I 
use "cell" as shorthand for a slot. So I might say:

"the parent slot of a Child is not a cell because Childs cannot change 
parents, and Cells are all about change."

That is using Cell as shorthand for "slot managed by Cells internals to 
which a Cell can sensibly be bound". Or I can say:

"I suspect Cells-Gtk could use fewer c-input cells and more c-formula 
cells."

There I am talking about what gets bound to a slot that can sensibly 
have a Cell bound to it.


>but I think it is might be:
>
> "A CELL is a slot in a CLOS object whose value is managed by readers and 
>writers that are part of a cells constraint network."
>

>
>It would be useful to have definition of the 'fm' methods.
>
Utilities useful for dealing with the Family class. Call me old-school, 
but I like prefixing, even where I might have a Family package with an 
FM nickname and use fm:find-one.

>
>As far as I can tell, (fm-find-one top name) just does this:
>
>(depth-first-search top #'(lambda (x) (eql (md-name x) name)) #'kids)))
>
I would like to see depht-first in the documentation, not the name. 
Anyway, why are you guessing at what fm-find-one does? Look at the 
signature:

  (fm-find-one family md-name &key must-find global-search skip-tree)

And I just added a doc string:

  "Search depth-first from starting point family for
a model instance with the given md-name and passing test,
skipping skip-tree and searching up the family tree for global-search.
Error if not found and must-find."

>
>So how about 
>
>fm-other - 
>
See the source:

(defmacro fm-other (md-name &key (starting 'self) skip-tree (test 
'#'true-that))
  `(fm-find-one ,starting ,(if (consp md-name)
                               `(list ',(car md-name) ,(cadr md-name))
                             `',md-name)
                :must-find t
                :skip-tree ,skip-tree
                :global-search t
                :test ,test))

>fm-other? -
>
fm-other, but no error if not found

>fm-traverse - 
>
see the name. :)

>fm-other-v -
>
>fm! -
>fm^ -
>
See the source. I forget. :) They are all pretty rare in my code. fm^ 
starts by searching up from self and excludes self (as the skip-tree). I 
just looked at fm! This insists on finding the other thing in the self 
tree (no global search). The mnemonic is "dammit! I know this exists and 
that it is a descendant of me". None of this wishy-washy "Golly, I know 
it is out there somewhere because someone else has one" of fm-other or 
even worse, the "i wonder if anyone made one of these" of fm-other?

I see fm-other-v is wrong, it should be fm-other?-v. It is an fm-other? 
that evaluates the md-name arg.

> It's OK with me if this isn't discussed further. 

No such luck. <g> You are asking good questions and I even agree to some 
extent with your take on my extending the syntax of :initform and 
:initarg, and I really am impressed by your success so far providing 
documentation for Cells-Gtk, so I am happy to respond.

-- 
Kenny

Why Lisp? http://wiki.alu.org/RtL_Highlight_Film

"I've wrestled with reality for 35 years, Doctor, and I'm happy to state I finally won out over it."
    Elwood P. Dowd, "Harvey", 1950






More information about the cells-gtk-devel mailing list