[cells-devel] Use of :initform c? and c-in
Peter Denno
peter.denno at nist.gov
Sun Oct 2 19:00:45 UTC 2005
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)...
>
> >See: http://common-lisp.net/project/cells-gtk/faq.html
>
> " 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.
--
- Best regards,
Peter
More information about the cells-devel
mailing list