Hi kenny, et al.,
I was just updating the cells-gtk documentation. I am wondering whether I answered this question about using :initform with c? versus c-in correctly,
Q: What is the difference between using c-in and c? in a slot's :initform ? A: The usual semantics of :initform do not apply when :initform is given a c? rule. Instead of just setting the value at initialization, when c? is used, the value of the slot is checked and updated using the rule throughout program execution.
If you have the time, take a look at the answer to "What is Cells?" too. See: http://common-lisp.net/project/cells-gtk/faq.html
BTW, I will soon be rolling out some new capabilities with cells-gtk, including GtkDrawingArea, and bindings for the GDK primitives for drawing. I hope to have a demo that presents a graph and uses cells to update the edges as the user drags the nodes around.
I also have a cells-gtk "lisp listener" (or, more usefully, some custom command shell) in the works.
Peter Denno wrote:
Hi kenny, et al.,
I was just updating the cells-gtk documentation. I am wondering whether I answered this question about using :initform with c? versus c-in correctly,
Q: What is the difference between using c-in and c? in a slot's :initform ? A: The usual semantics of :initform do not apply when :initform is given a c? rule. Instead of just setting the value at initialization, when c? is used, the value of the slot is checked and updated using the rule throughout program execution.
It is hard addressing this question without having gotten clear first the big picture. Then it is easy. So here is the big picture:
[aside: I see the link to Bill Clemtson's Cells write-up does not get all the way to the write-up. Too bad, that was pretty good.]
As you said here (after the URL)...
" If you are at all familiar with developing moderately complex software that is operated through a GUI, then you have probably learned this: Keeping what is presented through the GUI in-sync with what the user is allowed to do, and in-sync with the computational state of the program is often tedious, complicated work."
Right. Cells solve a general problem of keeping program state (including what is being displayed to the user) self-consistent. How often have we seen a bug where we delete a huge chink of text and the scroll bars do not get updated properly? Then we all know what to do: drag the corner of the window to resize it, and then the scroll bars get updated correctly. What is going on? The bug (not propagating the new amount of text to the scroll bars) is in just one branch of code, where text deletion is done. The branch of code triggered by resizing does not have that bug.
As I said, this problem of keeping program state self-consistent is a general one, but as you said, a complex GUI is a great case of that.
So how do Cells help, or, what do they do? Somewhat abstractly, but most vitally, the paradigm goes from procedural ("gee, they just deleted a bunch of text. now what do I have to do to make other things consistent with that deletion. Hmmm, I have to redraw the screen, rewrap the text, update the scroll bars, flag the file as unsaved, turn on the "Save" menu item,.....") to a declarative paradigm (in which you describe what reality should arise from other realities and an unseen engine magically arranges for all that to happen): a file is changed if the undo history includes a destructive operation; a scroll bar is visible if there is more text than fits in the window; the line-breaks slot is a function of the text and margins, etc. This raises the next question....
Are you kidding? No, Cells is the little system that lets you provide a rule or formula (really, any arbitrary Lisp form) for the slot of an instance. I say instance instead of class because you can provide rules at make-instance time, so two different instances of the same class can and often do have different rules as dictated by application semantics). The rules will normally use other slots of other instances in their code. For example:
:line-breaks (c? (let ((max-chars-on-line (floor (width window)
(char-width (chosen-font window))))) ;; assuming fixed-width for simplicity (calculate line-breaks (text window) (width window) max-chars-on-line)))
What Cells do is guarantee that if you change fonts or resize the window or change the amount of text, the text will get re-wrapped. Now if you have a sense of deja-vu...
That is because you once used a spreadsheet like Lotus 1-2-3. It does the same thing for accountants that Cells do for programmers with a bunch of interdependent data structures that are constantly changing in the face of new program inputs. In the above example, because of the declarative paradigm, the folks handling code to do user font changes do not need to worry at all about line breaks. The person who handles text wrapping has to understand what other slots affect the wrapping, but that is their job! And it is much easier than sitting there after a font change trying to guess at everything that might need updating. This is the same as programming a spreadsheet: the only person who has to worry about a spreadsheet cell for, say, "earned run average" is the one writing the formula for ERA. And even they do not have to worry about the cell for "innings pitched" changing -- the spreadsheet software takes care of change. And if you do not think that is a huge win, you are too young to remember that spreadsheet programs were the first killer apps for microcomputers. Why were they?
Quite simply because folks were doing spreadsheets on paper long before computers came around. Now imagine having a complex financial model on a paper spreadsheet and you want to look at the upshot of a change in the prime rate or tax rates. You must manually change everything that depends on the rate, then everything that depends on those. And you have to do it in the right order, so that for each cell being recalculated you are sure you have recalculated any used cell (if it too is affected directly or indirectly by the rate). If that sounds crazy...
Yeah, it is, it sucks, and that is why GUI programming is so hard, because that is exactly what a programmer is doing while writing procedural code to keep GUI state self-consistent. And that is why the lamest user knows to close and reopen a window if it goes haywire, because windows so frequently do (go haywire). Programmers writing code to handle some user input (such as hitting the delete key to erase a huge chunk of text) sit there trying to think up all the code they need to write to get all other related program state updated as well. And they have to handle depth: A depends on B, B depends on C, C depends on D, D changes, now get /everything/ consistent with that. Yummy.
At this point, I wager the main problem is simply the extent of the paradigm shift: this is so different from normal programming that your brain has decided to shut down. It is too simple: slots of an instance somehow being maintained by Lotus 1-2-3 (Cells, in fact). Brains do not like to be messed with like that. You know how to program, and this is not it! You have my sympathy, and I confess that even after re-inventing Cells (the prior art is vast) I found myself falling back into a procedural paradigm on new code for at least a year. But Cells are as great for programming (not just GUIs) as spreadsheets are for accountants, and as much fun, so do not get discouraged. Take the pill: Cells is Lotus 1-2-3 for slots of CLOS instances. Plus a little twist:
When a slot changes, Cells will call a generic function specializable on the name of the slot and the types of the instance, new value, and old value. Very handy, and I heard from a friend that Microsoft Excel will call a VBA function or something when a spreadsheet cell changes. Same idea: it is great to have a model working by itself, but how do we get anything useful out of all those values changing automatically? What if the "buy" flag on a stock goes to "on"? How do we arrange for the damn stock actually to be bought? We need the option of a callback where we can initiate an actual trade electronically.
So. What is the difference between c-in (aka c-input) and c? (aka c-formula)? Simple. You have this big financial spreadsheet you use for "what if?" analysis. How do you play? You have one or more cells where you experiment with different possibilities. You just type in different prime rates or exchange rates or corporate tax rates. A thousand other cells have formulas leading back directly or indirectly to the rate, but a few cells do not have formulas, you just type in "42".
Same with CLOS and Cells: some slots just get set by procedural code, and some slots get calculated directly or indirectly off the first slots. So, having sung the praises of formulas and declarative programming, where would we want to use the evil procedural paradigm and SETF some slot? Actually, astute readers might be asking the opposite question: is it turtles all the way down? If every Cell is calculated, what is the bottom Cell standing on? Just as a spreadsheet must have some cells into which we type data, the Cells-based CLOS model must have some slots into which the application deposits program inputs, and these are for a GUI application simply the OS events. Every event handler (or /the/ event handler depending on the OS) does nothing but setf the received values into slots such as mouse-positon or mouse-state or key-code, inter alia.
So those slots are initialized as (c-input nil), and other slots get (c-formula <lisp forms>). End of story, except...
...certain complexities related to efficiency have been ducked. c-input is needed (and should only be used) where the application developer knows for sure they will have to setf that slot at some point. Big efficiencies result where one can safely code ":some-slot 42".
BTW, I will soon be rolling out some new capabilities with cells-gtk, including GtkDrawingArea, and bindings for the GDK primitives for drawing. I hope to have a demo that presents a graph and uses cells to update the edges as the user drags the nodes around.
I also have a cells-gtk "lisp listener" (or, more usefully, some custom command shell) in the works.
Glad to hear it. Lisp is continuing to catch on, and a universal GUI is needed. I think Cells-Gtk will be it.
Addendum.....
Take the pill: Cells is Lotus 1-2-3 for slots of CLOS instances. Plus a little twist:
When a slot changes, Cells will call a generic function specializable on the name of the slot and the types of the instance, new value, and old value. Very handy, and I heard from a friend that Microsoft Excel will call a VBA function or something when a spreadsheet cell changes. Same idea: it is great to have a model working by itself, but how do we get anything useful out of all those values changing automatically? What if the "buy" flag on a stock goes to "on"? How do we arrange for the damn stock actually to be bought? We need the option of a callback where we can initiate an actual trade electronically.
Last I looked, Cells-Gtk did not work much like a spreadsheet. Most slots (or more than I am used to) were c-input. Things still worked automatically, because Cells allows a change callback (defined by def-c-output) to SETF a c-input slot, but I for one try to avoid having things work that way because it loses some of the benefits of Cells. Most of them, actually. We are now back to a situation where the programmer has to figure out what things to SETF in a change callback. And we now no longer have a rule to look to for a slot, where we can see in one place the full algorithm for deciding a slot's value.
Anyway, my big long spreadsheet analogy might have folks who have seen only Cells-Gtk wondering what I am going on about, so I thought I should make this addendum. Everything I wrote is valid and it does explain the roles of c-input and c-formula, but Cells-Gtk may not feel very spreadsheet-y.
kt
On Sunday 02 October 2005 01:54, Kenny Tilton wrote:
Peter Denno wrote:
Hi kenny, et al.,
I was just updating the cells-gtk documentation. I am wondering whether I answered this question about using :initform with c? versus c-in correctly,
Q: What is the difference between using c-in and c? in a slot's :initform ? A: The usual semantics of :initform do not apply when :initform is given a c? rule. Instead of just setting the value at initialization, when c? is used, the value of the slot is checked and updated using the rule throughout program execution.
It is hard addressing this question without having gotten clear first the big picture. Then it is easy. So here is the big picture:
[aside: I see the link to Bill Clemtson's Cells write-up does not get all the way to the write-up. Too bad, that was pretty good.]
Fixed. Thanks. And yes, I agree it is a very good description.
... more stuff much further down in this email....
As you said here (after the URL)...
" If you are at all familiar with developing moderately complex software that is operated through a GUI, then you have probably learned this: Keeping what is presented through the GUI in-sync with what the user is allowed to do, and in-sync with the computational state of the program is often tedious, complicated work."
Right. Cells solve a general problem of keeping program state (including what is being displayed to the user) self-consistent. How often have we seen a bug where we delete a huge chink of text and the scroll bars do not get updated properly? Then we all know what to do: drag the corner of the window to resize it, and then the scroll bars get updated correctly. What is going on? The bug (not propagating the new amount of text to the scroll bars) is in just one branch of code, where text deletion is done. The branch of code triggered by resizing does not have that bug.
As I said, this problem of keeping program state self-consistent is a general one, but as you said, a complex GUI is a great case of that.
So how do Cells help, or, what do they do? Somewhat abstractly, but most vitally, the paradigm goes from procedural ("gee, they just deleted a bunch of text. now what do I have to do to make other things consistent with that deletion. Hmmm, I have to redraw the screen, rewrap the text, update the scroll bars, flag the file as unsaved, turn on the "Save" menu item,.....") to a declarative paradigm (in which you describe what reality should arise from other realities and an unseen engine magically arranges for all that to happen): a file is changed if the undo history includes a destructive operation; a scroll bar is visible if there is more text than fits in the window; the line-breaks slot is a function of the text and margins, etc. This raises the next question....
Are you kidding? No, Cells is the little system that lets you provide a rule or formula (really, any arbitrary Lisp form) for the slot of an instance. I say instance instead of class because you can provide rules at make-instance time, so two different instances of the same class can and often do have different rules as dictated by application semantics). The rules will normally use other slots of other instances in their
code. For example: :line-breaks (c? (let ((max-chars-on-line (floor (width
window)
(char-width (chosen-font window))))) ;; assuming
fixed-width for simplicity (calculate line-breaks (text window) (width window) max-chars-on-line)))
What Cells do is guarantee that if you change fonts or resize the window or change the amount of text, the text will get re-wrapped. Now if you have a sense of deja-vu...
That is because you once used a spreadsheet like Lotus 1-2-3. It does the same thing for accountants that Cells do for programmers with a bunch of interdependent data structures that are constantly changing in the face of new program inputs. In the above example, because of the declarative paradigm, the folks handling code to do user font changes do not need to worry at all about line breaks. The person who handles text wrapping has to understand what other slots affect the wrapping, but that is their job! And it is much easier than sitting there after a font change trying to guess at everything that might need updating. This is the same as programming a spreadsheet: the only person who has to worry about a spreadsheet cell for, say, "earned run average" is the one writing the formula for ERA. And even they do not have to worry about the cell for "innings pitched" changing -- the spreadsheet software takes care of change. And if you do not think that is a huge win, you are too young to remember that spreadsheet programs were the first killer apps for microcomputers. Why were they?
Quite simply because folks were doing spreadsheets on paper long before computers came around. Now imagine having a complex financial model on a paper spreadsheet and you want to look at the upshot of a change in the prime rate or tax rates. You must manually change everything that depends on the rate, then everything that depends on those. And you have to do it in the right order, so that for each cell being recalculated you are sure you have recalculated any used cell (if it too is affected directly or indirectly by the rate). If that sounds crazy...
Yeah, it is, it sucks, and that is why GUI programming is so hard, because that is exactly what a programmer is doing while writing procedural code to keep GUI state self-consistent. And that is why the lamest user knows to close and reopen a window if it goes haywire, because windows so frequently do (go haywire). Programmers writing code to handle some user input (such as hitting the delete key to erase a huge chunk of text) sit there trying to think up all the code they need to write to get all other related program state updated as well. And they have to handle depth: A depends on B, B depends on C, C depends on D, D changes, now get /everything/ consistent with that. Yummy.
At this point, I wager the main problem is simply the extent of the paradigm shift: this is so different from normal programming that your brain has decided to shut down. It is too simple: slots of an instance somehow being maintained by Lotus 1-2-3 (Cells, in fact). Brains do not like to be messed with like that. You know how to program, and this is not it! You have my sympathy, and I confess that even after re-inventing Cells (the prior art is vast) I found myself falling back into a procedural paradigm on new code for at least a year. But Cells are as great for programming (not just GUIs) as spreadsheets are for accountants, and as much fun, so do not get discouraged. Take the pill: Cells is Lotus 1-2-3 for slots of CLOS instances. Plus a little twist:
When a slot changes, Cells will call a generic function specializable on the name of the slot and the types of the instance, new value, and old value. Very handy, and I heard from a friend that Microsoft Excel will call a VBA function or something when a spreadsheet cell changes. Same idea: it is great to have a model working by itself, but how do we get anything useful out of all those values changing automatically? What if the "buy" flag on a stock goes to "on"? How do we arrange for the damn stock actually to be bought? We need the option of a callback where we can initiate an actual trade electronically.
So. What is the difference between c-in (aka c-input) and c? (aka c-formula)? Simple. You have this big financial spreadsheet you use for "what if?" analysis. How do you play? You have one or more cells where you experiment with different possibilities. You just type in different prime rates or exchange rates or corporate tax rates. A thousand other cells have formulas leading back directly or indirectly to the rate, but a few cells do not have formulas, you just type in "42".
Same with CLOS and Cells: some slots just get set by procedural code, and some slots get calculated directly or indirectly off the first slots. So, having sung the praises of formulas and declarative programming, where would we want to use the evil procedural paradigm and SETF some slot? Actually, astute readers might be asking the opposite question: is it turtles all the way down? If every Cell is calculated, what is the bottom Cell standing on? Just as a spreadsheet must have some cells into which we type data, the Cells-based CLOS model must have some slots into which the application deposits program inputs, and these are for a GUI application simply the OS events. Every event handler (or /the/ event handler depending on the OS) does nothing but setf the received values into slots such as mouse-positon or mouse-state or key-code, inter alia.
So those slots are initialized as (c-input nil), and other slots get (c-formula <lisp forms>). End of story, except...
...certain complexities related to efficiency have been ducked. c-input is needed (and should only be used) where the application developer knows for sure they will have to setf that slot at some point. Big efficiencies result where one can safely code ":some-slot 42".
Thanks, that was helpful. But I am still looking for a definition that nails the distinction. A definition is a single sentence that distinguishes a concept from other concepts in the domain of discourse. ;^)
How about this:
The two define different kinds of cells:
"A c-input cell is a cell whose value may be set through explicit declarative code, such as by using setf on the slot."
"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.
[It's actually this last part that is worth noting, I think. The semantics of :initform are different. IMO cells would be easier to learn had you not used :initform for the purpose of associating a formula with the slot. -- though :initform and whatever other keyword you might use to specify the c-formula would be mutually exclusive.]
BTW, I will soon be rolling out some new capabilities with cells-gtk, including GtkDrawingArea, and bindings for the GDK primitives for drawing. I hope to have a demo that presents a graph and uses cells to update the edges as the user drags the nodes around.
I also have a cells-gtk "lisp listener" (or, more usefully, some custom command shell) in the works.
Glad to hear it. Lisp is continuing to catch on, and a universal GUI is needed. I think Cells-Gtk will be it.
In the other email you sent you wrote:
k. tilton:
Last I looked, Cells-Gtk did not work much like a spreadsheet. Most slots (or more than I am used to) were c-input. Things still worked automatically, because Cells allows a change callback (defined by def-c-output) to SETF a c-input slot, but I for one try to avoid having things work that way because it loses some of the benefits of Cells. Most of them, actually. We are now back to a situation where the programmer has to figure out what things to SETF in a change callback. And we now no longer have a rule to look to for a slot, where we can see in one place the full algorithm for deciding a slot's value.
Anyway, my big long spreadsheet analogy might have folks who have seen only Cells-Gtk wondering what I am going on about, so I thought I should make this addendum. Everything I wrote is valid and it does explain the roles of c-input and c-formula, but Cells-Gtk may not feel very spreadsheet-y.
p. denno:
If you could find any spot where we might use cells more effectively, I'll try to fix it.
Peter Denno wrote:
On Sunday 02 October 2005 01:54, Kenny Tilton wrote:
Thanks, that was helpful. But I am still looking for a definition that nails the distinction. A definition is a single sentence that distinguishes a concept from other concepts in the domain of discourse. ;^)
How about this:
The two define different kinds of cells:
"A c-input cell is a cell whose value may be set through explicit declarative code, such as by using setf on the slot."
(a) I think you mean procedural, not declarative (b) "such as by using setf" sounds like there is some other way, but setf is the /only/ way. Note that (setf slot-value) is a backdoor operation which bypasses and pretty much breaks the Cells contract with users. So it is not an alternative to setf, and it is a Bad Idea.
"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.
[It's actually this last part that is worth noting, I think. The semantics of :initform are different. IMO cells would be easier to learn had you not used :initform for the purpose of associating a formula with the slot. -- though :initform and whatever other keyword you might use to specify the c-formula would be mutually exclusive.]
I like it. We could have a :formula option on slot definitions and generate a compile-time error if both initform and formula are specified. We then must also offer a :default-formulargs, generating an error if one duplicates a :default-initarg. But then how do we resolve conflicts where one subclass specifies a default-initarg for a slot which has been given a :formula, or vice versa, or a sub--sub-class goes with a :default-formularg and a subclass went with default-initarg?
I think the problem is that :initform is actually Deeply Correct. A form is being supplied for a slot. That form itself screams that it is a formula, so there is no ambiguity. You see confusion becuase the rule does not become the slot value, but (again) the form itself (c?...) or (c-formula...) screams that it is a formula that produces values for the slot. And as you acknowledge, :intiformula would be mutually exclusive with :initform, which suggests that in some very deep sense they are the same thing and should /not/ be specified by different keywords. the mere fact that the code now has to check for both and that we have sunk into a quagmire on how to resolve disputes in the class hierarchy suggests that :initformula would be a big mistake.
i think the problem of the initform not actually becoming the slot value is a problem only for those who have never seen Cells before and have not had the briefest introduction. So I say leave it as it is an explain it. :)
k. tilton:
Last I looked, Cells-Gtk did not work much like a spreadsheet.
p. denno:
If you could find any spot where we might use cells more effectively, I'll try to fix it.
I am a little maxed out now, but:
- to a large degree, there are two things at work in a cells-gtk app. The widgets all work together nicely. Cells helps. Ain't broke, don't fix, because ideally this code becomes stable and does not get in the way of other development. (I /would/ however be concerned if this ouput setf'ing became standard practice in the second thing, application code managing app semantics amongst multiple GYI widgets
- look for output methods setf'ing c-input cells. Decide if the setf'ed slots could be written as rules.
- I myself use setf in output methods only where A depends on B and B depends on A. A scroll bar can control the text, or the text cursor positiion can decide the text. If that circumstance does not hold, look to see if the value can be expressed as a rule.
On Sunday 02 October 2005 22:13, Kenny Tilton wrote:
Peter Denno wrote:
On Sunday 02 October 2005 01:54, Kenny Tilton wrote:
Thanks, that was helpful. But I am still looking for a definition that nails the distinction. A definition is a single sentence that distinguishes a concept from other concepts in the domain of discourse. ;^)
How about this:
The two define different kinds of cells:
"A c-input cell is a cell whose value may be set through explicit declarative code, such as by using setf on the slot."
(a) I think you mean procedural, not declarative
Of course. Thanks.
(b) "such as by using setf" sounds like there is some other way, but setf is the /only/ way. Note that (setf slot-value) is a backdoor operation which bypasses and pretty much breaks the Cells contract with users. So it is not an alternative to setf, and it is a Bad Idea.
"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.
[It's actually this last part that is worth noting, I think. The semantics of :initform are different. IMO cells would be easier to learn had you not used :initform for the purpose of associating a formula with the slot. -- though :initform and whatever other keyword you might use to specify the c-formula would be mutually exclusive.]
I like it. We could have a :formula option on slot definitions and generate a compile-time error if both initform and formula are specified. We then must also offer a :default-formulargs, generating an error if one duplicates a :default-initarg. But then how do we resolve conflicts where one subclass specifies a default-initarg for a slot which has been given a :formula, or vice versa, or a sub--sub-class goes with a :default-formularg and a subclass went with default-initarg?
I think the problem is that :initform is actually Deeply Correct. A form is being supplied for a slot. That form itself screams that it is a formula, so there is no ambiguity. You see confusion becuase the rule does not become the slot value, but (again) the form itself (c?...) or (c-formula...) screams that it is a formula that produces values for the slot. And as you acknowledge, :intiformula would be mutually exclusive with :initform, which suggests that in some very deep sense they are the same thing and should /not/ be specified by different keywords. the mere fact that the code now has to check for both and that we have sunk into a quagmire on how to resolve disputes in the class hierarchy suggests that :initformula would be a big mistake.
OK, but "Deeply Correct" I think not. A function is just another type of value. Its purpose in any given situation is defined by the /role/ it plays in that situation. :initform is a role in the object creation process. We shouldn't confuse the individual with some role played by the individual.
From the hyperspec: "The :initform slot option is used to provide a default initial value form to be used in the initialization of the slot. This form is evaluated every time it is used to initialize the slot." -- see, it says "every time it is used to initialize the slot" not "every time the slot is accessed."
I'd call the role :formula or even better :derived-by, not :initformula, but what's in a name? (provided that name doesn't already associate with a meaning, as does :initform).
i think the problem of the initform not actually becoming the slot value is a problem only for those who have never seen Cells before and have not had the briefest introduction. So I say leave it as it is an explain it. :)
Sure, it can be learned. Like GTK itself, I have just enough knowledge of Cells to be dangerous. My concern is getting cells-gtk users up to speed as quickly as possible. Definitions of the concepts used, and predictable semantics of the language are the what makes our work effective (and why we like lisp -- compare with Perl or Python, where the semantics change often, and are ill-defined).
But of course there are only so many hours in the day, and so much to do. So nothing is ever going to be perfect.
k. tilton:
Last I looked, Cells-Gtk did not work much like a spreadsheet.
p. denno:
If you could find any spot where we might use cells more effectively, I'll try to fix it.
I am a little maxed out now, but:
- to a large degree, there are two things at work in a cells-gtk app. The
widgets all work together nicely. Cells helps. Ain't broke, don't fix, because ideally this code becomes stable and does not get in the way of other development. (I /would/ however be concerned if this ouput setf'ing became standard practice in the second thing, application code managing app semantics amongst multiple GYI widgets
- look for output methods setf'ing c-input cells. Decide if the setf'ed
slots could be written as rules.
- I myself use setf in output methods only where A depends on B and B
depends on A. A scroll bar can control the text, or the text cursor positiion can decide the text. If that circumstance does not hold, look to see if the value can be expressed as a rule.
Thanks. I'll take a look.
Peter Denno writes:
On Sunday 02 October 2005 22:13, Kenny Tilton wrote:
I think the problem is that :initform is actually Deeply Correct. A form is being supplied for a slot. That form itself screams that it is a formula, so there is no ambiguity. You see confusion becuase the rule does not become the slot value, but (again) the form itself (c?...) or (c-formula...) screams that it is a formula that produces values for the slot. And as you acknowledge, :intiformula would be mutually exclusive with :initform, which suggests that in some very deep sense they are the same thing and should /not/ be specified by different keywords. the mere fact that the code now has to check for both and that we have sunk into a quagmire on how to resolve disputes in the class hierarchy suggests that :initformula would be a big mistake.
OK, but "Deeply Correct" I think not. A function is just another type of value. Its purpose in any given situation is defined by the /role/ it plays in that situation. :initform is a role in the object creation process. We shouldn't confuse the individual with some role played by the individual.
From the hyperspec:
"The :initform slot option is used to provide a default initial value form to be used in the initialization of the slot. This form is evaluated every time it is used to initialize the slot." -- see, it says "every time it is used to initialize the slot" not "every time the slot is accessed."
I think what you're missing is that c-formula does not return a function, and c-input does not return its argument. They return cells, that's the main thing.
As a secondary point, MODEL-CLASS is[*] a metaclass, which provides for special semantics for CELL-SLOTs. In general, most slots in MODEL-OBJECTs are CELL-SLOTs, but you can request a STANDARD-SLOT by specifying :CELL NIL. The cell that computes the value for a CELL-SLOT (either an input cell or a cell formula) can be provided by an initform, or by an initarg; or even later, by replacing it after TO-BE-time (but this is not recommended and I don't think covered by the test suite, so it could be broken atm as well). So, STANDARD-SLOTs have values, CELL-SLOTs compute their values.
[*] (Bill Clinton-style, I am in fact footnoting "is".) This is the model, anyhow. If the MOP were portable and portably efficient, it would be the implementation as well. As a "mere" portability and performance hack, this isn't how it's implemented, but it should be how you think about Cells.
I'd call the role :formula or even better :derived-by, not :initformula, but what's in a name? (provided that name doesn't already associate with a meaning, as does :initform).
Maybe it's really that you don't like the decision to make :CELL T the default and thus implicit in using DEFMODEL?
i think the problem of the initform not actually becoming the slot value is a problem only for those who have never seen Cells before and have not had the briefest introduction. So I say leave it as it is an explain it. :)
Sure, it can be learned. Like GTK itself, I have just enough knowledge of Cells to be dangerous. My concern is getting cells-gtk users up to speed as quickly as possible. Definitions of the concepts used, and predictable semantics of the language are the what makes our work effective (and why we like lisp -- compare with Perl or Python, where the semantics change often, and are ill-defined).
I've seen Cells' semantics change over time, but in the direction of more well-defined. They also stand in the long history of simple Knowledge Representation systems in Lisp. Admittedly, that's the family of OO systems that were neglected by the ANSI standard, but if you're familiar with CLOS and any of the other simple Constraints/OO systems in CL's history, the semantics of Cells are pretty obvious -- and actually, *really* erring on the CLOS side of things.
But of course there are only so many hours in the day, and so much to do. So nothing is ever going to be perfect.
You might also want to look at the documentation for Garnet and KR. One of the great things coming out of that research was a fantastic manual and some very readable papers. KR is a prototype-inheritance object system, and used lazy evaluation of rules (as oposed to Cells' being class-inheritance object system defaulting to eager evaluation); however, it provides examples of good style for using one-way constraints (what Kenny more descriptively calls a spreadsheet dataflow), and expecially in a GUI context. At the rate things are going, I won't have an alpha draft of the Cells manual until the end of 2006, and by that time Kenny will have produced some more good use-cases, but no manual -- so if you'd like a users' manual type of thing, I'd recommend crossing the Garnet docs with what you know about CLOS and Cells.
In the meantime, I'm prioritizing Cells-LTk over Cells docs for my little free time, because the main thing is to get a Cells-controlled toolkit that gives me Pin-Striped Aqua :-)
On Monday 03 October 2005 16:23, Thomas F. Burdick wrote:
> >From the hyperspec: > "The :initform slot option is used to provide a default initial value form to > be used in the initialization of the slot. This form is evaluated every time > it is used to initialize the slot." -- see, it says "every time it is used to > initialize the slot" not "every time the slot is accessed."
I think what you're missing is that c-formula does not return a function, and c-input does not return its argument. They return cells, that's the main thing.
As a secondary point, MODEL-CLASS is[*] a metaclass, which provides for special semantics for CELL-SLOTs. In general, most slots in MODEL-OBJECTs are CELL-SLOTs, but you can request a STANDARD-SLOT by specifying :CELL NIL. The cell that computes the value for a CELL-SLOT (either an input cell or a cell formula) can be provided by an initform, or by an initarg; or even later, by replacing it after TO-BE-time (but this is not recommended and I don't think covered by the test suite, so it could be broken atm as well). So, STANDARD-SLOTs have values, CELL-SLOTs compute their values.
[*] (Bill Clinton-style, I am in fact footnoting "is".) This is the model, anyhow. If the MOP were portable and portably efficient, it would be the implementation as well. As a "mere" portability and performance hack, this isn't how it's implemented, but it should be how you think about Cells.
Thanks. You are correct that I was not of that mindset -- thinking of c-formula and c-input as evaluating to cells. I'll still have problems though because (1) as you point out, defmodel creates standard-class, also (2) cell slots are standard-[direct/effective]-slot-definition -- there is no cell-slot from what I can see, (3) I really don't know what a cell is.
I've tried to define a taxonomy of cell in the cells-gtk documentation, but I'm really guessing. If I had that much, I think I could probably fill in some of the holes in the documentation.
Looking at the standard-class instance created by defmodel, I see what looks pretty much like a standard-class with standard slots. But it doesn't act like one. So an introspective program is as likely to be as confused from its viewpoint as I am from mine.
That said, I've written a fair amount of MOP code and wouldn't be critical of anyone taking a different route for reasons of portability.
> I'd call the role :formula or even better :derived-by, not :initformula, but > what's in a name? (provided that name doesn't already associate with a > meaning, as does :initform).
Maybe it's really that you don't like the decision to make :CELL T the default and thus implicit in using DEFMODEL?
> > i think the problem of the initform not actually becoming the slot value > > is a problem only for those who have never seen Cells before and have > > not had the briefest introduction. So I say leave it as it is an explain > > it. :):) > > Sure, it can be learned. Like GTK itself, I have just enough knowledge of > Cells to be dangerous. My concern is getting cells-gtk users up to speed as > quickly as possible. Definitions of the concepts used, and predictable > semantics of the language are the what makes our work effective (and why we > like lisp -- compare with Perl or Python, where the semantics change often, > and are ill-defined).
I've seen Cells' semantics change over time, but in the direction of more well-defined. They also stand in the long history of simple Knowledge Representation systems in Lisp. Admittedly, that's the family of OO systems that were neglected by the ANSI standard, but if you're familiar with CLOS and any of the other simple Constraints/OO systems in CL's history, the semantics of Cells are pretty obvious -- and actually, *really* erring on the CLOS side of things.
Yeah, I've used a few. Screamer, etc... While working for an apparel CAD company I wrote (in lisp) a constraint-based system to design the various sizes of a garment, given a base pattern.
Its not the concept that bothers me. Nor even the execution of it. Its just that every time I come back to my cells code, I've forgotten a few things about how it works, and I don't have enough notes to fall back on. And I suppose potential users of cells-gtk are put-off by the lack of guidance...maybe not ...I do it...who knows.
> But of course there are only so many hours in the day, and so much to do. So > nothing is ever going to be perfect.
You might also want to look at the documentation for Garnet and KR. One of the great things coming out of that research was a fantastic manual and some very readable papers. KR is a prototype-inheritance object system, and used lazy evaluation of rules (as oposed to Cells' being class-inheritance object system defaulting to eager evaluation); however, it provides examples of good style for using one-way constraints (what Kenny more descriptively calls a spreadsheet dataflow), and expecially in a GUI context. At the rate things are going, I won't have an alpha draft of the Cells manual until the end of 2006, and by that time Kenny will have produced some more good use-cases, but no manual -- so if you'd like a users' manual type of thing, I'd recommend crossing the Garnet docs with what you know about CLOS and Cells.
In the meantime, I'm prioritizing Cells-LTk over Cells docs for my little free time, because the main thing is to get a Cells-controlled toolkit that gives me Pin-Striped Aqua :-):-)
We could do pin-striped aqua in Cells-gtk, if it would mean you'd help by using it, debugging it, or write the cells docs :^)
I'd be happy to read a draft of any Cells documentation you write.
OK, but "Deeply Correct" I think not. A function is just another type of value. Its purpose in any given situation is defined by the /role/ it plays in that situation. :initform is a role in the object creation process. We shouldn't confuse the individual with some role played by the individual.
Just to confuse things, at one point Cells actually /did/ occupy the slot. The slot accessor handled the job of extracting a computed value and returned that. This would would also make debugging easier, but would be Deeply Wrong if we used this approach in something like AllegroStore which did Wonderful Things automatically off of slot values.
Also, re tfb's note on model-class effectively being a metaclass, at one point I /did/ use a metaclass to implement Cells and pulled it only because of portability, as you noted.
From the hyperspec: "The :initform slot option is used to provide a default initial value form to be used in the initialization of the slot. This form is evaluated every time it is used to initialize the slot." -- see, it says "every time it is used to initialize the slot" not "every time the slot is accessed."
Ah, but this describes exactly what is going on. You are confusing the stream of values coming from a formula with non-cell values normally used to initialize a slot. The one-time intialization is still present, it is just that the thing being bound to the slot is a formula or c-input (which really does no more than support an optimization).
by the way, you never explained to me how to resolve conflicts in the class precedence list where one class specifies an initform and another specifies an :initcell.
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?
I'd call the role :formula or even better :derived-by, not :initformula, but what's in a name? (provided that name doesn't already associate with a meaning, as does :initform).
i think the problem of the initform not actually becoming the slot value is a problem only for those who have never seen Cells before and have not had the briefest introduction. So I say leave it as it is an explain it. :)
Sure, it can be learned. Like GTK itself, I have just enough knowledge of Cells to be dangerous. My concern is getting cells-gtk users up to speed as quickly as possible. Definitions of the concepts used, and predictable semantics of the language are the what makes our work effective (and why we like lisp -- compare with Perl or Python, where the semantics change often, and are ill-defined).
But of course there are only so many hours in the day, and so much to do. So nothing is ever going to be perfect.
Could someone somewhere explain to me what is so hard to understand about:
(make-instance 'rect :area (c? (* (length self) (width self))))
Seriously. I realize it is astonishing that it works, but what else? Let's add:
(def-c-output area ((self room) new-value old-value) (when (> new-value (area (carpet self))) <trigger electronic ordering of new carpet>)))
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?
I can see questions about obscure syntax or edge cases, but not something basic like the use of :initform to supply the cell that will be mediating a slot.
kenny
On Monday 03 October 2005 22:16, Kenny Tilton wrote:
From the hyperspec:
"The :initform slot option is used to provide a default initial value form to be used in the initialization of the slot. This form is evaluated every time it is used to initialize the slot." -- see, it says "every time it is used to initialize the slot" not "every time the slot is accessed."
Ah, but this describes exactly what is going on. You are confusing the stream of values coming from a formula with non-cell values normally used to initialize a slot. The one-time intialization is still present, it is just that the thing being bound to the slot is a formula or c-input (which really does no more than support an optimization).
by the way, you never explained to me how to resolve conflicts in the class precedence list where one class specifies an initform and another specifies an :initcell.
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, :formula (or any declaration that "this slot is a cell-slot") is about providing reader and writer functions. 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. 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. -- But, hey, if you are going to say "its sooo... easy" 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'd call the role :formula or even better :derived-by, not :initformula, but what's in a name? (provided that name doesn't already associate with a meaning, as does :initform).
i think the problem of the initform not actually becoming the slot value is a problem only for those who have never seen Cells before and have not had the briefest introduction. So I say leave it as it is an explain it. :)
Sure, it can be learned. Like GTK itself, I have just enough knowledge of Cells to be dangerous. My concern is getting cells-gtk users up to speed as quickly as possible. Definitions of the concepts used, and predictable semantics of the language are the what makes our work effective (and why we like lisp -- compare with Perl or Python, where the semantics change often, and are ill-defined).
But of course there are only so many hours in the day, and so much to do. So nothing is ever going to be perfect.
Could someone somewhere explain to me what is so hard to understand about:
(make-instance 'rect :area (c? (* (length self) (width self))))
Looks fine to me.
Seriously. I realize it is astonishing that it works, but what else? Let's add:
(def-c-output area ((self room) new-value old-value) (when (> new-value (area (carpet self))) <trigger electronic ordering of new carpet>)))
Also looks fine.
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. 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.
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" 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.
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)))
So how about
fm-other - fm-other? - fm-traverse - fm-other-v - fm! - fm^ -
I can see questions about obscure syntax or edge cases, but not something basic like the use of :initform to supply the cell that will be mediating a slot.
It's OK with me if this isn't discussed further. Again, I am just trying to get some documentation for cells-gtk.
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@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.