Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Cells for CormanLisp

6 views
Skip to first unread message

Kenny Tilton

unread,
Mar 17, 2003, 7:49:21 PM3/17/03
to
OK, CormanLisp 2.01 now has available patches to fix up the defstruct
issues. A little fancy footwork on the Cells side and we have...

Cells for CormanLisp (and ACL, LW, and CLisp):

http://www.tilton-technology.com/cells_top.html

Same link, so reload page if the "new for..." graph does not mention
CormanLisp.

One heads up: the :default-initargs option of defclass is effectively
ignored by my CormanLisp 2.01 patched just with the two files to fix
defstructs, clos.lisp and structures.lisp. I do not know if this is a
problem introduced by the patches or if CormanLisp has always been like
that. I did not hear from anyone on the Corman mailing list re this
astonishing gap/bug, so I presume all CormanLispers are out celebrating
St. Patrick's Day, as I will be shortly.

When I recover, I plan to start a little Cello tutorial project. A port
to CMUCL will be running in parallel, and with luck Cello will cover
win32 and X11 by the time the Cello doc is worth a damn.

--

kenny tilton
clinisys, inc
http://www.tilton-technology.com/
---------------------------------------------------------------
"Cells let us walk, talk, think, make love and realize
the bath water is cold." -- Lorraine Lee Cudmore

reini urban

unread,
Mar 18, 2003, 1:49:39 PM3/18/03
to
Kenny Tilton wrote:
> OK, CormanLisp 2.01 now has available patches to fix up the defstruct
> issues. A little fancy footwork on the Cells side and we have...
>
> Cells for CormanLisp (and ACL, LW, and CLisp):
> http://www.tilton-technology.com/cells_top.html

I still don't get it exactly. So in short:
Is it something like the garnet object-system, only on top of CLOS?

(I think it was called KR)
--
Reini Urban
http://xarch.tu-graz.ac.at/home/rurban/

Thomas F. Burdick

unread,
Mar 18, 2003, 9:23:15 PM3/18/03
to
reini urban <rur...@x-ray.at> writes:

> Kenny Tilton wrote:
> > OK, CormanLisp 2.01 now has available patches to fix up the defstruct
> > issues. A little fancy footwork on the Cells side and we have...
> >
> > Cells for CormanLisp (and ACL, LW, and CLisp):
> > http://www.tilton-technology.com/cells_top.html
>
> I still don't get it exactly. So in short:
> Is it something like the garnet object-system, only on top of CLOS?
>
> (I think it was called KR)

Like KR, it's a one-way constraints system. Cells simply lets you
specify a formula to constrain the value of a slot of a
standard-object -- it doesn't have any of the other parts of KR,
though (which is not necessarily a bad thing).

--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'

Kenny Tilton

unread,
Mar 18, 2003, 11:09:43 PM3/18/03
to
reini urban <rur...@x-ray.at> wrote in message news:<3e776aa5$1...@e-post.inode.at>...

> Kenny Tilton wrote:
> > OK, CormanLisp 2.01 now has available patches to fix up the defstruct
> > issues. A little fancy footwork on the Cells side and we have...
> >
> > Cells for CormanLisp (and ACL, LW, and CLisp):
> > http://www.tilton-technology.com/cells_top.html
>
> I still don't get it exactly. So in short:
> Is it something like the garnet object-system, only on top of CLOS?

Yes.

>
> (I think it was called KR)

Disclaimer: I read a lot of the KR doc, never once used it, and I am a
lousy reader. Corrections welcome (if phrased pleasantly, Marc <g>).

From the KR manual: "In addition, the system supports a constraint
maintenance mechanism which allows any value to be computed from a
combination of other values."

Check. Scarily similar (even when one is accustomed to independent
discovery) on the face of it.

Cells have cleaner, more transparent syntax (sometimes none), and
Cells have more features such as varieties of Cells (normal,
ephemeral, delta, stream, and more as necessary to suit new
requirements) and Synapses (lotsa games can be played here) which
mediate dependencies.

KR has an on-change callback mechanism called demon invocation,
similar to the Cells echo mechanism, but again not as rich.

Here we are very close: "Formulas represent one-directional
connections between a dependent value and any number of depended
values. Formulas specify an expression which computes the dependent
value based upon the depended values, as well as a permanent
dependency ...."

Check, except dependencies in Cells are not permanent (and I wonder if
they /really/ are in KR or if that is a doc error). In Cells, if the
rule is:

(if (a) (b) (c))

... the dependencies arising from only one of (b) or (c) are in place,
depending on the Lispian truth of (a). ie, dependencies are
dynamically (re)determined on each evaluation of the rule.

As for: "Formulas can contain arbitrary Lisp expressions, which
generally reference at least one particular depended value."

yep. Don't know about KR, but Cells are smart enough to optimize
themselves away if after any evaluation they are not dependent on
anything which might actually change. Saves a lot of time, that.

But now Cells and KR constraints deviate wildly: "Formulas are not
recomputed immediately when one of the depended values changes. This
reduces the amount of unnecessary computation."

A Cells application /works/ by cell-driven dataflow, so eager
evaluation is essential. And all the computation is necessary. That
said, if someone comes up with a requirement that /certain/ Cells not
be recomputed until accessed, we could do that, but I think in a case
like that, just don't use Cells.

The problem with lazy evaluation is this. If A depends on B which
depends on C and C changes, KR doc says B gets marked as invalid. What
about A? That's invalid, too. Now an example in the doc suggests KR
does know that, so... while KR is running all over the dependency
graph merely marking things as invalid, all of which will get
recomputed when something far away dependency-wise gets read, in the
meantime Cells is simply recalculating stuff and "making it so". If a
recalculation produces the same value as the cache, no further
propagation takes place. But lazy evaluation cannot determine that, in
the case above, the change to C would not produce a change to B absent
the recalculation of B, so it must continue along the dependency graph
erroneously and inefficiently marking stuff as invalid. That's what I
call unnecessary computation.

"Moreover, formulas are not recomputed every time their value is
accessed. Each formula, instead, keeps a cache of the last value it
computed. Unless the formula is marked invalid, and thus needs to be
recomputed, the cached value is simply reused."

Same with Cells.

"This factor causes a dramatic improvement in the performance of the
constraint maintenance system, since under ordinary circumstances the
rate of change is low and most changes are local in nature."

Which is why eager evaluation is so efficient. :)

Another difference: "Constraints may involve circular chains of
dependency."

They say they use the cached value when calculating A requires A. I
wonder what they use on the first calculation? Probably nil or 42. The
Cells system would prefer the programmer figure out what the hell they
mean. :)

Another difference: "It is possible for a dependency path to become
temporarily unavailable. This would happen, for instance, if schema
POINT-1 in Figure 5-1 was deleted..[snip]. KR handles such situations
automatically. If a formula needs to be evaluated but one of its
dependency paths is broken, the current cached value of the formula is
simply reused. This makes it completely safe to modify schemata that
happen to be involved in a dependency path, since the system
handles the situation gracefully."

You say "gracefully", we say "erroneously". The world has changed, the
cached value is not good enough. With cells the schemata is itself
cell-based. If the schema is going to change, the parent slot for its
children is mediated by a cell. (Cells internals arbitrarily enforce
this.) Any other cell that accesses that slot gets recalculated as the
schema changes. This is huge, btw, having the /population/ of the
model determined by a cell on which other state can depend, and having
the population depend on other state.

To me the lazy/eager thing is decisive. Without eager evaluation, the
programmer still has their hands on the controls. The paradigm shift
(to a dataflow model) does not occur. It took me a while to get used
to it, but early on in the development of Cells I realized I would
have to "let go" and commit to the declarative model: write the rules
then let 'er rip.

This felt reckless, but then again I think the power of the
declarative model is well-understood. Looked at another way, if we are
going to find a significantly more productive way of programming,
mustn't it involve relieving the programmer of some onerous
responsibility?

I get into this in the doc at the link below: Simple, linear
constraints combined with eager evaluation make our models run by
themselves, according to the rules we set. Cells effectively endow
state change with causal power over other state. They provide
automatic animation of models. Without Cells and esp. eager
evaluation, we programmers are puppeteers hand-animating the dataflow
required by any interesting model. That's a lot of work, hard even to
get right. I never realized how much work it was until I started using
Cells.

Again, KR veterans please weigh in with corrections.

Fred Gilham

unread,
Mar 19, 2003, 1:12:14 PM3/19/03
to

Kenny Tilton writes (at the very end):

> Again, KR veterans please weigh in with corrections.

I guess "veteran" is true of me. If you had said "expert" I would
have had to beg off. :-)

Cells sounds (sound?) interesting. Because of your emphasis on
portability it has the potential to become a de-facto standard.
Because it's based on CLOS, I think people will be more comfortable
with it than with Garnet. I should say, though, that I really like
the prototype-instance object model for GUI stuff, but that's just me
I suppose.

> Check, except dependencies in Cells are not permanent (and I wonder
> if they /really/ are in KR or if that is a doc error).

The dependency can actually change as the system runs. KR is pretty
flexible, allowing you to remove slots from schemas dynamically,
automatically handling the effects on the dependency graph of doing
that. You can create a new schema that inherits from another schema
and adds slots dynamically as well (though it doesn't look like you
can modify a particular schema to add slots).

> yep. Don't know about KR, but Cells are smart enough to optimize
> themselves away if after any evaluation they are not dependent on
> anything which might actually change. Saves a lot of time, that.

KR has a similar feature called "constant formulas" (section 8.5 in
the Garnet docs.) It allows the user to declare that a slot is
constant. If a formula depends only on constant slots, it will be
optimized away as you describe. Note that this happens at run time.

Slots can also become constant by inference, which will allow the
system to automatically determine that formulas are unneeded even when
the slot wasn't declared constant.

> But now Cells and KR constraints deviate wildly: "Formulas are not
> recomputed immediately when one of the depended values changes. This
> reduces the amount of unnecessary computation."
>
> A Cells application /works/ by cell-driven dataflow, so eager
> evaluation is essential. And all the computation is necessary. That
> said, if someone comes up with a requirement that /certain/ Cells
> not be recomputed until accessed, we could do that, but I think in a
> case like that, just don't use Cells.

I wouldn't be surprised if, as you claim, the approach Cells takes is
more efficient at least part of the time. On the other hand, I
suspect the reverse will be true as well. I guess the problem that
could arise is that repeated changes to a particular slot (Cell) would
cause repeated evaluations with Cells, while that wouldn't happen with
KR. If the evaluation was expensive you could waste a lot of work.
But I'm sure you know the tradeoff already.

You do short-circuit the process if the computed value doesn't change,
but I wonder how often the short-circuiting would happen. Do you have
any way of instrumenting things to see how effective the various
strategies are?

> They say they use the cached value when calculating A requires A. I
> wonder what they use on the first calculation? Probably nil or
> 42. The Cells system would prefer the programmer figure out what the
> hell they mean. :)

If you intend a circular dependency, you just supply an initial value
for at least one of the slots in the dependency cycle. It's actually
a nice technique to have available. Maybe this would fit in with your
eager model as it stands, since you short-circuit recalculation once a
value doesn't change. On the other hand, I guess I'm assuming that
you'll always hit some kind of fixpoint; probably that's not the case.

The above sounds pretty compelling to me. When Cells becomes
(become?) available for CLX/CMUCL, I'll be one of the first to try it
out.

--
Fred Gilham gil...@csl.sri.com
When an economist criticizes any human institution because it has
failed to convey to mankind an incommunicable attribute of God, we can
safely dismiss that economist. The trouble is, there remains a market
for these economists in academia. I regard this fact as one more piece
of evidence for the failure of tax-subsidized education. -- Gary North

Kenny Tilton

unread,
Mar 18, 2003, 3:48:33 PM3/18/03
to

reini urban wrote:
> Kenny Tilton wrote:
>
>> OK, CormanLisp 2.01 now has available patches to fix up the defstruct
>> issues. A little fancy footwork on the Cells side and we have...
>>
>> Cells for CormanLisp (and ACL, LW, and CLisp):
>> http://www.tilton-technology.com/cells_top.html
>
>
> I still don't get it exactly. So in short:
> Is it something like the garnet object-system, only on top of CLOS?
>
> (I think it was called KR)

Disclaimer: I read a lot of the KR doc, never once used it, and I am a

lousy reader. Corrections welcome (if phrased pleasantly, Marc <g>).

From the KR manual: "In addition, the system supports a constraint
maintenance mechanism which allows any value to be computed from a
combination of other values."

Check. Scarily similar (even when one is accustomed to independent
discovery) on the face of it.

Cells have cleaner, more transparent syntax (sometimes none), and Cells
have more features such as varieties of Cells (normal, ephemeral, delta,

stream, more as necessary to suit new requirements) and Synapses (lotsa

games can be played here) which mediate dependencies.

KR has an on-change callback mechanism called demon invocation, similar
to the Cells echo mechanism, but again not as rich.

Here we are very close: "Formulas represent one-directional connections
between a dependent value and any number of depended values. Formulas
specify an expression which computes the dependent value based upon the
depended values, as well as a permanent dependency ...."

Check, except dependencies in Cells are not permanent (and I wonder if

they /really/ are in KR or if that is a doc error). In Cells, if the
rule is:

(if (a) (b) (c))

... the dependencies arising from (b) or (c) are in place, depending on

the Lispian truth of (a). ie, dependencies are dynamically
(re)determined on each evaluation of the rule.

As for: "Formulas can contain arbitrary Lisp expressions, which
generally reference at least one particular depended value."

yep. Don't know about KR, but Cells are smart enough to optimize

themselves away if after any evaluation they are not dependent on
anything which might actually change.

Now Cells and KR constraints deviate wildly: "Formulas are not

recomputed immediately when one of the depended values changes. This
reduces the amount of unnecessary computation."

A Cells application /works/ by cell-driven dataflow, so eager evaluation

is essential. That said, if someone comes up with a requirement that
certain Cells not be recomputed until accessed, we could do that.

The problem with lazy evaluation is this. If A depends on B which
depends on C and C changes, KR doc says B gets marked as invalid. What
about A? That's invalid, too. Now an example in the doc suggests KR does
know that, so... while KR is running all over the dependency graph
merely marking things as invalid, all of which will get recomputed when
something far away dependency-wise gets read, in the meantime Cells is
simply recalculating stuff and "making it so". If a recalculation
produces the same value as the cache, no further propagation takes

place. But lazy evaluation cannot determine that, so it must continue

along the dependency graph erroneously and inefficiently marking stuff
as invalid.

"Moreover, formulas are not recomputed every time their value is


accessed. Each formula, instead, keeps a cache of the last value it
computed. Unless the formula is marked invalid, and thus needs to be
recomputed, the cached value is simply reused."

Same with Cells.

"This factor causes a dramatic improvement in the performance of the
constraint maintenance system, since under ordinary circumstances the
rate of change is low and most changes are local in nature."

Which is why eager evaluation is so efficient. :)

Another difference: "Constraints may involve circular chains of
dependency."

They say they use the cached value when calculating A requires A. I

wonder what they use on the first calculation? Probably nil or 42. The
Cells system would prefer the programmer figure out what the hell they
mean. :)

Another difference: "It is possible for a dependency path to become

temporarily unavailable. This would happen, for instance, if schema
POINT-1 in Figure 5-1 was deleted..[snip]. KR handles such situations
automatically. If a formula needs to be evaluated but one of its
dependency paths is broken, the current cached value of the formula is
simply reused. This makes it completely safe to modify schemata that
happen to be involved in a dependency path, since the system
handles the situation gracefully."

You say "gracefully", we say "erroneously". The world has changed, the
cached value is not good enough. With cells the schemata is itself
cell-based. If the schema is going to change, the parent slot for its
children is mediated by a cell. (Cells internals arbitrarily enforce
this.) Any other cell that accesses that slot gets recalculated as the
schema changes. This is huge, btw, having the /population/ of the model
determined by a cell on which other state can depend, and having the
population depend on other state.

To me the lazy/eager thing is decisive. Without eager evaluation, the
programmer still has their hands on the controls. The paradigm shift

does not occur. It took me a while to get used to it, but early on in
the development of Cells I realized I would have to "let go" and commit
to the declarative model: write the rules then let 'er rip.

This felt reckless, but then again I think the power of the declarative
model is well-understood. Looked at another way, if we are going to find

a significantly more productive way of programming, must it not involve

relieving the programmer of some onerous responsibility?

I get into this in the doc at the link below: Simple, linear constraints

combined with eager evaluation make our models run by themselves,
according to the rules we set. Cells effectively endow state change with
causal power over other state. They provide automatic animation of
models. Without Cells and esp. eager evaluation, we programmers are
puppeteers hand-animating the dataflow required by any interesting

model. That's a lot of work never mind how hard it is to get right, and
I never realized how much until I started using Cells.

I said it before, I'll say it again: KR veterans please weigh in with
corrections.

--

Kenny Tilton

unread,
Mar 19, 2003, 3:19:12 PM3/19/03
to

Fred Gilham wrote:
> Kenny Tilton writes (at the very end):

> Cells sounds (sound?) interesting. Because of your emphasis on
> portability it has the potential to become a de-facto standard.
> Because it's based on CLOS, I think people will be more comfortable
> with it than with Garnet. I should say, though, that I really like
> the prototype-instance object model for GUI stuff, but that's just me
> I suppose.

I think I like prototyping, too, tho I have never used it. Sounds like
it makes it possible to handle custom situations without forever making
new classes--one just keeps sculpting away at the object to make new ones.

> KR has a similar feature called "constant formulas" (section 8.5 in
> the Garnet docs.)

whoa, glad I said I was a bad reader. i missed that whole section this
time thru, tho i had read it years ago. maybe it is a good thing i
missed it this time, i would have written twice as much.

having read it I do see many more similarities, and one big difference:
KR is just jam-packed with backdoors that let the user subvert the
constraints mechanism.

Cells is the complete opposite, the philosophy being that the
productivity benefit comes from living within the system so the system
can manage everything. One /really/ does not want to fly an F-16 without
computer assist.

When I cannot do what I need to do in Cells, i extend the mechanism. In
practice, half of these hacks have been backed out when I realized the
problems they solved were solvable with vanilla Cells.

> I guess the problem that
> could arise is that repeated changes to a particular slot (Cell) would
> cause repeated evaluations with Cells, while that wouldn't happen with
> KR. If the evaluation was expensive you could waste a lot of work.
> But I'm sure you know the tradeoff already.

Yes. Hey, let's wait for a good example to come along. I think better in
concrete. I have trouble imagining a situation in which state has
changed and i do not want it manifested outside the model. If we are
talking about a flood of input which needs only periodic inspection,
Synapses can handle that by mediating a specific dependency.

Synapses are filters between a cell and a value on which it depends.
These filters can transform the value (perhaps yielding the delta since
the last sampling instead of the absolute value) and/or suppress
re-calculation ("dear used value: don't bother me until you have changed
by 5%, or five minutes have gone by, which ever comes first. tia.")

Finally, I could add lazy Cells pretty easily, the plumbing is all there.

>
> You do short-circuit the process if the computed value doesn't change,
> but I wonder how often the short-circuiting would happen. Do you have
> any way of instrumenting things to see how effective the various
> strategies are?

Short-circuiting is pretty common when it comes to GUI layout. Yes, I
have done up ad hoc metrics to count such things. And there is a general
counting utility I use which lets me spot overactive Cells. There is a
lot of room here for diagnostics.

I also think Cells will provide a decent objective measure of an
application's complexity (after it is developed, unfortunately). Just
lexically count the models, the rules, the dataflow inputs (c-variables)
and the echos. maybe look at the runtime dependency graph as well. I bet
that correlates well with development cost.


> If you intend a circular dependency, you just supply an initial value
> for at least one of the slots in the dependency cycle.

oh, Cells have something like that. I call them Drifters... they start
with an initial value and then /change/ according to some rule; the rule
result is taken to be a delta, not the new value.

> It's actually
> a nice technique to have available. Maybe this would fit in with your
> eager model as it stands, since you short-circuit recalculation once a
> value doesn't change.

I do handle circularity in data propagation vs calculation. A and B can
both be dataflow inputs, and their echos can setf each other (this would
normally be a multi-way constraint, which I try to avoid as it seems to
have been a tar pit for the constraints crowd). But if A sets B, when B
goes to set A it sees the circularity and stops.

This is how a scroll thumb widget can scroll a page and a scrolling page
canmove a scroll thumb. I hate this circular setf stuff and plan someday
RSN to work out a SeeSaw mechanism for two Cells so they can just
declare rules which are circular (and yeah, we'll have to start
someplace such as zero or nil.

> The above sounds pretty compelling to me. When Cells becomes
> (become?) available for CLX/CMUCL, I'll be one of the first to try it
> out.

Watch this space. :) Cells (just the dataflow, not the GUI which I call
"Cello") breaks even the new PCL. Gerd Moellmann has fixed that for a
future release, but made the source available. Thomas Burdick is helping
me out on this, and at some point soon there should exist binaries that
include Gerd's latest as well as Thomas's brainstorm: a CMUCL callback
mechanism suitable for C libraries such as GLUT. Then comes Cello for
CMUCL and X11.

Meanwhile I actually have started today on a Cello tutorial, and with luck
I can get enough done by the time CMUCL comes on line that we can release a
primodial Cello+tutorial for win32 (ACL and LW) and X11 (CMUCL first,
then MCL).

Kenny Tilton

unread,
Mar 18, 2003, 8:44:53 PM3/18/03
to
reini urban wrote:
> Kenny Tilton wrote:
>
>> OK, CormanLisp 2.01 now has available patches to fix up the defstruct
>> issues. A little fancy footwork on the Cells side and we have...
>>
>> Cells for CormanLisp (and ACL, LW, and CLisp):
>> http://www.tilton-technology.com/cells_top.html
>
>
> I still don't get it exactly. So in short:
> Is it something like the garnet object-system, only on top of CLOS?
>
> (I think it was called KR)

I posted a longer answer but it has not shown up even on my own news
server after six hours. I'll chop it up or put it on my web site in a
few hours, but for now:

Yes.

To be precise, the KR doc talks about a few major accomplishments, only
one of which is a simple, linear constraint mechanism much like Cells
which, yes, messes CLOS.

The big difference between Cells and KR constraints is eager vs lazy
evaluation.

Alan Baljeu

unread,
Mar 20, 2003, 6:34:22 PM3/20/03
to
> > I guess the problem that
> > could arise is that repeated changes to a particular slot (Cell) would
> > cause repeated evaluations with Cells, while that wouldn't happen with
> > KR. If the evaluation was expensive you could waste a lot of work.
> > But I'm sure you know the tradeoff already.
>
> Yes. Hey, let's wait for a good example to come along. I think better in
> concrete. I have trouble imagining a situation in which state has
> changed and i do not want it manifested outside the model. If we are
> talking about a flood of input which needs only periodic inspection,
> Synapses can handle that by mediating a specific dependency.
>
Apologies if I get the notation wrong.

Semi-concrete:
(defparameter *s2* (to-be (make-instance 'sheet
:a1 (cv 2)
:a2 (c? (f (a1 self)))
:a3 (c? (slow-computation (a2 self)))

Now loop incrementing a1 until (> (a2 self) 11). In this case, you hope
a3 doesn't recompute every time a1 changes.

Second reason:
(defparameter *s3* (to-be (make-instance 'sheet
:a1 (cv 2)
:a2 (cv 3)
:a3 (c? (slow-computation2 (a2 self) (a1 self)))

Suppose you decide to change a1 and a2. Or suppose instead of a3 you have
a large network of dependencies on a1 and a2, and you want to change a1 and
a2. It would be good if you put this on hold.

What would be good in such cases is to have a
(delayed-update (change a1) (change a2)) form. However, if
1. b depends on a,
2. c depends on b, d,
3. You change a and d.
then you hope the update process updates b first and then c, rather than
c first then b, because c would need re-refreshing.

On the other hand, you want the update mechanism to be efficient, so there's
a trade-off.

I also don't know KR, but lazy update can be equally as accurate as eager
if every cell reference forces the values to be updated. The pain comes
when you have to go around to every cell manually and say "please
update". It would be better if the cell came to you and told you a
refresh is needed. I suppose Cells does that.

Alan

Kenny Tilton

unread,
Mar 21, 2003, 1:29:23 AM3/21/03
to
Alan Baljeu wrote:
> Semi-concrete:

zero concrete! what is A1? A2? A3? The slow computation?

> (defparameter *s2* (to-be (make-instance 'sheet
> :a1 (cv 2)
> :a2 (c? (f (a1 self)))
> :a3 (c? (slow-computation (a2 self)))
>

> Now loop incrementing a1 until (> (a1 self) 11).


> In this case, you hope
> a3 doesn't recompute every time a1 changes.

Why not? A1 has changed, A2 has changed. If A3 does not recompute,
A3 is now out of whack with the model. It holds a logically inconsistent
value. That's a bug, unless there is a concrete example which can go
un-recomputed because of some concrete real quality.

If you say, well, A1 is a flood of inputs coming in a FireWire
connection, and A3 only needs to be checked when A2 has changed by a
certain percentage, then we have something to talk about. And we
would say, place a synapse on the dependency on A2:

:a3 (c? (slow-computation (^a2 self (fsensitivity 0.05))))

The effect is that the formula does not get kicked off until A2 has
changed by 5%. Or if A3 does not need to be calculated until the user
asks to see the current status, then we just write the rule accordingly

:a3 (c? (if (eql (request user) :refresh)
(slow-compute (a2 self))
.cache.))

That alone would make things hum because even tho A2 is changing wildly,
the rule quickly determines (request user) is null and then returns the
.cache. Alternatively, there /is/ a without-dependency macro to suppress
unwanted recalculations:

:a3 (c? (if (eql (request user) :refresh)
(slow-compute (without-dependency (a2 self)))
.cache.))


>
> Second reason:
> (defparameter *s3* (to-be (make-instance 'sheet
> :a1 (cv 2)
> :a2 (cv 3)
> :a3 (c? (slow-computation2 (a2 self) (a1 self)))
>
> Suppose you decide to change a1 and a2. Or suppose instead of a3 you have
> a large network of dependencies on a1 and a2, and you want to change a1 and
> a2. It would be good if you put this on hold.

Background: I am all for speed. I noticed once that most things to be
documented about cells have to do with performance optimizations -- all
explanations lead to speed. I have solved a lot of over-calculation
problems several different ways with cells, but I have never had to put
the eager-evaluation model or any part of it on hold.

Cells help manage complexity. If I have just one situation where they
are a bottleneck and Synapses won't help and other tricks I have used
won't help and I cannot think of a new trick to help, hey, don't use
Cells right here. Like any hairy optimization, it's not a problem if you
just have to do it in one nasty little corner of the algorithm.
Complexity does not explode when I optimize one intractable
computational overload.

>
> What would be good in such cases is to have a
> (delayed-update (change a1) (change a2)) form. However, if
> 1. b depends on a,
> 2. c depends on b, d,
> 3. You change a and d.
> then you hope the update process updates b first and then c, rather than
> c first then b, because c would need re-refreshing.

I had to address that anyway, because you could have:

b depends on a
c depends on b and a

if a changes and c gets calculated first, it would use an obsolete value
of b to compute a value inconsistent with the facts, and perhaps launch
an ICBM before the next phase in which b finally gets recalculated and c
gets recalculated a second time (correctly, but too late to recall the
missile).

>
> On the other hand, you want the update mechanism to be efficient, so there's
> a trade-off.
>
> I also don't know KR, but lazy update can be equally as accurate as eager
> if every cell reference forces the values to be updated.

In the dataflow model, the inputs drive the application. That is how
things happen. The model you describe is the traditional
programmer-driven model, where programmers are at the controls. We get a
mouseclick and then start running all over the place (in our logic)
trying to make the right things happen in the right order. we usually
forget something.

cells makes you stop and think about how to set up (declare) a model
which will work by itself via dataflow. that's a lot of fun, by the way,
and, once you work it out, everything Just Works (as early cell users
marveled (until we got used to it)) .

> The pain comes
> when you have to go around to every cell manually and say "please
> update". It would be better if the cell came to you and told you a
> refresh is needed. I suppose Cells does that.

right. KR came close to getting this right, but in the end they panicked
and did not force the developer to live within a natural dataflow model.
They provided endless opportunities for me to write code which
discontinuously fucked with my models.

Why? Because they responsed poorly to problems with a purer form of
constraints. Instead of keeping the declarative model pure, they elected
to punt and throw the burden back on the poor programmer: "Here, we'll
let you change the formula of a slot on the fly, we cannot think of any
other way out of this bind." programmers soon enough resumed manual
control of the application and wrote procedural, imperative code which
dynamically tweaked the reality of their models -- which they still
thought ran automatically.

Hey, it's probably easiest to just watch me develop an object inspector
and see if one likes cells/cello.

Jakub Travnik

unread,
Mar 21, 2003, 7:51:43 AM3/21/03
to
On Tue, 18 Mar 2003 00:49:21 +0000, Kenny Tilton wrote:

> OK, CormanLisp 2.01 now has available patches to fix up the defstruct
> issues. A little fancy footwork on the Cells side and we have...
>
> Cells for CormanLisp (and ACL, LW, and CLisp):
>
> http://www.tilton-technology.com/cells_top.html
>

Hello,

what are license conditions for Cells?


Jakub Travnik
jabber://jt...@jabber.com

Kenny Tilton

unread,
Mar 21, 2003, 10:09:37 AM3/21/03
to

Jakub Travnik wrote:
> what are license conditions for Cells?

One version was released under the GPL. Anyone using that could get a
different, uninfectious license for the terms described below.

The current version is just plain proprietary, until events sway me back
towards GPL or even LGPL.

My plan would be to have free runtime use, with developer seats costing
something (which would include some base level of support).

When I do start selling it, my thinking was to start silly-cheap and
then increase the price to some reasonable level over time. That way if
it just dies, no one has paid very much.

It also compensates early adopters for the pain they will endure reading
my doc (which will be evolving in response to user feedback) and
watching me change the whole thing every month so they have to rewrite
all their code. (Well, not Cells, that is stable, but Cello...)

Vlad S.

unread,
Mar 21, 2003, 1:19:26 PM3/21/03
to
Kenny Tilton <kti...@nyc.rr.com> wrote in message news:<3E77CD6F...@nyc.rr.com>...

> I posted a longer answer but it has not shown up even on my own news
> server after six hours. I'll chop it up or put it on my web site in a
> few hours, but for now:
>
> Yes.
>
> To be precise, the KR doc talks about a few major accomplishments, only
> one of which is a simple, linear constraint mechanism much like Cells
> which, yes, messes CLOS.
>
> The big difference between Cells and KR constraints is eager vs lazy
> evaluation.

There is an extension to Garnet called Multi-Garnet written by Michael
Sannella at U of Washington sometime in the early 90s. It supports
multi-way constraints (hence the name) by replacing KR's constraint
solver with their constraint system called SkyBlue, which besides
being based on eager evaluation also has a separate constraint
propagation planning stage that it uses to resolve the constraint
hierarchy (it supports required and 'weak' constraints) and perform a
bunch of optimizations. I've recently obtained permission from
Sannella to modify and redistribute the original sources, and I'm
reading through the Multi-Garnet paper right now. Hopefully I'll
understand enough to at least fix it up to work right on Garnet 3.0.
The nice thing is that it can coexist with regular Garnet in the same
image.

The bad thing about Garnet is that it doesn't play nicely with CLOS.
The best approach seems to be the one by Russell Almond, which
involves putting an after method on the setf method for the particular
CLOS object in question.

http://groups.google.ca/groups?q=garnet+clos&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=9304290000.AA17234%40bass.statsci.com&rnum=3

http://groups.google.ca/groups?q=garnet+clos&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=9310140045.AA25086%40herb.statsci.com&rnum=1
(details on Russell's KR-CLOS method)

http://www.cs.washington.edu/research/constraints/ui/multi-garnet-92.html

http://www.cs.washington.edu/research/constraints/index.html
(the aforementioned pages on Multi-Garnet and Alan Borning's
Constraints research group. their ftp site seems to be down right
now).

Thomas F. Burdick

unread,
Mar 21, 2003, 2:15:06 PM3/21/03
to
Kenny Tilton <kti...@nyc.rr.com> writes:

> If you say, well, A1 is a flood of inputs coming in a FireWire
> connection, and A3 only needs to be checked when A2 has changed by a
> certain percentage, then we have something to talk about. And we
> would say, place a synapse on the dependency on A2:

[snip]

It sounds like Synapses essentially let you get carefully-controlled
delayed evaluation, which is probably good enough in practice. With
KR, you pretty much know when you're depending on the lazy evaluation,
so I don't think this would be different there. On the flip side, you
sometimes unnecessarily check a value in order to force evaluation, so
it sounds like Cells just inverts this. Again, in practice, I think
most cells/formulas (>= 90%?) would work correctly under both models.

> right. KR came close to getting this right, but in the end they panicked
> and did not force the developer to live within a natural dataflow model.
> They provided endless opportunities for me to write code which
> discontinuously fucked with my models.
>
> Why? Because they responsed poorly to problems with a purer form of
> constraints. Instead of keeping the declarative model pure, they elected
> to punt and throw the burden back on the poor programmer: "Here, we'll
> let you change the formula of a slot on the fly, we cannot think of any
> other way out of this bind." programmers soon enough resumed manual
> control of the application and wrote procedural, imperative code which
> dynamically tweaked the reality of their models -- which they still
> thought ran automatically.

Well. It sounds like you also provide endless opportunities to
unnecessarily delay computation. Providing tools is different than
creating an environment where they need to be used. In my own code, I
found programming with KR (both Garnet and non-Garnet code) to be very
declarative. Within the KR-managed parts of the code, there were
little bits of imperative code that were mostly used to setup initial
state, or to construct the declarative world -- essentially to
bootstrap the declarative part of the program. IMO, it would raise a
zillion bad-style flags if KR code looked super-imperative.

I'm sure that the designers of KR made an intentional choice to use
lazy evaluation, which might have been along the lines you're
theorizing, or maybe it was for entirely different reasons. It was
originally developed for non-Garnet-related Knowledge Representation,
and I would imagine that there might be more discussion of *why* KR
does things the way it does, in some of the papers cited in the Garnet
docs. Unfortunately, I've never tracked down a copy of any of those.
In case anyone has a copy they want to send me ;) or, has something to
say on the matter, the papers I mean are:

Dario Giuse. KR: an Efficient Knowledge Representation System.
Technical Report CMU-RI-TR-87-23, Carnegie Mellon University
Robotics Institute, October, 1987.

Dario Giuse. KR: Constraint-Based Knowledge Representation.
Technical Report CMU-CS-89-142, Carnegie Mellon University
Computer Science Department, April, 1989.

Giuse, D.A. Efficient Knowledge Representation Systems.
Knowledge Engineering Review 5(1):35-50, 1990.

Kenny Tilton

unread,
Mar 21, 2003, 5:11:52 PM3/21/03
to

Vlad S. wrote:
> I've recently obtained permission from
> Sannella to modify and redistribute the original sources, and I'm
> reading through the Multi-Garnet paper right now. Hopefully I'll
> understand enough to at least fix it up to work right on Garnet 3.0.
> The nice thing is that it can coexist with regular Garnet in the same
> image.

Sounds like fun. When I get some spare time I would like to do a simple
multi-way trick in Cells by creating a SeeSaw structure which links
exactly two Cells. I have had that come up a couple of times (the scroll
bar thumb position-text scroll position being a classic pair) and don't
like the way I got around it.

Early on I did something interesting (before dumping it in favor of the
workaround I do not like either). I created the concept of a cellular
Gosub. When one of these was instantiated, it installed temporarily new
rules in any abitrary number of instances' slots. With the scroll thumb
example, the normal rule was that it slavishly reflected the amount the
page had been scrolled by cursor movements, pagedowns, text searches,
etc. But if there were a mousedown in the scroll thumb, a Gosub was
instantiated which had the scroll thumb dependent on mouse movement and
made the text scroll position dependent on the scroll thumb. the neat
thing was that the Gosub was itself Cellular, and a "return" cell (with
rule (c? (mouseUp (window self)))) was echoed by snuffing the Gosub,
including backing out the temporary rules and restoring the originals.

Cute, but eventually the discontinuity got to me. Reality does not
suddenly swap in new rules, I should I have to do that? And of course
yanking Gosubs eliminated a whole wadge of code, which is nice.

Anyway, getting back to multi-way (MW), I think that is a tool for an
entirely different class of problem than making an application run. MW
lets one have a logic engine find solutions for us, when all we have are
partial constraints on a problem. But if I the developer am not faced
with such a problem--if I know how I want my model to work--I think
one-way (1W), fully-determinative rules suffice. (Except for scroll
thumbs.) But for quite a few different kinds of application (tutorial,
crossword puzzlr, modeling of a pendulum as a physical system, the vast
CiniSys application) 1W has been enough.

Of course MW is a superset of 1W, so I would guess any of the MW systems
could be used to power something like Cells.

>
> The bad thing about Garnet is that it doesn't play nicely with CLOS.
> The best approach seems to be the one by Russell Almond, which
> involves putting an after method on the setf method for the particular
> CLOS object in question.

Why not just carve out the constraints logic so you don't end up with an
app with two object models and this glue (thx for the links):

>
> http://groups.google.ca/groups?q=garnet+clos&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=9304290000.AA17234%40bass.statsci.com&rnum=3

From there I pulled:

> Here is how I solve the problems:
>
> +--------+ announcement +----------+ notification +--------+
> | |------------->| Mediator |-------------->| |
> | CLOS | +----------+ | KR |
> | object | call-back (action function) | object |
> | |<----------------------------------------| |
> +--------+ +--------+
>
...snip...
>
> Although this seems a bit convoluted,

Ya think? :) But one thing I am learning is that some folks just plain
like the Prototype OO model, esp. for GUI stuff, so maybe that is a win
big enough to justify the effort of splicing CLOS and KR.

Good luck with Multi-Garnet.

Kenny Tilton

unread,
Mar 21, 2003, 5:57:43 PM3/21/03
to

Thomas F. Burdick wrote:
> Kenny Tilton <kti...@nyc.rr.com> writes:
>
>
>>If you say, well, A1 is a flood of inputs coming in a FireWire
>>connection, and A3 only needs to be checked when A2 has changed by a
>>certain percentage, then we have something to talk about. And we
>>would say, place a synapse on the dependency on A2:
>
>
> [snip]
>
> It sounds like Synapses essentially let you get carefully-controlled
> delayed evaluation, which is probably good enough in practice.

Yeah, and I forgot to mention that Synapses can be programmed with any
logic one likes, so the determination of whether to trigger reevaluation
can be made on any basis one likes. This is in contrast with Cells,
which come in a few predetermined variets. (One direction Cells could
take would be to carve out an interface to the Cell engine so users
could define new kinds of Cells.)


> With
> KR, you pretty much know when you're depending on the lazy evaluation,
> so I don't think this would be different there. On the flip side, you

> sometimes unnecessarily check a value in order to force evaluation, ...

yecch. As soon as we stumbled onto cells we knew we had a winner. But
the win was productivity, so I have a policy of rejecting any "fix" or
feature in which the user has to think about the internals. Or at least
that is a design goal, we'll see how successful I have been if others
oblivious to the internals start using Cells.

One good example was deleting a character at the end of a line. In two
separate and independent development efforts (of mini text editors) the
same bug arose: the programmer first truncated the text, then moved the
cursor back one. So the app crashed when some code went out of range
trying to process the old cursor (at the end of the text when backspace
was hit). I realized I could avoid the problem by first moving the
cursor left one and then deleting the last character, but then I
pictured FAQs on comp.constraints.cells where the answer was "you have
to think about the order in which you change the program state, or hit
it over the head and use (with-one-propagation ...)".

yecch, end of productivity win. this is supposed to be a declarative
programming model, now I am compensating in my code for constraint
engine internals issues.

in this case I trapped the runtime error and put the cell which failed
because the cursor was outside the text (probably the cell deciding the
cursor's new position) into a "pending" state. pending meaning "I hope
the next imperative statement or two changes some other state so I can
compute myself without error." as long as no one tried to use the
pending value before a curing state change came to pass, no runtime
error resulted.

That code is gone, I think, but could be resurrected. Pretty sure I just
learned to program with Cells a little better and managed to code so
that kind timing bind did not arise.

> Well. It sounds like you also provide endless opportunities to
> unnecessarily delay computation. Providing tools is different than
> creating an environment where they need to be used.

Touche. I /was/ wondering as I wrote how often KR veterans actually
availed themselves of the myriad backdoors. Sounds like you eschewed
those. If so, was that because you were simply never tempted (ie, yer a
natural), or because you resisted occasional temptation deliberately to
protect the declarative purity (for its productivity advantage)? Other?

BTW, without pretending I do not have an epee tip lodged in my side, I
would like to point out that Synapses are still declarative and nicely
encapsulated and that there is nothing semantically discontinuous about
them. They simply offer one more rule which runs when the dataflow
engine says it should run, offering the programmer a chance to optimize
model performance by working within the system, not by defeating the system.

Gosubs got tossed because, well, there's a line between
within-the-system and without, and they crossed it. And I got to delete
code.

Kenny Tilton

unread,
Mar 21, 2003, 8:26:22 PM3/21/03
to

kenny tilton wrote:
>>right. KR came close to getting this right, but in the end they panicked
>>and did not force the developer to live within a natural dataflow model.
>>They provided endless opportunities for me to write code which
>>discontinuously fucked with my models.

uh-oh. Just found a disclaimer at the beginning of the chapter offering
those endless opportunities:

"This section describes features of KR that are seldom needed by casual
Garnet users. These features are useful for large application programs,
especially ones which manipulate constraints directly, or for
application programs which use the more advanced knowledge
representation features of KR."

Never mind. :)

Thomas F. Burdick

unread,
Mar 22, 2003, 10:22:12 PM3/22/03
to
Kenny Tilton <kti...@nyc.rr.com> writes:

> Thomas F. Burdick wrote:
>
> > Well. It sounds like you also provide endless opportunities to
> > unnecessarily delay computation. Providing tools is different than
> > creating an environment where they need to be used.
>
> Touche. I /was/ wondering as I wrote how often KR veterans actually
> availed themselves of the myriad backdoors. Sounds like you eschewed
> those. If so, was that because you were simply never tempted (ie, yer a
> natural), or because you resisted occasional temptation deliberately to
> protect the declarative purity (for its productivity advantage)? Other?

Well, I made an effort to do KR programming on its own terms, and not
mess with the internals of the constraints system. After that effort,
it was pretty natural to just do things declaratively, which I think
mostly a testament to KR. As you already said in a later message, you
noticed the "not for most users" note at the top of this section in
the documentation. Having thought about it, I think I like the idea
of eager-evaluation+Synapses better than the way KR managed the same
problems, but KR's model is pretty nice and easily useable nonetheless.

Joerg Hoehle

unread,
Mar 27, 2003, 10:21:07 AM3/27/03
to
Kenny Tilton <kti...@nyc.rr.com> writes:
> I do handle circularity in data propagation vs calculation. A and B can
> both be dataflow inputs, and their echos can setf each other (this would
> normally be a multi-way constraint, which I try to avoid as it seems to
> have been a tar pit for the constraints crowd). But if A sets B, when B
> goes to set A it sees the circularity and stops.

Even if the new value is (sligthly) different?
- beware of oscillating systems!

> This is how a scroll thumb widget can scroll a page and a scrolling page
> canmove a scroll thumb. I hate this circular setf stuff and plan someday
> RSN to work out a SeeSaw mechanism for two Cells so they can just
> declare rules which are circular (and yeah, we'll have to start
> someplace such as zero or nil.

When I looked into GUI programming a decade ago, I remember a nice demo:
Something like a volume control with two ways of setting it:
- a proportional slider with a knob
- a digital input where you could type the number (0-100)
Modifying with mouse or keyboard changed the other's display.
I believe this requires cycles in the dependency graph, if it were
done via cells.

It would be nice if one of your papers would include an example similar
to this. So far, I found nothing which looked like this (the .pdf
from 2001 are very loosely structured, so it seems to me). BTW, 2.5
and 2.6 of the hello-world.pdf seem identical: "dataflow change direction".


Here's an example of a two-iteration, but non-oscillating system:
Suppose the propotional slider has internal resolution 0-65535. Even
though you cannot actually use that resolution via the GUI, suppose
your mouse movements sets it to 32970. The digital display must then
update itself to 50(%). Then the system may conclude: "the digital
display was changed to 50(%), so let's put the proportional slider at
32768". Good? Wrong? Bad?

For some systems this may be a resonable thing to do. It depends on
the application. For a GUI, I don't like sliders moving slightly away
from where I put them with the mouse, unless there's a compelling
reason to do so (e.g. the slider actually has only two positions,
e.g. for showing a 2-9-page document page by page: it can then exihit
jumping instead of sliding behaviour).
MS-Windows application's GUIs tend to behave badly.

In this particular example (volume or gain control), I believe it's
acceptable for the slider to provide higher resolution that the 0-100
keyboard input. As a consequence, the slider must not be set to 32768
and keep the position corresponding to 32970 (~50,3%).

For another application, e.g. choosing a number from 1-10, a jumping
scrollbar with values limited to 0, 656, ..., 65535 may be the right
choice instead.

Regards,
Jorg Hohle
Telekom/T-Systems Technology Center

Kenny Tilton

unread,
Mar 27, 2003, 1:24:58 PM3/27/03
to

Joerg Hoehle wrote:
> Kenny Tilton <kti...@nyc.rr.com> writes:
>

>>But if A sets B, when B
>>goes to set A it sees the circularity and stops.
>
>
> Even if the new value is (sligthly) different?

yep. mind you, this hack simply supports a couple of (what i call)
see-saw dependencies, where I know that only one value is driving the
other /at any one point in the user interaction/. hmm, maybe see-saw is
not such a good metaphor. :)

a falling stone is a tougher case. the distance is one-half acceleration
times the square of the time, and the acceleration increases as the
distance fallen increases, so it occured to me at one point that we
could take a model like this and just let it run with one change
triggering another: oh, time has changed, my position has changed, the
gravitational pull has changed, i should recompute the distance--hang
on, time is supposed to be driving this model, now we are about to start
running, well, naturally, as the effect of each cause becomes a cause
itself of some new effect.

we would not need to have a global time variable to cause things to
happen. of course the model would run slower the more stuff there was
changing, because there would be more work to do with more
interdependencies. i conclude this is why gravity slows time. :)


> When I looked into GUI programming a decade ago, I remember a nice demo:
> Something like a volume control with two ways of setting it:
> - a proportional slider with a knob
> - a digital input where you could type the number (0-100)
> Modifying with mouse or keyboard changed the other's display.
> I believe this requires cycles in the dependency graph, if it were
> done via cells.

the circularity can be avoided at a price. the trick is to have the
controls operate directly on some "volume" vector, then have their
appearance be dependent on the "volume" vector. ie, the mouse does not
really move the slider, it changes the volume which the slider is
watching for its position.

the price is that one is then not using cells to their fullest, and it
can cause a visible lag in how tightly the slider follows the mouse
because of the delay in propagating the change thru the volume and back
to the slider's position.

anyway, the cyclic setf hack works for this, unless they are typing and
using the mouse at the same time. (just kidding, it would still work.)
but i do want to extend cells someday to handle better these simple
binary cycles.

>
> It would be nice if one of your papers would include an example similar
> to this.

will do. and maybe i will make the enhancement i have in mind before
doing so--why document a kludge one is about to fix?

> So far, I found nothing which looked like this (the .pdf
> from 2001 are very loosely structured, so it seems to me).

you are a very nice person. those old docs are garbage, as my web page
proudly states.

i am working on some new doc now. i am developing a graphical CLOS (and
other) object inspector incrementally, just as I would anyway. when I
hit a Cell-related problem, I am documenting that and explaining the
workaround. i call it reality documentation.

one very cool thing here is that Cells went upside my head in a way they
never have before, which is not easy to do after all these years of
intensive use. this is like George Willig falling for real when a
sandstone hold broke off on a "show" climb for Wide World of Sports
during his fifteen minutes of fame after climbing the WTC. Jim McKay had
a cow. I hope the doc readers enjoy my face plant as much as I enjoyed
Willig's tumble.

>
>
> Here's an example of a two-iteration, but non-oscillating system:
> Suppose the propotional slider has internal resolution 0-65535. Even
> though you cannot actually use that resolution via the GUI, suppose
> your mouse movements sets it to 32970. The digital display must then
> update itself to 50(%). Then the system may conclude: "the digital
> display was changed to 50(%), so let's put the proportional slider at
> 32768". Good? Wrong? Bad?

Not so. :) The digital display should have an internal value which gets
set to 32970/65535 and which merely gets shown as "50". It has to take a
/typed/ "50" and publish 1/2 in its internal value anyway unless we want
each of its clients to determine for itself the semantics of "50".

>
> For some systems this may be a resonable thing to do. It depends on
> the application. For a GUI, I don't like sliders moving slightly away
> from where I put them with the mouse, unless there's a compelling
> reason to do so (e.g. the slider actually has only two positions,
> e.g. for showing a 2-9-page document page by page: it can then exihit
> jumping instead of sliding behaviour).

Yikes, hopalong widgets? Sounds horrid, but i usually turn on
"snap-to-grid" when doing gui layout, and that's ok. but there the
dragged element is larger than the grid resolution, so my mouse need not
leave the element by much or at all before the element snaps to a new
location.

Wolfgang Mederle

unread,
Mar 27, 2003, 3:14:09 PM3/27/03
to
Joerg Hoehle wrote:

> When I looked into GUI programming a decade ago, I remember a nice
> demo: Something like a volume control with two ways of setting it:
> - a proportional slider with a knob
> - a digital input where you could type the number (0-100)
> Modifying with mouse or keyboard changed the other's display.

Sounds like Garnet. (Even if it wasn't, Garnet has sliders and
scrollbars with this functionality.) I'm working on a small program at
the moment that uses it, and it is really a joy.

--
Wolfgang Mederle

$BONMOT

Kenny Tilton

unread,
Mar 27, 2003, 5:10:41 PM3/27/03
to

You know, I always am encouraged in re Cells and the Cell-powered gui
Cello by encomiums to Garnet, but should I be? Garnet is not dead, but
at the risk of pissing off its maintainers it seems to be dead in the
water. If it is so wonderful, how come it is not thriving?

Let me offer two tentative answers: Amulet (a dead end itself, it seems)
and "CLOS not spoken here"?

Wolfgang Mederle

unread,
Mar 27, 2003, 7:47:55 PM3/27/03
to
Kenny Tilton wrote:

> You know, I always am encouraged in re Cells and the Cell-powered gui
> Cello by encomiums to Garnet, but should I be? Garnet is not dead, but
> at the risk of pissing off its maintainers it seems to be dead in the
> water. If it is so wonderful, how come it is not thriving?
>
> Let me offer two tentative answers: Amulet (a dead end itself, it
> seems) and "CLOS not spoken here"?

Amulet, which is for C++, I don't know. I rather wonder why C++ was
chosen at all, when CMUCL with its good performance was developed at the
same University. Was the speed difference so big at the time?

The lack of CLOS, though, might be a drawback today. In 1994, when the
docs (which are excellent) were written, performance issues with CLOS
were given as one of the reasons for using a custom object system.
Should not be a problem anymore.

Plus:

* No Debian package available. I don't use Debian myself, but I
converted many packages for Slackware and use common-lisp-controller.
Debian seems to be the preferred Linux platform for Lispers.
* No asdf/defsystem installer. Install is easy, but still not as
comfortable.
* No transparency, no 3D look. I like the look, but it is not "modern".
* Other toolkits packaged with commercial Lisps.
* Not much talk about it anymore. I was glad to receive a few answers
for a question on the Garnet Users mailing list, but basically they
said "I don't remember it well" or "I don't use it now".
* comp.windows.garnet is dead. Absolutely no response to my question
there. This /could/ mean that the total user base at this very moment
is me. On the other hand, the total user base of Common Lisp at my
institute at University is me, too. I'm working on leveraging it,
though.

--
Wolfgang Mederle

$BONMOT

CY

unread,
Mar 28, 2003, 12:03:14 PM3/28/03
to
Kenny Tilton <kti...@nyc.rr.com> wrote in message news:<3E83787A...@nyc.rr.com>...

> Wolfgang Mederle wrote:
> > Joerg Hoehle wrote:
> >
> >
> >>When I looked into GUI programming a decade ago, I remember a nice
> >>demo: Something like a volume control with two ways of setting it:
> >> - a proportional slider with a knob
> >> - a digital input where you could type the number (0-100)
> >>Modifying with mouse or keyboard changed the other's display.
> >
> >
> > Sounds like Garnet. (Even if it wasn't, Garnet has sliders and
> > scrollbars with this functionality.) I'm working on a small program at
> > the moment that uses it, and it is really a joy.
> >
>
> You know, I always am encouraged in re Cells and the Cell-powered gui
> Cello by encomiums to Garnet, but should I be? Garnet is not dead, but
> at the risk of pissing off its maintainers it seems to be dead in the
> water. If it is so wonderful, how come it is not thriving?

Not too much maintainance going on right now really. That may change
in the future when it becomes useful for a project, but currently it's
not high on the priority list. Basically the SF site is a place for
bug fixes to be added, if/when people find and fix them.

> Let me offer two tentative answers: Amulet (a dead end itself, it seems)
> and "CLOS not spoken here"?

Amulet... I don't think Amulet is a reason anymore, since if people
are looking to use Garnet they are looking for a Lisp toolkit. It was
one of the reasons CMU discontinued development on Garnet, IIRC. CLOS
is also another big issue, although bridging is apparently possible.
I think the look of it doesn't help, either - it's quite advanced and
powerful, but looks like a really old MacOS interface out of box. The
Motif look is a bit better, but a Windows look would help quite a bit.

Thomas F. Burdick

unread,
Mar 28, 2003, 1:02:26 PM3/28/03
to
Kenny Tilton <kti...@nyc.rr.com> writes:

> Wolfgang Mederle wrote:
> > Joerg Hoehle wrote:
> >
> >
> >>When I looked into GUI programming a decade ago, I remember a nice
> >>demo: Something like a volume control with two ways of setting it:
> >> - a proportional slider with a knob
> >> - a digital input where you could type the number (0-100)
> >>Modifying with mouse or keyboard changed the other's display.
> >
> >
> > Sounds like Garnet. (Even if it wasn't, Garnet has sliders and
> > scrollbars with this functionality.) I'm working on a small program at
> > the moment that uses it, and it is really a joy.
>
> You know, I always am encouraged in re Cells and the Cell-powered gui
> Cello by encomiums to Garnet, but should I be? Garnet is not dead, but
> at the risk of pissing off its maintainers it seems to be dead in the
> water. If it is so wonderful, how come it is not thriving?
>
> Let me offer two tentative answers: Amulet (a dead end itself, it seems)
> and "CLOS not spoken here"?

Here's my $0.02 on this: it looks like it stalled when it lost its
institutional support from CMU. Amulet caused Garnet to be orphaned
around the same time that CMU orphaned CMUCL. The lisp implementation
succeeded in getting a volunteer development group supporting it,
largely, I think, because it's compatible with the commercial
implementations (ie, it's an ANSI Common Lisp). Garnet, on the other
hand, is completely incompatible with any other GUI kit for CL, and is
pretty conceptually different, too.

Why hasn't it regained mindshare? This might be due in part to the
docs' use of the old-style look&feel, instead of the Motif l&f --
anyone just glancing through the docs is going to say "wow, that looks
weird". Or, "wow, that looks like my Mac 512K", depending on their
personal history. And it suffers greatly from the fact that there are
other good (commercial) toolkits, and you have to try it to realize
how cool KR is.

For any lurkers at UC-Berkeley: if you want to try out Garnet, it's
installed at the OCF. Get an OCF account, start CMUCL, and type
(require :garnet) at the toplevel. Bada-bing, bada-boom. The docs
are in /opt/local/packages/garnet/docs/.

Vladimir S.

unread,
Mar 28, 2003, 5:28:08 PM3/28/03
to
Kenny Tilton <kti...@nyc.rr.com> writes:

> Wolfgang Mederle wrote:
> > Joerg Hoehle wrote:
> >
> >>When I looked into GUI programming a decade ago, I remember a nice
> >>demo: Something like a volume control with two ways of setting it:
> >> - a proportional slider with a knob
> >> - a digital input where you could type the number (0-100)
> >>Modifying with mouse or keyboard changed the other's display.
> > Sounds like Garnet. (Even if it wasn't, Garnet has sliders and
> > scrollbars with this functionality.) I'm working on a small program at
> > the moment that uses it, and it is really a joy.
> >
>
> You know, I always am encouraged in re Cells and the Cell-powered gui
> Cello by encomiums to Garnet, but should I be? Garnet is not dead, but
> at the risk of pissing off its maintainers it seems to be dead in the
> water. If it is so wonderful, how come it is not thriving?
>
> Let me offer two tentative answers: Amulet (a dead end itself, it
> seems) and "CLOS not spoken here"?

I guess I can weigh in my ignorant opinion as well since there is
something about Garnet that's been frustrating me for the past couple
of days. For something written in CL by competent CL programmers, it
sure seems un-Lispy.

You immediatly notice this in the manual - every example encourages
you to use the 's-value' function to change slot values (I think
there's only one place (in the KR docs) where the setf method for
changing schema (KR object) values is mentioned). The 'interesting'
function names (I really don't understand why 'create-instance' is the
external function for making schema, and 'make-schema' is the internal
one). Many functions are just redundant - 'add-component' can only add
one schema to an aggregate, but 'add-components' signals an error if
you try to add only one schema.

Then there's the thing that has gotten on my nerves - virtual
aggregates (containers for static screen elements that draw them
without making a separate object for each one) - I wanted to write the
plot routines for Mark Watson's _Common Lisp Modules_ book, but when
using the regular aggregate and objects, the fractal examples spent
most of the time just adding rectangles. The interface to virtual
aggregates is messy (not to mention the bad function naming and
redundancy - 'add-component' only works on regular aggregates, and
'add-item' only on virtual ones), and I can't get the damn things to
work on rectangles (I subscribe to CMU's Garnet mailing list, but
judging by the replies Wolfgang received (sorry for not answering, but
I don't know anything about aggrelists) they can't offer me much help
either).

So not everything is peachy about Garnet. While the above complaints
aren't very difficult to resolve (and I guess I am a bit sensetive
about these things as I am re-reading Kent and Norvig's "Good Lisp
Style" talk papers), and actually I am planning to resolve them by
making a new interface to Garnet after I'm done wrangling with
Multi-Garnet, the CLOS integration issue is more hairy. So yes,
Mr. Tilton, you do have reason to be encouraged :). Personally I am
really looking forward to Cello.

Kenny Tilton

unread,
Mar 28, 2003, 6:26:24 PM3/28/03
to

Vladimir S. wrote:
> Kenny Tilton <kti...@nyc.rr.com> writes:

>>You know, I always am encouraged in re Cells and the Cell-powered gui
>>Cello by encomiums to Garnet, but should I be? Garnet is not dead, but
>>at the risk of pissing off its maintainers it seems to be dead in the
>>water. If it is so wonderful, how come it is not thriving?
>>

...


> So not everything is peachy about Garnet. While the above complaints
> aren't very difficult to resolve (and I guess I am a bit sensetive
> about these things as I am re-reading Kent and Norvig's "Good Lisp
> Style" talk papers), and actually I am planning to resolve them by
> making a new interface to Garnet after I'm done wrangling with
> Multi-Garnet, the CLOS integration issue is more hairy. So yes,
> Mr. Tilton, you do have reason to be encouraged :). Personally I am
> really looking forward to Cello.

Thanks to you and everyone for your insights on Garnet. I'll keep going
on Cello. :)

I have thought of doing something like aggregates in the past, but so
far they have not been necessary, and that is how Cello grows, in
response to new demands.

Fractals are computationally expensive, but it does not sound like
somehting that is hard to keep straight the way a big application is. I
would likely just have a fractal widget and let it worry about how to
create the fratal image.

It would be /fun/ to do with Cells and Cello, and probably instructive,
but too slow.

Wolfgang Mederle

unread,
Mar 28, 2003, 7:50:56 PM3/28/03
to
Vladimir S. wrote:

> I guess I can weigh in my ignorant opinion as well since there is
> something about Garnet that's been frustrating me for the past couple
> of days.

Which already doubles the user base from my point of view.

> So yes, Mr. Tilton, you do have reason to be encouraged :). Personally
> I am really looking forward to Cello.

I'll just add a "me too" here.

--
Wolfgang Mederle

0 new messages